entities.php ➔ elgg_enable_entity()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 1
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Procedural code for creating, loading, and modifying \ElggEntity objects.
4
 *
5
 * @package Elgg.Core
6
 * @subpackage DataModel.Entities
7
 */
8
9
/**
10
 * Cache entities in memory once loaded.
11
 *
12
 * @global \ElggEntity[] $ENTITY_CACHE
13
 * @access private
14
 */
15
global $ENTITY_CACHE;
16
$ENTITY_CACHE = array();
17
18
/**
19
 * GUIDs of entities banned from the entity cache (during this request)
20
 *
21
 * @global array $ENTITY_CACHE_DISABLED_GUIDS
22
 * @access private
23
 */
24
global $ENTITY_CACHE_DISABLED_GUIDS;
25
$ENTITY_CACHE_DISABLED_GUIDS = array();
26
27
/**
28
 * Remove this entity from the entity cache and make sure it is not re-added
29
 *
30
 * @param int $guid The entity guid
31
 *
32
 * @access private
33
 * @todo this is a workaround until #5604 can be implemented
34
 */
35
function _elgg_disable_caching_for_entity($guid) {
36
	global $ENTITY_CACHE_DISABLED_GUIDS;
37
38
	_elgg_invalidate_cache_for_entity($guid);
39
	$ENTITY_CACHE_DISABLED_GUIDS[$guid] = true;
40
}
41
42
/**
43
 * Allow this entity to be stored in the entity cache
44
 *
45
 * @param int $guid The entity guid
46
 *
47
 * @access private
48
 */
49
function _elgg_enable_caching_for_entity($guid) {
50
	global $ENTITY_CACHE_DISABLED_GUIDS;
51
52
	unset($ENTITY_CACHE_DISABLED_GUIDS[$guid]);
53
}
54
55
/**
56
 * Invalidate this class's entry in the cache.
57
 *
58
 * @param int $guid The entity guid
59
 *
60
 * @return void
61
 * @access private
62
 */
63
function _elgg_invalidate_cache_for_entity($guid) {
64
	global $ENTITY_CACHE;
65
66
	$guid = (int)$guid;
67
68
	if (isset($ENTITY_CACHE[$guid])) {
69
		unset($ENTITY_CACHE[$guid]);
70
71
		// Purge separate metadata cache. Original idea was to do in entity destructor, but that would
72
		// have caused a bunch of unnecessary purges at every shutdown. Doing it this way we have no way
73
		// to know that the expunged entity will be GCed (might be another reference living), but that's
74
		// OK; the metadata will reload if necessary.
75
		_elgg_services()->metadataCache->clear($guid);
76
	}
77
}
78
79
/**
80
 * Cache an entity.
81
 *
82
 * Stores an entity in $ENTITY_CACHE;
83
 *
84
 * @param \ElggEntity $entity Entity to cache
85
 *
86
 * @return void
87
 * @see _elgg_retrieve_cached_entity()
88
 * @see _elgg_invalidate_cache_for_entity()
89
 * @access private
90
 * @todo Use an \ElggCache object
91
 */
92
function _elgg_cache_entity(\ElggEntity $entity) {
93
	global $ENTITY_CACHE, $ENTITY_CACHE_DISABLED_GUIDS;
94
95
	// Don't cache non-plugin entities while access control is off, otherwise they could be
96
	// exposed to users who shouldn't see them when control is re-enabled.
97
	if (!($entity instanceof \ElggPlugin) && elgg_get_ignore_access()) {
98
		return;
99
	}
100
101
	$guid = $entity->getGUID();
102
	if (isset($ENTITY_CACHE_DISABLED_GUIDS[$guid])) {
103
		return;
104
	}
105
106
	// Don't store too many or we'll have memory problems
107
	// @todo Pick a less arbitrary limit
108
	if (count($ENTITY_CACHE) > 256) {
109
		_elgg_invalidate_cache_for_entity(array_rand($ENTITY_CACHE));
110
	}
111
112
	$ENTITY_CACHE[$guid] = $entity;
113
}
114
115
/**
116
 * Retrieve a entity from the cache.
117
 *
118
 * @param int $guid The guid
119
 *
120
 * @return \ElggEntity|bool false if entity not cached, or not fully loaded
121
 * @see _elgg_cache_entity()
122
 * @see _elgg_invalidate_cache_for_entity()
123
 * @access private
124
 */
