Nette-2.1.0/ 40777 0 0 0 12261522617 5614 5Nette-2.1.0/license.txt100777 0 0 5337 12261522617 10107 0Licenses ======== 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) Nette-2.1.0/Nette/ 40777 0 0 0 12261522617 6673 5Nette-2.1.0/Nette/Application/ 40777 0 0 0 12261522616 11135 5Nette-2.1.0/Nette/Application/Application.php100777 0 0 13314 12261522616 14233 0httpRequest = $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()); $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); } } Nette-2.1.0/Nette/Application/Diagnostics/ 40777 0 0 0 12261522616 13404 5Nette-2.1.0/Nette/Application/Diagnostics/RoutingPanel.php100777 0 0 7476 12261522616 16642 0addPanel(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; } } Nette-2.1.0/Nette/Application/Diagnostics/templates/ 40777 0 0 0 12261522616 15402 5Nette-2.1.0/Nette/Application/Diagnostics/templates/RoutingPanel.panel.phtml100777 0 0 6030 12261522616 22254 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? Class Mask Defaults Module Request
$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()) ?>

Nette-2.1.0/Nette/Application/Diagnostics/templates/RoutingPanel.tab.phtml100777 0 0 2666 12261522616 21736 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 ?> Nette-2.1.0/Nette/Application/ErrorPresenter.php100777 0 0 1476 12261522616 14737 0parameters['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()); } } Nette-2.1.0/Nette/Application/exceptions.php100777 0 0 2261 12261522616 14130 0 504 ? $this->defaultCode : $code, $previous); } } /** * Forbidden request exception - access denied. */ class ForbiddenRequestException extends BadRequestException { /** @var int */ protected $defaultCode = 403; } Nette-2.1.0/Nette/Application/IPresenter.php100777 0 0 574 12261522616 14014 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); } Nette-2.1.0/Nette/Application/IResponse.php100777 0 0 705 12261522616 13637 0context = $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; } } Nette-2.1.0/Nette/Application/PresenterFactory.php100777 0 0 12320 12261522616 15263 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'; } } Nette-2.1.0/Nette/Application/Request.php100777 0 0 7314 12261522616 13403 0name = $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]); } } Nette-2.1.0/Nette/Application/Responses/ 40777 0 0 0 12261522616 13116 5Nette-2.1.0/Nette/Application/Responses/FileResponse.php100777 0 0 5656 12261522616 16341 0file = $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); } } Nette-2.1.0/Nette/Application/Responses/ForwardResponse.php100777 0 0 1554 12261522616 17057 0request = $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) { } } Nette-2.1.0/Nette/Application/Responses/JsonResponse.php100777 0 0 3077 12261522616 16366 0payload = $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); } } Nette-2.1.0/Nette/Application/Responses/RedirectResponse.php100777 0 0 2143 12261522616 17207 0url = (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); } } Nette-2.1.0/Nette/Application/Responses/TextResponse.php100777 0 0 1705 12261522616 16375 0source = $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; } } } Nette-2.1.0/Nette/Application/Routers/ 40777 0 0 0 12261522616 12600 5Nette-2.1.0/Nette/Application/Routers/CliRouter.php100777 0 0 4445 12261522616 15330 0defaults = $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; } } Nette-2.1.0/Nette/Application/Routers/Route.php100777 0 0 53713 12261522616 14540 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; } } Nette-2.1.0/Nette/Application/Routers/RouteList.php100777 0 0 5576 12261522616 15360 0module = $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; } } Nette-2.1.0/Nette/Application/Routers/SimpleRouter.php100777 0 0 7031 12261522616 16044 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; } } Nette-2.1.0/Nette/Application/templates/ 40777 0 0 0 12261522616 13133 5Nette-2.1.0/Nette/Application/templates/error.phtml100777 0 0 3106 12261522616 15432 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

