Test Failed
Push — master ( 8c47c2...3acf9f )
by Steve
12:37
created

engine/lib/entities.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Procedural code for creating, loading, and modifying \ElggEntity objects.
4
 */
5
6
use Elgg\Database\EntityTable\UserFetchFailureException;
7
8
/**
9
 * Return the id for a given subtype.
10
 *
11
 * \ElggEntity objects have a type and a subtype.  Subtypes
12
 * are defined upon creation and cannot be changed.
13
 *
14
 * Plugin authors generally don't need to use this function
15
 * unless writing their own SQL queries.  Use {@link \ElggEntity::getSubtype()}
16
 * to return the string subtype.
17
 *
18
 * Subtypes are stored in the entity_subtypes table.  There is a foreign
19
 * key in the entities table.
20
 *
21
 * @param string $type    Type
22
 * @param string $subtype Subtype
23
 *
24
 * @return int Subtype ID
25
 * @see get_subtype_from_id()
26
 */
27
function get_subtype_id($type, $subtype) {
28 261
	return _elgg_services()->subtypeTable->getId($type, $subtype);
29
}
30
31
/**
32
 * Gets the denormalized string for a given subtype ID.
33
 *
34
 * @param int $subtype_id Subtype ID from database
35
 * @return string|false Subtype name, false if subtype not found
36
 * @see get_subtype_id()
37
 * @access private
38
 */
39
function get_subtype_from_id($subtype_id) {
40 89
	return _elgg_services()->subtypeTable->getSubtype($subtype_id);
41
}
42
43
/**
44
 * Return the class name for a registered type and subtype.
45
 *
46
 * Entities can be registered to always be loaded as a certain class
47
 * with add_subtype() or update_subtype(). This function returns the class
48
 * name if found and null if not.
49
 *
50
 * @param string $type    The type
51
 * @param string $subtype The subtype
52
 *
53
 * @return string|null a class name or null
54
 * @see get_subtype_from_id()
55
 * @see get_subtype_class_from_id()
56
 */
57
function get_subtype_class($type, $subtype) {
58
	return _elgg_services()->subtypeTable->getClass($type, $subtype);
59
}
60
61
/**
62
 * Returns the class name for a subtype id.
63
 *
64
 * @param int $subtype_id The subtype id
65
 *
66
 * @return string|null
67
 * @see get_subtype_class()
68
 * @see get_subtype_from_id()
69
 * @access private
70
 */
71
function get_subtype_class_from_id($subtype_id) {
72
	return _elgg_services()->subtypeTable->getClassFromId($subtype_id);
73
}
74
75
/**
76
 * Register \ElggEntities with a certain type and subtype to be loaded as a specific class.
77
 *
78
 * By default entities are loaded as one of the 4 parent objects: site, user, object, or group.
79
 * If you subclass any of these you can register the classname with add_subtype() so
80
 * it will be loaded as that class automatically when retrieved from the database with
81
 * {@link get_entity()}.
82
 *
83
 * @warning This function cannot be used to change the class for a type-subtype pair.
84
 * Use update_subtype() for that.
85
 *
86
 * @param string $type    The type you're subtyping (site, user, object, or group)
87
 * @param string $subtype The subtype
88
 * @param string $class   Optional class name for the object
89
 *
90
 * @return int
91
 * @see update_subtype()
92
 * @see remove_subtype()
93
 * @see get_entity()
94
 */
95
function add_subtype($type, $subtype, $class = "") {
96 199
	return _elgg_services()->subtypeTable->add($type, $subtype, $class);
97
}
98
99
/**
100
 * Removes a registered \ElggEntity type, subtype, and classname.
101
 *
102
 * @warning You do not want to use this function. If you want to unregister
103
 * a class for a subtype, use update_subtype(). Using this function will
104
 * permanently orphan all the objects created with the specified subtype.
105
 *
106
 * @param string $type    Type
107
 * @param string $subtype Subtype
108
 *
109
 * @return bool
110
 * @see add_subtype()
111
 * @see update_subtype()
112
 */
113
function remove_subtype($type, $subtype) {
114
	return _elgg_services()->subtypeTable->remove($type, $subtype);
115
}
116
117
/**
118
 * Update a registered \ElggEntity type, subtype, and class name
119
 *
120
 * @param string $type    Type
121
 * @param string $subtype Subtype
122
 * @param string $class   Class name to use when loading this entity
123
 *
124
 * @return bool
125
 */