125
function _elgg_retrieve_cached_entity($guid) {
126
	global $ENTITY_CACHE;
127
128
	if (isset($ENTITY_CACHE[$guid])) {
129
		if ($ENTITY_CACHE[$guid]->isFullyLoaded()) {
130
			return $ENTITY_CACHE[$guid];
131
		}
132
	}
133
134
	return false;
135
}
136
137
/**
138
 * Return the id for a given subtype.
139
 *
140
 * \ElggEntity objects have a type and a subtype.  Subtypes
141
 * are defined upon creation and cannot be changed.
142
 *
143
 * Plugin authors generally don't need to use this function
144
 * unless writing their own SQL queries.  Use {@link \ElggEntity::getSubtype()}
145
 * to return the string subtype.
146
 *
147
 * @internal Subtypes are stored in the entity_subtypes table.  There is a foreign
148
 * key in the entities table.
149
 *
150
 * @param string $type    Type
151
 * @param string $subtype Subtype
152
 *
153
 * @return int Subtype ID
154
 * @see get_subtype_from_id()
155
 * @access private
156
 */
157
function get_subtype_id($type, $subtype) {
158
	return _elgg_services()->subtypeTable->getId($type, $subtype);
159
}
160
161
/**
162
 * Gets the denormalized string for a given subtype ID.
163
 *
164
 * @param int $subtype_id Subtype ID from database
165
 * @return string|false Subtype name, false if subtype not found
166
 * @see get_subtype_id()
167
 * @access private
168
 */
169
function get_subtype_from_id($subtype_id) {
170
	return _elgg_services()->subtypeTable->getSubtype($subtype_id);
171
}
172
173
/**
174
 * Retrieve subtype from the cache.
175
 *
176
 * @param string $type
177
 * @param string $subtype
178
 * @return \stdClass|null
179
 *
180
 * @access private
181
 */
182
function _elgg_retrieve_cached_subtype($type, $subtype) {
183
	return _elgg_services()->subtypeTable->retrieveFromCache($type, $subtype);
184
}
185
186
/**
187
 * Fetch all suptypes from DB to local cache.
188
 *
189
 * @access private
190
 */
191
function _elgg_populate_subtype_cache() {
192
	return _elgg_services()->subtypeTable->populateCache();
193
}
194
195
/**
196
 * Return the class name for a registered type and subtype.
197
 *
198
 * Entities can be registered to always be loaded as a certain class
199
 * with add_subtype() or update_subtype(). This function returns the class
200
 * name if found and null if not.
201
 *
202
 * @param string $type    The type
203
 * @param string $subtype The subtype
204
 *
205
 * @return string|null a class name or null
206
 * @see get_subtype_from_id()
207
 * @see get_subtype_class_from_id()
208
 * @access private
209
 */
210
function get_subtype_class($type, $subtype) {
211
	return _elgg_services()->subtypeTable->getClass($type, $subtype);
212
}
213
214
/**
215
 * Returns the class name for a subtype id.
216
 *
217
 * @param int $subtype_id The subtype id
218
 *
219
 * @return string|null
220
 * @see get_subtype_class()
221
 * @see get_subtype_from_id()
222
 * @access private
223
 */
224
function get_subtype_class_from_id($subtype_id) {
225
	return _elgg_services()->subtypeTable->getClassFromId($subtype_id);
226
}
227
228
/**
229
 * Register \ElggEntities with a certain type and subtype to be loaded as a specific class.
230
 *
231
 * By default entities are loaded as one of the 4 parent objects: site, user, object, or group.
232
 * If you subclass any of these you can register the classname with add_subtype() so
233
 * it will be loaded as that class automatically when retrieved from the database with
234
 * {@link get_entity()}.
235
 *
236
 * @warning This function cannot be used to change the class for a type-subtype pair.
237
 * Use update_subtype() for that.
238
 *
239
 * @param string $type    The type you're subtyping (site, user, object, or group)
240
 * @param string $subtype The subtype
241
 * @param string $class   Optional class name for the object
242
 *
243
 * @return int
244
 * @see update_subtype()
245
 * @see remove_subtype()
246
 * @see get_entity()
247
 */
248
function add_subtype($type, $subtype, $class = "") {
249
	return _elgg_services()->subtypeTable->add($type, $subtype, $class);
250
}
251
252
/**
253
 * Removes a registered \ElggEntity type, subtype, and classname.
254
 *
255
 * @warning You do not want to use this function. If you want to unregister
256
 * a class for a subtype, use update_subtype(). Using this function will
257
 * permanently orphan all the objects created with the specified subtype.
258
 *
259
 * @param string $type    Type
260
 * @param string $subtype Subtype
261
 *
262
 * @return bool
263
 * @see add_subtype()
264
 * @see update_subtype()
265
 */
