Elgg  Version 1.9
ElggVolatileMetadataCache.php
Go to the documentation of this file.
1 <?php
12 
20  protected $values = array();
21 
28  protected $isSynchronized = array();
29 
33  protected $ignoreAccess = null;
34 
42  public function saveAll($entity_guid, array $values) {
43  if (!$this->getIgnoreAccess()) {
44  $this->values[$entity_guid] = $values;
45  $this->isSynchronized[$entity_guid] = true;
46  }
47  }
48 
55  public function loadAll($entity_guid) {
56  if (isset($this->values[$entity_guid])) {
57  return $this->values[$entity_guid];
58  } else {
59  return array();
60  }
61  }
62 
70  public function markOutOfSync($entity_guid) {
71  unset($this->isSynchronized[$entity_guid]);
72  }
73 
80  public function isSynchronized($entity_guid) {
81  return isset($this->isSynchronized[$entity_guid]);
82  }
83 
95  public function save($entity_guid, $name, $value, $allow_multiple = false) {
96  if ($this->getIgnoreAccess()) {
97  // we don't know if what gets saves here will be available to user once
98  // access control returns, hence it's best to forget :/
100  } else {
101  if ($allow_multiple) {
102  if ($this->isKnown($entity_guid, $name)) {
103  $existing = $this->load($entity_guid, $name);
104  if ($existing !== null) {
105  $existing = (array) $existing;
106  $existing[] = $value;
107  $value = $existing;
108  }
109  } else {
110  // we don't know whether there are unknown values, so it's
111  // safest to leave that assumption
112  $this->markUnknown($entity_guid, $name);
113  return;
114  }
115  }
116  $this->values[$entity_guid][$name] = $value;
117  }
118  }
119 
129  public function load($entity_guid, $name) {
130  if (isset($this->values[$entity_guid]) && array_key_exists($name, $this->values[$entity_guid])) {
131  return $this->values[$entity_guid][$name];
132  } else {
133  return null;
134  }
135  }
136 
145  public function markUnknown($entity_guid, $name) {
146  unset($this->values[$entity_guid][$name]);
147  $this->markOutOfSync($entity_guid);
148  }
149 
157  public function isKnown($entity_guid, $name) {
158  if (isset($this->isSynchronized[$entity_guid])) {
159  return true;
160  } else {
161  return (isset($this->values[$entity_guid]) && array_key_exists($name, $this->values[$entity_guid]));
162  }
163 
164  }
165 
173  public function markEmpty($entity_guid, $name) {
174  $this->values[$entity_guid][$name] = null;
175  }
176 
183  public function clear($entity_guid) {
184  unset($this->values[$entity_guid]);
185  $this->markOutOfSync($entity_guid);
186  }
187 
193  public function flush() {
194  $this->values = array();
195  $this->isSynchronized = array();
196  }
197 
207  public function setIgnoreAccess($ignore) {
208  $this->ignoreAccess = (bool) $ignore;
209  }
210 
216  public function unsetIgnoreAccess() {
217  $this->ignoreAccess = null;
218  }
219 
225  protected function getIgnoreAccess() {
226  if (null === $this->ignoreAccess) {
227  return elgg_get_ignore_access();
228  } else {
229  return $this->ignoreAccess;
230  }
231  }
232 
242  public function invalidateByOptions($action, array $options) {
243  // remove as little as possible, optimizing for common cases
244  if (empty($options['guid'])) {
245  // safest to clear everything unless we want to make this even more complex :(
246  $this->flush();
247  } else {
248  if (empty($options['metadata_name'])) {
249  // safest to clear the whole entity
250  $this->clear($options['guid']);
251  } else {
252  switch ($action) {
253  case 'delete':
254  $this->markEmpty($options['guid'], $options['metadata_name']);
255  break;
256  default:
257  $this->markUnknown($options['guid'], $options['metadata_name']);
258  }
259  }
260  }
261  }
262 
269  public function populateFromEntities($guids) {
270  if (empty($guids)) {
271  return;
272  }
273  if (!is_array($guids)) {
274  $guids = array($guids);
275  }
276  $guids = array_unique($guids);
277 
278  // could be useful at some point in future
279  //$guids = $this->filterMetadataHeavyEntities($guids);
280 
281  $db_prefix = elgg_get_config('dbprefix');
282  $options = array(
283  'guids' => $guids,
284  'limit' => 0,
285  'callback' => false,
286  'joins' => array(
287  "JOIN {$db_prefix}metastrings v ON n_table.value_id = v.id",
288  "JOIN {$db_prefix}metastrings n ON n_table.name_id = n.id",
289  ),
290  'selects' => array('n.string AS name', 'v.string AS value'),
291  'order_by' => 'n_table.entity_guid, n_table.time_created ASC',
292 
293  // @todo don't know why this is necessary
294  'wheres' => array(_elgg_get_access_where_sql(array('table_alias' => 'n_table'))),
295  );
297 
298  // build up metadata for each entity, save when GUID changes (or data ends)
299  $last_guid = null;
300  $metadata = array();
301  $last_row_idx = count($data) - 1;
302  foreach ($data as $i => $row) {
303  $name = $row->name;
304  $value = ($row->value_type === 'text') ? $row->value : (int) $row->value;
305  $guid = $row->entity_guid;
306  if ($guid !== $last_guid) {
307  if ($last_guid) {
308  $this->saveAll($last_guid, $metadata);
309  }
310  $metadata = array();
311  }
312  if (isset($metadata[$name])) {
313  $metadata[$name] = (array) $metadata[$name];
314  $metadata[$name][] = $value;
315  } else {
317  }
318  if (($i == $last_row_idx)) {
319  $this->saveAll($guid, $metadata);
320  }
321  $last_guid = $guid;
322  }
323  }
324 
334  public function filterMetadataHeavyEntities(array $guids, $limit = 1024000) {
335  $db_prefix = elgg_get_config('dbprefix');
336 
337  $options = array(
338  'guids' => $guids,
339  'limit' => 0,
340  'callback' => false,
341  'joins' => "JOIN {$db_prefix}metastrings v ON n_table.value_id = v.id",
342  'selects' => array('SUM(LENGTH(v.string)) AS bytes'),
343  'order_by' => 'n_table.entity_guid, n_table.time_created ASC',
344  'group_by' => 'n_table.entity_guid',
345  );
347  // don't cache if metadata for entity is over 10MB (or rolled INT)
348  foreach ($data as $row) {
349  if ($row->bytes > $limit || $row->bytes < 0) {
350  array_splice($guids, array_search($row->entity_guid, $guids), 1);
351  }
352  }
353  return $guids;
354  }
355 }
elgg_get_config($name, $site_guid=0)
Get an Elgg configuration value.
markUnknown($entity_guid, $name)
Forget about this metadata entry.
populateFromEntities($guids)
Populate the cache from a set of entities.
isKnown($entity_guid, $name)
If true, load() will return an accurate value for this name.
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
$metadata
Definition: entity.php:19
$data
Definition: opendd.php:13
$value
Definition: longtext.php:29
$guid
Removes an admin notice.
invalidateByOptions($action, array $options)
Invalidate based on options passed to the global *_metadata functions.
filterMetadataHeavyEntities(array $guids, $limit=1024000)
Filter out entities whose concatenated metadata values (INTs casted as string) exceed a threshold in ...
$action
save($entity_guid, $name, $value, $allow_multiple=false)
Cache a piece of metadata.
elgg_get_ignore_access()
Get current ignore access setting.
Definition: access.php:57
clear($entity_guid)
Forget about all metadata for an entity.
$entity_guid
Definition: save.php:9
$options
Definition: index.php:14
isSynchronized($entity_guid)
Have all the metadata for this entity been cached?
load($entity_guid, $name)
Warning: You should always call isKnown() beforehand to verify that this function&#39;s return value shou...
$limit
Definition: userpicker.php:33
getIgnoreAccess()
Get the ignore access value.
setIgnoreAccess($ignore)
Use this value instead of calling elgg_get_ignore_access().
unsetIgnoreAccess()
Tell the cache to call elgg_get_ignore_access() to determing access status.
saveAll($entity_guid, array $values)
Cache metadata for an entity.
markEmpty($entity_guid, $name)
Declare that metadata under this name is known to be not fetch-able from storage. ...
$guids
markOutOfSync($entity_guid)
Declare that there may be fetch-able metadata names in storage that this cache doesn&#39;t know about...
elgg_get_metadata(array $options=array())
Returns metadata.
Definition: metadata.php:282
$row
_elgg_get_access_where_sql(array $options=array())
Returns the SQL where clause for enforcing read access to data.
Definition: access.php:343
loadAll($entity_guid)
Get the metadata for an entity.
if(!$num_display) $db_prefix
Definition: content.php:12
flush()
Clear entire cache and mark all entities as out of sync.