Elgg  Version 4.3
Annotations.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Database;
4 
14 
21 class Annotations extends Repository {
22 
26  public function count() {
27  $qb = Select::fromTable('annotations', 'n_table');
28 
29  $count_expr = $this->options->distinct ? "DISTINCT n_table.id" : "*";
30  $qb->select("COUNT({$count_expr}) AS total");
31 
32  $qb = $this->buildQuery($qb);
33 
34  $result = _elgg_services()->db->getDataRow($qb);
35 
36  if (empty($result)) {
37  return 0;
38  }
39 
40  return (int) $result->total;
41  }
42 
53  public function calculate($function, $property, $property_type = null) {
54 
55  if (!in_array(strtolower($function), QueryBuilder::$calculations)) {
56  throw new InvalidArgumentException("'$function' is not a valid numeric function");
57  }
58 
59  if (!isset($property_type)) {
60  $property_type = 'annotation';
61  }
62 
63  $qb = Select::fromTable('annotations', 'n_table');
64 
65  switch ($property_type) {
66  case 'attribute':
67  if (!in_array($property, \ElggEntity::PRIMARY_ATTR_NAMES)) {
68  throw new InvalidParameterException("'$property' is not a valid attribute");
69  }
70 
71  $alias = $qb->joinEntitiesTable('n_table', 'entity_guid', 'inner', 'e');
72  $qb->select("{$function}({$alias}.{$property}) AS calculation");
73  break;
74 
75  case 'annotation' :
76  $alias = 'n_table';
77  if (!empty($this->options->annotation_name_value_pairs) && $this->options->annotation_name_value_pairs[0]->names != $property) {
78  $alias = $qb->joinAnnotationTable('n_table', 'entity_guid', $property);
79  }
80  $qb->select("{$function}($alias.value) AS calculation");
81  break;
82 
83  case 'metadata' :
84  $alias = $qb->joinMetadataTable('n_table', 'entity_guid', $property);
85  $qb->select("{$function}({$alias}.value) AS calculation");
86  break;
87 
88  case 'private_setting' :
89  $alias = $qb->joinPrivateSettingsTable('n_table', 'entity_guid', $property);
90  $qb->select("{$function}({$alias}.value) AS calculation");
91  break;
92  }
93 
94  $qb = $this->buildQuery($qb);
95 
96  $result = _elgg_services()->db->getDataRow($qb);
97 
98  if (empty($result)) {
99  return 0;
100  }
101 
102  return (int) $result->calculation;
103  }
104 
114  public function get($limit = null, $offset = null, $callback = null) {
115 
116  $qb = Select::fromTable('annotations', 'n_table');
117 
118  $distinct = $this->options->distinct ? "DISTINCT" : "";
119  $qb->select("$distinct n_table.*");
120 
121  $this->expandInto($qb, 'n_table');
122 
123  $qb = $this->buildQuery($qb);
124 
125  // Keeping things backwards compatible
126  $original_order = elgg_extract('order_by', $this->options->__original_options);
127  if (empty($original_order) && $original_order !== false) {
128  $qb->addOrderBy('n_table.time_created', 'asc');
129  $qb->addOrderBy('n_table.id', 'asc');
130  }
131 
132  if ($limit > 0) {
133  $qb->setMaxResults((int) $limit);
134  $qb->setFirstResult((int) $offset);
135  }
136 
137  $callback = $callback ? : $this->options->callback;
138  if (!isset($callback)) {
139  $callback = function ($row) {
140  return new \ElggAnnotation($row);
141  };
142  }
143 
144  $results = _elgg_services()->db->getData($qb, $callback);
145  if (!empty($results) && $this->options->preload_owners) {
146  _elgg_services()->entityPreloader->preload($results, ['owner_guid']);
147  }
148 
149  return $results;
150  }
151 
158  public function execute() {
159 
160  if ($this->options->annotation_calculation) {
161  $clauses = $this->options->annotation_name_value_pairs;
162  if (count($clauses) > 1 && $this->options->annotation_name_value_pairs_operator !== 'OR') {
163  throw new LogicException("Annotation calculation can not be performed on multiple annotation name value pairs merged with AND");
164  }
165 
166  $clause = array_shift($clauses);
167 
168  return $this->calculate($this->options->annotation_calculation, $clause->names, 'annotation');
169  } else if ($this->options->metadata_calculation) {
170  $clauses = $this->options->metadata_name_value_pairs;
171  if (count($clauses) > 1 && $this->options->metadata_name_value_pairs_operator !== 'OR') {
172  throw new LogicException("Metadata calculation can not be performed on multiple metadata name value pairs merged with AND");
173  }
174 
175  $clause = array_shift($clauses);
176 
177  return $this->calculate($this->options->metadata_calculation, $clause->names, 'metadata');
178  } else if ($this->options->count) {
179  return $this->count();
180  } else if ($this->options->batch) {
181  return $this->batch($this->options->limit, $this->options->offset, $this->options->callback);
182  } else {
183  return $this->get($this->options->limit, $this->options->offset, $this->options->callback);
184  }
185  }
186 
194  protected function buildQuery(QueryBuilder $qb) {
195 
196  $ands = [];
197 
198  foreach ($this->options->joins as $join) {
199  $join->prepare($qb, 'n_table');
200  }
201 
202  foreach ($this->options->wheres as $where) {
203  $ands[] = $where->prepare($qb, 'n_table');
204  }
205 
206  $ands[] = $this->buildPairedAnnotationClause($qb, $this->options->annotation_name_value_pairs, $this->options->annotation_name_value_pairs_operator);
207  $ands[] = $this->buildEntityWhereClause($qb);
208  $ands[] = $this->buildPairedMetadataClause($qb, $this->options->metadata_name_value_pairs, $this->options->metadata_name_value_pairs_operator);
209  $ands[] = $this->buildPairedMetadataClause($qb, $this->options->search_name_value_pairs, 'OR');
210  $ands[] = $this->buildPairedPrivateSettingsClause($qb, $this->options->private_setting_name_value_pairs, $this->options->private_setting_name_value_pairs_operator);
211  $ands[] = $this->buildPairedRelationshipClause($qb, $this->options->relationship_pairs);
212 
213  $ands = $qb->merge($ands);
214 
215  if (!empty($ands)) {
216  $qb->andWhere($ands);
217  }
218 
219  return $qb;
220  }
221 
231  $joined_alias = $qb->joinEntitiesTable('n_table', 'entity_guid', 'inner', 'e');
232  return EntityWhereClause::factory($this->options)->prepare($qb, $joined_alias);
233  }
234 
245  protected function buildPairedAnnotationClause(QueryBuilder $qb, $clauses, $boolean = 'AND') {
246  $parts = [];
247 
248  if (empty($clauses)) {
249  // We need to make sure that enabled and access clauses are appended to the query
250  $clauses[] = new AnnotationWhereClause();
251  }
252 
253  foreach ($clauses as $clause) {
254  $parts[] = $clause->prepare($qb, 'n_table');
255  }
256 
257  return $qb->merge($parts, $boolean);
258  }
259 
270  protected function buildPairedMetadataClause(QueryBuilder $qb, $clauses, $boolean = 'AND') {
271  $parts = [];
272 
273  foreach ($clauses as $clause) {
274  if (strtoupper($boolean) === 'OR' || count($clauses) > 1) {
275  $joined_alias = $qb->joinMetadataTable('n_table', 'entity_guid');
276  } else {
277  $joined_alias = $qb->joinMetadataTable('n_table', 'entity_guid', $clause->names);
278  }
279  $parts[] = $clause->prepare($qb, $joined_alias);
280  }
281 
282  return $qb->merge($parts, $boolean);
283  }
284 
295  protected function buildPairedPrivateSettingsClause(QueryBuilder $qb, $clauses, $boolean = 'AND') {
296  $parts = [];
297 
298  foreach ($clauses as $clause) {
299  if (strtoupper($boolean) === 'OR' || count($clauses) > 1) {
300  $joined_alias = $qb->joinPrivateSettingsTable('n_table', 'entity_guid');
301  } else {
302  $joined_alias = $qb->joinPrivateSettingsTable('n_table', 'entity_guid', $clause->names);
303  }
304  $parts[] = $clause->prepare($qb, $joined_alias);
305  }
306 
307  return $qb->merge($parts, $boolean);
308  }
309 
320  protected function buildPairedRelationshipClause(QueryBuilder $qb, $clauses, $boolean = 'AND') {
321  $parts = [];
322 
323  foreach ($clauses as $clause) {
324  $join_on = $clause->join_on == 'guid' ? 'entity_guid' : $clause->join_on;
325  if (strtoupper($boolean) == 'OR' || count($clauses) > 1) {
326  $joined_alias = $qb->joinRelationshipTable('n_table', $join_on, null, $clause->inverse);
327  } else {
328  $joined_alias = $qb->joinRelationshipTable('n_table', $join_on, $clause->names, $clause->inverse);
329  }
330  $parts[] = $clause->prepare($qb, $joined_alias);
331  }
332 
333  return $qb->merge($parts, $boolean);
334  }
335 }
buildPairedAnnotationClause(QueryBuilder $qb, $clauses, $boolean= 'AND')
Process annotation name value pairs Applies where clauses to the selected annotation table...
Exception thrown if an argument is not of the expected type.
batch($limit=null, $offset=null, $callback=null)
{Fetch rows as an ElggBatch.Number of rows to fetch Index of the first row Callback function to run d...
Definition: Repository.php:97
const PRIMARY_ATTR_NAMES
Definition: ElggEntity.php:50
buildPairedRelationshipClause(QueryBuilder $qb, $clauses, $boolean= 'AND')
Process relationship name value pairs Joins relationship table on entity_guid in the annotations tabl...
calculate($function, $property, $property_type=null)
Performs a mathematical calculation on metadata or metadata entity&#39;s properties.
Definition: Annotations.php:53
if(!$count) $offset
Definition: pagination.php:26
Database abstraction query builder.
if($pagination &&($position== 'after'||$position== 'both')) $limit
Definition: list.php:108
Builds queries for matching annotations against their properties.
joinEntitiesTable($from_alias= '', $from_column= 'guid', $join_type= 'inner', $joined_alias=null)
Join entity table from alias and return joined table alias.
buildPairedMetadataClause(QueryBuilder $qb, $clauses, $boolean= 'AND')
Process metadata name value pairs Joins metadata table on entity_guid in the annotations table and ap...
Abstract methods for interfacing with the database.
Definition: Repository.php:16
expandInto(QueryBuilder $qb, $table_alias=null)
Extend query builder with select, group_by, having and order_by clauses from $options.
Definition: Repository.php:181
Exception that represents error in the program logic.
count()
{Count rows.int}
Definition: Annotations.php:26
$results
Definition: content.php:22
elgg_extract($key, $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:547
static fromTable($table, $alias=null)
{}
Definition: Select.php:13
joinPrivateSettingsTable($from_alias= '', $from_column= 'guid', $name=null, $join_type= 'inner', $joined_alias=null)
Join private settings table from alias and return joined table alias.
execute()
Execute the query resolving calculation, count and/or batch options.
merge($parts=null, $boolean= 'AND')
Merges multiple composite expressions with a boolean.
buildQuery(QueryBuilder $qb)
Build a database query.
_elgg_services()
Get the global service provider.
Definition: elgglib.php:638
joinMetadataTable($from_alias= '', $from_column= 'guid', $name=null, $join_type= 'inner', $joined_alias=null)
Join metadata table from alias and return joined table alias.
joinRelationshipTable($from_alias= '', $from_column= 'guid', $name=null, $inverse=false, $join_type= 'inner', $joined_alias=null)
Join relationship table from alias and return joined table alias.
Annotation repository contains methods for fetching annotations from database or performing calculati...
Definition: Annotations.php:21
buildEntityWhereClause(QueryBuilder $qb)
Process entity attribute wheres Joins entities table on entity guid in annotations table and applies ...
$qb
Definition: queue.php:11
buildPairedPrivateSettingsClause(QueryBuilder $qb, $clauses, $boolean= 'AND')
Process private settings name value pairs Joins private settings table on entity_guid in the annotati...