266
function remove_subtype($type, $subtype) {
267
	return _elgg_services()->subtypeTable->remove($type, $subtype);
268
}
269
270
/**
271
 * Update a registered \ElggEntity type, subtype, and class name
272
 *
273
 * @param string $type    Type
274
 * @param string $subtype Subtype
275
 * @param string $class   Class name to use when loading this entity
276
 *
277
 * @return bool
278
 */
279
function update_subtype($type, $subtype, $class = '') {
280
	return _elgg_services()->subtypeTable->update($type, $subtype, $class);
281
}
282
283
/**
284
 * Determine if a given user can write to an entity container.
285
 *
286
 * An entity can be a container for any other entity by setting the
287
 * container_guid.  container_guid can differ from owner_guid.
288
 *
289
 * A plugin hook container_permissions_check:$entity_type is emitted to allow granular
290
 * access controls in plugins.
291
 *
292
 * @param int    $user_guid      The user guid, or 0 for logged in user.
293
 * @param int    $container_guid The container, or 0 for the current page owner.
294
 * @param string $type           The type of entity we want to create (default: 'all')
295
 * @param string $subtype        The subtype of the entity we want to create (default: 'all')
296
 *
297
 * @return bool
298
 */
299
function can_write_to_container($user_guid = 0, $container_guid = 0, $type = 'all', $subtype = 'all') {
300
	$container_guid = (int)$container_guid;
301
	if (!$container_guid) {
302
		$container_guid = elgg_get_page_owner_guid();
303
	}
304
305
	$container = get_entity($container_guid);
306
307
	$user_guid = (int)$user_guid;
308
	if ($user_guid == 0) {
309
		$user = elgg_get_logged_in_user_entity();
310
		$user_guid = elgg_get_logged_in_user_guid();
311
	} else {
312
		$user = get_user($user_guid);
313
		if (!$user) {
314
			return false;
315
		}
316
	}
317
318
	$return = false;
319
	if ($container) {
320
		// If the user can edit the container, they can also write to it
321
		if ($container->canEdit($user_guid)) {
322
			$return = true;
323
		}
324
	}
325
326
	// See if anyone else has anything to say
327
	return elgg_trigger_plugin_hook(
328
			'container_permissions_check',
329
			$type,
330
			array(
331
				'container' => $container,
332
				'user' => $user,
333
				'subtype' => $subtype
334
			),
335
			$return);
336
}
337
338
/**
339
 * Returns a database row from the entities table.
340
 *
341
 * @tip Use get_entity() to return the fully loaded entity.
342
 *
343
 * @warning This will only return results if a) it exists, b) you have access to it.
344
 * see {@link _elgg_get_access_where_sql()}.
345
 *
346
 * @param int $guid The GUID of the object to extract
347
 *
348
 * @return \stdClass|false
349
 * @see entity_row_to_elggstar()
350
 * @access private
351
 */
352
function get_entity_as_row($guid) {
353
	return _elgg_services()->entityTable->getRow($guid);
354
}
355
356
/**
357
 * Create an Elgg* object from a given entity row.
358
 *
359
 * Handles loading all tables into the correct class.
360
 *
361
 * @param \stdClass $row The row of the entry in the entities table.
362
 *
363
 * @return \ElggEntity|false
364
 * @see get_entity_as_row()
365
 * @see add_subtype()
366
 * @see get_entity()
367
 * @access private
368
 *
369
 * @throws ClassException|InstallationException
370
 */
371
function entity_row_to_elggstar($row) {
372
	return _elgg_services()->entityTable->rowToElggStar($row);
373
}
374
375
/**
376
 * Loads and returns an entity object from a guid.
377
 *
378
 * @param int $guid The GUID of the entity
379
 *
380
 * @return \ElggEntity The correct Elgg or custom object based upon entity type and subtype
381
 */
382
function get_entity($guid) {
383 1
	return _elgg_services()->entityTable->get($guid);
384
}
385
386
/**
387
 * Does an entity exist?
388
 *
389
 * This function checks for the existence of an entity independent of access
390
 * permissions. It is useful for situations when a user cannot access an entity
391
 * and it must be determined whether entity has been deleted or the access level
392
 * has changed.
393
 *
394
 * @param int $guid The GUID of the entity
395
 *
396
 * @return bool
397
 * @since 1.8.0
398
 */