126
function update_subtype($type, $subtype, $class = '') {
127
	return _elgg_services()->subtypeTable->update($type, $subtype, $class);
128
}
129
130
/**
131
 * Determine if a given user can write to an entity container.
132
 *
133
 * An entity can be a container for any other entity by setting the
134
 * container_guid.  container_guid can differ from owner_guid.
135
 *
136
 * A plugin hook container_permissions_check:$entity_type is emitted to allow granular
137
 * access controls in plugins.
138
 *
139
 * @param int    $user_guid      The user guid, or 0 for logged in user.
140
 * @param int    $container_guid The container, or 0 for the current page owner.
141
 * @param string $type           The type of entity we want to create (default: 'all')
142
 * @param string $subtype        The subtype of the entity we want to create (default: 'all')
143
 *
144
 * @return bool
145
 * @deprecated 2.2
146
 */
147
function can_write_to_container($user_guid = 0, $container_guid = 0, $type = 'all', $subtype = 'all') {
148
	elgg_deprecated_notice(__FUNCTION__ . ' is deprecated. Use ElggEntity::canWriteToContainer()', '2.2');
149
	if (!$container_guid) {
150
		$container_guid = elgg_get_page_owner_guid();
151
	}
152
	$container = get_entity($container_guid);
153
	if (!$container) {
154
		return false;
155
	}
156
157
	return $container->canWriteToContainer($user_guid, $type, $subtype);
158
}
159
160
/**
161
 * Returns a database row from the entities table.
162
 *
163
 * @tip Use get_entity() to return the fully loaded entity.
164
 *
165
 * @warning This will only return results if a) it exists, b) you have access to it.
166
 * see {@link _elgg_get_access_where_sql()}.
167
 *
168
 * @param int $guid The GUID of the object to extract
169
 *
170
 * @return \stdClass|false
171
 * @see entity_row_to_elggstar()
172
 * @access private
173
 */
174
function get_entity_as_row($guid) {
175
	return _elgg_services()->entityTable->getRow($guid);
176
}
177
178
/**
179
 * Create an Elgg* object from a given entity row.
180
 *
181
 * Handles loading all tables into the correct class.
182
 *
183
 * @param \stdClass $row The row of the entry in the entities table.
184
 *
185
 * @return \ElggEntity|false
186
 * @see get_entity_as_row()
187
 * @see add_subtype()
188
 * @see get_entity()
189
 * @access private
190
 *
191
 * @throws ClassException|InstallationException
192
 */
193
function entity_row_to_elggstar($row) {
194
	return _elgg_services()->entityTable->rowToElggStar($row);
195
}
196
197
/**
198
 * Loads and returns an entity object from a guid.
199
 *
200
 * @param int $guid The GUID of the entity
201
 *
202
 * @return \ElggEntity The correct Elgg or custom object based upon entity type and subtype
203
 */
204
function get_entity($guid) {
205 117
	return _elgg_services()->entityTable->get($guid);
206
}
207
208
/**
209
 * Does an entity exist?
210
 *
211
 * This function checks for the existence of an entity independent of access
212
 * permissions. It is useful for situations when a user cannot access an entity
213
 * and it must be determined whether entity has been deleted or the access level
214
 * has changed.
215
 *
216
 * @param int $guid The GUID of the entity
217
 *
218
 * @return bool
219
 * @since 1.8.0
220
 */
221
function elgg_entity_exists($guid) {
222
	return _elgg_services()->entityTable->exists($guid);
223
}
224
225
/**
226
 * Enable an entity.
227
 *
228
 * @param int  $guid      GUID of entity to enable
229
 * @param bool $recursive Recursively enable all entities disabled with the entity?
230
 *
231
 * @return bool
232
 * @since 1.9.0
233
 */
