vendor/pimcore/data-hub/src/WorkspaceHelper.php line 228

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\Bundle\DataHubBundle;
  15. use Pimcore\Bundle\DataHubBundle\Configuration\Workspace\Dao;
  16. use Pimcore\Bundle\DataHubBundle\Event\GraphQL\Model\PermissionEvent;
  17. use Pimcore\Bundle\DataHubBundle\Event\GraphQL\PermissionEvents;
  18. use Pimcore\Bundle\DataHubBundle\GraphQL\Exception\ClientSafeException;
  19. use Pimcore\Bundle\DataHubBundle\GraphQL\Exception\NotAllowedException;
  20. use Pimcore\Cache\RuntimeCache;
  21. use Pimcore\Db;
  22. use Pimcore\Logger;
  23. use Pimcore\Model\DataObject\OwnerAwareFieldInterface;
  24. use Pimcore\Model\Element\ElementInterface;
  25. use Pimcore\Model\Element\Service;
  26. use Symfony\Component\EventDispatcher\EventDispatcher;
  27. class WorkspaceHelper
  28. {
  29.     const MODIFY_SPACE_OBJECT 'object';
  30.     const MODIFY_SPACE_ASSET 'asset';
  31.     const MODIFY_SPACE_DOCUMENT 'document';
  32.     const MODIFY_TYPE_REPLACE 'replace';
  33.     const MODIFY_TYPE_DELETE 'delete';
  34.     /**
  35.      * @param array $workspaces
  36.      *
  37.      * @return array
  38.      */
  39.     public static function cleanupWorkspaces(array $workspaces)
  40.     {
  41.         foreach ($workspaces as $type => &$spaces) {
  42.             if (!is_array($spaces)) {
  43.                 continue;
  44.             }
  45.             foreach ($spaces as $spaceIndex => $space) {
  46.                 $element Service::getElementByPath($type$space['cpath']);
  47.                 if ($element instanceof ElementInterface) {
  48.                     continue;
  49.                 }
  50.                 unset($spaces[$spaceIndex]);
  51.             }
  52.             $spaces array_values($spaces); // reset array keys
  53.         }
  54.         return $workspaces;
  55.     }
  56.     /**
  57.      * @param Configuration $configurationEntity
  58.      * @param string        $spaceType
  59.      * @param string        $modificationType
  60.      * @param string        $searchValue
  61.      * @param string|null   $replaceValue
  62.      *
  63.      * @return Configuration|void
  64.      */
  65.     public static function modifyWorkspaceRowByType(Configuration $configurationEntity$spaceType$modificationType$searchValue$replaceValue)
  66.     {
  67.         $changed false;
  68.         $configuration $configurationEntity->getConfiguration();
  69.         if (!isset($configuration['workspaces']) || !is_array($configuration['workspaces'])) {
  70.             return;
  71.         }
  72.         $workspaces $configuration['workspaces'];
  73.         if (!isset($workspaces[$spaceType])) {
  74.             return;
  75.         }
  76.         $spaces $workspaces[$spaceType];
  77.         if (!is_array($spaces)) {
  78.             return;
  79.         }
  80.         foreach ($spaces as $spaceIndex => &$space) {
  81.             if (!isset($space['cpath'])) {
  82.                 continue;
  83.             }
  84.             $cPath $space['cpath'];
  85.             $cTrailingPath sprintf('%s/'$space['cpath']);
  86.             $cTrailingSearchValue sprintf('%s/'$searchValue);
  87.             $cTrailingReplaceValue sprintf('%s/'$replaceValue);
  88.             if ($cPath === $searchValue) {
  89.                 // it's the element itself
  90.                 $changed true;
  91.                 if ($modificationType === self::MODIFY_TYPE_REPLACE) {
  92.                     $space['cpath'] = $replaceValue;
  93.                 } elseif ($modificationType === self::MODIFY_TYPE_DELETE) {
  94.                     unset($spaces[$spaceIndex]);
  95.                     $spaces array_values($spaces); // reset array keys
  96.                 }
  97.             } elseif (strpos($cTrailingPath$cTrailingSearchValue) !== false) {
  98.                 // it's a sub element
  99.                 $changed true;
  100.                 if ($modificationType === self::MODIFY_TYPE_REPLACE) {
  101.                     $space['cpath'] = str_replace($cTrailingSearchValue$cTrailingReplaceValue$space['cpath']);
  102.                 } elseif ($modificationType === self::MODIFY_TYPE_DELETE) {
  103.                     unset($spaces[$spaceIndex]);
  104.                     $spaces array_values($spaces); // reset array keys
  105.                 }
  106.             }
  107.         }
  108.         if ($changed === false) {
  109.             return;
  110.         }
  111.         $workspaces[$spaceType] = $spaces;
  112.         $configuration['workspaces'] = $workspaces;
  113.         $configurationEntity->setConfiguration($configuration);
  114.         return $configurationEntity;
  115.     }
  116.     /**
  117.      * @param Configuration $config
  118.      * @param array         $workspaces
  119.      *
  120.      * @throws \Exception
  121.      */
  122.     public static function saveWorkspaces(Configuration $config$workspaces)
  123.     {
  124.         $db Db::get();
  125.         $db->delete(Dao::TABLE_NAME_DOCUMENT, ['configuration' => $config->getName()]);
  126.         $db->delete(Dao::TABLE_NAME_ASSET, ['configuration' => $config->getName()]);
  127.         $db->delete(Dao::TABLE_NAME_DATAOBJECT, ['configuration' => $config->getName()]);
  128.         if (is_array($workspaces)) {
  129.             foreach ($workspaces as $type => $spaces) {
  130.                 foreach ($spaces as $space) {
  131.                     $element \Pimcore\Model\Element\Service::getElementByPath($type$space['cpath']);
  132.                     if ($element) {
  133.                         $className '\\Pimcore\\Bundle\\DataHubBundle\\Configuration\\Workspace\\' \Pimcore\Model\Element\Service::getBaseClassNameForElement($type);
  134.                         /** @var Configuration\Workspace\AbstractWorkspace $workspace */
  135.                         $workspace = new $className();
  136.                         $workspace->setValues($space);
  137.                         $workspace->setConfiguration($config->getName());
  138.                         $workspace->setCid($element->getId());
  139.                         $workspace->setCpath($element->getRealFullPath());
  140.                         $workspace->save();
  141.                     }
  142.                 }
  143.             }
  144.         }
  145.     }
  146.     /**
  147.      * @param Configuration $configuration
  148.      *
  149.      * @return array
  150.      *
  151.      * @throws \Exception
  152.      */
  153.     public static function loadWorkspaces(Configuration $configuration)
  154.     {
  155.         $workspaces = [];
  156.         $types = ['document''asset''object'];
  157.         $db Db::get();
  158.         foreach ($types as $type) {
  159.             $workspaces[$type] = [];
  160.             $className '\\Pimcore\\Bundle\\DataHubBundle\\Configuration\\Workspace\\' \Pimcore\Model\Element\Service::getBaseClassNameForElement($type);
  161.             $result $db->fetchAllAssociative('SELECT * FROM plugin_datahub_workspaces_' $type ' WHERE configuration = ?', [$configuration->getName()]);
  162.             foreach ($result as $row) {
  163.                 $workspace = new $className();
  164.                 $workspace->setValues($row);
  165.                 $workspaces[$type][] = $workspace;
  166.             }
  167.         }
  168.         return $workspaces;
  169.     }
  170.     /**
  171.      * @param Configuration $config
  172.      *
  173.      * @throws \Exception
  174.      */
  175.     public static function deleteConfiguration(Configuration $config)
  176.     {
  177.         $db Db::get();
  178.         $db->delete(Dao::TABLE_NAME_DOCUMENT, ['configuration' => $config->getName()]);
  179.         $db->delete(Dao::TABLE_NAME_ASSET, ['configuration' => $config->getName()]);
  180.         $db->delete(Dao::TABLE_NAME_DATAOBJECT, ['configuration' => $config->getName()]);
  181.     }
  182.     /**
  183.      * @param ElementInterface|OwnerAwareFieldInterface $element
  184.      * @param string $type
  185.      *
  186.      * @return bool
  187.      *
  188.      * @throws NotAllowedException
  189.      */
  190.     public static function checkPermission($element$type)
  191.     {
  192.         $context RuntimeCache::get('datahub_context');
  193.         /** @var Configuration $configuration */
  194.         $configuration $context['configuration'];
  195.         if ($configuration->skipPermisssionCheck()) {
  196.             return true;
  197.         }
  198.         $event = new PermissionEvent($element$type);
  199.         /** @var EventDispatcher $eventDispatcher */
  200.         $eventDispatcher \Pimcore::getContainer()->get('event_dispatcher');
  201.         $eventDispatcher->dispatch($eventPermissionEvents::PRE_CHECK);
  202.         if (!$event->isGranted() && PimcoreDataHubBundle::getNotAllowedPolicy() === PimcoreDataHubBundle::NOT_ALLOWED_POLICY_EXCEPTION) {
  203.             throw new ClientSafeException('access for '.  $element->getFullPath() . ' denied');
  204.         }
  205.         $isAllowed self::isAllowed($element$configuration$type);
  206.         if (!$isAllowed && PimcoreDataHubBundle::getNotAllowedPolicy() === PimcoreDataHubBundle::NOT_ALLOWED_POLICY_EXCEPTION) {
  207.             $elementType Service::getElementType($element);
  208.             throw new ClientSafeException($type ' access for ' $elementType ' ' $element->getFullPath() . ' denied');
  209.         }
  210.         return $isAllowed;
  211.     }
  212.     /**
  213.      * @internal
  214.      *
  215.      * @param ElementInterface|OwnerAwareFieldInterface|null $element
  216.      * @param Configuration $configuration
  217.      * @param string $type
  218.      *
  219.      * @return bool
  220.      */
  221.     public static function isAllowed($elementConfiguration $configurationstring $type)
  222.     {
  223.         if (!$element) {
  224.             return false;
  225.         }
  226.         $elementType Service::getElementType($element);
  227.         // collect properties via parent - ids
  228.         $parentIds = [1];
  229.         $parent $element->getParent();
  230.         if ($parent) {
  231.             while ($parent) {
  232.                 $parentIds[] = $parent->getId();
  233.                 $parent $parent->getParent();
  234.             }
  235.         }
  236.         if ($element->getId()) {
  237.             $parentIds[] = $element->getId();
  238.         }
  239.         try {
  240.             $db Db::get();
  241.             $sql 'SELECT `' $type '` FROM plugin_datahub_workspaces_' $elementType ' WHERE cid IN (' implode(','$parentIds) . ') AND configuration = ' $db->quote($configuration->getName()) . ' AND `' $type '`=1 ORDER BY LENGTH(cpath) DESC LIMIT 1';
  242.             $permissionsParent $db->fetchOne($sql);
  243.             if ($permissionsParent) {
  244.                 return true;
  245.             }
  246.             // exception for read permission
  247.             if (empty($permissionsParent) && $type === 'read') {
  248.                 // check for children with permissions
  249.                 $path $element->getRealFullPath() . '/';
  250.                 $path str_replace('_''\\_'$path);
  251.                 if ($element->getId() === 1) {
  252.                     $path '/';
  253.                 }
  254.                 $permissionsChildren $db->fetchOne('SELECT ' $type ' FROM plugin_datahub_workspaces_' $elementType ' WHERE cpath LIKE ? AND configuration = ' $db->quote($configuration->getName()) . ' AND ' $type ' = 1 LIMIT 1', [$path '%']);
  255.                 if ($permissionsChildren) {
  256.                     return true;
  257.                 }
  258.             }
  259.         } catch (\Exception $e) {
  260.             Logger::warn('Unable to get permission ' $type ' for ' $elementType ' ' $element->getId());
  261.         }
  262.         return false;
  263.     }
  264. }