399
function elgg_entity_exists($guid) {
400
	return _elgg_services()->entityTable->exists($guid);
401
}
402
403
/**
404
 * Enable an entity.
405
 *
406
 * @param int  $guid      GUID of entity to enable
407
 * @param bool $recursive Recursively enable all entities disabled with the entity?
408
 *
409
 * @return bool
410
 * @since 1.9.0
411
 */
412
function elgg_enable_entity($guid, $recursive = true) {
413
	return _elgg_services()->entityTable->enable($guid, $recursive);
414
}
415
416
/**
417
 * Returns an array of entities with optional filtering.
418
 *
419
 * Entities are the basic unit of storage in Elgg.  This function
420
 * provides the simplest way to get an array of entities.  There
421
 * are many options available that can be passed to filter
422
 * what sorts of entities are returned.
423
 *
424
 * @tip To output formatted strings of entities, use {@link elgg_list_entities()} and
425
 * its cousins.
426
 *
427
 * @tip Plural arguments can be written as singular if only specifying a
428
 * single element.  ('type' => 'object' vs 'types' => array('object')).
429
 *
430
 * @param array $options Array in format:
431
 *
432
 * 	types => null|STR entity type (type IN ('type1', 'type2')
433
 *           Joined with subtypes by AND. See below)
434
 *
435
 * 	subtypes => null|STR entity subtype (SQL: subtype IN ('subtype1', 'subtype2))
436
 *              Use ELGG_ENTITIES_NO_VALUE to match the default subtype.
437
 *              Use ELGG_ENTITIES_ANY_VALUE to match any subtype.
438
 *
439
 * 	type_subtype_pairs => null|ARR (array('type' => 'subtype'))
440
 *                        array(
441
 *                            'object' => array('blog', 'file'), // All objects with subtype of 'blog' or 'file'
442
 *                            'user' => ELGG_ENTITY_ANY_VALUE, // All users irrespective of subtype
443
 *                        );
444
 *
445
 *	guids => null|ARR Array of entity guids
446
 *
447
 * 	owner_guids => null|ARR Array of owner guids
448
 *
449
 * 	container_guids => null|ARR Array of container_guids
450
 *
451
 * 	site_guids => null (current_site)|ARR Array of site_guid
452
 *
453
 * 	order_by => null (time_created desc)|STR SQL order by clause
454
 *
455
 *  reverse_order_by => BOOL Reverse the default order by clause
456
 *
457
 * 	limit => null (from settings)|INT SQL limit clause (0 means no limit)
458
 *
459
 * 	offset => null (0)|INT SQL offset clause
460
 *
461
 * 	created_time_lower => null|INT Created time lower boundary in epoch time
462
 *
463
 * 	created_time_upper => null|INT Created time upper boundary in epoch time
464
 *
465
 * 	modified_time_lower => null|INT Modified time lower boundary in epoch time
466
 *
467
 * 	modified_time_upper => null|INT Modified time upper boundary in epoch time
468
 *
469
 * 	count => true|false return a count instead of entities
470
 *
471
 * 	wheres => array() Additional where clauses to AND together
472
 *
473
 * 	joins => array() Additional joins
474
 *
475
 * 	preload_owners => bool (false) If set to true, this function will preload
476
 * 					  all the owners of the returned entities resulting in better
477
 * 					  performance when displaying entities owned by several users
478
 *
479
 * 	callback => string A callback function to pass each row through
480
 *
481
 * 	distinct => bool (true) If set to false, Elgg will drop the DISTINCT clause from
482
 *				the MySQL query, which will improve performance in some situations.
483
 *				Avoid setting this option without a full understanding of the underlying
484
 *				SQL query Elgg creates.
485
 *
486
 * @return mixed If count, int. If not count, array. false on errors.
487
 * @since 1.7.0
488
 * @see elgg_get_entities_from_metadata()
489
 * @see elgg_get_entities_from_relationship()
490
 * @see elgg_get_entities_from_access_id()
491
 * @see elgg_get_entities_from_annotations()
492
 * @see elgg_list_entities()
493
 */
494
function elgg_get_entities(array $options = array()) {
495
	return _elgg_services()->entityTable->getEntities($options);
496
}
497
498
/**
499
 * Return entities from an SQL query generated by elgg_get_entities.
500
 *
501
 * @param string    $sql
502
 * @param \ElggBatch $batch
503
 * @return \ElggEntity[]
504
 *
505
 * @access private
506
 * @throws LogicException
507
 */