234
function elgg_enable_entity($guid, $recursive = true) {
235
	return _elgg_services()->entityTable->enable($guid, $recursive);
236
}
237
238
/**
239
 * Returns an array of entities with optional filtering.
240
 *
241
 * Entities are the basic unit of storage in Elgg.  This function
242
 * provides the simplest way to get an array of entities.  There
243
 * are many options available that can be passed to filter
244
 * what sorts of entities are returned.
245
 *
246
 * @tip To output formatted strings of entities, use {@link elgg_list_entities()} and
247
 * its cousins.
248
 *
249
 * @tip Plural arguments can be written as singular if only specifying a
250
 * single element.  ('type' => 'object' vs 'types' => array('object')).
251
 *
252
 * @param array $options Array in format:
253
 *
254
 * 	types => null|STR entity type (type IN ('type1', 'type2')
255
 *           Joined with subtypes by AND. See below)
256
 *
257
 * 	subtypes => null|STR entity subtype (SQL: subtype IN ('subtype1', 'subtype2))
258
 *              Use ELGG_ENTITIES_NO_VALUE to match the default subtype.
259
 *              Use ELGG_ENTITIES_ANY_VALUE to match any subtype.
260
 *
261
 * 	type_subtype_pairs => null|ARR (array('type' => 'subtype'))
262
 *                        array(
263
 *                            'object' => array('blog', 'file'), // All objects with subtype of 'blog' or 'file'
264
 *                            'user' => ELGG_ENTITY_ANY_VALUE, // All users irrespective of subtype
265
 *                        );
266
 *
267
 *	guids => null|ARR Array of entity guids
268
 *
269
 * 	owner_guids => null|ARR Array of owner guids
270
 *
271
 * 	container_guids => null|ARR Array of container_guids
272
 *
273
 * 	order_by => null (time_created desc)|STR SQL order by clause
274
 *
275
 *  reverse_order_by => BOOL Reverse the default order by clause
276
 *
277
 * 	limit => null (from settings)|INT SQL limit clause (0 means no limit)
278
 *
279
 * 	offset => null (0)|INT SQL offset clause
280
 *
281
 * 	created_time_lower => null|INT Created time lower boundary in epoch time
282
 *
283
 * 	created_time_upper => null|INT Created time upper boundary in epoch time
284
 *
285
 * 	modified_time_lower => null|INT Modified time lower boundary in epoch time
286
 *
287
 * 	modified_time_upper => null|INT Modified time upper boundary in epoch time
288
 *
289
 * 	count => true|false return a count instead of entities
290
 *
291
 * 	wheres => array() Additional where clauses to AND together
292
 *
293
 * 	joins => array() Additional joins
294
 *
295
 * 	preload_owners => bool (false) If set to true, this function will preload
296
 * 					  all the owners of the returned entities resulting in better
297
 * 					  performance when displaying entities owned by several users
298
 *
299
 * 	callback => string A callback function to pass each row through
300
 *
301
 * 	distinct => bool (true) If set to false, Elgg will drop the DISTINCT clause from
302
 *				the MySQL query, which will improve performance in some situations.
303
 *				Avoid setting this option without a full understanding of the underlying
304
 *				SQL query Elgg creates.
305
 *
306
 *  batch => bool (false) If set to true, an Elgg\BatchResult object will be returned instead of an array.
307
 *           Since 2.3
308
 *
309
 *  batch_inc_offset => bool (true) If "batch" is used, this tells the batch to increment the offset
310
 *                      on each fetch. This must be set to false if you delete the batched results.
311
 *
312
 *  batch_size => int (25) If "batch" is used, this is the number of entities/rows to pull in before
313
 *                requesting more.
314
 *
315
 * @return \ElggEntity[]|int|mixed If count, int. Otherwise an array or an Elgg\BatchResult. false on errors.
316
 *
317
 * @since 1.7.0
318
 * @see elgg_get_entities_from_metadata()
319
 * @see elgg_get_entities_from_relationship()
320
 * @see elgg_get_entities_from_access_id()
321
 * @see elgg_get_entities_from_annotations()
322
 * @see elgg_list_entities()
323
 */
324
function elgg_get_entities(array $options = []) {
325 2
	return _elgg_services()->entityTable->getEntities($options);
326
}
327
328
/**
329
 * Returns SQL where clause for owner and containers.
330
 *
331
 * @param string     $column Column name the guids should be checked against. Usually
332
 *                           best to provide in table.column format.
333
 * @param null|array $guids  Array of GUIDs.
334
 *
335
 * @return false|string
336
 * @since 1.8.0
337
 * @access private
338
 */
