Total Complexity | 240 |
Total Lines | 2082 |
Duplicated Lines | 0 % |
Coverage | 79.82% |
Changes | 0 |
Complex classes like ElggEntity often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ElggEntity, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
43 | abstract class ElggEntity extends \ElggData implements |
||
44 | Locatable, // Geocoding interface |
||
45 | EntityIcon // Icon interface |
||
46 | { |
||
47 | |||
48 | public static $primary_attr_names = [ |
||
49 | 'guid', |
||
50 | 'type', |
||
51 | 'subtype', |
||
52 | 'owner_guid', |
||
53 | 'container_guid', |
||
54 | 'access_id', |
||
55 | 'time_created', |
||
56 | 'time_updated', |
||
57 | 'last_action', |
||
58 | 'enabled', |
||
59 | ]; |
||
60 | |||
61 | protected static $integer_attr_names = [ |
||
62 | 'guid', |
||
63 | 'owner_guid', |
||
64 | 'container_guid', |
||
65 | 'access_id', |
||
66 | 'time_created', |
||
67 | 'time_updated', |
||
68 | 'last_action', |
||
69 | ]; |
||
70 | |||
71 | /** |
||
72 | * Holds metadata until entity is saved. Once the entity is saved, |
||
73 | * metadata are written immediately to the database. |
||
74 | * @var array |
||
75 | */ |
||
76 | protected $temp_metadata = []; |
||
77 | |||
78 | /** |
||
79 | * Holds annotations until entity is saved. Once the entity is saved, |
||
80 | * annotations are written immediately to the database. |
||
81 | * @var array |
||
82 | */ |
||
83 | protected $temp_annotations = []; |
||
84 | |||
85 | /** |
||
86 | * Holds private settings until entity is saved. Once the entity is saved, |
||
87 | * private settings are written immediately to the database. |
||
88 | * @var array |
||
89 | */ |
||
90 | protected $temp_private_settings = []; |
||
91 | |||
92 | /** |
||
93 | * Volatile data structure for this object, allows for storage of data |
||
94 | * in-memory that isn't sync'd back to the metadata table. |
||
95 | * @var array |
||
96 | */ |
||
97 | protected $volatile = []; |
||
98 | |||
99 | /** |
||
100 | * Holds the original (persisted) attribute values that have been changed but not yet saved. |
||
101 | * @var array |
||
102 | */ |
||
103 | protected $orig_attributes = []; |
||
104 | |||
105 | /** |
||
106 | * @var bool |
||
107 | */ |
||
108 | protected $_is_cacheable = true; |
||
109 | |||
110 | /** |
||
111 | * Create a new entity. |
||
112 | * |
||
113 | * Plugin developers should only use the constructor to create a new entity. |
||
114 | * To retrieve entities, use get_entity() and the elgg_get_entities* functions. |
||
115 | * |
||
116 | * If no arguments are passed, it creates a new entity. |
||
117 | * If a database result is passed as a \stdClass instance, it instantiates |
||
118 | * that entity. |
||
119 | * |
||
120 | * @param stdClass $row Database row result. Default is null to create a new object. |
||
121 | * |
||
122 | * @throws IOException If cannot load remaining data from db |
||
123 | */ |
||
124 | 5322 | public function __construct(stdClass $row = null) { |
|
125 | 5322 | $this->initializeAttributes(); |
|
126 | |||
127 | 5322 | if ($row && !$this->load($row)) { |
|
128 | $msg = "Failed to load new " . get_class() . " for GUID:" . $row->guid; |
||
129 | throw new \IOException($msg); |
||
130 | } |
||
131 | 5322 | } |
|
132 | |||
133 | /** |
||
134 | * Initialize the attributes array. |
||
135 | * |
||
136 | * This is vital to distinguish between metadata and base parameters. |
||
137 | * |
||
138 | * @return void |
||
139 | */ |
||
140 | 5322 | protected function initializeAttributes() { |
|
141 | 5322 | parent::initializeAttributes(); |
|
142 | |||
143 | 5322 | $this->attributes['guid'] = null; |
|
144 | 5322 | $this->attributes['type'] = null; |
|
145 | 5322 | $this->attributes['subtype'] = null; |
|
146 | |||
147 | 5322 | $this->attributes['owner_guid'] = _elgg_services()->session->getLoggedInUserGuid(); |
|
148 | 5322 | $this->attributes['container_guid'] = _elgg_services()->session->getLoggedInUserGuid(); |
|
149 | |||
150 | 5322 | $this->attributes['access_id'] = ACCESS_PRIVATE; |
|
151 | 5322 | $this->attributes['time_updated'] = null; |
|
152 | 5322 | $this->attributes['last_action'] = null; |
|
153 | 5322 | $this->attributes['enabled'] = "yes"; |
|
154 | |||
155 | 5322 | $this->attributes['type'] = $this->getType(); |
|
156 | 5322 | } |
|
157 | |||
158 | /** |
||
159 | * Clone an entity |
||
160 | * |
||
161 | * Resets the guid so that the entity can be saved as a distinct entity from |
||
162 | * the original. Creation time will be set when this new entity is saved. |
||
163 | * The owner and container guids come from the original entity. The clone |
||
164 | * method copies metadata but does not copy annotations or private settings. |
||
165 | * |
||
166 | * @note metadata will have its owner and access id set when the entity is saved |
||
167 | * and it will be the same as that of the entity. |
||
168 | * |
||
169 | * @return void |
||
170 | */ |
||
171 | 1 | public function __clone() { |
|
172 | 1 | $orig_entity = get_entity($this->guid); |
|
173 | 1 | if (!$orig_entity) { |
|
174 | _elgg_services()->logger->error("Failed to clone entity with GUID $this->guid"); |
||
175 | return; |
||
176 | } |
||
177 | |||
178 | 1 | $metadata_array = elgg_get_metadata([ |
|
179 | 1 | 'guid' => $this->guid, |
|
180 | 1 | 'limit' => 0 |
|
181 | ]); |
||
182 | |||
183 | 1 | $this->attributes['guid'] = null; |
|
184 | 1 | $this->attributes['time_created'] = null; |
|
185 | 1 | $this->attributes['time_updated'] = null; |
|
186 | 1 | $this->attributes['last_action'] = null; |
|
187 | |||
188 | 1 | $this->attributes['subtype'] = $orig_entity->getSubtype(); |
|
189 | |||
190 | // copy metadata over to new entity - slightly convoluted due to |
||
191 | // handling of metadata arrays |
||
192 | 1 | if (is_array($metadata_array)) { |
|
193 | // create list of metadata names |
||
194 | 1 | $metadata_names = []; |
|
195 | 1 | foreach ($metadata_array as $metadata) { |
|
196 | 1 | $metadata_names[] = $metadata['name']; |
|
197 | } |
||
198 | // arrays are stored with multiple enties per name |
||
199 | 1 | $metadata_names = array_unique($metadata_names); |
|
200 | |||
201 | // move the metadata over |
||
202 | 1 | foreach ($metadata_names as $name) { |
|
203 | 1 | $this->__set($name, $orig_entity->$name); |
|
204 | } |
||
205 | } |
||
206 | 1 | } |
|
207 | |||
208 | /** |
||
209 | * Set an attribute or metadata value for this entity |
||
210 | * |
||
211 | * Anything that is not an attribute is saved as metadata. |
||
212 | * |
||
213 | * @warning Metadata set this way will inherit the entity's owner and |
||
214 | * access ID. If you want more control over metadata, use \ElggEntity::setMetadata() |
||
215 | * |
||
216 | * @param string $name Name of the attribute or metadata |
||
217 | * @param mixed $value The value to be set |
||
218 | * @return void |
||
219 | * @see \ElggEntity::setMetadata() |
||
220 | */ |
||
221 | 1092 | public function __set($name, $value) { |
|
222 | 1092 | if ($this->$name === $value) { |
|
223 | // quick return if value is not changing |
||
224 | 289 | return; |
|
225 | } |
||
226 | |||
227 | // Due to https://github.com/Elgg/Elgg/pull/5456#issuecomment-17785173, certain attributes |
||
228 | // will store empty strings as null in the DB. In the somewhat common case that we're re-setting |
||
229 | // the value to empty string, don't consider this a change. |
||
230 | 1092 | if (in_array($name, ['title', 'name', 'description']) |
|
231 | 1092 | && $this->$name === null |
|
232 | 1092 | && $value === "") { |
|
233 | return; |
||
234 | } |
||
235 | |||
236 | 1092 | if (array_key_exists($name, $this->attributes)) { |
|
237 | // if an attribute is 1 (integer) and it's set to "1" (string), don't consider that a change. |
||
238 | 589 | if (is_int($this->attributes[$name]) |
|
239 | 589 | && is_string($value) |
|
240 | 589 | && ((string) $this->attributes[$name] === $value)) { |
|
241 | 1 | return; |
|
242 | } |
||
243 | |||
244 | // keep original values |
||
245 | 589 | if ($this->guid && !array_key_exists($name, $this->orig_attributes)) { |
|
246 | 9 | $this->orig_attributes[$name] = $this->attributes[$name]; |
|
247 | } |
||
248 | |||
249 | // Certain properties should not be manually changed! |
||
250 | 589 | switch ($name) { |
|
251 | case 'guid': |
||
252 | case 'time_updated': |
||
253 | case 'last_action': |
||
254 | return; |
||
255 | break; |
||
|
|||
256 | case 'access_id': |
||
257 | case 'owner_guid': |
||
258 | case 'container_guid': |
||
259 | 482 | if ($value !== null) { |
|
260 | 482 | $this->attributes[$name] = (int) $value; |
|
261 | } else { |
||
262 | $this->attributes[$name] = null; |
||
263 | } |
||
264 | 482 | break; |
|
265 | default: |
||
266 | 443 | $this->attributes[$name] = $value; |
|
267 | 443 | break; |
|
268 | } |
||
269 | 589 | return; |
|
270 | } |
||
271 | |||
272 | 1062 | $this->setMetadata($name, $value); |
|
273 | 1062 | } |
|
274 | |||
275 | /** |
||
276 | * Get the original values of attribute(s) that have been modified since the entity was persisted. |
||
277 | * |
||
278 | * @return array |
||
279 | */ |
||
280 | 59 | public function getOriginalAttributes() { |
|
281 | 59 | return $this->orig_attributes; |
|
282 | } |
||
283 | |||
284 | /** |
||
285 | * Get an attribute or metadata value |
||
286 | * |
||
287 | * If the name matches an attribute, the attribute is returned. If metadata |
||
288 | * does not exist with that name, a null is returned. |
||
289 | * |
||
290 | * This only returns an array if there are multiple values for a particular |
||
291 | * $name key. |
||
292 | * |
||
293 | * @param string $name Name of the attribute or metadata |
||
294 | * @return mixed |
||
295 | */ |
||
296 | 5387 | public function __get($name) { |
|
297 | 5387 | if (array_key_exists($name, $this->attributes)) { |
|
298 | 5386 | return $this->attributes[$name]; |
|
299 | } |
||
300 | |||
301 | 5363 | return $this->getMetadata($name); |
|
302 | } |
||
303 | |||
304 | /** |
||
305 | * Get the entity's display name |
||
306 | * |
||
307 | * @return string The title or name of this entity. |
||
308 | */ |
||
309 | 19 | public function getDisplayName() { |
|
310 | 19 | return $this->name; |
|
311 | } |
||
312 | |||
313 | /** |
||
314 | * Sets the title or name of this entity. |
||
315 | * |
||
316 | * @param string $display_name The title or name of this entity. |
||
317 | * @return void |
||
318 | */ |
||
319 | public function setDisplayName($display_name) { |
||
321 | } |
||
322 | |||
323 | /** |
||
324 | * Return the value of a piece of metadata. |
||
325 | * |
||
326 | * @param string $name Name |
||
327 | * |
||
328 | * @return mixed The value, or null if not found. |
||
329 | */ |
||
330 | 5363 | public function getMetadata($name) { |
|
331 | 5363 | $guid = $this->guid; |
|
332 | |||
333 | 5363 | if (!$guid) { |
|
334 | 572 | if (isset($this->temp_metadata[$name])) { |
|
335 | // md is returned as an array only if more than 1 entry |
||
336 | 285 | if (count($this->temp_metadata[$name]) == 1) { |
|
337 | 285 | return $this->temp_metadata[$name][0]; |
|
338 | } else { |
||
339 | 158 | return $this->temp_metadata[$name]; |
|
340 | } |
||
341 | } else { |
||
342 | 572 | return null; |
|
343 | } |
||
344 | } |
||
345 | |||
346 | // upon first cache miss, just load/cache all the metadata and retry. |
||
347 | // if this works, the rest of this function may not be needed! |
||
348 | 5354 | $cache = _elgg_services()->metadataCache; |
|
349 | 5354 | if ($cache->isLoaded($guid)) { |
|
350 | 2238 | return $cache->getSingle($guid, $name); |
|
351 | } else { |
||
352 | 4136 | $cache->populateFromEntities([$guid]); |
|
353 | // in case ignore_access was on, we have to check again... |
||
354 | 4136 | if ($cache->isLoaded($guid)) { |
|
355 | 1082 | return $cache->getSingle($guid, $name); |
|
356 | } |
||
357 | |||
358 | return null; |
||
359 | 4083 | } |
|
360 | 4083 | } |
|
361 | 4083 | ||
362 | 4083 | /** |
|
363 | * Unset a property from metadata or attribute. |
||
364 | * |
||
365 | * @warning If you use this to unset an attribute, you must save the object! |
||
366 | 4083 | * |
|
367 | * @param string $name The name of the attribute or metadata. |
||
368 | 4083 | * |
|
369 | * @return void |
||
370 | 4083 | * @todo some attributes should be set to null or other default values |
|
371 | */ |
||
372 | 4083 | public function __unset($name) { |
|
373 | if (array_key_exists($name, $this->attributes)) { |
||
374 | $this->attributes[$name] = ""; |
||
375 | } else { |
||
376 | 4083 | $this->deleteMetadata($name); |
|
377 | } |
||
378 | } |
||
379 | |||
380 | /** |
||
381 | * Set metadata on this entity. |
||
382 | * |
||
383 | * Plugin developers usually want to use the magic set method ($entity->name = 'value'). |
||
384 | * Use this method if you want to explicitly set the owner or access of the metadata. |
||
385 | * You cannot set the owner/access before the entity has been saved. |
||
386 | * |
||
387 | * @param string $name Name of the metadata |
||
388 | * @param mixed $value Value of the metadata (doesn't support assoc arrays) |
||
389 | 49 | * @param string $value_type 'text', 'integer', or '' for automatic detection |
|
390 | 49 | * @param bool $multiple Allow multiple values for a single name. |
|
391 | * Does not support associative arrays. |
||
392 | * |
||
393 | 49 | * @return bool |
|
394 | * @throws InvalidArgumentException |
||
395 | 49 | */ |
|
396 | public function setMetadata($name, $value, $value_type = '', $multiple = false) { |
||
397 | |||
398 | // normalize value to an array that we will loop over |
||
399 | // remove indexes if value already an array. |
||
400 | if (is_array($value)) { |
||
401 | $value = array_values($value); |
||
402 | } else { |
||
403 | $value = [$value]; |
||
404 | } |
||
405 | |||
406 | // strip null values from array |
||
407 | $value = array_filter($value, function($var) { |
||
408 | return !is_null($var); |
||
409 | }); |
||
410 | |||
411 | if (empty($this->guid)) { |
||
412 | // unsaved entity. store in temp array |
||
413 | 1062 | return $this->setTempMetadata($name, $value, $multiple); |
|
414 | } |
||
415 | |||
416 | // saved entity. persist md to db. |
||
417 | 1062 | if (!$multiple) { |
|
418 | 162 | $current_metadata = $this->getMetadata($name); |
|
419 | |||
420 | 1061 | if ((is_array($current_metadata) || count($value) > 1 || $value === []) && isset($current_metadata)) { |
|
421 | // remove current metadata if needed |
||
422 | // need to remove access restrictions right now to delete |
||
423 | // because this is the expected behavior |
||
424 | 1062 | $ia = elgg_set_ignore_access(true); |
|
425 | 1062 | $delete_result = elgg_delete_metadata([ |
|
426 | 1062 | 'guid' => $this->guid, |
|
427 | 'metadata_name' => $name, |
||
428 | 1062 | 'limit' => false, |
|
429 | ]); |
||
430 | 569 | elgg_set_ignore_access($ia); |
|
431 | |||
432 | if (false === $delete_result) { |
||
433 | return false; |
||
434 | 1028 | } |
|
435 | 1028 | } |
|
436 | |||
437 | 1028 | if (count($value) > 1) { |
|
438 | // new value is a multiple valued metadata |
||
439 | $multiple = true; |
||
440 | } |
||
441 | 8 | } |
|
442 | 8 | ||
443 | 8 | // create new metadata |
|
444 | 8 | foreach ($value as $value_tmp) { |
|
445 | $metadata = new ElggMetadata(); |
||
446 | $metadata->entity_guid = $this->guid; |
||
447 | 8 | $metadata->name = $name; |
|
448 | $metadata->value_type = $value_type; |
||
449 | 8 | $metadata->value = $value_tmp; |
|
450 | $md_id = _elgg_services()->metadataTable->create($metadata, $multiple); |
||
451 | if (!$md_id) { |
||
452 | return false; |
||
453 | } |
||
454 | 1028 | } |
|
455 | |||
456 | 162 | return true; |
|
457 | } |
||
458 | |||
459 | /** |
||
460 | * Set temp metadata on this entity. |
||
461 | 1028 | * |
|
462 | 1028 | * @param string $name Name of the metadata |
|
463 | 1028 | * @param mixed $value Value of the metadata (doesn't support assoc arrays) |
|
464 | 1028 | * @param bool $multiple Allow multiple values for a single name. |
|
465 | 1028 | * Does not support associative arrays. |
|
466 | 1028 | * |
|
467 | 1028 | * @return bool |
|
468 | 1028 | */ |
|
469 | 1028 | protected function setTempMetadata($name, $value, $multiple = false) { |
|
470 | // if overwrite, delete first |
||
471 | if (!$multiple) { |
||
472 | unset($this->temp_metadata[$name]); |
||
473 | 1028 | if (count($value)) { |
|
474 | // only save if value array contains data |
||
475 | $this->temp_metadata[$name] = $value; |
||
476 | } |
||
477 | return true; |
||
478 | } |
||
479 | |||
480 | if (!isset($this->temp_metadata[$name])) { |
||
481 | $this->temp_metadata[$name] = []; |
||
482 | } |
||
483 | |||
484 | $this->temp_metadata[$name] = array_merge($this->temp_metadata[$name], $value); |
||
485 | |||
486 | 569 | return true; |
|
487 | } |
||
488 | 569 | ||
489 | 569 | ||
490 | 569 | ||
491 | /** |
||
492 | 569 | * Deletes all metadata on this object (metadata.entity_guid = $this->guid). |
|
493 | * If you pass a name, only metadata matching that name will be deleted. |
||
494 | 569 | * |
|
495 | * @warning Calling this with no $name will clear all metadata on the entity. |
||
496 | * |
||
497 | 3 | * @param null|string $name The name of the metadata to remove. |
|
498 | * @return bool|null |
||
499 | * @since 1.8 |
||
500 | */ |
||
501 | 3 | public function deleteMetadata($name = null) { |
|
502 | |||
503 | 3 | if (!$this->guid) { |
|
504 | // remove from temp_metadata |
||
505 | if ($name) { |
||
506 | if (!isset($this->temp_metadata[$name])) { |
||
507 | return null; |
||
508 | } else { |
||
509 | unset($this->temp_metadata[$name]); |
||
510 | return true; |
||
511 | } |
||
512 | } else { |
||
513 | $this->temp_metadata = []; |
||
514 | return true; |
||
515 | } |
||
516 | } |
||
517 | |||
518 | 266 | $options = [ |
|
519 | 'guid' => $this->guid, |
||
520 | 266 | 'limit' => 0 |
|
521 | ]; |
||
522 | 2 | if ($name) { |
|
523 | 2 | $options['metadata_name'] = $name; |
|
524 | } |
||
525 | |||
526 | 2 | return elgg_delete_metadata($options); |
|
527 | 2 | } |
|
528 | |||
529 | /** |
||
530 | * Get a piece of volatile (non-persisted) data on this entity. |
||
531 | * |
||
532 | * @param string $name The name of the volatile data |
||
533 | * |
||
534 | * @return mixed The value or null if not found. |
||
535 | */ |
||
536 | 266 | public function getVolatileData($name) { |
|
537 | 266 | return array_key_exists($name, $this->volatile) ? $this->volatile[$name] : null; |
|
538 | } |
||
539 | 266 | ||
540 | 55 | /** |
|
541 | * Set a piece of volatile (non-persisted) data on this entity |
||
542 | * |
||
543 | 266 | * @param string $name Name |
|
544 | * @param mixed $value Value |
||
545 | * |
||
546 | * @return void |
||
547 | */ |
||
548 | public function setVolatileData($name, $value) { |
||
549 | $this->volatile[$name] = $value; |
||
550 | } |
||
551 | |||
552 | /** |
||
553 | 25 | * Remove all relationships to and from this entity. |
|
554 | 25 | * If you pass a relationship name, only relationships matching that name |
|
555 | * will be deleted. |
||
556 | * |
||
557 | * @warning Calling this with no $relationship will clear all relationships |
||
558 | * for this entity. |
||
559 | * |
||
560 | * @param null|string $relationship The name of the relationship to remove. |
||
561 | * @return bool |
||
562 | * @see \ElggEntity::addRelationship() |
||
563 | * @see \ElggEntity::removeRelationship() |
||
564 | */ |
||
565 | 26 | public function deleteRelationships($relationship = null) { |
|
566 | 26 | $relationship = (string) $relationship; |
|
567 | 26 | $result = remove_entity_relationships($this->getGUID(), $relationship); |
|
568 | return $result && remove_entity_relationships($this->getGUID(), $relationship, true); |
||
569 | } |
||
570 | |||
571 | /** |
||
572 | * Add a relationship between this an another entity. |
||
573 | * |
||
574 | * @tip Read the relationship like "This entity is a $relationship of $guid_two." |
||
575 | * |
||
576 | * @param int $guid_two GUID of the target entity of the relationship. |
||
577 | * @param string $relationship The type of relationship. |
||
578 | * |
||
579 | * @return bool |
||
580 | * @see \ElggEntity::removeRelationship() |
||
581 | * @see \ElggEntity::deleteRelationships() |
||
582 | 214 | */ |
|
583 | 214 | public function addRelationship($guid_two, $relationship) { |
|
584 | 214 | return add_entity_relationship($this->getGUID(), $relationship, $guid_two); |
|
585 | 214 | } |
|
586 | |||
587 | /** |
||
588 | * Remove a relationship |
||
589 | * |
||
590 | * @param int $guid_two GUID of the target entity of the relationship. |
||
591 | * @param string $relationship The type of relationship. |
||
592 | * |
||
593 | * @return bool |
||
594 | * @see \ElggEntity::addRelationship() |
||
595 | * @see \ElggEntity::deleteRelationships() |
||
596 | */ |
||
597 | public function removeRelationship($guid_two, $relationship) { |
||
598 | return remove_entity_relationship($this->getGUID(), $relationship, $guid_two); |
||
599 | } |
||
600 | 5 | ||
601 | 5 | /** |
|
602 | * Adds a private setting to this entity. |
||
603 | * |
||
604 | * @warning Private settings are stored as strings |
||
605 | * Unlike metadata and annotations there is no reverse casting when you retrieve the setting |
||
606 | * When saving integers, they will be cast to strings |
||
607 | * Booleans will be cast to '0' and '1' |
||
608 | * |
||
609 | * @param string $name Name of private setting |
||
610 | * @param mixed $value Value of private setting |
||
611 | * |
||
612 | * @return bool |
||
613 | * @throws DatabaseException |
||
614 | 1 | */ |
|
615 | 1 | public function setPrivateSetting($name, $value) { |
|
616 | if (is_bool($value)) { |
||
617 | $value = (int) $value; |
||
618 | } |
||
619 | |||
620 | if (!$this->guid) { |
||
621 | $this->temp_private_settings[$name] = $value; |
||
622 | |||
623 | return true; |
||
624 | } |
||
625 | |||
626 | return _elgg_services()->privateSettings->set($this, $name, $value); |
||
627 | } |
||
628 | |||
629 | 124 | /** |
|
630 | 124 | * Returns a private setting value |
|
631 | 123 | * |
|
632 | * @warning Private settings are always returned as strings |
||
633 | 45 | * Make sure you can your values back to expected type |
|
634 | 45 | * |
|
635 | * @param string $name Name of the private setting |
||
636 | * |
||
637 | * @return string|null |
||
638 | * @throws DatabaseException |
||
639 | */ |
||
640 | public function getPrivateSetting($name) { |
||
641 | if (!$this->guid) { |
||
642 | return elgg_extract($name, $this->temp_private_settings); |
||
643 | } |
||
644 | |||
645 | 37 | return _elgg_services()->privateSettings->get($this, $name); |
|
646 | 37 | } |
|
647 | 37 | ||
648 | /** |
||
649 | 5 | * Returns all private settings |
|
650 | 5 | * |
|
651 | * @return array |
||
652 | * @throws DatabaseException |
||
653 | 5 | */ |
|
654 | public function getAllPrivateSettings() { |
||
655 | if (!$this->guid) { |
||
656 | return $this->temp_private_settings; |
||
657 | } |
||
658 | |||
659 | return _elgg_services()->privateSettings->getAllForEntity($this); |
||
660 | } |
||
661 | |||
662 | /** |
||
663 | 3 | * Removes private setting |
|
664 | 3 | * |
|
665 | * @param string $name Name of the private setting |
||
666 | * |
||
667 | * @return bool |
||
668 | * @throws DatabaseException |
||
669 | */ |
||
670 | public function removePrivateSetting($name) { |
||
671 | if (!$this->guid) { |
||
672 | unset($this->temp_private_settings[$name]); |
||
673 | return true; |
||
674 | } |
||
675 | |||
676 | return _elgg_services()->privateSettings->remove($this, $name); |
||
677 | 214 | } |
|
678 | |||
679 | 214 | /** |
|
680 | 214 | * Removes all private settings |
|
681 | * |
||
682 | 214 | * @return bool |
|
683 | 1 | * @throws DatabaseException |
|
684 | */ |
||
685 | public function removeAllPrivateSettings() { |
||
686 | 214 | if (!$this->guid) { |
|
687 | $this->temp_private_settings = []; |
||
688 | return true; |
||
689 | } |
||
690 | |||
691 | return _elgg_services()->privateSettings->removeAllForEntity($this); |
||
692 | } |
||
693 | |||
694 | /** |
||
695 | * Deletes all annotations on this object (annotations.entity_guid = $this->guid). |
||
696 | * If you pass a name, only annotations matching that name will be deleted. |
||
697 | 214 | * |
|
698 | * @warning Calling this with no or empty arguments will clear all annotations on the entity. |
||
699 | * |
||
700 | 214 | * @param null|string $name The annotations name to remove. |
|
701 | * @return bool |
||
702 | 214 | * @since 1.8 |
|
703 | 214 | */ |
|
704 | public function deleteAnnotations($name = null) { |
||
705 | 214 | $options = [ |
|
706 | 'guid' => $this->guid, |
||
707 | 'limit' => 0 |
||
708 | ]; |
||
709 | 214 | if ($name) { |
|
710 | 214 | $options['annotation_name'] = $name; |
|
711 | 214 | } |
|
712 | |||
713 | return elgg_delete_annotations($options); |
||
714 | } |
||
715 | |||
716 | /** |
||
717 | * Deletes all annotations owned by this object (annotations.owner_guid = $this->guid). |
||
718 | * If you pass a name, only annotations matching that name will be deleted. |
||
719 | * |
||
720 | * @param null|string $name The name of annotations to delete. |
||
721 | 5 | * @return bool |
|
722 | * @since 1.8 |
||
723 | 5 | */ |
|
724 | 5 | public function deleteOwnedAnnotations($name = null) { |
|
725 | // access is turned off for this because they might |
||
726 | 5 | // no longer have access to an entity they created annotations on. |
|
727 | $ia = elgg_set_ignore_access(true); |
||
728 | $options = [ |
||
729 | 'annotation_owner_guid' => $this->guid, |
||
730 | 5 | 'limit' => 0 |
|
731 | ]; |
||
732 | if ($name) { |
||
733 | $options['annotation_name'] = $name; |
||
734 | } |
||
735 | |||
736 | $r = elgg_delete_annotations($options); |
||
737 | elgg_set_ignore_access($ia); |
||
738 | return $r; |
||
739 | } |
||
740 | |||
741 | /** |
||
742 | 3 | * Disables annotations for this entity, optionally based on name. |
|
743 | * |
||
744 | 3 | * @param string $name An options name of annotations to disable. |
|
745 | 3 | * @return bool |
|
746 | * @since 1.8 |
||
747 | 3 | */ |
|
748 | public function disableAnnotations($name = '') { |
||
749 | $options = [ |
||
750 | 'guid' => $this->guid, |
||
751 | 3 | 'limit' => 0 |
|
752 | ]; |
||
753 | if ($name) { |
||
754 | $options['annotation_name'] = $name; |
||
755 | } |
||
756 | |||
757 | return elgg_disable_annotations($options); |
||
758 | } |
||
759 | |||
760 | /** |
||
761 | 2 | * Enables annotations for this entity, optionally based on name. |
|
762 | * |
||
763 | 2 | * @warning Before calling this, you must use {@link access_show_hidden_entities()} |
|
764 | * |
||
765 | 2 | * @param string $name An options name of annotations to enable. |
|
766 | 2 | * @return bool |
|
767 | * @since 1.8 |
||
768 | */ |
||
769 | 2 | public function enableAnnotations($name = '') { |
|
770 | $options = [ |
||
771 | 'guid' => $this->guid, |
||
772 | 'limit' => 0 |
||
773 | ]; |
||
774 | if ($name) { |
||
775 | $options['annotation_name'] = $name; |
||
776 | } |
||
777 | |||
778 | return elgg_enable_annotations($options); |
||
779 | } |
||
780 | |||
781 | /** |
||
782 | * Helper function to return annotation calculation results |
||
783 | * |
||
784 | * @param string $name The annotation name. |
||
785 | * @param string $calculation A valid MySQL function to run its values through |
||
786 | * @return mixed |
||
787 | */ |
||
788 | private function getAnnotationCalculation($name, $calculation) { |
||
797 | 93 | } |
|
798 | 93 | ||
799 | 93 | /** |
|
800 | 93 | * Adds an annotation to an entity. |
|
801 | 93 | * |
|
802 | 93 | * @warning By default, annotations are private. |
|
803 | 93 | * |
|
804 | * @warning Annotating an unsaved entity more than once with the same name |
||
805 | 17 | * will only save the last annotation. |
|
806 | * |
||
807 | 17 | * @todo Update temp_annotations to store an instance of ElggAnnotation and simply call ElggAnnotation::save(), |
|
808 | * after entity is saved |
||
809 | * |
||
810 | * @param string $name Annotation name |
||
811 | * @param mixed $value Annotation value |
||
812 | * @param int $access_id Access ID |
||
813 | * @param int $owner_guid GUID of the annotation owner |
||
814 | * @param string $value_type The type of annotation value |
||
815 | * |
||
816 | * @return bool|int Returns int if an annotation is saved |
||
817 | */ |
||
818 | public function annotate($name, $value, $access_id = ACCESS_PRIVATE, $owner_guid = 0, $value_type = "") { |
||
819 | if ($this->guid) { |
||
820 | if (!$owner_guid) { |
||
821 | 9 | $owner_guid = elgg_get_logged_in_user_guid(); |
|
822 | 9 | } |
|
823 | 9 | $annotation = new ElggAnnotation(); |
|
824 | $annotation->entity_guid = $this->guid; |
||
825 | 9 | $annotation->name = $name; |
|
826 | $annotation->value_type = $value_type; |
||
827 | $annotation->value = $value; |
||
828 | $annotation->owner_guid = $owner_guid; |
||
829 | $annotation->access_id = $access_id; |
||
830 | return $annotation->save(); |
||
831 | } else { |
||
832 | $this->temp_annotations[$name] = $value; |
||
833 | } |
||
834 | return true; |
||
835 | } |
||
836 | |||
837 | /** |
||
838 | * Gets an array of annotations. |
||
839 | * |
||
840 | * To retrieve annotations on an unsaved entity, pass array('name' => [annotation name]) |
||
841 | * as the options array. |
||
842 | * |
||
843 | * @param array $options Array of options for elgg_get_annotations() except guid. |
||
844 | 2 | * |
|
845 | 2 | * @return array |
|
846 | * @see elgg_get_annotations() |
||
847 | */ |
||
848 | public function getAnnotations(array $options = []) { |
||
849 | if ($this->guid) { |
||
850 | $options['guid'] = $this->guid; |
||
851 | |||
852 | return elgg_get_annotations($options); |
||
853 | } else { |
||
854 | $name = elgg_extract('annotation_name', $options, ''); |
||
855 | |||
856 | if (isset($this->temp_annotations[$name])) { |
||
857 | return [$this->temp_annotations[$name]]; |
||
858 | } |
||
859 | } |
||
860 | |||
861 | return []; |
||
862 | } |
||
863 | |||
864 | /** |
||
865 | * Count annotations. |
||
866 | * |
||
867 | * @param string $name The type of annotation. |
||
868 | * |
||
869 | * @return int |
||
870 | */ |
||
871 | public function countAnnotations($name = "") { |
||
872 | return $this->getAnnotationCalculation($name, 'count'); |
||
873 | } |
||
874 | |||
875 | /** |
||
876 | * Get the average of an integer type annotation. |
||
877 | * |
||
878 | * @param string $name Annotation name |
||
879 | * |
||
880 | * @return int |
||
881 | */ |
||
882 | public function getAnnotationsAvg($name) { |
||
883 | return $this->getAnnotationCalculation($name, 'avg'); |
||
884 | } |
||
885 | |||
886 | /** |
||
887 | * Get the sum of integer type annotations of a given name. |
||
888 | * |
||
889 | * @param string $name Annotation name |
||
890 | * |
||
891 | * @return int |
||
892 | */ |
||
893 | public function getAnnotationsSum($name) { |
||
894 | return $this->getAnnotationCalculation($name, 'sum'); |
||
895 | } |
||
896 | |||
897 | /** |
||
898 | 2 | * Get the minimum of integer type annotations of given name. |
|
899 | 2 | * |
|
900 | 2 | * @param string $name Annotation name |
|
901 | * |
||
902 | 2 | * @return int |
|
903 | */ |
||
904 | public function getAnnotationsMin($name) { |
||
905 | return $this->getAnnotationCalculation($name, 'min'); |
||
906 | 2 | } |
|
907 | 2 | ||
908 | 2 | /** |
|
909 | 2 | * Get the maximum of integer type annotations of a given name. |
|
910 | * |
||
911 | * @param string $name Annotation name |
||
912 | * |
||
913 | * @return int |
||
914 | */ |
||
915 | public function getAnnotationsMax($name) { |
||
916 | return $this->getAnnotationCalculation($name, 'max'); |
||
917 | } |
||
918 | |||
919 | /** |
||
920 | * Count the number of comments attached to this entity. |
||
921 | * |
||
922 | * @return int Number of comments |
||
923 | * @since 1.8.0 |
||
924 | */ |
||
925 | 218 | public function countComments() { |
|
926 | 218 | $params = ['entity' => $this]; |
|
927 | 218 | $num = _elgg_services()->hooks->trigger('comments:count', $this->getType(), $params); |
|
928 | |||
929 | if (is_int($num)) { |
||
930 | return $num; |
||
931 | } |
||
932 | |||
933 | return elgg_get_entities([ |
||
1 ignored issue
–
show
|
|||
934 | 'type' => 'object', |
||
935 | 'subtype' => 'comment', |
||
936 | 'container_guid' => $this->getGUID(), |
||
937 | 'count' => true, |
||
938 | 'distinct' => false, |
||
939 | ]); |
||
940 | } |
||
941 | |||
942 | /** |
||
943 | * Returns the ACLs owned by the entity |
||
944 | * |
||
945 | * @param array $options additional options to get the access collections with |
||
946 | * |
||
947 | * @return \ElggAccessCollection[] |
||
948 | * |
||
949 | * @see elgg_get_access_collections() |
||
950 | * @since 3.0 |
||
951 | */ |
||
952 | public function getOwnedAccessCollections($options = []) { |
||
953 | $options['owner_guid'] = $this->guid; |
||
954 | return _elgg_services()->accessCollections->getEntityCollections($options); |
||
955 | } |
||
956 | |||
957 | /** |
||
958 | * Returns the first ACL owned by the entity with a given subtype |
||
959 | * |
||
960 | * @param string $subtype subtype of the ACL |
||
961 | * |
||
962 | * @return \ElggAccessCollection|false |
||
963 | * |
||
964 | * @since 3.0 |
||
965 | */ |
||
966 | public function getOwnedAccessCollection($subtype) { |
||
967 | if (!is_string($subtype) || $subtype === '') { |
||
968 | return false; |
||
969 | } |
||
970 | |||
971 | $acls = $this->getOwnedAccessCollections([ |
||
972 | 'subtype' => $subtype, |
||
973 | ]); |
||
974 | |||
975 | return elgg_extract(0, $acls, false); |
||
976 | } |
||
977 | |||
978 | /** |
||
979 | * Gets an array of entities with a relationship to this entity. |
||
980 | * |
||
981 | * @param array $options Options array. See elgg_get_entities_from_relationship() |
||
982 | * for a list of options. 'relationship_guid' is set to |
||
983 | * this entity. |
||
984 | * |
||
985 | * @return array|false An array of entities or false on failure |
||
986 | * @see elgg_get_entities_from_relationship() |
||
987 | */ |
||
988 | public function getEntitiesFromRelationship(array $options = []) { |
||
989 | $options['relationship_guid'] = $this->guid; |
||
990 | return elgg_get_entities($options); |
||
991 | } |
||
992 | |||
993 | 399 | /** |
|
994 | 399 | * Gets the number of entities from a specific relationship type |
|
995 | * |
||
996 | * @param string $relationship Relationship type (eg "friends") |
||
997 | * @param bool $inverse_relationship Invert relationship |
||
998 | * |
||
999 | * @return int|false The number of entities or false on failure |
||
1000 | */ |
||
1001 | public function countEntitiesFromRelationship($relationship, $inverse_relationship = false) { |
||
1002 | return elgg_get_entities([ |
||
1003 | 'relationship' => $relationship, |
||
1004 | 'relationship_guid' => $this->getGUID(), |
||
1005 | 'inverse_relationship' => $inverse_relationship, |
||
1006 | 'count' => true |
||
1007 | ]); |
||
1008 | 462 | } |
|
1009 | 462 | ||
1010 | /** |
||
1011 | * Can a user edit this entity? |
||
1012 | * |
||
1013 | * @tip Can be overridden by registering for the permissions_check plugin hook. |
||
1014 | * |
||
1015 | * @param int $user_guid The user GUID, optionally (default: logged in user) |
||
1016 | * |
||
1017 | * @return bool Whether this entity is editable by the given user. |
||
1018 | * @see elgg_set_ignore_access() |
||
1019 | */ |
||
1020 | public function canEdit($user_guid = 0) { |
||
1021 | return _elgg_services()->userCapabilities->canEdit($this, $user_guid); |
||
1022 | } |
||
1023 | |||
1024 | /** |
||
1025 | * Can a user delete this entity? |
||
1026 | * |
||
1027 | 338 | * @tip Can be overridden by registering for the permissions_check:delete plugin hook. |
|
1028 | 338 | * |
|
1029 | * @param int $user_guid The user GUID, optionally (default: logged in user) |
||
1030 | * |
||
1031 | * @return bool Whether this entity is deletable by the given user. |
||
1032 | * @since 1.11 |
||
1033 | * @see elgg_set_ignore_access() |
||
1034 | */ |
||
1035 | public function canDelete($user_guid = 0) { |
||
1036 | return _elgg_services()->userCapabilities->canDelete($this, $user_guid); |
||
1037 | } |
||
1038 | |||
1039 | /** |
||
1040 | * Can a user edit metadata on this entity? |
||
1041 | 407 | * |
|
1042 | 407 | * If no specific metadata is passed, it returns whether the user can |
|
1043 | * edit any metadata on the entity. |
||
1044 | * |
||
1045 | * @tip Can be overridden by by registering for the permissions_check:metadata |
||
1046 | * plugin hook. |
||
1047 | * |
||
1048 | * @param \ElggMetadata $metadata The piece of metadata to specifically check or null for any metadata |
||
1049 | * @param int $user_guid The user GUID, optionally (default: logged in user) |
||
1050 | * |
||
1051 | * @return bool |
||
1052 | * @see elgg_set_ignore_access() |
||
1053 | */ |
||
1054 | public function canEditMetadata($metadata = null, $user_guid = 0) { |
||
1055 | 4 | return _elgg_services()->userCapabilities->canEditMetadata($this, $user_guid, $metadata); |
|
1056 | 4 | } |
|
1057 | |||
1058 | /** |
||
1059 | * Can a user add an entity to this container |
||
1060 | * |
||
1061 | * @param int $user_guid The GUID of the user creating the entity (0 for logged in user). |
||
1062 | * @param string $type The type of entity we're looking to write |
||
1063 | * @param string $subtype The subtype of the entity we're looking to write |
||
1064 | * |
||
1065 | * @return bool |
||
1066 | * @see elgg_set_ignore_access() |
||
1067 | */ |
||
1068 | public function canWriteToContainer($user_guid = 0, $type = 'all', $subtype = 'all') { |
||
1069 | return _elgg_services()->userCapabilities->canWriteToContainer($this, $user_guid, $type, $subtype); |
||
1070 | } |
||
1071 | |||
1072 | /** |
||
1073 | 8 | * Can a user comment on an entity? |
|
1074 | 8 | * |
|
1075 | * @tip Can be overridden by registering for the permissions_check:comment, |
||
1076 | * <entity type> plugin hook. |
||
1077 | * |
||
1078 | * @param int $user_guid User guid (default is logged in user) |
||
1079 | * @param bool $default Default permission |
||
1080 | * @return bool |
||
1081 | */ |
||
1082 | public function canComment($user_guid = 0, $default = null) { |
||
1083 | return _elgg_services()->userCapabilities->canComment($this, $user_guid, $default); |
||
1084 | } |
||
1085 | |||
1086 | /** |
||
1087 | * Can a user annotate an entity? |
||
1088 | * |
||
1089 | * @tip Can be overridden by registering for the plugin hook [permissions_check:annotate:<name>, |
||
1090 | * <entity type>] or [permissions_check:annotate, <entity type>]. The hooks are called in that order. |
||
1091 | 548 | * |
|
1092 | 548 | * @tip If you want logged out users to annotate an object, do not call |
|
1093 | * canAnnotate(). It's easier than using the plugin hook. |
||
1094 | * |
||
1095 | * @param int $user_guid User guid (default is logged in user) |
||
1096 | * @param string $annotation_name The name of the annotation (default is unspecified) |
||
1097 | * |
||
1098 | * @return bool |
||
1099 | */ |
||
1100 | 1 | public function canAnnotate($user_guid = 0, $annotation_name = '') { |
|
1101 | return _elgg_services()->userCapabilities->canAnnotate($this, $user_guid, $annotation_name); |
||
1102 | 1 | } |
|
1103 | |||
1104 | /** |
||
1105 | * Returns the access_id. |
||
1106 | * |
||
1107 | * @return int The access ID |
||
1108 | */ |
||
1109 | public function getAccessID() { |
||
1110 | 566 | return $this->access_id; |
|
1111 | 566 | } |
|
1112 | |||
1113 | /** |
||
1114 | * Returns the guid. |
||
1115 | * |
||
1116 | * @return int|null GUID |
||
1117 | */ |
||
1118 | public function getGUID() { |
||
1119 | 95 | return $this->guid; |
|
1120 | 95 | } |
|
1121 | |||
1122 | /** |
||
1123 | * Returns the entity type |
||
1124 | * |
||
1125 | * @return string The entity type |
||
1126 | */ |
||
1127 | public function getType() { |
||
1130 | } |
||
1131 | |||
1132 | /** |
||
1133 | * Get the entity subtype |
||
1134 | * |
||
1135 | * @return string The entity subtype |
||
1136 | */ |
||
1137 | public function getSubtype() { |
||
1138 | return $this->attributes['subtype']; |
||
1139 | 1 | } |
|
1140 | 1 | ||
1141 | /** |
||
1142 | * Get the guid of the entity's owner. |
||
1143 | * |
||
1144 | * @return int The owner GUID |
||
1145 | */ |
||
1146 | public function getOwnerGUID() { |
||
1147 | return (int) $this->owner_guid; |
||
1148 | 425 | } |
|
1149 | 425 | ||
1150 | /** |
||
1151 | * Gets the \ElggEntity that owns this entity. |
||
1152 | * |
||
1153 | * @return \ElggEntity The owning entity |
||
1154 | */ |
||
1155 | public function getOwnerEntity() { |
||
1156 | return get_entity($this->owner_guid); |
||
1157 | } |
||
1158 | 420 | ||
1159 | 420 | /** |
|
1160 | * Set the container for this object. |
||
1161 | * |
||
1162 | * @param int $container_guid The ID of the container. |
||
1163 | * |
||
1164 | * @return bool |
||
1165 | */ |
||
1166 | public function setContainerGUID($container_guid) { |
||
1167 | 5 | return $this->container_guid = (int) $container_guid; |
|
1168 | 5 | } |
|
1169 | |||
1170 | /** |
||
1171 | * Gets the container GUID for this entity. |
||
1172 | * |
||
1173 | * @return int |
||
1174 | */ |
||
1175 | public function getContainerGUID() { |
||
1176 | return (int) $this->container_guid; |
||
1177 | } |
||
1178 | |||
1179 | 42 | /** |
|
1180 | 42 | * Get the container entity for this object. |
|
1181 | * |
||
1182 | 42 | * @return \ElggEntity |
|
1183 | 39 | * @since 1.8.0 |
|
1184 | */ |
||
1185 | public function getContainerEntity() { |
||
1186 | 3 | return get_entity($this->getContainerGUID()); |
|
1187 | } |
||
1188 | |||
1189 | /** |
||
1190 | * Returns the UNIX epoch time that this entity was last updated |
||
1191 | * |
||
1192 | * @return int UNIX epoch time |
||
1193 | */ |
||
1194 | public function getTimeUpdated() { |
||
1195 | return $this->time_updated; |
||
1196 | } |
||
1197 | |||
1198 | /** |
||
1199 | * Gets the URL for this entity. |
||
1200 | * |
||
1201 | * Plugins can register for the 'entity:url', <type> plugin hook to |
||
1202 | * customize the url for an entity. |
||
1203 | * |
||
1204 | * @return string The URL of the entity |
||
1205 | */ |
||
1206 | public function getURL() { |
||
1207 | $url = _elgg_services()->hooks->trigger('entity:url', $this->getType(), ['entity' => $this]); |
||
1208 | |||
1209 | if ($url === null || $url === '' || $url === false) { |
||
1210 | return ''; |
||
1211 | } |
||
1212 | |||
1213 | return elgg_normalize_url($url); |
||
1214 | } |
||
1215 | |||
1216 | /** |
||
1217 | * Saves icons using an uploaded file as the source. |
||
1218 | * |
||
1219 | * @param string $input_name Form input name |
||
1220 | * @param string $type The name of the icon. e.g., 'icon', 'cover_photo' |
||
1221 | * @param array $coords An array of cropping coordinates x1, y1, x2, y2 |
||
1222 | * @return bool |
||
1223 | */ |
||
1224 | public function saveIconFromUploadedFile($input_name, $type = 'icon', array $coords = []) { |
||
1225 | return _elgg_services()->iconService->saveIconFromUploadedFile($this, $input_name, $type, $coords); |
||
1226 | } |
||
1227 | |||
1228 | /** |
||
1229 | * Saves icons using a local file as the source. |
||
1230 | * |
||
1231 | * @param string $filename The full path to the local file |
||
1232 | * @param string $type The name of the icon. e.g., 'icon', 'cover_photo' |
||
1233 | 7 | * @param array $coords An array of cropping coordinates x1, y1, x2, y2 |
|
1234 | 7 | * @return bool |
|
1235 | */ |
||
1236 | public function saveIconFromLocalFile($filename, $type = 'icon', array $coords = []) { |
||
1237 | return _elgg_services()->iconService->saveIconFromLocalFile($this, $filename, $type, $coords); |
||
1238 | } |
||
1239 | |||
1240 | /** |
||
1241 | * Saves icons using a file located in the data store as the source. |
||
1242 | * |
||
1243 | 1 | * @param string $file An ElggFile instance |
|
1244 | 1 | * @param string $type The name of the icon. e.g., 'icon', 'cover_photo' |
|
1245 | * @param array $coords An array of cropping coordinates x1, y1, x2, y2 |
||
1246 | * @return bool |
||
1247 | */ |
||
1248 | public function saveIconFromElggFile(\ElggFile $file, $type = 'icon', array $coords = []) { |
||
1249 | return _elgg_services()->iconService->saveIconFromElggFile($this, $file, $type, $coords); |
||
1250 | } |
||
1251 | |||
1252 | /** |
||
1253 | * Returns entity icon as an ElggIcon object |
||
1254 | * The icon file may or may not exist on filestore |
||
1255 | * |
||
1256 | * @param string $size Size of the icon |
||
1257 | * @param string $type The name of the icon. e.g., 'icon', 'cover_photo' |
||
1258 | * @return \ElggIcon |
||
1259 | */ |
||
1260 | public function getIcon($size, $type = 'icon') { |
||
1261 | return _elgg_services()->iconService->getIcon($this, $size, $type); |
||
1262 | } |
||
1263 | |||
1264 | /** |
||
1265 | * Removes all icon files and metadata for the passed type of icon. |
||
1266 | 3 | * |
|
1267 | 3 | * @param string $type The name of the icon. e.g., 'icon', 'cover_photo' |
|
1268 | * @return bool |
||
1269 | */ |
||
1270 | public function deleteIcon($type = 'icon') { |
||
1271 | return _elgg_services()->iconService->deleteIcon($this, $type); |
||
1272 | } |
||
1273 | |||
1274 | /** |
||
1275 | * Returns the timestamp of when the icon was changed. |
||
1276 | * |
||
1277 | * @param string $size The size of the icon |
||
1278 | * @param string $type The name of the icon. e.g., 'icon', 'cover_photo' |
||
1279 | * |
||
1280 | * @return int|null A unix timestamp of when the icon was last changed, or null if not set. |
||
1281 | 12 | */ |
|
1282 | 12 | public function getIconLastChange($size, $type = 'icon') { |
|
1283 | return _elgg_services()->iconService->getIconLastChange($this, $size, $type); |
||
1284 | } |
||
1285 | |||
1286 | /** |
||
1287 | * Returns if the entity has an icon of the passed type. |
||
1288 | * |
||
1289 | * @param string $size The size of the icon |
||
1290 | 533 | * @param string $type The name of the icon. e.g., 'icon', 'cover_photo' |
|
1291 | 533 | * @return bool |
|
1292 | 533 | */ |
|
1293 | 194 | public function hasIcon($size, $type = 'icon') { |
|
1294 | return _elgg_services()->iconService->hasIcon($this, $size, $type); |
||
1295 | 509 | } |
|
1296 | 509 | ||
1297 | /** |
||
1298 | * Get the URL for this entity's icon |
||
1299 | * |
||
1300 | * Plugins can register for the 'entity:icon:url', <type> plugin hook |
||
1301 | * to customize the icon for an entity. |
||
1302 | * |
||
1303 | * @param mixed $params A string defining the size of the icon (e.g. tiny, small, medium, large) |
||
1304 | * or an array of parameters including 'size' |
||
1305 | 533 | * @return string The URL |
|
1306 | 513 | * @since 1.8.0 |
|
1307 | */ |
||
1308 | public function getIconURL($params = []) { |
||
1309 | 533 | return _elgg_services()->iconService->getIconURL($this, $params); |
|
1310 | } |
||
1311 | |||
1312 | /** |
||
1313 | * Save an entity. |
||
1314 | * |
||
1315 | * @return bool|int |
||
1316 | */ |
||
1317 | public function save() { |
||
1318 | $guid = $this->guid; |
||
1319 | if ($guid > 0) { |
||
1320 | $guid = $this->update(); |
||
1321 | } else { |
||
1322 | $guid = $this->create(); |
||
1323 | if ($guid && !_elgg_services()->hooks->getEvents()->trigger('create', $this->type, $this)) { |
||
1324 | // plugins that return false to event don't need to override the access system |
||
1325 | 509 | $ia = elgg_set_ignore_access(true); |
|
1326 | $this->delete(); |
||
1327 | 509 | elgg_set_ignore_access($ia); |
|
1328 | 509 | return false; |
|
1329 | } |
||
1330 | } |
||
1331 | |||
1332 | if ($guid) { |
||
1333 | 509 | $this->cache(); |
|
1334 | 509 | } |
|
1335 | |||
1336 | return $guid; |
||
1 ignored issue
–
show
|
|||
1337 | } |
||
1338 | 509 | ||
1339 | 509 | /** |
|
1340 | 509 | * Create a new entry in the entities table. |
|
1341 | 509 | * |
|
1342 | * Saves the base information in the entities table for the entity. Saving |
||
1343 | 509 | * the type-specific information is handled in the calling class method. |
|
1344 | 509 | * |
|
1345 | 179 | * @warning Entities must have an entry in both the entities table and their type table |
|
1346 | 179 | * or they will throw an exception when loaded. |
|
1347 | * |
||
1348 | 509 | * @return int The new entity's GUID |
|
1349 | * @throws InvalidParameterException If the entity's type has not been set. |
||
1350 | 509 | * @throws IOException If the new row fails to write to the DB. |
|
1351 | */ |
||
1352 | protected function create() { |
||
1353 | |||
1354 | 509 | $type = $this->attributes['type']; |
|
1355 | if (!in_array($type, \Elgg\Config::getEntityTypes())) { |
||
1356 | throw new \InvalidParameterException('Entity type must be one of the allowed types: ' |
||
1357 | . implode(', ', \Elgg\Config::getEntityTypes())); |
||
1358 | 509 | } |
|
1359 | |||
1360 | $subtype = $this->attributes['subtype']; |
||
1361 | 509 | if (!$subtype) { |
|
1362 | 402 | throw new \InvalidParameterException("All entities must have a subtype"); |
|
1363 | 402 | } |
|
1364 | |||
1365 | $owner_guid = (int) $this->attributes['owner_guid']; |
||
1366 | $access_id = (int) $this->attributes['access_id']; |
||
1367 | $now = $this->getCurrentTime()->getTimestamp(); |
||
1368 | $time_created = isset($this->attributes['time_created']) ? (int) $this->attributes['time_created'] : $now; |
||
1369 | |||
1370 | $container_guid = $this->attributes['container_guid']; |
||
1371 | 402 | if ($container_guid == 0) { |
|
1372 | $container_guid = $owner_guid; |
||
1373 | $this->attributes['container_guid'] = $container_guid; |
||
1374 | } |
||
1375 | $container_guid = (int) $container_guid; |
||
1376 | |||
1377 | if ($access_id == ACCESS_DEFAULT) { |
||
1378 | throw new \InvalidParameterException('ACCESS_DEFAULT is not a valid access level. See its documentation in constants.php'); |
||
1379 | 509 | } |
|
1380 | 403 | ||
1381 | 403 | if ($access_id == ACCESS_FRIENDS) { |
|
1382 | throw new \InvalidParameterException('ACCESS_FRIENDS is not a valid access level. See its documentation in constants.php'); |
||
1383 | } |
||
1384 | |||
1385 | $user_guid = elgg_get_logged_in_user_guid(); |
||
1386 | |||
1387 | 403 | // If given an owner, verify it can be loaded |
|
1388 | if ($owner_guid) { |
||
1389 | $owner = $this->getOwnerEntity(); |
||
1390 | if (!$owner) { |
||
1391 | _elgg_services()->logger->error("User $user_guid tried to create a ($type, $subtype), but the given" |
||
1392 | . " owner $owner_guid could not be loaded."); |
||
1393 | return false; |
||
1394 | } |
||
1395 | 509 | ||
1396 | 509 | // If different owner than logged in, verify can write to container. |
|
1397 | 509 | ||
1398 | 509 | if ($user_guid != $owner_guid && !$owner->canWriteToContainer($user_guid, $type, $subtype)) { |
|
1399 | 509 | _elgg_services()->logger->error("User $user_guid tried to create a ($type, $subtype) with owner" |
|
1400 | 509 | . " $owner_guid, but the user wasn't permitted to write to the owner's container."); |
|
1401 | 509 | return false; |
|
1402 | 509 | } |
|
1403 | 509 | } |
|
1404 | 509 | ||
1405 | // If given a container, verify it can be loaded and that the current user can write to it |
||
1406 | 509 | if ($container_guid) { |
|
1407 | $container = $this->getContainerEntity(); |
||
1408 | if (!$container) { |
||
1409 | _elgg_services()->logger->error("User $user_guid tried to create a ($type, $subtype), but the given" |
||
1410 | 509 | . " container $container_guid could not be loaded."); |
|
1411 | 509 | return false; |
|
1412 | 509 | } |
|
1413 | 509 | ||
1414 | 509 | if (!$container->canWriteToContainer($user_guid, $type, $subtype)) { |
|
1415 | 509 | _elgg_services()->logger->error("User $user_guid tried to create a ($type, $subtype), but was not" |
|
1416 | . " permitted to write to container $container_guid."); |
||
1417 | return false; |
||
1418 | } |
||
1419 | } |
||
1420 | 509 | ||
1421 | // Create primary table row |
||
1422 | $guid = _elgg_services()->entityTable->insertRow((object) [ |
||
1423 | 509 | 'type' => $type, |
|
1424 | 475 | 'subtype' => $subtype, |
|
1425 | 475 | 'owner_guid' => $owner_guid, |
|
1426 | 'container_guid' => $container_guid, |
||
1427 | 475 | 'access_id' => $access_id, |
|
1428 | 'time_created' => $time_created, |
||
1429 | 475 | 'time_updated' => $now, |
|
1430 | 'last_action' => $now, |
||
1431 | ], $this->attributes); |
||
1432 | |||
1433 | 475 | if (!$guid) { |
|
1434 | throw new \IOException("Unable to save new object's base entity information!"); |
||
1435 | } |
||
1436 | |||
1437 | 509 | $this->attributes['subtype'] = $subtype; |
|
1438 | 17 | $this->attributes['guid'] = (int) $guid; |
|
1439 | 17 | $this->attributes['time_created'] = (int) $time_created; |
|
1440 | $this->attributes['time_updated'] = (int) $now; |
||
1441 | $this->attributes['last_action'] = (int) $now; |
||
1442 | 17 | $this->attributes['container_guid'] = (int) $container_guid; |
|
1443 | |||
1444 | // We are writing this new entity to cache to make sure subsequent calls |
||
1445 | // to get_entity() load the entity from cache and not from the DB. This |
||
1446 | 509 | // MUST come before the metadata and annotation writes below! |
|
1447 | 44 | $this->cache(); |
|
1448 | 44 | ||
1449 | // Save any unsaved metadata |
||
1450 | if (sizeof($this->temp_metadata) > 0) { |
||
1451 | 44 | foreach ($this->temp_metadata as $name => $value) { |
|
1452 | if (count($value) == 1) { |
||
1453 | // temp metadata is always an array, but if there is only one value return just the value |
||
1454 | 509 | $this->$name = $value[0]; |
|
1455 | } else { |
||
1456 | $this->$name = $value; |
||
1457 | } |
||
1458 | } |
||
1459 | |||
1460 | $this->temp_metadata = []; |
||
1461 | } |
||
1462 | |||
1463 | // Save any unsaved annotations. |
||
1464 | 194 | if (sizeof($this->temp_annotations) > 0) { |
|
1465 | foreach ($this->temp_annotations as $name => $value) { |
||
1466 | 194 | $this->annotate($name, $value); |
|
1467 | 26 | } |
|
1468 | |||
1469 | $this->temp_annotations = []; |
||
1470 | } |
||
1471 | 172 | ||
1472 | // Save any unsaved private settings. |
||
1473 | if (sizeof($this->temp_private_settings) > 0) { |
||
1474 | foreach ($this->temp_private_settings as $name => $value) { |
||
1475 | 172 | $this->setPrivateSetting($name, $value); |
|
1476 | } |
||
1477 | |||
1478 | 172 | $this->temp_private_settings = []; |
|
1479 | 172 | } |
|
1480 | 172 | ||
1481 | 172 | return $guid; |
|
1482 | 172 | } |
|
1483 | 172 | ||
1484 | /** |
||
1485 | 172 | * Update the entity in the database. |
|
1486 | * |
||
1487 | * @return bool Whether the update was successful. |
||
1488 | * |
||
1489 | 172 | * @throws InvalidParameterException |
|
1490 | */ |
||
1491 | protected function update() { |
||
1492 | |||
1493 | if (!$this->canEdit()) { |
||
1494 | 172 | return false; |
|
1495 | 172 | } |
|
1496 | 172 | ||
1497 | 172 | // give old update event a chance to stop the update |
|
1498 | 172 | if (!_elgg_services()->hooks->getEvents()->trigger('update', $this->type, $this)) { |
|
1499 | 172 | return false; |
|
1500 | 172 | } |
|
1501 | |||
1502 | 172 | $this->invalidateCache(); |
|
1503 | |||
1504 | // See #6225. We copy these after the update event in case a handler changed one of them. |
||
1505 | $guid = (int) $this->guid; |
||
1506 | 172 | $owner_guid = (int) $this->owner_guid; |
|
1507 | $access_id = (int) $this->access_id; |
||
1508 | 172 | $container_guid = (int) $this->container_guid; |
|
1509 | $time_created = (int) $this->time_created; |
||
1510 | $time = $this->getCurrentTime()->getTimestamp(); |
||
1511 | 172 | ||
1512 | 5 | if ($access_id == ACCESS_DEFAULT) { |
|
1513 | throw new \InvalidParameterException('ACCESS_DEFAULT is not a valid access level. See its documentation in constants.php'); |
||
1514 | } |
||
1515 | 172 | ||
1516 | if ($access_id == ACCESS_FRIENDS) { |
||
1517 | 172 | throw new \InvalidParameterException('ACCESS_FRIENDS is not a valid access level. See its documentation in constants.php'); |
|
1518 | } |
||
1519 | |||
1520 | 172 | // Update primary table |
|
1521 | $ret = _elgg_services()->entityTable->updateRow($guid, (object) [ |
||
1522 | 'owner_guid' => $owner_guid, |
||
1523 | 'container_guid' => $container_guid, |
||
1524 | 'access_id' => $access_id, |
||
1525 | 'time_created' => $time_created, |
||
1526 | 'time_updated' => $time, |
||
1527 | 'guid' => $guid, |
||
1528 | ]); |
||
1529 | if ($ret === false) { |
||
1530 | 5313 | return false; |
|
1531 | 5313 | } |
|
1532 | |||
1533 | 5313 | $this->attributes['time_updated'] = $time; |
|
1534 | |||
1535 | elgg_trigger_after_event('update', $this->type, $this); |
||
1536 | |||
1537 | // TODO(evan): Move this to \ElggObject? |
||
1538 | 5313 | if ($this instanceof \ElggObject && isset($this->orig_attributes['access_id'])) { |
|
1539 | 5313 | update_river_access_by_object($guid, $access_id); |
|
1540 | 24 | } |
|
1541 | 24 | ||
1542 | 24 | $this->orig_attributes = []; |
|
1543 | |||
1544 | $this->cache(); |
||
1545 | 5313 | ||
1546 | 5313 | // Handle cases where there was no error BUT no rows were updated! |
|
1547 | return true; |
||
1548 | } |
||
1549 | |||
1550 | 5313 | /** |
|
1551 | * Loads attributes from the entities table into the object. |
||
1552 | 5313 | * |
|
1553 | * @param stdClass $row Object of properties from database row(s) |
||
1554 | 5313 | * |
|
1555 | * @return bool |
||
1556 | */ |
||
1557 | protected function load(stdClass $row) { |
||
1558 | $attributes = array_merge($this->attributes, (array) $row); |
||
1559 | |||
1560 | if (array_diff(self::$primary_attr_names, array_keys($attributes)) !== []) { |
||
1561 | // Some primary attributes are missing |
||
1562 | return false; |
||
1563 | } |
||
1564 | |||
1565 | foreach ($attributes as $name => $value) { |
||
1566 | if (!in_array($name, self::$primary_attr_names)) { |
||
1567 | $this->setVolatileData("select:$name", $value); |
||
1568 | unset($attributes[$name]); |
||
1569 | continue; |
||
1570 | } |
||
1571 | |||
1572 | if (in_array($name, self::$integer_attr_names)) { |
||
1573 | $attributes[$name] = (int) $value; |
||
1574 | } |
||
1575 | } |
||
1576 | |||
1577 | $this->attributes = $attributes; |
||
1578 | |||
1579 | $this->cache(); |
||
1580 | |||
1581 | return true; |
||
1582 | } |
||
1583 | |||
1584 | /** |
||
1585 | * Load new data from database into existing entity. Overwrites data but |
||
1586 | * does not change values not included in the latest data. |
||
1587 | * |
||
1588 | * @internal This is used when the same entity is selected twice during a |
||
1589 | * request in case different select clauses were used to load different data |
||
1590 | * into volatile data. |
||
1591 | * |
||
1592 | * @param stdClass $row DB row with new entity data |
||
1593 | * @return bool |
||
1594 | * @access private |
||
1595 | 5 | */ |
|
1596 | 5 | public function refresh(stdClass $row) { |
|
1597 | if ($row instanceof stdClass) { |
||
1598 | return $this->load($row); |
||
1599 | } |
||
1600 | 5 | return false; |
|
1601 | } |
||
1602 | |||
1603 | /** |
||
1604 | 5 | * Disable this entity. |
|
1605 | * |
||
1606 | * Disabled entities are not returned by getter functions. |
||
1607 | * To enable an entity, use {@link \ElggEntity::enable()}. |
||
1608 | 5 | * |
|
1609 | * Recursively disabling an entity will disable all entities |
||
1610 | 1 | * owned or contained by the parent entity. |
|
1611 | 1 | * |
|
1612 | * You can ignore the disabled field by using {@link access_show_hidden_entities()}. |
||
1613 | 4 | * |
|
1614 | * @note Internal: Disabling an entity sets the 'enabled' column to 'no'. |
||
1615 | * |
||
1616 | 5 | * @param string $reason Optional reason |
|
1617 | * @param bool $recursive Recursively disable all contained entities? |
||
1618 | * |
||
1619 | * @return bool |
||
1620 | 5 | * @see \ElggEntity::enable() |
|
1621 | */ |
||
1622 | 5 | public function disable($reason = "", $recursive = true) { |
|
1623 | if (!$this->guid) { |
||
1624 | 5 | return false; |
|
1625 | } |
||
1626 | 5 | ||
1627 | 5 | if (!_elgg_services()->hooks->getEvents()->trigger('disable', $this->type, $this)) { |
|
1628 | return false; |
||
1629 | 5 | } |
|
1630 | |||
1631 | if (!$this->canEdit()) { |
||
1632 | 5 | return false; |
|
1633 | 5 | } |
|
1634 | |||
1635 | if ($this instanceof ElggUser && !$this->isBanned()) { |
||
1636 | // temporarily ban to prevent using the site during disable |
||
1637 | $this->ban(); |
||
1638 | 5 | $unban_after = true; |
|
1639 | 5 | } else { |
|
1640 | 5 | $unban_after = false; |
|
1641 | } |
||
1642 | 5 | ||
1643 | 5 | if ($reason) { |
|
1644 | $this->disable_reason = $reason; |
||
1 ignored issue
–
show
|
|||
1645 | 5 | } |
|
1646 | |||
1647 | 2 | $dbprefix = _elgg_config()->dbprefix; |
|
1648 | |||
1649 | $guid = (int) $this->guid; |
||
1650 | 2 | ||
1651 | 5 | if ($recursive) { |
|
1652 | // Only disable enabled subentities |
||
1653 | $hidden = access_get_show_hidden_status(); |
||
1654 | access_show_hidden_entities(false); |
||
1655 | 5 | ||
1656 | 5 | $ia = elgg_set_ignore_access(true); |
|
1657 | |||
1658 | $base_options = [ |
||
1659 | 5 | 'wheres' => [ |
|
1660 | "e.guid != $guid", |
||
1661 | ], |
||
1662 | 5 | 'limit' => false, |
|
1663 | ]; |
||
1664 | |||
1665 | foreach (['owner_guid', 'container_guid'] as $db_column) { |
||
1666 | $options = $base_options; |
||
1667 | 5 | $options[$db_column] = $guid; |
|
1668 | |||
1669 | 5 | $subentities = new \ElggBatch('elgg_get_entities', $options); |
|
1670 | $subentities->setIncrementOffset(false); |
||
1671 | 5 | ||
1672 | 1 | foreach ($subentities as $subentity) { |
|
1673 | /* @var $subentity \ElggEntity */ |
||
1674 | if (!$subentity->isEnabled()) { |
||
1675 | 5 | continue; |
|
1676 | 5 | } |
|
1677 | add_entity_relationship($subentity->guid, 'disabled_with', $guid); |
||
1678 | 5 | $subentity->disable($reason); |
|
1679 | 5 | } |
|
1680 | } |
||
1681 | |||
1682 | 5 | access_show_hidden_entities($hidden); |
|
1683 | elgg_set_ignore_access($ia); |
||
1684 | } |
||
1685 | |||
1686 | $this->disableAnnotations(); |
||
1687 | |||
1688 | $sql = " |
||
1689 | UPDATE {$dbprefix}entities |
||
1690 | SET enabled = 'no' |
||
1691 | WHERE guid = :guid |
||
1692 | "; |
||
1693 | $params = [ |
||
1694 | ':guid' => $guid, |
||
1695 | 3 | ]; |
|
1696 | 3 | $disabled = $this->getDatabase()->updateData($sql, false, $params); |
|
1697 | 3 | ||
1698 | if ($unban_after) { |
||
1699 | $this->unban(); |
||
1 ignored issue
–
show
|
|||
1700 | } |
||
1701 | 3 | ||
1702 | if ($disabled) { |
||
1703 | $this->invalidateCache(); |
||
1704 | |||
1705 | 3 | $this->attributes['enabled'] = 'no'; |
|
1706 | _elgg_services()->hooks->getEvents()->trigger('disable:after', $this->type, $this); |
||
1707 | } |
||
1708 | |||
1709 | return (bool) $disabled; |
||
1710 | 3 | } |
|
1711 | 3 | ||
1712 | /** |
||
1713 | 3 | * Enable the entity |
|
1714 | 3 | * |
|
1715 | 3 | * @warning Disabled entities can't be loaded unless |
|
1716 | * {@link access_show_hidden_entities(true)} has been called. |
||
1717 | 3 | * |
|
1718 | * @param bool $recursive Recursively enable all entities disabled with the entity? |
||
1719 | * @see access_show_hiden_entities() |
||
1720 | 3 | * @return bool |
|
1721 | 3 | */ |
|
1722 | public function enable($recursive = true) { |
||
1723 | 3 | $guid = (int) $this->guid; |
|
1724 | 3 | if (!$guid) { |
|
1725 | 3 | return false; |
|
1726 | 3 | } |
|
1727 | |||
1728 | 3 | if (!_elgg_services()->hooks->getEvents()->trigger('enable', $this->type, $this)) { |
|
1729 | return false; |
||
1730 | } |
||
1731 | 3 | ||
1732 | 1 | if (!$this->canEdit()) { |
|
1733 | 1 | return false; |
|
1734 | } |
||
1735 | |||
1736 | // Override access only visible entities |
||
1737 | 3 | $old_access_status = access_get_show_hidden_status(); |
|
1738 | access_show_hidden_entities(true); |
||
1739 | 3 | ||
1740 | 3 | $db = $this->getDatabase(); |
|
1741 | 3 | $result = $db->updateData(" |
|
1742 | UPDATE {$db->prefix}entities |
||
1743 | SET enabled = 'yes' |
||
1744 | 3 | WHERE guid = $guid |
|
1745 | "); |
||
1746 | |||
1747 | $this->deleteMetadata('disable_reason'); |
||
1748 | $this->enableAnnotations(); |
||
1749 | |||
1750 | if ($recursive) { |
||
1751 | $disabled_with_it = elgg_get_entities([ |
||
1752 | 8 | 'relationship' => 'disabled_with', |
|
1753 | 8 | 'relationship_guid' => $guid, |
|
1754 | 'inverse_relationship' => true, |
||
1755 | 'limit' => 0, |
||
1756 | ]); |
||
1757 | |||
1758 | foreach ($disabled_with_it as $e) { |
||
1759 | $e->enable(); |
||
1760 | remove_entity_relationship($e->guid, 'disabled_with', $guid); |
||
1761 | } |
||
1762 | } |
||
1763 | |||
1764 | access_show_hidden_entities($old_access_status); |
||
1765 | |||
1766 | if ($result) { |
||
1767 | $this->attributes['enabled'] = 'yes'; |
||
1768 | _elgg_services()->hooks->getEvents()->trigger('enable:after', $this->type, $this); |
||
1769 | } |
||
1770 | |||
1771 | return $result; |
||
1772 | } |
||
1773 | 459 | ||
1774 | /** |
||
1775 | * Is this entity enabled? |
||
1776 | * |
||
1777 | 459 | * @return boolean Whether this entity is enabled. |
|
1778 | 247 | */ |
|
1779 | public function isEnabled() { |
||
1780 | return $this->enabled == 'yes'; |
||
1781 | } |
||
1782 | 215 | ||
1783 | /** |
||
1784 | * Deletes the entity. |
||
1785 | * |
||
1786 | * Removes the entity and its metadata, annotations, relationships, |
||
1787 | * river entries, and private data. |
||
1788 | * |
||
1789 | * Optionally can remove entities contained and owned by this entity. |
||
1790 | * |
||
1791 | * @warning If deleting recursively, this bypasses ownership of items contained by |
||
1792 | 5 | * the entity. That means that if the container_guid = $this->guid, the item will |
|
1793 | 5 | * be deleted regardless of who owns it. |
|
1794 | 5 | * |
|
1795 | 5 | * @param bool $recursive If true (default) then all entities which are |
|
1796 | 5 | * owned or contained by $this will also be deleted. |
|
1797 | * |
||
1798 | * @return bool |
||
1799 | */ |
||
1800 | public function delete($recursive = true) { |
||
1801 | // first check if we can delete this entity |
||
1802 | // NOTE: in Elgg <= 1.10.3 this was after the delete event, |
||
1803 | // which could potentially remove some content if the user didn't have access |
||
1804 | if (!$this->canDelete()) { |
||
1805 | 5 | return false; |
|
1806 | 5 | } |
|
1807 | 5 | ||
1808 | 5 | try { |
|
1809 | 5 | return _elgg_services()->entityTable->delete($this, $recursive); |
|
1810 | 5 | } catch (DatabaseException $ex) { |
|
1811 | 5 | elgg_log($ex->getMessage(), 'ERROR'); |
|
1812 | 5 | return false; |
|
1813 | 5 | } |
|
1814 | 5 | } |
|
1815 | 5 | ||
1816 | /** |
||
1817 | * {@inheritdoc} |
||
1818 | */ |
||
1819 | public function toObject() { |
||
1820 | $object = $this->prepareObject(new stdClass()); |
||
1821 | $params = ['entity' => $this]; |
||
1822 | $object = _elgg_services()->hooks->trigger('to:object', 'entity', $params, $object); |
||
1823 | return $object; |
||
1824 | } |
||
1825 | |||
1826 | /** |
||
1827 | * Prepare an object copy for toObject() |
||
1828 | * |
||
1829 | * @param stdClass $object Object representation of the entity |
||
1830 | * @return stdClass |
||
1831 | */ |
||
1832 | protected function prepareObject($object) { |
||
1833 | $object->guid = $this->guid; |
||
1834 | $object->type = $this->getType(); |
||
1835 | $object->subtype = $this->getSubtype(); |
||
1836 | $object->owner_guid = $this->getOwnerGUID(); |
||
1837 | $object->container_guid = $this->getContainerGUID(); |
||
1838 | $object->time_created = date('c', $this->getTimeCreated()); |
||
1839 | $object->time_updated = date('c', $this->getTimeUpdated()); |
||
1840 | $object->url = $this->getURL(); |
||
1841 | $object->read_access = (int) $this->access_id; |
||
1842 | return $object; |
||
1843 | } |
||
1844 | |||
1845 | /* |
||
1846 | * LOCATABLE INTERFACE |
||
1847 | */ |
||
1848 | |||
1849 | /** |
||
1850 | * Gets the 'location' metadata for the entity |
||
1851 | * |
||
1852 | * @return string The location |
||
1853 | */ |
||
1854 | public function getLocation() { |
||
1855 | return $this->location; |
||
1856 | } |
||
1857 | |||
1858 | /** |
||
1859 | * Sets the 'location' metadata for the entity |
||
1860 | * |
||
1861 | * @param string $location String representation of the location |
||
1862 | 3 | * |
|
1863 | 3 | * @return void |
|
1864 | */ |
||
1865 | public function setLocation($location) { |
||
1866 | $this->location = $location; |
||
1867 | } |
||
1868 | |||
1869 | /** |
||
1870 | * Set latitude and longitude metadata tags for a given entity. |
||
1871 | * |
||
1872 | 3 | * @param float $lat Latitude |
|
1873 | 3 | * @param float $long Longitude |
|
1874 | * |
||
1875 | * @return void |
||
1876 | * @todo Unimplemented |
||
1877 | */ |
||
1878 | public function setLatLong($lat, $long) { |
||
1879 | $this->{"geo:lat"} = $lat; |
||
1880 | $this->{"geo:long"} = $long; |
||
1881 | } |
||
1882 | |||
1883 | /** |
||
1884 | * Return the entity's latitude. |
||
1885 | * |
||
1886 | 350 | * @return float |
|
1887 | 350 | * @todo Unimplemented |
|
1888 | */ |
||
1889 | public function getLatitude() { |
||
1890 | return (float) $this->{"geo:lat"}; |
||
1891 | } |
||
1892 | |||
1893 | /** |
||
1894 | * Return the entity's longitude |
||
1895 | * |
||
1896 | * @return float |
||
1897 | * @todo Unimplemented |
||
1898 | */ |
||
1899 | public function getLongitude() { |
||
1901 | } |
||
1902 | |||
1903 | /* |
||
1904 | * SYSTEM LOG INTERFACE |
||
1905 | */ |
||
1906 | |||
1907 | /** |
||
1908 | * Return an identification for the object for storage in the system log. |
||
1909 | * This id must be an integer. |
||
1910 | * |
||
1911 | * @return int |
||
1912 | */ |
||
1913 | public function getSystemLogID() { |
||
1914 | return $this->getGUID(); |
||
1915 | } |
||
1916 | |||
1917 | /** |
||
1918 | * For a given ID, return the object associated with it. |
||
1919 | * This is used by the system log. It can be called on any Loggable object. |
||
1920 | * |
||
1921 | * @param int $id GUID. |
||
1922 | * @return int GUID |
||
1923 | */ |
||
1924 | public function getObjectFromID($id) { |
||
1925 | return get_entity($id); |
||
1926 | } |
||
1927 | |||
1928 | /** |
||
1929 | * Returns tags for this entity. |
||
1930 | * |
||
1931 | * @warning Tags must be registered by {@link elgg_register_tag_metadata_name()}. |
||
1932 | * |
||
1933 | * @param array $tag_names Optionally restrict by tag metadata names. |
||
1934 | * |
||
1935 | * @return array |
||
1936 | */ |
||
1937 | public function getTags($tag_names = null) { |
||
1938 | if ($tag_names && !is_array($tag_names)) { |
||
1939 | $tag_names = [$tag_names]; |
||
1940 | } |
||
1941 | |||
1942 | $valid_tags = elgg_get_registered_tag_metadata_names(); |
||
1943 | 214 | $entity_tags = []; |
|
1944 | |||
1945 | 214 | foreach ($valid_tags as $tag_name) { |
|
1946 | if (is_array($tag_names) && !in_array($tag_name, $tag_names)) { |
||
1947 | continue; |
||
1948 | } |
||
1949 | 214 | ||
1950 | 191 | if ($tags = $this->$tag_name) { |
|
1951 | // if a single tag, metadata returns a string. |
||
1952 | // if multiple tags, metadata returns an array. |
||
1953 | 70 | if (is_array($tags)) { |
|
1954 | $entity_tags = array_merge($entity_tags, $tags); |
||
1955 | 70 | } else { |
|
1956 | 70 | $entity_tags[] = $tags; |
|
1957 | 69 | } |
|
1958 | } |
||
1959 | } |
||
1960 | 4 | ||
1961 | 4 | return $entity_tags; |
|
1962 | 4 | } |
|
1963 | |||
1964 | /** |
||
1965 | 4 | * Remove the membership of all access collections for this entity (if the entity is a user) |
|
1966 | * |
||
1967 | * @return bool |
||
1968 | * @since 1.11 |
||
1969 | */ |
||
1970 | public function deleteAccessCollectionMemberships() { |
||
1993 | } |
||
1994 | |||
1995 | /** |
||
1996 | * Remove all access collections owned by this entity |
||
1997 | * |
||
1998 | * @return bool |
||
1999 | * @since 1.11 |
||
2000 | */ |
||
2001 | public function deleteOwnedAccessCollections() { |
||
2002 | |||
2003 | 122 | if (!$this->guid) { |
|
2004 | 122 | return false; |
|
2005 | 122 | } |
|
2006 | 122 | ||
2007 | 122 | $collections = $this->getOwnedAccessCollections(); |
|
2008 | if (empty($collections)) { |
||
2009 | 122 | return true; |
|
2010 | } |
||
2011 | |||
2012 | $result = true; |
||
2013 | foreach ($collections as $collection) { |
||
2018 | 2 | } |
|
2019 | 2 | ||
2020 | 2 | /** |
|
2021 | 2 | * Update the last_action column in the entities table. |
|
2022 | * |
||
2023 | 2 | * @warning This is different to time_updated. Time_updated is automatically set, |
|
2024 | * while last_action is only set when explicitly called. |
||
2025 | * |
||
2026 | * @param int $posted Timestamp of last action |
||
2027 | * @return int|false |
||
2028 | * @access private |
||
2029 | */ |
||
2030 | public function updateLastAction($posted = null) { |
||
2031 | 1 | $posted = _elgg_services()->entityTable->updateLastAction($this, $posted); |
|
2032 | 1 | if ($posted) { |
|
2033 | 1 | $this->attributes['last_action'] = $posted; |
|
2034 | $this->cache(); |
||
2035 | } |
||
2036 | return $posted; |
||
2037 | } |
||
2038 | |||
2039 | /** |
||
2040 | * Disable runtime caching for entity |
||
2041 | 5308 | * |
|
2042 | 5308 | * @return void |
|
2043 | 827 | * @internal |
|
2044 | */ |
||
2045 | 5118 | public function disableCaching() { |
|
2046 | $this->_is_cacheable = false; |
||
2047 | if ($this->guid) { |
||
2048 | _elgg_services()->entityCache->delete($this->guid); |
||
2049 | } |
||
2050 | } |
||
2051 | |||
2052 | /** |
||
2053 | * Enable runtime caching for entity |
||
2054 | * |
||
2055 | * @return void |
||
2056 | 5313 | * @internal |
|
2057 | 5313 | */ |
|
2058 | 828 | public function enableCaching() { |
|
2059 | $this->_is_cacheable = true; |
||
2060 | } |
||
2061 | 5125 | ||
2062 | /** |
||
2063 | 5125 | * Is entity cacheable in the runtime cache |
|
2064 | 5125 | * |
|
2065 | * @return bool |
||
2066 | * @internal |
||
2067 | 5125 | */ |
|
2068 | public function isCacheable() { |
||
2073 | 5125 | } |
|
2074 | |||
2075 | /** |
||
2076 | * Cache the entity in a session and persisted caches |
||
2077 | * |
||
2078 | * @param bool $persist Store in persistent cache |
||
2079 | * |
||
2080 | * @return void |
||
2081 | 1068 | * @internal |
|
2082 | 1068 | */ |
|
2083 | public function cache($persist = true) { |
||
2084 | if (!$this->isCacheable()) { |
||
2085 | return; |
||
2086 | 1068 | } |
|
2087 | |||
2088 | 1068 | _elgg_services()->entityCache->save($this); |
|
2089 | |||
2090 | if ($persist) { |
||
2091 | 1068 | $tmp = $this->volatile; |
|
2092 | |||
2093 | // don't store volatile data |
||
2094 | $this->volatile = []; |
||
2095 | |||
2096 | 1068 | _elgg_services()->dataCache->entities->save($this->guid, $this); |
|
2097 | 1068 | ||
2098 | $this->volatile = $tmp; |
||
2099 | 1068 | } |
|
2100 | } |
||
2101 | |||
2102 | /** |
||
2103 | * Invalidate cache for entity |
||
2104 | * |
||
2105 | * @return void |
||
2106 | * @internal |
||
2107 | */ |
||
2108 | public function invalidateCache() { |
||
2125 | } |
||
2126 | } |
||
2127 | } |
||
2128 |
The
break
statement is not necessary if it is preceded for example by areturn
statement:If you would like to keep this construct to be consistent with other
case
statements, you can safely mark this issue as a false-positive.