508
function _elgg_fetch_entities_from_sql($sql, \ElggBatch $batch = null) {
509
	return _elgg_services()->entityTable->fetchFromSql($sql, $batch);
510
}
511
512
/**
513
 * Returns SQL where clause for type and subtype on main entity table
514
 *
515
 * @param string     $table    Entity table prefix as defined in SELECT...FROM entities $table
516
 * @param null|array $types    Array of types or null if none.
517
 * @param null|array $subtypes Array of subtypes or null if none
518
 * @param null|array $pairs    Array of pairs of types and subtypes
519
 *
520
 * @return false|string
521
 * @since 1.7.0
522
 * @access private
523
 */
524
function _elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pairs) {
525
	return _elgg_services()->entityTable->getEntityTypeSubtypeWhereSql($table, $types, $subtypes, $pairs);
526
}
527
528
/**
529
 * Returns SQL where clause for owner and containers.
530
 *
531
 * @param string     $column Column name the guids should be checked against. Usually
532
 *                           best to provide in table.column format.
533
 * @param null|array $guids  Array of GUIDs.
534
 *
535
 * @return false|string
536
 * @since 1.8.0
537
 * @access private
538
 */
539
function _elgg_get_guid_based_where_sql($column, $guids) {
540
	return _elgg_services()->entityTable->getGuidBasedWhereSql($column, $guids);
541
}
542
543
/**
544
 * Returns SQL where clause for entity time limits.
545
 *
546
 * @param string   $table              Entity table prefix as defined in
547
 *                                     SELECT...FROM entities $table
548
 * @param null|int $time_created_upper Time created upper limit
549
 * @param null|int $time_created_lower Time created lower limit
550
 * @param null|int $time_updated_upper Time updated upper limit
551
 * @param null|int $time_updated_lower Time updated lower limit
552
 *
553
 * @return false|string false on fail, string on success.
554
 * @since 1.7.0
555
 * @access private
556
 */
557
function _elgg_get_entity_time_where_sql($table, $time_created_upper = null,
558
		$time_created_lower = null, $time_updated_upper = null, $time_updated_lower = null) {
559
	return _elgg_services()->entityTable->getEntityTimeWhereSql($table,
560
		$time_created_upper, $time_created_lower, $time_updated_upper, $time_updated_lower);
561
}
562
563
/**
564
 * Returns a string of rendered entities.
565
 *
566
 * Displays list of entities with formatting specified by the entity view.
567
 *
568
 * @tip Pagination is handled automatically.
569
 *
570
 * @note Internal: This also provides the views for elgg_view_annotation().
571
 *
572
 * @note Internal: If the initial COUNT query returns 0, the $getter will not be called again.
573
 *
574
 * @param array    $options Any options from $getter options plus:
575
 *                   item_view => STR Optional. Alternative view used to render list items
576
 *                   full_view => BOOL Display full view of entities (default: false)
577
 *                   list_type => STR 'list' or 'gallery'
578
 *                   list_type_toggle => BOOL Display gallery / list switch
579
 *                   pagination => BOOL Display pagination links
580
 *                   no_results => STR|Closure Message to display when there are no entities
581
 *
582
 * @param callback $getter  The entity getter function to use to fetch the entities.
583
 * @param callback $viewer  The function to use to view the entity list.
584
 *
585
 * @return string
586
 * @since 1.7
587
 * @see elgg_get_entities()
588
 * @see elgg_view_entity_list()
589
 */