339
function _elgg_get_guid_based_where_sql($column, $guids) {
340 98
	return _elgg_services()->entityTable->getGuidBasedWhereSql($column, $guids);
341
}
342
343
/**
344
 * Returns SQL where clause for entity time limits.
345
 *
346
 * @param string   $table              Entity table prefix as defined in
347
 *                                     SELECT...FROM entities $table
348
 * @param null|int $time_created_upper Time created upper limit
349
 * @param null|int $time_created_lower Time created lower limit
350
 * @param null|int $time_updated_upper Time updated upper limit
351
 * @param null|int $time_updated_lower Time updated lower limit
352
 *
353
 * @return false|string false on fail, string on success.
354
 * @since 1.7.0
355
 * @access private
356
 */
357
function _elgg_get_entity_time_where_sql($table, $time_created_upper = null,
358
		$time_created_lower = null, $time_updated_upper = null, $time_updated_lower = null) {
359 98
	return _elgg_services()->entityTable->getEntityTimeWhereSql($table,
360 98
		$time_created_upper, $time_created_lower, $time_updated_upper, $time_updated_lower);
361
}
362
363
/**
364
 * Returns a string of rendered entities.
365
 *
366
 * Displays list of entities with formatting specified by the entity view.
367
 *
368
 * @tip Pagination is handled automatically.
369
 *
370
 * @note Internal: This also provides the views for elgg_view_annotation().
371
 *
372
 * @note Internal: If the initial COUNT query returns 0, the $getter will not be called again.
373
 *
374
 * @param array    $options Any options from $getter options plus:
375
 *                   item_view => STR Optional. Alternative view used to render list items
376
 *                   full_view => BOOL Display full view of entities (default: false)
377
 *                   list_type => STR 'list', 'gallery', or 'table'
378
 *                   columns => ARR instances of Elgg\Views\TableColumn if list_type is "table"
379
 *                   list_type_toggle => BOOL Display gallery / list switch
380
 *                   pagination => BOOL Display pagination links
381
 *                   no_results => STR|Closure Message to display when there are no entities
382
 *
383
 * @param callback $getter  The entity getter function to use to fetch the entities.
384
 * @param callback $viewer  The function to use to view the entity list.
385
 *
386
 * @return string
387
 * @since 1.7
388
 * @see elgg_get_entities()
389
 * @see elgg_view_entity_list()
390
 */
391
function elgg_list_entities(array $options = [], $getter = 'elgg_get_entities',
392
	$viewer = 'elgg_view_entity_list') {
393
394
	elgg_register_rss_link();
395
396
	$offset_key = isset($options['offset_key']) ? $options['offset_key'] : 'offset';
397
398
	$defaults = [
399
		'offset' => (int) max(get_input($offset_key, 0), 0),
400
		'limit' => (int) max(get_input('limit', _elgg_config()->default_limit), 0),
401
		'full_view' => false,
402
		'list_type_toggle' => false,
403
		'pagination' => true,
404
		'no_results' => '',
405
	];
406
407
	$options = array_merge($defaults, $options);
408
409
	$entities = [];
410
	
411
	if (!$options['pagination']) {
412
		$options['count'] = false;
413
		$entities = call_user_func($getter, $options);
414
		unset($options['count']);
415
	} else {
416
		$options['count'] = true;
417
		$count = call_user_func($getter, $options);
418
	
419
		if ($count > 0) {
420
			$options['count'] = false;
421
			$entities = call_user_func($getter, $options);
422
		}
423
424
		$options['count'] = $count;
425
	}
426
	
427
	return call_user_func($viewer, $entities, $options);
428
}
429
430
/**
431
 * Gets entities based upon attributes in secondary tables.
432
 * Also accepts all options available to elgg_get_entities(),
433
 * elgg_get_entities_from_metadata(), and elgg_get_entities_from_relationship().
434
 *
435
 * @warning requires that the entity type be specified and there can only be one
436
 * type.
437
 *
438
 * @see elgg_get_entities
439
 * @see elgg_get_entities_from_metadata
440
 * @see elgg_get_entities_from_relationship
441
 *
442
 * @param array $options Array in format:
443
 *
444
 * 	attribute_name_value_pairs => ARR (
445
 *                                   'name' => 'name',
446
 *                                   'value' => 'value',
447
 *                                   'operand' => '=', (optional)
448
 *                                   'case_sensitive' => false (optional)
449
 *                                  )
450
 * 	                             If multiple values are sent via
451
 *                               an array ('value' => array('value1', 'value2')
452
 *                               the pair's operand will be forced to "IN".
453
 *
454
 * 	attribute_name_value_pairs_operator => null|STR The operator to use for combining
455
 *                                        (name = value) OPERATOR (name = value); default is AND
456
 *
457
 * @return \ElggEntity[]|mixed If count, int. If not count, array. false on errors.
458
 * @since 1.9.0
459
 * @throws InvalidArgumentException
460
 * @todo Does not support ordering by attributes or using an attribute pair shortcut like this ('title' => 'foo')
461
 */
