Skip to content

Commit

Permalink
fix(river): optional joins now added to river and metastring queries …
Browse files Browse the repository at this point in the history
…after default joins to allow default joins to be referenced by optional joins.

    When building more complex queries there may be a need to reference table aliases introduced by the default joins in _elgg_get_metastring_based_objects and elgg_get_river. This fix ensures that the default join table aliases are available when defining custom joins - which is a requirement for building effective and efficient queries.

    Fixes Elgg#8580
  • Loading branch information
ura soul committed May 31, 2016
1 parent aa1cb04 commit c8881c8
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 21 deletions.
21 changes: 12 additions & 9 deletions engine/lib/metastrings.php
Expand Up @@ -215,7 +215,7 @@ function _elgg_get_metastring_based_objects($options) {
$options['joins'] = array($options['joins']);
}

$joins = $options['joins'];
$joins = array();
$joins[] = "JOIN {$db_prefix}entities e ON n_table.entity_guid = e.guid";

// evaluate selects
Expand All @@ -232,7 +232,7 @@ function _elgg_get_metastring_based_objects($options) {
$custom_callback = ($options['callback'] == 'row_to_elggmetadata'
|| $options['callback'] == 'row_to_elggannotation');
$is_calculation = $options['metastring_calculation'] ? true : false;

if ($custom_callback || $is_calculation) {
$joins[] = "JOIN {$db_prefix}metastrings n on n_table.name_id = n.id";
$joins[] = "JOIN {$db_prefix}metastrings v on n_table.value_id = v.id";
Expand All @@ -241,13 +241,8 @@ function _elgg_get_metastring_based_objects($options) {
$selects[] = 'v.string as value';
}

foreach ($joins as $i => $join) {
if ($join === false) {
return false;
} elseif (empty($join)) {
unset($joins[$i]);
}
}
// add optional joins
$joins = array_merge($joins, $options['joins']);

// metastrings
$metastring_clauses = _elgg_get_metastring_sql('n_table', $options['metastring_names'],
Expand Down Expand Up @@ -284,6 +279,14 @@ function _elgg_get_metastring_based_objects($options) {
$query = "SELECT {$options['metastring_calculation']}(v.string) as calculation FROM {$db_prefix}$type n_table";
}

foreach ($joins as $i => $join) {
if ($join === false) {
return false;
} elseif (empty($join)) {
unset($joins[$i]);
}
}

// remove identical join clauses
$joins = array_unique($joins);

Expand Down
31 changes: 19 additions & 12 deletions engine/lib/river.php
Expand Up @@ -341,15 +341,19 @@ function elgg_get_river(array $options = array()) {
if ($options['posted_time_upper'] && is_int($options['posted_time_upper'])) {
$wheres[] = "rv.posted <= {$options['posted_time_upper']}";
}

if (!access_get_show_hidden_status()) {
$wheres[] = "rv.enabled = 'yes'";
}

$joins = $options['joins'];

$dbprefix = elgg_get_config('dbprefix');

// joins
$joins = array();
$joins[] = "JOIN {$dbprefix}entities oe ON rv.object_guid = oe.guid";

// LEFT JOIN is used because all river items do not necessarily have target
$joins[] = "LEFT JOIN {$dbprefix}entities te ON rv.target_guid = te.guid";

Expand All @@ -365,6 +369,9 @@ function elgg_get_river(array $options = array()) {
}
}

// add optional joins
$joins = array_merge($joins, $options['joins']);

// see if any functions failed
// remove empty strings on successful functions
foreach ($wheres as $i => $where) {
Expand All @@ -380,12 +387,12 @@ function elgg_get_river(array $options = array()) {

if (!$options['count']) {
$distinct = $options['distinct'] ? "DISTINCT" : "";

$query = "SELECT $distinct rv.* FROM {$CONFIG->dbprefix}river rv ";
} else {
// note: when DISTINCT unneeded, it's slightly faster to compute COUNT(*) than IDs
$count_expr = $options['distinct'] ? "DISTINCT rv.id" : "*";

$query = "SELECT COUNT($count_expr) as total FROM {$CONFIG->dbprefix}river rv ";
}

Expand Down Expand Up @@ -760,46 +767,46 @@ function _elgg_river_test($hook, $type, $value) {

/**
* Disable river entries that reference a disabled entity as subject/object/target
*
*
* @param string $event The event 'disable'
* @param string $type Type of entity being disabled 'all'
* @param mixed $entity The entity being disabled
* @return boolean
* @access private
*/
function _elgg_river_disable($event, $type, $entity) {

if (!elgg_instanceof($entity)) {
return true;
}

$dbprefix = elgg_get_config('dbprefix');
$query = <<<QUERY
UPDATE {$dbprefix}river AS rv
SET rv.enabled = 'no'
WHERE (rv.subject_guid = {$entity->guid} OR rv.object_guid = {$entity->guid} OR rv.target_guid = {$entity->guid});
QUERY;

update_data($query);
return true;
}


/**
* Enable river entries that reference a re-enabled entity as subject/object/target
*
*
* @param string $event The event 'enable'
* @param string $type Type of entity being enabled 'all'
* @param mixed $entity The entity being enabled
* @return boolean
* @access private
*/
function _elgg_river_enable($event, $type, $entity) {

if (!elgg_instanceof($entity)) {
return true;
}

$dbprefix = elgg_get_config('dbprefix');
$query = <<<QUERY
UPDATE {$dbprefix}river AS rv
Expand All @@ -808,9 +815,9 @@ function _elgg_river_enable($event, $type, $entity) {
LEFT JOIN {$dbprefix}entities AS te ON te.guid = rv.target_guid
SET rv.enabled = 'yes'
WHERE (
(se.enabled = 'yes' OR se.guid IS NULL) AND
(se.enabled = 'yes' OR se.guid IS NULL) AND
(oe.enabled = 'yes' OR oe.guid IS NULL) AND
(te.enabled = 'yes' OR te.guid IS NULL)
(te.enabled = 'yes' OR te.guid IS NULL)
)
AND (se.guid = {$entity->guid} OR oe.guid = {$entity->guid} OR te.guid = {$entity->guid});
QUERY;
Expand Down

0 comments on commit c8881c8

Please sign in to comment.