Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements #4453: entities/river queries alterable by hooks (WIP) #6256

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions docs/guides/hooks-list.rst
Expand Up @@ -149,6 +149,52 @@ Views
**head, page**
In elgg_view_page(), filters $vars['head']

Named query hooks
=================

If a string is passed in for ``$options["query_name"]`` in some query functions, the ``$options`` parameter
will be filtered through one of the following hooks.

**entities:options, <query_name>**
In elgg_get_entities(), filters the ``$options`` argument if ``$options["query_name"]`` is present.

With this hook the following query names are used in Elgg core:

- ``blog/(all|friends|owner|group|archive)``
- ``bookmarks/(all|owner|friends)``
- ``custom_index/(blog|bookmark|file|member|group)``
- ``discussion/(all|owner|latest)``
- ``file/(all|friends|owner)``
- ``friends(of)``
- ``group_module/(blog|bookmark|discussion|file|page)``
- ``groups/(all|owner|member)``
- ``members/(all|popular)``
- ``messages/(inbox|sent)``
- ``pages/(all|friends|owner)``
- ``sidebar/(featured_groups|group_members|comments_block)``
- ``thewire/(all|friends|owner|thread)``

**river:options, <query_name>**
In elgg_get_river(), filters the ``$options`` argument if ``$options["query_name"]`` is present.

With this hook the following query names are used in Elgg core:

- ``activity/(all|friends|owner|group)``
- ``group_module/activity``

**annotations:options, <query_name>**
In elgg_get_annotations(), filters the ``$options`` argument if ``$options["query_name"]`` is present.

With this hook the following query names are used in Elgg core:

- ``pages/history``
- ``sidebar/page_history``

E.g. to show 50 river entries on the site-wide activity page, register for the
``[river:options, activity/all]`` hook, and in your handler set ``$return_value['limit'] = 50;``

Note: Often the hook will be called twice, the first time for a COUNT query.

Other
=====