462
function elgg_get_entities_from_attributes(array $options = []) {
463
	return _elgg_services()->entityTable->getEntitiesFromAttributes($options);
464
}
465
466
/**
467
 * Get the join and where clauses for working with entity attributes
468
 *
469
 * @return false|array False on fail, array('joins', 'wheres')
470
 * @since 1.9.0
471
 * @access private
472
 * @throws InvalidArgumentException
473
 */
474
function _elgg_get_entity_attribute_where_sql(array $options = []) {
475
	return _elgg_services()->entityTable->getEntityAttributeWhereSql($options);
476
}
477
478
/**
479
 * Returns a list of months in which entities were updated or created.
480
 *
481
 * @tip Use this to generate a list of archives by month for when entities were added or updated.
482
 *
483
 * @todo document how to pass in array for $subtype
484
 *
485
 * @warning Months are returned in the form YYYYMM.
486
 *
487
 * @param string $type           The type of entity
488
 * @param string $subtype        The subtype of entity
489
 * @param int    $container_guid The container GUID that the entities belong to
490
 * @param int    $ignored        Ignored parameter
491
 * @param string $order_by       Order_by SQL order by clause
492
 *
493
 * @return array|false Either an array months as YYYYMM, or false on failure
494
 */
495
function get_entity_dates($type = '', $subtype = '', $container_guid = 0, $ignored = 0, $order_by = 'time_created') {
496
	return _elgg_services()->entityTable->getDates($type, $subtype, $container_guid, $order_by);
497
}
498
499
/**
500
 * Registers an entity type and subtype as a public-facing entity that should
501
 * be shown in search and by {@link elgg_list_registered_entities()}.
502
 *
503
 * @warning Entities that aren't registered here will not show up in search.
504
 *
505
 * @tip Add a language string item:type:subtype to make sure the items are display properly.
506
 *
507
 * @param string $type    The type of entity (object, site, user, group)
508
 * @param string $subtype The subtype to register (may be blank)
509
 *
510
 * @return bool Depending on success
511
 * @see get_registered_entity_types()
512
 */
513
function elgg_register_entity_type($type, $subtype = null) {
514
	global $CONFIG;
515
516
	$type = strtolower($type);
517
	if (!in_array($type, $CONFIG->entity_types)) {
518
		return false;
519
	}
520
521
	if (!isset($CONFIG->registered_entities)) {
522
		$CONFIG->registered_entities = [];
523
	}
524
525
	if (!isset($CONFIG->registered_entities[$type])) {
526
		$CONFIG->registered_entities[$type] = [];
527
	}
528
529
	if ($subtype) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $subtype of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
530
		$CONFIG->registered_entities[$type][] = $subtype;
531
	}
532
533
	return true;
534
}
535
536
/**
537
 * Unregisters an entity type and subtype as a public-facing type.
538
 *
539
 * @warning With a blank subtype, it unregisters that entity type including
540
 * all subtypes. This must be called after all subtypes have been registered.
541
 *
542
 * @param string $type    The type of entity (object, site, user, group)
543
 * @param string $subtype The subtype to register (may be blank)
544
 *
545
 * @return bool Depending on success
546
 * @see elgg_register_entity_type()
547
 */
548
function elgg_unregister_entity_type($type, $subtype = null) {
549
	global $CONFIG;
550
551
	$type = strtolower($type);
552
	if (!in_array($type, $CONFIG->entity_types)) {
553
		return false;
554
	}
555
556
	if (!isset($CONFIG->registered_entities)) {
557
		return false;
558
	}
559
560
	if (!isset($CONFIG->registered_entities[$type])) {
561
		return false;
562
	}
563
564
	if ($subtype) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $subtype of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
565
		if (in_array($subtype, $CONFIG->registered_entities[$type])) {
566
			$key = array_search($subtype, $CONFIG->registered_entities[$type]);
567
			unset($CONFIG->registered_entities[$type][$key]);
568
		} else {
569
			return false;
570
		}
571
	} else {
572
		unset($CONFIG->registered_entities[$type]);
573
	}
