Elgg Core Proposal: New Table “entity_list_items”

[This proposal has been superseded with ElggCollection.]

As of Elgg 1.7.4 there’s no way to specify a specific list or ordering of entities for use in an elgg_get_entities query. E.g. one might want to implement:

  • A “featured items” list for a group or user widget. On a group page this could be implemented in “left” and “right” lists for better display control
  • “Sticky” entities in discussion lists, or any other object lists
  • A “favorites” list for each user

Also there’s no good data structure to store such data. One could store a list of entity GUIDs like “123,525,23,734” as metadata, but this would be painful and slow to integrate with the elgg_get_entities function.

One simple solution would be a table entity_list_items with the following columns:

  • key (varchar 32) the unique key of a particular ordered list.
  • entity_guid (int)
  • site_guid (int)
  • reversed_position (int/NULL) the position of the entity when the list is reversed.
  • PRIMARY KEY (key, entity_guid)

To create a list, we first use a predictable algorithm to create a key. E.g. a featured items list for a group might have the key "group:234|featuredItems". If a plugin wished to allow particular users to have desired ordering of any set of objects within any container, the plugin author might use something like this: $key = md5("{$userGuid}|{$containerGuid}|{$type}");

With key in hand, the GUIDs of entities would then be added to the table. If the list is to be ordered, the reversed_position column would be populated such that the last item has value “1”, next to last “2”, et.al.

With a list in place, we can join the table in the elgg_get_entities query:

  • The result set remains limited by access controls
  • Joins would use a clause like:
    [join type] entity_list_items li
      ON li.site_guid = $siteGuid
         AND li.key = '$key'
         AND li.entity_guid = e.guid
  • [INNER] JOIN would limit the result set to entities in the list
  • LEFT JOIN would not limit the result set
  • ORDER BY reversed_position DESC would return entities in their list order. Entities not in the list (if any) would appear at the end.

It might be a good idea to provide core functions to automate the setting of options for elgg_get_entities. E.g.:

function elgg_get_entities_list(
  $options,               // options for elgg_get_entities
  $list_key,              // entity_list_items.key
  $limit_to_list = false, // return only items in the list?
  $reversed = false       // return items in reverse order?
)

This single table model has some properties that are worth considering:

  • No owner or access required to alter any list
  • No defined structure of keys (key collisions could occur)
  • Duplication of string keys in every row

Some of these can be mitigated by requiring use of API functions. Some of these might be seen as a boon to flexibility/coding simplicity.

Heavier option

Alternately each list could have an ElggObject (subtype “entity_list”) with the key as the title. Then in entity_list_items we would replace key and site_guid with the single column entity_list_guid. This would bring an owner, acl, metadata, etc. to each list, but also mean more intensive DB lookups to find the entity_list_guid required in the entity lookup query.

One advantage to this approach is that the metadata could provide hints on the default join type and ordering. The API could take advantage of this, providing a more straightforward extension to elgg_get_entities:

function elgg_get_entities_list(
  $entity_list_guid,
  $options = array(), // options to pass on to elgg_get_entities
)

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.