590
function elgg_list_entities(array $options = array(), $getter = 'elgg_get_entities',
591
	$viewer = 'elgg_view_entity_list') {
592
593
	global $autofeed;
594
	$autofeed = true;
595
596
	$offset_key = isset($options['offset_key']) ? $options['offset_key'] : 'offset';
597
598
	$defaults = array(
599
		'offset' => (int) max(get_input($offset_key, 0), 0),
600
		'limit' => (int) max(get_input('limit', elgg_get_config('default_limit')), 0),
601
		'full_view' => false,
602
		'list_type_toggle' => false,
603
		'pagination' => true,
604
		'no_results' => '',
605
	);
606
607
	$options = array_merge($defaults, $options);
608
609
	// backward compatibility
610 View Code Duplication
	if (isset($options['view_type_toggle'])) {
611
		elgg_deprecated_notice("Option 'view_type_toggle' deprecated by 'list_type_toggle' in elgg_list* functions", 1.9);
612
		$options['list_type_toggle'] = $options['view_type_toggle'];
613
	}
614
615
	$options['count'] = true;
616
	$count = call_user_func($getter, $options);
617
618
	if ($count > 0) {
619
		$options['count'] = false;
620
		$entities = call_user_func($getter, $options);
621
	} else {
622
		$entities = array();
623
	}
624
625
	$options['count'] = $count;
626
627
	return call_user_func($viewer, $entities, $options);
628
}
629
630
/**
631
 * Gets entities based upon attributes in secondary tables.
632
 * Also accepts all options available to elgg_get_entities(),
633
 * elgg_get_entities_from_metadata(), and elgg_get_entities_from_relationship().
634
 *
635
 * @warning requires that the entity type be specified and there can only be one
636
 * type.
637
 *
638
 * @see elgg_get_entities
639
 * @see elgg_get_entities_from_metadata
640
 * @see elgg_get_entities_from_relationship
641
 *
642
 * @param array $options Array in format:
643
 *
644
 * 	attribute_name_value_pairs => ARR (
645
 *                                   'name' => 'name',
646
 *                                   'value' => 'value',
647
 *                                   'operand' => '=', (optional)
648
 *                                   'case_sensitive' => false (optional)
649
 *                                  )
650
 * 	                             If multiple values are sent via
651
 *                               an array ('value' => array('value1', 'value2')
652
 *                               the pair's operand will be forced to "IN".
653
 *
654
 * 	attribute_name_value_pairs_operator => null|STR The operator to use for combining
655
 *                                        (name = value) OPERATOR (name = value); default is AND
656
 *
657
 * @return \ElggEntity[]|mixed If count, int. If not count, array. false on errors.
658
 * @since 1.9.0
659
 * @throws InvalidArgumentException
660
 * @todo Does not support ordering by attributes or using an attribute pair shortcut like this ('title' => 'foo')
661
 */
662
function elgg_get_entities_from_attributes(array $options = array()) {
663
	return _elgg_services()->entityTable->getEntitiesFromAttributes($options);
664
}
665
666
/**
667
 * Get the join and where clauses for working with entity attributes
668
 *
669
 * @return false|array False on fail, array('joins', 'wheres')
670
 * @since 1.9.0
671
 * @access private
672
 * @throws InvalidArgumentException
673
 */
674
function _elgg_get_entity_attribute_where_sql(array $options = array()) {
675
	return _elgg_services()->entityTable->getEntityAttributeWhereSql($options);
676
}
677
678
/**
679
 * Returns a list of months in which entities were updated or created.
680
 *
681
 * @tip Use this to generate a list of archives by month for when entities were added or updated.
682
 *
683
 * @todo document how to pass in array for $subtype
684
 *
685
 * @warning Months are returned in the form YYYYMM.
686
 *
687
 * @param string $type           The type of entity
688
 * @param string $subtype        The subtype of entity
689
 * @param int    $container_guid The container GUID that the entities belong to
690
 * @param int    $site_guid      The site GUID
691
 * @param string $order_by       Order_by SQL order by clause
692
 *
693
 * @return array|false Either an array months as YYYYMM, or false on failure
694
 */
695
function get_entity_dates($type = '', $subtype = '', $container_guid = 0, $site_guid = 0,
696
		$order_by = 'time_created') {
697
	return _elgg_services()->entityTable->getDates(
698
		$type, $subtype, $container_guid, $site_guid, $order_by);
699
}
700
701
/**
702
 * Registers an entity type and subtype as a public-facing entity that should
703
 * be shown in search and by {@link elgg_list_registered_entities()}.
704
 *
705
 * @warning Entities that aren't registered here will not show up in search.
706
 *
707
 * @tip Add a language string item:type:subtype to make sure the items are display properly.
708
 *
709
 * @param string $type    The type of entity (object, site, user, group)
710
 * @param string $subtype The subtype to register (may be blank)
711
 *
712
 * @return bool Depending on success
713
 * @see get_registered_entity_types()
714
 */
