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

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