Source of file TemplatePathStack.php
Size: 8,835 Bytes - Last Modified: 2014-03-12T23:21:18+01:00
/home/theseer/Downloads/ZendFramework-2.3.0/library/Zend/View/Resolver/TemplatePathStack.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 | <?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\View\Resolver; use SplFileInfo; use Traversable; use Zend\Stdlib\SplStack; use Zend\View\Exception; use Zend\View\Renderer\RendererInterface as Renderer; /** * Resolves view scripts based on a stack of paths */ class TemplatePathStack implements ResolverInterface { const FAILURE_NO_PATHS = 'TemplatePathStack_Failure_No_Paths'; const FAILURE_NOT_FOUND = 'TemplatePathStack_Failure_Not_Found'; /** * Default suffix to use * * Appends this suffix if the template requested does not use it. * * @var string */ protected $defaultSuffix = 'phtml'; /** * @var SplStack */ protected $paths; /** * Reason for last lookup failure * * @var false|string */ protected $lastLookupFailure = false; /** * Flag indicating whether or not LFI protection for rendering view scripts is enabled * @var bool */ protected $lfiProtectionOn = true; /**@+ * Flags used to determine if a stream wrapper should be used for enabling short tags * @var bool */ protected $useViewStream = false; protected $useStreamWrapper = false; /**@-*/ /** * Constructor * * @param null|array|Traversable $options */ public function __construct($options = null) { $this->useViewStream = (bool) ini_get('short_open_tag'); if ($this->useViewStream) { if (!in_array('zend.view', stream_get_wrappers())) { stream_wrapper_register('zend.view', 'Zend\View\Stream'); } } $this->paths = new SplStack; if (null !== $options) { $this->setOptions($options); } } /** * Configure object * * @param array|Traversable $options * @return void * @throws Exception\InvalidArgumentException */ public function setOptions($options) { if (!is_array($options) && !$options instanceof Traversable) { throw new Exception\InvalidArgumentException(sprintf( 'Expected array or Traversable object; received "%s"', (is_object($options) ? get_class($options) : gettype($options)) )); } foreach ($options as $key => $value) { switch (strtolower($key)) { case 'lfi_protection': $this->setLfiProtection($value); break; case 'script_paths': $this->addPaths($value); break; case 'use_stream_wrapper': $this->setUseStreamWrapper($value); break; case 'default_suffix': $this->setDefaultSuffix($value); break; default: break; } } } /** * Set default file suffix * * @param string $defaultSuffix * @return TemplatePathStack */ public function setDefaultSuffix($defaultSuffix) { $this->defaultSuffix = (string) $defaultSuffix; $this->defaultSuffix = ltrim($this->defaultSuffix, '.'); return $this; } /** * Get default file suffix * * @return string */ public function getDefaultSuffix() { return $this->defaultSuffix; } /** * Add many paths to the stack at once * * @param array $paths * @return TemplatePathStack */ public function addPaths(array $paths) { foreach ($paths as $path) { $this->addPath($path); } return $this; } /** * Rest the path stack to the paths provided * * @param SplStack|array $paths * @return TemplatePathStack * @throws Exception\InvalidArgumentException */ public function setPaths($paths) { if ($paths instanceof SplStack) { $this->paths = $paths; } elseif (is_array($paths)) { $this->clearPaths(); $this->addPaths($paths); } else { throw new Exception\InvalidArgumentException( "Invalid argument provided for \$paths, expecting either an array or SplStack object" ); } return $this; } /** * Normalize a path for insertion in the stack * * @param string $path * @return string */ public static function normalizePath($path) { $path = rtrim($path, '/'); $path = rtrim($path, '\\'); $path .= DIRECTORY_SEPARATOR; return $path; } /** * Add a single path to the stack * * @param string $path * @return TemplatePathStack * @throws Exception\InvalidArgumentException */ public function addPath($path) { if (!is_string($path)) { throw new Exception\InvalidArgumentException(sprintf( 'Invalid path provided; must be a string, received %s', gettype($path) )); } $this->paths[] = static::normalizePath($path); return $this; } /** * Clear all paths * * @return void */ public function clearPaths() { $this->paths = new SplStack; } /** * Returns stack of paths * * @return SplStack */ public function getPaths() { return $this->paths; } /** * Set LFI protection flag * * @param bool $flag * @return TemplatePathStack */ public function setLfiProtection($flag) { $this->lfiProtectionOn = (bool) $flag; return $this; } /** * Return status of LFI protection flag * * @return bool */ public function isLfiProtectionOn() { return $this->lfiProtectionOn; } /** * Set flag indicating if stream wrapper should be used if short_open_tag is off * * @param bool $flag * @return TemplatePathStack */ public function setUseStreamWrapper($flag) { $this->useStreamWrapper = (bool) $flag; return $this; } /** * Should the stream wrapper be used if short_open_tag is off? * * Returns true if the use_stream_wrapper flag is set, and if short_open_tag * is disabled. * * @return bool */ public function useStreamWrapper() { return ($this->useViewStream && $this->useStreamWrapper); } /** * Retrieve the filesystem path to a view script * * @param string $name * @param null|Renderer $renderer * @return string * @throws Exception\DomainException */ public function resolve($name, Renderer $renderer = null) { $this->lastLookupFailure = false; if ($this->isLfiProtectionOn() && preg_match('#\.\.[\\\/]#', $name)) { throw new Exception\DomainException( 'Requested scripts may not include parent directory traversal ("../", "..\\" notation)' ); } if (!count($this->paths)) { $this->lastLookupFailure = static::FAILURE_NO_PATHS; return false; } // Ensure we have the expected file extension $defaultSuffix = $this->getDefaultSuffix(); if (pathinfo($name, PATHINFO_EXTENSION) == '') { $name .= '.' . $defaultSuffix; } foreach ($this->paths as $path) { $file = new SplFileInfo($path . $name); if ($file->isReadable()) { // Found! Return it. if (($filePath = $file->getRealPath()) === false && substr($path, 0, 7) === 'phar://') { // Do not try to expand phar paths (realpath + phars == fail) $filePath = $path . $name; if (!file_exists($filePath)) { break; } } if ($this->useStreamWrapper()) { // If using a stream wrapper, prepend the spec to the path $filePath = 'zend.view://' . $filePath; } return $filePath; } } $this->lastLookupFailure = static::FAILURE_NOT_FOUND; return false; } /** * Get the last lookup failure message, if any * * @return false|string */ public function getLastLookupFailure() { return $this->lastLookupFailure; } } |