vendor/pimcore/pimcore/models/Dependency/Dao.php line 130

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\Dependency;
  15. use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
  16. use Pimcore\Logger;
  17. use Pimcore\Messenger\SanityCheckMessage;
  18. use Pimcore\Model;
  19. use Pimcore\Model\Element;
  20. use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
  21. use Symfony\Component\Messenger\MessageBusInterface;
  22. /**
  23.  * @internal
  24.  *
  25.  * @property \Pimcore\Model\Dependency $model
  26.  */
  27. class Dao extends Model\Dao\AbstractDao
  28. {
  29.     /**
  30.      * Loads the relations for the given sourceId and type
  31.      *
  32.      * @param int $id
  33.      * @param string $type
  34.      *
  35.      * @return void
  36.      */
  37.     public function getBySourceId($id null$type null)
  38.     {
  39.         if ($id && $type) {
  40.             $this->model->setSourceId($id);
  41.             $this->model->setSourceType($type);
  42.         }
  43.         // requires
  44.         $data $this->db->fetchAll('SELECT dependencies.targetid,dependencies.targettype
  45.             FROM dependencies
  46.             LEFT JOIN objects ON dependencies.targetid=objects.o_id AND dependencies.targettype="object"
  47.             LEFT JOIN assets ON dependencies.targetid=assets.id AND dependencies.targettype="asset"
  48.             LEFT JOIN documents ON dependencies.targetid=documents.id AND dependencies.targettype="document"
  49.             WHERE dependencies.sourceid = ? AND dependencies.sourcetype = ?
  50.             ORDER BY objects.o_path, objects.o_key, documents.path, documents.key, assets.path, assets.filename',
  51.             [$this->model->getSourceId(), $this->model->getSourceType()]);
  52.         if (is_array($data) && count($data) > 0) {
  53.             foreach ($data as $d) {
  54.                 $this->model->addRequirement($d['targetid'], $d['targettype']);
  55.             }
  56.         }
  57.     }
  58.     /**
  59.      * Clear all relations in the database
  60.      *
  61.      * @param Element\ElementInterface $element
  62.      *
  63.      * @return void
  64.      */
  65.     public function cleanAllForElement($element)
  66.     {
  67.         try {
  68.             $id $element->getId();
  69.             $type Element\Service::getElementType($element);
  70.             //schedule for sanity check
  71.             $data $this->db->fetchAll('SELECT `sourceid`, `sourcetype` FROM dependencies WHERE targetid = ? AND targettype = ?', [$id$type]);
  72.             if (is_array($data)) {
  73.                 foreach ($data as $row) {
  74.                     \Pimcore::getContainer()->get(MessageBusInterface::class)->dispatch(
  75.                         new SanityCheckMessage($row['sourcetype'], $row['sourceid'])
  76.                     );
  77.                 }
  78.             }
  79.             $this->db->selectAndDeleteWhere('dependencies''id'$this->db->quoteInto('sourceid = ?'$id) . ' AND  ' $this->db->quoteInto('sourcetype = ?'$type));
  80.         } catch (\Exception $e) {
  81.             Logger::error($e);
  82.         }
  83.     }
  84.     /**
  85.      * Clear all relations in the database for current source id
  86.      *
  87.      * @return void
  88.      */
  89.     public function clear()
  90.     {
  91.         try {
  92.             $this->db->selectAndDeleteWhere('dependencies''id'$this->db->quoteInto('sourceid = ?'$this->model->getSourceId()) . ' AND  ' $this->db->quoteInto('sourcetype = ?'$this->model->getSourceType()));
  93.         } catch (\Exception $e) {
  94.             Logger::error($e);
  95.         }
  96.     }
  97.     /**
  98.      * Save to database
  99.      *
  100.      * @return void
  101.      */
  102.     public function save()
  103.     {
  104.         // get existing dependencies
  105.         $existingDependenciesRaw $this->db->fetchAll('SELECT id, targetType, targetId FROM dependencies WHERE sourceType= ? AND sourceId = ?',
  106.             [$this->model->getSourceType(), $this->model->getSourceId()]);
  107.         $existingDepencies = [];
  108.         foreach ($existingDependenciesRaw as $dep) {
  109.             $targetType $dep['targetType'];
  110.             $targetId $dep['targetId'];
  111.             $rowId $dep['id'];
  112.             if (!isset($existingDepencies[$targetType])) {
  113.                 $existingDepencies[$targetType] = [];
  114.             }
  115.             $existingDepencies[$targetType][$targetId] = $rowId;
  116.         }
  117.         $requires $this->model->getRequires();
  118.         // now calculate the delta, everything that stays in existingDependencies has to be deleted
  119.         $newData = [];
  120.         foreach ($requires as $r) {
  121.             $targetType $r['type'];
  122.             $targetId $r['id'];
  123.             if ($targetType && $targetId) {
  124.                 if (!isset($existingDepencies[$targetType][$targetId])) {
  125.                     // mark for insertion
  126.                     $newData[] = $r;
  127.                 } else {
  128.                     // unmark for deletion
  129.                     unset($existingDepencies[$targetType][$targetId]);
  130.                 }
  131.             }
  132.         }
  133.         // collect all IDs for deletion
  134.         $idsForDeletion = [];
  135.         foreach ($existingDepencies as $targetType => $targetIds) {
  136.             foreach ($targetIds as $targetId => $rowId) {
  137.                 $idsForDeletion[] = $rowId;
  138.             }
  139.         }
  140.         if ($idsForDeletion) {
  141.             $idString implode(','$idsForDeletion);
  142.             $this->db->deleteWhere('dependencies''id IN (' $idString ')');
  143.         }
  144.         if ($newData) {
  145.             foreach ($newData as $target) {
  146.                 try {
  147.                     $this->db->insert('dependencies', [
  148.                         'sourceid' => $this->model->getSourceId(),
  149.                         'sourcetype' => $this->model->getSourceType(),
  150.                         'targetid' => $target['id'],
  151.                         'targettype' => $target['type'],
  152.                     ]);
  153.                 } catch (UniqueConstraintViolationException $e) {
  154.                 }
  155.             }
  156.         }
  157.     }
  158.     /**
  159.      * Loads the relations that need the given source element
  160.      *
  161.      * @param int $offset
  162.      * @param int $limit
  163.      *
  164.      * @return array
  165.      */
  166.     public function getRequiredBy($offset null$limit null)
  167.     {
  168.         $query '
  169.             SELECT dependencies.sourceid, dependencies.sourcetype FROM dependencies
  170.             LEFT JOIN objects ON dependencies.sourceid=objects.o_id AND dependencies.sourcetype="object"
  171.             LEFT JOIN assets ON dependencies.sourceid=assets.id AND dependencies.sourcetype="asset"
  172.             LEFT JOIN documents ON dependencies.sourceid=documents.id AND dependencies.sourcetype="document"
  173.             WHERE dependencies.targetid = ? AND dependencies.targettype = ?
  174.             ORDER BY objects.o_path, objects.o_key, documents.path, documents.key, assets.path, assets.filename
  175.         ';
  176.         if ($offset !== null && $limit !== null) {
  177.             $query sprintf($query ' LIMIT %d,%d'$offset$limit);
  178.         }
  179.         $data $this->db->fetchAll($query, [$this->model->getSourceId(), $this->model->getSourceType()]);
  180.         $requiredBy = [];
  181.         if (is_array($data) && count($data) > 0) {
  182.             foreach ($data as $d) {
  183.                 $requiredBy[] = [
  184.                     'id' => $d['sourceid'],
  185.                     'type' => $d['sourcetype'],
  186.                 ];
  187.             }
  188.         }
  189.         return $requiredBy;
  190.     }
  191.     /**
  192.      * @param string|null $orderBy
  193.      * @param string|null $orderDirection
  194.      * @param int|null $offset
  195.      * @param int|null $limit
  196.      *
  197.      * @return array
  198.      */
  199.     public function getRequiredByWithPath($offset null$limit null$orderBy null$orderDirection null)
  200.     {
  201.         $targetId = (int)$this->model->getSourceId();
  202.         if (in_array($this->model->getSourceType(), ['object''document''asset'])) {
  203.             $targetType $this->model->getSourceType();
  204.         } else {
  205.             throw new SuspiciousOperationException('Illegal source type ' $this->model->getSourceType());
  206.         }
  207.         if (!in_array($orderBy, ['id''type''path'])) {
  208.             $orderBy 'id';
  209.         }
  210.         if (!in_array($orderDirection, ['ASC''DESC'])) {
  211.             $orderDirection 'ASC';
  212.         }
  213.         $query '
  214.             SELECT id, type, path
  215.             FROM (
  216.                 SELECT d.sourceid as id, d.sourcetype as type, CONCAT(o.o_path, o.o_key) as path
  217.                 FROM dependencies d
  218.                 JOIN objects o ON o.o_id = d.sourceid
  219.                 WHERE d.targetid = ' $targetId " AND  d.targettype = '" $targetType"' AND d.sourceType = 'object'
  220.                 UNION
  221.                 SELECT d.sourceid as id, d.sourcetype as type, CONCAT(doc.path, doc.key) as path
  222.                 FROM dependencies d
  223.                 JOIN documents doc ON doc.id = d.sourceid
  224.                 WHERE d.targetid = " $targetId " AND  d.targettype = '" $targetType"' AND d.sourceType = 'document'
  225.                 UNION
  226.                 SELECT d.sourceid as id, d.sourcetype as type, CONCAT(a.path, a.filename) as path
  227.                 FROM dependencies d
  228.                 JOIN assets a ON a.id = d.sourceid
  229.                 WHERE d.targetid = " $targetId " AND  d.targettype = '" $targetType"' AND d.sourceType = 'asset'
  230.             ) dep
  231.             ORDER BY " $orderBy ' ' $orderDirection;
  232.         if (is_int($offset) && is_int($limit)) {
  233.             $query .= ' LIMIT ' $offset ', ' $limit;
  234.         }
  235.         $requiredBy $this->db->fetchAll($query);
  236.         if (is_array($requiredBy) && count($requiredBy) > 0) {
  237.             return $requiredBy;
  238.         } else {
  239.             return [];
  240.         }
  241.     }
  242.     /**
  243.      * get total count of required by records
  244.      *
  245.      * @return int
  246.      */
  247.     public function getRequiredByTotalCount()
  248.     {
  249.         return (int) $this->db->fetchOne('SELECT COUNT(*) FROM dependencies WHERE targetid = ? AND targettype = ?', [$this->model->getSourceId(), $this->model->getSourceType()]);
  250.     }
  251. }