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

engine/lib/entities.php (5 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) {
0 ignored issues
show
The expression $types of type array|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
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) {
0 ignored issues
show
The parameter $hooks is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
821
	$events->registerHandler('init', 'system', '_elgg_entities_init');
822
};
823