vendor/pimcore/pimcore/lib/Model/Listing/AbstractListing.php line 556

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\Listing;
  15. use Doctrine\DBAL\Connection;
  16. use Doctrine\DBAL\Query\QueryBuilder;
  17. use Pimcore\Db;
  18. use Pimcore\Model\AbstractModel;
  19. use Pimcore\Model\Listing\Dao\AbstractDao;
  20. /**
  21. * @method AbstractDao getDao()
  22. * @method QueryBuilder getQueryBuilder()
  23. */
  24. abstract class AbstractListing extends AbstractModel implements \Iterator, \Countable
  25. {
  26. /**
  27. * @var array
  28. */
  29. protected $order = [];
  30. /**
  31. * @var array
  32. */
  33. protected $orderKey = [];
  34. /**
  35. * @var int
  36. */
  37. protected $limit;
  38. /**
  39. * @var int
  40. */
  41. protected $offset;
  42. /**
  43. * @var string
  44. */
  45. protected $condition;
  46. /**
  47. * @var array
  48. */
  49. protected $conditionVariables = [];
  50. /**
  51. * @var array
  52. */
  53. protected $conditionVariablesFromSetCondition;
  54. /**
  55. * @var string
  56. */
  57. protected $groupBy;
  58. /**
  59. * @var array
  60. */
  61. protected $validOrders = [
  62. 'ASC',
  63. 'DESC',
  64. ];
  65. /**
  66. * @var array
  67. */
  68. protected $conditionParams = [];
  69. /**
  70. * @var array
  71. */
  72. protected $conditionVariableTypes = [];
  73. /**
  74. * @var array|null
  75. */
  76. protected $data;
  77. /**
  78. * @return array
  79. */
  80. public function getConditionVariableTypes(): array
  81. {
  82. if (!$this->conditionVariables) {
  83. $this->getCondition();
  84. }
  85. return $this->conditionVariableTypes;
  86. }
  87. /**
  88. * @param array $conditionVariableTypes
  89. */
  90. public function setConditionVariableTypes(array $conditionVariableTypes): void
  91. {
  92. $this->conditionVariableTypes = $conditionVariableTypes;
  93. }
  94. /**
  95. * @param string $key
  96. *
  97. * @return bool
  98. */
  99. public function isValidOrderKey($key)
  100. {
  101. return true;
  102. }
  103. /**
  104. * @return int
  105. */
  106. public function getLimit()
  107. {
  108. return $this->limit;
  109. }
  110. /**
  111. * @return int
  112. */
  113. public function getOffset()
  114. {
  115. return $this->offset;
  116. }
  117. /**
  118. * @return array
  119. */
  120. public function getOrder()
  121. {
  122. return $this->order;
  123. }
  124. /**
  125. * @param int $limit
  126. *
  127. * @return $this
  128. */
  129. public function setLimit($limit)
  130. {
  131. $this->setData(null);
  132. if ((int)$limit > 0) {
  133. $this->limit = (int)$limit;
  134. }
  135. return $this;
  136. }
  137. /**
  138. * @param int $offset
  139. *
  140. * @return $this
  141. */
  142. public function setOffset($offset)
  143. {
  144. $this->setData(null);
  145. if ((int)$offset >= 0) {
  146. $this->offset = (int)$offset;
  147. }
  148. return $this;
  149. }
  150. /**
  151. * @param array|string $order
  152. *
  153. * @return $this
  154. */
  155. public function setOrder($order)
  156. {
  157. $this->setData(null);
  158. $this->order = [];
  159. if (!empty($order)) {
  160. if (is_string($order)) {
  161. $order = strtoupper($order);
  162. if (in_array($order, $this->validOrders)) {
  163. $this->order[] = $order;
  164. }
  165. } elseif (is_array($order)) {
  166. foreach ($order as $o) {
  167. $o = strtoupper($o);
  168. if (in_array($o, $this->validOrders)) {
  169. $this->order[] = $o;
  170. }
  171. }
  172. }
  173. }
  174. return $this;
  175. }
  176. /**
  177. * @return array
  178. */
  179. public function getOrderKey()
  180. {
  181. return $this->orderKey;
  182. }
  183. /**
  184. * @param string|array $orderKey
  185. * @param bool $quote
  186. *
  187. * @return $this
  188. */
  189. public function setOrderKey($orderKey, $quote = true)
  190. {
  191. $this->setData(null);
  192. $this->orderKey = [];
  193. if (is_string($orderKey) && !empty($orderKey)) {
  194. $orderKey = [$orderKey];
  195. }
  196. if (is_array($orderKey)) {
  197. foreach ($orderKey as $o) {
  198. if ($quote === false) {
  199. $this->orderKey[] = $o;
  200. } elseif ($this->isValidOrderKey($o)) {
  201. $this->orderKey[] = '`' . $o . '`';
  202. }
  203. }
  204. }
  205. return $this;
  206. }
  207. /**
  208. * @param string $key
  209. * @param mixed $value
  210. * @param string $concatenator
  211. *
  212. * @return $this
  213. */
  214. public function addConditionParam($key, $value = null, $concatenator = 'AND')
  215. {
  216. $this->setData(null);
  217. $key = '('.$key.')';
  218. $ignore = true;
  219. if (strpos($key, '?') !== false || strpos($key, ':') !== false) {
  220. $ignore = false;
  221. }
  222. $this->conditionParams[$key] = [
  223. 'value' => $value,
  224. 'concatenator' => $concatenator,
  225. 'ignore-value' => $ignore, // If there is not a placeholder, ignore value!
  226. ];
  227. return $this;
  228. }
  229. /**
  230. * @return array
  231. */
  232. public function getConditionParams()
  233. {
  234. return $this->conditionParams;
  235. }
  236. /**
  237. * @return $this
  238. */
  239. public function resetConditionParams()
  240. {
  241. $this->setData(null);
  242. $this->conditionParams = [];
  243. return $this;
  244. }
  245. /**
  246. * @return string
  247. */
  248. public function getCondition()
  249. {
  250. $conditionString = '';
  251. $conditionVariableTypes = [];
  252. $conditionParams = $this->getConditionParams();
  253. $db = \Pimcore\Db::get();
  254. $params = [];
  255. if (!empty($conditionParams)) {
  256. $i = 0;
  257. foreach ($conditionParams as $key => $value) {
  258. if (!$this->condition && $i == 0) {
  259. $conditionString .= $key . ' ';
  260. } else {
  261. $conditionString .= ' ' . $value['concatenator'] . ' ' . $key . ' ';
  262. }
  263. // If there is not a placeholder, ignore value!
  264. if (!$value['ignore-value']) {
  265. if (is_array($value['value'])) {
  266. foreach ($value['value'] as $k => $v) {
  267. if (is_int($k)) {
  268. $params[] = $v;
  269. } else {
  270. $params[$k] = $v;
  271. }
  272. }
  273. } else {
  274. $params[] = $value['value'];
  275. }
  276. }
  277. $i++;
  278. }
  279. }
  280. $params = array_merge((array) $this->getConditionVariablesFromSetCondition(), $params);
  281. $this->setConditionVariables($params);
  282. foreach ($params as $pkey => $param) {
  283. if (is_array($param)) {
  284. if (isset($param[0]) && is_string($param[0])) {
  285. $conditionVariableTypes[$pkey] = Connection::PARAM_STR_ARRAY;
  286. } else {
  287. $conditionVariableTypes[$pkey] = Connection::PARAM_INT_ARRAY;
  288. }
  289. } else {
  290. if (is_bool($param)) {
  291. $type = \PDO::PARAM_BOOL;
  292. } elseif (is_int($param)) {
  293. $type = \PDO::PARAM_INT;
  294. } elseif (is_null($param)) {
  295. $type = \PDO::PARAM_NULL;
  296. } else {
  297. $type = \PDO::PARAM_STR;
  298. }
  299. $conditionVariableTypes[$pkey] = $type;
  300. }
  301. }
  302. $this->setConditionVariableTypes($conditionVariableTypes);
  303. $condition = $this->condition . $conditionString;
  304. return $condition;
  305. }
  306. /**
  307. * @param string $condition
  308. * @param array|scalar $conditionVariables
  309. *
  310. * @return $this
  311. */
  312. public function setCondition($condition, $conditionVariables = null)
  313. {
  314. $this->setData(null);
  315. $this->condition = $condition;
  316. // statement variables
  317. if (is_array($conditionVariables)) {
  318. $this->setConditionVariablesFromSetCondition($conditionVariables);
  319. } elseif ($conditionVariables !== null) {
  320. $this->setConditionVariablesFromSetCondition([$conditionVariables]);
  321. }
  322. return $this;
  323. }
  324. /**
  325. * @return string
  326. */
  327. public function getGroupBy()
  328. {
  329. return $this->groupBy;
  330. }
  331. /**
  332. * @return array
  333. */
  334. public function getValidOrders()
  335. {
  336. return $this->validOrders;
  337. }
  338. /**
  339. * @param string $groupBy
  340. * @param bool $qoute
  341. *
  342. * @return $this
  343. */
  344. public function setGroupBy($groupBy, $qoute = true)
  345. {
  346. $this->setData(null);
  347. if ($groupBy) {
  348. $this->groupBy = $groupBy;
  349. if ($qoute && strpos($groupBy, '`') !== 0) {
  350. $this->groupBy = '`' . $this->groupBy . '`';
  351. }
  352. }
  353. return $this;
  354. }
  355. /**
  356. * @param array $validOrders
  357. *
  358. * @return $this
  359. */
  360. public function setValidOrders($validOrders)
  361. {
  362. $this->validOrders = $validOrders;
  363. return $this;
  364. }
  365. /**
  366. * @param mixed $value
  367. * @param int|null $type
  368. *
  369. * @return string
  370. */
  371. public function quote($value, $type = null)
  372. {
  373. $db = Db::get();
  374. return $db->quote($value, $type);
  375. }
  376. /**
  377. * @param string $value
  378. *
  379. * @return string
  380. */
  381. public function escapeLike(string $value): string
  382. {
  383. $db = Db::get();
  384. return $db->escapeLike($value);
  385. }
  386. /**
  387. * @param array $conditionVariables
  388. *
  389. * @return $this
  390. */
  391. public function setConditionVariables($conditionVariables)
  392. {
  393. $this->conditionVariables = $conditionVariables;
  394. return $this;
  395. }
  396. /**
  397. * @return array
  398. */
  399. public function getConditionVariables()
  400. {
  401. $this->getCondition(); // this will merge conditionVariablesFromSetCondition and additional params into conditionVariables
  402. return $this->conditionVariables;
  403. }
  404. /**
  405. * @param array $conditionVariables
  406. *
  407. * @return $this
  408. */
  409. public function setConditionVariablesFromSetCondition($conditionVariables)
  410. {
  411. $this->setData(null);
  412. $this->conditionVariablesFromSetCondition = $conditionVariables;
  413. return $this;
  414. }
  415. /**
  416. * @return array
  417. */
  418. public function getConditionVariablesFromSetCondition()
  419. {
  420. return $this->conditionVariablesFromSetCondition;
  421. }
  422. /**
  423. * @return bool
  424. */
  425. public function isLoaded()
  426. {
  427. return $this->data !== null;
  428. }
  429. /**
  430. * @return array
  431. */
  432. public function getData()
  433. {
  434. if ($this->data === null) {
  435. $this->getDao()->load();
  436. }
  437. return $this->data;
  438. }
  439. /**
  440. * @param array|null $data
  441. *
  442. * @return static
  443. */
  444. public function setData(?array $data): self
  445. {
  446. $this->data = $data;
  447. return $this;
  448. }
  449. /**
  450. * @return mixed
  451. */
  452. public function current()
  453. {
  454. $this->getData();
  455. return current($this->data);
  456. }
  457. /**
  458. * @return mixed
  459. */
  460. public function key()
  461. {
  462. $this->getData();
  463. return key($this->data);
  464. }
  465. /**
  466. * @return mixed|null
  467. */
  468. public function next()
  469. {
  470. $this->getData();
  471. return next($this->data);
  472. }
  473. /**
  474. * @return bool
  475. */
  476. public function valid()
  477. {
  478. $this->getData();
  479. return $this->current() !== false;
  480. }
  481. public function rewind()
  482. {
  483. $this->getData();
  484. reset($this->data);
  485. }
  486. /**
  487. * @return int
  488. */
  489. public function count()
  490. {
  491. return $this->getDao()->getTotalCount();
  492. }
  493. }