diff options
-rw-r--r-- | engine/lib/private_settings.php | 497 | ||||
-rw-r--r-- | engine/tests/api/entity_getter_functions.php | 85 |
2 files changed, 387 insertions, 195 deletions
diff --git a/engine/lib/private_settings.php b/engine/lib/private_settings.php index 3f6a10e3d..0d86b93a1 100644 --- a/engine/lib/private_settings.php +++ b/engine/lib/private_settings.php @@ -24,134 +24,68 @@ * @param mixed $container_guid The container(s) GUIDs * * @return array A list of entities. - * @todo deprecate + * @deprecated 1.8 */ function get_entities_from_private_setting($name = "", $value = "", $type = "", $subtype = "", $owner_guid = 0, $order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0, $container_guid = null) { + elgg_deprecated_notice('get_entities_from_private_setting() was deprecated by elgg_get_entities_from_private_setting()!', 1.8); - global $CONFIG; - - if ($subtype === false || $subtype === null || $subtype === 0) { - return false; - } - - $name = sanitise_string($name); - $value = sanitise_string($value); + $options = array(); - if ($order_by == "") { - $order_by = "e.time_created desc"; - } - $order_by = sanitise_string($order_by); - $limit = (int)$limit; - $offset = (int)$offset; - $site_guid = (int) $site_guid; - if ($site_guid == 0) { - $site_guid = $CONFIG->site_guid; - } + $options['private_setting_name'] = $name; + $options['private_setting_value'] = $value; - $where = array(); - - if (is_array($type)) { - $tempwhere = ""; - if (sizeof($type)) { - foreach ($type as $typekey => $subtypearray) { - foreach ($subtypearray as $subtypeval) { - $typekey = sanitise_string($typekey); - if (!empty($subtypeval)) { - if (!$subtypeval = (int) get_subtype_id($typekey, $subtypeval)) { - return false; - } - } else { - $subtypeval = 0; - } - if (!empty($tempwhere)) { - $tempwhere .= " or "; - } - $tempwhere .= "(e.type = '{$typekey}' and e.subtype = {$subtypeval})"; - } - } - } - if (!empty($tempwhere)) { - $where[] = "({$tempwhere})"; - } - } else { - $type = sanitise_string($type); - if ($subtype AND !$subtype = get_subtype_id($type, $subtype)) { - return false; + // set container_guid to owner_guid to emulate old functionality + if ($owner_guid != "") { + if (is_null($container_guid)) { + $container_guid = $owner_guid; } + } - if ($type != "") { - $where[] = "e.type='$type'"; - } - if ($subtype !== "") { - $where[] = "e.subtype=$subtype"; - } + if ($type) { + $options['types'] = $type; } - if ($owner_guid != "") { - if (!is_array($owner_guid)) { - $owner_array = array($owner_guid); - $owner_guid = (int) $owner_guid; - } else if (sizeof($owner_guid) > 0) { - $owner_array = array_map('sanitise_int', $owner_guid); - } - if (is_null($container_guid)) { - $container_guid = $owner_array; - } + if ($subtype) { + $options['subtypes'] = $subtype; } - if ($site_guid > 0) { - $where[] = "e.site_guid = {$site_guid}"; + if ($owner_guid) { + if (is_array($owner_guid)) { + $options['owner_guids'] = $owner_guid; + } else { + $options['owner_guid'] = $owner_guid; + } } - if (!is_null($container_guid)) { + if ($container_guid) { if (is_array($container_guid)) { - foreach ($container_guid as $key => $val) { - $container_guid[$key] = (int) $val; - } - $where[] = "e.container_guid in (" . implode(",", $container_guid) . ")"; + $options['container_guids'] = $container_guid; } else { - $container_guid = (int) $container_guid; - $where[] = "e.container_guid = {$container_guid}"; + $options['container_guid'] = $container_guid; } } - if ($name != "") { - $where[] = "s.name = '$name'"; - } + $options['limit'] = $limit; - if ($value != "") { - $where[] = "s.value='$value'"; + if ($offset) { + $options['offset'] = $offset; } - if (!$count) { - $query = "SELECT distinct e.* - from {$CONFIG->dbprefix}entities e - JOIN {$CONFIG->dbprefix}private_settings s ON e.guid=s.entity_guid where "; - } else { - $query = "SELECT count(distinct e.guid) as total - from {$CONFIG->dbprefix}entities e JOIN {$CONFIG->dbprefix}private_settings s - ON e.guid=s.entity_guid where "; + if ($order_by) { + $options['order_by']; } - foreach ($where as $w) { - $query .= " $w and "; + + if ($site_guid) { + $options['site_guid']; } - // Add access controls - $query .= get_access_sql_suffix('e'); - if (!$count) { - $query .= " order by $order_by"; - if ($limit) { - // Add order and limit - $query .= " limit $offset, $limit"; - } - $dt = get_data($query, "entity_row_to_elggstar"); - return $dt; - } else { - $total = get_data_row($query); - return $total->total; + if ($count) { + $options['count'] = $count; } + + return elgg_get_entities_from_private_settings($options); } /** @@ -169,137 +103,310 @@ $container_guid = null) { * @param mixed $container_guid Container GUID * * @return array A list of entities. - * @todo deprecate + * @deprecated 1.8 */ function get_entities_from_private_setting_multi(array $name, $type = "", $subtype = "", $owner_guid = 0, $order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0, $container_guid = null) { - global $CONFIG; + elgg_deprecated_notice('get_entities_from_private_setting_multi() was deprecated by elgg_get_entities_from_private_setting()!', 1.8); + + $options = array(); - if ($subtype === false || $subtype === null || $subtype === 0) { - return false; + $pairs = array(); + foreach ($name as $setting_name => $setting_value) { + $pairs[] = array('name' => $setting_name, 'value' => $setting_value); } + $options['private_setting_name_value_pairs'] = $pairs; - if ($order_by == "") { - $order_by = "e.time_created desc"; + // set container_guid to owner_guid to emulate old functionality + if ($owner_guid != "") { + if (is_null($container_guid)) { + $container_guid = $owner_guid; + } } - $order_by = sanitise_string($order_by); - $limit = (int)$limit; - $offset = (int)$offset; - $site_guid = (int) $site_guid; - if ($site_guid == 0) { - $site_guid = $CONFIG->site_guid; + + if ($type) { + $options['types'] = $type; } - $where = array(); - - if (is_array($type)) { - $tempwhere = ""; - if (sizeof($type)) { - foreach ($type as $typekey => $subtypearray) { - foreach ($subtypearray as $subtypeval) { - $typekey = sanitise_string($typekey); - if (!empty($subtypeval)) { - if (!$subtypeval = (int) get_subtype_id($typekey, $subtypeval)) { - return false; - } - } else { - $subtypeval = 0; - } - if (!empty($tempwhere)) { - $tempwhere .= " or "; - } - $tempwhere .= "(e.type = '{$typekey}' and e.subtype = {$subtypeval})"; - } - } - } - if (!empty($tempwhere)) { - $where[] = "({$tempwhere})"; + if ($subtype) { + $options['subtypes'] = $subtype; + } + + if ($owner_guid) { + if (is_array($owner_guid)) { + $options['owner_guids'] = $owner_guid; + } else { + $options['owner_guid'] = $owner_guid; } + } - } else { - $type = sanitise_string($type); - if ($subtype AND !$subtype = get_subtype_id($type, $subtype)) { - return false; + if ($container_guid) { + if (is_array($container_guid)) { + $options['container_guids'] = $container_guid; + } else { + $options['container_guid'] = $container_guid; } + } + + $options['limit'] = $limit; + + if ($offset) { + $options['offset'] = $offset; + } + + if ($order_by) { + $options['order_by']; + } - if ($type != "") { - $where[] = "e.type='$type'"; + if ($site_guid) { + $options['site_guid']; + } + + if ($count) { + $options['count'] = $count; + } + + return elgg_get_entities_from_private_settings($options); +} + +/** + * Returns entities based upon private settings. Also accepts all + * options available to elgg_get_entities(). Supports + * the singular option shortcut. + * + * @see elgg_get_entities + * + * @param array $options Array in format: + * + * private_setting_names => NULL|ARR private setting names + * + * private_setting_values => NULL|ARR metadata values + * + * private_setting_name_value_pairs => NULL|ARR ( + * name => 'name', + * value => 'value', + * 'operand' => '=', + * ) + * Currently if multiple values are sent via + * an array (value => array('value1', 'value2') + * the pair's operand will be forced to "IN". + * + * private_setting_name_value_pairs_operator => NULL|STR The operator to use for combining + * (name = value) OPERATOR (name = value); default AND + * + * + * @return array + * @since 1.8.0 + */ +function elgg_get_entities_from_private_settings(array $options = array()) { + $defaults = array( + 'private_setting_names' => ELGG_ENTITIES_ANY_VALUE, + 'private_setting_values' => ELGG_ENTITIES_ANY_VALUE, + 'private_setting_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE, + 'private_setting_name_value_pairs_operator' => 'AND', + ); + + $options = array_merge($defaults, $options); + + $singulars = array('private_setting_name', 'private_setting_value', + 'private_setting_name_value_pair'); + + $options = elgg_normalise_plural_options_array($options, $singulars); + + $clauses = elgg_get_entity_private_settings_where_sql('e', $options['private_setting_names'], + $options['private_setting_values'], $options['private_setting_name_value_pairs'], + $options['private_setting_name_value_pairs_operator']); + + if ($clauses) { + // merge wheres to pass to get_entities() + if (isset($options['wheres']) && !is_array($options['wheres'])) { + $options['wheres'] = array($options['wheres']); + } elseif (!isset($options['wheres'])) { + $options['wheres'] = array(); } - if ($subtype !== "") { - $where[] = "e.subtype=$subtype"; + $options['wheres'] = array_merge($options['wheres'], $clauses['wheres']); + + // merge joins to pass to get_entities() + if (isset($options['joins']) && !is_array($options['joins'])) { + $options['joins'] = array($options['joins']); + } elseif (!isset($options['joins'])) { + $options['joins'] = array(); } + + $options['joins'] = array_merge($options['joins'], $clauses['joins']); } - if ($owner_guid != "") { - if (!is_array($owner_guid)) { - $owner_array = array($owner_guid); - $owner_guid = (int) $owner_guid; - } else if (sizeof($owner_guid) > 0) { - $owner_array = array_map('sanitise_int', $owner_guid); + return elgg_get_entities($options); +} + +/** + * Returns private setting name and value SQL where/join clauses for entities. + * + * @param string $table Entities table name + * @param array|null $names Array of names + * @param array|null $values Array of values + * @param array|null $pairs Array of names / values / operands + * @param string $pair_operator Operator for joining pairs where clauses + * @return array + * @since 1.8.0 + */ +function elgg_get_entity_private_settings_where_sql($table, $names = NULL, $values = NULL, +$pairs = NULL, $pair_operator = 'AND') { + + global $CONFIG; + + // @todo short circuit test + + $return = array ( + 'joins' => array (), + 'wheres' => array(), + ); + + $return['joins'][] = "JOIN {$CONFIG->dbprefix}private_settings ps on + {$table}.guid = ps.entity_guid"; + + $wheres = array(); + + // get names wheres + $names_where = ''; + if ($names !== NULL) { + if (!is_array($names)) { + $names = array($names); } - if (is_null($container_guid)) { - $container_guid = $owner_array; + + $sanitised_names = array(); + foreach ($names as $name) { + $sanitised_names[] = '\'' . sanitise_string($name) . '\''; + } + + $names_str = implode(',', $sanitised_names); + if ($names_str) { + $names_where = "(ps.name IN ($names_str))"; } - } - if ($site_guid > 0) { - $where[] = "e.site_guid = {$site_guid}"; } - if (!is_null($container_guid)) { - if (is_array($container_guid)) { - foreach ($container_guid as $key => $val) { - $container_guid[$key] = (int) $val; + // get values wheres + $values_where = ''; + if ($values !== NULL) { + if (!is_array($values)) { + $values = array($values); + } + + $sanitised_values = array(); + foreach ($values as $value) { + // normalize to 0 + if (!$value) { + $value = 0; } - $where[] = "e.container_guid in (" . implode(",", $container_guid) . ")"; - } else { - $container_guid = (int) $container_guid; - $where[] = "e.container_guid = {$container_guid}"; + $sanitised_values[] = '\'' . sanitise_string($value) . '\''; } - } - if ($name) { - $s_join = ""; - $i = 1; - foreach ($name as $k => $n) { - $k = sanitise_string($k); - $n = sanitise_string($n); - $s_join .= " JOIN {$CONFIG->dbprefix}private_settings s$i ON e.guid=s$i.entity_guid"; - $where[] = "s$i.name = '$k'"; - $where[] = "s$i.value = '$n'"; - $i++; + $values_str = implode(',', $sanitised_values); + if ($values_str) { + $values_where = "(ps.value IN ($values_str))"; } } - if (!$count) { - $query = "SELECT distinct e.* from {$CONFIG->dbprefix}entities e $s_join where "; - } else { - $query = "SELECT count(distinct e.guid) as total - from {$CONFIG->dbprefix}entities e $s_join where "; + if ($names_where && $values_where) { + $wheres[] = "($names_where AND $values_where)"; + } elseif ($names_where) { + $wheres[] = "($names_where)"; + } elseif ($values_where) { + $wheres[] = "($values_where)"; } - foreach ($where as $w) { - $query .= " $w and "; - } + // add pairs which must be in arrays. + if (is_array($pairs)) { + // join counter for incremental joins in pairs + $i = 1; + + // check if this is an array of pairs or just a single pair. + if (isset($pairs['name']) || isset($pairs['value'])) { + $pairs = array($pairs); + } + + $pair_wheres = array(); + + foreach ($pairs as $index => $pair) { + // @todo move this elsewhere? + // support shortcut 'n' => 'v' method. + if (!is_array($pair)) { + $pair = array( + 'name' => $index, + 'value' => $pair + ); + } + + // must have at least a name and value + if (!isset($pair['name']) || !isset($pair['value'])) { + // @todo should probably return false. + continue; + } + + if (isset($pair['operand'])) { + $operand = sanitise_string($pair['operand']); + } else { + $operand = ' = '; + } + + // for comparing + $trimmed_operand = trim(strtolower($operand)); - // Add access controls - $query .= get_access_sql_suffix('e'); + // if the value is an int, don't quote it because str '15' < str '5' + // if the operand is IN don't quote it because quoting should be done already. + if (is_numeric($pair['value'])) { + $value = sanitise_string($pair['value']); + } else if (is_array($pair['value'])) { + $values_array = array(); - if (!$count) { - $query .= " order by $order_by"; - // Add order and limit - if ($limit) { - $query .= " limit $offset, $limit"; + foreach ($pair['value'] as $pair_value) { + if (is_numeric($pair_value)) { + $values_array[] = sanitise_string($pair_value); + } else { + $values_array[] = "'" . sanitise_string($pair_value) . "'"; + } + } + + if ($values_array) { + $value = '(' . implode(', ', $values_array) . ')'; + } + + // @todo allow support for non IN operands with array of values. + // will have to do more silly joins. + $operand = 'IN'; + } else if ($trimmed_operand == 'in') { + $value = "({$pair['value']})"; + } else { + $value = "'" . sanitise_string($pair['value']) . "'"; + } + + $name = sanitise_string($pair['name']); + + // @todo The multiple joins are only needed when the operator is AND + $return['joins'][] = "JOIN {$CONFIG->dbprefix}private_settings ps{$i} + on {$table}.guid = ps{$i}.entity_guid"; + + $pair_wheres[] = "(ps{$i}.name = '$name' AND ps{$i}.value + $operand $value)"; + + $i++; } - $dt = get_data($query, "entity_row_to_elggstar"); - return $dt; - } else { - $total = get_data_row($query); - return $total->total; + $where = implode (" $pair_operator ", $pair_wheres); + if ($where) { + $wheres[] = "($where)"; + } + } + + $where = implode(' AND ', $wheres); + if ($where) { + $return['wheres'][] = "($where)"; } + + return $return; } /** diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php index ce14bd4ee..07fb1fd8c 100644 --- a/engine/tests/api/entity_getter_functions.php +++ b/engine/tests/api/entity_getter_functions.php @@ -2361,4 +2361,89 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest { get_entity($guid)->delete(); } } + + /** + * Private settings + */ + public function testElggApiGettersEntitiesFromPrivateSettings() { + + // create some test private settings + $setting_name = 'test_setting_name_' . rand(); + $setting_value = rand(1000, 9999); + $setting_name2 = 'test_setting_name_' . rand(); + $setting_value2 = rand(1000, 9999); + + $subtypes = $this->getRandomValidSubtypes(array('object'), 1); + $subtype = $subtypes[0]; + $guids = array(); + + // our targets + $valid = new ElggObject(); + $valid->subtype = $subtype; + $valid->save(); + $guids[] = $valid->getGUID(); + set_private_setting($valid->getGUID(), $setting_name, $setting_value); + set_private_setting($valid->getGUID(), $setting_name2, $setting_value2); + + $valid2 = new ElggObject(); + $valid2->subtype = $subtype; + $valid2->save(); + $guids[] = $valid2->getGUID(); + set_private_setting($valid2->getGUID(), $setting_name, $setting_value); + set_private_setting($valid2->getGUID(), $setting_name2, $setting_value2); + + // simple test with name + $options = array( + 'private_setting_name' => $setting_name + ); + + $entities = elgg_get_entities_from_private_settings($options); + + foreach ($entities as $entity) { + $this->assertTrue(in_array($entity->getGUID(), $guids)); + $value = get_private_setting($entity->getGUID(), $setting_name); + $this->assertEqual($value, $setting_value); + } + + // simple test with value + $options = array( + 'private_setting_value' => $setting_value + ); + + $entities = elgg_get_entities_from_private_settings($options); + + foreach ($entities as $entity) { + $this->assertTrue(in_array($entity->getGUID(), $guids)); + $value = get_private_setting($entity->getGUID(), $setting_name); + $this->assertEqual($value, $setting_value); + } + + // test pairs + $options = array( + 'type' => 'object', + 'subtype' => $subtype, + 'private_setting_name_value_pairs' => array( + array( + 'name' => $setting_name, + 'value' => $setting_value + ), + array( + 'name' => $setting_name2, + 'value' => $setting_value2 + ) + ) + ); + + $entities = elgg_get_entities_from_private_settings($options); + $this->assertEqual(2, count($entities)); + foreach ($entities as $entity) { + $this->assertTrue(in_array($entity->getGUID(), $guids)); + } + + foreach ($guids as $guid) { + if ($e = get_entity($guid)) { + $e->delete(); + } + } + } } |