diff -Nru php-nette-2.1.4/debian/changelog php-nette-2.1.5/debian/changelog --- php-nette-2.1.4/debian/changelog 2014-05-27 01:26:45.000000000 +0000 +++ php-nette-2.1.5/debian/changelog 2014-08-31 20:15:22.000000000 +0000 @@ -1,3 +1,13 @@ +php-nette (2.1.5-1) unstable; urgency=medium + + [ David Grudl ] + * Released version 2.1.5 + + [ David Prévot ] + * Track the PEAR based package + + -- David Prévot Sun, 31 Aug 2014 16:07:29 -0400 + php-nette (2.1.4-1) unstable; urgency=medium [ David Grudl ] diff -Nru php-nette-2.1.4/debian/control php-nette-2.1.5/debian/control --- php-nette-2.1.4/debian/control 2014-05-13 20:06:25.000000000 +0000 +++ php-nette-2.1.5/debian/control 2014-08-31 19:58:20.000000000 +0000 @@ -6,7 +6,7 @@ Build-Depends: debhelper (>= 9), pear-channels, pkg-php-tools (>= 1.1~) Standards-Version: 3.9.5 Homepage: http://nette.org/ -Vcs-Git: git://anonscm.debian.org/pkg-php/php-nette.git +Vcs-Git: git://anonscm.debian.org/pkg-php/php-nette.git -b pear Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-php/php-nette.git Package: php-nette diff -Nru php-nette-2.1.4/debian/gbp.conf php-nette-2.1.5/debian/gbp.conf --- php-nette-2.1.4/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/debian/gbp.conf 2014-08-31 19:58:20.000000000 +0000 @@ -0,0 +1,4 @@ +[DEFAULT] +pristine-tar = True +debian-branch = pear +upstream-branch = upstream-pear diff -Nru php-nette-2.1.4/debian/upstream-changelog php-nette-2.1.5/debian/upstream-changelog --- php-nette-2.1.4/debian/upstream-changelog 2014-05-27 01:24:26.000000000 +0000 +++ php-nette-2.1.5/debian/upstream-changelog 2014-08-31 20:02:53.000000000 +0000 @@ -1,5 +1,37 @@ +2.1.5 - 2014-08-28 + + new way how to detect errors in native PHP function (used in Session, Mail, Strings, …) + Configurator::setDebugMode() without argument uses autodetection + DI: fixed inheritance + DI: better exception messages + Forms: fixed erasing of manually added errors via addError + Forms: fixed getHttpData() for multiple file uploads + Latte: macro {includeblock} gently trims output + Http\Response: added $warnOnBuffer + Mail: fixed headers encoding nette/mail#4 + Mail: setHtmlBody() decodes %XX in URL + PhpGenerator: ClassType::from processes only own properties + PhpGenerator: fixed dumping of non-public properties + + +2.1.5 RC2 - 2014-08-10 + + +2.1.5 RC - 2014-07-09 + + 2.1.4 - 2014-05-24 + Latte & Nette\Utils\Html: added protection against innerHTML mXSS vulnerability + Latte: fixed parsing {macro|modifier /} + Latte: fixed including parent block multiple times + Latte, DI: improved error messages + Tracy: Dumper prints attribute data-tracy-href only when option 'location' is enabled + RadioList: attrs of radiolist label aren't appended to labels of radio + Database: ResultSet: empty keys are not converted to properties + Strings::toAscii(): support for czech and french quotation marks + RobotLoader: works with PHP 5.6 syntax ClassName::class + 2.1.3 - 2014-05-12 diff -Nru php-nette-2.1.4/Nette-2.1.4/license.txt php-nette-2.1.5/Nette-2.1.4/license.txt --- php-nette-2.1.4/Nette-2.1.4/license.txt 2014-05-24 20:50:40.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/license.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -Licenses -======== - -Good news! You may use Nette Framework under the terms of either -the New BSD License or the GNU General Public License (GPL) version 2 or 3. - -The BSD License is recommended for most projects. It is easy to understand and it -places almost no restrictions on what you can do with the framework. If the GPL -fits better to your project, you can use the framework under this license. - -You don't have to notify anyone which license you are using. You can freely -use Nette Framework in commercial projects as long as the copyright header -remains intact. - -Please be advised that the name "Nette Framework" is a protected trademark and its -usage has some limitations. So please do not use word "Nette" in the name of your -project or top-level domain, and choose a name that stands on its own merits. -If your stuff is good, it will not take long to establish a reputation for yourselves. - - -New BSD License ---------------- - -Copyright (c) 2004, 2014 David Grudl (http://davidgrudl.com) -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name of "Nette Framework" nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -This software is provided by the copyright holders and contributors "as is" and -any express or implied warranties, including, but not limited to, the implied -warranties of merchantability and fitness for a particular purpose are -disclaimed. In no event shall the copyright owner or contributors be liable for -any direct, indirect, incidental, special, exemplary, or consequential damages -(including, but not limited to, procurement of substitute goods or services; -loss of use, data, or profits; or business interruption) however caused and on -any theory of liability, whether in contract, strict liability, or tort -(including negligence or otherwise) arising in any way out of the use of this -software, even if advised of the possibility of such damage. - - -GNU General Public License --------------------------- - -GPL licenses are very very long, so instead of including them here we offer -you URLs with full text: - -- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html) -- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html) diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Application.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Application.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Application.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Application.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,243 +0,0 @@ -httpRequest = $httpRequest; - $this->httpResponse = $httpResponse; - $this->presenterFactory = $presenterFactory; - $this->router = $router; - } - - - /** - * Dispatch a HTTP request to a front controller. - * @return void - */ - public function run() - { - try { - $this->onStartup($this); - $this->processRequest($this->createInitialRequest()); - $this->onShutdown($this); - - } catch (\Exception $e) { - $this->onError($this, $e); - if ($this->catchExceptions && $this->errorPresenter) { - try { - $this->processException($e); - $this->onShutdown($this, $e); - return; - - } catch (\Exception $e) { - $this->onError($this, $e); - } - } - $this->onShutdown($this, $e); - throw $e; - } - } - - - /** - * @return Request - */ - public function createInitialRequest() - { - $request = $this->router->match($this->httpRequest); - - if (!$request instanceof Request) { - throw new BadRequestException('No route for HTTP request.'); - - } elseif (strcasecmp($request->getPresenterName(), $this->errorPresenter) === 0) { - throw new BadRequestException('Invalid request. Presenter is not achievable.'); - } - - try { - $name = $request->getPresenterName(); - $this->presenterFactory->getPresenterClass($name); - $request->setPresenterName($name); - } catch (InvalidPresenterException $e) { - throw new BadRequestException($e->getMessage(), 0, $e); - } - - return $request; - } - - - /** - * @return void - */ - public function processRequest(Request $request) - { - if (count($this->requests) > self::$maxLoop) { - throw new ApplicationException('Too many loops detected in application life cycle.'); - } - - $this->requests[] = $request; - $this->onRequest($this, $request); - - $this->presenter = $this->presenterFactory->createPresenter($request->getPresenterName()); - $this->onPresenter($this, $this->presenter); - $response = $this->presenter->run($request); - - if ($response instanceof Responses\ForwardResponse) { - $this->processRequest($response->getRequest()); - - } elseif ($response) { - $this->onResponse($this, $response); - $response->send($this->httpRequest, $this->httpResponse); - } - } - - - /** - * @return void - */ - public function processException(\Exception $e) - { - if (!$this->httpResponse->isSent()) { - $this->httpResponse->setCode($e instanceof BadRequestException ? ($e->getCode() ?: 404) : 500); - } - - $args = array('exception' => $e, 'request' => end($this->requests) ?: NULL); - if ($this->presenter instanceof UI\Presenter) { - try { - $this->presenter->forward(":$this->errorPresenter:", $args); - } catch (AbortException $foo) { - $this->processRequest($this->presenter->getLastCreatedRequest()); - } - } else { - $this->processRequest(new Request($this->errorPresenter, Request::FORWARD, $args)); - } - } - - - /** - * Returns all processed requests. - * @return Request[] - */ - public function getRequests() - { - return $this->requests; - } - - - /** - * Returns current presenter. - * @return IPresenter - */ - public function getPresenter() - { - return $this->presenter; - } - - - /********************* services ****************d*g**/ - - - /** - * Returns router. - * @return IRouter - */ - public function getRouter() - { - return $this->router; - } - - - /** - * Returns presenter factory. - * @return IPresenterFactory - */ - public function getPresenterFactory() - { - return $this->presenterFactory; - } - - - /********************* request serialization ****************d*g**/ - - - /** @deprecated */ - function storeRequest($expiration = '+ 10 minutes') - { - trigger_error(__METHOD__ . '() is deprecated; use $presenter->storeRequest() instead.', E_USER_DEPRECATED); - return $this->presenter->storeRequest($expiration); - } - - /** @deprecated */ - function restoreRequest($key) - { - trigger_error(__METHOD__ . '() is deprecated; use $presenter->restoreRequest() instead.', E_USER_DEPRECATED); - return $this->presenter->restoreRequest($key); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Diagnostics/RoutingPanel.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Diagnostics/RoutingPanel.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Diagnostics/RoutingPanel.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Diagnostics/RoutingPanel.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -addPanel(function($e) use ($application) { - return $e ? NULL : array( - 'tab' => 'Nette Application', - 'panel' => '

Requests

' . Dumper::toHtml($application->getRequests()) - . '

Presenter

' . Dumper::toHtml($application->getPresenter()) - ); - }); - } - - - public function __construct(Nette\Application\IRouter $router, Nette\Http\IRequest $httpRequest, Nette\Application\IPresenterFactory $presenterFactory) - { - $this->router = $router; - $this->httpRequest = $httpRequest; - $this->presenterFactory = $presenterFactory; - } - - - /** - * Renders tab. - * @return string - */ - public function getTab() - { - $this->analyse($this->router); - ob_start(); - require __DIR__ . '/templates/RoutingPanel.tab.phtml'; - return ob_get_clean(); - } - - - /** - * Renders panel. - * @return string - */ - public function getPanel() - { - ob_start(); - require __DIR__ . '/templates/RoutingPanel.panel.phtml'; - return ob_get_clean(); - } - - - /** - * Analyses simple route. - * @param Nette\Application\IRouter - * @return void - */ - private function analyse($router, $module = '') - { - if ($router instanceof Routers\RouteList) { - foreach ($router as $subRouter) { - $this->analyse($subRouter, $module . $router->getModule()); - } - return; - } - - $matched = 'no'; - $request = $router->match($this->httpRequest); - if ($request) { - $request->setPresenterName($module . $request->getPresenterName()); - $matched = 'may'; - if (empty($this->request)) { - $this->request = $request; - $this->findSource(); - $matched = 'yes'; - } - } - - $this->routers[] = array( - 'matched' => $matched, - 'class' => get_class($router), - 'defaults' => $router instanceof Routers\Route || $router instanceof Routers\SimpleRouter ? $router->getDefaults() : array(), - 'mask' => $router instanceof Routers\Route ? $router->getMask() : NULL, - 'request' => $request, - 'module' => rtrim($module, ':') - ); - } - - - private function findSource() - { - $request = $this->request; - $presenter = $request->getPresenterName(); - try { - $class = $this->presenterFactory->getPresenterClass($presenter); - } catch (Nette\Application\InvalidPresenterException $e) { - return; - } - $rc = Nette\Reflection\ClassType::from($class); - - if ($rc->isSubclassOf('Nette\Application\UI\Presenter')) { - if (isset($request->parameters[Presenter::SIGNAL_KEY])) { - $method = $class::formatSignalMethod($request->parameters[Presenter::SIGNAL_KEY]); - - } elseif (isset($request->parameters[Presenter::ACTION_KEY])) { - $action = $request->parameters[Presenter::ACTION_KEY]; - $method = $class::formatActionMethod($action); - if (!$rc->hasMethod($method)) { - $method = $class::formatRenderMethod($action); - } - } - } - - $this->source = isset($method) && $rc->hasMethod($method) ? $rc->getMethod($method) : $rc; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Diagnostics/templates/RoutingPanel.panel.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Application/Diagnostics/templates/RoutingPanel.panel.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Diagnostics/templates/RoutingPanel.panel.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Diagnostics/templates/RoutingPanel.panel.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ - - - -
-

-request)): ?> - no route - - request->getPresenterName() . ':' . (isset($this->request->parameters[Presenter::ACTION_KEY]) ? $this->request->parameters[Presenter::ACTION_KEY] : Presenter::DEFAULT_ACTION) . (isset($this->request->parameters[Presenter::SIGNAL_KEY]) ? " {$this->request->parameters[Presenter::SIGNAL_KEY]}!" : '')) ?> - -

- -
-

httpRequest->getUrl()) ?>

- -routers)): ?> -

No routers defined.

- - - - - - - - - - - - - - - - routers as $router): ?> - - - - - - - - - - - - - - - -
Matched?ClassMaskDefaultsModuleRequest
- $value): ?> - TRUE))) ?>
- -
- getParameters(); ?> - getPresenterName() . ':' . (isset($params[Presenter::ACTION_KEY]) ? $params[Presenter::ACTION_KEY] : Presenter::DEFAULT_ACTION)) ?>
- - $value): ?> - TRUE))) ?>
- -
- - - source): ?>

source ?> in source->getFileName(), $this->source->getStartLine()) ?>

-
-
diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Diagnostics/templates/RoutingPanel.tab.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Application/Diagnostics/templates/RoutingPanel.tab.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Diagnostics/templates/RoutingPanel.tab.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Diagnostics/templates/RoutingPanel.tab.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ - -request)): ?>no routerequest->getPresenterName() . ':' . (isset($this->request->parameters[Presenter::ACTION_KEY]) ? $this->request->parameters[Presenter::ACTION_KEY] : Presenter::DEFAULT_ACTION) . (isset($this->request->parameters[Presenter::SIGNAL_KEY]) ? " {$this->request->parameters[Presenter::SIGNAL_KEY]}!" : '')); endif ?> diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/ErrorPresenter.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/ErrorPresenter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/ErrorPresenter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/ErrorPresenter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -parameters['exception']; - if ($e instanceof Application\BadRequestException) { - $code = $e->getCode(); - } else { - $code = 500; - Debugger::log($e, Debugger::ERROR); - } - ob_start(); - require __DIR__ . '/templates/error.phtml'; - return new Application\Responses\TextResponse(ob_get_clean()); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/exceptions.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/exceptions.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/exceptions.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/exceptions.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ - 504 ? $this->defaultCode : $code, $previous); - } - -} - - -/** - * Forbidden request exception - access denied. - */ -class ForbiddenRequestException extends BadRequestException -{ - /** @var int */ - protected $defaultCode = 403; - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/IPresenterFactory.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/IPresenterFactory.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/IPresenterFactory.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/IPresenterFactory.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ - - */ -interface IPresenterFactory -{ - - /** - * Generates and checks presenter class name. - * @param string presenter name - * @return string class name - * @throws InvalidPresenterException - */ - function getPresenterClass(& $name); - - /** - * Creates new presenter instance. - * @param string presenter name - * @return IPresenter - */ - function createPresenter($name); - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/IPresenter.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/IPresenter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/IPresenter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/IPresenter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -context = $context; - } - - - /** - * Gets the context. - * @return \SystemContainer|Nette\DI\Container - */ - public function getContext() - { - return $this->context; - } - - - /** - * @return Nette\Application\IResponse - */ - public function run(Application\Request $request) - { - $this->request = $request; - - $httpRequest = $this->context->getByType('Nette\Http\IRequest'); - if (!$httpRequest->isAjax() && ($request->isMethod('get') || $request->isMethod('head'))) { - $refUrl = clone $httpRequest->getUrl(); - $url = $this->context->getByType('Nette\Application\IRouter')->constructUrl($request, $refUrl->setPath($refUrl->getScriptPath())); - if ($url !== NULL && !$httpRequest->getUrl()->isEqual($url)) { - return new Responses\RedirectResponse($url, Http\IResponse::S301_MOVED_PERMANENTLY); - } - } - - $params = $request->getParameters(); - if (!isset($params['callback'])) { - throw new Application\BadRequestException('Parameter callback is missing.'); - } - $params['presenter'] = $this; - $callback = $params['callback']; - $reflection = Nette\Utils\Callback::toReflection(Nette\Utils\Callback::check($callback)); - $params = Application\UI\PresenterComponentReflection::combineArgs($reflection, $params); - - foreach ($reflection->getParameters() as $param) { - if ($param->getClassName()) { - unset($params[$param->getPosition()]); - } - } - $params = Nette\DI\Helpers::autowireArguments($reflection, $params, $this->context); - - $response = call_user_func_array($callback, $params); - - if (is_string($response)) { - $response = array($response, array()); - } - if (is_array($response)) { - if ($response[0] instanceof \SplFileInfo) { - $response = $this->createTemplate('Nette\Templating\FileTemplate') - ->setParameters($response[1])->setFile($response[0]); - } else { - $response = $this->createTemplate('Nette\Templating\Template') - ->setParameters($response[1])->setSource($response[0]); - } - } - if ($response instanceof Nette\Templating\ITemplate) { - return new Responses\TextResponse($response); - } else { - return $response; - } - } - - - /** - * Template factory. - * @param string - * @param callable - * @return Nette\Templating\ITemplate - */ - public function createTemplate($class = NULL, $latteFactory = NULL) - { - $template = $class ? new $class : new Nette\Templating\FileTemplate; - - $template->setParameters($this->request->getParameters()); - $template->presenter = $this; - $template->context = $context = $this->context; - $url = $context->getByType('Nette\Http\IRequest')->getUrl(); - $template->baseUrl = rtrim($url->getBaseUrl(), '/'); - $template->basePath = rtrim($url->getBasePath(), '/'); - - $template->registerHelperLoader('Nette\Templating\Helpers::loader'); - $template->setCacheStorage($context->getService('nette.templateCacheStorage')); - $template->onPrepareFilters[] = function($template) use ($latteFactory) { - $template->registerFilter($latteFactory ? $latteFactory() : new Nette\Latte\Engine); - }; - return $template; - } - - - /** - * Redirects to another URL. - * @param string - * @param int HTTP code - * @return Nette\Application\Responses\RedirectResponse - */ - public function redirectUrl($url, $code = Http\IResponse::S302_FOUND) - { - return new Responses\RedirectResponse($url, $code); - } - - - /** - * Throws HTTP error. - * @param string - * @param int HTTP error code - * @return void - * @throws Nette\Application\BadRequestException - */ - public function error($message = NULL, $code = Http\IResponse::S404_NOT_FOUND) - { - throw new Application\BadRequestException($message, $code); - } - - - /** - * @return Nette\Application\IRequest - */ - public function getRequest() - { - return $this->request; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/PresenterFactory.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/PresenterFactory.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/PresenterFactory.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/PresenterFactory.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,193 +0,0 @@ - splited mask */ - private $mapping = array( - '*' => array('', '*Module\\', '*Presenter'), - 'Nette' => array('NetteModule\\', '*\\', '*Presenter'), - ); - - /** @var string */ - private $baseDir; - - /** @var array */ - private $cache = array(); - - /** @var Nette\DI\Container */ - private $container; - - - /** - * @param string - */ - public function __construct($baseDir, Nette\DI\Container $container) - { - $this->baseDir = $baseDir; - $this->container = $container; - } - - - /** - * Creates new presenter instance. - * @param string presenter name - * @return IPresenter - */ - public function createPresenter($name) - { - $class = $this->getPresenterClass($name); - if (count($services = $this->container->findByType($class)) === 1) { - $presenter = $this->container->createService($services[0]); - } else { - $presenter = $this->container->createInstance($class); - } - $this->container->callInjects($presenter); - - if ($presenter instanceof UI\Presenter && $presenter->invalidLinkMode === NULL) { - $presenter->invalidLinkMode = $this->container->parameters['debugMode'] ? UI\Presenter::INVALID_LINK_WARNING : UI\Presenter::INVALID_LINK_SILENT; - } - return $presenter; - } - - - /** - * Generates and checks presenter class name. - * @param string presenter name - * @return string class name - * @throws InvalidPresenterException - */ - public function getPresenterClass(& $name) - { - if (isset($this->cache[$name])) { - list($class, $name) = $this->cache[$name]; - return $class; - } - - if (!is_string($name) || !Nette\Utils\Strings::match($name, '#^[a-zA-Z\x7f-\xff][a-zA-Z0-9\x7f-\xff:]*\z#')) { - throw new InvalidPresenterException("Presenter name must be alphanumeric string, '$name' is invalid."); - } - - $class = $this->formatPresenterClass($name); - - if (!class_exists($class)) { - // internal autoloading - $file = $this->formatPresenterFile($name); - if (is_file($file) && is_readable($file)) { - call_user_func(function() use ($file) { require $file; }); - } - - if (!class_exists($class)) { - throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' was not found in '$file'."); - } - } - - $reflection = new Nette\Reflection\ClassType($class); - $class = $reflection->getName(); - - if (!$reflection->implementsInterface('Nette\Application\IPresenter')) { - throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is not Nette\\Application\\IPresenter implementor."); - } - - if ($reflection->isAbstract()) { - throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is abstract."); - } - - // canonicalize presenter name - $realName = $this->unformatPresenterClass($class); - if ($name !== $realName) { - if ($this->caseSensitive) { - throw new InvalidPresenterException("Cannot load presenter '$name', case mismatch. Real name is '$realName'."); - } else { - $this->cache[$name] = array($class, $realName); - $name = $realName; - } - } else { - $this->cache[$name] = array($class, $realName); - } - - return $class; - } - - - /** - * Sets mapping as pairs [module => mask] - * @return self - */ - public function setMapping(array $mapping) - { - foreach ($mapping as $module => $mask) { - if (!preg_match('#^\\\\?([\w\\\\]*\\\\)?(\w*\*\w*?\\\\)?([\w\\\\]*\*\w*)\z#', $mask, $m)) { - throw new Nette\InvalidStateException("Invalid mapping mask '$mask'."); - } - $this->mapping[$module] = array($m[1], $m[2] ?: '*Module\\', $m[3]); - } - return $this; - } - - - /** - * Formats presenter class name from its name. - * @param string - * @return string - */ - public function formatPresenterClass($presenter) - { - $parts = explode(':', $presenter); - $mapping = isset($parts[1], $this->mapping[$parts[0]]) - ? $this->mapping[array_shift($parts)] - : $this->mapping['*']; - - while ($part = array_shift($parts)) { - $mapping[0] .= str_replace('*', $part, $mapping[$parts ? 1 : 2]); - } - return $mapping[0]; - } - - - /** - * Formats presenter name from class name. - * @param string - * @return string - */ - public function unformatPresenterClass($class) - { - foreach ($this->mapping as $module => $mapping) { - $mapping = str_replace(array('\\', '*'), array('\\\\', '(\w+)'), $mapping); - if (preg_match("#^\\\\?$mapping[0]((?:$mapping[1])*)$mapping[2]\\z#i", $class, $matches)) { - return ($module === '*' ? '' : $module . ':') - . preg_replace("#$mapping[1]#iA", '$1:', $matches[1]) . $matches[3]; - } - } - } - - - /** - * Formats presenter class file name. - * @param string - * @return string - */ - public function formatPresenterFile($presenter) - { - $path = '/' . str_replace(':', 'Module/', $presenter); - return $this->baseDir . substr_replace($path, '/presenters', strrpos($path, '/'), 0) . 'Presenter.php'; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Request.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Request.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Request.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Request.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,224 +0,0 @@ -name = $name; - $this->method = $method; - $this->params = $params; - $this->post = $post; - $this->files = $files; - $this->flags = $flags; - } - - - /** - * Sets the presenter name. - * @param string - * @return self - */ - public function setPresenterName($name) - { - $this->name = $name; - return $this; - } - - - /** - * Retrieve the presenter name. - * @return string - */ - public function getPresenterName() - { - return $this->name; - } - - - /** - * Sets variables provided to the presenter. - * @return self - */ - public function setParameters(array $params) - { - $this->params = $params; - return $this; - } - - - /** - * Returns all variables provided to the presenter (usually via URL). - * @return array - */ - public function getParameters() - { - return $this->params; - } - - - /** - * Sets variables provided to the presenter via POST. - * @return self - */ - public function setPost(array $params) - { - $this->post = $params; - return $this; - } - - - /** - * Returns all variables provided to the presenter via POST. - * @return array - */ - public function getPost() - { - return $this->post; - } - - - /** - * Sets all uploaded files. - * @return self - */ - public function setFiles(array $files) - { - $this->files = $files; - return $this; - } - - - /** - * Returns all uploaded files. - * @return array - */ - public function getFiles() - { - return $this->files; - } - - - /** - * Sets the method. - * @param string - * @return self - */ - public function setMethod($method) - { - $this->method = $method; - return $this; - } - - - /** - * Returns the method. - * @return string - */ - public function getMethod() - { - return $this->method; - } - - - /** - * Checks if the method is the given one. - * @param string - * @return bool - */ - public function isMethod($method) - { - return strcasecmp($this->method, $method) === 0; - } - - - /** - * Checks if the method is POST. - * @return bool - */ - public function isPost() - { - return strcasecmp($this->method, 'post') === 0; - } - - - /** - * Sets the flag. - * @param string - * @param bool - * @return self - */ - public function setFlag($flag, $value = TRUE) - { - $this->flags[$flag] = (bool) $value; - return $this; - } - - - /** - * Checks the flag. - * @param string - * @return bool - */ - public function hasFlag($flag) - { - return !empty($this->flags[$flag]); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/FileResponse.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/FileResponse.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/FileResponse.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/FileResponse.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,130 +0,0 @@ -file = $file; - $this->name = $name ? $name : basename($file); - $this->contentType = $contentType ? $contentType : 'application/octet-stream'; - } - - - /** - * Returns the path to a downloaded file. - * @return string - */ - public function getFile() - { - return $this->file; - } - - - /** - * Returns the file name. - * @return string - */ - public function getName() - { - return $this->name; - } - - - /** - * Returns the MIME content type of a downloaded file. - * @return string - */ - public function getContentType() - { - return $this->contentType; - } - - - /** - * Sends response to output. - * @return void - */ - public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse) - { - $httpResponse->setContentType($this->contentType); - $httpResponse->setHeader('Content-Disposition', 'attachment; filename="' . $this->name . '"'); - - $filesize = $length = filesize($this->file); - $handle = fopen($this->file, 'r'); - - if ($this->resuming) { - $httpResponse->setHeader('Accept-Ranges', 'bytes'); - if (preg_match('#^bytes=(\d*)-(\d*)\z#', $httpRequest->getHeader('Range'), $matches)) { - list(, $start, $end) = $matches; - if ($start === '') { - $start = max(0, $filesize - $end); - $end = $filesize - 1; - - } elseif ($end === '' || $end > $filesize - 1) { - $end = $filesize - 1; - } - if ($end < $start) { - $httpResponse->setCode(416); // requested range not satisfiable - return; - } - - $httpResponse->setCode(206); - $httpResponse->setHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $filesize); - $length = $end - $start + 1; - fseek($handle, $start); - - } else { - $httpResponse->setHeader('Content-Range', 'bytes 0-' . ($filesize - 1) . '/' . $filesize); - } - } - - $httpResponse->setHeader('Content-Length', $length); - while (!feof($handle) && $length > 0) { - echo $s = fread($handle, min(4e6, $length)); - $length -= strlen($s); - } - fclose($handle); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/ForwardResponse.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/ForwardResponse.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/ForwardResponse.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/ForwardResponse.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -request = $request; - } - - - /** - * @return Nette\Application\Request - */ - public function getRequest() - { - return $this->request; - } - - - /** - * Sends response to output. - * @return void - */ - public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse) - { - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/JsonResponse.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/JsonResponse.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/JsonResponse.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/JsonResponse.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -payload = $payload; - $this->contentType = $contentType ? $contentType : 'application/json'; - } - - - /** - * @return array|\stdClass - */ - public function getPayload() - { - return $this->payload; - } - - - /** - * Returns the MIME content type of a downloaded file. - * @return string - */ - public function getContentType() - { - return $this->contentType; - } - - - /** - * Sends response to output. - * @return void - */ - public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse) - { - $httpResponse->setContentType($this->contentType); - $httpResponse->setExpiration(FALSE); - echo Nette\Utils\Json::encode($this->payload); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/RedirectResponse.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/RedirectResponse.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/RedirectResponse.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/RedirectResponse.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -url = (string) $url; - $this->code = (int) $code; - } - - - /** - * @return string - */ - public function getUrl() - { - return $this->url; - } - - - /** - * @return int - */ - public function getCode() - { - return $this->code; - } - - - /** - * Sends response to output. - * @return void - */ - public function send(Http\IRequest $httpRequest, Http\IResponse $httpResponse) - { - $httpResponse->redirect($this->url, $this->code); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/TextResponse.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/TextResponse.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Responses/TextResponse.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Responses/TextResponse.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -source = $source; - } - - - /** - * @return mixed - */ - public function getSource() - { - return $this->source; - } - - - /** - * Sends response to output. - * @return void - */ - public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse) - { - if ($this->source instanceof Nette\Templating\ITemplate) { - $this->source->render(); - - } else { - echo $this->source; - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Routers/CliRouter.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Routers/CliRouter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Routers/CliRouter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Routers/CliRouter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -defaults = $defaults; - } - - - /** - * Maps command line arguments to a Request object. - * @return Nette\Application\Request|NULL - */ - public function match(Nette\Http\IRequest $httpRequest) - { - if (empty($_SERVER['argv']) || !is_array($_SERVER['argv'])) { - return NULL; - } - - $names = array(self::PRESENTER_KEY); - $params = $this->defaults; - $args = $_SERVER['argv']; - array_shift($args); - $args[] = '--'; - - foreach ($args as $arg) { - $opt = preg_replace('#/|-+#A', '', $arg); - if ($opt === $arg) { - if (isset($flag) || $flag = array_shift($names)) { - $params[$flag] = $arg; - } else { - $params[] = $arg; - } - $flag = NULL; - continue; - } - - if (isset($flag)) { - $params[$flag] = TRUE; - $flag = NULL; - } - - if ($opt !== '') { - $pair = explode('=', $opt, 2); - if (isset($pair[1])) { - $params[$pair[0]] = $pair[1]; - } else { - $flag = $pair[0]; - } - } - } - - if (!isset($params[self::PRESENTER_KEY])) { - throw new Nette\InvalidStateException('Missing presenter & action in route definition.'); - } - $presenter = $params[self::PRESENTER_KEY]; - if ($a = strrpos($presenter, ':')) { - $params[self::PRESENTER_KEY] = substr($presenter, $a + 1); - $presenter = substr($presenter, 0, $a); - } - - return new Application\Request( - $presenter, - 'CLI', - $params - ); - } - - - /** - * This router is only unidirectional. - * @return NULL - */ - public function constructUrl(Application\Request $appRequest, Nette\Http\Url $refUrl) - { - return NULL; - } - - - /** - * Returns default values. - * @return array - */ - public function getDefaults() - { - return $this->defaults; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Routers/RouteList.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Routers/RouteList.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Routers/RouteList.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Routers/RouteList.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -module = $module ? $module . ':' : ''; - } - - - /** - * Maps HTTP request to a Request object. - * @return Nette\Application\Request|NULL - */ - public function match(Nette\Http\IRequest $httpRequest) - { - foreach ($this as $route) { - $appRequest = $route->match($httpRequest); - if ($appRequest !== NULL) { - $name = $appRequest->getPresenterName(); - if (strncmp($name, 'Nette:', 6)) { - $appRequest->setPresenterName($this->module . $name); - } - return $appRequest; - } - } - return NULL; - } - - - /** - * Constructs absolute URL from Request object. - * @return string|NULL - */ - public function constructUrl(Nette\Application\Request $appRequest, Nette\Http\Url $refUrl) - { - if ($this->cachedRoutes === NULL) { - $routes = array(); - $routes['*'] = array(); - - foreach ($this as $route) { - $presenter = $route instanceof Route ? $route->getTargetPresenter() : NULL; - - if ($presenter === FALSE) { - continue; - } - - if (is_string($presenter)) { - $presenter = strtolower($presenter); - if (!isset($routes[$presenter])) { - $routes[$presenter] = $routes['*']; - } - $routes[$presenter][] = $route; - - } else { - foreach ($routes as $id => $foo) { - $routes[$id][] = $route; - } - } - } - - $this->cachedRoutes = $routes; - } - - if ($this->module) { - if (strncasecmp($tmp = $appRequest->getPresenterName(), $this->module, strlen($this->module)) === 0) { - $appRequest = clone $appRequest; - $appRequest->setPresenterName(substr($tmp, strlen($this->module))); - } else { - return NULL; - } - } - - $presenter = strtolower($appRequest->getPresenterName()); - if (!isset($this->cachedRoutes[$presenter])) { - $presenter = '*'; - } - - foreach ($this->cachedRoutes[$presenter] as $route) { - $url = $route->constructUrl($appRequest, $refUrl); - if ($url !== NULL) { - return $url; - } - } - - return NULL; - } - - - /** - * Adds the router. - * @param mixed - * @param Nette\Application\IRouter - * @return void - */ - public function offsetSet($index, $route) - { - if (!$route instanceof Nette\Application\IRouter) { - throw new Nette\InvalidArgumentException('Argument must be IRouter descendant.'); - } - parent::offsetSet($index, $route); - } - - - /** - * @return string - */ - public function getModule() - { - return $this->module; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Routers/Route.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Routers/Route.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Routers/Route.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Routers/Route.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,828 +0,0 @@ - array( // default style for path parameters - self::PATTERN => '[^/]+', - self::FILTER_IN => 'rawurldecode', - self::FILTER_OUT => array(__CLASS__, 'param2path'), - ), - '?#' => array( // default style for query parameters - ), - 'module' => array( - self::PATTERN => '[a-z][a-z0-9.-]*', - self::FILTER_IN => array(__CLASS__, 'path2presenter'), - self::FILTER_OUT => array(__CLASS__, 'presenter2path'), - ), - 'presenter' => array( - self::PATTERN => '[a-z][a-z0-9.-]*', - self::FILTER_IN => array(__CLASS__, 'path2presenter'), - self::FILTER_OUT => array(__CLASS__, 'presenter2path'), - ), - 'action' => array( - self::PATTERN => '[a-z][a-z0-9-]*', - self::FILTER_IN => array(__CLASS__, 'path2action'), - self::FILTER_OUT => array(__CLASS__, 'action2path'), - ), - '?module' => array( - ), - '?presenter' => array( - ), - '?action' => array( - ), - ); - - /** @var string */ - private $mask; - - /** @var array */ - private $sequence; - - /** @var string regular expression pattern */ - private $re; - - /** @var array of [value & fixity, filterIn, filterOut] */ - private $metadata = array(); - - /** @var array */ - private $xlat; - - /** @var int HOST, PATH, RELATIVE */ - private $type; - - /** @var int */ - private $flags; - - - /** - * @param string URL mask, e.g. '//' - * @param array|string default values or metadata - * @param int flags - */ - public function __construct($mask, $metadata = array(), $flags = 0) - { - if (is_string($metadata)) { - $a = strrpos($metadata, ':'); - if (!$a) { - throw new Nette\InvalidArgumentException("Second argument must be array or string in format Presenter:action, '$metadata' given."); - } - $metadata = array( - self::PRESENTER_KEY => substr($metadata, 0, $a), - 'action' => $a === strlen($metadata) - 1 ? NULL : substr($metadata, $a + 1), - ); - } elseif ($metadata instanceof \Closure || $metadata instanceof Nette\Callback) { - $metadata = array( - self::PRESENTER_KEY => 'Nette:Micro', - 'callback' => $metadata, - ); - } - - $this->flags = $flags | static::$defaultFlags; - $this->setMask($mask, $metadata); - } - - - /** - * Maps HTTP request to a Request object. - * @return Nette\Application\Request|NULL - */ - public function match(Nette\Http\IRequest $httpRequest) - { - // combine with precedence: mask (params in URL-path), fixity, query, (post,) defaults - - // 1) URL MASK - $url = $httpRequest->getUrl(); - $re = $this->re; - - if ($this->type === self::HOST) { - $path = '//' . $url->getHost() . $url->getPath(); - $host = array_reverse(explode('.', $url->getHost())); - $re = strtr($re, array( - '/%basePath%/' => preg_quote($url->getBasePath(), '#'), - '%tld%' => $host[0], - '%domain%' => isset($host[1]) ? "$host[1]\\.$host[0]" : $host[0], - )); - - } elseif ($this->type === self::RELATIVE) { - $basePath = $url->getBasePath(); - if (strncmp($url->getPath(), $basePath, strlen($basePath)) !== 0) { - return NULL; - } - $path = (string) substr($url->getPath(), strlen($basePath)); - - } else { - $path = $url->getPath(); - } - - if ($path !== '') { - $path = rtrim($path, '/') . '/'; - } - - if (!$matches = Strings::match($path, $re)) { - // stop, not matched - return NULL; - } - - // deletes numeric keys, restore '-' chars - $params = array(); - foreach ($matches as $k => $v) { - if (is_string($k) && $v !== '') { - $params[str_replace('___', '-', $k)] = $v; // trick - } - } - - - // 2) CONSTANT FIXITY - foreach ($this->metadata as $name => $meta) { - if (isset($params[$name])) { - //$params[$name] = $this->flags & self::CASE_SENSITIVE === 0 ? strtolower($params[$name]) : */$params[$name]; // strtolower damages UTF-8 - - } elseif (isset($meta['fixity']) && $meta['fixity'] !== self::OPTIONAL) { - $params[$name] = NULL; // cannot be overwriten in 3) and detected by isset() in 4) - } - } - - - // 3) QUERY - if ($this->xlat) { - $params += self::renameKeys($httpRequest->getQuery(), array_flip($this->xlat)); - } else { - $params += $httpRequest->getQuery(); - } - - - // 4) APPLY FILTERS & FIXITY - foreach ($this->metadata as $name => $meta) { - if (isset($params[$name])) { - if (!is_scalar($params[$name])) { - - } elseif (isset($meta[self::FILTER_TABLE][$params[$name]])) { // applies filterTable only to scalar parameters - $params[$name] = $meta[self::FILTER_TABLE][$params[$name]]; - - } elseif (isset($meta[self::FILTER_TABLE]) && !empty($meta[self::FILTER_STRICT])) { - return NULL; // rejected by filterTable - - } elseif (isset($meta[self::FILTER_IN])) { // applies filterIn only to scalar parameters - $params[$name] = call_user_func($meta[self::FILTER_IN], (string) $params[$name]); - if ($params[$name] === NULL && !isset($meta['fixity'])) { - return NULL; // rejected by filter - } - } - - } elseif (isset($meta['fixity'])) { - $params[$name] = $meta[self::VALUE]; - } - } - - if (isset($this->metadata[NULL][self::FILTER_IN])) { - $params = call_user_func($this->metadata[NULL][self::FILTER_IN], $params); - if ($params === NULL) { - return NULL; - } - } - - // 5) BUILD Request - if (!isset($params[self::PRESENTER_KEY])) { - throw new Nette\InvalidStateException('Missing presenter in route definition.'); - } elseif (!is_string($params[self::PRESENTER_KEY])) { - return NULL; - } - if (isset($this->metadata[self::MODULE_KEY])) { - if (!isset($params[self::MODULE_KEY])) { - throw new Nette\InvalidStateException('Missing module in route definition.'); - } - $presenter = $params[self::MODULE_KEY] . ':' . $params[self::PRESENTER_KEY]; - unset($params[self::MODULE_KEY], $params[self::PRESENTER_KEY]); - - } else { - $presenter = $params[self::PRESENTER_KEY]; - unset($params[self::PRESENTER_KEY]); - } - - return new Application\Request( - $presenter, - $httpRequest->getMethod(), - $params, - $httpRequest->getPost(), - $httpRequest->getFiles(), - array(Application\Request::SECURED => $httpRequest->isSecured()) - ); - } - - - /** - * Constructs absolute URL from Request object. - * @return string|NULL - */ - public function constructUrl(Application\Request $appRequest, Nette\Http\Url $refUrl) - { - if ($this->flags & self::ONE_WAY) { - return NULL; - } - - $params = $appRequest->getParameters(); - $metadata = $this->metadata; - - $presenter = $appRequest->getPresenterName(); - $params[self::PRESENTER_KEY] = $presenter; - - if (isset($metadata[NULL][self::FILTER_OUT])) { - $params = call_user_func($metadata[NULL][self::FILTER_OUT], $params); - if ($params === NULL) { - return NULL; - } - } - - if (isset($metadata[self::MODULE_KEY])) { // try split into module and [submodule:]presenter parts - $module = $metadata[self::MODULE_KEY]; - if (isset($module['fixity']) && strncasecmp($presenter, $module[self::VALUE] . ':', strlen($module[self::VALUE]) + 1) === 0) { - $a = strlen($module[self::VALUE]); - } else { - $a = strrpos($presenter, ':'); - } - if ($a === FALSE) { - $params[self::MODULE_KEY] = ''; - } else { - $params[self::MODULE_KEY] = substr($presenter, 0, $a); - $params[self::PRESENTER_KEY] = substr($presenter, $a + 1); - } - } - - foreach ($metadata as $name => $meta) { - if (!isset($params[$name])) { - continue; // retains NULL values - } - - if (isset($meta['fixity'])) { - if ($params[$name] === FALSE) { - $params[$name] = '0'; - } - if (is_scalar($params[$name]) ? strcasecmp($params[$name], $meta[self::VALUE]) === 0 - : $params[$name] === $meta[self::VALUE] - ) { // remove default values; NULL values are retain - unset($params[$name]); - continue; - - } elseif ($meta['fixity'] === self::CONSTANT) { - return NULL; // missing or wrong parameter '$name' - } - } - - if (is_scalar($params[$name]) && isset($meta['filterTable2'][$params[$name]])) { - $params[$name] = $meta['filterTable2'][$params[$name]]; - - } elseif (isset($meta['filterTable2']) && !empty($meta[self::FILTER_STRICT])) { - return NULL; - - } elseif (isset($meta[self::FILTER_OUT])) { - $params[$name] = call_user_func($meta[self::FILTER_OUT], $params[$name]); - } - - if (isset($meta[self::PATTERN]) && !preg_match($meta[self::PATTERN], rawurldecode($params[$name]))) { - return NULL; // pattern not match - } - } - - // compositing path - $sequence = $this->sequence; - $brackets = array(); - $required = NULL; // NULL for auto-optional - $url = ''; - $i = count($sequence) - 1; - do { - $url = $sequence[$i] . $url; - if ($i === 0) { - break; - } - $i--; - - $name = $sequence[$i]; $i--; // parameter name - - if ($name === ']') { // opening optional part - $brackets[] = $url; - - } elseif ($name[0] === '[') { // closing optional part - $tmp = array_pop($brackets); - if ($required < count($brackets) + 1) { // is this level optional? - if ($name !== '[!') { // and not "required"-optional - $url = $tmp; - } - } else { - $required = count($brackets); - } - - } elseif ($name[0] === '?') { // "foo" parameter - continue; - - } elseif (isset($params[$name]) && $params[$name] != '') { // intentionally == - $required = count($brackets); // make this level required - $url = $params[$name] . $url; - unset($params[$name]); - - } elseif (isset($metadata[$name]['fixity'])) { // has default value? - if ($required === NULL && !$brackets) { // auto-optional - $url = ''; - } else { - $url = $metadata[$name]['defOut'] . $url; - } - - } else { - return NULL; // missing parameter '$name' - } - } while (TRUE); - - - // absolutize path - if ($this->type === self::RELATIVE) { - $url = '//' . $refUrl->getAuthority() . $refUrl->getBasePath() . $url; - - } elseif ($this->type === self::PATH) { - $url = '//' . $refUrl->getAuthority() . $url; - - } else { - $host = array_reverse(explode('.', $refUrl->getHost())); - $url = strtr($url, array( - '/%basePath%/' => $refUrl->getBasePath(), - '%tld%' => $host[0], - '%domain%' => isset($host[1]) ? "$host[1].$host[0]" : $host[0], - )); - } - - if (strpos($url, '//', 2) !== FALSE) { - return NULL; // TODO: implement counterpart in match() ? - } - - $url = ($this->flags & self::SECURED ? 'https:' : 'http:') . $url; - - // build query string - if ($this->xlat) { - $params = self::renameKeys($params, $this->xlat); - } - - $sep = ini_get('arg_separator.input'); - $query = http_build_query($params, '', $sep ? $sep[0] : '&'); - if ($query != '') { // intentionally == - $url .= '?' . $query; - } - - return $url; - } - - - /** - * Parse mask and array of default values; initializes object. - * @param string - * @param array - * @return void - */ - private function setMask($mask, array $metadata) - { - $this->mask = $mask; - - // detect '//host/path' vs. '/abs. path' vs. 'relative path' - if (substr($mask, 0, 2) === '//') { - $this->type = self::HOST; - - } elseif (substr($mask, 0, 1) === '/') { - $this->type = self::PATH; - - } else { - $this->type = self::RELATIVE; - } - - foreach ($metadata as $name => $meta) { - if (!is_array($meta)) { - $metadata[$name] = array(self::VALUE => $meta, 'fixity' => self::CONSTANT); - - } elseif (array_key_exists(self::VALUE, $meta)) { - $metadata[$name]['fixity'] = self::CONSTANT; - } - } - - // PARSE MASK - // or [ or ] or ?... - $parts = Strings::split($mask, '/<([^>#= ]+)(=[^># ]*)? *([^>#]*)(#?[^>\[\]]*)>|(\[!?|\]|\s*\?.*)/'); - - $this->xlat = array(); - $i = count($parts) - 1; - - // PARSE QUERY PART OF MASK - if (isset($parts[$i - 1]) && substr(ltrim($parts[$i - 1]), 0, 1) === '?') { - // name= - $matches = Strings::matchAll($parts[$i - 1], '/(?:([a-zA-Z0-9_.-]+)=)?<([^># ]+) *([^>#]*)(#?[^>]*)>/'); - - foreach ($matches as $match) { - list(, $param, $name, $pattern, $class) = $match; // $pattern is not used - - if ($class !== '') { - if (!isset(static::$styles[$class])) { - throw new Nette\InvalidStateException("Parameter '$name' has '$class' flag, but Route::\$styles['$class'] is not set."); - } - $meta = static::$styles[$class]; - - } elseif (isset(static::$styles['?' . $name])) { - $meta = static::$styles['?' . $name]; - - } else { - $meta = static::$styles['?#']; - } - - if (isset($metadata[$name])) { - $meta = $metadata[$name] + $meta; - } - - if (array_key_exists(self::VALUE, $meta)) { - $meta['fixity'] = self::OPTIONAL; - } - - unset($meta['pattern']); - $meta['filterTable2'] = empty($meta[self::FILTER_TABLE]) ? NULL : array_flip($meta[self::FILTER_TABLE]); - - $metadata[$name] = $meta; - if ($param !== '') { - $this->xlat[$name] = $param; - } - } - $i -= 6; - } - - // PARSE PATH PART OF MASK - $brackets = 0; // optional level - $re = ''; - $sequence = array(); - $autoOptional = TRUE; - do { - array_unshift($sequence, $parts[$i]); - $re = preg_quote($parts[$i], '#') . $re; - if ($i === 0) { - break; - } - $i--; - - $part = $parts[$i]; // [ or ] - if ($part === '[' || $part === ']' || $part === '[!') { - $brackets += $part[0] === '[' ? -1 : 1; - if ($brackets < 0) { - throw new Nette\InvalidArgumentException("Unexpected '$part' in mask '$mask'."); - } - array_unshift($sequence, $part); - $re = ($part[0] === '[' ? '(?:' : ')?') . $re; - $i -= 5; - continue; - } - - $class = $parts[$i]; $i--; // validation class - $pattern = trim($parts[$i]); $i--; // validation condition (as regexp) - $default = $parts[$i]; $i--; // default value - $name = $parts[$i]; $i--; // parameter name - array_unshift($sequence, $name); - - if ($name[0] === '?') { // "foo" parameter - $name = substr($name, 1); - $re = $pattern ? '(?:' . preg_quote($name, '#') . "|$pattern)$re" : preg_quote($name, '#') . $re; - $sequence[1] = $name . $sequence[1]; - continue; - } - - // check name (limitation by regexp) - if (preg_match('#[^a-z0-9_-]#i', $name)) { - throw new Nette\InvalidArgumentException("Parameter name must be alphanumeric string due to limitations of PCRE, '$name' given."); - } - - // pattern, condition & metadata - if ($class !== '') { - if (!isset(static::$styles[$class])) { - throw new Nette\InvalidStateException("Parameter '$name' has '$class' flag, but Route::\$styles['$class'] is not set."); - } - $meta = static::$styles[$class]; - - } elseif (isset(static::$styles[$name])) { - $meta = static::$styles[$name]; - - } else { - $meta = static::$styles['#']; - } - - if (isset($metadata[$name])) { - $meta = $metadata[$name] + $meta; - } - - if ($pattern == '' && isset($meta[self::PATTERN])) { - $pattern = $meta[self::PATTERN]; - } - - if ($default !== '') { - $meta[self::VALUE] = (string) substr($default, 1); - $meta['fixity'] = self::PATH_OPTIONAL; - } - - $meta['filterTable2'] = empty($meta[self::FILTER_TABLE]) ? NULL : array_flip($meta[self::FILTER_TABLE]); - if (array_key_exists(self::VALUE, $meta)) { - if (isset($meta['filterTable2'][$meta[self::VALUE]])) { - $meta['defOut'] = $meta['filterTable2'][$meta[self::VALUE]]; - - } elseif (isset($meta[self::FILTER_OUT])) { - $meta['defOut'] = call_user_func($meta[self::FILTER_OUT], $meta[self::VALUE]); - - } else { - $meta['defOut'] = $meta[self::VALUE]; - } - } - $meta[self::PATTERN] = "#(?:$pattern)\\z#A" . ($this->flags & self::CASE_SENSITIVE ? '' : 'iu'); - - // include in expression - $re = '(?P<' . str_replace('-', '___', $name) . '>(?U)' . $pattern . ')' . $re; // str_replace is dirty trick to enable '-' in parameter name - if ($brackets) { // is in brackets? - if (!isset($meta[self::VALUE])) { - $meta[self::VALUE] = $meta['defOut'] = NULL; - } - $meta['fixity'] = self::PATH_OPTIONAL; - - } elseif (!$autoOptional) { - unset($meta['fixity']); - - } elseif (isset($meta['fixity'])) { // auto-optional - $re = '(?:' . $re . ')?'; - $meta['fixity'] = self::PATH_OPTIONAL; - - } else { - $autoOptional = FALSE; - } - - $metadata[$name] = $meta; - } while (TRUE); - - if ($brackets) { - throw new Nette\InvalidArgumentException("Missing closing ']' in mask '$mask'."); - } - - $this->re = '#' . $re . '/?\z#A' . ($this->flags & self::CASE_SENSITIVE ? '' : 'iu'); - $this->metadata = $metadata; - $this->sequence = $sequence; - } - - - /** - * Returns mask. - * @return string - */ - public function getMask() - { - return $this->mask; - } - - - /** - * Returns default values. - * @return array - */ - public function getDefaults() - { - $defaults = array(); - foreach ($this->metadata as $name => $meta) { - if (isset($meta['fixity'])) { - $defaults[$name] = $meta[self::VALUE]; - } - } - return $defaults; - } - - - /** - * Returns flags. - * @return int - */ - public function getFlags() - { - return $this->flags; - } - - - /********************* Utilities ****************d*g**/ - - - /** - * Proprietary cache aim. - * @internal - * @return string|FALSE - */ - public function getTargetPresenter() - { - if ($this->flags & self::ONE_WAY) { - return FALSE; - } - - $m = $this->metadata; - $module = ''; - - if (isset($m[self::MODULE_KEY])) { - if (isset($m[self::MODULE_KEY]['fixity']) && $m[self::MODULE_KEY]['fixity'] === self::CONSTANT) { - $module = $m[self::MODULE_KEY][self::VALUE] . ':'; - } else { - return NULL; - } - } - - if (isset($m[self::PRESENTER_KEY]['fixity']) && $m[self::PRESENTER_KEY]['fixity'] === self::CONSTANT) { - return $module . $m[self::PRESENTER_KEY][self::VALUE]; - } - return NULL; - } - - - /** - * Rename keys in array. - * @param array - * @param array - * @return array - */ - private static function renameKeys($arr, $xlat) - { - if (empty($xlat)) { - return $arr; - } - - $res = array(); - $occupied = array_flip($xlat); - foreach ($arr as $k => $v) { - if (isset($xlat[$k])) { - $res[$xlat[$k]] = $v; - - } elseif (!isset($occupied[$k])) { - $res[$k] = $v; - } - } - return $res; - } - - - /********************* Inflectors ****************d*g**/ - - - /** - * camelCaseAction name -> dash-separated. - * @param string - * @return string - */ - private static function action2path($s) - { - $s = preg_replace('#(.)(?=[A-Z])#', '$1-', $s); - $s = strtolower($s); - $s = rawurlencode($s); - return $s; - } - - - /** - * dash-separated -> camelCaseAction name. - * @param string - * @return string - */ - private static function path2action($s) - { - $s = strtolower($s); - $s = preg_replace('#-(?=[a-z])#', ' ', $s); - $s = substr(ucwords('x' . $s), 1); - //$s = lcfirst(ucwords($s)); - $s = str_replace(' ', '', $s); - return $s; - } - - - /** - * PascalCase:Presenter name -> dash-and-dot-separated. - * @param string - * @return string - */ - private static function presenter2path($s) - { - $s = strtr($s, ':', '.'); - $s = preg_replace('#([^.])(?=[A-Z])#', '$1-', $s); - $s = strtolower($s); - $s = rawurlencode($s); - return $s; - } - - - /** - * dash-and-dot-separated -> PascalCase:Presenter name. - * @param string - * @return string - */ - private static function path2presenter($s) - { - $s = strtolower($s); - $s = preg_replace('#([.-])(?=[a-z])#', '$1 ', $s); - $s = ucwords($s); - $s = str_replace('. ', ':', $s); - $s = str_replace('- ', '', $s); - return $s; - } - - - /** - * Url encode. - * @param string - * @return string - */ - private static function param2path($s) - { - return str_replace('%2F', '/', rawurlencode($s)); - } - - - /********************* Route::$styles manipulator ****************d*g**/ - - - /** - * Creates new style. - * @param string style name (#style, urlParameter, ?queryParameter) - * @param string optional parent style name - * @return void - */ - public static function addStyle($style, $parent = '#') - { - if (isset(static::$styles[$style])) { - throw new Nette\InvalidArgumentException("Style '$style' already exists."); - } - - if ($parent !== NULL) { - if (!isset(static::$styles[$parent])) { - throw new Nette\InvalidArgumentException("Parent style '$parent' doesn't exist."); - } - static::$styles[$style] = static::$styles[$parent]; - - } else { - static::$styles[$style] = array(); - } - } - - - /** - * Changes style property value. - * @param string style name (#style, urlParameter, ?queryParameter) - * @param string property name (Route::PATTERN, Route::FILTER_IN, Route::FILTER_OUT, Route::FILTER_TABLE) - * @param mixed property value - * @return void - */ - public static function setStyleProperty($style, $key, $value) - { - if (!isset(static::$styles[$style])) { - throw new Nette\InvalidArgumentException("Style '$style' doesn't exist."); - } - static::$styles[$style][$key] = $value; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/Routers/SimpleRouter.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/Routers/SimpleRouter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/Routers/SimpleRouter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/Routers/SimpleRouter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ - substr($defaults, 0, $a), - 'action' => $a === strlen($defaults) - 1 ? Application\UI\Presenter::DEFAULT_ACTION : substr($defaults, $a + 1), - ); - } - - if (isset($defaults[self::MODULE_KEY])) { - $this->module = $defaults[self::MODULE_KEY] . ':'; - unset($defaults[self::MODULE_KEY]); - } - - $this->defaults = $defaults; - $this->flags = $flags; - } - - - /** - * Maps HTTP request to a Request object. - * @return Nette\Application\Request|NULL - */ - public function match(Nette\Http\IRequest $httpRequest) - { - if ($httpRequest->getUrl()->getPathInfo() !== '') { - return NULL; - } - // combine with precedence: get, (post,) defaults - $params = $httpRequest->getQuery(); - $params += $this->defaults; - - if (!isset($params[self::PRESENTER_KEY]) || !is_string($params[self::PRESENTER_KEY])) { - return NULL; - } - - $presenter = $this->module . $params[self::PRESENTER_KEY]; - unset($params[self::PRESENTER_KEY]); - - return new Application\Request( - $presenter, - $httpRequest->getMethod(), - $params, - $httpRequest->getPost(), - $httpRequest->getFiles(), - array(Application\Request::SECURED => $httpRequest->isSecured()) - ); - } - - - /** - * Constructs absolute URL from Request object. - * @return string|NULL - */ - public function constructUrl(Application\Request $appRequest, Nette\Http\Url $refUrl) - { - if ($this->flags & self::ONE_WAY) { - return NULL; - } - $params = $appRequest->getParameters(); - - // presenter name - $presenter = $appRequest->getPresenterName(); - if (strncasecmp($presenter, $this->module, strlen($this->module)) === 0) { - $params[self::PRESENTER_KEY] = substr($presenter, strlen($this->module)); - } else { - return NULL; - } - - // remove default values; NULL values are retain - foreach ($this->defaults as $key => $value) { - if (isset($params[$key]) && $params[$key] == $value) { // intentionally == - unset($params[$key]); - } - } - - $url = ($this->flags & self::SECURED ? 'https://' : 'http://') . $refUrl->getAuthority() . $refUrl->getPath(); - $sep = ini_get('arg_separator.input'); - $query = http_build_query($params, '', $sep ? $sep[0] : '&'); - if ($query != '') { // intentionally == - $url .= '?' . $query; - } - return $url; - } - - - /** - * Returns default values. - * @return array - */ - public function getDefaults() - { - return $this->defaults; - } - - - /** - * Returns flags. - * @return int - */ - public function getFlags() - { - return $this->flags; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/templates/error.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Application/templates/error.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/templates/error.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/templates/error.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ - array('Oops...', 'Your browser sent a request that this server could not understand or process.'), - 403 => array('Access Denied', 'You do not have permission to view this page. Please try contact the web site administrator if you believe you should be able to view this page.'), - 404 => array('Page Not Found', 'The page you requested could not be found. It is possible that the address is incorrect, or that the page no longer exists. Please use a search engine to find what you are looking for.'), - 405 => array('Method Not Allowed', 'The requested method is not allowed for the URL.'), - 410 => array('Page Not Found', 'The page you requested has been taken off the site. We apologize for the inconvenience.'), - 500 => array('Server Error', 'We\'re sorry! The server encountered an internal error and was unable to complete your request. Please try again later.'), -); -$message = isset($messages[$code]) ? $messages[$code] : $messages[0]; - -?> - - - - - - -<?php echo $message[0] ?> - -

- -

- -

error

diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/BadSignalException.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/BadSignalException.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/BadSignalException.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/BadSignalException.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -template === NULL) { - $value = $this->createTemplate(); - if (!$value instanceof Nette\Templating\ITemplate && $value !== NULL) { - $class2 = get_class($value); $class = get_class($this); - throw new Nette\UnexpectedValueException("Object returned by $class::createTemplate() must be instance of Nette\\Templating\\ITemplate, '$class2' given."); - } - $this->template = $value; - } - return $this->template; - } - - - /** - * @param string|NULL - * @return Nette\Templating\ITemplate - */ - protected function createTemplate($class = NULL) - { - $template = $class ? new $class : new Nette\Templating\FileTemplate; - $presenter = $this->getPresenter(FALSE); - $template->onPrepareFilters[] = $this->templatePrepareFilters; - $template->registerHelperLoader('Nette\Templating\Helpers::loader'); - - // default parameters - $template->control = $template->_control = $this; - $template->presenter = $template->_presenter = $presenter; - if ($presenter instanceof Presenter) { - $template->setCacheStorage($presenter->getContext()->getService('nette.templateCacheStorage')); - $template->user = $presenter->getUser(); - $template->netteHttpResponse = $presenter->getHttpResponse(); - $template->netteCacheStorage = $presenter->getContext()->getByType('Nette\Caching\IStorage'); - $template->baseUri = $template->baseUrl = rtrim($presenter->getHttpRequest()->getUrl()->getBaseUrl(), '/'); - $template->basePath = preg_replace('#https?://[^/]+#A', '', $template->baseUrl); - - // flash message - if ($presenter->hasFlashSession()) { - $id = $this->getParameterId('flash'); - $template->flashes = $presenter->getFlashSession()->$id; - } - } - if (!isset($template->flashes) || !is_array($template->flashes)) { - $template->flashes = array(); - } - - return $template; - } - - - /** - * Descendant can override this method to customize template compile-time filters. - * @param Nette\Templating\Template - * @return void - */ - public function templatePrepareFilters($template) - { - $template->registerFilter($this->getPresenter()->getContext()->createService('nette.latte')); - } - - - /** - * Saves the message to template, that can be displayed after redirect. - * @param string - * @param string - * @return \stdClass - */ - public function flashMessage($message, $type = 'info') - { - $id = $this->getParameterId('flash'); - $messages = $this->getPresenter()->getFlashSession()->$id; - $messages[] = $flash = (object) array( - 'message' => $message, - 'type' => $type, - ); - $this->getTemplate()->flashes = $messages; - $this->getPresenter()->getFlashSession()->$id = $messages; - return $flash; - } - - - /********************* rendering ****************d*g**/ - - - /** - * Forces control or its snippet to repaint. - * @return void - */ - public function redrawControl($snippet = NULL, $redraw = TRUE) - { - if ($redraw) { - $this->invalidSnippets[$snippet] = TRUE; - - } elseif ($snippet === NULL) { - $this->invalidSnippets = array(); - - } else { - unset($this->invalidSnippets[$snippet]); - } - } - - - /** @deprecated */ - function invalidateControl($snippet = NULL) - { - $this->redrawControl($snippet); - } - - /** @deprecated */ - function validateControl($snippet = NULL) - { - $this->redrawControl($snippet, FALSE); - } - - - /** - * Is required to repaint the control or its snippet? - * @param string snippet name - * @return bool - */ - public function isControlInvalid($snippet = NULL) - { - if ($snippet === NULL) { - if (count($this->invalidSnippets) > 0) { - return TRUE; - - } else { - $queue = array($this); - do { - foreach (array_shift($queue)->getComponents() as $component) { - if ($component instanceof IRenderable) { - if ($component->isControlInvalid()) { - // $this->invalidSnippets['__child'] = TRUE; // as cache - return TRUE; - } - - } elseif ($component instanceof Nette\ComponentModel\IContainer) { - $queue[] = $component; - } - } - } while ($queue); - - return FALSE; - } - - } else { - return isset($this->invalidSnippets[NULL]) || isset($this->invalidSnippets[$snippet]); - } - } - - - /** - * Returns snippet HTML ID. - * @param string snippet name - * @return string - */ - public function getSnippetId($name = NULL) - { - // HTML 4 ID & NAME: [A-Za-z][A-Za-z0-9:_.-]* - return 'snippet-' . $this->getUniqueId() . '-' . $name; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/Form.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/Form.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/Form.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/Form.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,137 +0,0 @@ -monitor('Nette\Application\UI\Presenter'); - if ($parent !== NULL) { - $parent->addComponent($this, $name); - } - } - - - /** - * Returns the presenter where this component belongs to. - * @param bool throw exception if presenter doesn't exist? - * @return Presenter|NULL - */ - public function getPresenter($need = TRUE) - { - return $this->lookup('Nette\Application\UI\Presenter', $need); - } - - - /** - * This method will be called when the component (or component's parent) - * becomes attached to a monitored object. Do not call this method yourself. - * @param Nette\ComponentModel\IComponent - * @return void - */ - protected function attached($presenter) - { - if ($presenter instanceof Presenter) { - $name = $this->lookupPath('Nette\Application\UI\Presenter'); - - if (!isset($this->getElementPrototype()->id)) { - $this->getElementPrototype()->id = 'frm-' . $name; - } - - if (!$this->getAction()) { - $this->setAction(new Link( - $presenter, - $name . self::NAME_SEPARATOR . 'submit!', - array() - )); - } - - if (iterator_count($this->getControls()) && $this->isSubmitted()) { - foreach ($this->getControls() as $control) { - if (!$control->isDisabled()) { - $control->loadHttpData(); - } - } - } - } - parent::attached($presenter); - } - - - /** - * Tells if the form is anchored. - * @return bool - */ - public function isAnchored() - { - return (bool) $this->getPresenter(FALSE); - } - - - /** - * Internal: returns submitted HTTP data or NULL when form was not submitted. - * @return array|NULL - */ - protected function receiveHttpData() - { - $presenter = $this->getPresenter(); - if (!$presenter->isSignalReceiver($this, 'submit')) { - return; - } - - $isPost = $this->getMethod() === self::POST; - $request = $presenter->getRequest(); - if ($request->isMethod('forward') || $request->isMethod('post') !== $isPost) { - return; - } - - if ($isPost) { - return Nette\Utils\Arrays::mergeTree($request->getPost(), $request->getFiles()); - } else { - return $request->getParameters(); - } - } - - - /********************* interface ISignalReceiver ****************d*g**/ - - - /** - * This method is called by presenter. - * @param string - * @return void - */ - public function signalReceived($signal) - { - if ($signal === 'submit') { - if (!$this->getPresenter()->getRequest()->hasFlag(Nette\Application\Request::RESTORED)) { - $this->fireEvents(); - } - } else { - $class = get_class($this); - throw new BadSignalException("Missing handler for signal '$signal' in $class."); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/InvalidLinkException.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/InvalidLinkException.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/InvalidLinkException.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/InvalidLinkException.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -component = $component; - $this->destination = $destination; - $this->params = $params; - } - - - /** - * Returns link destination. - * @return string - */ - public function getDestination() - { - return $this->destination; - } - - - /** - * Changes link parameter. - * @param string - * @param mixed - * @return self - */ - public function setParameter($key, $value) - { - $this->params[$key] = $value; - return $this; - } - - - /** - * Returns link parameter. - * @param string - * @return mixed - */ - public function getParameter($key) - { - return isset($this->params[$key]) ? $this->params[$key] : NULL; - } - - - /** - * Returns link parameters. - * @return array - */ - public function getParameters() - { - return $this->params; - } - - - /** - * Converts link to URL. - * @return string - */ - public function __toString() - { - try { - return (string) $this->component->link($this->destination, $this->params); - - } catch (\Exception $e) { - if (func_num_args()) { - throw $e; - } - trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/Multiplier.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/Multiplier.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/Multiplier.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/Multiplier.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -factory = Nette\Utils\Callback::check($factory); - } - - - protected function createComponent($name) - { - return call_user_func($this->factory, $name, $this); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/PresenterComponent.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/PresenterComponent.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/PresenterComponent.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/PresenterComponent.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,402 +0,0 @@ -lookup('Nette\Application\UI\Presenter', $need); - } - - - /** - * Returns a fully-qualified name that uniquely identifies the component - * within the presenter hierarchy. - * @return string - */ - public function getUniqueId() - { - return $this->lookupPath('Nette\Application\UI\Presenter', TRUE); - } - - - /** - * This method will be called when the component (or component's parent) - * becomes attached to a monitored object. Do not call this method yourself. - * @param Nette\ComponentModel\IComponent - * @return void - */ - protected function attached($presenter) - { - if ($presenter instanceof Presenter) { - $this->loadState($presenter->popGlobalParameters($this->getUniqueId())); - } - } - - - /** - * @return void - */ - protected function validateParent(Nette\ComponentModel\IContainer $parent) - { - parent::validateParent($parent); - $this->monitor('Nette\Application\UI\Presenter'); - } - - - /** - * Calls public method if exists. - * @param string - * @param array - * @return bool does method exist? - */ - protected function tryCall($method, array $params) - { - $rc = $this->getReflection(); - if ($rc->hasMethod($method)) { - $rm = $rc->getMethod($method); - if ($rm->isPublic() && !$rm->isAbstract() && !$rm->isStatic()) { - $this->checkRequirements($rm); - $rm->invokeArgs($this, $rc->combineArgs($rm, $params)); - return TRUE; - } - } - return FALSE; - } - - - /** - * Checks for requirements such as authorization. - * @return void - */ - public function checkRequirements($element) - { - } - - - /** - * Access to reflection. - * @return PresenterComponentReflection - */ - public static function getReflection() - { - return new PresenterComponentReflection(get_called_class()); - } - - - /********************* interface IStatePersistent ****************d*g**/ - - - /** - * Loads state informations. - * @param array - * @return void - */ - public function loadState(array $params) - { - $reflection = $this->getReflection(); - foreach ($reflection->getPersistentParams() as $name => $meta) { - if (isset($params[$name])) { // NULLs are ignored - $type = gettype($meta['def']); - if (!$reflection->convertType($params[$name], $type)) { - throw new Nette\Application\BadRequestException("Invalid value for persistent parameter '$name' in '{$this->getName()}', expected " . ($type === 'NULL' ? 'scalar' : $type) . "."); - } - $this->$name = & $params[$name]; - } else { - $params[$name] = & $this->$name; - } - } - $this->params = $params; - } - - - /** - * Saves state informations for next request. - * @param array - * @param PresenterComponentReflection (internal, used by Presenter) - * @return void - */ - public function saveState(array & $params, $reflection = NULL) - { - $reflection = $reflection === NULL ? $this->getReflection() : $reflection; - foreach ($reflection->getPersistentParams() as $name => $meta) { - - if (isset($params[$name])) { - // injected value - - } elseif (array_key_exists($name, $params)) { // NULLs are skipped - continue; - - } elseif (!isset($meta['since']) || $this instanceof $meta['since']) { - $params[$name] = $this->$name; // object property value - - } else { - continue; // ignored parameter - } - - $type = gettype($meta['def']); - if (!PresenterComponentReflection::convertType($params[$name], $type)) { - throw new InvalidLinkException(sprintf("Invalid value for persistent parameter '%s' in '%s', expected %s.", $name, $this->getName(), $type === 'NULL' ? 'scalar' : $type)); - } - - if ($params[$name] === $meta['def'] || ($meta['def'] === NULL && is_scalar($params[$name]) && (string) $params[$name] === '')) { - $params[$name] = NULL; // value transmit is unnecessary - } - } - } - - - /** - * Returns component param. - * @param string key - * @param mixed default value - * @return mixed - */ - public function getParameter($name = NULL, $default = NULL) - { - if (func_num_args() === 0) { - trigger_error('Calling ' . __METHOD__ . ' with no arguments to get all parameters is deprecated, use getParameters() instead.', E_USER_DEPRECATED); - return $this->params; - - } elseif (isset($this->params[$name])) { - return $this->params[$name]; - - } else { - return $default; - } - } - - - /** - * Returns component parameters. - * @return array - */ - public function getParameters() - { - return $this->params; - } - - - /** - * Returns a fully-qualified name that uniquely identifies the parameter. - * @param string - * @return string - */ - public function getParameterId($name) - { - $uid = $this->getUniqueId(); - return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name; - } - - - /** @deprecated */ - function getParam($name = NULL, $default = NULL) - { - //trigger_error(__METHOD__ . '() is deprecated; use getParameter() instead.', E_USER_DEPRECATED); - return func_num_args() ? $this->getParameter($name, $default) : $this->getParameter(); - } - - - /** - * Returns array of classes persistent parameters. They have public visibility and are non-static. - * This default implementation detects persistent parameters by annotation @persistent. - * @return array - */ - public static function getPersistentParams() - { - $rc = new Nette\Reflection\ClassType(get_called_class()); - $params = array(); - foreach ($rc->getProperties(\ReflectionProperty::IS_PUBLIC) as $rp) { - if (!$rp->isStatic() && $rp->hasAnnotation('persistent')) { - $params[] = $rp->getName(); - } - } - return $params; - } - - - /********************* interface ISignalReceiver ****************d*g**/ - - - /** - * Calls signal handler method. - * @param string - * @return void - * @throws BadSignalException if there is not handler method - */ - public function signalReceived($signal) - { - if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) { - $class = get_class($this); - throw new BadSignalException("There is no handler for signal '$signal' in class $class."); - } - } - - - /** - * Formats signal handler method name -> case sensitivity doesn't matter. - * @param string - * @return string - */ - public static function formatSignalMethod($signal) - { - return $signal == NULL ? NULL : 'handle' . $signal; // intentionally == - } - - - /********************* navigation ****************d*g**/ - - - /** - * Generates URL to presenter, action or signal. - * @param string destination in format "[[module:]presenter:]action" or "signal!" or "this" - * @param array|mixed - * @return string - * @throws InvalidLinkException - */ - public function link($destination, $args = array()) - { - try { - return $this->getPresenter()->createRequest($this, $destination, is_array($args) ? $args : array_slice(func_get_args(), 1), 'link'); - - } catch (InvalidLinkException $e) { - return $this->getPresenter()->handleInvalidLink($e); - } - } - - - /** - * Returns destination as Link object. - * @param string destination in format "[[module:]presenter:]view" or "signal!" - * @param array|mixed - * @return Link - */ - public function lazyLink($destination, $args = array()) - { - return new Link($this, $destination, is_array($args) ? $args : array_slice(func_get_args(), 1)); - } - - - /** - * Determines whether it links to the current page. - * @param string destination in format "[[module:]presenter:]action" or "signal!" or "this" - * @param array|mixed - * @return bool - * @throws InvalidLinkException - */ - public function isLinkCurrent($destination = NULL, $args = array()) - { - if ($destination !== NULL) { - $this->getPresenter()->createRequest($this, $destination, is_array($args) ? $args : array_slice(func_get_args(), 1), 'test'); - } - return $this->getPresenter()->getLastCreatedRequestFlag('current'); - } - - - /** - * Redirect to another presenter, action or signal. - * @param int [optional] HTTP error code - * @param string destination in format "[[module:]presenter:]view" or "signal!" - * @param array|mixed - * @return void - * @throws Nette\Application\AbortException - */ - public function redirect($code, $destination = NULL, $args = array()) - { - if (!is_numeric($code)) { // first parameter is optional - $args = $destination; - $destination = $code; - $code = NULL; - } - - if (!is_array($args)) { - $args = array_slice(func_get_args(), is_numeric($code) ? 2 : 1); - } - - $presenter = $this->getPresenter(); - $presenter->redirectUrl($presenter->createRequest($this, $destination, $args, 'redirect'), $code); - } - - - /********************* interface \ArrayAccess ****************d*g**/ - - - /** - * Adds the component to the container. - * @param string component name - * @param Nette\ComponentModel\IComponent - * @return void - */ - public function offsetSet($name, $component) - { - $this->addComponent($component, $name); - } - - - /** - * Returns component specified by name. Throws exception if component doesn't exist. - * @param string component name - * @return Nette\ComponentModel\IComponent - * @throws Nette\InvalidArgumentException - */ - public function offsetGet($name) - { - return $this->getComponent($name, TRUE); - } - - - /** - * Does component specified by name exists? - * @param string component name - * @return bool - */ - public function offsetExists($name) - { - return $this->getComponent($name, FALSE) !== NULL; - } - - - /** - * Removes component from the container. - * @param string component name - * @return void - */ - public function offsetUnset($name) - { - $component = $this->getComponent($name, FALSE); - if ($component !== NULL) { - $this->removeComponent($component); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/PresenterComponentReflection.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/PresenterComponentReflection.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/PresenterComponentReflection.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/PresenterComponentReflection.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,165 +0,0 @@ -getName() : $class; // TODO - $params = & self::$ppCache[$class]; - if ($params !== NULL) { - return $params; - } - $params = array(); - if (is_subclass_of($class, 'Nette\Application\UI\PresenterComponent')) { - $defaults = get_class_vars($class); - foreach ($class::getPersistentParams() as $name => $default) { - if (is_int($name)) { - $name = $default; - $default = $defaults[$name]; - } - $params[$name] = array( - 'def' => $default, - 'since' => $class, - ); - } - foreach ($this->getPersistentParams(get_parent_class($class)) as $name => $param) { - if (isset($params[$name])) { - $params[$name]['since'] = $param['since']; - continue; - } - - $params[$name] = $param; - } - } - return $params; - } - - - /** - * @param string|NULL - * @return array of persistent components. - */ - public function getPersistentComponents($class = NULL) - { - $class = $class === NULL ? $this->getName() : $class; - $components = & self::$pcCache[$class]; - if ($components !== NULL) { - return $components; - } - $components = array(); - if (is_subclass_of($class, 'Nette\Application\UI\Presenter')) { - foreach ($class::getPersistentComponents() as $name => $meta) { - if (is_string($meta)) { - $name = $meta; - } - $components[$name] = array('since' => $class); - } - $components = $this->getPersistentComponents(get_parent_class($class)) + $components; - } - return $components; - } - - - /** - * Is a method callable? It means class is instantiable and method has - * public visibility, is non-static and non-abstract. - * @param string method name - * @return bool - */ - public function hasCallableMethod($method) - { - $class = $this->getName(); - $cache = & self::$mcCache[strtolower($class . ':' . $method)]; - if ($cache === NULL) try { - $cache = FALSE; - $rm = Nette\Reflection\Method::from($class, $method); - $cache = $this->isInstantiable() && $rm->isPublic() && !$rm->isAbstract() && !$rm->isStatic(); - } catch (\ReflectionException $e) { - } - return $cache; - } - - - /** - * @return array - */ - public static function combineArgs(\ReflectionFunctionAbstract $method, $args) - { - $res = array(); - $i = 0; - foreach ($method->getParameters() as $param) { - $name = $param->getName(); - if (isset($args[$name])) { // NULLs are ignored - $res[$i++] = $args[$name]; - $type = $param->isArray() ? 'array' : ($param->isDefaultValueAvailable() && $param->isOptional() ? gettype($param->getDefaultValue()) : 'NULL'); - if (!self::convertType($res[$i-1], $type)) { - $mName = $method instanceof \ReflectionMethod ? $method->getDeclaringClass()->getName() . '::' . $method->getName() : $method->getName(); - throw new BadRequestException("Invalid value for parameter '$name' in method $mName(), expected " . ($type === 'NULL' ? 'scalar' : $type) . "."); - } - } else { - $res[$i++] = $param->isDefaultValueAvailable() && $param->isOptional() ? $param->getDefaultValue() : ($param->isArray() ? array() : NULL); - } - } - return $res; - } - - - /** - * Non data-loss type conversion. - * @param mixed - * @param string - * @return bool - */ - public static function convertType(& $val, $type) - { - if ($val === NULL || is_object($val)) { - // ignore - } elseif ($type === 'array') { - if (!is_array($val)) { - return FALSE; - } - } elseif (!is_scalar($val)) { - return FALSE; - - } elseif ($type !== 'NULL') { - $old = $val = ($val === FALSE ? '0' : (string) $val); - settype($val, $type); - if ($old !== ($val === FALSE ? '0' : (string) $val)) { - return FALSE; // data-loss occurs - } - } - return TRUE; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/Presenter.php php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/Presenter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Application/UI/Presenter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Application/UI/Presenter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,1396 +0,0 @@ -request; - } - - - /** - * Returns self. - * @return Presenter - */ - public function getPresenter($need = TRUE) - { - return $this; - } - - - /** - * Returns a name that uniquely identifies component. - * @return string - */ - public function getUniqueId() - { - return ''; - } - - - /********************* interface IPresenter ****************d*g**/ - - - /** - * @return Nette\Application\IResponse - */ - public function run(Application\Request $request) - { - try { - // STARTUP - $this->request = $request; - $this->payload = new \stdClass; - $this->setParent($this->getParent(), $request->getPresenterName()); - - if (!$this->httpResponse->isSent()) { - $this->httpResponse->addHeader('Vary', 'X-Requested-With'); - } - - $this->initGlobalParameters(); - $this->checkRequirements($this->getReflection()); - $this->startup(); - if (!$this->startupCheck) { - $class = $this->getReflection()->getMethod('startup')->getDeclaringClass()->getName(); - throw new Nette\InvalidStateException("Method $class::startup() or its descendant doesn't call parent::startup()."); - } - // calls $this->action() - $this->tryCall($this->formatActionMethod($this->action), $this->params); - - // autoload components - foreach ($this->globalParams as $id => $foo) { - $this->getComponent($id, FALSE); - } - - if ($this->autoCanonicalize) { - $this->canonicalize(); - } - if ($this->httpRequest->isMethod('head')) { - $this->terminate(); - } - - // SIGNAL HANDLING - // calls $this->handle() - $this->processSignal(); - - // RENDERING VIEW - $this->beforeRender(); - // calls $this->render() - $this->tryCall($this->formatRenderMethod($this->view), $this->params); - $this->afterRender(); - - // save component tree persistent state - $this->saveGlobalState(); - if ($this->isAjax()) { - $this->payload->state = $this->getGlobalState(); - } - - // finish template rendering - $this->sendTemplate(); - - } catch (Application\AbortException $e) { - // continue with shutting down - if ($this->isAjax()) try { - $hasPayload = (array) $this->payload; unset($hasPayload['state']); - if ($this->response instanceof Responses\TextResponse && $this->isControlInvalid()) { // snippets - TODO - $this->snippetMode = TRUE; - $this->response->send($this->httpRequest, $this->httpResponse); - $this->sendPayload(); - - } elseif (!$this->response && $hasPayload) { // back compatibility for use terminate() instead of sendPayload() - $this->sendPayload(); - } - } catch (Application\AbortException $e) { } - - if ($this->hasFlashSession()) { - $this->getFlashSession()->setExpiration($this->response instanceof Responses\RedirectResponse ? '+ 30 seconds' : '+ 3 seconds'); - } - - // SHUTDOWN - $this->onShutdown($this, $this->response); - $this->shutdown($this->response); - - return $this->response; - } - } - - - /** - * @return void - */ - protected function startup() - { - $this->startupCheck = TRUE; - } - - - /** - * Common render method. - * @return void - */ - protected function beforeRender() - { - } - - - /** - * Common render method. - * @return void - */ - protected function afterRender() - { - } - - - /** - * @param Nette\Application\IResponse - * @return void - */ - protected function shutdown($response) - { - } - - - /** - * Checks authorization. - * @return void - */ - public function checkRequirements($element) - { - $user = (array) $element->getAnnotation('User'); - if (in_array('loggedIn', $user) && !$this->user->isLoggedIn()) { - throw new Application\ForbiddenRequestException; - } - } - - - /********************* signal handling ****************d*g**/ - - - /** - * @return void - * @throws BadSignalException - */ - public function processSignal() - { - if ($this->signal === NULL) { - return; - } - - try { - $component = $this->signalReceiver === '' ? $this : $this->getComponent($this->signalReceiver, FALSE); - } catch (Nette\InvalidArgumentException $e) {} - - if (isset($e) || $component === NULL) { - throw new BadSignalException("The signal receiver component '$this->signalReceiver' is not found.", NULL, isset($e) ? $e : NULL); - - } elseif (!$component instanceof ISignalReceiver) { - throw new BadSignalException("The signal receiver component '$this->signalReceiver' is not ISignalReceiver implementor."); - } - - $component->signalReceived($this->signal); - $this->signal = NULL; - } - - - /** - * Returns pair signal receiver and name. - * @return array|NULL - */ - public function getSignal() - { - return $this->signal === NULL ? NULL : array($this->signalReceiver, $this->signal); - } - - - /** - * Checks if the signal receiver is the given one. - * @param mixed component or its id - * @param string signal name (optional) - * @return bool - */ - public function isSignalReceiver($component, $signal = NULL) - { - if ($component instanceof Nette\ComponentModel\Component) { - $component = $component === $this ? '' : $component->lookupPath(__CLASS__, TRUE); - } - - if ($this->signal === NULL) { - return FALSE; - - } elseif ($signal === TRUE) { - return $component === '' - || strncmp($this->signalReceiver . '-', $component . '-', strlen($component) + 1) === 0; - - } elseif ($signal === NULL) { - return $this->signalReceiver === $component; - - } else { - return $this->signalReceiver === $component && strcasecmp($signal, $this->signal) === 0; - } - } - - - /********************* rendering ****************d*g**/ - - - /** - * Returns current action name. - * @return string - */ - public function getAction($fullyQualified = FALSE) - { - return $fullyQualified ? ':' . $this->getName() . ':' . $this->action : $this->action; - } - - - /** - * Changes current action. Only alphanumeric characters are allowed. - * @param string - * @return void - */ - public function changeAction($action) - { - if (is_string($action) && Nette\Utils\Strings::match($action, '#^[a-zA-Z0-9][a-zA-Z0-9_\x7f-\xff]*\z#')) { - $this->action = $action; - $this->view = $action; - - } else { - $this->error('Action name is not alphanumeric string.'); - } - } - - - /** - * Returns current view. - * @return string - */ - public function getView() - { - return $this->view; - } - - - /** - * Changes current view. Any name is allowed. - * @param string - * @return self - */ - public function setView($view) - { - $this->view = (string) $view; - return $this; - } - - - /** - * Returns current layout name. - * @return string|FALSE - */ - public function getLayout() - { - return $this->layout; - } - - - /** - * Changes or disables layout. - * @param string|FALSE - * @return self - */ - public function setLayout($layout) - { - $this->layout = $layout === FALSE ? FALSE : (string) $layout; - return $this; - } - - - /** - * @return void - * @throws Nette\Application\BadRequestException if no template found - * @throws Nette\Application\AbortException - */ - public function sendTemplate() - { - $template = $this->getTemplate(); - if (!$template) { - return; - } - - if ($template instanceof Nette\Templating\IFileTemplate && !$template->getFile()) { // content template - $files = $this->formatTemplateFiles(); - foreach ($files as $file) { - if (is_file($file)) { - $template->setFile($file); - break; - } - } - - if (!$template->getFile()) { - $file = preg_replace('#^.*([/\\\\].{1,70})\z#U', "\xE2\x80\xA6\$1", reset($files)); - $file = strtr($file, '/', DIRECTORY_SEPARATOR); - $this->error("Page not found. Missing template '$file'."); - } - } - - $this->sendResponse(new Responses\TextResponse($template)); - } - - - /** - * Finds layout template file name. - * @return string - */ - public function findLayoutTemplateFile() - { - if ($this->layout === FALSE) { - return; - } - $files = $this->formatLayoutTemplateFiles(); - foreach ($files as $file) { - if (is_file($file)) { - return $file; - } - } - - if ($this->layout) { - $file = preg_replace('#^.*([/\\\\].{1,70})\z#U', "\xE2\x80\xA6\$1", reset($files)); - $file = strtr($file, '/', DIRECTORY_SEPARATOR); - throw new Nette\FileNotFoundException("Layout not found. Missing template '$file'."); - } - } - - - /** - * Formats layout template file names. - * @return array - */ - public function formatLayoutTemplateFiles() - { - $name = $this->getName(); - $presenter = substr($name, strrpos(':' . $name, ':')); - $layout = $this->layout ? $this->layout : 'layout'; - $dir = dirname($this->getReflection()->getFileName()); - $dir = is_dir("$dir/templates") ? $dir : dirname($dir); - $list = array( - "$dir/templates/$presenter/@$layout.latte", - "$dir/templates/$presenter.@$layout.latte", - "$dir/templates/$presenter/@$layout.phtml", - "$dir/templates/$presenter.@$layout.phtml", - ); - do { - $list[] = "$dir/templates/@$layout.latte"; - $list[] = "$dir/templates/@$layout.phtml"; - $dir = dirname($dir); - } while ($dir && ($name = substr($name, 0, strrpos($name, ':')))); - return $list; - } - - - /** - * Formats view template file names. - * @return array - */ - public function formatTemplateFiles() - { - $name = $this->getName(); - $presenter = substr($name, strrpos(':' . $name, ':')); - $dir = dirname($this->getReflection()->getFileName()); - $dir = is_dir("$dir/templates") ? $dir : dirname($dir); - return array( - "$dir/templates/$presenter/$this->view.latte", - "$dir/templates/$presenter.$this->view.latte", - "$dir/templates/$presenter/$this->view.phtml", - "$dir/templates/$presenter.$this->view.phtml", - ); - } - - - /** - * Formats action method name. - * @param string - * @return string - */ - public static function formatActionMethod($action) - { - return 'action' . $action; - } - - - /** - * Formats render view method name. - * @param string - * @return string - */ - public static function formatRenderMethod($view) - { - return 'render' . $view; - } - - - /********************* partial AJAX rendering ****************d*g**/ - - - /** - * @return \stdClass - */ - public function getPayload() - { - return $this->payload; - } - - - /** - * Is AJAX request? - * @return bool - */ - public function isAjax() - { - if ($this->ajaxMode === NULL) { - $this->ajaxMode = $this->httpRequest->isAjax(); - } - return $this->ajaxMode; - } - - - /** - * Sends AJAX payload to the output. - * @return void - * @throws Nette\Application\AbortException - */ - public function sendPayload() - { - $this->sendResponse(new Responses\JsonResponse($this->payload)); - } - - - /** - * Sends JSON data to the output. - * @param mixed $data - * @return void - * @throws Nette\Application\AbortException - */ - public function sendJson($data) - { - $this->sendResponse(new Responses\JsonResponse($data)); - } - - - /********************* navigation & flow ****************d*g**/ - - - /** - * Sends response and terminates presenter. - * @return void - * @throws Nette\Application\AbortException - */ - public function sendResponse(Application\IResponse $response) - { - $this->response = $response; - $this->terminate(); - } - - - /** - * Correctly terminates presenter. - * @return void - * @throws Nette\Application\AbortException - */ - public function terminate() - { - if (func_num_args() !== 0) { - trigger_error(__METHOD__ . ' is not intended to send a Application\Response; use sendResponse() instead.', E_USER_WARNING); - $this->sendResponse(func_get_arg(0)); - } - throw new Application\AbortException(); - } - - - /** - * Forward to another presenter or action. - * @param string|Request - * @param array|mixed - * @return void - * @throws Nette\Application\AbortException - */ - public function forward($destination, $args = array()) - { - if ($destination instanceof Application\Request) { - $this->sendResponse(new Responses\ForwardResponse($destination)); - } - - $this->createRequest($this, $destination, is_array($args) ? $args : array_slice(func_get_args(), 1), 'forward'); - $this->sendResponse(new Responses\ForwardResponse($this->lastCreatedRequest)); - } - - - /** - * Redirect to another URL and ends presenter execution. - * @param string - * @param int HTTP error code - * @return void - * @throws Nette\Application\AbortException - */ - public function redirectUrl($url, $code = NULL) - { - if ($this->isAjax()) { - $this->payload->redirect = (string) $url; - $this->sendPayload(); - - } elseif (!$code) { - $code = $this->httpRequest->isMethod('post') - ? Http\IResponse::S303_POST_GET - : Http\IResponse::S302_FOUND; - } - $this->sendResponse(new Responses\RedirectResponse($url, $code)); - } - - - /** - * Throws HTTP error. - * @param string - * @param int HTTP error code - * @return void - * @throws Nette\Application\BadRequestException - */ - public function error($message = NULL, $code = Http\IResponse::S404_NOT_FOUND) - { - throw new Application\BadRequestException($message, $code); - } - - - /** - * Link to myself. - * @return string - */ - public function backlink() - { - return $this->getAction(TRUE); - } - - - /** - * Returns the last created Request. - * @return Nette\Application\Request - */ - public function getLastCreatedRequest() - { - return $this->lastCreatedRequest; - } - - - /** - * Returns the last created Request flag. - * @param string - * @return bool - */ - public function getLastCreatedRequestFlag($flag) - { - return !empty($this->lastCreatedRequestFlag[$flag]); - } - - - /** - * Conditional redirect to canonicalized URI. - * @return void - * @throws Nette\Application\AbortException - */ - public function canonicalize() - { - if (!$this->isAjax() && ($this->request->isMethod('get') || $this->request->isMethod('head'))) { - try { - $url = $this->createRequest($this, $this->action, $this->getGlobalState() + $this->request->getParameters(), 'redirectX'); - } catch (InvalidLinkException $e) {} - if (isset($url) && !$this->httpRequest->getUrl()->isEqual($url)) { - $this->sendResponse(new Responses\RedirectResponse($url, Http\IResponse::S301_MOVED_PERMANENTLY)); - } - } - } - - - /** - * Attempts to cache the sent entity by its last modification date. - * @param string|int|DateTime last modified time - * @param string strong entity tag validator - * @param mixed optional expiration time - * @return void - * @throws Nette\Application\AbortException - */ - public function lastModified($lastModified, $etag = NULL, $expire = NULL) - { - if ($expire !== NULL) { - $this->httpResponse->setExpiration($expire); - } - - if (!$this->httpContext->isModified($lastModified, $etag)) { - $this->terminate(); - } - } - - - /** - * Request/URL factory. - * @param PresenterComponent base - * @param string destination in format "[[module:]presenter:]action" or "signal!" or "this" - * @param array array of arguments - * @param string forward|redirect|link - * @return string URL - * @throws InvalidLinkException - * @internal - */ - protected function createRequest($component, $destination, array $args, $mode) - { - // note: createRequest supposes that saveState(), run() & tryCall() behaviour is final - - // cached services for better performance - static $presenterFactory, $router, $refUrl; - if ($presenterFactory === NULL) { - $presenterFactory = $this->application->getPresenterFactory(); - $router = $this->application->getRouter(); - $refUrl = new Http\Url($this->httpRequest->getUrl()); - $refUrl->setPath($this->httpRequest->getUrl()->getScriptPath()); - } - - $this->lastCreatedRequest = $this->lastCreatedRequestFlag = NULL; - - // PARSE DESTINATION - // 1) fragment - $a = strpos($destination, '#'); - if ($a === FALSE) { - $fragment = ''; - } else { - $fragment = substr($destination, $a); - $destination = substr($destination, 0, $a); - } - - // 2) ?query syntax - $a = strpos($destination, '?'); - if ($a !== FALSE) { - parse_str(substr($destination, $a + 1), $args); // requires disabled magic quotes - $destination = substr($destination, 0, $a); - } - - // 3) URL scheme - $a = strpos($destination, '//'); - if ($a === FALSE) { - $scheme = FALSE; - } else { - $scheme = substr($destination, 0, $a); - $destination = substr($destination, $a + 2); - } - - // 4) signal or empty - if (!$component instanceof Presenter || substr($destination, -1) === '!') { - $signal = rtrim($destination, '!'); - $a = strrpos($signal, ':'); - if ($a !== FALSE) { - $component = $component->getComponent(strtr(substr($signal, 0, $a), ':', '-')); - $signal = (string) substr($signal, $a + 1); - } - if ($signal == NULL) { // intentionally == - throw new InvalidLinkException("Signal must be non-empty string."); - } - $destination = 'this'; - } - - if ($destination == NULL) { // intentionally == - throw new InvalidLinkException("Destination must be non-empty string."); - } - - // 5) presenter: action - $current = FALSE; - $a = strrpos($destination, ':'); - if ($a === FALSE) { - $action = $destination === 'this' ? $this->action : $destination; - $presenter = $this->getName(); - $presenterClass = get_class($this); - - } else { - $action = (string) substr($destination, $a + 1); - if ($destination[0] === ':') { // absolute - if ($a < 2) { - throw new InvalidLinkException("Missing presenter name in '$destination'."); - } - $presenter = substr($destination, 1, $a - 1); - - } else { // relative - $presenter = $this->getName(); - $b = strrpos($presenter, ':'); - if ($b === FALSE) { // no module - $presenter = substr($destination, 0, $a); - } else { // with module - $presenter = substr($presenter, 0, $b + 1) . substr($destination, 0, $a); - } - } - try { - $presenterClass = $presenterFactory->getPresenterClass($presenter); - } catch (Application\InvalidPresenterException $e) { - throw new InvalidLinkException($e->getMessage(), NULL, $e); - } - } - - // PROCESS SIGNAL ARGUMENTS - if (isset($signal)) { // $component must be IStatePersistent - $reflection = new PresenterComponentReflection(get_class($component)); - if ($signal === 'this') { // means "no signal" - $signal = ''; - if (array_key_exists(0, $args)) { - throw new InvalidLinkException("Unable to pass parameters to 'this!' signal."); - } - - } elseif (strpos($signal, self::NAME_SEPARATOR) === FALSE) { // TODO: AppForm exception - // counterpart of signalReceived() & tryCall() - $method = $component->formatSignalMethod($signal); - if (!$reflection->hasCallableMethod($method)) { - throw new InvalidLinkException("Unknown signal '$signal', missing handler {$reflection->name}::$method()"); - } - if ($args) { // convert indexed parameters to named - self::argsToParams(get_class($component), $method, $args); - } - } - - // counterpart of IStatePersistent - if ($args && array_intersect_key($args, $reflection->getPersistentParams())) { - $component->saveState($args); - } - - if ($args && $component !== $this) { - $prefix = $component->getUniqueId() . self::NAME_SEPARATOR; - foreach ($args as $key => $val) { - unset($args[$key]); - $args[$prefix . $key] = $val; - } - } - } - - // PROCESS ARGUMENTS - if (is_subclass_of($presenterClass, __CLASS__)) { - if ($action === '') { - $action = self::DEFAULT_ACTION; - } - - $current = ($action === '*' || strcasecmp($action, $this->action) === 0) && $presenterClass === get_class($this); // TODO - - $reflection = new PresenterComponentReflection($presenterClass); - if ($args || $destination === 'this') { - // counterpart of run() & tryCall() - $method = $presenterClass::formatActionMethod($action); - if (!$reflection->hasCallableMethod($method)) { - $method = $presenterClass::formatRenderMethod($action); - if (!$reflection->hasCallableMethod($method)) { - $method = NULL; - } - } - - // convert indexed parameters to named - if ($method === NULL) { - if (array_key_exists(0, $args)) { - throw new InvalidLinkException("Unable to pass parameters to action '$presenter:$action', missing corresponding method."); - } - - } elseif ($destination === 'this') { - self::argsToParams($presenterClass, $method, $args, $this->params); - - } else { - self::argsToParams($presenterClass, $method, $args); - } - } - - // counterpart of IStatePersistent - if ($args && array_intersect_key($args, $reflection->getPersistentParams())) { - $this->saveState($args, $reflection); - } - - if ($mode === 'redirect') { - $this->saveGlobalState(); - } - - $globalState = $this->getGlobalState($destination === 'this' ? NULL : $presenterClass); - if ($current && $args) { - $tmp = $globalState + $this->params; - foreach ($args as $key => $val) { - if (http_build_query(array($val)) !== (isset($tmp[$key]) ? http_build_query(array($tmp[$key])) : '')) { - $current = FALSE; - break; - } - } - } - $args += $globalState; - } - - // ADD ACTION & SIGNAL & FLASH - if ($action) { - $args[self::ACTION_KEY] = $action; - } - if (!empty($signal)) { - $args[self::SIGNAL_KEY] = $component->getParameterId($signal); - $current = $current && $args[self::SIGNAL_KEY] === $this->getParameter(self::SIGNAL_KEY); - } - if (($mode === 'redirect' || $mode === 'forward') && $this->hasFlashSession()) { - $args[self::FLASH_KEY] = $this->getParameter(self::FLASH_KEY); - } - - $this->lastCreatedRequest = new Application\Request( - $presenter, - Application\Request::FORWARD, - $args, - array(), - array() - ); - $this->lastCreatedRequestFlag = array('current' => $current); - - if ($mode === 'forward' || $mode === 'test') { - return; - } - - // CONSTRUCT URL - $url = $router->constructUrl($this->lastCreatedRequest, $refUrl); - if ($url === NULL) { - unset($args[self::ACTION_KEY]); - $params = urldecode(http_build_query($args, NULL, ', ')); - throw new InvalidLinkException("No route for $presenter:$action($params)"); - } - - // make URL relative if possible - if ($mode === 'link' && $scheme === FALSE && !$this->absoluteUrls) { - $hostUrl = $refUrl->getHostUrl() . '/'; - if (strncmp($url, $hostUrl, strlen($hostUrl)) === 0) { - $url = substr($url, strlen($hostUrl) - 1); - } - } - - return $url . $fragment; - } - - - /** - * Converts list of arguments to named parameters. - * @param string class name - * @param string method name - * @param array arguments - * @param array supplemental arguments - * @return void - * @throws InvalidLinkException - */ - private static function argsToParams($class, $method, & $args, $supplemental = array()) - { - $i = 0; - $rm = new \ReflectionMethod($class, $method); - foreach ($rm->getParameters() as $param) { - $name = $param->getName(); - if (array_key_exists($i, $args)) { - $args[$name] = $args[$i]; - unset($args[$i]); - $i++; - - } elseif (array_key_exists($name, $args)) { - // continue with process - - } elseif (array_key_exists($name, $supplemental)) { - $args[$name] = $supplemental[$name]; - - } else { - continue; - } - - if ($args[$name] === NULL) { - continue; - } - - $def = $param->isDefaultValueAvailable() && $param->isOptional() ? $param->getDefaultValue() : NULL; // see PHP bug #62988 - $type = $param->isArray() ? 'array' : gettype($def); - if (!PresenterComponentReflection::convertType($args[$name], $type)) { - throw new InvalidLinkException("Invalid value for parameter '$name' in method $class::$method(), expected " . ($type === 'NULL' ? 'scalar' : $type) . "."); - } - - if ($args[$name] === $def || ($def === NULL && is_scalar($args[$name]) && (string) $args[$name] === '')) { - $args[$name] = NULL; // value transmit is unnecessary - } - } - - if (array_key_exists($i, $args)) { - $method = $rm->getName(); - throw new InvalidLinkException("Passed more parameters than method $class::$method() expects."); - } - } - - - /** - * Invalid link handler. Descendant can override this method to change default behaviour. - * @return string - * @throws InvalidLinkException - */ - protected function handleInvalidLink(InvalidLinkException $e) - { - if ($this->invalidLinkMode === self::INVALID_LINK_SILENT) { - return '#'; - - } elseif ($this->invalidLinkMode === self::INVALID_LINK_WARNING) { - return 'error: ' . $e->getMessage(); - - } else { // self::INVALID_LINK_EXCEPTION - throw $e; - } - } - - - /********************* request serialization ****************d*g**/ - - - /** - * Stores current request to session. - * @param mixed optional expiration time - * @return string key - */ - public function storeRequest($expiration = '+ 10 minutes') - { - $session = $this->session->getSection('Nette.Application/requests'); - do { - $key = Nette\Utils\Strings::random(5); - } while (isset($session[$key])); - - $session[$key] = array($this->user->getId(), $this->request); - $session->setExpiration($expiration, $key); - return $key; - } - - - /** - * Restores request from session. - * @param string key - * @return void - */ - public function restoreRequest($key) - { - $session = $this->session->getSection('Nette.Application/requests'); - if (!isset($session[$key]) || ($session[$key][0] !== NULL && $session[$key][0] !== $this->user->getId())) { - return; - } - $request = clone $session[$key][1]; - unset($session[$key]); - $request->setFlag(Application\Request::RESTORED, TRUE); - $params = $request->getParameters(); - $params[self::FLASH_KEY] = $this->getParameter(self::FLASH_KEY); - $request->setParameters($params); - $this->sendResponse(new Responses\ForwardResponse($request)); - } - - - /********************* interface IStatePersistent ****************d*g**/ - - - /** - * Returns array of persistent components. - * This default implementation detects components by class-level annotation @persistent(cmp1, cmp2). - * @return array - */ - public static function getPersistentComponents() - { - return (array) Reflection\ClassType::from(get_called_class())->getAnnotation('persistent'); - } - - - /** - * Saves state information for all subcomponents to $this->globalState. - * @return array - */ - private function getGlobalState($forClass = NULL) - { - $sinces = & $this->globalStateSinces; - - if ($this->globalState === NULL) { - $state = array(); - foreach ($this->globalParams as $id => $params) { - $prefix = $id . self::NAME_SEPARATOR; - foreach ($params as $key => $val) { - $state[$prefix . $key] = $val; - } - } - $this->saveState($state, $forClass ? new PresenterComponentReflection($forClass) : NULL); - - if ($sinces === NULL) { - $sinces = array(); - foreach ($this->getReflection()->getPersistentParams() as $name => $meta) { - $sinces[$name] = $meta['since']; - } - } - - $components = $this->getReflection()->getPersistentComponents(); - $iterator = $this->getComponents(TRUE, 'Nette\Application\UI\IStatePersistent'); - - foreach ($iterator as $name => $component) { - if ($iterator->getDepth() === 0) { - // counts with Nette\Application\RecursiveIteratorIterator::SELF_FIRST - $since = isset($components[$name]['since']) ? $components[$name]['since'] : FALSE; // FALSE = nonpersistent - } - $prefix = $component->getUniqueId() . self::NAME_SEPARATOR; - $params = array(); - $component->saveState($params); - foreach ($params as $key => $val) { - $state[$prefix . $key] = $val; - $sinces[$prefix . $key] = $since; - } - } - - } else { - $state = $this->globalState; - } - - if ($forClass !== NULL) { - $since = NULL; - foreach ($state as $key => $foo) { - if (!isset($sinces[$key])) { - $x = strpos($key, self::NAME_SEPARATOR); - $x = $x === FALSE ? $key : substr($key, 0, $x); - $sinces[$key] = isset($sinces[$x]) ? $sinces[$x] : FALSE; - } - if ($since !== $sinces[$key]) { - $since = $sinces[$key]; - $ok = $since && (is_subclass_of($forClass, $since) || $forClass === $since); - } - if (!$ok) { - unset($state[$key]); - } - } - } - - return $state; - } - - - /** - * Permanently saves state information for all subcomponents to $this->globalState. - * @return void - */ - protected function saveGlobalState() - { - $this->globalParams = array(); - $this->globalState = $this->getGlobalState(); - } - - - /** - * Initializes $this->globalParams, $this->signal & $this->signalReceiver, $this->action, $this->view. Called by run(). - * @return void - * @throws Nette\Application\BadRequestException if action name is not valid - */ - private function initGlobalParameters() - { - // init $this->globalParams - $this->globalParams = array(); - $selfParams = array(); - - $params = $this->request->getParameters(); - if ($this->isAjax()) { - $params += $this->request->getPost(); - } - - foreach ($params as $key => $value) { - if (!preg_match('#^((?:[a-z0-9_]+-)*)((?!\d+\z)[a-z0-9_]+)\z#i', $key, $matches)) { - continue; - } elseif (!$matches[1]) { - $selfParams[$key] = $value; - } else { - $this->globalParams[substr($matches[1], 0, -1)][$matches[2]] = $value; - } - } - - // init & validate $this->action & $this->view - $this->changeAction(isset($selfParams[self::ACTION_KEY]) ? $selfParams[self::ACTION_KEY] : self::DEFAULT_ACTION); - - // init $this->signalReceiver and key 'signal' in appropriate params array - $this->signalReceiver = $this->getUniqueId(); - if (isset($selfParams[self::SIGNAL_KEY])) { - $param = $selfParams[self::SIGNAL_KEY]; - if (!is_string($param)) { - $this->error('Signal name is not string.'); - } - $pos = strrpos($param, '-'); - if ($pos) { - $this->signalReceiver = substr($param, 0, $pos); - $this->signal = substr($param, $pos + 1); - } else { - $this->signalReceiver = $this->getUniqueId(); - $this->signal = $param; - } - if ($this->signal == NULL) { // intentionally == - $this->signal = NULL; - } - } - - $this->loadState($selfParams); - } - - - /** - * Pops parameters for specified component. - * @param string component id - * @return array - */ - public function popGlobalParameters($id) - { - if (isset($this->globalParams[$id])) { - $res = $this->globalParams[$id]; - unset($this->globalParams[$id]); - return $res; - - } else { - return array(); - } - } - - - /********************* flash session ****************d*g**/ - - - /** - * Checks if a flash session namespace exists. - * @return bool - */ - public function hasFlashSession() - { - return !empty($this->params[self::FLASH_KEY]) - && $this->session->hasSection('Nette.Application.Flash/' . $this->params[self::FLASH_KEY]); - } - - - /** - * Returns session namespace provided to pass temporary data between redirects. - * @return Nette\Http\SessionSection - */ - public function getFlashSession() - { - if (empty($this->params[self::FLASH_KEY])) { - $this->params[self::FLASH_KEY] = Nette\Utils\Strings::random(4); - } - return $this->session->getSection('Nette.Application.Flash/' . $this->params[self::FLASH_KEY]); - } - - - /********************* services ****************d*g**/ - - - public function injectPrimary(Nette\DI\Container $context, Application\Application $application, Http\Context $httpContext, Http\IRequest $httpRequest, Http\IResponse $httpResponse, Http\Session $session, Nette\Security\User $user) - { - if ($this->application !== NULL) { - throw new Nette\InvalidStateException("Method " . __METHOD__ . " is intended for initialization and should not be called more than once."); - } - - $this->context = $context; - $this->application = $application; - $this->httpContext = $httpContext; - $this->httpRequest = $httpRequest; - $this->httpResponse = $httpResponse; - $this->session = $session; - $this->user = $user; - } - - - /** - * Gets the context. - * @return \SystemContainer|Nette\DI\Container - * @deprecated - */ - public function getContext() - { - return $this->context; - } - - - /** - * @deprecated - */ - public function getService($name) - { - trigger_error(__METHOD__ . '() is deprecated; use dependency injection instead.', E_USER_DEPRECATED); - return $this->context->getService($name); - } - - - /** - * @return Nette\Http\IRequest - */ - protected function getHttpRequest() - { - return $this->httpRequest; - } - - - /** - * @return Nette\Http\IResponse - */ - protected function getHttpResponse() - { - return $this->httpResponse; - } - - - /** - * @deprecated - */ - protected function getHttpContext() - { - trigger_error(__METHOD__ . '() is deprecated; use dependency injection instead.', E_USER_DEPRECATED); - return $this->httpContext; - } - - - /** - * @deprecated - */ - public function getApplication() - { - trigger_error(__METHOD__ . '() is deprecated; use dependency injection instead.', E_USER_DEPRECATED); - return $this->application; - } - - - /** - * @param string - * @return Nette\Http\Session|Nette\Http\SessionSection - */ - public function getSession($namespace = NULL) - { - $handler = $this->session; - return $namespace === NULL ? $handler : $handler->getSection($namespace); - } - - - /** - * @return Nette\Security\User - */ - public function getUser() - { - return $this->user; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Cache.php php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Cache.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Cache.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Cache.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,394 +0,0 @@ -storage = $storage; - $this->namespace = $namespace . self::NAMESPACE_SEPARATOR; - } - - - /** - * Returns cache storage. - * @return IStorage - */ - public function getStorage() - { - return $this->storage; - } - - - /** - * Returns cache namespace. - * @return string - */ - public function getNamespace() - { - return (string) substr($this->namespace, 0, -1); - } - - - /** - * Returns new nested cache object. - * @param string - * @return Cache - */ - public function derive($namespace) - { - $derived = new static($this->storage, $this->namespace . $namespace); - return $derived; - } - - - /** - * Reads the specified item from the cache or generate it. - * @param mixed key - * @param callable - * @return mixed|NULL - */ - public function load($key, $fallback = NULL) - { - $data = $this->storage->read($this->generateKey($key)); - if ($data === NULL && $fallback) { - return $this->save($key, Callback::closure($fallback)); - } - return $data; - } - - - /** - * Writes item into the cache. - * Dependencies are: - * - Cache::PRIORITY => (int) priority - * - Cache::EXPIRATION => (timestamp) expiration - * - Cache::SLIDING => (bool) use sliding expiration? - * - Cache::TAGS => (array) tags - * - Cache::FILES => (array|string) file names - * - Cache::ITEMS => (array|string) cache items - * - Cache::CONSTS => (array|string) cache items - * - * @param mixed key - * @param mixed value - * @param array dependencies - * @return mixed value itself - * @throws Nette\InvalidArgumentException - */ - public function save($key, $data, array $dependencies = NULL) - { - $this->release(); - $key = $this->generateKey($key); - - if ($data instanceof Nette\Callback || $data instanceof \Closure) { - $this->storage->lock($key); - $data = call_user_func_array($data, array(& $dependencies)); - } - - if ($data === NULL) { - $this->storage->remove($key); - } else { - $this->storage->write($key, $data, $this->completeDependencies($dependencies, $data)); - return $data; - } - } - - - private function completeDependencies($dp, $data) - { - if (is_object($data)) { - $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkSerializationVersion'), get_class($data), - Nette\Reflection\ClassType::from($data)->getAnnotation('serializationVersion')); - } - - // convert expire into relative amount of seconds - if (isset($dp[Cache::EXPIRATION])) { - $dp[Cache::EXPIRATION] = Nette\DateTime::from($dp[Cache::EXPIRATION])->format('U') - time(); - } - - // convert FILES into CALLBACKS - if (isset($dp[self::FILES])) { - //clearstatcache(); - foreach (array_unique((array) $dp[self::FILES]) as $item) { - $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkFile'), $item, @filemtime($item)); // @ - stat may fail - } - unset($dp[self::FILES]); - } - - // add namespaces to items - if (isset($dp[self::ITEMS])) { - $dp[self::ITEMS] = array_unique(array_map(array($this, 'generateKey'), (array) $dp[self::ITEMS])); - } - - // convert CONSTS into CALLBACKS - if (isset($dp[self::CONSTS])) { - foreach (array_unique((array) $dp[self::CONSTS]) as $item) { - $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkConst'), $item, constant($item)); - } - unset($dp[self::CONSTS]); - } - - if (!is_array($dp)) { - $dp = array(); - } - return $dp; - } - - - /** - * Removes item from the cache. - * @param mixed key - * @return void - */ - public function remove($key) - { - $this->save($key, NULL); - } - - - /** - * Removes items from the cache by conditions. - * Conditions are: - * - Cache::PRIORITY => (int) priority - * - Cache::TAGS => (array) tags - * - Cache::ALL => TRUE - * @return void - */ - public function clean(array $conditions = NULL) - { - $this->release(); - $this->storage->clean((array) $conditions); - } - - - /** - * Caches results of function/method calls. - * @param mixed - * @return mixed - */ - public function call($function) - { - $key = func_get_args(); - $key[0] = Callback::toReflection($function); - return $this->load($key, function() use ($function, $key) { - return Callback::invokeArgs($function, array_slice($key, 1)); - }); - } - - - /** - * Caches results of function/method calls. - * @param mixed - * @param array dependencies - * @return Closure - */ - public function wrap($function, array $dependencies = NULL) - { - $cache = $this; - return function() use ($cache, $function, $dependencies) { - $key = array(Callback::toReflection($function), func_get_args()); - $data = $cache->load($key); - if ($data === NULL) { - $data = $cache->save($key, Callback::invokeArgs($function, $key[1]), $dependencies); - } - return $data; - }; - } - - - /** - * Starts the output cache. - * @param mixed key - * @return OutputHelper|NULL - */ - public function start($key) - { - $data = $this->load($key); - if ($data === NULL) { - return new OutputHelper($this, $key); - } - echo $data; - } - - - /** - * Generates internal cache key. - * - * @param string - * @return string - */ - protected function generateKey($key) - { - return $this->namespace . md5(is_scalar($key) ? $key : serialize($key)); - } - - - /********************* interface ArrayAccess ****************d*g**/ - - - /** - * Inserts (replaces) item into the cache (\ArrayAccess implementation). - * @param mixed key - * @param mixed - * @return void - * @throws Nette\InvalidArgumentException - */ - public function offsetSet($key, $data) - { - $this->save($key, $data); - } - - - /** - * Retrieves the specified item from the cache or NULL if the key is not found (\ArrayAccess implementation). - * @param mixed key - * @return mixed|NULL - * @throws Nette\InvalidArgumentException - */ - public function offsetGet($key) - { - $key = is_scalar($key) ? (string) $key : serialize($key); - if ($this->key !== $key) { - $this->key = $key; - $this->data = $this->load($key); - } - return $this->data; - } - - - /** - * Exists item in cache? (\ArrayAccess implementation). - * @param mixed key - * @return bool - * @throws Nette\InvalidArgumentException - */ - public function offsetExists($key) - { - $this->release(); - return $this->offsetGet($key) !== NULL; - } - - - /** - * Removes the specified item from the cache. - * @param mixed key - * @return void - * @throws Nette\InvalidArgumentException - */ - public function offsetUnset($key) - { - $this->save($key, NULL); - } - - - /** - * Discards the internal cache used by ArrayAccess. - * @return void - */ - public function release() - { - $this->key = $this->data = NULL; - } - - - /********************* dependency checkers ****************d*g**/ - - - /** - * Checks CALLBACKS dependencies. - * @param array - * @return bool - */ - public static function checkCallbacks($callbacks) - { - foreach ($callbacks as $callback) { - if (!call_user_func_array(array_shift($callback), $callback)) { - return FALSE; - } - } - return TRUE; - } - - - /** - * Checks CONSTS dependency. - * @param string - * @param mixed - * @return bool - */ - private static function checkConst($const, $value) - { - return defined($const) && constant($const) === $value; - } - - - /** - * Checks FILES dependency. - * @param string - * @param int - * @return bool - */ - private static function checkFile($file, $time) - { - return @filemtime($file) == $time; // @ - stat may fail - } - - - /** - * Checks object @serializationVersion label. - * @param string - * @param mixed - * @return bool - */ - private static function checkSerializationVersion($class, $value) - { - return Nette\Reflection\ClassType::from($class)->getAnnotation('serializationVersion') === $value; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Caching/IStorage.php php-nette-2.1.5/Nette-2.1.4/Nette/Caching/IStorage.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Caching/IStorage.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Caching/IStorage.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -cache = $cache; - $this->key = $key; - ob_start(); - } - - - /** - * Stops and saves the cache. - * @param array dependencies - * @return void - */ - public function end(array $dependencies = NULL) - { - if ($this->cache === NULL) { - throw new Nette\InvalidStateException('Output cache has already been saved.'); - } - $this->cache->save($this->key, ob_get_flush(), (array) $dependencies + (array) $this->dependencies); - $this->cache = NULL; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/DevNullStorage.php php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/DevNullStorage.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/DevNullStorage.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/DevNullStorage.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ - 0, - self::PRIORITY => 1, - self::ENTRIES => 2, - self::DATA => 3, - ); - - - /** - * @param string Directory containing journal file - */ - public function __construct($dir) - { - $this->file = $dir . '/' . self::FILE; - } - - - /** - * @return void - */ - public function __destruct() - { - if ($this->handle) { - $this->headerCommit(); - flock($this->handle, LOCK_UN); // Since PHP 5.3.3 is manual unlock necessary - fclose($this->handle); - $this->handle = FALSE; - } - } - - - /** - * Writes entry information into the journal. - * @param string - * @param array - * @return void - */ - public function write($key, array $dependencies) - { - $this->lock(); - - $priority = !isset($dependencies[Cache::PRIORITY]) ? FALSE : (int) $dependencies[Cache::PRIORITY]; - $tags = empty($dependencies[Cache::TAGS]) ? FALSE : (array) $dependencies[Cache::TAGS]; - - $exists = FALSE; - $keyHash = crc32($key); - list($entriesNodeId, $entriesNode) = $this->findIndexNode(self::ENTRIES, $keyHash); - - if (isset($entriesNode[$keyHash])) { - $entries = $this->mergeIndexData($entriesNode[$keyHash]); - foreach ($entries as $link => $foo) { - $dataNode = $this->getNode($link >> self::BITROT); - if ($dataNode[$link][self::KEY] === $key) { - if ($dataNode[$link][self::TAGS] == $tags && $dataNode[$link][self::PRIORITY] === $priority) { // intentionally ==, the order of tags does not matter - if ($dataNode[$link][self::DELETED]) { - $dataNode[$link][self::DELETED] = FALSE; - $this->saveNode($link >> self::BITROT, $dataNode); - } - $exists = TRUE; - } else { // Already exists, but with other tags or priority - $toDelete = array(); - foreach ($dataNode[$link][self::TAGS] as $tag) { - $toDelete[self::TAGS][$tag][$link] = TRUE; - } - if ($dataNode[$link][self::PRIORITY] !== FALSE) { - $toDelete[self::PRIORITY][$dataNode[$link][self::PRIORITY]][$link] = TRUE; - } - $toDelete[self::ENTRIES][$keyHash][$link] = TRUE; - $this->cleanFromIndex($toDelete); - - unset($dataNode[$link]); - $this->saveNode($link >> self::BITROT, $dataNode); - - // Node was changed but may be empty, find it again - list($entriesNodeId, $entriesNode) = $this->findIndexNode(self::ENTRIES, $keyHash); - } - break; - } - } - } - - if ($exists === FALSE) { - // Magical constants - $requiredSize = strlen($key) + 75; - if ($tags) { - foreach ($tags as $tag) { - $requiredSize += strlen($tag) + 13; - } - } - $requiredSize += $priority ? 10 : 1; - - $freeDataNode = $this->findFreeDataNode($requiredSize); - $data = $this->getNode($freeDataNode); - - if ($data === FALSE) { - $data = array( - self::INFO => array( - self::LAST_INDEX => ($freeDataNode << self::BITROT), - self::TYPE => self::DATA, - ) - ); - } - - $dataNodeKey = $this->findNextFreeKey($freeDataNode, $data); - $data[$dataNodeKey] = array( - self::KEY => $key, - self::TAGS => $tags ? $tags : array(), - self::PRIORITY => $priority, - self::DELETED => FALSE, - ); - - $this->saveNode($freeDataNode, $data); - - // Save to entries tree, ... - $entriesNode[$keyHash][$dataNodeKey] = 1; - $this->saveNode($entriesNodeId, $entriesNode); - - // ...tags tree... - if ($tags) { - foreach ($tags as $tag) { - list($nodeId, $node) = $this->findIndexNode(self::TAGS, $tag); - $node[$tag][$dataNodeKey] = 1; - $this->saveNode($nodeId, $node); - } - } - - // ...and priority tree. - if ($priority !== FALSE) { - list($nodeId, $node) = $this->findIndexNode(self::PRIORITY, $priority); - $node[$priority][$dataNodeKey] = 1; - $this->saveNode($nodeId, $node); - } - } - - $this->commit(); - $this->unlock(); - } - - - /** - * Cleans entries from journal. - * @param array - * @return array of removed items or NULL when performing a full cleanup - */ - public function clean(array $conditions) - { - $this->lock(); - - if (!empty($conditions[Cache::ALL])) { - $this->nodeCache = $this->nodeChanged = $this->dataNodeFreeSpace = array(); - $this->deleteAll(); - $this->unlock(); - return NULL; - } - - $toDelete = array( - self::TAGS => array(), - self::PRIORITY => array(), - self::ENTRIES => array() - ); - - $entries = array(); - - if (!empty($conditions[Cache::TAGS])) { - $entries = $this->cleanTags((array) $conditions[Cache::TAGS], $toDelete); - } - - if (isset($conditions[Cache::PRIORITY])) { - $this->arrayAppend($entries, $this->cleanPriority((int) $conditions[Cache::PRIORITY], $toDelete)); - } - - $this->deletedLinks = array(); - $this->cleanFromIndex($toDelete); - - $this->commit(); - $this->unlock(); - - return $entries; - } - - - /** - * Cleans entries from journal by tags. - * @param array - * @param array - * @return array of removed items - */ - private function cleanTags(array $tags, array & $toDelete) - { - $entries = array(); - - foreach ($tags as $tag) { - list(, $node) = $this->findIndexNode(self::TAGS, $tag); - - if (isset($node[$tag])) { - $ent = $this->cleanLinks($this->mergeIndexData($node[$tag]), $toDelete); - $this->arrayAppend($entries, $ent); - } - } - - return $entries; - } - - - /** - * Cleans entries from journal by priority. - * @param integer - * @param array - * @return array of removed items - */ - private function cleanPriority($priority, array & $toDelete) - { - list(, $node) = $this->findIndexNode(self::PRIORITY, $priority); - - ksort($node); - - $allData = array(); - - foreach ($node as $prior => $data) { - if ($prior === self::INFO) { - continue; - } elseif ($prior > $priority) { - break; - } - - $this->arrayAppendKeys($allData, $this->mergeIndexData($data)); - } - - $nodeInfo = $node[self::INFO]; - while ($nodeInfo[self::PREV_NODE] !== -1) { - $nodeId = $nodeInfo[self::PREV_NODE]; - $node = $this->getNode($nodeId); - - if ($node === FALSE) { - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot load node number $nodeId."); - } - break; - } - - $nodeInfo = $node[self::INFO]; - unset($node[self::INFO]); - - foreach ($node as $data) { - $this->arrayAppendKeys($allData, $this->mergeIndexData($data)); - } - } - - return $this->cleanLinks($allData, $toDelete); - } - - - /** - * Cleans links from $data. - * @param array - * @param array - * @return array of removed items - */ - private function cleanLinks(array $data, array & $toDelete) - { - $return = array(); - - $data = array_keys($data); - sort($data); - $max = count($data); - $data[] = 0; - $i = 0; - - while ($i < $max) { - $searchLink = $data[$i]; - - if (isset($this->deletedLinks[$searchLink])) { - ++$i; - continue; - } - - $nodeId = $searchLink >> self::BITROT; - $node = $this->getNode($nodeId); - - if ($node === FALSE) { - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot load node number $nodeId."); - } - ++$i; - continue; - } - - do { - $link = $data[$i]; - - if (!isset($node[$link])) { - if (self::$debug) { - throw new Nette\InvalidStateException("Link with ID $searchLink is not in node $nodeId."); - } - continue; - } elseif (isset($this->deletedLinks[$link])) { - continue; - } - - $nodeLink = & $node[$link]; - if (!$nodeLink[self::DELETED]) { - $nodeLink[self::DELETED] = TRUE; - $return[] = $nodeLink[self::KEY]; - } else { - foreach ($nodeLink[self::TAGS] as $tag) { - $toDelete[self::TAGS][$tag][$link] = TRUE; - } - if ($nodeLink[self::PRIORITY] !== FALSE) { - $toDelete[self::PRIORITY][$nodeLink[self::PRIORITY]][$link] = TRUE; - } - $toDelete[self::ENTRIES][crc32($nodeLink[self::KEY])][$link] = TRUE; - unset($node[$link]); - $this->deletedLinks[$link] = TRUE; - } - } while (($data[++$i] >> self::BITROT) === $nodeId); - - $this->saveNode($nodeId, $node); - } - - return $return; - } - - - /** - * Remove links to deleted keys from index. - * @param array - */ - private function cleanFromIndex(array $toDeleteFromIndex) - { - foreach ($toDeleteFromIndex as $type => $toDelete) { - ksort($toDelete); - - while (!empty($toDelete)) { - reset($toDelete); - $searchKey = key($toDelete); - list($masterNodeId, $masterNode) = $this->findIndexNode($type, $searchKey); - - if (!isset($masterNode[$searchKey])) { - if (self::$debug) { - throw new Nette\InvalidStateException('Bad index.'); - } - unset($toDelete[$searchKey]); - continue; - } - - foreach ($toDelete as $key => $links) { - if (isset($masterNode[$key])) { - foreach ($links as $link => $foo) { - if (isset($masterNode[$key][$link])) { - unset($masterNode[$key][$link], $links[$link]); - } - } - - if (!empty($links) && isset($masterNode[$key][self::INDEX_DATA])) { - $this->cleanIndexData($masterNode[$key][self::INDEX_DATA], $links, $masterNode[$key]); - } - - if (empty($masterNode[$key])) { - unset($masterNode[$key]); - } - unset($toDelete[$key]); - } else { - break; - } - } - $this->saveNode($masterNodeId, $masterNode); - } - } - } - - - /** - * Merge data with index data in other nodes. - * @param array - * @return array of merged items - */ - private function mergeIndexData(array $data) - { - while (isset($data[self::INDEX_DATA])) { - $id = $data[self::INDEX_DATA]; - unset($data[self::INDEX_DATA]); - $childNode = $this->getNode($id); - - if ($childNode === FALSE) { - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot load node number $id."); - } - break; - } - - $this->arrayAppendKeys($data, $childNode[self::INDEX_DATA]); - } - - return $data; - } - - - /** - * Cleans links from other nodes. - * @param int - * @param array - * @param array - * @return void - */ - private function cleanIndexData($nextNodeId, array $links, & $masterNodeLink) - { - $prev = -1; - - while ($nextNodeId && !empty($links)) { - $nodeId = $nextNodeId; - $node = $this->getNode($nodeId); - - if ($node === FALSE) { - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot load node number $nodeId."); - } - break; - } - - foreach ($links as $link => $foo) { - if (isset($node[self::INDEX_DATA][$link])) { - unset($node[self::INDEX_DATA][$link], $links[$link]); - } - } - - if (isset($node[self::INDEX_DATA][self::INDEX_DATA])) { - $nextNodeId = $node[self::INDEX_DATA][self::INDEX_DATA]; - } else { - $nextNodeId = FALSE; - } - - if (empty($node[self::INDEX_DATA]) || (count($node[self::INDEX_DATA]) === 1 && $nextNodeId)) { - if ($prev === -1) { - if ($nextNodeId === FALSE) { - unset($masterNodeLink[self::INDEX_DATA]); - } else { - $masterNodeLink[self::INDEX_DATA] = $nextNodeId; - } - } else { - $prevNode = $this->getNode($prev); - if ($prevNode === FALSE) { - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot load node number $prev."); - } - } else { - if ($nextNodeId === FALSE) { - unset($prevNode[self::INDEX_DATA][self::INDEX_DATA]); - if (empty($prevNode[self::INDEX_DATA])) { - unset($prevNode[self::INDEX_DATA]); - } - } else { - $prevNode[self::INDEX_DATA][self::INDEX_DATA] = $nextNodeId; - } - - $this->saveNode($prev, $prevNode); - } - } - unset($node[self::INDEX_DATA]); - } else { - $prev = $nodeId; - } - - $this->saveNode($nodeId, $node); - } - } - - - /** - * Get node from journal. - * @param integer - * @return array - */ - private function getNode($id) - { - // Load from cache - if (isset($this->nodeCache[$id])) { - return $this->nodeCache[$id]; - } - - $binary = stream_get_contents($this->handle, self::NODE_SIZE, self::HEADER_SIZE + self::NODE_SIZE * $id); - - if (empty($binary)) { - // empty node, no Exception - return FALSE; - } - - list(, $magic, $length) = unpack('N2', $binary); - if ($magic !== self::INDEX_MAGIC && $magic !== self::DATA_MAGIC) { - if (!empty($magic)) { - if (self::$debug) { - throw new Nette\InvalidStateException("Node $id has malformed header."); - } - $this->deleteNode($id); - } - return FALSE; - } - - $data = substr($binary, 2 * self::INT32_SIZE, $length - 2 * self::INT32_SIZE); - - $node = @unserialize($data); // intentionally @ - if ($node === FALSE) { - $this->deleteNode($id); - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot unserialize node number $id."); - } - return FALSE; - } - - // Save to cache and return - return $this->nodeCache[$id] = $node; - } - - - /** - * Save node to cache. - * @param integer - * @param array - * @return void - */ - private function saveNode($id, array $node) - { - if (count($node) === 1) { // Nod contains only INFO - $nodeInfo = $node[self::INFO]; - if ($nodeInfo[self::TYPE] !== self::DATA) { - - if ($nodeInfo[self::END] !== -1) { - $this->nodeCache[$id] = $node; - $this->nodeChanged[$id] = TRUE; - return; - } - - if ($nodeInfo[self::MAX] === -1) { - $max = PHP_INT_MAX; - } else { - $max = $nodeInfo[self::MAX]; - } - - list(, , $parentId) = $this->findIndexNode($nodeInfo[self::TYPE], $max, $id); - if ($parentId !== -1 && $parentId !== $id) { - $parentNode = $this->getNode($parentId); - if ($parentNode === FALSE) { - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot load node number $parentId."); - } - } else { - if ($parentNode[self::INFO][self::END] === $id) { - if (count($parentNode) === 1) { - $parentNode[self::INFO][self::END] = -1; - } else { - end($parentNode); - $lastKey = key($parentNode); - $parentNode[self::INFO][self::END] = $parentNode[$lastKey]; - unset($parentNode[$lastKey]); - } - } else { - unset($parentNode[$nodeInfo[self::MAX]]); - } - - $this->saveNode($parentId, $parentNode); - } - } - - if ($nodeInfo[self::TYPE] === self::PRIORITY) { // only priority tree has link to prevNode - if ($nodeInfo[self::MAX] === -1) { - if ($nodeInfo[self::PREV_NODE] !== -1) { - $prevNode = $this->getNode($nodeInfo[self::PREV_NODE]); - if ($prevNode === FALSE) { - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot load node number {$nodeInfo[self::PREV_NODE]}."); - } - } else { - $prevNode[self::INFO][self::MAX] = -1; - $this->saveNode($nodeInfo[self::PREV_NODE], $prevNode); - } - } - } else { - list($nextId, $nextNode) = $this->findIndexNode($nodeInfo[self::TYPE], $nodeInfo[self::MAX] + 1, NULL, $id); - if ($nextId !== -1 && $nextId !== $id) { - $nextNode[self::INFO][self::PREV_NODE] = $nodeInfo[self::PREV_NODE]; - $this->saveNode($nextId, $nextNode); - } - } - } - } - $this->nodeCache[$id] = FALSE; - } else { - $this->nodeCache[$id] = $node; - } - $this->nodeChanged[$id] = TRUE; - } - - - /** - * Commit all changed nodes from cache to journal file. - * @return void - */ - private function commit() - { - do { - foreach ($this->nodeChanged as $id => $foo) { - if ($this->prepareNode($id, $this->nodeCache[$id])) { - unset($this->nodeChanged[$id]); - } - } - } while (!empty($this->nodeChanged)); - - foreach ($this->toCommit as $node => $str) { - $this->commitNode($node, $str); - } - $this->toCommit = array(); - } - - - /** - * Prepare node to journal file structure. - * @param integer - * @param array|bool - * @return bool Successfully committed - */ - private function prepareNode($id, $node) - { - if ($node === FALSE) { - if ($id < $this->lastNode) { - $this->lastNode = $id; - } - unset($this->nodeCache[$id]); - unset($this->dataNodeFreeSpace[$id]); - $this->deleteNode($id); - return TRUE; - } - - $data = serialize($node); - $dataSize = strlen($data) + 2 * self::INT32_SIZE; - - $isData = $node[self::INFO][self::TYPE] === self::DATA; - if ($dataSize > self::NODE_SIZE) { - if ($isData) { - throw new Nette\InvalidStateException('Saving node is bigger than maximum node size.'); - } else { - $this->bisectNode($id, $node); - return FALSE; - } - } - - $this->toCommit[$id] = pack('N2', $isData ? self::DATA_MAGIC : self::INDEX_MAGIC, $dataSize) . $data; - - if ($this->lastNode < $id) { - $this->lastNode = $id; - } - if ($isData) { - $this->dataNodeFreeSpace[$id] = self::NODE_SIZE - $dataSize; - } - - return TRUE; - } - - - /** - * Commit node string to journal file. - * @param integer - * @param string - * @return void - */ - private function commitNode($id, $str) - { - fseek($this->handle, self::HEADER_SIZE + self::NODE_SIZE * $id); - $written = fwrite($this->handle, $str); - if ($written === FALSE) { - throw new Nette\InvalidStateException("Cannot write node number $id to journal."); - } - } - - - /** - * Find right node in B+tree. . - * @param string Tree type (TAGS, PRIORITY or ENTRIES) - * @param int Searched item - * @return array Node - */ - private function findIndexNode($type, $search, $childId = NULL, $prevId = NULL) - { - $nodeId = self::$startNode[$type]; - - $parentId = -1; - while (TRUE) { - $node = $this->getNode($nodeId); - - if ($node === FALSE) { - return array( - $nodeId, - array( - self::INFO => array( - self::TYPE => $type, - self::IS_LEAF => TRUE, - self::PREV_NODE => -1, - self::END => -1, - self::MAX => -1, - ) - ), - $parentId, - ); // Init empty node - } - - if ($node[self::INFO][self::IS_LEAF] || $nodeId === $childId || $node[self::INFO][self::PREV_NODE] === $prevId) { - return array($nodeId, $node, $parentId); - } - - $parentId = $nodeId; - - if (isset($node[$search])) { - $nodeId = $node[$search]; - } else { - foreach ($node as $key => $childNode) { - if ($key > $search and $key !== self::INFO) { - $nodeId = $childNode; - continue 2; - } - } - - $nodeId = $node[self::INFO][self::END]; - } - } - } - - - /** - * Find complete free node. - * @param integer - * @return array|integer Node ID - */ - private function findFreeNode($count = 1) - { - $id = $this->lastNode; - $nodesId = array(); - - do { - if (isset($this->nodeCache[$id])) { - ++$id; - continue; - } - - $offset = self::HEADER_SIZE + self::NODE_SIZE * $id; - - $binary = stream_get_contents($this->handle, self::INT32_SIZE, $offset); - - if (empty($binary)) { - $nodesId[] = $id; - } else { - list(, $magic) = unpack('N', $binary); - if ($magic !== self::INDEX_MAGIC && $magic !== self::DATA_MAGIC) { - $nodesId[] = $id; - } - } - - ++$id; - } while (count($nodesId) !== $count); - - if ($count === 1) { - return $nodesId[0]; - } else { - return $nodesId; - } - } - - - /** - * Find free data node that has $size bytes of free space. - * @param integer size in bytes - * @return integer Node ID - */ - private function findFreeDataNode($size) - { - foreach ($this->dataNodeFreeSpace as $id => $freeSpace) { - if ($freeSpace > $size) { - return $id; - } - } - - $id = self::$startNode[self::DATA]; - while (TRUE) { - if (isset($this->dataNodeFreeSpace[$id]) || isset($this->nodeCache[$id])) { - ++$id; - continue; - } - - $offset = self::HEADER_SIZE + self::NODE_SIZE * $id; - $binary = stream_get_contents($this->handle, 2 * self::INT32_SIZE, $offset); - - if (empty($binary)) { - $this->dataNodeFreeSpace[$id] = self::NODE_SIZE; - return $id; - } - - list(, $magic, $nodeSize) = unpack('N2', $binary); - if (empty($magic)) { - $this->dataNodeFreeSpace[$id] = self::NODE_SIZE; - return $id; - } elseif ($magic === self::DATA_MAGIC) { - $freeSpace = self::NODE_SIZE - $nodeSize; - $this->dataNodeFreeSpace[$id] = $freeSpace; - - if ($freeSpace > $size) { - return $id; - } - } - - ++$id; - } - } - - - /** - * Bisect node or when has only one key, move part to data node. - * @param integer Node ID - * @param array Node - * @return void - */ - private function bisectNode($id, array $node) - { - $nodeInfo = $node[self::INFO]; - unset($node[self::INFO]); - - if (count($node) === 1) { - $key = key($node); - - $dataId = $this->findFreeDataNode(self::NODE_SIZE); - $this->saveNode($dataId, array( - self::INDEX_DATA => $node[$key], - self::INFO => array( - self::TYPE => self::DATA, - self::LAST_INDEX => ($dataId << self::BITROT), - ))); - - unset($node[$key]); - $node[$key][self::INDEX_DATA] = $dataId; - $node[self::INFO] = $nodeInfo; - - $this->saveNode($id, $node); - return; - } - - ksort($node); - $halfCount = ceil(count($node) / 2); - - list($first, $second) = array_chunk($node, $halfCount, TRUE); - - end($first); - $halfKey = key($first); - - if ($id <= 2) { // Root - list($firstId, $secondId) = $this->findFreeNode(2); - - $first[self::INFO] = array( - self::TYPE => $nodeInfo[self::TYPE], - self::IS_LEAF => $nodeInfo[self::IS_LEAF], - self::PREV_NODE => -1, - self::END => -1, - self::MAX => $halfKey, - ); - $this->saveNode($firstId, $first); - - $second[self::INFO] = array( - self::TYPE => $nodeInfo[self::TYPE], - self::IS_LEAF => $nodeInfo[self::IS_LEAF], - self::PREV_NODE => $firstId, - self::END => $nodeInfo[self::END], - self::MAX => -1, - ); - $this->saveNode($secondId, $second); - - $parentNode = array( - self::INFO => array( - self::TYPE => $nodeInfo[self::TYPE], - self::IS_LEAF => FALSE, - self::PREV_NODE => -1, - self::END => $secondId, - self::MAX => -1, - ), - $halfKey => $firstId, - ); - $this->saveNode($id, $parentNode); - } else { - $firstId = $this->findFreeNode(); - - $first[self::INFO] = array( - self::TYPE => $nodeInfo[self::TYPE], - self::IS_LEAF => $nodeInfo[self::IS_LEAF], - self::PREV_NODE => $nodeInfo[self::PREV_NODE], - self::END => -1, - self::MAX => $halfKey, - ); - $this->saveNode($firstId, $first); - - $second[self::INFO] = array( - self::TYPE => $nodeInfo[self::TYPE], - self::IS_LEAF => $nodeInfo[self::IS_LEAF], - self::PREV_NODE => $firstId, - self::END => $nodeInfo[self::END], - self::MAX => $nodeInfo[self::MAX], - ); - $this->saveNode($id, $second); - - list(,, $parent) = $this->findIndexNode($nodeInfo[self::TYPE], $halfKey); - $parentNode = $this->getNode($parent); - if ($parentNode === FALSE) { - if (self::$debug) { - throw new Nette\InvalidStateException("Cannot load node number $parent."); - } - } else { - $parentNode[$halfKey] = $firstId; - ksort($parentNode); // Parent index must be always sorted. - $this->saveNode($parent, $parentNode); - } - } - } - - - /** - * Commit header to journal file. - * @return void - */ - private function headerCommit() - { - fseek($this->handle, self::INT32_SIZE); - @fwrite($this->handle, pack('N', $this->lastNode)); // intentionally @, save is not necessary - } - - - /** - * Remove node from journal file. - * @param integer - * @return void - */ - private function deleteNode($id) - { - fseek($this->handle, 0, SEEK_END); - $end = ftell($this->handle); - - if ($end <= (self::HEADER_SIZE + self::NODE_SIZE * ($id + 1))) { - $packedNull = pack('N', 0); - - do { - $binary = stream_get_contents($this->handle, self::INT32_SIZE, (self::HEADER_SIZE + self::NODE_SIZE * --$id)); - } while (empty($binary) || $binary === $packedNull); - - if (!ftruncate($this->handle, self::HEADER_SIZE + self::NODE_SIZE * ($id + 1))) { - throw new Nette\InvalidStateException('Cannot truncate journal file.'); - } - } else { - fseek($this->handle, self::HEADER_SIZE + self::NODE_SIZE * $id); - $written = fwrite($this->handle, pack('N', 0)); - if ($written !== self::INT32_SIZE) { - throw new Nette\InvalidStateException("Cannot delete node number $id from journal."); - } - } - } - - - /** - * Complete delete all nodes from file. - * @throws \Nette\InvalidStateException - */ - private function deleteAll() - { - if (!ftruncate($this->handle, self::HEADER_SIZE)) { - throw new Nette\InvalidStateException('Cannot truncate journal file.'); - } - } - - - /** - * Lock file for writing and reading and delete node cache when file has changed. - * @throws \Nette\InvalidStateException - */ - private function lock() - { - if (!$this->handle) { - $this->prepare(); - } - - if (!flock($this->handle, LOCK_EX)) { - throw new Nette\InvalidStateException("Cannot acquire exclusive lock on journal file '$this->file'."); - } - - $lastProcessIdentifier = stream_get_contents($this->handle, self::INT32_SIZE, self::INT32_SIZE * 2); - if ($lastProcessIdentifier !== $this->processIdentifier) { - $this->nodeCache = $this->dataNodeFreeSpace = array(); - - // Write current processIdentifier to file header - fseek($this->handle, self::INT32_SIZE * 2); - fwrite($this->handle, $this->processIdentifier); - } - } - - - /** - * Open btfj.dat file (or create it if not exists) and load metainformation - * @throws \Nette\InvalidStateException - */ - private function prepare() - { - // Create journal file when not exists - if (!file_exists($this->file)) { - $init = @fopen($this->file, 'xb'); // intentionally @ - if (!$init) { - clearstatcache(); - if (!file_exists($this->file)) { - throw new Nette\InvalidStateException("Cannot create journal file '$this->file'."); - } - } else { - $written = fwrite($init, pack('N2', self::FILE_MAGIC, $this->lastNode)); - fclose($init); - if ($written !== self::INT32_SIZE * 2) { - throw new Nette\InvalidStateException("Cannot write journal header."); - } - } - } - - $this->handle = fopen($this->file, 'r+b'); - - if (!$this->handle) { - throw new Nette\InvalidStateException("Cannot open journal file '$this->file'."); - } - - if (!flock($this->handle, LOCK_SH)) { - throw new Nette\InvalidStateException('Cannot acquire shared lock on journal.'); - } - - $header = stream_get_contents($this->handle, 2 * self::INT32_SIZE, 0); - - flock($this->handle, LOCK_UN); - - list(, $fileMagic, $this->lastNode) = unpack('N2', $header); - - if ($fileMagic !== self::FILE_MAGIC) { - fclose($this->handle); - $this->handle = FALSE; - throw new Nette\InvalidStateException("Malformed journal file '$this->file'."); - } - - $this->processIdentifier = pack('N', mt_rand()); - } - - - /** - * Unlock file and save last modified time. - * @return void - */ - private function unlock() - { - if ($this->handle) { - fflush($this->handle); - flock($this->handle, LOCK_UN); - } - } - - - /** - * @param int $nodeId - * @param array $nodeData - * @return int - * @throws \Nette\InvalidStateException - */ - private function findNextFreeKey($nodeId, array & $nodeData) - { - $newKey = $nodeData[self::INFO][self::LAST_INDEX] + 1; - $maxKey = ($nodeId + 1) << self::BITROT; - - if ($newKey >= $maxKey) { - $start = $nodeId << self::BITROT; - for ($i = $start; $i < $maxKey; $i++) { - if (!isset($nodeData[$i])) { - return $i; - } - } - throw new Nette\InvalidStateException("Node $nodeId is full."); - } else { - return ++$nodeData[self::INFO][self::LAST_INDEX]; - } - } - - - /** - * Append $append to $array. - * This function is much faster then $array = array_merge($array, $append) - * @param array - * @param array - * @return void - */ - private function arrayAppend(array & $array, array $append) - { - foreach ($append as $value) { - $array[] = $value; - } - } - - - /** - * Append $append to $array with preserve keys. - * This function is much faster then $array = $array + $append - * @param array - * @param array - * @return void - */ - private function arrayAppendKeys(array & $array, array $append) - { - foreach ($append as $key => $value) { - $array[$key] = $value; - } - } -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/FileStorage.php php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/FileStorage.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/FileStorage.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/FileStorage.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,407 +0,0 @@ - timestamp) - META_CALLBACKS = 'callbacks'; // array of callbacks (function, args) - - /** additional cache structure */ - const FILE = 'file', - HANDLE = 'handle'; - - - /** @var float probability that the clean() routine is started */ - public static $gcProbability = 0.001; - - /** @var bool */ - public static $useDirectories = TRUE; - - /** @var string */ - private $dir; - - /** @var bool */ - private $useDirs; - - /** @var IJournal */ - private $journal; - - /** @var array */ - private $locks; - - - public function __construct($dir, IJournal $journal = NULL) - { - $this->dir = realpath($dir); - if ($this->dir === FALSE) { - throw new Nette\DirectoryNotFoundException("Directory '$dir' not found."); - } - - $this->useDirs = (bool) static::$useDirectories; - $this->journal = $journal; - - if (mt_rand() / mt_getrandmax() < static::$gcProbability) { - $this->clean(array()); - } - } - - - /** - * Read from cache. - * @param string key - * @return mixed|NULL - */ - public function read($key) - { - $meta = $this->readMetaAndLock($this->getCacheFile($key), LOCK_SH); - if ($meta && $this->verify($meta)) { - return $this->readData($meta); // calls fclose() - - } else { - return NULL; - } - } - - - /** - * Verifies dependencies. - * @param array - * @return bool - */ - private function verify($meta) - { - do { - if (!empty($meta[self::META_DELTA])) { - // meta[file] was added by readMetaAndLock() - if (filemtime($meta[self::FILE]) + $meta[self::META_DELTA] < time()) { - break; - } - touch($meta[self::FILE]); - - } elseif (!empty($meta[self::META_EXPIRE]) && $meta[self::META_EXPIRE] < time()) { - break; - } - - if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) { - break; - } - - if (!empty($meta[self::META_ITEMS])) { - foreach ($meta[self::META_ITEMS] as $depFile => $time) { - $m = $this->readMetaAndLock($depFile, LOCK_SH); - if ($m[self::META_TIME] !== $time || ($m && !$this->verify($m))) { - break 2; - } - } - } - - return TRUE; - } while (FALSE); - - $this->delete($meta[self::FILE], $meta[self::HANDLE]); // meta[handle] & meta[file] was added by readMetaAndLock() - return FALSE; - } - - - /** - * Prevents item reading and writing. Lock is released by write() or remove(). - * @param string key - * @return void - */ - public function lock($key) - { - $cacheFile = $this->getCacheFile($key); - if ($this->useDirs && !is_dir($dir = dirname($cacheFile))) { - @mkdir($dir); // @ - directory may already exist - } - $handle = fopen($cacheFile, 'c+b'); - if ($handle) { - $this->locks[$key] = $handle; - flock($handle, LOCK_EX); - } - } - - - /** - * Writes item into the cache. - * @param string key - * @param mixed data - * @param array dependencies - * @return void - */ - public function write($key, $data, array $dp) - { - $meta = array( - self::META_TIME => microtime(), - ); - - if (isset($dp[Cache::EXPIRATION])) { - if (empty($dp[Cache::SLIDING])) { - $meta[self::META_EXPIRE] = $dp[Cache::EXPIRATION] + time(); // absolute time - } else { - $meta[self::META_DELTA] = (int) $dp[Cache::EXPIRATION]; // sliding time - } - } - - if (isset($dp[Cache::ITEMS])) { - foreach ((array) $dp[Cache::ITEMS] as $item) { - $depFile = $this->getCacheFile($item); - $m = $this->readMetaAndLock($depFile, LOCK_SH); - $meta[self::META_ITEMS][$depFile] = $m[self::META_TIME]; // may be NULL - unset($m); - } - } - - if (isset($dp[Cache::CALLBACKS])) { - $meta[self::META_CALLBACKS] = $dp[Cache::CALLBACKS]; - } - - if (!isset($this->locks[$key])) { - $this->lock($key); - if (!isset($this->locks[$key])) { - return; - } - } - $handle = $this->locks[$key]; - unset($this->locks[$key]); - - $cacheFile = $this->getCacheFile($key); - - if (isset($dp[Cache::TAGS]) || isset($dp[Cache::PRIORITY])) { - if (!$this->journal) { - throw new Nette\InvalidStateException('CacheJournal has not been provided.'); - } - $this->journal->write($cacheFile, $dp); - } - - ftruncate($handle, 0); - - if (!is_string($data)) { - $data = serialize($data); - $meta[self::META_SERIALIZED] = TRUE; - } - - $head = serialize($meta) . '?>'; - $head = 'delete($cacheFile, $handle); - } - - - /** - * Removes item from the cache. - * @param string key - * @return void - */ - public function remove($key) - { - unset($this->locks[$key]); - $this->delete($this->getCacheFile($key)); - } - - - /** - * Removes items from the cache by conditions & garbage collector. - * @param array conditions - * @return void - */ - public function clean(array $conditions) - { - $all = !empty($conditions[Cache::ALL]); - $collector = empty($conditions); - - // cleaning using file iterator - if ($all || $collector) { - $now = time(); - foreach (Nette\Utils\Finder::find('_*')->from($this->dir)->childFirst() as $entry) { - $path = (string) $entry; - if ($entry->isDir()) { // collector: remove empty dirs - @rmdir($path); // @ - removing dirs is not necessary - continue; - } - if ($all) { - $this->delete($path); - - } else { // collector - $meta = $this->readMetaAndLock($path, LOCK_SH); - if (!$meta) { - continue; - } - - if ((!empty($meta[self::META_DELTA]) && filemtime($meta[self::FILE]) + $meta[self::META_DELTA] < $now) - || (!empty($meta[self::META_EXPIRE]) && $meta[self::META_EXPIRE] < $now) - ) { - $this->delete($path, $meta[self::HANDLE]); - continue; - } - - flock($meta[self::HANDLE], LOCK_UN); - fclose($meta[self::HANDLE]); - } - } - - if ($this->journal) { - $this->journal->clean($conditions); - } - return; - } - - // cleaning using journal - if ($this->journal) { - foreach ($this->journal->clean($conditions) as $file) { - $this->delete($file); - } - } - } - - - /** - * Reads cache data from disk. - * @param string file path - * @param int lock mode - * @return array|NULL - */ - protected function readMetaAndLock($file, $lock) - { - $handle = @fopen($file, 'r+b'); // @ - file may not exist - if (!$handle) { - return NULL; - } - - flock($handle, $lock); - - $head = stream_get_contents($handle, self::META_HEADER_LEN); - if ($head && strlen($head) === self::META_HEADER_LEN) { - $size = (int) substr($head, -6); - $meta = stream_get_contents($handle, $size, self::META_HEADER_LEN); - $meta = @unserialize($meta); // intentionally @ - if (is_array($meta)) { - $meta[self::FILE] = $file; - $meta[self::HANDLE] = $handle; - return $meta; - } - } - - flock($handle, LOCK_UN); - fclose($handle); - return NULL; - } - - - /** - * Reads cache data from disk and closes cache file handle. - * @param array - * @return mixed - */ - protected function readData($meta) - { - $data = stream_get_contents($meta[self::HANDLE]); - flock($meta[self::HANDLE], LOCK_UN); - fclose($meta[self::HANDLE]); - - if (empty($meta[self::META_SERIALIZED])) { - return $data; - } else { - return @unserialize($data); // intentionally @ - } - } - - - /** - * Returns file name. - * @param string - * @return string - */ - protected function getCacheFile($key) - { - $file = urlencode($key); - if ($this->useDirs && $a = strrpos($file, '%00')) { // %00 = urlencode(Nette\Caching\Cache::NAMESPACE_SEPARATOR) - $file = substr_replace($file, '/_', $a, 3); - } - return $this->dir . '/_' . $file; - } - - - /** - * Deletes and closes file. - * @param string - * @param resource - * @return void - */ - private static function delete($file, $handle = NULL) - { - if (@unlink($file)) { // @ - file may not already exist - if ($handle) { - flock($handle, LOCK_UN); - fclose($handle); - } - return; - } - - if (!$handle) { - $handle = @fopen($file, 'r+'); // @ - file may not exist - } - if ($handle) { - flock($handle, LOCK_EX); - ftruncate($handle, 0); - flock($handle, LOCK_UN); - fclose($handle); - @unlink($file); // @ - file may not already exist - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/IJournal.php php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/IJournal.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/IJournal.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/IJournal.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -prefix = $prefix; - $this->journal = $journal; - $this->memcache = new \Memcache; - if ($host) { - $this->addServer($host, $port); - } - } - - - public function addServer($host = 'localhost', $port = 11211, $timeout = 1) - { - if ($this->memcache->addServer($host, $port, TRUE, 1, $timeout) === FALSE) { - $error = error_get_last(); - throw new Nette\InvalidStateException("Memcache::addServer(): $error[message]."); - } - } - - - /** - * @return \Memcache - */ - public function getConnection() - { - return $this->memcache; - } - - - /** - * Read from cache. - * @param string key - * @return mixed|NULL - */ - public function read($key) - { - $key = $this->prefix . $key; - $meta = $this->memcache->get($key); - if (!$meta) { - return NULL; - } - - // meta structure: - // array( - // data => stored data - // delta => relative (sliding) expiration - // callbacks => array of callbacks (function, args) - // ) - - // verify dependencies - if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) { - $this->memcache->delete($key, 0); - return NULL; - } - - if (!empty($meta[self::META_DELTA])) { - $this->memcache->replace($key, $meta, 0, $meta[self::META_DELTA] + time()); - } - - return $meta[self::META_DATA]; - } - - - /** - * Prevents item reading and writing. Lock is released by write() or remove(). - * @param string key - * @return void - */ - public function lock($key) - { - } - - - /** - * Writes item into the cache. - * @param string key - * @param mixed data - * @param array dependencies - * @return void - */ - public function write($key, $data, array $dp) - { - if (isset($dp[Cache::ITEMS])) { - throw new Nette\NotSupportedException('Dependent items are not supported by MemcachedStorage.'); - } - - $key = $this->prefix . $key; - $meta = array( - self::META_DATA => $data, - ); - - $expire = 0; - if (isset($dp[Cache::EXPIRATION])) { - $expire = (int) $dp[Cache::EXPIRATION]; - if (!empty($dp[Cache::SLIDING])) { - $meta[self::META_DELTA] = $expire; // sliding time - } - } - - if (isset($dp[Cache::CALLBACKS])) { - $meta[self::META_CALLBACKS] = $dp[Cache::CALLBACKS]; - } - - if (isset($dp[Cache::TAGS]) || isset($dp[Cache::PRIORITY])) { - if (!$this->journal) { - throw new Nette\InvalidStateException('CacheJournal has not been provided.'); - } - $this->journal->write($key, $dp); - } - - $this->memcache->set($key, $meta, 0, $expire); - } - - - /** - * Removes item from the cache. - * @param string key - * @return void - */ - public function remove($key) - { - $this->memcache->delete($this->prefix . $key, 0); - } - - - /** - * Removes items from the cache by conditions & garbage collector. - * @param array conditions - * @return void - */ - public function clean(array $conditions) - { - if (!empty($conditions[Cache::ALL])) { - $this->memcache->flush(); - - } elseif ($this->journal) { - foreach ($this->journal->clean($conditions) as $entry) { - $this->memcache->delete($entry, 0); - } - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/MemoryStorage.php php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/MemoryStorage.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/MemoryStorage.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/MemoryStorage.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -data[$key]) ? $this->data[$key] : NULL; - } - - - /** - * Prevents item reading and writing. Lock is released by write() or remove(). - * @param string key - * @return void - */ - public function lock($key) - { - } - - - /** - * Writes item into the cache. - * @param string key - * @param mixed data - * @param array dependencies - * @return void - */ - public function write($key, $data, array $dependencies) - { - $this->data[$key] = $data; - } - - - /** - * Removes item from the cache. - * @param string key - * @return void - */ - public function remove($key) - { - unset($this->data[$key]); - } - - - /** - * Removes items from the cache by conditions & garbage collector. - * @param array conditions - * @return void - */ - public function clean(array $conditions) - { - if (!empty($conditions[Nette\Caching\Cache::ALL])) { - $this->data = array(); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/PhpFileStorage.php php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/PhpFileStorage.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/PhpFileStorage.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/PhpFileStorage.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ - $meta[self::FILE], - 'handle' => $meta[self::HANDLE], - ); - } - - - /** - * Returns file name. - * @param string - * @return string - */ - protected function getCacheFile($key) - { - return parent::getCacheFile(substr_replace( - $key, - trim(strtr($this->hint, '\\/@', '.._'), '.') . '-', - strpos($key, Nette\Caching\Cache::NAMESPACE_SEPARATOR) + 1, - 0 - )) . '.php'; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/SQLiteStorage.php php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/SQLiteStorage.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Caching/Storages/SQLiteStorage.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Caching/Storages/SQLiteStorage.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -pdo = new \PDO('sqlite:' . $path, NULL, NULL, array(\PDO::ATTR_PERSISTENT => TRUE)); - $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $this->pdo->exec(' - PRAGMA foreign_keys = ON; - CREATE TABLE IF NOT EXISTS cache ( - key BLOB NOT NULL PRIMARY KEY, data BLOB NOT NULL - ); - CREATE TABLE IF NOT EXISTS tags ( - key BLOB NOT NULL REFERENCES cache ON DELETE CASCADE, - tag BLOB NOT NULL - ); - CREATE INDEX IF NOT EXISTS tags_key ON tags(key); - CREATE INDEX IF NOT EXISTS tags_tag ON tags(tag); - '); - } - - - /** - * Read from cache. - * @param string key - * @return mixed|NULL - */ - public function read($key) - { - $stmt = $this->pdo->prepare('SELECT data FROM cache WHERE key=?'); - $stmt->execute(array($key)); - if ($res = $stmt->fetchColumn()) { - return unserialize($res); - } - } - - - /** - * Prevents item reading and writing. Lock is released by write() or remove(). - * @param string key - * @return void - */ - public function lock($key) - { - } - - - /** - * Writes item into the cache. - * @param string key - * @param mixed data - * @param array dependencies - * @return void - */ - public function write($key, $data, array $dependencies) - { - $this->pdo->prepare('BEGIN TRANSACTION'); - $this->pdo->prepare('REPLACE INTO cache (key, data) VALUES (?, ?)') - ->execute(array($key, serialize($data))); - - if (!empty($dependencies[Cache::TAGS])) { - foreach ((array) $dependencies[Cache::TAGS] as $tag) { - $arr[] = $key; - $arr[] = $tag; - } - $this->pdo->prepare('INSERT INTO tags (key, tag) SELECT ?, ?' . str_repeat('UNION SELECT ?, ?', count($arr) / 2 - 1)) - ->execute($arr); - } - $this->pdo->prepare('COMMIT'); - } - - - /** - * Removes item from the cache. - * @param string key - * @return void - */ - public function remove($key) - { - $this->pdo->prepare('DELETE FROM cache WHERE key=?') - ->execute(array($key)); - } - - - /** - * Removes items from the cache by conditions & garbage collector. - * @param array conditions - * @return void - */ - public function clean(array $conditions) - { - if (!empty($conditions[Cache::ALL])) { - $this->pdo->prepare('DELETE FROM cache'); - - } elseif (!empty($conditions[Cache::TAGS])) { - $tags = (array) $conditions[Cache::TAGS]; - $this->pdo->prepare('DELETE FROM cache WHERE key IN (SELECT key FROM tags WHERE tag IN (?' - . str_repeat(',?', count($tags) - 1) . '))')->execute($tags); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/ArrayHash.php php-nette-2.1.5/Nette-2.1.4/Nette/common/ArrayHash.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/ArrayHash.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/ArrayHash.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ - $value) { - if ($recursive && is_array($value)) { - $obj->$key = static::from($value, TRUE); - } else { - $obj->$key = $value; - } - } - return $obj; - } - - - /** - * Returns an iterator over all items. - * @return \RecursiveArrayIterator - */ - public function getIterator() - { - return new \RecursiveArrayIterator($this); - } - - - /** - * Returns items count. - * @return int - */ - public function count() - { - return count((array) $this); - } - - - /** - * Replaces or appends a item. - * @return void - */ - public function offsetSet($key, $value) - { - if (!is_scalar($key)) { // prevents NULL - throw new Nette\InvalidArgumentException(sprintf('Key must be either a string or an integer, %s given.', gettype($key))); - } - $this->$key = $value; - } - - - /** - * Returns a item. - * @return mixed - */ - public function offsetGet($key) - { - return $this->$key; - } - - - /** - * Determines whether a item exists. - * @return bool - */ - public function offsetExists($key) - { - return isset($this->$key); - } - - - /** - * Removes the element from this list. - * @return void - */ - public function offsetUnset($key) - { - unset($this->$key); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/ArrayList.php php-nette-2.1.5/Nette-2.1.4/Nette/common/ArrayList.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/ArrayList.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/ArrayList.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -list); - } - - - /** - * Returns items count. - * @return int - */ - public function count() - { - return count($this->list); - } - - - /** - * Replaces or appends a item. - * @param int - * @param mixed - * @return void - * @throws OutOfRangeException - */ - public function offsetSet($index, $value) - { - if ($index === NULL) { - $this->list[] = $value; - - } elseif ($index < 0 || $index >= count($this->list)) { - throw new OutOfRangeException('Offset invalid or out of range'); - - } else { - $this->list[(int) $index] = $value; - } - } - - - /** - * Returns a item. - * @param int - * @return mixed - * @throws OutOfRangeException - */ - public function offsetGet($index) - { - if ($index < 0 || $index >= count($this->list)) { - throw new OutOfRangeException('Offset invalid or out of range'); - } - return $this->list[(int) $index]; - } - - - /** - * Determines whether a item exists. - * @param int - * @return bool - */ - public function offsetExists($index) - { - return $index >= 0 && $index < count($this->list); - } - - - /** - * Removes the element at the specified position in this list. - * @param int - * @return void - * @throws OutOfRangeException - */ - public function offsetUnset($index) - { - if ($index < 0 || $index >= count($this->list)) { - throw new OutOfRangeException('Offset invalid or out of range'); - } - array_splice($this->list, (int) $index, 1); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/Callback.php php-nette-2.1.5/Nette-2.1.4/Nette/common/Callback.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/Callback.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/Callback.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,172 +0,0 @@ -invoke() in PHP 5.3. - * @param mixed class, object, callable - * @param string method - * @return Callback - */ - public static function create($callback, $m = NULL) - { - return new self($callback, $m); - } - - - /** - * @param mixed class, object, callable - * @param string method - */ - public function __construct($cb, $m = NULL) - { - if ($m !== NULL) { - $cb = array($cb, $m); - - } elseif ($cb instanceof self) { // prevents wrapping itself - $this->cb = $cb->cb; - return; - } - - if (!is_callable($cb, TRUE)) { - throw new InvalidArgumentException("Invalid callback."); - } - $this->cb = $cb; - } - - - /** - * Invokes callback. Do not call directly. - * @return mixed - */ - public function __invoke() - { - if (!is_callable($this->cb)) { - throw new InvalidStateException("Callback '$this' is not callable."); - } - return call_user_func_array($this->cb, func_get_args()); - } - - - /** - * Invokes callback. - * @return mixed - */ - public function invoke() - { - if (!is_callable($this->cb)) { - throw new InvalidStateException("Callback '$this' is not callable."); - } - return call_user_func_array($this->cb, func_get_args()); - } - - - /** - * Invokes callback with an array of parameters. - * @param array - * @return mixed - */ - public function invokeArgs(array $args) - { - if (!is_callable($this->cb)) { - throw new InvalidStateException("Callback '$this' is not callable."); - } - return call_user_func_array($this->cb, $args); - } - - - /** - * Verifies that callback can be called. - * @return bool - */ - public function isCallable() - { - return is_callable($this->cb); - } - - - /** - * Returns PHP callback pseudotype. - * @return string|array|\Closure - */ - public function getNative() - { - return $this->cb; - } - - - /** - * Returns callback reflection. - * @return Nette\Reflection\GlobalFunction|Nette\Reflection\Method - */ - public function toReflection() - { - if (is_string($this->cb) && strpos($this->cb, '::')) { - return new Nette\Reflection\Method($this->cb); - } elseif (is_array($this->cb)) { - return new Nette\Reflection\Method($this->cb[0], $this->cb[1]); - } elseif (is_object($this->cb) && !$this->cb instanceof \Closure) { - return new Nette\Reflection\Method($this->cb, '__invoke'); - } else { - return new Nette\Reflection\GlobalFunction($this->cb); - } - } - - - /** - * @return bool - */ - public function isStatic() - { - return is_array($this->cb) ? is_string($this->cb[0]) : is_string($this->cb); - } - - - /** - * Duplicates the callback with a new bound object. - * @return Callback - */ - public function bindTo($newthis) - { - if (is_string($this->cb) && strpos($this->cb, '::')) { - $this->cb = explode('::', $this->cb); - } elseif (!is_array($this->cb)) { - throw new InvalidStateException("Callback '$this' have not any bound object."); - } - return new static($newthis, $this->cb[1]); - } - - - /** - * @return string - */ - public function __toString() - { - if ($this->cb instanceof \Closure) { - return '{closure}'; - } elseif (is_string($this->cb) && $this->cb[0] === "\0") { - return '{lambda}'; - } else { - is_callable($this->cb, TRUE, $textual); - return $textual; - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/Configurator.php php-nette-2.1.5/Nette-2.1.4/Nette/common/Configurator.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/Configurator.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/Configurator.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,303 +0,0 @@ - 'Nette\DI\Extensions\PhpExtension', - 'constants' => 'Nette\DI\Extensions\ConstantsExtension', - 'nette' => 'Nette\DI\Extensions\NetteExtension', - 'extensions' => 'Nette\DI\Extensions\ExtensionsExtension', - ); - - /** @var array */ - protected $parameters; - - /** @var array */ - protected $files = array(); - - - public function __construct() - { - $this->parameters = $this->getDefaultParameters(); - } - - - /** - * Set parameter %debugMode%. - * @param bool|string|array - * @return self - */ - public function setDebugMode($value = TRUE) - { - $this->parameters['debugMode'] = is_string($value) || is_array($value) ? static::detectDebugMode($value) : (bool) $value; - $this->parameters['productionMode'] = !$this->parameters['debugMode']; // compatibility - return $this; - } - - - /** - * @return bool - */ - public function isDebugMode() - { - return $this->parameters['debugMode']; - } - - - /** - * Sets path to temporary directory. - * @return self - */ - public function setTempDirectory($path) - { - $this->parameters['tempDir'] = $path; - return $this; - } - - - /** - * Adds new parameters. The %params% will be expanded. - * @return self - */ - public function addParameters(array $params) - { - $this->parameters = DI\Config\Helpers::merge($params, $this->parameters); - return $this; - } - - - /** - * @return array - */ - protected function getDefaultParameters() - { - $trace = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : FALSE); - $debugMode = static::detectDebugMode(); - return array( - 'appDir' => isset($trace[1]['file']) ? dirname($trace[1]['file']) : NULL, - 'wwwDir' => isset($_SERVER['SCRIPT_FILENAME']) - ? dirname(realpath($_SERVER['SCRIPT_FILENAME'])) - : NULL, - 'debugMode' => $debugMode, - 'productionMode' => !$debugMode, - 'environment' => $debugMode ? 'development' : 'production', - 'consoleMode' => PHP_SAPI === 'cli', - 'container' => array( - 'class' => 'SystemContainer', - 'parent' => 'Nette\DI\Container', - ) - ); - } - - - /** - * @param string error log directory - * @param string administrator email - * @return void - */ - public function enableDebugger($logDirectory = NULL, $email = NULL) - { - Nette\Diagnostics\Debugger::$strictMode = TRUE; - Nette\Diagnostics\Debugger::enable(!$this->parameters['debugMode'], $logDirectory, $email); - } - - - /** - * @return Nette\Loaders\RobotLoader - */ - public function createRobotLoader() - { - $loader = new Nette\Loaders\RobotLoader; - $loader->setCacheStorage(new Nette\Caching\Storages\FileStorage($this->getCacheDirectory())); - $loader->autoRebuild = $this->parameters['debugMode']; - return $loader; - } - - - /** - * Adds configuration file. - * @return self - */ - public function addConfig($file, $section = NULL) - { - $this->files[] = array($file, $section === self::AUTO ? $this->parameters['environment'] : $section); - return $this; - } - - - /** - * Returns system DI container. - * @return \SystemContainer - */ - public function createContainer() - { - $cache = new Nette\Caching\Cache(new Nette\Caching\Storages\PhpFileStorage($this->getCacheDirectory()), 'Nette.Configurator'); - $cacheKey = array($this->parameters, $this->files); - $cached = $cache->load($cacheKey); - if (!$cached) { - $code = $this->buildContainer($dependencies); - $cache->save($cacheKey, $code, array($cache::FILES => $dependencies)); - $cached = $cache->load($cacheKey); - } - require_once $cached['file']; - - $container = new $this->parameters['container']['class']; - $container->initialize(); - Nette\Environment::setContext($container); // back compatibility - return $container; - } - - - /** - * Build system container class. - * @return string - */ - protected function buildContainer(& $dependencies = NULL) - { - $loader = $this->createLoader(); - $config = array(); - $code = "files as $tmp) { - list($file, $section) = $tmp; - $code .= "// source: $file $section\n"; - try { - if ($section === NULL) { // back compatibility - $config = DI\Config\Helpers::merge($loader->load($file, $this->parameters['environment']), $config); - continue; - } - } catch (Nette\InvalidStateException $e) { - } catch (Nette\Utils\AssertionException $e) { - } - - $config = DI\Config\Helpers::merge($loader->load($file, $section), $config); - } - $code .= "\n"; - - if (!isset($config['parameters'])) { - $config['parameters'] = array(); - } - $config['parameters'] = DI\Config\Helpers::merge($config['parameters'], $this->parameters); - - $compiler = $this->createCompiler(); - $this->onCompile($this, $compiler); - - $code .= $compiler->compile( - $config, - $this->parameters['container']['class'], - $config['parameters']['container']['parent'] - ); - $dependencies = array_merge($loader->getDependencies(), $this->parameters['debugMode'] ? $compiler->getContainerBuilder()->getDependencies() : array()); - return $code; - } - - - /** - * @return Compiler - */ - protected function createCompiler() - { - $compiler = new DI\Compiler; - - foreach ($this->defaultExtensions as $name => $class) { - $compiler->addExtension($name, new $class); - } - - return $compiler; - } - - - /** - * @return Loader - */ - protected function createLoader() - { - return new DI\Config\Loader; - } - - - protected function getCacheDirectory() - { - if (empty($this->parameters['tempDir'])) { - throw new Nette\InvalidStateException("Set path to temporary directory using setTempDirectory()."); - } - $dir = $this->parameters['tempDir'] . '/cache'; - if (!is_dir($dir)) { - mkdir($dir); - } - return $dir; - } - - - /********************* tools ****************d*g**/ - - - /** - * Detects debug mode by IP address. - * @param string|array IP addresses or computer names whitelist detection - * @return bool - */ - public static function detectDebugMode($list = NULL) - { - $list = is_string($list) ? preg_split('#[,\s]+#', $list) : (array) $list; - if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $list[] = '127.0.0.1'; - $list[] = '::1'; - } - return in_array(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : php_uname('n'), $list, TRUE); - } - - - /** @deprecated */ - public function setProductionMode($value = TRUE) - { - trigger_error(__METHOD__ . '() is deprecated; use setDebugMode(!$value) instead.', E_USER_DEPRECATED); - return $this->setDebugMode(is_bool($value) ? !$value : $value); - } - - - /** @deprecated */ - public function isProductionMode() - { - trigger_error(__METHOD__ . '() is deprecated; use !isDebugMode() instead.', E_USER_DEPRECATED); - return !$this->isDebugMode(); - } - - - /** @deprecated */ - public static function detectProductionMode($list = NULL) - { - trigger_error(__METHOD__ . '() is deprecated; use !detectDebugMode() instead.', E_USER_DEPRECATED); - return !static::detectDebugMode($list); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/DateTime.php php-nette-2.1.5/Nette-2.1.4/Nette/common/DateTime.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/DateTime.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/DateTime.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -format('Y-m-d H:i:s'), $time->getTimezone()); - - } elseif (is_numeric($time)) { - if ($time <= self::YEAR) { - $time += time(); - } - $tmp = new static('@' . $time); - return $tmp->setTimeZone(new \DateTimeZone(date_default_timezone_get())); - - } else { // textual or NULL - return new static($time); - } - } - - - public function __toString() - { - return $this->format('Y-m-d H:i:s'); - } - - - public function modifyClone($modify = '') - { - $dolly = clone $this; - return $modify ? $dolly->modify($modify) : $dolly; - } - - - public function setTimestamp($timestamp) - { - $zone = $this->getTimezone(); - $this->__construct('@' . $timestamp); - return $this->setTimeZone($zone); - } - - - public function getTimestamp() - { - $ts = $this->format('U'); - return is_float($tmp = $ts * 1) ? $ts : $tmp; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/Environment.php php-nette-2.1.5/Nette-2.1.4/Nette/common/Environment.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/Environment.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/Environment.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,331 +0,0 @@ -expand($value); - } - self::getContext()->parameters[$name] = $value; - } - - - /** - * Returns the value of an environment variable or $default if there is no element set. - * @param string - * @param mixed default value to use if key not found - * @return mixed - * @throws InvalidStateException - */ - public static function getVariable($name, $default = NULL) - { - if (isset(self::getContext()->parameters[$name])) { - return self::getContext()->parameters[$name]; - } elseif (func_num_args() > 1) { - return $default; - } else { - throw new InvalidStateException("Unknown environment variable '$name'."); - } - } - - - /** - * Returns the all environment variables. - * @return array - */ - public static function getVariables() - { - return self::getContext()->parameters; - } - - - /** - * Returns expanded variable. - * @param string - * @return string - * @throws InvalidStateException - */ - public static function expand($s) - { - return self::getContext()->expand($s); - } - - - /********************* context ****************d*g**/ - - - /** - * Sets initial instance of context. - * @return void - */ - public static function setContext(DI\Container $context) - { - if (self::$createdAt) { - throw new Nette\InvalidStateException('Configurator & SystemContainer has already been created automatically by Nette\Environment at ' . self::$createdAt); - } - self::$context = $context; - } - - - /** - * Get initial instance of context. - * @return \SystemContainer|Nette\DI\Container - */ - public static function getContext() - { - if (self::$context === NULL) { - self::loadConfig(); - } - return self::$context; - } - - - /** - * Gets the service object of the specified type. - * @param string service name - * @return object - */ - public static function getService($name) - { - return self::getContext()->getService($name); - } - - - /** - * Calling to undefined static method. - * @param string method name - * @param array arguments - * @return object service - */ - public static function __callStatic($name, $args) - { - if (!$args && strncasecmp($name, 'get', 3) === 0) { - return self::getService(lcfirst(substr($name, 3))); - } else { - throw new MemberAccessException("Call to undefined static method Nette\\Environment::$name()."); - } - } - - - /** - * @return Nette\Http\Request - */ - public static function getHttpRequest() - { - return self::getContext()->getByType('Nette\Http\IRequest'); - } - - - /** - * @return Nette\Http\Context - */ - public static function getHttpContext() - { - return self::getContext()->getByType('Nette\Http\Context'); - } - - - /** - * @return Nette\Http\Response - */ - public static function getHttpResponse() - { - return self::getContext()->getByType('Nette\Http\IResponse'); - } - - - /** - * @return Nette\Application\Application - */ - public static function getApplication() - { - return self::getContext()->getByType('Nette\Application\Application'); - } - - - /** - * @return Nette\Security\User - */ - public static function getUser() - { - return self::getContext()->getByType('Nette\Security\User'); - } - - - /** - * @return Nette\Loaders\RobotLoader - */ - public static function getRobotLoader() - { - return self::getContext()->getByType('Nette\Loaders\RobotLoader'); - } - - - /********************* service factories ****************d*g**/ - - - /** - * @param string - * @return Nette\Caching\Cache - */ - public static function getCache($namespace = '') - { - return new Caching\Cache(self::getContext()->getByType('Nette\Caching\IStorage'), $namespace); - } - - - /** - * Returns instance of session or session namespace. - * @param string - * @return Nette\Http\Session - */ - public static function getSession($namespace = NULL) - { - return $namespace === NULL - ? self::getContext()->getByType('Nette\Http\Session') - : self::getContext()->getByType('Nette\Http\Session')->getSection($namespace); - } - - - /********************* global configuration ****************d*g**/ - - - /** - * Loads global configuration from file and process it. - * @param string - * @param string - * @return Nette\ArrayHash - */ - public static function loadConfig($file = NULL, $section = NULL) - { - if (self::$createdAt) { - throw new Nette\InvalidStateException('Nette\Configurator has already been created automatically by Nette\Environment at ' . self::$createdAt); - } elseif (!defined('TEMP_DIR')) { - throw new Nette\InvalidStateException('Nette\Environment requires constant TEMP_DIR with path to temporary directory.'); - } - $configurator = new Nette\Configurator; - $configurator - ->setDebugMode(!self::isProduction()) - ->setTempDirectory(TEMP_DIR) - ->addParameters(array('container' => array('class' => 'EnvironmentContainer'))); - if ($file) { - $configurator->addConfig($file, $section); - } - self::$context = $configurator->createContainer(); - - self::$createdAt = '?'; - foreach (debug_backtrace(FALSE) as $row) { - if (isset($row['file']) && $row['file'] !== __FILE__ && is_file($row['file'])) { - self::$createdAt = "$row[file]:$row[line]"; - break; - } - } - return self::getConfig(); - } - - - /** - * Returns the global configuration. - * @param string key - * @param mixed default value - * @return mixed - */ - public static function getConfig($key = NULL, $default = NULL) - { - $params = Nette\ArrayHash::from(self::getContext()->parameters); - if (func_num_args()) { - return isset($params[$key]) ? $params[$key] : $default; - } else { - return $params; - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/exceptions.php php-nette-2.1.5/Nette-2.1.4/Nette/common/exceptions.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/exceptions.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/exceptions.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -context = $context; - trigger_error(__CLASS__ . ' is deprecated, use ErrorException.', E_USER_DEPRECATED); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/Framework.php php-nette-2.1.5/Nette-2.1.4/Nette/common/Framework.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/Framework.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/Framework.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -frozen = TRUE; - } - - - /** - * Is the object unmodifiable? - * @return bool - */ - public function isFrozen() - { - return $this->frozen; - } - - - /** - * Creates a modifiable clone of the object. - * @return void - */ - public function __clone() - { - $this->frozen = FALSE; - } - - - /** - * @return void - */ - protected function updating() - { - if ($this->frozen) { - $class = get_class($this); - throw new InvalidStateException("Cannot modify a frozen object $class."); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/IFreezable.php php-nette-2.1.5/Nette-2.1.4/Nette/common/IFreezable.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/IFreezable.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/IFreezable.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ - - * $image = Image::fromFile('nette.jpg'); - * $image->resize(150, 100); - * $image->sharpen(); - * $image->send(); - * - * - * @author David Grudl - * - * @method void alphaBlending(bool $on) - * @method void antialias(bool $on) - * @method void arc($x, $y, $w, $h, $s, $e, $color) - * @method void char($font, $x, $y, $char, $color) - * @method void charUp($font, $x, $y, $char, $color) - * @method int colorAllocate($red, $green, $blue) - * @method int colorAllocateAlpha($red, $green, $blue, $alpha) - * @method int colorAt($x, $y) - * @method int colorClosest($red, $green, $blue) - * @method int colorClosestAlpha($red, $green, $blue, $alpha) - * @method int colorClosestHWB($red, $green, $blue) - * @method void colorDeallocate($color) - * @method int colorExact($red, $green, $blue) - * @method int colorExactAlpha($red, $green, $blue, $alpha) - * @method void colorMatch(Image $image2) - * @method int colorResolve($red, $green, $blue) - * @method int colorResolveAlpha($red, $green, $blue, $alpha) - * @method void colorSet($index, $red, $green, $blue) - * @method array colorsForIndex($index) - * @method int colorsTotal() - * @method int colorTransparent([$color]) - * @method void convolution(array $matrix, float $div, float $offset) - * @method void copy(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH) - * @method void copyMerge(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH, $opacity) - * @method void copyMergeGray(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH, $opacity) - * @method void copyResampled(Image $src, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) - * @method void copyResized(Image $src, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) - * @method void dashedLine($x1, $y1, $x2, $y2, $color) - * @method void ellipse($cx, $cy, $w, $h, $color) - * @method void fill($x, $y, $color) - * @method void filledArc($cx, $cy, $w, $h, $s, $e, $color, $style) - * @method void filledEllipse($cx, $cy, $w, $h, $color) - * @method void filledPolygon(array $points, $numPoints, $color) - * @method void filledRectangle($x1, $y1, $x2, $y2, $color) - * @method void fillToBorder($x, $y, $border, $color) - * @method void filter($filtertype [, ...]) - * @method int fontHeight($font) - * @method int fontWidth($font) - * @method array ftBBox($size, $angle, string $fontFile, string $text [, array $extrainfo]) - * @method array ftText($size, $angle, $x, $y, $col, string $fontFile, string $text [, array $extrainfo]) - * @method void gammaCorrect(float $inputgamma, float $outputgamma) - * @method int interlace([$interlace]) - * @method bool isTrueColor() - * @method void layerEffect($effect) - * @method void line($x1, $y1, $x2, $y2, $color) - * @method int loadFont(string $file) - * @method void paletteCopy(Image $source) - * @method void polygon(array $points, $numPoints, $color) - * @method array psBBox(string $text, $font, $size [, $space] [, $tightness] [, float $angle]) - * @method void psEncodeFont($fontIndex, string $encodingfile) - * @method void psExtendFont($fontIndex, float $extend) - * @method void psFreeFont($fontindex) - * @method resource psLoadFont(string $filename) - * @method void psSlantFont($fontIndex, float $slant) - * @method array psText(string $text, $font, $size, $color, $backgroundColor, $x, $y [, $space] [, $tightness] [, float $angle] [, $antialiasSteps]) - * @method void rectangle($x1, $y1, $x2, $y2, $col) - * @method Image rotate(float $angle, $backgroundColor) - * @method void saveAlpha(bool $saveflag) - * @method void setBrush(Image $brush) - * @method void setPixel($x, $y, $color) - * @method void setStyle(array $style) - * @method void setThickness($thickness) - * @method void setTile(Image $tile) - * @method void string($font, $x, $y, string $s, $col) - * @method void stringUp($font, $x, $y, string $s, $col) - * @method void trueColorToPalette(bool $dither, $ncolors) - * @method array ttfBBox($size, $angle, string $fontfile, string $text) - * @method array ttfText($size, $angle, $x, $y, $color, string $fontfile, string $text) - * @method int types() - * @property-read int $width - * @property-read int $height - * @property-read resource $imageResource - */ -class Image extends Object -{ - /** {@link resize()} only shrinks images */ - const SHRINK_ONLY = 1; - - /** {@link resize()} will ignore aspect ratio */ - const STRETCH = 2; - - /** {@link resize()} fits in given area so its dimensions are less than or equal to the required dimensions */ - const FIT = 0; - - /** {@link resize()} fills given area so its dimensions are greater than or equal to the required dimensions */ - const FILL = 4; - - /** {@link resize()} fills given area exactly */ - const EXACT = 8; - - /** @int image types {@link send()} */ - const JPEG = IMAGETYPE_JPEG, - PNG = IMAGETYPE_PNG, - GIF = IMAGETYPE_GIF; - - const EMPTY_GIF = "GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;"; - - /** @deprecated */ - const ENLARGE = 0; - - /** @var resource */ - private $image; - - - /** - * Returns RGB color. - * @param int red 0..255 - * @param int green 0..255 - * @param int blue 0..255 - * @param int transparency 0..127 - * @return array - */ - public static function rgb($red, $green, $blue, $transparency = 0) - { - return array( - 'red' => max(0, min(255, (int) $red)), - 'green' => max(0, min(255, (int) $green)), - 'blue' => max(0, min(255, (int) $blue)), - 'alpha' => max(0, min(127, (int) $transparency)), - ); - } - - - /** - * Opens image from file. - * @param string - * @param mixed detected image format - * @throws Nette\NotSupportedException if gd extension is not loaded - * @throws UnknownImageFileException if file not found or file type is not known - * @return Image - */ - public static function fromFile($file, & $format = NULL) - { - if (!extension_loaded('gd')) { - throw new NotSupportedException('PHP extension GD is not loaded.'); - } - - $info = @getimagesize($file); // @ - files smaller than 12 bytes causes read error - - switch ($format = $info[2]) { - case self::JPEG: - return new static(imagecreatefromjpeg($file)); - - case self::PNG: - return new static(imagecreatefrompng($file)); - - case self::GIF: - return new static(imagecreatefromgif($file)); - - default: - throw new UnknownImageFileException("Unknown image type or file '$file' not found."); - } - } - - - /** - * Get format from the image stream in the string. - * @param string - * @return mixed detected image format - */ - public static function getFormatFromString($s) - { - $types = array('image/jpeg' => self::JPEG, 'image/gif' => self::GIF, 'image/png' => self::PNG); - $type = Utils\MimeTypeDetector::fromString($s); - return isset($types[$type]) ? $types[$type] : NULL; - } - - - /** - * Create a new image from the image stream in the string. - * @param string - * @param mixed detected image format - * @return Image - */ - public static function fromString($s, & $format = NULL) - { - if (!extension_loaded('gd')) { - throw new NotSupportedException('PHP extension GD is not loaded.'); - } - - $format = static::getFormatFromString($s); - - return new static(imagecreatefromstring($s)); - } - - - /** - * Creates blank image. - * @param int - * @param int - * @param array - * @return Image - */ - public static function fromBlank($width, $height, $color = NULL) - { - if (!extension_loaded('gd')) { - throw new NotSupportedException('PHP extension GD is not loaded.'); - } - - $width = (int) $width; - $height = (int) $height; - if ($width < 1 || $height < 1) { - throw new InvalidArgumentException('Image width and height must be greater than zero.'); - } - - $image = imagecreatetruecolor($width, $height); - if (is_array($color)) { - $color += array('alpha' => 0); - $color = imagecolorallocatealpha($image, $color['red'], $color['green'], $color['blue'], $color['alpha']); - imagealphablending($image, FALSE); - imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $color); - imagealphablending($image, TRUE); - } - return new static($image); - } - - - /** - * Wraps GD image. - * @param resource - */ - public function __construct($image) - { - $this->setImageResource($image); - imagesavealpha($image, TRUE); - } - - - /** - * Returns image width. - * @return int - */ - public function getWidth() - { - return imagesx($this->image); - } - - - /** - * Returns image height. - * @return int - */ - public function getHeight() - { - return imagesy($this->image); - } - - - /** - * Sets image resource. - * @param resource - * @return self - */ - protected function setImageResource($image) - { - if (!is_resource($image) || get_resource_type($image) !== 'gd') { - throw new InvalidArgumentException('Image is not valid.'); - } - $this->image = $image; - return $this; - } - - - /** - * Returns image GD resource. - * @return resource - */ - public function getImageResource() - { - return $this->image; - } - - - /** - * Resizes image. - * @param mixed width in pixels or percent - * @param mixed height in pixels or percent - * @param int flags - * @return self - */ - public function resize($width, $height, $flags = self::FIT) - { - if ($flags & self::EXACT) { - return $this->resize($width, $height, self::FILL)->crop('50%', '50%', $width, $height); - } - - list($newWidth, $newHeight) = static::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $flags); - - if ($newWidth !== $this->getWidth() || $newHeight !== $this->getHeight()) { // resize - $newImage = static::fromBlank($newWidth, $newHeight, self::RGB(0, 0, 0, 127))->getImageResource(); - imagecopyresampled( - $newImage, $this->getImageResource(), - 0, 0, 0, 0, - $newWidth, $newHeight, $this->getWidth(), $this->getHeight() - ); - $this->image = $newImage; - } - - if ($width < 0 || $height < 0) { // flip is processed in two steps for better quality - $newImage = static::fromBlank($newWidth, $newHeight, self::RGB(0, 0, 0, 127))->getImageResource(); - imagecopyresampled( - $newImage, $this->getImageResource(), - 0, 0, $width < 0 ? $newWidth - 1 : 0, $height < 0 ? $newHeight - 1 : 0, - $newWidth, $newHeight, $width < 0 ? -$newWidth : $newWidth, $height < 0 ? -$newHeight : $newHeight - ); - $this->image = $newImage; - } - return $this; - } - - - /** - * Calculates dimensions of resized image. - * @param mixed source width - * @param mixed source height - * @param mixed width in pixels or percent - * @param mixed height in pixels or percent - * @param int flags - * @return array - */ - public static function calculateSize($srcWidth, $srcHeight, $newWidth, $newHeight, $flags = self::FIT) - { - if (substr($newWidth, -1) === '%') { - $newWidth = round($srcWidth / 100 * abs($newWidth)); - $percents = TRUE; - } else { - $newWidth = (int) abs($newWidth); - } - - if (substr($newHeight, -1) === '%') { - $newHeight = round($srcHeight / 100 * abs($newHeight)); - $flags |= empty($percents) ? 0 : self::STRETCH; - } else { - $newHeight = (int) abs($newHeight); - } - - if ($flags & self::STRETCH) { // non-proportional - if (empty($newWidth) || empty($newHeight)) { - throw new InvalidArgumentException('For stretching must be both width and height specified.'); - } - - if ($flags & self::SHRINK_ONLY) { - $newWidth = round($srcWidth * min(1, $newWidth / $srcWidth)); - $newHeight = round($srcHeight * min(1, $newHeight / $srcHeight)); - } - - } else { // proportional - if (empty($newWidth) && empty($newHeight)) { - throw new InvalidArgumentException('At least width or height must be specified.'); - } - - $scale = array(); - if ($newWidth > 0) { // fit width - $scale[] = $newWidth / $srcWidth; - } - - if ($newHeight > 0) { // fit height - $scale[] = $newHeight / $srcHeight; - } - - if ($flags & self::FILL) { - $scale = array(max($scale)); - } - - if ($flags & self::SHRINK_ONLY) { - $scale[] = 1; - } - - $scale = min($scale); - $newWidth = round($srcWidth * $scale); - $newHeight = round($srcHeight * $scale); - } - - return array(max((int) $newWidth, 1), max((int) $newHeight, 1)); - } - - - /** - * Crops image. - * @param mixed x-offset in pixels or percent - * @param mixed y-offset in pixels or percent - * @param mixed width in pixels or percent - * @param mixed height in pixels or percent - * @return self - */ - public function crop($left, $top, $width, $height) - { - list($left, $top, $width, $height) = static::calculateCutout($this->getWidth(), $this->getHeight(), $left, $top, $width, $height); - $newImage = static::fromBlank($width, $height, self::RGB(0, 0, 0, 127))->getImageResource(); - imagecopy($newImage, $this->getImageResource(), 0, 0, $left, $top, $width, $height); - $this->image = $newImage; - return $this; - } - - - /** - * Calculates dimensions of cutout in image. - * @param mixed source width - * @param mixed source height - * @param mixed x-offset in pixels or percent - * @param mixed y-offset in pixels or percent - * @param mixed width in pixels or percent - * @param mixed height in pixels or percent - * @return array - */ - public static function calculateCutout($srcWidth, $srcHeight, $left, $top, $newWidth, $newHeight) - { - if (substr($newWidth, -1) === '%') { - $newWidth = round($srcWidth / 100 * $newWidth); - } - if (substr($newHeight, -1) === '%') { - $newHeight = round($srcHeight / 100 * $newHeight); - } - if (substr($left, -1) === '%') { - $left = round(($srcWidth - $newWidth) / 100 * $left); - } - if (substr($top, -1) === '%') { - $top = round(($srcHeight - $newHeight) / 100 * $top); - } - if ($left < 0) { - $newWidth += $left; $left = 0; - } - if ($top < 0) { - $newHeight += $top; $top = 0; - } - $newWidth = min((int) $newWidth, $srcWidth - $left); - $newHeight = min((int) $newHeight, $srcHeight - $top); - return array($left, $top, $newWidth, $newHeight); - } - - - /** - * Sharpen image. - * @return self - */ - public function sharpen() - { - imageconvolution($this->getImageResource(), array( // my magic numbers ;) - array( -1, -1, -1 ), - array( -1, 24, -1 ), - array( -1, -1, -1 ), - ), 16, 0); - return $this; - } - - - /** - * Puts another image into this image. - * @param Image - * @param mixed x-coordinate in pixels or percent - * @param mixed y-coordinate in pixels or percent - * @param int opacity 0..100 - * @return self - */ - public function place(Image $image, $left = 0, $top = 0, $opacity = 100) - { - $opacity = max(0, min(100, (int) $opacity)); - - if (substr($left, -1) === '%') { - $left = round(($this->getWidth() - $image->getWidth()) / 100 * $left); - } - - if (substr($top, -1) === '%') { - $top = round(($this->getHeight() - $image->getHeight()) / 100 * $top); - } - - if ($opacity === 100) { - imagecopy( - $this->getImageResource(), $image->getImageResource(), - $left, $top, 0, 0, $image->getWidth(), $image->getHeight() - ); - - } elseif ($opacity <> 0) { - imagecopymerge( - $this->getImageResource(), $image->getImageResource(), - $left, $top, 0, 0, $image->getWidth(), $image->getHeight(), - $opacity - ); - } - return $this; - } - - - /** - * Saves image to the file. - * @param string filename - * @param int quality 0..100 (for JPEG and PNG) - * @param int optional image type - * @return bool TRUE on success or FALSE on failure. - */ - public function save($file = NULL, $quality = NULL, $type = NULL) - { - if ($type === NULL) { - switch (strtolower(pathinfo($file, PATHINFO_EXTENSION))) { - case 'jpg': - case 'jpeg': - $type = self::JPEG; - break; - case 'png': - $type = self::PNG; - break; - case 'gif': - $type = self::GIF; - } - } - - switch ($type) { - case self::JPEG: - $quality = $quality === NULL ? 85 : max(0, min(100, (int) $quality)); - return imagejpeg($this->getImageResource(), $file, $quality); - - case self::PNG: - $quality = $quality === NULL ? 9 : max(0, min(9, (int) $quality)); - return imagepng($this->getImageResource(), $file, $quality); - - case self::GIF: - return imagegif($this->getImageResource(), $file); - - default: - throw new InvalidArgumentException('Unsupported image type.'); - } - } - - - /** - * Outputs image to string. - * @param int image type - * @param int quality 0..100 (for JPEG and PNG) - * @return string - */ - public function toString($type = self::JPEG, $quality = NULL) - { - ob_start(); - $this->save(NULL, $quality, $type); - return ob_get_clean(); - } - - - /** - * Outputs image to string. - * @return string - */ - public function __toString() - { - try { - return $this->toString(); - } catch (\Exception $e) { - if (func_num_args()) { - throw $e; - } - trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); - } - } - - - /** - * Outputs image to browser. - * @param int image type - * @param int quality 0..100 (for JPEG and PNG) - * @return bool TRUE on success or FALSE on failure. - */ - public function send($type = self::JPEG, $quality = NULL) - { - if ($type !== self::GIF && $type !== self::PNG && $type !== self::JPEG) { - throw new InvalidArgumentException('Unsupported image type.'); - } - header('Content-Type: ' . image_type_to_mime_type($type)); - return $this->save(NULL, $quality, $type); - } - - - /** - * Call to undefined method. - * - * @param string method name - * @param array arguments - * @return mixed - * @throws MemberAccessException - */ - public function __call($name, $args) - { - $function = 'image' . $name; - if (function_exists($function)) { - foreach ($args as $key => $value) { - if ($value instanceof self) { - $args[$key] = $value->getImageResource(); - - } elseif (is_array($value) && isset($value['red'])) { // rgb - $args[$key] = imagecolorallocatealpha( - $this->getImageResource(), - $value['red'], $value['green'], $value['blue'], $value['alpha'] - ); - } - } - array_unshift($args, $this->getImageResource()); - - $res = call_user_func_array($function, $args); - return is_resource($res) && get_resource_type($res) === 'gd' ? $this->setImageResource($res) : $res; - } - - return parent::__call($name, $args); - } - - - public function __clone() - { - ob_start(); - imagegd2($this->getImageResource()); - $this->setImageResource(imagecreatefromstring(ob_get_clean())); - } - -} - - -/** - * The exception that indicates invalid image file. - */ -class UnknownImageFileException extends \Exception -{ -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/ObjectMixin.php php-nette-2.1.5/Nette-2.1.4/Nette/common/ObjectMixin.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/ObjectMixin.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/ObjectMixin.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,395 +0,0 @@ - 0 | bool | array) used by getMethods() */ - private static $methods; - - /** @var array (name => 'event' | TRUE) used by hasProperty() */ - private static $props; - - /** @var array (name => array(type => callback)) used by get|setExtensionMethod() */ - private static $extMethods; - - - /** - * Static class - cannot be instantiated. - */ - final public function __construct() - { - throw new StaticClassException; - } - - - /** - * __call() implementation. - * @param object - * @param string - * @param array - * @return mixed - * @throws MemberAccessException - */ - public static function call($_this, $name, $args) - { - $class = get_class($_this); - $isProp = self::hasProperty($class, $name); - $methods = & self::getMethods($class); - - if ($name === '') { - throw new MemberAccessException("Call to class '$class' method without name."); - - } elseif ($isProp && $_this->$name instanceof \Closure) { // closure in property - return call_user_func_array($_this->$name, $args); - - } elseif ($isProp === 'event') { // calling event handlers - if (is_array($_this->$name) || $_this->$name instanceof \Traversable) { - foreach ($_this->$name as $handler) { - Nette\Utils\Callback::invokeArgs($handler, $args); - } - } elseif ($_this->$name !== NULL) { - throw new UnexpectedValueException("Property $class::$$name must be array or NULL, " . gettype($_this->$name) ." given."); - } - - } elseif (isset($methods[$name]) && is_array($methods[$name])) { // magic @methods - list($op, $rp, $type) = $methods[$name]; - if (count($args) !== ($op === 'get' ? 0 : 1)) { - throw new InvalidArgumentException("$class::$name() expects " . ($op === 'get' ? 'no' : '1') . ' argument, ' . count($args) . ' given.'); - - } elseif ($type && $args && !self::checkType($args[0], $type)) { - throw new InvalidArgumentException("Argument passed to $class::$name() must be $type, " . gettype($args[0]) . ' given.'); - } - - if ($op === 'get') { - return $rp->getValue($_this); - } elseif ($op === 'set') { - $rp->setValue($_this, $args[0]); - } elseif ($op === 'add') { - $val = $rp->getValue($_this); - $val[] = $args[0]; - $rp->setValue($_this, $val); - } - return $_this; - - } elseif ($cb = self::getExtensionMethod($class, $name)) { // extension methods - array_unshift($args, $_this); - return Nette\Utils\Callback::invokeArgs($cb, $args); - - } else { - if (method_exists($class, $name)) { // called parent::$name() - $class = 'parent'; - } - throw new MemberAccessException("Call to undefined method $class::$name()."); - } - } - - - /** - * __callStatic() implementation. - * @param string - * @param string - * @param array - * @return void - * @throws MemberAccessException - */ - public static function callStatic($class, $method, $args) - { - throw new MemberAccessException("Call to undefined static method $class::$method()."); - } - - - /** - * __get() implementation. - * @param object - * @param string property name - * @return mixed property value - * @throws MemberAccessException if the property is not defined. - */ - public static function & get($_this, $name) - { - $class = get_class($_this); - $uname = ucfirst($name); - $methods = & self::getMethods($class); - - if ($name === '') { - throw new MemberAccessException("Cannot read a class '$class' property without name."); - - } elseif (isset($methods[$m = 'get' . $uname]) || isset($methods[$m = 'is' . $uname])) { // property getter - if ($methods[$m] === 0) { - $rm = new \ReflectionMethod($class, $m); - $methods[$m] = $rm->returnsReference(); - } - if ($methods[$m] === TRUE) { - return $_this->$m(); - } else { - $val = $_this->$m(); - return $val; - } - - } elseif (isset($methods[$name])) { // public method as closure getter - if (PHP_VERSION_ID >= 50400) { - $rm = new \ReflectionMethod($class, $name); - $val = $rm->getClosure($_this); - } else { - $val = Nette\Utils\Callback::closure($_this, $name); - } - return $val; - - } else { // strict class - $type = isset($methods['set' . $uname]) ? 'a write-only' : 'an undeclared'; - throw new MemberAccessException("Cannot read $type property $class::\$$name."); - } - } - - - /** - * __set() implementation. - * @param object - * @param string property name - * @param mixed property value - * @return void - * @throws MemberAccessException if the property is not defined or is read-only - */ - public static function set($_this, $name, $value) - { - $class = get_class($_this); - $uname = ucfirst($name); - $methods = & self::getMethods($class); - - if ($name === '') { - throw new MemberAccessException("Cannot write to a class '$class' property without name."); - - } elseif (self::hasProperty($class, $name)) { // unsetted property - $_this->$name = $value; - - } elseif (isset($methods[$m = 'set' . $uname])) { // property setter - $_this->$m($value); - - } else { // strict class - $type = isset($methods['get' . $uname]) || isset($methods['is' . $uname]) - ? 'a read-only' : 'an undeclared'; - throw new MemberAccessException("Cannot write to $type property $class::\$$name."); - } - } - - - /** - * __unset() implementation. - * @param object - * @param string property name - * @return void - * @throws MemberAccessException - */ - public static function remove($_this, $name) - { - $class = get_class($_this); - if (!self::hasProperty($class, $name)) { // strict class - throw new MemberAccessException("Cannot unset the property $class::\$$name."); - } - } - - - /** - * __isset() implementation. - * @param object - * @param string property name - * @return bool - */ - public static function has($_this, $name) - { - $name = ucfirst($name); - $methods = & self::getMethods(get_class($_this)); - return $name !== '' && (isset($methods['get' . $name]) || isset($methods['is' . $name])); - } - - - /** - * Checks if the public non-static property exists. - * @return mixed - */ - private static function hasProperty($class, $name) - { - $prop = & self::$props[$class][$name]; - if ($prop === NULL) { - $prop = FALSE; - try { - $rp = new \ReflectionProperty($class, $name); - if ($rp->isPublic() && !$rp->isStatic()) { - $prop = preg_match('#^on[A-Z]#', $name) ? 'event' : TRUE; - } - } catch (\ReflectionException $e) {} - } - return $prop; - } - - - /** - * Returns array of public (static, non-static and magic) methods. - * @return array - */ - private static function & getMethods($class) - { - if (!isset(self::$methods[$class])) { - self::$methods[$class] = array_fill_keys(get_class_methods($class), 0) + self::getMagicMethods($class); - if ($parent = get_parent_class($class)) { - self::$methods[$class] += self::getMethods($parent); - } - } - return self::$methods[$class]; - } - - - /** - * Returns array of magic methods defined by annotation @method. - * @return array - */ - public static function getMagicMethods($class) - { - $rc = new \ReflectionClass($class); - preg_match_all('~^ - [ \t*]* @method [ \t]+ - (?: [^\s(]+ [ \t]+ )? - (set|get|is|add) ([A-Z]\w*) [ \t]* - (?: \( [ \t]* ([^)$\s]+) )? - ()~mx', $rc->getDocComment(), $matches, PREG_SET_ORDER); - - $methods = array(); - foreach ($matches as $m) { - list(, $op, $prop, $type) = $m; - $name = $op . $prop; - $prop = strtolower($prop[0]) . substr($prop, 1) . ($op === 'add' ? 's' : ''); - if ($rc->hasProperty($prop) && ($rp = $rc->getProperty($prop)) && !$rp->isStatic()) { - $rp->setAccessible(TRUE); - if ($op === 'get' || $op === 'is') { - $type = NULL; $op = 'get'; - } elseif (!$type && preg_match('#@var[ \t]+(\S+)' . ($op === 'add' ? '\[\]#' : '#'), $rp->getDocComment(), $m)) { - $type = $m[1]; - } - if ($rc->inNamespace() && preg_match('#^[A-Z]\w+(\[|\||\z)#', $type)) { - $type = $rc->getNamespaceName() . '\\' . $type; - } - $methods[$name] = array($op, $rp, $type); - } - } - return $methods; - } - - - /** - * Finds whether a variable is of expected type and do non-data-loss conversion. - * @return bool - */ - public static function checkType(& $val, $type) - { - if (strpos($type, '|') !== FALSE) { - $found = NULL; - foreach (explode('|', $type) as $type) { - $tmp = $val; - if (self::checkType($tmp, $type)) { - if ($val === $tmp) { - return TRUE; - } - $found[] = $tmp; - } - } - if ($found) { - $val = $found[0]; - return TRUE; - } - return FALSE; - - } elseif (substr($type, -2) === '[]') { - if (!is_array($val)) { - return FALSE; - } - $type = substr($type, 0, -2); - $res = array(); - foreach ($val as $k => $v) { - if (!self::checkType($v, $type)) { - return FALSE; - } - $res[$k] = $v; - } - $val = $res; - return TRUE; - } - - switch (strtolower($type)) { - case NULL: - case 'mixed': - return TRUE; - case 'bool': - case 'boolean': - return ($val === NULL || is_scalar($val)) && settype($val, 'bool'); - case 'string': - return ($val === NULL || is_scalar($val) || (is_object($val) && method_exists($val, '__toString'))) && settype($val, 'string'); - case 'int': - case 'integer': - return ($val === NULL || is_bool($val) || is_numeric($val)) && ((float) (int) $val === (float) $val) && settype($val, 'int'); - case 'float': - return ($val === NULL || is_bool($val) || is_numeric($val)) && settype($val, 'float'); - case 'scalar': - case 'array': - case 'object': - case 'callable': - case 'resource': - case 'null': - return call_user_func("is_$type", $val); - default: - return $val instanceof $type; - } - } - - - /** - * Adds a method to class. - * @param string - * @param string - * @param mixed callable - * @return void - */ - public static function setExtensionMethod($class, $name, $callback) - { - $name = strtolower($name); - self::$extMethods[$name][$class] = Nette\Utils\Callback::closure($callback); - self::$extMethods[$name][''] = NULL; - } - - - /** - * Returns extension method. - * @param string - * @param string - * @return mixed - */ - public static function getExtensionMethod($class, $name) - { - $list = & self::$extMethods[strtolower($name)]; - $cache = & $list[''][$class]; - if (isset($cache)) { - return $cache; - } - - foreach (array($class) + class_parents($class) + class_implements($class) as $cl) { - if (isset($list[$cl])) { - return $cache = $list[$cl]; - } - } - return $cache = FALSE; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/Object.php php-nette-2.1.5/Nette-2.1.4/Nette/common/Object.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/Object.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/Object.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,162 +0,0 @@ - - * $val = $obj->label; // equivalent to $val = $obj->getLabel(); - * $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette'); - * - * Property names are case-sensitive, and they are written in the camelCaps - * or PascalCaps. - * - * Event functionality is provided by declaration of property named 'on{Something}' - * Multiple handlers are allowed. - * - * public $onClick; // declaration in class - * $this->onClick[] = 'callback'; // attaching event handler - * if (!empty($this->onClick)) ... // are there any handlers? - * $this->onClick($sender, $arg); // raises the event with arguments - * - * - * Adding method to class (i.e. to all instances) works similar to JavaScript - * prototype property. The syntax for adding a new method is: - * - * MyClass::extensionMethod('newMethod', function(MyClass $obj, $arg, ...) { ... }); - * $obj = new MyClass; - * $obj->newMethod($x); - * - * - * @author David Grudl - * - * @property-read Nette\Reflection\ClassType $reflection - */ -abstract class Object -{ - - /** - * Access to reflection. - * @return Nette\Reflection\ClassType - */ - public static function getReflection() - { - return new Reflection\ClassType(get_called_class()); - } - - - /** - * Call to undefined method. - * @param string method name - * @param array arguments - * @return mixed - * @throws MemberAccessException - */ - public function __call($name, $args) - { - return ObjectMixin::call($this, $name, $args); - } - - - /** - * Call to undefined static method. - * @param string method name (in lower case!) - * @param array arguments - * @return mixed - * @throws MemberAccessException - */ - public static function __callStatic($name, $args) - { - return ObjectMixin::callStatic(get_called_class(), $name, $args); - } - - - /** - * Adding method to class. - * @param string method name - * @param callable - * @return mixed - */ - public static function extensionMethod($name, $callback = NULL) - { - if (strpos($name, '::') === FALSE) { - $class = get_called_class(); - } else { - list($class, $name) = explode('::', $name); - $rc = new \ReflectionClass($class); - $class = $rc->getName(); - } - if ($callback === NULL) { - return ObjectMixin::getExtensionMethod($class, $name); - } else { - ObjectMixin::setExtensionMethod($class, $name, $callback); - } - } - - - /** - * Returns property value. Do not call directly. - * @param string property name - * @return mixed property value - * @throws MemberAccessException if the property is not defined. - */ - public function &__get($name) - { - return ObjectMixin::get($this, $name); - } - - - /** - * Sets value of a property. Do not call directly. - * @param string property name - * @param mixed property value - * @return void - * @throws MemberAccessException if the property is not defined or is read-only - */ - public function __set($name, $value) - { - ObjectMixin::set($this, $name, $value); - } - - - /** - * Is property defined? - * @param string property name - * @return bool - */ - public function __isset($name) - { - return ObjectMixin::has($this, $name); - } - - - /** - * Access to undeclared property. - * @param string property name - * @return void - * @throws MemberAccessException - */ - public function __unset($name) - { - ObjectMixin::remove($this, $name); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/common/shortcuts.php php-nette-2.1.5/Nette-2.1.4/Nette/common/shortcuts.php --- php-nette-2.1.4/Nette-2.1.4/Nette/common/shortcuts.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/common/shortcuts.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ - [obj, depth, path, is_monitored?]] */ - private $monitors = array(); - - - public function __construct(IContainer $parent = NULL, $name = NULL) - { - if ($parent !== NULL) { - $parent->addComponent($this, $name); - - } elseif (is_string($name)) { - $this->name = $name; - } - } - - - /** - * Lookup hierarchy for component specified by class or interface name. - * @param string class/interface type - * @param bool throw exception if component doesn't exist? - * @return IComponent - */ - public function lookup($type, $need = TRUE) - { - if (!isset($this->monitors[$type])) { // not monitored or not processed yet - $obj = $this->parent; - $path = self::NAME_SEPARATOR . $this->name; - $depth = 1; - while ($obj !== NULL) { - $parent = $obj->getParent(); - if ($type ? $obj instanceof $type : $parent === NULL) { - break; - } - $path = self::NAME_SEPARATOR . $obj->getName() . $path; - $depth++; - $obj = $parent; // IComponent::getParent() - if ($obj === $this) { - $obj = NULL; // prevent cycling - } - } - - if ($obj) { - $this->monitors[$type] = array($obj, $depth, substr($path, 1), FALSE); - - } else { - $this->monitors[$type] = array(NULL, NULL, NULL, FALSE); // not found - } - } - - if ($need && $this->monitors[$type][0] === NULL) { - throw new Nette\InvalidStateException("Component '$this->name' is not attached to '$type'."); - } - - return $this->monitors[$type][0]; - } - - - /** - * Lookup for component specified by class or interface name. Returns backtrace path. - * A path is the concatenation of component names separated by self::NAME_SEPARATOR. - * @param string class/interface type - * @param bool throw exception if component doesn't exist? - * @return string - */ - public function lookupPath($type, $need = TRUE) - { - $this->lookup($type, $need); - return $this->monitors[$type][2]; - } - - - /** - * Starts monitoring. - * @param string class/interface type - * @return void - */ - public function monitor($type) - { - if (empty($this->monitors[$type][3])) { - if ($obj = $this->lookup($type, FALSE)) { - $this->attached($obj); - } - $this->monitors[$type][3] = TRUE; // mark as monitored - } - } - - - /** - * Stops monitoring. - * @param string class/interface type - * @return void - */ - public function unmonitor($type) - { - unset($this->monitors[$type]); - } - - - /** - * This method will be called when the component (or component's parent) - * becomes attached to a monitored object. Do not call this method yourself. - * @param IComponent - * @return void - */ - protected function attached($obj) - { - } - - - /** - * This method will be called before the component (or component's parent) - * becomes detached from a monitored object. Do not call this method yourself. - * @param IComponent - * @return void - */ - protected function detached($obj) - { - } - - - /********************* interface IComponent ****************d*g**/ - - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - - /** - * Returns the container if any. - * @return IContainer|NULL - */ - public function getParent() - { - return $this->parent; - } - - - /** - * Sets the parent of this component. This method is managed by containers and should - * not be called by applications - * @param IContainer New parent or null if this component is being removed from a parent - * @param string - * @return self - * @throws Nette\InvalidStateException - * @internal - */ - public function setParent(IContainer $parent = NULL, $name = NULL) - { - if ($parent === NULL && $this->parent === NULL && $name !== NULL) { - $this->name = $name; // just rename - return $this; - - } elseif ($parent === $this->parent && $name === NULL) { - return $this; // nothing to do - } - - // A component cannot be given a parent if it already has a parent. - if ($this->parent !== NULL && $parent !== NULL) { - throw new Nette\InvalidStateException("Component '$this->name' already has a parent."); - } - - // remove from parent? - if ($parent === NULL) { - $this->refreshMonitors(0); - $this->parent = NULL; - - } else { // add to parent - $this->validateParent($parent); - $this->parent = $parent; - if ($name !== NULL) { - $this->name = $name; - } - - $tmp = array(); - $this->refreshMonitors(0, $tmp); - } - return $this; - } - - - /** - * Is called by a component when it is about to be set new parent. Descendant can - * override this method to disallow a parent change by throwing an Nette\InvalidStateException - * @return void - * @throws Nette\InvalidStateException - */ - protected function validateParent(IContainer $parent) - { - } - - - /** - * Refreshes monitors. - * @param int - * @param array|NULL (array = attaching, NULL = detaching) - * @param array - * @return void - */ - private function refreshMonitors($depth, & $missing = NULL, & $listeners = array()) - { - if ($this instanceof IContainer) { - foreach ($this->getComponents() as $component) { - if ($component instanceof Component) { - $component->refreshMonitors($depth + 1, $missing, $listeners); - } - } - } - - if ($missing === NULL) { // detaching - foreach ($this->monitors as $type => $rec) { - if (isset($rec[1]) && $rec[1] > $depth) { - if ($rec[3]) { // monitored - $this->monitors[$type] = array(NULL, NULL, NULL, TRUE); - $listeners[] = array($this, $rec[0]); - } else { // not monitored, just randomly cached - unset($this->monitors[$type]); - } - } - } - - } else { // attaching - foreach ($this->monitors as $type => $rec) { - if (isset($rec[0])) { // is in cache yet - continue; - - } elseif (!$rec[3]) { // not monitored, just randomly cached - unset($this->monitors[$type]); - - } elseif (isset($missing[$type])) { // known from previous lookup - $this->monitors[$type] = array(NULL, NULL, NULL, TRUE); - - } else { - $this->monitors[$type] = NULL; // forces re-lookup - if ($obj = $this->lookup($type, FALSE)) { - $listeners[] = array($this, $obj); - } else { - $missing[$type] = TRUE; - } - $this->monitors[$type][3] = TRUE; // mark as monitored - } - } - } - - if ($depth === 0) { // call listeners - $method = $missing === NULL ? 'detached' : 'attached'; - foreach ($listeners as $item) { - $item[0]->$method($item[1]); - } - } - } - - - /********************* cloneable, serializable ****************d*g**/ - - - /** - * Object cloning. - */ - public function __clone() - { - if ($this->parent === NULL) { - return; - - } elseif ($this->parent instanceof Container) { - $this->parent = $this->parent->_isCloning(); - if ($this->parent === NULL) { // not cloning - $this->refreshMonitors(0); - } - - } else { - $this->parent = NULL; - $this->refreshMonitors(0); - } - } - - - /** - * Prevents serialization. - */ - public function __sleep() - { - throw new Nette\NotImplementedException('Object serialization is not supported by class ' . get_class($this)); - } - - - /** - * Prevents unserialization. - */ - public function __wakeup() - { - throw new Nette\NotImplementedException('Object unserialization is not supported by class ' . get_class($this)); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/ComponentModel/Container.php php-nette-2.1.5/Nette-2.1.4/Nette/ComponentModel/Container.php --- php-nette-2.1.4/Nette-2.1.4/Nette/ComponentModel/Container.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/ComponentModel/Container.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,246 +0,0 @@ -getName(); - } - - if (is_int($name)) { - $name = (string) $name; - - } elseif (!is_string($name)) { - throw new Nette\InvalidArgumentException(sprintf('Component name must be integer or string, %s given.', gettype($name))); - - } elseif (!preg_match('#^[a-zA-Z0-9_]+\z#', $name)) { - throw new Nette\InvalidArgumentException("Component name must be non-empty alphanumeric string, '$name' given."); - } - - if (isset($this->components[$name])) { - throw new Nette\InvalidStateException("Component with name '$name' already exists."); - } - - // check circular reference - $obj = $this; - do { - if ($obj === $component) { - throw new Nette\InvalidStateException("Circular reference detected while adding component '$name'."); - } - $obj = $obj->getParent(); - } while ($obj !== NULL); - - // user checking - $this->validateChildComponent($component); - - try { - if (isset($this->components[$insertBefore])) { - $tmp = array(); - foreach ($this->components as $k => $v) { - if ($k === $insertBefore) { - $tmp[$name] = $component; - } - $tmp[$k] = $v; - } - $this->components = $tmp; - } else { - $this->components[$name] = $component; - } - $component->setParent($this, $name); - - } catch (\Exception $e) { - unset($this->components[$name]); // undo - throw $e; - } - return $this; - } - - - /** - * Removes a component from the IContainer. - * @return void - */ - public function removeComponent(IComponent $component) - { - $name = $component->getName(); - if (!isset($this->components[$name]) || $this->components[$name] !== $component) { - throw new Nette\InvalidArgumentException("Component named '$name' is not located in this container."); - } - - unset($this->components[$name]); - $component->setParent(NULL); - } - - - /** - * Returns component specified by name or path. - * @param string - * @param bool throw exception if component doesn't exist? - * @return IComponent|NULL - */ - public function getComponent($name, $need = TRUE) - { - if (is_int($name)) { - $name = (string) $name; - - } elseif (!is_string($name)) { - throw new Nette\InvalidArgumentException(sprintf('Component name must be integer or string, %s given.', gettype($name))); - - } else { - $a = strpos($name, self::NAME_SEPARATOR); - if ($a !== FALSE) { - $ext = (string) substr($name, $a + 1); - $name = substr($name, 0, $a); - } - - if ($name === '') { - if ($need) { - throw new Nette\InvalidArgumentException('Component or subcomponent name must not be empty string.'); - } - return; - } - } - - if (!isset($this->components[$name])) { - $component = $this->createComponent($name); - if ($component instanceof IComponent && $component->getParent() === NULL) { - $this->addComponent($component, $name); - } - } - - if (isset($this->components[$name])) { - if (!isset($ext)) { - return $this->components[$name]; - - } elseif ($this->components[$name] instanceof IContainer) { - return $this->components[$name]->getComponent($ext, $need); - - } elseif ($need) { - throw new Nette\InvalidArgumentException("Component with name '$name' is not container and cannot have '$ext' component."); - } - - } elseif ($need) { - throw new Nette\InvalidArgumentException("Component with name '$name' does not exist."); - } - } - - - /** - * Component factory. Delegates the creation of components to a createComponent method. - * @param string component name - * @return IComponent the created component (optionally) - */ - protected function createComponent($name) - { - $ucname = ucfirst($name); - $method = 'createComponent' . $ucname; - if ($ucname !== $name && method_exists($this, $method) && $this->getReflection()->getMethod($method)->getName() === $method) { - $component = $this->$method($name); - if (!$component instanceof IComponent && !isset($this->components[$name])) { - $class = get_class($this); - throw new Nette\UnexpectedValueException("Method $class::$method() did not return or create the desired component."); - } - return $component; - } - } - - - /** - * Iterates over components. - * @param bool recursive? - * @param string class types filter - * @return \ArrayIterator - */ - public function getComponents($deep = FALSE, $filterType = NULL) - { - $iterator = new RecursiveComponentIterator($this->components); - if ($deep) { - $deep = $deep > 0 ? \RecursiveIteratorIterator::SELF_FIRST : \RecursiveIteratorIterator::CHILD_FIRST; - $iterator = new \RecursiveIteratorIterator($iterator, $deep); - } - if ($filterType) { - $iterator = new Nette\Iterators\Filter($iterator, function($item) use ($filterType) { - return $item instanceof $filterType; - }); - } - return $iterator; - } - - - /** - * Descendant can override this method to disallow insert a child by throwing an Nette\InvalidStateException. - * @return void - * @throws Nette\InvalidStateException - */ - protected function validateChildComponent(IComponent $child) - { - } - - - /********************* cloneable, serializable ****************d*g**/ - - - /** - * Object cloning. - */ - public function __clone() - { - if ($this->components) { - $oldMyself = reset($this->components)->getParent(); - $oldMyself->cloning = $this; - foreach ($this->components as $name => $component) { - $this->components[$name] = clone $component; - } - $oldMyself->cloning = NULL; - } - parent::__clone(); - } - - - /** - * Is container cloning now? - * @return NULL|IComponent - * @internal - */ - public function _isCloning() - { - return $this->cloning; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/ComponentModel/IComponent.php php-nette-2.1.5/Nette-2.1.4/Nette/ComponentModel/IComponent.php --- php-nette-2.1.4/Nette-2.1.4/Nette/ComponentModel/IComponent.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/ComponentModel/IComponent.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -current() instanceof IContainer; - } - - - /** - * The sub-iterator for the current element. - * @return \RecursiveIterator - */ - public function getChildren() - { - return $this->current()->getComponents(); - } - - - /** - * Returns the count of elements. - * @return int - */ - public function count() - { - return iterator_count($this); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Connection.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Connection.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Connection.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Connection.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,278 +0,0 @@ - 4) { // compatibility - $options['driverClass'] = func_get_arg(4); - } - $this->params = array($dsn, $user, $password); - $this->options = (array) $options; - - if (empty($options['lazy'])) { - $this->connect(); - } - } - - - public function connect() - { - if ($this->pdo) { - return; - } - $this->pdo = new PDO($this->params[0], $this->params[1], $this->params[2], $this->options); - $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - $class = empty($this->options['driverClass']) - ? 'Nette\Database\Drivers\\' . ucfirst(str_replace('sql', 'Sql', $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME))) . 'Driver' - : $this->options['driverClass']; - $this->driver = new $class($this, $this->options); - $this->preprocessor = new SqlPreprocessor($this); - $this->onConnect($this); - } - - - /** @return string */ - public function getDsn() - { - return $this->params[0]; - } - - - /** @return PDO */ - public function getPdo() - { - $this->connect(); - return $this->pdo; - } - - - /** @return ISupplementalDriver */ - public function getSupplementalDriver() - { - $this->connect(); - return $this->driver; - } - - - /** - * @param string sequence object - * @return string - */ - public function getInsertId($name = NULL) - { - return $this->getPdo()->lastInsertId($name); - } - - - /** - * @param string string to be quoted - * @param int data type hint - * @return string - */ - public function quote($string, $type = PDO::PARAM_STR) - { - return $this->getPdo()->quote($string, $type); - } - - - /** @deprecated */ - function beginTransaction() - { - $this->queryArgs('::beginTransaction', array()); - } - - - /** @deprecated */ - function commit() - { - $this->queryArgs('::commit', array()); - } - - - /** @deprecated */ - public function rollBack() - { - $this->queryArgs('::rollBack', array()); - } - - - /** @deprecated */ - public function query($statement) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args); - } - - - /** @deprecated */ - function queryArgs($statement, array $params) - { - $this->connect(); - if ($params) { - array_unshift($params, $statement); - list($statement, $params) = $this->preprocessor->process($params); - } - - try { - $result = new ResultSet($this, $statement, $params); - } catch (\PDOException $e) { - $e->queryString = $statement; - $this->onQuery($this, $e); - throw $e; - } - $this->onQuery($this, $result); - return $result; - } - - - /********************* shortcuts ****************d*g**/ - - - /** @deprecated */ - function fetch($args) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->fetch(); - } - - - /** @deprecated */ - function fetchField($args) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->fetchField(); - } - - - /** @deprecated */ - function fetchPairs($args) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->fetchPairs(); - } - - - /** @deprecated */ - function fetchAll($args) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->fetchAll(); - } - - - /** @deprecated */ - static function literal($value) - { - $args = func_get_args(); - return new SqlLiteral(array_shift($args), $args); - } - - - /********************* Selection ****************d*g**/ - - - /** @deprecated */ - function table($table) - { - trigger_error(__METHOD__ . '() is deprecated; use Nette\Database\Context::table() instead.', E_USER_DEPRECATED); - if (!$this->context) { - $this->context = new Context($this); - } - return $this->context->table($table); - } - - - /** @deprecated */ - function setContext(Context $context) - { - $this->context = $context; - return $this; - } - - - /** @deprecated */ - function getContext() - { - return $this->context; - } - - - /** @deprecated */ - function setDatabaseReflection() - { - trigger_error(__METHOD__ . '() is deprecated; use Nette\Database\Context instead.', E_USER_DEPRECATED); - return $this; - } - - - /** @deprecated */ - function setCacheStorage() - { - trigger_error(__METHOD__ . '() is deprecated; use Nette\Database\Context instead.', E_USER_DEPRECATED); - } - - - /** @deprecated */ - function lastInsertId($name = NULL) - { - trigger_error(__METHOD__ . '() is deprecated; use getInsertId() instead.', E_USER_DEPRECATED); - return $this->getInsertId($name); - } - - - /** @deprecated */ - function exec($statement) - { - trigger_error(__METHOD__ . '() is deprecated; use Nette\Database\Context::query()->getRowCount() instead.', E_USER_DEPRECATED); - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->getRowCount(); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Context.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Context.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Context.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Context.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,198 +0,0 @@ -connection = $connection; - $this->reflection = $reflection ?: new Reflection\ConventionalReflection; - $this->cacheStorage = $cacheStorage; - } - - - /** @return void */ - public function beginTransaction() - { - $this->queryArgs('::beginTransaction', array()); - } - - - /** @return void */ - public function commit() - { - $this->queryArgs('::commit', array()); - } - - - /** @return void */ - public function rollBack() - { - $this->queryArgs('::rollBack', array()); - } - - - /** - * @param string sequence object - * @return string - */ - public function getInsertId($name = NULL) - { - return $this->connection->getInsertId($name); - } - - - /** - * Generates and executes SQL query. - * @param string statement - * @param mixed [parameters, ...] - * @return ResultSet - */ - public function query($statement) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args); - } - - - /** - * @param string statement - * @param array - * @return ResultSet - */ - public function queryArgs($statement, array $params) - { - $this->connection->connect(); - if ($params) { - if (!$this->preprocessor) { - $this->preprocessor = new SqlPreprocessor($this->connection); - } - array_unshift($params, $statement); - list($statement, $params) = $this->preprocessor->process($params); - } - - try { - $result = new ResultSet($this->connection, $statement, $params); - } catch (\PDOException $e) { - $e->queryString = $statement; - $this->connection->onQuery($this->connection, $e); - throw $e; - } - $this->connection->onQuery($this->connection, $result); - return $result; - } - - - /** @return Nette\Database\Table\Selection */ - public function table($table) - { - return new Table\Selection($this->connection, $table, $this->reflection, $this->cacheStorage); - } - - - /** @return Connection */ - public function getConnection() - { - return $this->connection; - } - - - /** @return IReflection */ - public function getDatabaseReflection() - { - return $this->reflection; - } - - - /********************* shortcuts ****************d*g**/ - - - /** - * Shortcut for query()->fetch() - * @param string statement - * @param mixed [parameters, ...] - * @return Row - */ - public function fetch($args) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->fetch(); - } - - - /** - * Shortcut for query()->fetchField() - * @param string statement - * @param mixed [parameters, ...] - * @return mixed - */ - public function fetchField($args) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->fetchField(); - } - - - /** - * Shortcut for query()->fetchPairs() - * @param string statement - * @param mixed [parameters, ...] - * @return array - */ - public function fetchPairs($args) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->fetchPairs(); - } - - - /** - * Shortcut for query()->fetchAll() - * @param string statement - * @param mixed [parameters, ...] - * @return array - */ - public function fetchAll($args) - { - $args = func_get_args(); - return $this->queryArgs(array_shift($args), $args)->fetchAll(); - } - - - /** - * @return SqlLiteral - */ - public static function literal($value) - { - $args = func_get_args(); - return new SqlLiteral(array_shift($args), $args); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Diagnostics/ConnectionPanel.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Diagnostics/ConnectionPanel.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Diagnostics/ConnectionPanel.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Diagnostics/ConnectionPanel.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,175 +0,0 @@ -onQuery[] = array($this, 'logQuery'); - } - - - public function logQuery(Nette\Database\Connection $connection, $result) - { - if ($this->disabled) { - return; - } - $this->count++; - - $source = NULL; - $trace = $result instanceof \PDOException ? $result->getTrace() : debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : FALSE); - foreach ($trace as $row) { - if (isset($row['file']) && is_file($row['file']) && !Nette\Diagnostics\Debugger::getBluescreen()->isCollapsed($row['file'])) { - if ((isset($row['function']) && strpos($row['function'], 'call_user_func') === 0) - || (isset($row['class']) && is_subclass_of($row['class'], '\\Nette\\Database\\Connection')) - ) { - continue; - } - $source = array($row['file'], (int) $row['line']); - break; - } - } - if ($result instanceof Nette\Database\ResultSet) { - $this->totalTime += $result->getTime(); - if ($this->count < $this->maxQueries) { - $this->queries[] = array($connection, $result->getQueryString(), $result->getParameters(), $source, $result->getTime(), $result->getRowCount(), NULL); - } - - } elseif ($result instanceof \PDOException && $this->count < $this->maxQueries) { - $this->queries[] = array($connection, $result->queryString, NULL, $source, NULL, NULL, $result->getMessage()); - } - } - - - public static function renderException($e) - { - if (!$e instanceof \PDOException) { - return; - } - if (isset($e->queryString)) { - $sql = $e->queryString; - - } elseif ($item = Nette\Diagnostics\Helpers::findTrace($e->getTrace(), 'PDO::prepare')) { - $sql = $item['args'][0]; - } - return isset($sql) ? array( - 'tab' => 'SQL', - 'panel' => Helpers::dumpSql($sql), - ) : NULL; - } - - - public function getTab() - { - return '' - . '' - . $this->count . ' ' . ($this->count === 1 ? 'query' : 'queries') - . ($this->totalTime ? ' / ' . sprintf('%0.1f', $this->totalTime * 1000) . ' ms' : '') - . ''; - } - - - public function getPanel() - { - $this->disabled = TRUE; - $s = ''; - foreach ($this->queries as $query) { - list($connection, $sql, $params, $source, $time, $rows, $error) = $query; - - $explain = NULL; // EXPLAIN is called here to work SELECT FOUND_ROWS() - if (!$error && $this->explain && preg_match('#\s*\(?\s*SELECT\s#iA', $sql)) { - try { - $cmd = is_string($this->explain) ? $this->explain : 'EXPLAIN'; - $explain = $connection->queryArgs("$cmd $sql", $params)->fetchAll(); - } catch (\PDOException $e) {} - } - - $s .= ''; - if ($error) { - $s .= 'ERROR'; - } elseif ($time !== NULL) { - $s .= sprintf('%0.3f', $time * 1000); - } - if ($explain) { - static $counter; - $counter++; - $s .= "
explain"; - } - - $s .= '' . Helpers::dumpSql($sql, $params); - if ($explain) { - $s .= ""; - foreach ($explain[0] as $col => $foo) { - $s .= ''; - } - $s .= ""; - foreach ($explain as $row) { - $s .= ""; - foreach ($row as $col) { - $s .= ''; - } - $s .= ""; - } - $s .= "
' . htmlSpecialChars($col) . '
' . htmlSpecialChars($col) . '
"; - } - if ($source) { - $s .= Nette\Diagnostics\Helpers::editorLink($source[0], $source[1])->class('nette-DbConnectionPanel-source'); - } - - $s .= '' . $rows . ''; - } - - return $this->count ? - ' -

Queries: ' . $this->count - . ($this->totalTime ? ', time: ' . sprintf('%0.3f', $this->totalTime * 1000) . ' ms' : '') . ', ' . htmlSpecialChars($this->name) . '

-
- - ' . $s . ' -
Time msSQL QueryRows
' - . (count($this->queries) < $this->count ? '

...and more

' : '') - . '
' : ''; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/MsSqlDriver.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/MsSqlDriver.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/MsSqlDriver.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/MsSqlDriver.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ -connection = $connection; - } - - - /********************* SQL ****************d*g**/ - - - /** - * Delimites identifier for use in a SQL statement. - */ - public function delimite($name) - { - // @see http://msdn.microsoft.com/en-us/library/ms176027.aspx - return '[' . str_replace(array('[', ']'), array('[[', ']]'), $name) . ']'; - } - - - /** - * Formats boolean for use in a SQL statement. - */ - public function formatBool($value) - { - return $value ? '1' : '0'; - } - - - /** - * Formats date-time for use in a SQL statement. - */ - public function formatDateTime(/*\DateTimeInterface*/ $value) - { - return $value->format("'Y-m-d H:i:s'"); - } - - - /** - * Encodes string for use in a LIKE statement. - */ - public function formatLike($value, $pos) - { - $value = strtr($value, array("'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]')); - return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); - } - - - /** - * Injects LIMIT/OFFSET to the SQL query. - */ - public function applyLimit(& $sql, $limit, $offset) - { - if ($limit >= 0) { - $sql = preg_replace('#^\s*(SELECT|UPDATE|DELETE)#i', '$0 TOP ' . (int) $limit, $sql, 1, $count); - if (!$count) { - throw new Nette\InvalidArgumentException('SQL query must begin with SELECT, UPDATE or DELETE command.'); - } - } - - if ($offset) { - throw new Nette\NotSupportedException('Offset is not supported by this database.'); - } - } - - - /** - * Normalizes result row. - */ - public function normalizeRow($row) - { - return $row; - } - - - /********************* reflection ****************d*g**/ - - - /** - * Returns list of tables. - */ - public function getTables() - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns metadata for all columns in a table. - */ - public function getColumns($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns metadata for all indexes in a table. - */ - public function getIndexes($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns metadata for all foreign keys in a table. - */ - public function getForeignKeys($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns associative array of detected types (IReflection::FIELD_*) in result set. - */ - public function getColumnTypes(\PDOStatement $statement) - { - return Nette\Database\Helpers::detectTypes($statement); - } - - - /** - * @return bool - */ - public function isSupported($item) - { - return $item === self::SUPPORT_SUBSELECT; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/MySqlDriver.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/MySqlDriver.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/MySqlDriver.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/MySqlDriver.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,237 +0,0 @@ - character encoding to set (default is utf8) - * - sqlmode => see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html - */ - public function __construct(Nette\Database\Connection $connection, array $options) - { - $this->connection = $connection; - $charset = isset($options['charset']) ? $options['charset'] : 'utf8'; - if ($charset) { - $connection->query("SET NAMES '$charset'"); - } - if (isset($options['sqlmode'])) { - $connection->query("SET sql_mode='$options[sqlmode]'"); - } - } - - - /********************* SQL ****************d*g**/ - - - /** - * Delimites identifier for use in a SQL statement. - */ - public function delimite($name) - { - // @see http://dev.mysql.com/doc/refman/5.0/en/identifiers.html - return '`' . str_replace('`', '``', $name) . '`'; - } - - - /** - * Formats boolean for use in a SQL statement. - */ - public function formatBool($value) - { - return $value ? '1' : '0'; - } - - - /** - * Formats date-time for use in a SQL statement. - */ - public function formatDateTime(/*\DateTimeInterface*/ $value) - { - return $value->format("'Y-m-d H:i:s'"); - } - - - /** - * Encodes string for use in a LIKE statement. - */ - public function formatLike($value, $pos) - { - $value = addcslashes(str_replace('\\', '\\\\', $value), "\x00\n\r\\'%_"); - return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); - } - - - /** - * Injects LIMIT/OFFSET to the SQL query. - */ - public function applyLimit(& $sql, $limit, $offset) - { - if ($limit >= 0 || $offset > 0) { - // see http://dev.mysql.com/doc/refman/5.0/en/select.html - $sql .= ' LIMIT ' . ($limit < 0 ? '18446744073709551615' : (int) $limit) - . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); - } - } - - - /** - * Normalizes result row. - */ - public function normalizeRow($row) - { - return $row; - } - - - /********************* reflection ****************d*g**/ - - - /** - * Returns list of tables. - */ - public function getTables() - { - /*$this->connection->query(" - SELECT TABLE_NAME as name, TABLE_TYPE = 'VIEW' as view - FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_SCHEMA = DATABASE() - ");*/ - $tables = array(); - foreach ($this->connection->query('SHOW FULL TABLES') as $row) { - $tables[] = array( - 'name' => $row[0], - 'view' => isset($row[1]) && $row[1] === 'VIEW', - ); - } - return $tables; - } - - - /** - * Returns metadata for all columns in a table. - */ - public function getColumns($table) - { - /*$this->connection->query(" - SELECT * - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = {$this->connection->quote($table)} AND TABLE_SCHEMA = DATABASE() - ");*/ - $columns = array(); - foreach ($this->connection->query('SHOW FULL COLUMNS FROM ' . $this->delimite($table)) as $row) { - $type = explode('(', $row['Type']); - $columns[] = array( - 'name' => $row['Field'], - 'table' => $table, - 'nativetype' => strtoupper($type[0]), - 'size' => isset($type[1]) ? (int) $type[1] : NULL, - 'unsigned' => (bool) strstr($row['Type'], 'unsigned'), - 'nullable' => $row['Null'] === 'YES', - 'default' => $row['Default'], - 'autoincrement' => $row['Extra'] === 'auto_increment', - 'primary' => $row['Key'] === 'PRI', - 'vendor' => (array) $row, - ); - } - return $columns; - } - - - /** - * Returns metadata for all indexes in a table. - */ - public function getIndexes($table) - { - /*$this->connection->query(" - SELECT * - FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE - WHERE TABLE_NAME = {$this->connection->quote($table)} AND TABLE_SCHEMA = DATABASE() - AND REFERENCED_COLUMN_NAME IS NULL - ");*/ - $indexes = array(); - foreach ($this->connection->query('SHOW INDEX FROM ' . $this->delimite($table)) as $row) { - $indexes[$row['Key_name']]['name'] = $row['Key_name']; - $indexes[$row['Key_name']]['unique'] = !$row['Non_unique']; - $indexes[$row['Key_name']]['primary'] = $row['Key_name'] === 'PRIMARY'; - $indexes[$row['Key_name']]['columns'][$row['Seq_in_index'] - 1] = $row['Column_name']; - } - return array_values($indexes); - } - - - /** - * Returns metadata for all foreign keys in a table. - */ - public function getForeignKeys($table) - { - $keys = array(); - $query = 'SELECT CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE ' - . 'WHERE TABLE_SCHEMA = DATABASE() AND REFERENCED_TABLE_NAME IS NOT NULL AND TABLE_NAME = ' . $this->connection->quote($table); - - foreach ($this->connection->query($query) as $id => $row) { - $keys[$id]['name'] = $row['CONSTRAINT_NAME']; // foreign key name - $keys[$id]['local'] = $row['COLUMN_NAME']; // local columns - $keys[$id]['table'] = $row['REFERENCED_TABLE_NAME']; // referenced table - $keys[$id]['foreign'] = $row['REFERENCED_COLUMN_NAME']; // referenced columns - } - - return array_values($keys); - } - - - /** - * Returns associative array of detected types (IReflection::FIELD_*) in result set. - */ - public function getColumnTypes(\PDOStatement $statement) - { - $types = array(); - $count = $statement->columnCount(); - for ($col = 0; $col < $count; $col++) { - $meta = $statement->getColumnMeta($col); - if (isset($meta['native_type'])) { - $types[$meta['name']] = $type = Nette\Database\Helpers::detectType($meta['native_type']); - if ($type === Nette\Database\IReflection::FIELD_TIME) { - $types[$meta['name']] = Nette\Database\IReflection::FIELD_TIME_INTERVAL; - } - } - } - return $types; - } - - - /** - * @return bool - */ - public function isSupported($item) - { - // MULTI_COLUMN_AS_OR_COND due to mysql bugs: - // - http://bugs.mysql.com/bug.php?id=31188 - // - http://bugs.mysql.com/bug.php?id=35819 - // and more. - return $item === self::SUPPORT_SELECT_UNGROUPED_COLUMNS || $item === self::SUPPORT_MULTI_COLUMN_AS_OR_COND; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/OciDriver.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/OciDriver.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/OciDriver.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/OciDriver.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,165 +0,0 @@ -connection = $connection; - $this->fmtDateTime = isset($options['formatDateTime']) ? $options['formatDateTime'] : 'U'; - } - - - /********************* SQL ****************d*g**/ - - - /** - * Delimites identifier for use in a SQL statement. - */ - public function delimite($name) - { - // @see http://download.oracle.com/docs/cd/B10500_01/server.920/a96540/sql_elements9a.htm - return '"' . str_replace('"', '""', $name) . '"'; - } - - - /** - * Formats boolean for use in a SQL statement. - */ - public function formatBool($value) - { - return $value ? '1' : '0'; - } - - - /** - * Formats date-time for use in a SQL statement. - */ - public function formatDateTime(/*\DateTimeInterface*/ $value) - { - return $value->format($this->fmtDateTime); - } - - - /** - * Encodes string for use in a LIKE statement. - */ - public function formatLike($value, $pos) - { - throw new Nette\NotImplementedException; - } - - - /** - * Injects LIMIT/OFFSET to the SQL query. - */ - public function applyLimit(& $sql, $limit, $offset) - { - if ($offset > 0) { - // see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html - $sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t ' - . ($limit >= 0 ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '') - . ') WHERE "__rnum" > '. (int) $offset; - - } elseif ($limit >= 0) { - $sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . (int) $limit; - } - } - - - /** - * Normalizes result row. - */ - public function normalizeRow($row) - { - return $row; - } - - - /********************* reflection ****************d*g**/ - - - /** - * Returns list of tables. - */ - public function getTables() - { - $tables = array(); - foreach ($this->connection->query('SELECT * FROM cat') as $row) { - if ($row[1] === 'TABLE' || $row[1] === 'VIEW') { - $tables[] = array( - 'name' => $row[0], - 'view' => $row[1] === 'VIEW', - ); - } - } - return $tables; - } - - - /** - * Returns metadata for all columns in a table. - */ - public function getColumns($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns metadata for all indexes in a table. - */ - public function getIndexes($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns metadata for all foreign keys in a table. - */ - public function getForeignKeys($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns associative array of detected types (IReflection::FIELD_*) in result set. - */ - public function getColumnTypes(\PDOStatement $statement) - { - return Nette\Database\Helpers::detectTypes($statement); - } - - - /** - * @return bool - */ - public function isSupported($item) - { - return $item === self::SUPPORT_SEQUENCE || $item === self::SUPPORT_SUBSELECT; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/OdbcDriver.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/OdbcDriver.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/OdbcDriver.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/OdbcDriver.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -connection = $connection; - } - - - /********************* SQL ****************d*g**/ - - - /** - * Delimites identifier for use in a SQL statement. - */ - public function delimite($name) - { - return '[' . str_replace(array('[', ']'), array('[[', ']]'), $name) . ']'; - } - - - /** - * Formats boolean for use in a SQL statement. - */ - public function formatBool($value) - { - return $value ? '1' : '0'; - } - - - /** - * Formats date-time for use in a SQL statement. - */ - public function formatDateTime(/*\DateTimeInterface*/ $value) - { - return $value->format('#m/d/Y H:i:s#'); - } - - - /** - * Encodes string for use in a LIKE statement. - */ - public function formatLike($value, $pos) - { - $value = strtr($value, array("'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]')); - return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); - } - - - /** - * Injects LIMIT/OFFSET to the SQL query. - */ - public function applyLimit(& $sql, $limit, $offset) - { - if ($limit >= 0) { - $sql = preg_replace('#^\s*(SELECT|UPDATE|DELETE)#i', '$0 TOP ' . (int) $limit, $sql, 1, $count); - if (!$count) { - throw new Nette\InvalidArgumentException('SQL query must begin with SELECT, UPDATE or DELETE command.'); - } - } - - if ($offset) { - throw new Nette\NotSupportedException('Offset is not supported by this database.'); - } - } - - - /** - * Normalizes result row. - */ - public function normalizeRow($row) - { - return $row; - } - - - /********************* reflection ****************d*g**/ - - - /** - * Returns list of tables. - */ - public function getTables() - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns metadata for all columns in a table. - */ - public function getColumns($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns metadata for all indexes in a table. - */ - public function getIndexes($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns metadata for all foreign keys in a table. - */ - public function getForeignKeys($table) - { - throw new Nette\NotImplementedException; - } - - - /** - * Returns associative array of detected types (IReflection::FIELD_*) in result set. - */ - public function getColumnTypes(\PDOStatement $statement) - { - return Nette\Database\Helpers::detectTypes($statement); - } - - - /** - * @return bool - */ - public function isSupported($item) - { - return $item === self::SUPPORT_SUBSELECT; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/PgSqlDriver.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/PgSqlDriver.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/PgSqlDriver.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/PgSqlDriver.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,245 +0,0 @@ -connection = $connection; - } - - - /********************* SQL ****************d*g**/ - - - /** - * Delimites identifier for use in a SQL statement. - */ - public function delimite($name) - { - // @see http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS - return '"' . str_replace('"', '""', $name) . '"'; - } - - - /** - * Formats boolean for use in a SQL statement. - */ - public function formatBool($value) - { - return $value ? 'TRUE' : 'FALSE'; - } - - - /** - * Formats date-time for use in a SQL statement. - */ - public function formatDateTime(/*\DateTimeInterface*/ $value) - { - return $value->format("'Y-m-d H:i:s'"); - } - - - /** - * Encodes string for use in a LIKE statement. - */ - public function formatLike($value, $pos) - { - $value = strtr($value, array("'" => "''", '\\' => '\\\\', '%' => '\\\\%', '_' => '\\\\_')); - return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); - } - - - /** - * Injects LIMIT/OFFSET to the SQL query. - */ - public function applyLimit(& $sql, $limit, $offset) - { - if ($limit >= 0) { - $sql .= ' LIMIT ' . (int) $limit; - } - if ($offset > 0) { - $sql .= ' OFFSET ' . (int) $offset; - } - } - - - /** - * Normalizes result row. - */ - public function normalizeRow($row) - { - return $row; - } - - - /********************* reflection ****************d*g**/ - - - /** - * Returns list of tables. - */ - public function getTables() - { - $tables = array(); - foreach ($this->connection->query(" - SELECT - c.relname::varchar AS name, - c.relkind = 'v' AS view - FROM - pg_catalog.pg_class AS c - JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace - WHERE - c.relkind IN ('r', 'v') - AND ARRAY[n.nspname] <@ pg_catalog.current_schemas(FALSE) - ORDER BY - c.relname - ") as $row) { - $tables[] = (array) $row; - } - - return $tables; - } - - - /** - * Returns metadata for all columns in a table. - */ - public function getColumns($table) - { - $columns = array(); - foreach ($this->connection->query(" - SELECT - a.attname::varchar AS name, - c.relname::varchar AS table, - upper(t.typname) AS nativetype, - NULL AS size, - FALSE AS unsigned, - NOT (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS nullable, - pg_catalog.pg_get_expr(ad.adbin, 'pg_catalog.pg_attrdef'::regclass)::varchar AS default, - coalesce(co.contype = 'p' AND strpos(ad.adsrc, 'nextval') = 1, FALSE) AS autoincrement, - coalesce(co.contype = 'p', FALSE) AS primary, - substring(pg_catalog.pg_get_expr(ad.adbin, 'pg_catalog.pg_attrdef'::regclass) from 'nextval[(]''\"?([^''\"]+)') AS sequence - FROM - pg_catalog.pg_attribute AS a - JOIN pg_catalog.pg_class AS c ON a.attrelid = c.oid - JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace - JOIN pg_catalog.pg_type AS t ON a.atttypid = t.oid - LEFT JOIN pg_catalog.pg_attrdef AS ad ON ad.adrelid = c.oid AND ad.adnum = a.attnum - LEFT JOIN pg_catalog.pg_constraint AS co ON co.connamespace = n.oid AND contype = 'p' AND co.conrelid = c.oid AND a.attnum = ANY(co.conkey) - WHERE - c.relkind IN ('r', 'v') - AND c.relname::varchar = {$this->connection->quote($table)} - AND ARRAY[n.nspname] <@ pg_catalog.current_schemas(FALSE) - AND a.attnum > 0 - AND NOT a.attisdropped - ORDER BY - a.attnum - ") as $row) { - $column = (array) $row; - $column['vendor'] = $column; - unset($column['sequence']); - - $columns[] = $column; - } - - return $columns; - } - - - /** - * Returns metadata for all indexes in a table. - */ - public function getIndexes($table) - { - $indexes = array(); - foreach ($this->connection->query(" - SELECT - c2.relname::varchar AS name, - i.indisunique AS unique, - i.indisprimary AS primary, - a.attname::varchar AS column - FROM - pg_catalog.pg_class AS c1 - JOIN pg_catalog.pg_namespace AS n ON c1.relnamespace = n.oid - JOIN pg_catalog.pg_index AS i ON c1.oid = i.indrelid - JOIN pg_catalog.pg_class AS c2 ON i.indexrelid = c2.oid - LEFT JOIN pg_catalog.pg_attribute AS a ON c1.oid = a.attrelid AND a.attnum = ANY(i.indkey) - WHERE - ARRAY[n.nspname] <@ pg_catalog.current_schemas(FALSE) - AND c1.relkind = 'r' - AND c1.relname = {$this->connection->quote($table)} - ") as $row) { - $indexes[$row['name']]['name'] = $row['name']; - $indexes[$row['name']]['unique'] = $row['unique']; - $indexes[$row['name']]['primary'] = $row['primary']; - $indexes[$row['name']]['columns'][] = $row['column']; - } - - return array_values($indexes); - } - - - /** - * Returns metadata for all foreign keys in a table. - */ - public function getForeignKeys($table) - { - /* Does't work with multicolumn foreign keys */ - return $this->connection->query(" - SELECT - co.conname::varchar AS name, - al.attname::varchar AS local, - cf.relname::varchar AS table, - af.attname::varchar AS foreign - FROM - pg_catalog.pg_constraint AS co - JOIN pg_catalog.pg_namespace AS n ON co.connamespace = n.oid - JOIN pg_catalog.pg_class AS cl ON co.conrelid = cl.oid - JOIN pg_catalog.pg_class AS cf ON co.confrelid = cf.oid - JOIN pg_catalog.pg_attribute AS al ON al.attrelid = cl.oid AND al.attnum = co.conkey[1] - JOIN pg_catalog.pg_attribute AS af ON af.attrelid = cf.oid AND af.attnum = co.confkey[1] - WHERE - ARRAY[n.nspname] <@ pg_catalog.current_schemas(FALSE) - AND co.contype = 'f' - AND cl.relname = {$this->connection->quote($table)} - ")->fetchAll(); - } - - - /** - * Returns associative array of detected types (IReflection::FIELD_*) in result set. - */ - public function getColumnTypes(\PDOStatement $statement) - { - return Nette\Database\Helpers::detectTypes($statement); - } - - - /** - * @return bool - */ - public function isSupported($item) - { - return $item === self::SUPPORT_SEQUENCE || $item === self::SUPPORT_SUBSELECT; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/Sqlite2Driver.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/Sqlite2Driver.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/Sqlite2Driver.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/Sqlite2Driver.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -connection = $connection; - $this->fmtDateTime = isset($options['formatDateTime']) ? $options['formatDateTime'] : 'U'; - //$connection->query('PRAGMA foreign_keys = ON'); - } - - - /********************* SQL ****************d*g**/ - - - /** - * Delimites identifier for use in a SQL statement. - */ - public function delimite($name) - { - return '[' . strtr($name, '[]', ' ') . ']'; - } - - - /** - * Formats boolean for use in a SQL statement. - */ - public function formatBool($value) - { - return $value ? '1' : '0'; - } - - - /** - * Formats date-time for use in a SQL statement. - */ - public function formatDateTime(/*\DateTimeInterface*/ $value) - { - return $value->format($this->fmtDateTime); - } - - - /** - * Encodes string for use in a LIKE statement. - */ - public function formatLike($value, $pos) - { - $value = addcslashes(substr($this->connection->quote($value), 1, -1), '%_\\'); - return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'"; - } - - - /** - * Injects LIMIT/OFFSET to the SQL query. - */ - public function applyLimit(& $sql, $limit, $offset) - { - if ($limit >= 0 || $offset > 0) { - $sql .= ' LIMIT ' . (int) $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : ''); - } - } - - - /** - * Normalizes result row. - */ - public function normalizeRow($row) - { - foreach ($row as $key => $value) { - unset($row[$key]); - if ($key[0] === '[' || $key[0] === '"') { - $key = substr($key, 1, -1); - } - $row[$key] = $value; - } - return $row; - } - - - /********************* reflection ****************d*g**/ - - - /** - * Returns list of tables. - */ - public function getTables() - { - $tables = array(); - foreach ($this->connection->query(" - SELECT name, type = 'view' as view FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%' - UNION ALL - SELECT name, type = 'view' as view FROM sqlite_temp_master WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%' - ORDER BY name - ") as $row) { - $tables[] = array( - 'name' => $row->name, - 'view' => (bool) $row->view, - ); - } - - return $tables; - } - - - /** - * Returns metadata for all columns in a table. - */ - public function getColumns($table) - { - $meta = $this->connection->query(" - SELECT sql FROM sqlite_master WHERE type = 'table' AND name = {$this->connection->quote($table)} - UNION ALL - SELECT sql FROM sqlite_temp_master WHERE type = 'table' AND name = {$this->connection->quote($table)} - ")->fetch(); - - $columns = array(); - foreach ($this->connection->query("PRAGMA table_info({$this->delimite($table)})") as $row) { - $column = $row['name']; - $pattern = "/(\"$column\"|\[$column\]|$column)\\s+[^,]+\\s+PRIMARY\\s+KEY\\s+AUTOINCREMENT/Ui"; - $type = explode('(', $row['type']); - $columns[] = array( - 'name' => $column, - 'table' => $table, - 'nativetype' => strtoupper($type[0]), - 'size' => isset($type[1]) ? (int) $type[1] : NULL, - 'unsigned' => FALSE, - 'nullable' => $row['notnull'] == '0', - 'default' => $row['dflt_value'], - 'autoincrement' => (bool) preg_match($pattern, $meta['sql']), - 'primary' => $row['pk'] > 0, - 'vendor' => (array) $row, - ); - } - return $columns; - } - - - /** - * Returns metadata for all indexes in a table. - */ - public function getIndexes($table) - { - $indexes = array(); - foreach ($this->connection->query("PRAGMA index_list({$this->delimite($table)})") as $row) { - $indexes[$row['name']]['name'] = $row['name']; - $indexes[$row['name']]['unique'] = (bool) $row['unique']; - $indexes[$row['name']]['primary'] = FALSE; - } - - foreach ($indexes as $index => $values) { - $res = $this->connection->query("PRAGMA index_info({$this->delimite($index)})"); - while ($row = $res->fetch(TRUE)) { - $indexes[$index]['columns'][$row['seqno']] = $row['name']; - } - } - - $columns = $this->getColumns($table); - foreach ($indexes as $index => $values) { - $column = $indexes[$index]['columns'][0]; - foreach ($columns as $info) { - if ($column == $info['name']) { - $indexes[$index]['primary'] = (bool) $info['primary']; - break; - } - } - } - if (!$indexes) { // @see http://www.sqlite.org/lang_createtable.html#rowid - foreach ($columns as $column) { - if ($column['vendor']['pk']) { - $indexes[] = array( - 'name' => 'ROWID', - 'unique' => TRUE, - 'primary' => TRUE, - 'columns' => array($column['name']), - ); - break; - } - } - } - - return array_values($indexes); - } - - - /** - * Returns metadata for all foreign keys in a table. - */ - public function getForeignKeys($table) - { - $keys = array(); - foreach ($this->connection->query("PRAGMA foreign_key_list({$this->delimite($table)})") as $row) { - $keys[$row['id']]['name'] = $row['id']; // foreign key name - $keys[$row['id']]['local'] = $row['from']; // local columns - $keys[$row['id']]['table'] = $row['table']; // referenced table - $keys[$row['id']]['foreign'] = $row['to']; // referenced columns - $keys[$row['id']]['onDelete'] = $row['on_delete']; - $keys[$row['id']]['onUpdate'] = $row['on_update']; - - if ($keys[$row['id']]['foreign'][0] == NULL) { - $keys[$row['id']]['foreign'] = NULL; - } - } - return array_values($keys); - } - - - /** - * Returns associative array of detected types (IReflection::FIELD_*) in result set. - */ - public function getColumnTypes(\PDOStatement $statement) - { - $types = array(); - $count = $statement->columnCount(); - for ($col = 0; $col < $count; $col++) { - $meta = $statement->getColumnMeta($col); - if (isset($meta['sqlite:decl_type'])) { - if ($meta['sqlite:decl_type'] === 'DATE') { - $types[$meta['name']] = Nette\Database\IReflection::FIELD_UNIX_TIMESTAMP; - } else { - $types[$meta['name']] = Nette\Database\Helpers::detectType($meta['sqlite:decl_type']); - } - } elseif (isset($meta['native_type'])) { - $types[$meta['name']] = Nette\Database\Helpers::detectType($meta['native_type']); - } - } - return $types; - } - - - /** - * @return bool - */ - public function isSupported($item) - { - return $item === self::SUPPORT_MULTI_INSERT_AS_SELECT || $item === self::SUPPORT_SUBSELECT || $item === self::SUPPORT_MULTI_COLUMN_AS_OR_COND; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/SqlsrvDriver.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/SqlsrvDriver.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Drivers/SqlsrvDriver.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Drivers/SqlsrvDriver.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,269 +0,0 @@ -connection = $connection; - } - - - /********************* SQL ****************d*g**/ - - - /** - * Delimites identifier for use in a SQL statement. - */ - public function delimite($name) - { - /** @see http://msdn.microsoft.com/en-us/library/ms176027.aspx */ - return '[' . str_replace(']', ']]', $name) . ']'; - } - - - /** - * Formats boolean for use in a SQL statement. - */ - public function formatBool($value) - { - return $value ? '1' : '0'; - } - - - /** - * Formats date-time for use in a SQL statement. - */ - public function formatDateTime(/*\DateTimeInterface*/ $value) - { - /** @see http://msdn.microsoft.com/en-us/library/ms187819.aspx */ - return $value->format("'Y-m-d H:i:s'"); - } - - - /** - * Encodes string for use in a LIKE statement. - */ - public function formatLike($value, $pos) - { - /** @see http://msdn.microsoft.com/en-us/library/ms179859.aspx */ - $value = strtr($value, array("'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]')); - return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'"); - } - - - /** - * Injects LIMIT/OFFSET to the SQL query. - */ - public function applyLimit(& $sql, $limit, $offset) - { - if ($limit >= 0) { - $sql = preg_replace('#^\s*(SELECT|UPDATE|DELETE)#i', '$0 TOP ' . (int) $limit, $sql, 1, $count); - if (!$count) { - throw new Nette\InvalidArgumentException('SQL query must begin with SELECT, UPDATE or DELETE command.'); - } - } - - if ($offset > 0) { - throw new Nette\NotSupportedException('Offset is not supported by this database.'); - } - } - - - /** - * Normalizes result row. - */ - public function normalizeRow($row) - { - return $row; - } - - - /********************* reflection ****************d*g**/ - - - /** - * Returns list of tables. - */ - public function getTables() - { - $tables = array(); - foreach ($this->connection->query(" - SELECT - name, - CASE type - WHEN 'U' THEN 0 - WHEN 'V' THEN 1 - END AS [view] - FROM - sys.objects - WHERE - type IN ('U', 'V') - ") as $row) { - $tables[] = array( - 'name' => $row->name, - 'view' => (bool) $row->view, - ); - } - - return $tables; - } - - - /** - * Returns metadata for all columns in a table. - */ - public function getColumns($table) - { - $columns = array(); - foreach ($this->connection->query(" - SELECT - c.name AS name, - o.name AS [table], - UPPER(t.name) AS nativetype, - NULL AS size, - 0 AS unsigned, - c.is_nullable AS nullable, - OBJECT_DEFINITION(c.default_object_id) AS [default], - c.is_identity AS autoincrement, - CASE WHEN i.index_id IS NULL - THEN 0 - ELSE 1 - END AS [primary] - FROM - sys.columns c - JOIN sys.objects o ON c.object_id = o.object_id - LEFT JOIN sys.types t ON c.user_type_id = t.user_type_id - LEFT JOIN sys.key_constraints k ON o.object_id = k.parent_object_id AND k.type = 'PK' - LEFT JOIN sys.index_columns i ON k.parent_object_id = i.object_id AND i.index_id = k.unique_index_id AND i.column_id = c.column_id - WHERE - o.type IN ('U', 'V') - AND o.name = {$this->connection->quote($table)} - ") as $row) { - $row = (array) $row; - $row['vendor'] = $row; - $row['unsigned'] = (bool) $row['unsigned']; - $row['nullable'] = (bool) $row['nullable']; - $row['autoincrement'] = (bool) $row['autoincrement']; - $row['primary'] = (bool) $row['primary']; - - $columns[] = $row; - } - - return $columns; - } - - - /** - * Returns metadata for all indexes in a table. - */ - public function getIndexes($table) - { - $indexes = array(); - foreach ($this->connection->query(" - SELECT - i.name AS name, - CASE WHEN i.is_unique = 1 OR i.is_unique_constraint = 1 - THEN 1 - ELSE 0 - END AS [unique], - i.is_primary_key AS [primary], - c.name AS [column] - FROM - sys.indexes i - JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id - JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id - JOIN sys.tables t ON i.object_id = t.object_id - WHERE - t.name = {$this->connection->quote($table)} - ORDER BY - i.index_id, - ic.index_column_id - ") as $row) { - $indexes[$row->name]['name'] = $row->name; - $indexes[$row->name]['unique'] = (bool) $row->unique; - $indexes[$row->name]['primary'] = (bool) $row->primary; - $indexes[$row->name]['columns'][] = $row->column; - } - - return array_values($indexes); - } - - - /** - * Returns metadata for all foreign keys in a table. - */ - public function getForeignKeys($table) - { - // Does't work with multicolumn foreign keys - $keys = array(); - foreach ($this->connection->query(" - SELECT - fk.name AS name, - cl.name AS local, - tf.name AS [table], - cf.name AS [column] - FROM - sys.foreign_keys fk - JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id - JOIN sys.tables tl ON fkc.parent_object_id = tl.object_id - JOIN sys.columns cl ON fkc.parent_object_id = cl.object_id AND fkc.parent_column_id = cl.column_id - JOIN sys.tables tf ON fkc.referenced_object_id = tf.object_id - JOIN sys.columns cf ON fkc.referenced_object_id = cf.object_id AND fkc.referenced_column_id = cf.column_id - WHERE - tl.name = {$this->connection->quote($table)} - ") as $row) { - $keys[$row->name] = (array) $row; - } - - return array_values($keys); - } - - - /** - * Returns associative array of detected types (IReflection::FIELD_*) in result set. - */ - public function getColumnTypes(\PDOStatement $statement) - { - $types = array(); - $count = $statement->columnCount(); - for ($col = 0; $col < $count; $col++) { - $meta = $statement->getColumnMeta($col); - if (isset($meta['sqlsrv:decl_type']) && $meta['sqlsrv:decl_type'] !== 'timestamp') { // timestamp does not mean time in sqlsrv - $types[$meta['name']] = Nette\Database\Helpers::detectType($meta['sqlsrv:decl_type']); - } elseif (isset($meta['native_type'])) { - $types[$meta['name']] = Nette\Database\Helpers::detectType($meta['native_type']); - } - } - return $types; - } - - - /** - * @return bool - */ - public function isSupported($item) - { - return $item === self::SUPPORT_SUBSELECT; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Helpers.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Helpers.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Helpers.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Helpers.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,258 +0,0 @@ - IReflection::FIELD_TEXT, // PostgreSQL arrays - 'BYTEA|BLOB|BIN' => IReflection::FIELD_BINARY, - 'TEXT|CHAR|POINT|INTERVAL' => IReflection::FIELD_TEXT, - 'YEAR|BYTE|COUNTER|SERIAL|INT|LONG|SHORT|^TINY$' => IReflection::FIELD_INTEGER, - 'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC|NUMBER' => IReflection::FIELD_FLOAT, - '^TIME$' => IReflection::FIELD_TIME, - 'TIME' => IReflection::FIELD_DATETIME, // DATETIME, TIMESTAMP - 'DATE' => IReflection::FIELD_DATE, - 'BOOL' => IReflection::FIELD_BOOL, - ); - - - /** - * Displays complete result set as HTML table for debug purposes. - * @return void - */ - public static function dumpResult(ResultSet $result) - { - echo "\n\n\n"; - if (!$result->getColumnCount()) { - echo "\t\n\t\t\n\t\t\n\t\n
" . htmlSpecialChars($result->getQueryString()) . "
Affected rows:", $result->getRowCount(), "
\n"; - return; - } - $i = 0; - foreach ($result as $row) { - if ($i === 0) { - echo "\n\t\n\t\t#row\n"; - foreach ($row as $col => $foo) { - echo "\t\t" . htmlSpecialChars($col) . "\n"; - } - echo "\t\n\n\n"; - } - echo "\t\n\t\t", $i, "\n"; - foreach ($row as $col) { - //if (is_object($col)) $col = $col->__toString(); - echo "\t\t", htmlSpecialChars($col), "\n"; - } - echo "\t\n"; - $i++; - } - - if ($i === 0) { - echo "\t\n\t\tempty result set\n\t\n\n"; - } else { - echo "\n\n"; - } - } - - - /** - * Returns syntax highlighted SQL command. - * @param string - * @return string - */ - public static function dumpSql($sql, array $params = NULL) - { - static $keywords1 = 'SELECT|(?:ON\s+DUPLICATE\s+KEY)?UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|CALL|UNION|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE'; - static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|IGNORE|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|[RI]?LIKE|REGEXP|TRUE|FALSE'; - - // insert new lines - $sql = " $sql "; - $sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql); - - // reduce spaces - $sql = preg_replace('#[ \t]{2,}#', ' ', $sql); - - $sql = wordwrap($sql, 100); - $sql = preg_replace('#([ \t]*\r?\n){2,}#', "\n", $sql); - - // syntax highlight - $sql = htmlSpecialChars($sql); - $sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", function($matches) { - if (!empty($matches[1])) { // comment - return '' . $matches[1] . ''; - - } elseif (!empty($matches[2])) { // error - return '' . $matches[2] . ''; - - } elseif (!empty($matches[3])) { // most important keywords - return '' . $matches[3] . ''; - - } elseif (!empty($matches[4])) { // other keywords - return '' . $matches[4] . ''; - } - }, $sql); - - // parameters - $sql = preg_replace_callback('#\?#', function() use ($params) { - static $i = 0; - if (!isset($params[$i])) { - return '?'; - } - $param = $params[$i++]; - if (is_string($param) && (preg_match('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u', $param) || preg_last_error())) { - return '<binary>'; - - } elseif (is_string($param)) { - return '\'' . htmlspecialchars(Nette\Utils\Strings::truncate($param, Helpers::$maxLength)) . "'"; - - } elseif (is_resource($param)) { - $type = get_resource_type($param); - if ($type === 'stream') { - $info = stream_get_meta_data($param); - } - return '<' . htmlSpecialChars($type) . ' resource> '; - - } else { - return htmlspecialchars($param); - } - }, $sql); - - return '
' . trim($sql) . "
\n"; - } - - - /** - * Common column type detection. - * @return array - */ - public static function detectTypes(\PDOStatement $statement) - { - $types = array(); - $count = $statement->columnCount(); // driver must be meta-aware, see PHP bugs #53782, #54695 - for ($col = 0; $col < $count; $col++) { - $meta = $statement->getColumnMeta($col); - if (isset($meta['native_type'])) { - $types[$meta['name']] = self::detectType($meta['native_type']); - } - } - return $types; - } - - - /** - * Heuristic column type detection. - * @param string - * @return string - * @internal - */ - public static function detectType($type) - { - static $cache; - if (!isset($cache[$type])) { - $cache[$type] = 'string'; - foreach (self::$typePatterns as $s => $val) { - if (preg_match("#$s#i", $type)) { - return $cache[$type] = $val; - } - } - } - return $cache[$type]; - } - - - /** - * Import SQL dump from file - extremely fast. - * @return int count of commands - */ - public static function loadFromFile(Connection $connection, $file) - { - @set_time_limit(0); // intentionally @ - - $handle = @fopen($file, 'r'); // intentionally @ - if (!$handle) { - throw new Nette\FileNotFoundException("Cannot open file '$file'."); - } - - $count = 0; - $sql = ''; - while (!feof($handle)) { - $s = fgets($handle); - $sql .= $s; - if (substr(rtrim($s), -1) === ';') { - $connection->query($sql); // native query without logging - $sql = ''; - $count++; - } - } - if (trim($sql) !== '') { - $connection->query($sql); - $count++; - } - fclose($handle); - return $count; - } - - - public static function createDebugPanel($connection, $explain = TRUE, $name = NULL) - { - $panel = new Nette\Database\Diagnostics\ConnectionPanel($connection); - $panel->explain = $explain; - $panel->name = $name; - Nette\Diagnostics\Debugger::getBar()->addPanel($panel); - return $panel; - } - - - /** - * Reformat source to key -> value pairs. - * @return array - */ - public static function toPairs(array $rows, $key = NULL, $value = NULL) - { - if (!$rows) { - return array(); - } - - $keys = array_keys((array) reset($rows)); - if (!count($keys)) { - throw new \LogicException('Result set does not contain any column.'); - - } elseif ($key === NULL && $value === NULL) { - if (count($keys) === 1) { - list($value) = $keys; - } else { - list($key, $value) = $keys; - } - } - - $return = array(); - if ($key === NULL) { - foreach ($rows as $row) { - $return[] = ($value === NULL ? $row : $row[$value]); - } - } else { - foreach ($rows as $row) { - $return[is_object($row[$key]) ? (string) $row[$key] : $row[$key]] = ($value === NULL ? $row : $row[$value]); - } - } - - return $return; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/IReflection.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/IReflection.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/IReflection.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/IReflection.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -, %2$s for table name - * @param string %1$s stands for key used after ->, %2$s for table name - */ - public function __construct($primary = 'id', $foreign = '%s_id', $table = '%s') - { - $this->primary = $primary; - $this->foreign = $foreign; - $this->table = $table; - } - - - public function getPrimary($table) - { - return sprintf($this->primary, $this->getColumnFromTable($table)); - } - - - public function getHasManyReference($table, $key) - { - $table = $this->getColumnFromTable($table); - return array( - sprintf($this->table, $key, $table), - sprintf($this->foreign, $table, $key), - ); - } - - - public function getBelongsToReference($table, $key) - { - $table = $this->getColumnFromTable($table); - return array( - sprintf($this->table, $key, $table), - sprintf($this->foreign, $key, $table), - ); - } - - - protected function getColumnFromTable($name) - { - if ($this->table !== '%s' && preg_match('(^' . str_replace('%s', '(.*)', preg_quote($this->table)) . '\z)', $name, $match)) { - return $match[1]; - } - - return $name; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Reflection/DiscoveredReflection.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Reflection/DiscoveredReflection.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Reflection/DiscoveredReflection.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Reflection/DiscoveredReflection.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,175 +0,0 @@ -connection = $connection; - if ($cacheStorage) { - $this->cache = new Nette\Caching\Cache($cacheStorage, 'Nette.Database.' . md5($connection->getDsn())); - $this->structure = $this->loadedStructure = $this->cache->load('structure') ?: array(); - } - } - - - public function __destruct() - { - if ($this->cache && $this->structure !== $this->loadedStructure) { - $this->cache->save('structure', $this->structure); - } - } - - - public function getPrimary($table) - { - $primary = & $this->structure['primary'][strtolower($table)]; - if (isset($primary)) { - return empty($primary) ? NULL : $primary; - } - - $columns = $this->connection->getSupplementalDriver()->getColumns($table); - $primary = array(); - foreach ($columns as $column) { - if ($column['primary']) { - $primary[] = $column['name']; - } - } - - if (count($primary) === 0) { - return NULL; - } elseif (count($primary) === 1) { - $primary = reset($primary); - } - - return $primary; - } - - - public function getHasManyReference($table, $key, $refresh = TRUE) - { - if (isset($this->structure['hasMany'][strtolower($table)])) { - $candidates = $columnCandidates = array(); - foreach ($this->structure['hasMany'][strtolower($table)] as $targetPair) { - list($targetColumn, $targetTable) = $targetPair; - if (stripos($targetTable, $key) === FALSE) { - continue; - } - - $candidates[] = array($targetTable, $targetColumn); - if (stripos($targetColumn, $table) !== FALSE) { - $columnCandidates[] = $candidate = array($targetTable, $targetColumn); - if (strtolower($targetTable) === strtolower($key)) { - return $candidate; - } - } - } - - if (count($columnCandidates) === 1) { - return reset($columnCandidates); - } elseif (count($candidates) === 1) { - return reset($candidates); - } - - foreach ($candidates as $candidate) { - if (strtolower($candidate[0]) === strtolower($key)) { - return $candidate; - } - } - } - - if ($refresh) { - $this->reloadAllForeignKeys(); - return $this->getHasManyReference($table, $key, FALSE); - } - - if (empty($candidates)) { - throw new MissingReferenceException("No reference found for \${$table}->related({$key})."); - } else { - throw new AmbiguousReferenceKeyException('Ambiguous joining column in related call.'); - } - } - - - public function getBelongsToReference($table, $key, $refresh = TRUE) - { - if (isset($this->structure['belongsTo'][strtolower($table)])) { - foreach ($this->structure['belongsTo'][strtolower($table)] as $column => $targetTable) { - if (stripos($column, $key) !== FALSE) { - return array($targetTable, $column); - } - } - } - - if ($refresh) { - $this->reloadForeignKeys($table); - return $this->getBelongsToReference($table, $key, FALSE); - } - - throw new MissingReferenceException("No reference found for \${$table}->{$key}."); - } - - - protected function reloadAllForeignKeys() - { - $this->structure['hasMany'] = $this->structure['belongsTo'] = array(); - - foreach ($this->connection->getSupplementalDriver()->getTables() as $table) { - if ($table['view'] == FALSE) { - $this->reloadForeignKeys($table['name']); - } - } - - foreach ($this->structure['hasMany'] as & $table) { - uksort($table, function($a, $b) { - return strlen($a) - strlen($b); - }); - } - } - - - protected function reloadForeignKeys($table) - { - foreach ($this->connection->getSupplementalDriver()->getForeignKeys($table) as $row) { - $this->structure['belongsTo'][strtolower($table)][$row['local']] = $row['table']; - $this->structure['hasMany'][strtolower($row['table'])][$row['local'] . $table] = array($row['local'], $table); - } - - if (isset($this->structure['belongsTo'][$table])) { - uksort($this->structure['belongsTo'][$table], function($a, $b) { - return strlen($a) - strlen($b); - }); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Reflection/exceptions.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Reflection/exceptions.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Reflection/exceptions.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Reflection/exceptions.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -connection = $connection; - $this->supplementalDriver = $connection->getSupplementalDriver(); - $this->queryString = $queryString; - $this->params = $params; - - if (substr($queryString, 0, 2) === '::') { - $connection->getPdo()->{substr($queryString, 2)}(); - } elseif ($queryString !== NULL) { - $this->pdoStatement = $connection->getPdo()->prepare($queryString); - $this->pdoStatement->setFetchMode(PDO::FETCH_ASSOC); - $this->pdoStatement->execute($params); - } - $this->time = microtime(TRUE) - $time; - } - - - /** - * @return Connection - */ - public function getConnection() - { - return $this->connection; - } - - - /** - * @internal - * @return \PDOStatement - */ - public function getPdoStatement() - { - return $this->pdoStatement; - } - - - /** - * @return string - */ - public function getQueryString() - { - return $this->queryString; - } - - - /** - * @return array - */ - public function getParameters() - { - return $this->params; - } - - - /** - * @return int - */ - public function getColumnCount() - { - return $this->pdoStatement ? $this->pdoStatement->columnCount() : NULL; - } - - - /** - * @return int - */ - public function getRowCount() - { - return $this->pdoStatement ? $this->pdoStatement->rowCount() : NULL; - } - - - /** - * @return float - */ - public function getTime() - { - return $this->time; - } - - - /** - * Normalizes result row. - * @param array - * @return array - */ - public function normalizeRow($row) - { - if ($this->types === NULL) { - $this->types = (array) $this->supplementalDriver->getColumnTypes($this->pdoStatement); - } - - foreach ($this->types as $key => $type) { - $value = $row[$key]; - if ($value === NULL || $value === FALSE || $type === IReflection::FIELD_TEXT) { - - } elseif ($type === IReflection::FIELD_INTEGER) { - $row[$key] = is_float($tmp = $value * 1) ? $value : $tmp; - - } elseif ($type === IReflection::FIELD_FLOAT) { - if (($pos = strpos($value, '.')) !== FALSE) { - $value = rtrim(rtrim($pos === 0 ? "0$value" : $value, '0'), '.'); - } - $float = (float) $value; - $row[$key] = (string) $float === $value ? $float : $value; - - } elseif ($type === IReflection::FIELD_BOOL) { - $row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F'; - - } elseif ($type === IReflection::FIELD_DATETIME || $type === IReflection::FIELD_DATE || $type === IReflection::FIELD_TIME) { - $row[$key] = new Nette\DateTime($value); - - } elseif ($type === IReflection::FIELD_TIME_INTERVAL) { - preg_match('#^(-?)(\d+)\D(\d+)\D(\d+)\z#', $value, $m); - $row[$key] = new \DateInterval("PT$m[2]H$m[3]M$m[4]S"); - $row[$key]->invert = (int) (bool) $m[1]; - - } elseif ($type === IReflection::FIELD_UNIX_TIMESTAMP) { - $row[$key] = Nette\DateTime::from($value); - } - } - - return $this->supplementalDriver->normalizeRow($row); - } - - - /********************* misc tools ****************d*g**/ - - - /** - * Displays complete result set as HTML table for debug purposes. - * @return void - */ - public function dump() - { - Helpers::dumpResult($this); - } - - - /********************* interface Iterator ****************d*g**/ - - - public function rewind() - { - if ($this->result === FALSE) { - throw new Nette\InvalidStateException('Nette\\Database\\ResultSet implements only one way iterator.'); - } - } - - - public function current() - { - return $this->result; - } - - - public function key() - { - return $this->resultKey; - } - - - public function next() - { - $this->result = FALSE; - } - - - public function valid() - { - if ($this->result) { - return TRUE; - } - - return $this->fetch() !== FALSE; - } - - - /********************* interface IRowContainer ****************d*g**/ - - - /** - * @inheritDoc - */ - public function fetch() - { - $data = $this->pdoStatement ? $this->pdoStatement->fetch() : NULL; - if (!$data) { - $this->pdoStatement->closeCursor(); - return FALSE; - } - - $row = new Row; - foreach ($this->normalizeRow($data) as $key => $value) { - if ($key !== '') { - $row->$key = $value; - } - } - - if ($this->result === NULL && count($data) !== $this->pdoStatement->columnCount()) { - trigger_error('Found duplicate columns in database result set.', E_USER_NOTICE); - } - - $this->resultKey++; - return $this->result = $row; - } - - - /** - * Fetches single field. - * @return mixed|FALSE - */ - public function fetchField($column = 0) - { - $row = $this->fetch(); - return $row ? $row[$column] : FALSE; - } - - - /** - * @inheritDoc - */ - public function fetchPairs($key = NULL, $value = NULL) - { - return Helpers::toPairs($this->fetchAll(), $key, $value); - } - - - /** - * @inheritDoc - */ - public function fetchAll() - { - if ($this->results === NULL) { - $this->results = iterator_to_array($this); - } - return $this->results; - } - - - /** @deprecated */ - function columnCount() - { - trigger_error(__METHOD__ . '() is deprecated; use getColumnCount() instead.', E_USER_DEPRECATED); - return $this->getColumnCount(); - } - - - /** @deprecated */ - function rowCount() - { - trigger_error(__METHOD__ . '() is deprecated; use getRowCount() instead.', E_USER_DEPRECATED); - return $this->getRowCount(); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Row.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Row.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Row.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Row.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -$key; - } - - - /** - * Checks if $key exists. - * @param mixed key or index - * @return bool - */ - public function offsetExists($key) - { - if (is_int($key)) { - return (bool) current(array_slice((array) $this, $key, 1)); - } - return parent::offsetExists($key); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/SqlLiteral.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/SqlLiteral.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/SqlLiteral.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/SqlLiteral.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -value = (string) $value; - $this->parameters = $parameters; - } - - - /** - * @return array - */ - public function getParameters() - { - return $this->parameters; - } - - - /** - * @return string - */ - public function __toString() - { - return $this->value; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/SqlPreprocessor.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/SqlPreprocessor.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/SqlPreprocessor.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/SqlPreprocessor.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,225 +0,0 @@ -connection = $connection; - $this->driver = $connection->getSupplementalDriver(); - $this->arrayModes = array( - 'INSERT' => $this->driver->isSupported(ISupplementalDriver::SUPPORT_MULTI_INSERT_AS_SELECT) ? 'select' : 'values', - 'REPLACE' => 'values', - 'UPDATE' => 'assoc', - 'WHERE' => 'and', - 'HAVING' => 'and', - 'ORDER BY' => 'order', - 'GROUP BY' => 'order', - ); - } - - - /** - * @param array - * @return array of [sql, params] - */ - public function process($params) - { - $this->params = $params; - $this->counter = 0; - $this->remaining = array(); - $this->arrayMode = 'assoc'; - $res = array(); - - while ($this->counter < count($params)) { - $param = $params[$this->counter++]; - - if (($this->counter === 2 && count($params) === 2) || !is_scalar($param)) { - $res[] = $this->formatValue($param); - } else { - $res[] = Nette\Utils\Strings::replace( - $param, - '~\'.*?\'|".*?"|\?|\b(?:INSERT|REPLACE|UPDATE|WHERE|HAVING|ORDER BY|GROUP BY)\b|/\*.*?\*/|--[^\n]*~si', - array($this, 'callback') - ); - } - } - - return array(implode(' ', $res), $this->remaining); - } - - - /** @internal */ - public function callback($m) - { - $m = $m[0]; - if ($m[0] === "'" || $m[0] === '"' || $m[0] === '/' || $m[0] === '-') { // string or comment - return $m; - - } elseif ($m === '?') { // placeholder - if ($this->counter >= count($this->params)) { - throw new Nette\InvalidArgumentException('There are more placeholders than passed parameters.'); - } - return $this->formatValue($this->params[$this->counter++]); - - } else { // command - $this->arrayMode = $this->arrayModes[strtoupper($m)]; - return $m; - } - } - - - private function formatValue($value) - { - if (is_string($value)) { - if (strlen($value) > 20) { - $this->remaining[] = $value; - return '?'; - - } else { - return $this->connection->quote($value); - } - - } elseif (is_int($value)) { - return (string) $value; - - } elseif (is_float($value)) { - return rtrim(rtrim(number_format($value, 10, '.', ''), '0'), '.'); - - } elseif (is_bool($value)) { - return $this->driver->formatBool($value); - - } elseif ($value === NULL) { - return 'NULL'; - - } elseif ($value instanceof Table\IRow) { - return $value->getPrimary(); - - } elseif (is_array($value) || $value instanceof \Traversable) { - $vx = $kx = array(); - - if ($value instanceof \Traversable) { - $value = iterator_to_array($value); - } - - if (isset($value[0])) { // non-associative; value, value, value - foreach ($value as $v) { - if (is_array($v) && isset($v[0])) { // no-associative; (value), (value), (value) - $vx[] = '(' . $this->formatValue($v) . ')'; - } else { - $vx[] = $this->formatValue($v); - } - } - if ($this->arrayMode === 'union') { - return implode(' ', $vx); - } - return implode(', ', $vx); - - } elseif ($this->arrayMode === 'values') { // (key, key, ...) VALUES (value, value, ...) - $this->arrayMode = 'multi'; - foreach ($value as $k => $v) { - $kx[] = $this->driver->delimite($k); - $vx[] = $this->formatValue($v); - } - return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')'; - - } elseif ($this->arrayMode === 'select') { // (key, key, ...) SELECT value, value, ... - $this->arrayMode = 'union'; - foreach ($value as $k => $v) { - $kx[] = $this->driver->delimite($k); - $vx[] = $this->formatValue($v); - } - return '(' . implode(', ', $kx) . ') SELECT ' . implode(', ', $vx); - - } elseif ($this->arrayMode === 'assoc') { // key=value, key=value, ... - foreach ($value as $k => $v) { - if (substr($k, -1) === '=') { - $k2 = $this->driver->delimite(substr($k, 0, -2)); - $vx[] = $k2 . '=' . $k2 . ' ' . substr($k, -2, 1) . ' ' . $this->formatValue($v); - } else { - $vx[] = $this->driver->delimite($k) . '=' . $this->formatValue($v); - } - } - return implode(', ', $vx); - - } elseif ($this->arrayMode === 'multi') { // multiple insert (value, value, ...), ... - foreach ($value as $v) { - $vx[] = $this->formatValue($v); - } - return '(' . implode(', ', $vx) . ')'; - - } elseif ($this->arrayMode === 'union') { // UNION ALL SELECT value, value, ... - foreach ($value as $v) { - $vx[] = $this->formatValue($v); - } - return 'UNION ALL SELECT ' . implode(', ', $vx); - - } elseif ($this->arrayMode === 'and') { // (key [operator] value) AND ... - foreach ($value as $k => $v) { - $k = $this->driver->delimite($k); - if (is_array($v)) { - $vx[] = $v ? ($k . ' IN (' . $this->formatValue(array_values($v)) . ')') : '1=0'; - } else { - $v = $this->formatValue($v); - $vx[] = $k . ($v === 'NULL' ? ' IS ' : ' = ') . $v; - } - } - return $value ? '(' . implode(') AND (', $vx) . ')' : '1=1'; - - } elseif ($this->arrayMode === 'order') { // key, key DESC, ... - foreach ($value as $k => $v) { - $vx[] = $this->driver->delimite($k) . ($v > 0 ? '' : ' DESC'); - } - return implode(', ', $vx); - } - - } elseif ($value instanceof \DateTime || $value instanceof \DateTimeInterface) { - return $this->driver->formatDateTime($value); - - } elseif ($value instanceof SqlLiteral) { - $this->remaining = array_merge($this->remaining, $value->getParameters()); - return $value->__toString(); - - } else { - $this->remaining[] = $value; - return '?'; - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Table/ActiveRow.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Table/ActiveRow.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Table/ActiveRow.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Table/ActiveRow.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,339 +0,0 @@ -data = $data; - $this->table = $table; - } - - - /** - * @internal - * @ignore - */ - public function setTable(Selection $table) - { - $this->table = $table; - } - - - /** - * @internal - */ - public function getTable() - { - return $this->table; - } - - - public function __toString() - { - try { - return (string) $this->getPrimary(); - } catch (\Exception $e) { - if (func_num_args()) { - throw $e; - } - trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); - } - } - - - /** - * @return array - */ - public function toArray() - { - $this->accessColumn(NULL); - return $this->data; - } - - - /** - * Returns primary key value. - * @param bool - * @return mixed possible int, string, array, object (Nette\DateTime) - */ - public function getPrimary($need = TRUE) - { - $primary = $this->table->getPrimary($need); - if ($primary === NULL) { - return NULL; - - } elseif (!is_array($primary)) { - if (isset($this->data[$primary])) { - return $this->data[$primary]; - } elseif ($need) { - throw new Nette\InvalidStateException("Row does not contain primary $primary column data."); - } else { - return NULL; - } - - } else { - $primaryVal = array(); - foreach ($primary as $key) { - if (!isset($this->data[$key])) { - if ($need) { - throw new Nette\InvalidStateException("Row does not contain primary $key column data."); - } else { - return NULL; - } - } - $primaryVal[$key] = $this->data[$key]; - } - return $primaryVal; - } - } - - - /** - * Returns row signature (composition of primary keys) - * @param bool - * @return string - */ - public function getSignature($need = TRUE) - { - return implode('|', (array) $this->getPrimary($need)); - } - - - /** - * Returns referenced row. - * @param string - * @param string - * @return IRow or NULL if the row does not exist - */ - public function ref($key, $throughColumn = NULL) - { - if (!$throughColumn) { - list($key, $throughColumn) = $this->table->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key); - } - - return $this->getReference($key, $throughColumn); - } - - - /** - * Returns referencing rows. - * @param string - * @param string - * @return GroupedSelection - */ - public function related($key, $throughColumn = NULL) - { - if (strpos($key, '.') !== FALSE) { - list($key, $throughColumn) = explode('.', $key); - } elseif (!$throughColumn) { - list($key, $throughColumn) = $this->table->getDatabaseReflection()->getHasManyReference($this->table->getName(), $key); - } - - return $this->table->getReferencingTable($key, $throughColumn, $this[$this->table->getPrimary()]); - } - - - /** - * Updates row. - * @param array|\Traversable (column => value) - * @return bool - */ - public function update($data) - { - $selection = $this->table->createSelectionInstance() - ->wherePrimary($this->getPrimary()); - - if ($selection->update($data)) { - $this->isModified = TRUE; - $selection->select('*'); - if (($row = $selection->fetch()) === FALSE) { - throw new Nette\InvalidStateException('Database refetch failed; row does not exist!'); - } - $this->data = $row->data; - return TRUE; - } else { - return FALSE; - } - } - - - /** - * Deletes row. - * @return int number of affected rows - */ - public function delete() - { - $res = $this->table->createSelectionInstance() - ->wherePrimary($this->getPrimary()) - ->delete(); - - if ($res > 0 && ($signature = $this->getSignature(FALSE))) { - unset($this->table[$signature]); - } - - return $res; - } - - - /********************* interface IteratorAggregate ****************d*g**/ - - - public function getIterator() - { - $this->accessColumn(NULL); - return new \ArrayIterator($this->data); - } - - - /********************* interface ArrayAccess & magic accessors ****************d*g**/ - - - /** - * Stores value in column. - * @param string column name - * @param string value - * @return void - */ - public function offsetSet($key, $value) - { - $this->__set($key, $value); - } - - - /** - * Returns value of column. - * @param string column name - * @return string - */ - public function offsetGet($key) - { - return $this->__get($key); - } - - - /** - * Tests if column exists. - * @param string column name - * @return bool - */ - public function offsetExists($key) - { - return $this->__isset($key); - } - - - /** - * Removes column from data. - * @param string column name - * @return void - */ - public function offsetUnset($key) - { - $this->__unset($key); - } - - - public function __set($key, $value) - { - throw new Nette\DeprecatedException('ActiveRow is read-only; use update() method instead.'); - } - - - public function &__get($key) - { - $this->accessColumn($key); - if (array_key_exists($key, $this->data)) { - return $this->data[$key]; - } - - try { - list($table, $column) = $this->table->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key); - $referenced = $this->getReference($table, $column); - if ($referenced !== FALSE) { - $this->accessColumn($key, FALSE); - return $referenced; - } - } catch(MissingReferenceException $e) {} - - $this->removeAccessColumn($key); - throw new Nette\MemberAccessException("Cannot read an undeclared column '$key'."); - } - - - public function __isset($key) - { - $this->accessColumn($key); - if (array_key_exists($key, $this->data)) { - return isset($this->data[$key]); - } - $this->removeAccessColumn($key); - return FALSE; - } - - - public function __unset($key) - { - throw new Nette\DeprecatedException('ActiveRow is read-only.'); - } - - - protected function accessColumn($key, $selectColumn = TRUE) - { - $this->table->accessColumn($key, $selectColumn); - if ($this->table->getDataRefreshed() && !$this->dataRefreshed) { - $this->data = $this->table[$this->getSignature()]->data; - $this->dataRefreshed = TRUE; - } - } - - - protected function removeAccessColumn($key) - { - $this->table->removeAccessColumn($key); - } - - - protected function getReference($table, $column) - { - $this->accessColumn($column); - if (array_key_exists($column, $this->data)) { - $value = $this->data[$column]; - $referenced = $this->table->getReferencedTable($table, $column, $value); - return isset($referenced[$value]) ? $referenced[$value] : NULL; // referenced row may not exist - } - - return FALSE; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Table/GroupedSelection.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Table/GroupedSelection.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Table/GroupedSelection.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Table/GroupedSelection.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,259 +0,0 @@ -refTable = $refTable; - $this->column = $column; - parent::__construct($refTable->connection, $table, $refTable->reflection, $refTable->cache ? $refTable->cache->getStorage() : NULL); - } - - - /** - * Sets active group. - * @internal - * @param int primary key of grouped rows - * @return GroupedSelection - */ - public function setActive($active) - { - $this->active = $active; - return $this; - } - - - /** @deprecated */ - public function through($column) - { - trigger_error(__METHOD__ . '() is deprecated; use ' . __CLASS__ . '::related("' . $this->name . '", "' . $column . '") instead.', E_USER_DEPRECATED); - $this->column = $column; - $this->delimitedColumn = $this->refTable->connection->getSupplementalDriver()->delimite($this->column); - return $this; - } - - - public function select($columns) - { - if (!$this->sqlBuilder->getSelect()) { - $this->sqlBuilder->addSelect("$this->name.$this->column"); - } - - return call_user_func_array('parent::select', func_get_args()); - } - - - public function order($columns) - { - if (!$this->sqlBuilder->getOrder()) { - // improve index utilization - $this->sqlBuilder->addOrder("$this->name.$this->column" . (preg_match('~\bDESC\z~i', $columns) ? ' DESC' : '')); - } - - return call_user_func_array('parent::order', func_get_args()); - } - - - /********************* aggregations ****************d*g**/ - - - public function aggregation($function) - { - $aggregation = & $this->getRefTable($refPath)->aggregation[$refPath . $function . $this->getSql() . json_encode($this->sqlBuilder->getParameters())]; - - if ($aggregation === NULL) { - $aggregation = array(); - - $selection = $this->createSelectionInstance(); - $selection->getSqlBuilder()->importConditions($this->getSqlBuilder()); - $selection->select($function); - $selection->select("$this->name.$this->column"); - $selection->group("$this->name.$this->column"); - - foreach ($selection as $row) { - $aggregation[$row[$this->column]] = $row; - } - } - - if (isset($aggregation[$this->active])) { - foreach ($aggregation[$this->active] as $val) { - return $val; - } - } - } - - - public function count($column = NULL) - { - $return = parent::count($column); - return isset($return) ? $return : 0; - } - - - /********************* internal ****************d*g**/ - - - protected function execute() - { - if ($this->rows !== NULL) { - $this->observeCache = $this; - return; - } - - $accessedColumns = $this->accessedColumns; - $this->loadRefCache(); - - if (!isset($this->refCacheCurrent['data'])) { - // we have not fetched any data yet => init accessedColumns by cached accessedColumns - $this->accessedColumns = $accessedColumns; - - $limit = $this->sqlBuilder->getLimit(); - $rows = count($this->refTable->rows); - if ($limit && $rows > 1) { - $this->sqlBuilder->setLimit(NULL, NULL); - } - parent::execute(); - $this->sqlBuilder->setLimit($limit, NULL); - $data = array(); - $offset = array(); - $this->accessColumn($this->column); - foreach ((array) $this->rows as $key => $row) { - $ref = & $data[$row[$this->column]]; - $skip = & $offset[$row[$this->column]]; - if ($limit === NULL || $rows <= 1 || (count($ref) < $limit && $skip >= $this->sqlBuilder->getOffset())) { - $ref[$key] = $row; - } else { - unset($this->rows[$key]); - } - $skip++; - unset($ref, $skip); - } - - $this->refCacheCurrent['data'] = $data; - $this->data = & $this->refCacheCurrent['data'][$this->active]; - } - - $this->observeCache = $this; - if ($this->data === NULL) { - $this->data = array(); - } else { - foreach ($this->data as $row) { - $row->setTable($this); // injects correct parent GroupedSelection - } - reset($this->data); - } - } - - - protected function getRefTable(& $refPath) - { - $refObj = $this->refTable; - $refPath = $this->name . '.'; - while ($refObj instanceof GroupedSelection) { - $refPath .= $refObj->name . '.'; - $refObj = $refObj->refTable; - } - - return $refObj; - } - - - protected function loadRefCache() - { - $hash = $this->getSpecificCacheKey(); - $referencing = & $this->refCache['referencing'][$this->getGeneralCacheKey()]; - $this->observeCache = & $referencing['observeCache']; - $this->refCacheCurrent = & $referencing[$hash]; - $this->accessedColumns = & $referencing[$hash]['accessed']; - $this->specificCacheKey = & $referencing[$hash]['specificCacheKey']; - $this->rows = & $referencing[$hash]['rows']; - - if (isset($referencing[$hash]['data'][$this->active])) { - $this->data = & $referencing[$hash]['data'][$this->active]; - } - } - - - /********************* manipulation ****************d*g**/ - - - public function insert($data) - { - if ($data instanceof \Traversable && !$data instanceof Selection) { - $data = iterator_to_array($data); - } - - if (Nette\Utils\Arrays::isList($data)) { - foreach (array_keys($data) as $key) { - $data[$key][$this->column] = $this->active; - } - } else { - $data[$this->column] = $this->active; - } - - return parent::insert($data); - } - - - public function update($data) - { - $builder = $this->sqlBuilder; - - $this->sqlBuilder = clone $this->sqlBuilder; - $this->where($this->column, $this->active); - $return = parent::update($data); - - $this->sqlBuilder = $builder; - return $return; - } - - - public function delete() - { - $builder = $this->sqlBuilder; - - $this->sqlBuilder = clone $this->sqlBuilder; - $this->where($this->column, $this->active); - $return = parent::delete(); - - $this->sqlBuilder = $builder; - return $return; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Table/IRowContainer.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Table/IRowContainer.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Table/IRowContainer.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Table/IRowContainer.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ - IRow] format */ - protected $rows; - - /** @var IRow[] modifiable data in [primary key => IRow] format */ - protected $data; - - /** @var bool */ - protected $dataRefreshed = FALSE; - - /** @var mixed cache array of Selection and GroupedSelection prototypes */ - protected $globalRefCache; - - /** @var mixed */ - protected $refCache; - - /** @var string */ - protected $generalCacheKey; - - /** @var string */ - protected $specificCacheKey; - - /** @var array of [conditions => [key => IRow]]; used by GroupedSelection */ - protected $aggregation = array(); - - /** @var array of touched columns */ - protected $accessedColumns; - - /** @var array of earlier touched columns */ - protected $previousAccessedColumns; - - /** @var bool should instance observe accessed columns caching */ - protected $observeCache = FALSE; - - /** @var array of primary key values */ - protected $keys = array(); - - - /** - * Creates filtered table representation. - * @param Nette\Database\Connection - * @param string database table name - */ - public function __construct(Nette\Database\Connection $connection, $table, Nette\Database\IReflection $reflection, Nette\Caching\IStorage $cacheStorage = NULL) - { - $this->name = $table; - $this->connection = $connection; - $this->reflection = $reflection; - $this->cache = $cacheStorage ? new Nette\Caching\Cache($cacheStorage, 'Nette.Database.' . md5($connection->getDsn())) : NULL; - $this->primary = $reflection->getPrimary($table); - $this->sqlBuilder = new SqlBuilder($table, $connection, $reflection); - $this->refCache = & $this->getRefTable($refPath)->globalRefCache[$refPath]; - } - - - public function __destruct() - { - $this->saveCacheState(); - } - - - public function __clone() - { - $this->sqlBuilder = clone $this->sqlBuilder; - } - - - /** - * @return Nette\Database\Connection - */ - public function getConnection() - { - return $this->connection; - } - - - /** - * @return Nette\Database\IReflection - */ - public function getDatabaseReflection() - { - return $this->reflection; - } - - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - - /** - * @param bool - * @return string|array - */ - public function getPrimary($need = TRUE) - { - if ($this->primary === NULL && $need) { - throw new \LogicException("Table '{$this->name}' does not have a primary key."); - } - return $this->primary; - } - - - /** - * @return string - */ - public function getPrimarySequence() - { - if ($this->primarySequence === FALSE) { - $this->primarySequence = NULL; - $driver = $this->connection->getSupplementalDriver(); - if ($driver->isSupported(ISupplementalDriver::SUPPORT_SEQUENCE) && $this->primary !== NULL) { - foreach ($driver->getColumns($this->name) as $column) { - if ($column['name'] === $this->primary) { - $this->primarySequence = $column['vendor']['sequence']; - break; - } - } - } - } - - return $this->primarySequence; - } - - - /** - * @param string - * @return self - */ - public function setPrimarySequence($sequence) - { - $this->primarySequence = $sequence; - return $this; - } - - - /** - * @return string - */ - public function getSql() - { - return $this->sqlBuilder->buildSelectQuery($this->getPreviousAccessedColumns()); - } - - - /** - * Loads cache of previous accessed columns and returns it. - * @internal - * @return array|false - */ - public function getPreviousAccessedColumns() - { - if ($this->cache && $this->previousAccessedColumns === NULL) { - $this->accessedColumns = $this->previousAccessedColumns = $this->cache->load($this->getGeneralCacheKey()); - if ($this->previousAccessedColumns === NULL) { - $this->previousAccessedColumns = array(); - } - } - - return array_keys(array_filter((array) $this->previousAccessedColumns)); - } - - - /** - * @internal - * @return SqlBuilder - */ - public function getSqlBuilder() - { - return $this->sqlBuilder; - } - - - /********************* quick access ****************d*g**/ - - - /** - * Returns row specified by primary key. - * @param mixed primary key - * @return IRow or FALSE if there is no such row - */ - public function get($key) - { - $clone = clone $this; - return $clone->wherePrimary($key)->fetch(); - } - - - /** - * @inheritDoc - */ - public function fetch() - { - $this->execute(); - $return = current($this->data); - next($this->data); - return $return; - } - - - /** - * @inheritDoc - */ - public function fetchPairs($key = NULL, $value = NULL) - { - return Nette\Database\Helpers::toPairs(iterator_to_array($this), $key, $value); - } - - - /** - * @inheritDoc - */ - public function fetchAll() - { - return iterator_to_array($this); - } - - - /********************* sql selectors ****************d*g**/ - - - /** - * Adds select clause, more calls appends to the end. - * @param string for example "column, MD5(column) AS column_md5" - * @return self - */ - public function select($columns) - { - $this->emptyResultSet(); - call_user_func_array(array($this->sqlBuilder, 'addSelect'), func_get_args()); - return $this; - } - - - /** - * @deprecated - */ - public function find($key) - { - trigger_error(__METHOD__ . '() is deprecated; use $selection->wherePrimary() instead.', E_USER_DEPRECATED); - return $this->wherePrimary($key); - } - - - /** - * Adds condition for primary key. - * @param mixed - * @return self - */ - public function wherePrimary($key) - { - if (is_array($this->primary) && Nette\Utils\Arrays::isList($key)) { - if (isset($key[0]) && is_array($key[0])) { - $this->where($this->primary, $key); - } else { - foreach ($this->primary as $i => $primary) { - $this->where($this->name . '.' . $primary, $key[$i]); - } - } - } elseif (is_array($key) && !Nette\Utils\Arrays::isList($key)) { // key contains column names - $this->where($key); - } else { - $this->where($this->name . '.' . $this->getPrimary(), $key); - } - - return $this; - } - - - /** - * Adds where condition, more calls appends with AND. - * @param string condition possibly containing ? - * @param mixed - * @param mixed ... - * @return self - */ - public function where($condition, $parameters = array()) - { - if (is_array($condition) && $parameters === array()) { // where(array('column1' => 1, 'column2 > ?' => 2)) - foreach ($condition as $key => $val) { - if (is_int($key)) { - $this->where($val); // where('full condition') - } else { - $this->where($key, $val); // where('column', 1) - } - } - return $this; - } - - $this->emptyResultSet(); - call_user_func_array(array($this->sqlBuilder, 'addWhere'), func_get_args()); - return $this; - } - - - /** - * Adds order clause, more calls appends to the end. - * @param string for example 'column1, column2 DESC' - * @return self - */ - public function order($columns) - { - $this->emptyResultSet(); - call_user_func_array(array($this->sqlBuilder, 'addOrder'), func_get_args()); - return $this; - } - - - /** - * Sets limit clause, more calls rewrite old values. - * @param int - * @param int - * @return self - */ - public function limit($limit, $offset = NULL) - { - $this->emptyResultSet(); - $this->sqlBuilder->setLimit($limit, $offset); - return $this; - } - - - /** - * Sets offset using page number, more calls rewrite old values. - * @param int - * @param int - * @return self - */ - public function page($page, $itemsPerPage, & $numOfPages = NULL) - { - if (func_num_args() > 2) { - $numOfPages = (int) ceil($this->count('*') / $itemsPerPage); - } - return $this->limit($itemsPerPage, ($page - 1) * $itemsPerPage); - } - - - /** - * Sets group clause, more calls rewrite old value. - * @param string - * @return self - */ - public function group($columns) - { - $this->emptyResultSet(); - if (func_num_args() === 2 && strpos($columns, '?') === FALSE) { - trigger_error('Calling ' . __METHOD__ . '() with second argument is deprecated; use $selection->having() instead.', E_USER_DEPRECATED); - $this->having(func_get_arg(1)); - $this->sqlBuilder->setGroup($columns); - } else { - call_user_func_array(array($this->sqlBuilder, 'setGroup'), func_get_args()); - } - return $this; - } - - - /** - * Sets having clause, more calls rewrite old value. - * @param string - * @return self - */ - public function having($having) - { - $this->emptyResultSet(); - call_user_func_array(array($this->sqlBuilder, 'setHaving'), func_get_args()); - return $this; - } - - - /********************* aggregations ****************d*g**/ - - - /** - * Executes aggregation function. - * @param string select call in "FUNCTION(column)" format - * @return string - */ - public function aggregation($function) - { - $selection = $this->createSelectionInstance(); - $selection->getSqlBuilder()->importConditions($this->getSqlBuilder()); - $selection->select($function); - foreach ($selection->fetch() as $val) { - return $val; - } - } - - - /** - * Counts number of rows. - * @param string if it is not provided returns count of result rows, otherwise runs new sql counting query - * @return int - */ - public function count($column = NULL) - { - if (!$column) { - $this->execute(); - return count($this->data); - } - return $this->aggregation("COUNT($column)"); - } - - - /** - * Returns minimum value from a column. - * @param string - * @return int - */ - public function min($column) - { - return $this->aggregation("MIN($column)"); - } - - - /** - * Returns maximum value from a column. - * @param string - * @return int - */ - public function max($column) - { - return $this->aggregation("MAX($column)"); - } - - - /** - * Returns sum of values in a column. - * @param string - * @return int - */ - public function sum($column) - { - return $this->aggregation("SUM($column)"); - } - - - /********************* internal ****************d*g**/ - - - protected function execute() - { - if ($this->rows !== NULL) { - return; - } - - $this->observeCache = $this; - - if ($this->primary === NULL && $this->sqlBuilder->getSelect() === NULL) { - throw new Nette\InvalidStateException('Table with no primary key requires an explicit select clause.'); - } - - try { - $result = $this->query($this->getSql()); - - } catch (\PDOException $exception) { - if (!$this->sqlBuilder->getSelect() && $this->previousAccessedColumns) { - $this->previousAccessedColumns = FALSE; - $this->accessedColumns = array(); - $result = $this->query($this->getSql()); - } else { - throw $exception; - } - } - - $this->rows = array(); - $usedPrimary = TRUE; - foreach ($result->getPdoStatement() as $key => $row) { - $row = $this->createRow($result->normalizeRow($row)); - $primary = $row->getSignature(FALSE); - $usedPrimary = $usedPrimary && $primary; - $this->rows[$primary ?: $key] = $row; - } - $this->data = $this->rows; - - if ($usedPrimary && $this->accessedColumns !== FALSE) { - foreach ((array) $this->primary as $primary) { - $this->accessedColumns[$primary] = TRUE; - } - } - } - - - protected function createRow(array $row) - { - return new ActiveRow($row, $this); - } - - - public function createSelectionInstance($table = NULL) - { - return new Selection($this->connection, $table ?: $this->name, $this->reflection, $this->cache ? $this->cache->getStorage() : NULL); - } - - - protected function createGroupedSelectionInstance($table, $column) - { - return new GroupedSelection($this, $table, $column); - } - - - protected function query($query) - { - return $this->connection->queryArgs($query, $this->sqlBuilder->getParameters()); - } - - - protected function emptyResultSet($saveCache = TRUE) - { - if ($this->rows !== NULL && $saveCache) { - $this->saveCacheState(); - } - - $this->rows = NULL; - $this->specificCacheKey = NULL; - $this->generalCacheKey = NULL; - $this->refCache['referencingPrototype'] = array(); - } - - - protected function saveCacheState() - { - if ($this->observeCache === $this && $this->cache && !$this->sqlBuilder->getSelect() && $this->accessedColumns !== $this->previousAccessedColumns) { - $previousAccessed = $this->cache->load($this->getGeneralCacheKey()); - $accessed = $this->accessedColumns; - $needSave = is_array($accessed) && is_array($previousAccessed) - ? array_intersect_key($accessed, $previousAccessed) !== $accessed - : $accessed !== $previousAccessed; - - if ($needSave) { - $save = is_array($accessed) && is_array($previousAccessed) ? $previousAccessed + $accessed : $accessed; - $this->cache->save($this->getGeneralCacheKey(), $save); - $this->previousAccessedColumns = NULL; - } - } - } - - - /** - * Returns Selection parent for caching. - * @return Selection - */ - protected function getRefTable(& $refPath) - { - return $this; - } - - - /** - * Loads refCache references - */ - protected function loadRefCache() - { - } - - - /** - * Returns general cache key independent on query parameters or sql limit - * Used e.g. for previously accessed columns caching - * @return string - */ - protected function getGeneralCacheKey() - { - if ($this->generalCacheKey) { - return $this->generalCacheKey; - } - - return $this->generalCacheKey = md5(serialize(array(__CLASS__, $this->name, $this->sqlBuilder->getConditions()))); - } - - - /** - * Returns object specific cache key dependent on query parameters - * Used e.g. for reference memory caching - * @return string - */ - protected function getSpecificCacheKey() - { - if ($this->specificCacheKey) { - return $this->specificCacheKey; - } - - return $this->specificCacheKey = md5($this->getSql() . json_encode($this->sqlBuilder->getParameters())); - } - - - /** - * @internal - * @param string|NULL column name or NULL to reload all columns - * @param bool - */ - public function accessColumn($key, $selectColumn = TRUE) - { - if (!$this->cache) { - return; - } - - if ($key === NULL) { - $this->accessedColumns = FALSE; - $currentKey = key((array) $this->data); - } elseif ($this->accessedColumns !== FALSE) { - $this->accessedColumns[$key] = $selectColumn; - } - - if ($selectColumn && !$this->sqlBuilder->getSelect() && $this->previousAccessedColumns && ($key === NULL || !isset($this->previousAccessedColumns[$key]))) { - $this->previousAccessedColumns = array(); - - if ($this->sqlBuilder->getLimit()) { - $generalCacheKey = $this->generalCacheKey; - $sqlBuilder = $this->sqlBuilder; - - $primaryValues = array(); - foreach ((array) $this->rows as $row) { - $primary = $row->getPrimary(); - $primaryValues[] = is_array($primary) ? array_values($primary) : $primary; - } - - $this->emptyResultSet(FALSE); - $this->sqlBuilder = clone $this->sqlBuilder; - $this->sqlBuilder->setLimit(NULL, NULL); - $this->wherePrimary($primaryValues); - - $this->generalCacheKey = $generalCacheKey; - $this->execute(); - $this->sqlBuilder = $sqlBuilder; - } else { - $this->emptyResultSet(FALSE); - $this->execute(); - } - - $this->dataRefreshed = TRUE; - - // move iterator to specific key - if (isset($currentKey)) { - while (key($this->data) !== $currentKey) { - next($this->data); - } - } - } - } - - - /** - * @internal - * @param string - */ - public function removeAccessColumn($key) - { - if ($this->cache && is_array($this->accessedColumns)) { - $this->accessedColumns[$key] = FALSE; - } - } - - - /** - * Returns if selection requeried for more columns. - * @return bool - */ - public function getDataRefreshed() - { - return $this->dataRefreshed; - } - - - /********************* manipulation ****************d*g**/ - - - /** - * Inserts row in a table. - * @param array|\Traversable|Selection array($column => $value)|\Traversable|Selection for INSERT ... SELECT - * @return IRow|int|bool Returns IRow or number of affected rows for Selection or table without primary key - */ - public function insert($data) - { - if ($data instanceof Selection) { - $data = new Nette\Database\SqlLiteral($data->getSql(), $data->getSqlBuilder()->getParameters()); - - } elseif ($data instanceof \Traversable) { - $data = iterator_to_array($data); - } - - $return = $this->connection->query($this->sqlBuilder->buildInsertQuery(), $data); - $this->loadRefCache(); - - if ($data instanceof Nette\Database\SqlLiteral || $this->primary === NULL) { - unset($this->refCache['referencing'][$this->getGeneralCacheKey()][$this->getSpecificCacheKey()]); - return $return->getRowCount(); - } - - $primaryKey = $this->connection->getInsertId($this->getPrimarySequence()); - if ($primaryKey === FALSE) { - unset($this->refCache['referencing'][$this->getGeneralCacheKey()][$this->getSpecificCacheKey()]); - return $return->getRowCount(); - } - - if (is_array($this->getPrimary())) { - $primaryKey = array(); - - foreach ((array) $this->getPrimary() as $key) { - if (!isset($data[$key])) { - return $data; - } - - $primaryKey[$key] = $data[$key]; - } - if (count($primaryKey) === 1) { - $primaryKey = reset($primaryKey); - } - } - - $row = $this->createSelectionInstance() - ->select('*') - ->wherePrimary($primaryKey) - ->fetch(); - - if ($this->rows !== NULL) { - if ($signature = $row->getSignature(FALSE)) { - $this->rows[$signature] = $row; - $this->data[$signature] = $row; - } else { - $this->rows[] = $row; - $this->data[] = $row; - } - } - - return $row; - } - - - /** - * Updates all rows in result set. - * Joins in UPDATE are supported only in MySQL - * @param array|\Traversable ($column => $value) - * @return int number of affected rows - */ - public function update($data) - { - if ($data instanceof \Traversable) { - $data = iterator_to_array($data); - - } elseif (!is_array($data)) { - throw new Nette\InvalidArgumentException; - } - - if (!$data) { - return 0; - } - - return $this->connection->queryArgs( - $this->sqlBuilder->buildUpdateQuery(), - array_merge(array($data), $this->sqlBuilder->getParameters()) - )->getRowCount(); - } - - - /** - * Deletes all rows in result set. - * @return int number of affected rows - */ - public function delete() - { - return $this->query($this->sqlBuilder->buildDeleteQuery())->getRowCount(); - } - - - /********************* references ****************d*g**/ - - - /** - * Returns referenced row. - * @param string - * @param string - * @param mixed primary key to check for $table and $column references - * @return Selection or array() if the row does not exist - */ - public function getReferencedTable($table, $column, $checkPrimaryKey) - { - $referenced = & $this->refCache['referenced'][$this->getSpecificCacheKey()]["$table.$column"]; - $selection = & $referenced['selection']; - $cacheKeys = & $referenced['cacheKeys']; - if ($selection === NULL || !isset($cacheKeys[$checkPrimaryKey])) { - $this->execute(); - $cacheKeys = array(); - foreach ($this->rows as $row) { - if ($row[$column] === NULL) { - continue; - } - - $key = $row[$column]; - $cacheKeys[$key] = TRUE; - } - - if ($cacheKeys) { - $selection = $this->createSelectionInstance($table); - $selection->where($selection->getPrimary(), array_keys($cacheKeys)); - } else { - $selection = array(); - } - } - - return $selection; - } - - - /** - * Returns referencing rows. - * @param string - * @param string - * @param int primary key - * @return GroupedSelection - */ - public function getReferencingTable($table, $column, $active = NULL) - { - $prototype = & $this->refCache['referencingPrototype']["$table.$column"]; - if (!$prototype) { - $prototype = $this->createGroupedSelectionInstance($table, $column); - $prototype->where("$table.$column", array_keys((array) $this->rows)); - } - - $clone = clone $prototype; - $clone->setActive($active); - return $clone; - } - - - /********************* interface Iterator ****************d*g**/ - - - public function rewind() - { - $this->execute(); - $this->keys = array_keys($this->data); - reset($this->keys); - } - - - /** @return IRow */ - public function current() - { - if (($key = current($this->keys)) !== FALSE) { - return $this->data[$key]; - } else { - return FALSE; - } - } - - - /** - * @return string row ID - */ - public function key() - { - return current($this->keys); - } - - - public function next() - { - next($this->keys); - } - - - public function valid() - { - return current($this->keys) !== FALSE; - } - - - /********************* interface ArrayAccess ****************d*g**/ - - - /** - * Mimic row. - * @param string row ID - * @param IRow - * @return NULL - */ - public function offsetSet($key, $value) - { - $this->execute(); - $this->rows[$key] = $value; - } - - - /** - * Returns specified row. - * @param string row ID - * @return IRow or NULL if there is no such row - */ - public function offsetGet($key) - { - $this->execute(); - return $this->rows[$key]; - } - - - /** - * Tests if row exists. - * @param string row ID - * @return bool - */ - public function offsetExists($key) - { - $this->execute(); - return isset($this->rows[$key]); - } - - - /** - * Removes row from result set. - * @param string row ID - * @return NULL - */ - public function offsetUnset($key) - { - $this->execute(); - unset($this->rows[$key], $this->data[$key]); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Database/Table/SqlBuilder.php php-nette-2.1.5/Nette-2.1.4/Nette/Database/Table/SqlBuilder.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Database/Table/SqlBuilder.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Database/Table/SqlBuilder.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,494 +0,0 @@ - array(), - 'where' => array(), - 'group' => array(), - 'having' => array(), - 'order' => array(), - ); - - /** @var array or columns to order by */ - protected $order = array(); - - /** @var int number of rows to fetch */ - protected $limit = NULL; - - /** @var int first row to fetch */ - protected $offset = NULL; - - /** @var string columns to grouping */ - protected $group = ''; - - /** @var string grouping condition */ - protected $having = ''; - - - public function __construct($tableName, Connection $connection, IReflection $reflection) - { - $this->tableName = $tableName; - $this->databaseReflection = $reflection; - $this->driver = $connection->getSupplementalDriver(); - $this->delimitedTable = $this->tryDelimite($tableName); - } - - - public function buildInsertQuery() - { - return "INSERT INTO {$this->delimitedTable}"; - } - - - public function buildUpdateQuery() - { - if ($this->limit !== NULL || $this->offset) { - throw new Nette\NotSupportedException('LIMIT clause is not supported in UPDATE query.'); - } - return $this->tryDelimite("UPDATE {$this->tableName} SET ?" . $this->buildConditions()); - } - - - public function buildDeleteQuery() - { - if ($this->limit !== NULL || $this->offset) { - throw new Nette\NotSupportedException('LIMIT clause is not supported in DELETE query.'); - } - return $this->tryDelimite("DELETE FROM {$this->tableName}" . $this->buildConditions()); - } - - - /** - * Returns SQL query. - * @param string list of columns - * @return string - */ - public function buildSelectQuery($columns = NULL) - { - $queryCondition = $this->buildConditions(); - $queryEnd = $this->buildQueryEnd(); - - $joins = array(); - $this->parseJoins($joins, $queryCondition); - $this->parseJoins($joins, $queryEnd); - - if ($this->select) { - $querySelect = $this->buildSelect($this->select); - $this->parseJoins($joins, $querySelect); - - } elseif ($columns) { - $prefix = $joins ? "{$this->delimitedTable}." : ''; - $cols = array(); - foreach ($columns as $col) { - $cols[] = $prefix . $col; - } - $querySelect = $this->buildSelect($cols); - - } elseif ($this->group && !$this->driver->isSupported(ISupplementalDriver::SUPPORT_SELECT_UNGROUPED_COLUMNS)) { - $querySelect = $this->buildSelect(array($this->group)); - $this->parseJoins($joins, $querySelect); - - } else { - $prefix = $joins ? "{$this->delimitedTable}." : ''; - $querySelect = $this->buildSelect(array($prefix . '*')); - - } - - $queryJoins = $this->buildQueryJoins($joins); - $query = "{$querySelect} FROM {$this->tableName}{$queryJoins}{$queryCondition}{$queryEnd}"; - - if ($this->limit !== NULL || $this->offset) { - $this->driver->applyLimit($query, $this->limit, $this->offset); - } - - return $this->tryDelimite($query); - } - - - public function getParameters() - { - return array_merge( - $this->parameters['select'], - $this->parameters['where'], - $this->parameters['group'], - $this->parameters['having'], - $this->parameters['order'] - ); - } - - - public function importConditions(SqlBuilder $builder) - { - $this->where = $builder->where; - $this->parameters['where'] = $builder->parameters['where']; - $this->conditions = $builder->conditions; - } - - - /********************* SQL selectors ****************d*g**/ - - - public function addSelect($columns) - { - if (is_array($columns)) { - throw new Nette\InvalidArgumentException('Select column must be a string.'); - } - $this->select[] = $columns; - $this->parameters['select'] = array_merge($this->parameters['select'], array_slice(func_get_args(), 1)); - } - - - public function getSelect() - { - return $this->select; - } - - - public function addWhere($condition, $parameters = array()) - { - if (is_array($condition) && is_array($parameters) && !empty($parameters)) { - return $this->addWhereComposition($condition, $parameters); - } - - $args = func_get_args(); - $hash = md5(json_encode($args)); - if (isset($this->conditions[$hash])) { - return FALSE; - } - - $this->conditions[$hash] = $condition; - $placeholderCount = substr_count($condition, '?'); - if ($placeholderCount > 1 && count($args) === 2 && is_array($parameters)) { - $args = $parameters; - } else { - array_shift($args); - } - - $condition = trim($condition); - if ($placeholderCount === 0 && count($args) === 1) { - $condition .= ' ?'; - } elseif ($placeholderCount !== count($args)) { - throw new Nette\InvalidArgumentException('Argument count does not match placeholder count.'); - } - - $replace = NULL; - $placeholderNum = 0; - foreach ($args as $arg) { - preg_match('#(?:.*?\?.*?){' . $placeholderNum . '}(((?:&|\||^|~|\+|-|\*|/|%|\(|,|<|>|=|(?<=\W|^)(?:REGEXP|ALL|AND|ANY|BETWEEN|EXISTS|IN|[IR]?LIKE|OR|NOT|SOME|INTERVAL))\s*)?(?:\(\?\)|\?))#s', $condition, $match, PREG_OFFSET_CAPTURE); - $hasOperator = ($match[1][0] === '?' && $match[1][1] === 0) ? TRUE : !empty($match[2][0]); - - if ($arg === NULL) { - if ($hasOperator) { - throw new Nette\InvalidArgumentException('Column operator does not accept NULL argument.'); - } - $replace = 'IS NULL'; - } elseif (is_array($arg) || $arg instanceof Selection) { - if ($hasOperator) { - if (trim($match[2][0]) === 'NOT') { - $match[2][0] = rtrim($match[2][0]) . ' IN '; - } elseif (trim($match[2][0]) !== 'IN') { - throw new Nette\InvalidArgumentException('Column operator does not accept array argument.'); - } - } else { - $match[2][0] = 'IN '; - } - - if ($arg instanceof Selection) { - $clone = clone $arg; - if (!$clone->getSqlBuilder()->select) { - try { - $clone->select($clone->getPrimary()); - } catch (\LogicException $e) { - throw new Nette\InvalidArgumentException('Selection argument must have defined a select column.', 0, $e); - } - } - - if ($this->driver->isSupported(ISupplementalDriver::SUPPORT_SUBSELECT)) { - $arg = NULL; - $replace = $match[2][0] . '(' . $clone->getSql() . ')'; - $this->parameters['where'] = array_merge($this->parameters['where'], $clone->getSqlBuilder()->parameters['where']); - } else { - $arg = array(); - foreach ($clone as $row) { - $arg[] = array_values(iterator_to_array($row)); - } - } - } - - if ($arg !== NULL) { - if (!$arg) { - $hasBrackets = strpos($condition, '(') !== FALSE; - $hasOperators = preg_match('#AND|OR#', $condition); - $hasNot = strpos($condition, 'NOT') !== FALSE; - $hasPrefixNot = strpos($match[2][0], 'NOT') !== FALSE; - if (!$hasBrackets && ($hasOperators || ($hasNot && !$hasPrefixNot))) { - throw new Nette\InvalidArgumentException('Possible SQL query corruption. Add parentheses around operators.'); - } - if ($hasPrefixNot) { - $replace = 'IS NULL OR TRUE'; - } else { - $replace = 'IS NULL AND FALSE'; - } - $arg = NULL; - } else { - $replace = $match[2][0] . '(?)'; - $this->parameters['where'][] = $arg; - } - } - } elseif ($arg instanceof SqlLiteral) { - $this->parameters['where'][] = $arg; - } else { - if (!$hasOperator) { - $replace = '= ?'; - } - $this->parameters['where'][] = $arg; - } - - if ($replace) { - $condition = substr_replace($condition, $replace, $match[1][1], strlen($match[1][0])); - $replace = NULL; - } - - if ($arg !== NULL) { - $placeholderNum++; - } - } - - $this->where[] = $condition; - return TRUE; - } - - - public function getConditions() - { - return array_values($this->conditions); - } - - - public function addOrder($columns) - { - $this->order[] = $columns; - $this->parameters['order'] = array_merge($this->parameters['order'], array_slice(func_get_args(), 1)); - } - - - public function getOrder() - { - return $this->order; - } - - - public function setLimit($limit, $offset) - { - $this->limit = $limit; - $this->offset = $offset; - } - - - public function getLimit() - { - return $this->limit; - } - - - public function getOffset() - { - return $this->offset; - } - - - public function setGroup($columns) - { - $this->group = $columns; - $this->parameters['group'] = array_slice(func_get_args(), 1); - } - - - public function getGroup() - { - return $this->group; - } - - - public function setHaving($having) - { - $this->having = $having; - $this->parameters['having'] = array_slice(func_get_args(), 1); - } - - - public function getHaving() - { - return $this->having; - } - - - /********************* SQL building ****************d*g**/ - - - protected function buildSelect(array $columns) - { - return 'SELECT ' . implode(', ', $columns); - } - - - protected function parseJoins(& $joins, & $query) - { - $builder = $this; - $query = preg_replace_callback('~ - (?(DEFINE) - (?P [a-z][\w_]* ) - (?P [.:] ) - (?P (?&del)? (?&word) (\((?&word)\))? ) - ) - (?P (?!\.) (?&node)*) \. (?P (?&word) | \* ) - ~xi', function($match) use (& $joins, $builder) { - return $builder->parseJoinsCb($joins, $match); - }, $query); - } - - - public function parseJoinsCb(& $joins, $match) - { - $chain = $match['chain']; - if (!empty($chain[0]) && ($chain[0] !== '.' || $chain[0] !== ':')) { - $chain = '.' . $chain; // unified chain format - } - - $parent = $parentAlias = $this->tableName; - if ($chain == ".{$parent}") { // case-sensitive - return "{$parent}.{$match['column']}"; - } - - preg_match_all('~ - (?(DEFINE) - (?P [a-z][\w_]* ) - ) - (?P [.:])?(?P (?&word))(\((?P (?&word))\))? - ~xi', $chain, $keyMatches, PREG_SET_ORDER); - - foreach ($keyMatches as $keyMatch) { - if ($keyMatch['del'] === ':') { - if (isset($keyMatch['throughColumn'])) { - $table = $keyMatch['key']; - list(, $primary) = $this->databaseReflection->getBelongsToReference($table, $keyMatch['throughColumn']); - } else { - list($table, $primary) = $this->databaseReflection->getHasManyReference($parent, $keyMatch['key']); - } - $column = $this->databaseReflection->getPrimary($parent); - } else { - list($table, $column) = $this->databaseReflection->getBelongsToReference($parent, $keyMatch['key']); - $primary = $this->databaseReflection->getPrimary($table); - } - - $joins[$table . $column] = array($table, $keyMatch['key'] ?: $table, $parentAlias, $column, $primary); - $parent = $table; - $parentAlias = $keyMatch['key']; - } - - return ($keyMatch['key'] ?: $table) . ".{$match['column']}"; - } - - - protected function buildQueryJoins(array $joins) - { - $return = ''; - foreach ($joins as $join) { - list($joinTable, $joinAlias, $table, $tableColumn, $joinColumn) = $join; - - $return .= - " LEFT JOIN {$joinTable}" . ($joinTable !== $joinAlias ? " AS {$joinAlias}" : '') . - " ON {$table}.{$tableColumn} = {$joinAlias}.{$joinColumn}"; - } - - return $return; - } - - - protected function buildConditions() - { - return $this->where ? ' WHERE (' . implode(') AND (', $this->where) . ')' : ''; - } - - - protected function buildQueryEnd() - { - $return = ''; - if ($this->group) { - $return .= ' GROUP BY '. $this->group; - } - if ($this->having) { - $return .= ' HAVING '. $this->having; - } - if ($this->order) { - $return .= ' ORDER BY ' . implode(', ', $this->order); - } - return $return; - } - - - protected function tryDelimite($s) - { - $driver = $this->driver; - return preg_replace_callback('#(?<=[^\w`"\[]|^)[a-z_][a-z0-9_]*(?=[^\w`"(\]]|\z)#i', function($m) use ($driver) { - return strtoupper($m[0]) === $m[0] ? $m[0] : $driver->delimite($m[0]); - }, $s); - } - - - protected function addWhereComposition(array $columns, array $parameters) - { - if ($this->driver->isSupported(ISupplementalDriver::SUPPORT_MULTI_COLUMN_AS_OR_COND)) { - $conditionFragment = '(' . implode(' = ? AND ', $columns) . ' = ?) OR '; - $condition = substr(str_repeat($conditionFragment, count($parameters)), 0, -4); - return $this->addWhere($condition, Nette\Utils\Arrays::flatten($parameters)); - } else { - return $this->addWhere('(' . implode(', ', $columns) . ') IN', $parameters); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/CompilerExtension.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/CompilerExtension.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/CompilerExtension.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/CompilerExtension.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -compiler = $compiler; - $this->name = $name; - return $this; - } - - - /** - * Returns extension configuration. - * @param array default unexpanded values. - * @return array - */ - public function getConfig(array $defaults = NULL) - { - $config = $this->compiler->getConfig(); - $config = isset($config[$this->name]) ? $config[$this->name] : array(); - unset($config['services'], $config['factories']); - return Config\Helpers::merge($config, $this->compiler->getContainerBuilder()->expand($defaults)); - } - - - /** - * @return ContainerBuilder - */ - public function getContainerBuilder() - { - return $this->compiler->getContainerBuilder(); - } - - - /** - * Reads configuration from file. - * @param string file name - * @return array - */ - public function loadFromFile($file) - { - $loader = new Config\Loader; - $res = $loader->load($file); - $container = $this->compiler->getContainerBuilder(); - foreach ($loader->getDependencies() as $file) { - $container->addDependency($file); - } - return $res; - } - - - /** - * Prepend extension name to identifier or service name. - * @param string - * @return string - */ - public function prefix($id) - { - return substr_replace($id, $this->name . '.', substr($id, 0, 1) === '@' ? 1 : 0, 0); - } - - - /** - * Processes configuration data. Intended to be overridden by descendant. - * @return void - */ - public function loadConfiguration() - { - } - - - /** - * Adjusts DI container before is compiled to PHP class. Intended to be overridden by descendant. - * @return void - */ - public function beforeCompile() - { - } - - - /** - * Adjusts DI container compiled to PHP class. Intended to be overridden by descendant. - * @return void - */ - public function afterCompile(Nette\PhpGenerator\ClassType $class) - { - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Compiler.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Compiler.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Compiler.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Compiler.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,366 +0,0 @@ - 1, 'factories' => 1, 'parameters' => 1); - - - /** - * Add custom configurator extension. - * @return self - */ - public function addExtension($name, CompilerExtension $extension) - { - if (isset(self::$reserved[$name])) { - throw new Nette\InvalidArgumentException("Name '$name' is reserved."); - } - $this->extensions[$name] = $extension->setCompiler($this, $name); - return $this; - } - - - /** - * @return array - */ - public function getExtensions($type = NULL) - { - return $type - ? array_filter($this->extensions, function($item) use ($type) { return $item instanceof $type; }) - : $this->extensions; - } - - - /** - * @return ContainerBuilder - */ - public function getContainerBuilder() - { - return $this->builder; - } - - - /** - * Returns configuration. - * @return array - */ - public function getConfig() - { - return $this->config; - } - - - /** - * @return string - */ - public function compile(array $config, $className, $parentName) - { - $this->config = $config; - $this->builder = new ContainerBuilder; - $this->processParameters(); - $this->processExtensions(); - $this->processServices(); - return $this->generateCode($className, $parentName); - } - - - public function processParameters() - { - if (isset($this->config['parameters'])) { - $this->builder->parameters = Helpers::expand($this->config['parameters'], $this->config['parameters'], TRUE); - } - } - - - public function processExtensions() - { - for ($i = 0; $slice = array_slice($this->extensions, $i, 1, TRUE); $i++) { - $name = key($slice); - if (isset($this->config[$name])) { - $this->config[$name] = $this->builder->expand($this->config[$name]); - } - $this->extensions[$name]->loadConfiguration(); - } - - if ($extra = array_diff_key($this->config, self::$reserved, $this->extensions)) { - $extra = implode("', '", array_keys($extra)); - throw new Nette\InvalidStateException("Found sections '$extra' in configuration, but corresponding extensions are missing."); - } - } - - - public function processServices() - { - $this->parseServices($this->builder, $this->config); - - foreach ($this->extensions as $name => $extension) { - if (isset($this->config[$name])) { - $this->parseServices($this->builder, $this->config[$name], $name); - } - } - } - - - public function generateCode($className, $parentName) - { - foreach ($this->extensions as $extension) { - $extension->beforeCompile(); - $this->builder->addDependency(Nette\Reflection\ClassType::from($extension)->getFileName()); - } - - $classes = $this->builder->generateClasses($className, $parentName); - $classes[0]->addMethod('initialize'); - - foreach ($this->extensions as $extension) { - $extension->afterCompile($classes[0]); - } - return implode("\n\n\n", $classes); - } - - - /********************* tools ****************d*g**/ - - - /** - * Parses section 'services' from (unexpanded) configuration file. - * @return void - */ - public static function parseServices(ContainerBuilder $builder, array $config, $namespace = NULL) - { - if (!empty($config['factories'])) { - trigger_error("Section 'factories' is deprecated, move definitions to section 'services' and append key 'autowired: no'.", E_USER_DEPRECATED); - } - - $services = isset($config['services']) ? $config['services'] : array(); - $factories = isset($config['factories']) ? $config['factories'] : array(); - $all = array_merge($services, $factories); - - $depths = array(); - foreach ($all as $name => $def) { - $path = array(); - while (Config\Helpers::isInheriting($def)) { - $path[] = $def; - $def = $all[$def[Config\Helpers::EXTENDS_KEY]]; - if (in_array($def, $path, TRUE)) { - throw new ServiceCreationException("Circular reference detected for service '$name'."); - } - } - $depths[$name] = count($path); - } - array_multisort($depths, $all); - - foreach ($all as $origName => $def) { - if ((string) (int) $origName === (string) $origName) { - $name = count($builder->getDefinitions()) - . preg_replace('#\W+#', '_', $def instanceof \stdClass ? ".$def->value" : (is_scalar($def) ? ".$def" : '')); - } elseif (array_key_exists($origName, $services) && array_key_exists($origName, $factories)) { - throw new ServiceCreationException("It is not allowed to use services and factories with the same name: '$origName'."); - } else { - $name = ($namespace ? $namespace . '.' : '') . strtr($origName, '\\', '_'); - } - - $params = $builder->parameters; - if (is_array($def) && isset($def['parameters'])) { - foreach ((array) $def['parameters'] as $k => $v) { - $v = explode(' ', is_int($k) ? $v : $k); - $params[end($v)] = $builder::literal('$' . end($v)); - } - } - $def = Helpers::expand($def, $params); - - if (($parent = Config\Helpers::takeParent($def)) && $parent !== $name) { - $builder->removeDefinition($name); - $definition = $builder->addDefinition( - $name, - $parent === Config\Helpers::OVERWRITE ? NULL : unserialize(serialize($builder->getDefinition($parent))) // deep clone - ); - } elseif ($builder->hasDefinition($name)) { - $definition = $builder->getDefinition($name); - } else { - $definition = $builder->addDefinition($name); - } - - try { - static::parseService($definition, $def); - } catch (\Exception $e) { - throw new ServiceCreationException("Service '$name': " . $e->getMessage(), NULL, $e); - } - - if (array_key_exists($origName, $factories)) { - $definition->setAutowired(FALSE); - } - - if ($definition->class === 'self') { - $definition->class = $origName; - trigger_error("Replace service definition '$origName: self' with '- $origName'.", E_USER_DEPRECATED); - } - if ($definition->factory && $definition->factory->entity === 'self') { - $definition->factory->entity = $origName; - trigger_error("Replace service definition '$origName: self' with '- $origName'.", E_USER_DEPRECATED); - } - } - } - - - /** - * Parses single service from configuration file. - * @return void - */ - public static function parseService(ServiceDefinition $definition, $config) - { - if ($config === NULL) { - return; - - } elseif (is_string($config) && interface_exists($config)) { - $config = array('class' => NULL, 'implement' => $config); - - } elseif ($config instanceof \stdClass && is_string($config->value) && interface_exists($config->value)) { - $config = array('class' => NULL, 'implement' => $config->value, 'factory' => array_shift($config->attributes)); - - } elseif (!is_array($config) || isset($config[0], $config[1])) { - $config = array('class' => NULL, 'create' => $config); - } - - if (array_key_exists('factory', $config)) { - $config['create'] = $config['factory']; - unset($config['factory']); - }; - - $known = array('class', 'create', 'arguments', 'setup', 'autowired', 'inject', 'parameters', 'implement', 'run', 'tags'); - if ($error = array_diff(array_keys($config), $known)) { - throw new Nette\InvalidStateException(sprintf("Unknown or deprecated key '%s' in definition of service.", implode("', '", $error))); - } - - $arguments = array(); - if (array_key_exists('arguments', $config)) { - Validators::assertField($config, 'arguments', 'array'); - $arguments = self::filterArguments($config['arguments']); - $definition->setArguments($arguments); - } - - if (array_key_exists('class', $config) || array_key_exists('create', $config)) { - $definition->class = NULL; - $definition->factory = NULL; - } - - if (array_key_exists('class', $config)) { - Validators::assertField($config, 'class', 'string|stdClass|null'); - if ($config['class'] instanceof \stdClass) { - $definition->setClass($config['class']->value, self::filterArguments($config['class']->attributes)); - } else { - $definition->setClass($config['class'], $arguments); - } - } - - if (array_key_exists('create', $config)) { - Validators::assertField($config, 'create', 'callable|stdClass|null'); - if ($config['create'] instanceof \stdClass) { - $definition->setFactory($config['create']->value, self::filterArguments($config['create']->attributes)); - } else { - $definition->setFactory($config['create'], $arguments); - } - } - - if (isset($config['setup'])) { - if (Config\Helpers::takeParent($config['setup'])) { - $definition->setup = array(); - } - Validators::assertField($config, 'setup', 'list'); - foreach ($config['setup'] as $id => $setup) { - Validators::assert($setup, 'callable|stdClass', "setup item #$id"); - if ($setup instanceof \stdClass) { - Validators::assert($setup->value, 'callable', "setup item #$id"); - $definition->addSetup($setup->value, self::filterArguments($setup->attributes)); - } else { - $definition->addSetup($setup); - } - } - } - - if (isset($config['parameters'])) { - Validators::assertField($config, 'parameters', 'array'); - $definition->setParameters($config['parameters']); - } - - if (isset($config['implement'])) { - Validators::assertField($config, 'implement', 'string'); - $definition->setImplement($config['implement']); - $definition->setAutowired(TRUE); - } - - if (isset($config['autowired'])) { - Validators::assertField($config, 'autowired', 'bool'); - $definition->setAutowired($config['autowired']); - } - - if (isset($config['inject'])) { - Validators::assertField($config, 'inject', 'bool'); - $definition->setInject($config['inject']); - } - - if (isset($config['run'])) { - $config['tags']['run'] = (bool) $config['run']; - } - - if (isset($config['tags'])) { - Validators::assertField($config, 'tags', 'array'); - if (Config\Helpers::takeParent($config['tags'])) { - $definition->tags = array(); - } - foreach ($config['tags'] as $tag => $attrs) { - if (is_int($tag) && is_string($attrs)) { - $definition->addTag($attrs); - } else { - $definition->addTag($tag, $attrs); - } - } - } - } - - - /** - * Removes ... and replaces entities with Statement. - * @return array - */ - public static function filterArguments(array $args) - { - foreach ($args as $k => $v) { - if ($v === '...') { - unset($args[$k]); - } elseif ($v instanceof \stdClass && isset($v->value, $v->attributes)) { - $args[$k] = new Statement($v->value, self::filterArguments($v->attributes)); - } - } - return $args; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Config/Adapters/IniAdapter.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Config/Adapters/IniAdapter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Config/Adapters/IniAdapter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Config/Adapters/IniAdapter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ - $secData) { - if (is_array($secData)) { // is section? - if (substr($secName, -1) === self::RAW_SECTION) { - $secName = substr($secName, 0, -1); - } else { // process key nesting separator (key1.key2.key3) - $tmp = array(); - foreach ($secData as $key => $val) { - $cursor = & $tmp; - $key = str_replace(self::ESCAPED_KEY_SEPARATOR, "\xFF", $key); - foreach (explode(self::KEY_SEPARATOR, $key) as $part) { - $part = str_replace("\xFF", self::KEY_SEPARATOR, $part); - if (!isset($cursor[$part]) || is_array($cursor[$part])) { - $cursor = & $cursor[$part]; - } else { - throw new Nette\InvalidStateException("Invalid key '$key' in section [$secName] in file '$file'."); - } - } - $cursor = $val; - } - $secData = $tmp; - } - - $parts = explode(self::INHERITING_SEPARATOR, $secName); - if (count($parts) > 1) { - $secName = trim($parts[0]); - $secData[Helpers::EXTENDS_KEY] = trim($parts[1]); - } - } - - $cursor = & $data; // nesting separator in section name - foreach (explode(self::KEY_SEPARATOR, $secName) as $part) { - if (!isset($cursor[$part]) || is_array($cursor[$part])) { - $cursor = & $cursor[$part]; - } else { - throw new Nette\InvalidStateException("Invalid section [$secName] in file '$file'."); - } - } - - if (is_array($secData) && is_array($cursor)) { - $secData = Helpers::merge($secData, $cursor); - } - - $cursor = $secData; - } - - return $data; - } - - - /** - * Generates configuration in INI format. - * @return string - */ - public function dump(array $data) - { - $output = array(); - foreach ($data as $name => $secData) { - if (!is_array($secData)) { - $output = array(); - self::build($data, $output, ''); - break; - } - if ($parent = Helpers::takeParent($secData)) { - $output[] = "[$name " . self::INHERITING_SEPARATOR . " $parent]"; - } else { - $output[] = "[$name]"; - } - self::build($secData, $output, ''); - $output[] = ''; - } - return "; generated by Nette\n\n" . implode(PHP_EOL, $output); - } - - - /** - * Recursive builds INI list. - * @return void - */ - private static function build($input, & $output, $prefix) - { - foreach ($input as $key => $val) { - $key = str_replace(self::KEY_SEPARATOR, self::ESCAPED_KEY_SEPARATOR, $key); - if (is_array($val)) { - self::build($val, $output, $prefix . $key . self::KEY_SEPARATOR); - - } elseif (is_bool($val)) { - $output[] = "$prefix$key = " . ($val ? 'true' : 'false'); - - } elseif (is_numeric($val)) { - $output[] = "$prefix$key = $val"; - - } elseif (is_string($val)) { - $output[] = "$prefix$key = \"$val\""; - - } else { - throw new Nette\InvalidArgumentException(sprintf("The '%s' item must be scalar or array, %s given.", $prefix . $key, gettype($val))); - } - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Config/Adapters/NeonAdapter.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Config/Adapters/NeonAdapter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Config/Adapters/NeonAdapter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Config/Adapters/NeonAdapter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -process((array) Neon::decode(file_get_contents($file))); - } - - - private function process(array $arr) - { - $res = array(); - foreach ($arr as $key => $val) { - if (substr($key, -1) === self::PREVENT_MERGING) { - if (!is_array($val) && $val !== NULL) { - throw new Nette\InvalidStateException("Replacing operator is available only for arrays, item '$key' is not array."); - } - $key = substr($key, 0, -1); - $val[Helpers::EXTENDS_KEY] = Helpers::OVERWRITE; - - } elseif (preg_match('#^(\S+)\s+' . self::INHERITING_SEPARATOR . '\s+(\S+)\z#', $key, $matches)) { - if (!is_array($val) && $val !== NULL) { - throw new Nette\InvalidStateException("Inheritance operator is available only for arrays, item '$key' is not array."); - } - list(, $key, $val[Helpers::EXTENDS_KEY]) = $matches; - if (isset($res[$key])) { - throw new Nette\InvalidStateException("Duplicated key '$key'."); - } - } - - if (is_array($val)) { - $val = $this->process($val); - } elseif ($val instanceof Nette\Utils\NeonEntity) { - $val = (object) array('value' => $val->value, 'attributes' => $this->process($val->attributes)); - } - $res[$key] = $val; - } - return $res; - } - - - /** - * Generates configuration in NEON format. - * @return string - */ - public function dump(array $data) - { - $tmp = array(); - foreach ($data as $name => $secData) { - if ($parent = Helpers::takeParent($secData)) { - $name .= ' ' . self::INHERITING_SEPARATOR . ' ' . $parent; - } - $tmp[$name] = $secData; - } - return "# generated by Nette\n\n" . Neon::encode($tmp, Neon::BLOCK); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Config/Adapters/PhpAdapter.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Config/Adapters/PhpAdapter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Config/Adapters/PhpAdapter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Config/Adapters/PhpAdapter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ - $val) { - if (is_int($key)) { - $right[] = $val; - } else { - if (is_array($val) && isset($val[self::EXTENDS_KEY])) { - if ($val[self::EXTENDS_KEY] === self::OVERWRITE) { - unset($val[self::EXTENDS_KEY]); - } - } elseif (isset($right[$key])) { - $val = static::merge($val, $right[$key]); - } - $right[$key] = $val; - } - } - return $right; - - } elseif ($left === NULL && is_array($right)) { - return $right; - - } else { - return $left; - } - } - - - /** - * Finds out and removes information about the parent. - * @return mixed - */ - public static function takeParent(& $data) - { - if (is_array($data) && isset($data[self::EXTENDS_KEY])) { - $parent = $data[self::EXTENDS_KEY]; - unset($data[self::EXTENDS_KEY]); - return $parent; - } - } - - - /** - * @return bool - */ - public static function isOverwriting(& $data) - { - return is_array($data) && isset($data[self::EXTENDS_KEY]) && $data[self::EXTENDS_KEY] === self::OVERWRITE; - } - - - /** - * @return bool - */ - public static function isInheriting(& $data) - { - return is_array($data) && isset($data[self::EXTENDS_KEY]) && $data[self::EXTENDS_KEY] !== self::OVERWRITE; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Config/IAdapter.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Config/IAdapter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Config/IAdapter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Config/IAdapter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ - 'Nette\DI\Config\Adapters\PhpAdapter', - 'ini' => 'Nette\DI\Config\Adapters\IniAdapter', - 'neon' => 'Nette\DI\Config\Adapters\NeonAdapter', - ); - - private $dependencies = array(); - - - /** - * Reads configuration from file. - * @param string file name - * @param string optional section to load - * @return array - */ - public function load($file, $section = NULL) - { - if (!is_file($file) || !is_readable($file)) { - throw new Nette\FileNotFoundException("File '$file' is missing or is not readable."); - } - $this->dependencies[] = $file = realpath($file); - $data = $this->getAdapter($file)->load($file); - - if ($section) { - if (isset($data[self::INCLUDES_KEY])) { - throw new Nette\InvalidStateException("Section 'includes' must be placed under some top section in file '$file'."); - } - $data = $this->getSection($data, $section, $file); - } - - // include child files - $merged = array(); - if (isset($data[self::INCLUDES_KEY])) { - Validators::assert($data[self::INCLUDES_KEY], 'list', "section 'includes' in file '$file'"); - foreach ($data[self::INCLUDES_KEY] as $include) { - $merged = Helpers::merge($this->load(dirname($file) . '/' . $include), $merged); - } - } - unset($data[self::INCLUDES_KEY]); - - return Helpers::merge($data, $merged); - } - - - /** - * Save configuration to file. - * @param array - * @param string file - * @return void - */ - public function save($data, $file) - { - if (file_put_contents($file, $this->getAdapter($file)->dump($data)) === FALSE) { - throw new Nette\IOException("Cannot write file '$file'."); - } - } - - - /** - * Returns configuration files. - * @return array - */ - public function getDependencies() - { - return array_unique($this->dependencies); - } - - - /** - * Registers adapter for given file extension. - * @param string file extension - * @param string|Nette\DI\Config\IAdapter - * @return self - */ - public function addAdapter($extension, $adapter) - { - $this->adapters[strtolower($extension)] = $adapter; - return $this; - } - - - /** @return IAdapter */ - private function getAdapter($file) - { - $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION)); - if (!isset($this->adapters[$extension])) { - throw new Nette\InvalidArgumentException("Unknown file extension '$file'."); - } - return is_object($this->adapters[$extension]) ? $this->adapters[$extension] : new $this->adapters[$extension]; - } - - - private function getSection(array $data, $key, $file) - { - Validators::assertField($data, $key, 'array|null', "section '%' in file '$file'"); - $item = $data[$key]; - if ($parent = Helpers::takeParent($item)) { - $item = Helpers::merge($item, $this->getSection($data, $parent, $file)); - } - return $item; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/ContainerBuilder.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/ContainerBuilder.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/ContainerBuilder.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/ContainerBuilder.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,717 +0,0 @@ -definitions[$name])) { - throw new Nette\InvalidStateException("Service '$name' has already been added."); - } - return $this->definitions[$name] = $definition ?: new ServiceDefinition; - } - - - /** - * Removes the specified service definition. - * @param string - * @return void - */ - public function removeDefinition($name) - { - unset($this->definitions[$name]); - } - - - /** - * Gets the service definition. - * @param string - * @return ServiceDefinition - */ - public function getDefinition($name) - { - if (!isset($this->definitions[$name])) { - throw new MissingServiceException("Service '$name' not found."); - } - return $this->definitions[$name]; - } - - - /** - * Gets all service definitions. - * @return array - */ - public function getDefinitions() - { - return $this->definitions; - } - - - /** - * Does the service definition exist? - * @param string - * @return bool - */ - public function hasDefinition($name) - { - return isset($this->definitions[$name]); - } - - - /********************* class resolving ****************d*g**/ - - - /** - * Resolves service name by type. - * @param string class or interface - * @return string service name or NULL - * @throws ServiceCreationException - */ - public function getByType($class) - { - if ($this->currentService !== NULL && Reflection\ClassType::from($this->definitions[$this->currentService]->class)->is($class)) { - return $this->currentService; - } - - $lower = ltrim(strtolower($class), '\\'); - if (!isset($this->classes[$lower])) { - return; - - } elseif (count($this->classes[$lower]) === 1) { - return $this->classes[$lower][0]; - - } else { - throw new ServiceCreationException("Multiple services of type $class found: " . implode(', ', $this->classes[$lower])); - } - } - - - /** - * Gets the service objects of the specified tag. - * @param string - * @return array of [service name => tag attributes] - */ - public function findByTag($tag) - { - $found = array(); - foreach ($this->definitions as $name => $def) { - if (isset($def->tags[$tag])) { - $found[$name] = $def->tags[$tag]; - } - } - return $found; - } - - - /** - * Creates a list of arguments using autowiring. - * @return array - */ - public function autowireArguments($class, $method, array $arguments) - { - $rc = Reflection\ClassType::from($class); - if (!$rc->hasMethod($method)) { - if (!Nette\Utils\Arrays::isList($arguments)) { - throw new ServiceCreationException("Unable to pass specified arguments to $class::$method()."); - } - return $arguments; - } - - $rm = $rc->getMethod($method); - if (!$rm->isPublic()) { - throw new ServiceCreationException("$rm is not callable."); - } - $this->addDependency($rm->getFileName()); - return Helpers::autowireArguments($rm, $arguments, $this); - } - - - /** - * Generates $dependencies, $classes and normalizes class names. - * @return array - */ - public function prepareClassList() - { - $this->classes = FALSE; - - // prepare generated factories - foreach ($this->definitions as $name => $def) { - if (!$def->implement) { - continue; - } - - if (!interface_exists($def->implement)) { - throw new ServiceCreationException("Interface $def->implement used in service '$name' has not been found."); - } - $rc = Reflection\ClassType::from($def->implement); - $method = $rc->hasMethod('create') ? $rc->getMethod('create') : ($rc->hasMethod('get') ? $rc->getMethod('get') : NULL); - if (count($rc->getMethods()) !== 1 || !$method || $method->isStatic()) { - throw new ServiceCreationException("Interface $def->implement used in service '$name' must have just one non-static method create() or get()."); - } - $def->implement = $rc->getName(); - $def->implementType = $rc->hasMethod('create') ? 'create' : 'get'; - - if (!$def->class && empty($def->factory->entity)) { - $returnType = $method->getAnnotation('return'); - if (!$returnType) { - throw new ServiceCreationException("Method $method used in service '$name' has not @return annotation."); - } - - $returnType = Reflection\AnnotationsParser::expandClassName(preg_replace('#[|\s].*#', '', $returnType), $rc); - if (!class_exists($returnType)) { - throw new ServiceCreationException("Please check a @return annotation of the $method method used in service '$name'. Class '$returnType' cannot be found."); - } - $def->setClass($returnType); - } - - if ($method->getName() === 'get') { - if ($method->getParameters()) { - throw new ServiceCreationException("Method $method used in service '$name' must have no arguments."); - } - if (empty($def->factory->entity)) { - $def->setFactory('@\\' . ltrim($def->class, '\\')); - } elseif (!$this->getServiceName($def->factory->entity)) { - throw new ServiceCreationException("Invalid factory in service '$name' definition."); - } - } - - if (!$def->parameters) { - foreach ($method->getParameters() as $param) { - $paramDef = ($param->isArray() ? 'array' : $param->getClassName()) . ' ' . $param->getName(); - if ($param->isOptional()) { - $def->parameters[$paramDef] = $param->getDefaultValue(); - } else { - $def->parameters[] = $paramDef; - } - } - } - } - - // complete class-factory pairs - foreach ($this->definitions as $name => $def) { - if (!$def->factory || !$def->factory->entity) { - if (!$def->class) { - throw new ServiceCreationException("Class and factory are missing in service '$name' definition."); - } - if ($def->factory) { - $def->factory->entity = $def->class; - } else { - $def->factory = new Statement($def->class); - } - } - } - - // check if services are instantiable - foreach ($this->definitions as $name => $def) { - $factory = $def->factory->entity = $this->normalizeEntity($def->factory->entity); - - if (is_string($factory) && preg_match('#^[\w\\\\]+\z#', $factory) && $factory !== self::THIS_SERVICE) { - if (!class_exists($factory) || !Reflection\ClassType::from($factory)->isInstantiable()) { - throw new ServiceCreationException("Class $factory used in service '$name' has not been found or is not instantiable."); - } - } - } - - // complete classes - foreach ($this->definitions as $name => $def) { - $this->resolveClass($name); - - if (!$def->class) { - continue; - } elseif (!class_exists($def->class) && !interface_exists($def->class)) { - throw new ServiceCreationException("Class or interface $def->class used in service '$name' has not been found."); - } else { - $def->class = Reflection\ClassType::from($def->class)->getName(); - } - } - - // build auto-wiring list - $this->classes = array(); - foreach ($this->definitions as $name => $def) { - $class = $def->implement ?: $def->class; - if ($def->autowired && $class) { - foreach (class_parents($class) + class_implements($class) + array($class) as $parent) { - $this->classes[strtolower($parent)][] = (string) $name; - } - } - } - - foreach ($this->classes as $class => $foo) { - $this->addDependency(Reflection\ClassType::from($class)->getFileName()); - } - } - - - private function resolveClass($name, $recursive = array()) - { - if (isset($recursive[$name])) { - throw new ServiceCreationException(sprintf('Circular reference detected for services: %s.', implode(', ', array_keys($recursive)))); - } - $recursive[$name] = TRUE; - - $def = $this->definitions[$name]; - $factory = $def->factory->entity; - - if ($def->class) { - return $def->class; - - } elseif (is_array($factory)) { // method calling - if ($service = $this->getServiceName($factory[0])) { - if (Strings::contains($service, '\\')) { // @\Class - $factory[0] = $service; - } else { - $factory[0] = $this->resolveClass($service, $recursive); - if (!$factory[0]) { - return; - } - if ($this->definitions[$service]->implement && $factory[1] === 'create') { - return $def->class = $factory[0]; - } - } - } - try { - $reflection = Nette\Utils\Callback::toReflection($factory); - } catch (\ReflectionException $e) { - $name = array_slice(array_keys($recursive), -1); - throw new ServiceCreationException("Factory '" . Nette\Utils\Callback::toString($factory) . "' used in service '$name[0]' is not callable."); - } - $def->class = preg_replace('#[|\s].*#', '', $reflection->getAnnotation('return')); - if ($def->class && $reflection instanceof \ReflectionMethod) { - $def->class = Reflection\AnnotationsParser::expandClassName($tmp = $def->class, $reflection->getDeclaringClass()); - if ($tmp !== $def->class && $tmp[0] !== '\\' && class_exists($tmp)) { - $def->class = $tmp; - trigger_error("You should use @return \\$tmp' in $reflection.", E_USER_WARNING); - } - } - - } elseif ($service = $this->getServiceName($factory)) { // alias or factory - if (!$def->implement) { - $def->autowired = FALSE; - } - if (Strings::contains($service, '\\')) { // @\Class - return $def->class = $service; - } - if ($this->definitions[$service]->implement) { - $def->autowired = FALSE; - } - return $def->class = $this->definitions[$service]->implement ?: $this->resolveClass($service, $recursive); - - } else { - return $def->class = $factory; // class name - } - } - - - /** - * Adds a file to the list of dependencies. - * @return self - */ - public function addDependency($file) - { - $this->dependencies[$file] = TRUE; - return $this; - } - - - /** - * Returns the list of dependent files. - * @return array - */ - public function getDependencies() - { - unset($this->dependencies[FALSE]); - return array_keys($this->dependencies); - } - - - /********************* code generator ****************d*g**/ - - - /** - * Generates PHP classes. First class is the container. - * @return Nette\PhpGenerator\ClassType[] - */ - public function generateClasses($className = 'Container', $parentName = 'Nette\DI\Container') - { - unset($this->definitions[self::THIS_CONTAINER]); - $this->addDefinition(self::THIS_CONTAINER)->setClass('Nette\DI\Container'); - - $this->generatedClasses = array(); - $this->prepareClassList(); - - $containerClass = $this->generatedClasses[] = new Nette\PhpGenerator\ClassType($className); - $containerClass->setExtends($parentName); - $containerClass->addMethod('__construct') - ->addBody('parent::__construct(?);', array($this->parameters)); - - $definitions = $this->definitions; - ksort($definitions); - - $meta = $containerClass->addProperty('meta', array()) - ->setVisibility('protected') - ->setValue(array(Container::TYPES => $this->classes)); - - foreach ($definitions as $name => $def) { - foreach ($def->tags as $tag => $value) { - $meta->value[Container::TAGS][$tag][$name] = $value; - } - } - - foreach ($definitions as $name => $def) { - try { - $name = (string) $name; - $methodName = Container::getMethodName($name); - if (!PhpHelpers::isIdentifier($methodName)) { - throw new ServiceCreationException('Name contains invalid characters.'); - } - $containerClass->addMethod($methodName) - ->addDocument('@return ' . ($def->implement ?: $def->class)) - ->setBody($name === self::THIS_CONTAINER ? 'return $this;' : $this->generateService($name)) - ->setParameters($def->implement ? array() : $this->convertParameters($def->parameters)); - } catch (\Exception $e) { - throw new ServiceCreationException("Service '$name': " . $e->getMessage(), NULL, $e); - } - } - - return $this->generatedClasses; - } - - - /** - * Generates body of service method. - * @return string - */ - private function generateService($name) - { - $this->currentService = NULL; - $def = $this->definitions[$name]; - - $serviceRef = $this->getServiceName($def->factory->entity); - $factory = $serviceRef && !$def->factory->arguments && !$def->setup && $def->implementType !== 'create' - ? new Statement(array('@' . ContainerBuilder::THIS_CONTAINER, 'getService'), array($serviceRef)) - : $def->factory; - - $code = '$service = ' . $this->formatStatement($factory) . ";\n"; - $this->currentService = $name; - - if ($def->class && $def->class !== $def->factory->entity && !$serviceRef) { - $code .= PhpHelpers::formatArgs("if (!\$service instanceof $def->class) {\n" - . "\tthrow new Nette\\UnexpectedValueException(?);\n}\n", - array("Unable to create service '$name', value returned by factory is not $def->class type.") - ); - } - - $setups = (array) $def->setup; - if ($def->inject && $def->class) { - $injects = array(); - foreach (Helpers::getInjectProperties(Reflection\ClassType::from($def->class)) as $property => $type) { - $injects[] = new Statement('$' . $property, array('@\\' . ltrim($type, '\\'))); - } - - foreach (get_class_methods($def->class) as $method) { - if (substr($method, 0, 6) === 'inject') { - $injects[] = new Statement($method); - } - } - - foreach ($injects as $inject) { - foreach ($setups as $key => $setup) { - if ($setup->entity === $inject->entity) { - $inject = $setup; - unset($setups[$key]); - } - } - array_unshift($setups, $inject); - } - } - - foreach ($setups as $setup) { - if (is_string($setup->entity) && strpbrk($setup->entity, ':@?') === FALSE) { // auto-prepend @self - $setup->entity = array('@self', $setup->entity); - } - $code .= $this->formatStatement($setup) . ";\n"; - } - - $code .= 'return $service;'; - - if (!$def->implement) { - return $code; - } - - $factoryClass = $this->generatedClasses[] = new Nette\PhpGenerator\ClassType; - $factoryClass->setName(str_replace(array('\\', '.'), '_', "{$this->generatedClasses[0]->name}_{$def->implement}Impl_{$name}")) - ->addImplement($def->implement) - ->setFinal(TRUE); - - $factoryClass->addProperty('container') - ->setVisibility('private'); - - $factoryClass->addMethod('__construct') - ->addBody('$this->container = $container;') - ->addParameter('container') - ->setTypeHint('Nette\DI\Container'); - - $factoryClass->addMethod($def->implementType) - ->setParameters($this->convertParameters($def->parameters)) - ->setBody(str_replace('$this', '$this->container', $code)); - - return "return new {$factoryClass->name}(\$this);"; - } - - - /** - * Converts parameters from ServiceDefinition to PhpGenerator. - * @return Nette\PhpGenerator\Parameter[] - */ - private function convertParameters(array $parameters) - { - $res = array(); - foreach ($parameters as $k => $v) { - $tmp = explode(' ', is_int($k) ? $v : $k); - $param = $res[] = new Nette\PhpGenerator\Parameter; - $param->setName(end($tmp)); - if (!is_int($k)) { - $param = $param->setOptional(TRUE)->setDefaultValue($v); - } - if (isset($tmp[1])) { - $param->setTypeHint($tmp[0]); - } - } - return $res; - } - - - /** - * Formats PHP code for class instantiating, function calling or property setting in PHP. - * @return string - * @internal - */ - public function formatStatement(Statement $statement) - { - $entity = $this->normalizeEntity($statement->entity); - $arguments = $statement->arguments; - - if (is_string($entity) && Strings::contains($entity, '?')) { // PHP literal - return $this->formatPhp($entity, $arguments); - - } elseif ($service = $this->getServiceName($entity)) { // factory calling - $params = array(); - foreach ($this->definitions[$service]->parameters as $k => $v) { - $params[] = preg_replace('#\w+\z#', '\$$0', (is_int($k) ? $v : $k)) . (is_int($k) ? '' : ' = ' . PhpHelpers::dump($v)); - } - $rm = new Reflection\GlobalFunction(create_function(implode(', ', $params), '')); - $arguments = Helpers::autowireArguments($rm, $arguments, $this); - return $this->formatPhp('$this->?(?*)', array(Container::getMethodName($service), $arguments)); - - } elseif ($entity === 'not') { // operator - return $this->formatPhp('!?', array($arguments[0])); - - } elseif (is_string($entity)) { // class name - if ($constructor = Reflection\ClassType::from($entity)->getConstructor()) { - $this->addDependency($constructor->getFileName()); - $arguments = Helpers::autowireArguments($constructor, $arguments, $this); - } elseif ($arguments) { - throw new ServiceCreationException("Unable to pass arguments, class $entity has no constructor."); - } - return $this->formatPhp("new $entity" . ($arguments ? '(?*)' : ''), array($arguments)); - - } elseif (!Nette\Utils\Arrays::isList($entity) || count($entity) !== 2) { - throw new ServiceCreationException(sprintf('Expected class, method or property, %s given.', PhpHelpers::dump($entity))); - - } elseif ($entity[0] === '') { // globalFunc - return $this->formatPhp("$entity[1](?*)", array($arguments)); - - } elseif (Strings::contains($entity[1], '$')) { // property setter - Validators::assert($arguments, 'list:1', "setup arguments for '" . Nette\Utils\Callback::toString($entity) . "'"); - if ($this->getServiceName($entity[0])) { - return $this->formatPhp('?->? = ?', array($entity[0], substr($entity[1], 1), $arguments[0])); - } else { - return $this->formatPhp($entity[0] . '::$? = ?', array(substr($entity[1], 1), $arguments[0])); - } - - } elseif ($service = $this->getServiceName($entity[0])) { // service method - $class = $this->definitions[$service]->implement; - if (!$class || !method_exists($class, $entity[1])) { - $class = $this->definitions[$service]->class; - } - if ($class) { - $arguments = $this->autowireArguments($class, $entity[1], $arguments); - } - return $this->formatPhp('?->?(?*)', array($entity[0], $entity[1], $arguments)); - - } else { // static method - $arguments = $this->autowireArguments($entity[0], $entity[1], $arguments); - return $this->formatPhp("$entity[0]::$entity[1](?*)", array($arguments)); - } - } - - - /** - * Formats PHP statement. - * @return string - */ - public function formatPhp($statement, $args) - { - $that = $this; - array_walk_recursive($args, function(& $val) use ($that) { - if ($val instanceof Statement) { - $val = ContainerBuilder::literal($that->formatStatement($val)); - - } elseif ($val === $that) { - $val = ContainerBuilder::literal('$this'); - - } elseif ($val instanceof ServiceDefinition) { - $val = '@' . current(array_keys($that->definitions, $val, TRUE)); - - } elseif (is_string($val) && preg_match('#^[\w\\\\]*::[A-Z][A-Z0-9_]*\z#', $val, $m)) { - $val = ContainerBuilder::literal(ltrim($val, ':')); - } - - if (is_string($val) && substr($val, 0, 1) === '@') { - $pair = explode('::', $val, 2); - $name = $that->getServiceName($pair[0]); - if (isset($pair[1]) && preg_match('#^[A-Z][A-Z0-9_]*\z#', $pair[1], $m)) { - $val = $that->definitions[$name]->class . '::' . $pair[1]; - } else { - if ($name === ContainerBuilder::THIS_CONTAINER) { - $val = '$this'; - } elseif ($name === $that->currentService) { - $val = '$service'; - } else { - $val = $that->formatStatement(new Statement(array('@' . ContainerBuilder::THIS_CONTAINER, 'getService'), array($name))); - } - $val .= (isset($pair[1]) ? PhpHelpers::formatArgs('->?', array($pair[1])) : ''); - } - $val = ContainerBuilder::literal($val); - } - }); - return PhpHelpers::formatArgs($statement, $args); - } - - - /** - * Expands %placeholders% in strings. - * @return mixed - */ - public function expand($value) - { - return Helpers::expand($value, $this->parameters); - } - - - /** - * @return Nette\PhpGenerator\PhpLiteral - */ - public static function literal($phpCode) - { - return new Nette\PhpGenerator\PhpLiteral($phpCode); - } - - - /** @internal */ - public function normalizeEntity($entity) - { - if (is_string($entity) && Strings::contains($entity, '::') && !Strings::contains($entity, '?')) { // Class::method -> [Class, method] - $entity = explode('::', $entity); - } - - if (is_array($entity) && $entity[0] instanceof ServiceDefinition) { // [ServiceDefinition, ...] -> [@serviceName, ...] - $entity[0] = '@' . current(array_keys($this->definitions, $entity[0], TRUE)); - - } elseif ($entity instanceof ServiceDefinition) { // ServiceDefinition -> @serviceName - $entity = '@' . current(array_keys($this->definitions, $entity, TRUE)); - - } elseif (is_array($entity) && $entity[0] === $this) { // [$this, ...] -> [@container, ...] - $entity[0] = '@' . ContainerBuilder::THIS_CONTAINER; - } - return $entity; // Class, @service, [Class, member], [@service, member], [, globalFunc] - } - - - /** - * Converts @service or @\Class -> service name and checks its existence. - * @return string of FALSE, if argument is not service name - */ - public function getServiceName($arg) - { - if (!is_string($arg) || !preg_match('#^@[\w\\\\.].*\z#', $arg)) { - return FALSE; - } - $service = substr($arg, 1); - if ($service === self::THIS_SERVICE) { - $service = $this->currentService; - } - if (Strings::contains($service, '\\')) { - if ($this->classes === FALSE) { // may be disabled by prepareClassList - return $service; - } - $res = $this->getByType($service); - if (!$res) { - throw new ServiceCreationException("Reference to missing service of type $service."); - } - return $res; - } - if (!isset($this->definitions[$service])) { - throw new ServiceCreationException("Reference to missing service '$service'."); - } - return $service; - } - - - /** @deprecated */ - function generateClass() - { - throw new Nette\DeprecatedException(__METHOD__ . '() is deprecated; use generateClasses()[0] instead.'); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Container.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Container.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Container.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Container.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,337 +0,0 @@ -parameters = $params + $this->parameters; - } - - - /** - * @return array - */ - public function getParameters() - { - return $this->parameters; - } - - - /** - * Adds the service to the container. - * @param string - * @param object - * @return self - */ - public function addService($name, $service) - { - if (func_num_args() > 2) { - throw new Nette\DeprecatedException('Parameter $meta has been removed.'); - - } elseif (!is_string($name) || !$name) { - throw new Nette\InvalidArgumentException(sprintf('Service name must be a non-empty string, %s given.', gettype($name))); - - } elseif (isset($this->registry[$name])) { - throw new Nette\InvalidStateException("Service '$name' already exists."); - - } elseif (is_string($service) || is_array($service) || $service instanceof \Closure || $service instanceof Nette\Callback) { - trigger_error(sprintf('Passing factories to %s() is deprecated; pass the object itself.', __METHOD__), E_USER_DEPRECATED); - $service = is_string($service) && !preg_match('#\x00|:#', $service) ? new $service : call_user_func($service, $this); - } - - if (!is_object($service)) { - throw new Nette\InvalidArgumentException(sprintf('Service must be a object, %s given.', gettype($service))); - } - - $this->registry[$name] = $service; - return $this; - } - - - /** - * Removes the service from the container. - * @param string - * @return void - */ - public function removeService($name) - { - unset($this->registry[$name]); - } - - - /** - * Gets the service object by name. - * @param string - * @return object - * @throws MissingServiceException - */ - public function getService($name) - { - if (!isset($this->registry[$name])) { - $this->registry[$name] = $this->createService($name); - } - return $this->registry[$name]; - } - - - /** - * Does the service exist? - * @param string service name - * @return bool - */ - public function hasService($name) - { - return isset($this->registry[$name]) - || method_exists($this, $method = Container::getMethodName($name)) && $this->getReflection()->getMethod($method)->getName() === $method; - } - - - /** - * Is the service created? - * @param string service name - * @return bool - */ - public function isCreated($name) - { - if (!$this->hasService($name)) { - throw new MissingServiceException("Service '$name' not found."); - } - return isset($this->registry[$name]); - } - - - /** - * Creates new instance of the service. - * @param string service name - * @return object - * @throws MissingServiceException - */ - public function createService($name, array $args = array()) - { - $method = Container::getMethodName($name); - if (isset($this->creating[$name])) { - throw new Nette\InvalidStateException(sprintf('Circular reference detected for services: %s.', implode(', ', array_keys($this->creating)))); - - } elseif (!method_exists($this, $method) || $this->getReflection()->getMethod($method)->getName() !== $method) { - throw new MissingServiceException("Service '$name' not found."); - } - - $this->creating[$name] = TRUE; - try { - $service = call_user_func_array(array($this, $method), $args); - } catch (\Exception $e) { - unset($this->creating[$name]); - throw $e; - } - unset($this->creating[$name]); - - if (!is_object($service)) { - throw new Nette\UnexpectedValueException("Unable to create service '$name', value returned by method $method() is not object."); - } - - return $service; - } - - - /** - * Resolves service by type. - * @param string class or interface - * @param bool throw exception if service doesn't exist? - * @return object service or NULL - * @throws MissingServiceException - */ - public function getByType($class, $need = TRUE) - { - $names = $this->findByType($class); - if (!$names) { - if ($need) { - throw new MissingServiceException("Service of type $class not found."); - } - } elseif (count($names) > 1) { - throw new MissingServiceException("Multiple services of type $class found: " . implode(', ', $names) . '.'); - } else { - return $this->getService($names[0]); - } - } - - - /** - * Gets the service names of the specified type. - * @param string - * @return string[] - */ - public function findByType($class) - { - $class = ltrim(strtolower($class), '\\'); - return isset($this->meta[self::TYPES][$class]) ? $this->meta[self::TYPES][$class] : array(); - } - - - /** - * Gets the service names of the specified tag. - * @param string - * @return array of [service name => tag attributes] - */ - public function findByTag($tag) - { - return isset($this->meta[self::TAGS][$tag]) ? $this->meta[self::TAGS][$tag] : array(); - } - - - /********************* autowiring ****************d*g**/ - - - /** - * Creates new instance using autowiring. - * @param string class - * @param array arguments - * @return object - * @throws Nette\InvalidArgumentException - */ - public function createInstance($class, array $args = array()) - { - $rc = Nette\Reflection\ClassType::from($class); - if (!$rc->isInstantiable()) { - throw new ServiceCreationException("Class $class is not instantiable."); - - } elseif ($constructor = $rc->getConstructor()) { - return $rc->newInstanceArgs(Helpers::autowireArguments($constructor, $args, $this)); - - } elseif ($args) { - throw new ServiceCreationException("Unable to pass arguments, class $class has no constructor."); - } - return new $class; - } - - - /** - * Calls all methods starting with with "inject" using autowiring. - * @param object - * @return void - */ - public function callInjects($service) - { - if (!is_object($service)) { - throw new Nette\InvalidArgumentException(sprintf('Service must be object, %s given.', gettype($service))); - } - - foreach (array_reverse(get_class_methods($service)) as $method) { - if (substr($method, 0, 6) === 'inject') { - $this->callMethod(array($service, $method)); - } - } - - foreach (Helpers::getInjectProperties(Nette\Reflection\ClassType::from($service)) as $property => $type) { - $service->$property = $this->getByType($type); - } - } - - - /** - * Calls method using autowiring. - * @param mixed class, object, function, callable - * @param array arguments - * @return mixed - */ - public function callMethod($function, array $args = array()) - { - return call_user_func_array( - $function, - Helpers::autowireArguments(Nette\Utils\Callback::toReflection($function), $args, $this) - ); - } - - - /********************* shortcuts ****************d*g**/ - - - /** - * Expands %placeholders%. - * @param mixed - * @return mixed - */ - public function expand($s) - { - return Helpers::expand($s, $this->parameters); - } - - - /** @deprecated */ - public function &__get($name) - { - $this->error(__METHOD__, 'getService'); - $tmp = $this->getService($name); - return $tmp; - } - - - /** @deprecated */ - public function __set($name, $service) - { - $this->error(__METHOD__, 'addService'); - $this->addService($name, $service); - } - - - /** @deprecated */ - public function __isset($name) - { - $this->error(__METHOD__, 'hasService'); - return $this->hasService($name); - } - - - /** @deprecated */ - public function __unset($name) - { - $this->error(__METHOD__, 'removeService'); - $this->removeService($name); - } - - - private function error($oldName, $newName) - { - if (empty($this->parameters['container']['accessors'])) { - trigger_error("$oldName() is deprecated; use $newName() or enable nette.container.accessors in configuration.", E_USER_DEPRECATED); - } - } - - - public static function getMethodName($name) - { - $uname = ucfirst($name); - return 'createService' . ((string) $name === $uname ? '__' : '') . str_replace('.', '__', $uname); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Diagnostics/ContainerPanel.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Diagnostics/ContainerPanel.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Diagnostics/ContainerPanel.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Diagnostics/ContainerPanel.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -container = $container; - } - - - /** - * Renders tab. - * @return string - */ - public function getTab() - { - ob_start(); - require __DIR__ . '/templates/ContainerPanel.tab.phtml'; - return ob_get_clean(); - } - - - /** - * Renders panel. - * @return string - */ - public function getPanel() - { - $services = array(); - foreach (Nette\Reflection\ClassType::from($this->container)->getMethods() as $method) { - if (preg_match('#^createService_*(.+)\z#', $method->getName(), $m)) { - $services[str_replace('__', '.', strtolower(substr($m[1], 0, 1)) . substr($m[1], 1))] = $method->getAnnotation('return'); - } - } - ksort($services); - $container = $this->container; - $registry = $this->getContainerProperty('registry'); - $tags = array(); - $meta = $this->getContainerProperty('meta'); - if (isset($meta[Container::TAGS])) { - foreach ($meta[Container::TAGS] as $tag => $tmp) { - foreach ($tmp as $service => $val) { - $tags[$service][$tag] = $val; - } - } - } - - ob_start(); - require __DIR__ . '/templates/ContainerPanel.panel.phtml'; - return ob_get_clean(); - } - - - private function getContainerProperty($name) - { - $prop = Nette\Reflection\ClassType::from('Nette\DI\Container')->getProperty($name); - $prop->setAccessible(TRUE); - return $prop->getValue($this->container); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Diagnostics/templates/ContainerPanel.panel.phtml php-nette-2.1.5/Nette-2.1.4/Nette/DI/Diagnostics/templates/ContainerPanel.panel.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Diagnostics/templates/ContainerPanel.panel.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Diagnostics/templates/ContainerPanel.panel.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ - - - -
-

container) ?>

- -
-

Services

- - - - - - - - - - - - $class): ?> - findByType($class)); ?> - - - - - - - - -
NameAutowiredServiceTags
- - TRUE)); ?> - - - - - - TRUE)); } ?>
- -

Parameters

- -
- container->parameters); ?> -
-
-
diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Diagnostics/templates/ContainerPanel.tab.phtml php-nette-2.1.5/Nette-2.1.4/Nette/DI/Diagnostics/templates/ContainerPanel.tab.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Diagnostics/templates/ContainerPanel.tab.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Diagnostics/templates/ContainerPanel.tab.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ - -  diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/exceptions.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/exceptions.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/exceptions.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/exceptions.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -getConfig() as $name => $value) { - $class->methods['initialize']->addBody('define(?, ?);', array($name, $value)); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Extensions/ExtensionsExtension.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Extensions/ExtensionsExtension.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Extensions/ExtensionsExtension.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Extensions/ExtensionsExtension.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -getConfig() as $name => $class) { - $this->compiler->addExtension($name, new $class); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Extensions/NetteAccessor.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Extensions/NetteAccessor.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Extensions/NetteAccessor.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Extensions/NetteAccessor.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -container = $container; - } - - - public function __call($name, $args) - { - if (substr($name, 0, 6) === 'create') { - $method = $this->container->getMethodName('nette.' . substr($name, 6)); - trigger_error("Factory accessing via nette->$name() is deprecated, use $method().", E_USER_DEPRECATED); - return call_user_func_array(array($this->container, $method), $args); - } - throw new Nette\NotSupportedException; - } - - - public function &__get($name) - { - trigger_error("Service accessing via nette->$name is deprecated, use 'nette.$name'.", E_USER_DEPRECATED); - $service = $this->container->getService("nette.$name"); - return $service; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Extensions/NetteExtension.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Extensions/NetteExtension.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Extensions/NetteExtension.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Extensions/NetteExtension.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,495 +0,0 @@ - array( - 'proxy' => array(), - ), - 'session' => array( - 'debugger' => FALSE, - 'autoStart' => 'smart', // true|false|smart - 'expiration' => NULL, - ), - 'application' => array( - 'debugger' => TRUE, - 'errorPresenter' => 'Nette:Error', - 'catchExceptions' => '%productionMode%', - 'mapping' => NULL - ), - 'routing' => array( - 'debugger' => TRUE, - 'routes' => array(), // of [mask => action] - ), - 'security' => array( - 'debugger' => TRUE, - 'frames' => 'SAMEORIGIN', // X-Frame-Options - 'users' => array(), // of [user => password] - 'roles' => array(), // of [role => parents] - 'resources' => array(), // of [resource => parents] - ), - 'mailer' => array( - 'smtp' => FALSE, - 'host' => NULL, - 'port' => NULL, - 'username' => NULL, - 'password' => NULL, - 'secure' => NULL, - 'timeout' => NULL, - ), - 'database' => array(), // of [name => dsn, user, password, debugger, explain, autowired, reflection] - 'forms' => array( - 'messages' => array(), - ), - 'latte' => array( - 'xhtml' => FALSE, - 'macros' => array(), - ), - 'container' => array( - 'debugger' => FALSE, - 'accessors' => TRUE, - ), - 'debugger' => array( - 'email' => NULL, - 'editor' => NULL, - 'browser' => NULL, - 'strictMode' => NULL, - 'maxLen' => NULL, - 'maxDepth' => NULL, - 'showLocation' => NULL, - 'scream' => NULL, - 'bar' => array(), // of class name - 'blueScreen' => array(), // of callback - ), - ); - - public $databaseDefaults = array( - 'dsn' => NULL, - 'user' => NULL, - 'password' => NULL, - 'options' => NULL, - 'debugger' => TRUE, - 'explain' => TRUE, - 'reflection' => 'Nette\Database\Reflection\DiscoveredReflection', - 'autowired' => NULL, - ); - - - public function loadConfiguration() - { - $container = $this->getContainerBuilder(); - $config = $this->getConfig($this->defaults); - - if (isset($config['xhtml'])) { - $config['latte']['xhtml'] = $config['xhtml']; - unset($config['xhtml']); - } - $container->addDefinition('nette')->setClass('Nette\DI\Extensions\NetteAccessor', array('@container')); - - $this->validate($config, $this->defaults, 'nette'); - - $this->setupCache($container); - $this->setupHttp($container, $config['http']); - $this->setupSession($container, $config['session']); - $this->setupSecurity($container, $config['security']); - $this->setupApplication($container, $config['application']); - $this->setupRouting($container, $config['routing']); - $this->setupMailer($container, $config['mailer']); - $this->setupForms($container); - $this->setupLatte($container, $config['latte']); - $this->setupDatabase($container, $config['database']); - $this->setupContainer($container, $config['container']); - } - - - private function setupCache(ContainerBuilder $container) - { - $container->addDefinition($this->prefix('cacheJournal')) - ->setClass('Nette\Caching\Storages\FileJournal', array($container->expand('%tempDir%'))); - - $container->addDefinition('cacheStorage') // no namespace for back compatibility - ->setClass('Nette\Caching\Storages\FileStorage', array($container->expand('%tempDir%/cache'))); - - $container->addDefinition($this->prefix('templateCacheStorage')) - ->setClass('Nette\Caching\Storages\PhpFileStorage', array($container->expand('%tempDir%/cache'))) - ->setAutowired(FALSE); - - $container->addDefinition($this->prefix('cache')) - ->setClass('Nette\Caching\Cache', array(1 => $container::literal('$namespace'))) - ->addSetup('::trigger_error', array('Service cache is deprecated.', E_USER_DEPRECATED)) - ->setParameters(array('namespace' => NULL)); - } - - - private function setupHttp(ContainerBuilder $container, array $config) - { - $this->validate($config, $this->defaults['http'], 'nette.http'); - - $container->addDefinition($this->prefix('httpRequestFactory')) - ->setClass('Nette\Http\RequestFactory') - ->addSetup('setProxy', array($config['proxy'])); - - $container->addDefinition('httpRequest') // no namespace for back compatibility - ->setClass('Nette\Http\Request') - ->setFactory('@Nette\Http\RequestFactory::createHttpRequest'); - - $container->addDefinition('httpResponse') // no namespace for back compatibility - ->setClass('Nette\Http\Response'); - - $container->addDefinition($this->prefix('httpContext')) - ->setClass('Nette\Http\Context'); - } - - - private function setupSession(ContainerBuilder $container, array $config) - { - $session = $container->addDefinition('session') // no namespace for back compatibility - ->setClass('Nette\Http\Session'); - - if (isset($config['expiration'])) { - $session->addSetup('setExpiration', array($config['expiration'])); - } - - if ($container->parameters['debugMode'] && $config['debugger']) { - $session->addSetup('Nette\Diagnostics\Debugger::getBar()->addPanel(?)', array( - new Nette\DI\Statement('Nette\Http\Diagnostics\SessionPanel') - )); - } - - unset($config['expiration'], $config['autoStart'], $config['debugger']); - if (!empty($config)) { - $session->addSetup('setOptions', array($config)); - } - } - - - private function setupSecurity(ContainerBuilder $container, array $config) - { - $this->validate($config, $this->defaults['security'], 'nette.security'); - - $container->addDefinition($this->prefix('userStorage')) - ->setClass('Nette\Http\UserStorage'); - - $user = $container->addDefinition('user') // no namespace for back compatibility - ->setClass('Nette\Security\User'); - - if ($container->parameters['debugMode'] && $config['debugger']) { - $user->addSetup('Nette\Diagnostics\Debugger::getBar()->addPanel(?)', array( - new Nette\DI\Statement('Nette\Security\Diagnostics\UserPanel') - )); - } - - if ($config['users']) { - $container->addDefinition($this->prefix('authenticator')) - ->setClass('Nette\Security\SimpleAuthenticator', array($config['users'])); - } - - if ($config['roles'] || $config['resources']) { - $authorizator = $container->addDefinition($this->prefix('authorizator')) - ->setClass('Nette\Security\Permission'); - foreach ($config['roles'] as $role => $parents) { - $authorizator->addSetup('addRole', array($role, $parents)); - } - foreach ($config['resources'] as $resource => $parents) { - $authorizator->addSetup('addResource', array($resource, $parents)); - } - } - } - - - private function setupApplication(ContainerBuilder $container, array $config) - { - $this->validate($config, $this->defaults['application'], 'nette.application'); - - $application = $container->addDefinition('application') // no namespace for back compatibility - ->setClass('Nette\Application\Application') - ->addSetup('$catchExceptions', array($config['catchExceptions'])) - ->addSetup('$errorPresenter', array($config['errorPresenter'])); - - if ($config['debugger']) { - $application->addSetup('Nette\Application\Diagnostics\RoutingPanel::initializePanel'); - } - - $presenterFactory = $container->addDefinition($this->prefix('presenterFactory')) - ->setClass('Nette\Application\PresenterFactory', array( - isset($container->parameters['appDir']) ? $container->parameters['appDir'] : NULL - )); - if ($config['mapping']) { - $presenterFactory->addSetup('setMapping', array($config['mapping'])); - } - } - - - private function setupRouting(ContainerBuilder $container, array $config) - { - $this->validate($config, $this->defaults['routing'], 'nette.routing'); - - $router = $container->addDefinition('router') // no namespace for back compatibility - ->setClass('Nette\Application\Routers\RouteList'); - - foreach ($config['routes'] as $mask => $action) { - $router->addSetup('$service[] = new Nette\Application\Routers\Route(?, ?);', array($mask, $action)); - } - - if ($container->parameters['debugMode'] && $config['debugger']) { - $container->getDefinition('application')->addSetup('Nette\Diagnostics\Debugger::getBar()->addPanel(?)', array( - new Nette\DI\Statement('Nette\Application\Diagnostics\RoutingPanel') - )); - } - } - - - private function setupMailer(ContainerBuilder $container, array $config) - { - $this->validate($config, $this->defaults['mailer'], 'nette.mailer'); - - if (empty($config['smtp'])) { - $container->addDefinition($this->prefix('mailer')) - ->setClass('Nette\Mail\SendmailMailer'); - } else { - $container->addDefinition($this->prefix('mailer')) - ->setClass('Nette\Mail\SmtpMailer', array($config)); - } - - $container->addDefinition($this->prefix('mail')) - ->setClass('Nette\Mail\Message') - ->addSetup('::trigger_error', array('Service nette.mail is deprecated.', E_USER_DEPRECATED)) - ->addSetup('setMailer') - ->setAutowired(FALSE); - } - - - private function setupForms(ContainerBuilder $container) - { - $container->addDefinition($this->prefix('basicForm')) - ->setClass('Nette\Forms\Form') - ->addSetup('::trigger_error', array('Service nette.basicForm is deprecated.', E_USER_DEPRECATED)) - ->setAutowired(FALSE); - } - - - private function setupLatte(ContainerBuilder $container, array $config) - { - $this->validate($config, $this->defaults['latte'], 'nette.latte'); - - $latte = $container->addDefinition($this->prefix('latte')) - ->setClass('Nette\Latte\Engine') - ->setAutowired(FALSE); - - if ($config['xhtml']) { - $latte->addSetup('$service->getCompiler()->defaultContentType = ?', array(Nette\Latte\Compiler::CONTENT_XHTML)); - } - - $container->addDefinition($this->prefix('template')) - ->setClass('Nette\Templating\FileTemplate') - ->addSetup('registerFilter', array($latte)) - ->addSetup('registerHelperLoader', array('Nette\Templating\Helpers::loader')) - ->setAutowired(FALSE); - - foreach ($config['macros'] as $macro) { - if (strpos($macro, '::') === FALSE && class_exists($macro)) { - $macro .= '::install'; - - } else { - Validators::assert($macro, 'callable'); - } - - $latte->addSetup($macro . '(?->compiler)', array('@self')); - } - } - - - private function setupDatabase(ContainerBuilder $container, array $config) - { - if (isset($config['dsn'])) { - $config = array('default' => $config); - } - - $autowired = TRUE; - foreach ((array) $config as $name => $info) { - if (!is_array($info)) { - continue; - } - $this->validate($info, $this->databaseDefaults, 'nette.database'); - - $info += array('autowired' => $autowired) + $this->databaseDefaults; - $autowired = FALSE; - - foreach ((array) $info['options'] as $key => $value) { - if (preg_match('#^PDO::\w+\z#', $key)) { - unset($info['options'][$key]); - $info['options'][constant($key)] = $value; - } - } - - if (!$info['reflection']) { - $reflection = NULL; - } elseif (is_string($info['reflection'])) { - $reflection = new Nette\DI\Statement(preg_match('#^[a-z]+\z#', $info['reflection']) - ? 'Nette\Database\Reflection\\' . ucfirst($info['reflection']) . 'Reflection' - : $info['reflection'], strtolower($info['reflection']) === 'discovered' ? array('@self') : array()); - } else { - $tmp = Nette\DI\Compiler::filterArguments(array($info['reflection'])); - $reflection = reset($tmp); - } - - $connection = $container->addDefinition($this->prefix("database.$name")) - ->setClass('Nette\Database\Connection', array($info['dsn'], $info['user'], $info['password'], $info['options'])) - ->setAutowired($info['autowired']) - ->addSetup('setContext', array( - new Nette\DI\Statement('Nette\Database\Context', array('@self', $reflection)), - )) - ->addSetup('Nette\Diagnostics\Debugger::getBlueScreen()->addPanel(?)', array( - 'Nette\Database\Diagnostics\ConnectionPanel::renderException' - )); - - $container->addDefinition($this->prefix("database.$name.context")) - ->setClass('Nette\Database\Context') - ->setFactory(array($connection, 'getContext')) - ->setAutowired($info['autowired']); - - if ($container->parameters['debugMode'] && $info['debugger']) { - $connection->addSetup('Nette\Database\Helpers::createDebugPanel', array($connection, !empty($info['explain']), $name)); - } - } - } - - - private function setupContainer(ContainerBuilder $container, array $config) - { - $this->validate($config, $this->defaults['container'], 'nette.container'); - - if ($config['accessors']) { - $container->parameters['container']['accessors'] = TRUE; - } - } - - - public function afterCompile(Nette\PhpGenerator\ClassType $class) - { - $initialize = $class->methods['initialize']; - $container = $this->getContainerBuilder(); - $config = $this->getConfig($this->defaults); - - // debugger - foreach (array('email', 'editor', 'browser', 'strictMode', 'maxLen', 'maxDepth', 'showLocation', 'scream') as $key) { - if (isset($config['debugger'][$key])) { - $initialize->addBody('Nette\Diagnostics\Debugger::$? = ?;', array($key, $config['debugger'][$key])); - } - } - - if ($container->parameters['debugMode']) { - if ($config['container']['debugger']) { - $config['debugger']['bar'][] = 'Nette\DI\Diagnostics\ContainerPanel'; - } - - foreach ((array) $config['debugger']['bar'] as $item) { - $initialize->addBody($container->formatPhp( - 'Nette\Diagnostics\Debugger::getBar()->addPanel(?);', - Nette\DI\Compiler::filterArguments(array(is_string($item) ? new Nette\DI\Statement($item) : $item)) - )); - } - } - - foreach ((array) $config['debugger']['blueScreen'] as $item) { - $initialize->addBody($container->formatPhp( - 'Nette\Diagnostics\Debugger::getBlueScreen()->addPanel(?);', - Nette\DI\Compiler::filterArguments(array($item)) - )); - } - - if (!empty($container->parameters['tempDir'])) { - $initialize->addBody('Nette\Caching\Storages\FileStorage::$useDirectories = ?;', array($this->checkTempDir($container->expand('%tempDir%/cache')))); - } - - foreach ((array) $config['forms']['messages'] as $name => $text) { - $initialize->addBody('Nette\Forms\Rules::$defaultMessages[Nette\Forms\Form::?] = ?;', array($name, $text)); - } - - if ($config['session']['autoStart'] === 'smart') { - $initialize->addBody('$this->getByType("Nette\Http\Session")->exists() && $this->getByType("Nette\Http\Session")->start();'); - } elseif ($config['session']['autoStart']) { - $initialize->addBody('$this->getByType("Nette\Http\Session")->start();'); - } - - if ($config['latte']['xhtml']) { - $initialize->addBody('Nette\Utils\Html::$xhtml = ?;', array(TRUE)); - } - - if (isset($config['security']['frames']) && $config['security']['frames'] !== TRUE) { - $frames = $config['security']['frames']; - if ($frames === FALSE) { - $frames = 'DENY'; - } elseif (preg_match('#^https?:#', $frames)) { - $frames = "ALLOW-FROM $frames"; - } - $initialize->addBody('header(?);', array("X-Frame-Options: $frames")); - } - - foreach ($container->findByTag('run') as $name => $on) { - if ($on) { - $initialize->addBody('$this->getService(?);', array($name)); - } - } - - if (!empty($config['container']['accessors'])) { - $definitions = $container->definitions; - ksort($definitions); - foreach ($definitions as $name => $def) { - if (Nette\PhpGenerator\Helpers::isIdentifier($name)) { - $type = $def->implement ?: $def->class; - $class->addDocument("@property $type \$$name"); - } - } - } - - $initialize->addBody("@header('X-Powered-By: Nette Framework');"); - $initialize->addBody("@header('Content-Type: text/html; charset=utf-8');"); - $initialize->addBody('Nette\Utils\SafeStream::register();'); - } - - - private function checkTempDir($dir) - { - // checks whether directory is writable - $uniq = uniqid('_', TRUE); - if (!@mkdir("$dir/$uniq")) { // @ - is escalated to exception - throw new Nette\InvalidStateException("Unable to write to directory '$dir'. Make this directory writable."); - } - - // checks whether subdirectory is writable - $isWritable = @file_put_contents("$dir/$uniq/_", '') !== FALSE; // @ - error is expected - if ($isWritable) { - unlink("$dir/$uniq/_"); - } - rmdir("$dir/$uniq"); - return $isWritable; - } - - - private function validate(array $config, array $expected, $name) - { - if ($extra = array_diff_key($config, $expected)) { - $extra = implode(", $name.", array_keys($extra)); - throw new Nette\InvalidStateException("Unknown option $name.$extra."); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Extensions/PhpExtension.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Extensions/PhpExtension.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Extensions/PhpExtension.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Extensions/PhpExtension.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -methods['initialize']; - foreach ($this->getConfig() as $name => $value) { - if (!is_scalar($value)) { - throw new Nette\InvalidStateException("Configuration value for directive '$name' is not scalar."); - - } elseif ($name === 'include_path') { - $initialize->addBody('set_include_path(?);', array(str_replace(';', PATH_SEPARATOR, $value))); - - } elseif ($name === 'ignore_user_abort') { - $initialize->addBody('ignore_user_abort(?);', array($value)); - - } elseif ($name === 'max_execution_time') { - $initialize->addBody('set_time_limit(?);', array($value)); - - } elseif ($name === 'date.timezone') { - $initialize->addBody('date_default_timezone_set(?);', array($value)); - - } elseif (function_exists('ini_set')) { - $initialize->addBody('ini_set(?, ?);', array($name, $value)); - - } elseif (ini_get($name) != $value) { // intentionally == - throw new Nette\NotSupportedException('Required function ini_set() is disabled.'); - } - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Helpers.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Helpers.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Helpers.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Helpers.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,173 +0,0 @@ - $val) { - $res[$key] = self::expand($val, $params, $recursive); - } - return $res; - - } elseif ($var instanceof \stdClass || $var instanceof Statement) { - $res = clone $var; - foreach ($var as $key => $val) { - $res->$key = self::expand($val, $params, $recursive); - } - return $res; - - } elseif (!is_string($var)) { - return $var; - } - - $parts = preg_split('#%([\w.-]*)%#i', $var, -1, PREG_SPLIT_DELIM_CAPTURE); - $res = ''; - foreach ($parts as $n => $part) { - if ($n % 2 === 0) { - $res .= $part; - - } elseif ($part === '') { - $res .= '%'; - - } elseif (isset($recursive[$part])) { - throw new Nette\InvalidArgumentException(sprintf('Circular reference detected for variables: %s.', implode(', ', array_keys($recursive)))); - - } else { - try { - $val = Nette\Utils\Arrays::get($params, explode('.', $part)); - } catch (Nette\InvalidArgumentException $e) { - throw new Nette\InvalidArgumentException("Missing parameter '$part'.", 0, $e); - } - if ($recursive) { - $val = self::expand($val, $params, (is_array($recursive) ? $recursive : array()) + array($part => 1)); - } - if (strlen($part) + 2 === strlen($var)) { - return $val; - } - if (!is_scalar($val)) { - throw new Nette\InvalidArgumentException("Unable to concatenate non-scalar parameter '$part' into '$var'."); - } - $res .= $val; - } - } - return $res; - } - - - /** - * Generates list of arguments using autowiring. - * @param Nette\Reflection\GlobalFunction|Nette\Reflection\Method - * @return array - */ - public static function autowireArguments(\ReflectionFunctionAbstract $method, array $arguments, $container) - { - $optCount = 0; - $num = -1; - $res = array(); - - foreach ($method->getParameters() as $num => $parameter) { - if (array_key_exists($num, $arguments)) { - $res[$num] = $arguments[$num]; - unset($arguments[$num]); - $optCount = 0; - - } elseif (array_key_exists($parameter->getName(), $arguments)) { - $res[$num] = $arguments[$parameter->getName()]; - unset($arguments[$parameter->getName()]); - $optCount = 0; - - } elseif ($class = $parameter->getClassName()) { // has object type hint - $res[$num] = $container->getByType($class, FALSE); - if ($res[$num] === NULL) { - if ($parameter->allowsNull()) { - $optCount++; - } else { - throw new ServiceCreationException("No service of type {$class} found. Make sure the type hint in $method is written correctly and service of this type is registered."); - } - } else { - if ($container instanceof ContainerBuilder) { - $res[$num] = '@' . $res[$num]; - } - $optCount = 0; - } - - } elseif ($parameter->isOptional()) { - // PDO::__construct has optional parameter without default value (and isArray() and allowsNull() returns FALSE) - $res[$num] = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : NULL; - $optCount++; - - } else { - throw new ServiceCreationException("Parameter $parameter has no type hint, so its value must be specified."); - } - } - - // extra parameters - while (array_key_exists(++$num, $arguments)) { - $res[$num] = $arguments[$num]; - unset($arguments[$num]); - $optCount = 0; - } - if ($arguments) { - throw new ServiceCreationException("Unable to pass specified arguments to $method."); - } - - return $optCount ? array_slice($res, 0, -$optCount) : $res; - } - - - /** - * Generates list of properties with annotation @inject. - * @return array - */ - public static function getInjectProperties(Nette\Reflection\ClassType $class) - { - $res = array(); - foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { - $type = $property->getAnnotation('var'); - if (!$property->getAnnotation('inject')) { - continue; - - } elseif (!$type) { - throw new Nette\InvalidStateException("Property $property has not @var annotation."); - - } elseif (!class_exists($type) && !interface_exists($type)) { - if ($type[0] !== '\\') { - $type = $property->getDeclaringClass()->getNamespaceName() . '\\' . $type; - } - if (!class_exists($type) && !interface_exists($type)) { - throw new Nette\InvalidStateException("Please use a fully qualified name of class/interface in @var annotation at $property property. Class '$type' cannot be found."); - } - } - $res[$property->getName()] = $type; - } - return $res; - } - - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/ServiceDefinition.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/ServiceDefinition.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/ServiceDefinition.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/ServiceDefinition.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,131 +0,0 @@ -class = $class; - if ($args) { - $this->setFactory($class, $args); - } - return $this; - } - - - public function setFactory($factory, array $args = array()) - { - $this->factory = new Statement($factory, $args); - return $this; - } - - - public function setArguments(array $args = array()) - { - if ($this->factory) { - $this->factory->arguments = $args; - } else { - $this->setClass($this->class, $args); - } - return $this; - } - - - public function addSetup($target, array $args = array()) - { - $this->setup[] = new Statement($target, $args); - return $this; - } - - - public function setParameters(array $params) - { - $this->shared = $this->autowired = FALSE; - $this->parameters = $params; - return $this; - } - - - public function addTag($tag, $attrs = TRUE) - { - $this->tags[$tag] = $attrs; - return $this; - } - - - public function setAutowired($on) - { - $this->autowired = $on; - return $this; - } - - - /** @deprecated */ - public function setShared($on) - { - $this->shared = (bool) $on; - $this->autowired = $this->shared ? $this->autowired : FALSE; - return $this; - } - - - public function setInject($on) - { - $this->inject = (bool) $on; - return $this; - } - - - public function setImplement($implement) - { - $this->implement = $implement; - $this->shared = TRUE; - return $this; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/DI/Statement.php php-nette-2.1.5/Nette-2.1.4/Nette/DI/Statement.php --- php-nette-2.1.4/Nette-2.1.4/Nette/DI/Statement.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/DI/Statement.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -entity = $entity; - $this->arguments = $arguments; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/Bar.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/Bar.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/Bar.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/Bar.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -panels[$id])); - } - $this->panels[$id] = $panel; - return $this; - } - - - /** - * Returns panel with given id - * @param string - * @return IBarPanel|NULL - */ - public function getPanel($id) - { - return isset($this->panels[$id]) ? $this->panels[$id] : NULL; - } - - - /** - * Renders debug bar. - * @return void - */ - public function render() - { - $obLevel = ob_get_level(); - $panels = array(); - foreach ($this->panels as $id => $panel) { - try { - $panels[] = array( - 'id' => preg_replace('#[^a-z0-9]+#i', '-', $id), - 'tab' => $tab = (string) $panel->getTab(), - 'panel' => $tab ? (string) $panel->getPanel() : NULL, - ); - } catch (\Exception $e) { - $panels[] = array( - 'id' => "error-" . preg_replace('#[^a-z0-9]+#i', '-', $id), - 'tab' => "Error in $id", - 'panel' => '

Error: ' . $id . '

' . nl2br(htmlSpecialChars($e, ENT_IGNORE)) . '
', - ); - while (ob_get_level() > $obLevel) { // restore ob-level if broken - ob_end_clean(); - } - } - } - - @session_start(); - $session = & $_SESSION['__NF']['debuggerbar']; - if (preg_match('#^Location:#im', implode("\n", headers_list()))) { - $session[] = $panels; - return; - } - - foreach (array_reverse((array) $session) as $reqId => $oldpanels) { - $panels[] = array( - 'tab' => 'previous', - 'panel' => NULL, - 'previous' => TRUE, - ); - foreach ($oldpanels as $panel) { - $panel['id'] .= '-' . $reqId; - $panels[] = $panel; - } - } - $session = NULL; - - require __DIR__ . '/templates/bar.phtml'; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/BlueScreen.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/BlueScreen.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/BlueScreen.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/BlueScreen.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,168 +0,0 @@ -panels, TRUE)) { - $this->panels[] = $panel; - } - return $this; - } - - - /** - * Renders blue screen. - * @param \Exception - * @return void - */ - public function render(\Exception $exception) - { - $panels = $this->panels; - require __DIR__ . '/templates/bluescreen.phtml'; - } - - - /** - * Returns syntax highlighted source code. - * @param string - * @param int - * @param int - * @return string - */ - public static function highlightFile($file, $line, $lines = 15, $vars = array()) - { - $source = @file_get_contents($file); // intentionally @ - if ($source) { - return substr_replace( - static::highlightPhp($source, $line, $lines, $vars), - ' data-nette-href="' . htmlspecialchars(strtr(Debugger::$editor, array('%file' => rawurlencode($file), '%line' => $line))) . '"', - 4, 0 - ); - } - } - - - /** - * Returns syntax highlighted source code. - * @param string - * @param int - * @param int - * @return string - */ - public static function highlightPhp($source, $line, $lines = 15, $vars = array()) - { - if (function_exists('ini_set')) { - ini_set('highlight.comment', '#998; font-style: italic'); - ini_set('highlight.default', '#000'); - ini_set('highlight.html', '#06B'); - ini_set('highlight.keyword', '#D24; font-weight: bold'); - ini_set('highlight.string', '#080'); - } - - $source = str_replace(array("\r\n", "\r"), "\n", $source); - $source = explode("\n", highlight_string($source, TRUE)); - $out = $source[0]; // - $source = str_replace('
', "\n", $source[1]); - $out .= static::highlightLine($source, $line, $lines); - - if ($vars) { - $out = preg_replace_callback('#">\$(\w+)( )?
#', function($m) use ($vars) { - return array_key_exists($m[1], $vars) - ? '" title="' . str_replace('"', '"', trim(strip_tags(Dumper::toHtml($vars[$m[1]])))) . $m[0] - : $m[0]; - }, $out); - } - - return "
$out
"; - } - - - - /** - * Returns highlighted line in HTML code. - * @return string - */ - public static function highlightLine($html, $line, $lines = 15) - { - $source = explode("\n", "\n" . str_replace("\r\n", "\n", $html)); - $out = ''; - $spans = 1; - $start = $i = max(1, $line - floor($lines * 2/3)); - while (--$i >= 1) { // find last highlighted block - if (preg_match('#.*(]*>)#', $source[$i], $m)) { - if ($m[1] !== '') { - $spans++; - $out .= $m[1]; - } - break; - } - } - - $source = array_slice($source, $start, $lines, TRUE); - end($source); - $numWidth = strlen((string) key($source)); - - foreach ($source as $n => $s) { - $spans += substr_count($s, ']+>#', $s, $tags); - if ($n == $line) { - $out .= sprintf( - "%{$numWidth}s: %s\n%s", - $n, - strip_tags($s), - implode('', $tags[0]) - ); - } else { - $out .= sprintf("%{$numWidth}s: %s\n", $n, $s); - } - } - $out .= str_repeat('', $spans) . '
'; - return $out; - } - - - /** - * Should a file be collapsed in stack trace? - * @param string - * @return bool - */ - public function isCollapsed($file) - { - foreach ($this->collapsePaths as $path) { - if (strpos(strtr($file, '\\', '/'), strtr("$path/", '\\', '/')) === 0) { - return TRUE; - } - } - return FALSE; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/Debugger.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/Debugger.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/Debugger.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/Debugger.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,666 +0,0 @@ - 'Fatal Error', - E_USER_ERROR => 'User Error', - E_RECOVERABLE_ERROR => 'Recoverable Error', - E_CORE_ERROR => 'Core Error', - E_COMPILE_ERROR => 'Compile Error', - E_PARSE => 'Parse Error', - E_WARNING => 'Warning', - E_CORE_WARNING => 'Core Warning', - E_COMPILE_WARNING => 'Compile Warning', - E_USER_WARNING => 'User Warning', - E_NOTICE => 'Notice', - E_USER_NOTICE => 'User Notice', - E_STRICT => 'Strict standards', - E_DEPRECATED => 'Deprecated', - E_USER_DEPRECATED => 'User Deprecated', - ); - - /********************* logging ****************d*g**/ - - /** @deprecated @var Logger */ - public static $logger; - - /** @deprecated @var FireLogger */ - public static $fireLogger; - - /** @var string name of the directory where errors should be logged; FALSE means that logging is disabled */ - public static $logDirectory; - - /** @var string|array email(s) to which send error notifications */ - public static $email; - - /** @deprecated */ - public static $mailer = array('Nette\Diagnostics\Logger', 'defaultMailer'); - - /** @deprecated */ - public static $emailSnooze = 172800; - - /** {@link Debugger::log()} and {@link Debugger::fireLog()} */ - const DEBUG = 'debug', - INFO = 'info', - WARNING = 'warning', - ERROR = 'error', - CRITICAL = 'critical'; - - /********************* debug bar ****************d*g**/ - - /** @deprecated @var Bar */ - public static $bar; - - - /** - * Static class - cannot be instantiated. - */ - final public function __construct() - { - throw new Nette\StaticClassException; - } - - - /** - * Enables displaying or logging errors and exceptions. - * @param mixed production, development mode, autodetection or IP address(es) whitelist. - * @param string error log directory; enables logging in production mode, FALSE means that logging is disabled - * @param string administrator email; enables email sending in production mode - * @return void - */ - public static function enable($mode = NULL, $logDirectory = NULL, $email = NULL) - { - self::$time = isset($_SERVER['REQUEST_TIME_FLOAT']) ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime(TRUE); - if (isset($_SERVER['REQUEST_URI'])) { - self::$source = (!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') - . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') - . $_SERVER['REQUEST_URI']; - } else { - self::$source = empty($_SERVER['argv']) ? 'CLI' : 'CLI: ' . implode(' ', $_SERVER['argv']); - } - self::$consoleColors = & Dumper::$terminalColors; - error_reporting(E_ALL | E_STRICT); - - // production/development mode detection - if (is_bool($mode)) { - self::$productionMode = $mode; - - } elseif ($mode !== self::DETECT || self::$productionMode === NULL) { // IP addresses or computer names whitelist detection - $list = is_string($mode) ? preg_split('#[,\s]+#', $mode) : (array) $mode; - if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $list[] = '127.0.0.1'; - $list[] = '::1'; - } - self::$productionMode = !in_array(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : php_uname('n'), $list, TRUE); - } - - // logging configuration - if (is_string($logDirectory)) { - self::$logDirectory = realpath($logDirectory); - if (self::$logDirectory === FALSE) { - echo __METHOD__ . "() error: Log directory is not found or is not directory.\n"; - exit(254); - } - } elseif ($logDirectory === FALSE || self::$logDirectory === NULL) { - self::$logDirectory = FALSE; - } - if (self::$logDirectory) { - ini_set('error_log', self::$logDirectory . '/php_error.log'); - } - - // php configuration - if (function_exists('ini_set')) { - ini_set('display_errors', !self::$productionMode); // or 'stderr' - ini_set('html_errors', FALSE); - ini_set('log_errors', FALSE); - - } elseif (ini_get('display_errors') != !self::$productionMode && ini_get('display_errors') !== (self::$productionMode ? 'stderr' : 'stdout')) { // intentionally == - echo __METHOD__ . "() error: Unable to set 'display_errors' because function ini_set() is disabled.\n"; - exit(254); - } - - if ($email) { - if (!is_string($email) && !is_array($email)) { - echo __METHOD__ . "() error: Email address must be a string.\n"; - exit(254); - } - self::$email = $email; - } - - if (!self::$enabled) { - register_shutdown_function(array(__CLASS__, '_shutdownHandler')); - set_exception_handler(array(__CLASS__, '_exceptionHandler')); - set_error_handler(array(__CLASS__, '_errorHandler')); - - foreach (array('Nette\Diagnostics\Bar', 'Nette\Diagnostics\BlueScreen', 'Nette\Diagnostics\DefaultBarPanel', 'Nette\Diagnostics\Dumper', 'Nette\Diagnostics\FireLogger', - 'Nette\Diagnostics\Helpers', 'Nette\Diagnostics\Logger', 'Nette\Utils\Html', 'Nette\Utils\Strings') as $class) { - class_exists($class); - } - self::$enabled = TRUE; - } - } - - - /** - * @return BlueScreen - */ - public static function getBlueScreen() - { - if (!self::$blueScreen) { - self::$blueScreen = new BlueScreen; - self::$blueScreen->collapsePaths[] = dirname(__DIR__); - self::$blueScreen->addPanel(function($e) { - if ($e instanceof Nette\Templating\FilterException) { - return array( - 'tab' => 'Template', - 'panel' => '

File: ' . Helpers::editorLink($e->sourceFile, $e->sourceLine) . '

' - . ($e->sourceLine ? BlueScreen::highlightFile($e->sourceFile, $e->sourceLine) : '') - ); - } elseif ($e instanceof Nette\Utils\NeonException && preg_match('#line (\d+)#', $e->getMessage(), $m)) { - if ($item = Helpers::findTrace($e->getTrace(), 'Nette\DI\Config\Adapters\NeonAdapter::load')) { - return array( - 'tab' => 'NEON', - 'panel' => '

File: ' . Helpers::editorLink($item['args'][0], $m[1]) . '

' - . BlueScreen::highlightFile($item['args'][0], $m[1]) - ); - } elseif ($item = Helpers::findTrace($e->getTrace(), 'Nette\Utils\Neon::decode')) { - return array( - 'tab' => 'NEON', - 'panel' => BlueScreen::highlightPhp($item['args'][0], $m[1]) - ); - } - } - }); - } - return self::$blueScreen; - } - - - /** - * @return Bar - */ - public static function getBar() - { - if (!self::$bar) { - self::$bar = new Bar; - self::$bar->addPanel(new DefaultBarPanel('time')); - self::$bar->addPanel(new DefaultBarPanel('memory')); - self::$bar->addPanel(new DefaultBarPanel('errors'), __CLASS__ . ':errors'); // filled by _errorHandler() - self::$bar->addPanel(new DefaultBarPanel('dumps'), __CLASS__ . ':dumps'); // filled by barDump() - } - return self::$bar; - } - - - /** - * @return void - */ - public static function setLogger($logger) - { - self::$logger = $logger; - } - - - /** - * @return Logger - */ - public static function getLogger() - { - if (!self::$logger) { - self::$logger = new Logger; - self::$logger->directory = & self::$logDirectory; - self::$logger->email = & self::$email; - self::$logger->mailer = & self::$mailer; - self::$logger->emailSnooze = & self::$emailSnooze; - } - return self::$logger; - } - - - /** - * @return FireLogger - */ - public static function getFireLogger() - { - if (!self::$fireLogger) { - self::$fireLogger = new FireLogger; - } - return self::$fireLogger; - } - - - /** - * Is Debug enabled? - * @return bool - */ - public static function isEnabled() - { - return self::$enabled; - } - - - /** - * Logs message or exception to file (if not disabled) and sends email notification (if enabled). - * @param string|Exception - * @param int one of constant Debugger::INFO, WARNING, ERROR (sends email), CRITICAL (sends email) - * @return string logged error filename - */ - public static function log($message, $priority = self::INFO) - { - if (self::$logDirectory === FALSE) { - return; - - } elseif (!self::$logDirectory) { - throw new Nette\InvalidStateException('Logging directory is not specified in Nette\Diagnostics\Debugger::$logDirectory.'); - } - - $exceptionFilename = NULL; - if ($message instanceof \Exception) { - $exception = $message; - while ($exception) { - $tmp[] = ($exception instanceof ErrorException - ? 'Fatal error: ' . $exception->getMessage() - : get_class($exception) . ": " . $exception->getMessage()) - . " in " . $exception->getFile() . ":" . $exception->getLine(); - $exception = $exception->getPrevious(); - } - $exception = $message; - $message = implode($tmp, "\ncaused by "); - - $hash = md5(preg_replace('~(Resource id #)\d+~', '$1', $exception)); - $exceptionFilename = "exception-" . @date('Y-m-d-H-i-s') . "-$hash.html"; - foreach (new \DirectoryIterator(self::$logDirectory) as $entry) { - if (strpos($entry, $hash)) { - $exceptionFilename = $entry; - $saved = TRUE; - break; - } - } - } elseif (!is_string($message)) { - $message = Dumper::toText($message); - } - - if ($exceptionFilename) { - $exceptionFilename = self::$logDirectory . '/' . $exceptionFilename; - if (empty($saved) && $logHandle = @fopen($exceptionFilename, 'w')) { - ob_start(); // double buffer prevents sending HTTP headers in some PHP - ob_start(function($buffer) use ($logHandle) { fwrite($logHandle, $buffer); }, 4096); - self::getBlueScreen()->render($exception); - ob_end_flush(); - ob_end_clean(); - fclose($logHandle); - } - } - - self::getLogger()->log(array( - @date('[Y-m-d H-i-s]'), - trim($message), - self::$source ? ' @ ' . self::$source : NULL, - $exceptionFilename ? ' @@ ' . basename($exceptionFilename) : NULL - ), $priority); - - return $exceptionFilename ? strtr($exceptionFilename, '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR) : NULL; - } - - - /** - * Shutdown handler to catch fatal errors and execute of the planned activities. - * @return void - * @internal - */ - public static function _shutdownHandler() - { - if (!self::$enabled) { - return; - } - - $error = error_get_last(); - if (in_array($error['type'], array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE))) { - self::_exceptionHandler(Helpers::fixStack(new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line'])), TRUE); - - } elseif (!connection_aborted() && !self::$productionMode && self::isHtmlMode()) { - self::getBar()->render(); - } - } - - - /** - * Handler to catch uncaught exception. - * @param \Exception - * @return void - * @internal - */ - public static function _exceptionHandler(\Exception $exception, $shutdown = FALSE) - { - if (!self::$enabled) { - return; - } - self::$enabled = FALSE; // prevent double rendering - - if (!headers_sent()) { - $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; - $code = isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE ') !== FALSE ? 503 : 500; - header("$protocol $code", TRUE, $code); - } - - try { - if (self::$productionMode) { - try { - self::log($exception, self::ERROR); - } catch (\Exception $e) { - echo 'FATAL ERROR: unable to log error'; - } - - if (self::isHtmlMode()) { - require __DIR__ . '/templates/error.phtml'; - - } else { - echo "ERROR: the server encountered an internal error and was unable to complete your request.\n"; - } - - } else { - if (!connection_aborted() && self::isHtmlMode()) { - self::getBlueScreen()->render($exception); - self::getBar()->render(); - - } elseif (connection_aborted() || !self::fireLog($exception)) { - $file = self::log($exception, self::ERROR); - if (!headers_sent()) { - header("X-Nette-Error-Log: $file"); - } - echo "$exception\n" . ($file ? "(stored in $file)\n" : ''); - if (self::$browser) { - exec(self::$browser . ' ' . escapeshellarg($file)); - } - } - } - - foreach (self::$onFatalError as $handler) { - call_user_func($handler, $exception); - } - - } catch (\Exception $e) { - if (self::$productionMode) { - echo self::isHtmlMode() ? 'FATAL ERROR' : 'FATAL ERROR'; - } else { - echo "FATAL ERROR: thrown ", get_class($e), ': ', $e->getMessage(), - "\nwhile processing ", get_class($exception), ': ', $exception->getMessage(), "\n"; - } - } - - if (!$shutdown) { - exit(254); - } - } - - - /** - * Handler to catch warnings and notices. - * @param int level of the error raised - * @param string error message - * @param string file that the error was raised in - * @param int line number the error was raised at - * @param array an array of variables that existed in the scope the error was triggered in - * @return bool FALSE to call normal error handler, NULL otherwise - * @throws ErrorException - * @internal - */ - public static function _errorHandler($severity, $message, $file, $line, $context) - { - if (self::$scream) { - error_reporting(E_ALL | E_STRICT); - } - - if (self::$lastError !== FALSE && ($severity & error_reporting()) === $severity) { // tryError mode - self::$lastError = new \ErrorException($message, 0, $severity, $file, $line); - return NULL; - } - - if ($severity === E_RECOVERABLE_ERROR || $severity === E_USER_ERROR) { - if (Helpers::findTrace(debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : FALSE), '*::__toString')) { - $previous = isset($context['e']) && $context['e'] instanceof \Exception ? $context['e'] : NULL; - $e = new ErrorException($message, 0, $severity, $file, $line, $previous); - $e->context = $context; - self::_exceptionHandler($e); - } - - $e = new ErrorException($message, 0, $severity, $file, $line); - $e->context = $context; - throw $e; - - } elseif (($severity & error_reporting()) !== $severity) { - return FALSE; // calls normal error handler to fill-in error_get_last() - - } elseif (!self::$productionMode && (is_bool(self::$strictMode) ? self::$strictMode : ((self::$strictMode & $severity) === $severity))) { - $e = new ErrorException($message, 0, $severity, $file, $line); - $e->context = $context; - self::_exceptionHandler($e); - } - - $message = 'PHP ' . (isset(self::$errorTypes[$severity]) ? self::$errorTypes[$severity] : 'Unknown error') . ": $message"; - $count = & self::getBar()->getPanel(__CLASS__ . ':errors')->data["$file|$line|$message"]; - - if ($count++) { // repeated error - return NULL; - - } elseif (self::$productionMode) { - self::log("$message in $file:$line", self::ERROR); - return NULL; - - } else { - self::fireLog(new ErrorException($message, 0, $severity, $file, $line)); - return self::isHtmlMode() ? NULL : FALSE; // FALSE calls normal error handler - } - } - - - /** @deprecated */ - public static function toStringException(\Exception $exception) - { - trigger_error(__METHOD__ . '() is deprecated; use trigger_error(..., E_USER_ERROR) instead.', E_USER_DEPRECATED); - if (self::$enabled) { - self::_exceptionHandler($exception); - } else { - trigger_error($exception->getMessage(), E_USER_ERROR); - } - } - - - /** @deprecated */ - public static function tryError() - { - trigger_error(__METHOD__ . '() is deprecated; use own error handler instead.', E_USER_DEPRECATED); - if (!self::$enabled && self::$lastError === FALSE) { - set_error_handler(array(__CLASS__, '_errorHandler')); - } - self::$lastError = NULL; - } - - - /** @deprecated */ - public static function catchError(& $error) - { - trigger_error(__METHOD__ . '() is deprecated; use own error handler instead.', E_USER_DEPRECATED); - if (!self::$enabled && self::$lastError !== FALSE) { - restore_error_handler(); - } - $error = self::$lastError; - self::$lastError = FALSE; - return (bool) $error; - } - - - /********************* useful tools ****************d*g**/ - - - /** - * Dumps information about a variable in readable format. - * @tracySkipLocation - * @param mixed variable to dump - * @param bool return output instead of printing it? (bypasses $productionMode) - * @return mixed variable itself or dump - */ - public static function dump($var, $return = FALSE) - { - if ($return) { - ob_start(); - Dumper::dump($var, array( - Dumper::DEPTH => self::$maxDepth, - Dumper::TRUNCATE => self::$maxLen, - )); - return ob_get_clean(); - - } elseif (!self::$productionMode) { - Dumper::dump($var, array( - Dumper::DEPTH => self::$maxDepth, - Dumper::TRUNCATE => self::$maxLen, - Dumper::LOCATION => self::$showLocation, - )); - } - - return $var; - } - - - /** - * Starts/stops stopwatch. - * @param string name - * @return float elapsed seconds - */ - public static function timer($name = NULL) - { - static $time = array(); - $now = microtime(TRUE); - $delta = isset($time[$name]) ? $now - $time[$name] : 0; - $time[$name] = $now; - return $delta; - } - - - /** - * Dumps information about a variable in Nette Debug Bar. - * @tracySkipLocation - * @param mixed variable to dump - * @param string optional title - * @param array dumper options - * @return mixed variable itself - */ - public static function barDump($var, $title = NULL, array $options = NULL) - { - if (!self::$productionMode) { - self::getBar()->getPanel(__CLASS__ . ':dumps')->data[] = array('title' => $title, 'dump' => Dumper::toHtml($var, (array) $options + array( - Dumper::DEPTH => self::$maxDepth, - Dumper::TRUNCATE => self::$maxLen, - Dumper::LOCATION => self::$showLocation, - ))); - } - return $var; - } - - - /** - * Sends message to FireLogger console. - * @param mixed message to log - * @return bool was successful? - */ - public static function fireLog($message) - { - if (!self::$productionMode) { - return self::getFireLogger()->log($message); - } - } - - - private static function isHtmlMode() - { - return empty($_SERVER['HTTP_X_REQUESTED_WITH']) - && PHP_SAPI !== 'cli' - && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list())); - } - - - public static function addPanel(IBarPanel $panel, $id = NULL) - { - return self::getBar()->addPanel($panel, $id); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/DefaultBarPanel.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/DefaultBarPanel.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/DefaultBarPanel.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/DefaultBarPanel.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -id = $id; - } - - - /** - * Renders HTML code for custom tab. - * @return string - */ - public function getTab() - { - ob_start(); - require __DIR__ . "/templates/bar.{$this->id}.tab.phtml"; - return ob_get_clean(); - } - - - /** - * Renders HTML code for custom panel. - * @return string - */ - public function getPanel() - { - ob_start(); - if (is_file(__DIR__ . "/templates/bar.{$this->id}.panel.phtml")) { - require __DIR__ . "/templates/bar.{$this->id}.panel.phtml"; - } - return ob_get_clean(); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/Dumper.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/Dumper.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/Dumper.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/Dumper.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,337 +0,0 @@ - '1;33', - 'null' => '1;33', - 'number' => '1;32', - 'string' => '1;36', - 'array' => '1;31', - 'key' => '1;37', - 'object' => '1;31', - 'visibility' => '1;30', - 'resource' => '1;37', - 'indent' => '1;30', - ); - - /** @var array */ - public static $resources = array( - 'stream' => 'stream_get_meta_data', - 'stream-context' => 'stream_context_get_options', - 'curl' => 'curl_getinfo', - ); - - - /** - * Dumps variable to the output. - * @return mixed variable - */ - public static function dump($var, array $options = NULL) - { - if (PHP_SAPI !== 'cli' && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list()))) { - echo self::toHtml($var, $options); - } elseif (self::detectColors()) { - echo self::toTerminal($var, $options); - } else { - echo self::toText($var, $options); - } - return $var; - } - - - /** - * Dumps variable to HTML. - * @return string - */ - public static function toHtml($var, array $options = NULL) - { - $options = (array) $options + array( - self::DEPTH => 4, - self::TRUNCATE => 150, - self::COLLAPSE => FALSE, - self::COLLAPSE_COUNT => 7, - self::LOCATION => FALSE, - ); - list($file, $line, $code) = $options[self::LOCATION] ? self::findLocation() : NULL; - return '
' : '>')
-			. self::dumpVar($var, $options)
-			. ($file ? 'in ' . Helpers::editorLink($file, $line) . '' : '')
-			. "
\n"; - } - - - /** - * Dumps variable to plain text. - * @return string - */ - public static function toText($var, array $options = NULL) - { - return htmlspecialchars_decode(strip_tags(self::toHtml($var, $options)), ENT_QUOTES); - } - - - /** - * Dumps variable to x-terminal. - * @return string - */ - public static function toTerminal($var, array $options = NULL) - { - return htmlspecialchars_decode(strip_tags(preg_replace_callback('#|#', function($m) { - return "\033[" . (isset($m[1], Dumper::$terminalColors[$m[1]]) ? Dumper::$terminalColors[$m[1]] : '0') . "m"; - }, self::toHtml($var, $options))), ENT_QUOTES); - } - - - /** - * Internal toHtml() dump implementation. - * @param mixed variable to dump - * @param array options - * @param int current recursion level - * @return string - */ - private static function dumpVar(& $var, array $options, $level = 0) - { - if (method_exists(__CLASS__, $m = 'dump' . gettype($var))) { - return self::$m($var, $options, $level); - } else { - return "unknown type\n"; - } - } - - - private static function dumpNull() - { - return "NULL\n"; - } - - - private static function dumpBoolean(& $var) - { - return '' . ($var ? 'TRUE' : 'FALSE') . "\n"; - } - - - private static function dumpInteger(& $var) - { - return "$var\n"; - } - - - private static function dumpDouble(& $var) - { - $var = is_finite($var) - ? ($tmp = json_encode($var)) . (strpos($tmp, '.') === FALSE ? '.0' : '') - : var_export($var, TRUE); - return "$var\n"; - } - - - private static function dumpString(& $var, $options) - { - return '' - . self::encodeString($options[self::TRUNCATE] && strlen($var) > $options[self::TRUNCATE] ? substr($var, 0, $options[self::TRUNCATE]) . ' ... ' : $var) - . '' . (strlen($var) > 1 ? ' (' . strlen($var) . ')' : '') . "\n"; - } - - - private static function dumpArray(& $var, $options, $level) - { - static $marker; - if ($marker === NULL) { - $marker = uniqid("\x00", TRUE); - } - - $out = 'array ('; - - if (empty($var)) { - return $out . ")\n"; - - } elseif (isset($var[$marker])) { - return $out . (count($var) - 1) . ") [ RECURSION ]\n"; - - } elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH]) { - $collapsed = $level ? count($var) >= $options[self::COLLAPSE_COUNT] : $options[self::COLLAPSE]; - $out = '' . $out . count($var) . ")\n'; - $var[$marker] = TRUE; - foreach ($var as $k => & $v) { - if ($k !== $marker) { - $out .= ' ' . str_repeat('| ', $level) . '' - . '' . (preg_match('#^\w+\z#', $k) ? $k : self::encodeString($k)) . ' => ' - . self::dumpVar($v, $options, $level + 1); - } - } - unset($var[$marker]); - return $out . ''; - - } else { - return $out . count($var) . ") [ ... ]\n"; - } - } - - - private static function dumpObject(& $var, $options, $level) - { - if ($var instanceof \Closure) { - $rc = new \ReflectionFunction($var); - $fields = array(); - foreach ($rc->getParameters() as $param) { - $fields[] = '$' . $param->getName(); - } - $fields = array( - 'file' => $rc->getFileName(), 'line' => $rc->getStartLine(), - 'variables' => $rc->getStaticVariables(), 'parameters' => implode(', ', $fields) - ); - } elseif ($var instanceof \SplFileInfo) { - $fields = array('path' => $var->getPathname()); - } elseif ($var instanceof \SplObjectStorage) { - $fields = array(); - foreach (clone $var as $obj) { - $fields[] = array('object' => $obj, 'data' => $var[$obj]); - } - } else { - $fields = (array) $var; - } - - static $list = array(); - $rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var); - $out = 'getFileName() ? ' data-nette-href="' . htmlspecialchars(strtr(Debugger::$editor, array('%file' => rawurlencode($rc->getFileName()), '%line' => $rc->getStartLine()))) . '"' : '') - . '>' . get_class($var) . ' #' . substr(md5(spl_object_hash($var)), 0, 4) . ''; - - if (empty($fields)) { - return $out . "\n"; - - } elseif (in_array($var, $list, TRUE)) { - return $out . " { RECURSION }\n"; - - } elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH] || $var instanceof \Closure) { - $collapsed = $level ? count($fields) >= $options[self::COLLAPSE_COUNT] : $options[self::COLLAPSE]; - $out = '' . $out . "\n'; - $list[] = $var; - foreach ($fields as $k => & $v) { - $vis = ''; - if ($k[0] === "\x00") { - $vis = ' ' . ($k[1] === '*' ? 'protected' : 'private') . ''; - $k = substr($k, strrpos($k, "\x00") + 1); - } - $out .= ' ' . str_repeat('| ', $level) . '' - . '' . (preg_match('#^\w+\z#', $k) ? $k : self::encodeString($k)) . "$vis => " - . self::dumpVar($v, $options, $level + 1); - } - array_pop($list); - return $out . ''; - - } else { - return $out . " { ... }\n"; - } - } - - - private static function dumpResource(& $var, $options, $level) - { - $type = get_resource_type($var); - $out = '' . htmlSpecialChars($type) . ' resource'; - if (isset(self::$resources[$type])) { - $out = "$out\n
"; - foreach (call_user_func(self::$resources[$type], $var) as $k => $v) { - $out .= ' ' . str_repeat('| ', $level) . '' - . '' . htmlSpecialChars($k) . " => " . self::dumpVar($v, $options, $level + 1); - } - return $out . '
'; - } - return "$out\n"; - } - - - private static function encodeString($s) - { - static $table; - if ($table === NULL) { - foreach (array_merge(range("\x00", "\x1F"), range("\x7F", "\xFF")) as $ch) { - $table[$ch] = '\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT); - } - $table["\\"] = '\\\\'; - $table["\r"] = '\r'; - $table["\n"] = '\n'; - $table["\t"] = '\t'; - } - - if (preg_match('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u', $s) || preg_last_error()) { - $s = strtr($s, $table); - } - return '"' . htmlSpecialChars($s, ENT_NOQUOTES) . '"'; - } - - - /** - * Finds the location where dump was called. - * @return array [file, line, code] - */ - private static function findLocation() - { - foreach (debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : FALSE) as $item) { - if (isset($item['class']) && $item['class'] === __CLASS__) { - $location = $item; - continue; - } elseif (isset($item['function'])) { - try { - $reflection = isset($item['class']) - ? new \ReflectionMethod($item['class'], $item['function']) - : new \ReflectionFunction($item['function']); - if (preg_match('#\s@tracySkipLocation\s#', $reflection->getDocComment())) { - $location = $item; - continue; - } - } catch (\ReflectionException $e) {} - } - break; - } - - if (isset($location['file'], $location['line']) && is_file($location['file'])) { - $lines = file($location['file']); - $line = $lines[$location['line'] - 1]; - return array( - $location['file'], - $location['line'], - trim(preg_match('#\w*dump(er::\w+)?\(.*\)#i', $line, $m) ? $m[0] : $line) - ); - } - } - - - /** - * @return bool - */ - private static function detectColors() - { - return self::$terminalColors && - (getenv('ConEmuANSI') === 'ON' - || getenv('ANSICON') !== FALSE - || (defined('STDOUT') && function_exists('posix_isatty') && posix_isatty(STDOUT))); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/FireLogger.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/FireLogger.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/FireLogger.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/FireLogger.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,181 +0,0 @@ - array()); - - - /** - * Sends message to FireLogger console. - * @param mixed - * @return bool was successful? - */ - public static function log($message, $priority = self::DEBUG) - { - if (!isset($_SERVER['HTTP_X_FIRELOGGER']) || headers_sent()) { - return FALSE; - } - - $item = array( - 'name' => 'PHP', - 'level' => $priority, - 'order' => count(self::$payload['logs']), - 'time' => str_pad(number_format((microtime(TRUE) - Debugger::$time) * 1000, 1, '.', ' '), 8, '0', STR_PAD_LEFT) . ' ms', - 'template' => '', - 'message' => '', - 'style' => 'background:#767ab6', - ); - - $args = func_get_args(); - if (isset($args[0]) && is_string($args[0])) { - $item['template'] = array_shift($args); - } - - if (isset($args[0]) && $args[0] instanceof \Exception) { - $e = array_shift($args); - $trace = $e->getTrace(); - if (isset($trace[0]['class']) && $trace[0]['class'] === 'Nette\Diagnostics\Debugger' - && ($trace[0]['function'] === '_shutdownHandler' || $trace[0]['function'] === '_errorHandler') - ) { - unset($trace[0]); - } - - $file = str_replace(dirname(dirname(dirname($e->getFile()))), "\xE2\x80\xA6", $e->getFile()); - $item['template'] = ($e instanceof \ErrorException ? '' : get_class($e) . ': ') - . $e->getMessage() . ($e->getCode() ? ' #' . $e->getCode() : '') . ' in ' . $file . ':' . $e->getLine(); - $item['pathname'] = $e->getFile(); - $item['lineno'] = $e->getLine(); - - } else { - $trace = debug_backtrace(); - if (isset($trace[1]['class']) && $trace[1]['class'] === 'Nette\Diagnostics\Debugger' - && ($trace[1]['function'] === 'fireLog') - ) { - unset($trace[0]); - } - - foreach ($trace as $frame) { - if (isset($frame['file']) && is_file($frame['file'])) { - $item['pathname'] = $frame['file']; - $item['lineno'] = $frame['line']; - break; - } - } - } - - $item['exc_info'] = array('', '', array()); - $item['exc_frames'] = array(); - - foreach ($trace as $frame) { - $frame += array('file' => NULL, 'line' => NULL, 'class' => NULL, 'type' => NULL, 'function' => NULL, 'object' => NULL, 'args' => NULL); - $item['exc_info'][2][] = array($frame['file'], $frame['line'], "$frame[class]$frame[type]$frame[function]", $frame['object']); - $item['exc_frames'][] = $frame['args']; - } - - if (isset($args[0]) && in_array($args[0], array(self::DEBUG, self::INFO, self::WARNING, self::ERROR, self::CRITICAL), TRUE)) { - $item['level'] = array_shift($args); - } - - $item['args'] = $args; - - self::$payload['logs'][] = self::jsonDump($item, -1); - foreach (str_split(base64_encode(@json_encode(self::$payload)), 4990) as $k => $v) { // intentionally @ - header("FireLogger-de11e-$k:$v"); - } - return TRUE; - } - - - /** - * Dump implementation for JSON. - * @param mixed variable to dump - * @param int current recursion level - * @return string - */ - private static function jsonDump(& $var, $level = 0) - { - if (is_bool($var) || is_null($var) || is_int($var) || is_float($var)) { - return $var; - - } elseif (is_string($var)) { - if (Debugger::$maxLen && strlen($var) > Debugger::$maxLen) { - $var = substr($var, 0, Debugger::$maxLen) . " \xE2\x80\xA6 "; - } - return Nette\Utils\Strings::fixEncoding($var); - - } elseif (is_array($var)) { - static $marker; - if ($marker === NULL) { - $marker = uniqid("\x00", TRUE); - } - if (isset($var[$marker])) { - return "\xE2\x80\xA6RECURSION\xE2\x80\xA6"; - - } elseif ($level < Debugger::$maxDepth || !Debugger::$maxDepth) { - $var[$marker] = TRUE; - $res = array(); - foreach ($var as $k => & $v) { - if ($k !== $marker) { - $res[self::jsonDump($k)] = self::jsonDump($v, $level + 1); - } - } - unset($var[$marker]); - return $res; - - } else { - return " \xE2\x80\xA6 "; - } - - } elseif (is_object($var)) { - $arr = (array) $var; - static $list = array(); - if (in_array($var, $list, TRUE)) { - return "\xE2\x80\xA6RECURSION\xE2\x80\xA6"; - - } elseif ($level < Debugger::$maxDepth || !Debugger::$maxDepth) { - $list[] = $var; - $res = array("\x00" => '(object) ' . get_class($var)); - foreach ($arr as $k => & $v) { - if ($k[0] === "\x00") { - $k = substr($k, strrpos($k, "\x00") + 1); - } - $res[self::jsonDump($k)] = self::jsonDump($v, $level + 1); - } - array_pop($list); - return $res; - - } else { - return " \xE2\x80\xA6 "; - } - - } elseif (is_resource($var)) { - return "resource " . get_resource_type($var); - - } else { - return "unknown type"; - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/Helpers.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/Helpers.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/Helpers.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/Helpers.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -href(strtr(Debugger::$editor, array('%file' => rawurlencode($file), '%line' => $line))) - ->title("$file:$line") - ->setHtml(htmlSpecialChars(rtrim($dir, DIRECTORY_SEPARATOR), ENT_IGNORE) . DIRECTORY_SEPARATOR . '' . htmlSpecialChars(basename($file), ENT_IGNORE) . '' . ($line ? ":$line" : '')); - } else { - return Nette\Utils\Html::el('span')->setText($file . ($line ? ":$line" : '')); - } - } - - - public static function findTrace(array $trace, $method, & $index = NULL) - { - $m = explode('::', $method); - foreach ($trace as $i => $item) { - if (isset($item['function']) && $item['function'] === end($m) - && isset($item['class']) === isset($m[1]) - && (!isset($item['class']) || $item['class'] === $m[0] || $m[0] === '*' || is_subclass_of($item['class'], $m[0])) - ) { - $index = $i; - return $item; - } - } - } - - - public static function fixStack($exception) - { - if (function_exists('xdebug_get_function_stack')) { - $stack = array(); - foreach (array_slice(array_reverse(xdebug_get_function_stack()), 2, -1) as $row) { - $frame = array( - 'file' => $row['file'], - 'line' => $row['line'], - 'function' => isset($row['function']) ? $row['function'] : '*unknown*', - 'args' => array(), - ); - if (!empty($row['class'])) { - $frame['type'] = isset($row['type']) && $row['type'] === 'dynamic' ? '->' : '::'; - $frame['class'] = $row['class']; - } - $stack[] = $frame; - } - $ref = new \ReflectionProperty('Exception', 'trace'); - $ref->setAccessible(TRUE); - $ref->setValue($exception, $stack); - } - return $exception; - } - - - /** @deprecated */ - public static function htmlDump($var) - { - trigger_error(__METHOD__ . '() is deprecated; use Nette\Diagnostics\Dumper::toHtml() instead.', E_USER_DEPRECATED); - return Dumper::toHtml($var); - } - - /** @deprecated */ - public static function clickableDump($var) - { - trigger_error(__METHOD__ . '() is deprecated; use Nette\Diagnostics\Dumper::toHtml() instead.', E_USER_DEPRECATED); - return Dumper::toHtml($var); - } - - /** @deprecated */ - public static function textDump($var) - { - trigger_error(__METHOD__ . '() is deprecated; use Nette\Diagnostics\Dumper::toText() instead.', E_USER_DEPRECATED); - return Dumper::toText($var); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/IBarPanel.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/IBarPanel.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/IBarPanel.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/IBarPanel.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -directory)) { - throw new Nette\DirectoryNotFoundException("Directory '$this->directory' is not found or is not directory."); - } - - if (is_array($message)) { - $message = implode(' ', $message); - } - $message = preg_replace('#\s*\r?\n\s*#', ' ', trim($message)); - $file = $this->directory . '/' . strtolower($priority ?: self::INFO) . '.log'; - $res = (bool) file_put_contents($file, $message . PHP_EOL, FILE_APPEND | LOCK_EX); - - if (($priority === self::ERROR || $priority === self::CRITICAL) && $this->email && $this->mailer - && @filemtime($this->directory . '/email-sent') + $this->emailSnooze < time() // @ - file may not exist - && @file_put_contents($this->directory . '/email-sent', 'sent') // @ - file may not be writable - ) { - call_user_func($this->mailer, $message, implode(', ', (array) $this->email)); - } - return $res; - } - - - /** - * Default mailer. - * @param string - * @param string - * @return void - */ - public static function defaultMailer($message, $email) - { - $host = preg_replace('#[^\w.-]+#', '', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n')); - $parts = str_replace( - array("\r\n", "\n"), - array("\n", PHP_EOL), - array( - 'headers' => implode("\n", array( - "From: noreply@$host", - 'X-Mailer: Nette Framework', - 'Content-Type: text/plain; charset=UTF-8', - 'Content-Transfer-Encoding: 8bit', - )) . "\n", - 'subject' => "PHP: An error occurred on the server $host", - 'body' => "[" . @date('Y-m-d H:i:s') . "] $message", // @ - timezone may not be set - ) - ); - - mail($email, $parts['subject'], $parts['body'], $parts['headers']); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/OutputDebugger.php php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/OutputDebugger.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/OutputDebugger.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/OutputDebugger.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -start(); - } - - - public function start() - { - foreach (get_included_files() as $file) { - if (fread(fopen($file, 'r'), 3) === self::BOM) { - $this->list[] = array($file, 1, self::BOM); - } - } - ob_start(array($this, 'handler'), PHP_VERSION_ID >= 50400 ? 1 : 2); - } - - - public function handler($s, $phase) - { - $trace = debug_backtrace(FALSE); - if (isset($trace[0]['file'], $trace[0]['line'])) { - if ($this->lastFile === $trace[0]['file']) { - $this->list[count($this->list) - 1][2] .= $s; - } else { - $this->list[] = array($this->lastFile = $trace[0]['file'], $trace[0]['line'], $s); - } - } - if ($phase === PHP_OUTPUT_HANDLER_FINAL) { - return $this->renderHtml(); - } - } - - - private function renderHtml() - { - $res = ''; - foreach ($this->list as $item) { - list($file, $line, $s) = $item; - $res .= Helpers::editorLink($item[0], $item[1]) . ' ' - . str_replace(self::BOM, 'BOM', Dumper::toHtml($item[2])) . "
\n"; - } - return $res . '
'; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.css php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.css --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.css 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.css 1970-01-01 00:00:00.000000000 +0000 @@ -1,318 +0,0 @@ -/** - * Debugger Bar - * - * This file is part of the Nette Framework (http://nette.org) - * Copyright (c) 2004 David Grudl (http://davidgrudl.com) - */ - -/* common styles */ -#nette-debug { - display: none; - direction: ltr; -} - -body#nette-debug { - margin: 5px 5px 0; - display: block; -} - -body #nette-debug { - position: absolute; - bottom: 0; - right: 0; -} - -#nette-debug * { - font: inherit; - color: inherit; - background: transparent; - margin: 0; - padding: 0; - border: none; - text-align: inherit; - list-style: inherit; - opacity: 1; - border-radius: 0; - box-shadow: none; -} - -#nette-debug b, #nette-debug strong { - font-weight: bold; -} - -#nette-debug i, #nette-debug em { - font-style: italic; -} - -#nette-debug a { - color: #125EAE; - text-decoration: none; -} - -#nette-debug .nette-panel a { - color: #125EAE; - text-decoration: none; -} - -#nette-debug a:hover, #nette-debug a:active, #nette-debug a:focus { - background-color: #125EAE; - color: white; -} - -#nette-debug .nette-panel h2, #nette-debug .nette-panel h3, #nette-debug .nette-panel p { - margin: .4em 0; -} - -#nette-debug .nette-panel table { - border-collapse: collapse; - background: #FDF5CE; -} - -#nette-debug .nette-panel tr:nth-child(2n) td { - background: #F7F0CB; -} - -#nette-debug .nette-panel td, #nette-debug .nette-panel th { - border: 1px solid #E6DFBF; - padding: 2px 5px; - vertical-align: top; - text-align: left; -} - -#nette-debug .nette-panel th { - background: #F4F3F1; - color: #655E5E; - font-size: 90%; - font-weight: bold; -} - -#nette-debug .nette-panel pre, #nette-debug .nette-panel code { - font: 9pt/1.5 Consolas, monospace; -} - -#nette-debug table .nette-right { - text-align: right; -} - - -/* bar */ -#nette-debug-bar { - font: normal normal 12px/21px Tahoma, sans-serif; - color: #333; - border: 1px solid #c9c9c9; - background: #EDEAE0 url('data:image/png;base64,R0lGODlhAQAVALMAAOTh1/Px6eHe1fHv5e/s4vLw6Ofk2u3q4PPw6PPx6PDt5PLw5+Dd1OXi2Ojm3Orn3iH5BAAAAAAALAAAAAABABUAAAQPMISEyhpYkfOcaQAgCEwEADs=') top; - position: fixed; - right: 0; - bottom: 0; - overflow: auto; - min-height: 21px; - - min-width: 50px; - white-space: nowrap; - - z-index: 30000; - opacity: .9; - transition: opacity 0.2s; - - border-radius: 3px; - box-shadow: 1px 1px 10px rgba(0, 0, 0, .15); -} - -#nette-debug-bar:hover { - opacity: 1; - transition: opacity 0.1s; -} - -#nette-debug-bar ul { - list-style: none none; - margin-left: 4px; - clear: left; -} - -#nette-debug-bar li { - float: left; -} - -#nette-debug-bar ul.nette-previous li { - font-size: 90%; - opacity: .6; - background: #F5F3EE; -} - -#nette-debug-bar ul.nette-previous li:first-child { - width: 45px; -} - -#nette-debug-bar img { - vertical-align: middle; - position: relative; - top: -1px; - margin-right: 3px; -} - -#nette-debug-bar li a { - color: #000; - display: block; - padding: 0 4px; -} - -#nette-debug-bar li a:hover { - color: black; - background: #c3c1b8; -} - -#nette-debug-bar li .nette-warning { - color: #D32B2B; - font-weight: bold; -} - -#nette-debug-bar li > span { - padding: 0 4px; -} - -#nette-debug-logo { - background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAPCAYAAABwfkanAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABiFJREFUSMe1VglPlGcQ5i+1xjZNqxREtGq8ahCPWsVGvEDBA1BBRQFBDjkE5BYUzwpovRBUREBEBbl3OVaWPfj2vi82eTrvbFHamLRJ4yYTvm+u95mZZ96PoKAv+LOatXBYZ+Bx6uFy6DGnt1m0EOKwSmQzwmHTgX5B/1W+yM9GYJ02CX6/B/5ZF+w2A4x6FYGTYDVp4PdY2Tbrs5N+mnRa2Km4/wV6rhPzQQj5fDc1mJM5nd0iYdZtQWtrCxobGnDpUiledTynbuvg99mgUMhw924Trl2rR01NNSTNJE9iDpTV8innv4K2kZPLroPXbYLHZeSu2K1aeF0muJ2GvwGzmNSwU2E+svm8ZrgdBliMaha/34Vx+RAKCgpwpa4OdbW1UE/L2cc/68WtWzdRVlaG6uoqtD1/BA/pA1MIxLvtes7pc5vhoDOE/rOgbVSdf9aJWa8dBp0Kyg+jdLiTx2vQKWEyqGmcNkqg4iTC1+dzQatWkK+cJqPD7KyFaKEjvRuNjY24fLkGdXW1ePjwAeX4QHonDNI0A75+/RpqqqshH+6F2UAUMaupYXouykV0mp6SQ60coxgL8Z4aMg/4x675/V60v3jKB+Xl5WJibIC4KPEIS0qKqWv5GOh7BZ/HSIk9kA33o7y8DOfPZ6GQOipkXDZAHXKxr4ipqqpkKS6+iIrycgz2dyMnJxtVlZUsotNZWZmor79KBbvgpdjm5sfIzc1hv4L8fKJPDTfJZZc+gRYKr8sAEy2DcBRdEEk62ltx9uwZ5qNILoDU1l6mbrvx5EkzUlKSuTiR7PHjR3x4fv4FyIbeIic7G5WVFUyN+qtX+Lnt2SPcvn2LfURjhF7kE4WPDr+Bx+NEUVEhkpNPoImm5CSOl5aUIC3tLOMR59gtAY4HidGIzj14cB8ZGRkM8kJeHk6cOI4xWR8vSl5uLlJTT6O74xnT5lB8PM6cSYXVqILb5UBWZiYSExMYkE4zzjqX00QHG+h9AjPqMei0k3ywy2khMdNiq6BVCf04T6ekuBgJCUdRUVHOBQwPvkNSUiLjaGi4Q/5qFgYtHgTXRJdTT59GenoaA5gY64deq0Bc3EGuNj4+DnppEheLijhZRkY6SktLsGPHdi6irOwSFTRAgO04deokTSIFsbExuHfvLnFSx8DevelAfFwcA0lJTqZi5PDS9aci/sbE7Oe4wsICbtD27b/ye1NTI3FeSX4W2gdFALRD3A4eM44ePcKViuD79/8gnZP5Kg4+cCAW2dnnqUM2Lujw4UM4ePAA2ztfPsHIYA/sdOt43A50d7UFCjkUj+joXVBMDJDeDhcVk08cjd61C3v37uFYp8PKXX3X8xJRUTtw7FgSn3Xzxg10d7ZCqRjkM+02C7pettDNogqAFjzxuI3YHR2Nffv2coXy0V44HGZERm7kJNu2/cK8bW9rwbp1axnMnj27uUijQQOb1QyTcYZ3YMOGn/Hbzp1crAAvaDfY38O5hW3//n0ce+TIYWiUcub1xo0R2Lp1y8cYsUMWM125VhPe93Zj7do1vEPi26GfUdBFbhK8tGHrli1YsWwpgoOD0dXRQqAtXMCy8DBs3rwJoSGLsWrVclylBdoUGYlVK1dg9eqVCFsSSs8/4btvvmUwEnE0KTERISE/IiIiAsGLF2HhwgU8qbc97QgPX8qFr1mzGgu+/opzdL5o5l1aEhqC9evXYWlYKFYsD6e/YVj0w/dMGZVyBDMqeaDTRuKpkxYjIz2dOyeup6H3r2kkOuJ1H3N5Z1QUzp3LQF9vJ4xGLQYHXiM9LY0pEhsTg+PHj9HNcJu4OcL3uaQZY86LiZw8mcJTkmhBTUYJbU8fcoygobgWR4Z6iKtTPLE7d35HYkICT1dIZuY59HQ9412StBPQTMvw8Z6WaMNFxy3Gab4TeQT0M9IHwUT/G0i0MGIJ9CTiJjBIH+iQaQbC7+QnfEXiQL6xgF09TjETHCt8RbeMuil+D8RNsV1LHdQoZfR/iJJzCZuYmEE/Bd3MJNs/+0UURgFWJJ//aQ8k+CsxVTqnVytHObkQrUoG8T4/bs4u4ubbxLPwFzYNPc8HI2zijLm84l39Dx8hfwJenFezFBKKQwAAAABJRU5ErkJggg==') 0 50% no-repeat; - min-width: 45px; - cursor: move; -} - -#nette-debug-logo span { - display: none; -} - - -/* panels */ -#nette-debug .nette-panel { - font: normal normal 12px/1.5 sans-serif; - background: white; - color: #333; - text-align: left; -} - -#nette-debug h1 { - font: normal normal 23px/1.4 Tahoma, sans-serif; - color: #575753; - margin: -5px -5px 5px; - padding: 0 25px 5px 5px; -} - -#nette-debug .nette-mode-peek .nette-inner, #nette-debug .nette-mode-float .nette-inner { - max-width: 700px; - max-height: 500px; - overflow: auto; -} - -#nette-debug .nette-panel .nette-icons { - display: none; -} - -#nette-debug .nette-mode-peek { - display: none; - position: fixed; - right: 0; - bottom: 0; - padding: 10px; - min-width: 150px; - min-height: 50px; - border-radius: 5px; - box-shadow: 1px 1px 20px rgba(102, 102, 102, 0.36); - border: 1px solid rgba(0, 0, 0, 0.1); -} - -#nette-debug .nette-mode-peek h1 { - cursor: move; -} - -#nette-debug .nette-mode-float { - position: fixed; - right: 0; - bottom: 0; - padding: 10px; - min-width: 150px; - min-height: 50px; - border-radius: 5px; - opacity: .95; - transition: opacity 0.2s; - box-shadow: 1px 1px 30px rgba(102, 102, 102, 0.36); - border: 1px solid rgba(0, 0, 0, 0.1); -} - -#nette-debug .nette-focused { - opacity: 1; - transition: opacity 0.1s; -} - -#nette-debug .nette-mode-float h1 { - cursor: move; -} - -#nette-debug .nette-mode-float .nette-icons { - display: block; - position: absolute; - top: 0; - right: 5px; - font-size: 18px; -} - -#nette-debug .nette-icons a { - color: #575753; -} - -#nette-debug .nette-icons a:hover { - color: white; -} - - -/* dump */ -#nette-debug pre.nette-dump div { - padding-left: 3ex; -} - -#nette-debug pre.nette-dump div div { - border-left: 1px solid rgba(0, 0, 0, .1); - margin-left: .5ex; -} - -#nette-debug pre.nette-dump { - background: #FDF5CE; - padding: .4em .7em; - border: 1px dotted silver; - overflow: auto; -} - -#nette-debug table pre.nette-dump { - padding: 0; - margin: 0; - border: none; -} - -#nette-debug .nette-dump-array, #nette-debug .nette-dump-object { - color: #C22; -} - -#nette-debug .nette-dump-string { - color: #35D; -} - -#nette-debug .nette-dump-number { - color: #090; -} - -#nette-debug .nette-dump-null, #nette-debug .nette-dump-bool { - color: #850; -} - -#nette-debug .nette-dump-visibility, #nette-debug .nette-dump-hash { - font-size: 85%; color: #999; -} - -#nette-debug .nette-dump-indent { - display: none; -} - - -@media print { - #nette-debug * { - display: none; - } -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.dumps.panel.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.dumps.panel.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.dumps.panel.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.dumps.panel.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ - - - - -

Dumped variables

- -
-data as $item): ?> - -

- - - - - - - -
- -
diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.dumps.tab.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.dumps.tab.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.dumps.tab.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.dumps.tab.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -data)) { - return; -} -?> -variables diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.errors.panel.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.errors.panel.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.errors.panel.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.errors.panel.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ - -

Errors

- -
- - -data as $item => $count): list($file, $line, $message) = explode('|', $item, 3) ?> - - - - - -
-
diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.errors.tab.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.errors.tab.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.errors.tab.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.errors.tab.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -data)) { - return; -} -?> -data), $sum > 1 ? ' errors' : ' error' ?> diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.js php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.js --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.js 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,293 +0,0 @@ -/** - * Debugger Bar - * - * This file is part of the Nette Framework (http://nette.org) - * Copyright (c) 2004 David Grudl (http://davidgrudl.com) - */ - -(function(){ - - var $ = Nette.Query.factory; - - var Panel = Nette.DebugPanel = function(id) { - this.id = 'nette-debug-panel-' + id; - this.elem = $('#' + this.id); - }; - - Panel.PEEK = 'nette-mode-peek'; - Panel.FLOAT = 'nette-mode-float'; - Panel.WINDOW = 'nette-mode-window'; - Panel.FOCUSED = 'nette-focused'; - Panel.zIndex = 20000; - - Panel.prototype.init = function() { - var _this = this; - - this.elem.data().onmove = function(coords) { - _this.moveConstrains(this, coords); - }; - - this.elem.draggable({ - rightEdge: true, - bottomEdge: true, - handle: this.elem.find('h1'), - stop: function() { - _this.toFloat(); - } - - }).bind('mouseenter', function() { - _this.focus(); - - }).bind('mouseleave', function() { - _this.blur(); - }); - - this.elem.find('.nette-icons').find('a').bind('click', function(e) { - if (this.rel === 'close') { - _this.toPeek(); - } else { - _this.toWindow(); - } - e.preventDefault(); - }); - - this.restorePosition(); - }; - - Panel.prototype.is = function(mode) { - return this.elem.hasClass(mode); - }; - - Panel.prototype.focus = function(callback) { - var elem = this.elem; - if (this.is(Panel.WINDOW)) { - elem.data().win.focus(); - } else { - clearTimeout(elem.data().displayTimeout); - elem.data().displayTimeout = setTimeout(function() { - elem.addClass(Panel.FOCUSED).show(); - elem[0].style.zIndex = Panel.zIndex++; - if (callback) { - callback(); - } - }, 50); - } - }; - - Panel.prototype.blur = function() { - var elem = this.elem; - elem.removeClass(Panel.FOCUSED); - if (this.is(Panel.PEEK)) { - clearTimeout(elem.data().displayTimeout); - elem.data().displayTimeout = setTimeout(function() { - elem.hide(); - }, 50); - } - }; - - Panel.prototype.toFloat = function() { - this.elem.removeClass(Panel.WINDOW). - removeClass(Panel.PEEK). - addClass(Panel.FLOAT). - show(); - this.reposition(); - }; - - Panel.prototype.toPeek = function() { - this.elem.removeClass(Panel.WINDOW). - removeClass(Panel.FLOAT). - addClass(Panel.PEEK). - hide(); - document.cookie = this.id + '=; path=/'; // delete position - }; - - Panel.prototype.toWindow = function() { - var offset = this.elem.offset(); - offset.left += typeof window.screenLeft === 'number' ? window.screenLeft : (window.screenX + 10); - offset.top += typeof window.screenTop === 'number' ? window.screenTop : (window.screenY + 50); - - var win = window.open('', this.id.replace(/-/g, '_'), 'left='+offset.left+',top='+offset.top+',width='+offset.width+',height='+(offset.height+15)+',resizable=yes,scrollbars=yes'); - if (!win) { - return; - } - - var doc = win.document; - doc.write(' - - - - - - - - -
- -
- ¤ - × -
-
- - -
-
    - - -
      '; ?> -
    • ', trim($panel['tab']), ''; endif ?>
    • - -
    • ×
    • -
    -
- - - - - - diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.time.tab.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.time.tab.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bar.time.tab.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bar.time.tab.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - - ms diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bluescreen.css php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bluescreen.css --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bluescreen.css 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bluescreen.css 1970-01-01 00:00:00.000000000 +0000 @@ -1,271 +0,0 @@ -/** - * Debugger Bluescreen - * - * This file is part of the Nette Framework (http://nette.org) - * Copyright (c) 2004 David Grudl (http://davidgrudl.com) - */ - -html { - overflow-y: scroll; -} - -#netteBluescreen { - font: 9pt/1.5 Verdana, sans-serif; - background: white; - color: #333; - position: absolute; - left: 0; - top: 0; - width: 100%; - text-align: left; -} - -#netteBluescreen * { - font: inherit; - color: inherit; - background: transparent; - border: none; - margin: 0; - padding: 0; - text-align: inherit; - text-indent: 0; -} - -#netteBluescreen b { - font-weight: bold; -} - -#netteBluescreen i { - font-style: italic; -} - -#netteBluescreen a { - text-decoration: none; - color: #328ADC; - padding: 2px 4px; - margin: -2px -4px; -} - -#netteBluescreen a:hover, #netteBluescreen a:active, #netteBluescreen a:focus { - color: #085AA3; -} - -#netteBluescreenIcon { - position: absolute; - right: .5em; - top: .5em; - z-index: 20000; - text-decoration: none; - background: #CD1818; - color: white !important; - padding: 3px; -} - -#netteBluescreenError { - background: #CD1818; - color: white; - font: 13pt/1.5 Verdana, sans-serif !important; - display: block; -} - -#netteBluescreenError #netteBsSearch { - color: #CD1818; - font-size: .7em; -} - -#netteBluescreenError:hover #netteBsSearch { - color: #ED8383; -} - -#netteBluescreen h1 { - font-size: 18pt; - font-weight: normal; - text-shadow: 1px 1px 0 rgba(0, 0, 0, .4); - margin: .7em 0; -} - -#netteBluescreen h2 { - font: 14pt/1.5 sans-serif !important; - color: #888; - margin: .6em 0; -} - -#netteBluescreen h3 { - font: bold 10pt/1.5 Verdana, sans-serif !important; - margin: 1em 0; - padding: 0; -} - -#netteBluescreen p, #netteBluescreen pre { - margin: .8em 0 -} - -#netteBluescreen pre, #netteBluescreen code, #netteBluescreen table { - font: 9pt/1.5 Consolas, monospace !important; -} - -#netteBluescreen pre, #netteBluescreen table { - background: #FDF5CE; - padding: .4em .7em; - border: 1px dotted silver; - overflow: auto; -} - -#netteBluescreen table pre { - padding: 0; - margin: 0; - border: none; -} - -#netteBluescreen table { - border-collapse: collapse; - width: 100%; -} - -#netteBluescreen td, #netteBluescreen th { - vertical-align: top; - text-align: left; - padding: 2px 6px; - border: 1px solid #e6dfbf; -} - -#netteBluescreen th { - font-weight: bold; -} - -#netteBluescreen tr > :first-child { - width: 20%; -} - -#netteBluescreen tr:nth-child(2n), #netteBluescreen tr:nth-child(2n) pre { - background-color: #F7F0CB; -} - -#netteBluescreen ol { - margin: 1em 0; - padding-left: 2.5em; -} - -#netteBluescreen ul { - font: 7pt/1.5 Verdana, sans-serif !important; - padding: 2em 4em; - margin: 1em 0 0; - color: #777; - background: #F6F5F3 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAAAjCAMAAADbuxbOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADBQTFRF/fz24d7Y7Onj5uLd9vPu3drUzMvG09LN39zW8e7o2NbQ3NnT29jS0M7J1tXQAAAApvmsFgAAABB0Uk5T////////////////////AOAjXRkAAAKlSURBVHja7FbbsqQgDAwENEgc//9vN+SCWDtbtXPmZR/Wc6o02mlC58LA9ckFAOszvMV8xNgyUjyXhojfMVKvRL0ZHavxXYy5JrmchMdzou8YlTClxajtK8ZGGpWRoBr1+gFjKfHkJPbizabLgzE3pH7Iu4K980xgFvlrVzMZoVBWhtvouCDdcTDmTgMCJdVxJ9MKO6XxnliM7hxi5lbj2ZVM4l8DqYyKoNLYcfqBB1/LpHYxEcfVG6ZpMDgyFUVWY/Q1sSYPpIdSAKWqLWL0XqWiMWc4hpH0OQOMOAgdycY4N9Sb7wWANQs3rsDSdLAYiuxi5siVfOhBWIrtH0G3kNaF/8Q4kCPE1kMucG/ZMUBUCOgiKJkPuWWTLGVgLGpwns1DraUayCtoBqERyaYtVsm85NActRooezvSLO/sKZP/nq8n4+xcyjNsRu8zW6KWpdb7wjiQd4WrtFZYFiKHENSmWp6xshh96c2RQ+c7Lt+qbijyEjHWUJ/pZsy8MGIUuzNiPySK2Gqoh6ZTRF6ko6q3nVTkaA//itIrDpW6l3SLo8juOmqMXkYknu5FdQxWbhCfKHEGDhxxyTVaXJF3ZjSl3jMksjSOOKmne9pI+mcG5QvaUJhI9HpkmRo2NpCrDJvsktRhRE2MM6F2n7dt4OaMUq8bCctk0+PoMRzL+1l5PZ2eyM/Owr86gf8z/tOM53lom5+nVcFuB+eJVzlXwAYy9TZ9s537tfqcsJWbEU4nBngZo6FfO9T9CdhfBtmk2dLiAy8uS4zwOpMx2HqYbTC+amNeAYTpsP4SIgvWfUBWXxn3CMHW3ffd7k3+YIkx7w0t/CVGvcPejoeOlzOWzeGbawOHqXQGUTMZRcfj4XPCgW9y/fuvVn8zD9P1QHzv80uAAQA0i3Jer7Jr7gAAAABJRU5ErkJggg==') 99% 10px no-repeat; - border-top: 1px solid #DDD; -} - -#netteBluescreen div.panel { - padding: 1px 25px; -} - -#netteBluescreen div.inner { - background: #F4F3F1; - padding: .1em 1em 1em; - border-radius: 8px; -} - -#netteBluescreen .outer { - overflow: auto; -} - - -/* source code */ -#netteBluescreen pre.php div { - min-width: 100%; - float: left; - white-space: pre; -} - -#netteBluescreen .highlight { - background: #CD1818; - color: white; - font-weight: bold; - font-style: normal; - display: block; - padding: 0 .4em; - margin: 0 -.4em; -} - -#netteBluescreen .line { - color: #9F9C7F; - font-weight: normal; - font-style: normal; -} - -#netteBluescreen a[href^=editor\:] { - color: inherit; - border-bottom: 1px dotted rgba(0, 0, 0, .2); -} - -#netteBluescreen span[data-nette-href] { - border-bottom: 1px dotted rgba(0, 0, 0, .2); -} - - -/* toggle */ -html.js #netteBluescreen .nette-collapsed { - display: none; -} - -#netteBluescreen .nette-toggle, #netteBluescreen .nette-toggle-collapsed { - cursor: pointer; -} - -#netteBluescreen .nette-toggle:after { - content: " ▼"; - opacity: .4; -} - -#netteBluescreen .nette-toggle-collapsed:after { - content: " ►"; - opacity: .4; -} - - -/* dump */ -#netteBluescreen .nette-dump-array, #netteBluescreen .nette-dump-object { - color: #C22; -} - -#netteBluescreen .nette-dump-string { - color: #35D; -} - -#netteBluescreen .nette-dump-number { - color: #090; -} - -#netteBluescreen .nette-dump-null, #netteBluescreen .nette-dump-bool { - color: #850; -} - -#netteBluescreen .nette-dump-visibility, #netteBluescreen .nette-dump-hash { - font-size: 85%; - color: #998; -} - -#netteBluescreen .nette-dump-indent { - display: none; -} - -#netteBluescreen pre.nette-dump div { - padding-left: 3ex; -} - -#netteBluescreen pre.nette-dump div div { - border-left: 1px solid rgba(0, 0, 0, .1); - margin-left: .5ex; -} - -#netteBluescreen .caused { - float: right; - padding: .3em .6em; - background: #df8075; - border-radius: 0 0 0 8px; - white-space: nowrap; -} - -#netteBluescreen .caused a { - color: white; -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bluescreen.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bluescreen.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/bluescreen.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/bluescreen.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,348 +0,0 @@ -getSeverity()])) ? Debugger::$errorTypes[$exception->getSeverity()] : get_class($exception); - -$counter = 0; - -?>
- - - - - - - <?php echo htmlspecialchars($title) ?> - - - - - - - -
- -
-
-

getCode() ? ' #' . $exception->getCode() : '') ?>

- -

getMessage(), ENT_IGNORE) ?> getMessage())) ?>" id="netteBsSearch" rel="noreferrer">search►

-
- - getPrevious()): ?> - - - - - - - - -
> -

Caused by

- -
-
-

getCode() ? ' #' . $ex->getCode() : '')) ?>

- -

getMessage(), ENT_IGNORE) ?>

-
- - - - - - -
-

- -
- -
- - - - getTrace(); $expanded = NULL ?> - getSeverity(), array(E_USER_NOTICE, E_USER_WARNING, E_USER_DEPRECATED))) && $this->isCollapsed($ex->getFile())) { - foreach ($stack as $key => $row) { - if (isset($row['file']) && !$this->isCollapsed($row['file'])) { $expanded = $key; break; } - } - } ?> - -
-

Source file

- -
-

File: getFile(), $ex->getLine()) ?>

- getFile())): ?>getFile(), $ex->getLine(), 15, $ex instanceof \ErrorException && isset($ex->context) ? $ex->context : NULL) ?> -
- - - - -
-

Call stack

- -
-
    - $row): ?> -
  1. - - - - - inner-code - - - " class="nette-toggle-collapsed">source  - - " ?> - - ' ?> - - - (" class="nette-toggle-collapsed">arguments) -

    - - -
    id="netteBsSrc">
    - - - -
    ">
    - - - -
    "> - - getParameters(); - } catch (\Exception $e) { - $params = array(); - } - foreach ($row['args'] as $k => $v) { - echo '\n"; - } - ?> -
    ', htmlspecialchars(isset($params[$k]) ? '$' . $params[$k]->name : "#$k"), ''; - echo Dumper::toHtml($v); - echo "
    -
    - -
  2. - -
-
- - - - context) && is_array($ex->context)):?> -
-

Variables

- -
-
- - context as $k => $v) { - echo '\n"; - } - ?> -
$', htmlspecialchars($k), '', Dumper::toHtml($v), "
-
-
- - - getPrevious()); ?> -
' ?> - - - - - - -
-

- -
- -
- - - -
-

Environment

- -
-

$_SERVER

-
- - $v) echo '\n"; - ?> -
', htmlspecialchars($k), '', Dumper::toHtml($v), "
-
- - -

$_SESSION

-
- -

empty

- - - $v) echo '\n"; - ?> -
', htmlspecialchars($k), '', $k === '__NF' ? 'Nette Session' : Dumper::toHtml($v), "
- -
- - - -

Nette Session

-
- - $v) echo '\n"; - ?> -
', htmlspecialchars($k), '', Dumper::toHtml($v), "
-
- - - - -

Constants

-
- - $v) { - echo ''; - echo '\n"; - } - ?> -
', htmlspecialchars($k), '', Dumper::toHtml($v), "
-
- - - -

Included files ()

-
- - \n"; - } - ?> -
', htmlspecialchars($v, ENT_IGNORE), "
-
- - -

Configuration options

-
- |.+\z#s', '', ob_get_clean()) ?> -
-
- - -
-

HTTP request

- -
- -

Headers

-
- - $v) echo '\n"; - ?> -
', htmlspecialchars($k), '', htmlspecialchars($v), "
-
- - - - -

$

- -

empty

- -
- - $v) echo '\n"; - ?> -
', htmlspecialchars($k), '', Dumper::toHtml($v), "
-
- - -
- - -
-

HTTP response

- -
-

Headers

- -
';
-			?>
- -

no headers

- -
- - - -
-

- -
- -
- - - -
    -
  • Report generated at
  • - -
  • - -
  • - -
  • PHP
  • -
  • -
  • (revision )
  • -
-
-
- - - - diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/dumper.css php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/dumper.css --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/dumper.css 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/dumper.css 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -/** - * Dumper - * - * This file is part of the Nette Framework (http://nette.org) - * Copyright (c) 2004 David Grudl (http://davidgrudl.com) - */ - -/* toggle */ -.nette-collapsed { - display: none; -} - -.nette-toggle, .nette-toggle-collapsed { - cursor: pointer; -} - -.nette-toggle:after { - content: " ▼"; - opacity: .4; -} - -.nette-toggle-collapsed:after { - content: " ►"; - opacity: .4; -} - - -/* dump */ -pre.nette-dump { - color: #444; - background: white; -} - -pre.nette-dump div { - padding-left: 3ex; -} - -pre.nette-dump div div { - border-left: 1px solid rgba(0, 0, 0, .1); - margin-left: .5ex; -} - -.nette-dump-array, .nette-dump-object { - color: #C22; -} - -.nette-dump-string { - color: #35D; -} - -.nette-dump-number { - color: #090; -} - -.nette-dump-null, .nette-dump-bool { - color: #850; -} - -.nette-dump-visibility, .nette-dump-hash { - font-size: 85%; color: #999; -} - -.nette-dump-indent { - display: none; -} - -span[data-nette-href] { - border-bottom: 1px dotted rgba(0, 0, 0, .2); -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/dumper.js php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/dumper.js --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/dumper.js 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/dumper.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/** - * Dumper - * - * This file is part of the Nette Framework (http://nette.org) - * Copyright (c) 2004 David Grudl (http://davidgrudl.com) - */ - -(function(){ - - var $ = Nette.Query.factory; - - var Dumper = Nette.Dumper = {}; - - Dumper.init = function() { - $(document.body).bind('click', function(e) { - var link; - - // enables & ctrl key - for (link = e.target; link && (!link.getAttribute || !link.getAttribute('data-nette-href')); link = link.parentNode) {} - if (e.ctrlKey && link) { - location.href = link.getAttribute('data-nette-href'); - return false; - } - - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { - return; - } - - // enables or toggling - for (link = e.target; link && (!link.tagName || typeof link.className !== 'string' || !link.className.match(/\bnette-toggle(-collapsed)?\b/)); link = link.parentNode) {} - if (!link) { - return; - } - var collapsed = $(link).hasClass('nette-toggle-collapsed'), - ref = link.getAttribute('data-ref') || link.getAttribute('href', 2), - dest = ref && ref !== '#' ? $(ref) : $(link).next(''), - panel = $(link).closest('.nette-panel'), - oldPosition = panel.position(); - - link.className = 'nette-toggle' + (collapsed ? '' : '-collapsed'); - dest[collapsed ? 'removeClass' : 'addClass']('nette-collapsed'); - e.preventDefault(); - - if (panel.length) { - var newPosition = panel.position(); - panel.position({ - right: newPosition.right - newPosition.width + oldPosition.width, - bottom: newPosition.bottom - newPosition.height + oldPosition.height - }); - } - }); - }; - -})(); diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/error.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/error.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/error.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/error.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ - - - - - - - - -Server Error - -

Server Error

- -

We're sorry! The server encountered an internal error and -was unable to complete your request. Please try again later.

- -

error 500

diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/netteQ.js php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/netteQ.js --- php-nette-2.1.4/Nette-2.1.4/Nette/Diagnostics/templates/netteQ.js 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Diagnostics/templates/netteQ.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,328 +0,0 @@ -/** - * NetteQ - * - * This file is part of the Nette Framework. - * Copyright (c) 2004, 2014 David Grudl (http://davidgrudl.com) - */ - -var Nette = Nette || {}; - -(function(){ - - // supported cross-browser selectors: #id | div | div.class | .class - var Query = Nette.Query = function(selector) { - if (typeof selector === "string") { - selector = this._find(document, selector); - - } else if (!selector || selector.nodeType || selector.length === undefined || selector === window) { - selector = [selector]; - } - - for (var i = 0, len = selector.length; i < len; i++) { - if (selector[i]) { this[this.length++] = selector[i]; } - } - }; - - Query.factory = function(selector) { - return new Query(selector); - }; - - Query.prototype.length = 0; - - Query.prototype.find = function(selector) { - return new Query(this._find(this[0], selector)); - }; - - Query.prototype._find = function(context, selector) { - if (!context || !selector) { - return []; - - } else if (document.querySelectorAll) { - return context.querySelectorAll(selector); - - } else if (selector.charAt(0) === '#') { // #id - return [document.getElementById(selector.substring(1))]; - - } else { // div | div.class | .class - selector = selector.split('.'); - var elms = context.getElementsByTagName(selector[0] || '*'); - - if (selector[1]) { - var list = [], pattern = new RegExp('(^|\\s)' + selector[1] + '(\\s|$)'); - for (var i = 0, len = elms.length; i < len; i++) { - if (pattern.test(elms[i].className)) { list.push(elms[i]); } - } - return list; - } else { - return elms; - } - } - }; - - Query.prototype.dom = function() { - return this[0]; - }; - - Query.prototype.each = function(callback) { - for (var i = 0; i < this.length; i++) { - if (callback.apply(this[i]) === false) { break; } - } - return this; - }; - - // cross-browser event attach - Query.prototype.bind = function(event, handler) { - if (document.addEventListener && (event === 'mouseenter' || event === 'mouseleave')) { // simulate mouseenter & mouseleave using mouseover & mouseout - var old = handler; - event = event === 'mouseenter' ? 'mouseover' : 'mouseout'; - handler = function(e) { - for (var target = e.relatedTarget; target; target = target.parentNode) { - if (target === this) { return; } // target must not be inside this - } - old.call(this, e); - }; - } - - return this.each(function() { - var elem = this, // fixes 'this' in iE - data = elem.nette ? elem.nette : elem.nette = {}, - events = data.events = data.events || {}; // use own handler queue - - if (!events[event]) { - var handlers = events[event] = [], - generic = function(e) { // dont worry, 'e' is passed in IE - if (!e.target) { - e.target = e.srcElement; - } - if (!e.preventDefault) { - e.preventDefault = function() { e.returnValue = false; }; - } - if (!e.stopPropagation) { - e.stopPropagation = function() { e.cancelBubble = true; }; - } - e.stopImmediatePropagation = function() { this.stopPropagation(); i = handlers.length; }; - for (var i = 0; i < handlers.length; i++) { - handlers[i].call(elem, e); - } - }; - - if (document.addEventListener) { // non-IE - elem.addEventListener(event, generic, false); - } else if (document.attachEvent) { // IE < 9 - elem.attachEvent('on' + event, generic); - } - } - - events[event].push(handler); - }); - }; - - // adds class to element - Query.prototype.addClass = function(className) { - return this.each(function() { - this.className = this.className.replace(/^|\s+|$/g, ' ').replace(' '+className+' ', ' ') + ' ' + className; - }); - }; - - // removes class from element - Query.prototype.removeClass = function(className) { - return this.each(function() { - this.className = this.className.replace(/^|\s+|$/g, ' ').replace(' '+className+' ', ' '); - }); - }; - - // tests whether element has given class - Query.prototype.hasClass = function(className) { - return this[0] && this[0].className.replace(/^|\s+|$/g, ' ').indexOf(' '+className+' ') > -1; - }; - - Query.prototype.show = function() { - Query.displays = Query.displays || {}; - return this.each(function() { - var tag = this.tagName; - if (!Query.displays[tag]) { - Query.displays[tag] = (new Query(document.body.appendChild(document.createElement(tag)))).css('display'); - } - this.style.display = Query.displays[tag]; - }); - }; - - Query.prototype.hide = function() { - return this.each(function() { - this.style.display = 'none'; - }); - }; - - Query.prototype.css = function(property) { - if (this[0] && this[0].currentStyle) { - return this[0].currentStyle[property]; - } else if (this[0] && window.getComputedStyle) { - return document.defaultView.getComputedStyle(this[0], null).getPropertyValue(property) - } - }; - - Query.prototype.data = function() { - if (this[0]) { - return this[0].nette ? this[0].nette : this[0].nette = {}; - } - }; - - Query.prototype.val = function() { - var elem = this[0]; - if (!elem) { - return undefined; - - } else if (!elem.nodeName) { // radio - for (var i = 0, len = elem.length; i < len; i++) { - if (this[i].checked) { return this[i].value; } - } - return null; - - } else if (elem.nodeName.toLowerCase() === 'select') { - var index = elem.selectedIndex, options = elem.options; - - if (index < 0) { - return null; - - } else if (elem.type === 'select-one') { - return options[index].value; - } - - for (var i = 0, values = [], len = options.length; i < len; i++) { - if (options[i].selected) { values.push(options[i].value); } - } - return values; - - } else if (elem.type === 'checkbox') { - return elem.checked; - - } else if (elem.value) { - return elem.value.replace(/^\s+|\s+$/g, ''); - } - }; - - Query.prototype._trav = function(elem, selector, fce) { - selector = selector.split('.'); - while (elem && !(elem.nodeType === 1 && - (!selector[0] || elem.tagName.toLowerCase() === selector[0]) && - (!selector[1] || (new Query(elem)).hasClass(selector[1])))) { - elem = elem[fce]; - } - return new Query(elem || []); - }; - - Query.prototype.closest = function(selector) { - return this._trav(this[0], selector, 'parentNode'); - }; - - Query.prototype.prev = function(selector) { - return this._trav(this[0] && this[0].previousSibling, selector, 'previousSibling'); - }; - - Query.prototype.next = function(selector) { - return this._trav(this[0] && this[0].nextSibling, selector, 'nextSibling'); - }; - - // returns total offset for element - Query.prototype.offset = function(coords) { - if (coords) { - return this.each(function() { - var elem = this, ofs = {left: -coords.left || 0, top: -coords.top || 0}; - while (elem = elem.offsetParent) { - ofs.left += elem.offsetLeft; ofs.top += elem.offsetTop; - } - this.style.left = -ofs.left + 'px'; - this.style.top = -ofs.top + 'px'; - }); - } else if (this[0]) { - var elem = this[0], res = {left: elem.offsetLeft, top: elem.offsetTop}; - while (elem = elem.offsetParent) { - res.left += elem.offsetLeft; res.top += elem.offsetTop; - } - return res; - } - }; - - // returns current position or move to new position - Query.prototype.position = function(coords) { - if (coords) { - return this.each(function() { - if (this.nette && this.nette.onmove) { - this.nette.onmove.call(this, coords); - } - for (var item in coords) { - this.style[item] = coords[item] + 'px'; - } - }); - } else if (this[0]) { - return { - left: this[0].offsetLeft, top: this[0].offsetTop, - right: this[0].style.right ? parseInt(this[0].style.right, 10) : 0, bottom: this[0].style.bottom ? parseInt(this[0].style.bottom, 10) : 0, - width: this[0].offsetWidth, height: this[0].offsetHeight - }; - } - }; - - // makes element draggable - Query.prototype.draggable = function(options) { - var elem = this[0], dE = document.documentElement, started; - options = options || {}; - - (options.handle ? new Query(options.handle) : this).bind('mousedown', function(e) { - var $el = new Query(options.handle ? elem : this); - e.preventDefault(); - e.stopPropagation(); - - if (Query.dragging) { // missed mouseup out of window? - return dE.onmouseup(e); - } - - var pos = $el.position(), - deltaX = options.rightEdge ? pos.right + e.clientX : pos.left - e.clientX, - deltaY = options.bottomEdge ? pos.bottom + e.clientY : pos.top - e.clientY; - - Query.dragging = true; - started = false; - - dE.onmousemove = function(e) { - e = e || event; - if (!started) { - if (options.draggedClass) { - $el.addClass(options.draggedClass); - } - if (options.start) { - options.start(e, $el); - } - started = true; - } - - var pos = {}; - pos[options.rightEdge ? 'right' : 'left'] = options.rightEdge ? deltaX - e.clientX : e.clientX + deltaX; - pos[options.bottomEdge ? 'bottom' : 'top'] = options.bottomEdge ? deltaY - e.clientY : e.clientY + deltaY; - $el.position(pos); - return false; - }; - - dE.onmouseup = function(e) { - if (started) { - if (options.draggedClass) { - $el.removeClass(options.draggedClass); - } - if (options.stop) { - options.stop(e || event, $el); - } - } - Query.dragging = dE.onmousemove = dE.onmouseup = null; - return false; - }; - - }).bind('click', function(e) { - if (started) { - e.stopImmediatePropagation(); - } - }); - - return this; - }; - -})(); diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Container.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Container.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Container.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Container.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,479 +0,0 @@ -getForm(FALSE); - if (!$form || !$form->isAnchored() || !$form->isSubmitted()) { - $this->setValues($values, $erase); - } - return $this; - } - - - /** - * Fill-in with values. - * @param array|\Traversable values used to fill the form - * @param bool erase other controls? - * @return self - */ - public function setValues($values, $erase = FALSE) - { - if ($values instanceof \Traversable) { - $values = iterator_to_array($values); - - } elseif (!is_array($values)) { - throw new Nette\InvalidArgumentException(sprintf('First parameter must be an array, %s given.', gettype($values))); - } - - foreach ($this->getComponents() as $name => $control) { - if ($control instanceof IControl) { - if (array_key_exists($name, $values)) { - $control->setValue($values[$name]); - - } elseif ($erase) { - $control->setValue(NULL); - } - - } elseif ($control instanceof Container) { - if (array_key_exists($name, $values)) { - $control->setValues($values[$name], $erase); - - } elseif ($erase) { - $control->setValues(array(), $erase); - } - } - } - return $this; - } - - - /** - * Returns the values submitted by the form. - * @param bool return values as an array? - * @return Nette\ArrayHash|array - */ - public function getValues($asArray = FALSE) - { - $values = $asArray ? array() : new Nette\ArrayHash; - foreach ($this->getComponents() as $name => $control) { - if ($control instanceof IControl && !$control->isOmitted()) { - $values[$name] = $control->getValue(); - - } elseif ($control instanceof Container) { - $values[$name] = $control->getValues($asArray); - } - } - return $values; - } - - - /********************* validation ****************d*g**/ - - - /** - * Is form valid? - * @return bool - */ - public function isValid() - { - if (!$this->validated) { - $this->validate(); - } - return !$this->getErrors(); - } - - - /** - * Performs the server side validation. - * @param IControl[] - * @return void - */ - public function validate(array $controls = NULL) - { - foreach ($controls === NULL ? $this->getControls() : $controls as $control) { - $control->validate(); - } - $this->onValidate($this); - $this->validated = TRUE; - } - - - /** - * Returns all validation errors. - * @return array - */ - public function getErrors() - { - $errors = array(); - foreach ($this->getControls() as $control) { - $errors = array_merge($errors, $control->getErrors()); - } - return array_unique($errors); - } - - - /********************* form building ****************d*g**/ - - - /** - * @return self - */ - public function setCurrentGroup(ControlGroup $group = NULL) - { - $this->currentGroup = $group; - return $this; - } - - - /** - * Returns current group. - * @return ControlGroup - */ - public function getCurrentGroup() - { - return $this->currentGroup; - } - - - /** - * Adds the specified component to the IContainer. - * @param IComponent - * @param string - * @param string - * @return self - * @throws Nette\InvalidStateException - */ - public function addComponent(Nette\ComponentModel\IComponent $component, $name, $insertBefore = NULL) - { - parent::addComponent($component, $name, $insertBefore); - if ($this->currentGroup !== NULL && $component instanceof IControl) { - $this->currentGroup->add($component); - } - return $this; - } - - - /** - * Iterates over all form controls. - * @return \ArrayIterator - */ - public function getControls() - { - return $this->getComponents(TRUE, 'Nette\Forms\IControl'); - } - - - /** - * Returns form. - * @param bool throw exception if form doesn't exist? - * @return Form - */ - public function getForm($need = TRUE) - { - return $this->lookup('Nette\Forms\Form', $need); - } - - - /********************* control factories ****************d*g**/ - - - /** - * Adds single-line text input control to the form. - * @param string control name - * @param string label - * @param int width of the control (deprecated) - * @param int maximum number of characters the user may enter - * @return Nette\Forms\Controls\TextInput - */ - public function addText($name, $label = NULL, $cols = NULL, $maxLength = NULL) - { - $control = new Controls\TextInput($label, $maxLength); - $control->setAttribute('size', $cols); - return $this[$name] = $control; - } - - - /** - * Adds single-line text input control used for sensitive input such as passwords. - * @param string control name - * @param string label - * @param int width of the control (deprecated) - * @param int maximum number of characters the user may enter - * @return Nette\Forms\Controls\TextInput - */ - public function addPassword($name, $label = NULL, $cols = NULL, $maxLength = NULL) - { - $control = new Controls\TextInput($label, $maxLength); - $control->setAttribute('size', $cols); - return $this[$name] = $control->setType('password'); - } - - - /** - * Adds multi-line text input control to the form. - * @param string control name - * @param string label - * @param int width of the control - * @param int height of the control in text lines - * @return Nette\Forms\Controls\TextArea - */ - public function addTextArea($name, $label = NULL, $cols = NULL, $rows = NULL) - { - $control = new Controls\TextArea($label); - $control->setAttribute('cols', $cols)->setAttribute('rows', $rows); - return $this[$name] = $control; - } - - - /** - * Adds control that allows the user to upload files. - * @param string control name - * @param string label - * @param bool allows to upload multiple files - * @return Nette\Forms\Controls\UploadControl - */ - public function addUpload($name, $label = NULL, $multiple = FALSE) - { - return $this[$name] = new Controls\UploadControl($label, $multiple); - } - - - /** - * Adds hidden form control used to store a non-displayed value. - * @param string control name - * @param mixed default value - * @return Nette\Forms\Controls\HiddenField - */ - public function addHidden($name, $default = NULL) - { - $control = new Controls\HiddenField; - $control->setDefaultValue($default); - return $this[$name] = $control; - } - - - /** - * Adds check box control to the form. - * @param string control name - * @param string caption - * @return Nette\Forms\Controls\Checkbox - */ - public function addCheckbox($name, $caption = NULL) - { - return $this[$name] = new Controls\Checkbox($caption); - } - - - /** - * Adds set of radio button controls to the form. - * @param string control name - * @param string label - * @param array options from which to choose - * @return Nette\Forms\Controls\RadioList - */ - public function addRadioList($name, $label = NULL, array $items = NULL) - { - return $this[$name] = new Controls\RadioList($label, $items); - } - - - /** - * Adds set of checkbox controls to the form. - * @return Nette\Forms\Controls\CheckboxList - */ - public function addCheckboxList($name, $label = NULL, array $items = NULL) - { - return $this[$name] = new Controls\CheckboxList($label, $items); - } - - - /** - * Adds select box control that allows single item selection. - * @param string control name - * @param string label - * @param array items from which to choose - * @param int number of rows that should be visible - * @return Nette\Forms\Controls\SelectBox - */ - public function addSelect($name, $label = NULL, array $items = NULL, $size = NULL) - { - $control = new Controls\SelectBox($label, $items); - if ($size > 1) { - $control->setAttribute('size', (int) $size); - } - return $this[$name] = $control; - } - - - /** - * Adds select box control that allows multiple item selection. - * @param string control name - * @param string label - * @param array options from which to choose - * @param int number of rows that should be visible - * @return Nette\Forms\Controls\MultiSelectBox - */ - public function addMultiSelect($name, $label = NULL, array $items = NULL, $size = NULL) - { - $control = new Controls\MultiSelectBox($label, $items); - if ($size > 1) { - $control->setAttribute('size', (int) $size); - } - return $this[$name] = $control; - } - - - /** - * Adds button used to submit form. - * @param string control name - * @param string caption - * @return Nette\Forms\Controls\SubmitButton - */ - public function addSubmit($name, $caption = NULL) - { - return $this[$name] = new Controls\SubmitButton($caption); - } - - - /** - * Adds push buttons with no default behavior. - * @param string control name - * @param string caption - * @return Nette\Forms\Controls\Button - */ - public function addButton($name, $caption = NULL) - { - return $this[$name] = new Controls\Button($caption); - } - - - /** - * Adds graphical button used to submit form. - * @param string control name - * @param string URI of the image - * @param string alternate text for the image - * @return Nette\Forms\Controls\ImageButton - */ - public function addImage($name, $src = NULL, $alt = NULL) - { - return $this[$name] = new Controls\ImageButton($src, $alt); - } - - - /** - * Adds naming container to the form. - * @param string name - * @return Container - */ - public function addContainer($name) - { - $control = new Container; - $control->currentGroup = $this->currentGroup; - return $this[$name] = $control; - } - - - /********************* interface \ArrayAccess ****************d*g**/ - - - /** - * Adds the component to the container. - * @param string component name - * @param Nette\ComponentModel\IComponent - * @return void - */ - public function offsetSet($name, $component) - { - $this->addComponent($component, $name); - } - - - /** - * Returns component specified by name. Throws exception if component doesn't exist. - * @param string component name - * @return Nette\ComponentModel\IComponent - * @throws Nette\InvalidArgumentException - */ - public function offsetGet($name) - { - return $this->getComponent($name, TRUE); - } - - - /** - * Does component specified by name exists? - * @param string component name - * @return bool - */ - public function offsetExists($name) - { - return $this->getComponent($name, FALSE) !== NULL; - } - - - /** - * Removes component from the container. - * @param string component name - * @return void - */ - public function offsetUnset($name) - { - $component = $this->getComponent($name, FALSE); - if ($component !== NULL) { - $this->removeComponent($component); - } - } - - - /** - * Prevents cloning. - */ - public function __clone() - { - throw new Nette\NotImplementedException('Form cloning is not supported yet.'); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/ControlGroup.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/ControlGroup.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/ControlGroup.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/ControlGroup.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -controls = new \SplObjectStorage; - } - - - /** - * @return self - */ - public function add() - { - foreach (func_get_args() as $num => $item) { - if ($item instanceof IControl) { - $this->controls->attach($item); - - } elseif ($item instanceof \Traversable || is_array($item)) { - foreach ($item as $control) { - $this->controls->attach($control); - } - - } else { - throw new Nette\InvalidArgumentException("Only IFormControl items are allowed, the #$num parameter is invalid."); - } - } - return $this; - } - - - /** - * @return array IFormControl - */ - public function getControls() - { - return iterator_to_array($this->controls); - } - - - /** - * Sets user-specific option. - * Options recognized by DefaultFormRenderer - * - 'label' - textual or Html object label - * - 'visual' - indicates visual group - * - 'container' - container as Html object - * - 'description' - textual or Html object description - * - 'embedNext' - describes how render next group - * - * @param string key - * @param mixed value - * @return self - */ - public function setOption($key, $value) - { - if ($value === NULL) { - unset($this->options[$key]); - - } else { - $this->options[$key] = $value; - } - return $this; - } - - - /** - * Returns user-specific option. - * @param string key - * @param mixed default value - * @return mixed - */ - public function getOption($key, $default = NULL) - { - return isset($this->options[$key]) ? $this->options[$key] : $default; - } - - - /** - * Returns user-specific options. - * @return array - */ - public function getOptions() - { - return $this->options; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/BaseControl.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/BaseControl.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/BaseControl.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/BaseControl.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,705 +0,0 @@ -monitor('Nette\Forms\Form'); - parent::__construct(); - $this->control = Html::el('input', array('type' => NULL, 'name' => NULL)); - $this->label = Html::el('label'); - $this->caption = $caption; - $this->rules = new Nette\Forms\Rules($this); - $this->setValue(NULL); - } - - - /** - * This method will be called when the component becomes attached to Form. - * @param Nette\ComponentModel\IComponent - * @return void - */ - protected function attached($form) - { - if (!$this->isDisabled() && $form instanceof Form && $form->isAnchored() && $form->isSubmitted()) { - $this->loadHttpData(); - } - } - - - /** - * Returns form. - * @param bool throw exception if form doesn't exist? - * @return Nette\Forms\Form - */ - public function getForm($need = TRUE) - { - return $this->lookup('Nette\Forms\Form', $need); - } - - - /** - * Loads HTTP data. - * @return void - */ - public function loadHttpData() - { - $this->setValue($this->getHttpData(Form::DATA_TEXT)); - } - - - /** - * Loads HTTP data. - * @return mixed - */ - public function getHttpData($type, $htmlTail = NULL) - { - return $this->getForm()->getHttpData($type, $this->getHtmlName() . $htmlTail); - } - - - /** - * Returns HTML name of control. - * @return string - */ - public function getHtmlName() - { - return Nette\Forms\Helpers::generateHtmlName($this->lookupPath('Nette\Forms\Form')); - } - - - /********************* interface IFormControl ****************d*g**/ - - - /** - * Sets control's value. - * @return self - */ - public function setValue($value) - { - $this->value = $value; - return $this; - } - - - /** - * Returns control's value. - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - - /** - * Is control filled? - * @return bool - */ - public function isFilled() - { - $value = $this->getValue(); - return $value !== NULL && $value !== array() && $value !== ''; - } - - - /** - * Sets control's default value. - * @return self - */ - public function setDefaultValue($value) - { - $form = $this->getForm(FALSE); - if ($this->isDisabled() || !$form || !$form->isAnchored() || !$form->isSubmitted()) { - $this->setValue($value); - } - return $this; - } - - - /** - * Disables or enables control. - * @param bool - * @return self - */ - public function setDisabled($value = TRUE) - { - if ($this->disabled = (bool) $value) { - $this->omitted = TRUE; - $this->setValue(NULL); - } - return $this; - } - - - /** - * Is control disabled? - * @return bool - */ - public function isDisabled() - { - return $this->disabled === TRUE; - } - - - /** - * Sets whether control value is excluded from $form->getValues() result. - * @param bool - * @return self - */ - public function setOmitted($value = TRUE) - { - $this->omitted = (bool) $value; - return $this; - } - - - /** - * Is control value excluded from $form->getValues() result? - * @return bool - */ - public function isOmitted() - { - return $this->omitted; - } - - - /********************* rendering ****************d*g**/ - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl() - { - $this->setOption('rendered', TRUE); - - $rules = self::exportRules($this->rules); - $el = clone $this->control; - return $el->addAttributes(array( - 'name' => $this->getHtmlName(), - 'id' => $this->getHtmlId(), - 'required' => $this->isRequired(), - 'disabled' => $this->isDisabled(), - 'data-nette-rules' => $rules ? Nette\Utils\Json::encode($rules) : NULL, - )); - } - - - /** - * Generates label's HTML element. - * @param string - * @return Nette\Utils\Html - */ - public function getLabel($caption = NULL) - { - $label = clone $this->label; - $label->for = $this->getHtmlId(); - $label->setText($this->translate($caption === NULL ? $this->caption : $caption)); - return $label; - } - - - /** - * Returns control's HTML element template. - * @return Nette\Utils\Html - */ - public function getControlPrototype() - { - return $this->control; - } - - - /** - * Returns label's HTML element template. - * @return Nette\Utils\Html - */ - public function getLabelPrototype() - { - return $this->label; - } - - - /** - * Changes control's HTML id. - * @param string new ID, or FALSE or NULL - * @return self - */ - public function setHtmlId($id) - { - $this->control->id = $id; - return $this; - } - - - /** - * Returns control's HTML id. - * @return string - */ - public function getHtmlId() - { - if (!isset($this->control->id)) { - $this->control->id = sprintf(self::$idMask, $this->lookupPath(NULL)); - } - return $this->control->id; - } - - - /** - * Changes control's HTML attribute. - * @param string name - * @param mixed value - * @return self - */ - public function setAttribute($name, $value = TRUE) - { - $this->control->$name = $value; - return $this; - } - - - /********************* translator ****************d*g**/ - - - /** - * Sets translate adapter. - * @return self - */ - public function setTranslator(Nette\Localization\ITranslator $translator = NULL) - { - $this->translator = $translator; - return $this; - } - - - /** - * Returns translate adapter. - * @return Nette\Localization\ITranslator|NULL - */ - public function getTranslator() - { - if ($this->translator === TRUE) { - return $this->getForm(FALSE) ? $this->getForm()->getTranslator() : NULL; - } - return $this->translator; - } - - - /** - * Returns translated string. - * @param mixed - * @param int plural count - * @return string - */ - public function translate($value, $count = NULL) - { - if ($translator = $this->getTranslator()) { - $tmp = is_array($value) ? array(& $value) : array(array(& $value)); - foreach ($tmp[0] as & $v) { - if ($v != NULL && !$v instanceof Html) { // intentionally == - $v = $translator->translate((string) $v, $count); - } - } - } - return $value; - } - - - /********************* rules ****************d*g**/ - - - /** - * Adds a validation rule. - * @param mixed rule type - * @param string message to display for invalid data - * @param mixed optional rule arguments - * @return self - */ - public function addRule($operation, $message = NULL, $arg = NULL) - { - $this->rules->addRule($operation, $message, $arg); - return $this; - } - - - /** - * Adds a validation condition a returns new branch. - * @param mixed condition type - * @param mixed optional condition arguments - * @return Nette\Forms\Rules new branch - */ - public function addCondition($operation, $value = NULL) - { - return $this->rules->addCondition($operation, $value); - } - - - /** - * Adds a validation condition based on another control a returns new branch. - * @param Nette\Forms\IControl form control - * @param mixed condition type - * @param mixed optional condition arguments - * @return Nette\Forms\Rules new branch - */ - public function addConditionOn(IControl $control, $operation, $value = NULL) - { - return $this->rules->addConditionOn($control, $operation, $value); - } - - - /** - * @return Nette\Forms\Rules - */ - public function getRules() - { - return $this->rules; - } - - - /** - * Makes control mandatory. - * @param mixed state or error message - * @return self - */ - public function setRequired($value = TRUE) - { - $this->rules->setRequired($value); - return $this; - } - - - /** - * Is control mandatory? - * @return bool - */ - public function isRequired() - { - return $this->rules->isRequired(); - } - - - /** - * Performs the server side validation. - * @return void - */ - public function validate() - { - if ($this->isDisabled()) { - return; - } - $this->cleanErrors(); - $this->rules->validate(); - } - - - /** - * Adds error message to the list. - * @param string error message - * @return void - */ - public function addError($message) - { - $this->errors[] = $message; - } - - - /** - * Returns errors corresponding to control. - * @return string - */ - public function getError() - { - return $this->errors ? implode(' ', array_unique($this->errors)) : NULL; - } - - - /** - * Returns errors corresponding to control. - * @return array - */ - public function getErrors() - { - return array_unique($this->errors); - } - - - /** - * @return bool - */ - public function hasErrors() - { - return (bool) $this->errors; - } - - - /** - * @return void - */ - public function cleanErrors() - { - $this->errors = array(); - } - - - /** - * @return array - */ - protected static function exportRules($rules) - { - $payload = array(); - foreach ($rules as $rule) { - if (!is_string($op = $rule->operation)) { - if (!Nette\Utils\Callback::isStatic($op)) { - continue; - } - $op = Nette\Utils\Callback::toString($op); - } - if ($rule->type === Rule::VALIDATOR) { - $item = array('op' => ($rule->isNegative ? '~' : '') . $op, 'msg' => $rules->formatMessage($rule, FALSE)); - - } elseif ($rule->type === Rule::CONDITION) { - $item = array( - 'op' => ($rule->isNegative ? '~' : '') . $op, - 'rules' => static::exportRules($rule->subRules), - 'control' => $rule->control->getHtmlName() - ); - if ($rule->subRules->getToggles()) { - $item['toggle'] = $rule->subRules->getToggles(); - } - } - - if (is_array($rule->arg)) { - foreach ($rule->arg as $key => $value) { - $item['arg'][$key] = $value instanceof IControl ? array('control' => $value->getHtmlName()) : $value; - } - } elseif ($rule->arg !== NULL) { - $item['arg'] = $rule->arg instanceof IControl ? array('control' => $rule->arg->getHtmlName()) : $rule->arg; - } - - $payload[] = $item; - } - return $payload; - } - - - /********************* validators ****************d*g**/ - - - /** - * Is control's value equal with second parameter? - * @return bool - */ - public static function validateEqual(IControl $control, $arg) - { - $value = $control->getValue(); - foreach ((is_array($value) ? $value : array($value)) as $val) { - foreach ((is_array($arg) ? $arg : array($arg)) as $item) { - if ((string) $val === (string) $item) { - continue 2; - } - } - return FALSE; - } - return TRUE; - } - - - /** - * Is control's value not equal with second parameter? - * @return bool - */ - public static function validateNotEqual(IControl $control, $arg) - { - return !static::validateEqual($control, $arg); - } - - - /** - * Is control filled? - * @return bool - */ - public static function validateFilled(IControl $control) - { - return $control->isFilled(); - } - - - /** - * Is control not filled? - * @return bool - */ - public static function validateBlank(IControl $control) - { - return !$control->isFilled(); - } - - - /** - * Is control valid? - * @return bool - */ - public static function validateValid(IControl $control) - { - return $control->rules->validate(); - } - - - /** - * Is a control's value number in specified range? - * @param Nette\Forms\IControl - * @param array min and max value pair - * @return bool - */ - public static function validateRange(IControl $control, $range) - { - return Nette\Utils\Validators::isInRange($control->getValue(), $range); - } - - - /** - * Count/length validator. Range is array, min and max length pair. - * @return bool - */ - public static function validateLength(IControl $control, $range) - { - if (!is_array($range)) { - $range = array($range, $range); - } - $value = $control->getValue(); - return Nette\Utils\Validators::isInRange(is_array($value) ? count($value) : Nette\Utils\Strings::length($value), $range); - } - - - /** - * Has control's value minimal count/length? - * @return bool - */ - public static function validateMinLength(IControl $control, $length) - { - return static::validateLength($control, array($length, NULL)); - } - - - /** - * Is control's value count/length in limit? - * @return bool - */ - public static function validateMaxLength(IControl $control, $length) - { - return static::validateLength($control, array(NULL, $length)); - } - - - /********************* user data ****************d*g**/ - - - /** - * Sets user-specific option. - * @return self - */ - public function setOption($key, $value) - { - if ($value === NULL) { - unset($this->options[$key]); - } else { - $this->options[$key] = $value; - } - return $this; - } - - - /** - * Returns user-specific option. - * @return mixed - */ - public function getOption($key, $default = NULL) - { - return isset($this->options[$key]) ? $this->options[$key] : $default; - } - - - /** - * Returns user-specific options. - * @return array - */ - public function getOptions() - { - return $this->options; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/Button.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/Button.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/Button.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/Button.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -control->type = 'button'; - } - - - /** - * Is button pressed? - * @return bool - */ - public function isFilled() - { - $value = $this->getValue(); - return $value !== NULL && $value !== array(); - } - - - /** - * Bypasses label generation. - * @return void - */ - public function getLabel($caption = NULL) - { - return NULL; - } - - - /** - * Generates control's HTML element. - * @param string - * @return Nette\Utils\Html - */ - public function getControl($caption = NULL) - { - $this->setOption('rendered', TRUE); - $el = clone $this->control; - return $el->addAttributes(array( - 'name' => $this->getHtmlName(), - 'id' => $this->getHtmlId(), - 'disabled' => $this->isDisabled(), - 'value' => $this->translate($caption === NULL ? $this->caption : $caption), - )); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/CheckboxList.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/CheckboxList.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/CheckboxList.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/CheckboxList.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -control->type = 'checkbox'; - $this->separator = Html::el('br'); - } - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl() - { - $items = $this->getItems(); - reset($items); - $input = parent::getControl(); - return Nette\Forms\Helpers::createInputList( - $this->translate($items), - array_merge($input->attrs, array( - 'id' => NULL, - 'checked?' => $this->value, - 'disabled:' => $this->disabled, - 'required' => NULL, - 'data-nette-rules:' => array(key($items) => $input->attrs['data-nette-rules']), - )), - $this->label->attrs, - $this->separator - ); - } - - - /** - * Generates label's HTML element. - * @param string - * @return Nette\Utils\Html - */ - public function getLabel($caption = NULL) - { - return parent::getLabel($caption)->for(NULL); - } - - - /** - * Returns separator HTML element template. - * @return Nette\Utils\Html - */ - public function getSeparatorPrototype() - { - return $this->separator; - } - - - /** - * @return Nette\Utils\Html - */ - public function getControlPart($key) - { - return parent::getControl()->addAttributes(array( - 'id' => $this->getHtmlId() . '-' . $key, - 'checked' => in_array($key, (array) $this->value), - 'disabled' => is_array($this->disabled) ? isset($this->disabled[$key]) : $this->disabled, - 'required' => NULL, - 'value' => $key, - )); - } - - - /** - * @return Nette\Utils\Html - */ - public function getLabelPart($key) - { - return parent::getLabel($this->items[$key])->for($this->getHtmlId() . '-' . $key); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/Checkbox.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/Checkbox.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/Checkbox.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/Checkbox.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -control->type = 'checkbox'; - $this->wrapper = Nette\Utils\Html::el(); - } - - - /** - * Sets control's value. - * @param bool - * @return self - */ - public function setValue($value) - { - if (!is_scalar($value) && $value !== NULL) { - throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or NULL, %s given in field '%s'.", gettype($value), $this->name)); - } - $this->value = (bool) $value; - return $this; - } - - - /** - * Is control filled? - * @return bool - */ - public function isFilled() - { - return $this->getValue() !== FALSE; // back compatibility - } - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl() - { - return $this->wrapper->setHtml($this->getLabelPart()->insert(0, $this->getControlPart())); - } - - - /** - * Bypasses label generation. - * @return void - */ - public function getLabel($caption = NULL) - { - return NULL; - } - - - /** - * @return Nette\Utils\Html - */ - public function getControlPart() - { - return parent::getControl()->checked($this->value); - } - - - /** - * @return Nette\Utils\Html - */ - public function getLabelPart() - { - return parent::getLabel(); - } - - - /** - * Returns wrapper HTML element template. - * @return Nette\Utils\Html - */ - public function getSeparatorPrototype() - { - return $this->wrapper; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/ChoiceControl.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/ChoiceControl.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/ChoiceControl.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/ChoiceControl.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -setItems($items); - } - } - - - /** - * Loads HTTP data. - * @return void - */ - public function loadHttpData() - { - $this->value = $this->getHttpData(Nette\Forms\Form::DATA_TEXT); - if ($this->value !== NULL) { - if (is_array($this->disabled) && isset($this->disabled[$this->value])) { - $this->value = NULL; - } else { - $this->value = key(array($this->value => NULL)); - } - } - } - - - /** - * Sets selected item (by key). - * @param scalar - * @return self - */ - public function setValue($value) - { - if ($value !== NULL && !array_key_exists((string) $value, $this->items)) { - $range = Nette\Utils\Strings::truncate(implode(', ', array_map(function($s) { return var_export($s, TRUE); }, array_keys($this->items))), 70, '...'); - throw new Nette\InvalidArgumentException("Value '$value' is out of allowed range [$range] in field '{$this->name}'."); - } - $this->value = $value === NULL ? NULL : key(array((string) $value => NULL)); - return $this; - } - - - /** - * Returns selected key. - * @return scalar - */ - public function getValue() - { - return array_key_exists($this->value, $this->items) ? $this->value : NULL; - } - - - /** - * Returns selected key (not checked). - * @return scalar - */ - public function getRawValue() - { - return $this->value; - } - - - /** - * Is any item selected? - * @return bool - */ - public function isFilled() - { - return $this->getValue() !== NULL; - } - - - /** - * Sets items from which to choose. - * @param array - * @param bool - * @return self - */ - public function setItems(array $items, $useKeys = TRUE) - { - $this->items = $useKeys ? $items : array_combine($items, $items); - return $this; - } - - - /** - * Returns items from which to choose. - * @return array - */ - public function getItems() - { - return $this->items; - } - - - /** - * Returns selected value. - * @return mixed - */ - public function getSelectedItem() - { - $value = $this->getValue(); - return $value === NULL ? NULL : $this->items[$value]; - } - - - /** - * Disables or enables control or items. - * @param bool|array - * @return self - */ - public function setDisabled($value = TRUE) - { - if (!is_array($value)) { - return parent::setDisabled($value); - } - - parent::setDisabled(FALSE); - $this->disabled = array_fill_keys($value, TRUE); - if (isset($this->disabled[$this->value])) { - $this->value = NULL; - } - return $this; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/CsrfProtection.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/CsrfProtection.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/CsrfProtection.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/CsrfProtection.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -setOmitted()->addRule(self::PROTECTION, $message); - $this->monitor('Nette\Application\UI\Presenter'); - } - - - protected function attached($parent) - { - parent::attached($parent); - if (!$this->session && $parent instanceof Nette\Application\UI\Presenter) { - $this->session = $parent->getSession(); - } - } - - - /** - * @return string - */ - public function getToken() - { - $session = $this->getSession()->getSection(__CLASS__); - if (!isset($session->token)) { - $session->token = Nette\Utils\Strings::random(); - } - return $session->token; - } - - - /** - * @return string - */ - private function generateToken($random = NULL) - { - if ($random === NULL) { - $random = Nette\Utils\Strings::random(10); - } - return $random . base64_encode(sha1($this->getToken() . $random, TRUE)); - } - - - /** - * Generates control's HTML element. - * - * @return Nette\Utils\Html - */ - public function getControl() - { - return parent::getControl()->value($this->generateToken()); - } - - - /** - * @return bool - */ - public static function validateCsrf(CsrfProtection $control) - { - $value = $control->getValue(); - return $control->generateToken(substr($value, 0, 10)) === $value; - } - - - /********************* backend ****************d*g**/ - - - /** - * @return Nette\Http\Session - */ - private function getSession() - { - if (!$this->session) { - $this->session = new Nette\Http\Session($this->getForm()->httpRequest, new Nette\Http\Response); - } - return $this->session; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/HiddenField.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/HiddenField.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/HiddenField.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/HiddenField.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -control->type = 'hidden'; - if ($persistentValue !== NULL) { - $this->unmonitor('Nette\Forms\Form'); - $this->persistValue = TRUE; - $this->value = (string) $persistentValue; - } - } - - - /** - * Sets control's value. - * @param string - * @return self - */ - public function setValue($value) - { - if (!is_scalar($value) && $value !== NULL && !method_exists($value, '__toString')) { - throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or NULL, %s given in field '%s'.", gettype($value), $this->name)); - } - if (!$this->persistValue) { - $this->value = (string) $value; - } - return $this; - } - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl() - { - $this->setOption('rendered', TRUE); - $el = clone $this->control; - return $el->addAttributes(array( - 'name' => $this->getHtmlName(), - 'id' => $this->getHtmlId(), - 'disabled' => $this->isDisabled(), - 'value' => $this->value, - )); - } - - - /** - * Bypasses label generation. - * @return void - */ - public function getLabel($caption = NULL) - { - return NULL; - } - - - /** - * Adds error message to the list. - * @param string error message - * @return void - */ - public function addError($message) - { - $this->getForm()->addError($message); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/ImageButton.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/ImageButton.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/ImageButton.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/ImageButton.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -control->type = 'image'; - $this->control->src = $src; - $this->control->alt = $alt; - } - - - /** - * Loads HTTP data. - * @return void - */ - public function loadHttpData() - { - parent::loadHttpData(); - $this->value = $this->value - ? array((int) array_shift($this->value), (int) array_shift($this->value)) - : NULL; - } - - - /** - * Returns HTML name of control. - * @return string - */ - public function getHtmlName() - { - return parent::getHtmlName() . '[]'; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/MultiChoiceControl.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/MultiChoiceControl.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/MultiChoiceControl.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/MultiChoiceControl.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,170 +0,0 @@ -setItems($items); - } - } - - - /** - * Loads HTTP data. - * @return void - */ - public function loadHttpData() - { - $this->value = array_keys(array_flip($this->getHttpData(Nette\Forms\Form::DATA_TEXT))); - if (is_array($this->disabled)) { - $this->value = array_diff($this->value, array_keys($this->disabled)); - } - } - - - /** - * Sets selected items (by keys). - * @param array - * @return self - */ - public function setValue($values) - { - if (is_scalar($values) || $values === NULL) { - $values = (array) $values; - } elseif (!is_array($values)) { - throw new Nette\InvalidArgumentException(sprintf("Value must be array or NULL, %s given in field '%s'.", gettype($values), $this->name)); - } - $flip = array(); - foreach ($values as $value) { - if (!is_scalar($value) && !method_exists($value, '__toString')) { - throw new Nette\InvalidArgumentException(sprintf("Values must be scalar, %s given in field '%s'.", gettype($value), $this->name)); - } - $flip[(string) $value] = TRUE; - } - $values = array_keys($flip); - if ($diff = array_diff($values, array_keys($this->items))) { - $range = Nette\Utils\Strings::truncate(implode(', ', array_map(function($s) { return var_export($s, TRUE); }, array_keys($this->items))), 70, '...'); - $vals = (count($diff) > 1 ? 's' : '') . " '" . implode("', '", $diff) . "'"; - throw new Nette\InvalidArgumentException("Value$vals are out of allowed range [$range] in field '{$this->name}'."); - } - $this->value = $values; - return $this; - } - - - /** - * Returns selected keys. - * @return array - */ - public function getValue() - { - return array_values(array_intersect($this->value, array_keys($this->items))); - } - - - /** - * Returns selected keys (not checked). - * @return array - */ - public function getRawValue() - { - return $this->value; - } - - - /** - * Is any item selected? - * @return bool - */ - public function isFilled() - { - return $this->getValue() !== array(); - } - - - /** - * Sets items from which to choose. - * @param array - * @param bool - * @return self - */ - public function setItems(array $items, $useKeys = TRUE) - { - $this->items = $useKeys ? $items : array_combine($items, $items); - return $this; - } - - - /** - * Returns items from which to choose. - * @return array - */ - public function getItems() - { - return $this->items; - } - - - /** - * Returns selected values. - * @return array - */ - public function getSelectedItems() - { - return array_intersect_key($this->items, array_flip($this->value)); - } - - - /** - * Disables or enables control or items. - * @param bool|array - * @return self - */ - public function setDisabled($value = TRUE) - { - if (!is_array($value)) { - return parent::setDisabled($value); - } - - parent::setDisabled(FALSE); - $this->disabled = array_fill_keys($value, TRUE); - $this->value = array_diff($this->value, $value); - return $this; - } - - - /** - * Returns HTML name of control. - * @return string - */ - public function getHtmlName() - { - return parent::getHtmlName() . '[]'; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/MultiSelectBox.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/MultiSelectBox.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/MultiSelectBox.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/MultiSelectBox.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ - $value) { - unset($items[$key]); - if (is_array($value)) { - foreach ($value as $val) { - $res[$key][(string) $val] = $val; - } - } else { - $res[(string) $value] = $value; - } - } - $items = $res; - } - $this->options = $items; - return parent::setItems(Nette\Utils\Arrays::flatten($items, TRUE)); - } - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl() - { - $items = array(); - foreach ($this->options as $key => $value) { - $items[is_array($value) ? $this->translate($key) : $key] = $this->translate($value); - } - - return Nette\Forms\Helpers::createSelectBox( - $items, - array( - 'selected?' => $this->value, - 'disabled:' => is_array($this->disabled) ? $this->disabled : NULL - ) - )->addAttributes(parent::getControl()->attrs)->multiple(TRUE); - } - - - /** @deprecated */ - function getSelectedItem() - { - trigger_error(__METHOD__ . '(TRUE) is deprecated; use getSelectedItems() instead.', E_USER_DEPRECATED); - return $this->getSelectedItems(); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/RadioList.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/RadioList.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/RadioList.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/RadioList.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,148 +0,0 @@ -control->type = 'radio'; - $this->container = Html::el(); - $this->separator = Html::el('br'); - } - - - /** - * Returns selected radio value. - * @return mixed - */ - public function getValue($raw = FALSE) - { - if ($raw) { - trigger_error(__METHOD__ . '(TRUE) is deprecated; use getRawValue() instead.', E_USER_DEPRECATED); - return $this->getRawValue(); - } - return parent::getValue(); - } - - - /** - * Returns separator HTML element template. - * @return Nette\Utils\Html - */ - public function getSeparatorPrototype() - { - return $this->separator; - } - - - /** - * Returns container HTML element template. - * @return Nette\Utils\Html - */ - public function getContainerPrototype() - { - return $this->container; - } - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl($key = NULL) - { - if ($key !== NULL) { - trigger_error(sprintf('Partial %s() is deprecated; use getControlPart() instead.', __METHOD__), E_USER_DEPRECATED); - return $this->getControlPart($key); - } - - $input = parent::getControl(); - $ids = array(); - foreach ($this->getItems() as $value => $label) { - $ids[$value] = $input->id . '-' . $value; - } - - return $this->container->setHtml( - Nette\Forms\Helpers::createInputList( - $this->translate($this->getItems()), - array_merge($input->attrs, array( - 'id:' => $ids, - 'checked?' => $this->value, - 'disabled:' => $this->disabled, - 'data-nette-rules:' => array(key($ids) => $input->attrs['data-nette-rules']), - )), - array('for:' => $ids), - $this->separator - ) - ); - } - - - /** - * Generates label's HTML element. - * @param string - * @return Nette\Utils\Html - */ - public function getLabel($caption = NULL, $key = NULL) - { - if ($key !== NULL) { - trigger_error(sprintf('Partial %s() is deprecated; use getLabelPart() instead.', __METHOD__), E_USER_DEPRECATED); - return $this->getLabelPart($key); - } - return parent::getLabel($caption)->for(NULL); - } - - - /** - * @return Nette\Utils\Html - */ - public function getControlPart($key) - { - return parent::getControl()->addAttributes(array( - 'id' => $this->getHtmlId() . '-' . $key, - 'checked' => in_array($key, (array) $this->value), - 'disabled' => is_array($this->disabled) ? isset($this->disabled[$key]) : $this->disabled, - 'value' => $key, - )); - } - - - /** - * @return Nette\Utils\Html - */ - public function getLabelPart($key) - { - return parent::getLabel($this->items[$key])->for($this->getHtmlId() . '-' . $key); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/SelectBox.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/SelectBox.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/SelectBox.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/SelectBox.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,119 +0,0 @@ -getItems(); - $prompt = reset($items); - unset($this->options[key($items)], $items[key($items)]); - $this->setItems($items); - } - $this->prompt = $prompt; - return $this; - } - - - /** - * Returns first prompt item? - * @return mixed - */ - public function getPrompt() - { - return $this->prompt; - } - - - /** - * Sets options and option groups from which to choose. - * @return self - */ - public function setItems(array $items, $useKeys = TRUE) - { - if (!$useKeys) { - $res = array(); - foreach ($items as $key => $value) { - unset($items[$key]); - if (is_array($value)) { - foreach ($value as $val) { - $res[$key][(string) $val] = $val; - } - } else { - $res[(string) $value] = $value; - } - } - $items = $res; - } - $this->options = $items; - return parent::setItems(Nette\Utils\Arrays::flatten($items, TRUE)); - } - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl() - { - $items = $this->prompt === FALSE ? array() : array('' => $this->translate($this->prompt)); - foreach ($this->options as $key => $value) { - $items[is_array($value) ? $this->translate($key) : $key] = $this->translate($value); - } - - return Nette\Forms\Helpers::createSelectBox( - $items, - array( - 'selected?' => $this->value, - 'disabled:' => is_array($this->disabled) ? $this->disabled : NULL - ) - )->addAttributes(parent::getControl()->attrs); - } - - - /** - * Performs the server side validation. - * @return void - */ - public function validate() - { - parent::validate(); - if (!$this->isDisabled() && $this->prompt === FALSE && $this->getValue() === NULL && $this->options) { - $this->addError(Nette\Forms\Rules::$defaultMessages[self::VALID]); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/SubmitButton.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/SubmitButton.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/SubmitButton.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/SubmitButton.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -control->type = 'submit'; - $this->setOmitted(TRUE); - } - - - /** - * Loads HTTP data. - * @return void - */ - public function loadHttpData() - { - parent::loadHttpData(); - if ($this->isFilled()) { - $this->getForm()->setSubmittedBy($this); - } - } - - - /** - * Tells if the form was submitted by this button. - * @return bool - */ - public function isSubmittedBy() - { - return $this->getForm()->isSubmitted() === $this; - } - - - /** - * Sets the validation scope. Clicking the button validates only the controls within the specified scope. - * @return self - */ - public function setValidationScope(/*array*/$scope = NULL) - { - if ($scope === NULL || $scope === TRUE) { - $this->validationScope = NULL; - } else { - $this->validationScope = array(); - foreach ($scope ?: array() as $control) { - if (!$control instanceof Nette\Forms\Container && !$control instanceof Nette\Forms\IControl) { - throw new Nette\InvalidArgumentException('Validation scope accepts only Nette\Forms\Container or Nette\Forms\IControl instances.'); - } - $this->validationScope[] = $control; - } - } - return $this; - } - - - /** - * Gets the validation scope. - * @return array|NULL - */ - public function getValidationScope() - { - return $this->validationScope; - } - - - /** - * Fires click event. - * @return void - */ - public function click() - { - $this->onClick($this); - } - - - /** - * Generates control's HTML element. - * @param string - * @return Nette\Utils\Html - */ - public function getControl($caption = NULL) - { - $scope = array(); - foreach ((array) $this->validationScope as $control) { - $scope[] = $control->lookupPath('Nette\Forms\Form'); - } - return parent::getControl($caption)->addAttributes(array( - 'formnovalidate' => $this->validationScope !== NULL, - 'data-nette-validation-scope' => $scope ? json_encode($scope) : NULL, - )); - } - - - /** - * Submitted validator: has been button pressed? - * @return bool - */ - public static function validateSubmitted(SubmitButton $control) - { - return $control->isSubmittedBy(); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/TextArea.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/TextArea.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/TextArea.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/TextArea.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -control->setName('textarea'); - } - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl() - { - $value = $this->getValue(); - if ($value === '') { - $value = $this->translate($this->emptyValue); - } - return parent::getControl() - ->setText($value); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/TextBase.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/TextBase.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/TextBase.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/TextBase.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,228 +0,0 @@ -name)); - } - $this->rawValue = $this->value = $value; - return $this; - } - - - /** - * Returns control's value. - * @return string - */ - public function getValue() - { - $value = $this->value; - if (!empty($this->control->maxlength)) { - $value = Nette\Utils\Strings::substring($value, 0, $this->control->maxlength); - } - foreach ($this->filters as $filter) { - $value = (string) call_user_func($filter, $value); - } - return $value === $this->translate($this->emptyValue) ? '' : $value; - } - - - /** - * Sets the special value which is treated as empty string. - * @param string - * @return self - */ - public function setEmptyValue($value) - { - $this->emptyValue = (string) $value; - return $this; - } - - - /** - * Returns the special value which is treated as empty string. - * @return string - */ - public function getEmptyValue() - { - return $this->emptyValue; - } - - - /** - * Appends input string filter callback. - * @param callable - * @return self - */ - public function addFilter($filter) - { - $this->filters[] = Nette\Utils\Callback::check($filter); - return $this; - } - - - public function getControl() - { - $el = parent::getControl(); - if ($this->emptyValue !== '') { - $el->attrs['data-nette-empty-value'] = $this->translate($this->emptyValue); - } - if (isset($el->placeholder)) { - $el->placeholder = $this->translate($el->placeholder); - } - return $el; - } - - - public function addRule($operation, $message = NULL, $arg = NULL) - { - if ($operation === Form::LENGTH || $operation === Form::MAX_LENGTH) { - $tmp = is_array($arg) ? $arg[1] : $arg; - if (is_scalar($tmp)) { - $this->control->maxlength = isset($this->control->maxlength) ? min($this->control->maxlength, $tmp) : $tmp; - } - } - return parent::addRule($operation, $message, $arg); - } - - - /********************* validators ****************d*g**/ - - - /** - * Is control's value valid email address? - * @return bool - */ - public static function validateEmail(TextBase $control) - { - return Validators::isEmail($control->getValue()); - } - - - /** - * Is control's value valid URL? - * @return bool - */ - public static function validateUrl(TextBase $control) - { - if (Validators::isUrl($value = $control->getValue())) { - return TRUE; - - } elseif (Validators::isUrl($value = "http://$value")) { - $control->setValue($value); - return TRUE; - } - return FALSE; - } - - - /** - * URL string cleanup. - * @param string - * @return string - */ - public static function filterUrl($s) - { - return Validators::isUrl('http://' . $s) ? 'http://' . $s : $s; - } - - - /** @deprecated */ - public static function validateRegexp(TextBase $control, $regexp) - { - trigger_error('Validator REGEXP is deprecated; use PATTERN instead (which is matched against the entire value and is case sensitive).', E_USER_DEPRECATED); - return (bool) Strings::match($control->getValue(), $regexp); - } - - - /** - * Matches control's value regular expression? - * @return bool - */ - public static function validatePattern(TextBase $control, $pattern) - { - return (bool) Strings::match($control->getValue(), "\x01^($pattern)\\z\x01u"); - } - - - /** - * Is a control's value decimal number? - * @return bool - */ - public static function validateInteger(TextBase $control) - { - if (Validators::isNumericInt($value = $control->getValue())) { - if (!is_float($tmp = $value * 1)) { // bigint leave as string - $control->setValue($tmp); - } - return TRUE; - } - return FALSE; - } - - - /** - * Is a control's value float number? - * @return bool - */ - public static function validateFloat(TextBase $control) - { - $value = self::filterFloat($control->getValue()); - if (Validators::isNumeric($value)) { - $control->setValue((float) $value); - return TRUE; - } - return FALSE; - } - - - /** - * Float string cleanup. - * @param string - * @return string - */ - public static function filterFloat($s) - { - return str_replace(array(' ', ','), array('', '.'), $s); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/TextInput.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/TextInput.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/TextInput.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/TextInput.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -control->type = 'text'; - $this->control->maxlength = $maxLength; - } - - - /** - * Loads HTTP data. - * @return void - */ - public function loadHttpData() - { - $this->setValue($this->getHttpData(Nette\Forms\Form::DATA_LINE)); - } - - - /** - * Changes control's type attribute. - * @param string - * @return self - */ - public function setType($type) - { - $this->control->type = $type; - return $this; - } - - - /** @deprecated */ - public function setPasswordMode($mode = TRUE) - { - trigger_error(__METHOD__ . '() is deprecated; use setType("password") instead.', E_USER_DEPRECATED); - $this->control->type = $mode ? 'password' : 'text'; - return $this; - } - - - /** - * Generates control's HTML element. - * @return Nette\Utils\Html - */ - public function getControl() - { - $input = parent::getControl(); - - foreach ($this->getRules() as $rule) { - if ($rule->isNegative || $rule->type !== Nette\Forms\Rule::VALIDATOR) { - - } elseif ($rule->operation === Nette\Forms\Form::RANGE - && in_array($input->type, array('number', 'range', 'datetime-local', 'datetime', 'date', 'month', 'week', 'time')) - ) { - if (isset($rule->arg[0]) && is_scalar($rule->arg[0])) { - $input->min = isset($input->min) ? max($input->min, $rule->arg[0]) : $rule->arg[0]; - } - if (isset($rule->arg[1]) && is_scalar($rule->arg[1])) { - $input->max = isset($input->max) ? min($input->max, $rule->arg[1]) : $rule->arg[1]; - } - - } elseif ($rule->operation === Nette\Forms\Form::PATTERN && is_scalar($rule->arg) - && in_array($input->type, array('text', 'search', 'tel', 'url', 'email', 'password')) - ) { - $input->pattern = $rule->arg; - } - } - - if ($input->type !== 'password') { - $input->value = $this->rawValue === '' ? $this->translate($this->emptyValue) : $this->rawValue; - } - return $input; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/UploadControl.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/UploadControl.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Controls/UploadControl.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Controls/UploadControl.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,152 +0,0 @@ -control->type = 'file'; - $this->control->multiple = (bool) $multiple; - } - - - /** - * This method will be called when the component (or component's parent) - * becomes attached to a monitored object. Do not call this method yourself. - * @param Nette\ComponentModel\IComponent - * @return void - */ - protected function attached($form) - { - if ($form instanceof Nette\Forms\Form) { - if ($form->getMethod() !== Nette\Forms\Form::POST) { - throw new Nette\InvalidStateException('File upload requires method POST.'); - } - $form->getElementPrototype()->enctype = 'multipart/form-data'; - } - parent::attached($form); - } - - - /** - * Loads HTTP data. - * @return void - */ - public function loadHttpData() - { - $this->value = $this->getHttpData(Nette\Forms\Form::DATA_FILE); - if ($this->value === NULL) { - $this->value = new FileUpload(NULL); - } - } - - - /** - * Returns HTML name of control. - * @return string - */ - public function getHtmlName() - { - return parent::getHtmlName() . ($this->control->multiple ? '[]' : ''); - } - - - /** - * @return self - */ - public function setValue($value) - { - return $this; - } - - - /** - * Has been any file uploaded? - * @return bool - */ - public function isFilled() - { - return $this->value instanceof FileUpload ? $this->value->isOk() : (bool) $this->value; // ignore NULL object - } - - - /********************* validators ****************d*g**/ - - - /** - * Is file size in limit? - * @return bool - */ - public static function validateFileSize(UploadControl $control, $limit) - { - foreach (static::toArray($control->getValue()) as $file) { - if ($file->getSize() > $limit || $file->getError() === UPLOAD_ERR_INI_SIZE) { - return FALSE; - } - } - return TRUE; - } - - - /** - * Has file specified mime type? - * @return bool - */ - public static function validateMimeType(UploadControl $control, $mimeType) - { - $mimeTypes = is_array($mimeType) ? $mimeType : explode(',', $mimeType); - foreach (static::toArray($control->getValue()) as $file) { - $type = strtolower($file->getContentType()); - if (!in_array($type, $mimeTypes, TRUE) && !in_array(preg_replace('#/.*#', '/*', $type), $mimeTypes, TRUE)) { - return FALSE; - } - } - return TRUE; - } - - - /** - * Is file image? - * @return bool - */ - public static function validateImage(UploadControl $control) - { - foreach (static::toArray($control->getValue()) as $file) { - if (!$file->isImage()) { - return FALSE; - } - } - return TRUE; - } - - - /** - * @return array - */ - public static function toArray($value) - { - return $value instanceof FileUpload ? array($value) : (array) $value; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Form.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Form.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Form.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Form.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,633 +0,0 @@ - element */ - private $element; - - /** @var IFormRenderer */ - private $renderer; - - /** @var Nette\Localization\ITranslator */ - private $translator; - - /** @var ControlGroup[] */ - private $groups = array(); - - /** @var array */ - private $errors = array(); - - /** @var Nette\Http\IRequest used only by standalone form */ - public $httpRequest; - - - /** - * Form constructor. - * @param string - */ - public function __construct($name = NULL) - { - $this->element = Nette\Utils\Html::el('form'); - $this->element->action = ''; // RFC 1808 -> empty uri means 'this' - $this->element->method = self::POST; - $this->element->id = $name === NULL ? NULL : 'frm-' . $name; - - $this->monitor(__CLASS__); - if ($name !== NULL) { - $tracker = new Controls\HiddenField($name); - $tracker->setOmitted(); - $this[self::TRACKER_ID] = $tracker; - } - parent::__construct(NULL, $name); - } - - - /** - * This method will be called when the component (or component's parent) - * becomes attached to a monitored object. Do not call this method yourself. - * @param Nette\ComponentModel\IComponent - * @return void - */ - protected function attached($obj) - { - if ($obj instanceof self) { - throw new Nette\InvalidStateException('Nested forms are forbidden.'); - } - } - - - /** - * Returns self. - * @return Form - */ - public function getForm($need = TRUE) - { - return $this; - } - - - /** - * Sets form's action. - * @param mixed URI - * @return self - */ - public function setAction($url) - { - $this->element->action = $url; - return $this; - } - - - /** - * Returns form's action. - * @return mixed URI - */ - public function getAction() - { - return $this->element->action; - } - - - /** - * Sets form's method. - * @param string get | post - * @return self - */ - public function setMethod($method) - { - if ($this->httpData !== NULL) { - throw new Nette\InvalidStateException(__METHOD__ . '() must be called until the form is empty.'); - } - $this->element->method = strtolower($method); - return $this; - } - - - /** - * Returns form's method. - * @return string get | post - */ - public function getMethod() - { - return $this->element->method; - } - - - /** - * Cross-Site Request Forgery (CSRF) form protection. - * @param string - * @return Controls\CsrfProtection - */ - public function addProtection($message = NULL) - { - return $this[self::PROTECTOR_ID] = new Controls\CsrfProtection($message); - } - - - /** - * Adds fieldset group to the form. - * @param string caption - * @param bool set this group as current - * @return ControlGroup - */ - public function addGroup($caption = NULL, $setAsCurrent = TRUE) - { - $group = new ControlGroup; - $group->setOption('label', $caption); - $group->setOption('visual', TRUE); - - if ($setAsCurrent) { - $this->setCurrentGroup($group); - } - - if (!is_scalar($caption) || isset($this->groups[$caption])) { - return $this->groups[] = $group; - } else { - return $this->groups[$caption] = $group; - } - } - - - /** - * Removes fieldset group from form. - * @param string|ControlGroup - * @return void - */ - public function removeGroup($name) - { - if (is_string($name) && isset($this->groups[$name])) { - $group = $this->groups[$name]; - - } elseif ($name instanceof ControlGroup && in_array($name, $this->groups, TRUE)) { - $group = $name; - $name = array_search($group, $this->groups, TRUE); - - } else { - throw new Nette\InvalidArgumentException("Group not found in form '$this->name'"); - } - - foreach ($group->getControls() as $control) { - $control->getParent()->removeComponent($control); - } - - unset($this->groups[$name]); - } - - - /** - * Returns all defined groups. - * @return ControlGroup[] - */ - public function getGroups() - { - return $this->groups; - } - - - /** - * Returns the specified group. - * @param string name - * @return ControlGroup - */ - public function getGroup($name) - { - return isset($this->groups[$name]) ? $this->groups[$name] : NULL; - } - - - /********************* translator ****************d*g**/ - - - /** - * Sets translate adapter. - * @return self - */ - public function setTranslator(Nette\Localization\ITranslator $translator = NULL) - { - $this->translator = $translator; - return $this; - } - - - /** - * Returns translate adapter. - * @return Nette\Localization\ITranslator|NULL - */ - public function getTranslator() - { - return $this->translator; - } - - - /********************* submission ****************d*g**/ - - - /** - * Tells if the form is anchored. - * @return bool - */ - public function isAnchored() - { - return TRUE; - } - - - /** - * Tells if the form was submitted. - * @return ISubmitterControl|FALSE submittor control - */ - public function isSubmitted() - { - if ($this->submittedBy === NULL) { - $this->getHttpData(); - } - return $this->submittedBy; - } - - - /** - * Tells if the form was submitted and successfully validated. - * @return bool - */ - public function isSuccess() - { - return $this->isSubmitted() && $this->isValid(); - } - - - /** - * Sets the submittor control. - * @return self - */ - public function setSubmittedBy(ISubmitterControl $by = NULL) - { - $this->submittedBy = $by === NULL ? FALSE : $by; - return $this; - } - - - /** - * Returns submitted HTTP data. - * @return mixed - */ - public function getHttpData($type = NULL, $htmlName = NULL) - { - if ($this->httpData === NULL) { - if (!$this->isAnchored()) { - throw new Nette\InvalidStateException('Form is not anchored and therefore can not determine whether it was submitted.'); - } - $data = $this->receiveHttpData(); - $this->httpData = (array) $data; - $this->submittedBy = is_array($data); - } - if ($htmlName === NULL) { - return $this->httpData; - } - return Helpers::extractHttpData($this->httpData, $htmlName, $type); - } - - - /** - * Fires submit/click events. - * @return void - */ - public function fireEvents() - { - if (!$this->isSubmitted()) { - return; - } - - $this->validate(); - - if ($this->submittedBy instanceof ISubmitterControl) { - if ($this->isValid()) { - $this->submittedBy->onClick($this->submittedBy); - } else { - $this->submittedBy->onInvalidClick($this->submittedBy); - } - } - - if ($this->onSuccess) { - foreach ($this->onSuccess as $handler) { - if (!$this->isValid()) { - $this->onError($this); - break; - } - Nette\Utils\Callback::invoke($handler, $this); - } - } elseif (!$this->isValid()) { - $this->onError($this); - } - $this->onSubmit($this); - } - - - /** - * Internal: returns submitted HTTP data or NULL when form was not submitted. - * @return array|NULL - */ - protected function receiveHttpData() - { - $httpRequest = $this->getHttpRequest(); - if (strcasecmp($this->getMethod(), $httpRequest->getMethod())) { - return; - } - - if ($httpRequest->isMethod('post')) { - $data = Nette\Utils\Arrays::mergeTree($httpRequest->getPost(), $httpRequest->getFiles()); - } else { - $data = $httpRequest->getQuery(); - if (!$data) { - return; - } - } - - if ($tracker = $this->getComponent(self::TRACKER_ID, FALSE)) { - if (!isset($data[self::TRACKER_ID]) || $data[self::TRACKER_ID] !== $tracker->getValue()) { - return; - } - } - - return $data; - } - - - /********************* validation ****************d*g**/ - - - public function validate(array $controls = NULL) - { - $this->cleanErrors(); - if ($controls === NULL && $this->submittedBy instanceof ISubmitterControl) { - $controls = $this->submittedBy->getValidationScope(); - } - $this->validateMaxPostSize(); - parent::validate($controls); - } - - - public function validateMaxPostSize() - { - if (!$this->submittedBy || strcasecmp($this->getMethod(), 'POST') || empty($_SERVER['CONTENT_LENGTH'])) { - return; - } - $maxSize = ini_get('post_max_size'); - $units = array('k' => 10, 'm' => 20, 'g' => 30); - if (isset($units[$ch = strtolower(substr($maxSize, -1))])) { - $maxSize <<= $units[$ch]; - } - if ($maxSize > 0 && $maxSize < $_SERVER['CONTENT_LENGTH']) { - $this->addError(sprintf(Rules::$defaultMessages[self::MAX_FILE_SIZE], $maxSize)); - } - } - - - /** - * Adds global error message. - * @param string error message - * @return void - */ - public function addError($message) - { - $this->errors[] = $message; - } - - - /** - * Returns global validation errors. - * @return array - */ - public function getErrors() - { - return array_unique(array_merge($this->errors, parent::getErrors())); - } - - - /** - * @return bool - */ - public function hasErrors() - { - return (bool) $this->getErrors(); - } - - - /** - * @return void - */ - public function cleanErrors() - { - $this->errors = array(); - } - - - /** - * Returns form's validation errors. - * @return array - */ - public function getOwnErrors() - { - return array_unique($this->errors); - } - - - /** @deprecated */ - public function getAllErrors() - { - trigger_error(__METHOD__ . '() is deprecated; use getErrors() instead.', E_USER_DEPRECATED); - return $this->getErrors(); - } - - - /********************* rendering ****************d*g**/ - - - /** - * Returns form's HTML element template. - * @return Nette\Utils\Html - */ - public function getElementPrototype() - { - return $this->element; - } - - - /** - * Sets form renderer. - * @return self - */ - public function setRenderer(IFormRenderer $renderer = NULL) - { - $this->renderer = $renderer; - return $this; - } - - - /** - * Returns form renderer. - * @return IFormRenderer - */ - public function getRenderer() - { - if ($this->renderer === NULL) { - $this->renderer = new Rendering\DefaultFormRenderer; - } - return $this->renderer; - } - - - /** - * Renders form. - * @return void - */ - public function render() - { - $args = func_get_args(); - array_unshift($args, $this); - echo call_user_func_array(array($this->getRenderer(), 'render'), $args); - } - - - /** - * Renders form to string. - * @return can throw exceptions? (hidden parameter) - * @return string - */ - public function __toString() - { - try { - return $this->getRenderer()->render($this); - - } catch (\Exception $e) { - if (func_num_args()) { - throw $e; - } - trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); - } - } - - - /********************* backend ****************d*g**/ - - - /** - * @return Nette\Http\IRequest - */ - private function getHttpRequest() - { - if (!$this->httpRequest) { - $factory = new Nette\Http\RequestFactory; - $this->httpRequest = $factory->createHttpRequest(); - } - return $this->httpRequest; - } - - - /** - * @return array - */ - public function getToggles() - { - $toggles = array(); - foreach ($this->getControls() as $control) { - $toggles = $control->getRules()->getToggleStates($toggles); - } - return $toggles; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Helpers.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Helpers.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Helpers.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Helpers.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,181 +0,0 @@ - $v) { - $data[$k] = $v = static::sanitize($itype, $v); - if ($v === NULL) { - return array(); - } - } - if ($type & Form::DATA_KEYS) { - return $data; - } - return array_values($data); - } else { - return static::sanitize($itype, $data); - } - } - - - private static function sanitize($type, $value) - { - if ($type === Form::DATA_TEXT) { - return is_scalar($value) ? Strings::normalizeNewLines($value) : NULL; - - } elseif ($type === Form::DATA_LINE) { - return is_scalar($value) ? Strings::trim(strtr($value, "\r\n", ' ')) : NULL; - - } elseif ($type === Form::DATA_FILE) { - return $value instanceof Nette\Http\FileUpload ? $value : NULL; - - } else { - throw new Nette\InvalidArgumentException('Unknown data type'); - } - } - - - /** - * Converts control name to HTML name. - * @return string - */ - public static function generateHtmlName($id) - { - $name = str_replace(Nette\ComponentModel\IComponent::NAME_SEPARATOR, '][', $id, $count); - if ($count) { - $name = substr_replace($name, '', strpos($name, ']'), 1) . ']'; - } - if (is_numeric($name) || in_array($name, self::$unsafeNames)) { - $name = '_' . $name; - } - return $name; - } - - - /** - * @return string - */ - public static function createInputList(array $items, array $inputAttrs = NULL, array $labelAttrs = NULL, $wrapper = NULL) - { - list($inputAttrs, $inputTag) = self::prepareAttrs($inputAttrs, 'input'); - list($labelAttrs, $labelTag) = self::prepareAttrs($labelAttrs, 'label'); - $res = ''; - $input = Html::el(); - $label = Html::el(); - list($wrapper, $wrapperEnd) = $wrapper instanceof Html ? array($wrapper->startTag(), $wrapper->endTag()) : array((string) $wrapper, ''); - - foreach ($items as $value => $caption) { - foreach ($inputAttrs as $k => $v) { - $input->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL; - } - foreach ($labelAttrs as $k => $v) { - $label->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL; - } - $input->value = $value; - $res .= ($res === '' && $wrapperEnd === '' ? '' : $wrapper) - . $labelTag . $label->attributes() . '>' - . $inputTag . $input->attributes() . (Html::$xhtml ? ' />' : '>') - . ($caption instanceof Html ? $caption : htmlspecialchars($caption)) - . '' - . $wrapperEnd; - } - return $res; - } - - - /** - * @return Nette\Utils\Html - */ - public static function createSelectBox(array $items, array $optionAttrs = NULL) - { - list($optionAttrs, $optionTag) = self::prepareAttrs($optionAttrs, 'option'); - $option = Html::el(); - $res = $tmp = ''; - foreach ($items as $group => $subitems) { - if (is_array($subitems)) { - $res .= Html::el('optgroup')->label($group)->startTag(); - $tmp = ''; - } else { - $subitems = array($group => $subitems); - } - foreach ($subitems as $value => $caption) { - $option->value = $value; - foreach ($optionAttrs as $k => $v) { - $option->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL; - } - if ($caption instanceof Html) { - $caption = clone $caption; - $res .= $caption->setName('option')->addAttributes($option->attrs); - } else { - $res .= $optionTag . $option->attributes() . '>' - . htmlspecialchars($caption) - . ''; - } - } - $res .= $tmp; - $tmp = ''; - } - return Html::el('select')->setHtml($res); - } - - - private static function prepareAttrs($attrs, $name) - { - $dynamic = array(); - foreach ((array) $attrs as $k => $v) { - $p = str_split($k, strlen($k) - 1); - if ($p[1] === '?' || $p[1] === ':') { - unset($attrs[$k], $attrs[$p[0]]); - if ($p[1] === '?') { - $dynamic[$p[0]] = array_fill_keys((array) $v, TRUE); - } elseif (is_array($v) && $v) { - $dynamic[$p[0]] = $v; - } else { - $attrs[$p[0]] = $v; - } - } - } - return array($dynamic, '<' . $name . Html::el(NULL, $attrs)->attributes()); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/IControl.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/IControl.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/IControl.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/IControl.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -getValues() result? - * @return bool - */ - function isOmitted(); - - /** - * Returns translated string. - * @param string - * @param int plural count - * @return string - */ - function translate($s, $count = NULL); - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/IFormRenderer.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/IFormRenderer.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/IFormRenderer.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/IFormRenderer.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ - array( - 'container' => NULL, - ), - - 'error' => array( - 'container' => 'ul class=error', - 'item' => 'li', - ), - - 'group' => array( - 'container' => 'fieldset', - 'label' => 'legend', - 'description' => 'p', - ), - - 'controls' => array( - 'container' => 'table', - ), - - 'pair' => array( - 'container' => 'tr', - '.required' => 'required', - '.optional' => NULL, - '.odd' => NULL, - '.error' => NULL, - ), - - 'control' => array( - 'container' => 'td', - '.odd' => NULL, - - 'description' => 'small', - 'requiredsuffix' => '', - 'errorcontainer' => 'span class=error', - 'erroritem' => '', - - '.required' => 'required', - '.text' => 'text', - '.password' => 'text', - '.file' => 'text', - '.submit' => 'button', - '.image' => 'imagebutton', - '.button' => 'button', - ), - - 'label' => array( - 'container' => 'th', - 'suffix' => NULL, - 'requiredsuffix' => '', - ), - - 'hidden' => array( - 'container' => 'div', - ), - ); - - /** @var Nette\Forms\Form */ - protected $form; - - /** @var int */ - protected $counter; - - - /** - * Provides complete form rendering. - * @param Nette\Forms\Form - * @param string 'begin', 'errors', 'ownerrors', 'body', 'end' or empty to render all - * @return string - */ - public function render(Nette\Forms\Form $form, $mode = NULL) - { - if ($this->form !== $form) { - $this->form = $form; - $this->init(); - } - - $s = ''; - if (!$mode || $mode === 'begin') { - $s .= $this->renderBegin(); - } - if (!$mode || strtolower($mode) === 'ownerrors') { - $s .= $this->renderErrors(); - - } elseif ($mode === 'errors') { - $s .= $this->renderErrors(NULL, FALSE); - } - if (!$mode || $mode === 'body') { - $s .= $this->renderBody(); - } - if (!$mode || $mode === 'end') { - $s .= $this->renderEnd(); - } - return $s; - } - - - /** - * Initializes form. - * @return void - */ - protected function init() - { - // TODO: only for back compatiblity - remove? - $wrapper = & $this->wrappers['control']; - foreach ($this->form->getControls() as $control) { - if ($control->isRequired() && isset($wrapper['.required'])) { - $control->getLabelPrototype()->class($wrapper['.required'], TRUE); - } - - $el = $control->getControlPrototype(); - if ($el->getName() === 'input' && isset($wrapper['.' . $el->type])) { - $el->class($wrapper['.' . $el->type], TRUE); - } - } - } - - - /** - * Renders form begin. - * @return string - */ - public function renderBegin() - { - $this->counter = 0; - - foreach ($this->form->getControls() as $control) { - $control->setOption('rendered', FALSE); - } - - if (strcasecmp($this->form->getMethod(), 'get') === 0) { - $el = clone $this->form->getElementPrototype(); - $query = parse_url($el->action, PHP_URL_QUERY); - $el->action = str_replace("?$query", '', $el->action); - $s = ''; - foreach (preg_split('#[;&]#', $query, NULL, PREG_SPLIT_NO_EMPTY) as $param) { - $parts = explode('=', $param, 2); - $name = urldecode($parts[0]); - if (!isset($this->form[$name])) { - $s .= Html::el('input', array('type' => 'hidden', 'name' => $name, 'value' => urldecode($parts[1]))); - } - } - return $el->startTag() . ($s ? "\n\t" . $this->getWrapper('hidden container')->setHtml($s) : ''); - - } else { - return $this->form->getElementPrototype()->startTag(); - } - } - - - /** - * Renders form end. - * @return string - */ - public function renderEnd() - { - $s = ''; - foreach ($this->form->getControls() as $control) { - if ($control instanceof Nette\Forms\Controls\HiddenField && !$control->getOption('rendered')) { - $s .= $control->getControl(); - } - } - if (iterator_count($this->form->getComponents(TRUE, 'Nette\Forms\Controls\TextInput')) < 2) { - $s .= ''; - } - if ($s) { - $s = $this->getWrapper('hidden container')->setHtml($s) . "\n"; - } - - return $s . $this->form->getElementPrototype()->endTag() . "\n"; - } - - - /** - * Renders validation errors (per form or per control). - * @return string - */ - public function renderErrors(Nette\Forms\IControl $control = NULL, $own = TRUE) - { - $errors = $control - ? $control->getErrors() - : ($own ? $this->form->getOwnErrors() : $this->form->getErrors()); - if (!$errors) { - return; - } - $container = $this->getWrapper($control ? 'control errorcontainer' : 'error container'); - $item = $this->getWrapper($control ? 'control erroritem' : 'error item'); - - foreach ($errors as $error) { - $item = clone $item; - if ($error instanceof Html) { - $item->add($error); - } else { - $item->setText($error); - } - $container->add($item); - } - return "\n" . $container->render($control ? 1 : 0); - } - - - /** - * Renders form body. - * @return string - */ - public function renderBody() - { - $s = $remains = ''; - - $defaultContainer = $this->getWrapper('group container'); - $translator = $this->form->getTranslator(); - - foreach ($this->form->getGroups() as $group) { - if (!$group->getControls() || !$group->getOption('visual')) { - continue; - } - - $container = $group->getOption('container', $defaultContainer); - $container = $container instanceof Html ? clone $container : Html::el($container); - - $s .= "\n" . $container->startTag(); - - $text = $group->getOption('label'); - if ($text instanceof Html) { - $s .= $this->getWrapper('group label')->add($text); - - } elseif (is_string($text)) { - if ($translator !== NULL) { - $text = $translator->translate($text); - } - $s .= "\n" . $this->getWrapper('group label')->setText($text) . "\n"; - } - - $text = $group->getOption('description'); - if ($text instanceof Html) { - $s .= $text; - - } elseif (is_string($text)) { - if ($translator !== NULL) { - $text = $translator->translate($text); - } - $s .= $this->getWrapper('group description')->setText($text) . "\n"; - } - - $s .= $this->renderControls($group); - - $remains = $container->endTag() . "\n" . $remains; - if (!$group->getOption('embedNext')) { - $s .= $remains; - $remains = ''; - } - } - - $s .= $remains . $this->renderControls($this->form); - - $container = $this->getWrapper('form container'); - $container->setHtml($s); - return $container->render(0); - } - - - /** - * Renders group of controls. - * @param Nette\Forms\Container|FormGroup - * @return string - */ - public function renderControls($parent) - { - if (!($parent instanceof Nette\Forms\Container || $parent instanceof Nette\Forms\ControlGroup)) { - throw new Nette\InvalidArgumentException('Argument must be FormContainer or FormGroup instance.'); - } - - $container = $this->getWrapper('controls container'); - - $buttons = NULL; - foreach ($parent->getControls() as $control) { - if ($control->getOption('rendered') || $control instanceof Nette\Forms\Controls\HiddenField || $control->getForm(FALSE) !== $this->form) { - // skip - - } elseif ($control instanceof Nette\Forms\Controls\Button) { - $buttons[] = $control; - - } else { - if ($buttons) { - $container->add($this->renderPairMulti($buttons)); - $buttons = NULL; - } - $container->add($this->renderPair($control)); - } - } - - if ($buttons) { - $container->add($this->renderPairMulti($buttons)); - } - - $s = ''; - if (count($container)) { - $s .= "\n" . $container . "\n"; - } - - return $s; - } - - - /** - * Renders single visual row. - * @return string - */ - public function renderPair(Nette\Forms\IControl $control) - { - $pair = $this->getWrapper('pair container'); - $pair->add($this->renderLabel($control)); - $pair->add($this->renderControl($control)); - $pair->class($this->getValue($control->isRequired() ? 'pair .required' : 'pair .optional'), TRUE); - $pair->class($control->hasErrors() ? $this->getValue('pair .error') : NULL, TRUE); - $pair->class($control->getOption('class'), TRUE); - if (++$this->counter % 2) { - $pair->class($this->getValue('pair .odd'), TRUE); - } - $pair->id = $control->getOption('id'); - return $pair->render(0); - } - - - /** - * Renders single visual row of multiple controls. - * @param IFormControl[] - * @return string - */ - public function renderPairMulti(array $controls) - { - $s = array(); - foreach ($controls as $control) { - if (!$control instanceof Nette\Forms\IControl) { - throw new Nette\InvalidArgumentException('Argument must be array of IFormControl instances.'); - } - $description = $control->getOption('description'); - if ($description instanceof Html) { - $description = ' ' . $control->getOption('description'); - - } elseif (is_string($description)) { - $description = ' ' . $this->getWrapper('control description')->setText($control->translate($description)); - - } else { - $description = ''; - } - - $s[] = $control->getControl() . $description; - } - $pair = $this->getWrapper('pair container'); - $pair->add($this->renderLabel($control)); - $pair->add($this->getWrapper('control container')->setHtml(implode(' ', $s))); - return $pair->render(0); - } - - - /** - * Renders 'label' part of visual row of controls. - * @return string - */ - public function renderLabel(Nette\Forms\IControl $control) - { - $suffix = $this->getValue('label suffix') . ($control->isRequired() ? $this->getValue('label requiredsuffix') : ''); - $label = $control->getLabel(); - if ($label instanceof Html) { - $label->add($suffix); - } elseif ($label != NULL) { // @intentionally == - $label .= $suffix; - } - return $this->getWrapper('label container')->setHtml($label); - } - - - /** - * Renders 'control' part of visual row of controls. - * @return string - */ - public function renderControl(Nette\Forms\IControl $control) - { - $body = $this->getWrapper('control container'); - if ($this->counter % 2) { - $body->class($this->getValue('control .odd'), TRUE); - } - - $description = $control->getOption('description'); - if ($description instanceof Html) { - $description = ' ' . $description; - - } elseif (is_string($description)) { - $description = ' ' . $this->getWrapper('control description')->setText($control->translate($description)); - - } else { - $description = ''; - } - - if ($control->isRequired()) { - $description = $this->getValue('control requiredsuffix') . $description; - } - - $el = $control->getControl(); - return $body->setHtml($el . $description . $this->renderErrors($control)); - } - - - /** - * @param string - * @return Nette\Utils\Html - */ - protected function getWrapper($name) - { - $data = $this->getValue($name); - return $data instanceof Html ? clone $data : Html::el($data); - } - - - /** - * @param string - * @return string - */ - protected function getValue($name) - { - $name = explode(' ', $name); - $data = & $this->wrappers[$name[0]][$name[1]]; - return $data; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Rule.php php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Rule.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Forms/Rule.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Forms/Rule.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ - 'Please submit this form again (security token has expired).', - Form::EQUAL => 'Please enter %s.', - Form::NOT_EQUAL => 'This value should not be %s.', - Form::FILLED => 'This field is required.', - Form::BLANK => 'This field should be blank.', - Form::MIN_LENGTH => 'Please enter at least %d characters.', - Form::MAX_LENGTH => 'Please enter no more than %d characters.', - Form::LENGTH => 'Please enter a value between %d and %d characters long.', - Form::EMAIL => 'Please enter a valid email address.', - Form::URL => 'Please enter a valid URL.', - Form::INTEGER => 'Please enter a valid integer.', - Form::FLOAT => 'Please enter a valid number.', - Form::RANGE => 'Please enter a value between %d and %d.', - Form::MAX_FILE_SIZE => 'The size of the uploaded file can be up to %d bytes.', - Form::MAX_POST_SIZE => 'The uploaded data exceeds the limit of %d bytes.', - Form::IMAGE => 'The uploaded file must be image in format JPEG, GIF or PNG.', - Form::MIME_TYPE => 'The uploaded file is not in the expected format.', - Nette\Forms\Controls\SelectBox::VALID => 'Please select a valid option.', - ); - - /** @var Rule */ - private $required; - - /** @var Rule[] */ - private $rules = array(); - - /** @var Rules */ - private $parent; - - /** @var array */ - private $toggles = array(); - - /** @var IControl */ - private $control; - - - public function __construct(IControl $control) - { - $this->control = $control; - } - - - /** - * Makes control mandatory. - * @param mixed state or error message - * @return self - */ - public function setRequired($value = TRUE) - { - if ($value) { - $this->addRule(Form::REQUIRED, is_string($value) ? $value : NULL); - } else { - $this->required = NULL; - } - return $this; - } - - - /** - * Is control mandatory? - * @return bool - */ - public function isRequired() - { - return $this->required instanceof Rule ? !$this->required->isNegative : FALSE; - } - - - /** - * Adds a validation rule for the current control. - * @param mixed rule type - * @param string message to display for invalid data - * @param mixed optional rule arguments - * @return self - */ - public function addRule($operation, $message = NULL, $arg = NULL) - { - $rule = new Rule; - $rule->control = $this->control; - $rule->operation = $operation; - $this->adjustOperation($rule); - $rule->arg = $arg; - $rule->type = Rule::VALIDATOR; - $rule->message = $message; - if ($rule->operation === Form::REQUIRED) { - $this->required = $rule; - } else { - $this->rules[] = $rule; - } - return $this; - } - - - /** - * Adds a validation condition a returns new branch. - * @param mixed condition type - * @param mixed optional condition arguments - * @return Rules new branch - */ - public function addCondition($operation, $arg = NULL) - { - return $this->addConditionOn($this->control, $operation, $arg); - } - - - /** - * Adds a validation condition on specified control a returns new branch. - * @param IControl form control - * @param mixed condition type - * @param mixed optional condition arguments - * @return Rules new branch - */ - public function addConditionOn(IControl $control, $operation, $arg = NULL) - { - $rule = new Rule; - $rule->control = $control; - $rule->operation = $operation; - $this->adjustOperation($rule); - $rule->arg = $arg; - $rule->type = Rule::CONDITION; - $rule->subRules = new static($this->control); - $rule->subRules->parent = $this; - - $this->rules[] = $rule; - return $rule->subRules; - } - - - /** - * Adds a else statement. - * @return Rules else branch - */ - public function elseCondition() - { - $rule = clone end($this->parent->rules); - $rule->isNegative = !$rule->isNegative; - $rule->subRules = new static($this->parent->control); - $rule->subRules->parent = $this->parent; - $this->parent->rules[] = $rule; - return $rule->subRules; - } - - - /** - * Ends current validation condition. - * @return Rules parent branch - */ - public function endCondition() - { - return $this->parent; - } - - - /** - * Toggles HTML element visibility. - * @param string element id - * @param bool hide element? - * @return self - */ - public function toggle($id, $hide = TRUE) - { - $this->toggles[$id] = $hide; - return $this; - } - - - /** - * @param bool - * @return array - */ - public function getToggles($actual = FALSE) - { - return $actual ? $this->getToggleStates() : $this->toggles; - } - - - /** - * @internal - * @return array - */ - public function getToggleStates($toggles = array(), $success = TRUE) - { - foreach ($this->toggles as $id => $hide) { - $toggles[$id] = ($success xor !$hide) || !empty($toggles[$id]); - } - - foreach ($this as $rule) { - if ($rule->type === Rule::CONDITION) { - $toggles = $rule->subRules->getToggleStates($toggles, $success && static::validateRule($rule)); - } - } - return $toggles; - } - - - /** - * Validates against ruleset. - * @return bool - */ - public function validate() - { - foreach ($this as $rule) { - $success = $this->validateRule($rule); - - if ($rule->type === Rule::CONDITION && $success && !$rule->subRules->validate()) { - return FALSE; - - } elseif ($rule->type === Rule::VALIDATOR && !$success) { - $rule->control->addError(static::formatMessage($rule, TRUE)); - return FALSE; - } - } - return TRUE; - } - - - /** - * Validates single rule. - * @return bool - */ - public static function validateRule(Rule $rule) - { - $args = is_array($rule->arg) ? $rule->arg : array($rule->arg); - foreach ($args as & $val) { - $val = $val instanceof IControl ? $val->getValue() : $val; - } - return $rule->isNegative - xor call_user_func(self::getCallback($rule), $rule->control, is_array($rule->arg) ? $args : $args[0]); - } - - - /** - * Iterates over complete ruleset. - * @return \ArrayIterator - */ - public function getIterator() - { - $rules = $this->rules; - if ($this->required) { - array_unshift($rules, $this->required); - } - return new \ArrayIterator($rules); - } - - - /** - * Process 'operation' string. - * @param Rule - * @return void - */ - private function adjustOperation($rule) - { - if (is_string($rule->operation) && ord($rule->operation[0]) > 127) { - $rule->isNegative = TRUE; - $rule->operation = ~$rule->operation; - } - - if (!is_callable($this->getCallback($rule))) { - $operation = is_scalar($rule->operation) ? " '$rule->operation'" : ''; - throw new Nette\InvalidArgumentException("Unknown operation$operation for control '{$rule->control->name}'."); - } - } - - - private static function getCallback($rule) - { - $op = $rule->operation; - if (is_string($op) && strncmp($op, ':', 1) === 0) { - return get_class($rule->control) . '::' . self::VALIDATE_PREFIX . ltrim($op, ':'); - } else { - return $op; - } - } - - - public static function formatMessage($rule, $withValue) - { - $message = $rule->message; - if ($message instanceof Nette\Utils\Html) { - return $message; - - } elseif ($message === NULL && is_string($rule->operation) && isset(self::$defaultMessages[$rule->operation])) { - $message = self::$defaultMessages[$rule->operation]; - - } elseif ($message == NULL) { // intentionally == - trigger_error("Missing validation message for control '{$rule->control->name}'.", E_USER_WARNING); - } - - if ($translator = $rule->control->getForm()->getTranslator()) { - $message = $translator->translate($message, is_int($rule->arg) ? $rule->arg : NULL); - } - - $message = preg_replace_callback('#%(name|label|value|\d+\$[ds]|[ds])#', function($m) use ($rule, $withValue) { - static $i = -1; - switch ($m[1]) { - case 'name': return $rule->control->getName(); - case 'label': return $rule->control->translate($rule->control->caption); - case 'value': return $withValue ? $rule->control->getValue() : $m[0]; - default: - $args = is_array($rule->arg) ? $rule->arg : array($rule->arg); - $i = (int) $m[1] ? $m[1] - 1 : $i + 1; - return isset($args[$i]) ? ($args[$i] instanceof IControl ? ($withValue ? $args[$i]->getValue() : "%$i") : $args[$i]) : ''; - } - }, $message); - return $message; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/Context.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/Context.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/Context.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/Context.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -request = $request; - $this->response = $response; - } - - - /** - * Attempts to cache the sent entity by its last modification date. - * @param string|int|DateTime last modified time - * @param string strong entity tag validator - * @return bool - */ - public function isModified($lastModified = NULL, $etag = NULL) - { - if ($lastModified) { - $this->response->setHeader('Last-Modified', $this->response->date($lastModified)); - } - if ($etag) { - $this->response->setHeader('ETag', '"' . addslashes($etag) . '"'); - } - - $ifNoneMatch = $this->request->getHeader('If-None-Match'); - if ($ifNoneMatch === '*') { - $match = TRUE; // match, check if-modified-since - - } elseif ($ifNoneMatch !== NULL) { - $etag = $this->response->getHeader('ETag'); - - if ($etag == NULL || strpos(' ' . strtr($ifNoneMatch, ",\t", ' '), ' ' . $etag) === FALSE) { - return TRUE; - - } else { - $match = TRUE; // match, check if-modified-since - } - } - - $ifModifiedSince = $this->request->getHeader('If-Modified-Since'); - if ($ifModifiedSince !== NULL) { - $lastModified = $this->response->getHeader('Last-Modified'); - if ($lastModified != NULL && strtotime($lastModified) <= strtotime($ifModifiedSince)) { - $match = TRUE; - - } else { - return TRUE; - } - } - - if (empty($match)) { - return TRUE; - } - - $this->response->setCode(IResponse::S304_NOT_MODIFIED); - return FALSE; - } - - - /** - * @return IRequest - */ - public function getRequest() - { - return $this->request; - } - - - /** - * @return IResponse - */ - public function getResponse() - { - return $this->response; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/Diagnostics/SessionPanel.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/Diagnostics/SessionPanel.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/Diagnostics/SessionPanel.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/Diagnostics/SessionPanel.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ - - - -
-

Session # (Lifetime: )

- -
- -

empty

- - - $v) { - if ($k === '__NF') { - $k = 'Nette Session'; $v = isset($v['DATA']) ? $v['DATA'] : NULL; - } - echo '\n"; - }?> -
', htmlspecialchars($k), '', Nette\Diagnostics\Dumper::toHtml($v), "
- -
-
diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml php-nette-2.1.5/Nette-2.1.4/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ - -Session diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/FileUpload.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/FileUpload.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/FileUpload.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/FileUpload.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,203 +0,0 @@ -error = UPLOAD_ERR_NO_FILE; - return; // or throw exception? - } - } - $this->name = $value['name']; - $this->size = $value['size']; - $this->tmpName = $value['tmp_name']; - $this->error = $value['error']; - } - - - /** - * Returns the file name. - * @return string - */ - public function getName() - { - return $this->name; - } - - - /** - * Returns the sanitized file name. - * @return string - */ - public function getSanitizedName() - { - return trim(Nette\Utils\Strings::webalize($this->name, '.', FALSE), '.-'); - } - - - /** - * Returns the MIME content type of an uploaded file. - * @return string - */ - public function getContentType() - { - if ($this->isOk() && $this->type === NULL) { - $this->type = Nette\Utils\MimeTypeDetector::fromFile($this->tmpName); - } - return $this->type; - } - - - /** - * Returns the size of an uploaded file. - * @return int - */ - public function getSize() - { - return $this->size; - } - - - /** - * Returns the path to an uploaded file. - * @return string - */ - public function getTemporaryFile() - { - return $this->tmpName; - } - - - /** - * Returns the path to an uploaded file. - * @return string - */ - public function __toString() - { - return (string) $this->tmpName; - } - - - /** - * Returns the error code. {@link http://php.net/manual/en/features.file-upload.errors.php} - * @return int - */ - public function getError() - { - return $this->error; - } - - - /** - * Is there any error? - * @return bool - */ - public function isOk() - { - return $this->error === UPLOAD_ERR_OK; - } - - - /** - * Move uploaded file to new location. - * @param string - * @return self - */ - public function move($dest) - { - @mkdir(dirname($dest), 0777, TRUE); // @ - dir may already exist - @unlink($dest); // @ - file may not exists - if (!call_user_func(is_uploaded_file($this->tmpName) ? 'move_uploaded_file' : 'rename', $this->tmpName, $dest)) { - throw new Nette\InvalidStateException("Unable to move uploaded file '$this->tmpName' to '$dest'."); - } - chmod($dest, 0666); - $this->tmpName = $dest; - return $this; - } - - - /** - * Is uploaded file GIF, PNG or JPEG? - * @return bool - */ - public function isImage() - { - return in_array($this->getContentType(), array('image/gif', 'image/png', 'image/jpeg'), TRUE); - } - - - /** - * Returns the image. - * @return Nette\Image - */ - public function toImage() - { - return Nette\Image::fromFile($this->tmpName); - } - - - /** - * Returns the dimensions of an uploaded image as array. - * @return array - */ - public function getImageSize() - { - return $this->isOk() ? @getimagesize($this->tmpName) : NULL; // @ - files smaller than 12 bytes causes read error - } - - - /** - * Get file contents. - * @return string - */ - public function getContents() - { - // future implementation can try to work around safe_mode and open_basedir limitations - return $this->isOk() ? file_get_contents($this->tmpName) : NULL; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/Helpers.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/Helpers.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/Helpers.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/Helpers.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ - $max) { - return FALSE; - } elseif ($ipv4) { - $arr = array(ip2long($ip), ip2long($mask)); - } else { - $arr = unpack('N*', inet_pton($ip) . inet_pton($mask)); - $size = $size === '' ? 0 : $max - $size; - } - $bits = implode('', array_map(function ($n) { - return sprintf('%032b', $n); - }, $arr)); - return substr($bits, 0, $max - $size) === substr($bits, $max, $max - $size); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/IRequest.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/IRequest.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/IRequest.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/IRequest.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ - array('#/{2,}#' => '/'), // '%20' => '' - 'url' => array(), // '#[.,)]\z#' => '' - ); - - /** @var bool */ - private $binary = FALSE; - - /** @var array */ - private $proxies = array(); - - - /** - * @param bool - * @return self - */ - public function setBinary($binary = TRUE) - { - $this->binary = (bool) $binary; - return $this; - } - - - /** - * @param array|string - * @return self - */ - public function setProxy($proxy) - { - $this->proxies = (array) $proxy; - return $this; - } - - - /** - * Creates current HttpRequest object. - * @return Request - */ - public function createHttpRequest() - { - // DETECTS URI, base path and script path of the request. - $url = new UrlScript; - $url->scheme = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https' : 'http'; - $url->user = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''; - $url->password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; - - // host & port - if ((isset($_SERVER[$tmp = 'HTTP_HOST']) || isset($_SERVER[$tmp = 'SERVER_NAME'])) - && preg_match('#^([a-z0-9_.-]+|\[[a-f0-9:]+\])(:\d+)?\z#i', $_SERVER[$tmp], $pair) - ) { - $url->host = strtolower($pair[1]); - if (isset($pair[2])) { - $url->port = (int) substr($pair[2], 1); - } elseif (isset($_SERVER['SERVER_PORT'])) { - $url->port = (int) $_SERVER['SERVER_PORT']; - } - } - - // path & query - if (isset($_SERVER['REQUEST_URI'])) { // Apache, IIS 6.0 - $requestUrl = $_SERVER['REQUEST_URI']; - - } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0 (PHP as CGI ?) - $requestUrl = $_SERVER['ORIG_PATH_INFO']; - if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '') { - $requestUrl .= '?' . $_SERVER['QUERY_STRING']; - } - } else { - $requestUrl = ''; - } - - $requestUrl = Strings::replace($requestUrl, $this->urlFilters['url']); - $tmp = explode('?', $requestUrl, 2); - $url->path = Strings::replace($tmp[0], $this->urlFilters['path']); - $url->query = isset($tmp[1]) ? $tmp[1] : ''; - - // normalized url - $url->canonicalize(); - $url->path = Strings::fixEncoding($url->path); - - // detect script path - if (isset($_SERVER['SCRIPT_NAME'])) { - $script = $_SERVER['SCRIPT_NAME']; - } elseif (isset($_SERVER['DOCUMENT_ROOT'], $_SERVER['SCRIPT_FILENAME']) - && strncmp($_SERVER['DOCUMENT_ROOT'], $_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])) === 0 - ) { - $script = '/' . ltrim(strtr(substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])), '\\', '/'), '/'); - } else { - $script = '/'; - } - - $path = strtolower($url->path) . '/'; - $script = strtolower($script) . '/'; - $max = min(strlen($path), strlen($script)); - for ($i = 0; $i < $max; $i++) { - if ($path[$i] !== $script[$i]) { - break; - } elseif ($path[$i] === '/') { - $url->scriptPath = substr($url->path, 0, $i + 1); - } - } - - // GET, POST, COOKIE - $useFilter = (!in_array(ini_get('filter.default'), array('', 'unsafe_raw')) || ini_get('filter.default_flags')); - - parse_str($url->query, $query); - if (!$query) { - $query = $useFilter ? filter_input_array(INPUT_GET, FILTER_UNSAFE_RAW) : (empty($_GET) ? array() : $_GET); - } - $post = $useFilter ? filter_input_array(INPUT_POST, FILTER_UNSAFE_RAW) : (empty($_POST) ? array() : $_POST); - $cookies = $useFilter ? filter_input_array(INPUT_COOKIE, FILTER_UNSAFE_RAW) : (empty($_COOKIE) ? array() : $_COOKIE); - - $gpc = (bool) get_magic_quotes_gpc(); - - // remove fucking quotes, control characters and check encoding - if ($gpc || !$this->binary) { - $list = array(& $query, & $post, & $cookies); - while (list($key, $val) = each($list)) { - foreach ($val as $k => $v) { - unset($list[$key][$k]); - - if ($gpc) { - $k = stripslashes($k); - } - - if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) { - // invalid key -> ignore - - } elseif (is_array($v)) { - $list[$key][$k] = $v; - $list[] = & $list[$key][$k]; - - } else { - if ($gpc && !$useFilter) { - $v = stripSlashes($v); - } - if (!$this->binary && (preg_match(self::NONCHARS, $v) || preg_last_error())) { - $v = ''; - } - $list[$key][$k] = $v; - } - } - } - unset($list, $key, $val, $k, $v); - } - - - // FILES and create FileUpload objects - $files = array(); - $list = array(); - if (!empty($_FILES)) { - foreach ($_FILES as $k => $v) { - if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) { - continue; - } - $v['@'] = & $files[$k]; - $list[] = $v; - } - } - - while (list(, $v) = each($list)) { - if (!isset($v['name'])) { - continue; - - } elseif (!is_array($v['name'])) { - if ($gpc) { - $v['name'] = stripSlashes($v['name']); - } - if (!$this->binary && (preg_match(self::NONCHARS, $v['name']) || preg_last_error())) { - $v['name'] = ''; - } - if ($v['error'] !== UPLOAD_ERR_NO_FILE) { - $v['@'] = new FileUpload($v); - } - continue; - } - - foreach ($v['name'] as $k => $foo) { - if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) { - continue; - } - $list[] = array( - 'name' => $v['name'][$k], - 'type' => $v['type'][$k], - 'size' => $v['size'][$k], - 'tmp_name' => $v['tmp_name'][$k], - 'error' => $v['error'][$k], - '@' => & $v['@'][$k], - ); - } - } - - - // HEADERS - if (function_exists('apache_request_headers')) { - $headers = array_change_key_case(apache_request_headers(), CASE_LOWER); - } else { - $headers = array(); - foreach ($_SERVER as $k => $v) { - if (strncmp($k, 'HTTP_', 5) == 0) { - $k = substr($k, 5); - } elseif (strncmp($k, 'CONTENT_', 8)) { - continue; - } - $headers[ strtr(strtolower($k), '_', '-') ] = $v; - } - } - - - $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL; - $remoteHost = isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : NULL; - - // proxy - foreach ($this->proxies as $proxy) { - if (Helpers::ipMatch($remoteAddr, $proxy)) { - if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $remoteAddr = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']))); - } - if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { - $remoteHost = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']))); - } - break; - } - } - - - $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL; - if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) - && preg_match('#^[A-Z]+\z#', $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) - ) { - $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']; - } - - return new Request($url, $query, $post, $files, $cookies, $headers, $method, $remoteAddr, $remoteHost); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/Request.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/Request.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/Request.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/Request.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,334 +0,0 @@ -url = $url; - if ($query === NULL) { - parse_str($url->query, $this->query); - } else { - $this->query = (array) $query; - } - $this->post = (array) $post; - $this->files = (array) $files; - $this->cookies = (array) $cookies; - $this->headers = (array) $headers; - $this->method = $method; - $this->remoteAddress = $remoteAddress; - $this->remoteHost = $remoteHost; - } - - - /** - * Returns URL object. - * @return UrlScript - */ - public function getUrl() - { - return $this->url; - } - - - /********************* query, post, files & cookies ****************d*g**/ - - - /** - * Returns variable provided to the script via URL query ($_GET). - * If no key is passed, returns the entire array. - * @param string key - * @param mixed default value - * @return mixed - */ - public function getQuery($key = NULL, $default = NULL) - { - if (func_num_args() === 0) { - return $this->query; - - } elseif (isset($this->query[$key])) { - return $this->query[$key]; - - } else { - return $default; - } - } - - - /** - * Returns variable provided to the script via POST method ($_POST). - * If no key is passed, returns the entire array. - * @param string key - * @param mixed default value - * @return mixed - */ - public function getPost($key = NULL, $default = NULL) - { - if (func_num_args() === 0) { - return $this->post; - - } elseif (isset($this->post[$key])) { - return $this->post[$key]; - - } else { - return $default; - } - } - - - /** - * Returns uploaded file. - * @param string key (or more keys) - * @return FileUpload - */ - public function getFile($key) - { - return Nette\Utils\Arrays::get($this->files, func_get_args(), NULL); - } - - - /** - * Returns uploaded files. - * @return array - */ - public function getFiles() - { - return $this->files; - } - - - /** - * Returns variable provided to the script via HTTP cookies. - * @param string key - * @param mixed default value - * @return mixed - */ - public function getCookie($key, $default = NULL) - { - if (func_num_args() === 0) { - return $this->cookies; - - } elseif (isset($this->cookies[$key])) { - return $this->cookies[$key]; - - } else { - return $default; - } - } - - - /** - * Returns variables provided to the script via HTTP cookies. - * @return array - */ - public function getCookies() - { - return $this->cookies; - } - - - /********************* method & headers ****************d*g**/ - - - /** - * Returns HTTP request method (GET, POST, HEAD, PUT, ...). The method is case-sensitive. - * @return string - */ - public function getMethod() - { - return $this->method; - } - - - /** - * Checks if the request method is the given one. - * @param string - * @return bool - */ - public function isMethod($method) - { - return strcasecmp($this->method, $method) === 0; - } - - - /** - * Checks if the request method is POST. - * @return bool - */ - public function isPost() - { - return $this->isMethod('POST'); - } - - - /** - * Return the value of the HTTP header. Pass the header name as the - * plain, HTTP-specified header name (e.g. 'Accept-Encoding'). - * @param string - * @param mixed - * @return mixed - */ - public function getHeader($header, $default = NULL) - { - $header = strtolower($header); - if (isset($this->headers[$header])) { - return $this->headers[$header]; - } else { - return $default; - } - } - - - /** - * Returns all HTTP headers. - * @return array - */ - public function getHeaders() - { - return $this->headers; - } - - - /** - * Returns referrer. - * @return Url|NULL - */ - public function getReferer() - { - return isset($this->headers['referer']) ? new Url($this->headers['referer']) : NULL; - } - - - /** - * Is the request is sent via secure channel (https). - * @return bool - */ - public function isSecured() - { - return $this->url->scheme === 'https'; - } - - - /** - * Is AJAX request? - * @return bool - */ - public function isAjax() - { - return $this->getHeader('X-Requested-With') === 'XMLHttpRequest'; - } - - - /** - * Returns the IP address of the remote client. - * @return string - */ - public function getRemoteAddress() - { - return $this->remoteAddress; - } - - - /** - * Returns the host of the remote client. - * @return string - */ - public function getRemoteHost() - { - if (!$this->remoteHost) { - $this->remoteHost = $this->remoteAddress ? getHostByAddr($this->remoteAddress) : NULL; - } - return $this->remoteHost; - } - - - /** - * Parse Accept-Language header and returns prefered language. - * @param array Supported languages - * @return string|null - */ - public function detectLanguage(array $langs) - { - $header = $this->getHeader('Accept-Language'); - if (!$header) { - return NULL; - } - - $s = strtolower($header); // case insensitive - $s = strtr($s, '_', '-'); // cs_CZ means cs-CZ - rsort($langs); // first more specific - preg_match_all('#(' . implode('|', $langs) . ')(?:-[^\s,;=]+)?\s*(?:;\s*q=([0-9.]+))?#', $s, $matches); - - if (!$matches[0]) { - return NULL; - } - - $max = 0; - $lang = NULL; - foreach ($matches[1] as $key => $value) { - $q = $matches[2][$key] === '' ? 1.0 : (float) $matches[2][$key]; - if ($q > $max) { - $max = $q; $lang = $value; - } - } - - return $lang; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/Response.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/Response.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/Response.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/Response.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,319 +0,0 @@ -= 50400) { - if (is_int(http_response_code())) { - $this->code = http_response_code(); - } - header_register_callback($this->removeDuplicateCookies); - } - } - - - /** - * Sets HTTP response code. - * @param int - * @return self - * @throws Nette\InvalidArgumentException if code is invalid - * @throws Nette\InvalidStateException if HTTP headers have been sent - */ - public function setCode($code) - { - $code = (int) $code; - if ($code < 100 || $code > 599) { - throw new Nette\InvalidArgumentException("Bad HTTP response '$code'."); - } - self::checkHeaders(); - $this->code = $code; - $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; - header($protocol . ' ' . $code, TRUE, $code); - return $this; - } - - - /** - * Returns HTTP response code. - * @return int - */ - public function getCode() - { - return $this->code; - } - - - /** - * Sends a HTTP header and replaces a previous one. - * @param string header name - * @param string header value - * @return self - * @throws Nette\InvalidStateException if HTTP headers have been sent - */ - public function setHeader($name, $value) - { - self::checkHeaders(); - if ($value === NULL) { - header_remove($name); - } elseif (strcasecmp($name, 'Content-Length') === 0 && ini_get('zlib.output_compression')) { - // ignore, PHP bug #44164 - } else { - header($name . ': ' . $value, TRUE, $this->code); - } - return $this; - } - - - /** - * Adds HTTP header. - * @param string header name - * @param string header value - * @return self - * @throws Nette\InvalidStateException if HTTP headers have been sent - */ - public function addHeader($name, $value) - { - self::checkHeaders(); - header($name . ': ' . $value, FALSE, $this->code); - return $this; - } - - - /** - * Sends a Content-type HTTP header. - * @param string mime-type - * @param string charset - * @return self - * @throws Nette\InvalidStateException if HTTP headers have been sent - */ - public function setContentType($type, $charset = NULL) - { - $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : '')); - return $this; - } - - - /** - * Redirects to a new URL. Note: call exit() after it. - * @param string URL - * @param int HTTP code - * @return void - * @throws Nette\InvalidStateException if HTTP headers have been sent - */ - public function redirect($url, $code = self::S302_FOUND) - { - $this->setCode($code); - $this->setHeader('Location', $url); - echo "

Redirect

\n\n

Please click here to continue.

"; - } - - - /** - * Sets the number of seconds before a page cached on a browser expires. - * @param string|int|DateTime time, value 0 means "until the browser is closed" - * @return self - * @throws Nette\InvalidStateException if HTTP headers have been sent - */ - public function setExpiration($time) - { - if (!$time) { // no cache - $this->setHeader('Cache-Control', 's-maxage=0, max-age=0, must-revalidate'); - $this->setHeader('Expires', 'Mon, 23 Jan 1978 10:00:00 GMT'); - return $this; - } - - $time = Nette\DateTime::from($time); - $this->setHeader('Cache-Control', 'max-age=' . ($time->format('U') - time())); - $this->setHeader('Expires', self::date($time)); - return $this; - } - - - /** - * Checks if headers have been sent. - * @return bool - */ - public function isSent() - { - return headers_sent(); - } - - - /** - * Return the value of the HTTP header. - * @param string - * @param mixed - * @return mixed - */ - public function getHeader($header, $default = NULL) - { - $header .= ':'; - $len = strlen($header); - foreach (headers_list() as $item) { - if (strncasecmp($item, $header, $len) === 0) { - return ltrim(substr($item, $len)); - } - } - return $default; - } - - - /** - * Returns a list of headers to sent. - * @return array - */ - public function getHeaders() - { - $headers = array(); - foreach (headers_list() as $header) { - $a = strpos($header, ':'); - $headers[substr($header, 0, $a)] = (string) substr($header, $a + 2); - } - return $headers; - } - - - /** - * Returns HTTP valid date format. - * @param string|int|DateTime - * @return string - */ - public static function date($time = NULL) - { - $time = Nette\DateTime::from($time); - $time->setTimezone(new \DateTimeZone('GMT')); - return $time->format('D, d M Y H:i:s \G\M\T'); - } - - - /** - * @return void - */ - public function __destruct() - { - if (self::$fixIE && isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE ') !== FALSE - && in_array($this->code, array(400, 403, 404, 405, 406, 408, 409, 410, 500, 501, 505), TRUE) - && preg_match('#^text/html(?:;|$)#', $this->getHeader('Content-Type', 'text/html')) - ) { - echo Nette\Utils\Strings::random(2e3, " \t\r\n"); // sends invisible garbage for IE - self::$fixIE = FALSE; - } - } - - - /** - * Sends a cookie. - * @param string name of the cookie - * @param string value - * @param string|int|DateTime expiration time, value 0 means "until the browser is closed" - * @param string - * @param string - * @param bool - * @param bool - * @return self - * @throws Nette\InvalidStateException if HTTP headers have been sent - */ - public function setCookie($name, $value, $time, $path = NULL, $domain = NULL, $secure = NULL, $httpOnly = NULL) - { - self::checkHeaders(); - setcookie( - $name, - $value, - $time ? Nette\DateTime::from($time)->format('U') : 0, - $path === NULL ? $this->cookiePath : (string) $path, - $domain === NULL ? $this->cookieDomain : (string) $domain, - $secure === NULL ? $this->cookieSecure : (bool) $secure, - $httpOnly === NULL ? $this->cookieHttpOnly : (bool) $httpOnly - ); - $this->removeDuplicateCookies(); - return $this; - } - - - /** - * Deletes a cookie. - * @param string name of the cookie. - * @param string - * @param string - * @param bool - * @return void - * @throws Nette\InvalidStateException if HTTP headers have been sent - */ - public function deleteCookie($name, $path = NULL, $domain = NULL, $secure = NULL) - { - $this->setCookie($name, FALSE, 0, $path, $domain, $secure); - } - - - /** - * Removes duplicate cookies from response. - * @return void - */ - public function removeDuplicateCookies() - { - if (headers_sent($file, $line) || ini_get('suhosin.cookie.encrypt')) { - return; - } - - $flatten = array(); - foreach (headers_list() as $header) { - if (preg_match('#^Set-Cookie: .+?=#', $header, $m)) { - $flatten[$m[0]] = $header; - header_remove('Set-Cookie'); - } - } - foreach (array_values($flatten) as $key => $header) { - header($header, $key === 0); - } - } - - - private function checkHeaders() - { - if (headers_sent($file, $line)) { - throw new Nette\InvalidStateException('Cannot send header after HTTP headers have been sent' . ($file ? " (output started at $file:$line)." : '.')); - } elseif (ob_get_length() && !array_filter(ob_get_status(TRUE), function($i) { return !$i['chunk_size']; })) { - trigger_error('Possible problem: you are sending a HTTP header while already having some data in output buffer. Try OutputDebugger or start session earlier.', E_USER_NOTICE); - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/Session.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/Session.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/Session.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/Session.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,558 +0,0 @@ - '', // must be disabled because PHP implementation is invalid - 'use_cookies' => 1, // must be enabled to prevent Session Hijacking and Fixation - 'use_only_cookies' => 1, // must be enabled to prevent Session Fixation - 'use_trans_sid' => 0, // must be disabled to prevent Session Hijacking and Fixation - - // cookies - 'cookie_lifetime' => 0, // until the browser is closed - 'cookie_path' => '/', // cookie is available within the entire domain - 'cookie_domain' => '', // cookie is available on current subdomain only - 'cookie_secure' => FALSE, // cookie is available on HTTP & HTTPS - 'cookie_httponly' => TRUE,// must be enabled to prevent Session Hijacking - - // other - 'gc_maxlifetime' => self::DEFAULT_FILE_LIFETIME,// 3 hours - 'cache_limiter' => NULL, // (default "nocache", special value "\0") - 'cache_expire' => NULL, // (default "180") - 'hash_function' => NULL, // (default "0", means MD5) - 'hash_bits_per_character' => NULL, // (default "4") - ); - - /** @var IRequest */ - private $request; - - /** @var IResponse */ - private $response; - - - public function __construct(IRequest $request, IResponse $response) - { - $this->request = $request; - $this->response = $response; - } - - - /** - * Starts and initializes session data. - * @throws Nette\InvalidStateException - * @return void - */ - public function start() - { - if (self::$started) { - return; - } - - $this->configure($this->options); - - $id = & $_COOKIE[session_name()]; - if (!is_string($id) || !preg_match('#^[0-9a-zA-Z,-]{22,128}\z#i', $id)) { - unset($_COOKIE[session_name()]); - } - - set_error_handler(function($severity, $message) use (& $error) { // session_start returns FALSE on failure only sometimes - if (($severity & error_reporting()) === $severity) { - $error = $message; - restore_error_handler(); - } - }); - session_start(); - if (!$error) { - restore_error_handler(); - } - $this->response->removeDuplicateCookies(); - if ($error) { - @session_write_close(); // this is needed - throw new Nette\InvalidStateException("session_start(): $error"); - } - - self::$started = TRUE; - - /* structure: - __NF: BrowserKey, Data, Meta, Time - DATA: section->variable = data - META: section->variable = Timestamp, Browser, Version - */ - $nf = & $_SESSION['__NF']; - - // regenerate empty session - if (empty($nf['Time'])) { - $nf['Time'] = time(); - $this->regenerated = TRUE; - } - - // browser closing detection - $browserKey = $this->request->getCookie('nette-browser'); - if (!$browserKey) { - $browserKey = Nette\Utils\Strings::random(); - } - $browserClosed = !isset($nf['B']) || $nf['B'] !== $browserKey; - $nf['B'] = $browserKey; - - // resend cookie - $this->sendCookie(); - - // process meta metadata - if (isset($nf['META'])) { - $now = time(); - // expire section variables - foreach ($nf['META'] as $section => $metadata) { - if (is_array($metadata)) { - foreach ($metadata as $variable => $value) { - if ((!empty($value['B']) && $browserClosed) || (!empty($value['T']) && $now > $value['T']) // whenBrowserIsClosed || Time - || (isset($nf['DATA'][$section][$variable]) && is_object($nf['DATA'][$section][$variable]) && (isset($value['V']) ? $value['V'] : NULL) // Version - != Nette\Reflection\ClassType::from($nf['DATA'][$section][$variable])->getAnnotation('serializationVersion')) // intentionally != - ) { - if ($variable === '') { // expire whole section - unset($nf['META'][$section], $nf['DATA'][$section]); - continue 2; - } - unset($nf['META'][$section][$variable], $nf['DATA'][$section][$variable]); - } - } - } - } - } - - if ($this->regenerated) { - $this->regenerated = FALSE; - $this->regenerateId(); - } - - register_shutdown_function(array($this, 'clean')); - } - - - /** - * Has been session started? - * @return bool - */ - public function isStarted() - { - return (bool) self::$started; - } - - - /** - * Ends the current session and store session data. - * @return void - */ - public function close() - { - if (self::$started) { - $this->clean(); - session_write_close(); - self::$started = FALSE; - } - } - - - /** - * Destroys all data registered to a session. - * @return void - */ - public function destroy() - { - if (!self::$started) { - throw new Nette\InvalidStateException('Session is not started.'); - } - - session_destroy(); - $_SESSION = NULL; - self::$started = FALSE; - if (!$this->response->isSent()) { - $params = session_get_cookie_params(); - $this->response->deleteCookie(session_name(), $params['path'], $params['domain'], $params['secure']); - } - } - - - /** - * Does session exists for the current request? - * @return bool - */ - public function exists() - { - return self::$started || $this->request->getCookie($this->getName()) !== NULL; - } - - - /** - * Regenerates the session ID. - * @throws Nette\InvalidStateException - * @return void - */ - public function regenerateId() - { - if (self::$started && !$this->regenerated) { - if (headers_sent($file, $line)) { - throw new Nette\InvalidStateException("Cannot regenerate session ID after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : ".")); - } - session_regenerate_id(TRUE); - session_write_close(); - $backup = $_SESSION; - session_start(); - $_SESSION = $backup; - $this->response->removeDuplicateCookies(); - } - $this->regenerated = TRUE; - } - - - /** - * Returns the current session ID. Don't make dependencies, can be changed for each request. - * @return string - */ - public function getId() - { - return session_id(); - } - - - /** - * Sets the session name to a specified one. - * @param string - * @return self - */ - public function setName($name) - { - if (!is_string($name) || !preg_match('#[^0-9.][^.]*\z#A', $name)) { - throw new Nette\InvalidArgumentException('Session name must be a string and cannot contain dot.'); - } - - session_name($name); - return $this->setOptions(array( - 'name' => $name, - )); - } - - - /** - * Gets the session name. - * @return string - */ - public function getName() - { - return isset($this->options['name']) ? $this->options['name'] : session_name(); - } - - - /********************* sections management ****************d*g**/ - - - /** - * Returns specified session section. - * @param string - * @param string - * @return SessionSection - * @throws Nette\InvalidArgumentException - */ - public function getSection($section, $class = 'Nette\Http\SessionSection') - { - return new $class($this, $section); - } - - - /** - * Checks if a session section exist and is not empty. - * @param string - * @return bool - */ - public function hasSection($section) - { - if ($this->exists() && !self::$started) { - $this->start(); - } - - return !empty($_SESSION['__NF']['DATA'][$section]); - } - - - /** - * Iteration over all sections. - * @return \ArrayIterator - */ - public function getIterator() - { - if ($this->exists() && !self::$started) { - $this->start(); - } - - if (isset($_SESSION['__NF']['DATA'])) { - return new \ArrayIterator(array_keys($_SESSION['__NF']['DATA'])); - - } else { - return new \ArrayIterator; - } - } - - - /** - * Cleans and minimizes meta structures. This method is called automatically on shutdown, do not call it directly. - * @internal - * @return void - */ - public function clean() - { - if (!self::$started || empty($_SESSION)) { - return; - } - - $nf = & $_SESSION['__NF']; - if (isset($nf['META']) && is_array($nf['META'])) { - foreach ($nf['META'] as $name => $foo) { - if (empty($nf['META'][$name])) { - unset($nf['META'][$name]); - } - } - } - - if (empty($nf['META'])) { - unset($nf['META']); - } - - if (empty($nf['DATA'])) { - unset($nf['DATA']); - } - } - - - /********************* configuration ****************d*g**/ - - - /** - * Sets session options. - * @param array - * @return self - * @throws Nette\NotSupportedException - * @throws Nette\InvalidStateException - */ - public function setOptions(array $options) - { - if (self::$started) { - $this->configure($options); - } - $this->options = $options + $this->options; - if (!empty($options['auto_start'])) { - $this->start(); - } - return $this; - } - - - /** - * Returns all session options. - * @return array - */ - public function getOptions() - { - return $this->options; - } - - - /** - * Configurates session environment. - * @param array - * @return void - */ - private function configure(array $config) - { - $special = array('cache_expire' => 1, 'cache_limiter' => 1, 'save_path' => 1, 'name' => 1); - - foreach ($config as $key => $value) { - if (!strncmp($key, 'session.', 8)) { // back compatibility - $key = substr($key, 8); - } - $key = strtolower(preg_replace('#(.)(?=[A-Z])#', '$1_', $key)); - - if ($value === NULL || ini_get("session.$key") == $value) { // intentionally == - continue; - - } elseif (strncmp($key, 'cookie_', 7) === 0) { - if (!isset($cookie)) { - $cookie = session_get_cookie_params(); - } - $cookie[substr($key, 7)] = $value; - - } else { - if (defined('SID')) { - throw new Nette\InvalidStateException("Unable to set 'session.$key' to value '$value' when session has been started" . ($this->started ? "." : " by session.auto_start or session_start().")); - } - if (isset($special[$key])) { - $key = "session_$key"; - $key($value); - - } elseif (function_exists('ini_set')) { - ini_set("session.$key", $value); - - } elseif (ini_get("session.$key") != $value) { // intentionally == - throw new Nette\NotSupportedException("Unable to set 'session.$key' to '$value' because function ini_set() is disabled."); - } - } - } - - if (isset($cookie)) { - session_set_cookie_params( - $cookie['lifetime'], $cookie['path'], $cookie['domain'], - $cookie['secure'], $cookie['httponly'] - ); - if (self::$started) { - $this->sendCookie(); - } - } - } - - - /** - * Sets the amount of time allowed between requests before the session will be terminated. - * @param string|int|DateTime time, value 0 means "until the browser is closed" - * @return self - */ - public function setExpiration($time) - { - if (empty($time)) { - return $this->setOptions(array( - 'gc_maxlifetime' => self::DEFAULT_FILE_LIFETIME, - 'cookie_lifetime' => 0, - )); - - } else { - $time = Nette\DateTime::from($time)->format('U') - time(); - return $this->setOptions(array( - 'gc_maxlifetime' => $time, - 'cookie_lifetime' => $time, - )); - } - } - - - /** - * Sets the session cookie parameters. - * @param string path - * @param string domain - * @param bool secure - * @return self - */ - public function setCookieParameters($path, $domain = NULL, $secure = NULL) - { - return $this->setOptions(array( - 'cookie_path' => $path, - 'cookie_domain' => $domain, - 'cookie_secure' => $secure - )); - } - - - /** - * Returns the session cookie parameters. - * @return array containing items: lifetime, path, domain, secure, httponly - */ - public function getCookieParameters() - { - return session_get_cookie_params(); - } - - - /** - * Sets path of the directory used to save session data. - * @return self - */ - public function setSavePath($path) - { - return $this->setOptions(array( - 'save_path' => $path, - )); - } - - - /** - * Sets user session storage for PHP < 5.4. For PHP >= 5.4, use setHandler(). - * @return self - */ - public function setStorage(ISessionStorage $storage) - { - if (self::$started) { - throw new Nette\InvalidStateException('Unable to set storage when session has been started.'); - } - session_set_save_handler( - array($storage, 'open'), array($storage, 'close'), array($storage, 'read'), - array($storage, 'write'), array($storage, 'remove'), array($storage, 'clean') - ); - } - - - /** - * Sets user session handler. - * @return self - */ - public function setHandler(\SessionHandlerInterface $handler) - { - if (self::$started) { - throw new Nette\InvalidStateException('Unable to set handler when session has been started.'); - } - session_set_save_handler($handler); - } - - - /** - * Sends the session cookies. - * @return void - */ - private function sendCookie() - { - if (!headers_sent() && ob_get_level() && ob_get_length()) { - trigger_error('Possible problem: you are starting session while already having some data in output buffer. This may not work if the outputted data grows. Try starting the session earlier.', E_USER_NOTICE); - } - - $cookie = $this->getCookieParameters(); - $this->response->setCookie( - session_name(), session_id(), - $cookie['lifetime'] ? $cookie['lifetime'] + time() : 0, - $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httponly'] - - )->setCookie( - 'nette-browser', $_SESSION['__NF']['B'], - Response::BROWSER, $cookie['path'], $cookie['domain'] - ); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/SessionSection.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/SessionSection.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/SessionSection.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/SessionSection.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,254 +0,0 @@ -session = $session; - $this->name = $name; - } - - - /** - * Do not call directly. Use Session::getNamespace(). - */ - private function start() - { - if ($this->meta === FALSE) { - $this->session->start(); - $this->data = & $_SESSION['__NF']['DATA'][$this->name]; - $this->meta = & $_SESSION['__NF']['META'][$this->name]; - } - } - - - /** - * Returns an iterator over all section variables. - * @return \ArrayIterator - */ - public function getIterator() - { - $this->start(); - if (isset($this->data)) { - return new \ArrayIterator($this->data); - } else { - return new \ArrayIterator; - } - } - - - /** - * Sets a variable in this session section. - * @param string name - * @param mixed value - * @return void - */ - public function __set($name, $value) - { - $this->start(); - $this->data[$name] = $value; - if (is_object($value)) { - $this->meta[$name]['V'] = Nette\Reflection\ClassType::from($value)->getAnnotation('serializationVersion'); - } - } - - - /** - * Gets a variable from this session section. - * @param string name - * @return mixed - */ - public function &__get($name) - { - $this->start(); - if ($this->warnOnUndefined && !array_key_exists($name, $this->data)) { - trigger_error("The variable '$name' does not exist in session section", E_USER_NOTICE); - } - - return $this->data[$name]; - } - - - /** - * Determines whether a variable in this session section is set. - * @param string name - * @return bool - */ - public function __isset($name) - { - if ($this->session->exists()) { - $this->start(); - } - return isset($this->data[$name]); - } - - - /** - * Unsets a variable in this session section. - * @param string name - * @return void - */ - public function __unset($name) - { - $this->start(); - unset($this->data[$name], $this->meta[$name]); - } - - - /** - * Sets a variable in this session section. - * @param string name - * @param mixed value - * @return void - */ - public function offsetSet($name, $value) - { - $this->__set($name, $value); - } - - - /** - * Gets a variable from this session section. - * @param string name - * @return mixed - */ - public function offsetGet($name) - { - return $this->__get($name); - } - - - /** - * Determines whether a variable in this session section is set. - * @param string name - * @return bool - */ - public function offsetExists($name) - { - return $this->__isset($name); - } - - - /** - * Unsets a variable in this session section. - * @param string name - * @return void - */ - public function offsetUnset($name) - { - $this->__unset($name); - } - - - /** - * Sets the expiration of the section or specific variables. - * @param string|int|DateTime time, value 0 means "until the browser is closed" - * @param mixed optional list of variables / single variable to expire - * @return self - */ - public function setExpiration($time, $variables = NULL) - { - $this->start(); - if (empty($time)) { - $time = NULL; - $whenBrowserIsClosed = TRUE; - } else { - $time = Nette\DateTime::from($time)->format('U'); - $max = ini_get('session.gc_maxlifetime'); - if ($time - time() > $max + 3) { // bulgarian constant - trigger_error("The expiration time is greater than the session expiration $max seconds", E_USER_NOTICE); - } - $whenBrowserIsClosed = FALSE; - } - - if ($variables === NULL) { // to entire section - $this->meta['']['T'] = $time; - $this->meta['']['B'] = $whenBrowserIsClosed; - - } elseif (is_array($variables)) { // to variables - foreach ($variables as $variable) { - $this->meta[$variable]['T'] = $time; - $this->meta[$variable]['B'] = $whenBrowserIsClosed; - } - - } else { // to variable - $this->meta[$variables]['T'] = $time; - $this->meta[$variables]['B'] = $whenBrowserIsClosed; - } - return $this; - } - - - /** - * Removes the expiration from the section or specific variables. - * @param mixed optional list of variables / single variable to expire - * @return void - */ - public function removeExpiration($variables = NULL) - { - $this->start(); - if ($variables === NULL) { - // from entire section - unset($this->meta['']['T'], $this->meta['']['B']); - - } elseif (is_array($variables)) { - // from variables - foreach ($variables as $variable) { - unset($this->meta[$variable]['T'], $this->meta[$variable]['B']); - } - } else { - unset($this->meta[$variables]['T'], $this->meta[$variables]['B']); - } - } - - - /** - * Cancels the current session section. - * @return void - */ - public function remove() - { - $this->start(); - $this->data = NULL; - $this->meta = NULL; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/Url.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/Url.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/Url.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/Url.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,485 +0,0 @@ - - * scheme user password host port basePath relativeUrl - * | | | | | | | - * /--\ /--\ /------\ /-------\ /--\/--\/----------------------------\ - * http://john:x0y17575@nette.org:8042/en/manual.php?name=param#fragment <-- absoluteUrl - * \__________________________/\____________/^\________/^\______/ - * | | | | - * authority path query fragment - * - * - * - authority: [user[:password]@]host[:port] - * - hostUrl: http://user:password@nette.org:8042 - * - basePath: /en/ (everything before relative URI not including the script name) - * - baseUrl: http://user:password@nette.org:8042/en/ - * - relativeUrl: manual.php - * - * @author David Grudl - * - * @property string $scheme - * @property string $user - * @property string $password - * @property string $host - * @property string $port - * @property string $path - * @property string $query - * @property string $fragment - * @property-read string $absoluteUrl - * @property-read string $authority - * @property-read string $hostUrl - * @property-read string $basePath - * @property-read string $baseUrl - * @property-read string $relativeUrl - */ -class Url extends Nette\Object -{ - /** @var array */ - public static $defaultPorts = array( - 'http' => 80, - 'https' => 443, - 'ftp' => 21, - 'news' => 119, - 'nntp' => 119, - ); - - /** @var string */ - private $scheme = ''; - - /** @var string */ - private $user = ''; - - /** @var string */ - private $pass = ''; - - /** @var string */ - private $host = ''; - - /** @var int */ - private $port = NULL; - - /** @var string */ - private $path = ''; - - /** @var string */ - private $query = ''; - - /** @var string */ - private $fragment = ''; - - - /** - * @param string URL - * @throws Nette\InvalidArgumentException - */ - public function __construct($url = NULL) - { - if (is_string($url)) { - $parts = @parse_url($url); // @ - is escalated to exception - if ($parts === FALSE) { - throw new Nette\InvalidArgumentException("Malformed or unsupported URI '$url'."); - } - - foreach ($parts as $key => $val) { - $this->$key = $val; - } - - if (!$this->port && isset(self::$defaultPorts[$this->scheme])) { - $this->port = self::$defaultPorts[$this->scheme]; - } - - if ($this->path === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { - $this->path = '/'; - } - - } elseif ($url instanceof self) { - foreach ($this as $key => $val) { - $this->$key = $url->$key; - } - } - } - - - /** - * Sets the scheme part of URI. - * @param string - * @return self - */ - public function setScheme($value) - { - $this->scheme = (string) $value; - return $this; - } - - - /** - * Returns the scheme part of URI. - * @return string - */ - public function getScheme() - { - return $this->scheme; - } - - - /** - * Sets the user name part of URI. - * @param string - * @return self - */ - public function setUser($value) - { - $this->user = (string) $value; - return $this; - } - - - /** - * Returns the user name part of URI. - * @return string - */ - public function getUser() - { - return $this->user; - } - - - /** - * Sets the password part of URI. - * @param string - * @return self - */ - public function setPassword($value) - { - $this->pass = (string) $value; - return $this; - } - - - /** - * Returns the password part of URI. - * @return string - */ - public function getPassword() - { - return $this->pass; - } - - - /** - * Sets the host part of URI. - * @param string - * @return self - */ - public function setHost($value) - { - $this->host = (string) $value; - return $this; - } - - - /** - * Returns the host part of URI. - * @return string - */ - public function getHost() - { - return $this->host; - } - - - /** - * Sets the port part of URI. - * @param string - * @return self - */ - public function setPort($value) - { - $this->port = (int) $value; - return $this; - } - - - /** - * Returns the port part of URI. - * @return string - */ - public function getPort() - { - return $this->port; - } - - - /** - * Sets the path part of URI. - * @param string - * @return self - */ - public function setPath($value) - { - $this->path = (string) $value; - return $this; - } - - - /** - * Returns the path part of URI. - * @return string - */ - public function getPath() - { - return $this->path; - } - - - /** - * Sets the query part of URI. - * @param string|array - * @return self - */ - public function setQuery($value) - { - $this->query = (string) (is_array($value) ? http_build_query($value, '', '&') : $value); - return $this; - } - - - /** - * Appends the query part of URI. - * @param string|array - * @return Url - */ - public function appendQuery($value) - { - $value = (string) (is_array($value) ? http_build_query($value, '', '&') : $value); - $this->query .= ($this->query === '' || $value === '') ? $value : '&' . $value; - return $this; - } - - - /** - * Returns the query part of URI. - * @return string - */ - public function getQuery() - { - return $this->query; - } - - - /** - * @param string - * @param mixed - * @return mixed - */ - public function getQueryParameter($name, $default = NULL) - { - parse_str($this->query, $params); - return isset($params[$name]) ? $params[$name] : $default; - } - - - /** - * @param string - * @param mixed NULL unsets the parameter - * @return self - */ - public function setQueryParameter($name, $value) - { - parse_str($this->query, $params); - if ($value === NULL) { - unset($params[$name]); - } else { - $params[$name] = $value; - } - $this->setQuery($params); - return $this; - } - - - /** - * Sets the fragment part of URI. - * @param string - * @return self - */ - public function setFragment($value) - { - $this->fragment = (string) $value; - return $this; - } - - - /** - * Returns the fragment part of URI. - * @return string - */ - public function getFragment() - { - return $this->fragment; - } - - - /** - * Returns the entire URI including query string and fragment. - * @return string - */ - public function getAbsoluteUrl() - { - return $this->getHostUrl() . $this->path - . ($this->query === '' ? '' : '?' . $this->query) - . ($this->fragment === '' ? '' : '#' . $this->fragment); - } - - - /** - * Returns the [user[:pass]@]host[:port] part of URI. - * @return string - */ - public function getAuthority() - { - $authority = $this->host; - if ($this->port && (!isset(self::$defaultPorts[$this->scheme]) || $this->port !== self::$defaultPorts[$this->scheme])) { - $authority .= ':' . $this->port; - } - - if ($this->user !== '' && $this->scheme !== 'http' && $this->scheme !== 'https') { - $authority = $this->user . ($this->pass === '' ? '' : ':' . $this->pass) . '@' . $authority; - } - - return $authority; - } - - - /** - * Returns the scheme and authority part of URI. - * @return string - */ - public function getHostUrl() - { - return ($this->scheme ? $this->scheme . ':' : '') . '//' . $this->getAuthority(); - } - - - /** - * Returns the base-path. - * @return string - */ - public function getBasePath() - { - $pos = strrpos($this->path, '/'); - return $pos === FALSE ? '' : substr($this->path, 0, $pos + 1); - } - - - /** - * Returns the base-URI. - * @return string - */ - public function getBaseUrl() - { - return $this->getHostUrl() . $this->getBasePath(); - } - - - /** - * Returns the relative-URI. - * @return string - */ - public function getRelativeUrl() - { - return (string) substr($this->getAbsoluteUrl(), strlen($this->getBaseUrl())); - } - - - /** - * URI comparsion (this object must be in canonical form). - * @param string - * @return bool - */ - public function isEqual($url) - { - // compare host + path - $part = self::unescape(strtok($url, '?#'), '%/'); - if (strncmp($part, '//', 2) === 0) { // absolute URI without scheme - if ($part !== '//' . $this->getAuthority() . $this->path) { - return FALSE; - } - - } elseif (strncmp($part, '/', 1) === 0) { // absolute path - if ($part !== $this->path) { - return FALSE; - } - - } else { - if ($part !== $this->getHostUrl() . $this->path) { - return FALSE; - } - } - - // compare query strings - $part = preg_split('#[&;]#', self::unescape(strtr((string) strtok('?#'), '+', ' '), '%&;=+')); - sort($part); - $query = preg_split('#[&;]#', $this->query); - sort($query); - return $part === $query; - } - - - /** - * Transform to canonical form. - * @return Url - */ - public function canonicalize() - { - $this->path = $this->path === '' ? '/' : self::unescape($this->path, '%/'); - $this->host = strtolower(rawurldecode($this->host)); - $this->query = self::unescape(strtr($this->query, '+', ' '), '%&;=+'); - return $this; - } - - - /** - * @return string - */ - public function __toString() - { - return $this->getAbsoluteUrl(); - } - - - /** - * Similar to rawurldecode, but preserve reserved chars encoded. - * @param string to decode - * @param string reserved characters - * @return string - */ - public static function unescape($s, $reserved = '%;/?:@&=+$,') - { - // reserved (@see RFC 2396) = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," - // within a path segment, the characters "/", ";", "=", "?" are reserved - // within a query component, the characters ";", "/", "?", ":", "@", "&", "=", "+", ",", "$" are reserved. - preg_match_all('#(?<=%)[a-f0-9][a-f0-9]#i', $s, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); - foreach (array_reverse($matches) as $match) { - $ch = chr(hexdec($match[0][0])); - if (strpos($reserved, $ch) === FALSE) { - $s = substr_replace($s, $ch, $match[0][1] - 1, 3); - } - } - return $s; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/UrlScript.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/UrlScript.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/UrlScript.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/UrlScript.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ - - * http://nette.org/admin/script.php/pathinfo/?name=param#fragment - * \_______________/\________/ - * | | - * scriptPath pathInfo - * - * - * - scriptPath: /admin/script.php (or simply /admin/ when script is directory index) - * - pathInfo: /pathinfo/ (additional path information) - * - * @author David Grudl - * - * @property string $scriptPath - * @property-read string $pathInfo - */ -class UrlScript extends Url -{ - /** @var string */ - private $scriptPath = '/'; - - - /** - * Sets the script-path part of URI. - * @param string - * @return self - */ - public function setScriptPath($value) - { - $this->scriptPath = (string) $value; - return $this; - } - - - /** - * Returns the script-path part of URI. - * @return string - */ - public function getScriptPath() - { - return $this->scriptPath; - } - - - /** - * Returns the base-path. - * @return string - */ - public function getBasePath() - { - $pos = strrpos($this->scriptPath, '/'); - return $pos === FALSE ? '' : substr($this->path, 0, $pos + 1); - } - - - /** - * Returns the additional path information. - * @return string - */ - public function getPathInfo() - { - return (string) substr($this->path, strlen($this->scriptPath)); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Http/UserStorage.php php-nette-2.1.5/Nette-2.1.4/Nette/Http/UserStorage.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Http/UserStorage.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Http/UserStorage.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,206 +0,0 @@ -sessionHandler = $sessionHandler; - } - - - /** - * Sets the authenticated status of this user. - * @param bool - * @return self - */ - public function setAuthenticated($state) - { - $section = $this->getSessionSection(TRUE); - $section->authenticated = (bool) $state; - - // Session Fixation defence - $this->sessionHandler->regenerateId(); - - if ($state) { - $section->reason = NULL; - $section->authTime = time(); // informative value - - } else { - $section->reason = self::MANUAL; - $section->authTime = NULL; - } - return $this; - } - - - /** - * Is this user authenticated? - * @return bool - */ - public function isAuthenticated() - { - $session = $this->getSessionSection(FALSE); - return $session && $session->authenticated; - } - - - /** - * Sets the user identity. - * @return self - */ - public function setIdentity(IIdentity $identity = NULL) - { - $this->getSessionSection(TRUE)->identity = $identity; - return $this; - } - - - /** - * Returns current user identity, if any. - * @return Nette\Security\IIdentity|NULL - */ - public function getIdentity() - { - $session = $this->getSessionSection(FALSE); - return $session ? $session->identity : NULL; - } - - - /** - * Changes namespace; allows more users to share a session. - * @param string - * @return self - */ - public function setNamespace($namespace) - { - if ($this->namespace !== $namespace) { - $this->namespace = (string) $namespace; - $this->sessionSection = NULL; - } - return $this; - } - - - /** - * Returns current namespace. - * @return string - */ - public function getNamespace() - { - return $this->namespace; - } - - - /** - * Enables log out after inactivity. - * @param string|int|DateTime Number of seconds or timestamp - * @param int Log out when the browser is closed | Clear the identity from persistent storage? - * @return self - */ - public function setExpiration($time, $flags = 0) - { - $section = $this->getSessionSection(TRUE); - if ($time) { - $time = Nette\DateTime::from($time)->format('U'); - $section->expireTime = $time; - $section->expireDelta = $time - time(); - - } else { - unset($section->expireTime, $section->expireDelta); - } - - $section->expireIdentity = (bool) ($flags & self::CLEAR_IDENTITY); - $section->expireBrowser = (bool) ($flags & self::BROWSER_CLOSED); - $section->browserCheck = TRUE; - $section->setExpiration(0, 'browserCheck'); - $section->setExpiration($time, 'foo'); // time check - return $this; - } - - - /** - * Why was user logged out? - * @return int - */ - public function getLogoutReason() - { - $session = $this->getSessionSection(FALSE); - return $session ? $session->reason : NULL; - } - - - /** - * Returns and initializes $this->sessionSection. - * @return SessionSection - */ - protected function getSessionSection($need) - { - if ($this->sessionSection !== NULL) { - return $this->sessionSection; - } - - if (!$need && !$this->sessionHandler->exists()) { - return NULL; - } - - $this->sessionSection = $section = $this->sessionHandler->getSection('Nette.Http.UserStorage/' . $this->namespace); - - if (!$section->identity instanceof IIdentity || !is_bool($section->authenticated)) { - $section->remove(); - } - - if ($section->authenticated && $section->expireBrowser && !$section->browserCheck) { // check if browser was closed? - $section->reason = self::BROWSER_CLOSED; - $section->authenticated = FALSE; - if ($section->expireIdentity) { - unset($section->identity); - } - } - - if ($section->authenticated && $section->expireDelta > 0) { // check time expiration - if ($section->expireTime < time()) { - $section->reason = self::INACTIVITY; - $section->authenticated = FALSE; - if ($section->expireIdentity) { - unset($section->identity); - } - } - $section->expireTime = time() + $section->expireDelta; // sliding expiration - } - - if (!$section->authenticated) { - unset($section->expireTime, $section->expireDelta, $section->expireIdentity, - $section->expireBrowser, $section->browserCheck, $section->authTime); - } - - return $this->sessionSection; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/CachingIterator.php php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/CachingIterator.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/CachingIterator.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/CachingIterator.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,243 +0,0 @@ -getIterator(); - - } elseif (!$iterator instanceof \Iterator) { - $iterator = new \IteratorIterator($iterator); - } - - } else { - throw new Nette\InvalidArgumentException(sprintf('Invalid argument passed to foreach resp. %s; array or Traversable expected, %s given.', __CLASS__, is_object($iterator) ? get_class($iterator) : gettype($iterator))); - } - - parent::__construct($iterator, 0); - } - - - /** - * Is the current element the first one? - * @param int grid width - * @return bool - */ - public function isFirst($width = NULL) - { - return $this->counter === 1 || ($width && $this->counter !== 0 && (($this->counter - 1) % $width) === 0); - } - - - /** - * Is the current element the last one? - * @param int grid width - * @return bool - */ - public function isLast($width = NULL) - { - return !$this->hasNext() || ($width && ($this->counter % $width) === 0); - } - - - /** - * Is the iterator empty? - * @return bool - */ - public function isEmpty() - { - return $this->counter === 0; - } - - - /** - * Is the counter odd? - * @return bool - */ - public function isOdd() - { - return $this->counter % 2 === 1; - } - - - /** - * Is the counter even? - * @return bool - */ - public function isEven() - { - return $this->counter % 2 === 0; - } - - - /** - * Returns the counter. - * @return int - */ - public function getCounter() - { - return $this->counter; - } - - - /** - * Returns the count of elements. - * @return int - */ - public function count() - { - $inner = $this->getInnerIterator(); - if ($inner instanceof \Countable) { - return $inner->count(); - - } else { - throw new Nette\NotSupportedException('Iterator is not countable.'); - } - } - - - /** - * Forwards to the next element. - * @return void - */ - public function next() - { - parent::next(); - if (parent::valid()) { - $this->counter++; - } - } - - - /** - * Rewinds the Iterator. - * @return void - */ - public function rewind() - { - parent::rewind(); - $this->counter = parent::valid() ? 1 : 0; - } - - - /** - * Returns the next key. - * @return mixed - */ - public function getNextKey() - { - return $this->getInnerIterator()->key(); - } - - - /** - * Returns the next element. - * @return mixed - */ - public function getNextValue() - { - return $this->getInnerIterator()->current(); - } - - - /********************* Nette\Object behaviour ****************d*g**/ - - - /** - * Call to undefined method. - * @param string method name - * @param array arguments - * @return mixed - * @throws Nette\MemberAccessException - */ - public function __call($name, $args) - { - return Nette\ObjectMixin::call($this, $name, $args); - } - - - /** - * Returns property value. Do not call directly. - * @param string property name - * @return mixed property value - * @throws Nette\MemberAccessException if the property is not defined. - */ - public function &__get($name) - { - return Nette\ObjectMixin::get($this, $name); - } - - - /** - * Sets value of a property. Do not call directly. - * @param string property name - * @param mixed property value - * @return void - * @throws Nette\MemberAccessException if the property is not defined or is read-only - */ - public function __set($name, $value) - { - Nette\ObjectMixin::set($this, $name, $value); - } - - - /** - * Is property defined? - * @param string property name - * @return bool - */ - public function __isset($name) - { - return Nette\ObjectMixin::has($this, $name); - } - - - /** - * Access to undeclared property. - * @param string property name - * @return void - * @throws Nette\MemberAccessException - */ - public function __unset($name) - { - Nette\ObjectMixin::remove($this, $name); - } - - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/Filter.php php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/Filter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/Filter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/Filter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -callback = Nette\Utils\Callback::check($callback); - } - - - public function accept() - { - return call_user_func($this->callback, $this->current(), $this->key(), $this); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/Mapper.php php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/Mapper.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/Mapper.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/Mapper.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -callback = Nette\Utils\Callback::check($callback); - } - - - public function current() - { - return call_user_func($this->callback, parent::current(), parent::key()); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/RecursiveFilter.php php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/RecursiveFilter.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/RecursiveFilter.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/RecursiveFilter.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -getInnerIterator()->hasChildren(); - } - - - public function getChildren() - { - return new static($this->getInnerIterator()->getChildren(), $this->callback); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/Recursor.php php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/Recursor.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Iterators/Recursor.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Iterators/Recursor.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -current(); - return ($obj instanceof \IteratorAggregate && $obj->getIterator() instanceof \RecursiveIterator) - || $obj instanceof \RecursiveIterator; - } - - - /** - * The sub-iterator for the current element. - * @return \RecursiveIterator - */ - public function getChildren() - { - $obj = $this->current(); - return $obj instanceof \IteratorAggregate ? $obj->getIterator() : $obj; - } - - - /** - * Returns the count of elements. - * @return int - */ - public function count() - { - return iterator_count($this); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Compiler.php php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Compiler.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Compiler.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Compiler.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,577 +0,0 @@ - IMacro[]] */ - private $macros; - - /** @var \SplObjectStorage */ - private $macroHandlers; - - /** @var HtmlNode */ - private $htmlNode; - - /** @var MacroNode */ - private $macroNode; - - /** @var string[] */ - private $attrCodes = array(); - - /** @var string */ - private $contentType; - - /** @var array [context, subcontext] */ - private $context; - - /** @var string */ - private $templateId; - - /** Context-aware escaping content types */ - const CONTENT_HTML = 'html', - CONTENT_XHTML = 'xhtml', - CONTENT_XML = 'xml', - CONTENT_JS = 'js', - CONTENT_CSS = 'css', - CONTENT_URL = 'url', - CONTENT_ICAL = 'ical', - CONTENT_TEXT = 'text'; - - /** @internal Context-aware escaping HTML contexts */ - const CONTEXT_COMMENT = 'comment', - CONTEXT_SINGLE_QUOTED_ATTR = "'", - CONTEXT_DOUBLE_QUOTED_ATTR = '"', - CONTEXT_UNQUOTED_ATTR = '='; - - - public function __construct() - { - $this->macroHandlers = new \SplObjectStorage; - } - - - /** - * Adds new macro. - * @param string - * @return self - */ - public function addMacro($name, IMacro $macro) - { - $this->macros[$name][] = $macro; - $this->macroHandlers->attach($macro); - return $this; - } - - - /** - * Compiles tokens to PHP code. - * @param Token[] - * @return string - */ - public function compile(array $tokens) - { - $this->templateId = Strings::random(); - $this->tokens = $tokens; - $output = ''; - $this->output = & $output; - $this->htmlNode = $this->macroNode = NULL; - $this->setContentType($this->defaultContentType); - - foreach ($this->macroHandlers as $handler) { - $handler->initialize($this); - } - - try { - foreach ($tokens as $this->position => $token) { - $this->{"process$token->type"}($token); - } - } catch (CompileException $e) { - $e->sourceLine = $token->line; - throw $e; - } - - while ($this->htmlNode) { - if (!empty($this->htmlNode->macroAttrs)) { - throw new CompileException('Missing ' . self::printEndTag($this->macroNode), 0, $token->line); - } - $this->htmlNode = $this->htmlNode->parentNode; - } - - $prologs = $epilogs = ''; - foreach ($this->macroHandlers as $handler) { - $res = $handler->finalize(); - $handlerName = get_class($handler); - $prologs .= empty($res[0]) ? '' : ""; - $epilogs = (empty($res[1]) ? '' : "") . $epilogs; - } - $output = ($prologs ? $prologs . "\n" : '') . $output . $epilogs; - - if ($this->macroNode) { - throw new CompileException('Missing ' . self::printEndTag($this->macroNode), 0, $token->line); - } - - $output = $this->expandTokens($output); - return $output; - } - - - /** - * @return self - */ - public function setContentType($type) - { - $this->contentType = $type; - $this->context = NULL; - return $this; - } - - - /** - * @return string - */ - public function getContentType() - { - return $this->contentType; - } - - - /** - * @return self - */ - public function setContext($context, $sub = NULL) - { - $this->context = array($context, $sub); - return $this; - } - - - /** - * @return array [context, subcontext] - */ - public function getContext() - { - return $this->context; - } - - - /** - * @return string - */ - public function getTemplateId() - { - return $this->templateId; - } - - - /** - * @return MacroNode|NULL - */ - public function getMacroNode() - { - return $this->macroNode; - } - - - /** - * Returns current line number. - * @return int - */ - public function getLine() - { - return $this->tokens ? $this->tokens[$this->position]->line : NULL; - } - - - public function expandTokens($s) - { - return strtr($s, $this->attrCodes); - } - - - private function processText(Token $token) - { - if (($this->context[0] === self::CONTEXT_SINGLE_QUOTED_ATTR || $this->context[0] === self::CONTEXT_DOUBLE_QUOTED_ATTR) - && $token->text === $this->context[0] - ) { - $this->setContext(self::CONTEXT_UNQUOTED_ATTR); - } - $this->output .= $token->text; - } - - - private function processMacroTag(Token $token) - { - $isRightmost = !isset($this->tokens[$this->position + 1]) - || substr($this->tokens[$this->position + 1]->text, 0, 1) === "\n"; - - if ($token->name[0] === '/') { - $this->closeMacro((string) substr($token->name, 1), $token->value, $token->modifiers, $isRightmost); - } else { - $this->openMacro($token->name, $token->value, $token->modifiers, $isRightmost && !$token->empty); - if ($token->empty) { - $this->closeMacro($token->name, NULL, NULL, $isRightmost); - } - } - } - - - private function processHtmlTagBegin(Token $token) - { - if ($token->closing) { - while ($this->htmlNode) { - if (strcasecmp($this->htmlNode->name, $token->name) === 0) { - break; - } - if ($this->htmlNode->macroAttrs) { - throw new CompileException("Unexpected name>, expecting " . self::printEndTag($this->macroNode)); - } - $this->htmlNode = $this->htmlNode->parentNode; - } - if (!$this->htmlNode) { - $this->htmlNode = new HtmlNode($token->name); - } - $this->htmlNode->closing = TRUE; - $this->htmlNode->offset = strlen($this->output); - $this->setContext(NULL); - - } elseif ($token->text === '') { - $this->output .= $token->text; - $this->setContext(NULL); - return; - } - - $htmlNode = $this->htmlNode; - $isEmpty = !$htmlNode->closing && (Strings::contains($token->text, '/') || $htmlNode->isEmpty); - $end = ''; - - if ($isEmpty && in_array($this->contentType, array(self::CONTENT_HTML, self::CONTENT_XHTML))) { // auto-correct - $token->text = preg_replace('#^.*>#', $htmlNode->isEmpty && $this->contentType === self::CONTENT_XHTML ? ' />' : '>', $token->text); - if (!$htmlNode->isEmpty) { - $end = "name>"; - } - } - - if (empty($htmlNode->macroAttrs)) { - $this->output .= $token->text . $end; - } else { - $code = substr($this->output, $htmlNode->offset) . $token->text; - $this->output = substr($this->output, 0, $htmlNode->offset); - $this->writeAttrsMacro($code); - if ($isEmpty) { - $htmlNode->closing = TRUE; - $this->writeAttrsMacro($end); - } - } - - if ($isEmpty) { - $htmlNode->closing = TRUE; - } - - $lower = strtolower($htmlNode->name); - if (!$htmlNode->closing && ($lower === 'script' || $lower === 'style')) { - $this->setContext($lower === 'script' ? self::CONTENT_JS : self::CONTENT_CSS); - } else { - $this->setContext(NULL); - if ($htmlNode->closing) { - $this->htmlNode = $this->htmlNode->parentNode; - } - } - } - - - private function processHtmlAttribute(Token $token) - { - if (Strings::startsWith($token->name, Parser::N_PREFIX)) { - $name = substr($token->name, strlen(Parser::N_PREFIX)); - if (isset($this->htmlNode->macroAttrs[$name])) { - throw new CompileException("Found multiple macro-attributes $token->name."); - - } elseif ($this->macroNode && $this->macroNode->htmlNode === $this->htmlNode) { - throw new CompileException("Macro-attributes must not appear inside macro; found $token->name inside {{$this->macroNode->name}}."); - } - $this->htmlNode->macroAttrs[$name] = $token->value; - return; - } - - $this->htmlNode->attrs[$token->name] = TRUE; - $this->output .= $token->text; - - $context = NULL; - if (in_array($this->contentType, array(self::CONTENT_HTML, self::CONTENT_XHTML))) { - $lower = strtolower($token->name); - if (substr($lower, 0, 2) === 'on') { - $context = self::CONTENT_JS; - } elseif ($lower === 'style') { - $context = self::CONTENT_CSS; - } elseif (in_array($lower, array('href', 'src', 'action', 'formaction')) - || ($lower === 'data' && strtolower($this->htmlNode->name) === 'object') - ) { - $context = self::CONTENT_URL; - } - } - $this->setContext($token->value ?: self::CONTEXT_UNQUOTED_ATTR, $context); - } - - - private function processComment(Token $token) - { - $isLeftmost = trim(substr($this->output, strrpos("\n$this->output", "\n"))) === ''; - if (!$isLeftmost) { - $this->output .= substr($token->text, strlen(rtrim($token->text, "\n"))); - } - } - - - /********************* macros ****************d*g**/ - - - /** - * Generates code for {macro ...} to the output. - * @param string - * @param string - * @param string - * @param bool - * @return MacroNode - */ - public function openMacro($name, $args = NULL, $modifiers = NULL, $isRightmost = FALSE, $nPrefix = NULL) - { - $node = $this->expandMacro($name, $args, $modifiers, $nPrefix); - if ($node->isEmpty) { - $this->writeCode($node->openingCode, $this->output, $isRightmost); - } else { - $this->macroNode = $node; - $node->saved = array(& $this->output, $isRightmost); - $this->output = & $node->content; - } - return $node; - } - - - /** - * Generates code for {/macro ...} to the output. - * @param string - * @param string - * @param string - * @param bool - * @return MacroNode - */ - public function closeMacro($name, $args = NULL, $modifiers = NULL, $isRightmost = FALSE, $nPrefix = NULL) - { - $node = $this->macroNode; - - if (!$node || ($node->name !== $name && '' !== $name) || $modifiers - || ($args && $node->args && !Strings::startsWith("$node->args ", "$args ")) - || $nPrefix !== $node->prefix - ) { - $name = $nPrefix - ? "htmlNode->name}> for macro-attribute " . Parser::N_PREFIX . implode(' and ' . Parser::N_PREFIX, array_keys($this->htmlNode->macroAttrs)) - : '{/' . $name . ($args ? ' ' . $args : '') . $modifiers . '}'; - throw new CompileException("Unexpected $name" . ($node ? ', expecting ' . self::printEndTag($node) : '')); - } - - $this->macroNode = $node->parentNode; - if (!$node->args) { - $node->setArgs($args); - } - - $isLeftmost = $node->content ? trim(substr($this->output, strrpos("\n$this->output", "\n"))) === '' : FALSE; - - $node->closing = TRUE; - $node->macro->nodeClosed($node); - - $this->output = & $node->saved[0]; - $this->writeCode($node->openingCode, $this->output, $node->saved[1]); - $this->writeCode($node->closingCode, $node->content, $isRightmost, $isLeftmost); - $this->output .= $node->content; - return $node; - } - - - private function writeCode($code, & $output, $isRightmost, $isLeftmost = NULL) - { - if ($isRightmost) { - $leftOfs = strrpos("\n$output", "\n"); - $isLeftmost = $isLeftmost === NULL ? trim(substr($output, $leftOfs)) === '' : $isLeftmost; - if ($isLeftmost && substr($code, 0, 11) !== ' remove indentation - } elseif (substr($code, -2) === '?>') { - $code .= "\n"; // double newline to avoid newline eating by PHP - } - } - $output .= $code; - } - - - /** - * Generates code for macro to the output. - * @param string - * @return void - */ - public function writeAttrsMacro($code) - { - $attrs = $this->htmlNode->macroAttrs; - $left = $right = array(); - - foreach ($this->macros as $name => $foo) { - $attrName = MacroNode::PREFIX_INNER . "-$name"; - if (isset($attrs[$attrName])) { - if ($this->htmlNode->closing) { - $left[] = array('closeMacro', $name, '', MacroNode::PREFIX_INNER); - } else { - array_unshift($right, array('openMacro', $name, $attrs[$attrName], MacroNode::PREFIX_INNER)); - } - unset($attrs[$attrName]); - } - } - - foreach (array_reverse($this->macros) as $name => $foo) { - $attrName = MacroNode::PREFIX_TAG . "-$name"; - if (isset($attrs[$attrName])) { - $left[] = array('openMacro', $name, $attrs[$attrName], MacroNode::PREFIX_TAG); - array_unshift($right, array('closeMacro', $name, '', MacroNode::PREFIX_TAG)); - unset($attrs[$attrName]); - } - } - - foreach ($this->macros as $name => $foo) { - if (isset($attrs[$name])) { - if ($this->htmlNode->closing) { - $right[] = array('closeMacro', $name, '', MacroNode::PREFIX_NONE); - } else { - array_unshift($left, array('openMacro', $name, $attrs[$name], MacroNode::PREFIX_NONE)); - } - unset($attrs[$name]); - } - } - - if ($attrs) { - throw new CompileException('Unknown macro-attribute ' . Parser::N_PREFIX - . implode(' and ' . Parser::N_PREFIX, array_keys($attrs))); - } - - if (!$this->htmlNode->closing) { - $this->htmlNode->attrCode = & $this->attrCodes[$uniq = ' n:' . Nette\Utils\Strings::random()]; - $code = substr_replace($code, $uniq, strrpos($code, '/>') ?: strrpos($code, '>'), 0); - } - - foreach ($left as $item) { - $node = $this->{$item[0]}($item[1], $item[2], NULL, NULL, $item[3]); - if ($node->closing || $node->isEmpty) { - $this->htmlNode->attrCode .= $node->attrCode; - if ($node->isEmpty) { - unset($this->htmlNode->macroAttrs[$node->name]); - } - } - } - - $this->output .= $code; - - foreach ($right as $item) { - $node = $this->{$item[0]}($item[1], $item[2], NULL, NULL, $item[3]); - if ($node->closing) { - $this->htmlNode->attrCode .= $node->attrCode; - } - } - - if ($right && substr($this->output, -2) === '?>') { - $this->output .= "\n"; - } - } - - - /** - * Expands macro and returns node & code. - * @param string - * @param string - * @param string - * @return MacroNode - */ - public function expandMacro($name, $args, $modifiers = NULL, $nPrefix = NULL) - { - $inScript = in_array($this->context[0], array(self::CONTENT_JS, self::CONTENT_CSS)); - - if (empty($this->macros[$name])) { - throw new CompileException("Unknown macro {{$name}}" . ($inScript ? ' (in JavaScript or CSS, try to put a space after bracket.)' : '')); - } - - if ($this->context[1] === self::CONTENT_URL) { - $modifiers = preg_replace('#\|nosafeurl\s?(?=\||\z)#i', '', $modifiers, -1, $found); - if (!$found && !preg_match('#\|datastream(?=\s|\||\z)#i', $modifiers)) { - $modifiers .= '|safeurl'; - } - } - - $modifiers = preg_replace('#\|noescape\s?(?=\||\z)#i', '', $modifiers, -1, $found); - if (!$found && strpbrk($name, '=~%^&_')) { - $modifiers .= '|escape'; - } - - if (!$found && $inScript && $name === '=' && preg_match('#["\'] *\z#', $this->tokens[$this->position - 1]->text)) { - throw new CompileException("Do not place {$this->tokens[$this->position]->text} inside quotes."); - } - - foreach (array_reverse($this->macros[$name]) as $macro) { - $node = new MacroNode($macro, $name, $args, $modifiers, $this->macroNode, $this->htmlNode, $nPrefix); - if ($macro->nodeOpened($node) !== FALSE) { - return $node; - } - } - - throw new CompileException($nPrefix ? 'Unknown macro-attribute ' . Parser::N_PREFIX . "$nPrefix-$name" : "Unhandled macro {{$name}}"); - } - - - private static function printEndTag(MacroNode $node) - { - if ($node->prefix) { - return "htmlNode->name}> for macro-attribute " . Parser::N_PREFIX - . implode(' and ' . Parser::N_PREFIX, array_keys($node->htmlNode->macroAttrs)); - } else { - return "{/$node->name}"; - } - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Engine.php php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Engine.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Engine.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Engine.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -parser = new Parser; - $this->compiler = new Compiler; - $this->compiler->defaultContentType = Compiler::CONTENT_HTML; - - Macros\CoreMacros::install($this->compiler); - $this->compiler->addMacro('cache', new Macros\CacheMacro($this->compiler)); - Macros\UIMacros::install($this->compiler); - Macros\FormMacros::install($this->compiler); - } - - - /** - * Invokes filter. - * @param string - * @return string - */ - public function __invoke($s) - { - return $this->compiler->compile($this->parser->parse($s)); - } - - - /** - * @return Parser - */ - public function getParser() - { - return $this->parser; - } - - - /** - * @return Compiler - */ - public function getCompiler() - { - return $this->compiler; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Latte/exceptions.php php-nette-2.1.5/Nette-2.1.4/Nette/Latte/exceptions.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Latte/exceptions.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Latte/exceptions.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -name = $name; - $this->parentNode = $parentNode; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Latte/IMacro.php php-nette-2.1.5/Nette-2.1.4/Nette/Latte/IMacro.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Latte/IMacro.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Latte/IMacro.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -macro = $macro; - $this->name = (string) $name; - $this->modifiers = (string) $modifiers; - $this->parentNode = $parentNode; - $this->htmlNode = $htmlNode; - $this->prefix = $prefix; - $this->data = new \stdClass; - $this->setArgs($args); - } - - - public function setArgs($args) - { - $this->args = (string) $args; - $this->tokenizer = new MacroTokens($this->args); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Macros/CacheMacro.php php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Macros/CacheMacro.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Macros/CacheMacro.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Macros/CacheMacro.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,120 +0,0 @@ -used = FALSE; - } - - - /** - * Finishes template parsing. - * @return array(prolog, epilog) - */ - public function finalize() - { - if ($this->used) { - return array('Nette\Latte\Macros\CacheMacro::initRuntime($template, $_g);'); - } - } - - - /** - * New node is found. - * @return bool - */ - public function nodeOpened(Latte\MacroNode $node) - { - $this->used = TRUE; - $node->isEmpty = FALSE; - $node->openingCode = Latte\PhpWriter::using($node) - ->write('caches, %node.array?)) { ?>', - Nette\Utils\Strings::random() - ); - } - - - /** - * Node is closed. - * @return void - */ - public function nodeClosed(Latte\MacroNode $node) - { - $node->closingCode = 'tmp = array_pop($_g->caches); if (!$_l->tmp instanceof stdClass) $_l->tmp->end(); } ?>'; - } - - - /********************* run-time helpers ****************d*g**/ - - - /** - * @return void - */ - public static function initRuntime(Nette\Templating\FileTemplate $template, \stdClass $global) - { - if (!empty($global->caches)) { - end($global->caches)->dependencies[Nette\Caching\Cache::FILES][] = $template->getFile(); - } - } - - - /** - * Starts the output cache. Returns Nette\Caching\OutputHelper object if buffering was started. - * @param Nette\Caching\IStorage - * @param string - * @param Nette\Caching\OutputHelper[] - * @param array - * @return Nette\Caching\OutputHelper - */ - public static function createCache(Nette\Caching\IStorage $cacheStorage, $key, & $parents, array $args = NULL) - { - if ($args) { - if (array_key_exists('if', $args) && !$args['if']) { - return $parents[] = new \stdClass; - } - $key = array_merge(array($key), array_intersect_key($args, range(0, count($args)))); - } - if ($parents) { - end($parents)->dependencies[Nette\Caching\Cache::ITEMS][] = $key; - } - - $cache = new Nette\Caching\Cache($cacheStorage, 'Nette.Templating.Cache'); - if ($helper = $cache->start($key)) { - if (isset($args['expire'])) { - $args['expiration'] = $args['expire']; // back compatibility - } - $helper->dependencies = array( - Nette\Caching\Cache::TAGS => isset($args['tags']) ? $args['tags'] : NULL, - Nette\Caching\Cache::EXPIRATION => isset($args['expiration']) ? $args['expiration'] : '+ 7 days', - ); - $parents[] = $helper; - } - return $helper; - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Macros/CoreMacros.php php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Macros/CoreMacros.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Macros/CoreMacros.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Macros/CoreMacros.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,443 +0,0 @@ - value} set template parameter - * - {default var => value} set default template parameter - * - {dump $var} - * - {debugbreak} - * - {l} {r} to display { } - * - * @author David Grudl - */ -class CoreMacros extends MacroSet -{ - - - public static function install(Latte\Compiler $compiler) - { - $me = new static($compiler); - - $me->addMacro('if', array($me, 'macroIf'), array($me, 'macroEndIf')); - $me->addMacro('elseif', '} elseif (%node.args) {'); - $me->addMacro('else', array($me, 'macroElse')); - $me->addMacro('ifset', 'if (isset(%node.args)) {', '}'); - $me->addMacro('elseifset', '} elseif (isset(%node.args)) {'); - $me->addMacro('ifcontent', array($me, 'macroIfContent'), array($me, 'macroEndIfContent')); - - $me->addMacro('switch', '$_l->switch[] = (%node.args); if (FALSE) {', '} array_pop($_l->switch)'); - $me->addMacro('case', '} elseif (end($_l->switch) === (%node.args)) {'); - - $me->addMacro('foreach', '', array($me, 'macroEndForeach')); - $me->addMacro('for', 'for (%node.args) {', '}'); - $me->addMacro('while', 'while (%node.args) {', '}'); - $me->addMacro('continueIf', array($me, 'macroBreakContinueIf')); - $me->addMacro('breakIf', array($me, 'macroBreakContinueIf')); - $me->addMacro('first', 'if ($iterator->isFirst(%node.args)) {', '}'); - $me->addMacro('last', 'if ($iterator->isLast(%node.args)) {', '}'); - $me->addMacro('sep', 'if (!$iterator->isLast(%node.args)) {', '}'); - - $me->addMacro('var', array($me, 'macroVar')); - $me->addMacro('assign', array($me, 'macroVar')); // deprecated - $me->addMacro('default', array($me, 'macroVar')); - $me->addMacro('dump', array($me, 'macroDump')); - $me->addMacro('debugbreak', array($me, 'macroDebugbreak')); - $me->addMacro('l', '?>{addMacro('r', '?>}addMacro('_', array($me, 'macroTranslate'), array($me, 'macroTranslate')); - $me->addMacro('=', array($me, 'macroExpr')); - $me->addMacro('?', array($me, 'macroExpr')); - - $me->addMacro('capture', array($me, 'macroCapture'), array($me, 'macroCaptureEnd')); - $me->addMacro('include', array($me, 'macroInclude')); - $me->addMacro('use', array($me, 'macroUse')); - - $me->addMacro('class', NULL, NULL, array($me, 'macroClass')); - $me->addMacro('attr', array($me, 'macroOldAttr'), '', array($me, 'macroAttr')); - $me->addMacro('href', NULL); // TODO: placeholder - } - - - /** - * Finishes template parsing. - * @return array(prolog, epilog) - */ - public function finalize() - { - return array('list($_l, $_g) = Nette\Latte\Macros\CoreMacros::initRuntime($template, ' - . var_export($this->getCompiler()->getTemplateId(), TRUE) . ')'); - } - - - /********************* macros ****************d*g**/ - - - /** - * {if ...} - */ - public function macroIf(MacroNode $node, PhpWriter $writer) - { - if ($node->data->capture = ($node->args === '')) { - return 'ob_start()'; - } - if ($node->prefix === $node::PREFIX_TAG) { - return $writer->write($node->htmlNode->closing ? 'if (array_pop($_l->ifs)) {' : 'if ($_l->ifs[] = (%node.args)) {'); - } - return $writer->write('if (%node.args) {'); - } - - - /** - * {/if ...} - */ - public function macroEndIf(MacroNode $node, PhpWriter $writer) - { - if ($node->data->capture) { - if ($node->args === '') { - throw new CompileException('Missing condition in {if} macro.'); - } - return $writer->write('if (%node.args) ' - . (isset($node->data->else) ? '{ ob_end_clean(); ob_end_flush(); }' : 'ob_end_flush();') - . ' else ' - . (isset($node->data->else) ? '{ $_else = ob_get_contents(); ob_end_clean(); ob_end_clean(); echo $_else; }' : 'ob_end_clean();') - ); - } - return '}'; - } - - - /** - * {else} - */ - public function macroElse(MacroNode $node, PhpWriter $writer) - { - $ifNode = $node->parentNode; - if ($ifNode && $ifNode->name === 'if' && $ifNode->data->capture) { - if (isset($ifNode->data->else)) { - throw new CompileException('Macro {if} supports only one {else}.'); - } - $ifNode->data->else = TRUE; - return 'ob_start()'; - } - return '} else {'; - } - - - /** - * n:ifcontent - */ - public function macroIfContent(MacroNode $node, PhpWriter $writer) - { - if (!$node->prefix) { - throw new CompileException("Unknown macro {{$node->name}}, use n:{$node->name} attribute."); - } elseif ($node->prefix !== MacroNode::PREFIX_NONE) { - throw new CompileException("Unknown attribute n:{$node->prefix}-{$node->name}, use n:{$node->name} attribute."); - } - - return $writer->write('ob_start()'); - } - - - /** - * n:ifcontent - */ - public function macroEndIfContent(MacroNode $node, PhpWriter $writer) - { - preg_match('#(^.*?>)(.*)(<.*\z)#s', $node->content, $parts); - $node->content = $parts[1] - . '' - . $parts[2] - . '' - . $parts[3]; - return 'rtrim($_ifcontent) === "" ? ob_end_clean() : ob_end_flush()'; - } - - - /** - * {_$var |modifiers} - */ - public function macroTranslate(MacroNode $node, PhpWriter $writer) - { - if ($node->closing) { - return $writer->write('echo %modify($template->translate(ob_get_clean()))'); - - } elseif ($node->isEmpty = ($node->args !== '')) { - return $writer->write('echo %modify($template->translate(%node.args))'); - - } else { - return 'ob_start()'; - } - } - - - /** - * {include "file" [,] [params]} - */ - public function macroInclude(MacroNode $node, PhpWriter $writer) - { - $code = $writer->write('Nette\Latte\Macros\CoreMacros::includeTemplate(%node.word, %node.array? + $template->getParameters(), $_l->templates[%var])', - $this->getCompiler()->getTemplateId()); - - if ($node->modifiers) { - return $writer->write('echo %modify(%raw->__toString(TRUE))', $code); - } else { - return $code . '->render()'; - } - } - - - /** - * {use class MacroSet} - */ - public function macroUse(MacroNode $node, PhpWriter $writer) - { - Nette\Utils\Callback::invoke(array($node->tokenizer->fetchWord(), 'install'), $this->getCompiler()) - ->initialize(); - } - - - /** - * {capture $variable} - */ - public function macroCapture(MacroNode $node, PhpWriter $writer) - { - $variable = $node->tokenizer->fetchWord(); - if (substr($variable, 0, 1) !== '$') { - throw new CompileException("Invalid capture block variable '$variable'"); - } - $node->data->variable = $variable; - return 'ob_start()'; - } - - - /** - * {/capture} - */ - public function macroCaptureEnd(MacroNode $node, PhpWriter $writer) - { - return $node->data->variable . $writer->write(' = %modify(ob_get_clean())'); - } - - - /** - * {foreach ...} - */ - public function macroEndForeach(MacroNode $node, PhpWriter $writer) - { - if ($node->modifiers !== '|noiterator' && preg_match('#\W(\$iterator|include|require|get_defined_vars)\W#', $this->getCompiler()->expandTokens($node->content))) { - $node->openingCode = 'its[] = new Nette\Iterators\CachingIterator(' - . preg_replace('#(.*)\s+as\s+#i', '$1) as ', $writer->formatArgs(), 1) . ') { ?>'; - $node->closingCode = 'its); $iterator = end($_l->its) ?>'; - } else { - $node->openingCode = 'formatArgs() . ') { ?>'; - $node->closingCode = ''; - } - } - - - /** - * {breakIf ...} - * {continueIf ...} - */ - public function macroBreakContinueIf(MacroNode $node, PhpWriter $writer) - { - $cmd = str_replace('If', '', $node->name); - if ($node->parentNode && $node->parentNode->prefix === $node::PREFIX_NONE) { - return $writer->write("if (%node.args) { echo \"parentNode->htmlNode->name}>\\n\"; $cmd; }"); - } - return $writer->write("if (%node.args) $cmd"); - } - - - /** - * n:class="..." - */ - public function macroClass(MacroNode $node, PhpWriter $writer) - { - return $writer->write('if ($_l->tmp = array_filter(%node.array)) echo \' class="\' . %escape(implode(" ", array_unique($_l->tmp))) . \'"\''); - } - - - /** - * n:attr="..." - */ - public function macroAttr(MacroNode $node, PhpWriter $writer) - { - return $writer->write('echo Nette\Utils\Html::el(NULL, %node.array)->attributes()'); - } - - - /** - * {attr ...} - * @deprecated - */ - public function macroOldAttr(MacroNode $node) - { - trigger_error('Macro {attr} is deprecated; use n:attr="..." instead.', E_USER_DEPRECATED); - return Nette\Utils\Strings::replace($node->args . ' ', '#\)\s+#', ')->'); - } - - - /** - * {dump ...} - */ - public function macroDump(MacroNode $node, PhpWriter $writer) - { - $args = $writer->formatArgs(); - return 'Nette\Diagnostics\Debugger::barDump(' . ($node->args ? "array(" . $writer->write('%var', $args) . " => $args)" : 'get_defined_vars()') - . ', "Template " . str_replace(dirname(dirname($template->getFile())), "\xE2\x80\xA6", $template->getFile()))'; - } - - - /** - * {debugbreak ...} - */ - public function macroDebugbreak(MacroNode $node, PhpWriter $writer) - { - return $writer->write(($node->args == NULL ? '' : 'if (!(%node.args)); else') - . 'if (function_exists("debugbreak")) debugbreak(); elseif (function_exists("xdebug_break")) xdebug_break()'); - } - - - /** - * {var ...} - * {default ...} - */ - public function macroVar(MacroNode $node, PhpWriter $writer) - { - if ($node->args === '' && $node->parentNode && $node->parentNode->name === 'switch') { - return '} else {'; - - } elseif ($node->name === 'assign') { - trigger_error('Macro {assign} is deprecated; use {var} instead.', E_USER_DEPRECATED); - } - - $var = TRUE; - $tokens = $writer->preprocess(); - $res = new Latte\MacroTokens; - while ($tokens->nextToken()) { - if ($var && $tokens->isCurrent(Latte\MacroTokens::T_SYMBOL, Latte\MacroTokens::T_VARIABLE)) { - if ($node->name === 'default') { - $res->append("'" . ltrim($tokens->currentValue(), '$') . "'"); - } else { - $res->append('$' . ltrim($tokens->currentValue(), '$')); - } - $var = NULL; - - } elseif ($tokens->isCurrent('=', '=>') && $tokens->depth === 0) { - $res->append($node->name === 'default' ? '=>' : '='); - $var = FALSE; - - } elseif ($tokens->isCurrent(',') && $tokens->depth === 0) { - $res->append($node->name === 'default' ? ',' : ';'); - $var = TRUE; - - } elseif ($var === NULL && $node->name === 'default' && !$tokens->isCurrent(Latte\MacroTokens::T_WHITESPACE)) { - throw new CompileException("Unexpected '{$tokens->currentValue()}' in {default $node->args}"); - - } else { - $res->append($tokens->currentToken()); - } - } - $out = $writer->quoteFilter($res)->joinAll(); - return $node->name === 'default' ? "extract(array($out), EXTR_SKIP)" : $out; - } - - - /** - * {= ...} - * {? ...} - */ - public function macroExpr(MacroNode $node, PhpWriter $writer) - { - return $writer->write(($node->name === '?' ? '' : 'echo ') . '%modify(%node.args)'); - } - - - /********************* run-time helpers ****************d*g**/ - - - /** - * Includes subtemplate. - * @param mixed included file name or template - * @param array parameters - * @param Nette\Templating\ITemplate current template - * @return Nette\Templating\Template - */ - public static function includeTemplate($destination, array $params, Nette\Templating\ITemplate $template) - { - if ($destination instanceof Nette\Templating\ITemplate) { - $tpl = $destination; - - } elseif ($destination == NULL) { // intentionally == - throw new Nette\InvalidArgumentException("Template file name was not specified."); - - } elseif ($template instanceof Nette\Templating\IFileTemplate) { - if (substr($destination, 0, 1) !== '/' && substr($destination, 1, 1) !== ':') { - $destination = dirname($template->getFile()) . '/' . $destination; - } - $tpl = clone $template; - $tpl->setFile($destination); - - } else { - throw new Nette\NotSupportedException('Macro {include "filename"} is supported only with Nette\Templating\IFileTemplate.'); - } - - $tpl->setParameters($params); // interface? - return $tpl; - } - - - /** - * Initializes local & global storage in template. - * @return \stdClass - */ - public static function initRuntime(Nette\Templating\ITemplate $template, $templateId) - { - // local storage - if (isset($template->_l)) { - $local = $template->_l; - unset($template->_l); - } else { - $local = new \stdClass; - } - $local->templates[$templateId] = $template; - - // global storage - if (!isset($template->_g)) { - $template->_g = new \stdClass; - } - - return array($local, $template->_g); - } - -} diff -Nru php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Macros/FormMacros.php php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Macros/FormMacros.php --- php-nette-2.1.4/Nette-2.1.4/Nette/Latte/Macros/FormMacros.php 2014-05-24 20:50:39.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.4/Nette/Latte/Macros/FormMacros.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,276 +0,0 @@ -addMacro('form', array($me, 'macroForm'), 'Nette\Latte\Macros\FormMacros::renderFormEnd($_form)'); - $me->addMacro('formContainer', array($me, 'macroFormContainer'), '$_form = array_pop($_formStack)'); - $me->addMacro('label', array($me, 'macroLabel'), array($me, 'macroLabelEnd')); - $me->addMacro('input', array($me, 'macroInput'), NULL, array($me, 'macroInputAttr')); - $me->addMacro('name', array($me, 'macroName'), array($me, 'macroNameEnd'), array($me, 'macroNameAttr')); - $me->addMacro('inputError', array($me, 'macroInputError')); - } - - - /********************* macros ****************d*g**/ - - - /** - * {form ...} - */ - public function macroForm(MacroNode $node, PhpWriter $writer) - { - if ($node->htmlNode && strtolower($node->htmlNode->name) === 'form') { - throw new CompileException('Did you mean
?'); - } - $name = $node->tokenizer->fetchWord(); - if ($name === FALSE) { - throw new CompileException("Missing form name in {{$node->name}}."); - } - $node->tokenizer->reset(); - return $writer->write( - 'Nette\Latte\Macros\FormMacros::renderFormBegin($form = $_form = ' - . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '') - . '$_control[%node.word], %node.array)' - ); - } - - - /** - * {formContainer ...} - */ - public function macroFormContainer(MacroNode $node, PhpWriter $writer) - { - $name = $node->tokenizer->fetchWord(); - if ($name === FALSE) { - throw new CompileException("Missing form name in {{$node->name}}."); - } - $node->tokenizer->reset(); - return $writer->write( - '$_formStack[] = $_form; $formContainer = $_form = ' . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '') . '$_form[%node.word]' - ); - } - - - /** - * {label ...} - */ - public function macroLabel(MacroNode $node, PhpWriter $writer) - { - $words = $node->tokenizer->fetchWords(); - if (!$words) { - throw new CompileException("Missing name in {{$node->name}}."); - } - $name = array_shift($words); - return $writer->write( - ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; if ($_label = $_input' : 'if ($_label = $_form[%0.word]') - . '->%1.raw) echo $_label' - . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''), - $name, - $words ? ('getLabelPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')') : 'getLabel()' - ); - } - - - /** - * {/label} - */ - public function macroLabelEnd(MacroNode $node, PhpWriter $writer) - { - if ($node->content != NULL) { - $node->openingCode = rtrim($node->openingCode, '?> ') . '->startTag() ?>'; - return $writer->write('if ($_label) echo $_label->endTag()'); - } - } - - - /** - * {input ...} - */ - public function macroInput(MacroNode $node, PhpWriter $writer) - { - $words = $node->tokenizer->fetchWords(); - if (!$words) { - throw new CompileException("Missing name in {{$node->name}}."); - } - $name = array_shift($words); - return $writer->write( - ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; echo $_input' : 'echo $_form[%0.word]') - . '->%1.raw' - . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''), - $name, - $words ? 'getControlPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')' : 'getControl()' - ); - } - - - /** - * deprecated n:input - */ - public function macroInputAttr(MacroNode $node, PhpWriter $writer) - { - if (strtolower($node->htmlNode->name) === 'input') { - return $this->macroNameAttr($node, $writer); - } else { - throw new CompileException("Use n:name instead of n:input."); - } - } - - - /** - * , , + + + + + + + <?php echo htmlspecialchars($title) ?> + + + + + + + +
+ +
+
+

getCode() ? ' #' . $exception->getCode() : '') ?>

+ +

getMessage(), ENT_IGNORE) ?> getMessage())) ?>" id="netteBsSearch" rel="noreferrer">search►

+
+ + getPrevious()): ?> + + + + + + + + +
> +

Caused by

+ +
+
+

getCode() ? ' #' . $ex->getCode() : '')) ?>

+ +

getMessage(), ENT_IGNORE) ?>

+
+ + + + + + +
+

+ +
+ +
+ + + + getTrace(); $expanded = NULL ?> + getSeverity(), array(E_USER_NOTICE, E_USER_WARNING, E_USER_DEPRECATED), TRUE)) && $this->isCollapsed($ex->getFile())) { + foreach ($stack as $key => $row) { + if (isset($row['file']) && !$this->isCollapsed($row['file'])) { $expanded = $key; break; } + } + } ?> + +
+

Source file

+ +
+

File: getFile(), $ex->getLine()) ?>

+ getFile())): ?>getFile(), $ex->getLine(), 15, $ex instanceof \ErrorException && isset($ex->context) ? $ex->context : NULL) ?> +
+ + + + +
+

Call stack

+ +
+
    + $row): ?> +
  1. + + + + + inner-code + + + " class="nette-toggle">source  + + " ?> + + ' ?> + + + (" class="nette-toggle-collapsed">arguments) +

    + + +
    id="netteBsSrc">
    + + + +
    ">
    + + + +
    "> + + getParameters(); + } catch (\Exception $e) { + $params = array(); + } + foreach ($row['args'] as $k => $v) { + echo '\n"; + } + ?> +
    ', htmlspecialchars(isset($params[$k]) ? '$' . $params[$k]->name : "#$k"), ''; + echo Dumper::toHtml($v); + echo "
    +
    + +
  2. + +
+
+ + + + context) && is_array($ex->context)):?> +
+

Variables

+ +
+
+ + context as $k => $v) { + echo '\n"; + } + ?> +
$', htmlspecialchars($k), '', Dumper::toHtml($v), "
+
+
+ + + getPrevious()); ?> +
' ?> + + + + + + +
+

+ +
+ +
+ + + +
+

Environment

+ +
+

$_SERVER

+
+ + $v) echo '\n"; + ?> +
', htmlspecialchars($k), '', Dumper::toHtml($v), "
+
+ + +

$_SESSION

+
+ +

empty

+ + + $v) echo '\n"; + ?> +
', htmlspecialchars($k), '', $k === '__NF' ? 'Nette Session' : Dumper::toHtml($v), "
+ +
+ + + +

Nette Session

+
+ + $v) echo '\n"; + ?> +
', htmlspecialchars($k), '', Dumper::toHtml($v), "
+
+ + + + +

Constants

+
+ + $v) { + echo ''; + echo '\n"; + } + ?> +
', htmlspecialchars($k), '', Dumper::toHtml($v), "
+
+ + + +

Included files ()

+
+ + \n"; + } + ?> +
', htmlspecialchars($v, ENT_IGNORE), "
+
+ + +

Configuration options

+
+ |.+\z#s', '', ob_get_clean()) ?> +
+
+ + +
+

HTTP request

+ +
+ +

Headers

+
+ + $v) echo '\n"; + ?> +
', htmlspecialchars($k), '', htmlspecialchars($v), "
+
+ + + + +

$

+ +

empty

+ +
+ + $v) echo '\n"; + ?> +
', htmlspecialchars($k), '', Dumper::toHtml($v), "
+
+ + +
+ + +
+

HTTP response

+ +
+

Headers

+ +
';
+			?>
+ +

no headers

+ +
+ + + +
+

+ +
+ +
+ + + +
    +
  • Report generated at
  • + +
  • + +
  • + +
  • PHP
  • +
  • +
  • (revision )
  • +
+
+
+ + + + diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Diagnostics/templates/dumper.css php-nette-2.1.5/Nette-2.1.5/Nette/Diagnostics/templates/dumper.css --- php-nette-2.1.4/Nette-2.1.5/Nette/Diagnostics/templates/dumper.css 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Diagnostics/templates/dumper.css 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,69 @@ +/** + * Dumper + * + * This file is part of the Nette Framework (http://nette.org) + * Copyright (c) 2004 David Grudl (http://davidgrudl.com) + */ + +/* toggle */ +.nette-collapsed { + display: none; +} + +.nette-toggle, .nette-toggle-collapsed { + cursor: pointer; +} + +.nette-toggle:after { + content: " ▼"; + opacity: .4; +} + +.nette-toggle-collapsed:after { + content: " ►"; + opacity: .4; +} + + +/* dump */ +pre.nette-dump { + color: #444; + background: white; +} + +pre.nette-dump div { + padding-left: 3ex; +} + +pre.nette-dump div div { + border-left: 1px solid rgba(0, 0, 0, .1); + margin-left: .5ex; +} + +.nette-dump-array, .nette-dump-object { + color: #C22; +} + +.nette-dump-string { + color: #35D; +} + +.nette-dump-number { + color: #090; +} + +.nette-dump-null, .nette-dump-bool { + color: #850; +} + +.nette-dump-visibility, .nette-dump-hash { + font-size: 85%; color: #999; +} + +.nette-dump-indent { + display: none; +} + +span[data-nette-href] { + border-bottom: 1px dotted rgba(0, 0, 0, .2); +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Diagnostics/templates/dumper.js php-nette-2.1.5/Nette-2.1.5/Nette/Diagnostics/templates/dumper.js --- php-nette-2.1.4/Nette-2.1.5/Nette/Diagnostics/templates/dumper.js 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Diagnostics/templates/dumper.js 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,54 @@ +/** + * Dumper + * + * This file is part of the Nette Framework (http://nette.org) + * Copyright (c) 2004 David Grudl (http://davidgrudl.com) + */ + +(function(){ + + var $ = Nette.Query.factory; + + var Dumper = Nette.Dumper = {}; + + Dumper.init = function() { + $(document.body).bind('click', function(e) { + var link; + + // enables & ctrl key + for (link = e.target; link && (!link.getAttribute || !link.getAttribute('data-nette-href')); link = link.parentNode) {} + if (e.ctrlKey && link) { + location.href = link.getAttribute('data-nette-href'); + return false; + } + + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { + return; + } + + // enables or toggling + for (link = e.target; link && (!link.tagName || typeof link.className !== 'string' || !link.className.match(/\bnette-toggle(-collapsed)?\b/)); link = link.parentNode) {} + if (!link) { + return; + } + var collapsed = $(link).hasClass('nette-toggle-collapsed'), + ref = link.getAttribute('data-ref') || link.getAttribute('href', 2), + dest = ref && ref !== '#' ? $(ref) : $(link).next(''), + panel = $(link).closest('.nette-panel'), + oldPosition = panel.position(); + + link.className = 'nette-toggle' + (collapsed ? '' : '-collapsed'); + dest[collapsed ? 'removeClass' : 'addClass']('nette-collapsed'); + e.preventDefault(); + + if (panel.length) { + var newPosition = panel.position(); + panel.position({ + right: newPosition.right - newPosition.width + oldPosition.width, + bottom: newPosition.bottom - newPosition.height + oldPosition.height + }); + } + }); + }; + +})(); diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Diagnostics/templates/error.phtml php-nette-2.1.5/Nette-2.1.5/Nette/Diagnostics/templates/error.phtml --- php-nette-2.1.4/Nette-2.1.5/Nette/Diagnostics/templates/error.phtml 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Diagnostics/templates/error.phtml 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,23 @@ + + + + + + + +Server Error + +

Server Error

+ +

We're sorry! The server encountered an internal error and +was unable to complete your request. Please try again later.

+ +

error 500

diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Diagnostics/templates/netteQ.js php-nette-2.1.5/Nette-2.1.5/Nette/Diagnostics/templates/netteQ.js --- php-nette-2.1.4/Nette-2.1.5/Nette/Diagnostics/templates/netteQ.js 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Diagnostics/templates/netteQ.js 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,328 @@ +/** + * NetteQ + * + * This file is part of the Nette Framework. + * Copyright (c) 2004, 2014 David Grudl (http://davidgrudl.com) + */ + +var Nette = Nette || {}; + +(function(){ + + // supported cross-browser selectors: #id | div | div.class | .class + var Query = Nette.Query = function(selector) { + if (typeof selector === "string") { + selector = this._find(document, selector); + + } else if (!selector || selector.nodeType || selector.length === undefined || selector === window) { + selector = [selector]; + } + + for (var i = 0, len = selector.length; i < len; i++) { + if (selector[i]) { this[this.length++] = selector[i]; } + } + }; + + Query.factory = function(selector) { + return new Query(selector); + }; + + Query.prototype.length = 0; + + Query.prototype.find = function(selector) { + return new Query(this._find(this[0], selector)); + }; + + Query.prototype._find = function(context, selector) { + if (!context || !selector) { + return []; + + } else if (document.querySelectorAll) { + return context.querySelectorAll(selector); + + } else if (selector.charAt(0) === '#') { // #id + return [document.getElementById(selector.substring(1))]; + + } else { // div | div.class | .class + selector = selector.split('.'); + var elms = context.getElementsByTagName(selector[0] || '*'); + + if (selector[1]) { + var list = [], pattern = new RegExp('(^|\\s)' + selector[1] + '(\\s|$)'); + for (var i = 0, len = elms.length; i < len; i++) { + if (pattern.test(elms[i].className)) { list.push(elms[i]); } + } + return list; + } else { + return elms; + } + } + }; + + Query.prototype.dom = function() { + return this[0]; + }; + + Query.prototype.each = function(callback) { + for (var i = 0; i < this.length; i++) { + if (callback.apply(this[i]) === false) { break; } + } + return this; + }; + + // cross-browser event attach + Query.prototype.bind = function(event, handler) { + if (document.addEventListener && (event === 'mouseenter' || event === 'mouseleave')) { // simulate mouseenter & mouseleave using mouseover & mouseout + var old = handler; + event = event === 'mouseenter' ? 'mouseover' : 'mouseout'; + handler = function(e) { + for (var target = e.relatedTarget; target; target = target.parentNode) { + if (target === this) { return; } // target must not be inside this + } + old.call(this, e); + }; + } + + return this.each(function() { + var elem = this, // fixes 'this' in iE + data = elem.nette ? elem.nette : elem.nette = {}, + events = data.events = data.events || {}; // use own handler queue + + if (!events[event]) { + var handlers = events[event] = [], + generic = function(e) { // dont worry, 'e' is passed in IE + if (!e.target) { + e.target = e.srcElement; + } + if (!e.preventDefault) { + e.preventDefault = function() { e.returnValue = false; }; + } + if (!e.stopPropagation) { + e.stopPropagation = function() { e.cancelBubble = true; }; + } + e.stopImmediatePropagation = function() { this.stopPropagation(); i = handlers.length; }; + for (var i = 0; i < handlers.length; i++) { + handlers[i].call(elem, e); + } + }; + + if (document.addEventListener) { // non-IE + elem.addEventListener(event, generic, false); + } else if (document.attachEvent) { // IE < 9 + elem.attachEvent('on' + event, generic); + } + } + + events[event].push(handler); + }); + }; + + // adds class to element + Query.prototype.addClass = function(className) { + return this.each(function() { + this.className = this.className.replace(/^|\s+|$/g, ' ').replace(' '+className+' ', ' ') + ' ' + className; + }); + }; + + // removes class from element + Query.prototype.removeClass = function(className) { + return this.each(function() { + this.className = this.className.replace(/^|\s+|$/g, ' ').replace(' '+className+' ', ' '); + }); + }; + + // tests whether element has given class + Query.prototype.hasClass = function(className) { + return this[0] && this[0].className.replace(/^|\s+|$/g, ' ').indexOf(' '+className+' ') > -1; + }; + + Query.prototype.show = function() { + Query.displays = Query.displays || {}; + return this.each(function() { + var tag = this.tagName; + if (!Query.displays[tag]) { + Query.displays[tag] = (new Query(document.body.appendChild(document.createElement(tag)))).css('display'); + } + this.style.display = Query.displays[tag]; + }); + }; + + Query.prototype.hide = function() { + return this.each(function() { + this.style.display = 'none'; + }); + }; + + Query.prototype.css = function(property) { + if (this[0] && this[0].currentStyle) { + return this[0].currentStyle[property]; + } else if (this[0] && window.getComputedStyle) { + return document.defaultView.getComputedStyle(this[0], null).getPropertyValue(property) + } + }; + + Query.prototype.data = function() { + if (this[0]) { + return this[0].nette ? this[0].nette : this[0].nette = {}; + } + }; + + Query.prototype.val = function() { + var elem = this[0]; + if (!elem) { + return undefined; + + } else if (!elem.nodeName) { // radio + for (var i = 0, len = elem.length; i < len; i++) { + if (this[i].checked) { return this[i].value; } + } + return null; + + } else if (elem.nodeName.toLowerCase() === 'select') { + var index = elem.selectedIndex, options = elem.options; + + if (index < 0) { + return null; + + } else if (elem.type === 'select-one') { + return options[index].value; + } + + for (var i = 0, values = [], len = options.length; i < len; i++) { + if (options[i].selected) { values.push(options[i].value); } + } + return values; + + } else if (elem.type === 'checkbox') { + return elem.checked; + + } else if (elem.value) { + return elem.value.replace(/^\s+|\s+$/g, ''); + } + }; + + Query.prototype._trav = function(elem, selector, fce) { + selector = selector.split('.'); + while (elem && !(elem.nodeType === 1 && + (!selector[0] || elem.tagName.toLowerCase() === selector[0]) && + (!selector[1] || (new Query(elem)).hasClass(selector[1])))) { + elem = elem[fce]; + } + return new Query(elem || []); + }; + + Query.prototype.closest = function(selector) { + return this._trav(this[0], selector, 'parentNode'); + }; + + Query.prototype.prev = function(selector) { + return this._trav(this[0] && this[0].previousSibling, selector, 'previousSibling'); + }; + + Query.prototype.next = function(selector) { + return this._trav(this[0] && this[0].nextSibling, selector, 'nextSibling'); + }; + + // returns total offset for element + Query.prototype.offset = function(coords) { + if (coords) { + return this.each(function() { + var elem = this, ofs = {left: -coords.left || 0, top: -coords.top || 0}; + while (elem = elem.offsetParent) { + ofs.left += elem.offsetLeft; ofs.top += elem.offsetTop; + } + this.style.left = -ofs.left + 'px'; + this.style.top = -ofs.top + 'px'; + }); + } else if (this[0]) { + var elem = this[0], res = {left: elem.offsetLeft, top: elem.offsetTop}; + while (elem = elem.offsetParent) { + res.left += elem.offsetLeft; res.top += elem.offsetTop; + } + return res; + } + }; + + // returns current position or move to new position + Query.prototype.position = function(coords) { + if (coords) { + return this.each(function() { + if (this.nette && this.nette.onmove) { + this.nette.onmove.call(this, coords); + } + for (var item in coords) { + this.style[item] = coords[item] + 'px'; + } + }); + } else if (this[0]) { + return { + left: this[0].offsetLeft, top: this[0].offsetTop, + right: this[0].style.right ? parseInt(this[0].style.right, 10) : 0, bottom: this[0].style.bottom ? parseInt(this[0].style.bottom, 10) : 0, + width: this[0].offsetWidth, height: this[0].offsetHeight + }; + } + }; + + // makes element draggable + Query.prototype.draggable = function(options) { + var elem = this[0], dE = document.documentElement, started; + options = options || {}; + + (options.handle ? new Query(options.handle) : this).bind('mousedown', function(e) { + var $el = new Query(options.handle ? elem : this); + e.preventDefault(); + e.stopPropagation(); + + if (Query.dragging) { // missed mouseup out of window? + return dE.onmouseup(e); + } + + var pos = $el.position(), + deltaX = options.rightEdge ? pos.right + e.clientX : pos.left - e.clientX, + deltaY = options.bottomEdge ? pos.bottom + e.clientY : pos.top - e.clientY; + + Query.dragging = true; + started = false; + + dE.onmousemove = function(e) { + e = e || event; + if (!started) { + if (options.draggedClass) { + $el.addClass(options.draggedClass); + } + if (options.start) { + options.start(e, $el); + } + started = true; + } + + var pos = {}; + pos[options.rightEdge ? 'right' : 'left'] = options.rightEdge ? deltaX - e.clientX : e.clientX + deltaX; + pos[options.bottomEdge ? 'bottom' : 'top'] = options.bottomEdge ? deltaY - e.clientY : e.clientY + deltaY; + $el.position(pos); + return false; + }; + + dE.onmouseup = function(e) { + if (started) { + if (options.draggedClass) { + $el.removeClass(options.draggedClass); + } + if (options.stop) { + options.stop(e || event, $el); + } + } + Query.dragging = dE.onmousemove = dE.onmouseup = null; + return false; + }; + + }).bind('click', function(e) { + if (started) { + e.stopImmediatePropagation(); + } + }); + + return this; + }; + +})(); diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Container.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Container.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Container.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Container.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,482 @@ +getForm(FALSE); + if (!$form || !$form->isAnchored() || !$form->isSubmitted()) { + $this->setValues($values, $erase); + } + return $this; + } + + + /** + * Fill-in with values. + * @param array|\Traversable values used to fill the form + * @param bool erase other controls? + * @return self + */ + public function setValues($values, $erase = FALSE) + { + if ($values instanceof \Traversable) { + $values = iterator_to_array($values); + + } elseif (!is_array($values)) { + throw new Nette\InvalidArgumentException(sprintf('First parameter must be an array, %s given.', gettype($values))); + } + + foreach ($this->getComponents() as $name => $control) { + if ($control instanceof IControl) { + if (array_key_exists($name, $values)) { + $control->setValue($values[$name]); + + } elseif ($erase) { + $control->setValue(NULL); + } + + } elseif ($control instanceof Container) { + if (array_key_exists($name, $values)) { + $control->setValues($values[$name], $erase); + + } elseif ($erase) { + $control->setValues(array(), $erase); + } + } + } + return $this; + } + + + /** + * Returns the values submitted by the form. + * @param bool return values as an array? + * @return Nette\ArrayHash|array + */ + public function getValues($asArray = FALSE) + { + $values = $asArray ? array() : new Nette\ArrayHash; + foreach ($this->getComponents() as $name => $control) { + if ($control instanceof IControl && !$control->isOmitted()) { + $values[$name] = $control->getValue(); + + } elseif ($control instanceof Container) { + $values[$name] = $control->getValues($asArray); + } + } + return $values; + } + + + /********************* validation ****************d*g**/ + + + /** + * Is form valid? + * @return bool + */ + public function isValid() + { + if (!$this->validated) { + if ($this->getErrors()) { + return FALSE; + } + $this->validate(); + } + return !$this->getErrors(); + } + + + /** + * Performs the server side validation. + * @param IControl[] + * @return void + */ + public function validate(array $controls = NULL) + { + foreach ($controls === NULL ? $this->getControls() : $controls as $control) { + $control->validate(); + } + $this->onValidate($this); + $this->validated = TRUE; + } + + + /** + * Returns all validation errors. + * @return array + */ + public function getErrors() + { + $errors = array(); + foreach ($this->getControls() as $control) { + $errors = array_merge($errors, $control->getErrors()); + } + return array_unique($errors); + } + + + /********************* form building ****************d*g**/ + + + /** + * @return self + */ + public function setCurrentGroup(ControlGroup $group = NULL) + { + $this->currentGroup = $group; + return $this; + } + + + /** + * Returns current group. + * @return ControlGroup + */ + public function getCurrentGroup() + { + return $this->currentGroup; + } + + + /** + * Adds the specified component to the IContainer. + * @param IComponent + * @param string + * @param string + * @return self + * @throws Nette\InvalidStateException + */ + public function addComponent(Nette\ComponentModel\IComponent $component, $name, $insertBefore = NULL) + { + parent::addComponent($component, $name, $insertBefore); + if ($this->currentGroup !== NULL && $component instanceof IControl) { + $this->currentGroup->add($component); + } + return $this; + } + + + /** + * Iterates over all form controls. + * @return \ArrayIterator + */ + public function getControls() + { + return $this->getComponents(TRUE, 'Nette\Forms\IControl'); + } + + + /** + * Returns form. + * @param bool throw exception if form doesn't exist? + * @return Form + */ + public function getForm($need = TRUE) + { + return $this->lookup('Nette\Forms\Form', $need); + } + + + /********************* control factories ****************d*g**/ + + + /** + * Adds single-line text input control to the form. + * @param string control name + * @param string label + * @param int width of the control (deprecated) + * @param int maximum number of characters the user may enter + * @return Nette\Forms\Controls\TextInput + */ + public function addText($name, $label = NULL, $cols = NULL, $maxLength = NULL) + { + $control = new Controls\TextInput($label, $maxLength); + $control->setAttribute('size', $cols); + return $this[$name] = $control; + } + + + /** + * Adds single-line text input control used for sensitive input such as passwords. + * @param string control name + * @param string label + * @param int width of the control (deprecated) + * @param int maximum number of characters the user may enter + * @return Nette\Forms\Controls\TextInput + */ + public function addPassword($name, $label = NULL, $cols = NULL, $maxLength = NULL) + { + $control = new Controls\TextInput($label, $maxLength); + $control->setAttribute('size', $cols); + return $this[$name] = $control->setType('password'); + } + + + /** + * Adds multi-line text input control to the form. + * @param string control name + * @param string label + * @param int width of the control + * @param int height of the control in text lines + * @return Nette\Forms\Controls\TextArea + */ + public function addTextArea($name, $label = NULL, $cols = NULL, $rows = NULL) + { + $control = new Controls\TextArea($label); + $control->setAttribute('cols', $cols)->setAttribute('rows', $rows); + return $this[$name] = $control; + } + + + /** + * Adds control that allows the user to upload files. + * @param string control name + * @param string label + * @param bool allows to upload multiple files + * @return Nette\Forms\Controls\UploadControl + */ + public function addUpload($name, $label = NULL, $multiple = FALSE) + { + return $this[$name] = new Controls\UploadControl($label, $multiple); + } + + + /** + * Adds hidden form control used to store a non-displayed value. + * @param string control name + * @param mixed default value + * @return Nette\Forms\Controls\HiddenField + */ + public function addHidden($name, $default = NULL) + { + $control = new Controls\HiddenField; + $control->setDefaultValue($default); + return $this[$name] = $control; + } + + + /** + * Adds check box control to the form. + * @param string control name + * @param string caption + * @return Nette\Forms\Controls\Checkbox + */ + public function addCheckbox($name, $caption = NULL) + { + return $this[$name] = new Controls\Checkbox($caption); + } + + + /** + * Adds set of radio button controls to the form. + * @param string control name + * @param string label + * @param array options from which to choose + * @return Nette\Forms\Controls\RadioList + */ + public function addRadioList($name, $label = NULL, array $items = NULL) + { + return $this[$name] = new Controls\RadioList($label, $items); + } + + + /** + * Adds set of checkbox controls to the form. + * @return Nette\Forms\Controls\CheckboxList + */ + public function addCheckboxList($name, $label = NULL, array $items = NULL) + { + return $this[$name] = new Controls\CheckboxList($label, $items); + } + + + /** + * Adds select box control that allows single item selection. + * @param string control name + * @param string label + * @param array items from which to choose + * @param int number of rows that should be visible + * @return Nette\Forms\Controls\SelectBox + */ + public function addSelect($name, $label = NULL, array $items = NULL, $size = NULL) + { + $control = new Controls\SelectBox($label, $items); + if ($size > 1) { + $control->setAttribute('size', (int) $size); + } + return $this[$name] = $control; + } + + + /** + * Adds select box control that allows multiple item selection. + * @param string control name + * @param string label + * @param array options from which to choose + * @param int number of rows that should be visible + * @return Nette\Forms\Controls\MultiSelectBox + */ + public function addMultiSelect($name, $label = NULL, array $items = NULL, $size = NULL) + { + $control = new Controls\MultiSelectBox($label, $items); + if ($size > 1) { + $control->setAttribute('size', (int) $size); + } + return $this[$name] = $control; + } + + + /** + * Adds button used to submit form. + * @param string control name + * @param string caption + * @return Nette\Forms\Controls\SubmitButton + */ + public function addSubmit($name, $caption = NULL) + { + return $this[$name] = new Controls\SubmitButton($caption); + } + + + /** + * Adds push buttons with no default behavior. + * @param string control name + * @param string caption + * @return Nette\Forms\Controls\Button + */ + public function addButton($name, $caption = NULL) + { + return $this[$name] = new Controls\Button($caption); + } + + + /** + * Adds graphical button used to submit form. + * @param string control name + * @param string URI of the image + * @param string alternate text for the image + * @return Nette\Forms\Controls\ImageButton + */ + public function addImage($name, $src = NULL, $alt = NULL) + { + return $this[$name] = new Controls\ImageButton($src, $alt); + } + + + /** + * Adds naming container to the form. + * @param string name + * @return Container + */ + public function addContainer($name) + { + $control = new Container; + $control->currentGroup = $this->currentGroup; + return $this[$name] = $control; + } + + + /********************* interface \ArrayAccess ****************d*g**/ + + + /** + * Adds the component to the container. + * @param string component name + * @param Nette\ComponentModel\IComponent + * @return void + */ + public function offsetSet($name, $component) + { + $this->addComponent($component, $name); + } + + + /** + * Returns component specified by name. Throws exception if component doesn't exist. + * @param string component name + * @return Nette\ComponentModel\IComponent + * @throws Nette\InvalidArgumentException + */ + public function offsetGet($name) + { + return $this->getComponent($name, TRUE); + } + + + /** + * Does component specified by name exists? + * @param string component name + * @return bool + */ + public function offsetExists($name) + { + return $this->getComponent($name, FALSE) !== NULL; + } + + + /** + * Removes component from the container. + * @param string component name + * @return void + */ + public function offsetUnset($name) + { + $component = $this->getComponent($name, FALSE); + if ($component !== NULL) { + $this->removeComponent($component); + } + } + + + /** + * Prevents cloning. + */ + public function __clone() + { + throw new Nette\NotImplementedException('Form cloning is not supported yet.'); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/ControlGroup.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/ControlGroup.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/ControlGroup.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/ControlGroup.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,113 @@ +controls = new \SplObjectStorage; + } + + + /** + * @return self + */ + public function add() + { + foreach (func_get_args() as $num => $item) { + if ($item instanceof IControl) { + $this->controls->attach($item); + + } elseif ($item instanceof \Traversable || is_array($item)) { + foreach ($item as $control) { + $this->controls->attach($control); + } + + } else { + throw new Nette\InvalidArgumentException("Only IFormControl items are allowed, the #$num parameter is invalid."); + } + } + return $this; + } + + + /** + * @return array IFormControl + */ + public function getControls() + { + return iterator_to_array($this->controls); + } + + + /** + * Sets user-specific option. + * Options recognized by DefaultFormRenderer + * - 'label' - textual or Html object label + * - 'visual' - indicates visual group + * - 'container' - container as Html object + * - 'description' - textual or Html object description + * - 'embedNext' - describes how render next group + * + * @param string key + * @param mixed value + * @return self + */ + public function setOption($key, $value) + { + if ($value === NULL) { + unset($this->options[$key]); + + } else { + $this->options[$key] = $value; + } + return $this; + } + + + /** + * Returns user-specific option. + * @param string key + * @param mixed default value + * @return mixed + */ + public function getOption($key, $default = NULL) + { + return isset($this->options[$key]) ? $this->options[$key] : $default; + } + + + /** + * Returns user-specific options. + * @return array + */ + public function getOptions() + { + return $this->options; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/BaseControl.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/BaseControl.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/BaseControl.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/BaseControl.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,714 @@ +monitor('Nette\Forms\Form'); + parent::__construct(); + $this->control = Html::el('input', array('type' => NULL, 'name' => NULL)); + $this->label = Html::el('label'); + $this->caption = $caption; + $this->rules = new Nette\Forms\Rules($this); + $this->setValue(NULL); + } + + + /** + * This method will be called when the component becomes attached to Form. + * @param Nette\ComponentModel\IComponent + * @return void + */ + protected function attached($form) + { + if (!$this->isDisabled() && $form instanceof Form && $form->isAnchored() && $form->isSubmitted()) { + $this->loadHttpData(); + } + } + + + /** + * Returns form. + * @param bool throw exception if form doesn't exist? + * @return Nette\Forms\Form + */ + public function getForm($need = TRUE) + { + return $this->lookup('Nette\Forms\Form', $need); + } + + + /** + * Loads HTTP data. + * @return void + */ + public function loadHttpData() + { + $this->setValue($this->getHttpData(Form::DATA_TEXT)); + } + + + /** + * Loads HTTP data. + * @return mixed + */ + public function getHttpData($type, $htmlTail = NULL) + { + return $this->getForm()->getHttpData($type, $this->getHtmlName() . $htmlTail); + } + + + /** + * Returns HTML name of control. + * @return string + */ + public function getHtmlName() + { + return Nette\Forms\Helpers::generateHtmlName($this->lookupPath('Nette\Forms\Form')); + } + + + /********************* interface IFormControl ****************d*g**/ + + + /** + * Sets control's value. + * @return self + */ + public function setValue($value) + { + $this->value = $value; + return $this; + } + + + /** + * Returns control's value. + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + + /** + * Is control filled? + * @return bool + */ + public function isFilled() + { + $value = $this->getValue(); + return $value !== NULL && $value !== array() && $value !== ''; + } + + + /** + * Sets control's default value. + * @return self + */ + public function setDefaultValue($value) + { + $form = $this->getForm(FALSE); + if ($this->isDisabled() || !$form || !$form->isAnchored() || !$form->isSubmitted()) { + $this->setValue($value); + } + return $this; + } + + + /** + * Disables or enables control. + * @param bool + * @return self + */ + public function setDisabled($value = TRUE) + { + if ($this->disabled = (bool) $value) { + $this->omitted = TRUE; + $this->setValue(NULL); + } + return $this; + } + + + /** + * Is control disabled? + * @return bool + */ + public function isDisabled() + { + return $this->disabled === TRUE; + } + + + /** + * Sets whether control value is excluded from $form->getValues() result. + * @param bool + * @return self + */ + public function setOmitted($value = TRUE) + { + $this->omitted = (bool) $value; + return $this; + } + + + /** + * Is control value excluded from $form->getValues() result? + * @return bool + */ + public function isOmitted() + { + return $this->omitted; + } + + + /********************* rendering ****************d*g**/ + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html|string + */ + public function getControl() + { + $this->setOption('rendered', TRUE); + + $rules = self::exportRules($this->rules); + $el = clone $this->control; + return $el->addAttributes(array( + 'name' => $this->getHtmlName(), + 'id' => $this->getHtmlId(), + 'required' => $this->isRequired(), + 'disabled' => $this->isDisabled(), + 'data-nette-rules' => $rules ? Nette\Utils\Json::encode($rules) : NULL, + )); + } + + + /** + * Generates label's HTML element. + * @param string + * @return Nette\Utils\Html|string + */ + public function getLabel($caption = NULL) + { + $label = clone $this->label; + $label->for = $this->getHtmlId(); + $label->setText($this->translate($caption === NULL ? $this->caption : $caption)); + return $label; + } + + + /** + * Returns control's HTML element template. + * @return Nette\Utils\Html + */ + public function getControlPrototype() + { + return $this->control; + } + + + /** + * Returns label's HTML element template. + * @return Nette\Utils\Html + */ + public function getLabelPrototype() + { + return $this->label; + } + + + /** + * Changes control's HTML id. + * @param string new ID, or FALSE or NULL + * @return self + */ + public function setHtmlId($id) + { + $this->control->id = $id; + return $this; + } + + + /** + * Returns control's HTML id. + * @return string + */ + public function getHtmlId() + { + if (!isset($this->control->id)) { + $this->control->id = sprintf(self::$idMask, $this->lookupPath(NULL)); + } + return $this->control->id; + } + + + /** + * Changes control's HTML attribute. + * @param string name + * @param mixed value + * @return self + */ + public function setAttribute($name, $value = TRUE) + { + $this->control->$name = $value; + return $this; + } + + + /********************* translator ****************d*g**/ + + + /** + * Sets translate adapter. + * @return self + */ + public function setTranslator(Nette\Localization\ITranslator $translator = NULL) + { + $this->translator = $translator; + return $this; + } + + + /** + * Returns translate adapter. + * @return Nette\Localization\ITranslator|NULL + */ + public function getTranslator() + { + if ($this->translator === TRUE) { + return $this->getForm(FALSE) ? $this->getForm()->getTranslator() : NULL; + } + return $this->translator; + } + + + /** + * Returns translated string. + * @param mixed + * @param int plural count + * @return string + */ + public function translate($value, $count = NULL) + { + if ($translator = $this->getTranslator()) { + $tmp = is_array($value) ? array(& $value) : array(array(& $value)); + foreach ($tmp[0] as & $v) { + if ($v != NULL && !$v instanceof Html) { // intentionally == + $v = $translator->translate((string) $v, $count); + } + } + } + return $value; + } + + + /********************* rules ****************d*g**/ + + + /** + * Adds a validation rule. + * @param mixed rule type + * @param string message to display for invalid data + * @param mixed optional rule arguments + * @return self + */ + public function addRule($operation, $message = NULL, $arg = NULL) + { + $this->rules->addRule($operation, $message, $arg); + return $this; + } + + + /** + * Adds a validation condition a returns new branch. + * @param mixed condition type + * @param mixed optional condition arguments + * @return Nette\Forms\Rules new branch + */ + public function addCondition($operation, $value = NULL) + { + return $this->rules->addCondition($operation, $value); + } + + + /** + * Adds a validation condition based on another control a returns new branch. + * @param Nette\Forms\IControl form control + * @param mixed condition type + * @param mixed optional condition arguments + * @return Nette\Forms\Rules new branch + */ + public function addConditionOn(IControl $control, $operation, $value = NULL) + { + return $this->rules->addConditionOn($control, $operation, $value); + } + + + /** + * @return Nette\Forms\Rules + */ + public function getRules() + { + return $this->rules; + } + + + /** + * Makes control mandatory. + * @param mixed state or error message + * @return self + */ + public function setRequired($value = TRUE) + { + $this->rules->setRequired($value); + return $this; + } + + + /** + * Is control mandatory? + * @return bool + */ + public function isRequired() + { + return $this->rules->isRequired(); + } + + + /** + * Performs the server side validation. + * @return void + */ + public function validate() + { + if ($this->isDisabled()) { + return; + } + $this->cleanErrors(); + $this->rules->validate(); + } + + + /** + * Adds error message to the list. + * @param string error message + * @return void + */ + public function addError($message) + { + $this->errors[] = $message; + } + + + /** + * Returns errors corresponding to control. + * @return string + */ + public function getError() + { + return $this->errors ? implode(' ', array_unique($this->errors)) : NULL; + } + + + /** + * Returns errors corresponding to control. + * @return array + */ + public function getErrors() + { + return array_unique($this->errors); + } + + + /** + * @return bool + */ + public function hasErrors() + { + return (bool) $this->errors; + } + + + /** + * @return void + */ + public function cleanErrors() + { + $this->errors = array(); + } + + + /** + * @return array + */ + protected static function exportRules($rules) + { + $payload = array(); + foreach ($rules as $rule) { + if (!is_string($op = $rule->operation)) { + if (!Nette\Utils\Callback::isStatic($op)) { + continue; + } + $op = Nette\Utils\Callback::toString($op); + } + if ($rule->type === Rule::VALIDATOR) { + $item = array('op' => ($rule->isNegative ? '~' : '') . $op, 'msg' => $rules->formatMessage($rule, FALSE)); + + } elseif ($rule->type === Rule::CONDITION) { + $item = array( + 'op' => ($rule->isNegative ? '~' : '') . $op, + 'rules' => static::exportRules($rule->subRules), + 'control' => $rule->control->getHtmlName() + ); + if ($rule->subRules->getToggles()) { + $item['toggle'] = $rule->subRules->getToggles(); + } + } + + if (is_array($rule->arg)) { + foreach ($rule->arg as $key => $value) { + $item['arg'][$key] = $value instanceof IControl ? array('control' => $value->getHtmlName()) : $value; + } + } elseif ($rule->arg !== NULL) { + $item['arg'] = $rule->arg instanceof IControl ? array('control' => $rule->arg->getHtmlName()) : $rule->arg; + } + + $payload[] = $item; + } + return $payload; + } + + + /********************* validators ****************d*g**/ + + + /** + * Is control's value equal with second parameter? + * @return bool + * @internal + */ + public static function validateEqual(IControl $control, $arg) + { + $value = $control->getValue(); + foreach ((is_array($value) ? $value : array($value)) as $val) { + foreach ((is_array($arg) ? $arg : array($arg)) as $item) { + if ((string) $val === (string) $item) { + continue 2; + } + } + return FALSE; + } + return TRUE; + } + + + /** + * Is control's value not equal with second parameter? + * @return bool + * @internal + */ + public static function validateNotEqual(IControl $control, $arg) + { + return !static::validateEqual($control, $arg); + } + + + /** + * Is control filled? + * @return bool + * @internal + */ + public static function validateFilled(IControl $control) + { + return $control->isFilled(); + } + + + /** + * Is control not filled? + * @return bool + * @internal + */ + public static function validateBlank(IControl $control) + { + return !$control->isFilled(); + } + + + /** + * Is control valid? + * @return bool + * @internal + */ + public static function validateValid(IControl $control) + { + return $control->rules->validate(); + } + + + /** + * Is a control's value number in specified range? + * @param Nette\Forms\IControl + * @param array min and max value pair + * @return bool + * @internal + */ + public static function validateRange(IControl $control, $range) + { + return Nette\Utils\Validators::isInRange($control->getValue(), $range); + } + + + /** + * Count/length validator. Range is array, min and max length pair. + * @return bool + * @internal + */ + public static function validateLength(IControl $control, $range) + { + if (!is_array($range)) { + $range = array($range, $range); + } + $value = $control->getValue(); + return Nette\Utils\Validators::isInRange(is_array($value) ? count($value) : Nette\Utils\Strings::length($value), $range); + } + + + /** + * Has control's value minimal count/length? + * @return bool + * @internal + */ + public static function validateMinLength(IControl $control, $length) + { + return static::validateLength($control, array($length, NULL)); + } + + + /** + * Is control's value count/length in limit? + * @return bool + * @internal + */ + public static function validateMaxLength(IControl $control, $length) + { + return static::validateLength($control, array(NULL, $length)); + } + + + /********************* user data ****************d*g**/ + + + /** + * Sets user-specific option. + * @return self + */ + public function setOption($key, $value) + { + if ($value === NULL) { + unset($this->options[$key]); + } else { + $this->options[$key] = $value; + } + return $this; + } + + + /** + * Returns user-specific option. + * @return mixed + */ + public function getOption($key, $default = NULL) + { + return isset($this->options[$key]) ? $this->options[$key] : $default; + } + + + /** + * Returns user-specific options. + * @return array + */ + public function getOptions() + { + return $this->options; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/Button.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/Button.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/Button.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/Button.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,69 @@ +control->type = 'button'; + } + + + /** + * Is button pressed? + * @return bool + */ + public function isFilled() + { + $value = $this->getValue(); + return $value !== NULL && $value !== array(); + } + + + /** + * Bypasses label generation. + * @return void + */ + public function getLabel($caption = NULL) + { + return NULL; + } + + + /** + * Generates control's HTML element. + * @param string + * @return Nette\Utils\Html + */ + public function getControl($caption = NULL) + { + $this->setOption('rendered', TRUE); + $el = clone $this->control; + return $el->addAttributes(array( + 'name' => $this->getHtmlName(), + 'id' => $this->getHtmlId(), + 'disabled' => $this->isDisabled(), + 'value' => $this->translate($caption === NULL ? $this->caption : $caption), + )); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/CheckboxList.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/CheckboxList.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/CheckboxList.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/CheckboxList.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,103 @@ +control->type = 'checkbox'; + $this->separator = Html::el('br'); + } + + + /** + * Generates control's HTML element. + * @return string + */ + public function getControl() + { + $items = $this->getItems(); + reset($items); + $input = parent::getControl(); + return Nette\Forms\Helpers::createInputList( + $this->translate($items), + array_merge($input->attrs, array( + 'id' => NULL, + 'checked?' => $this->value, + 'disabled:' => $this->disabled, + 'required' => NULL, + 'data-nette-rules:' => array(key($items) => $input->attrs['data-nette-rules']), + )), + $this->label->attrs, + $this->separator + ); + } + + + /** + * Generates label's HTML element. + * @param string + * @return Nette\Utils\Html + */ + public function getLabel($caption = NULL) + { + return parent::getLabel($caption)->for(NULL); + } + + + /** + * Returns separator HTML element template. + * @return Nette\Utils\Html + */ + public function getSeparatorPrototype() + { + return $this->separator; + } + + + /** + * @return Nette\Utils\Html + */ + public function getControlPart($key) + { + return parent::getControl()->addAttributes(array( + 'id' => $this->getHtmlId() . '-' . $key, + 'checked' => in_array($key, (array) $this->value, TRUE), + 'disabled' => is_array($this->disabled) ? isset($this->disabled[$key]) : $this->disabled, + 'required' => NULL, + 'value' => $key, + )); + } + + + /** + * @return Nette\Utils\Html + */ + public function getLabelPart($key) + { + return parent::getLabel($this->items[$key])->for($this->getHtmlId() . '-' . $key); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/Checkbox.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/Checkbox.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/Checkbox.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/Checkbox.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,107 @@ +control->type = 'checkbox'; + $this->wrapper = Nette\Utils\Html::el(); + } + + + /** + * Sets control's value. + * @param bool + * @return self + */ + public function setValue($value) + { + if (!is_scalar($value) && $value !== NULL) { + throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or NULL, %s given in field '%s'.", gettype($value), $this->name)); + } + $this->value = (bool) $value; + return $this; + } + + + /** + * Is control filled? + * @return bool + */ + public function isFilled() + { + return $this->getValue() !== FALSE; // back compatibility + } + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html + */ + public function getControl() + { + return $this->wrapper->setHtml($this->getLabelPart()->insert(0, $this->getControlPart())); + } + + + /** + * Bypasses label generation. + * @return void + */ + public function getLabel($caption = NULL) + { + return NULL; + } + + + /** + * @return Nette\Utils\Html + */ + public function getControlPart() + { + return parent::getControl()->checked($this->value); + } + + + /** + * @return Nette\Utils\Html + */ + public function getLabelPart() + { + return parent::getLabel(); + } + + + /** + * Returns wrapper HTML element template. + * @return Nette\Utils\Html + */ + public function getSeparatorPrototype() + { + return $this->wrapper; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/ChoiceControl.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/ChoiceControl.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/ChoiceControl.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/ChoiceControl.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,153 @@ +setItems($items); + } + } + + + /** + * Loads HTTP data. + * @return void + */ + public function loadHttpData() + { + $this->value = $this->getHttpData(Nette\Forms\Form::DATA_TEXT); + if ($this->value !== NULL) { + if (is_array($this->disabled) && isset($this->disabled[$this->value])) { + $this->value = NULL; + } else { + $this->value = key(array($this->value => NULL)); + } + } + } + + + /** + * Sets selected item (by key). + * @param scalar + * @return self + */ + public function setValue($value) + { + if ($value !== NULL && !array_key_exists((string) $value, $this->items)) { + $range = Nette\Utils\Strings::truncate(implode(', ', array_map(function($s) { return var_export($s, TRUE); }, array_keys($this->items))), 70, '...'); + throw new Nette\InvalidArgumentException("Value '$value' is out of allowed range [$range] in field '{$this->name}'."); + } + $this->value = $value === NULL ? NULL : key(array((string) $value => NULL)); + return $this; + } + + + /** + * Returns selected key. + * @return scalar + */ + public function getValue() + { + return array_key_exists($this->value, $this->items) ? $this->value : NULL; + } + + + /** + * Returns selected key (not checked). + * @return scalar + */ + public function getRawValue() + { + return $this->value; + } + + + /** + * Is any item selected? + * @return bool + */ + public function isFilled() + { + return $this->getValue() !== NULL; + } + + + /** + * Sets items from which to choose. + * @param array + * @param bool + * @return self + */ + public function setItems(array $items, $useKeys = TRUE) + { + $this->items = $useKeys ? $items : array_combine($items, $items); + return $this; + } + + + /** + * Returns items from which to choose. + * @return array + */ + public function getItems() + { + return $this->items; + } + + + /** + * Returns selected value. + * @return mixed + */ + public function getSelectedItem() + { + $value = $this->getValue(); + return $value === NULL ? NULL : $this->items[$value]; + } + + + /** + * Disables or enables control or items. + * @param bool|array + * @return self + */ + public function setDisabled($value = TRUE) + { + if (!is_array($value)) { + return parent::setDisabled($value); + } + + parent::setDisabled(FALSE); + $this->disabled = array_fill_keys($value, TRUE); + if (isset($this->disabled[$this->value])) { + $this->value = NULL; + } + return $this; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/CsrfProtection.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/CsrfProtection.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/CsrfProtection.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/CsrfProtection.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,105 @@ +setOmitted()->addRule(self::PROTECTION, $message); + $this->monitor('Nette\Application\UI\Presenter'); + } + + + protected function attached($parent) + { + parent::attached($parent); + if (!$this->session && $parent instanceof Nette\Application\UI\Presenter) { + $this->session = $parent->getSession(); + } + } + + + /** + * @return string + */ + public function getToken() + { + $session = $this->getSession()->getSection(__CLASS__); + if (!isset($session->token)) { + $session->token = Nette\Utils\Strings::random(); + } + return $session->token; + } + + + /** + * @return string + */ + private function generateToken($random = NULL) + { + if ($random === NULL) { + $random = Nette\Utils\Strings::random(10); + } + return $random . base64_encode(sha1($this->getToken() . $random, TRUE)); + } + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html + */ + public function getControl() + { + return parent::getControl()->value($this->generateToken()); + } + + + /** + * @return bool + * @internal + */ + public static function validateCsrf(CsrfProtection $control) + { + $value = $control->getValue(); + return $control->generateToken(substr($value, 0, 10)) === $value; + } + + + /********************* backend ****************d*g**/ + + + /** + * @return Nette\Http\Session + */ + private function getSession() + { + if (!$this->session) { + $this->session = new Nette\Http\Session($this->getForm()->httpRequest, new Nette\Http\Response); + } + return $this->session; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/HiddenField.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/HiddenField.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/HiddenField.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/HiddenField.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,90 @@ +control->type = 'hidden'; + if ($persistentValue !== NULL) { + $this->unmonitor('Nette\Forms\Form'); + $this->persistValue = TRUE; + $this->value = (string) $persistentValue; + } + } + + + /** + * Sets control's value. + * @param string + * @return self + */ + public function setValue($value) + { + if (!is_scalar($value) && $value !== NULL && !method_exists($value, '__toString')) { + throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or NULL, %s given in field '%s'.", gettype($value), $this->name)); + } + if (!$this->persistValue) { + $this->value = (string) $value; + } + return $this; + } + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html + */ + public function getControl() + { + $this->setOption('rendered', TRUE); + $el = clone $this->control; + return $el->addAttributes(array( + 'name' => $this->getHtmlName(), + 'id' => $this->getHtmlId(), + 'disabled' => $this->isDisabled(), + 'value' => $this->value, + )); + } + + + /** + * Bypasses label generation. + * @return void + */ + public function getLabel($caption = NULL) + { + return NULL; + } + + + /** + * Adds error message to the list. + * @param string error message + * @return void + */ + public function addError($message) + { + $this->getForm()->addError($message); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/ImageButton.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/ImageButton.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/ImageButton.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/ImageButton.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,56 @@ +control->type = 'image'; + $this->control->src = $src; + $this->control->alt = $alt; + } + + + /** + * Loads HTTP data. + * @return void + */ + public function loadHttpData() + { + parent::loadHttpData(); + $this->value = $this->value + ? array((int) array_shift($this->value), (int) array_shift($this->value)) + : NULL; + } + + + /** + * Returns HTML name of control. + * @return string + */ + public function getHtmlName() + { + return parent::getHtmlName() . '[]'; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/MultiChoiceControl.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/MultiChoiceControl.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/MultiChoiceControl.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/MultiChoiceControl.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,170 @@ +setItems($items); + } + } + + + /** + * Loads HTTP data. + * @return void + */ + public function loadHttpData() + { + $this->value = array_keys(array_flip($this->getHttpData(Nette\Forms\Form::DATA_TEXT))); + if (is_array($this->disabled)) { + $this->value = array_diff($this->value, array_keys($this->disabled)); + } + } + + + /** + * Sets selected items (by keys). + * @param array + * @return self + */ + public function setValue($values) + { + if (is_scalar($values) || $values === NULL) { + $values = (array) $values; + } elseif (!is_array($values)) { + throw new Nette\InvalidArgumentException(sprintf("Value must be array or NULL, %s given in field '%s'.", gettype($values), $this->name)); + } + $flip = array(); + foreach ($values as $value) { + if (!is_scalar($value) && !method_exists($value, '__toString')) { + throw new Nette\InvalidArgumentException(sprintf("Values must be scalar, %s given in field '%s'.", gettype($value), $this->name)); + } + $flip[(string) $value] = TRUE; + } + $values = array_keys($flip); + if ($diff = array_diff($values, array_keys($this->items))) { + $range = Nette\Utils\Strings::truncate(implode(', ', array_map(function($s) { return var_export($s, TRUE); }, array_keys($this->items))), 70, '...'); + $vals = (count($diff) > 1 ? 's' : '') . " '" . implode("', '", $diff) . "'"; + throw new Nette\InvalidArgumentException("Value$vals are out of allowed range [$range] in field '{$this->name}'."); + } + $this->value = $values; + return $this; + } + + + /** + * Returns selected keys. + * @return array + */ + public function getValue() + { + return array_values(array_intersect($this->value, array_keys($this->items))); + } + + + /** + * Returns selected keys (not checked). + * @return array + */ + public function getRawValue() + { + return $this->value; + } + + + /** + * Is any item selected? + * @return bool + */ + public function isFilled() + { + return $this->getValue() !== array(); + } + + + /** + * Sets items from which to choose. + * @param array + * @param bool + * @return self + */ + public function setItems(array $items, $useKeys = TRUE) + { + $this->items = $useKeys ? $items : array_combine($items, $items); + return $this; + } + + + /** + * Returns items from which to choose. + * @return array + */ + public function getItems() + { + return $this->items; + } + + + /** + * Returns selected values. + * @return array + */ + public function getSelectedItems() + { + return array_intersect_key($this->items, array_flip($this->value)); + } + + + /** + * Disables or enables control or items. + * @param bool|array + * @return self + */ + public function setDisabled($value = TRUE) + { + if (!is_array($value)) { + return parent::setDisabled($value); + } + + parent::setDisabled(FALSE); + $this->disabled = array_fill_keys($value, TRUE); + $this->value = array_diff($this->value, $value); + return $this; + } + + + /** + * Returns HTML name of control. + * @return string + */ + public function getHtmlName() + { + return parent::getHtmlName() . '[]'; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/MultiSelectBox.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/MultiSelectBox.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/MultiSelectBox.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/MultiSelectBox.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,77 @@ + $value) { + unset($items[$key]); + if (is_array($value)) { + foreach ($value as $val) { + $res[$key][(string) $val] = $val; + } + } else { + $res[(string) $value] = $value; + } + } + $items = $res; + } + $this->options = $items; + return parent::setItems(Nette\Utils\Arrays::flatten($items, TRUE)); + } + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html + */ + public function getControl() + { + $items = array(); + foreach ($this->options as $key => $value) { + $items[is_array($value) ? $this->translate($key) : $key] = $this->translate($value); + } + + return Nette\Forms\Helpers::createSelectBox( + $items, + array( + 'selected?' => $this->value, + 'disabled:' => is_array($this->disabled) ? $this->disabled : NULL + ) + )->addAttributes(parent::getControl()->attrs)->multiple(TRUE); + } + + + /** @deprecated */ + function getSelectedItem() + { + trigger_error(__METHOD__ . '(TRUE) is deprecated; use getSelectedItems() instead.', E_USER_DEPRECATED); + return $this->getSelectedItems(); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/RadioList.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/RadioList.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/RadioList.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/RadioList.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,148 @@ +control->type = 'radio'; + $this->container = Html::el(); + $this->separator = Html::el('br'); + } + + + /** + * Returns selected radio value. + * @return mixed + */ + public function getValue($raw = FALSE) + { + if ($raw) { + trigger_error(__METHOD__ . '(TRUE) is deprecated; use getRawValue() instead.', E_USER_DEPRECATED); + return $this->getRawValue(); + } + return parent::getValue(); + } + + + /** + * Returns separator HTML element template. + * @return Nette\Utils\Html + */ + public function getSeparatorPrototype() + { + return $this->separator; + } + + + /** + * Returns container HTML element template. + * @return Nette\Utils\Html + */ + public function getContainerPrototype() + { + return $this->container; + } + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html + */ + public function getControl($key = NULL) + { + if ($key !== NULL) { + trigger_error(sprintf('Partial %s() is deprecated; use getControlPart() instead.', __METHOD__), E_USER_DEPRECATED); + return $this->getControlPart($key); + } + + $input = parent::getControl(); + $ids = array(); + foreach ($this->getItems() as $value => $label) { + $ids[$value] = $input->id . '-' . $value; + } + + return $this->container->setHtml( + Nette\Forms\Helpers::createInputList( + $this->translate($this->getItems()), + array_merge($input->attrs, array( + 'id:' => $ids, + 'checked?' => $this->value, + 'disabled:' => $this->disabled, + 'data-nette-rules:' => array(key($ids) => $input->attrs['data-nette-rules']), + )), + array('for:' => $ids), + $this->separator + ) + ); + } + + + /** + * Generates label's HTML element. + * @param string + * @return Nette\Utils\Html + */ + public function getLabel($caption = NULL, $key = NULL) + { + if ($key !== NULL) { + trigger_error(sprintf('Partial %s() is deprecated; use getLabelPart() instead.', __METHOD__), E_USER_DEPRECATED); + return $this->getLabelPart($key); + } + return parent::getLabel($caption)->for(NULL); + } + + + /** + * @return Nette\Utils\Html + */ + public function getControlPart($key) + { + return parent::getControl()->addAttributes(array( + 'id' => $this->getHtmlId() . '-' . $key, + 'checked' => in_array($key, (array) $this->value, TRUE), + 'disabled' => is_array($this->disabled) ? isset($this->disabled[$key]) : $this->disabled, + 'value' => $key, + )); + } + + + /** + * @return Nette\Utils\Html + */ + public function getLabelPart($key) + { + return parent::getLabel($this->items[$key])->for($this->getHtmlId() . '-' . $key); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/SelectBox.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/SelectBox.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/SelectBox.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/SelectBox.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,119 @@ +getItems(); + $prompt = reset($items); + unset($this->options[key($items)], $items[key($items)]); + $this->setItems($items); + } + $this->prompt = $prompt; + return $this; + } + + + /** + * Returns first prompt item? + * @return mixed + */ + public function getPrompt() + { + return $this->prompt; + } + + + /** + * Sets options and option groups from which to choose. + * @return self + */ + public function setItems(array $items, $useKeys = TRUE) + { + if (!$useKeys) { + $res = array(); + foreach ($items as $key => $value) { + unset($items[$key]); + if (is_array($value)) { + foreach ($value as $val) { + $res[$key][(string) $val] = $val; + } + } else { + $res[(string) $value] = $value; + } + } + $items = $res; + } + $this->options = $items; + return parent::setItems(Nette\Utils\Arrays::flatten($items, TRUE)); + } + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html + */ + public function getControl() + { + $items = $this->prompt === FALSE ? array() : array('' => $this->translate($this->prompt)); + foreach ($this->options as $key => $value) { + $items[is_array($value) ? $this->translate($key) : $key] = $this->translate($value); + } + + return Nette\Forms\Helpers::createSelectBox( + $items, + array( + 'selected?' => $this->value, + 'disabled:' => is_array($this->disabled) ? $this->disabled : NULL + ) + )->addAttributes(parent::getControl()->attrs); + } + + + /** + * Performs the server side validation. + * @return void + */ + public function validate() + { + parent::validate(); + if (!$this->isDisabled() && $this->prompt === FALSE && $this->getValue() === NULL && $this->options) { + $this->addError(Nette\Forms\Rules::$defaultMessages[self::VALID]); + } + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/SubmitButton.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/SubmitButton.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/SubmitButton.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/SubmitButton.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,136 @@ +control->type = 'submit'; + $this->setOmitted(TRUE); + } + + + /** + * Loads HTTP data. + * @return void + */ + public function loadHttpData() + { + parent::loadHttpData(); + if ($this->isFilled()) { + $this->getForm()->setSubmittedBy($this); + } + } + + + /** + * Tells if the form was submitted by this button. + * @return bool + */ + public function isSubmittedBy() + { + return $this->getForm()->isSubmitted() === $this; + } + + + /** + * Sets the validation scope. Clicking the button validates only the controls within the specified scope. + * @return self + */ + public function setValidationScope(/*array*/$scope = NULL) + { + if ($scope === NULL || $scope === TRUE) { + $this->validationScope = NULL; + } else { + $this->validationScope = array(); + foreach ($scope ?: array() as $control) { + if (!$control instanceof Nette\Forms\Container && !$control instanceof Nette\Forms\IControl) { + throw new Nette\InvalidArgumentException('Validation scope accepts only Nette\Forms\Container or Nette\Forms\IControl instances.'); + } + $this->validationScope[] = $control; + } + } + return $this; + } + + + /** + * Gets the validation scope. + * @return array|NULL + */ + public function getValidationScope() + { + return $this->validationScope; + } + + + /** + * Fires click event. + * @return void + */ + public function click() + { + $this->onClick($this); + } + + + /** + * Generates control's HTML element. + * @param string + * @return Nette\Utils\Html + */ + public function getControl($caption = NULL) + { + $scope = array(); + foreach ((array) $this->validationScope as $control) { + $scope[] = $control->lookupPath('Nette\Forms\Form'); + } + return parent::getControl($caption)->addAttributes(array( + 'formnovalidate' => $this->validationScope !== NULL, + 'data-nette-validation-scope' => $scope ? json_encode($scope) : NULL, + )); + } + + + /** + * Submitted validator: has been button pressed? + * @return bool + * @internal + */ + public static function validateSubmitted(SubmitButton $control) + { + return $control->isSubmittedBy(); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/TextArea.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/TextArea.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/TextArea.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/TextArea.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,45 @@ +control->setName('textarea'); + } + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html + */ + public function getControl() + { + $value = $this->getValue(); + if ($value === '') { + $value = $this->translate($this->emptyValue); + } + return parent::getControl() + ->setText($value); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/TextBase.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/TextBase.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/TextBase.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/TextBase.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,235 @@ +name)); + } + $this->rawValue = $this->value = $value; + return $this; + } + + + /** + * Returns control's value. + * @return string + */ + public function getValue() + { + $value = $this->value; + if (!empty($this->control->maxlength)) { + $value = Nette\Utils\Strings::substring($value, 0, $this->control->maxlength); + } + foreach ($this->filters as $filter) { + $value = (string) call_user_func($filter, $value); + } + return $value === $this->translate($this->emptyValue) ? '' : $value; + } + + + /** + * Sets the special value which is treated as empty string. + * @param string + * @return self + */ + public function setEmptyValue($value) + { + $this->emptyValue = (string) $value; + return $this; + } + + + /** + * Returns the special value which is treated as empty string. + * @return string + */ + public function getEmptyValue() + { + return $this->emptyValue; + } + + + /** + * Appends input string filter callback. + * @param callable + * @return self + * @deprecated + */ + public function addFilter($filter) + { + $this->filters[] = Nette\Utils\Callback::check($filter); + return $this; + } + + + public function getControl() + { + $el = parent::getControl(); + if ($this->emptyValue !== '') { + $el->attrs['data-nette-empty-value'] = $this->translate($this->emptyValue); + } + if (isset($el->placeholder)) { + $el->placeholder = $this->translate($el->placeholder); + } + return $el; + } + + + public function addRule($operation, $message = NULL, $arg = NULL) + { + if ($operation === Form::LENGTH || $operation === Form::MAX_LENGTH) { + $tmp = is_array($arg) ? $arg[1] : $arg; + if (is_scalar($tmp)) { + $this->control->maxlength = isset($this->control->maxlength) ? min($this->control->maxlength, $tmp) : $tmp; + } + } + return parent::addRule($operation, $message, $arg); + } + + + /********************* validators ****************d*g**/ + + + /** + * Is control's value valid email address? + * @return bool + * @internal + */ + public static function validateEmail(TextBase $control) + { + return Validators::isEmail($control->getValue()); + } + + + /** + * Is control's value valid URL? + * @return bool + * @internal + */ + public static function validateUrl(TextBase $control) + { + if (Validators::isUrl($value = $control->getValue())) { + return TRUE; + + } elseif (Validators::isUrl($value = "http://$value")) { + $control->setValue($value); + return TRUE; + } + return FALSE; + } + + + /** + * URL string cleanup. + * @param string + * @return string + */ + public static function filterUrl($s) + { + return Validators::isUrl('http://' . $s) ? 'http://' . $s : $s; + } + + + /** @deprecated */ + public static function validateRegexp(TextBase $control, $regexp) + { + trigger_error('Validator REGEXP is deprecated; use PATTERN instead (which is matched against the entire value and is case sensitive).', E_USER_DEPRECATED); + return (bool) Strings::match($control->getValue(), $regexp); + } + + + /** + * Matches control's value regular expression? + * @return bool + * @internal + */ + public static function validatePattern(TextBase $control, $pattern) + { + return (bool) Strings::match($control->getValue(), "\x01^($pattern)\\z\x01u"); + } + + + /** + * Is a control's value decimal number? + * @return bool + * @internal + */ + public static function validateInteger(TextBase $control) + { + if (Validators::isNumericInt($value = $control->getValue())) { + if (!is_float($tmp = $value * 1)) { // bigint leave as string + $control->setValue($tmp); + } + return TRUE; + } + return FALSE; + } + + + /** + * Is a control's value float number? + * @return bool + * @internal + */ + public static function validateFloat(TextBase $control) + { + $value = self::filterFloat($control->getValue()); + if (Validators::isNumeric($value)) { + $control->setValue((float) $value); + return TRUE; + } + return FALSE; + } + + + /** + * Float string cleanup. + * @param string + * @return string + * @internal + */ + public static function filterFloat($s) + { + return str_replace(array(' ', ','), array('', '.'), $s); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/TextInput.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/TextInput.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/TextInput.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/TextInput.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,99 @@ +control->type = 'text'; + $this->control->maxlength = $maxLength; + } + + + /** + * Loads HTTP data. + * @return void + */ + public function loadHttpData() + { + $this->setValue($this->getHttpData(Nette\Forms\Form::DATA_LINE)); + } + + + /** + * Changes control's type attribute. + * @param string + * @return self + */ + public function setType($type) + { + $this->control->type = $type; + return $this; + } + + + /** @deprecated */ + public function setPasswordMode($mode = TRUE) + { + trigger_error(__METHOD__ . '() is deprecated; use setType("password") instead.', E_USER_DEPRECATED); + $this->control->type = $mode ? 'password' : 'text'; + return $this; + } + + + /** + * Generates control's HTML element. + * @return Nette\Utils\Html + */ + public function getControl() + { + $input = parent::getControl(); + + foreach ($this->getRules() as $rule) { + if ($rule->isNegative || $rule->type !== Nette\Forms\Rule::VALIDATOR) { + + } elseif ($rule->operation === Nette\Forms\Form::RANGE + && in_array($input->type, array('number', 'range', 'datetime-local', 'datetime', 'date', 'month', 'week', 'time'), TRUE) + ) { + if (isset($rule->arg[0]) && is_scalar($rule->arg[0])) { + $input->min = isset($input->min) ? max($input->min, $rule->arg[0]) : $rule->arg[0]; + } + if (isset($rule->arg[1]) && is_scalar($rule->arg[1])) { + $input->max = isset($input->max) ? min($input->max, $rule->arg[1]) : $rule->arg[1]; + } + + } elseif ($rule->operation === Nette\Forms\Form::PATTERN && is_scalar($rule->arg) + && in_array($input->type, array('text', 'search', 'tel', 'url', 'email', 'password'), TRUE) + ) { + $input->pattern = $rule->arg; + } + } + + if ($input->type !== 'password') { + $input->value = $this->rawValue === '' ? $this->translate($this->emptyValue) : $this->rawValue; + } + return $input; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/UploadControl.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/UploadControl.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Controls/UploadControl.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Controls/UploadControl.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,155 @@ +control->type = 'file'; + $this->control->multiple = (bool) $multiple; + } + + + /** + * This method will be called when the component (or component's parent) + * becomes attached to a monitored object. Do not call this method yourself. + * @param Nette\ComponentModel\IComponent + * @return void + */ + protected function attached($form) + { + if ($form instanceof Nette\Forms\Form) { + if ($form->getMethod() !== Nette\Forms\Form::POST) { + throw new Nette\InvalidStateException('File upload requires method POST.'); + } + $form->getElementPrototype()->enctype = 'multipart/form-data'; + } + parent::attached($form); + } + + + /** + * Loads HTTP data. + * @return void + */ + public function loadHttpData() + { + $this->value = $this->getHttpData(Nette\Forms\Form::DATA_FILE); + if ($this->value === NULL) { + $this->value = new FileUpload(NULL); + } + } + + + /** + * Returns HTML name of control. + * @return string + */ + public function getHtmlName() + { + return parent::getHtmlName() . ($this->control->multiple ? '[]' : ''); + } + + + /** + * @return self + */ + public function setValue($value) + { + return $this; + } + + + /** + * Has been any file uploaded? + * @return bool + */ + public function isFilled() + { + return $this->value instanceof FileUpload ? $this->value->isOk() : (bool) $this->value; // ignore NULL object + } + + + /********************* validators ****************d*g**/ + + + /** + * Is file size in limit? + * @return bool + * @internal + */ + public static function validateFileSize(UploadControl $control, $limit) + { + foreach (static::toArray($control->getValue()) as $file) { + if ($file->getSize() > $limit || $file->getError() === UPLOAD_ERR_INI_SIZE) { + return FALSE; + } + } + return TRUE; + } + + + /** + * Has file specified mime type? + * @return bool + * @internal + */ + public static function validateMimeType(UploadControl $control, $mimeType) + { + $mimeTypes = is_array($mimeType) ? $mimeType : explode(',', $mimeType); + foreach (static::toArray($control->getValue()) as $file) { + $type = strtolower($file->getContentType()); + if (!in_array($type, $mimeTypes, TRUE) && !in_array(preg_replace('#/.*#', '/*', $type), $mimeTypes, TRUE)) { + return FALSE; + } + } + return TRUE; + } + + + /** + * Is file image? + * @return bool + * @internal + */ + public static function validateImage(UploadControl $control) + { + foreach (static::toArray($control->getValue()) as $file) { + if (!$file->isImage()) { + return FALSE; + } + } + return TRUE; + } + + + /** + * @return array + */ + public static function toArray($value) + { + return $value instanceof FileUpload ? array($value) : (array) $value; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Form.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Form.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Form.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Form.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,635 @@ + element */ + private $element; + + /** @var IFormRenderer */ + private $renderer; + + /** @var Nette\Localization\ITranslator */ + private $translator; + + /** @var ControlGroup[] */ + private $groups = array(); + + /** @var array */ + private $errors = array(); + + /** @var Nette\Http\IRequest used only by standalone form */ + public $httpRequest; + + + /** + * Form constructor. + * @param string + */ + public function __construct($name = NULL) + { + $this->element = Nette\Utils\Html::el('form'); + $this->element->action = ''; // RFC 1808 -> empty uri means 'this' + $this->element->method = self::POST; + $this->element->id = $name === NULL ? NULL : 'frm-' . $name; + + $this->monitor(__CLASS__); + if ($name !== NULL) { + $tracker = new Controls\HiddenField($name); + $tracker->setOmitted(); + $this[self::TRACKER_ID] = $tracker; + } + parent::__construct(NULL, $name); + } + + + /** + * This method will be called when the component (or component's parent) + * becomes attached to a monitored object. Do not call this method yourself. + * @param Nette\ComponentModel\IComponent + * @return void + */ + protected function attached($obj) + { + if ($obj instanceof self) { + throw new Nette\InvalidStateException('Nested forms are forbidden.'); + } + } + + + /** + * Returns self. + * @return Form + */ + public function getForm($need = TRUE) + { + return $this; + } + + + /** + * Sets form's action. + * @param mixed URI + * @return self + */ + public function setAction($url) + { + $this->element->action = $url; + return $this; + } + + + /** + * Returns form's action. + * @return mixed URI + */ + public function getAction() + { + return $this->element->action; + } + + + /** + * Sets form's method. + * @param string get | post + * @return self + */ + public function setMethod($method) + { + if ($this->httpData !== NULL) { + throw new Nette\InvalidStateException(__METHOD__ . '() must be called until the form is empty.'); + } + $this->element->method = strtolower($method); + return $this; + } + + + /** + * Returns form's method. + * @return string get | post + */ + public function getMethod() + { + return $this->element->method; + } + + + /** + * Cross-Site Request Forgery (CSRF) form protection. + * @param string + * @return Controls\CsrfProtection + */ + public function addProtection($message = NULL) + { + return $this[self::PROTECTOR_ID] = new Controls\CsrfProtection($message); + } + + + /** + * Adds fieldset group to the form. + * @param string caption + * @param bool set this group as current + * @return ControlGroup + */ + public function addGroup($caption = NULL, $setAsCurrent = TRUE) + { + $group = new ControlGroup; + $group->setOption('label', $caption); + $group->setOption('visual', TRUE); + + if ($setAsCurrent) { + $this->setCurrentGroup($group); + } + + if (!is_scalar($caption) || isset($this->groups[$caption])) { + return $this->groups[] = $group; + } else { + return $this->groups[$caption] = $group; + } + } + + + /** + * Removes fieldset group from form. + * @param string|ControlGroup + * @return void + */ + public function removeGroup($name) + { + if (is_string($name) && isset($this->groups[$name])) { + $group = $this->groups[$name]; + + } elseif ($name instanceof ControlGroup && in_array($name, $this->groups, TRUE)) { + $group = $name; + $name = array_search($group, $this->groups, TRUE); + + } else { + throw new Nette\InvalidArgumentException("Group not found in form '$this->name'"); + } + + foreach ($group->getControls() as $control) { + $control->getParent()->removeComponent($control); + } + + unset($this->groups[$name]); + } + + + /** + * Returns all defined groups. + * @return ControlGroup[] + */ + public function getGroups() + { + return $this->groups; + } + + + /** + * Returns the specified group. + * @param string name + * @return ControlGroup + */ + public function getGroup($name) + { + return isset($this->groups[$name]) ? $this->groups[$name] : NULL; + } + + + /********************* translator ****************d*g**/ + + + /** + * Sets translate adapter. + * @return self + */ + public function setTranslator(Nette\Localization\ITranslator $translator = NULL) + { + $this->translator = $translator; + return $this; + } + + + /** + * Returns translate adapter. + * @return Nette\Localization\ITranslator|NULL + */ + public function getTranslator() + { + return $this->translator; + } + + + /********************* submission ****************d*g**/ + + + /** + * Tells if the form is anchored. + * @return bool + */ + public function isAnchored() + { + return TRUE; + } + + + /** + * Tells if the form was submitted. + * @return ISubmitterControl|FALSE submittor control + */ + public function isSubmitted() + { + if ($this->submittedBy === NULL) { + $this->getHttpData(); + } + return $this->submittedBy; + } + + + /** + * Tells if the form was submitted and successfully validated. + * @return bool + */ + public function isSuccess() + { + return $this->isSubmitted() && $this->isValid(); + } + + + /** + * Sets the submittor control. + * @return self + */ + public function setSubmittedBy(ISubmitterControl $by = NULL) + { + $this->submittedBy = $by === NULL ? FALSE : $by; + return $this; + } + + + /** + * Returns submitted HTTP data. + * @return mixed + */ + public function getHttpData($type = NULL, $htmlName = NULL) + { + if ($this->httpData === NULL) { + if (!$this->isAnchored()) { + throw new Nette\InvalidStateException('Form is not anchored and therefore can not determine whether it was submitted.'); + } + $data = $this->receiveHttpData(); + $this->httpData = (array) $data; + $this->submittedBy = is_array($data); + } + if ($htmlName === NULL) { + return $this->httpData; + } + return Helpers::extractHttpData($this->httpData, $htmlName, $type); + } + + + /** + * Fires submit/click events. + * @return void + */ + public function fireEvents() + { + if (!$this->isSubmitted()) { + return; + + } elseif (!$this->getErrors()) { + $this->validate(); + } + + if ($this->submittedBy instanceof ISubmitterControl) { + if ($this->isValid()) { + $this->submittedBy->onClick($this->submittedBy); + } else { + $this->submittedBy->onInvalidClick($this->submittedBy); + } + } + + if ($this->onSuccess) { + foreach ($this->onSuccess as $handler) { + if (!$this->isValid()) { + $this->onError($this); + break; + } + Nette\Utils\Callback::invoke($handler, $this); + } + } elseif (!$this->isValid()) { + $this->onError($this); + } + $this->onSubmit($this); + } + + + /** + * Internal: returns submitted HTTP data or NULL when form was not submitted. + * @return array|NULL + */ + protected function receiveHttpData() + { + $httpRequest = $this->getHttpRequest(); + if (strcasecmp($this->getMethod(), $httpRequest->getMethod())) { + return; + } + + if ($httpRequest->isMethod('post')) { + $data = Nette\Utils\Arrays::mergeTree($httpRequest->getPost(), $httpRequest->getFiles()); + } else { + $data = $httpRequest->getQuery(); + if (!$data) { + return; + } + } + + if ($tracker = $this->getComponent(self::TRACKER_ID, FALSE)) { + if (!isset($data[self::TRACKER_ID]) || $data[self::TRACKER_ID] !== $tracker->getValue()) { + return; + } + } + + return $data; + } + + + /********************* validation ****************d*g**/ + + + public function validate(array $controls = NULL) + { + $this->cleanErrors(); + if ($controls === NULL && $this->submittedBy instanceof ISubmitterControl) { + $controls = $this->submittedBy->getValidationScope(); + } + $this->validateMaxPostSize(); + parent::validate($controls); + } + + + /** @internal */ + public function validateMaxPostSize() + { + if (!$this->submittedBy || strcasecmp($this->getMethod(), 'POST') || empty($_SERVER['CONTENT_LENGTH'])) { + return; + } + $maxSize = ini_get('post_max_size'); + $units = array('k' => 10, 'm' => 20, 'g' => 30); + if (isset($units[$ch = strtolower(substr($maxSize, -1))])) { + $maxSize <<= $units[$ch]; + } + if ($maxSize > 0 && $maxSize < $_SERVER['CONTENT_LENGTH']) { + $this->addError(sprintf(Rules::$defaultMessages[self::MAX_FILE_SIZE], $maxSize)); + } + } + + + /** + * Adds global error message. + * @param string error message + * @return void + */ + public function addError($message) + { + $this->errors[] = $message; + } + + + /** + * Returns global validation errors. + * @return array + */ + public function getErrors() + { + return array_unique(array_merge($this->errors, parent::getErrors())); + } + + + /** + * @return bool + */ + public function hasErrors() + { + return (bool) $this->getErrors(); + } + + + /** + * @return void + */ + public function cleanErrors() + { + $this->errors = array(); + } + + + /** + * Returns form's validation errors. + * @return array + */ + public function getOwnErrors() + { + return array_unique($this->errors); + } + + + /** @deprecated */ + public function getAllErrors() + { + trigger_error(__METHOD__ . '() is deprecated; use getErrors() instead.', E_USER_DEPRECATED); + return $this->getErrors(); + } + + + /********************* rendering ****************d*g**/ + + + /** + * Returns form's HTML element template. + * @return Nette\Utils\Html + */ + public function getElementPrototype() + { + return $this->element; + } + + + /** + * Sets form renderer. + * @return self + */ + public function setRenderer(IFormRenderer $renderer = NULL) + { + $this->renderer = $renderer; + return $this; + } + + + /** + * Returns form renderer. + * @return IFormRenderer + */ + public function getRenderer() + { + if ($this->renderer === NULL) { + $this->renderer = new Rendering\DefaultFormRenderer; + } + return $this->renderer; + } + + + /** + * Renders form. + * @return void + */ + public function render() + { + $args = func_get_args(); + array_unshift($args, $this); + echo call_user_func_array(array($this->getRenderer(), 'render'), $args); + } + + + /** + * Renders form to string. + * @return can throw exceptions? (hidden parameter) + * @return string + */ + public function __toString() + { + try { + return $this->getRenderer()->render($this); + + } catch (\Exception $e) { + if (func_num_args()) { + throw $e; + } + trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); + } + } + + + /********************* backend ****************d*g**/ + + + /** + * @return Nette\Http\IRequest + */ + private function getHttpRequest() + { + if (!$this->httpRequest) { + $factory = new Nette\Http\RequestFactory; + $this->httpRequest = $factory->createHttpRequest(); + } + return $this->httpRequest; + } + + + /** + * @return array + */ + public function getToggles() + { + $toggles = array(); + foreach ($this->getControls() as $control) { + $toggles = $control->getRules()->getToggleStates($toggles); + } + return $toggles; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Helpers.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Helpers.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Helpers.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Helpers.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,182 @@ + $v) { + $data[$k] = $v = static::sanitize($itype, $v); + if ($v === NULL) { + unset($data[$k]); + } + } + if ($type & Form::DATA_KEYS) { + return $data; + } + return array_values($data); + } else { + return static::sanitize($itype, $data); + } + } + + + private static function sanitize($type, $value) + { + if ($type === Form::DATA_TEXT) { + return is_scalar($value) ? Strings::normalizeNewLines($value) : NULL; + + } elseif ($type === Form::DATA_LINE) { + return is_scalar($value) ? Strings::trim(strtr($value, "\r\n", ' ')) : NULL; + + } elseif ($type === Form::DATA_FILE) { + return $value instanceof Nette\Http\FileUpload ? $value : NULL; + + } else { + throw new Nette\InvalidArgumentException('Unknown data type'); + } + } + + + /** + * Converts control name to HTML name. + * @return string + */ + public static function generateHtmlName($id) + { + $name = str_replace(Nette\ComponentModel\IComponent::NAME_SEPARATOR, '][', $id, $count); + if ($count) { + $name = substr_replace($name, '', strpos($name, ']'), 1) . ']'; + } + if (is_numeric($name) || in_array($name, self::$unsafeNames, TRUE)) { + $name = '_' . $name; + } + return $name; + } + + + /** + * @return string + */ + public static function createInputList(array $items, array $inputAttrs = NULL, array $labelAttrs = NULL, $wrapper = NULL) + { + list($inputAttrs, $inputTag) = self::prepareAttrs($inputAttrs, 'input'); + list($labelAttrs, $labelTag) = self::prepareAttrs($labelAttrs, 'label'); + $res = ''; + $input = Html::el(); + $label = Html::el(); + list($wrapper, $wrapperEnd) = $wrapper instanceof Html ? array($wrapper->startTag(), $wrapper->endTag()) : array((string) $wrapper, ''); + + foreach ($items as $value => $caption) { + foreach ($inputAttrs as $k => $v) { + $input->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL; + } + foreach ($labelAttrs as $k => $v) { + $label->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL; + } + $input->value = $value; + $res .= ($res === '' && $wrapperEnd === '' ? '' : $wrapper) + . $labelTag . $label->attributes() . '>' + . $inputTag . $input->attributes() . (Html::$xhtml ? ' />' : '>') + . ($caption instanceof Html ? $caption : htmlspecialchars($caption)) + . '' + . $wrapperEnd; + } + return $res; + } + + + /** + * @return Nette\Utils\Html + */ + public static function createSelectBox(array $items, array $optionAttrs = NULL) + { + list($optionAttrs, $optionTag) = self::prepareAttrs($optionAttrs, 'option'); + $option = Html::el(); + $res = $tmp = ''; + foreach ($items as $group => $subitems) { + if (is_array($subitems)) { + $res .= Html::el('optgroup')->label($group)->startTag(); + $tmp = ''; + } else { + $subitems = array($group => $subitems); + } + foreach ($subitems as $value => $caption) { + $option->value = $value; + foreach ($optionAttrs as $k => $v) { + $option->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL; + } + if ($caption instanceof Html) { + $caption = clone $caption; + $res .= $caption->setName('option')->addAttributes($option->attrs); + } else { + $res .= $optionTag . $option->attributes() . '>' + . htmlspecialchars($caption) + . ''; + } + } + $res .= $tmp; + $tmp = ''; + } + return Html::el('select')->setHtml($res); + } + + + private static function prepareAttrs($attrs, $name) + { + $dynamic = array(); + foreach ((array) $attrs as $k => $v) { + $p = str_split($k, strlen($k) - 1); + if ($p[1] === '?' || $p[1] === ':') { + unset($attrs[$k], $attrs[$p[0]]); + if ($p[1] === '?') { + $dynamic[$p[0]] = array_fill_keys((array) $v, TRUE); + } elseif (is_array($v) && $v) { + $dynamic[$p[0]] = $v; + } else { + $attrs[$p[0]] = $v; + } + } + } + return array($dynamic, '<' . $name . Html::el(NULL, $attrs)->attributes()); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/IControl.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/IControl.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/IControl.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/IControl.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,59 @@ +getValues() result? + * @return bool + */ + function isOmitted(); + + /** + * Returns translated string. + * @param string + * @param int plural count + * @return string + */ + function translate($s, $count = NULL); + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/IFormRenderer.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/IFormRenderer.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/IFormRenderer.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/IFormRenderer.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,27 @@ + array( + 'container' => NULL, + ), + + 'error' => array( + 'container' => 'ul class=error', + 'item' => 'li', + ), + + 'group' => array( + 'container' => 'fieldset', + 'label' => 'legend', + 'description' => 'p', + ), + + 'controls' => array( + 'container' => 'table', + ), + + 'pair' => array( + 'container' => 'tr', + '.required' => 'required', + '.optional' => NULL, + '.odd' => NULL, + '.error' => NULL, + ), + + 'control' => array( + 'container' => 'td', + '.odd' => NULL, + + 'description' => 'small', + 'requiredsuffix' => '', + 'errorcontainer' => 'span class=error', + 'erroritem' => '', + + '.required' => 'required', + '.text' => 'text', + '.password' => 'text', + '.file' => 'text', + '.submit' => 'button', + '.image' => 'imagebutton', + '.button' => 'button', + ), + + 'label' => array( + 'container' => 'th', + 'suffix' => NULL, + 'requiredsuffix' => '', + ), + + 'hidden' => array( + 'container' => 'div', + ), + ); + + /** @var Nette\Forms\Form */ + protected $form; + + /** @var int */ + protected $counter; + + + /** + * Provides complete form rendering. + * @param Nette\Forms\Form + * @param string 'begin', 'errors', 'ownerrors', 'body', 'end' or empty to render all + * @return string + */ + public function render(Nette\Forms\Form $form, $mode = NULL) + { + if ($this->form !== $form) { + $this->form = $form; + $this->init(); + } + + $s = ''; + if (!$mode || $mode === 'begin') { + $s .= $this->renderBegin(); + } + if (!$mode || strtolower($mode) === 'ownerrors') { + $s .= $this->renderErrors(); + + } elseif ($mode === 'errors') { + $s .= $this->renderErrors(NULL, FALSE); + } + if (!$mode || $mode === 'body') { + $s .= $this->renderBody(); + } + if (!$mode || $mode === 'end') { + $s .= $this->renderEnd(); + } + return $s; + } + + + /** + * Initializes form. + * @return void + */ + protected function init() + { + $wrapper = & $this->wrappers['control']; + foreach ($this->form->getControls() as $control) { + if ($control->isRequired() && isset($wrapper['.required'])) { + $control->getLabelPrototype()->class($wrapper['.required'], TRUE); + } + + $el = $control->getControlPrototype(); + if ($el->getName() === 'input' && isset($wrapper['.' . $el->type])) { + $el->class($wrapper['.' . $el->type], TRUE); + } + } + } + + + /** + * Renders form begin. + * @return string + */ + public function renderBegin() + { + $this->counter = 0; + + foreach ($this->form->getControls() as $control) { + $control->setOption('rendered', FALSE); + } + + if (strcasecmp($this->form->getMethod(), 'get') === 0) { + $el = clone $this->form->getElementPrototype(); + $query = parse_url($el->action, PHP_URL_QUERY); + $el->action = str_replace("?$query", '', $el->action); + $s = ''; + foreach (preg_split('#[;&]#', $query, NULL, PREG_SPLIT_NO_EMPTY) as $param) { + $parts = explode('=', $param, 2); + $name = urldecode($parts[0]); + if (!isset($this->form[$name])) { + $s .= Html::el('input', array('type' => 'hidden', 'name' => $name, 'value' => urldecode($parts[1]))); + } + } + return $el->startTag() . ($s ? "\n\t" . $this->getWrapper('hidden container')->setHtml($s) : ''); + + } else { + return $this->form->getElementPrototype()->startTag(); + } + } + + + /** + * Renders form end. + * @return string + */ + public function renderEnd() + { + $s = ''; + foreach ($this->form->getControls() as $control) { + if ($control instanceof Nette\Forms\Controls\HiddenField && !$control->getOption('rendered')) { + $s .= $control->getControl(); + } + } + if (iterator_count($this->form->getComponents(TRUE, 'Nette\Forms\Controls\TextInput')) < 2) { + $s .= ''; + } + if ($s) { + $s = $this->getWrapper('hidden container')->setHtml($s) . "\n"; + } + + return $s . $this->form->getElementPrototype()->endTag() . "\n"; + } + + + /** + * Renders validation errors (per form or per control). + * @return string + */ + public function renderErrors(Nette\Forms\IControl $control = NULL, $own = TRUE) + { + $errors = $control + ? $control->getErrors() + : ($own ? $this->form->getOwnErrors() : $this->form->getErrors()); + if (!$errors) { + return; + } + $container = $this->getWrapper($control ? 'control errorcontainer' : 'error container'); + $item = $this->getWrapper($control ? 'control erroritem' : 'error item'); + + foreach ($errors as $error) { + $item = clone $item; + if ($error instanceof Html) { + $item->add($error); + } else { + $item->setText($error); + } + $container->add($item); + } + return "\n" . $container->render($control ? 1 : 0); + } + + + /** + * Renders form body. + * @return string + */ + public function renderBody() + { + $s = $remains = ''; + + $defaultContainer = $this->getWrapper('group container'); + $translator = $this->form->getTranslator(); + + foreach ($this->form->getGroups() as $group) { + if (!$group->getControls() || !$group->getOption('visual')) { + continue; + } + + $container = $group->getOption('container', $defaultContainer); + $container = $container instanceof Html ? clone $container : Html::el($container); + + $s .= "\n" . $container->startTag(); + + $text = $group->getOption('label'); + if ($text instanceof Html) { + $s .= $this->getWrapper('group label')->add($text); + + } elseif (is_string($text)) { + if ($translator !== NULL) { + $text = $translator->translate($text); + } + $s .= "\n" . $this->getWrapper('group label')->setText($text) . "\n"; + } + + $text = $group->getOption('description'); + if ($text instanceof Html) { + $s .= $text; + + } elseif (is_string($text)) { + if ($translator !== NULL) { + $text = $translator->translate($text); + } + $s .= $this->getWrapper('group description')->setText($text) . "\n"; + } + + $s .= $this->renderControls($group); + + $remains = $container->endTag() . "\n" . $remains; + if (!$group->getOption('embedNext')) { + $s .= $remains; + $remains = ''; + } + } + + $s .= $remains . $this->renderControls($this->form); + + $container = $this->getWrapper('form container'); + $container->setHtml($s); + return $container->render(0); + } + + + /** + * Renders group of controls. + * @param Nette\Forms\Container|FormGroup + * @return string + */ + public function renderControls($parent) + { + if (!($parent instanceof Nette\Forms\Container || $parent instanceof Nette\Forms\ControlGroup)) { + throw new Nette\InvalidArgumentException('Argument must be FormContainer or FormGroup instance.'); + } + + $container = $this->getWrapper('controls container'); + + $buttons = NULL; + foreach ($parent->getControls() as $control) { + if ($control->getOption('rendered') || $control instanceof Nette\Forms\Controls\HiddenField || $control->getForm(FALSE) !== $this->form) { + // skip + + } elseif ($control instanceof Nette\Forms\Controls\Button) { + $buttons[] = $control; + + } else { + if ($buttons) { + $container->add($this->renderPairMulti($buttons)); + $buttons = NULL; + } + $container->add($this->renderPair($control)); + } + } + + if ($buttons) { + $container->add($this->renderPairMulti($buttons)); + } + + $s = ''; + if (count($container)) { + $s .= "\n" . $container . "\n"; + } + + return $s; + } + + + /** + * Renders single visual row. + * @return string + */ + public function renderPair(Nette\Forms\IControl $control) + { + $pair = $this->getWrapper('pair container'); + $pair->add($this->renderLabel($control)); + $pair->add($this->renderControl($control)); + $pair->class($this->getValue($control->isRequired() ? 'pair .required' : 'pair .optional'), TRUE); + $pair->class($control->hasErrors() ? $this->getValue('pair .error') : NULL, TRUE); + $pair->class($control->getOption('class'), TRUE); + if (++$this->counter % 2) { + $pair->class($this->getValue('pair .odd'), TRUE); + } + $pair->id = $control->getOption('id'); + return $pair->render(0); + } + + + /** + * Renders single visual row of multiple controls. + * @param IFormControl[] + * @return string + */ + public function renderPairMulti(array $controls) + { + $s = array(); + foreach ($controls as $control) { + if (!$control instanceof Nette\Forms\IControl) { + throw new Nette\InvalidArgumentException('Argument must be array of IFormControl instances.'); + } + $description = $control->getOption('description'); + if ($description instanceof Html) { + $description = ' ' . $control->getOption('description'); + + } elseif (is_string($description)) { + $description = ' ' . $this->getWrapper('control description')->setText($control->translate($description)); + + } else { + $description = ''; + } + + $s[] = $control->getControl() . $description; + } + $pair = $this->getWrapper('pair container'); + $pair->add($this->renderLabel($control)); + $pair->add($this->getWrapper('control container')->setHtml(implode(' ', $s))); + return $pair->render(0); + } + + + /** + * Renders 'label' part of visual row of controls. + * @return string + */ + public function renderLabel(Nette\Forms\IControl $control) + { + $suffix = $this->getValue('label suffix') . ($control->isRequired() ? $this->getValue('label requiredsuffix') : ''); + $label = $control->getLabel(); + if ($label instanceof Html) { + $label->add($suffix); + } elseif ($label != NULL) { // @intentionally == + $label .= $suffix; + } + return $this->getWrapper('label container')->setHtml($label); + } + + + /** + * Renders 'control' part of visual row of controls. + * @return string + */ + public function renderControl(Nette\Forms\IControl $control) + { + $body = $this->getWrapper('control container'); + if ($this->counter % 2) { + $body->class($this->getValue('control .odd'), TRUE); + } + + $description = $control->getOption('description'); + if ($description instanceof Html) { + $description = ' ' . $description; + + } elseif (is_string($description)) { + $description = ' ' . $this->getWrapper('control description')->setText($control->translate($description)); + + } else { + $description = ''; + } + + if ($control->isRequired()) { + $description = $this->getValue('control requiredsuffix') . $description; + } + + $el = $control->getControl(); + return $body->setHtml($el . $description . $this->renderErrors($control)); + } + + + /** + * @param string + * @return Nette\Utils\Html + */ + protected function getWrapper($name) + { + $data = $this->getValue($name); + return $data instanceof Html ? clone $data : Html::el($data); + } + + + /** + * @param string + * @return string + */ + protected function getValue($name) + { + $name = explode(' ', $name); + $data = & $this->wrappers[$name[0]][$name[1]]; + return $data; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Rule.php php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Rule.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Forms/Rule.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Forms/Rule.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,47 @@ + 'Please submit this form again (security token has expired).', + Form::EQUAL => 'Please enter %s.', + Form::NOT_EQUAL => 'This value should not be %s.', + Form::FILLED => 'This field is required.', + Form::BLANK => 'This field should be blank.', + Form::MIN_LENGTH => 'Please enter at least %d characters.', + Form::MAX_LENGTH => 'Please enter no more than %d characters.', + Form::LENGTH => 'Please enter a value between %d and %d characters long.', + Form::EMAIL => 'Please enter a valid email address.', + Form::URL => 'Please enter a valid URL.', + Form::INTEGER => 'Please enter a valid integer.', + Form::FLOAT => 'Please enter a valid number.', + Form::RANGE => 'Please enter a value between %d and %d.', + Form::MAX_FILE_SIZE => 'The size of the uploaded file can be up to %d bytes.', + Form::MAX_POST_SIZE => 'The uploaded data exceeds the limit of %d bytes.', + Form::IMAGE => 'The uploaded file must be image in format JPEG, GIF or PNG.', + Form::MIME_TYPE => 'The uploaded file is not in the expected format.', + Nette\Forms\Controls\SelectBox::VALID => 'Please select a valid option.', + ); + + /** @var Rule */ + private $required; + + /** @var Rule[] */ + private $rules = array(); + + /** @var Rules */ + private $parent; + + /** @var array */ + private $toggles = array(); + + /** @var IControl */ + private $control; + + + public function __construct(IControl $control) + { + $this->control = $control; + } + + + /** + * Makes control mandatory. + * @param mixed state or error message + * @return self + */ + public function setRequired($value = TRUE) + { + if ($value) { + $this->addRule(Form::REQUIRED, is_string($value) ? $value : NULL); + } else { + $this->required = NULL; + } + return $this; + } + + + /** + * Is control mandatory? + * @return bool + */ + public function isRequired() + { + return $this->required instanceof Rule ? !$this->required->isNegative : FALSE; + } + + + /** + * Adds a validation rule for the current control. + * @param mixed rule type + * @param string message to display for invalid data + * @param mixed optional rule arguments + * @return self + */ + public function addRule($operation, $message = NULL, $arg = NULL) + { + $rule = new Rule; + $rule->control = $this->control; + $rule->operation = $operation; + $this->adjustOperation($rule); + $rule->arg = $arg; + $rule->type = Rule::VALIDATOR; + $rule->message = $message; + if ($rule->operation === Form::REQUIRED) { + $this->required = $rule; + } else { + $this->rules[] = $rule; + } + return $this; + } + + + /** + * Adds a validation condition a returns new branch. + * @param mixed condition type + * @param mixed optional condition arguments + * @return Rules new branch + */ + public function addCondition($operation, $arg = NULL) + { + return $this->addConditionOn($this->control, $operation, $arg); + } + + + /** + * Adds a validation condition on specified control a returns new branch. + * @param IControl form control + * @param mixed condition type + * @param mixed optional condition arguments + * @return Rules new branch + */ + public function addConditionOn(IControl $control, $operation, $arg = NULL) + { + $rule = new Rule; + $rule->control = $control; + $rule->operation = $operation; + $this->adjustOperation($rule); + $rule->arg = $arg; + $rule->type = Rule::CONDITION; + $rule->subRules = new static($this->control); + $rule->subRules->parent = $this; + + $this->rules[] = $rule; + return $rule->subRules; + } + + + /** + * Adds a else statement. + * @return Rules else branch + */ + public function elseCondition() + { + $rule = clone end($this->parent->rules); + $rule->isNegative = !$rule->isNegative; + $rule->subRules = new static($this->parent->control); + $rule->subRules->parent = $this->parent; + $this->parent->rules[] = $rule; + return $rule->subRules; + } + + + /** + * Ends current validation condition. + * @return Rules parent branch + */ + public function endCondition() + { + return $this->parent; + } + + + /** + * Toggles HTML element visibility. + * @param string element id + * @param bool hide element? + * @return self + */ + public function toggle($id, $hide = TRUE) + { + $this->toggles[$id] = $hide; + return $this; + } + + + /** + * @param bool + * @return array + */ + public function getToggles($actual = FALSE) + { + return $actual ? $this->getToggleStates() : $this->toggles; + } + + + /** + * @internal + * @return array + */ + public function getToggleStates($toggles = array(), $success = TRUE) + { + foreach ($this->toggles as $id => $hide) { + $toggles[$id] = ($success xor !$hide) || !empty($toggles[$id]); + } + + foreach ($this as $rule) { + if ($rule->type === Rule::CONDITION) { + $toggles = $rule->subRules->getToggleStates($toggles, $success && static::validateRule($rule)); + } + } + return $toggles; + } + + + /** + * Validates against ruleset. + * @return bool + */ + public function validate() + { + foreach ($this as $rule) { + $success = $this->validateRule($rule); + + if ($rule->type === Rule::CONDITION && $success && !$rule->subRules->validate()) { + return FALSE; + + } elseif ($rule->type === Rule::VALIDATOR && !$success) { + $rule->control->addError(static::formatMessage($rule, TRUE)); + return FALSE; + } + } + return TRUE; + } + + + /** + * Validates single rule. + * @return bool + */ + public static function validateRule(Rule $rule) + { + $args = is_array($rule->arg) ? $rule->arg : array($rule->arg); + foreach ($args as & $val) { + $val = $val instanceof IControl ? $val->getValue() : $val; + } + return $rule->isNegative + xor call_user_func(self::getCallback($rule), $rule->control, is_array($rule->arg) ? $args : $args[0]); + } + + + /** + * Iterates over complete ruleset. + * @return \ArrayIterator + */ + public function getIterator() + { + $rules = $this->rules; + if ($this->required) { + array_unshift($rules, $this->required); + } + return new \ArrayIterator($rules); + } + + + /** + * Process 'operation' string. + * @param Rule + * @return void + */ + private function adjustOperation($rule) + { + if (is_string($rule->operation) && ord($rule->operation[0]) > 127) { + $rule->isNegative = TRUE; + $rule->operation = ~$rule->operation; + } + + if (!is_callable($this->getCallback($rule))) { + $operation = is_scalar($rule->operation) ? " '$rule->operation'" : ''; + throw new Nette\InvalidArgumentException("Unknown operation$operation for control '{$rule->control->name}'."); + } + } + + + private static function getCallback($rule) + { + $op = $rule->operation; + if (is_string($op) && strncmp($op, ':', 1) === 0) { + return get_class($rule->control) . '::' . self::VALIDATE_PREFIX . ltrim($op, ':'); + } else { + return $op; + } + } + + + public static function formatMessage($rule, $withValue) + { + $message = $rule->message; + if ($message instanceof Nette\Utils\Html) { + return $message; + + } elseif ($message === NULL && is_string($rule->operation) && isset(self::$defaultMessages[$rule->operation])) { + $message = self::$defaultMessages[$rule->operation]; + + } elseif ($message == NULL) { // intentionally == + trigger_error("Missing validation message for control '{$rule->control->name}'.", E_USER_WARNING); + } + + if ($translator = $rule->control->getForm()->getTranslator()) { + $message = $translator->translate($message, is_int($rule->arg) ? $rule->arg : NULL); + } + + $message = preg_replace_callback('#%(name|label|value|\d+\$[ds]|[ds])#', function($m) use ($rule, $withValue) { + static $i = -1; + switch ($m[1]) { + case 'name': return $rule->control->getName(); + case 'label': return $rule->control->translate($rule->control->caption); + case 'value': return $withValue ? $rule->control->getValue() : $m[0]; + default: + $args = is_array($rule->arg) ? $rule->arg : array($rule->arg); + $i = (int) $m[1] ? $m[1] - 1 : $i + 1; + return isset($args[$i]) ? ($args[$i] instanceof IControl ? ($withValue ? $args[$i]->getValue() : "%$i") : $args[$i]) : ''; + } + }, $message); + return $message; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/Context.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/Context.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/Context.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/Context.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,105 @@ +request = $request; + $this->response = $response; + } + + + /** + * Attempts to cache the sent entity by its last modification date. + * @param string|int|DateTime last modified time + * @param string strong entity tag validator + * @return bool + */ + public function isModified($lastModified = NULL, $etag = NULL) + { + if ($lastModified) { + $this->response->setHeader('Last-Modified', $this->response->date($lastModified)); + } + if ($etag) { + $this->response->setHeader('ETag', '"' . addslashes($etag) . '"'); + } + + $ifNoneMatch = $this->request->getHeader('If-None-Match'); + if ($ifNoneMatch === '*') { + $match = TRUE; // match, check if-modified-since + + } elseif ($ifNoneMatch !== NULL) { + $etag = $this->response->getHeader('ETag'); + + if ($etag == NULL || strpos(' ' . strtr($ifNoneMatch, ",\t", ' '), ' ' . $etag) === FALSE) { + return TRUE; + + } else { + $match = TRUE; // match, check if-modified-since + } + } + + $ifModifiedSince = $this->request->getHeader('If-Modified-Since'); + if ($ifModifiedSince !== NULL) { + $lastModified = $this->response->getHeader('Last-Modified'); + if ($lastModified != NULL && strtotime($lastModified) <= strtotime($ifModifiedSince)) { + $match = TRUE; + + } else { + return TRUE; + } + } + + if (empty($match)) { + return TRUE; + } + + $this->response->setCode(IResponse::S304_NOT_MODIFIED); + return FALSE; + } + + + /** + * @return IRequest + */ + public function getRequest() + { + return $this->request; + } + + + /** + * @return IResponse + */ + public function getResponse() + { + return $this->response; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/Diagnostics/SessionPanel.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/Diagnostics/SessionPanel.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/Diagnostics/SessionPanel.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/Diagnostics/SessionPanel.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,44 @@ + + + +
+

Session # (Lifetime: )

+ +
+ +

empty

+ + + $v) { + if ($k === '__NF') { + $k = 'Nette Session'; $v = isset($v['DATA']) ? $v['DATA'] : NULL; + } + echo '\n"; + }?> +
', htmlspecialchars($k), '', Nette\Diagnostics\Dumper::toHtml($v), "
+ +
+
diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml php-nette-2.1.5/Nette-2.1.5/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,9 @@ + +Session diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/FileUpload.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/FileUpload.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/FileUpload.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/FileUpload.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,203 @@ +error = UPLOAD_ERR_NO_FILE; + return; // or throw exception? + } + } + $this->name = $value['name']; + $this->size = $value['size']; + $this->tmpName = $value['tmp_name']; + $this->error = $value['error']; + } + + + /** + * Returns the file name. + * @return string + */ + public function getName() + { + return $this->name; + } + + + /** + * Returns the sanitized file name. + * @return string + */ + public function getSanitizedName() + { + return trim(Nette\Utils\Strings::webalize($this->name, '.', FALSE), '.-'); + } + + + /** + * Returns the MIME content type of an uploaded file. + * @return string + */ + public function getContentType() + { + if ($this->isOk() && $this->type === NULL) { + $this->type = Nette\Utils\MimeTypeDetector::fromFile($this->tmpName); + } + return $this->type; + } + + + /** + * Returns the size of an uploaded file. + * @return int + */ + public function getSize() + { + return $this->size; + } + + + /** + * Returns the path to an uploaded file. + * @return string + */ + public function getTemporaryFile() + { + return $this->tmpName; + } + + + /** + * Returns the path to an uploaded file. + * @return string + */ + public function __toString() + { + return (string) $this->tmpName; + } + + + /** + * Returns the error code. {@link http://php.net/manual/en/features.file-upload.errors.php} + * @return int + */ + public function getError() + { + return $this->error; + } + + + /** + * Is there any error? + * @return bool + */ + public function isOk() + { + return $this->error === UPLOAD_ERR_OK; + } + + + /** + * Move uploaded file to new location. + * @param string + * @return self + */ + public function move($dest) + { + @mkdir(dirname($dest), 0777, TRUE); // @ - dir may already exist + @unlink($dest); // @ - file may not exists + if (!call_user_func(is_uploaded_file($this->tmpName) ? 'move_uploaded_file' : 'rename', $this->tmpName, $dest)) { + throw new Nette\InvalidStateException("Unable to move uploaded file '$this->tmpName' to '$dest'."); + } + chmod($dest, 0666); + $this->tmpName = $dest; + return $this; + } + + + /** + * Is uploaded file GIF, PNG or JPEG? + * @return bool + */ + public function isImage() + { + return in_array($this->getContentType(), array('image/gif', 'image/png', 'image/jpeg'), TRUE); + } + + + /** + * Returns the image. + * @return Nette\Image + */ + public function toImage() + { + return Nette\Image::fromFile($this->tmpName); + } + + + /** + * Returns the dimensions of an uploaded image as array. + * @return array + */ + public function getImageSize() + { + return $this->isOk() ? @getimagesize($this->tmpName) : NULL; // @ - files smaller than 12 bytes causes read error + } + + + /** + * Get file contents. + * @return string + */ + public function getContents() + { + // future implementation can try to work around safe_mode and open_basedir limitations + return $this->isOk() ? file_get_contents($this->tmpName) : NULL; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/Helpers.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/Helpers.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/Helpers.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/Helpers.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,44 @@ + $max) { + return FALSE; + } elseif ($ipv4) { + $arr = array(ip2long($ip), ip2long($mask)); + } else { + $arr = unpack('N*', inet_pton($ip) . inet_pton($mask)); + $size = $size === '' ? 0 : $max - $size; + } + $bits = implode('', array_map(function ($n) { + return sprintf('%032b', $n); + }, $arr)); + return substr($bits, 0, $max - $size) === substr($bits, $max, $max - $size); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/IRequest.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/IRequest.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/IRequest.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/IRequest.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,135 @@ + array('#/{2,}#' => '/'), // '%20' => '' + 'url' => array(), // '#[.,)]\z#' => '' + ); + + /** @var bool */ + private $binary = FALSE; + + /** @var array */ + private $proxies = array(); + + + /** + * @param bool + * @return self + */ + public function setBinary($binary = TRUE) + { + $this->binary = (bool) $binary; + return $this; + } + + + /** + * @param array|string + * @return self + */ + public function setProxy($proxy) + { + $this->proxies = (array) $proxy; + return $this; + } + + + /** + * Creates current HttpRequest object. + * @return Request + */ + public function createHttpRequest() + { + // DETECTS URI, base path and script path of the request. + $url = new UrlScript; + $url->scheme = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https' : 'http'; + $url->user = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''; + $url->password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; + + // host & port + if ((isset($_SERVER[$tmp = 'HTTP_HOST']) || isset($_SERVER[$tmp = 'SERVER_NAME'])) + && preg_match('#^([a-z0-9_.-]+|\[[a-f0-9:]+\])(:\d+)?\z#i', $_SERVER[$tmp], $pair) + ) { + $url->host = strtolower($pair[1]); + if (isset($pair[2])) { + $url->port = (int) substr($pair[2], 1); + } elseif (isset($_SERVER['SERVER_PORT'])) { + $url->port = (int) $_SERVER['SERVER_PORT']; + } + } + + // path & query + if (isset($_SERVER['REQUEST_URI'])) { // Apache, IIS 6.0 + $requestUrl = $_SERVER['REQUEST_URI']; + + } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0 (PHP as CGI ?) + $requestUrl = $_SERVER['ORIG_PATH_INFO']; + if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '') { + $requestUrl .= '?' . $_SERVER['QUERY_STRING']; + } + } else { + $requestUrl = ''; + } + + $requestUrl = Strings::replace($requestUrl, $this->urlFilters['url']); + $tmp = explode('?', $requestUrl, 2); + $url->path = Strings::replace($tmp[0], $this->urlFilters['path']); + $url->query = isset($tmp[1]) ? $tmp[1] : ''; + + // normalized url + $url->canonicalize(); + $url->path = Strings::fixEncoding($url->path); + + // detect script path + if (isset($_SERVER['SCRIPT_NAME'])) { + $script = $_SERVER['SCRIPT_NAME']; + } elseif (isset($_SERVER['DOCUMENT_ROOT'], $_SERVER['SCRIPT_FILENAME']) + && strncmp($_SERVER['DOCUMENT_ROOT'], $_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])) === 0 + ) { + $script = '/' . ltrim(strtr(substr($_SERVER['SCRIPT_FILENAME'], strlen($_SERVER['DOCUMENT_ROOT'])), '\\', '/'), '/'); + } else { + $script = '/'; + } + + $path = strtolower($url->path) . '/'; + $script = strtolower($script) . '/'; + $max = min(strlen($path), strlen($script)); + for ($i = 0; $i < $max; $i++) { + if ($path[$i] !== $script[$i]) { + break; + } elseif ($path[$i] === '/') { + $url->scriptPath = substr($url->path, 0, $i + 1); + } + } + + // GET, POST, COOKIE + $useFilter = (!in_array(ini_get('filter.default'), array('', 'unsafe_raw'), TRUE) || ini_get('filter.default_flags')); + + parse_str($url->query, $query); + if (!$query) { + $query = $useFilter ? filter_input_array(INPUT_GET, FILTER_UNSAFE_RAW) : (empty($_GET) ? array() : $_GET); + } + $post = $useFilter ? filter_input_array(INPUT_POST, FILTER_UNSAFE_RAW) : (empty($_POST) ? array() : $_POST); + $cookies = $useFilter ? filter_input_array(INPUT_COOKIE, FILTER_UNSAFE_RAW) : (empty($_COOKIE) ? array() : $_COOKIE); + + $gpc = (bool) get_magic_quotes_gpc(); + + // remove fucking quotes, control characters and check encoding + if ($gpc || !$this->binary) { + $list = array(& $query, & $post, & $cookies); + while (list($key, $val) = each($list)) { + foreach ($val as $k => $v) { + unset($list[$key][$k]); + + if ($gpc) { + $k = stripslashes($k); + } + + if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) { + // invalid key -> ignore + + } elseif (is_array($v)) { + $list[$key][$k] = $v; + $list[] = & $list[$key][$k]; + + } else { + if ($gpc && !$useFilter) { + $v = stripSlashes($v); + } + if (!$this->binary && (preg_match(self::NONCHARS, $v) || preg_last_error())) { + $v = ''; + } + $list[$key][$k] = $v; + } + } + } + unset($list, $key, $val, $k, $v); + } + + + // FILES and create FileUpload objects + $files = array(); + $list = array(); + if (!empty($_FILES)) { + foreach ($_FILES as $k => $v) { + if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) { + continue; + } + $v['@'] = & $files[$k]; + $list[] = $v; + } + } + + while (list(, $v) = each($list)) { + if (!isset($v['name'])) { + continue; + + } elseif (!is_array($v['name'])) { + if ($gpc) { + $v['name'] = stripSlashes($v['name']); + } + if (!$this->binary && (preg_match(self::NONCHARS, $v['name']) || preg_last_error())) { + $v['name'] = ''; + } + if ($v['error'] !== UPLOAD_ERR_NO_FILE) { + $v['@'] = new FileUpload($v); + } + continue; + } + + foreach ($v['name'] as $k => $foo) { + if (!$this->binary && is_string($k) && (preg_match(self::NONCHARS, $k) || preg_last_error())) { + continue; + } + $list[] = array( + 'name' => $v['name'][$k], + 'type' => $v['type'][$k], + 'size' => $v['size'][$k], + 'tmp_name' => $v['tmp_name'][$k], + 'error' => $v['error'][$k], + '@' => & $v['@'][$k], + ); + } + } + + + // HEADERS + if (function_exists('apache_request_headers')) { + $headers = array_change_key_case(apache_request_headers(), CASE_LOWER); + } else { + $headers = array(); + foreach ($_SERVER as $k => $v) { + if (strncmp($k, 'HTTP_', 5) == 0) { + $k = substr($k, 5); + } elseif (strncmp($k, 'CONTENT_', 8)) { + continue; + } + $headers[ strtr(strtolower($k), '_', '-') ] = $v; + } + } + + + $remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL; + $remoteHost = isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : NULL; + + // proxy + foreach ($this->proxies as $proxy) { + if (Helpers::ipMatch($remoteAddr, $proxy)) { + if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $remoteAddr = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']))); + } + if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { + $remoteHost = trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']))); + } + break; + } + } + + + $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL; + if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) + && preg_match('#^[A-Z]+\z#', $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) + ) { + $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']; + } + + return new Request($url, $query, $post, $files, $cookies, $headers, $method, $remoteAddr, $remoteHost); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/Request.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/Request.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/Request.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/Request.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,334 @@ +url = $url; + if ($query === NULL) { + parse_str($url->query, $this->query); + } else { + $this->query = (array) $query; + } + $this->post = (array) $post; + $this->files = (array) $files; + $this->cookies = (array) $cookies; + $this->headers = (array) $headers; + $this->method = $method; + $this->remoteAddress = $remoteAddress; + $this->remoteHost = $remoteHost; + } + + + /** + * Returns URL object. + * @return UrlScript + */ + public function getUrl() + { + return $this->url; + } + + + /********************* query, post, files & cookies ****************d*g**/ + + + /** + * Returns variable provided to the script via URL query ($_GET). + * If no key is passed, returns the entire array. + * @param string key + * @param mixed default value + * @return mixed + */ + public function getQuery($key = NULL, $default = NULL) + { + if (func_num_args() === 0) { + return $this->query; + + } elseif (isset($this->query[$key])) { + return $this->query[$key]; + + } else { + return $default; + } + } + + + /** + * Returns variable provided to the script via POST method ($_POST). + * If no key is passed, returns the entire array. + * @param string key + * @param mixed default value + * @return mixed + */ + public function getPost($key = NULL, $default = NULL) + { + if (func_num_args() === 0) { + return $this->post; + + } elseif (isset($this->post[$key])) { + return $this->post[$key]; + + } else { + return $default; + } + } + + + /** + * Returns uploaded file. + * @param string key (or more keys) + * @return FileUpload + */ + public function getFile($key) + { + return Nette\Utils\Arrays::get($this->files, func_get_args(), NULL); + } + + + /** + * Returns uploaded files. + * @return array + */ + public function getFiles() + { + return $this->files; + } + + + /** + * Returns variable provided to the script via HTTP cookies. + * @param string key + * @param mixed default value + * @return mixed + */ + public function getCookie($key, $default = NULL) + { + if (func_num_args() === 0) { + return $this->cookies; + + } elseif (isset($this->cookies[$key])) { + return $this->cookies[$key]; + + } else { + return $default; + } + } + + + /** + * Returns variables provided to the script via HTTP cookies. + * @return array + */ + public function getCookies() + { + return $this->cookies; + } + + + /********************* method & headers ****************d*g**/ + + + /** + * Returns HTTP request method (GET, POST, HEAD, PUT, ...). The method is case-sensitive. + * @return string + */ + public function getMethod() + { + return $this->method; + } + + + /** + * Checks if the request method is the given one. + * @param string + * @return bool + */ + public function isMethod($method) + { + return strcasecmp($this->method, $method) === 0; + } + + + /** + * Checks if the request method is POST. + * @return bool + */ + public function isPost() + { + return $this->isMethod('POST'); + } + + + /** + * Return the value of the HTTP header. Pass the header name as the + * plain, HTTP-specified header name (e.g. 'Accept-Encoding'). + * @param string + * @param mixed + * @return mixed + */ + public function getHeader($header, $default = NULL) + { + $header = strtolower($header); + if (isset($this->headers[$header])) { + return $this->headers[$header]; + } else { + return $default; + } + } + + + /** + * Returns all HTTP headers. + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + + /** + * Returns referrer. + * @return Url|NULL + */ + public function getReferer() + { + return isset($this->headers['referer']) ? new Url($this->headers['referer']) : NULL; + } + + + /** + * Is the request is sent via secure channel (https). + * @return bool + */ + public function isSecured() + { + return $this->url->scheme === 'https'; + } + + + /** + * Is AJAX request? + * @return bool + */ + public function isAjax() + { + return $this->getHeader('X-Requested-With') === 'XMLHttpRequest'; + } + + + /** + * Returns the IP address of the remote client. + * @return string + */ + public function getRemoteAddress() + { + return $this->remoteAddress; + } + + + /** + * Returns the host of the remote client. + * @return string + */ + public function getRemoteHost() + { + if (!$this->remoteHost) { + $this->remoteHost = $this->remoteAddress ? getHostByAddr($this->remoteAddress) : NULL; + } + return $this->remoteHost; + } + + + /** + * Parse Accept-Language header and returns prefered language. + * @param array Supported languages + * @return string|null + */ + public function detectLanguage(array $langs) + { + $header = $this->getHeader('Accept-Language'); + if (!$header) { + return NULL; + } + + $s = strtolower($header); // case insensitive + $s = strtr($s, '_', '-'); // cs_CZ means cs-CZ + rsort($langs); // first more specific + preg_match_all('#(' . implode('|', $langs) . ')(?:-[^\s,;=]+)?\s*(?:;\s*q=([0-9.]+))?#', $s, $matches); + + if (!$matches[0]) { + return NULL; + } + + $max = 0; + $lang = NULL; + foreach ($matches[1] as $key => $value) { + $q = $matches[2][$key] === '' ? 1.0 : (float) $matches[2][$key]; + if ($q > $max) { + $max = $q; $lang = $value; + } + } + + return $lang; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/Response.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/Response.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/Response.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/Response.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,323 @@ += 50400) { + if (is_int(http_response_code())) { + $this->code = http_response_code(); + } + header_register_callback($this->removeDuplicateCookies); + } + } + + + /** + * Sets HTTP response code. + * @param int + * @return self + * @throws Nette\InvalidArgumentException if code is invalid + * @throws Nette\InvalidStateException if HTTP headers have been sent + */ + public function setCode($code) + { + $code = (int) $code; + if ($code < 100 || $code > 599) { + throw new Nette\InvalidArgumentException("Bad HTTP response '$code'."); + } + self::checkHeaders(); + $this->code = $code; + $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; + header($protocol . ' ' . $code, TRUE, $code); + return $this; + } + + + /** + * Returns HTTP response code. + * @return int + */ + public function getCode() + { + return $this->code; + } + + + /** + * Sends a HTTP header and replaces a previous one. + * @param string header name + * @param string header value + * @return self + * @throws Nette\InvalidStateException if HTTP headers have been sent + */ + public function setHeader($name, $value) + { + self::checkHeaders(); + if ($value === NULL) { + header_remove($name); + } elseif (strcasecmp($name, 'Content-Length') === 0 && ini_get('zlib.output_compression')) { + // ignore, PHP bug #44164 + } else { + header($name . ': ' . $value, TRUE, $this->code); + } + return $this; + } + + + /** + * Adds HTTP header. + * @param string header name + * @param string header value + * @return self + * @throws Nette\InvalidStateException if HTTP headers have been sent + */ + public function addHeader($name, $value) + { + self::checkHeaders(); + header($name . ': ' . $value, FALSE, $this->code); + return $this; + } + + + /** + * Sends a Content-type HTTP header. + * @param string mime-type + * @param string charset + * @return self + * @throws Nette\InvalidStateException if HTTP headers have been sent + */ + public function setContentType($type, $charset = NULL) + { + $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : '')); + return $this; + } + + + /** + * Redirects to a new URL. Note: call exit() after it. + * @param string URL + * @param int HTTP code + * @return void + * @throws Nette\InvalidStateException if HTTP headers have been sent + */ + public function redirect($url, $code = self::S302_FOUND) + { + $this->setCode($code); + $this->setHeader('Location', $url); + echo "

Redirect

\n\n

Please click here to continue.

"; + } + + + /** + * Sets the number of seconds before a page cached on a browser expires. + * @param string|int|DateTime time, value 0 means "until the browser is closed" + * @return self + * @throws Nette\InvalidStateException if HTTP headers have been sent + */ + public function setExpiration($time) + { + if (!$time) { // no cache + $this->setHeader('Cache-Control', 's-maxage=0, max-age=0, must-revalidate'); + $this->setHeader('Expires', 'Mon, 23 Jan 1978 10:00:00 GMT'); + return $this; + } + + $time = Nette\DateTime::from($time); + $this->setHeader('Cache-Control', 'max-age=' . ($time->format('U') - time())); + $this->setHeader('Expires', self::date($time)); + return $this; + } + + + /** + * Checks if headers have been sent. + * @return bool + */ + public function isSent() + { + return headers_sent(); + } + + + /** + * Return the value of the HTTP header. + * @param string + * @param mixed + * @return mixed + */ + public function getHeader($header, $default = NULL) + { + $header .= ':'; + $len = strlen($header); + foreach (headers_list() as $item) { + if (strncasecmp($item, $header, $len) === 0) { + return ltrim(substr($item, $len)); + } + } + return $default; + } + + + /** + * Returns a list of headers to sent. + * @return array + */ + public function getHeaders() + { + $headers = array(); + foreach (headers_list() as $header) { + $a = strpos($header, ':'); + $headers[substr($header, 0, $a)] = (string) substr($header, $a + 2); + } + return $headers; + } + + + /** + * Returns HTTP valid date format. + * @param string|int|DateTime + * @return string + */ + public static function date($time = NULL) + { + $time = Nette\DateTime::from($time); + $time->setTimezone(new \DateTimeZone('GMT')); + return $time->format('D, d M Y H:i:s \G\M\T'); + } + + + /** + * @return void + */ + public function __destruct() + { + if (self::$fixIE && isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE ') !== FALSE + && in_array($this->code, array(400, 403, 404, 405, 406, 408, 409, 410, 500, 501, 505), TRUE) + && preg_match('#^text/html(?:;|$)#', $this->getHeader('Content-Type', 'text/html')) + ) { + echo Nette\Utils\Strings::random(2e3, " \t\r\n"); // sends invisible garbage for IE + self::$fixIE = FALSE; + } + } + + + /** + * Sends a cookie. + * @param string name of the cookie + * @param string value + * @param string|int|DateTime expiration time, value 0 means "until the browser is closed" + * @param string + * @param string + * @param bool + * @param bool + * @return self + * @throws Nette\InvalidStateException if HTTP headers have been sent + */ + public function setCookie($name, $value, $time, $path = NULL, $domain = NULL, $secure = NULL, $httpOnly = NULL) + { + self::checkHeaders(); + setcookie( + $name, + $value, + $time ? Nette\DateTime::from($time)->format('U') : 0, + $path === NULL ? $this->cookiePath : (string) $path, + $domain === NULL ? $this->cookieDomain : (string) $domain, + $secure === NULL ? $this->cookieSecure : (bool) $secure, + $httpOnly === NULL ? $this->cookieHttpOnly : (bool) $httpOnly + ); + $this->removeDuplicateCookies(); + return $this; + } + + + /** + * Deletes a cookie. + * @param string name of the cookie. + * @param string + * @param string + * @param bool + * @return void + * @throws Nette\InvalidStateException if HTTP headers have been sent + */ + public function deleteCookie($name, $path = NULL, $domain = NULL, $secure = NULL) + { + $this->setCookie($name, FALSE, 0, $path, $domain, $secure); + } + + + /** + * Removes duplicate cookies from response. + * @return void + * @internal + */ + public function removeDuplicateCookies() + { + if (headers_sent($file, $line) || ini_get('suhosin.cookie.encrypt')) { + return; + } + + $flatten = array(); + foreach (headers_list() as $header) { + if (preg_match('#^Set-Cookie: .+?=#', $header, $m)) { + $flatten[$m[0]] = $header; + header_remove('Set-Cookie'); + } + } + foreach (array_values($flatten) as $key => $header) { + header($header, $key === 0); + } + } + + + private function checkHeaders() + { + if (headers_sent($file, $line)) { + throw new Nette\InvalidStateException('Cannot send header after HTTP headers have been sent' . ($file ? " (output started at $file:$line)." : '.')); + } elseif ($this->warnOnBuffer && ob_get_length() && !array_filter(ob_get_status(TRUE), function($i) { return !$i['chunk_size']; })) { + trigger_error('Possible problem: you are sending a HTTP header while already having some data in output buffer. Try OutputDebugger or start session earlier.', E_USER_NOTICE); + } + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/Session.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/Session.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/Session.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/Session.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,553 @@ + '', // must be disabled because PHP implementation is invalid + 'use_cookies' => 1, // must be enabled to prevent Session Hijacking and Fixation + 'use_only_cookies' => 1, // must be enabled to prevent Session Fixation + 'use_trans_sid' => 0, // must be disabled to prevent Session Hijacking and Fixation + + // cookies + 'cookie_lifetime' => 0, // until the browser is closed + 'cookie_path' => '/', // cookie is available within the entire domain + 'cookie_domain' => '', // cookie is available on current subdomain only + 'cookie_secure' => FALSE, // cookie is available on HTTP & HTTPS + 'cookie_httponly' => TRUE,// must be enabled to prevent Session Hijacking + + // other + 'gc_maxlifetime' => self::DEFAULT_FILE_LIFETIME,// 3 hours + 'cache_limiter' => NULL, // (default "nocache", special value "\0") + 'cache_expire' => NULL, // (default "180") + 'hash_function' => NULL, // (default "0", means MD5) + 'hash_bits_per_character' => NULL, // (default "4") + ); + + /** @var IRequest */ + private $request; + + /** @var IResponse */ + private $response; + + + public function __construct(IRequest $request, IResponse $response) + { + $this->request = $request; + $this->response = $response; + } + + + /** + * Starts and initializes session data. + * @throws Nette\InvalidStateException + * @return void + */ + public function start() + { + if (self::$started) { + return; + } + + $this->configure($this->options); + + $id = & $_COOKIE[session_name()]; + if (!is_string($id) || !preg_match('#^[0-9a-zA-Z,-]{22,128}\z#i', $id)) { + unset($_COOKIE[session_name()]); + } + + // session_start returns FALSE on failure only sometimes + Nette\Utils\Callback::invokeSafe('session_start', array(), function($message) use (& $error) { + $error = $message; + }); + + $this->response->removeDuplicateCookies(); + if ($error) { + @session_write_close(); // this is needed + throw new Nette\InvalidStateException($error); + } + + self::$started = TRUE; + + /* structure: + __NF: BrowserKey, Data, Meta, Time + DATA: section->variable = data + META: section->variable = Timestamp, Browser, Version + */ + $nf = & $_SESSION['__NF']; + + // regenerate empty session + if (empty($nf['Time'])) { + $nf['Time'] = time(); + $this->regenerated = TRUE; + } + + // browser closing detection + $browserKey = $this->request->getCookie('nette-browser'); + if (!$browserKey) { + $browserKey = Nette\Utils\Strings::random(); + } + $browserClosed = !isset($nf['B']) || $nf['B'] !== $browserKey; + $nf['B'] = $browserKey; + + // resend cookie + $this->sendCookie(); + + // process meta metadata + if (isset($nf['META'])) { + $now = time(); + // expire section variables + foreach ($nf['META'] as $section => $metadata) { + if (is_array($metadata)) { + foreach ($metadata as $variable => $value) { + if ((!empty($value['B']) && $browserClosed) || (!empty($value['T']) && $now > $value['T']) // whenBrowserIsClosed || Time + || (isset($nf['DATA'][$section][$variable]) && is_object($nf['DATA'][$section][$variable]) && (isset($value['V']) ? $value['V'] : NULL) // Version + != Nette\Reflection\ClassType::from($nf['DATA'][$section][$variable])->getAnnotation('serializationVersion')) // intentionally != + ) { + if ($variable === '') { // expire whole section + unset($nf['META'][$section], $nf['DATA'][$section]); + continue 2; + } + unset($nf['META'][$section][$variable], $nf['DATA'][$section][$variable]); + } + } + } + } + } + + if ($this->regenerated) { + $this->regenerated = FALSE; + $this->regenerateId(); + } + + register_shutdown_function(array($this, 'clean')); + } + + + /** + * Has been session started? + * @return bool + */ + public function isStarted() + { + return (bool) self::$started; + } + + + /** + * Ends the current session and store session data. + * @return void + */ + public function close() + { + if (self::$started) { + $this->clean(); + session_write_close(); + self::$started = FALSE; + } + } + + + /** + * Destroys all data registered to a session. + * @return void + */ + public function destroy() + { + if (!self::$started) { + throw new Nette\InvalidStateException('Session is not started.'); + } + + session_destroy(); + $_SESSION = NULL; + self::$started = FALSE; + if (!$this->response->isSent()) { + $params = session_get_cookie_params(); + $this->response->deleteCookie(session_name(), $params['path'], $params['domain'], $params['secure']); + } + } + + + /** + * Does session exists for the current request? + * @return bool + */ + public function exists() + { + return self::$started || $this->request->getCookie($this->getName()) !== NULL; + } + + + /** + * Regenerates the session ID. + * @throws Nette\InvalidStateException + * @return void + */ + public function regenerateId() + { + if (self::$started && !$this->regenerated) { + if (headers_sent($file, $line)) { + throw new Nette\InvalidStateException("Cannot regenerate session ID after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : ".")); + } + session_regenerate_id(TRUE); + session_write_close(); + $backup = $_SESSION; + session_start(); + $_SESSION = $backup; + $this->response->removeDuplicateCookies(); + } + $this->regenerated = TRUE; + } + + + /** + * Returns the current session ID. Don't make dependencies, can be changed for each request. + * @return string + */ + public function getId() + { + return session_id(); + } + + + /** + * Sets the session name to a specified one. + * @param string + * @return self + */ + public function setName($name) + { + if (!is_string($name) || !preg_match('#[^0-9.][^.]*\z#A', $name)) { + throw new Nette\InvalidArgumentException('Session name must be a string and cannot contain dot.'); + } + + session_name($name); + return $this->setOptions(array( + 'name' => $name, + )); + } + + + /** + * Gets the session name. + * @return string + */ + public function getName() + { + return isset($this->options['name']) ? $this->options['name'] : session_name(); + } + + + /********************* sections management ****************d*g**/ + + + /** + * Returns specified session section. + * @param string + * @param string + * @return SessionSection + * @throws Nette\InvalidArgumentException + */ + public function getSection($section, $class = 'Nette\Http\SessionSection') + { + return new $class($this, $section); + } + + + /** + * Checks if a session section exist and is not empty. + * @param string + * @return bool + */ + public function hasSection($section) + { + if ($this->exists() && !self::$started) { + $this->start(); + } + + return !empty($_SESSION['__NF']['DATA'][$section]); + } + + + /** + * Iteration over all sections. + * @return \ArrayIterator + */ + public function getIterator() + { + if ($this->exists() && !self::$started) { + $this->start(); + } + + if (isset($_SESSION['__NF']['DATA'])) { + return new \ArrayIterator(array_keys($_SESSION['__NF']['DATA'])); + + } else { + return new \ArrayIterator; + } + } + + + /** + * Cleans and minimizes meta structures. This method is called automatically on shutdown, do not call it directly. + * @internal + * @return void + */ + public function clean() + { + if (!self::$started || empty($_SESSION)) { + return; + } + + $nf = & $_SESSION['__NF']; + if (isset($nf['META']) && is_array($nf['META'])) { + foreach ($nf['META'] as $name => $foo) { + if (empty($nf['META'][$name])) { + unset($nf['META'][$name]); + } + } + } + + if (empty($nf['META'])) { + unset($nf['META']); + } + + if (empty($nf['DATA'])) { + unset($nf['DATA']); + } + } + + + /********************* configuration ****************d*g**/ + + + /** + * Sets session options. + * @param array + * @return self + * @throws Nette\NotSupportedException + * @throws Nette\InvalidStateException + */ + public function setOptions(array $options) + { + if (self::$started) { + $this->configure($options); + } + $this->options = $options + $this->options; + if (!empty($options['auto_start'])) { + $this->start(); + } + return $this; + } + + + /** + * Returns all session options. + * @return array + */ + public function getOptions() + { + return $this->options; + } + + + /** + * Configurates session environment. + * @param array + * @return void + */ + private function configure(array $config) + { + $special = array('cache_expire' => 1, 'cache_limiter' => 1, 'save_path' => 1, 'name' => 1); + + foreach ($config as $key => $value) { + if (!strncmp($key, 'session.', 8)) { // back compatibility + $key = substr($key, 8); + } + $key = strtolower(preg_replace('#(.)(?=[A-Z])#', '$1_', $key)); + + if ($value === NULL || ini_get("session.$key") == $value) { // intentionally == + continue; + + } elseif (strncmp($key, 'cookie_', 7) === 0) { + if (!isset($cookie)) { + $cookie = session_get_cookie_params(); + } + $cookie[substr($key, 7)] = $value; + + } else { + if (defined('SID')) { + throw new Nette\InvalidStateException("Unable to set 'session.$key' to value '$value' when session has been started" . ($this->started ? "." : " by session.auto_start or session_start().")); + } + if (isset($special[$key])) { + $key = "session_$key"; + $key($value); + + } elseif (function_exists('ini_set')) { + ini_set("session.$key", $value); + + } elseif (ini_get("session.$key") != $value) { // intentionally == + throw new Nette\NotSupportedException("Unable to set 'session.$key' to '$value' because function ini_set() is disabled."); + } + } + } + + if (isset($cookie)) { + session_set_cookie_params( + $cookie['lifetime'], $cookie['path'], $cookie['domain'], + $cookie['secure'], $cookie['httponly'] + ); + if (self::$started) { + $this->sendCookie(); + } + } + } + + + /** + * Sets the amount of time allowed between requests before the session will be terminated. + * @param string|int|DateTime time, value 0 means "until the browser is closed" + * @return self + */ + public function setExpiration($time) + { + if (empty($time)) { + return $this->setOptions(array( + 'gc_maxlifetime' => self::DEFAULT_FILE_LIFETIME, + 'cookie_lifetime' => 0, + )); + + } else { + $time = Nette\DateTime::from($time)->format('U') - time(); + return $this->setOptions(array( + 'gc_maxlifetime' => $time, + 'cookie_lifetime' => $time, + )); + } + } + + + /** + * Sets the session cookie parameters. + * @param string path + * @param string domain + * @param bool secure + * @return self + */ + public function setCookieParameters($path, $domain = NULL, $secure = NULL) + { + return $this->setOptions(array( + 'cookie_path' => $path, + 'cookie_domain' => $domain, + 'cookie_secure' => $secure + )); + } + + + /** + * Returns the session cookie parameters. + * @return array containing items: lifetime, path, domain, secure, httponly + */ + public function getCookieParameters() + { + return session_get_cookie_params(); + } + + + /** + * Sets path of the directory used to save session data. + * @return self + */ + public function setSavePath($path) + { + return $this->setOptions(array( + 'save_path' => $path, + )); + } + + + /** + * Sets user session storage for PHP < 5.4. For PHP >= 5.4, use setHandler(). + * @return self + */ + public function setStorage(ISessionStorage $storage) + { + if (self::$started) { + throw new Nette\InvalidStateException('Unable to set storage when session has been started.'); + } + session_set_save_handler( + array($storage, 'open'), array($storage, 'close'), array($storage, 'read'), + array($storage, 'write'), array($storage, 'remove'), array($storage, 'clean') + ); + } + + + /** + * Sets user session handler. + * @return self + */ + public function setHandler(\SessionHandlerInterface $handler) + { + if (self::$started) { + throw new Nette\InvalidStateException('Unable to set handler when session has been started.'); + } + session_set_save_handler($handler); + } + + + /** + * Sends the session cookies. + * @return void + */ + private function sendCookie() + { + if (!headers_sent() && ob_get_level() && ob_get_length()) { + trigger_error('Possible problem: you are starting session while already having some data in output buffer. This may not work if the outputted data grows. Try starting the session earlier.', E_USER_NOTICE); + } + + $cookie = $this->getCookieParameters(); + $this->response->setCookie( + session_name(), session_id(), + $cookie['lifetime'] ? $cookie['lifetime'] + time() : 0, + $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httponly'] + + )->setCookie( + 'nette-browser', $_SESSION['__NF']['B'], + Response::BROWSER, $cookie['path'], $cookie['domain'] + ); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/SessionSection.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/SessionSection.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/SessionSection.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/SessionSection.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,254 @@ +session = $session; + $this->name = $name; + } + + + /** + * Do not call directly. Use Session::getNamespace(). + */ + private function start() + { + if ($this->meta === FALSE) { + $this->session->start(); + $this->data = & $_SESSION['__NF']['DATA'][$this->name]; + $this->meta = & $_SESSION['__NF']['META'][$this->name]; + } + } + + + /** + * Returns an iterator over all section variables. + * @return \ArrayIterator + */ + public function getIterator() + { + $this->start(); + if (isset($this->data)) { + return new \ArrayIterator($this->data); + } else { + return new \ArrayIterator; + } + } + + + /** + * Sets a variable in this session section. + * @param string name + * @param mixed value + * @return void + */ + public function __set($name, $value) + { + $this->start(); + $this->data[$name] = $value; + if (is_object($value)) { + $this->meta[$name]['V'] = Nette\Reflection\ClassType::from($value)->getAnnotation('serializationVersion'); + } + } + + + /** + * Gets a variable from this session section. + * @param string name + * @return mixed + */ + public function &__get($name) + { + $this->start(); + if ($this->warnOnUndefined && !array_key_exists($name, $this->data)) { + trigger_error("The variable '$name' does not exist in session section", E_USER_NOTICE); + } + + return $this->data[$name]; + } + + + /** + * Determines whether a variable in this session section is set. + * @param string name + * @return bool + */ + public function __isset($name) + { + if ($this->session->exists()) { + $this->start(); + } + return isset($this->data[$name]); + } + + + /** + * Unsets a variable in this session section. + * @param string name + * @return void + */ + public function __unset($name) + { + $this->start(); + unset($this->data[$name], $this->meta[$name]); + } + + + /** + * Sets a variable in this session section. + * @param string name + * @param mixed value + * @return void + */ + public function offsetSet($name, $value) + { + $this->__set($name, $value); + } + + + /** + * Gets a variable from this session section. + * @param string name + * @return mixed + */ + public function offsetGet($name) + { + return $this->__get($name); + } + + + /** + * Determines whether a variable in this session section is set. + * @param string name + * @return bool + */ + public function offsetExists($name) + { + return $this->__isset($name); + } + + + /** + * Unsets a variable in this session section. + * @param string name + * @return void + */ + public function offsetUnset($name) + { + $this->__unset($name); + } + + + /** + * Sets the expiration of the section or specific variables. + * @param string|int|DateTime time, value 0 means "until the browser is closed" + * @param mixed optional list of variables / single variable to expire + * @return self + */ + public function setExpiration($time, $variables = NULL) + { + $this->start(); + if (empty($time)) { + $time = NULL; + $whenBrowserIsClosed = TRUE; + } else { + $time = Nette\DateTime::from($time)->format('U'); + $max = ini_get('session.gc_maxlifetime'); + if ($max !== 0 && ($time - time() > $max + 3)) { // 0 - unlimited in memcache handler, 3 - bulgarian constant + trigger_error("The expiration time is greater than the session expiration $max seconds", E_USER_NOTICE); + } + $whenBrowserIsClosed = FALSE; + } + + if ($variables === NULL) { // to entire section + $this->meta['']['T'] = $time; + $this->meta['']['B'] = $whenBrowserIsClosed; + + } elseif (is_array($variables)) { // to variables + foreach ($variables as $variable) { + $this->meta[$variable]['T'] = $time; + $this->meta[$variable]['B'] = $whenBrowserIsClosed; + } + + } else { // to variable + $this->meta[$variables]['T'] = $time; + $this->meta[$variables]['B'] = $whenBrowserIsClosed; + } + return $this; + } + + + /** + * Removes the expiration from the section or specific variables. + * @param mixed optional list of variables / single variable to expire + * @return void + */ + public function removeExpiration($variables = NULL) + { + $this->start(); + if ($variables === NULL) { + // from entire section + unset($this->meta['']['T'], $this->meta['']['B']); + + } elseif (is_array($variables)) { + // from variables + foreach ($variables as $variable) { + unset($this->meta[$variable]['T'], $this->meta[$variable]['B']); + } + } else { + unset($this->meta[$variables]['T'], $this->meta[$variables]['B']); + } + } + + + /** + * Cancels the current session section. + * @return void + */ + public function remove() + { + $this->start(); + $this->data = NULL; + $this->meta = NULL; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/Url.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/Url.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/Url.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/Url.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,485 @@ + + * scheme user password host port basePath relativeUrl + * | | | | | | | + * /--\ /--\ /------\ /-------\ /--\/--\/----------------------------\ + * http://john:x0y17575@nette.org:8042/en/manual.php?name=param#fragment <-- absoluteUrl + * \__________________________/\____________/^\________/^\______/ + * | | | | + * authority path query fragment + * + * + * - authority: [user[:password]@]host[:port] + * - hostUrl: http://user:password@nette.org:8042 + * - basePath: /en/ (everything before relative URI not including the script name) + * - baseUrl: http://user:password@nette.org:8042/en/ + * - relativeUrl: manual.php + * + * @author David Grudl + * + * @property string $scheme + * @property string $user + * @property string $password + * @property string $host + * @property string $port + * @property string $path + * @property string $query + * @property string $fragment + * @property-read string $absoluteUrl + * @property-read string $authority + * @property-read string $hostUrl + * @property-read string $basePath + * @property-read string $baseUrl + * @property-read string $relativeUrl + */ +class Url extends Nette\Object +{ + /** @var array */ + public static $defaultPorts = array( + 'http' => 80, + 'https' => 443, + 'ftp' => 21, + 'news' => 119, + 'nntp' => 119, + ); + + /** @var string */ + private $scheme = ''; + + /** @var string */ + private $user = ''; + + /** @var string */ + private $pass = ''; + + /** @var string */ + private $host = ''; + + /** @var int */ + private $port = NULL; + + /** @var string */ + private $path = ''; + + /** @var string */ + private $query = ''; + + /** @var string */ + private $fragment = ''; + + + /** + * @param string URL + * @throws Nette\InvalidArgumentException + */ + public function __construct($url = NULL) + { + if (is_string($url)) { + $parts = @parse_url($url); // @ - is escalated to exception + if ($parts === FALSE) { + throw new Nette\InvalidArgumentException("Malformed or unsupported URI '$url'."); + } + + foreach ($parts as $key => $val) { + $this->$key = $val; + } + + if (!$this->port && isset(self::$defaultPorts[$this->scheme])) { + $this->port = self::$defaultPorts[$this->scheme]; + } + + if ($this->path === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { + $this->path = '/'; + } + + } elseif ($url instanceof self) { + foreach ($this as $key => $val) { + $this->$key = $url->$key; + } + } + } + + + /** + * Sets the scheme part of URI. + * @param string + * @return self + */ + public function setScheme($value) + { + $this->scheme = (string) $value; + return $this; + } + + + /** + * Returns the scheme part of URI. + * @return string + */ + public function getScheme() + { + return $this->scheme; + } + + + /** + * Sets the user name part of URI. + * @param string + * @return self + */ + public function setUser($value) + { + $this->user = (string) $value; + return $this; + } + + + /** + * Returns the user name part of URI. + * @return string + */ + public function getUser() + { + return $this->user; + } + + + /** + * Sets the password part of URI. + * @param string + * @return self + */ + public function setPassword($value) + { + $this->pass = (string) $value; + return $this; + } + + + /** + * Returns the password part of URI. + * @return string + */ + public function getPassword() + { + return $this->pass; + } + + + /** + * Sets the host part of URI. + * @param string + * @return self + */ + public function setHost($value) + { + $this->host = (string) $value; + return $this; + } + + + /** + * Returns the host part of URI. + * @return string + */ + public function getHost() + { + return $this->host; + } + + + /** + * Sets the port part of URI. + * @param string + * @return self + */ + public function setPort($value) + { + $this->port = (int) $value; + return $this; + } + + + /** + * Returns the port part of URI. + * @return string + */ + public function getPort() + { + return $this->port; + } + + + /** + * Sets the path part of URI. + * @param string + * @return self + */ + public function setPath($value) + { + $this->path = (string) $value; + return $this; + } + + + /** + * Returns the path part of URI. + * @return string + */ + public function getPath() + { + return $this->path; + } + + + /** + * Sets the query part of URI. + * @param string|array + * @return self + */ + public function setQuery($value) + { + $this->query = (string) (is_array($value) ? http_build_query($value, '', '&') : $value); + return $this; + } + + + /** + * Appends the query part of URI. + * @param string|array + * @return Url + */ + public function appendQuery($value) + { + $value = (string) (is_array($value) ? http_build_query($value, '', '&') : $value); + $this->query .= ($this->query === '' || $value === '') ? $value : '&' . $value; + return $this; + } + + + /** + * Returns the query part of URI. + * @return string + */ + public function getQuery() + { + return $this->query; + } + + + /** + * @param string + * @param mixed + * @return mixed + */ + public function getQueryParameter($name, $default = NULL) + { + parse_str($this->query, $params); + return isset($params[$name]) ? $params[$name] : $default; + } + + + /** + * @param string + * @param mixed NULL unsets the parameter + * @return self + */ + public function setQueryParameter($name, $value) + { + parse_str($this->query, $params); + if ($value === NULL) { + unset($params[$name]); + } else { + $params[$name] = $value; + } + $this->setQuery($params); + return $this; + } + + + /** + * Sets the fragment part of URI. + * @param string + * @return self + */ + public function setFragment($value) + { + $this->fragment = (string) $value; + return $this; + } + + + /** + * Returns the fragment part of URI. + * @return string + */ + public function getFragment() + { + return $this->fragment; + } + + + /** + * Returns the entire URI including query string and fragment. + * @return string + */ + public function getAbsoluteUrl() + { + return $this->getHostUrl() . $this->path + . ($this->query === '' ? '' : '?' . $this->query) + . ($this->fragment === '' ? '' : '#' . $this->fragment); + } + + + /** + * Returns the [user[:pass]@]host[:port] part of URI. + * @return string + */ + public function getAuthority() + { + $authority = $this->host; + if ($this->port && (!isset(self::$defaultPorts[$this->scheme]) || $this->port !== self::$defaultPorts[$this->scheme])) { + $authority .= ':' . $this->port; + } + + if ($this->user !== '' && $this->scheme !== 'http' && $this->scheme !== 'https') { + $authority = $this->user . ($this->pass === '' ? '' : ':' . $this->pass) . '@' . $authority; + } + + return $authority; + } + + + /** + * Returns the scheme and authority part of URI. + * @return string + */ + public function getHostUrl() + { + return ($this->scheme ? $this->scheme . ':' : '') . '//' . $this->getAuthority(); + } + + + /** + * Returns the base-path. + * @return string + */ + public function getBasePath() + { + $pos = strrpos($this->path, '/'); + return $pos === FALSE ? '' : substr($this->path, 0, $pos + 1); + } + + + /** + * Returns the base-URI. + * @return string + */ + public function getBaseUrl() + { + return $this->getHostUrl() . $this->getBasePath(); + } + + + /** + * Returns the relative-URI. + * @return string + */ + public function getRelativeUrl() + { + return (string) substr($this->getAbsoluteUrl(), strlen($this->getBaseUrl())); + } + + + /** + * URI comparsion (this object must be in canonical form). + * @param string + * @return bool + */ + public function isEqual($url) + { + // compare host + path + $part = self::unescape(strtok($url, '?#'), '%/'); + if (strncmp($part, '//', 2) === 0) { // absolute URI without scheme + if ($part !== '//' . $this->getAuthority() . $this->path) { + return FALSE; + } + + } elseif (strncmp($part, '/', 1) === 0) { // absolute path + if ($part !== $this->path) { + return FALSE; + } + + } else { + if ($part !== $this->getHostUrl() . $this->path) { + return FALSE; + } + } + + // compare query strings + $part = preg_split('#[&;]#', self::unescape(strtr((string) strtok('?#'), '+', ' '), '%&;=+')); + sort($part); + $query = preg_split('#[&;]#', $this->query); + sort($query); + return $part === $query; + } + + + /** + * Transform to canonical form. + * @return Url + */ + public function canonicalize() + { + $this->path = $this->path === '' ? '/' : self::unescape($this->path, '%/'); + $this->host = strtolower(rawurldecode($this->host)); + $this->query = self::unescape(strtr($this->query, '+', ' '), '%&;=+'); + return $this; + } + + + /** + * @return string + */ + public function __toString() + { + return $this->getAbsoluteUrl(); + } + + + /** + * Similar to rawurldecode, but preserve reserved chars encoded. + * @param string to decode + * @param string reserved characters + * @return string + */ + public static function unescape($s, $reserved = '%;/?:@&=+$,') + { + // reserved (@see RFC 2396) = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," + // within a path segment, the characters "/", ";", "=", "?" are reserved + // within a query component, the characters ";", "/", "?", ":", "@", "&", "=", "+", ",", "$" are reserved. + preg_match_all('#(?<=%)[a-f0-9][a-f0-9]#i', $s, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); + foreach (array_reverse($matches) as $match) { + $ch = chr(hexdec($match[0][0])); + if (strpos($reserved, $ch) === FALSE) { + $s = substr_replace($s, $ch, $match[0][1] - 1, 3); + } + } + return $s; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/UrlScript.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/UrlScript.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/UrlScript.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/UrlScript.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,79 @@ + + * http://nette.org/admin/script.php/pathinfo/?name=param#fragment + * \_______________/\________/ + * | | + * scriptPath pathInfo + * + * + * - scriptPath: /admin/script.php (or simply /admin/ when script is directory index) + * - pathInfo: /pathinfo/ (additional path information) + * + * @author David Grudl + * + * @property string $scriptPath + * @property-read string $pathInfo + */ +class UrlScript extends Url +{ + /** @var string */ + private $scriptPath = '/'; + + + /** + * Sets the script-path part of URI. + * @param string + * @return self + */ + public function setScriptPath($value) + { + $this->scriptPath = (string) $value; + return $this; + } + + + /** + * Returns the script-path part of URI. + * @return string + */ + public function getScriptPath() + { + return $this->scriptPath; + } + + + /** + * Returns the base-path. + * @return string + */ + public function getBasePath() + { + $pos = strrpos($this->scriptPath, '/'); + return $pos === FALSE ? '' : substr($this->path, 0, $pos + 1); + } + + + /** + * Returns the additional path information. + * @return string + */ + public function getPathInfo() + { + return (string) substr($this->path, strlen($this->scriptPath)); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Http/UserStorage.php php-nette-2.1.5/Nette-2.1.5/Nette/Http/UserStorage.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Http/UserStorage.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Http/UserStorage.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,206 @@ +sessionHandler = $sessionHandler; + } + + + /** + * Sets the authenticated status of this user. + * @param bool + * @return self + */ + public function setAuthenticated($state) + { + $section = $this->getSessionSection(TRUE); + $section->authenticated = (bool) $state; + + // Session Fixation defence + $this->sessionHandler->regenerateId(); + + if ($state) { + $section->reason = NULL; + $section->authTime = time(); // informative value + + } else { + $section->reason = self::MANUAL; + $section->authTime = NULL; + } + return $this; + } + + + /** + * Is this user authenticated? + * @return bool + */ + public function isAuthenticated() + { + $session = $this->getSessionSection(FALSE); + return $session && $session->authenticated; + } + + + /** + * Sets the user identity. + * @return self + */ + public function setIdentity(IIdentity $identity = NULL) + { + $this->getSessionSection(TRUE)->identity = $identity; + return $this; + } + + + /** + * Returns current user identity, if any. + * @return Nette\Security\IIdentity|NULL + */ + public function getIdentity() + { + $session = $this->getSessionSection(FALSE); + return $session ? $session->identity : NULL; + } + + + /** + * Changes namespace; allows more users to share a session. + * @param string + * @return self + */ + public function setNamespace($namespace) + { + if ($this->namespace !== $namespace) { + $this->namespace = (string) $namespace; + $this->sessionSection = NULL; + } + return $this; + } + + + /** + * Returns current namespace. + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + + /** + * Enables log out after inactivity. + * @param string|int|DateTime Number of seconds or timestamp + * @param int Log out when the browser is closed | Clear the identity from persistent storage? + * @return self + */ + public function setExpiration($time, $flags = 0) + { + $section = $this->getSessionSection(TRUE); + if ($time) { + $time = Nette\DateTime::from($time)->format('U'); + $section->expireTime = $time; + $section->expireDelta = $time - time(); + + } else { + unset($section->expireTime, $section->expireDelta); + } + + $section->expireIdentity = (bool) ($flags & self::CLEAR_IDENTITY); + $section->expireBrowser = (bool) ($flags & self::BROWSER_CLOSED); + $section->browserCheck = TRUE; + $section->setExpiration(0, 'browserCheck'); + $section->setExpiration($time, 'foo'); // time check + return $this; + } + + + /** + * Why was user logged out? + * @return int + */ + public function getLogoutReason() + { + $session = $this->getSessionSection(FALSE); + return $session ? $session->reason : NULL; + } + + + /** + * Returns and initializes $this->sessionSection. + * @return SessionSection + */ + protected function getSessionSection($need) + { + if ($this->sessionSection !== NULL) { + return $this->sessionSection; + } + + if (!$need && !$this->sessionHandler->exists()) { + return NULL; + } + + $this->sessionSection = $section = $this->sessionHandler->getSection('Nette.Http.UserStorage/' . $this->namespace); + + if (!$section->identity instanceof IIdentity || !is_bool($section->authenticated)) { + $section->remove(); + } + + if ($section->authenticated && $section->expireBrowser && !$section->browserCheck) { // check if browser was closed? + $section->reason = self::BROWSER_CLOSED; + $section->authenticated = FALSE; + if ($section->expireIdentity) { + unset($section->identity); + } + } + + if ($section->authenticated && $section->expireDelta > 0) { // check time expiration + if ($section->expireTime < time()) { + $section->reason = self::INACTIVITY; + $section->authenticated = FALSE; + if ($section->expireIdentity) { + unset($section->identity); + } + } + $section->expireTime = time() + $section->expireDelta; // sliding expiration + } + + if (!$section->authenticated) { + unset($section->expireTime, $section->expireDelta, $section->expireIdentity, + $section->expireBrowser, $section->browserCheck, $section->authTime); + } + + return $this->sessionSection; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/CachingIterator.php php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/CachingIterator.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/CachingIterator.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/CachingIterator.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,244 @@ +getIterator(); + } while ($iterator instanceof \IteratorAggregate); + + } elseif ($iterator instanceof \Traversable) { + if (!$iterator instanceof \Iterator) { + $iterator = new \IteratorIterator($iterator); + } + } else { + throw new Nette\InvalidArgumentException(sprintf('Invalid argument passed to foreach resp. %s; array or Traversable expected, %s given.', __CLASS__, is_object($iterator) ? get_class($iterator) : gettype($iterator))); + } + + parent::__construct($iterator, 0); + } + + + /** + * Is the current element the first one? + * @param int grid width + * @return bool + */ + public function isFirst($width = NULL) + { + return $this->counter === 1 || ($width && $this->counter !== 0 && (($this->counter - 1) % $width) === 0); + } + + + /** + * Is the current element the last one? + * @param int grid width + * @return bool + */ + public function isLast($width = NULL) + { + return !$this->hasNext() || ($width && ($this->counter % $width) === 0); + } + + + /** + * Is the iterator empty? + * @return bool + */ + public function isEmpty() + { + return $this->counter === 0; + } + + + /** + * Is the counter odd? + * @return bool + */ + public function isOdd() + { + return $this->counter % 2 === 1; + } + + + /** + * Is the counter even? + * @return bool + */ + public function isEven() + { + return $this->counter % 2 === 0; + } + + + /** + * Returns the counter. + * @return int + */ + public function getCounter() + { + return $this->counter; + } + + + /** + * Returns the count of elements. + * @return int + */ + public function count() + { + $inner = $this->getInnerIterator(); + if ($inner instanceof \Countable) { + return $inner->count(); + + } else { + throw new Nette\NotSupportedException('Iterator is not countable.'); + } + } + + + /** + * Forwards to the next element. + * @return void + */ + public function next() + { + parent::next(); + if (parent::valid()) { + $this->counter++; + } + } + + + /** + * Rewinds the Iterator. + * @return void + */ + public function rewind() + { + parent::rewind(); + $this->counter = parent::valid() ? 1 : 0; + } + + + /** + * Returns the next key. + * @return mixed + */ + public function getNextKey() + { + return $this->getInnerIterator()->key(); + } + + + /** + * Returns the next element. + * @return mixed + */ + public function getNextValue() + { + return $this->getInnerIterator()->current(); + } + + + /********************* Nette\Object behaviour ****************d*g**/ + + + /** + * Call to undefined method. + * @param string method name + * @param array arguments + * @return mixed + * @throws Nette\MemberAccessException + */ + public function __call($name, $args) + { + return Nette\ObjectMixin::call($this, $name, $args); + } + + + /** + * Returns property value. Do not call directly. + * @param string property name + * @return mixed property value + * @throws Nette\MemberAccessException if the property is not defined. + */ + public function &__get($name) + { + return Nette\ObjectMixin::get($this, $name); + } + + + /** + * Sets value of a property. Do not call directly. + * @param string property name + * @param mixed property value + * @return void + * @throws Nette\MemberAccessException if the property is not defined or is read-only + */ + public function __set($name, $value) + { + Nette\ObjectMixin::set($this, $name, $value); + } + + + /** + * Is property defined? + * @param string property name + * @return bool + */ + public function __isset($name) + { + return Nette\ObjectMixin::has($this, $name); + } + + + /** + * Access to undeclared property. + * @param string property name + * @return void + * @throws Nette\MemberAccessException + */ + public function __unset($name) + { + Nette\ObjectMixin::remove($this, $name); + } + + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/Filter.php php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/Filter.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/Filter.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/Filter.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,36 @@ +callback = Nette\Utils\Callback::check($callback); + } + + + public function accept() + { + return call_user_func($this->callback, $this->current(), $this->key(), $this); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/Mapper.php php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/Mapper.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/Mapper.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/Mapper.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,36 @@ +callback = Nette\Utils\Callback::check($callback); + } + + + public function current() + { + return call_user_func($this->callback, parent::current(), parent::key()); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/RecursiveFilter.php php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/RecursiveFilter.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/RecursiveFilter.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/RecursiveFilter.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,38 @@ +getInnerIterator()->hasChildren(); + } + + + public function getChildren() + { + return new static($this->getInnerIterator()->getChildren(), $this->callback); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/Recursor.php php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/Recursor.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Iterators/Recursor.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Iterators/Recursor.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,53 @@ +current(); + return ($obj instanceof \IteratorAggregate && $obj->getIterator() instanceof \RecursiveIterator) + || $obj instanceof \RecursiveIterator; + } + + + /** + * The sub-iterator for the current element. + * @return \RecursiveIterator + */ + public function getChildren() + { + $obj = $this->current(); + return $obj instanceof \IteratorAggregate ? $obj->getIterator() : $obj; + } + + + /** + * Returns the count of elements. + * @return int + */ + public function count() + { + return iterator_count($this); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Compiler.php php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Compiler.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Compiler.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Compiler.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,582 @@ + IMacro[]] */ + private $macros; + + /** @var \SplObjectStorage */ + private $macroHandlers; + + /** @var HtmlNode */ + private $htmlNode; + + /** @var MacroNode */ + private $macroNode; + + /** @var string[] */ + private $attrCodes = array(); + + /** @var string */ + private $contentType; + + /** @var array [context, subcontext] */ + private $context; + + /** @var string */ + private $templateId; + + /** Context-aware escaping content types */ + const CONTENT_HTML = 'html', + CONTENT_XHTML = 'xhtml', + CONTENT_XML = 'xml', + CONTENT_JS = 'js', + CONTENT_CSS = 'css', + CONTENT_URL = 'url', + CONTENT_ICAL = 'ical', + CONTENT_TEXT = 'text'; + + /** @internal Context-aware escaping HTML contexts */ + const CONTEXT_COMMENT = 'comment', + CONTEXT_SINGLE_QUOTED_ATTR = "'", + CONTEXT_DOUBLE_QUOTED_ATTR = '"', + CONTEXT_UNQUOTED_ATTR = '='; + + + public function __construct() + { + $this->macroHandlers = new \SplObjectStorage; + } + + + /** + * Adds new macro. + * @param string + * @return self + */ + public function addMacro($name, IMacro $macro) + { + $this->macros[$name][] = $macro; + $this->macroHandlers->attach($macro); + return $this; + } + + + /** + * Compiles tokens to PHP code. + * @param Token[] + * @return string + */ + public function compile(array $tokens) + { + $this->templateId = Strings::random(); + $this->tokens = $tokens; + $output = ''; + $this->output = & $output; + $this->htmlNode = $this->macroNode = NULL; + $this->setContentType($this->defaultContentType); + + foreach ($this->macroHandlers as $handler) { + $handler->initialize($this); + } + + try { + foreach ($tokens as $this->position => $token) { + $this->{"process$token->type"}($token); + } + } catch (CompileException $e) { + $e->sourceLine = $token->line; + throw $e; + } + + while ($this->htmlNode) { + if (!empty($this->htmlNode->macroAttrs)) { + throw new CompileException('Missing ' . self::printEndTag($this->macroNode), 0, $token->line); + } + $this->htmlNode = $this->htmlNode->parentNode; + } + + $prologs = $epilogs = ''; + foreach ($this->macroHandlers as $handler) { + $res = $handler->finalize(); + $handlerName = get_class($handler); + $prologs .= empty($res[0]) ? '' : ""; + $epilogs = (empty($res[1]) ? '' : "") . $epilogs; + } + $output = ($prologs ? $prologs . "\n" : '') . $output . $epilogs; + + if ($this->macroNode) { + throw new CompileException('Missing ' . self::printEndTag($this->macroNode), 0, $token->line); + } + + $output = $this->expandTokens($output); + return $output; + } + + + /** + * @return self + */ + public function setContentType($type) + { + $this->contentType = $type; + $this->context = NULL; + return $this; + } + + + /** + * @return string + */ + public function getContentType() + { + return $this->contentType; + } + + + /** + * @return self + */ + public function setContext($context, $sub = NULL) + { + $this->context = array($context, $sub); + return $this; + } + + + /** + * @return array [context, subcontext] + */ + public function getContext() + { + return $this->context; + } + + + /** + * @return string + */ + public function getTemplateId() + { + return $this->templateId; + } + + + /** + * @return MacroNode|NULL + */ + public function getMacroNode() + { + return $this->macroNode; + } + + + /** + * Returns current line number. + * @return int + */ + public function getLine() + { + return $this->tokens ? $this->tokens[$this->position]->line : NULL; + } + + + public function expandTokens($s) + { + return strtr($s, $this->attrCodes); + } + + + private function processText(Token $token) + { + if (($this->context[0] === self::CONTEXT_SINGLE_QUOTED_ATTR || $this->context[0] === self::CONTEXT_DOUBLE_QUOTED_ATTR) + && $token->text === $this->context[0] + ) { + $this->setContext(self::CONTEXT_UNQUOTED_ATTR); + } + $this->output .= $token->text; + } + + + private function processMacroTag(Token $token) + { + $isRightmost = !isset($this->tokens[$this->position + 1]) + || substr($this->tokens[$this->position + 1]->text, 0, 1) === "\n"; + + if ($token->name[0] === '/') { + $this->closeMacro((string) substr($token->name, 1), $token->value, $token->modifiers, $isRightmost); + } else { + $this->openMacro($token->name, $token->value, $token->modifiers, $isRightmost && !$token->empty); + if ($token->empty) { + $this->closeMacro($token->name, NULL, NULL, $isRightmost); + } + } + } + + + private function processHtmlTagBegin(Token $token) + { + if ($token->closing) { + while ($this->htmlNode) { + if (strcasecmp($this->htmlNode->name, $token->name) === 0) { + break; + } + if ($this->htmlNode->macroAttrs) { + throw new CompileException("Unexpected name>, expecting " . self::printEndTag($this->macroNode)); + } + $this->htmlNode = $this->htmlNode->parentNode; + } + if (!$this->htmlNode) { + $this->htmlNode = new HtmlNode($token->name); + } + $this->htmlNode->closing = TRUE; + $this->htmlNode->offset = strlen($this->output); + $this->setContext(NULL); + + } elseif ($token->text === '') { + $this->output .= $token->text; + $this->setContext(NULL); + return; + } + + $htmlNode = $this->htmlNode; + $isEmpty = !$htmlNode->closing && (Strings::contains($token->text, '/') || $htmlNode->isEmpty); + $end = ''; + + if ($isEmpty && in_array($this->contentType, array(self::CONTENT_HTML, self::CONTENT_XHTML), TRUE)) { // auto-correct + $token->text = preg_replace('#^.*>#', $htmlNode->isEmpty && $this->contentType === self::CONTENT_XHTML ? ' />' : '>', $token->text); + if (!$htmlNode->isEmpty) { + $end = "name>"; + } + } + + if (empty($htmlNode->macroAttrs)) { + $this->output .= $token->text . $end; + } else { + $code = substr($this->output, $htmlNode->offset) . $token->text; + $this->output = substr($this->output, 0, $htmlNode->offset); + $this->writeAttrsMacro($code); + if ($isEmpty) { + $htmlNode->closing = TRUE; + $this->writeAttrsMacro($end); + } + } + + if ($isEmpty) { + $htmlNode->closing = TRUE; + } + + $lower = strtolower($htmlNode->name); + if (!$htmlNode->closing && ($lower === 'script' || $lower === 'style')) { + $this->setContext($lower === 'script' ? self::CONTENT_JS : self::CONTENT_CSS); + } else { + $this->setContext(NULL); + if ($htmlNode->closing) { + $this->htmlNode = $this->htmlNode->parentNode; + } + } + } + + + private function processHtmlAttribute(Token $token) + { + if (Strings::startsWith($token->name, Parser::N_PREFIX)) { + $name = substr($token->name, strlen(Parser::N_PREFIX)); + if (isset($this->htmlNode->macroAttrs[$name])) { + throw new CompileException("Found multiple macro-attributes $token->name."); + + } elseif ($this->macroNode && $this->macroNode->htmlNode === $this->htmlNode) { + throw new CompileException("Macro-attributes must not appear inside macro; found $token->name inside {{$this->macroNode->name}}."); + } + $this->htmlNode->macroAttrs[$name] = $token->value; + return; + } + + $this->htmlNode->attrs[$token->name] = TRUE; + $this->output .= $token->text; + + $contextMain = in_array($token->value, array(self::CONTEXT_SINGLE_QUOTED_ATTR, self::CONTEXT_DOUBLE_QUOTED_ATTR), TRUE) + ? $token->value + : self::CONTEXT_UNQUOTED_ATTR; + + $context = NULL; + if (in_array($this->contentType, array(self::CONTENT_HTML, self::CONTENT_XHTML), TRUE)) { + $lower = strtolower($token->name); + if (substr($lower, 0, 2) === 'on') { + $context = self::CONTENT_JS; + } elseif ($lower === 'style') { + $context = self::CONTENT_CSS; + } elseif (in_array($lower, array('href', 'src', 'action', 'formaction'), TRUE) + || ($lower === 'data' && strtolower($this->htmlNode->name) === 'object') + ) { + $context = self::CONTENT_URL; + } + } + + $this->setContext($contextMain, $context); + } + + + private function processComment(Token $token) + { + $isLeftmost = trim(substr($this->output, strrpos("\n$this->output", "\n"))) === ''; + if (!$isLeftmost) { + $this->output .= substr($token->text, strlen(rtrim($token->text, "\n"))); + } + } + + + /********************* macros ****************d*g**/ + + + /** + * Generates code for {macro ...} to the output. + * @param string + * @param string + * @param string + * @param bool + * @return MacroNode + */ + public function openMacro($name, $args = NULL, $modifiers = NULL, $isRightmost = FALSE, $nPrefix = NULL) + { + $node = $this->expandMacro($name, $args, $modifiers, $nPrefix); + if ($node->isEmpty) { + $this->writeCode($node->openingCode, $this->output, $isRightmost); + } else { + $this->macroNode = $node; + $node->saved = array(& $this->output, $isRightmost); + $this->output = & $node->content; + } + return $node; + } + + + /** + * Generates code for {/macro ...} to the output. + * @param string + * @param string + * @param string + * @param bool + * @return MacroNode + */ + public function closeMacro($name, $args = NULL, $modifiers = NULL, $isRightmost = FALSE, $nPrefix = NULL) + { + $node = $this->macroNode; + + if (!$node || ($node->name !== $name && '' !== $name) || $modifiers + || ($args && $node->args && !Strings::startsWith("$node->args ", "$args ")) + || $nPrefix !== $node->prefix + ) { + $name = $nPrefix + ? "htmlNode->name}> for macro-attribute " . Parser::N_PREFIX . implode(' and ' . Parser::N_PREFIX, array_keys($this->htmlNode->macroAttrs)) + : '{/' . $name . ($args ? ' ' . $args : '') . $modifiers . '}'; + throw new CompileException("Unexpected $name" . ($node ? ', expecting ' . self::printEndTag($node) : '')); + } + + $this->macroNode = $node->parentNode; + if (!$node->args) { + $node->setArgs($args); + } + + $isLeftmost = $node->content ? trim(substr($this->output, strrpos("\n$this->output", "\n"))) === '' : FALSE; + + $node->closing = TRUE; + $node->macro->nodeClosed($node); + + $this->output = & $node->saved[0]; + $this->writeCode($node->openingCode, $this->output, $node->saved[1]); + $this->writeCode($node->closingCode, $node->content, $isRightmost, $isLeftmost); + $this->output .= $node->content; + return $node; + } + + + private function writeCode($code, & $output, $isRightmost, $isLeftmost = NULL) + { + if ($isRightmost) { + $leftOfs = strrpos("\n$output", "\n"); + $isLeftmost = $isLeftmost === NULL ? trim(substr($output, $leftOfs)) === '' : $isLeftmost; + if ($isLeftmost && substr($code, 0, 11) !== ' remove indentation + } elseif (substr($code, -2) === '?>') { + $code .= "\n"; // double newline to avoid newline eating by PHP + } + } + $output .= $code; + } + + + /** + * Generates code for macro to the output. + * @param string + * @return void + */ + public function writeAttrsMacro($code) + { + $attrs = $this->htmlNode->macroAttrs; + $left = $right = array(); + + foreach ($this->macros as $name => $foo) { + $attrName = MacroNode::PREFIX_INNER . "-$name"; + if (isset($attrs[$attrName])) { + if ($this->htmlNode->closing) { + $left[] = array('closeMacro', $name, '', MacroNode::PREFIX_INNER); + } else { + array_unshift($right, array('openMacro', $name, $attrs[$attrName], MacroNode::PREFIX_INNER)); + } + unset($attrs[$attrName]); + } + } + + foreach (array_reverse($this->macros) as $name => $foo) { + $attrName = MacroNode::PREFIX_TAG . "-$name"; + if (isset($attrs[$attrName])) { + $left[] = array('openMacro', $name, $attrs[$attrName], MacroNode::PREFIX_TAG); + array_unshift($right, array('closeMacro', $name, '', MacroNode::PREFIX_TAG)); + unset($attrs[$attrName]); + } + } + + foreach ($this->macros as $name => $foo) { + if (isset($attrs[$name])) { + if ($this->htmlNode->closing) { + $right[] = array('closeMacro', $name, '', MacroNode::PREFIX_NONE); + } else { + array_unshift($left, array('openMacro', $name, $attrs[$name], MacroNode::PREFIX_NONE)); + } + unset($attrs[$name]); + } + } + + if ($attrs) { + throw new CompileException('Unknown macro-attribute ' . Parser::N_PREFIX + . implode(' and ' . Parser::N_PREFIX, array_keys($attrs))); + } + + if (!$this->htmlNode->closing) { + $this->htmlNode->attrCode = & $this->attrCodes[$uniq = ' n:' . Nette\Utils\Strings::random()]; + $code = substr_replace($code, $uniq, strrpos($code, '/>') ?: strrpos($code, '>'), 0); + } + + foreach ($left as $item) { + $node = $this->{$item[0]}($item[1], $item[2], NULL, NULL, $item[3]); + if ($node->closing || $node->isEmpty) { + $this->htmlNode->attrCode .= $node->attrCode; + if ($node->isEmpty) { + unset($this->htmlNode->macroAttrs[$node->name]); + } + } + } + + $this->output .= $code; + + foreach ($right as $item) { + $node = $this->{$item[0]}($item[1], $item[2], NULL, NULL, $item[3]); + if ($node->closing) { + $this->htmlNode->attrCode .= $node->attrCode; + } + } + + if ($right && substr($this->output, -2) === '?>') { + $this->output .= "\n"; + } + } + + + /** + * Expands macro and returns node & code. + * @param string + * @param string + * @param string + * @return MacroNode + */ + public function expandMacro($name, $args, $modifiers = NULL, $nPrefix = NULL) + { + $inScript = in_array($this->context[0], array(self::CONTENT_JS, self::CONTENT_CSS), TRUE); + + if (empty($this->macros[$name])) { + throw new CompileException("Unknown macro {{$name}}" . ($inScript ? ' (in JavaScript or CSS, try to put a space after bracket.)' : '')); + } + + if ($this->context[1] === self::CONTENT_URL) { + $modifiers = preg_replace('#\|nosafeurl\s?(?=\||\z)#i', '', $modifiers, -1, $found); + if (!$found && !preg_match('#\|datastream(?=\s|\||\z)#i', $modifiers)) { + $modifiers .= '|safeurl'; + } + } + + $modifiers = preg_replace('#\|noescape\s?(?=\||\z)#i', '', $modifiers, -1, $found); + if (!$found && strpbrk($name, '=~%^&_')) { + $modifiers .= '|escape'; + } + + if (!$found && $inScript && $name === '=' && preg_match('#["\'] *\z#', $this->tokens[$this->position - 1]->text)) { + throw new CompileException("Do not place {$this->tokens[$this->position]->text} inside quotes."); + } + + foreach (array_reverse($this->macros[$name]) as $macro) { + $node = new MacroNode($macro, $name, $args, $modifiers, $this->macroNode, $this->htmlNode, $nPrefix); + if ($macro->nodeOpened($node) !== FALSE) { + return $node; + } + } + + throw new CompileException($nPrefix ? 'Unknown macro-attribute ' . Parser::N_PREFIX . "$nPrefix-$name" : "Unhandled macro {{$name}}"); + } + + + private static function printEndTag(MacroNode $node) + { + if ($node->prefix) { + return "htmlNode->name}> for macro-attribute " . Parser::N_PREFIX + . implode(' and ' . Parser::N_PREFIX, array_keys($node->htmlNode->macroAttrs)); + } else { + return "{/$node->name}"; + } + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Engine.php php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Engine.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Engine.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Engine.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,68 @@ +parser = new Parser; + $this->compiler = new Compiler; + $this->compiler->defaultContentType = Compiler::CONTENT_HTML; + + Macros\CoreMacros::install($this->compiler); + $this->compiler->addMacro('cache', new Macros\CacheMacro($this->compiler)); + Macros\UIMacros::install($this->compiler); + Macros\FormMacros::install($this->compiler); + } + + + /** + * Invokes filter. + * @param string + * @return string + */ + public function __invoke($s) + { + return $this->compiler->compile($this->parser->parse($s)); + } + + + /** + * @return Parser + */ + public function getParser() + { + return $this->parser; + } + + + /** + * @return Compiler + */ + public function getCompiler() + { + return $this->compiler; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Latte/exceptions.php php-nette-2.1.5/Nette-2.1.5/Nette/Latte/exceptions.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Latte/exceptions.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Latte/exceptions.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,23 @@ +name = $name; + $this->parentNode = $parentNode; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Latte/IMacro.php php-nette-2.1.5/Nette-2.1.5/Nette/Latte/IMacro.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Latte/IMacro.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Latte/IMacro.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,45 @@ +macro = $macro; + $this->name = (string) $name; + $this->modifiers = (string) $modifiers; + $this->parentNode = $parentNode; + $this->htmlNode = $htmlNode; + $this->prefix = $prefix; + $this->data = new \stdClass; + $this->setArgs($args); + } + + + public function setArgs($args) + { + $this->args = (string) $args; + $this->tokenizer = new MacroTokens($this->args); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Macros/CacheMacro.php php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Macros/CacheMacro.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Macros/CacheMacro.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Macros/CacheMacro.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,120 @@ +used = FALSE; + } + + + /** + * Finishes template parsing. + * @return array(prolog, epilog) + */ + public function finalize() + { + if ($this->used) { + return array('Nette\Latte\Macros\CacheMacro::initRuntime($template, $_g);'); + } + } + + + /** + * New node is found. + * @return bool + */ + public function nodeOpened(Latte\MacroNode $node) + { + $this->used = TRUE; + $node->isEmpty = FALSE; + $node->openingCode = Latte\PhpWriter::using($node) + ->write('caches, %node.array?)) { ?>', + Nette\Utils\Strings::random() + ); + } + + + /** + * Node is closed. + * @return void + */ + public function nodeClosed(Latte\MacroNode $node) + { + $node->closingCode = 'tmp = array_pop($_g->caches); if (!$_l->tmp instanceof stdClass) $_l->tmp->end(); } ?>'; + } + + + /********************* run-time helpers ****************d*g**/ + + + /** + * @return void + */ + public static function initRuntime(Nette\Templating\FileTemplate $template, \stdClass $global) + { + if (!empty($global->caches)) { + end($global->caches)->dependencies[Nette\Caching\Cache::FILES][] = $template->getFile(); + } + } + + + /** + * Starts the output cache. Returns Nette\Caching\OutputHelper object if buffering was started. + * @param Nette\Caching\IStorage + * @param string + * @param Nette\Caching\OutputHelper[] + * @param array + * @return Nette\Caching\OutputHelper + */ + public static function createCache(Nette\Caching\IStorage $cacheStorage, $key, & $parents, array $args = NULL) + { + if ($args) { + if (array_key_exists('if', $args) && !$args['if']) { + return $parents[] = new \stdClass; + } + $key = array_merge(array($key), array_intersect_key($args, range(0, count($args)))); + } + if ($parents) { + end($parents)->dependencies[Nette\Caching\Cache::ITEMS][] = $key; + } + + $cache = new Nette\Caching\Cache($cacheStorage, 'Nette.Templating.Cache'); + if ($helper = $cache->start($key)) { + if (isset($args['expire'])) { + $args['expiration'] = $args['expire']; // back compatibility + } + $helper->dependencies = array( + Nette\Caching\Cache::TAGS => isset($args['tags']) ? $args['tags'] : NULL, + Nette\Caching\Cache::EXPIRATION => isset($args['expiration']) ? $args['expiration'] : '+ 7 days', + ); + $parents[] = $helper; + } + return $helper; + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Macros/CoreMacros.php php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Macros/CoreMacros.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Macros/CoreMacros.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Macros/CoreMacros.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,443 @@ + value} set template parameter + * - {default var => value} set default template parameter + * - {dump $var} + * - {debugbreak} + * - {l} {r} to display { } + * + * @author David Grudl + */ +class CoreMacros extends MacroSet +{ + + + public static function install(Latte\Compiler $compiler) + { + $me = new static($compiler); + + $me->addMacro('if', array($me, 'macroIf'), array($me, 'macroEndIf')); + $me->addMacro('elseif', '} elseif (%node.args) {'); + $me->addMacro('else', array($me, 'macroElse')); + $me->addMacro('ifset', 'if (isset(%node.args)) {', '}'); + $me->addMacro('elseifset', '} elseif (isset(%node.args)) {'); + $me->addMacro('ifcontent', array($me, 'macroIfContent'), array($me, 'macroEndIfContent')); + + $me->addMacro('switch', '$_l->switch[] = (%node.args); if (FALSE) {', '} array_pop($_l->switch)'); + $me->addMacro('case', '} elseif (end($_l->switch) === (%node.args)) {'); + + $me->addMacro('foreach', '', array($me, 'macroEndForeach')); + $me->addMacro('for', 'for (%node.args) {', '}'); + $me->addMacro('while', 'while (%node.args) {', '}'); + $me->addMacro('continueIf', array($me, 'macroBreakContinueIf')); + $me->addMacro('breakIf', array($me, 'macroBreakContinueIf')); + $me->addMacro('first', 'if ($iterator->isFirst(%node.args)) {', '}'); + $me->addMacro('last', 'if ($iterator->isLast(%node.args)) {', '}'); + $me->addMacro('sep', 'if (!$iterator->isLast(%node.args)) {', '}'); + + $me->addMacro('var', array($me, 'macroVar')); + $me->addMacro('assign', array($me, 'macroVar')); // deprecated + $me->addMacro('default', array($me, 'macroVar')); + $me->addMacro('dump', array($me, 'macroDump')); + $me->addMacro('debugbreak', array($me, 'macroDebugbreak')); + $me->addMacro('l', '?>{addMacro('r', '?>}addMacro('_', array($me, 'macroTranslate'), array($me, 'macroTranslate')); + $me->addMacro('=', array($me, 'macroExpr')); + $me->addMacro('?', array($me, 'macroExpr')); + + $me->addMacro('capture', array($me, 'macroCapture'), array($me, 'macroCaptureEnd')); + $me->addMacro('include', array($me, 'macroInclude')); + $me->addMacro('use', array($me, 'macroUse')); + + $me->addMacro('class', NULL, NULL, array($me, 'macroClass')); + $me->addMacro('attr', array($me, 'macroOldAttr'), '', array($me, 'macroAttr')); + $me->addMacro('href', NULL); // placeholder + } + + + /** + * Finishes template parsing. + * @return array(prolog, epilog) + */ + public function finalize() + { + return array('list($_l, $_g) = Nette\Latte\Macros\CoreMacros::initRuntime($template, ' + . var_export($this->getCompiler()->getTemplateId(), TRUE) . ')'); + } + + + /********************* macros ****************d*g**/ + + + /** + * {if ...} + */ + public function macroIf(MacroNode $node, PhpWriter $writer) + { + if ($node->data->capture = ($node->args === '')) { + return 'ob_start()'; + } + if ($node->prefix === $node::PREFIX_TAG) { + return $writer->write($node->htmlNode->closing ? 'if (array_pop($_l->ifs)) {' : 'if ($_l->ifs[] = (%node.args)) {'); + } + return $writer->write('if (%node.args) {'); + } + + + /** + * {/if ...} + */ + public function macroEndIf(MacroNode $node, PhpWriter $writer) + { + if ($node->data->capture) { + if ($node->args === '') { + throw new CompileException('Missing condition in {if} macro.'); + } + return $writer->write('if (%node.args) ' + . (isset($node->data->else) ? '{ ob_end_clean(); ob_end_flush(); }' : 'ob_end_flush();') + . ' else ' + . (isset($node->data->else) ? '{ $_else = ob_get_contents(); ob_end_clean(); ob_end_clean(); echo $_else; }' : 'ob_end_clean();') + ); + } + return '}'; + } + + + /** + * {else} + */ + public function macroElse(MacroNode $node, PhpWriter $writer) + { + $ifNode = $node->parentNode; + if ($ifNode && $ifNode->name === 'if' && $ifNode->data->capture) { + if (isset($ifNode->data->else)) { + throw new CompileException('Macro {if} supports only one {else}.'); + } + $ifNode->data->else = TRUE; + return 'ob_start()'; + } + return '} else {'; + } + + + /** + * n:ifcontent + */ + public function macroIfContent(MacroNode $node, PhpWriter $writer) + { + if (!$node->prefix) { + throw new CompileException("Unknown macro {{$node->name}}, use n:{$node->name} attribute."); + } elseif ($node->prefix !== MacroNode::PREFIX_NONE) { + throw new CompileException("Unknown attribute n:{$node->prefix}-{$node->name}, use n:{$node->name} attribute."); + } + + return $writer->write('ob_start()'); + } + + + /** + * n:ifcontent + */ + public function macroEndIfContent(MacroNode $node, PhpWriter $writer) + { + preg_match('#(^.*?>)(.*)(<.*\z)#s', $node->content, $parts); + $node->content = $parts[1] + . '' + . $parts[2] + . '' + . $parts[3]; + return 'rtrim($_ifcontent) === "" ? ob_end_clean() : ob_end_flush()'; + } + + + /** + * {_$var |modifiers} + */ + public function macroTranslate(MacroNode $node, PhpWriter $writer) + { + if ($node->closing) { + return $writer->write('echo %modify($template->translate(ob_get_clean()))'); + + } elseif ($node->isEmpty = ($node->args !== '')) { + return $writer->write('echo %modify($template->translate(%node.args))'); + + } else { + return 'ob_start()'; + } + } + + + /** + * {include "file" [,] [params]} + */ + public function macroInclude(MacroNode $node, PhpWriter $writer) + { + $code = $writer->write('Nette\Latte\Macros\CoreMacros::includeTemplate(%node.word, %node.array? + $template->getParameters(), $_l->templates[%var])', + $this->getCompiler()->getTemplateId()); + + if ($node->modifiers) { + return $writer->write('echo %modify(%raw->__toString(TRUE))', $code); + } else { + return $code . '->render()'; + } + } + + + /** + * {use class MacroSet} + */ + public function macroUse(MacroNode $node, PhpWriter $writer) + { + Nette\Utils\Callback::invoke(array($node->tokenizer->fetchWord(), 'install'), $this->getCompiler()) + ->initialize(); + } + + + /** + * {capture $variable} + */ + public function macroCapture(MacroNode $node, PhpWriter $writer) + { + $variable = $node->tokenizer->fetchWord(); + if (substr($variable, 0, 1) !== '$') { + throw new CompileException("Invalid capture block variable '$variable'"); + } + $node->data->variable = $variable; + return 'ob_start()'; + } + + + /** + * {/capture} + */ + public function macroCaptureEnd(MacroNode $node, PhpWriter $writer) + { + return $node->data->variable . $writer->write(' = %modify(ob_get_clean())'); + } + + + /** + * {foreach ...} + */ + public function macroEndForeach(MacroNode $node, PhpWriter $writer) + { + if ($node->modifiers !== '|noiterator' && preg_match('#\W(\$iterator|include|require|get_defined_vars)\W#', $this->getCompiler()->expandTokens($node->content))) { + $node->openingCode = 'its[] = new Nette\Iterators\CachingIterator(' + . preg_replace('#(.*)\s+as\s+#i', '$1) as ', $writer->formatArgs(), 1) . ') { ?>'; + $node->closingCode = 'its); $iterator = end($_l->its) ?>'; + } else { + $node->openingCode = 'formatArgs() . ') { ?>'; + $node->closingCode = ''; + } + } + + + /** + * {breakIf ...} + * {continueIf ...} + */ + public function macroBreakContinueIf(MacroNode $node, PhpWriter $writer) + { + $cmd = str_replace('If', '', $node->name); + if ($node->parentNode && $node->parentNode->prefix === $node::PREFIX_NONE) { + return $writer->write("if (%node.args) { echo \"parentNode->htmlNode->name}>\\n\"; $cmd; }"); + } + return $writer->write("if (%node.args) $cmd"); + } + + + /** + * n:class="..." + */ + public function macroClass(MacroNode $node, PhpWriter $writer) + { + return $writer->write('if ($_l->tmp = array_filter(%node.array)) echo \' class="\' . %escape(implode(" ", array_unique($_l->tmp))) . \'"\''); + } + + + /** + * n:attr="..." + */ + public function macroAttr(MacroNode $node, PhpWriter $writer) + { + return $writer->write('echo Nette\Utils\Html::el(NULL, %node.array)->attributes()'); + } + + + /** + * {attr ...} + * @deprecated + */ + public function macroOldAttr(MacroNode $node) + { + trigger_error('Macro {attr} is deprecated; use n:attr="..." instead.', E_USER_DEPRECATED); + return Nette\Utils\Strings::replace($node->args . ' ', '#\)\s+#', ')->'); + } + + + /** + * {dump ...} + */ + public function macroDump(MacroNode $node, PhpWriter $writer) + { + $args = $writer->formatArgs(); + return 'Nette\Diagnostics\Debugger::barDump(' . ($node->args ? "array(" . $writer->write('%var', $args) . " => $args)" : 'get_defined_vars()') + . ', "Template " . str_replace(dirname(dirname($template->getFile())), "\xE2\x80\xA6", $template->getFile()))'; + } + + + /** + * {debugbreak ...} + */ + public function macroDebugbreak(MacroNode $node, PhpWriter $writer) + { + return $writer->write(($node->args == NULL ? '' : 'if (!(%node.args)); else') + . 'if (function_exists("debugbreak")) debugbreak(); elseif (function_exists("xdebug_break")) xdebug_break()'); + } + + + /** + * {var ...} + * {default ...} + */ + public function macroVar(MacroNode $node, PhpWriter $writer) + { + if ($node->args === '' && $node->parentNode && $node->parentNode->name === 'switch') { + return '} else {'; + + } elseif ($node->name === 'assign') { + trigger_error('Macro {assign} is deprecated; use {var} instead.', E_USER_DEPRECATED); + } + + $var = TRUE; + $tokens = $writer->preprocess(); + $res = new Latte\MacroTokens; + while ($tokens->nextToken()) { + if ($var && $tokens->isCurrent(Latte\MacroTokens::T_SYMBOL, Latte\MacroTokens::T_VARIABLE)) { + if ($node->name === 'default') { + $res->append("'" . ltrim($tokens->currentValue(), '$') . "'"); + } else { + $res->append('$' . ltrim($tokens->currentValue(), '$')); + } + $var = NULL; + + } elseif ($tokens->isCurrent('=', '=>') && $tokens->depth === 0) { + $res->append($node->name === 'default' ? '=>' : '='); + $var = FALSE; + + } elseif ($tokens->isCurrent(',') && $tokens->depth === 0) { + $res->append($node->name === 'default' ? ',' : ';'); + $var = TRUE; + + } elseif ($var === NULL && $node->name === 'default' && !$tokens->isCurrent(Latte\MacroTokens::T_WHITESPACE)) { + throw new CompileException("Unexpected '{$tokens->currentValue()}' in {default $node->args}"); + + } else { + $res->append($tokens->currentToken()); + } + } + $out = $writer->quoteFilter($res)->joinAll(); + return $node->name === 'default' ? "extract(array($out), EXTR_SKIP)" : $out; + } + + + /** + * {= ...} + * {? ...} + */ + public function macroExpr(MacroNode $node, PhpWriter $writer) + { + return $writer->write(($node->name === '?' ? '' : 'echo ') . '%modify(%node.args)'); + } + + + /********************* run-time helpers ****************d*g**/ + + + /** + * Includes subtemplate. + * @param mixed included file name or template + * @param array parameters + * @param Nette\Templating\ITemplate current template + * @return Nette\Templating\Template + */ + public static function includeTemplate($destination, array $params, Nette\Templating\ITemplate $template) + { + if ($destination instanceof Nette\Templating\ITemplate) { + $tpl = $destination; + + } elseif ($destination == NULL) { // intentionally == + throw new Nette\InvalidArgumentException("Template file name was not specified."); + + } elseif ($template instanceof Nette\Templating\IFileTemplate) { + if (!preg_match('#/|\\\\|[a-z]:#iA', $destination)) { + $destination = dirname($template->getFile()) . '/' . $destination; + } + $tpl = clone $template; + $tpl->setFile($destination); + + } else { + throw new Nette\NotSupportedException('Macro {include "filename"} is supported only with Nette\Templating\IFileTemplate.'); + } + + $tpl->setParameters($params); // interface? + return $tpl; + } + + + /** + * Initializes local & global storage in template. + * @return \stdClass + */ + public static function initRuntime(Nette\Templating\ITemplate $template, $templateId) + { + // local storage + if (isset($template->_l)) { + $local = $template->_l; + unset($template->_l); + } else { + $local = new \stdClass; + } + $local->templates[$templateId] = $template; + + // global storage + if (!isset($template->_g)) { + $template->_g = new \stdClass; + } + + return array($local, $template->_g); + } + +} diff -Nru php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Macros/FormMacros.php php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Macros/FormMacros.php --- php-nette-2.1.4/Nette-2.1.5/Nette/Latte/Macros/FormMacros.php 1970-01-01 00:00:00.000000000 +0000 +++ php-nette-2.1.5/Nette-2.1.5/Nette/Latte/Macros/FormMacros.php 2014-08-28 13:13:57.000000000 +0000 @@ -0,0 +1,276 @@ +addMacro('form', array($me, 'macroForm'), 'Nette\Latte\Macros\FormMacros::renderFormEnd($_form)'); + $me->addMacro('formContainer', array($me, 'macroFormContainer'), '$_form = array_pop($_formStack)'); + $me->addMacro('label', array($me, 'macroLabel'), array($me, 'macroLabelEnd')); + $me->addMacro('input', array($me, 'macroInput'), NULL, array($me, 'macroInputAttr')); + $me->addMacro('name', array($me, 'macroName'), array($me, 'macroNameEnd'), array($me, 'macroNameAttr')); + $me->addMacro('inputError', array($me, 'macroInputError')); + } + + + /********************* macros ****************d*g**/ + + + /** + * {form ...} + */ + public function macroForm(MacroNode $node, PhpWriter $writer) + { + if ($node->htmlNode && strtolower($node->htmlNode->name) === 'form') { + throw new CompileException('Did you mean ?'); + } + $name = $node->tokenizer->fetchWord(); + if ($name === FALSE) { + throw new CompileException("Missing form name in {{$node->name}}."); + } + $node->tokenizer->reset(); + return $writer->write( + 'Nette\Latte\Macros\FormMacros::renderFormBegin($form = $_form = ' + . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '') + . '$_control[%node.word], %node.array)' + ); + } + + + /** + * {formContainer ...} + */ + public function macroFormContainer(MacroNode $node, PhpWriter $writer) + { + $name = $node->tokenizer->fetchWord(); + if ($name === FALSE) { + throw new CompileException("Missing form name in {{$node->name}}."); + } + $node->tokenizer->reset(); + return $writer->write( + '$_formStack[] = $_form; $formContainer = $_form = ' . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '') . '$_form[%node.word]' + ); + } + + + /** + * {label ...} + */ + public function macroLabel(MacroNode $node, PhpWriter $writer) + { + $words = $node->tokenizer->fetchWords(); + if (!$words) { + throw new CompileException("Missing name in {{$node->name}}."); + } + $name = array_shift($words); + return $writer->write( + ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; if ($_label = $_input' : 'if ($_label = $_form[%0.word]') + . '->%1.raw) echo $_label' + . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''), + $name, + $words ? ('getLabelPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')') : 'getLabel()' + ); + } + + + /** + * {/label} + */ + public function macroLabelEnd(MacroNode $node, PhpWriter $writer) + { + if ($node->content != NULL) { + $node->openingCode = rtrim($node->openingCode, '?> ') . '->startTag() ?>'; + return $writer->write('if ($_label) echo $_label->endTag()'); + } + } + + + /** + * {input ...} + */ + public function macroInput(MacroNode $node, PhpWriter $writer) + { + $words = $node->tokenizer->fetchWords(); + if (!$words) { + throw new CompileException("Missing name in {{$node->name}}."); + } + $name = array_shift($words); + return $writer->write( + ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; echo $_input' : 'echo $_form[%0.word]') + . '->%1.raw' + . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''), + $name, + $words ? 'getControlPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')' : 'getControl()' + ); + } + + + /** + * deprecated n:input + */ + public function macroInputAttr(MacroNode $node, PhpWriter $writer) + { + if (strtolower($node->htmlNode->name) === 'input') { + return $this->macroNameAttr($node, $writer); + } else { + throw new CompileException("Use n:name instead of n:input."); + } + } + + + /** + * , ,