diff options
Diffstat (limited to 'engine/lib/private_settings.php')
| -rw-r--r-- | engine/lib/private_settings.php | 481 |
1 files changed, 226 insertions, 255 deletions
diff --git a/engine/lib/private_settings.php b/engine/lib/private_settings.php index 3f6a10e3d..7541f7b3b 100644 --- a/engine/lib/private_settings.php +++ b/engine/lib/private_settings.php @@ -9,297 +9,249 @@ */ /** - * Get entities based on their private data. + * Returns entities based upon private settings. Also accepts all + * options available to elgg_get_entities(). Supports + * the singular option shortcut. * - * @param string $name The name of the setting - * @param string $value The value of the setting - * @param string $type The type of entity (eg "user", "object" etc) - * @param string $subtype The arbitrary subtype of the entity - * @param int $owner_guid The GUID of the owning user - * @param string $order_by The field to order by; by default, time_created desc - * @param int $limit The number of entities to return; 10 by default - * @param int $offset The indexing offset, 0 by default - * @param boolean $count Return a count of entities - * @param int $site_guid The site to get entities for. 0 for current, -1 for any - * @param mixed $container_guid The container(s) GUIDs + * @see elgg_get_entities * - * @return array A list of entities. - * @todo deprecate + * @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 + * + * private_setting_name_prefix => STR A prefix to apply to all private settings. Used to + * namespace plugin user settings or by plugins to namespace + * their own settings. + * + * + * @return mixed int If count, int. If not count, array. false on errors. + * @since 1.8.0 */ -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) { +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', + 'private_setting_name_prefix' => '', + ); + + $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'], $options['private_setting_name_prefix']); + + 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(); + } - global $CONFIG; + $options['wheres'] = array_merge($options['wheres'], $clauses['wheres']); - if ($subtype === false || $subtype === null || $subtype === 0) { - return false; + // 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']); } - $name = sanitise_string($name); - $value = sanitise_string($value); + return elgg_get_entities($options); +} - 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; - } +/** + * 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 + * @param string $name_prefix A string to prefix all names with + * @return array + * @since 1.8.0 + * @access private + */ +function elgg_get_entity_private_settings_where_sql($table, $names = NULL, $values = NULL, +$pairs = NULL, $pair_operator = 'AND', $name_prefix = '') { - $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; - } + global $CONFIG; - if ($type != "") { - $where[] = "e.type='$type'"; - } - if ($subtype !== "") { - $where[] = "e.subtype=$subtype"; + // @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 ($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); + $sanitised_names = array(); + foreach ($names as $name) { + $name = $name_prefix . $name; + $sanitised_names[] = '\'' . sanitise_string($name) . '\''; } - if (is_null($container_guid)) { - $container_guid = $owner_array; + + $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}"; - } + // get values wheres + $values_where = ''; + if ($values !== NULL) { + if (!is_array($values)) { + $values = array($values); + } - if (!is_null($container_guid)) { - if (is_array($container_guid)) { - foreach ($container_guid as $key => $val) { - $container_guid[$key] = (int) $val; + $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 != "") { - $where[] = "s.name = '$name'"; + $values_str = implode(',', $sanitised_values); + if ($values_str) { + $values_where = "(ps.value IN ($values_str))"; + } } - if ($value != "") { - $where[] = "s.value='$value'"; + if ($names_where && $values_where) { + $wheres[] = "($names_where AND $values_where)"; + } elseif ($names_where) { + $wheres[] = "($names_where)"; + } elseif ($values_where) { + $wheres[] = "($values_where)"; } - 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 "; - } - foreach ($where as $w) { - $query .= " $w and "; - } - // 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"; + // 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); } - $dt = get_data($query, "entity_row_to_elggstar"); - return $dt; - } else { - $total = get_data_row($query); - return $total->total; - } -} + $pair_wheres = array(); -/** - * Get entities based on their private data by multiple keys. - * - * @param string $name The name of the setting - * @param mixed $type Entity type - * @param string $subtype Entity subtype - * @param int $owner_guid The GUID of the owning user - * @param string $order_by The field to order by; by default, time_created desc - * @param int $limit The number of entities to return; 10 by default - * @param int $offset The indexing offset, 0 by default - * @param bool $count Count entities - * @param int $site_guid Site GUID. 0 for current, -1 for any. - * @param mixed $container_guid Container GUID - * - * @return array A list of entities. - * @todo deprecate - */ -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) { + foreach ($pairs as $index => $pair) { + // @todo move this elsewhere? + // support shortcut 'n' => 'v' method. + if (!is_array($pair)) { + $pair = array( + 'name' => $index, + 'value' => $pair + ); + } - global $CONFIG; + // must have at least a name and value + if (!isset($pair['name']) || !isset($pair['value'])) { + // @todo should probably return false. + continue; + } - if ($subtype === false || $subtype === null || $subtype === 0) { - return false; - } + if (isset($pair['operand'])) { + $operand = sanitise_string($pair['operand']); + } else { + $operand = ' = '; + } - 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; - } + // for comparing + $trimmed_operand = trim(strtolower($operand)); + + // 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(); - $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; - } + foreach ($pair['value'] as $pair_value) { + if (is_numeric($pair_value)) { + $values_array[] = sanitise_string($pair_value); } else { - $subtypeval = 0; + $values_array[] = "'" . sanitise_string($pair_value) . "'"; } - 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; - } + if ($values_array) { + $value = '(' . implode(', ', $values_array) . ')'; + } - if ($type != "") { - $where[] = "e.type='$type'"; - } + // @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']) . "'"; + } - if ($subtype !== "") { - $where[] = "e.subtype=$subtype"; - } - } + $name = sanitise_string($name_prefix . $pair['name']); - 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 ($site_guid > 0) { - $where[] = "e.site_guid = {$site_guid}"; - } + // @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"; - if (!is_null($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) . ")"; - } else { - $container_guid = (int) $container_guid; - $where[] = "e.container_guid = {$container_guid}"; - } - } + $pair_wheres[] = "(ps{$i}.name = '$name' AND ps{$i}.value + $operand $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++; } - } - 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 "; + $where = implode(" $pair_operator ", $pair_wheres); + if ($where) { + $wheres[] = "($where)"; + } } - foreach ($where as $w) { - $query .= " $w and "; + $where = implode(' AND ', $wheres); + if ($where) { + $return['wheres'][] = "($where)"; } - // Add access controls - $query .= get_access_sql_suffix('e'); - - if (!$count) { - $query .= " order by $order_by"; - // Add order and limit - if ($limit) { - $query .= " limit $offset, $limit"; - } - - $dt = get_data($query, "entity_row_to_elggstar"); - return $dt; - } else { - $total = get_data_row($query); - return $total->total; - } + return $return; } /** @@ -326,6 +278,11 @@ function get_private_setting($entity_guid, $name) { $entity_guid = (int) $entity_guid; $name = sanitise_string($name); + $entity = get_entity($entity_guid); + if (!$entity instanceof ElggEntity) { + return false; + } + $query = "SELECT value from {$CONFIG->dbprefix}private_settings where name = '{$name}' and entity_guid = {$entity_guid}"; $setting = get_data_row($query); @@ -352,6 +309,10 @@ function get_all_private_settings($entity_guid) { global $CONFIG; $entity_guid = (int) $entity_guid; + $entity = get_entity($entity_guid); + if (!$entity instanceof ElggEntity) { + return false; + } $query = "SELECT * from {$CONFIG->dbprefix}private_settings where entity_guid = {$entity_guid}"; $result = get_data($query); @@ -374,7 +335,7 @@ function get_all_private_settings($entity_guid) { * @param string $name The name of the setting * @param string $value The value of the setting * - * @return mixed The setting ID, or false on failure + * @return bool * @see get_private_setting() * @see get_all_private_settings() * @see remove_private_setting() @@ -390,12 +351,10 @@ function set_private_setting($entity_guid, $name, $value) { $result = insert_data("INSERT into {$CONFIG->dbprefix}private_settings (entity_guid, name, value) VALUES - ($entity_guid, '{$name}', '{$value}') + ($entity_guid, '$name', '$value') ON DUPLICATE KEY UPDATE value='$value'"); - if ($result === 0) { - return true; - } - return $result; + + return $result !== false; } /** @@ -404,7 +363,7 @@ function set_private_setting($entity_guid, $name, $value) { * @param int $entity_guid The Entity GUID * @param string $name The name of the setting * - * @return true|false depending on success + * @return bool * @see get_private_setting() * @see get_all_private_settings() * @see set_private_setting() @@ -415,11 +374,17 @@ function remove_private_setting($entity_guid, $name) { global $CONFIG; $entity_guid = (int) $entity_guid; + + $entity = get_entity($entity_guid); + if (!$entity instanceof ElggEntity) { + return false; + } + $name = sanitise_string($name); return delete_data("DELETE from {$CONFIG->dbprefix}private_settings - where name = '{$name}' - and entity_guid = {$entity_guid}"); + WHERE name = '{$name}' + AND entity_guid = {$entity_guid}"); } /** @@ -427,7 +392,7 @@ function remove_private_setting($entity_guid, $name) { * * @param int $entity_guid The Entity GUID * - * @return true|false depending on success + * @return bool * @see get_private_setting() * @see get_all_private_settings() * @see set_private_setting() @@ -438,6 +403,12 @@ function remove_all_private_settings($entity_guid) { global $CONFIG; $entity_guid = (int) $entity_guid; + + $entity = get_entity($entity_guid); + if (!$entity instanceof ElggEntity) { + return false; + } + return delete_data("DELETE from {$CONFIG->dbprefix}private_settings - where entity_guid = {$entity_guid}"); + WHERE entity_guid = {$entity_guid}"); } |
