Elgg  Version master
ElggEntity.php
Go to the documentation of this file.
1 <?php
2 
14 
52 abstract class ElggEntity extends \ElggData {
53 
55  use Annotations;
56  use Icons;
57  use Metadata;
58  use Relationships;
59  use Subscriptions;
60 
61  public const PRIMARY_ATTR_NAMES = [
62  'guid',
63  'type',
64  'subtype',
65  'owner_guid',
66  'container_guid',
67  'access_id',
68  'time_created',
69  'time_updated',
70  'last_action',
71  'enabled',
72  'deleted',
73  'time_deleted',
74  ];
75 
79  protected const INTEGER_ATTR_NAMES = [
80  'guid',
81  'owner_guid',
82  'container_guid',
83  'access_id',
84  'time_created',
85  'time_updated',
86  'last_action',
87  'time_deleted',
88  ];
89 
95  protected $volatile = [];
96 
101  protected $orig_attributes = [];
102 
106  protected $_is_cacheable = true;
107 
122  public function __construct(stdClass $row = null) {
123  $this->initializeAttributes();
124 
125  if (!empty($row) && !$this->load($row)) {
126  throw new IOException('Failed to load new ' . get_class() . " for GUID: {$row->guid}");
127  }
128  }
129 
137  protected function initializeAttributes() {
138  parent::initializeAttributes();
139 
140  $this->attributes['guid'] = null;
141  $this->attributes['type'] = null;
142  $this->attributes['subtype'] = null;
143 
144  $this->attributes['owner_guid'] = _elgg_services()->session_manager->getLoggedInUserGuid();
145  $this->attributes['container_guid'] = _elgg_services()->session_manager->getLoggedInUserGuid();
146 
147  $this->attributes['access_id'] = ACCESS_PRIVATE;
148  $this->attributes['time_updated'] = null;
149  $this->attributes['last_action'] = null;
150  $this->attributes['enabled'] = 'yes';
151  $this->attributes['deleted'] = 'no';
152  $this->attributes['time_deleted'] = null;
153  }
154 
165  public function __clone() {
166  $orig_entity = get_entity($this->guid);
167  if (!$orig_entity) {
168  _elgg_services()->logger->error("Failed to clone entity with GUID $this->guid");
169  return;
170  }
171 
172  $metadata_array = elgg_get_metadata([
173  'guid' => $this->guid,
174  'limit' => false,
175  ]);
176 
177  $this->attributes['guid'] = null;
178  $this->attributes['time_created'] = null;
179  $this->attributes['time_updated'] = null;
180  $this->attributes['last_action'] = null;
181 
182  $this->attributes['subtype'] = $orig_entity->getSubtype();
183 
184  // copy metadata over to new entity - slightly convoluted due to
185  // handling of metadata arrays
186  if (is_array($metadata_array)) {
187  // create list of metadata names
188  $metadata_names = [];
189  foreach ($metadata_array as $metadata) {
190  $metadata_names[] = $metadata->name;
191  }
192 
193  // arrays are stored with multiple entries per name
194  $metadata_names = array_unique($metadata_names);
195 
196  // move the metadata over
197  foreach ($metadata_names as $name) {
198  $this->__set($name, $orig_entity->$name);
199  }
200  }
201  }
202 
218  public function __set($name, $value) {
219  if ($this->$name === $value) {
220  // quick return if value is not changing
221  return;
222  }
223 
224  if (array_key_exists($name, $this->attributes)) {
225  // if an attribute is 1 (integer) and it's set to "1" (string), don't consider that a change.
226  if (is_int($this->attributes[$name])
227  && is_string($value)
228  && ((string) $this->attributes[$name] === $value)) {
229  return;
230  }
231 
232  // keep original values
233  if ($this->guid && !array_key_exists($name, $this->orig_attributes)) {
234  $this->orig_attributes[$name] = $this->attributes[$name];
235  }
236 
237  // Certain properties should not be manually changed!
238  switch ($name) {
239  case 'guid':
240  case 'last_action':
241  case 'time_deleted':
242  case 'time_updated':
243  case 'type':
244  return;
245  case 'subtype':
246  throw new ElggInvalidArgumentException(elgg_echo('ElggEntity:Error:SetSubtype', ['setSubtype()']));
247  case 'enabled':
248  throw new ElggInvalidArgumentException(elgg_echo('ElggEntity:Error:SetEnabled', ['enable() / disable()']));
249  case 'deleted':
250  throw new ElggInvalidArgumentException(elgg_echo('ElggEntity:Error:SetDeleted', ['delete() / restore()']));
251  case 'access_id':
252  case 'owner_guid':
253  case 'container_guid':
254  if ($value !== null) {
255  $this->attributes[$name] = (int) $value;
256  } else {
257  $this->attributes[$name] = null;
258  }
259  break;
260  default:
261  $this->attributes[$name] = $value;
262  break;
263  }
264 
265  return;
266  }
267 
268  $this->setMetadata($name, $value);
269  }
270 
276  public function getOriginalAttributes(): array {
277  return $this->orig_attributes;
278  }
279 
293  public function __get($name) {
294  if (array_key_exists($name, $this->attributes)) {
295  return $this->attributes[$name];
296  }
297 
298  return $this->getMetadata($name);
299  }
300 
306  public function getDisplayName(): string {
307  return (string) $this->name;
308  }
309 
317  public function setDisplayName(string $display_name): void {
318  $this->name = $display_name;
319  }
320 
328  public function getVolatileData(string $name) {
329  return array_key_exists($name, $this->volatile) ? $this->volatile[$name] : null;
330  }
331 
340  public function setVolatileData(string $name, $value): void {
341  $this->volatile[$name] = $value;
342  }
343 
349  public function removeAllRelatedRiverItems(): void {
350  elgg_delete_river(['subject_guid' => $this->guid, 'limit' => false]);
351  elgg_delete_river(['object_guid' => $this->guid, 'limit' => false]);
352  elgg_delete_river(['target_guid' => $this->guid, 'limit' => false]);
353  }
354 
361  public function countComments(): int {
362  if (!$this->hasCapability('commentable')) {
363  return 0;
364  }
365 
366  $params = ['entity' => $this];
367  $num = _elgg_services()->events->triggerResults('comments:count', $this->getType(), $params);
368 
369  if (is_int($num)) {
370  return $num;
371  }
372 
373  return \Elgg\Comments\DataService::instance()->getCommentsCount($this);
374  }
375 
384  public function hasAccess(int $user_guid = 0): bool {
385  return _elgg_services()->accessCollections->hasAccessToEntity($this, $user_guid);
386  }
387 
397  public function canEdit(int $user_guid = 0): bool {
398  return _elgg_services()->userCapabilities->canEdit($this, $user_guid);
399  }
400 
411  public function canDelete(int $user_guid = 0): bool {
412  return _elgg_services()->userCapabilities->canDelete($this, $user_guid);
413  }
414 
425  public function canWriteToContainer(int $user_guid = 0, string $type = '', string $subtype = ''): bool {
426  if (empty($type) || empty($subtype)) {
427  throw new ElggInvalidArgumentException(__METHOD__ . ' requires $type and $subtype to be set');
428  }
429 
430  return _elgg_services()->userCapabilities->canWriteToContainer($this, $type, $subtype, $user_guid);
431  }
432 
442  public function canComment(int $user_guid = 0): bool {
443  return _elgg_services()->userCapabilities->canComment($this, $user_guid);
444  }
445 
460  public function canAnnotate(int $user_guid = 0, string $annotation_name = ''): bool {
461  return _elgg_services()->userCapabilities->canAnnotate($this, $user_guid, $annotation_name);
462  }
463 
469  public function getGUID(): ?int {
470  return $this->guid;
471  }
472 
478  public function getType(): string {
479  return (string) $this->attributes['type'];
480  }
481 
490  public function setSubtype(string $subtype): void {
491  // keep original values
492  if ($this->guid && !array_key_exists('subtype', $this->orig_attributes)) {
493  $this->orig_attributes['subtype'] = $this->attributes['subtype'];
494  }
495 
496  $this->attributes['subtype'] = $subtype;
497  }
498 
504  public function getSubtype(): string {
505  return (string) $this->attributes['subtype'];
506  }
507 
513  public function getOwnerGUID(): int {
514  return (int) $this->owner_guid;
515  }
516 
522  public function getOwnerEntity(): ?\ElggEntity {
523  return $this->owner_guid ? get_entity($this->owner_guid) : null;
524  }
525 
533  public function setContainerGUID(int $container_guid): void {
535  }
536 
542  public function getContainerGUID(): int {
543  return (int) $this->container_guid;
544  }
545 
552  public function getContainerEntity(): ?\ElggEntity {
553  return $this->container_guid ? get_entity($this->getContainerGUID()) : null;
554  }
555 
561  public function getTimeUpdated(): int {
562  return (int) $this->time_updated;
563  }
564 
573  public function getURL(): string {
574  $url = elgg_generate_entity_url($this, 'view');
575 
576  $url = _elgg_services()->events->triggerResults('entity:url', "{$this->getType()}:{$this->getSubtype()}", ['entity' => $this], $url);
577  $url = _elgg_services()->events->triggerResults('entity:url', $this->getType(), ['entity' => $this], $url);
578  if (empty($url)) {
579  return '';
580  }
581 
582  return elgg_normalize_url($url);
583  }
584 
588  public function save(): bool {
589  if ($this->guid > 0) {
590  $result = $this->update();
591  } else {
592  $result = $this->create() !== false;
593  }
594 
595  if ($result) {
596  $this->cache();
597  }
598 
599  return $result;
600  }
601 
614  protected function create() {
615 
616  $type = $this->attributes['type'];
617  if (!in_array($type, \Elgg\Config::ENTITY_TYPES)) {
618  throw new ElggDomainException('Entity type must be one of the allowed types: ' . implode(', ', \Elgg\Config::ENTITY_TYPES));
619  }
620 
621  $subtype = $this->attributes['subtype'];
622  if (!$subtype) {
623  throw new ElggInvalidArgumentException('All entities must have a subtype');
624  }
625 
626  $owner_guid = (int) $this->attributes['owner_guid'];
627  $access_id = (int) $this->attributes['access_id'];
628  $now = $this->getCurrentTime()->getTimestamp();
629  $time_created = isset($this->attributes['time_created']) ? (int) $this->attributes['time_created'] : $now;
630  $deleted = $this->attributes['deleted'];
631  $time_deleted = (int) $this->attributes['time_deleted'];
632 
633  $container_guid = $this->attributes['container_guid'];
634  if ($container_guid == 0) {
636  $this->attributes['container_guid'] = $container_guid;
637  }
638 
640 
641  if ($access_id === ACCESS_DEFAULT) {
642  throw new ElggInvalidArgumentException('ACCESS_DEFAULT is not a valid access level. See its documentation in constants.php');
643  }
644 
645  if ($access_id === ACCESS_FRIENDS) {
646  throw new ElggInvalidArgumentException('ACCESS_FRIENDS is not a valid access level. See its documentation in constants.php');
647  }
648 
649  $user_guid = _elgg_services()->session_manager->getLoggedInUserGuid();
650 
651  // If given an owner, verify it can be loaded
652  if (!empty($owner_guid)) {
653  $owner = $this->getOwnerEntity();
654  if (!$owner instanceof \ElggEntity) {
655  $error = "User {$user_guid} tried to create a ({$type}, {$subtype}),";
656  $error .= " but the given owner {$owner_guid} could not be loaded.";
658  }
659 
660  // If different owner than logged in, verify can write to container.
661  if ($user_guid !== $owner_guid && !$owner->canEdit() && !$owner->canWriteToContainer($user_guid, $type, $subtype)) {
662  $error = "User {$user_guid} tried to create a ({$type}, {$subtype}) with owner {$owner_guid},";
663  $error .= " but the user wasn't permitted to write to the owner's container.";
665  }
666  }
667 
668  // If given a container, verify it can be loaded and that the current user can write to it
669  if (!empty($container_guid)) {
670  $container = $this->getContainerEntity();
671  if (!$container instanceof \ElggEntity) {
672  $error = "User {$user_guid} tried to create a ({$type}, {$subtype}),";
673  $error .= " but the given container {$container_guid} could not be loaded.";
675  }
676 
677  if (!$container->canWriteToContainer($user_guid, $type, $subtype)) {
678  $error = "User {$user_guid} tried to create a ({$type}, {$subtype}),";
679  $error .= " but was not permitted to write to container {$container_guid}.";
681  }
682  }
683 
684  if (!_elgg_services()->events->triggerBefore('create', $this->type, $this)) {
685  return false;
686  }
687 
688  // Create primary table row
689  $guid = _elgg_services()->entityTable->insertRow((object) [
690  'type' => $type,
691  'subtype' => $subtype,
692  'owner_guid' => $owner_guid,
693  'container_guid' => $container_guid,
694  'access_id' => $access_id,
695  'time_created' => $time_created,
696  'time_updated' => $now,
697  'last_action' => $now,
698  'deleted' => $deleted,
699  'time_deleted' => $time_deleted
700  ], $this->attributes);
701 
702  if (!$guid) {
703  throw new IOException("Unable to save new object's base entity information!");
704  }
705 
706  $this->attributes['subtype'] = $subtype;
707  $this->attributes['guid'] = (int) $guid;
708  $this->attributes['time_created'] = (int) $time_created;
709  $this->attributes['time_updated'] = (int) $now;
710  $this->attributes['last_action'] = (int) $now;
711  $this->attributes['container_guid'] = (int) $container_guid;
712  $this->attributes['deleted'] = $deleted;
713  $this->attributes['time_deleted'] = (int) $time_deleted;
714 
715  // We are writing this new entity to cache to make sure subsequent calls
716  // to get_entity() load the entity from cache and not from the DB. This
717  // MUST come before the metadata and annotation writes below!
718  $this->cache();
719 
720  // Save any unsaved metadata
721  if (count($this->temp_metadata) > 0) {
722  foreach ($this->temp_metadata as $name => $value) {
723  // temp metadata is always an array, but if there is only one value return just the value
724  $this->setMetadata($name, $value, '', count($value) > 1);
725  }
726 
727  $this->temp_metadata = [];
728  }
729 
730  // Save any unsaved annotations.
731  if (count($this->temp_annotations) > 0) {
732  foreach ($this->temp_annotations as $name => $value) {
733  $this->annotate($name, $value);
734  }
735 
736  $this->temp_annotations = [];
737  }
738 
739  if (isset($container) && !$container instanceof \ElggUser) {
740  // users have their own logic for setting last action
741  $container->updateLastAction();
742  }
743 
744  // for BC reasons this event is still needed (for example for notifications)
745  _elgg_services()->events->trigger('create', $this->type, $this);
746 
747  _elgg_services()->events->triggerAfter('create', $this->type, $this);
748 
749  return $guid;
750  }
751 
759  protected function update(): bool {
760 
761  if (!$this->canEdit()) {
762  return false;
763  }
764 
765  // give old update event a chance to stop the update
766  if (!_elgg_services()->events->trigger('update', $this->type, $this)) {
767  return false;
768  }
769 
770  $this->invalidateCache();
771 
772  // See #6225. We copy these after the update event in case a handler changed one of them.
773  $guid = (int) $this->guid;
774  $owner_guid = (int) $this->owner_guid;
775  $access_id = (int) $this->access_id;
776  $container_guid = (int) $this->container_guid;
777  $time_created = (int) $this->time_created;
778  $time = $this->getCurrentTime()->getTimestamp();
780  $time_deleted = (int) $this->time_deleted;
781 
782  if ($access_id == ACCESS_DEFAULT) {
783  throw new ElggInvalidArgumentException('ACCESS_DEFAULT is not a valid access level. See its documentation in constants.php');
784  }
785 
786  if ($access_id == ACCESS_FRIENDS) {
787  throw new ElggInvalidArgumentException('ACCESS_FRIENDS is not a valid access level. See its documentation in constants.php');
788  }
789 
790  // Update primary table
791  $ret = _elgg_services()->entityTable->updateRow($guid, (object) [
792  'owner_guid' => $owner_guid,
793  'container_guid' => $container_guid,
794  'access_id' => $access_id,
795  'time_created' => $time_created,
796  'time_updated' => $time,
797  'guid' => $guid,
798  'deleted' => $deleted,
799  'time_deleted' => $time_deleted
800  ]);
801  if ($ret === false) {
802  return false;
803  }
804 
805  $this->attributes['time_updated'] = $time;
806 
807  _elgg_services()->events->triggerAfter('update', $this->type, $this);
808 
809  $this->orig_attributes = [];
810 
811  $this->cache();
812 
813  // Handle cases where there was no error BUT no rows were updated!
814  return true;
815  }
816 
824  protected function load(stdClass $row): bool {
825  $attributes = array_merge($this->attributes, (array) $row);
826 
827  if (array_diff(self::PRIMARY_ATTR_NAMES, array_keys($attributes)) !== []) {
828  // Some primary attributes are missing
829  return false;
830  }
831 
832  foreach ($attributes as $name => $value) {
833  if (!in_array($name, self::PRIMARY_ATTR_NAMES)) {
834  $this->setVolatileData("select:{$name}", $value);
835  unset($attributes[$name]);
836  continue;
837  }
838 
839  if (in_array($name, static::INTEGER_ATTR_NAMES)) {
840  $attributes[$name] = (int) $value;
841  }
842  }
843 
844  $this->attributes = $attributes;
845 
846  $this->cache();
847 
848  return true;
849  }
850 
868  public function disable(string $reason = '', bool $recursive = true): bool {
869  if (!$this->guid) {
870  return false;
871  }
872 
873  if (!_elgg_services()->events->trigger('disable', $this->type, $this)) {
874  return false;
875  }
876 
877  if (!$this->canEdit()) {
878  return false;
879  }
880 
881  if ($this instanceof ElggUser && !$this->isBanned()) {
882  // temporarily ban to prevent using the site during disable
883  // not using ban function to bypass events
884  $this->setMetadata('banned', 'yes');
885  $unban_after = true;
886  } else {
887  $unban_after = false;
888  }
889 
890  if (!empty($reason)) {
891  $this->disable_reason = $reason;
892  }
893 
894  $guid = (int) $this->guid;
895 
896  if ($recursive) {
898  $base_options = [
899  'wheres' => [
900  function(QueryBuilder $qb, $main_alias) use ($guid) {
901  return $qb->compare("{$main_alias}.guid", '!=', $guid, ELGG_VALUE_GUID);
902  },
903  ],
904  'limit' => false,
905  'batch' => true,
906  'batch_inc_offset' => false,
907  ];
908 
909  foreach (['owner_guid', 'container_guid'] as $db_column) {
910  $options = $base_options;
911  $options[$db_column] = $guid;
912 
913  $subentities = elgg_get_entities($options);
914  /* @var $subentity \ElggEntity */
915  foreach ($subentities as $subentity) {
916  if (!$subentity->isEnabled()) {
917  continue;
918  }
919 
920  $subentity->addRelationship($guid, 'disabled_with');
921  $subentity->disable($reason, true);
922  }
923  }
924  });
925  }
926 
927  $disabled = _elgg_services()->entityTable->disable($this);
928 
929  if ($unban_after) {
930  $this->setMetadata('banned', 'no');
931  }
932 
933  if ($disabled) {
934  $this->invalidateCache();
935 
936  $this->attributes['enabled'] = 'no';
937  _elgg_services()->events->triggerAfter('disable', $this->type, $this);
938  }
939 
940  return $disabled;
941  }
942 
950  public function enable(bool $recursive = true): bool {
951  if (empty($this->guid)) {
952  return false;
953  }
954 
955  if (!_elgg_services()->events->trigger('enable', $this->type, $this)) {
956  return false;
957  }
958 
959  if (!$this->canEdit()) {
960  return false;
961  }
962 
964  $result = _elgg_services()->entityTable->enable($this);
965 
966  $this->deleteMetadata('disable_reason');
967 
968  if ($recursive) {
969  $disabled_with_it = elgg_get_entities([
970  'relationship' => 'disabled_with',
971  'relationship_guid' => $this->guid,
972  'inverse_relationship' => true,
973  'limit' => false,
974  'batch' => true,
975  'batch_inc_offset' => false,
976  ]);
977 
978  foreach ($disabled_with_it as $e) {
979  $e->enable($recursive);
980  $e->removeRelationship($this->guid, 'disabled_with');
981  }
982  }
983 
984  return $result;
985  });
986 
987  if ($result) {
988  $this->attributes['enabled'] = 'yes';
989  _elgg_services()->events->triggerAfter('enable', $this->type, $this);
990  }
991 
992  return $result;
993  }
994 
1000  public function isEnabled(): bool {
1001  return $this->enabled == 'yes';
1002  }
1003 
1021  public function delete(bool $recursive = true, bool $persistent = null): bool {
1022  if (!$this->canDelete()) {
1023  return false;
1024  }
1025 
1026  if (!elgg_get_config('trash_enabled')) {
1027  $persistent = true;
1028  }
1029 
1030  if (!isset($persistent)) {
1031  $persistent = !$this->hasCapability('restorable');
1032  }
1033 
1034  try {
1035  if (empty($this->guid) || $persistent) {
1036  return $this->persistentDelete($recursive);
1037  } else {
1038  return $this->trash($recursive);
1039  }
1040  } catch (DatabaseException $ex) {
1041  elgg_log($ex, \Psr\Log\LogLevel::ERROR);
1042  return false;
1043  }
1044  }
1045 
1054  protected function persistentDelete(bool $recursive = true): bool {
1055  return _elgg_services()->entityTable->delete($this, $recursive);
1056  }
1057 
1066  protected function trash(bool $recursive = true): bool {
1067  $result = _elgg_services()->entityTable->trash($this, $recursive);
1068  if ($result) {
1069  $this->attributes['deleted'] = 'yes';
1070  }
1071 
1072  return $result;
1073  }
1074 
1083  public function restore(bool $recursive = true): bool {
1084  if (!$this->isDeleted()) {
1085  return true;
1086  }
1087 
1088  if (empty($this->guid) || !$this->canEdit()) {
1089  return false;
1090  }
1091 
1092  return _elgg_services()->events->triggerSequence('restore', $this->type, $this, function () use ($recursive) {
1094  if (!_elgg_services()->entityTable->restore($this)) {
1095  return false;
1096  }
1097 
1098  $this->attributes['deleted'] = 'no';
1099  $this->attributes['time_deleted'] = 0;
1100 
1101  $this->removeAllRelationships('deleted_by');
1102  $this->removeAllRelationships('deleted_with');
1103 
1104  if (!$recursive) {
1105  return true;
1106  }
1107 
1108  set_time_limit(0);
1109 
1110  /* @var $deleted_with_it \ElggBatch */
1111  $deleted_with_it = elgg_get_entities([
1112  'relationship' => 'deleted_with',
1113  'relationship_guid' => $this->guid,
1114  'inverse_relationship' => true,
1115  'limit' => false,
1116  'batch' => true,
1117  'batch_inc_offset' => false,
1118  ]);
1119 
1120  /* @var $e \ElggEntity */
1121  foreach ($deleted_with_it as $e) {
1122  if (!$e->restore($recursive)) {
1123  $deleted_with_it->reportFailure();
1124  continue;
1125  }
1126  }
1127 
1128  return true;
1129  });
1130  });
1131  }
1132 
1138  public function isDeleted(): bool {
1139  return $this->deleted === 'yes';
1140  }
1141 
1149  public function toObject(array $params = []) {
1150  $object = $this->prepareObject(new \Elgg\Export\Entity());
1151 
1152  $params['entity'] = $this;
1153 
1154  return _elgg_services()->events->triggerResults('to:object', 'entity', $params, $object);
1155  }
1156 
1164  protected function prepareObject(\Elgg\Export\Entity $object) {
1165  $object->guid = $this->guid;
1166  $object->type = $this->getType();
1167  $object->subtype = $this->getSubtype();
1168  $object->owner_guid = $this->getOwnerGUID();
1169  $object->container_guid = $this->getContainerGUID();
1170  $object->time_created = date('c', $this->getTimeCreated());
1171  $object->time_updated = date('c', $this->getTimeUpdated());
1172  $object->url = $this->getURL();
1173  $object->read_access = (int) $this->access_id;
1174  return $object;
1175  }
1176 
1185  public function setLatLong(float $lat, float $long): void {
1186  $this->{'geo:lat'} = $lat;
1187  $this->{'geo:long'} = $long;
1188  }
1189 
1195  public function getLatitude(): float {
1196  return (float) $this->{'geo:lat'};
1197  }
1198 
1204  public function getLongitude(): float {
1205  return (float) $this->{'geo:long'};
1206  }
1207 
1208  /*
1209  * SYSTEM LOG INTERFACE
1210  */
1211 
1215  public function getSystemLogID(): int {
1216  return (int) $this->getGUID();
1217  }
1218 
1227  public function getObjectFromID(int $id): ?\ElggEntity {
1228  return get_entity($id);
1229  }
1230 
1242  public function updateLastAction(int $posted = null): int {
1243  $posted = _elgg_services()->entityTable->updateLastAction($this, $posted);
1244 
1245  $this->attributes['last_action'] = $posted;
1246  $this->cache();
1247 
1248  return $posted;
1249  }
1250 
1259  public function updateTimeDeleted(int $deleted = null): int {
1260  $deleted = _elgg_services()->entityTable->updateTimeDeleted($this, $deleted);
1261 
1262  $this->attributes['time_deleted'] = $deleted;
1263  $this->cache();
1264 
1265  return $deleted;
1266  }
1267 
1274  public function disableCaching(): void {
1275  $this->_is_cacheable = false;
1276  if ($this->guid) {
1277  _elgg_services()->entityCache->delete($this->guid);
1278  }
1279  }
1280 
1287  public function enableCaching(): void {
1288  $this->_is_cacheable = true;
1289  }
1290 
1297  public function isCacheable(): bool {
1298  if (!$this->guid) {
1299  return false;
1300  }
1301 
1302  if (_elgg_services()->session_manager->getIgnoreAccess()) {
1303  return false;
1304  }
1305 
1306  return $this->_is_cacheable;
1307  }
1308 
1315  public function cache(): void {
1316  if (!$this->isCacheable()) {
1317  return;
1318  }
1319 
1320  _elgg_services()->entityCache->save($this->guid, $this);
1321  }
1322 
1329  public function invalidateCache(): void {
1330  if (!$this->guid) {
1331  return;
1332  }
1333 
1334  _elgg_services()->entityCache->delete($this->guid);
1335  _elgg_services()->metadataCache->delete($this->guid);
1336  }
1337 
1346  public function hasCapability(string $capability): bool {
1347  return _elgg_services()->entity_capabilities->hasCapability($this->getType(), $this->getSubtype(), $capability);
1348  }
1349 }
elgg_call(int $flags, Closure $closure)
Calls a callable autowiring the arguments using public DI services and applying logic based on flags...
Definition: elgglib.php:304
getSubtype()
Get the entity subtype.
Definition: ElggEntity.php:504
$user_guid
Definition: login_as.php:10
$deleted
Definition: delete.php:25
getOwnerGUID()
Get the guid of the entity&#39;s owner.
Definition: ElggEntity.php:513
getTimeCreated()
Returns the UNIX epoch time that this entity was created.
Definition: ElggData.php:99
__clone()
Clone an entity.
Definition: ElggEntity.php:165
$params
Saves global plugin settings.
Definition: save.php:13
setVolatileData(string $name, $value)
Set a piece of volatile (non-persisted) data on this entity.
Definition: ElggEntity.php:340
__get($name)
Get an attribute or metadata value.
Definition: ElggEntity.php:293
elgg_get_config(string $name, $default=null)
Get an Elgg configuration value.
getOwnerEntity()
Gets the that owns this entity.
Definition: ElggEntity.php:522
persistentDelete(bool $recursive=true)
Permanently delete the entity from the database.
$owner
Definition: upload.php:7
const ACCESS_DEFAULT
Controls access levels on entities, metadata, and annotations.
Definition: constants.php:9
$posted
Definition: sidebar.php:21
An IO Exception, throw when an IO Exception occurs.
Definition: IOException.php:12
canWriteToContainer(int $user_guid=0, string $type= '', string $subtype= '')
Can a user add an entity to this container.
Definition: ElggEntity.php:425
const PRIMARY_ATTR_NAMES
Definition: ElggEntity.php:61
if(!$user||!$user->canDelete()) $name
Definition: delete.php:22
canDelete(int $user_guid=0)
Can a user delete this entity?
Definition: ElggEntity.php:411
const INTEGER_ATTR_NAMES
Definition: ElggEntity.php:79
invalidateCache()
Invalidate cache for entity.
canComment(int $user_guid=0)
Can a user comment on an entity?
Definition: ElggEntity.php:442
initializeAttributes()
Initialize the attributes array.
Definition: ElggEntity.php:137
const ACCESS_FRIENDS
Definition: constants.php:13
if(!$user instanceof\ElggUser) $time_created
Definition: online.php:13
countComments()
Count the number of comments attached to this entity.
Definition: ElggEntity.php:361
elgg_delete_river(array $options=[])
Delete river items based on $options.
Definition: river.php:135
getVolatileData(string $name)
Get a piece of volatile (non-persisted) data on this entity.
Definition: ElggEntity.php:328
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
Definition: LICENSE.txt:215
elgg_echo(string $message_key, array $args=[], string $language= '')
Elgg language module Functions to manage language and translations.
Definition: languages.php:17
enable(bool $recursive=true)
Enable the entity.
Definition: ElggEntity.php:950
if(!$annotation instanceof ElggAnnotation) $time
Definition: time.php:20
const ELGG_VALUE_GUID
Definition: constants.php:113
prepareObject(\Elgg\Export\Entity $object)
Prepare an object copy for toObject()
Database abstraction query builder.
getGUID()
Returns the guid.
Definition: ElggEntity.php:469
$time_updated
Definition: time.php:21
getContainerGUID()
Gets the container GUID for this entity.
Definition: ElggEntity.php:542
$type
Definition: delete.php:21
deleteMetadata(string $name=null)
Deletes all metadata on this object (metadata.entity_guid = $this->guid).
Definition: Metadata.php:198
getTimeUpdated()
Returns the UNIX epoch time that this entity was last updated.
Definition: ElggEntity.php:561
enableCaching()
Enable runtime caching for entity.
canAnnotate(int $user_guid=0, string $annotation_name= '')
Can a user annotate an entity?
Definition: ElggEntity.php:460
cache()
Cache the entity in a session cache.
canEdit(int $user_guid=0)
Can a user edit this entity?
Definition: ElggEntity.php:397
$value
Definition: generic.php:51
const ELGG_HIDE_DISABLED_ENTITIES
Definition: constants.php:124
getObjectFromID(int $id)
For a given ID, return the object associated with it.
getCurrentTime($modifier= '')
Get the (cloned) time.
Definition: TimeUsing.php:25
if($who_can_change_language=== 'nobody') elseif($who_can_change_language=== 'admin_only'&&!elgg_is_admin_logged_in()) $options
Definition: language.php:20
const ELGG_IGNORE_ACCESS
elgg_call() flags
Definition: constants.php:121
$owner_guid
$error
Bad request error.
Definition: 400.php:6
disableCaching()
Disable runtime caching for entity.
setSubtype(string $subtype)
Set the subtype of the entity.
Definition: ElggEntity.php:490
const ACCESS_PRIVATE
Definition: constants.php:10
const ELGG_SHOW_DISABLED_ENTITIES
Definition: constants.php:123
removeAllRelatedRiverItems()
Removes all river items related to this entity.
Definition: ElggEntity.php:349
get_entity(int $guid)
Loads and returns an entity object from a guid.
Definition: entities.php:70
elgg_get_entities(array $options=[])
Fetches/counts entities or performs a calculation on their properties.
Definition: entities.php:507
hasAccess(int $user_guid=0)
Check if the given user has access to this entity.
Definition: ElggEntity.php:384
load(stdClass $row)
Loads attributes from the entities table into the object.
Definition: ElggEntity.php:824
elgg_log($message, $level=\Psr\Log\LogLevel::NOTICE)
Log a message.
Definition: elgglib.php:86
compare(string $x, string $comparison, $y=null, string $type=null, bool $case_sensitive=null)
Build value comparison clause.
elgg_generate_entity_url(ElggEntity $entity, string $resource= 'view', string $subresource=null, array $parameters=[])
Generate entity URL from a named route.
A generic parent class for database exceptions.
__set($name, $value)
Set an attribute or metadata value for this entity.
Definition: ElggEntity.php:218
$container
Definition: delete.php:23
toObject(array $params=[])
Export an entity.
annotate($name, $value, $access_id=ACCESS_PRIVATE, $owner_guid=0, $value_type= '')
Adds an annotation to an entity.
trait Annotations
Bundle all annotations related functions for an .
Definition: Annotations.php:10
setMetadata(string $name, mixed $value, string $value_type= '', bool $multiple=false)
Set metadata on this entity.
Definition: Metadata.php:78
isDeleted()
Is the entity marked as deleted.
setLatLong(float $lat, float $long)
Set latitude and longitude metadata tags for a given entity.
hasCapability(string $capability)
Checks a specific capability is enabled for the entity type/subtype.
A generic class that contains shared code among , , and .
Definition: ElggData.php:10
isEnabled()
Is this entity enabled?
const ELGG_SHOW_DELETED_ENTITIES
Definition: constants.php:127
update()
Update the entity in the database.
Definition: ElggEntity.php:759
elgg_get_metadata(array $options=[])
Fetch metadata or perform a calculation on them.
Definition: metadata.php:32
if($entity instanceof\ElggComment) $comment container_guid
Definition: save.php:54
$comment access_id
Definition: save.php:55
if($email instanceof\Elgg\Email) $object
Definition: body.php:24
trash(bool $recursive=true)
Move the entity to the trash.
$metadata
Output annotation metadata.
Definition: metadata.php:9
getType()
Returns the entity type.
Definition: ElggEntity.php:478
$subtype
Definition: delete.php:22
updateTimeDeleted(int $deleted=null)
Update the time_deleted column in the entities table.
foreach($plugin_guids as $guid) if(empty($deactivated_plugins)) $url
Definition: deactivate.php:39
$access_id
Definition: access.php:10
create()
Create a new entry in the entities table.
Definition: ElggEntity.php:614
setContainerGUID(int $container_guid)
Set the container for this object.
Definition: ElggEntity.php:533
_elgg_services()
Get the global service provider.
Definition: elgglib.php:351
$persistent
Definition: login_as.php:21
getOriginalAttributes()
Get the original values of attribute(s) that have been modified since the entity was persisted...
Definition: ElggEntity.php:276
restore(bool $recursive=true)
Restore the entity.
getMetadata(string $name)
Return the value of a piece of metadata.
Definition: Metadata.php:27
isCacheable()
Is entity cacheable in the runtime cache.
getLatitude()
Return the entity&#39;s latitude.
if(!$new_container instanceof\ElggEntity) if(!$new_container->canWriteToContainer(0, $entity->type, $entity->subtype)) $display_name
__construct(stdClass $row=null)
Create a new entity.
Definition: ElggEntity.php:122
$container_guid
getContainerEntity()
Get the container entity for this object.
Definition: ElggEntity.php:552
elgg_normalize_url(string $url)
Definition: output.php:163
disable(string $reason= '', bool $recursive=true)
Disable this entity.
Definition: ElggEntity.php:868
$site name
Definition: settings.php:15
updateLastAction(int $posted=null)
Update the last_action column in the entities table.
getSystemLogID()
{}
$id
Generic annotation delete action.
Definition: delete.php:6
$qb
Definition: queue.php:12
getURL()
Gets the URL for this entity.
Definition: ElggEntity.php:573
setDisplayName(string $display_name)
Sets the title or name of this entity.
Definition: ElggEntity.php:317
getDisplayName()
Get the entity&#39;s display name.
Definition: ElggEntity.php:306
$guid
Reset an ElggUpgrade.
Definition: reset.php:6
getLongitude()
Return the entity&#39;s longitude.
trait Metadata
Bundle all metadata related functions for an .
Definition: Metadata.php:10