Nette-2.1.0/Nette/Application/UI/ 40777 0 0 0 12261522617 11453 5Nette-2.1.0/Nette/Application/UI/BadSignalException.php100777 0 0 605 12261522616 15747 0template === 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; } } Nette-2.1.0/Nette/Application/UI/Form.php100777 0 0 6170 12261522616 13172 0monitor('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."); } } } Nette-2.1.0/Nette/Application/UI/InvalidLinkException.php100777 0 0 501 12261522616 16322 0component = $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) { trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR); } } } Nette-2.1.0/Nette/Application/UI/Multiplier.php100777 0 0 1140 12261522617 14406 0factory = Nette\Utils\Callback::check($factory); } protected function createComponent($name) { return call_user_func($this->factory, $name, $this); } } Nette-2.1.0/Nette/Application/UI/Presenter.php100777 0 0 107345 12261522617 14305 0request; } /** * 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; } } Nette-2.1.0/Nette/Application/UI/PresenterComponent.php100777 0 0 25053 12261522617 16143 0lookup('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("Invalid value for persistent parameter '$name' in '{$this->getName()}', expected " . ($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); } } } Nette-2.1.0/Nette/Application/UI/PresenterComponentReflection.php100777 0 0 10712 12261522617 20152 0getName() : $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; } } Nette-2.1.0/Nette/Caching/ 40777 0 0 0 12261522617 10227 5Nette-2.1.0/Nette/Caching/Cache.php100777 0 0 21203 12261522617 12061 0storage = $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; } } Nette-2.1.0/Nette/Caching/IStorage.php100777 0 0 1757 12261522617 12567 0cache = $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; } } Nette-2.1.0/Nette/Caching/Storages/ 40777 0 0 0 12261522617 12016 5Nette-2.1.0/Nette/Caching/Storages/DevNullStorage.php100777 0 0 2231 12261522617 15523 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; } } } Nette-2.1.0/Nette/Caching/Storages/FileStorage.php100777 0 0 23236 12261522617 15061 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, 'r+b'); // @ - file may not exist if (!$handle) { $handle = fopen($cacheFile, 'wb'); if (!$handle) { return; } } $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 } } } Nette-2.1.0/Nette/Caching/Storages/IJournal.php100777 0 0 1240 12261522617 14347 0prefix = $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); } } } } Nette-2.1.0/Nette/Caching/Storages/MemoryStorage.php100777 0 0 2634 12261522617 15431 0data[$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(); } } } Nette-2.1.0/Nette/Caching/Storages/PhpFileStorage.php100777 0 0 1613 12261522617 15504 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'; } } Nette-2.1.0/Nette/Caching/Storages/SQLiteStorage.php100777 0 0 5624 12261522617 15324 0pdo = 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); } } } Nette-2.1.0/Nette/common/ 40777 0 0 0 12261522617 10163 5Nette-2.1.0/Nette/common/ArrayHash.php100777 0 0 3314 12261522617 12657 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 InvalidArgumentException("Key must be either a string or an integer, " . gettype($key) ." given."); } $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); } } Nette-2.1.0/Nette/common/ArrayList.php100777 0 0 4026 12261522617 12710 0list); } /** * 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); } } Nette-2.1.0/Nette/common/Callback.php100777 0 0 7025 12261522617 12474 0invoke() 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; } } } Nette-2.1.0/Nette/common/Configurator.php100777 0 0 17024 12261522617 13462 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); } } Nette-2.1.0/Nette/common/DateTime.php100777 0 0 3212 12261522617 12466 0format('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; } } Nette-2.1.0/Nette/common/Environment.php100777 0 0 16367 12261522617 13335 0expand($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; } } } Nette-2.1.0/Nette/common/exceptions.php100777 0 0 5670 12261522617 13165 0context = $context; trigger_error(__CLASS__ . ' is deprecated, use ErrorException.', E_USER_DEPRECATED); } } Nette-2.1.0/Nette/common/Framework.php100777 0 0 1130 12261522617 12724 0frozen = 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."); } } } Nette-2.1.0/Nette/common/IFreezable.php100777 0 0 776 12261522617 12776 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 * @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) { 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); } } /** * The exception that indicates invalid image file. */ class UnknownImageFileException extends \Exception { } Nette-2.1.0/Nette/common/Object.php100777 0 0 10222 12261522617 12217 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); } } Nette-2.1.0/Nette/common/ObjectMixin.php100777 0 0 25512 12261522617 13234 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]) && $methods[$name] !== 0) { // magic @methods list($op, $rp, $type) = $methods[$name]; if (!$rp) { throw new MemberAccessException("Magic method $class::$name() has not corresponding property $$op."); } elseif (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); } else { $methods[$name] = array($prop, NULL, NULL); } } 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; } } Nette-2.1.0/Nette/common/shortcuts.php100777 0 0 1561 12261522617 13035 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)); } } Nette-2.1.0/Nette/ComponentModel/Container.php100777 0 0 14664 12261522617 14404 0getName(); } if (is_int($name)) { $name = (string) $name; } elseif (!is_string($name)) { throw new Nette\InvalidArgumentException("Component name must be integer or string, " . gettype($name) . " given."); } 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("Component name must be integer or string, " . gettype($name) . " given."); } 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; } } Nette-2.1.0/Nette/ComponentModel/IComponent.php100777 0 0 1357 12261522617 14510 0current() 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); } } Nette-2.1.0/Nette/Database/ 40777 0 0 0 12261522617 10377 5Nette-2.1.0/Nette/Database/Connection.php100777 0 0 13415 12261522617 13333 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(); } } Nette-2.1.0/Nette/Database/Context.php100777 0 0 7753 12261522617 12650 0connection = $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); } } Nette-2.1.0/Nette/Database/Diagnostics/ 40777 0 0 0 12261522617 12646 5Nette-2.1.0/Nette/Database/Diagnostics/ConnectionPanel.php100777 0 0 13373 12261522617 16565 0onQuery[] = 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

