vendor/pimcore/pimcore/models/DataObject/Fieldcollection.php line 334

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Model\DataObject;
  15. use Pimcore\Logger;
  16. use Pimcore\Model;
  17. use Pimcore\Model\DataObject;
  18. use Pimcore\Model\Element\DirtyIndicatorInterface;
  19. /**
  20.  * @template TItem of Model\DataObject\Fieldcollection\Data\AbstractData
  21.  *
  22.  * @method array delete(Concrete $object, $saveMode = false)
  23.  * @method Fieldcollection\Dao getDao()
  24.  * @method array load(Concrete $object)
  25.  */
  26. class Fieldcollection extends Model\AbstractModel implements \IteratorDirtyIndicatorInterfaceObjectAwareFieldInterface
  27. {
  28.     use Model\Element\Traits\DirtyIndicatorTrait;
  29.     /**
  30.      * @internal
  31.      *
  32.      * @var array<TItem|\__PHP_Incomplete_Class>
  33.      */
  34.     protected $items = [];
  35.     /**
  36.      * @internal
  37.      *
  38.      * @var string
  39.      */
  40.     protected $fieldname;
  41.     /**
  42.      * @param TItem[] $items
  43.      * @param string|null $fieldname
  44.      */
  45.     public function __construct($items = [], $fieldname null)
  46.     {
  47.         if (!empty($items)) {
  48.             $this->setItems($items);
  49.         }
  50.         if ($fieldname) {
  51.             $this->setFieldname($fieldname);
  52.         }
  53.         $this->markFieldDirty('_self'true);
  54.     }
  55.     /**
  56.      * @return TItem[]
  57.      */
  58.     public function getItems()
  59.     {
  60.         return $this->items;
  61.     }
  62.     /**
  63.      * @param TItem[] $items
  64.      *
  65.      * @return $this
  66.      */
  67.     public function setItems($items)
  68.     {
  69.         $this->items $items;
  70.         $this->markFieldDirty('_self'true);
  71.         return $this;
  72.     }
  73.     /**
  74.      * @return string
  75.      */
  76.     public function getFieldname()
  77.     {
  78.         return $this->fieldname;
  79.     }
  80.     /**
  81.      * @param string $fieldname
  82.      *
  83.      * @return $this
  84.      */
  85.     public function setFieldname($fieldname)
  86.     {
  87.         $this->fieldname $fieldname;
  88.         return $this;
  89.     }
  90.     /**
  91.      * @internal
  92.      *
  93.      * @return Fieldcollection\Definition[]
  94.      */
  95.     public function getItemDefinitions()
  96.     {
  97.         $definitions = [];
  98.         foreach ($this->getItems() as $item) {
  99.             $definitions[$item->getType()] = $item->getDefinition();
  100.         }
  101.         return $definitions;
  102.     }
  103.     /**
  104.      * @param Concrete $object
  105.      * @param array $params
  106.      *
  107.      * @throws \Exception
  108.      */
  109.     public function save($object$params = [])
  110.     {
  111.         $saveRelationalData $this->getDao()->save($object$params);
  112.         /** @var Model\DataObject\ClassDefinition\Data\Fieldcollections $fieldDef */
  113.         $fieldDef $object->getClass()->getFieldDefinition($this->getFieldname());
  114.         $allowedTypes $fieldDef->getAllowedTypes();
  115.         $collectionItems $this->getItems();
  116.         if (is_array($collectionItems)) {
  117.             $index 0;
  118.             foreach ($collectionItems as $collection) {
  119.                 if ($collection instanceof Fieldcollection\Data\AbstractData) {
  120.                     if (in_array($collection->getType(), $allowedTypes)) {
  121.                         $collection->setFieldname($this->getFieldname());
  122.                         $collection->setIndex($index++);
  123.                         $params['owner'] = $collection;
  124.                         // set the current object again, this is necessary because the related object in $this->object can change (eg. clone & copy & paste, etc.)
  125.                         $collection->setObject($object);
  126.                         $collection->getDao()->save($object$params$saveRelationalData);
  127.                     } else {
  128.                         throw new \Exception('Fieldcollection of type ' $collection->getType() . ' is not allowed in field: ' $this->getFieldname());
  129.                     }
  130.                 }
  131.             }
  132.         }
  133.     }
  134.     /**
  135.      * @return bool
  136.      */
  137.     public function isEmpty()
  138.     {
  139.         return count($this->getItems()) < 1;
  140.     }
  141.     /**
  142.      * @param TItem $item
  143.      */
  144.     public function add($item)
  145.     {
  146.         $this->items[] = $item;
  147.         $this->markFieldDirty('_self'true);
  148.     }
  149.     /**
  150.      * @param int $index
  151.      */
  152.     public function remove($index)
  153.     {
  154.         if (isset($this->items[$index])) {
  155.             array_splice($this->items$index1);
  156.             $this->markFieldDirty('_self'true);
  157.         }
  158.     }
  159.     /**
  160.      * @param int $index
  161.      *
  162.      * @return Fieldcollection\Data\AbstractData|null
  163.      */
  164.     public function get($index)
  165.     {
  166.         return $this->items[$index] ?? null;
  167.     }
  168.     /**
  169.      * @param int|null $index
  170.      *
  171.      * @return Fieldcollection\Data\AbstractData|null
  172.      */
  173.     private function getByOriginalIndex($index)
  174.     {
  175.         if ($index === null) {
  176.             return null;
  177.         }
  178.         if (is_array($this->items)) {
  179.             foreach ($this->items as $item) {
  180.                 if ($item->getIndex() === $index) {
  181.                     return $item;
  182.                 }
  183.             }
  184.         }
  185.         return null;
  186.     }
  187.     /**
  188.      * @return int
  189.      */
  190.     public function getCount()
  191.     {
  192.         return count($this->getItems());
  193.     }
  194.     /**
  195.      * Methods for Iterator
  196.      */
  197.     /**
  198.      * @return void
  199.      */
  200.     #[\ReturnTypeWillChange]
  201.     public function rewind()// : void
  202.     {
  203.         reset($this->items);
  204.     }
  205.     /**
  206.      * @return TItem|false
  207.      */
  208.     #[\ReturnTypeWillChange]
  209.     public function current()// : Model\DataObject\Fieldcollection\Data\AbstractData|false
  210.     {
  211.         return current($this->items);
  212.     }
  213.     /**
  214.      * @return int|null
  215.      */
  216.     #[\ReturnTypeWillChange]
  217.     public function key()// : int|null
  218.     {
  219.         return key($this->items);
  220.     }
  221.     /**
  222.      * @return void
  223.      */
  224.     #[\ReturnTypeWillChange]
  225.     public function next()// : void
  226.     {
  227.         next($this->items);
  228.     }
  229.     /**
  230.      * @return bool
  231.      */
  232.     #[\ReturnTypeWillChange]
  233.     public function valid()// : bool
  234.     {
  235.         return $this->current() !== false;
  236.     }
  237.     /**
  238.      * @param Concrete $object
  239.      * @param string $type
  240.      * @param string $fcField
  241.      * @param int $index
  242.      * @param string $field
  243.      *
  244.      * @throws \Exception
  245.      *
  246.      * @internal
  247.      */
  248.     public function loadLazyField(Concrete $object$type$fcField$index$field)
  249.     {
  250.         // lazy loading existing can be data if the item already had an index
  251.         $item $this->getByOriginalIndex($index);
  252.         if ($item && !$item->isLazyKeyLoaded($field)) {
  253.             if ($type == $item->getType()) {
  254.                 $fcDef Model\DataObject\Fieldcollection\Definition::getByKey($type);
  255.                 /** @var Model\DataObject\ClassDefinition\Data\CustomResourcePersistingInterface $fieldDef */
  256.                 $fieldDef $fcDef->getFieldDefinition($field);
  257.                 $params = [
  258.                     'context' => [
  259.                         'object' => $object,
  260.                         'containerType' => 'fieldcollection',
  261.                         'containerKey' => $type,
  262.                         'fieldname' => $fcField,
  263.                         'index' => $index,
  264.                     ], ];
  265.                 $isDirtyDetectionDisabled DataObject::isDirtyDetectionDisabled();
  266.                 DataObject::disableDirtyDetection();
  267.                 $data $fieldDef->load($item$params);
  268.                 DataObject::setDisableDirtyDetection($isDirtyDetectionDisabled);
  269.                 $item->setObjectVar($field$data);
  270.             }
  271.             $item->markLazyKeyAsLoaded($field);
  272.         }
  273.     }
  274.     /**
  275.      * @return Concrete|null
  276.      */
  277.     protected function getObject(): ?Concrete
  278.     {
  279.         $this->rewind();
  280.         $item $this->current();
  281.         if ($item instanceof Model\DataObject\Fieldcollection\Data\AbstractData) {
  282.             return $item->getObject();
  283.         }
  284.         return null;
  285.     }
  286.     /**
  287.      * @param Concrete|null $object
  288.      *
  289.      * @return $this
  290.      */
  291.     public function setObject(?Concrete $object)
  292.     {
  293.         // update all items with the new $object
  294.         if (is_array($this->getItems())) {
  295.             foreach ($this->getItems() as $item) {
  296.                 if ($item instanceof Model\DataObject\Fieldcollection\Data\AbstractData) {
  297.                     $item->setObject($object);
  298.                 }
  299.             }
  300.         }
  301.         return $this;
  302.     }
  303.     /**
  304.      * @internal
  305.      */
  306.     public function loadLazyData()
  307.     {
  308.         $items $this->getItems();
  309.         if (is_array($items)) {
  310.             /** @var Model\DataObject\Fieldcollection\Data\AbstractData $item */
  311.             foreach ($items as $item) {
  312.                 $fcType $item->getType();
  313.                 $fieldcolDef Model\DataObject\Fieldcollection\Definition::getByKey($fcType);
  314.                 $fds $fieldcolDef->getFieldDefinitions();
  315.                 foreach ($fds as $fd) {
  316.                     $fieldGetter 'get' ucfirst($fd->getName());
  317.                     $fieldValue $item->$fieldGetter();
  318.                     if ($fieldValue instanceof Localizedfield) {
  319.                         $fieldValue->loadLazyData();
  320.                     }
  321.                 }
  322.             }
  323.         }
  324.     }
  325.     public function __wakeup()
  326.     {
  327.         if (is_array($this->items)) {
  328.             foreach ($this->items as $key => $item) {
  329.                 if ($item instanceof \__PHP_Incomplete_Class) {
  330.                     unset($this->items[$key]);
  331.                     Logger::error('fieldcollection item ' $key ' does not exist anymore');
  332.                 }
  333.             }
  334.         }
  335.     }
  336. }