vendor/jackalope/jackalope/src/Jackalope/NodePathIterator.php line 154

  1. <?php
  2. namespace Jackalope;
  3. use ArrayAccess;
  4. use Countable;
  5. use InvalidArgumentException;
  6. use SeekableIterator;
  7. /**
  8.  * @license http://www.apache.org/licenses Apache License Version 2.0, January 2004
  9.  * @license http://opensource.org/licenses/MIT MIT License
  10.  */
  11. class NodePathIterator implements SeekableIteratorArrayAccessCountable
  12. {
  13.     /**
  14.      * @var int
  15.      */
  16.     protected $position 0;
  17.     /**
  18.      * @var array
  19.      */
  20.     protected $nodes = [];
  21.     /**
  22.      * @var array
  23.      */
  24.     protected $paths;
  25.     protected $typeFilter;
  26.     protected $class;
  27.     /**
  28.      * @var int
  29.      */
  30.     protected $count 0;
  31.     protected $batchSize;
  32.     protected $objectManager;
  33.     public function __construct(
  34.         ObjectManager $objectManager,
  35.         $paths,
  36.         $class Node::class,
  37.         $typeFilter = [],
  38.         $batchSize 50
  39.     ) {
  40.         $this->objectManager $objectManager;
  41.         $this->paths array_values((array) $paths); // ensure paths are indexed numerically
  42.         $this->batchSize $batchSize;
  43.         $this->typeFilter $typeFilter;
  44.         $this->class $class;
  45.         $this->loadBatch();
  46.     }
  47.     /**
  48.      * Return the batchSize
  49.      *
  50.      * @return integer
  51.      */
  52.     public function getBatchSize()
  53.     {
  54.         return $this->batchSize;
  55.     }
  56.     /**
  57.      * Return the type filter
  58.      *
  59.      * @return string
  60.      */
  61.     public function getTypeFilter()
  62.     {
  63.         return $this->typeFilter;
  64.     }
  65.     /**
  66.      * {@inheritDoc}
  67.      */
  68.     #[\ReturnTypeWillChange]
  69.     public function current()
  70.     {
  71.         return $this->nodes[$this->paths[$this->position]];
  72.     }
  73.     /**
  74.      * {@inheritDoc}
  75.      */
  76.     #[\ReturnTypeWillChange]
  77.     public function next()
  78.     {
  79.         $this->position++;
  80.     }
  81.     /**
  82.      * {@inheritDoc}
  83.      */
  84.     #[\ReturnTypeWillChange]
  85.     public function rewind()
  86.     {
  87.         $this->position 0;
  88.     }
  89.     /**
  90.      * {@inheritDoc}
  91.      */
  92.     #[\ReturnTypeWillChange]
  93.     public function valid()
  94.     {
  95.         if (!isset($this->paths[$this->position])) {
  96.             return false;
  97.         }
  98.         $path $this->paths[$this->position];
  99.         // skip any paths which have been filtered in userland
  100.         // and move on
  101.         if ($path === null) {
  102.             $this->position++;
  103.             return $this->valid();
  104.         }
  105.         if (!array_key_exists($path$this->nodes)) {
  106.             $this->loadBatch();
  107.         }
  108.         if (empty($this->nodes[$path])) {
  109.             $this->position++;
  110.             return $this->valid();
  111.         }
  112.         return true;
  113.     }
  114.     /**
  115.      * {@inheritDoc}
  116.      */
  117.     #[\ReturnTypeWillChange]
  118.     public function key()
  119.     {
  120.         return $this->paths[$this->position];
  121.     }
  122.     /**
  123.      * Load a batch of records according to the
  124.      * batch size.
  125.      *
  126.      * @param integer $position - Optional position to start from
  127.      */
  128.     protected function loadBatch($position null)
  129.     {
  130.         if (=== count($this->paths)) {
  131.             return;
  132.         }
  133.         $paths array_slice(
  134.             $this->paths,
  135.             $position $position $this->position,
  136.             $this->batchSize
  137.         );
  138.         $nodes $this->objectManager->getNodesByPathAsArray(
  139.             $paths,
  140.             $this->class,
  141.             $this->typeFilter
  142.         );
  143.         foreach ($paths as $path) {
  144.             if (isset($nodes[$path]) && $nodes[$path] !== '') {
  145.                 $this->nodes[$path] =  $nodes[$path];
  146.                 $this->count++;
  147.             } else {
  148.                 $this->nodes[$path] =  null;
  149.             }
  150.         }
  151.     }
  152.     /**
  153.      * Ensure that the given path is loaded from the database.
  154.      * We will iterate over the batches until we either get to
  155.      * the end or we find the node we are looking for.
  156.      *
  157.      * Subsequent calls will start loading from the first path
  158.      * which does not have a corresponding array key in the nodes array
  159.      * - if the node is indeed not already loaded.
  160.      *
  161.      * @param integer $offset
  162.      */
  163.     protected function ensurePathLoaded($offset)
  164.     {
  165.         if (count($this->paths) > 0) {
  166.             if (!array_key_exists($offset$this->nodes)) {
  167.                 // start loading batches from the position of the first
  168.                 // "missing" node
  169.                 $position null;
  170.                 foreach ($this->paths as $position => $path) {
  171.                     if (!array_key_exists($path$this->nodes)) {
  172.                         break;
  173.                     }
  174.                 }
  175.                 while (isset($this->paths[$position])) {
  176.                     // keep loading batches until we get to the end of the paths
  177.                     // or we find the one we want.
  178.                     $this->loadBatch($position);
  179.                     $position += $this->batchSize;
  180.                     if (array_key_exists($offset$this->nodes)) {
  181.                         break;
  182.                     }
  183.                 }
  184.             }
  185.         }
  186.         // if it wasn't found, it doesn't exist, set it to null
  187.         if (!array_key_exists($offset$this->nodes)) {
  188.             $this->nodes[$offset] = null;
  189.         }
  190.     }
  191.     /**
  192.      * {@inheritDoc}
  193.      */
  194.     #[\ReturnTypeWillChange]
  195.     public function offsetExists($offset)
  196.     {
  197.         $this->ensurePathLoaded($offset);
  198.         return $this->nodes[$offset] === null false true;
  199.     }
  200.     /**
  201.      * {@inheritDoc}
  202.      */
  203.     #[\ReturnTypeWillChange]
  204.     public function offsetGet($offset)
  205.     {
  206.         $this->ensurePathLoaded($offset);
  207.         return $this->nodes[$offset];
  208.     }
  209.     /**
  210.      * {@inheritDoc}
  211.      */
  212.     #[\ReturnTypeWillChange]
  213.     public function offsetSet($offset$value)
  214.     {
  215.         throw new InvalidArgumentException('Node path collection is read only');
  216.     }
  217.     /**
  218.      * {@inheritDoc}
  219.      */
  220.     #[\ReturnTypeWillChange]
  221.     public function offsetUnset($offset)
  222.     {
  223.         throw new InvalidArgumentException('Node path collection is read only');
  224.     }
  225.     /**
  226.      * {@inheritDoc}
  227.      */
  228.     #[\ReturnTypeWillChange]
  229.     public function seek($position)
  230.     {
  231.         $this->position $position;
  232.     }
  233.     /**
  234.      * {@inheritDoc}
  235.      */
  236.     #[\ReturnTypeWillChange]
  237.     public function count()
  238.     {
  239.         $this->ensurePathLoaded(count($this->paths));
  240.         return $this->count;
  241.     }
  242. }