' : '') . '
' : ''; } } Nette-2.1.0/Nette/Database/Drivers/ 40777 0 0 0 12261522617 12015 5Nette-2.1.0/Nette/Database/Drivers/MsSqlDriver.php100777 0 0 6034 12261522617 15044 0connection = $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; } } Nette-2.1.0/Nette/Database/Drivers/MySqlDriver.php100777 0 0 14526 12261522617 15077 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; } } Nette-2.1.0/Nette/Database/Drivers/OciDriver.php100777 0 0 6567 12261522617 14532 0connection = $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; } } Nette-2.1.0/Nette/Database/Drivers/OdbcDriver.php100777 0 0 5730 12261522617 14656 0connection = $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; } } Nette-2.1.0/Nette/Database/Drivers/PgSqlDriver.php100777 0 0 14346 12261522617 15060 0connection = $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, ad.adsrc::varchar AS default, coalesce(co.contype = 'p' AND strpos(ad.adsrc, 'nextval') = 1, FALSE) AS autoincrement, coalesce(co.contype = 'p', FALSE) AS primary, substring(ad.adsrc 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; } } Nette-2.1.0/Nette/Database/Drivers/Sqlite2Driver.php100777 0 0 1270 12261522617 15325 0connection = $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'] == '1', '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; } } Nette-2.1.0/Nette/Database/Drivers/SqlsrvDriver.php100777 0 0 15267 12261522617 15327 0connection = $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; } } Nette-2.1.0/Nette/Database/Helpers.php100777 0 0 16325 12261522617 12641 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 - extreme 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; } } Nette-2.1.0/Nette/Database/IReflection.php100777 0 0 3023 12261522617 13411 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; } } Nette-2.1.0/Nette/Database/Reflection/DiscoveredReflection.php100777 0 0 11127 12261522617 17426 0connection = $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); }); } } } Nette-2.1.0/Nette/Database/Reflection/exceptions.php100777 0 0 656 12261522617 15452 0connection = $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) { $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(); } } Nette-2.1.0/Nette/Database/Row.php100777 0 0 1724 12261522617 11763 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); } } Nette-2.1.0/Nette/Database/SqlLiteral.php100777 0 0 1400 12261522617 13257 0value = (string) $value; $this->parameters = $parameters; } /** * @return array */ public function getParameters() { return $this->parameters; } /** * @return string */ public function __toString() { return $this->value; } } Nette-2.1.0/Nette/Database/SqlPreprocessor.php100777 0 0 14151 12261522617 14400 0connection = $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 '?'; } } } Nette-2.1.0/Nette/Database/Table/ 40777 0 0 0 12261522617 11426 5Nette-2.1.0/Nette/Database/Table/ActiveRow.php100777 0 0 16142 12261522617 14166 0data = $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) { 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; } } Nette-2.1.0/Nette/Database/Table/GroupedSelection.php100777 0 0 14777 12261522617 15552 0refTable = $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; } } Nette-2.1.0/Nette/Database/Table/IRow.php100777 0 0 1052 12261522617 13115 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_get_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 = (array) $this->cache->load($this->getGeneralCacheKey()); $accessed = (array) $this->accessedColumns; $needSave = array_intersect_key($accessed, $previousAccessed) !== $accessed; if ($needSave) { $this->cache->save($this->getGeneralCacheKey(), $previousAccessed + $accessed); $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 indenpendent 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]))) { if ($this->sqlBuilder->getLimit()) { $generalCacheKey = $this->generalCacheKey; $primaries = array(); foreach ((array) $this->rows as $row) { $primary = $row->getPrimary(); $primaries[] = is_array($primary) ? array_values($primary) : $primary; } } $this->previousAccessedColumns = array(); $this->emptyResultSet(FALSE); if ($this->sqlBuilder->getLimit()) { $this->sqlBuilder->setLimit(NULL, NULL); $this->wherePrimary($primaries); $this->generalCacheKey = $generalCacheKey; } $this->dataRefreshed = TRUE; if ($key === NULL) { // we need to move iterator in resultset $this->execute(); 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); if ($data instanceof Nette\Database\SqlLiteral || $this->primary === NULL) { return $return->getRowCount(); } $primaryKey = $this->connection->getInsertId($this->getPrimarySequence()); 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(); $this->loadRefCache(); 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]); } } Nette-2.1.0/Nette/Database/Table/SqlBuilder.php100777 0 0 32033 12261522617 14326 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); } } } Nette-2.1.0/Nette/DI/ 40777 0 0 0 12261522617 7167 5Nette-2.1.0/Nette/Diagnostics/ 40777 0 0 0 12261522617 11142 5Nette-2.1.0/Nette/Diagnostics/Bar.php100777 0 0 4350 12261522617 12461 0panels[$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'; } } Nette-2.1.0/Nette/Diagnostics/BlueScreen.php100777 0 0 7776 12261522617 14023 0panels, 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); $out = preg_replace_callback('#">\$(\w+)( )?
#', function($m) use ($vars) { return isset($vars[$m[1]]) ? '" title="' . str_replace('"', '"', 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; } } Nette-2.1.0/Nette/Diagnostics/Debugger.php100777 0 0 50224 12261522617 13522 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 = (isset($_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. * @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. * @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); } } Nette-2.1.0/Nette/Diagnostics/DefaultBarPanel.php100777 0 0 1706 12261522617 14750 0id = $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(); } } Nette-2.1.0/Nette/Diagnostics/Dumper.php100777 0 0 23765 12261522617 13244 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 " . htmlspecialchars($file, ENT_IGNORE) . ":$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 = json_encode($var); return '' . $var . (strpos($var, '.') === FALSE ? '.0' : '') . "\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['file']) && strpos($item['file'], __DIR__) === 0) { continue; } elseif (!isset($item['file'], $item['line']) || !is_file($item['file'])) { break; } else { $lines = file($item['file']); $line = $lines[$item['line'] - 1]; return array( $item['file'], $item['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))); } } Nette-2.1.0/Nette/Diagnostics/FireLogger.php100777 0 0 11757 12261522617 14033 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"; } } } Nette-2.1.0/Nette/Diagnostics/Helpers.php100777 0 0 6060 12261522617 13357 0href(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); } } Nette-2.1.0/Nette/Diagnostics/IBarPanel.php100777 0 0 747 12261522617 13540 0directory)) { 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']); } } Nette-2.1.0/Nette/Diagnostics/OutputDebugger.php100777 0 0 3155 12261522617 14724 0start(); } 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 . '
'; } } Nette-2.1.0/Nette/Diagnostics/templates/ 40777 0 0 0 12261522617 13140 5Nette-2.1.0/Nette/Diagnostics/templates/bar.css100777 0 0 17152 12261522617 14544 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; border-radius: 3px; box-shadow: 1px 1px 10px rgba(0, 0, 0, .15); } #nette-debug-bar:hover { opacity: 1; } #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; 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; } #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; } } Nette-2.1.0/Nette/Diagnostics/templates/bar.dumps.panel.phtml100777 0 0 1502 12261522617 17275 0

Dumped variables

data as $item): ?>