715
function elgg_register_entity_type($type, $subtype = null) {
716
	global $CONFIG;
717
718
	$type = strtolower($type);
719
	if (!in_array($type, $CONFIG->entity_types)) {
720
		return false;
721
	}
722
723
	if (!isset($CONFIG->registered_entities)) {
724
		$CONFIG->registered_entities = array();
725
	}
726
727
	if (!isset($CONFIG->registered_entities[$type])) {
728
		$CONFIG->registered_entities[$type] = array();
729
	}
730
731
	if ($subtype) {
0 ignored issues
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...
732
		$CONFIG->registered_entities[$type][] = $subtype;
733
	}
734
735
	return true;
736
}
737
738
/**
739
 * Unregisters an entity type and subtype as a public-facing type.
740
 *
741
 * @warning With a blank subtype, it unregisters that entity type including
742
 * all subtypes. This must be called after all subtypes have been registered.
743
 *
744
 * @param string $type    The type of entity (object, site, user, group)
745
 * @param string $subtype The subtype to register (may be blank)
746
 *
747
 * @return bool Depending on success
748
 * @see elgg_register_entity_type()
749
 */
750
function elgg_unregister_entity_type($type, $subtype = null) {
751
	global $CONFIG;
752
753
	$type = strtolower($type);
754
	if (!in_array($type, $CONFIG->entity_types)) {
755
		return false;
756
	}
757
758
	if (!isset($CONFIG->registered_entities)) {
759
		return false;
760
	}
761
762
	if (!isset($CONFIG->registered_entities[$type])) {
763
		return false;
764
	}
765
766
	if ($subtype) {
0 ignored issues
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...
767
		if (in_array($subtype, $CONFIG->registered_entities[$type])) {
768
			$key = array_search($subtype, $CONFIG->registered_entities[$type]);
769
			unset($CONFIG->registered_entities[$type][$key]);
770
		} else {
771
			return false;
772
		}
773
	} else {
774
		unset($CONFIG->registered_entities[$type]);
775
	}
776
777
	return true;
778
}
779
780
/**
781
 * Returns registered entity types and subtypes
782
 *
783
 * @param string $type The type of entity (object, site, user, group) or blank for all
784
 *
785
 * @return array|false Depending on whether entities have been registered
786
 * @see elgg_register_entity_type()
787
 */
788
function get_registered_entity_types($type = null) {
789
	global $CONFIG;
790
791
	if (!isset($CONFIG->registered_entities)) {
792
		return false;
793
	}
794
	if ($type) {
0 ignored issues
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...
795
		$type = strtolower($type);
796
	}
797
	if (!empty($type) && empty($CONFIG->registered_entities[$type])) {
798
		return false;
799
	}
800
801
	if (empty($type)) {
802
		return $CONFIG->registered_entities;
803
	}
804
805
	return $CONFIG->registered_entities[$type];
806
}
807
808
/**
809
 * Returns if the entity type and subtype have been registered with {@link elgg_register_entity_type()}.
810
 *
811
 * @param string $type    The type of entity (object, site, user, group)
812
 * @param string $subtype The subtype (may be blank)
813
 *
814
 * @return bool Depending on whether or not the type has been registered
815
 */
816
function is_registered_entity_type($type, $subtype = null) {
817
	global $CONFIG;
818
819
	if (!isset($CONFIG->registered_entities)) {
820
		return false;
821
	}
822
823
	$type = strtolower($type);
824
825
	// @todo registering a subtype implicitly registers the type.
826
	// see #2684
827
	if (!isset($CONFIG->registered_entities[$type])) {
828
		return false;
829
	}
830
831
	if ($subtype && !in_array($subtype, $CONFIG->registered_entities[$type])) {
0 ignored issues
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...
832
		return false;
833
	}
834
	return true;
835
}
836
837
/**
838
 * Returns a viewable list of entities based on the registered types.
839
 *
840
 * @see elgg_view_entity_list
841
 *
842
 * @param array $options Any elgg_get_entity() options plus:
843
 *
844
 * 	full_view => BOOL Display full view entities
845
 *
846
 * 	list_type_toggle => BOOL Display gallery / list switch
847
 *
848
 * 	allowed_types => true|ARRAY True to show all types or an array of valid types.
849
 *
850
 * 	pagination => BOOL Display pagination links
851
 *
852
 * @return string A viewable list of entities
853
 * @since 1.7.0
854
 */