Expand Down
11 changes: 10 additions & 1 deletion engine/lib/annotations.php
Expand Up @@ -198,13 +198,22 @@ function update_annotation($annotation_id, $name, $value, $value_type, $owner_gu
* objects.
* See the docs for elgg_get_entities_from_annotation_calculation()
* for the proper use of the "calculation" option.
*
* query_name => STR If provided, $options will be filtered by the plugin hook
* ["annotations:options", <query_name>]
*
* @return ElggAnnotation[]|mixed
* @since 1.8.0
*/
function elgg_get_annotations(array $options = array()) {

// allow modification of options before the defaults are merged in
if (!empty($options['query_name']) && is_string($options['query_name'])) {
$params = array(
'options' => $options,
);
$options = elgg_trigger_plugin_hook("annotations:options", $options['query_name'], $params, $options);
}

// @todo remove support for count shortcut - see #4393
if (isset($options['__egefac']) && $options['__egefac']) {
unset($options['__egefac']);
Expand Down
65 changes: 38 additions & 27 deletions engine/lib/entities.php
Expand Up @@ -764,6 +764,9 @@ function elgg_enable_entity($guid, $recursive = true) {
*
* joins => array() Additional joins
*
* query_name => string If provided, $options will be filtered by the plugin
* hook ["entities:options", <query_name>]
*
* callback => string A callback function to pass each row through
*
* @return mixed If count, int. If not count, array. false on errors.
Expand All @@ -777,34 +780,42 @@ function elgg_enable_entity($guid, $recursive = true) {
function elgg_get_entities(array $options = array()) {
global $CONFIG;

// allow modification of options before the defaults are merged in
if (!empty($options['query_name']) && is_string($options['query_name'])) {
$params = array(
'options' => $options,
);
$options = elgg_trigger_plugin_hook("entities:options", $options['query_name'], $params, $options);
}

$defaults = array(
'types' => ELGG_ENTITIES_ANY_VALUE,
'subtypes' => ELGG_ENTITIES_ANY_VALUE,
'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE,

'guids' => ELGG_ENTITIES_ANY_VALUE,
'owner_guids' => ELGG_ENTITIES_ANY_VALUE,
'container_guids' => ELGG_ENTITIES_ANY_VALUE,
'site_guids' => $CONFIG->site_guid,

'modified_time_lower' => ELGG_ENTITIES_ANY_VALUE,
'modified_time_upper' => ELGG_ENTITIES_ANY_VALUE,
'created_time_lower' => ELGG_ENTITIES_ANY_VALUE,
'created_time_upper' => ELGG_ENTITIES_ANY_VALUE,

'reverse_order_by' => false,
'order_by' => 'e.time_created desc',
'group_by' => ELGG_ENTITIES_ANY_VALUE,
'limit' => 10,
'offset' => 0,
'count' => false,
'selects' => array(),
'wheres' => array(),
'joins' => array(),

'callback' => 'entity_row_to_elggstar',

'__ElggBatch' => null,
'types' => ELGG_ENTITIES_ANY_VALUE,
'subtypes' => ELGG_ENTITIES_ANY_VALUE,
'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE,

'guids' => ELGG_ENTITIES_ANY_VALUE,
'owner_guids' => ELGG_ENTITIES_ANY_VALUE,
'container_guids' => ELGG_ENTITIES_ANY_VALUE,
'site_guids' => $CONFIG->site_guid,

'modified_time_lower' => ELGG_ENTITIES_ANY_VALUE,
'modified_time_upper' => ELGG_ENTITIES_ANY_VALUE,
'created_time_lower' => ELGG_ENTITIES_ANY_VALUE,
'created_time_upper' => ELGG_ENTITIES_ANY_VALUE,

'reverse_order_by' => false,
'order_by' => 'e.time_created desc',
'group_by' => ELGG_ENTITIES_ANY_VALUE,
'limit' => 10,
'offset' => 0,
'count' => false,
'selects' => array(),
'wheres' => array(),
'joins' => array(),

'callback' => 'entity_row_to_elggstar',

'__ElggBatch' => null,
);

$options = array_merge($defaults, $options);
Expand Down
11 changes: 11 additions & 0 deletions engine/lib/river.php
Expand Up @@ -279,12 +279,23 @@ function elgg_delete_river(array $options = array()) {
* order_by => STR Order by clause (rv.posted desc)
* group_by => STR Group by clause
*
* query_name => STR If provided, $options will be filtered by the
* plugin hook ["river:options", <query_name>]
*
* @return array|int
* @since 1.8.0
*/
function elgg_get_river(array $options = array()) {
global $CONFIG;

// allow modification of options before the defaults are merged in
if (!empty($options['query_name']) && is_string($options['query_name'])) {
$params = array(
'options' => $options,
);
$options = elgg_trigger_plugin_hook("river:options", $options['query_name'], $params, $options);
}

$defaults = array(
'ids' => ELGG_ENTITIES_ANY_VALUE,

Expand Down
23 changes: 23 additions & 0 deletions engine/tests/ElggCoreAnnotationAPITest.php
Expand Up @@ -145,4 +145,27 @@ public function testElggAnnotationExists() {
$this->assertTrue($e->delete());
$this->assertFalse(elgg_annotation_exists($guid, 'test_annotation'));
}

public function testNamedQueriesFilterOptions() {
$query_name = __FUNCTION__;
elgg_register_plugin_hook_handler('annotations:options', $query_name, __CLASS__ . '::namedQueryHandler');

// create in case no annotations
$user = elgg_get_logged_in_user_entity();
$id = $user->annotate('test', 'test');

$annotations = elgg_get_annotations(array(
'query_name' => $query_name,
'limit' => 1,
));
$this->assertIsA($annotations[0], 'stdClass');

elgg_delete_annotation_by_id($id);
}

public static function namedQueryHandler($hook, $type, $options, $param) {
return array_merge($options, array(
'callback' => '',
));
}
}
17 changes: 17 additions & 0 deletions engine/tests/ElggCoreGetEntitiesTest.php
Expand Up @@ -979,4 +979,21 @@ public function testEGEEmptySubtypePlurality() {
$entities = elgg_get_entities($options);
$this->assertTrue(is_array($entities));
}

public function testNamedQueriesFilterOptions() {
$query_name = __FUNCTION__;
elgg_register_plugin_hook_handler('entities:options', $query_name, __CLASS__ . '::namedQueryHandler');

$entities = elgg_get_entities(array(
'query_name' => $query_name,
'limit' => 1,
));
$this->assertIsA($entities[0], 'stdClass');
}

public static function namedQueryHandler($hook, $type, $options, $param) {
return array_merge($options, array(
'callback' => '',
));
}
}
27 changes: 27 additions & 0 deletions engine/tests/ElggCoreRiverAPITest.php
Expand Up @@ -98,4 +98,31 @@ public function testElggTypeSubtypeWhereSQL() {
$result = _elgg_get_river_type_subtype_where_sql('rv', $types, $subtypes, null);
$this->assertIdentical($result, "((rv.type = 'object') AND ((rv.subtype = 'blog') OR (rv.subtype = 'file')))");
}

public function testNamedQueriesFilterOptions() {
$query_name = __FUNCTION__;
elgg_register_plugin_hook_handler('river:options', $query_name, __CLASS__ . '::namedQueryHandler');

// create in case river is empty
$user = elgg_get_logged_in_user_entity();
$id = elgg_create_river_item(array(
'view' => 'river/relationship/friend/create',
'action_type' => 'create',
'subject_guid' => $user->guid,
'object_guid' => $user->guid,
));

$items = elgg_get_river(array(
'query_name' => $query_name,
));
$this->assertTrue(is_int($items));

elgg_delete_river(array('id' => $id));
}

public static function namedQueryHandler($hook, $type, $options, $param) {
return array_merge($options, array(
'count' => true,
));
}
}
6 changes: 6 additions & 0 deletions mod/blog/lib/blog.php
Expand Up @@ -84,15 +84,19 @@ function blog_get_page_content_list($container_guid = NULL) {

if ($current_user && ($container_guid == $current_user->guid)) {
$return['filter_context'] = 'mine';
$options['query_name'] = 'blog/owner';
} else if (elgg_instanceof($container, 'group')) {
$return['filter'] = false;
$options['query_name'] = 'blog/group';
} else {
// do not show button or select a tab when viewing someone else's posts
$return['filter_context'] = 'none';
$options['query_name'] = 'blog/owner';
}
} else {
$return['filter_context'] = 'all';
$return['title'] = elgg_echo('blog:title:all_blogs');
$options['query_name'] = 'blog/all';
elgg_pop_breadcrumb();
elgg_push_breadcrumb(elgg_echo('blog:blogs'));
}
Expand Down Expand Up @@ -136,6 +140,7 @@ function blog_get_page_content_friends($user_guid) {
'relationship_guid' => $user_guid,
'relationship_join_on' => 'container_guid',
'no_results' => elgg_echo('blog:none'),
'query_name' => 'blog/friends',
);

$return['content'] = elgg_list_entities_from_relationship($options);
Expand Down Expand Up @@ -178,6 +183,7 @@ function blog_get_page_content_archive($owner_guid, $lower = 0, $upper = 0) {
'subtype' => 'blog',
'full_view' => false,
'no_results' => elgg_echo('blog:none'),
'query_name' => 'blog/archive',
);

if ($owner_guid) {
Expand Down
3 changes: 2 additions & 1 deletion mod/blog/views/default/blog/group_module.php
Expand Up @@ -23,7 +23,8 @@
'limit' => 6,
'full_view' => false,
'pagination' => false,
'no_results' => elgg_echo('blog:none')
'no_results' => elgg_echo('blog:none'),
'query_name' => 'group_module/blog',
);
$content = elgg_list_entities($options);
elgg_pop_context();
Expand Down
1 change: 1 addition & 0 deletions mod/bookmarks/pages/bookmarks/all.php
Expand Up @@ -16,6 +16,7 @@
'full_view' => false,
'view_toggle_type' => false,
'no_results' => elgg_echo('bookmarks:none'),
'query_name' => 'bookmarks/all',
));

$title = elgg_echo('bookmarks:everyone');
Expand Down
1 change: 1 addition & 0 deletions mod/bookmarks/pages/bookmarks/friends.php
Expand Up @@ -25,6 +25,7 @@
'relationship_guid' => $page_owner->guid,
'relationship_join_on' => 'container_guid',
'no_results' => elgg_echo('bookmarks:none'),
'query_name' => 'bookmarks/friends',
));

$params = array(
Expand Down
1 change: 1 addition & 0 deletions mod/bookmarks/pages/bookmarks/owner.php
Expand Up @@ -21,6 +21,7 @@
'full_view' => false,
'view_toggle_type' => false,
'no_results' => elgg_echo('bookmarks:none'),
'query_name' => 'bookmarks/owner',
));

$title = elgg_echo('bookmarks:owner', array($page_owner->name));
Expand Down
1 change: 1 addition & 0 deletions mod/bookmarks/views/default/bookmarks/group_module.php
Expand Up @@ -26,6 +26,7 @@
'full_view' => false,
'pagination' => false,
'no_results' => elgg_echo('bookmarks:none'),
'query_name' => 'group_module/bookmark',
);
$content = elgg_list_entities($options);
elgg_pop_context();
Expand Down
5 changes: 5 additions & 0 deletions mod/custom_index/index.php
Expand Up @@ -18,14 +18,17 @@

