Passed
Push — master ( c0a3a7...3b84a4 )
by Jeroen
58:51
created

EntityTable::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 8
dl 0
loc 19
ccs 10
cts 10
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Elgg\Database;
4
5
use ClassException;
6
use DatabaseException;
7
use Elgg\Cache\EntityCache;
8
use Elgg\Cache\MetadataCache;
9
use Elgg\Config;
10
use Elgg\Database;
11
use Elgg\Database\Clauses\EntityWhereClause;
12
use Elgg\Database\Clauses\OrderByClause;
13
use Elgg\Database\EntityTable\UserFetchFailureException;
14
use Elgg\EntityPreloader;
15
use Elgg\EventsService;
16
use Elgg\I18n\Translator;
17
use Elgg\Logger;
18
use ElggBatch;
19
use ElggEntity;
20
use ElggGroup;
21
use ElggObject;
22
use ElggSession;
23
use ElggSite;
24
use ElggUser;
25
use InvalidParameterException;
26
use stdClass;
27
28
/**
29
 * WARNING: API IN FLUX. DO NOT USE DIRECTLY.
30
 *
31
 * @access     private
32
 *
33
 * @package    Elgg.Core
34
 * @subpackage Database
35
 * @since      1.10.0
36
 */
37
class EntityTable {
38
39
	use \Elgg\TimeUsing;
40
41
	/**
42
	 * @var Config
43
	 */
44
	protected $config;
45
46
	/**
47
	 * @var Database
48
	 */
49
	protected $db;
50
51
	/**
52
	 * @var string
53
	 */
54
	protected $table;
55
56
	/**
57
	 * @var array
58
	 */
59
	protected $entity_classes;
60
61
	/**
62
	 * @var EntityCache
63
	 */
64
	protected $entity_cache;
65
66
	/**
67
	 * @var EntityPreloader
68
	 */
69
	protected $entity_preloader;
70
71
	/**
72
	 * @var MetadataCache
73
	 */
74
	protected $metadata_cache;
75
76
	/**
77
	 * @var EventsService
78
	 */
79
	protected $events;
80
81
	/**
82
	 * @var ElggSession
83
	 */
84
	protected $session;
85
86
	/**
87
	 * @var Translator
88
	 */
89
	protected $translator;
90
91
	/**
92
	 * @var Logger
93
	 */
94
	protected $logger;
95
96
	/**
97
	 * Constructor
98
	 *
99
	 * @param Config        $config         Config
100
	 * @param Database      $db             Database
101
	 * @param EntityCache   $entity_cache   Entity cache
102
	 * @param MetadataCache $metadata_cache Metadata cache
103
	 * @param EventsService $events         Events service
104
	 * @param ElggSession   $session        Session
105
	 * @param Translator    $translator     Translator
106
	 * @param Logger        $logger         Logger
107
	 */
108 4417
	public function __construct(
109
		Config $config,
110
		Database $db,
111
		EntityCache $entity_cache,
112
		MetadataCache $metadata_cache,
113
		EventsService $events,
114
		ElggSession $session,
115
		Translator $translator,
116
		Logger $logger
117
	) {
118 4417
		$this->config = $config;
119 4417
		$this->db = $db;
120 4417
		$this->table = $this->db->prefix . 'entities';
121 4417
		$this->entity_cache = $entity_cache;
122 4417
		$this->metadata_cache = $metadata_cache;
123 4417
		$this->events = $events;
124 4417
		$this->session = $session;
125 4417
		$this->translator = $translator;
126 4417
		$this->logger = $logger;
127 4417
	}
128
129
	/**
130
	 * Sets class constructor name for entities with given type and subtype
131
	 *
132
	 * @param string $type    Entity type
133
	 * @param string $subtype Entity subtype
134
	 * @param string $class   Entity class
135
	 *
136
	 * @return void
137
	 * @throws InvalidParameterException
138
	 */
139 4791
	public function setEntityClass($type, $subtype, $class = '') {
140 4791
		if (!in_array($type, Config::getEntityTypes())) {
141
			throw new InvalidParameterException("$type is not a valid entity type");
142
		}
143
144 4791
		$this->entity_classes[$type][$subtype] = $class;
145 4791
	}
146
147
	/**
148
	 * Returns class name registered as a constructor for a given type and subtype
149
	 *
150
	 * @param string $type    Entity type
151
	 * @param string $subtype Entity subtype
152
	 *
153
	 * @return string
154
	 */
155 5313
	public function getEntityClass($type, $subtype) {
156 5313
		if (isset($this->entity_classes[$type][$subtype])) {
157 5137
			return $this->entity_classes[$type][$subtype];
158
		}
159
160 770
		return '';
161
	}
162
163
	/**
164
	 * Returns a database row from the entities table.
165
	 *
166
	 * @see     entity_row_to_elggstar()
167
	 *
168
	 * @tip     Use get_entity() to return the fully loaded entity.
169
	 *
170
	 * @warning This will only return results if a) it exists, b) you have access to it.
171
	 * see {@link _elgg_get_access_where_sql()}.
172
	 *
173
	 * @param int $guid      The GUID of the object to extract
174
	 * @param int $user_guid GUID of the user accessing the row
175
	 *                       Defaults to logged in user if null
176
	 *                       Builds an access query for a logged out user if 0
177
	 *
178
	 * @return stdClass|false
179
	 * @access  private
180
	 */
181 523
	public function getRow($guid, $user_guid = null) {
182
183 523
		if (!$guid) {
184
			return false;
185
		}
186
187 523
		$where = new EntityWhereClause();
188 523
		$where->guids = (int) $guid;
189 523
		$where->viewer_guid = $user_guid;
190
191 523
		$select = Select::fromTable('entities');
192 523
		$select->select('*');
193 523
		$select->addClause($where);
194
195 523
		return $this->db->getDataRow($select);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->db->getDataRow($select) returns the type array which is incompatible with the documented return type stdClass|false.
Loading history...
196
	}
197
198
	/**
199
	 * Adds a new row to the entity table
200
	 *
201
	 * @param stdClass $row        Entity base information
202
	 * @param array    $attributes All primary table attributes
203
	 *                             Used by database mock services to allow mocking
204
	 *                             entities that were instantiated using new keyword
205
	 *                             and calling ElggEntity::save()
206
	 *
207
	 * @return int|false
208
	 */
209 509
	public function insertRow(stdClass $row, array $attributes = []) {
210
211
		$sql = "
212 509
			INSERT INTO {$this->db->prefix}entities
213
			(type, subtype, owner_guid, container_guid, access_id, time_created, time_updated, last_action)
214
			VALUES
215
			(:type, :subtype, :owner_guid, :container_guid, :access_id, :time_created, :time_updated, :last_action)
216
		";
217
218 509
		return $this->db->insertData($sql, [
219 509
			':type' => $row->type,
220 509
			':subtype' => $row->subtype,
221 509
			':owner_guid' => $row->owner_guid,
222 509
			':container_guid' => $row->container_guid,
223 509
			':access_id' => $row->access_id,
224 509
			':time_created' => $row->time_created,
225 509
			':time_updated' => $row->time_updated,
226 509
			':last_action' => $row->last_action,
227
		]);
228
	}
229
230
	/**
231
	 * Update entity table row
232
	 *
233
	 * @param int      $guid Entity guid
234
	 * @param stdClass $row  Updated data
235
	 *
236
	 * @return int|false
237
	 */
238 172
	public function updateRow($guid, stdClass $row) {
239
		$sql = "
240 172
			UPDATE {$this->db->prefix}entities
241
			SET owner_guid = :owner_guid,
242
			    access_id = :access_id,
243
				container_guid = :container_guid,
244
				time_created = :time_created,
245
				time_updated = :time_updated
246
			WHERE guid = :guid
247
		";
248
249
		$params = [
250 172
			':owner_guid' => $row->owner_guid,
251 172
			':access_id' => $row->access_id,
252 172
			':container_guid' => $row->container_guid,
253 172
			':time_created' => $row->time_created,
254 172
			':time_updated' => $row->time_updated,
255 172
			':guid' => $guid,
256
		];
257
258 172
		return $this->db->updateData($sql, false, $params);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->db->update...a($sql, false, $params) returns the type true which is incompatible with the documented return type integer|false.
Loading history...
259
	}
260
261
	/**
262
	 * Create an Elgg* object from a given entity row.
263
	 *
264
	 * Handles loading all tables into the correct class.
265
	 *
266
	 * @see    get_entity_as_row()
267
	 * @see    get_entity()
268
	 *
269
	 * @access private
270
	 *
271
	 * @param stdClass $row The row of the entry in the entities table.
272
	 *
273
	 * @return ElggEntity|false
274
	 * @throws ClassException
275
	 * @throws InvalidParameterException
276
	 */
277 5313
	public function rowToElggStar(stdClass $row) {
278 5313
		if (!isset($row->guid) || !isset($row->subtype)) {
279
			return false;
280
		}
281
282 5313
		$class_name = $this->getEntityClass($row->type, $row->subtype);
283 5313
		if ($class_name && !class_exists($class_name)) {
284
			$this->logger->error("Class '$class_name' was not found, missing plugin?");
285
			$class_name = '';
286
		}
287
288 5313
		if (!$class_name) {
289
			$map = [
290 770
				'object' => ElggObject::class,
291
				'user' => ElggUser::class,
292
				'group' => ElggGroup::class,
293
				'site' => ElggSite::class,
294
			];
295
296 770
			if (isset($map[$row->type])) {
297 770
				$class_name = $map[$row->type];
298
			} else {
299
				throw new InvalidParameterException("Entity type {$row->type} is not supported.");
300
			}
301
		}
302
303 5313
		$entity = new $class_name($row);
304 5313
		if (!$entity instanceof ElggEntity) {
305
			throw new ClassException("$class_name must extend " . ElggEntity::class);
306
		}
307
308 5313
		return $entity;
309
	}
310
311
	/**
312
	 * Get an entity from the in-memory or memcache caches
313
	 *
314
	 * @param int $guid GUID
315
	 *
316
	 * @return \ElggEntity|false
317
	 */
318 5292
	public function getFromCache($guid) {
319 5292
		$entity = $this->entity_cache->load($guid);
320 5292
		if ($entity) {
321 499
			return $entity;
322
		}
323
324 5291
		$cache = _elgg_services()->dataCache->entities;
325 5291
		$entity = $cache->load($guid);
326 5291
		if (!$entity instanceof ElggEntity) {
327 5284
			return false;
328
		}
329
330
		// Validate accessibility if from cache
331 345
		if (!elgg_get_ignore_access() && !has_access_to_entity($entity)) {
332 1
			return false;
333
		}
334
335 344
		$entity->cache(false);
336
337 344
		return $entity;
338
	}
339
340
	/**
341
	 * Invalidate cache for entity
342
	 *
343
	 * @param int $guid GUID
344
	 * @return void
345
	 */
346 1065
	public function invalidateCache($guid) {
347 1065
		$ia = $this->session->setIgnoreAccess(true);
348 1065
		$ha = access_get_show_hidden_status();
349 1065
		access_show_hidden_entities(true);
350 1065
		$entity = $this->get($guid);
351 1065
		if ($entity) {
352 1065
			$entity->invalidateCache();
353
		}
354 1065
		access_show_hidden_entities($ha);
355 1065
		$this->session->setIgnoreAccess($ia);
356 1065
	}
357
358
	/**
359
	 * Loads and returns an entity object from a guid.
360
	 *
361
	 * @param int    $guid The GUID of the entity
362
	 * @param string $type The type of the entity. If given, even an existing entity with the given GUID
363
	 *                     will not be returned unless its type matches.
364
	 *
365
	 * @return ElggEntity|false The correct Elgg or custom object based upon entity type and subtype
366
	 * @throws ClassException
367
	 * @throws InvalidParameterException
368
	 */
369 5292
	public function get($guid, $type = '') {
370
		// We could also use: if (!(int) $guid) { return false },
371
		// but that evaluates to a false positive for $guid = true.
372
		// This is a bit slower, but more thorough.
373 5292
		if (!is_numeric($guid) || $guid === 0 || $guid === '0') {
374 70
			return false;
375
		}
376
377 5292
		$guid = (int) $guid;
378
379 5292
		$entity = $this->getFromCache($guid);
380 5292
		if ($entity && (!$type || elgg_instanceof($entity, $type))) {
381 802
			return $entity;
382
		}
383
384 5284
		$row = $this->getRow($guid);
385 5284
		if (!$row) {
386 42
			return false;
387
		}
388
389 5284
		if ($type && $row->type != $type) {
390 2
			return false;
391
		}
392
393 5284
		$entity = $row;
394
395 5284
		if ($entity instanceof \stdClass) {
396 5284
			$entity = $this->rowToElggStar($entity);
397
		}
398
399 5284
		$entity->cache();
400
401 5284
		return $entity;
402
	}
403
404
	/**
405
	 * Does an entity exist?
406
	 *
407
	 * This function checks for the existence of an entity independent of access
408
	 * permissions. It is useful for situations when a user cannot access an entity
409
	 * and it must be determined whether entity has been deleted or the access level
410
	 * has changed.
411
	 *
412
	 * @param int $guid The GUID of the entity
413
	 *
414
	 * @return bool
415
	 */
416 150
	public function exists($guid) {
417
418
		// need to ignore access and show hidden entities to check existence
419 150
		$ia = $this->session->setIgnoreAccess(true);
420 150
		$show_hidden = access_show_hidden_entities(true);
421
422 150
		$result = $this->getRow($guid);
423
424 150
		$this->session->setIgnoreAccess($ia);
425 150
		access_show_hidden_entities($show_hidden);
426
427 150
		return !empty($result);
428
	}
429
430
	/**
431
	 * Enable an entity.
432
	 *
433
	 * @param int  $guid      GUID of entity to enable
434
	 * @param bool $recursive Recursively enable all entities disabled with the entity?
435
	 *
436
	 * @return bool
437
	 */
438
	public function enable($guid, $recursive = true) {
439
440
		// Override access only visible entities
441
		$old_access_status = access_get_show_hidden_status();
442
		access_show_hidden_entities(true);
443
444
		$result = false;
445
		$entity = get_entity($guid);
446
		if ($entity) {
447
			$result = $entity->enable($recursive);
448
		}
449
450
		access_show_hidden_entities($old_access_status);
451
452
		return $result;
453
	}
454
455
	/**
456
	 * Returns an array of entities with optional filtering.
457
	 *
458
	 * Entities are the basic unit of storage in Elgg.  This function
459
	 * provides the simplest way to get an array of entities.  There
460
	 * are many options available that can be passed to filter
461
	 * what sorts of entities are returned.
462
	 *
463
	 * @param QueryBuilder $query   Query
464
	 * @param array        $options Options
465
	 *
466
	 * @return ElggEntity[]
467
	 * @throws DatabaseException
468
	 */
469 1171
	public function fetch(QueryBuilder $query, array $options = []) {
470 1171
		$results = $this->db->getData($query, $options['callback']);
471
472 1171
		if (empty($results)) {
473 889
			return [];
474
		}
475
476 512
		$preload = array_filter($results, function ($e) {
477 512
			return $e instanceof ElggEntity;
478 512
		});
479
		/* @var $preload ElggEntity[] */
480
481 512
		$this->metadata_cache->populateFromEntities($preload);
0 ignored issues
show
Bug introduced by
$preload of type ElggEntity[] is incompatible with the type integer[] expected by parameter $guids of Elgg\Cache\MetadataCache::populateFromEntities(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

481
		$this->metadata_cache->populateFromEntities(/** @scrutinizer ignore-type */ $preload);
Loading history...
482
483 512
		$props_to_preload = [];
484 512
		if (elgg_extract('preload_owners', $options, false)) {
485 1
			$props_to_preload[] = 'owner_guid';
486
		}
487 512
		if (elgg_extract('preload_containers', $options, false)) {
488
			$props_to_preload[] = 'container_guid';
489
		}
490
491 512
		if ($props_to_preload) {
492 1
			_elgg_services()->entityPreloader->preload($preload, $props_to_preload);
493
		}
494
495 512
		return $results;
496
	}
497
498
	/**
499
	 * Returns a list of months in which entities were updated or created.
500
	 *
501
	 * @tip     Use this to generate a list of archives by month for when entities were added or updated.
502
	 *
503
	 * @warning Months are returned in the form YYYYMM.
504
	 *
505
	 * @param string $type           The type of entity
506
	 * @param string $subtype        The subtype of entity
507
	 * @param int    $container_guid The container GUID that the entities belong to
508
	 * @param string $order_by       Order_by SQL order by clause
509
	 *
510
	 * @return array|false Either an array months as YYYYMM, or false on failure
511
	 */
512
	public function getDates($type = '', $subtype = '', $container_guid = 0, $order_by = 'time_created') {
513
514
		$options = [
515
			'types' => $type,
516
			'subtypes' => $subtype,
517
			'container_guids' => $container_guid,
518
			'callback' => false,
519
			'order_by' => [
520
				new OrderByClause($order_by),
521
			],
522
		];
523
524
		$options = new QueryOptions($options);
525
526
		$qb = Select::fromTable('entities');
527
		$qb->select("DISTINCT EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(time_created)) AS yearmonth");
528
		$qb->addClause(EntityWhereClause::factory($options));
529
530
		$results = _elgg_services()->db->getData($qb);
531
		if (empty($results)) {
532
			return false;
533
		}
534
535
		return array_map(function ($e) {
536
			return $e->yearmonth;
537
		}, $results);
538
	}
539
540
	/**
541
	 * Update the last_action column in the entities table for $guid.
542
	 *
543
	 * @warning This is different to time_updated.  Time_updated is automatically set,
544
	 * while last_action is only set when explicitly called.
545
	 *
546
	 * @param ElggEntity $entity Entity annotation|relationship action carried out on
547
	 * @param int        $posted Timestamp of last action
548
	 *
549
	 * @return int
550
	 * @access  private
551
	 */
552 122
	public function updateLastAction(ElggEntity $entity, $posted = null) {
553
554 122
		if (!$posted) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $posted of type null|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
555 2
			$posted = $this->getCurrentTime()->getTimestamp();
556
		}
557
558
		$query = "
559 122
			UPDATE {$this->db->prefix}entities
560
			SET last_action = :last_action
561
			WHERE guid = :guid
562
		";
563
564
		$params = [
565 122
			':last_action' => (int) $posted,
566 122
			':guid' => (int) $entity->guid,
567
		];
568
569 122
		$this->db->updateData($query, true, $params);
570
571 122
		return (int) $posted;
572
	}
573
574
	/**
575
	 * Get a user by GUID even if the entity is hidden or disabled
576
	 *
577
	 * @param int $guid User GUID. Default is logged in user
578
	 *
579
	 * @return ElggUser|false
580
	 * @throws ClassException
581
	 * @throws InvalidParameterException
582
	 * @access private
583
	 */
584 1228
	public function getUserForPermissionsCheck($guid = 0) {
585 1228
		if (!$guid) {
586 1219
			return $this->session->getLoggedInUser();
587
		}
588
589
		// need to ignore access and show hidden entities for potential hidden/disabled users
590 315
		$ia = $this->session->setIgnoreAccess(true);
591 315
		$show_hidden = access_show_hidden_entities(true);
592
593 315
		$user = $this->get($guid, 'user');
594 315
		if ($user) {
595 308
			$this->metadata_cache->populateFromEntities([$user->guid]);
596
		}
597
598 315
		$this->session->setIgnoreAccess($ia);
599 315
		access_show_hidden_entities($show_hidden);
600
601 315
		if (!$user) {
602
			// requested to check access for a specific user_guid, but there is no user entity, so the caller
603
			// should cancel the check and return false
604 7
			$message = $this->translator->translate('UserFetchFailureException', [$guid]);
605
			// $this->logger->warn($message);
606
607 7
			throw new UserFetchFailureException($message);
608
		}
609
610 308
		return $user;
611
	}
612
613
	/**
614
	 * Disables all entities owned and contained by a user (or another entity)
615
	 *
616
	 * @param ElggEntity $entity Owner/container entity
617
	 *
618
	 * @return bool
619
	 * @throws DatabaseException
620
	 */
621 1
	public function disableEntities(ElggEntity $entity) {
622 1
		if (!$entity->canEdit()) {
623
			return false;
624
		}
625
626 1
		if (!$this->events->trigger('disable', $entity->type, $entity)) {
627
			return false;
628
		}
629
630 1
		$qb = Update::table('entities');
631 1
		$qb->set('enabled', $qb->param('no', ELGG_VALUE_STRING))
632 1
			->where($qb->compare('owner_guid', '=', $entity->guid, ELGG_VALUE_INTEGER))
633 1
			->orWhere($qb->compare('container_guid', '=', $entity->guid, ELGG_VALUE_INTEGER));
634
635 1
		$this->db->updateData($qb, true);
636
637 1
		$entity->invalidateCache();
638
639 1
		return true;
640
	}
641
642
	/**
643
	 * Delete entity and all of its properties
644
	 *
645
	 * @param ElggEntity $entity    Entity
646
	 * @param bool       $recursive Delete all owned and contained entities
647
	 *
648
	 * @return bool
649
	 * @throws DatabaseException
650
	 */
651 215
	public function delete(\ElggEntity $entity, $recursive = true) {
652 215
		$guid = $entity->guid;
653 215
		if (!$guid) {
654 2
			return false;
655
		}
656
657 214
		if (!_elgg_services()->hooks->getEvents()->triggerBefore('delete', $entity->type, $entity)) {
0 ignored issues
show
Bug introduced by
$entity of type ElggEntity is incompatible with the type string expected by parameter $object of Elgg\EventsService::triggerBefore(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

657
		if (!_elgg_services()->hooks->getEvents()->triggerBefore('delete', $entity->type, /** @scrutinizer ignore-type */ $entity)) {
Loading history...
658
			return false;
659
		}
660
661
		// now trigger an event to let others know this entity is about to be deleted
662
		// so they can prevent it or take their own actions
663 214
		if (!_elgg_services()->hooks->getEvents()->triggerDeprecated('delete', $entity->type, $entity)) {
0 ignored issues
show
Bug introduced by
$entity of type ElggEntity is incompatible with the type string expected by parameter $object of Elgg\EventsService::triggerDeprecated(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

663
		if (!_elgg_services()->hooks->getEvents()->triggerDeprecated('delete', $entity->type, /** @scrutinizer ignore-type */ $entity)) {
Loading history...
664
			return false;
665
		}
666
667 214
		if ($entity instanceof ElggUser) {
668
			// ban to prevent using the site during delete
669 70
			$entity->ban();
670
		}
671
672 214
		if ($recursive) {
673 214
			$this->deleteRelatedEntities($entity);
674
		}
675
676 214
		$this->deleteEntityProperties($entity);
677
678 214
		$qb = Delete::fromTable('entities');
679 214
		$qb->where($qb->compare('guid', '=', $guid, ELGG_VALUE_INTEGER));
680
681 214
		$this->db->deleteData($qb);
682
683 214
		_elgg_services()->hooks->getEvents()->triggerAfter('delete', $entity->type, $entity);
0 ignored issues
show
Bug introduced by
$entity of type ElggEntity is incompatible with the type string expected by parameter $object of Elgg\EventsService::triggerAfter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

683
		_elgg_services()->hooks->getEvents()->triggerAfter('delete', $entity->type, /** @scrutinizer ignore-type */ $entity);
Loading history...
684
685 214
		return true;
686
	}
687
688
	/**
689
	 * Deletes entities owned or contained by the entity being deletes
690
	 *
691
	 * @param ElggEntity $entity Entity
692
	 *
693
	 * @return void
694
	 * @throws DatabaseException
695
	 */
696 214
	protected function deleteRelatedEntities(ElggEntity $entity) {
697
		// Temporarily overriding access controls
698 214
		$entity_disable_override = access_get_show_hidden_status();
699 214
		access_show_hidden_entities(true);
700 214
		$ia = elgg_set_ignore_access(true);
701
702
		$options = [
703 214
			'wheres' => function (QueryBuilder $qb) use ($entity) {
704 214
				$ors = $qb->merge([
705 214
					$qb->compare('e.owner_guid', '=', $entity->guid, ELGG_VALUE_INTEGER),
706 214
					$qb->compare('e.container_guid', '=', $entity->guid, ELGG_VALUE_INTEGER),
707
				]);
708
709 214
				return $qb->merge([
710 214
					$ors,
711 214
					$qb->compare('e.guid', 'neq', $entity->guid, ELGG_VALUE_INTEGER),
712
				]);
713 214
			},
714
			'limit' => false,
715
		];
716
717 214
		$batch = new ElggBatch('elgg_get_entities', $options);
718 214
		$batch->setIncrementOffset(false);
719
720
		/* @var $e \ElggEntity */
721 214
		foreach ($batch as $e) {
722 7
			$this->delete($e, true);
723
		}
724
725 214
		access_show_hidden_entities($entity_disable_override);
726 214
		elgg_set_ignore_access($ia);
727 214
	}
728
729
	/**
730
	 * Clear data from secondary tables
731
	 *
732
	 * @param ElggEntity $entity Entity
733
	 *
734
	 * @return void
735
	 */
736 214
	protected function deleteEntityProperties(ElggEntity $entity) {
737
738 214
		$guid = $entity->guid;
739
740 214
		$entity_disable_override = access_get_show_hidden_status();
741 214
		access_show_hidden_entities(true);
742 214
		$ia = elgg_set_ignore_access(true);
743
744 214
		elgg_delete_river(['subject_guid' => $guid, 'limit' => false]);
745 214
		elgg_delete_river(['object_guid' => $guid, 'limit' => false]);
746 214
		elgg_delete_river(['target_guid' => $guid, 'limit' => false]);
747
748 214
		remove_all_private_settings($guid);
749 214
		$entity->deleteOwnedAccessCollections();
750 214
		$entity->deleteAccessCollectionMemberships();
751 214
		$entity->deleteRelationships();
752 214
		$entity->deleteOwnedAnnotations();
753 214
		$entity->deleteAnnotations();
754 214
		$entity->deleteMetadata();
755
756 214
		access_show_hidden_entities($entity_disable_override);
757 214
		elgg_set_ignore_access($ia);
758
759 214
		$dir = new \Elgg\EntityDirLocator($guid);
760 214
		$file_path = _elgg_config()->dataroot . $dir;
761 214
		delete_directory($file_path);
762
763 214
	}
764
}
765