/web/core/lib/Drupal/Core/Database/Query/SelectExtender.php

https://gitlab.com/mohamed_hussein/prodt · PHP · 549 lines · 243 code · 76 blank · 230 comment · 5 complexity · c50aeddfaea83116c34c28c79e057245 MD5 · raw file

  1. <?php
  2. namespace Drupal\Core\Database\Query;
  3. use Drupal\Core\Database\Connection;
  4. /**
  5. * The base extender class for Select queries.
  6. */
  7. class SelectExtender implements SelectInterface {
  8. /**
  9. * The Select query object we are extending/decorating.
  10. *
  11. * @var \Drupal\Core\Database\Query\SelectInterface
  12. */
  13. protected $query;
  14. /**
  15. * The connection object on which to run this query.
  16. *
  17. * @var \Drupal\Core\Database\Connection
  18. */
  19. protected $connection;
  20. /**
  21. * A unique identifier for this query object.
  22. *
  23. * @var string
  24. */
  25. protected $uniqueIdentifier;
  26. /**
  27. * The placeholder counter.
  28. *
  29. * @var int
  30. */
  31. protected $placeholder = 0;
  32. public function __construct(SelectInterface $query, Connection $connection) {
  33. $this->uniqueIdentifier = uniqid('', TRUE);
  34. $this->query = $query;
  35. $this->connection = $connection;
  36. }
  37. /**
  38. * {@inheritdoc}
  39. */
  40. public function uniqueIdentifier() {
  41. return $this->uniqueIdentifier;
  42. }
  43. /**
  44. * {@inheritdoc}
  45. */
  46. public function nextPlaceholder() {
  47. return $this->placeholder++;
  48. }
  49. /**
  50. * {@inheritdoc}
  51. */
  52. public function addTag($tag) {
  53. $this->query->addTag($tag);
  54. return $this;
  55. }
  56. /**
  57. * {@inheritdoc}
  58. */
  59. public function hasTag($tag) {
  60. return $this->query->hasTag($tag);
  61. }
  62. /**
  63. * {@inheritdoc}
  64. */
  65. public function hasAllTags() {
  66. return call_user_func_array([$this->query, 'hasAllTags'], func_get_args());
  67. }
  68. /**
  69. * {@inheritdoc}
  70. */
  71. public function hasAnyTag() {
  72. return call_user_func_array([$this->query, 'hasAnyTag'], func_get_args());
  73. }
  74. /**
  75. * {@inheritdoc}
  76. */
  77. public function addMetaData($key, $object) {
  78. $this->query->addMetaData($key, $object);
  79. return $this;
  80. }
  81. /**
  82. * {@inheritdoc}
  83. */
  84. public function getMetaData($key) {
  85. return $this->query->getMetaData($key);
  86. }
  87. /**
  88. * {@inheritdoc}
  89. */
  90. public function condition($field, $value = NULL, $operator = '=') {
  91. $this->query->condition($field, $value, $operator);
  92. return $this;
  93. }
  94. /**
  95. * {@inheritdoc}
  96. */
  97. public function &conditions() {
  98. return $this->query->conditions();
  99. }
  100. /**
  101. * {@inheritdoc}
  102. */
  103. public function arguments() {
  104. return $this->query->arguments();
  105. }
  106. /**
  107. * {@inheritdoc}
  108. */
  109. public function where($snippet, $args = []) {
  110. $this->query->where($snippet, $args);
  111. return $this;
  112. }
  113. /**
  114. * {@inheritdoc}
  115. */
  116. public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
  117. return $this->query->compile($connection, $queryPlaceholder);
  118. }
  119. /**
  120. * {@inheritdoc}
  121. */
  122. public function compiled() {
  123. return $this->query->compiled();
  124. }
  125. /**
  126. * {@inheritdoc}
  127. */
  128. public function havingCondition($field, $value = NULL, $operator = '=') {
  129. $this->query->havingCondition($field, $value, $operator);
  130. return $this;
  131. }
  132. /**
  133. * {@inheritdoc}
  134. */
  135. public function &havingConditions() {
  136. return $this->query->havingConditions();
  137. }
  138. /**
  139. * {@inheritdoc}
  140. */
  141. public function havingArguments() {
  142. return $this->query->havingArguments();
  143. }
  144. /**
  145. * {@inheritdoc}
  146. */
  147. public function having($snippet, $args = []) {
  148. $this->query->having($snippet, $args);
  149. return $this;
  150. }
  151. /**
  152. * {@inheritdoc}
  153. */
  154. public function havingCompile(Connection $connection) {
  155. return $this->query->havingCompile($connection);
  156. }
  157. /**
  158. * {@inheritdoc}
  159. */
  160. public function havingIsNull($field) {
  161. $this->query->havingIsNull($field);
  162. return $this;
  163. }
  164. /**
  165. * {@inheritdoc}
  166. */
  167. public function havingIsNotNull($field) {
  168. $this->query->havingIsNotNull($field);
  169. return $this;
  170. }
  171. /**
  172. * {@inheritdoc}
  173. */
  174. public function havingExists(SelectInterface $select) {
  175. $this->query->havingExists($select);
  176. return $this;
  177. }
  178. /**
  179. * {@inheritdoc}
  180. */
  181. public function havingNotExists(SelectInterface $select) {
  182. $this->query->havingNotExists($select);
  183. return $this;
  184. }
  185. /**
  186. * {@inheritdoc}
  187. */
  188. public function extend($extender_name) {
  189. // We cannot call $this->query->extend(), because with multiple extenders
  190. // you will replace all the earlier extenders with the last extender,
  191. // instead of creating list of objects that extend each other.
  192. $parts = explode('\\', $extender_name);
  193. $class = end($parts);
  194. $driver_class = $this->connection->getDriverClass($class);
  195. if ($driver_class !== $class) {
  196. return new $driver_class($this, $this->connection);
  197. }
  198. return new $extender_name($this, $this->connection);
  199. }
  200. /* Alter accessors to expose the query data to alter hooks. */
  201. /**
  202. * {@inheritdoc}
  203. */
  204. public function &getFields() {
  205. return $this->query->getFields();
  206. }
  207. /**
  208. * {@inheritdoc}
  209. */
  210. public function &getExpressions() {
  211. return $this->query->getExpressions();
  212. }
  213. /**
  214. * {@inheritdoc}
  215. */
  216. public function &getOrderBy() {
  217. return $this->query->getOrderBy();
  218. }
  219. /**
  220. * {@inheritdoc}
  221. */
  222. public function &getGroupBy() {
  223. return $this->query->getGroupBy();
  224. }
  225. /**
  226. * {@inheritdoc}
  227. */
  228. public function &getTables() {
  229. return $this->query->getTables();
  230. }
  231. /**
  232. * {@inheritdoc}
  233. */
  234. public function &getUnion() {
  235. return $this->query->getUnion();
  236. }
  237. /**
  238. * {@inheritdoc}
  239. */
  240. public function escapeLike($string) {
  241. return $this->query->escapeLike($string);
  242. }
  243. /**
  244. * {@inheritdoc}
  245. */
  246. public function escapeField($string) {
  247. $this->query->escapeField($string);
  248. return $this;
  249. }
  250. /**
  251. * {@inheritdoc}
  252. */
  253. public function getArguments(PlaceholderInterface $queryPlaceholder = NULL) {
  254. return $this->query->getArguments($queryPlaceholder);
  255. }
  256. /**
  257. * {@inheritdoc}
  258. */
  259. public function isPrepared() {
  260. return $this->query->isPrepared();
  261. }
  262. /**
  263. * {@inheritdoc}
  264. */
  265. public function preExecute(SelectInterface $query = NULL) {
  266. // If no query object is passed in, use $this.
  267. if (!isset($query)) {
  268. $query = $this;
  269. }
  270. return $this->query->preExecute($query);
  271. }
  272. /**
  273. * {@inheritdoc}
  274. */
  275. public function execute() {
  276. // By calling preExecute() here, we force it to preprocess the extender
  277. // object rather than just the base query object. That means
  278. // hook_query_alter() gets access to the extended object.
  279. if (!$this->preExecute($this)) {
  280. return NULL;
  281. }
  282. return $this->query->execute();
  283. }
  284. /**
  285. * {@inheritdoc}
  286. */
  287. public function distinct($distinct = TRUE) {
  288. $this->query->distinct($distinct);
  289. return $this;
  290. }
  291. /**
  292. * {@inheritdoc}
  293. */
  294. public function addField($table_alias, $field, $alias = NULL) {
  295. return $this->query->addField($table_alias, $field, $alias);
  296. }
  297. /**
  298. * {@inheritdoc}
  299. */
  300. public function fields($table_alias, array $fields = []) {
  301. $this->query->fields($table_alias, $fields);
  302. return $this;
  303. }
  304. /**
  305. * {@inheritdoc}
  306. */
  307. public function addExpression($expression, $alias = NULL, $arguments = []) {
  308. return $this->query->addExpression($expression, $alias, $arguments);
  309. }
  310. /**
  311. * {@inheritdoc}
  312. */
  313. public function join($table, $alias = NULL, $condition = NULL, $arguments = []) {
  314. return $this->query->join($table, $alias, $condition, $arguments);
  315. }
  316. /**
  317. * {@inheritdoc}
  318. */
  319. public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
  320. return $this->query->innerJoin($table, $alias, $condition, $arguments);
  321. }
  322. /**
  323. * {@inheritdoc}
  324. */
  325. public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
  326. return $this->query->leftJoin($table, $alias, $condition, $arguments);
  327. }
  328. /**
  329. * {@inheritdoc}
  330. */
  331. public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = []) {
  332. return $this->query->addJoin($type, $table, $alias, $condition, $arguments);
  333. }
  334. /**
  335. * {@inheritdoc}
  336. */
  337. public function orderBy($field, $direction = 'ASC') {
  338. $this->query->orderBy($field, $direction);
  339. return $this;
  340. }
  341. /**
  342. * {@inheritdoc}
  343. */
  344. public function orderRandom() {
  345. $this->query->orderRandom();
  346. return $this;
  347. }
  348. /**
  349. * {@inheritdoc}
  350. */
  351. public function range($start = NULL, $length = NULL) {
  352. $this->query->range($start, $length);
  353. return $this;
  354. }
  355. /**
  356. * {@inheritdoc}
  357. */
  358. public function union(SelectInterface $query, $type = '') {
  359. $this->query->union($query, $type);
  360. return $this;
  361. }
  362. /**
  363. * {@inheritdoc}
  364. */
  365. public function groupBy($field) {
  366. $this->query->groupBy($field);
  367. return $this;
  368. }
  369. /**
  370. * {@inheritdoc}
  371. */
  372. public function forUpdate($set = TRUE) {
  373. $this->query->forUpdate($set);
  374. return $this;
  375. }
  376. /**
  377. * {@inheritdoc}
  378. */
  379. public function countQuery() {
  380. return $this->query->countQuery();
  381. }
  382. /**
  383. * {@inheritdoc}
  384. */
  385. public function isNull($field) {
  386. $this->query->isNull($field);
  387. return $this;
  388. }
  389. /**
  390. * {@inheritdoc}
  391. */
  392. public function isNotNull($field) {
  393. $this->query->isNotNull($field);
  394. return $this;
  395. }
  396. /**
  397. * {@inheritdoc}
  398. */
  399. public function exists(SelectInterface $select) {
  400. $this->query->exists($select);
  401. return $this;
  402. }
  403. /**
  404. * {@inheritdoc}
  405. */
  406. public function notExists(SelectInterface $select) {
  407. $this->query->notExists($select);
  408. return $this;
  409. }
  410. /**
  411. * {@inheritdoc}
  412. */
  413. public function alwaysFalse() {
  414. $this->query->alwaysFalse();
  415. return $this;
  416. }
  417. /**
  418. * {@inheritdoc}
  419. */
  420. public function __toString() {
  421. return (string) $this->query;
  422. }
  423. /**
  424. * {@inheritdoc}
  425. */
  426. public function __clone() {
  427. $this->uniqueIdentifier = uniqid('', TRUE);
  428. // We need to deep-clone the query we're wrapping, which in turn may
  429. // deep-clone other objects. Exciting!
  430. $this->query = clone($this->query);
  431. }
  432. /**
  433. * Magic override for undefined methods.
  434. *
  435. * If one extender extends another extender, then methods in the inner extender
  436. * will not be exposed on the outer extender. That's because we cannot know
  437. * in advance what those methods will be, so we cannot provide wrapping
  438. * implementations as we do above. Instead, we use this slower catch-all method
  439. * to handle any additional methods.
  440. */
  441. public function __call($method, $args) {
  442. $return = call_user_func_array([$this->query, $method], $args);
  443. // Some methods will return the called object as part of a fluent interface.
  444. // Others will return some useful value. If it's a value, then the caller
  445. // probably wants that value. If it's the called object, then we instead
  446. // return this object. That way we don't "lose" an extender layer when
  447. // chaining methods together.
  448. if ($return instanceof SelectInterface) {
  449. return $this;
  450. }
  451. else {
  452. return $return;
  453. }
  454. }
  455. /**
  456. * {@inheritdoc}
  457. */
  458. public function conditionGroupFactory($conjunction = 'AND') {
  459. return $this->connection->condition($conjunction);
  460. }
  461. /**
  462. * {@inheritdoc}
  463. */
  464. public function andConditionGroup() {
  465. return $this->conditionGroupFactory('AND');
  466. }
  467. /**
  468. * {@inheritdoc}
  469. */
  470. public function orConditionGroup() {
  471. return $this->conditionGroupFactory('OR');
  472. }
  473. }