1<?php 2/** 3 * Procedural code for creating, loading, and modifying \ElggEntity objects. 4 */ 5 6/** 7 * Return the class name registered as a constructor for an entity of a given type and subtype 8 * 9 * @see elgg_set_entity_type() 10 * 11 * @param string $type The type 12 * @param string $subtype The subtype 13 * 14 * @return string 15 */ 16function elgg_get_entity_class($type, $subtype) { 17 return _elgg_services()->entityTable->getEntityClass($type, $subtype); 18} 19 20/** 21 * Sets class constructor name for entities with given type and subtype 22 * 23 * By default entities are loaded as one of the 4 parent objects: 24 * - site: ElggSite 25 * - user: ElggUser 26 * - object: ElggObject 27 * - group: ElggGroup 28 * 29 * Entity classes for subtypes should extend the base class for entity type, 30 * e.g. ElggBlog must extend ElggObject 31 * 32 * @param string $type Entity type 33 * @param string $subtype Entity subtype 34 * @param string $class Class name for the object 35 * Can be empty to reset previously declared class name 36 * 37 * @return void 38 */ 39function elgg_set_entity_class($type, $subtype, $class = "") { 40 _elgg_services()->entityTable->setEntityClass($type, $subtype, $class); 41} 42 43 44/** 45 * Returns a database row from the entities table. 46 * 47 * @tip Use get_entity() to return the fully loaded entity. 48 * 49 * @warning This will only return results if a) it exists, b) you have access to it. 50 * see {@link _elgg_get_access_where_sql()}. 51 * 52 * @param int $guid The GUID of the object to extract 53 * 54 * @return \stdClass|false 55 * @see entity_row_to_elggstar() 56 * @internal 57 */ 58function get_entity_as_row($guid) { 59 return _elgg_services()->entityTable->getRow($guid); 60} 61 62/** 63 * Create an Elgg* object from a given entity row. 64 * 65 * Handles loading all tables into the correct class. 66 * 67 * @param \stdClass $row The row of the entry in the entities table. 68 * 69 * @return \ElggEntity|false 70 * @see get_entity_as_row() 71 * @see get_entity() 72 * @internal 73 * 74 * @throws ClassException|InstallationException 75 */ 76function entity_row_to_elggstar($row) { 77 return _elgg_services()->entityTable->rowToElggStar($row); 78} 79 80/** 81 * Loads and returns an entity object from a guid. 82 * 83 * @param int $guid The GUID of the entity 84 * 85 * @return \ElggEntity|false The correct Elgg or custom object based upon entity type and subtype 86 */ 87function get_entity($guid) { 88 if ($guid == 1) { 89 return _elgg_config()->site; 90 } 91 return _elgg_services()->entityTable->get($guid); 92} 93 94/** 95 * Does an entity exist? 96 * 97 * This function checks for the existence of an entity independent of access 98 * permissions. It is useful for situations when a user cannot access an entity 99 * and it must be determined whether entity has been deleted or the access level 100 * has changed. 101 * 102 * @param int $guid The GUID of the entity 103 * 104 * @return bool 105 * @since 1.8.0 106 */ 107function elgg_entity_exists($guid) { 108 return _elgg_services()->entityTable->exists($guid); 109} 110 111/** 112 * Get the current site entity 113 * 114 * @return \ElggSite 115 * @since 1.8.0 116 */ 117function elgg_get_site_entity() { 118 return _elgg_config()->site; 119} 120 121/** 122 * Fetches/counts entities or performs a calculation on their properties 123 * 124 * Note that you can use singulars for most options, e.g. $options['type'] will be normalized to $options['types'] 125 * 126 * ------------------------ 127 * TYPE SUBTYPE CONSTRAINTS 128 * ------------------------ 129 * 130 * Filter entities by their type and subtype 131 * 132 * @option string[] $types 133 * @option string[] $subtypes 134 * @option string[] $type_subtype_pairs 135 * 136 * <code> 137 * $options['types'] = ['object']; 138 * $options['subtypes'] = ['blog', 'file']; 139 * $options['type_subtype_pairs'] = [ 140 * 'object' => ['blog', 'file'], 141 * 'group' => [], // all group subtypes 142 * 'user' => null, // all user subtypes 143 * ]; 144 * </code> 145 * 146 * ---------------- 147 * GUID CONSTRAINTS 148 * ---------------- 149 * 150 * Filter entities by their guid, owner or container 151 * 152 * @option int[]|ElggEntity[] $guids 153 * @option int[]|ElggEntity[] $owner_guids 154 * @option int[]|ElggEntity[] $container_guids 155 * 156 * ---------------- 157 * TIME CONSTRAINTS 158 * ---------------- 159 * 160 * Filter entities that were created, updated or last acted on within certain bounds 161 * 162 * @option DateTime|string|int $created_after 163 * @option DateTime|string|int $created_before 164 * @option DateTime|string|int $updated_after 165 * @option DateTime|string|int $updated_before 166 * @option DateTime|string|int $last_action_after 167 * @option DateTime|string|int $last_action_before 168 * 169 * <code> 170 * $options['created_after'] = '-1 year'; 171 * $options['created_before'] = 'now'; 172 * </code> 173 * 174 * ------------------ 175 * ACCESS CONSTRAINTS 176 * ------------------ 177 * 178 * Filter entities by their access_id attribute. Note that this filter apply to entities that the user has access to. 179 * You can ignore access system using {@link elgg_call()} 180 * 181 * @option int[] $access_id 182 * 183 * ---------------- 184 * LIMIT AND OFFSET 185 * ---------------- 186 * 187 * This options are used for paginating lists of entities 188 * 189 * @option int $limit 190 * @option int $offset 191 * 192 * -------------------- 193 * METADATA CONSTRAINTS 194 * -------------------- 195 * 196 * Filter entities by their metadata and attributes 197 * 198 * The following options will be merged and applied as a metadata pair to @options['metadata_name_value_pairs'] 199 * Note metadata names can contain attributes names and will be resolved automatically during query building. 200 * @option int[] $metadata_ids 201 * @option string[] $metadata_names 202 * @option mixed $metadata_values 203 * @option DateTime|string|int $metadata_created_after 204 * @option DateTime|string|int $metadata_created_before 205 * @option bool $metadata_case_sensitive 206 * 207 * Metadata name value pairs will be joined by the boolean specified in $metadata_name_value_pairs_operator 208 * @option array $metadata_name_value_pairs 209 * @option string $metadata_name_value_pairs_operator 210 * 211 * In addition to metadata name value pairs, you can specify search pair, which will be merged using OR boolean 212 * and will filter entities regardless of metadata name value pairs and their operator 213 * @warning During normalization, search name value pairs will ignore properties under metadata_ namespace, that is 214 * you can not use metadata_ids, metadata_created_before, metadata_created_after, metadata_case_sensitive 215 * to constrain search pairs. You will need to pass these properties for each individual search pair, 216 * as seen in the example below 217 * 218 * @option array $search_name_value_pairs 219 * 220 * <code> 221 * // Search for entities with: 222 * // status of draft or unsaved_draft 223 * // AND index greater than 5 224 * // AND (title/description containing the word hello OR tags containing the word world) 225 * $options['metadata_name_value_pairs'] = [ 226 * [ 227 * 'name' => 'status', 228 * 'value' => ['draft', 'unsaved_draft'], 229 * 'operand' => 'IN', 230 * 'created_after' => '-1 day', 231 * ], 232 * [ 233 * 'name' => 'index', 234 * 'value' => 5, 235 * 'operand' => '>=', 236 * 'type' => ELGG_VALUE_INTEGER, 237 * ] 238 * ]; 239 * $options['search_name_value_pairs'] = [ 240 * [ 241 * 'name' => ['title', 'description'], 242 * 'value' => '%hello%', 243 * 'operand' => 'LIKE', 244 * 'case_sensitive' => false, 245 * ], 246 * [ 247 * // 'ids' => [55, 56, 57, 58, 59, 60], // only search these 5 metadata rows 248 * 'name' => 'tags', 249 * 'value' => '%world%', 250 * 'operand' => 'LIKE', 251 * 'case_sensitive' => false, 252 * 'created_after' => '-1 day', 253 * 'created_before' => 'now', 254 * ], 255 * ]; 256 * </code> 257 * 258 * ---------------------- 259 * ANNOTATION CONSTRAINTS 260 * ---------------------- 261 * 262 * Filter entities by their annotations 263 * 264 * The following options will be merged and applied as an annotation pair to @options['annotation_name_value_pairs'] 265 * @option int[] $annotation_ids 266 * @option string[] $annotation_names 267 * @option mixed $annotation_values 268 * @option bool $annotation_case_sensitive 269 * @option DateTime|string|int $annotation_created_after 270 * @option DateTime|string|int $annotation_created_before 271 * @option int[]|ElggEntity[] $annotation_owner_guids 272 * @option int[]|ElggEntity[] $annotation_access_ids 273 * 274 * Annotation name value pairs will be joined by the boolean specified in $annotation_name_value_pairs_operator 275 * @option array $annotation_name_value_pairs 276 * @option string $annotation_name_value_pairs_operator 277 ** 278 * <code> 279 * $options['annotation_name_value_pairs'] = [ 280 * [ 281 * 'name' => 'likes', 282 * 'created_after' => '-1 day', 283 * ], 284 * [ 285 * 'name' => 'rating', 286 * 'value' => 5, 287 * 'operand' => '>=', 288 * 'type' => ELGG_VALUE_INTEGER, 289 * ], 290 * [ 291 * 'name' => 'review', 292 * 'value' => '%awesome%', 293 * 'operand' => 'LIKE', 294 * 'type' => ELGG_VALUE_STRING, 295 * ] 296 * ]; 297 * </code> 298 * 299 * ------------------------ 300 * RELATIONSHIP CONSTRAINTS 301 * ------------------------ 302 * 303 * Filter entities by their relationships 304 * 305 * The following options will be merged and applied as a relationship pair to $options['relationship_name_value_pairs'] 306 * @option int[] $relationship_ids 307 * @option string[] $relationship 308 * @option int[]|ElggEntity[] $relationship_guid 309 * @option bool $inverse_relationship 310 * @option DateTime|string|int $relationship_created_after 311 * @option DateTime|string|int $relationship_created_before 312 * @option string $relationship_join_on Column name in the name main table 313 * 314 * @option array $relationship_pairs 315 * 316 * <code> 317 * // Get all entities that user with guid 25 has friended or been friended by 318 * $options['relationship_pairs'] = [ 319 * [ 320 * 'relationship' => 'friend', 321 * 'relationship_guid' => 25, 322 * 'inverse_relationship' => true, 323 * ], 324 * [ 325 * 'relationship' => 'friend', 326 * 'relationship_guid' => 25, 327 * 'inverse_relationship' => false, 328 * ], 329 * ]; 330 * </code> 331 * 332 * ---------------------------- 333 * PRIVATE SETTINGS CONSTRAINTS 334 * ---------------------------- 335 * 336 * Filter entities by their private settings 337 * 338 * The following options will be merged and applied as a private_setting pair to 339 * $options['private_setting_name_value_pairs'] 340 * @option int[] $private_setting_ids 341 * @option string[] $private_setting_names 342 * @option mixed $private_setting_values 343 * @option bool $private_setting_case_sensitive 344 * 345 * Private name value pairs will be joined by the boolean specified in $private_setting_name_value_pairs_operator 346 * @option array $private_setting_name_value_pairs 347 * @option string $private_setting_name_value_pairs_operator 348 * 349 * Setting names in all pairs can be namespaced using the prefix 350 * @option string $private_setting_name_prefix 351 * 352 * <code> 353 * $options['private_setting_name_value_pairs'] = [ 354 * [ 355 * 'name' => 'handler', 356 * 'value' => ['admin', 'dashboard'], 357 * 'operand' => 'IN', 358 * ], 359 * ]; 360 * </code> 361 * 362 * ------- 363 * SORTING 364 * ------- 365 * 366 * You can specify sorting options using ONE of the following options 367 * 368 * NOTE: Some order by options only work when fetching entities and not from 369 * derived function (eg elgg_get_annotations, elgg_get_relationships) 370 * 371 * Order by a calculation performed on annotation name value pairs 372 * $option array annotation_sort_by_calculation e.g. avg, max, min, sum 373 * 374 * Order by value of a specific annotation 375 * @option array $order_by_annotation 376 * 377 * Order by value of a specific metadata/attribute 378 * @option array $order_by_metadata 379 * 380 * Order by arbitrary clauses 381 * @option array $order_by 382 * 383 * <code> 384 * $options['order_by_metadata'] = [ 385 * 'name' => 'priority', 386 * 'direction' => 'DESC', 387 * 'as' => 'integer', 388 * ]; 389 * $options['order_by_annotation'] = [ 390 * 'name' => 'priority', 391 * 'direction' => 'DESC', 392 * 'as' => 'integer', 393 * ]; 394 * 395 * $sort_by = new \Elgg\Database\Clauses\EntitySortByClause(); 396 * $sort_by->property = 'private'; 397 * $sort_by->property_type = 'private_setting'; 398 * $sort_by->join_type = 'left'; 399 * 400 * $fallback = new \Elgg\Database\Clauses\OrderByClause('e.time_created', 'desc'); 401 * 402 * $options['order_by'] = [ 403 * $sort_by, 404 * $fallback, 405 * ]; 406 * </code> 407 * 408 * ----------------- 409 * COUNT/CALCULATION 410 * ----------------- 411 * 412 * Performs a calculation on a set of entities that match all of the criteria 413 * If any of these are specific, the return of this function will be int or float 414 * 415 * Return total number of entities 416 * @option bool $count 417 * 418 * Perform a calculation on a set of entity's annotations using a numeric sql function 419 * If specified, the number of annotation name value pairs can not be more than 1, or they must be merged using OR 420 * operator 421 * @option string $annotation_calculation e.g. avg, max, min, sum 422 * 423 * Perform a calculation on a set of entity's metadat using a numeric sql function 424 * If specified, the number of metadata name value pairs can not be more than 1, or they must be merged using OR 425 * operator 426 * @option string $metadata_calculation e.g. avg, max, min, sum 427 * 428 * ---------- 429 * SQL SELECT 430 * ---------- 431 * 432 * @option array $selects 433 * <code> 434 * $options['selects'] = [ 435 * 'e.last_action AS last_action', 436 * function(QueryBulder $qb, $main_alias) { 437 * $joined_alias = $qb->joinMetadataTable($main_alias, 'guid', 'status'); 438 * return "$joined_alias.value AS status"; 439 * } 440 * ]; 441 * </code> 442 * 443 * -------- 444 * SQL JOIN 445 * -------- 446 * 447 * @option array $joins 448 * <code> 449 * $on = function(QueryBuilder $qb, $joined_alias, $main_alias) { 450 * return $qb->compare("$joined_alias.user_guid", '=', "$main_alias.guid"); 451 * }; 452 * $options['joins'] = [ 453 * new JoinClause('access_collections_membership', 'acm', $on); 454 * ]; 455 * </code> 456 * 457 * ---------- 458 * SQL GROUPS 459 * ---------- 460 * 461 * @option array $group_by 462 * @option array $having 463 * 464 * <code> 465 * $options['group_by'] = [ 466 * function(QueryBuilder $qb, $main_alias) { 467 * return "$main_alias.guid"; 468 * } 469 * ]; 470 * $options['having'] = [ 471 * function(QueryBuilder $qb, $main_alias) { 472 * return $qb->compare("$main_alias.guid", '>=', 50, ELGG_VALUE_INTEGER); 473 * } 474 * ]; 475 * </code> 476 * 477 * --------- 478 * SQL WHERE 479 * --------- 480 * 481 * @option array $where 482 * <code> 483 * $options['wheres'] = [ 484 * function(QueryBuilder $qb, $main_alias) { 485 * return $qb->merge([ 486 * $qb->compare("$main_alias.guid", '>=', 50, ELGG_VALUE_INTEGER), 487 * $qb->compare("$main_alias.guid", '<=', 250, ELGG_VALUE_INTEGER), 488 * ], 'OR'); 489 * } 490 * ]; 491 * </code> 492 * 493 * -------------- 494 * RESULT OPTIONS 495 * -------------- 496 * 497 * @option bool $distinct If set to false, Elgg will drop the DISTINCT clause from 498 * the MySQL query, which will improve performance in some situations. 499 * Avoid setting this option without a full understanding of the underlying 500 * SQL query Elgg creates. 501 * Default: true 502 * @option callable|false $callback A callback function to pass each row through 503 * Default: entity_row_to_elggstar 504 * @option bool $preload_owners If set to true, this function will preload 505 * all the owners of the returned entities resulting in better 506 * performance when displaying entities owned by several users 507 * Default: false 508 * @option bool $preload_containers If set to true, this function will preload 509 * all the containers of the returned entities resulting in better 510 * performance when displaying entities contained by several users/groups 511 * Default: false 512 * @option bool $preload_private_settings If set to true, this function will preload 513 * all the private settings of the returned entities resulting in better 514 * performance when displaying entities where private settings are often used, such as widgets 515 * Default: false 516 * @option bool $batch If set to true, an Elgg\BatchResult object will be returned instead of an array. 517 * Default: false 518 * @option bool $batch_inc_offset If "batch" is used, this tells the batch to increment the offset 519 * on each fetch. This must be set to false if you delete the batched results. 520 * Default: true 521 * @option int $batch_size If "batch" is used, this is the number of entities/rows to pull in before 522 * requesting more. 523 * Default: 25 524 * 525 * 526 * @see elgg_list_entities() 527 * @see \Elgg\Database\LegacyQueryOptionsAdapter 528 * 529 * @param array $options Options 530 * 531 * @return \ElggEntity[]|int|mixed If count, int. Otherwise an array or an Elgg\BatchResult. false on errors. 532 * 533 * @since 1.7.0 534 */ 535function elgg_get_entities(array $options = []) { 536 return \Elgg\Database\Entities::find($options); 537} 538 539/** 540 * Returns a count of entities. 541 * 542 * @param array $options the same options as elgg_get_entities() but forces 'count' to true 543 * 544 * @return int 545 */ 546function elgg_count_entities(array $options = []) { 547 $options['count'] = true; 548 549 return (int) elgg_get_entities($options); 550} 551 552/** 553 * Returns a string of rendered entities. 554 * 555 * Displays list of entities with formatting specified by the entity view. 556 * 557 * @tip Pagination is handled automatically. 558 * 559 * @note Internal: This also provides the views for elgg_view_annotation(). 560 * 561 * @note Internal: If the initial COUNT query returns 0, the $getter will not be called again. 562 * 563 * @param array $options Any options from $getter options plus: 564 * item_view => STR Optional. Alternative view used to render list items 565 * full_view => BOOL Display full view of entities (default: false) 566 * list_type => STR 'list', 'gallery', or 'table' 567 * columns => ARR instances of Elgg\Views\TableColumn if list_type is "table" 568 * list_type_toggle => BOOL Display gallery / list switch 569 * pagination => BOOL Display pagination links 570 * no_results => STR|true for default notfound text|Closure Message to display when there are no entities 571 * 572 * @param callable $getter The entity getter function to use to fetch the entities. 573 * @param callable $viewer The function to use to view the entity list. 574 * 575 * @return string 576 * @since 1.7 577 * @see elgg_get_entities() 578 * @see elgg_view_entity_list() 579 */ 580function elgg_list_entities(array $options = [], $getter = 'elgg_get_entities', $viewer = 'elgg_view_entity_list') { 581 582 $offset_key = isset($options['offset_key']) ? $options['offset_key'] : 'offset'; 583 584 $defaults = [ 585 'offset' => (int) max(get_input($offset_key, 0), 0), 586 'limit' => (int) max(get_input('limit', _elgg_config()->default_limit), 0), 587 'full_view' => false, 588 'list_type_toggle' => false, 589 'pagination' => true, 590 'no_results' => '', 591 'preload_owners' => true, 592 'preload_containers' => true, 593 ]; 594 595 $options = array_merge($defaults, $options); 596 597 $options['register_rss_link'] = elgg_extract('register_rss_link', $options, elgg_extract('pagination', $options)); 598 if ($options['register_rss_link']) { 599 elgg_register_rss_link(); 600 } 601 602 if ($options['no_results'] === true) { 603 $options['no_results'] = elgg_echo('notfound'); 604 } 605 606 $options['count'] = false; 607 $entities = call_user_func($getter, $options); 608 $options['count'] = is_array($entities) ? count($entities) : 0; 609 610 if (!empty($entities) || !empty($options['offset'])) { 611 $count_needed = true; 612 if (!$options['pagination']) { 613 $count_needed = false; 614 } elseif (!$options['offset'] && !$options['limit']) { 615 $count_needed = false; 616 } elseif (($options['count'] < (int) $options['limit']) && !$options['offset']) { 617 $count_needed = false; 618 } 619 620 if ($count_needed) { 621 $options['count'] = true; 622 623 $options['count'] = (int) call_user_func($getter, $options); 624 } 625 } 626 627 return call_user_func($viewer, $entities, $options); 628} 629 630/** 631 * Returns a list of months in which entities were updated or created. 632 * 633 * @tip Use this to generate a list of archives by month for when entities were added or updated. 634 * 635 * @warning Months are returned in the form YYYYMM. 636 * 637 * @param array $options all entity options supported by {@see elgg_get_entities()} 638 * 639 * @return array|false Either an array months as YYYYMM, or false on failure 640 * @since 3.0 641 */ 642function elgg_get_entity_dates(array $options = []) { 643 return \Elgg\Database\Entities::with($options)->getDates(); 644} 645 646/** 647 * Registers an entity type and subtype as a public-facing entity that should 648 * be shown in search and by {@link elgg_list_registered_entities()}. 649 * 650 * @warning Entities that aren't registered here will not show up in search. 651 * 652 * @tip Add a language string item:type:subtype and collection:type:subtype to make sure the items are display properly. 653 * 654 * @param string $type The type of entity (object, site, user, group) 655 * @param string $subtype The subtype to register (may be blank) 656 * 657 * @return bool Depending on success 658 * @see get_registered_entity_types() 659 */ 660function elgg_register_entity_type($type, $subtype = null) { 661 $type = strtolower($type); 662 if (!in_array($type, \Elgg\Config::getEntityTypes())) { 663 return false; 664 } 665 666 $entities = _elgg_config()->registered_entities; 667 if (empty($entities)) { 668 $entities = []; 669 } 670 671 if (!isset($entities[$type])) { 672 $entities[$type] = []; 673 } 674 675 if ($subtype) { 676 if (in_array($subtype, $entities[$type])) { 677 // subtype already registered 678 return true; 679 } 680 681 $entities[$type][] = $subtype; 682 } 683 684 _elgg_config()->registered_entities = $entities; 685 686 return true; 687} 688 689/** 690 * Unregisters an entity type and subtype as a public-facing type. 691 * 692 * @warning With a blank subtype, it unregisters that entity type including 693 * all subtypes. This must be called after all subtypes have been registered. 694 * 695 * @param string $type The type of entity (object, site, user, group) 696 * @param string $subtype The subtype to register (may be blank) 697 * 698 * @return bool Depending on success 699 * @see elgg_register_entity_type() 700 */ 701function elgg_unregister_entity_type($type, $subtype = null) { 702 $type = strtolower($type); 703 if (!in_array($type, \Elgg\Config::getEntityTypes())) { 704 return false; 705 } 706 707 $entities = _elgg_config()->registered_entities; 708 if (empty($entities)) { 709 return false; 710 } 711 712 if (!isset($entities[$type])) { 713 return false; 714 } 715 716 if ($subtype) { 717 if (in_array($subtype, $entities[$type])) { 718 $key = array_search($subtype, $entities[$type]); 719 unset($entities[$type][$key]); 720 } else { 721 return false; 722 } 723 } else { 724 unset($entities[$type]); 725 } 726 727 _elgg_config()->registered_entities = $entities; 728 return true; 729} 730 731/** 732 * Returns registered entity types and subtypes 733 * 734 * @param string $type The type of entity (object, site, user, group) or blank for all 735 * 736 * @return array|false Depending on whether entities have been registered 737 * @see elgg_register_entity_type() 738 */ 739function get_registered_entity_types($type = null) { 740 $registered_entities = _elgg_config()->registered_entities; 741 if (empty($registered_entities)) { 742 return false; 743 } 744 745 if ($type) { 746 $type = strtolower($type); 747 } 748 749 if (!empty($type) && !isset($registered_entities[$type])) { 750 return false; 751 } 752 753 if (empty($type)) { 754 return $registered_entities; 755 } 756 757 return $registered_entities[$type]; 758} 759 760/** 761 * Returns if the entity type and subtype have been registered with {@link elgg_register_entity_type()}. 762 * 763 * @param string $type The type of entity (object, site, user, group) 764 * @param string $subtype The subtype (may be blank) 765 * 766 * @return bool Depending on whether or not the type has been registered 767 */ 768function is_registered_entity_type($type, $subtype = null) { 769 $registered_entities = _elgg_config()->registered_entities; 770 if (empty($registered_entities)) { 771 return false; 772 } 773 774 $type = strtolower($type); 775 776 // @todo registering a subtype implicitly registers the type. 777 // see #2684 778 if (!isset($registered_entities[$type])) { 779 return false; 780 } 781 782 if ($subtype && !in_array($subtype, $registered_entities[$type])) { 783 return false; 784 } 785 return true; 786} 787 788/** 789 * Checks options for the existing of site_guid or site_guids contents and reports a warning if found 790 * 791 * @param array $options array of options to check 792 * 793 * @return void 794 */ 795function _elgg_check_unsupported_site_guid(array $options = []) { 796 $site_guid = elgg_extract('site_guid', $options, elgg_extract('site_guids', $options)); 797 if ($site_guid === null) { 798 return; 799 } 800 801 $backtrace = debug_backtrace(); 802 // never show this call. 803 array_shift($backtrace); 804 805 if (!empty($backtrace[0]['class'])) { 806 $warning = "Passing site_guid or site_guids to the method {$backtrace[0]['class']}::{$backtrace[0]['file']} is not supported."; 807 $warning .= "Please update your usage of the method."; 808 } else { 809 $warning = "Passing site_guid or site_guids to the function {$backtrace[0]['function']} in {$backtrace[0]['file']} is not supported."; 810 $warning .= "Please update your usage of the function."; 811 } 812 813 _elgg_services()->logger->warning($warning); 814} 815