Nette-2.1.0/Nette/Diagnostics/templates/bar.dumps.tab.phtml100777 0 0 2202 12261522617 16742 0data)) { return; } ?> variables Nette-2.1.0/Nette/Diagnostics/templates/bar.errors.panel.phtml100777 0 0 1305 12261522617 17462 0

Errors

data as $item => $count): list($file, $line, $message) = explode('|', $item, 3) ?>
Nette-2.1.0/Nette/Diagnostics/templates/bar.errors.tab.phtml100777 0 0 2441 12261522617 17133 0data)) { return; } ?> data), $sum > 1 ? ' errors' : ' error' ?> Nette-2.1.0/Nette/Diagnostics/templates/bar.js100777 0 0 20571 12261522617 14367 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 ?>
    • ×
Nette-2.1.0/Nette/Diagnostics/templates/bar.time.tab.phtml100777 0 0 2552 12261522617 16560 0 ms Nette-2.1.0/Nette/Diagnostics/templates/bluescreen.css100777 0 0 13621 12261522617 16124 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; } body { margin: 0 0 2em; padding: 0; } #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; } Nette-2.1.0/Nette/Diagnostics/templates/bluescreen.phtml100777 0 0 47026 12261522617 16466 0getSeverity()])) ? Debugger::$errorTypes[$exception->getSeverity()] : get_class($exception); $counter = 0; ?> <?php echo htmlspecialchars($title) ?>

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

getMessage(), ENT_IGNORE) ?> getMessage())) ?>" id="netteBsSearch">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 "
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 )
Nette-2.1.0/Nette/Diagnostics/templates/dumper.css100777 0 0 2003 12261522617 15241 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); } Nette-2.1.0/Nette/Diagnostics/templates/dumper.js100777 0 0 3140 12261522617 15070 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 || link.className.indexOf('nette-toggle') < 0); 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 ? 'show' : 'hide'](); 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 }); } }); }; })(); Nette-2.1.0/Nette/Diagnostics/templates/error.phtml100777 0 0 1166 12261522617 15443 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