855
function elgg_list_registered_entities(array $options = array()) {
856
	global $autofeed;
857
	$autofeed = true;
858
859
	$defaults = array(
860
		'full_view' => false,
861
		'allowed_types' => true,
862
		'list_type_toggle' => false,
863
		'pagination' => true,
864
		'offset' => 0,
865
		'types' => array(),
866
		'type_subtype_pairs' => array(),
867
	);
868
869
	$options = array_merge($defaults, $options);
870
871
	// backward compatibility
872 View Code Duplication
	if (isset($options['view_type_toggle'])) {
873
		elgg_deprecated_notice("Option 'view_type_toggle' deprecated by 'list_type_toggle' in elgg_list* functions", 1.9);
874
		$options['list_type_toggle'] = $options['view_type_toggle'];
875
	}
876
877
	$types = get_registered_entity_types();
878
879
	foreach ($types as $type => $subtype_array) {
880
		if (in_array($type, $options['allowed_types']) || $options['allowed_types'] === true) {
881
			// you must explicitly register types to show up in here and in search for objects
882
			if ($type == 'object') {
883
				if (is_array($subtype_array) && count($subtype_array)) {
884
					$options['type_subtype_pairs'][$type] = $subtype_array;
885
				}
886
			} else {
887
				if (is_array($subtype_array) && count($subtype_array)) {
888
					$options['type_subtype_pairs'][$type] = $subtype_array;
889
				} else {
890
					$options['type_subtype_pairs'][$type] = ELGG_ENTITIES_ANY_VALUE;
891
				}
892
			}
893
		}
894
	}
895
896
	if (!empty($options['type_subtype_pairs'])) {
897
		$count = elgg_get_entities(array_merge(array('count' => true), $options));
898
		if ($count > 0) {
899
			$entities = elgg_get_entities($options);
900
		} else {
901
			$entities = array();
902
		}
903
	} else {
904
		$count = 0;
905
		$entities = array();
906
	}
907
908
	$options['count'] = $count;
909
	return elgg_view_entity_list($entities, $options);
910
}
911
912
/**
913
 * Checks if $entity is an \ElggEntity and optionally for type and subtype.
914
 *
915
 * @tip Use this function in actions and views to check that you are dealing
916
 * with the correct type of entity.
917
 *
918
 * @param mixed  $entity  Entity
919
 * @param string $type    Entity type
920
 * @param string $subtype Entity subtype
921
 * @param string $class   Class name
922
 *
923
 * @return bool
924
 * @since 1.8.0
925
 */
926
function elgg_instanceof($entity, $type = null, $subtype = null, $class = null) {
927 3
	$return = ($entity instanceof \ElggEntity);
928
929 3
	if ($type) {
0 ignored issues
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...
930
		/* @var \ElggEntity $entity */
931
		$return = $return && ($entity->getType() == $type);
932
	}
933
934 3
	if ($subtype) {
0 ignored issues
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...
935
		$return = $return && ($entity->getSubtype() == $subtype);
936
	}
937
938 3
	if ($class) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class 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...
939
		$return = $return && ($entity instanceof $class);
940
	}
941
942 3
	return $return;
943
}
944
945
/**
946
 * Update the last_action column in the entities table for $guid.
947
 *
948
 * @warning This is different to time_updated.  Time_updated is automatically set,
949
 * while last_action is only set when explicitly called.
950
 *
951
 * @param int $guid   Entity annotation|relationship action carried out on
952
 * @param int $posted Timestamp of last action
953
 *
954
 * @return bool
955
 * @access private
956
 */
957
function update_entity_last_action($guid, $posted = null) {
958
	return _elgg_services()->entityTable->updateLastAction($guid, $posted);
959
}
960
961
/**
962
 * Runs unit tests for the entity objects.
963
 *
964
 * @param string $hook   unit_test
965
 * @param string $type   system
966
 * @param array  $value  Array of tests
967
 *
968
 * @return array
969
 * @access private
970
 */
971
function _elgg_entities_test($hook, $type, $value) {
972
	global $CONFIG;
973
	$value[] = $CONFIG->path . 'engine/tests/ElggEntityTest.php';
974
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreAttributeLoaderTest.php';
975
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesTest.php';
976
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromAnnotationsTest.php';
977
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromMetadataTest.php';
978
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromPrivateSettingsTest.php';
979
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromRelationshipTest.php';
980
	$value[] = $CONFIG->path . 'engine/tests/ElggCoreGetEntitiesFromAttributesTest.php';
981
	$value[] = $CONFIG->path . 'engine/tests/ElggEntityPreloaderIntegrationTest.php';
982
	return $value;
983
}
984
985
/**
986
 * Entities init function; establishes the default entity page handler
987
 *
988
 * @return void
989
 * @elgg_event_handler init system
990
 * @access private
991
 */
992
function _elgg_entities_init() {
993
	elgg_register_plugin_hook_handler('unit_test', 'system', '_elgg_entities_test');
994
}
995
996
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
997
	$events->registerHandler('init', 'system', '_elgg_entities_init');
998
};
999