Elgg  Version 2.3
Annotations.php
Go to the documentation of this file.
1 <?php
2 namespace Elgg\Database;
3 
13 class Annotations {
14 
16 
20  protected $db;
21 
25  protected $session;
26 
30  protected $events;
31 
40  $this->db = $db;
41  $this->session = $session;
42  $this->events = $events;
43  }
44 
54  function get($id) {
55  return _elgg_get_metastring_based_object_from_id($id, 'annotation');
56  }
57 
64  function delete($id) {
65  $annotation = $this->get($id);
66  if (!$annotation) {
67  return false;
68  }
69  return $annotation->delete();
70  }
71 
84  function create($entity_guid, $name, $value, $value_type = '', $owner_guid = 0, $access_id = ACCESS_PRIVATE) {
85 
86 
87  $result = false;
88 
90  $value_type = \ElggExtender::detectValueType($value, $value_type);
91 
92  $owner_guid = (int)$owner_guid;
93  if ($owner_guid == 0) {
94  $owner_guid = $this->session->getLoggedInUserGuid();
95  }
96 
97  $access_id = (int)$access_id;
98  $time = $this->getCurrentTime()->getTimestamp();
99 
100  $value_id = elgg_get_metastring_id($value);
101  if (!$value_id) {
102  return false;
103  }
104 
105  $name_id = elgg_get_metastring_id($name);
106  if (!$name_id) {
107  return false;
108  }
109 
110  // @todo we don't check that the entity is loaded which means the user may
111  // not have access to the entity
113 
114  if ($this->events->trigger('annotate', $entity->type, $entity)) {
115  $result = $this->db->insertData("INSERT INTO {$this->db->prefix}annotations
116  (entity_guid, name_id, value_id, value_type, owner_guid, time_created, access_id) VALUES
117  ($entity_guid, $name_id, $value_id, '$value_type', $owner_guid, $time, $access_id)");
118 
119  if ($result !== false) {
121  if ($this->events->trigger('create', 'annotation', $obj)) {
122  return $result;
123  } else {
124  // plugin returned false to reject annotation
126  return false;
127  }
128  }
129  }
130 
131  return $result;
132  }
133 
146  function update($annotation_id, $name, $value, $value_type, $owner_guid, $access_id) {
147 
148 
149  $annotation_id = (int)$annotation_id;
150 
151  $annotation = $this->get($annotation_id);
152  if (!$annotation) {
153  return false;
154  }
155  if (!$annotation->canEdit()) {
156  return false;
157  }
158 
159  $name = trim($name);
160  $value_type = \ElggExtender::detectValueType($value, $value_type);
161 
162  $owner_guid = (int)$owner_guid;
163  if ($owner_guid == 0) {
164  $owner_guid = $this->session->getLoggedInUserGuid();
165  }
166 
167  $access_id = (int)$access_id;
168 
169  $value_id = elgg_get_metastring_id($value);
170  if (!$value_id) {
171  return false;
172  }
173 
174  $name_id = elgg_get_metastring_id($name);
175  if (!$name_id) {
176  return false;
177  }
178 
179  $result = $this->db->updateData("UPDATE {$this->db->prefix}annotations
180  SET name_id = $name_id, value_id = $value_id, value_type = '$value_type',
181  access_id = $access_id, owner_guid = $owner_guid
182  WHERE id = $annotation_id");
183 
184  if ($result !== false) {
185  // @todo add plugin hook that sends old and new annotation information before db access
186  $obj = $this->get($annotation_id);
187  $this->events->trigger('update', 'annotation', $obj);
188  }
189 
190  return $result;
191  }
192 
221  function find(array $options = array()) {
222 
223  // support shortcut of 'count' => true for 'annotation_calculation' => 'count'
224  if (isset($options['count']) && $options['count']) {
225  $options['annotation_calculation'] = 'count';
226  unset($options['count']);
227  }
228 
229  $options['metastring_type'] = 'annotations';
231  }
232 
243  function deleteAll(array $options) {
244  if (!_elgg_is_valid_options_for_batch_operation($options, 'annotation')) {
245  return false;
246  }
247 
248  $options['metastring_type'] = 'annotations';
249  return _elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback', false);
250  }
251 
260  function disableAll(array $options) {
261  if (!_elgg_is_valid_options_for_batch_operation($options, 'annotation')) {
262  return false;
263  }
264 
265  // if we can see hidden (disabled) we need to use the offset
266  // otherwise we risk an infinite loop if there are more than 50
267  $inc_offset = access_get_show_hidden_status();
268 
269  $options['metastring_type'] = 'annotations';
270  return _elgg_batch_metastring_based_objects($options, 'elgg_batch_disable_callback', $inc_offset);
271  }
272 
284  function enableAll(array $options) {
285  if (!$options || !is_array($options)) {
286  return false;
287  }
288 
289  $options['metastring_type'] = 'annotations';
290  return _elgg_batch_metastring_based_objects($options, 'elgg_batch_enable_callback');
291  }
292 
325  function getEntities(array $options = array()) {
326  $defaults = array(
327  'annotation_names' => ELGG_ENTITIES_ANY_VALUE,
328  'annotation_values' => ELGG_ENTITIES_ANY_VALUE,
329  'annotation_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE,
330 
331  'annotation_name_value_pairs_operator' => 'AND',
332  'annotation_case_sensitive' => true,
333  'order_by_annotation' => array(),
334 
335  'annotation_created_time_lower' => ELGG_ENTITIES_ANY_VALUE,
336  'annotation_created_time_upper' => ELGG_ENTITIES_ANY_VALUE,
337 
338  'annotation_owner_guids' => ELGG_ENTITIES_ANY_VALUE,
339  );
340 
341  $options = array_merge($defaults, $options);
342 
343  $singulars = array('annotation_name', 'annotation_value',
344  'annotation_name_value_pair', 'annotation_owner_guid');
345 
348 
349  if (!$options) {
350  return false;
351  }
352 
353  // because of performance issues support for ordering by maxtime has been dropped
354  // @see https://github.com/Elgg/Elgg/issues/6638
355  if (isset($options['order_by']) && preg_match('~\bmaxtime\b~i', $options['order_by'])) {
356  // check if the user provided maxtime
357  $deprecated = true;
358  if (isset($options['selects'])) {
359  $selects = $options['selects'];
360  if (!is_array($selects)) {
361  $selects = array($selects);
362  }
363 
364  foreach ($selects as $select) {
365  if (preg_match('~\bmaxtime\b~i', $options['order_by'])) {
366  $deprecated = false;
367  break;
368  }
369  }
370  }
371 
372  // the user didn't provide maxtime
373  if ($deprecated) {
374  // special sorting for annotations
375  elgg_deprecated_notice(__FUNCTION__ . ": no longer orders by annotations by default. If you order"
376  . " by maxtime, you must provide that column via \$options['selects']. See"
377  . " https://github.com/Elgg/Elgg/issues/6638#issuecomment-41562034", "1.10");
378 
379  $options['selects'][] = "MAX(n_table.time_created) AS maxtime";
380  $options['group_by'] = 'n_table.entity_guid';
381  }
382  }
383 
384  $time_wheres = _elgg_get_entity_time_where_sql('n_table', $options['annotation_created_time_upper'],
385  $options['annotation_created_time_lower']);
386 
387  if ($time_wheres) {
388  $options['wheres'][] = $time_wheres;
389  }
390 
392  }
393 
427 
428  if (isset($options['count']) && $options['count']) {
430  }
431 
432  $db_prefix = $this->db->prefix;
433  $defaults = array(
434  'calculation' => 'sum',
435  'order_by' => 'annotation_calculation desc'
436  );
437 
438  $options = array_merge($defaults, $options);
439 
440  $function = sanitize_string(elgg_extract('calculation', $options, 'sum', false));
441 
442  // you must cast this as an int or it sorts wrong.
443  $options['selects'][] = 'e.*';
444  $options['selects'][] = "$function(CAST(a_msv.string AS signed)) AS annotation_calculation";
445 
446  // need our own join to get the values because the lower level functions don't
447  // add all the joins if it's a different callback.
448  $options['joins'][] = "JOIN {$db_prefix}metastrings a_msv ON n_table.value_id = a_msv.id";
449 
450  // don't need access control because it's taken care of by elgg_get_annotations.
451  $options['group_by'] = 'n_table.entity_guid';
452 
453  // do not default to a callback function used in elgg_get_annotation()
454  if (!isset($options['callback'])) {
455  $options['callback'] = 'entity_row_to_elggstar';
456  }
457 
459  }
460 
470  function exists($entity_guid, $annotation_type, $owner_guid = null) {
471 
472 
473  if (!$owner_guid && !($owner_guid = $this->session->getLoggedInUserGuid())) {
474  return false;
475  }
476 
479  $annotation_type = sanitize_string($annotation_type);
480 
481  $sql = "SELECT a.id FROM {$this->db->prefix}annotations a" .
482  " JOIN {$this->db->prefix}metastrings m ON a.name_id = m.id" .
483  " WHERE a.owner_guid = $owner_guid AND a.entity_guid = $entity_guid" .
484  " AND m.string = '$annotation_type'";
485 
486  if ($this->db->getDataRow($sql)) {
487  return true;
488  }
489 
490  return false;
491  }
492 }
_elgg_entities_get_metastrings_options($type, $options)
Returns options to pass to elgg_get_entities() for metastrings operations.
_elgg_batch_metastring_based_objects(array $options, $callback, $inc_offset=true)
Runs metastrings-based objects found using $options through $callback.
elgg_get_entities_from_metadata(array $options=array())
interfaces
Definition: metadata.php:276
getEntities(array $options=array())
Returns entities based upon annotations.
elgg_get_metastring_id($string, $case_sensitive=true)
Gets the metastring identifier for a value.
Definition: metastrings.php:25
_elgg_is_valid_options_for_batch_operation($options, $type)
Checks if there are some constraints on the options array for potentially dangerous operations...
Definition: elgglib.php:1870
$annotation
Elgg default annotation view.
Definition: default.php:10
deleteAll(array $options)
Deletes annotations based on $options.
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
__construct(\Elgg\Database $db,\ElggSession $session,\Elgg\EventsService $events)
Constructor.
Definition: Annotations.php:39
$defaults
The Elgg database.
Definition: Database.php:17
elgg_get_entities_from_annotations(array $options=array())
Returns entities based upon annotations.
_elgg_get_entity_time_where_sql($table, $time_created_upper=null, $time_created_lower=null, $time_updated_upper=null, $time_updated_lower=null)
Returns SQL where clause for entity time limits.
Definition: entities.php:359
create($entity_guid, $name, $value, $value_type= '', $owner_guid=0, $access_id=ACCESS_PRIVATE)
Create a new annotation.
Definition: Annotations.php:84
if($selector) $select
Definition: filter.php:36
$value
Definition: longtext.php:42
static detectValueType($value, $value_type="")
Detect the value_type for a value to be stored as metadata or an annotation.
getCurrentTime($modifier= '')
Get the (cloned) time.
Definition: TimeUsing.php:26
disableAll(array $options)
Disables annotations based on $options.
sanitize_string($string)
Sanitizes a string for use in a query.
Definition: database.php:153
$options
Elgg admin footer.
Definition: footer.php:6
$entity_guid
Definition: save.php:9
$owner_guid
Save menu items.
elgg_get_annotation_from_id($id)
Get a specific annotation by its id.
Definition: annotations.php:36
exists($entity_guid, $annotation_type, $owner_guid=null)
Check to see if a user has already created an annotation on an object.
getEntitiesFromCalculation($options)
Get entities ordered by a mathematical calculation on annotation values.
elgg_delete_annotation_by_id($id)
Deletes an annotation using its ID.
Definition: annotations.php:46
_elgg_get_metastring_based_object_from_id($id, $type)
Returns a singular metastring-based object by its ID.
_elgg_get_metastring_based_objects($options)
Returns an array of either or objects.
Definition: metastrings.php:79
const ACCESS_PRIVATE
Definition: elgglib.php:2082
const ELGG_ENTITIES_ANY_VALUE
Definition: elgglib.php:2095
elgg_deprecated_notice($msg, $dep_version, $backtrace_level=1)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:1098
find(array $options=array())
Returns annotations.
access_get_show_hidden_status()
Return current status of showing disabled entities.
Definition: access.php:170
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:1375
elgg_get_annotations(array $options=array())
Returns annotations.
$entity
Definition: delete.php:7
update($annotation_id, $name, $value, $value_type, $owner_guid, $access_id)
Update an annotation.
trait TimeUsing
Adds methods for setting the current time (for testing)
Definition: TimeUsing.php:11
_elgg_normalize_plural_options_array($options, $singulars)
Normalise the singular keys in an options array to plural keys.
Definition: elgglib.php:1528
sanitize_int($int, $signed=true)
Sanitizes an integer for database use.
Definition: database.php:180
if(!$collection_name) $id
Definition: add.php:17
if(!$num_display) $db_prefix
Definition: content.php:13
get_entity($guid)
Loads and returns an entity object from a guid.
Definition: entities.php:204
enableAll(array $options)
Enables annotations based on $options.