Mercurial > hg > isophonics-drupal-site
comparison core/modules/workspaces/src/EntityQuery/Tables.php @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | |
children | af1871eacc83 |
comparison
equal
deleted
inserted
replaced
16:c2387f117808 | 17:129ea1e6d783 |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\workspaces\EntityQuery; | |
4 | |
5 use Drupal\Core\Database\Query\SelectInterface; | |
6 use Drupal\Core\Entity\EntityType; | |
7 use Drupal\Core\Entity\Query\Sql\Tables as BaseTables; | |
8 use Drupal\Core\Field\FieldStorageDefinitionInterface; | |
9 | |
10 /** | |
11 * Alters entity queries to use a workspace revision instead of the default one. | |
12 */ | |
13 class Tables extends BaseTables { | |
14 | |
15 /** | |
16 * The workspace manager. | |
17 * | |
18 * @var \Drupal\workspaces\WorkspaceManagerInterface | |
19 */ | |
20 protected $workspaceManager; | |
21 | |
22 /** | |
23 * Workspace association table array, key is base table name, value is alias. | |
24 * | |
25 * @var array | |
26 */ | |
27 protected $contentWorkspaceTables = []; | |
28 | |
29 /** | |
30 * Keeps track of the entity type IDs for each base table of the query. | |
31 * | |
32 * The array is keyed by the base table alias and the values are entity type | |
33 * IDs. | |
34 * | |
35 * @var array | |
36 */ | |
37 protected $baseTablesEntityType = []; | |
38 | |
39 /** | |
40 * {@inheritdoc} | |
41 */ | |
42 public function __construct(SelectInterface $sql_query) { | |
43 parent::__construct($sql_query); | |
44 | |
45 $this->workspaceManager = \Drupal::service('workspaces.manager'); | |
46 | |
47 // The join between the first 'workspace_association' table and base table | |
48 // of the query is done in | |
49 // \Drupal\workspaces\EntityQuery\QueryTrait::prepare(), so we need to | |
50 // initialize its entry manually. | |
51 if ($this->sqlQuery->getMetaData('active_workspace_id')) { | |
52 $this->contentWorkspaceTables['base_table'] = 'workspace_association'; | |
53 $this->baseTablesEntityType['base_table'] = $this->sqlQuery->getMetaData('entity_type'); | |
54 } | |
55 } | |
56 | |
57 /** | |
58 * {@inheritdoc} | |
59 */ | |
60 public function addField($field, $type, $langcode) { | |
61 // The parent method uses shared and dedicated revision tables only when the | |
62 // entity query is instructed to query all revisions. However, if we are | |
63 // looking for workspace-specific revisions, we have to force the parent | |
64 // method to always pick the revision tables if the field being queried is | |
65 // revisionable. | |
66 if ($active_workspace_id = $this->sqlQuery->getMetaData('active_workspace_id')) { | |
67 $previous_all_revisions = $this->sqlQuery->getMetaData('all_revisions'); | |
68 $this->sqlQuery->addMetaData('all_revisions', TRUE); | |
69 } | |
70 | |
71 $alias = parent::addField($field, $type, $langcode); | |
72 | |
73 // Restore the 'all_revisions' metadata because we don't want to interfere | |
74 // with the rest of the query. | |
75 if (isset($previous_all_revisions)) { | |
76 $this->sqlQuery->addMetaData('all_revisions', $previous_all_revisions); | |
77 } | |
78 | |
79 return $alias; | |
80 } | |
81 | |
82 /** | |
83 * {@inheritdoc} | |
84 */ | |
85 protected function addJoin($type, $table, $join_condition, $langcode, $delta = NULL) { | |
86 if ($this->sqlQuery->getMetaData('active_workspace_id')) { | |
87 // The join condition for a shared or dedicated field table is in the form | |
88 // of "%alias.$id_field = $base_table.$id_field". Whenever we join a field | |
89 // table we have to check: | |
90 // 1) if $base_table is of an entity type that can belong to a workspace; | |
91 // 2) if $id_field is the revision key of that entity type or the special | |
92 // 'revision_id' string used when joining dedicated field tables. | |
93 // If those two conditions are met, we have to update the join condition | |
94 // to also look for a possible workspace-specific revision using COALESCE. | |
95 $condition_parts = explode(' = ', $join_condition); | |
96 list($base_table, $id_field) = explode('.', $condition_parts[1]); | |
97 | |
98 if (isset($this->baseTablesEntityType[$base_table])) { | |
99 $entity_type_id = $this->baseTablesEntityType[$base_table]; | |
100 $revision_key = $this->entityManager->getDefinition($entity_type_id)->getKey('revision'); | |
101 | |
102 if ($id_field === $revision_key || $id_field === 'revision_id') { | |
103 $workspace_association_table = $this->contentWorkspaceTables[$base_table]; | |
104 $join_condition = "{$condition_parts[0]} = COALESCE($workspace_association_table.target_entity_revision_id, {$condition_parts[1]})"; | |
105 } | |
106 } | |
107 } | |
108 | |
109 return parent::addJoin($type, $table, $join_condition, $langcode, $delta); | |
110 } | |
111 | |
112 /** | |
113 * {@inheritdoc} | |
114 */ | |
115 protected function addNextBaseTable(EntityType $entity_type, $table, $sql_column, FieldStorageDefinitionInterface $field_storage) { | |
116 $next_base_table_alias = parent::addNextBaseTable($entity_type, $table, $sql_column, $field_storage); | |
117 | |
118 $active_workspace_id = $this->sqlQuery->getMetaData('active_workspace_id'); | |
119 if ($active_workspace_id && $this->workspaceManager->isEntityTypeSupported($entity_type)) { | |
120 $this->addWorkspaceAssociationJoin($entity_type->id(), $next_base_table_alias, $active_workspace_id); | |
121 } | |
122 | |
123 return $next_base_table_alias; | |
124 } | |
125 | |
126 /** | |
127 * Adds a new join to the 'workspace_association' table for an entity base table. | |
128 * | |
129 * This method assumes that the active workspace has already been determined | |
130 * to be a non-default workspace. | |
131 * | |
132 * @param string $entity_type_id | |
133 * The ID of the entity type whose base table we are joining. | |
134 * @param string $base_table_alias | |
135 * The alias of the entity type's base table. | |
136 * @param string $active_workspace_id | |
137 * The ID of the active workspace. | |
138 * | |
139 * @return string | |
140 * The alias of the joined table. | |
141 */ | |
142 public function addWorkspaceAssociationJoin($entity_type_id, $base_table_alias, $active_workspace_id) { | |
143 if (!isset($this->contentWorkspaceTables[$base_table_alias])) { | |
144 $entity_type = $this->entityManager->getDefinition($entity_type_id); | |
145 $id_field = $entity_type->getKey('id'); | |
146 | |
147 // LEFT join the Workspace association entity's table so we can properly | |
148 // include live content along with a possible workspace-specific revision. | |
149 $this->contentWorkspaceTables[$base_table_alias] = $this->sqlQuery->leftJoin('workspace_association', NULL, "%alias.target_entity_type_id = '$entity_type_id' AND %alias.target_entity_id = $base_table_alias.$id_field AND %alias.workspace = '$active_workspace_id'"); | |
150 | |
151 $this->baseTablesEntityType[$base_table_alias] = $entity_type->id(); | |
152 } | |
153 return $this->contentWorkspaceTables[$base_table_alias]; | |
154 } | |
155 | |
156 } |