"Fossies" - the Fresh Open Source Software Archive

Member "grav/system/src/Grav/Framework/Collection/AbstractFileCollection.php" (19 Mar 2020, 6317 Bytes) of package /linux/www/grav-v1.6.23.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "AbstractFileCollection.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 
    3 /**
    4  * @package    Grav\Framework\Collection
    5  *
    6  * @copyright  Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
    7  * @license    MIT License; see LICENSE file for details.
    8  */
    9 
   10 namespace Grav\Framework\Collection;
   11 
   12 use Doctrine\Common\Collections\Criteria;
   13 use Doctrine\Common\Collections\Expr\ClosureExpressionVisitor;
   14 use Grav\Common\Grav;
   15 use RocketTheme\Toolbox\ResourceLocator\RecursiveUniformResourceIterator;
   16 use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
   17 
   18 /**
   19  * Collection of objects stored into a filesystem.
   20  *
   21  * @package Grav\Framework\Collection
   22  */
   23 class AbstractFileCollection extends AbstractLazyCollection implements FileCollectionInterface
   24 {
   25     /**
   26      * @var string
   27      */
   28     protected $path;
   29 
   30     /**
   31      * @var \RecursiveDirectoryIterator|RecursiveUniformResourceIterator
   32      */
   33     protected $iterator;
   34 
   35     /**
   36      * @var callable
   37      */
   38     protected $createObjectFunction;
   39 
   40     /**
   41      * @var callable|null
   42      */
   43     protected $filterFunction;
   44 
   45     /**
   46      * @var int
   47      */
   48     protected $flags;
   49 
   50     /**
   51      * @var int
   52      */
   53     protected $nestingLimit;
   54 
   55     /**
   56      * @param string $path
   57      */
   58     protected function __construct($path)
   59     {
   60         $this->path = $path;
   61         $this->flags = self::INCLUDE_FILES | self::INCLUDE_FOLDERS;
   62         $this->nestingLimit = 0;
   63         $this->createObjectFunction = [$this, 'createObject'];
   64 
   65         $this->setIterator();
   66     }
   67 
   68     /**
   69      * @return string
   70      */
   71     public function getPath()
   72     {
   73         return $this->path;
   74     }
   75 
   76     /**
   77      * @param Criteria $criteria
   78      * @return ArrayCollection
   79      * @todo Implement lazy matching
   80      */
   81     public function matching(Criteria $criteria)
   82     {
   83         $expr = $criteria->getWhereExpression();
   84 
   85         $oldFilter = $this->filterFunction;
   86         if ($expr) {
   87             $visitor = new ClosureExpressionVisitor();
   88             $filter = $visitor->dispatch($expr);
   89             $this->addFilter($filter);
   90         }
   91 
   92         $filtered = $this->doInitializeByIterator($this->iterator, $this->nestingLimit);
   93         $this->filterFunction = $oldFilter;
   94 
   95         if ($orderings = $criteria->getOrderings()) {
   96             $next = null;
   97             foreach (array_reverse($orderings) as $field => $ordering) {
   98                 $next = ClosureExpressionVisitor::sortByField($field, $ordering === Criteria::DESC ? -1 : 1, $next);
   99             }
  100 
  101             uasort($filtered, $next);
  102         } else {
  103             ksort($filtered);
  104         }
  105 
  106         $offset = $criteria->getFirstResult();
  107         $length = $criteria->getMaxResults();
  108 
  109         if ($offset || $length) {
  110             $filtered = \array_slice($filtered, (int)$offset, $length);
  111         }
  112 
  113         return new ArrayCollection($filtered);
  114     }
  115 
  116     protected function setIterator()
  117     {
  118         $iteratorFlags = \RecursiveDirectoryIterator::SKIP_DOTS + \FilesystemIterator::UNIX_PATHS
  119             + \FilesystemIterator::CURRENT_AS_SELF + \FilesystemIterator::FOLLOW_SYMLINKS;
  120 
  121         if (strpos($this->path, '://')) {
  122             /** @var UniformResourceLocator $locator */
  123             $locator = Grav::instance()['locator'];
  124             $this->iterator = $locator->getRecursiveIterator($this->path, $iteratorFlags);
  125         } else {
  126             $this->iterator = new \RecursiveDirectoryIterator($this->path, $iteratorFlags);
  127         }
  128     }
  129 
  130     /**
  131      * @param callable $filterFunction
  132      * @return $this
  133      */
  134     protected function addFilter(callable $filterFunction)
  135     {
  136         if ($this->filterFunction) {
  137             $oldFilterFunction = $this->filterFunction;
  138             $this->filterFunction = function ($expr) use ($oldFilterFunction, $filterFunction) {
  139                 return $oldFilterFunction($expr) && $filterFunction($expr);
  140             };
  141         } else {
  142             $this->filterFunction = $filterFunction;
  143         }
  144 
  145         return $this;
  146     }
  147 
  148     /**
  149      * {@inheritDoc}
  150      */
  151     protected function doInitialize()
  152     {
  153         $filtered = $this->doInitializeByIterator($this->iterator, $this->nestingLimit);
  154         ksort($filtered);
  155 
  156         $this->collection = new ArrayCollection($filtered);
  157     }
  158 
  159     protected function doInitializeByIterator(\SeekableIterator $iterator, $nestingLimit)
  160     {
  161         $children = [];
  162         $objects = [];
  163         $filter = $this->filterFunction;
  164         $objectFunction = $this->createObjectFunction;
  165 
  166         /** @var \RecursiveDirectoryIterator $file */
  167         foreach ($iterator as $file) {
  168             // Skip files if they shouldn't be included.
  169             if (!($this->flags & static::INCLUDE_FILES) && $file->isFile()) {
  170                 continue;
  171             }
  172 
  173             // Apply main filter.
  174             if ($filter && !$filter($file)) {
  175                 continue;
  176             }
  177 
  178             // Include children if the recursive flag is set.
  179             if (($this->flags & static::RECURSIVE) && $nestingLimit > 0 && $file->hasChildren()) {
  180                 $children[] = $file->getChildren();
  181             }
  182 
  183             // Skip folders if they shouldn't be included.
  184             if (!($this->flags & static::INCLUDE_FOLDERS) && $file->isDir()) {
  185                 continue;
  186             }
  187 
  188             $object = $objectFunction($file);
  189             $objects[$object->key] = $object;
  190         }
  191 
  192         if ($children) {
  193             $objects += $this->doInitializeChildren($children, $nestingLimit - 1);
  194         }
  195 
  196         return $objects;
  197     }
  198 
  199     /**
  200      * @param \RecursiveDirectoryIterator[] $children
  201      * @return array
  202      */
  203     protected function doInitializeChildren(array $children, $nestingLimit)
  204     {
  205         $objects = [];
  206 
  207         foreach ($children as $iterator) {
  208             $objects += $this->doInitializeByIterator($iterator, $nestingLimit);
  209         }
  210 
  211         return $objects;
  212     }
  213 
  214     /**
  215      * @param \RecursiveDirectoryIterator $file
  216      * @return object
  217      */
  218     protected function createObject($file)
  219     {
  220         return (object) [
  221             'key' => $file->getSubPathname(),
  222             'type' => $file->isDir() ? 'folder' : 'file:' . $file->getExtension(),
  223             'url' => method_exists($file, 'getUrl') ? $file->getUrl() : null,
  224             'pathname' => $file->getPathname(),
  225             'mtime' => $file->getMTime()
  226         ];
  227     }
  228 }