Elgg  Version 4.3
Metadata.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Database;
4 
14 
21 class Metadata extends Repository {
22 
26  public function count() {
27  $qb = Select::fromTable('metadata', '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 = 'metadata';
61  }
62 
63  $qb = Select::fromTable('metadata', '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 
74  $alias = $qb->joinEntitiesTable('n_table', 'entity_guid', 'inner', 'e');
75  $qb->addSelect("{$function}({$alias}.{$property}) AS calculation");
76  break;
77 
78  case 'metadata' :
79  $alias = 'n_table';
80  if (!empty($this->options->metadata_name_value_pairs) && $this->options->metadata_name_value_pairs[0]->names != $property) {
81  $alias = $qb->joinMetadataTable('n_table', 'entity_guid', $property);
82  }
83  $qb->addSelect("{$function}($alias.value) AS calculation");
84  break;
85 
86  case 'annotation' :
87  $alias = $qb->joinAnnotationTable('n_table', 'entity_guid', $property);
88  $qb->addSelect("{$function}({$alias}.value) AS calculation");
89  break;
90 
91  case 'private_setting' :
92  $alias = $qb->joinPrivateSettingsTable('n_table', 'entity_guid', $property);
93  $qb->addSelect("{$function}({$alias}.value) AS calculation");
94  break;
95  }
96 
97  $qb = $this->buildQuery($qb);
98 
99  $result = _elgg_services()->db->getDataRow($qb);
100 
101  if (empty($result)) {
102  return 0;
103  }
104 
105  return (int) $result->calculation;
106  }
107 
117  public function get($limit = null, $offset = null, $callback = null) {
118 
119  $qb = Select::fromTable('metadata', 'n_table');
120 
121  $distinct = $this->options->distinct ? "DISTINCT" : "";
122  $qb->select("$distinct n_table.*");
123 
124  $this->expandInto($qb, 'n_table');
125 
126  $qb = $this->buildQuery($qb);
127 
128  // Keeping things backwards compatible
129  $original_order = elgg_extract('order_by', $this->options->__original_options);
130  if (empty($original_order) && $original_order !== false) {
131  $qb->addOrderBy('n_table.time_created', 'asc');
132  $qb->addOrderBy('n_table.id', 'asc');
133  }
134 
135  if ($limit > 0) {
136  $qb->setMaxResults((int) $limit);
137  $qb->setFirstResult((int) $offset);
138  }
139 
140  $callback = $callback ? : $this->options->callback;
141  if (!isset($callback)) {
142  $callback = function ($row) {
143  return new \ElggMetadata($row);
144  };
145  }
146 
147  return _elgg_services()->db->getData($qb, $callback);
148  }
149 
156  public function execute() {
157 
158  if ($this->options->annotation_calculation) {
159  $clauses = $this->options->annotation_name_value_pairs;
160  if (count($clauses) > 1 && $this->options->annotation_name_value_pairs_operator !== 'OR') {
161  throw new LogicException("Annotation calculation can not be performed on multiple annotation name value pairs merged with AND");
162  }
163 
164  $clause = array_shift($clauses);
165 
166  return $this->calculate($this->options->annotation_calculation, $clause->names, 'annotation');
167  } else if ($this->options->metadata_calculation) {
168  $clauses = $this->options->metadata_name_value_pairs;
169  if (count($clauses) > 1 && $this->options->metadata_name_value_pairs_operator !== 'OR') {
170  throw new LogicException("Metadata calculation can not be performed on multiple metadata name value pairs merged with AND");
171  }
172 
173  $clause = array_shift($clauses);
174 
175  return $this->calculate($this->options->metadata_calculation, $clause->names, 'metadata');
176  } else if ($this->options->count) {
177  return $this->count();
178  } else if ($this->options->batch) {
179  return $this->batch($this->options->limit, $this->options->offset, $this->options->callback);
180  } else {
181  return $this->get($this->options->limit, $this->options->offset, $this->options->callback);
182  }
183  }
184 
192  protected function buildQuery(QueryBuilder $qb) {
193 
194  $ands = [];
195 
196  foreach ($this->options->joins as $join) {
197  $join->prepare($qb, 'n_table');
198  }
199 
200  foreach ($this->options->wheres as $where) {
201  $ands[] = $where->prepare($qb, 'n_table');
202  }
203 
204  $ands[] = $this->buildPairedMetadataClause($qb, $this->options->metadata_name_value_pairs, $this->options->metadata_name_value_pairs_operator);
205  $ands[] = $this->buildEntityWhereClause($qb);
206  $ands[] = $this->buildPairedMetadataClause($qb, $this->options->search_name_value_pairs, 'OR');
207  $ands[] = $this->buildPairedAnnotationClause($qb, $this->options->annotation_name_value_pairs, $this->options->annotation_name_value_pairs_operator);
208  $ands[] = $this->buildPairedPrivateSettingsClause($qb, $this->options->private_setting_name_value_pairs, $this->options->private_setting_name_value_pairs_operator);
209  $ands[] = $this->buildPairedRelationshipClause($qb, $this->options->relationship_pairs);
210 
211  $ands = $qb->merge($ands);
212 
213  if (!empty($ands)) {
214  $qb->andWhere($ands);
215  }
216 
217  return $qb;
218  }
219 
229 
230  // Even if all of these properties are empty, we want to add this clause regardless,
231  // to ensure that entity access clauses are appended to the query
232 
233  $joined_alias = $qb->joinEntitiesTable('n_table', 'entity_guid', 'inner', 'e');
234  return EntityWhereClause::factory($this->options)->prepare($qb, $joined_alias);
235  }
236 
247  protected function buildPairedMetadataClause(QueryBuilder $qb, $clauses, $boolean = 'AND') {
248  $parts = [];
249 
250 
251  foreach ($clauses as $clause) {
252  $parts[] = $clause->prepare($qb, 'n_table');
253  }
254 
255  return $qb->merge($parts, $boolean);
256  }
257 
268  protected function buildPairedAnnotationClause(QueryBuilder $qb, $clauses, $boolean = 'AND') {
269  $parts = [];
270 
271  foreach ($clauses as $clause) {
272  if (strtoupper($boolean) === 'OR' || count($clauses) > 1) {
273  $joined_alias = $qb->joinAnnotationTable('n_table', 'entity_guid');
274  } else {
275  $joined_alias = $qb->joinAnnotationTable('n_table', 'entity_guid', $clause->names);
276  }
277  $parts[] = $clause->prepare($qb, $joined_alias);
278  }
279 
280  return $qb->merge($parts, $boolean);
281  }
282 
293  protected function buildPairedPrivateSettingsClause(QueryBuilder $qb, $clauses, $boolean = 'AND') {
294  $parts = [];
295 
296  foreach ($clauses as $clause) {
297  if (strtoupper($boolean) === 'OR' || count($clauses) > 1) {
298  $joined_alias = $qb->joinPrivateSettingsTable('n_table', 'entity_guid');
299  } else {
300  $joined_alias = $qb->joinPrivateSettingsTable('n_table', 'entity_guid', $clause->names);
301  }
302  $parts[] = $clause->prepare($qb, $joined_alias);
303  }
304 
305  return $qb->merge($parts, $boolean);
306  }
307 
320  protected function buildPairedRelationshipClause(QueryBuilder $qb, $clauses, $boolean = 'AND') {
321  $parts = [];
322 
323  foreach ($clauses as $clause) {
324  if (strtoupper($boolean) == 'OR' || count($clauses) > 1) {
325  $joined_alias = $qb->joinRelationshipTable('n_table', 'entity_guid', null, $clause->inverse);
326  } else {
327  $joined_alias = $qb->joinRelationshipTable('n_table', 'entity_guid', $clause->names, $clause->inverse);
328  }
329  $parts[] = $clause->prepare($qb, $joined_alias);
330  }
331 
332  return $qb->merge($parts, $boolean);
333  }
334 }
buildQuery(QueryBuilder $qb)
Build a database query.
Definition: Metadata.php:192
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
calculate($function, $property, $property_type=null)
Performs a mathematical calculation on metadata or metadata entity&#39;s properties.
Definition: Metadata.php:53
count()
{Count rows.int}
Definition: Metadata.php:26
if(!$count) $offset
Definition: pagination.php:26
buildEntityWhereClause(QueryBuilder $qb)
Process entity attribute wheres Joins entities table on entity guid in metadata table and applies whe...
Definition: Metadata.php:228
Database abstraction query builder.
if($pagination &&($position== 'after'||$position== 'both')) $limit
Definition: list.php:108
joinEntitiesTable($from_alias= '', $from_column= 'guid', $join_type= 'inner', $joined_alias=null)
Join entity table from alias and return joined table alias.
Metadata repository contains methods for fetching metadata from database or performing calculations o...
Definition: Metadata.php:21
Abstract methods for interfacing with the database.
Definition: Repository.php:16
execute()
Execute the query resolving calculation, count and/or batch options.
Definition: Metadata.php:156
expandInto(QueryBuilder $qb, $table_alias=null)
Extend query builder with select, group_by, having and order_by clauses from $options.
Definition: Repository.php:181
buildPairedAnnotationClause(QueryBuilder $qb, $clauses, $boolean= 'AND')
Process annotation name value pairs Joins annotation table on entity_guid in the metadata table and a...
Definition: Metadata.php:268
buildPairedPrivateSettingsClause(QueryBuilder $qb, $clauses, $boolean= 'AND')
Process private settings name value pairs Joins private settings table on entity_guid in the metadata...
Definition: Metadata.php:293
Exception that represents error in the program logic.
joinAnnotationTable($from_alias= '', $from_column= 'guid', $name=null, $join_type= 'inner', $joined_alias=null)
Join annotations table from alias and return joined table alias.
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.
merge($parts=null, $boolean= 'AND')
Merges multiple composite expressions with a boolean.
buildPairedRelationshipClause(QueryBuilder $qb, $clauses, $boolean= 'AND')
Process relationship name value pairs Joins relationship table on entity_guid in the metadata table a...
Definition: Metadata.php:320
_elgg_services()
Get the global service provider.
Definition: elgglib.php:638
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.
$qb
Definition: queue.php:11
buildPairedMetadataClause(QueryBuilder $qb, $clauses, $boolean= 'AND')
Process metadata name value pairs Applies where clauses to the selected metadata table.
Definition: Metadata.php:247