PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/web/core/modules/views/src/Plugin/views/query/QueryPluginBase.php

https://gitlab.com/andecode/theme-spark
PHP | 389 lines | 137 code | 46 blank | 206 comment | 13 complexity | f84eaea21240be0c2c68b06bd425fc35 MD5 | raw file
  1. <?php
  2. namespace Drupal\views\Plugin\views\query;
  3. use Drupal\Core\Cache\Cache;
  4. use Drupal\Core\Cache\CacheableDependencyInterface;
  5. use Drupal\Core\Form\FormStateInterface;
  6. use Drupal\views\Plugin\views\PluginBase;
  7. use Drupal\views\ViewExecutable;
  8. use Drupal\views\Views;
  9. /**
  10. * @defgroup views_query_plugins Views query plugins
  11. * @{
  12. * Plugins for views queries.
  13. *
  14. * Query plugins generate and execute a built query object against a
  15. * particular storage backend, converting the Views query object into an
  16. * actual query. Although query plugins need not necessarily use SQL, most
  17. * other handler plugins that affect the query (fields, filters, etc.)
  18. * implicitly assume that the query is using SQL.
  19. *
  20. * Query plugins extend \Drupal\views\Plugin\views\query\QueryPluginBase.
  21. * They must be annotated with \Drupal\views\Annotation\ViewsQuery
  22. * annotation, and they must be in namespace directory Plugin\views\query.
  23. *
  24. * @ingroup views_plugins
  25. * @see plugin_api
  26. */
  27. /**
  28. * Base plugin class for Views queries.
  29. */
  30. abstract class QueryPluginBase extends PluginBase implements CacheableDependencyInterface {
  31. /**
  32. * A pager plugin that should be provided by the display.
  33. *
  34. * @var views_plugin_pager
  35. */
  36. public $pager = NULL;
  37. /**
  38. * Stores the limit of items that should be requested in the query.
  39. *
  40. * @var int
  41. */
  42. protected $limit;
  43. /**
  44. * Generate a query and a countquery from all of the information supplied
  45. * to the object.
  46. *
  47. * @param $get_count
  48. * Provide a countquery if this is true, otherwise provide a normal query.
  49. */
  50. public function query($get_count = FALSE) {}
  51. /**
  52. * Let modules modify the query just prior to finalizing it.
  53. *
  54. * @param \Drupal\views\ViewExecutable $view
  55. * The view which is executed.
  56. */
  57. public function alter(ViewExecutable $view) {}
  58. /**
  59. * Builds the necessary info to execute the query.
  60. *
  61. * @param \Drupal\views\ViewExecutable $view
  62. * The view which is executed.
  63. */
  64. public function build(ViewExecutable $view) {}
  65. /**
  66. * Executes the query and fills the associated view object with according
  67. * values.
  68. *
  69. * Values to set: $view->result, $view->total_rows, $view->execute_time,
  70. * $view->pager['current_page'].
  71. *
  72. * $view->result should contain an array of objects. The array must use a
  73. * numeric index starting at 0.
  74. *
  75. * @param \Drupal\views\ViewExecutable $view
  76. * The view which is executed.
  77. */
  78. public function execute(ViewExecutable $view) {}
  79. /**
  80. * Add a signature to the query, if such a thing is feasible.
  81. *
  82. * This signature is something that can be used when perusing query logs to
  83. * discern where particular queries might be coming from.
  84. *
  85. * @param \Drupal\views\ViewExecutable $view
  86. * The view which is executed.
  87. */
  88. public function addSignature(ViewExecutable $view) {}
  89. /**
  90. * Get aggregation info for group by queries.
  91. *
  92. * If NULL, aggregation is not allowed.
  93. */
  94. public function getAggregationInfo() {}
  95. public function validateOptionsForm(&$form, FormStateInterface $form_state) {}
  96. public function submitOptionsForm(&$form, FormStateInterface $form_state) {}
  97. public function summaryTitle() {
  98. return $this->t('Settings');
  99. }
  100. /**
  101. * {@inheritdoc}
  102. */
  103. public function calculateDependencies() {
  104. $dependencies = [];
  105. foreach ($this->getEntityTableInfo() as $entity_type => $info) {
  106. if (!empty($info['provider'])) {
  107. $dependencies['module'][] = $info['provider'];
  108. }
  109. }
  110. return $dependencies;
  111. }
  112. /**
  113. * Set a LIMIT on the query, specifying a maximum number of results.
  114. */
  115. public function setLimit($limit) {
  116. $this->limit = $limit;
  117. }
  118. /**
  119. * Set an OFFSET on the query, specifying a number of results to skip.
  120. */
  121. public function setOffset($offset) {
  122. $this->offset = $offset;
  123. }
  124. /**
  125. * Returns the limit of the query.
  126. */
  127. public function getLimit() {
  128. return $this->limit;
  129. }
  130. /**
  131. * Create a new grouping for the WHERE or HAVING clause.
  132. *
  133. * @param $type
  134. * Either 'AND' or 'OR'. All items within this group will be added
  135. * to the WHERE clause with this logical operator.
  136. * @param $group
  137. * An ID to use for this group. If unspecified, an ID will be generated.
  138. * @param $where
  139. * 'where' or 'having'.
  140. *
  141. * @return
  142. * The group ID generated.
  143. */
  144. public function setWhereGroup($type = 'AND', $group = NULL, $where = 'where') {
  145. // Set an alias.
  146. $groups = &$this->$where;
  147. if (!isset($group)) {
  148. $group = empty($groups) ? 1 : max(array_keys($groups)) + 1;
  149. }
  150. // Create an empty group
  151. if (empty($groups[$group])) {
  152. $groups[$group] = ['conditions' => [], 'args' => []];
  153. }
  154. $groups[$group]['type'] = strtoupper($type);
  155. return $group;
  156. }
  157. /**
  158. * Control how all WHERE and HAVING groups are put together.
  159. *
  160. * @param $type
  161. * Either 'AND' or 'OR'
  162. */
  163. public function setGroupOperator($type = 'AND') {
  164. $this->groupOperator = strtoupper($type);
  165. }
  166. /**
  167. * Loads all entities contained in the passed-in $results.
  168. *
  169. * If the entity belongs to the base table, then it gets stored in
  170. * $result->_entity. Otherwise, it gets stored in
  171. * $result->_relationship_entities[$relationship_id];
  172. *
  173. * Query plugins that don't support entities can leave the method empty.
  174. */
  175. public function loadEntities(&$results) {}
  176. /**
  177. * Returns a Unix timestamp to database native timestamp expression.
  178. *
  179. * @param string $field
  180. * The query field that will be used in the expression.
  181. * @param bool $string_date
  182. * For certain databases, date format functions vary depending on string or
  183. * numeric storage.
  184. * @param bool $calculate_offset
  185. * If set to TRUE, the timezone offset will be included in the returned
  186. * field.
  187. *
  188. * @return string
  189. * An expression representing a timestamp with time zone.
  190. */
  191. public function getDateField($field, $string_date = FALSE, $calculate_offset = TRUE) {
  192. return $field;
  193. }
  194. /**
  195. * Set the database to the current user timezone.
  196. *
  197. * @return string
  198. * The current timezone as returned by date_default_timezone_get().
  199. */
  200. public function setupTimezone() {
  201. return date_default_timezone_get();
  202. }
  203. /**
  204. * Creates cross-database date formatting.
  205. *
  206. * @param string $field
  207. * An appropriate query expression pointing to the date field.
  208. * @param string $format
  209. * A format string for the result, like 'Y-m-d H:i:s'.
  210. * @param bool $string_date
  211. * For certain databases, date format functions vary depending on string or
  212. * numeric storage.
  213. *
  214. * @return string
  215. * A string representing the field formatted as a date in the format
  216. * specified by $format.
  217. */
  218. public function getDateFormat($field, $format, $string_date = FALSE) {
  219. return $field;
  220. }
  221. /**
  222. * Returns an array of all tables from the query that map to an entity type.
  223. *
  224. * Includes the base table and all relationships, if eligible.
  225. *
  226. * Available keys for each table:
  227. * - base: The actual base table (i.e. "user" for an author relationship).
  228. * - relationship_id: The id of the relationship, or "none".
  229. * - alias: The alias used for the relationship.
  230. * - entity_type: The entity type matching the base table.
  231. * - revision: A boolean that specifies whether the table is a base table or
  232. * a revision table of the entity type.
  233. *
  234. * @return array
  235. * An array of table information, keyed by table alias.
  236. */
  237. public function getEntityTableInfo() {
  238. // Start with the base table.
  239. $entity_tables = [];
  240. $views_data = Views::viewsData();
  241. $base_table = $this->view->storage->get('base_table');
  242. $base_table_data = $views_data->get($base_table);
  243. if (isset($base_table_data['table']['entity type'])) {
  244. $entity_tables[$base_table_data['table']['entity type']] = [
  245. 'base' => $base_table,
  246. 'alias' => $base_table,
  247. 'relationship_id' => 'none',
  248. 'entity_type' => $base_table_data['table']['entity type'],
  249. 'revision' => $base_table_data['table']['entity revision'],
  250. ];
  251. // Include the entity provider.
  252. if (!empty($base_table_data['table']['provider'])) {
  253. $entity_tables[$base_table_data['table']['entity type']]['provider'] = $base_table_data['table']['provider'];
  254. }
  255. }
  256. // Include all relationships.
  257. foreach ((array) $this->view->relationship as $relationship_id => $relationship) {
  258. $table_data = $views_data->get($relationship->definition['base']);
  259. if (isset($table_data['table']['entity type'])) {
  260. // If this is not one of the entity base tables, skip it.
  261. $entity_type = \Drupal::entityTypeManager()->getDefinition($table_data['table']['entity type']);
  262. $entity_base_tables = [$entity_type->getBaseTable(), $entity_type->getDataTable(), $entity_type->getRevisionTable(), $entity_type->getRevisionDataTable()];
  263. if (!in_array($relationship->definition['base'], $entity_base_tables)) {
  264. continue;
  265. }
  266. $entity_tables[$relationship_id . '__' . $relationship->tableAlias] = [
  267. 'base' => $relationship->definition['base'],
  268. 'relationship_id' => $relationship_id,
  269. 'alias' => $relationship->alias,
  270. 'entity_type' => $table_data['table']['entity type'],
  271. 'revision' => $table_data['table']['entity revision'],
  272. ];
  273. // Include the entity provider.
  274. if (!empty($table_data['table']['provider'])) {
  275. $entity_tables[$relationship_id . '__' . $relationship->tableAlias]['provider'] = $table_data['table']['provider'];
  276. }
  277. }
  278. }
  279. // Determine which of the tables are revision tables.
  280. foreach ($entity_tables as $table_alias => $table) {
  281. $entity_type = \Drupal::entityTypeManager()->getDefinition($table['entity_type']);
  282. if ($entity_type->getRevisionTable() == $table['base']) {
  283. $entity_tables[$table_alias]['revision'] = TRUE;
  284. }
  285. }
  286. return $entity_tables;
  287. }
  288. /**
  289. * {@inheritdoc}
  290. */
  291. public function getCacheMaxAge() {
  292. return Cache::PERMANENT;
  293. }
  294. /**
  295. * {@inheritdoc}
  296. */
  297. public function getCacheContexts() {
  298. $contexts = [];
  299. if (($views_data = Views::viewsData()->get($this->view->storage->get('base_table'))) && !empty($views_data['table']['entity type'])) {
  300. $entity_type_id = $views_data['table']['entity type'];
  301. $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
  302. $contexts = $entity_type->getListCacheContexts();
  303. }
  304. return $contexts;
  305. }
  306. /**
  307. * {@inheritdoc}
  308. */
  309. public function getCacheTags() {
  310. return [];
  311. }
  312. /**
  313. * Applies a timezone offset to the given field.
  314. *
  315. * @param string &$field
  316. * The date field, in string format.
  317. * @param int $offset
  318. * The timezone offset to apply to the field.
  319. */
  320. public function setFieldTimezoneOffset(&$field, $offset) {
  321. // No-op. Timezone offsets are implementation-specific and should implement
  322. // this method as needed.
  323. }
  324. /**
  325. * Get the timezone offset in seconds.
  326. *
  327. * @return int
  328. * The offset, in seconds, for the timezone being used.
  329. */
  330. public function getTimezoneOffset() {
  331. $timezone = $this->setupTimezone();
  332. $offset = 0;
  333. if ($timezone) {
  334. $dtz = new \DateTimeZone($timezone);
  335. $dt = new \DateTime('now', $dtz);
  336. $offset = $dtz->getOffset($dt);
  337. }
  338. return $offset;
  339. }
  340. }
  341. /**
  342. * @}
  343. */