vendor/pimcore/pimcore/models/DataObject/ClassDefinition/Data/Classificationstore.php line 461

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\ClassDefinition\Data;
  15. use Pimcore\Model;
  16. use Pimcore\Model\DataObject;
  17. use Pimcore\Model\DataObject\ClassDefinition\Data;
  18. use Pimcore\Model\DataObject\ClassDefinition\Layout;
  19. use Pimcore\Model\DataObject\Concrete;
  20. use Pimcore\Model\Element;
  21. use Pimcore\Normalizer\NormalizerInterface;
  22. use Pimcore\Tool;
  23. class Classificationstore extends Data implements CustomResourcePersistingInterface, TypeDeclarationSupportInterface, NormalizerInterface, PreGetDataInterface, LayoutDefinitionEnrichmentInterface
  24. {
  25. use Element\ChildsCompatibilityTrait;
  26. /**
  27. * Static type of this element
  28. *
  29. * @internal
  30. *
  31. * @var string
  32. */
  33. public $fieldtype = 'classificationstore';
  34. /**
  35. * @internal
  36. *
  37. * @var array
  38. */
  39. public $childs = [];
  40. /**
  41. * @internal
  42. *
  43. * @var string
  44. */
  45. public $name;
  46. /**
  47. * @internal
  48. *
  49. * @var string
  50. */
  51. public $region;
  52. /**
  53. * @internal
  54. *
  55. * @var string
  56. */
  57. public $layout;
  58. /**
  59. * @internal
  60. *
  61. * @var string
  62. */
  63. public $title;
  64. /**
  65. * @internal
  66. *
  67. * @var string|int
  68. */
  69. public $width = 0;
  70. /**
  71. * @internal
  72. *
  73. * @var string|int
  74. */
  75. public $height = 0;
  76. /**
  77. * @internal
  78. *
  79. * @var int
  80. */
  81. public $maxTabs;
  82. /**
  83. * @internal
  84. *
  85. * @var int
  86. */
  87. public $labelWidth = 0;
  88. /**
  89. * @internal
  90. *
  91. * @var bool
  92. */
  93. public $localized;
  94. /**
  95. * @internal
  96. *
  97. * @var int
  98. */
  99. public $storeId;
  100. /**
  101. * @internal
  102. *
  103. * @var bool
  104. */
  105. public $hideEmptyData;
  106. /**
  107. * @internal
  108. *
  109. * @var bool
  110. */
  111. public $disallowAddRemove;
  112. /**
  113. * contains further localized field definitions if there are more than one localized fields in on class
  114. *
  115. * @internal
  116. *
  117. * @var array
  118. */
  119. protected $referencedFields = [];
  120. /**
  121. * @internal
  122. *
  123. * @var array|null
  124. */
  125. public $fieldDefinitionsCache;
  126. /**
  127. * @internal
  128. *
  129. * @var array
  130. */
  131. public $allowedGroupIds;
  132. /**
  133. * @internal
  134. *
  135. * @var array
  136. */
  137. public $activeGroupDefinitions = [];
  138. /**
  139. * @internal
  140. *
  141. * @var int
  142. */
  143. public $maxItems;
  144. /**
  145. * @internal
  146. *
  147. * @var array
  148. */
  149. public $permissionView;
  150. /**
  151. * @internal
  152. *
  153. * @var array
  154. */
  155. public $permissionEdit;
  156. /**
  157. * @see Data::getDataForEditmode
  158. *
  159. * @param DataObject\Classificationstore|null $data
  160. * @param null|DataObject\Concrete $object
  161. * @param mixed $params
  162. *
  163. * @return array
  164. */
  165. public function getDataForEditmode($data, $object = null, $params = [])
  166. {
  167. if (!$data instanceof DataObject\Classificationstore) {
  168. return [];
  169. }
  170. $fieldData = [];
  171. $metaData = [];
  172. $result = $this->doGetDataForEditMode($data, $object, $fieldData, $metaData, 1);
  173. // replace the real data with the data for the editmode
  174. foreach ($result['data'] as $language => &$groups) {
  175. foreach ($groups as $groupId => &$keys) {
  176. foreach ($keys as $keyId => &$keyValue) {
  177. $keyConfig = DataObject\Classificationstore\DefinitionCache::get($keyId);
  178. if ($keyConfig->getEnabled()) {
  179. $fd = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($keyConfig);
  180. $keyValue = $fd->getDataForEditmode($keyValue, $object, $params);
  181. }
  182. }
  183. }
  184. }
  185. $activeGroupIds = $this->recursiveGetActiveGroupsIds($object);
  186. $validLanguages = $this->getValidLanguages();
  187. foreach ($validLanguages as $language) {
  188. foreach ($activeGroupIds as $groupId => $enabled) {
  189. if (!$enabled) {
  190. continue;
  191. }
  192. $relation = new DataObject\Classificationstore\KeyGroupRelation\Listing();
  193. $relation->setCondition("type = 'calculatedValue' and groupId = " . $relation->quote($groupId));
  194. $relation = $relation->load();
  195. foreach ($relation as $key) {
  196. $keyId = $key->getKeyId();
  197. $childDef = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($key);
  198. $childData = new DataObject\Data\CalculatedValue($this->getName());
  199. $childData->setContextualData('classificationstore', $this->getName(), null, $language, $groupId, $keyId, $childDef);
  200. $childData = $childDef->getDataForEditmode($childData, $object, $params);
  201. $result['data'][$language][$groupId][$keyId] = $childData;
  202. }
  203. }
  204. }
  205. $result['activeGroups'] = $data->getActiveGroups();
  206. $result['groupCollectionMapping'] = $data->getGroupCollectionMappings();
  207. return $result;
  208. }
  209. /**
  210. * @param DataObject\Classificationstore $data
  211. * @param DataObject\Concrete $object
  212. * @param array $fieldData structure: [language][groupId][keyId] = field data
  213. * @param array $metaData structure: [language][groupId][keyId] = array with meta info
  214. * @param int $level
  215. *
  216. * @return array
  217. */
  218. private function doGetDataForEditMode($data, $object, &$fieldData, &$metaData, $level = 1)
  219. {
  220. $class = $object->getClass();
  221. $inheritanceAllowed = $class->getAllowInherit();
  222. $inherited = false;
  223. $items = $data->getItems();
  224. foreach ($items as $groupId => $keys) {
  225. if (!isset($data->getActiveGroups()[$groupId])) {
  226. continue;
  227. }
  228. foreach ($keys as $keyId => $languages) {
  229. $keyConfig = DataObject\Classificationstore\DefinitionCache::get($keyId);
  230. if ($keyConfig->getEnabled()) {
  231. $fd = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($keyConfig);
  232. foreach ($languages as $language => $value) {
  233. $fdata = $value;
  234. if (!isset($fieldData[$language][$groupId][$keyId]) || $fd->isEmpty($fieldData[$language][$groupId][$keyId])) {
  235. // never override existing data
  236. $fieldData[$language][$groupId][$keyId] = $fdata;
  237. if (!$fd->isEmpty($fdata)) {
  238. $metaData[$language][$groupId][$keyId] = ['inherited' => $level > 1, 'objectid' => $object->getId()];
  239. }
  240. }
  241. }
  242. }
  243. }
  244. }
  245. // TODO
  246. if ($inheritanceAllowed) {
  247. // check if there is a parent with the same type
  248. $parent = DataObject\Service::hasInheritableParentObject($object);
  249. if ($parent) {
  250. // same type, iterate over all language and all fields and check if there is something missing
  251. if ($this->localized) {
  252. $validLanguages = Tool::getValidLanguages();
  253. } else {
  254. $validLanguages = [];
  255. }
  256. array_unshift($validLanguages, 'default');
  257. $foundEmptyValue = false;
  258. $activeGroupIds = $this->recursiveGetActiveGroupsIds($object);
  259. foreach ($validLanguages as $language) {
  260. foreach ($activeGroupIds as $groupId => $enabled) {
  261. if (!$enabled) {
  262. continue;
  263. }
  264. $relation = new DataObject\Classificationstore\KeyGroupRelation\Listing();
  265. $relation->setCondition('groupId = ' . $relation->quote($groupId));
  266. $relation = $relation->load();
  267. foreach ($relation as $key) {
  268. $keyId = $key->getKeyId();
  269. $fd = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($key);
  270. if ($fd->isEmpty($fieldData[$language][$groupId][$keyId] ?? null)) {
  271. $foundEmptyValue = true;
  272. $inherited = true;
  273. $metaData[$language][$groupId][$keyId] = ['inherited' => true, 'objectid' => $parent->getId()];
  274. }
  275. }
  276. }
  277. }
  278. if ($foundEmptyValue) {
  279. // still some values are missing, ask the parent
  280. $getter = 'get' . ucfirst($this->getName());
  281. $parentData = $parent->$getter();
  282. $parentResult = $this->doGetDataForEditMode($parentData, $parent, $fieldData, $metaData, $level + 1);
  283. }
  284. }
  285. }
  286. $result = [
  287. 'data' => $fieldData,
  288. 'metaData' => $metaData,
  289. 'inherited' => $inherited,
  290. ];
  291. return $result;
  292. }
  293. /**
  294. * @see Data::getDataFromEditmode
  295. *
  296. * @param array $containerData
  297. * @param null|DataObject\Concrete $object
  298. * @param mixed $params
  299. *
  300. * @return DataObject\Classificationstore
  301. */
  302. public function getDataFromEditmode($containerData, $object = null, $params = [])
  303. {
  304. $classificationStore = $this->getDataFromObjectParam($object);
  305. if (!$classificationStore instanceof DataObject\Classificationstore) {
  306. $classificationStore = new DataObject\Classificationstore();
  307. }
  308. $data = $containerData['data'];
  309. $activeGroups = $containerData['activeGroups'];
  310. $groupCollectionMapping = $containerData['groupCollectionMapping'];
  311. $correctedMapping = [];
  312. foreach ($groupCollectionMapping as $groupId => $collectionId) {
  313. if (isset($activeGroups[$groupId]) && $activeGroups[$groupId]) {
  314. $correctedMapping[$groupId] = $collectionId;
  315. }
  316. }
  317. $classificationStore->setGroupCollectionMappings($correctedMapping);
  318. if (is_array($data)) {
  319. foreach ($data as $language => $groups) {
  320. foreach ($groups as $groupId => $keys) {
  321. foreach ($keys as $keyId => $value) {
  322. $keyConfig = $this->getKeyConfiguration($keyId);
  323. $dataDefinition = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($keyConfig);
  324. $dataFromEditMode = $dataDefinition->getDataFromEditmode($value);
  325. $activeGroups[$groupId] = true;
  326. $classificationStore->setLocalizedKeyValue($groupId, $keyId, $dataFromEditMode, $language);
  327. }
  328. }
  329. }
  330. }
  331. $activeGroupIds = array_keys($activeGroups);
  332. $classificationStore->setActiveGroups($activeGroups);
  333. // cleanup
  334. $existingGroupIds = $classificationStore->getGroupIdsWithData();
  335. if (is_array($existingGroupIds)) {
  336. foreach ($existingGroupIds as $existingGroupId) {
  337. if (!in_array($existingGroupId, $activeGroupIds)) {
  338. $classificationStore->removeGroupData($existingGroupId);
  339. }
  340. }
  341. }
  342. return $classificationStore;
  343. }
  344. /**
  345. * @param mixed $data
  346. * @param DataObject\Concrete $object
  347. * @param mixed $params
  348. *
  349. * @return string
  350. */
  351. public function getDataForGrid($data, $object = null, $params = [])
  352. {
  353. return 'not supported';
  354. }
  355. /**
  356. * @see Data::getVersionPreview
  357. *
  358. * @param DataObject\Classificationstore|null $data
  359. * @param null|DataObject\Concrete $object
  360. * @param mixed $params
  361. *
  362. * @return string
  363. */
  364. public function getVersionPreview($data, $object = null, $params = [])
  365. {
  366. // this is handled directly in the template
  367. // /bundles/AdminBundle/Resources/views/Admin/DataObject/DataObject/previewVersion.html.twig
  368. return 'CLASSIFICATIONSTORE';
  369. }
  370. /**
  371. * {@inheritdoc}
  372. */
  373. public function getForCsvExport($object, $params = [])
  374. {
  375. return 'not supported';
  376. }
  377. /**
  378. * {@inheritdoc}
  379. */
  380. public function getDataForSearchIndex($object, $params = [])
  381. {
  382. $dataString = '';
  383. $getter = 'get' . ucfirst($this->getName());
  384. $classificationStore = $object->$getter();
  385. $items = $classificationStore->getItems();
  386. $activeGroups = $classificationStore->getActiveGroups();
  387. $params['owner'] = $classificationStore;
  388. if ($items) {
  389. foreach ($items as $groupId => $keys) {
  390. if (!isset($activeGroups[$groupId])) {
  391. continue;
  392. }
  393. foreach ($keys as $keyId => $values) {
  394. $keyConfig = $this->getKeyConfiguration($keyId);
  395. /** @var ResourcePersistenceAwareInterface $fieldDefinition */
  396. $fieldDefinition = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($keyConfig);
  397. foreach ($values as $language => $value) {
  398. $value = $fieldDefinition->getDataForResource($value, $object, $params);
  399. if (is_array($value)) {
  400. $value = implode(',', $value);
  401. }
  402. $dataString .= $value . ' ';
  403. }
  404. }
  405. }
  406. }
  407. return $dataString;
  408. }
  409. /**
  410. * @param DataObject\Classificationstore|null $data
  411. *
  412. * @return bool
  413. */
  414. public function isEmpty($data)
  415. {
  416. if ($data instanceof DataObject\Classificationstore) {
  417. return empty($data->getItems());
  418. }
  419. return is_null($data);
  420. }
  421. /**
  422. * @return array
  423. */
  424. public function getChildren()
  425. {
  426. return $this->childs;
  427. }
  428. /**
  429. * @param array $children
  430. *
  431. * @return $this
  432. */
  433. public function setChildren($children)
  434. {
  435. $this->childs = $children;
  436. $this->fieldDefinitionsCache = null;
  437. return $this;
  438. }
  439. /**
  440. * @return bool
  441. */
  442. public function hasChildren()
  443. {
  444. if (is_array($this->childs) && count($this->childs) > 0) {
  445. return true;
  446. }
  447. return false;
  448. }
  449. /**
  450. * @param Data|Layout $child
  451. */
  452. public function addChild($child)
  453. {
  454. $this->childs[] = $child;
  455. $this->fieldDefinitionsCache = null;
  456. }
  457. /**
  458. * @param array $referencedFields
  459. */
  460. public function setReferencedFields($referencedFields)
  461. {
  462. $this->referencedFields = $referencedFields;
  463. $this->fieldDefinitionsCache = null;
  464. }
  465. /**
  466. * @return array
  467. */
  468. public function getReferencedFields()
  469. {
  470. return $this->referencedFields;
  471. }
  472. /**
  473. * @param Data $field
  474. */
  475. public function addReferencedField($field)
  476. {
  477. $this->referencedFields[] = $field;
  478. $this->fieldDefinitionsCache = null;
  479. }
  480. /**
  481. * {@inheritdoc}
  482. */
  483. public function save($object, $params = [])
  484. {
  485. $classificationStore = $this->getDataFromObjectParam($object);
  486. if ($classificationStore instanceof DataObject\Classificationstore) {
  487. $classificationStore->setObject($object);
  488. $classificationStore->save();
  489. }
  490. }
  491. /**
  492. * {@inheritdoc}
  493. */
  494. public function load($object, $params = [])
  495. {
  496. $classificationStore = new DataObject\Classificationstore();
  497. $classificationStore->setObject($object);
  498. $classificationStore->setFieldname($this->getName());
  499. $classificationStore->load();
  500. return $classificationStore;
  501. }
  502. /**
  503. * {@inheritdoc}
  504. */
  505. public function delete($object, $params = [])
  506. {
  507. $classificationStore = $this->getDataFromObjectParam($object);
  508. if ($classificationStore instanceof DataObject\Classificationstore) {
  509. $classificationStore->setObject($object);
  510. $classificationStore->setFieldname($this->getName());
  511. $classificationStore->delete();
  512. }
  513. }
  514. /**
  515. * This method is called in DataObject\ClassDefinition::save() and is used to create the database table for the classification data
  516. *
  517. * @param DataObject\ClassDefinition $class
  518. * @param array $params
  519. */
  520. public function classSaved($class, $params = [])
  521. {
  522. $classificationStore = new DataObject\Classificationstore();
  523. $classificationStore->setClass($class);
  524. $classificationStore->createUpdateTable();
  525. }
  526. /**
  527. * { @inheritdoc }
  528. */
  529. public function preGetData(/** mixed */ $container, /** array */ $params = []) // : mixed
  530. {
  531. if (!$container instanceof DataObject\Concrete) {
  532. throw new \Exception('Classification store fields are only valid in Objects');
  533. }
  534. if (!$container->getObjectVar($this->getName()) instanceof DataObject\Classificationstore) {
  535. $store = new DataObject\Classificationstore();
  536. $store->setObject($container);
  537. $store->setFieldname($this->getName());
  538. $container->{'set' . $this->getName()}($store);
  539. }
  540. return $container->getObjectVar($this->getName());
  541. }
  542. /**
  543. * @param int $keyId
  544. *
  545. * @return mixed
  546. */
  547. public function getKeyConfiguration($keyId)
  548. {
  549. /** @var DataObject\Classificationstore\KeyConfig $keyConfig */
  550. $keyConfig = DataObject\Classificationstore\DefinitionCache::get($keyId);
  551. return $keyConfig;
  552. }
  553. /**
  554. * @param string|int $height
  555. *
  556. * @return $this
  557. */
  558. public function setHeight($height)
  559. {
  560. if (is_numeric($height)) {
  561. $height = (int)$height;
  562. }
  563. $this->height = $height;
  564. return $this;
  565. }
  566. /**
  567. * @return string|int
  568. */
  569. public function getHeight()
  570. {
  571. return $this->height;
  572. }
  573. /**
  574. * @param mixed $layout
  575. *
  576. * @return $this
  577. */
  578. public function setLayout($layout)
  579. {
  580. $this->layout = $layout;
  581. return $this;
  582. }
  583. /**
  584. * @return string
  585. */
  586. public function getLayout()
  587. {
  588. return $this->layout;
  589. }
  590. /**
  591. * @param string $name
  592. *
  593. * @return $this
  594. */
  595. public function setName($name)
  596. {
  597. $this->name = $name;
  598. return $this;
  599. }
  600. /**
  601. * @return string
  602. */
  603. public function getName()
  604. {
  605. return $this->name;
  606. }
  607. /**
  608. * @param string|null $region
  609. *
  610. * @return $this
  611. */
  612. public function setRegion($region)
  613. {
  614. $this->region = $region;
  615. return $this;
  616. }
  617. /**
  618. * @return string
  619. */
  620. public function getRegion()
  621. {
  622. return $this->region;
  623. }
  624. /**
  625. * @param string $title
  626. *
  627. * @return $this|void
  628. */
  629. public function setTitle($title)
  630. {
  631. $this->title = $title;
  632. return $this;
  633. }
  634. /**
  635. * @return string
  636. */
  637. public function getTitle()
  638. {
  639. return $this->title;
  640. }
  641. /**
  642. * @param string|int $width
  643. *
  644. * @return $this
  645. */
  646. public function setWidth($width)
  647. {
  648. if (is_numeric($width)) {
  649. $width = (int)$width;
  650. }
  651. $this->width = $width;
  652. return $this;
  653. }
  654. /**
  655. * @return string|int
  656. */
  657. public function getWidth()
  658. {
  659. return $this->width;
  660. }
  661. /**
  662. * {@inheritdoc}
  663. */
  664. public function checkValidity($data, $omitMandatoryCheck = false, $params = [])
  665. {
  666. $activeGroups = $data->getActiveGroups();
  667. if (!$activeGroups) {
  668. return;
  669. }
  670. $items = $data->getItems();
  671. $validLanguages = $this->getValidLanguages();
  672. $subItems = [];
  673. $getInheritedValues = DataObject::doGetInheritedValues();
  674. if (!$omitMandatoryCheck) {
  675. if ($this->maxItems > 0 && count($activeGroups) > $this->maxItems) {
  676. throw new Model\Element\ValidationException(
  677. 'Groups in field [' . $this->getName() . '] is bigger than ' . $this->getMaxItems()
  678. );
  679. }
  680. foreach ($activeGroups as $activeGroupId => $enabled) {
  681. if ($enabled) {
  682. $groupDefinition = DataObject\Classificationstore\GroupConfig::getById($activeGroupId);
  683. if (!$groupDefinition) {
  684. continue;
  685. }
  686. $keyGroupRelations = $groupDefinition->getRelations();
  687. foreach ($keyGroupRelations as $keyGroupRelation) {
  688. foreach ($validLanguages as $validLanguage) {
  689. $keyId = $keyGroupRelation->getKeyId();
  690. $object = $data->getObject();
  691. if ($object->getClass()->getAllowInherit()) {
  692. DataObject::setGetInheritedValues(true);
  693. $value = $data->getLocalizedKeyValue($activeGroupId, $keyId, $validLanguage, true);
  694. DataObject::setGetInheritedValues($getInheritedValues);
  695. } else {
  696. $value = $items[$activeGroupId][$keyId][$validLanguage] ?? null;
  697. }
  698. $keyDef = DataObject\Classificationstore\Service::getFieldDefinitionFromJson(json_decode($keyGroupRelation->getDefinition()), $keyGroupRelation->getType());
  699. if ($keyGroupRelation->isMandatory()) {
  700. $keyDef->setMandatory(1);
  701. }
  702. try {
  703. $keyDef->checkValidity($value, false, $params);
  704. } catch (\Exception $exception) {
  705. $subItems[] = new Model\Element\ValidationException(
  706. $exception->getMessage() . ' (' . $validLanguage . ')',
  707. $exception->getCode(),
  708. $exception->getPrevious()
  709. );
  710. }
  711. }
  712. }
  713. }
  714. }
  715. }
  716. if ($subItems) {
  717. $messages = array_map(function (Model\Element\ValidationException $validationException) {
  718. $validationException->addContext($this->getName());
  719. return $validationException->getMessage();
  720. }, $subItems);
  721. $validationException = new Model\Element\ValidationException(implode(', ', $messages));
  722. $validationException->setSubItems($subItems);
  723. throw $validationException;
  724. }
  725. }
  726. /**
  727. * @param mixed $data
  728. * @param DataObject\Concrete|null $object
  729. * @param mixed $params
  730. *
  731. * @throws \Exception
  732. */
  733. public function getDiffDataForEditmode($data, $object = null, $params = [])
  734. {
  735. throw new \Exception('not supported');
  736. }
  737. /**
  738. * @param array $data
  739. * @param DataObject\Concrete|null $object
  740. * @param mixed $params
  741. *
  742. * @throws \Exception
  743. */
  744. public function getDiffDataFromEditmode($data, $object = null, $params = [])
  745. {
  746. throw new \Exception('not supported');
  747. }
  748. /**
  749. * {@inheritdoc}
  750. */
  751. public function isDiffChangeAllowed($object, $params = [])
  752. {
  753. return false;
  754. }
  755. /**
  756. * @return array
  757. */
  758. public function __sleep()
  759. {
  760. $vars = get_object_vars($this);
  761. $blockedVars = [
  762. 'fieldDefinitionsCache',
  763. 'referencedFields',
  764. 'blockedVarsForExport',
  765. ];
  766. foreach ($blockedVars as $blockedVar) {
  767. unset($vars[$blockedVar]);
  768. }
  769. return array_keys($vars);
  770. }
  771. /**
  772. * @param int $maxTabs
  773. */
  774. public function setMaxTabs($maxTabs)
  775. {
  776. $this->maxTabs = $maxTabs;
  777. }
  778. /**
  779. * @return int
  780. */
  781. public function getMaxTabs()
  782. {
  783. return $this->maxTabs;
  784. }
  785. /**
  786. * @param int $labelWidth
  787. */
  788. public function setLabelWidth($labelWidth)
  789. {
  790. $this->labelWidth = (int)$labelWidth;
  791. }
  792. /**
  793. * @return int
  794. */
  795. public function getLabelWidth()
  796. {
  797. return $this->labelWidth;
  798. }
  799. /**
  800. * @param int $maxItems
  801. */
  802. public function setMaxItems($maxItems)
  803. {
  804. $this->maxItems = (int) $maxItems;
  805. }
  806. /**
  807. * @return int
  808. */
  809. public function getMaxItems()
  810. {
  811. return $this->maxItems;
  812. }
  813. /**
  814. * @return bool
  815. */
  816. public function isLocalized()
  817. {
  818. return $this->localized;
  819. }
  820. /**
  821. * @param bool $localized
  822. */
  823. public function setLocalized($localized)
  824. {
  825. $this->localized = $localized;
  826. }
  827. /**
  828. * @return array
  829. */
  830. public function getPermissionView(): ?array
  831. {
  832. return $this->permissionView;
  833. }
  834. /**
  835. * @param string|array|null $permissionView
  836. */
  837. public function setPermissionView($permissionView): void
  838. {
  839. $this->permissionView = $permissionView;
  840. }
  841. /**
  842. * @return array
  843. */
  844. public function getPermissionEdit(): ?array
  845. {
  846. return $this->permissionEdit;
  847. }
  848. /**
  849. * @param string|array|null $permissionEdit
  850. */
  851. public function setPermissionEdit($permissionEdit): void
  852. {
  853. $this->permissionEdit = $permissionEdit;
  854. }
  855. /**
  856. * @param DataObject\Concrete|null $object
  857. * @param array $mergedMapping
  858. *
  859. * @return array|null
  860. *
  861. * @todo: Method returns void/null, should be boolean or null
  862. */
  863. private function recursiveGetActiveGroupCollectionMapping($object, $mergedMapping = [])
  864. {
  865. if (!$object) {
  866. return null;
  867. }
  868. $getter = 'get' . ucfirst($this->getName());
  869. /** @var DataObject\Classificationstore $classificationStore */
  870. $classificationStore = $object->$getter();
  871. $mapping = $classificationStore->getGroupCollectionMappings();
  872. if (is_array($mapping)) {
  873. foreach ($mapping as $groupId => $collectionId) {
  874. if (!isset($mergedMapping[$groupId]) && $collectionId) {
  875. $mergedMapping[$groupId] = $collectionId;
  876. }
  877. }
  878. }
  879. $class = $object->getClass();
  880. $inheritanceAllowed = $class->getAllowInherit();
  881. if ($inheritanceAllowed) {
  882. $parent = DataObject\Service::hasInheritableParentObject($object);
  883. if ($parent) {
  884. $mergedMapping = $this->recursiveGetActiveGroupCollectionMapping($parent, $mergedMapping);
  885. }
  886. }
  887. return $mergedMapping;
  888. }
  889. /**
  890. * @internal
  891. *
  892. * @param DataObject\Concrete|null $object
  893. * @param array $activeGroups
  894. *
  895. * @return array|null
  896. */
  897. public function recursiveGetActiveGroupsIds($object, $activeGroups = [])
  898. {
  899. if (!$object) {
  900. return null;
  901. }
  902. $getter = 'get' . ucfirst($this->getName());
  903. /** @var DataObject\Classificationstore $classificationStore */
  904. $classificationStore = $object->$getter();
  905. $activeGroupIds = $classificationStore->getActiveGroups();
  906. if ($activeGroupIds) {
  907. $activeGroups = array_filter($activeGroupIds);
  908. }
  909. $class = $object->getClass();
  910. $inheritanceAllowed = $class->getAllowInherit();
  911. if ($inheritanceAllowed) {
  912. $parent = DataObject\Service::hasInheritableParentObject($object);
  913. if ($parent) {
  914. $activeGroups += $this->recursiveGetActiveGroupsIds($parent, $activeGroups);
  915. }
  916. }
  917. return $activeGroups;
  918. }
  919. /**
  920. * {@inheritdoc}
  921. */
  922. public function enrichLayoutDefinition(/*?Concrete */ $object, /** array */ $context = []) // : self
  923. {
  924. $this->activeGroupDefinitions = [];
  925. $activeGroupIds = $this->recursiveGetActiveGroupsIds($object);
  926. if (!$activeGroupIds) {
  927. return $this;
  928. }
  929. $filteredGroupIds = array_keys($activeGroupIds, true, true);
  930. $groupList = new DataObject\Classificationstore\GroupConfig\Listing();
  931. $groupList->setCondition('`id` in (' . implode(',', array_fill(0, count($filteredGroupIds), '?')) . ')', $filteredGroupIds);
  932. $groupList->setOrderKey(['id']);
  933. $groupList->setOrder(['ASC']);
  934. foreach ($groupList->load() as $group) {
  935. $keyList = [];
  936. $relation = new DataObject\Classificationstore\KeyGroupRelation\Listing();
  937. $relation->setCondition('`groupId` = ?', $group->getId());
  938. $relation->setOrderKey(['sorter', 'id']);
  939. $relation->setOrder(['ASC', 'ASC']);
  940. $relation = $relation->load();
  941. /** @var DataObject\Classificationstore\KeyGroupRelation $keyGroupRelation */
  942. foreach ($relation as $keyGroupRelation) {
  943. if (!$keyGroupRelation->isEnabled()) {
  944. continue;
  945. }
  946. $definition = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($keyGroupRelation);
  947. // changes here also have an effect here: "bundles/AdminBundle/Resources/public/js/pimcore/object/tags/classificationstore.js"
  948. $fallbackTooltip = $definition->getName();
  949. if (!empty($keyGroupRelation->getDescription())) {
  950. $fallbackTooltip .= ' - ' . $keyGroupRelation->getDescription();
  951. }
  952. $definition->setTooltip($definition->getTooltip() ?: $fallbackTooltip);
  953. if (method_exists($definition, '__wakeup')) {
  954. $definition->__wakeup();
  955. }
  956. $definition->setMandatory($definition->getMandatory() || $keyGroupRelation->isMandatory());
  957. //TODO Pimcore 11: remove method_exists BC layer
  958. if ($definition instanceof LayoutDefinitionEnrichmentInterface || method_exists($definition, 'enrichLayoutDefinition')) {
  959. if (!$definition instanceof LayoutDefinitionEnrichmentInterface) {
  960. trigger_deprecation('pimcore/pimcore', '10.1',
  961. sprintf('Usage of method_exists is deprecated since version 10.1 and will be removed in Pimcore 11.' .
  962. 'Implement the %s interface instead.', LayoutDefinitionEnrichmentInterface::class));
  963. }
  964. $context['object'] = $object;
  965. $context['class'] = $object->getClass();
  966. $context['ownerType'] = 'classificationstore';
  967. $context['ownerName'] = $this->getName();
  968. $context['keyId'] = $keyGroupRelation->getKeyId();
  969. $context['groupId'] = $keyGroupRelation->getGroupId();
  970. $context['keyDefinition'] = $definition;
  971. $definition = $definition->enrichLayoutDefinition($object, $context);
  972. }
  973. $keyList[] = [
  974. 'name' => $keyGroupRelation->getName(),
  975. 'id' => $keyGroupRelation->getKeyId(),
  976. 'description' => $keyGroupRelation->getDescription(),
  977. 'definition' => $definition,
  978. ];
  979. }
  980. $this->activeGroupDefinitions[$group->getId()] = [
  981. 'name' => $group->getName(),
  982. 'id' => $group->getId(),
  983. 'description' => $group->getDescription(),
  984. 'keys' => $keyList,
  985. ];
  986. }
  987. $groupCollectionMapping = $this->recursiveGetActiveGroupCollectionMapping($object);
  988. if (!empty($groupCollectionMapping)) {
  989. $collectionIds = array_values($groupCollectionMapping);
  990. $relation = new DataObject\Classificationstore\CollectionGroupRelation\Listing();
  991. $relation->setCondition('`colId` in (' . implode(',', array_fill(0, count($collectionIds), '?')) . ')', $collectionIds);
  992. $sorting = [];
  993. foreach ($relation->load() as $item) {
  994. $sorting[$item->getGroupId()] = $item->getSorter();
  995. }
  996. usort($this->activeGroupDefinitions, static function ($a, $b) use ($sorting) {
  997. $s1 = $sorting[$a['id']] ?: 0;
  998. $s2 = $sorting[$b['id']] ?: 0;
  999. return $s1 <=> $s2;
  1000. });
  1001. }
  1002. return $this;
  1003. }
  1004. /**
  1005. * @return array
  1006. */
  1007. public function getAllowedGroupIds()
  1008. {
  1009. return $this->allowedGroupIds;
  1010. }
  1011. /**
  1012. * @param array|string $allowedGroupIds
  1013. */
  1014. public function setAllowedGroupIds($allowedGroupIds)
  1015. {
  1016. $parts = [];
  1017. if (is_string($allowedGroupIds) && !empty($allowedGroupIds)) {
  1018. $allowedGroupIds = str_replace([' ', "\n"], '', $allowedGroupIds);
  1019. $parts = explode(',', $allowedGroupIds);
  1020. } elseif (is_array($allowedGroupIds)) {
  1021. $parts = $allowedGroupIds;
  1022. }
  1023. $this->allowedGroupIds = $parts;
  1024. }
  1025. /**
  1026. * @return int
  1027. */
  1028. public function getStoreId()
  1029. {
  1030. return $this->storeId ? $this->storeId : 1;
  1031. }
  1032. /**
  1033. * @param int $storeId
  1034. *
  1035. * @return $this
  1036. */
  1037. public function setStoreId($storeId)
  1038. {
  1039. $this->storeId = $storeId ? $storeId : 1;
  1040. return $this;
  1041. }
  1042. /**
  1043. * @return string[]
  1044. */
  1045. private function getValidLanguages()
  1046. {
  1047. if ($this->localized) {
  1048. $validLanguages = Tool::getValidLanguages();
  1049. } else {
  1050. $validLanguages = [];
  1051. }
  1052. array_unshift($validLanguages, 'default');
  1053. return $validLanguages;
  1054. }
  1055. /**
  1056. * @return bool
  1057. */
  1058. public function getHideEmptyData()
  1059. {
  1060. return $this->hideEmptyData;
  1061. }
  1062. /**
  1063. * @param bool $hideEmptyData
  1064. *
  1065. * @return $this
  1066. */
  1067. public function setHideEmptyData($hideEmptyData)
  1068. {
  1069. $this->hideEmptyData = (bool) $hideEmptyData;
  1070. return $this;
  1071. }
  1072. /**
  1073. * @return bool
  1074. */
  1075. public function isDisallowAddRemove()
  1076. {
  1077. return $this->disallowAddRemove;
  1078. }
  1079. /**
  1080. * @param bool $disallowAddRemove
  1081. *
  1082. * @return $this
  1083. */
  1084. public function setDisallowAddRemove($disallowAddRemove)
  1085. {
  1086. $this->disallowAddRemove = $disallowAddRemove;
  1087. return $this;
  1088. }
  1089. /**
  1090. * {@inheritdoc}
  1091. */
  1092. public function getParameterTypeDeclaration(): ?string
  1093. {
  1094. return '?\\' . DataObject\Classificationstore::class;
  1095. }
  1096. /**
  1097. * {@inheritdoc}
  1098. */
  1099. public function getReturnTypeDeclaration(): ?string
  1100. {
  1101. return '?\\' . DataObject\Classificationstore::class;
  1102. }
  1103. /**
  1104. * {@inheritdoc}
  1105. */
  1106. public function getPhpdocInputType(): ?string
  1107. {
  1108. return '\\' . DataObject\Classificationstore::class . '|null';
  1109. }
  1110. /**
  1111. * {@inheritdoc}
  1112. */
  1113. public function getPhpdocReturnType(): ?string
  1114. {
  1115. return '\\' . DataObject\Classificationstore::class . '|null';
  1116. }
  1117. /**
  1118. * {@inheritdoc}
  1119. */
  1120. public function normalize($value, $params = [])
  1121. {
  1122. if ($value instanceof DataObject\Classificationstore) {
  1123. $validLanguages = array_merge(['default'], Tool::getValidLanguages());
  1124. $result = [];
  1125. $activeGroups = $value->getActiveGroups();
  1126. if ($activeGroups) {
  1127. foreach ($activeGroups as $groupId => $active) {
  1128. if (!$active) {
  1129. continue;
  1130. }
  1131. $groupConfig = DataObject\Classificationstore\GroupConfig::getById($groupId);
  1132. $result[$groupConfig->getName()] = [];
  1133. $relation = new DataObject\Classificationstore\KeyGroupRelation\Listing();
  1134. $relation->setCondition('groupId = ' . $relation->quote($groupId));
  1135. $relation = $relation->load();
  1136. foreach ($validLanguages as $validLanguage) {
  1137. foreach ($relation as $key) {
  1138. $keyId = $key->getKeyId();
  1139. $csValue = $value->getLocalizedKeyValue($groupId, $keyId, $validLanguage, true, true);
  1140. $keyConfig = DataObject\Classificationstore\DefinitionCache::get($keyId);
  1141. $fd = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($keyConfig);
  1142. if ($fd instanceof NormalizerInterface) {
  1143. $csValue = $fd->normalize($csValue, $params);
  1144. }
  1145. if ($csValue !== null) {
  1146. $result[$groupConfig->getName()][$validLanguage][$key->getName()] = $csValue;
  1147. }
  1148. }
  1149. }
  1150. }
  1151. }
  1152. return $result;
  1153. }
  1154. return null;
  1155. }
  1156. /**
  1157. * {@inheritdoc}
  1158. */
  1159. public function denormalize($value, $params = [])
  1160. {
  1161. if (is_array($value)) {
  1162. $activeGroups = [];
  1163. $resultData = [];
  1164. foreach ($value as $groupName => $groupData) {
  1165. $groupConfig = DataObject\Classificationstore\GroupConfig::getByName($groupName);
  1166. $activeGroups[$groupConfig->getId()] = true;
  1167. $resultData[$groupConfig->getId()] = [];
  1168. foreach ($groupData as $language => $languageData) {
  1169. foreach ($languageData as $fieldKey => $fieldData) {
  1170. $keyConfig = DataObject\Classificationstore\KeyConfig::getByName($fieldKey);
  1171. $fd = DataObject\Classificationstore\Service::getFieldDefinitionFromKeyConfig($keyConfig);
  1172. if ($fd instanceof NormalizerInterface) {
  1173. $fieldData = $fd->denormalize($fieldData, $params);
  1174. }
  1175. $resultData[$groupConfig->getId()][$keyConfig->getId()][$language] = $fieldData;
  1176. }
  1177. }
  1178. }
  1179. $result = new DataObject\Classificationstore();
  1180. $result->setActiveGroups($activeGroups);
  1181. $result->setItems($resultData);
  1182. return $result;
  1183. }
  1184. return null;
  1185. }
  1186. }