574
575
	return true;
576
}
577
578
/**
579
 * Returns registered entity types and subtypes
580
 *
581
 * @param string $type The type of entity (object, site, user, group) or blank for all
582
 *
583
 * @return array|false Depending on whether entities have been registered
584
 * @see elgg_register_entity_type()
585
 */
586
function get_registered_entity_types($type = null) {
587
	global $CONFIG;
588
589
	if (!isset($CONFIG->registered_entities)) {
590
		return false;
591
	}
592
	if ($type) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
593
		$type = strtolower($type);
594
	}
595
	if (!empty($type) && empty($CONFIG->registered_entities[$type])) {
596
		return false;
597
	}
598
599
	if (empty($type)) {
600
		return $CONFIG->registered_entities;
601
	}
602
603
	return $CONFIG->registered_entities[$type];
604
}
605
606
/**
607
 * Returns if the entity type and subtype have been registered with {@link elgg_register_entity_type()}.
608
 *
609
 * @param string $type    The type of entity (object, site, user, group)
610
 * @param string $subtype The subtype (may be blank)
611
 *
612
 * @return bool Depending on whether or not the type has been registered
613
 */
614
function is_registered_entity_type($type, $subtype = null) {
615
	global $CONFIG;
616
617
	if (!isset($CONFIG->registered_entities)) {
618
		return false;
619
	}
620
621
	$type = strtolower($type);
622
623
	// @todo registering a subtype implicitly registers the type.
624
	// see #2684
625
	if (!isset($CONFIG->registered_entities[$type])) {
626
		return false;
627
	}
628
629
	if ($subtype && !in_array($subtype, $CONFIG->registered_entities[$type])) {
630
		return false;
631
	}
632
	return true;
633
}
634
635
/**
636
 * Returns a viewable list of entities based on the registered types.
637
 *
638
 * @see elgg_view_entity_list
639
 *
640
 * @param array $options Any elgg_get_entity() options plus:
641
 *
642
 * 	full_view => BOOL Display full view entities
643
 *
644
 * 	list_type_toggle => BOOL Display gallery / list switch
645
 *
646
 * 	allowed_types => true|ARRAY True to show all types or an array of valid types.
647
 *
648
 * 	pagination => BOOL Display pagination links
649
 *
650
 * @return string A viewable list of entities
651
 * @since 1.7.0
652
 */
653
function elgg_list_registered_entities(array $options = []) {
654
	elgg_register_rss_link();
655
656
	$defaults = [
657
		'full_view' => false,
658
		'allowed_types' => true,
659
		'list_type_toggle' => false,
660
		'pagination' => true,
661
		'offset' => 0,
662
		'types' => [],
663
		'type_subtype_pairs' => [],
664
	];
665
666
	$options = array_merge($defaults, $options);
667
668
	$types = get_registered_entity_types();
669
670
	foreach ($types as $type => $subtype_array) {
671
		if (in_array($type, $options['allowed_types']) || $options['allowed_types'] === true) {
672
			// you must explicitly register types to show up in here and in search for objects
673
			if ($type == 'object') {
674
				if (is_array($subtype_array) && count($subtype_array)) {
675
					$options['type_subtype_pairs'][$type] = $subtype_array;
676
				}
677
			} else {
678
				if (is_array($subtype_array) && count($subtype_array)) {
679
					$options['type_subtype_pairs'][$type] = $subtype_array;
680
				} else {
681
					$options['type_subtype_pairs'][$type] = ELGG_ENTITIES_ANY_VALUE;
682
				}
683
			}
684
		}
685
	}
686
687
	if (!empty($options['type_subtype_pairs'])) {
688
		$count = elgg_get_entities(array_merge(['count' => true], $options));
689
		if ($count > 0) {
690
			$entities = elgg_get_entities($options);
691
		} else {
692
			$entities = [];
693
		}
694
	} else {
695
		$count = 0;
696
		$entities = [];
697
	}
698
699
	$options['count'] = $count;
700
	return elgg_view_entity_list($entities, $options);
701
}
702
703
/**
704
 * Checks if $entity is an \ElggEntity and optionally for type and subtype.
705
 *
706
 * @tip Use this function in actions and views to check that you are dealing
707
 * with the correct type of entity.
708
 *
709
 * @param mixed  $entity  Entity
710
 * @param string $type    Entity type
711
 * @param string $subtype Entity subtype
712
 *
713
 * @return bool
714
 * @since 1.8.0
715
 */