//grab the latest 4 blog posts
$list_params['subtype'] = 'blog';
$list_params['query_name'] = 'custom_index/blog';
$blogs = elgg_list_entities($list_params);

//grab the latest bookmarks
$list_params['subtype'] = 'bookmarks';
$list_params['query_name'] = 'custom_index/bookmark';
$bookmarks = elgg_list_entities($list_params);

//grab the latest files
$list_params['subtype'] = 'file';
$list_params['query_name'] = 'custom_index/file';
$files = elgg_list_entities($list_params);

//get the newest members who have an avatar
Expand All @@ -38,11 +41,13 @@
'list_type' => 'gallery',
'gallery_class' => 'elgg-gallery-users',
'size' => 'small',
'query_name' => 'custom_index/member',
));

//newest groups
$list_params['type'] = 'group';
unset($list_params['subtype']);
$list_params['query_name'] = 'custom_index/group';
$groups = elgg_list_entities($list_params);

//grab the login form
Expand Down
1 change: 1 addition & 0 deletions mod/file/pages/file/friends.php
Expand Up @@ -26,6 +26,7 @@
'relationship_guid' => $owner->guid,
'relationship_join_on' => 'container_guid',
'no_results' => elgg_echo("file:none"),
'query_name' => 'file/friends',
));

$sidebar = file_get_type_cloud($owner->guid, true);
Expand Down
1 change: 1 addition & 0 deletions mod/file/pages/file/owner.php
Expand Up @@ -41,6 +41,7 @@
'container_guid' => $owner->guid,
'full_view' => false,
'no_results' => elgg_echo("file:none"),
'query_name' => 'file/owner',
));

$sidebar = file_get_type_cloud(elgg_get_page_owner_guid());
Expand Down
1 change: 1 addition & 0 deletions mod/file/pages/file/world.php
Expand Up @@ -16,6 +16,7 @@
'subtype' => 'file',
'full_view' => false,
'no_results' => elgg_echo("file:none"),
'query_name' => 'file/all',
));

$sidebar = file_get_type_cloud();
Expand Down