diff options
Diffstat (limited to 'engine')
| -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(); +			} +		} +	}  }  | 