716
function elgg_instanceof($entity, $type = null, $subtype = null) {
717 33
	$return = ($entity instanceof \ElggEntity);
718
719 33
	if ($type) {
720
		/* @var \ElggEntity $entity */
721 33
		$return = $return && ($entity->getType() == $type);
722
	}
723
724 33
	if ($subtype) {
725
		$return = $return && ($entity->getSubtype() == $subtype);
726
	}
727
728 33
	return $return;
729
}
730
731
/**
732
 * Checks options for the existing of site_guid or site_guids contents and reports a warning if found
733
 *
734
 * @param array $options array of options to check
735
 *
736
 * @return void
737
 */
738
function _elgg_check_unsupported_site_guid(array $options = []) {
739 3
	$site_guid = elgg_extract('site_guid', $options, elgg_extract('site_guids', $options));
740 3
	if ($site_guid === null) {
741 3
		return;
742
	}
743
	
744
	$backtrace = debug_backtrace();
745
	// never show this call.
746
	array_shift($backtrace);
747
748
	if (!empty($backtrace[0]['class'])) {
749
		$warning = "Passing site_guid or site_guids to the method {$backtrace[0]['class']}::{$backtrace[0]['file']} is not supported.";
750
		$warning .= "Please update your usage of the method.";
751
	} else {
752
		$warning = "Passing site_guid or site_guids to the function {$backtrace[0]['function']} in {$backtrace[0]['file']} is not supported.";
753
		$warning .= "Please update your usage of the function.";
754
	}
755
756
	_elgg_services()->logger->warn($warning);
757
}
758
759
/**
760
 * Update the last_action column in the entities table for $guid.
761
 *
762
 * @warning This is different to time_updated.  Time_updated is automatically set,
763
 * while last_action is only set when explicitly called.
764
 *
765
 * @param int $guid   Entity annotation|relationship action carried out on
766
 * @param int $posted Timestamp of last action
767
 *
768
 * @return int|false Timestamp or false on failure
769
 * @access private
770
 * @deprecated 2.3
771
 */
772
function update_entity_last_action($guid, $posted = null) {
773
	elgg_deprecated_notice(__FUNCTION__ . ' has been deprecated. Refrain from updating last action timestamp manually', '2.3');
774
775
	$result = false;
776
	$ia = elgg_set_ignore_access(true);
777
	$entity = get_entity($guid);
778
	if ($entity) {
779
		$result = $entity->updateLastAction($posted);
780
	}
781
	elgg_set_ignore_access($ia);
782
	return $result;
783
}
784
785
/**
786
 * Runs unit tests for the entity objects.
787
 *
788
 * @param string $hook   unit_test
789
 * @param string $type   system
790
 * @param array  $value  Array of tests
791
 *
792
 * @return array
793
 * @access private
794
 */
795
function _elgg_entities_test($hook, $type, $value) {
796
	global $CONFIG;
797
	$value[] = $CONFIG->path . 'engine/tests/ElggEntityTest.php';
798
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreAttributeLoaderTest.php';
799
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesTest.php';
800
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromAnnotationsTest.php';
801
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromMetadataTest.php';
802
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromPrivateSettingsTest.php';
803
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromRelationshipTest.php';
804
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromAttributesTest.php';
805
	$value[] = $CONFIG->path . 'engine/tests/ElggEntityPreloaderIntegrationTest.php';
806
	return $value;
807
}
808
809
/**
810
 * Entities init function; establishes the default entity page handler
811
 *
812
 * @return void
813
 * @elgg_event_handler init system
814
 * @access private
815
 */
816
function _elgg_entities_init() {
817
	elgg_register_plugin_hook_handler('unit_test', 'system', '_elgg_entities_test');
818
}
819
820
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
821
	$events->registerHandler('init', 'system', '_elgg_entities_init');
822
};
823