Nette-2.1.0/Nette/Diagnostics/templates/netteQ.js100777 0 0 22566 12261522617 15071 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; }; })(); Nette-2.1.0/Nette/DI/Compiler.php100777 0 0 25005 12261522617 11574 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) { $services = isset($config['services']) ? $config['services'] : array(); $factories = isset($config['factories']) ? $config['factories'] : array(); $all = array_merge($services, $factories); uasort($all, function($a, $b) { return strcmp(Config\Helpers::isInheriting($a), Config\Helpers::isInheriting($b)); }); if (!empty($config['factories'])) { trigger_error("Section 'factories' is deprecated, move definitions to section 'services' and append key 'autowired: no'.", E_USER_DEPRECATED); } 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 && interface_exists($config->value)) { $config = array('class' => NULL, 'implement' => $config->value, 'factory' => array_shift($config->attributes)); } elseif (!is_array($config)) { $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("Unknown or deprecated key '" . implode("', '", $error) . "' in definition of service."); } $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; } } Nette-2.1.0/Nette/DI/CompilerExtension.php100777 0 0 4525 12261522617 13455 0compiler = $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) { } } Nette-2.1.0/Nette/DI/Config/ 40777 0 0 0 12261522617 10374 5Nette-2.1.0/Nette/DI/Config/Adapters/ 40777 0 0 0 12261522617 12137 5Nette-2.1.0/Nette/DI/Config/Adapters/IniAdapter.php100777 0 0 7440 12261522617 14775 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("The '$prefix$key' item must be scalar or array, " . gettype($val) ." given."); } } } } Nette-2.1.0/Nette/DI/Config/Adapters/NeonAdapter.php100777 0 0 4355 12261522617 15157 0process((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); } } Nette-2.1.0/Nette/DI/Config/Adapters/PhpAdapter.php100777 0 0 1360 12261522617 15000 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; } } Nette-2.1.0/Nette/DI/Config/IAdapter.php100777 0 0 1036 12261522617 12676 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; } } Nette-2.1.0/Nette/DI/Container.php100777 0 0 20502 12261522617 11741 0parameters = $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('Service name must be a non-empty string, ' . gettype($name) . ' given.'); } 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('Passing factories to ' . __METHOD__ . '() is deprecated; pass the object itself.', 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('Service must be a object, ' . gettype($service) . ' given.'); } $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("Circular reference detected for services: " . 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('Service must be object, ' . gettype($service) . ' given.'); } 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); } } Nette-2.1.0/Nette/DI/ContainerBuilder.php100777 0 0 54216 12261522617 13261 0definitions[$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 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 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 has not @return annotation."); } $returnType = Reflection\AnnotationsParser::expandClassName($returnType, $rc); if (!class_exists($returnType)) { throw new ServiceCreationException("Please check a @return annotation of the $method method. Class '$returnType' cannot be found."); } $def->setClass($returnType); } if ($method->getName() === 'get') { if ($method->getParameters()) { throw new ServiceCreationException("Method $method 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) { if (!$def->class) { throw new ServiceCreationException("Class and factory are missing in service '$name' definition."); } $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('Circular reference detected for services: ' . 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]; } } } if (!is_callable($factory)) { throw new ServiceCreationException("Factory '" . Nette\Utils\Callback::toString($factory) . "' is not callable."); } try { $reflection = Nette\Utils\Callback::toReflection($factory); } catch (\ReflectionException $e) { throw new ServiceCreationException("Missing factory '" . Nette\Utils\Callback::toString($factory) . "'."); } $def->class = preg_replace('#[|\s].*#', '', $reflection->getAnnotation('return')); if ($def->class && !class_exists($def->class) && $def->class[0] !== '\\' && $reflection instanceof \ReflectionMethod) { $def->class = $reflection->getDeclaringClass()->getNamespaceName() . '\\' . $def->class; } } 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("Expected class, method or property, " . PhpHelpers::dump($entity) . " given."); } 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.'); } } Nette-2.1.0/Nette/DI/Diagnostics/ 40777 0 0 0 12261522617 11436 5Nette-2.1.0/Nette/DI/Diagnostics/ContainerPanel.php100777 0 0 3775 12261522617 15165 0container = $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 = $factories = array(); foreach (Nette\Reflection\ClassType::from($this->container)->getMethods() as $method) { if (preg_match('#^create(Service)?_*(.+)\z#', $method->getName(), $m)) { if ($m[1]) { $services[str_replace('__', '.', strtolower(substr($m[2], 0, 1)) . substr($m[2], 1))] = $method->getAnnotation('return'); } elseif ($method->isPublic()) { $factories['create' . $m[2]] = $method->getAnnotation('return'); } } } ksort($services); ksort($factories); $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); } } Nette-2.1.0/Nette/DI/Diagnostics/templates/ 40777 0 0 0 12261522617 13434 5Nette-2.1.0/Nette/DI/Diagnostics/templates/ContainerPanel.panel.phtml100777 0 0 4137 12261522617 20607 0

container) ?>

Parameters

container->parameters); ?>

Services

$class): ?> findByType($class)); ?>
Name Autowired Service Tags
TRUE)); ?> TRUE)); } ?>

Factories

