SelectExtender.php 11 KB

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