$class): ?>
Method Returns
()
Nette-2.1.0/Nette/DI/Diagnostics/templates/ContainerPanel.tab.phtml100777 0 0 1427 12261522617 20255 0   Nette-2.1.0/Nette/DI/exceptions.php100777 0 0 643 12261522617 12144 0getConfig() as $name => $value) { $class->methods['initialize']->addBody('define(?, ?);', array($name, $value)); } } } Nette-2.1.0/Nette/DI/Extensions/ExtensionsExtension.php100777 0 0 1016 12261522617 16171 0getConfig() as $name => $class) { $this->compiler->addExtension($name, new $class); } } } Nette-2.1.0/Nette/DI/Extensions/NetteAccessor.php100777 0 0 2036 12261522617 14702 0container = $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; } } Nette-2.1.0/Nette/DI/Extensions/NetteExtension.php100777 0 0 40570 12261522617 15141 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."); } } } Nette-2.1.0/Nette/DI/Extensions/PhpExtension.php100777 0 0 2605 12261522617 14566 0methods['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.'); } } } } Nette-2.1.0/Nette/DI/Helpers.php100777 0 0 11427 12261522617 11427 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('Circular reference detected for variables: ' . implode(', ', array_keys($recursive)) . '.'); } else { $val = Nette\Utils\Arrays::get($params, explode('.', $part)); 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; } } Nette-2.1.0/Nette/DI/ServiceDefinition.php100777 0 0 4341 12261522617 13413 0class = $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; } } Nette-2.1.0/Nette/DI/Statement.php100777 0 0 1053 12261522617 11743 0entity = $entity; $this->arguments = $arguments; } } Nette-2.1.0/Nette/Forms/ 40777 0 0 0 12261522617 7761 5Nette-2.1.0/Nette/Forms/Container.php100777 0 0 27067 12261522617 12550 0getForm(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('First parameter must be an array, ' . gettype($values) . ' given.'); } 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.'); } } Nette-2.1.0/Nette/Forms/ControlGroup.php100777 0 0 4250 12261522617 13230 0controls = 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; } } Nette-2.1.0/Nette/Forms/Controls/ 40777 0 0 0 12261522617 11564 5Nette-2.1.0/Nette/Forms/Controls/BaseControl.php100777 0 0 35054 12261522617 14637 0monitor('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**/ /** * Equal validator: are control's value and second parameter equal? * @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); } /** * Filled validator: 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(); } /** * Valid validator: is control valid? * @return bool */ public static function validateValid(IControl $control) { return $control->rules->validate(); } /** * Rangle validator: 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); } /** * Min-length validator: has control's value minimal count/length? * @return bool */ public static function validateMinLength(IControl $control, $length) { return static::validateLength($control, array($length, NULL)); } /** * Max-length validator: 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; } } Nette-2.1.0/Nette/Forms/Controls/Button.php100777 0 0 2361 12261522617 13652 0control->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), )); } } Nette-2.1.0/Nette/Forms/Controls/Checkbox.php100777 0 0 3572 12261522617 14132 0control->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('Value must be scalar or NULL, ' . gettype($value) . ' given.'); } $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; } } Nette-2.1.0/Nette/Forms/Controls/CheckboxList.php100777 0 0 4144 12261522617 14762 0control->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, '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, 'value' => $key, )); } /** * @return Nette\Utils\Html */ public function getLabelPart($key) { return parent::getLabel($this->items[$key])->for($this->getHtmlId() . '-' . $key); } } Nette-2.1.0/Nette/Forms/Controls/ChoiceControl.php100777 0 0 5515 12261522617 15136 0setItems($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 && !isset($this->items[(string) $value])) { throw new Nette\InvalidArgumentException("Value '$value' is out of range of current items."); } $this->value = $value === NULL ? NULL : key(array((string) $value => NULL)); return $this; } /** * Returns selected key. * @return scalar */ public function getValue() { return isset($this->items[$this->value]) ? $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; } } Nette-2.1.0/Nette/Forms/Controls/CsrfProtection.php100777 0 0 3345 12261522617 15346 0setOmitted()->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; } /** * Generates control's HTML element. * * @return Nette\Utils\Html */ public function getControl() { return parent::getControl()->value($this->getToken()); } /** * @return bool */ public static function validateCsrf(CsrfProtection $control) { return $control->getValue() === $control->getToken(); } /********************* 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; } } Nette-2.1.0/Nette/Forms/Controls/HiddenField.php100777 0 0 3402 12261522617 14533 0control->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('Value must be scalar or NULL, ' . gettype($value) . ' given.'); } 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); } } Nette-2.1.0/Nette/Forms/Controls/ImageButton.php100777 0 0 1765 12261522617 14624 0control->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() . '[]'; } } Nette-2.1.0/Nette/Forms/Controls/MultiChoiceControl.php100777 0 0 6607 12261522617 16154 0setItems($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('Value must be array or NULL, ' . gettype($values) . ' given.'); } $flip = array(); foreach ($values as $value) { if (!is_scalar($value) && !method_exists($value, '__toString')) { throw new Nette\InvalidArgumentException('Values must be scalar, ' . gettype($value) . ' given.'); } $flip[(string) $value] = TRUE; } $values = array_keys($flip); if ($diff = array_diff($values, array_keys($this->items))) { throw new Nette\InvalidArgumentException("Values '" . implode("', '", $diff) . "' are out of range of current items."); } $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() . '[]'; } } Nette-2.1.0/Nette/Forms/Controls/MultiSelectBox.php100777 0 0 3242 12261522617 15301 0 $value) { unset($items[$key]); if (is_array($value)) { foreach ($value as $val) { $items[$key][(string) $val] = $val; } } else { $items[(string) $value] = $value; } } } $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(); } } Nette-2.1.0/Nette/Forms/Controls/RadioList.php100777 0 0 6551 12261522617 14276 0control->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('Partial ' . __METHOD__ . '() is deprecated; use getControlPart() instead.', 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->label->attrs, $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('Partial ' . __METHOD__ . '() is deprecated; use getLabelPart() instead.', 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); } } Nette-2.1.0/Nette/Forms/Controls/SelectBox.php100777 0 0 5053 12261522617 14270 0getItems(); $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) { foreach ($items as $key => $value) { unset($items[$key]); if (is_array($value)) { foreach ($value as $val) { $items[$key][(string) $val] = $val; } } else { $items[(string) $value] = $value; } } } $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->addError(Nette\Forms\Rules::$defaultMessages[self::VALID]); } } } Nette-2.1.0/Nette/Forms/Controls/SubmitButton.php100777 0 0 5713 12261522617 15042 0control->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(); } } Nette-2.1.0/Nette/Forms/Controls/TextArea.php100777 0 0 1376 12261522617 14121 0control->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); } } Nette-2.1.0/Nette/Forms/Controls/TextBase.php100777 0 0 12110 12261522617 14127 0rawValue = $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; $this->control->maxlength = is_scalar($tmp) ? $tmp : NULL; } return parent::addRule($operation, $message, $arg); } /********************* validators ****************d*g**/ /** * Email validator: is control's value valid email address? * @param TextBase * @return bool */ public static function validateEmail(TextBase $control) { return Validators::isEmail($control->getValue()); } /** * URL validator: is control's value valid URL? * @param TextBase * @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); } /** * Regular expression validator: matches control's value regular expression? * @param TextBase * @param string * @return bool */ public static function validatePattern(TextBase $control, $pattern) { return (bool) Strings::match($control->getValue(), "\x01^($pattern)\\z\x01u"); } /** * Integer validator: is a control's value decimal number? * @param TextBase * @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; } /** * Float validator: is a control's value float number? * @param TextBase * @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); } } Nette-2.1.0/Nette/Forms/Controls/TextInput.php100777 0 0 4051 12261522617 14341 0control->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 && $input->type !== 'text') { $input->min = isset($rule->arg[0]) && is_scalar($rule->arg[0]) ? $rule->arg[0] : NULL; $input->max = isset($rule->arg[1]) && is_scalar($rule->arg[1]) ? $rule->arg[1] : NULL; } elseif ($rule->operation === Nette\Forms\Form::PATTERN && is_scalar($rule->arg)) { $input->pattern = $rule->arg; } } if ($input->type !== 'password') { $input->value = $this->rawValue === '' ? $this->translate($this->emptyValue) : $this->rawValue; } return $input; } } Nette-2.1.0/Nette/Forms/Controls/UploadControl.php100777 0 0 6630 12261522617 15167 0control->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**/ /** * FileSize validator: is file size in limit? * @param UploadControl * @param int file size 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; } /** * MimeType validator: has file specified mime type? * @param UploadControl * @param array|string 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; } /** * Image validator: 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; } } Nette-2.1.0/Nette/Forms/Form.php100777 0 0 32246 12261522617 11524 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->errors(); } /********************* 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 bool can throw exceptions? (hidden parameter) * @return string */ public function __toString() { try { return $this->getRenderer()->render($this); } catch (\Exception $e) { if (func_get_args() && func_get_arg(0)) { throw $e; } else { 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) { foreach ($control->getRules()->getToggles(TRUE) as $id => $hide) { $toggles[$id] = empty($toggles[$id]) ? $hide : TRUE; } } return $toggles; } } Nette-2.1.0/Nette/Forms/Helpers.php100777 0 0 11513 12261522617 12215 0startTag(), $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()); } } Nette-2.1.0/Nette/Forms/IControl.php100777 0 0 1725 12261522617 12330 0getValues() result? * @return bool */ function isOmitted(); /** * Returns translated string. * @param string * @param int plural count * @return string */ function translate($s, $count = NULL); } Nette-2.1.0/Nette/Forms/IFormRenderer.php100777 0 0 643 12261522617 13260 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; } } Nette-2.1.0/Nette/Forms/Rule.php100777 0 0 1431 12261522617 11500 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.', 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 elememnt visibility. * @param string element id * @param bool hide element? * @return self */ public function toggle($id, $hide = TRUE) { $this->toggles[$id] = $hide; return $this; } /** * 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); } /** * @param bool * @return array */ public function getToggles($actual = FALSE) { $toggles = $this->toggles; foreach ($actual ? $this : array() as $rule) { if ($rule->type === Rule::CONDITION) { $success = static::validateRule($rule); foreach ($rule->subRules->getToggles(TRUE) as $id => $hide) { $toggles[$id] = empty($toggles[$id]) ? ($success && $hide) : TRUE; } } } return $toggles; } /** * 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; } } Nette-2.1.0/Nette/Http/ 40777 0 0 0 12261522617 7612 5Nette-2.1.0/Nette/Http/Context.php100777 0 0 4265 12261522617 12056 0request = $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; } } Nette-2.1.0/Nette/Http/Diagnostics/ 40777 0 0 0 12261522617 12061 5Nette-2.1.0/Nette/Http/Diagnostics/SessionPanel.php100777 0 0 1347 12261522617 15302 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), "
Nette-2.1.0/Nette/Http/Diagnostics/templates/SessionPanel.tab.phtml100777 0 0 2065 12261522617 20400 0 Session Nette-2.1.0/Nette/Http/FileUpload.php100777 0 0 7751 12261522617 12461 0error = 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 $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; } } Nette-2.1.0/Nette/Http/Helpers.php100777 0 0 1706 12261522617 12031 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); } } Nette-2.1.0/Nette/Http/IRequest.php100777 0 0 5306 12261522617 12170 0url = $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 */ 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; } } Nette-2.1.0/Nette/Http/RequestFactory.php100777 0 0 16405 12261522617 13431 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); } } Nette-2.1.0/Nette/Http/Response.php100777 0 0 20311 12261522617 12236 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 && function_exists('header_remove')) { 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) && $this->getHeader('Content-Type', 'text/html') === '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() && ($info = ob_get_status(TRUE)) && $info[0]['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); } } } Nette-2.1.0/Nette/Http/Session.php100777 0 0 33371 12261522617 12075 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'] ); } } Nette-2.1.0/Nette/Http/SessionSection.php100777 0 0 12722 12261522617 13417 0session = $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; } } Nette-2.1.0/Nette/Http/Url.php100777 0 0 23616 12261522617 11215 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; } } Nette-2.1.0/Nette/Http/UrlScript.php100777 0 0 3012 12261522617 12346 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)); } } Nette-2.1.0/Nette/Http/UserStorage.php100777 0 0 11261 12261522617 12707 0sessionHandler = $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; } } Nette-2.1.0/Nette/Iterators/ 40777 0 0 0 12261522617 10647 5Nette-2.1.0/Nette/Iterators/CachingIterator.php100777 0 0 11243 12261522617 14547 0getIterator(); } elseif (!$iterator instanceof \Iterator) { $iterator = new \IteratorIterator($iterator); } } else { throw new Nette\InvalidArgumentException("Invalid argument passed to foreach resp. " . __CLASS__ . "; array or Traversable expected, " . (is_object($iterator) ? get_class($iterator) : gettype($iterator)) ." given."); } 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); } } Nette-2.1.0/Nette/Iterators/Filter.php100777 0 0 1221 12261522617 12701 0callback = Nette\Utils\Callback::check($callback); } public function accept() { return call_user_func($this->callback, $this->current(), $this->key(), $this); } } Nette-2.1.0/Nette/Iterators/Mapper.php100777 0 0 1246 12261522617 12707 0callback = Nette\Utils\Callback::check($callback); } public function current() { return call_user_func($this->callback, parent::current(), parent::key()); } } Nette-2.1.0/Nette/Iterators/RecursiveFilter.php100777 0 0 1303 12261522617 14572 0getInnerIterator()->hasChildren(); } public function getChildren() { return new static($this->getInnerIterator()->getChildren(), $this->callback); } } Nette-2.1.0/Nette/Iterators/Recursor.php100777 0 0 1770 12261522617 13271 0current(); 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); } } Nette-2.1.0/Nette/Latte/ 40777 0 0 0 12261522617 7744 5Nette-2.1.0/Nette/Latte/Compiler.php100777 0 0 36603 12261522617 12357 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); 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 ? ' />' : '>') : ">name>", $token->text); } if (empty($htmlNode->macroAttrs)) { $this->output .= $token->text; } 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(''); } } 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) { $node = $this->macroNode; if (!$node || ($node->name !== $name && '' !== $name) || $modifiers || ($args && $node->args && !Strings::startsWith("$node->args ", "$args ")) ) { $name .= $args ? ' ' : ''; throw new CompileException("Unexpected {/{$name}{$args}{$modifiers}}" . ($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(TRUE, $name, '', MacroNode::PREFIX_INNER); } else { array_unshift($right, array(FALSE, $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(FALSE, $name, $attrs[$attrName], MacroNode::PREFIX_TAG); array_unshift($right, array(TRUE, $name, '', MacroNode::PREFIX_TAG)); unset($attrs[$attrName]); } } foreach ($this->macros as $name => $foo) { if (isset($attrs[$name])) { if ($this->htmlNode->closing) { $right[] = array(TRUE, $name, '', MacroNode::PREFIX_NONE); } else { array_unshift($left, array(FALSE, $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 = $item[0] ? $this->closeMacro($item[1], $item[2]) : $this->openMacro($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 = $item[0] ? $this->closeMacro($item[1], $item[2]) : $this->openMacro($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) { $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("Unhandled macro {{$name}}"); } private static function printEndTag(MacroNode $node) { if ($node->htmlNode) { return "htmlNode->name}> for macro-attribute " . Parser::N_PREFIX . implode(' and ' . Parser::N_PREFIX, array_keys($node->htmlNode->macroAttrs)); } else { return "{/$node->name}"; } } } Nette-2.1.0/Nette/Latte/Engine.php100777 0 0 2216 12261522617 11763 0parser = 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; } } Nette-2.1.0/Nette/Latte/exceptions.php100777 0 0 657 12261522617 12726 0name = $name; $this->parentNode = $parentNode; } } Nette-2.1.0/Nette/Latte/IMacro.php100777 0 0 1260 12261522617 11726 0macro = $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); } } Nette-2.1.0/Nette/Latte/Macros/ 40777 0 0 0 12261522617 11170 5Nette-2.1.0/Nette/Latte/Macros/CacheMacro.php100777 0 0 5555 12261522617 14000 0used = 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; } } Nette-2.1.0/Nette/Latte/Macros/CoreMacros.php100777 0 0 32252 12261522617 14062 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->htmlNode) { 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 '$_ifcontent ? ob_end_flush() : ob_end_clean()'; } /** * {_$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); } } Nette-2.1.0/Nette/Latte/Macros/FormMacros.php100777 0 0 20777 12261522617 14106 0addMacro('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."); } } /** * , ,