aboutsummaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engine')
-rw-r--r--engine/lib/actions.php4
-rw-r--r--engine/lib/annotations.php292
-rw-r--r--engine/lib/database.php3
-rw-r--r--engine/lib/elgglib.php74
-rw-r--r--engine/lib/entities.php2
-rw-r--r--engine/lib/group.php1
-rw-r--r--engine/lib/metadata.php133
-rw-r--r--engine/lib/notification.php18
-rw-r--r--engine/lib/river2.php4
-rw-r--r--engine/lib/sessions.php83
-rw-r--r--engine/lib/upgrades/2010033101.php65
-rw-r--r--engine/lib/upgrades/2010040201.php40
-rw-r--r--engine/lib/users.php153
-rw-r--r--engine/lib/widgets.php22
-rw-r--r--engine/schema/upgrades/2009100701.sql29
-rw-r--r--engine/tests/api/entity_getter_functions.php311
-rw-r--r--engine/tests/objects/users.php131
17 files changed, 909 insertions, 456 deletions
diff --git a/engine/lib/actions.php b/engine/lib/actions.php
index 25ef411f6..7e8e43f40 100644
--- a/engine/lib/actions.php
+++ b/engine/lib/actions.php
@@ -30,11 +30,13 @@ function action($action, $forwarder = "") {
// Installation cannot use tokens because it requires site secret to be
// working. (#1462)
// Login and logout are for convenience.
+ // file/download (see #2010)
$exceptions = array(
'systemsettings/install',
'admin/plugins/disable',
'logout',
- 'login'
+ 'login',
+ 'file/download',
);
if (!in_array($action, $exceptions)) {
diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php
index c545682d5..6fdb69dc0 100644
--- a/engine/lib/annotations.php
+++ b/engine/lib/annotations.php
@@ -409,274 +409,62 @@ $value = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "asc", $time
/**
+ * Returns entities based upon annotations. Accepts the same values as
+ * elgg_get_entities_from_metadata() but uses the annotations table.
*
- * @todo Add support for arrays of names and values
+ * @see elgg_get_entities
+ * @see elgg_get_entities_from_metadata
+ * @param array $options Array in format:
*
- * @param $options
- * @return unknown_type
+ * annotation_names => NULL|ARR annotations names
+ *
+ * annotation_values => NULL|ARR annotations values
+ *
+ * annotation_name_value_pairs => NULL|ARR (name = 'name', value => 'value', 'operand' => '=', 'case_sensitive' => TRUE) entries.
+ * Currently if multiple values are sent via an array (value => array('value1', 'value2') the pair's operand will be forced to "IN".
+ *
+ * annotation_name_value_pairs_operator => NULL|STR The operator to use for combining (name = value) OPERATOR (name = value); default AND
+ *
+ * annotation_case_sensitive => BOOL Overall Case sensitive
+ *
+ * order_by_annotation => NULL|ARR (array('name' => 'annotation_text1', 'direction' => ASC|DESC, 'as' => text|integer),
+ * Also supports array('name' => 'annotation_text1')
+ *
+ * annotation_owner_guids => NULL|ARR guids for annotaiton owners
+ *
+ * @return array
*/
function elgg_get_entities_from_annotations(array $options = array()) {
$defaults = array(
- 'annotation_names' => NULL,
- 'annotation_name' => NULL,
- 'annotation_values' => NULL,
- 'annotation_value' => NULL,
- 'annotation_name_value_pair' => NULL,
- 'annotation_name_value_pairs' => NULL,
- 'annotation_name_value_pairs_operator' => 'AND',
- 'annotation_case_sensitive' => TRUE,
- 'order_by' => 'maxtime desc',
- 'group_by' => 'a.entity_guid'
- );
-
- $options = array_merge($defaults, $options);
-
- $singulars = array('annotation_name', 'annotation_value', 'annotation_name_value_pair');
- $options = elgg_normalise_plural_options_array($options, $singulars);
-
- $clauses = elgg_get_entity_annotation_where_sql('e', $options['annotation_names'], $options['annotation_values'],
- $options['annotation_name_value_pairs'], $options['annotation_name_value_pairs_operator'], $options['annotation_case_sensitive']);
-
- 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();
- }
-
- $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']);
-
- // merge selects to pass to get_entities()
- if (isset($options['selects']) && !is_array($options['selects'])) {
- $options['selects'] = array($options['selects']);
- } elseif (!isset($options['selects'])) {
- $options['selects'] = array();
- }
-
- $options['selects'] = array_merge($options['selects'], $clauses['selects']);
-
- /* @todo overwrites the current order and group bys
- if ($clauses['order_by']) {
- $options['order_by'] = $clauses['order_by'];
- }
- if ($clauses['group_by']) {
- $options['group_by'] = $clauses['group_by'];
- }
- */
- }
-
- return elgg_get_entities($options);
-}
+ 'annotation_names' => ELGG_ENTITIES_ANY_VALUE,
+ 'annotation_values' => ELGG_ENTITIES_ANY_VALUE,
+ 'annotation_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE,
-/**
- * Returns annotation name and value SQL where for entities.
- * nb: $names and $values are not paired. Use $pairs for this.
- * Pairs default to '=' operand.
- *
- * @param $prefix
- * @param ARR|NULL $names
- * @param ARR|NULL $values
- * @param ARR|NULL $pairs array of names / values / operands
- * @param AND|OR $pair_operator Operator to use to join the where clauses for pairs
- * @param BOOL $case_sensitive
- * @return FALSE|array False on fail, array('joins', 'wheres')
- */
-function elgg_get_entity_annotation_where_sql($table, $names = NULL, $values = NULL, $pairs = NULL, $pair_operator = 'AND', $case_sensitive = TRUE) {
- global $CONFIG;
-
- // short circuit if nothing requested
- // 0 is a valid (if not ill-conceived) annotation name.
- // 0 is also a valid annotation value for FALSE, NULL, or 0
- if ((!$names && $names !== 0)
- && (!$values && $values !== 0)
- && (!$pairs && $pairs !== 0)) {
- return '';
- }
+ 'annotation_name_value_pairs_operator' => 'AND',
+ 'annotation_case_sensitive' => TRUE,
+ 'order_by_annotation' => array(),
- // binary forces byte-to-byte comparision of strings, making
- // it case- and diacritical-mark- sensitive.
- // only supported on values.
- $binary = ($case_sensitive) ? ' BINARY ' : '';
+ 'annotation_owner_guids' => ELGG_ENTITIES_ANY_VALUE,
- $access = get_access_sql_suffix('a');
-
- $return = array (
- 'joins' => array (),
- 'wheres' => array(),
- 'selects' => array()
+ 'order_by' => 'maxtime desc',
+ 'group_by' => 'a.entity_guid'
);
- $wheres = array();
-
- // get names wheres and joins
- $names_where = '';
- if ($names !== NULL) {
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}annotations a on {$table}.guid = a.entity_guid";
- if (!is_array($names)) {
- $names = array($names);
- }
-
- $sanitised_names = array();
- foreach ($names as $name) {
- // normalise to 0.
- if (!$name) {
- $name = '0';
- }
- $sanitised_names[] = "'$name'";
- }
-
- if ($names_str = implode(',', $sanitised_names)) {
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msn on a.name_id = msn.id";
- $names_where = "(msn.string IN ($names_str))";
- }
- }
-
- // get values wheres and joins
- $values_where = '';
- if ($values !== NULL) {
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}annotations a on {$table}.guid = a.entity_guid";
-
- if (!is_array($values)) {
- $values = array($values);
- }
-
- $sanitised_values = array();
- foreach ($values as $value) {
- // normalize to 0
- if (!$value) {
- $value = 0;
- }
- $sanitised_values[] = "'$value'";
- }
-
- if ($values_str = implode(',', $sanitised_values)) {
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msv on a.value_id = msv.id";
- $values_where = "({$binary}msv.string IN ($values_str))";
- }
- }
-
- if ($names_where && $values_where) {
- $wheres[] = "($names_where AND $values_where AND $access)";
- } elseif ($names_where) {
- $wheres[] = "($names_where AND $access)";
- } elseif ($values_where) {
- $wheres[] = "($values_where AND $access)";
- }
-
- // add pairs
- // pairs must be in arrays.
- if (is_array($pairs)) {
- $array = array(
- 'name' => 'test',
- 'value' => 5
- );
-
- $array = array('test' => 5);
-
- // 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();
-
- // @todo when the pairs are > 3 should probably split the query up to
- // denormalize the strings table.
- $i = 1;
- foreach ($pairs as $index => $pair) {
- // @todo move this elsewhere?
- // support shortcut 'n' => 'v' method.
- if (!is_array($pair)) {
- $pair = array(
- 'name' => $index,
- 'value' => $pair
- );
- }
-
- // @todo The multiple joins are only needed when the operator is AND
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}annotations a{$i} on {$table}.guid = a{$i}.entity_guid";
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msn{$i} on a{$i}.name_id = msn{$i}.id";
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msv{$i} on a{$i}.value_id = msv{$i}.id";
-
- // must have at least a name and value
- if (!isset($pair['name']) || !isset($pair['value'])) {
- // @todo should probably return false.
- continue;
- }
-
- // case sensitivity can be specified per pair.
- // default to higher level setting.
- if (isset($pair['case_sensitive'])) {
- $pair_binary = ($pair['case_sensitive']) ? ' BINARY ' : '';
- } else {
- $pair_binary = $binary;
- }
-
- if (isset($pair['operand'])) {
- $operand = sanitise_string($pair['operand']);
- } else {
- $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.
- //$value = trim(strtolower($operand)) == 'in' ? $pair['value'] : "'{$pair['value']}'";
- if (trim(strtolower($operand)) == 'in' || sanitise_int($pair['value'])) {
- $value = $pair['value'];
- } else {
- $value = "'{$pair['value']}'";
- }
-
- $access = get_access_sql_suffix("a{$i}");
- $pair_wheres[] = "(msn{$i}.string = '{$pair['name']}' AND {$pair_binary}msv{$i}.string $operand $value AND $access)";
- $i++;
- }
+ $options = array_merge($defaults, $options);
- if ($where = implode (" $pair_operator ", $pair_wheres)) {
- $wheres[] = "($where)";
- }
+ if (!$options = elgg_entities_get_metastrings_options('annotation', $options)) {
+ return FALSE;
}
- if ($where = implode(' OR ', $wheres)) {
- $return['selects'][] = "max(a.time_created) as maxtime";
- $return['wheres'][] = "($where)";
- $return['group_by'] = 'a.entity_guid';
- $return['order_by'] = 'maxtime asc';
- }
+ // special sorting for annotations
+ //@todo overrides other sorting
+ $options['selects'][] = "max(n_table.time_created) as maxtime";
+ $options['group_by'] = 'n_table.entity_guid';
- return $return;
+ return elgg_get_entities($options);
}
/**
- * Return a list of entities which are annotated with a specific annotation.
- * These can be ordered by when the annotation was created/updated.
- *
- * @param string $entity_type Type of entity.
- * @param string $entity_subtype Subtype of entity.
- * @param string $name Name of annotation.
- * @param string $value Value of annotation.
- * @param int $owner_guid Owner.
- * @param int $group_guid Group container. Currently this is only supported if $entity_type == 'object'
- * @param int $limit Maximum number of results to return.
- * @param int $offset Place to start.
- * @param string $order_by How to order results.
- * @param boolean $count Whether to count entities rather than return them
- * @param int $timelower The earliest time the annotation can have been created. Default: all
- * @param int $timeupper The latest time the annotation can have been created. Default: all
- */
-
-
-/**
* @deprecated 1.7 Use elgg_get_entities_from_annotations()
* @param $entity_type
* @param $entity_subtype
@@ -714,7 +502,7 @@ $timelower = 0, $timeupper = 0) {
}
if ($owner_guid) {
- $options['owner_guid'] = $owner_guid;
+ $options['annotation_owner_guid'] = $owner_guid;
}
if ($group_guid) {
diff --git a/engine/lib/database.php b/engine/lib/database.php
index ec703992d..58685bb82 100644
--- a/engine/lib/database.php
+++ b/engine/lib/database.php
@@ -98,7 +98,8 @@ function setup_db_connections() {
function db_profiling_shutdown_hook() {
global $dbcalls;
- elgg_log("DB Queries for this page: $dbcalls", 'DEBUG');
+ // demoted to NOTICE as it corrupts javasript at DEBUG
+ elgg_log("DB Queries for this page: $dbcalls", 'NOTICE');
}
/**
diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php
index f106e4ded..9587bf1e4 100644
--- a/engine/lib/elgglib.php
+++ b/engine/lib/elgglib.php
@@ -14,10 +14,10 @@
*/
/**
- * Adds messages to the session so they'll be carried over, and forwards the browser.
+ * Forwards the browser.
* Returns false if headers have already been sent and the browser cannot be moved.
*
- * @param string $location URL to forward to browser to
+ * @param string $location URL to forward to browser to. Can be relative path.
* @return nothing|false
*/
function forward($location = "") {
@@ -25,10 +25,6 @@ function forward($location = "") {
if (!headers_sent()) {
$current_page = current_page_url();
- // What is this meant to do?
- //if (strpos($current_page, $CONFIG->wwwroot . "action") ===false)
-
- $_SESSION['msg'] = array_merge($_SESSION['msg'], system_messages());
if ((substr_count($location, 'http://') == 0) && (substr_count($location, 'https://') == 0)) {
$location = $CONFIG->url . $location;
}
@@ -1255,51 +1251,7 @@ function page_draw($title, $body, $sidebar = "") {
* @return string The friendly time
*/
function friendly_time($time) {
- $diff = time() - ((int) $time);
-
- $minute = 60;
- $hour = $minute * 60;
- $day = $hour * 24;
-
- if ($diff < $minute) {
- $friendly_time = elgg_echo("friendlytime:justnow");
- } else if ($diff < $hour) {
- $diff = round($diff / $minute);
- if ($diff == 0) {
- $diff = 1;
- }
-
- if ($diff > 1) {
- $friendly_time = sprintf(elgg_echo("friendlytime:minutes"), $diff);
- } else {
- $friendly_time = sprintf(elgg_echo("friendlytime:minutes:singular"), $diff);
- }
- } else if ($diff < $day) {
- $diff = round($diff / $hour);
- if ($diff == 0) {
- $diff = 1;
- }
-
- if ($diff > 1) {
- $friendly_time = sprintf(elgg_echo("friendlytime:hours"), $diff);
- } else {
- $friendly_time = sprintf(elgg_echo("friendlytime:hours:singular"), $diff);
- }
- } else {
- $diff = round($diff / $day);
- if ($diff == 0) {
- $diff = 1;
- }
-
- if ($diff > 1) {
- $friendly_time = sprintf(elgg_echo("friendlytime:days"), $diff);
- } else {
- $friendly_time = sprintf(elgg_echo("friendlytime:days:singular"), $diff);
- }
- }
-
- $timestamp = htmlentities(date(elgg_echo('friendlytime:date_format'), $time));
- return "<acronym title=\"$timestamp\">$friendly_time</acronym>";
+ return elgg_view('output/friendlytime', array('time' => $time));
}
/**
@@ -1309,12 +1261,7 @@ function friendly_time($time) {
* @return string The optimised title
*/
function friendly_title($title) {
- $title = trim($title);
- $title = strtolower($title);
- $title = preg_replace("/[^\w ]/","",$title);
- $title = str_replace(" ","-",$title);
- $title = str_replace("--","-",$title);
- return $title;
+ return elgg_view('output/friendlytitle', array('title' => $title));
}
/**
@@ -1990,7 +1937,8 @@ function elgg_log($message, $level='NOTICE') {
* @return void
*/
function elgg_dump($value, $to_screen = TRUE, $level = 'NOTICE') {
-
+ global $CONFIG;
+
// plugin can return false to stop the default logging method
$params = array('level' => $level,
'msg' => $value,
@@ -1999,6 +1947,13 @@ function elgg_dump($value, $to_screen = TRUE, $level = 'NOTICE') {
return;
}
+ // Do not want to write to screen before page creation has started.
+ // This is not fool-proof but probably fixes 95% of the cases when logging
+ // results in data sent to the browser before the page is begun.
+ if (!isset($CONFIG->pagesetupdone)) {
+ $to_screen = FALSE;
+ }
+
if ($to_screen == TRUE) {
echo '<pre>';
print_r($value);
@@ -2932,7 +2887,8 @@ function __elgg_shutdown_hook() {
trigger_elgg_event('shutdown', 'system');
$time = (float)(microtime(TRUE) - $START_MICROTIME);
- elgg_log("Page {$_SERVER['REQUEST_URI']} generated in $time seconds", 'DEBUG');
+ // demoted to NOTICE from DEBUG so javascript is not corrupted
+ elgg_log("Page {$_SERVER['REQUEST_URI']} generated in $time seconds", 'NOTICE');
}
/**
diff --git a/engine/lib/entities.php b/engine/lib/entities.php
index 3d16e1b3d..987328adc 100644
--- a/engine/lib/entities.php
+++ b/engine/lib/entities.php
@@ -2863,7 +2863,7 @@ function can_edit_entity($entity_guid, $user_guid = 0) {
$return = true;
}
if ($container_entity = get_entity($entity->container_guid)) {
- if ($container_entity->canEdit()) {
+ if ($container_entity->canEdit($user->getGUID())) {
$return = true;
}
}
diff --git a/engine/lib/group.php b/engine/lib/group.php
index 362f45402..68829dafb 100644
--- a/engine/lib/group.php
+++ b/engine/lib/group.php
@@ -842,6 +842,7 @@ function group_gatekeeper($forward = true) {
}
if ($forward && $allowed == false) {
+ register_error(elgg_echo('membershiprequired'));
forward($url);
exit;
}
diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php
index 5c248e0f6..bab919ca2 100644
--- a/engine/lib/metadata.php
+++ b/engine/lib/metadata.php
@@ -532,8 +532,6 @@ function find_metadata($meta_name = "", $meta_value = "", $entity_type = "", $en
return get_data($query, "row_to_elggmetadata");
}
-
-
/**
* Returns entities based upon metadata. Also accepts all
* options available to elgg_get_entities(). Supports
@@ -547,6 +545,7 @@ function find_metadata($meta_name = "", $meta_value = "", $entity_type = "", $en
* When in doubt, use name_value_pairs.
*
* @see elgg_get_entities
+ * @see elgg_get_entities_from_annotations
* @param array $options Array in format:
*
* metadata_names => NULL|ARR metadata names
@@ -560,30 +559,59 @@ function find_metadata($meta_name = "", $meta_value = "", $entity_type = "", $en
*
* metadata_case_sensitive => BOOL Overall Case sensitive
*
- * order_by_metadata => NULL|ARR (array('name' => 'metadata_text1', 'direction' => ASC|DESC, 'as' => text|integer),
- * Also supports array('name' => 'metadata_text1')
+ * order_by_metadata => NULL|ARR (array('name' => 'metadata_text1', 'direction' => ASC|DESC, 'as' => text|integer),
+ * Also supports array('name' => 'metadata_text1')
+ *
+ * metadata_owner_guids => NULL|ARR guids for metadata owners
*
* @return array
*/
function elgg_get_entities_from_metadata(array $options = array()) {
$defaults = array(
- 'metadata_names' => ELGG_ENTITIES_ANY_VALUE,
- 'metadata_values' => ELGG_ENTITIES_ANY_VALUE,
- 'metadata_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE,
+ 'metadata_names' => ELGG_ENTITIES_ANY_VALUE,
+ 'metadata_values' => ELGG_ENTITIES_ANY_VALUE,
+ 'metadata_name_value_pairs' => ELGG_ENTITIES_ANY_VALUE,
- 'metadata_name_value_pairs_operator' => 'AND',
- 'metadata_case_sensitive' => TRUE,
- 'order_by_metadata' => array(),
+ 'metadata_name_value_pairs_operator'=> 'AND',
+ 'metadata_case_sensitive' => TRUE,
+ 'order_by_metadata' => array(),
+
+ 'metadata_owner_guids' => ELGG_ENTITIES_ANY_VALUE,
);
$options = array_merge($defaults, $options);
- $singulars = array('metadata_name', 'metadata_value', 'metadata_name_value_pair');
+ if (!$options = elgg_entities_get_metastrings_options('metadata', $options)) {
+ return FALSE;
+ }
+
+ return elgg_get_entities($options);
+}
+
+/**
+ * Returns options to pass to elgg_get_entities() for metastrings operations.
+ *
+ * @param string $type Metastring type: annotations or metadata
+ * @param array $options Options
+ *
+ * @return array
+ */
+function elgg_entities_get_metastrings_options($type, $options) {
+ $valid_types = array('metadata', 'annotation');
+ if (!in_array($type, $valid_types)) {
+ return FALSE;
+ }
+
+ // the options for annotations are singular (annotation_name) but the table
+ // is plural (elgg_annotations) so rewrite for the table name.
+ $n_table = ($type == 'annotation') ? 'annotations' : $type;
+
+ $singulars = array("{$type}_name", "{$type}_value", "{$type}_name_value_pair", "{$type}_owner_guid");
$options = elgg_normalise_plural_options_array($options, $singulars);
- $clauses = elgg_get_entity_metadata_where_sql('e', $options['metadata_names'], $options['metadata_values'],
- $options['metadata_name_value_pairs'], $options['metadata_name_value_pairs_operator'], $options['metadata_case_sensitive'],
- $options['order_by_metadata']);
+ $clauses = elgg_get_entity_metadata_where_sql('e', $n_table, $options["{$type}_names"], $options["{$type}_values"],
+ $options["{$type}_name_value_pairs"], $options["{$type}_name_value_pairs_operator"], $options["{$type}_case_sensitive"],
+ $options["order_by_{$type}"], $options["{$type}_owner_guids"]);
if ($clauses) {
// merge wheres to pass to get_entities()
@@ -614,15 +642,19 @@ function elgg_get_entities_from_metadata(array $options = array()) {
}
}
- return elgg_get_entities($options);
+ return $options;
}
/**
* Returns metadata name and value SQL where for entities.
- * nb: $names and $values are not paired. Use $pairs for this.
+ * NB: $names and $values are not paired. Use $pairs for this.
* Pairs default to '=' operand.
*
- * @param $prefix
+ * This function is reused for annotations because the tables are
+ * exactly the same.
+ *
+ * @param string $e_table Entities table name
+ * @param string $n_table Normalized metastrings table name (Where entities, values, and names are joined. annotations / metadata)
* @param ARR|NULL $names
* @param ARR|NULL $values
* @param ARR|NULL $pairs array of names / values / operands
@@ -631,25 +663,30 @@ function elgg_get_entities_from_metadata(array $options = array()) {
* @param ARR|NULL $order_by_metadata array of names / direction
* @return FALSE|array False on fail, array('joins', 'wheres')
*/
-function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NULL, $pairs = NULL, $pair_operator = 'AND', $case_sensitive = TRUE, $order_by_metadata = NULL) {
+function elgg_get_entity_metadata_where_sql($e_table, $n_table, $names = NULL, $values = NULL, $pairs = NULL, $pair_operator = 'AND', $case_sensitive = TRUE, $order_by_metadata = NULL, $owner_guids = NULL) {
global $CONFIG;
// short circuit if nothing requested
// 0 is a valid (if not ill-conceived) metadata name.
// 0 is also a valid metadata value for FALSE, NULL, or 0
+ // 0 is also a valid(ish) owner_guid
if ((!$names && $names !== 0)
&& (!$values && $values !== 0)
&& (!$pairs && $pairs !== 0)
+ && (!$owner_guids && $owner_guids !== 0)
&& !isset($order_by_metadata)) {
return '';
}
+ // join counter for incremental joins.
+ $i = 1;
+
// binary forces byte-to-byte comparision of strings, making
// it case- and diacritical-mark- sensitive.
// only supported on values.
$binary = ($case_sensitive) ? ' BINARY ' : '';
- $access = get_access_sql_suffix('md');
+ $access = get_access_sql_suffix('n_table');
$return = array (
'joins' => array (),
@@ -657,12 +694,14 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
'orders' => array()
);
+ // will always want to join these tables if pulling metastrings.
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}{$n_table} n_table on {$e_table}.guid = n_table.entity_guid";
+
$wheres = array();
// get names wheres and joins
$names_where = '';
if ($names !== NULL) {
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metadata md on {$table}.guid = md.entity_guid";
if (!is_array($names)) {
$names = array($names);
}
@@ -677,7 +716,7 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
}
if ($names_str = implode(',', $sanitised_names)) {
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msn on md.name_id = msn.id";
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msn on n_table.name_id = msn.id";
$names_where = "(msn.string IN ($names_str))";
}
}
@@ -685,8 +724,6 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
// get values wheres and joins
$values_where = '';
if ($values !== NULL) {
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metadata md on {$table}.guid = md.entity_guid";
-
if (!is_array($values)) {
$values = array($values);
}
@@ -701,7 +738,7 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
}
if ($values_str = implode(',', $sanitised_values)) {
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msv on md.value_id = msv.id";
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msv on n_table.value_id = msv.id";
$values_where = "({$binary}msv.string IN ($values_str))";
}
}
@@ -714,8 +751,6 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
$wheres[] = "($values_where AND $access)";
}
- $i = 1;
-
// add pairs
// pairs must be in arrays.
if (is_array($pairs)) {
@@ -739,11 +774,6 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
);
}
- // @todo The multiple joins are only needed when the operator is AND
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metadata md{$i} on {$table}.guid = md{$i}.entity_guid";
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msn{$i} on md{$i}.name_id = msn{$i}.id";
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msv{$i} on md{$i}.value_id = msv{$i}.id";
-
// must have at least a name and value
if (!isset($pair['name']) || !isset($pair['value'])) {
// @todo should probably return false.
@@ -764,6 +794,10 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
$operand = ' = ';
}
+ // for comparing
+ $trimmed_operand = trim(strtolower($operand));
+
+ $access = get_access_sql_suffix("n_table{$i}");
// 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'])) {
@@ -772,10 +806,10 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
$values_array = array();
foreach ($pair['value'] as $pair_value) {
- if (is_numeric($v)) {
+ if (is_numeric($pair_value)) {
$values_array[] = sanitise_string($pair_value);
} else {
- $values_array[] = '\'' . sanitise_string($pair_value) . '\'';
+ $values_array[] = "'" . sanitise_string($pair_value) . "'";
}
}
@@ -786,16 +820,21 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
// @todo allow support for non IN operands with array of values.
// will have to do more silly joins.
$operand = 'IN';
- } else if (trim(strtolower($operand)) == 'in') {
+ } else if ($trimmed_operand == 'in') {
$value = "({$pair['value']})";
} else {
- $value = '\'' . sanitise_string($pair['value']) . '\'';
+ $value = "'" . sanitise_string($pair['value']) . "'";
}
$name = sanitise_string($pair['name']);
- $access = get_access_sql_suffix("md{$i}");
+ // @todo The multiple joins are only needed when the operator is AND
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}{$n_table} n_table{$i} on {$e_table}.guid = n_table{$i}.entity_guid";
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msn{$i} on n_table{$i}.name_id = msn{$i}.id";
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msv{$i} on n_table{$i}.value_id = msv{$i}.id";
+
$pair_wheres[] = "(msn{$i}.string = '$name' AND {$pair_binary}msv{$i}.string $operand $value AND $access)";
+
$i++;
}
@@ -804,7 +843,19 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
}
}
- if ($where = implode(' OR ', $wheres)) {
+ // add owner_guids
+ if ($owner_guids) {
+ if (is_array($owner_guids)) {
+ $sanitised = array_map('sanitise_int', $owner_guids);
+ $owner_str = implode(',', $sanitised);
+ } else {
+ $owner_str = sanitise_int($owner_guids);
+ }
+
+ $wheres[] = "(n_table.owner_guid IN ($owner_str))";
+ }
+
+ if ($where = implode(' AND ', $wheres)) {
$return['wheres'][] = "($where)";
}
@@ -821,11 +872,11 @@ function elgg_get_entity_metadata_where_sql($table, $names = NULL, $values = NUL
} else {
$direction = 'ASC';
}
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metadata md{$i} on {$table}.guid = md{$i}.entity_guid";
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msn{$i} on md{$i}.name_id = msn{$i}.id";
- $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msv{$i} on md{$i}.value_id = msv{$i}.id";
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}{$n_table} n_table{$i} on {$e_table}.guid = n_table{$i}.entity_guid";
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msn{$i} on n_table{$i}.name_id = msn{$i}.id";
+ $return['joins'][] = "JOIN {$CONFIG->dbprefix}metastrings msv{$i} on n_table{$i}.value_id = msv{$i}.id";
- $access = get_access_sql_suffix("md{$i}");
+ $access = get_access_sql_suffix("n_table{$i}");
$return['wheres'][] = "(msn{$i}.string = '$name' AND $access)";
if (isset($order_by['as']) && $order_by['as'] == 'integer') {
diff --git a/engine/lib/notification.php b/engine/lib/notification.php
index adc4ebace..024881e0f 100644
--- a/engine/lib/notification.php
+++ b/engine/lib/notification.php
@@ -51,6 +51,19 @@ function register_notification_handler($method, $handler, $params = NULL) {
}
/**
+ * This function unregisters a handler for a given notification type (eg "email")
+ *
+ * @param string $method The method
+ */
+function unregister_notification_handler($method) {
+ global $NOTIFICATION_HANDLERS;
+
+ if (isset($NOTIFICATION_HANDLERS[$method])) {
+ unset($NOTIFICATION_HANDLERS[$method]);
+ }
+}
+
+/**
* Notify a user via their preferences.
*
* @param mixed $to Either a guid or an array of guid's to notify.
@@ -101,6 +114,11 @@ function notify_user($to, $from, $subject, $message, array $params = NULL, $meth
if ($methods) {
// Deliver
foreach ($methods as $method) {
+
+ if (!isset($NOTIFICATION_HANDLERS[$method])) {
+ continue;
+ }
+
// Extract method details from list
$details = $NOTIFICATION_HANDLERS[$method];
$handler = $details->handler;
diff --git a/engine/lib/river2.php b/engine/lib/river2.php
index 7793ea192..3d826f517 100644
--- a/engine/lib/river2.php
+++ b/engine/lib/river2.php
@@ -21,8 +21,8 @@
* @return true|false Depending on success
*/
function add_to_river($view,$action_type,$subject_guid,$object_guid,$access_id = "",$posted = 0, $annotation_id = 0) {
- // Sanitise variables
- if (!elgg_view_exists($view)) {
+ // use default viewtype for when called from REST api
+ if (!elgg_view_exists($view, 'default')) {
return false;
}
if (!($subject = get_entity($subject_guid))) {
diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php
index fdc6d1806..f4b1fc69b 100644
--- a/engine/lib/sessions.php
+++ b/engine/lib/sessions.php
@@ -92,17 +92,17 @@ class ElggSession implements ArrayAccess {
return true;
}
}
-
-
+
+
// Alias functions
function get($key) {
return $this->offsetGet($key);
}
-
+
function set($key, $value) {
return $this->offsetSet($key, $value);
}
-
+
function del($key) {
return $this->offsetUnset($key);
}
@@ -166,16 +166,16 @@ function isloggedin() {
*/
function isadminloggedin() {
if (!is_installed()) {
- return false;
+ return FALSE;
}
$user = get_loggedin_user();
- if ((isloggedin()) && (($user->admin || $user->siteadmin))) {
- return true;
+ if ((isloggedin()) && $user->isAdmin()) {
+ return TRUE;
}
- return false;
+ return FALSE;
}
/**
@@ -187,40 +187,41 @@ function isadminloggedin() {
*/
function elgg_is_admin_user($user_guid) {
global $CONFIG;
-
- // cannot use metadata here because of recursion
-
- // caching is done at the db level so no need to here.
- $query = "SELECT * FROM {$CONFIG->dbprefix}users_entity as e,
- {$CONFIG->dbprefix}metastrings as ms1,
- {$CONFIG->dbprefix}metastrings as ms2,
- {$CONFIG->dbprefix}metadata as md
- WHERE (
- (
- (ms1.string = 'admin' AND ms2.string = 'yes')
- OR (ms1.string = 'admin' AND ms2.string = '1')
- )
- AND md.name_id = ms1.id AND md.value_id = ms2.id
- AND e.guid = md.entity_guid
- AND e.guid = {$user_guid}
- AND e.banned = 'no'
+ // cannot use magic metadata here because of recursion
+
+ // must support the old way of getting admin from metadata
+ // in order to run the upgrade to move it into the users table.
+ $version = (int) datalist_get('version');
+
+ if ($version < 2010040201) {
+ $admin = get_metastring_id('admin');
+ $yes = get_metastring_id('yes');
+ $one = get_metastring_id('1');
+
+ $query = "SELECT * FROM {$CONFIG->dbprefix}users_entity as e,
+ {$CONFIG->dbprefix}metadata as md
+ WHERE (
+ md.name_id = '$admin'
+ AND md.value_id IN ('$yes', '$one')
+ AND e.guid = md.entity_guid
+ AND e.guid = {$user_guid}
+ AND e.banned = 'no'
)";
-// OR (
-// ms1.string = 'admin' AND ms2.string = '1'
-// AND md.name_id = ms1.id AND md.value_id = ms2.id
-// AND e.guid = md.entity_guid
-// AND e.guid = {$user_guid}
-// AND e.banned = 'no'
-// )";
-
+ } else {
+ $query = "SELECT * FROM {$CONFIG->dbprefix}users_entity as e
+ WHERE (
+ e.guid = {$user_guid}
+ AND e.admin = 'yes'
+ )";
+ }
// normalizing the results from get_data()
// See #1242
$info = get_data($query);
- if (!((is_array($info) && count($info) < 1) || $info === false)) {
- return true;
+ if (!((is_array($info) && count($info) < 1) || $info === FALSE)) {
+ return TRUE;
}
- return false;
+ return FALSE;
}
/**
@@ -254,7 +255,7 @@ function pam_auth_userpass($credentials = NULL) {
if ($user = get_user_by_username($credentials['username'])) {
// Let admins log in without validating their email, but normal users must have validated their email or been admin created
- if ((!$user->admin) && (!$user->validated) && (!$user->admin_created)) {
+ if ((!$user->isAdmin()) && (!$user->validated) && (!$user->admin_created)) {
return false;
}
@@ -335,7 +336,7 @@ function reset_login_failure_count($user_guid) {
* @return bool on exceeded limit.
*/
function check_rate_limit_exceeded($user_guid) {
- // 5 failures in 5 minutes causes temporary block on logins
+ // 5 failures in 5 minutes causes temporary block on logins
$limit = 5;
$user_guid = (int)$user_guid;
$user = get_entity($user_guid);
@@ -434,7 +435,7 @@ function login(ElggUser $user, $persistent = false) {
function logout() {
global $CONFIG;
- if (isset($_SESSION['user'])) {
+ if (isset($_SESSION['user'])) {
if (!trigger_elgg_event('logout','user',$_SESSION['user'])) {
return false;
}
@@ -532,7 +533,7 @@ function session_init($event, $object_type, $object) {
unset($_SESSION['id']);
unset($_SESSION['guid']);
unset($_SESSION['code']);
-
+
// is there a remember me cookie
if (isset($_COOKIE['elggperm'])) {
// we have a cookie, so try to log the user in
@@ -545,7 +546,7 @@ function session_init($event, $object_type, $object) {
$_SESSION['guid'] = $_SESSION['id'];
$_SESSION['code'] = $_COOKIE['elggperm'];
}
- }
+ }
} else {
// we have a session and we have already checked the fingerprint
// reload the user object from database in case it has changed during the session
diff --git a/engine/lib/upgrades/2010033101.php b/engine/lib/upgrades/2010033101.php
new file mode 100644
index 000000000..b137e0285
--- /dev/null
+++ b/engine/lib/upgrades/2010033101.php
@@ -0,0 +1,65 @@
+<?php
+/*
+ * Conditional upgrade for UTF8 as described in http://trac.elgg.org/ticket/1928
+ */
+
+// get_version() returns the code version.
+// we want the DB version.
+$dbversion = (int) datalist_get('version');
+
+// 2009100701 was the utf8 upgrade for 1.7.
+// if we've already upgraded, don't try again.
+if ($dbversion < 2009100701) {
+ // if the default client connection is utf8 there is no reason
+ // to run this upgrade because the strings are already stored correctly.
+
+ // start a new link to the DB to see what its defaults are.
+ $link = mysql_connect($CONFIG->dbhost, $CONFIG->dbuser, $CONFIG->dbpass, TRUE);
+ mysql_select_db($CONFIG->dbname, $link);
+
+ $q = "SHOW VARIABLES LIKE 'character_set_client'";
+ $r = mysql_query($q);
+ $client = mysql_fetch_assoc($r);
+
+ $q = "SHOW VARIABLES LIKE 'character_set_connection'";
+ $r = mysql_query($q);
+ $connection = mysql_fetch_assoc($r);
+
+ // only run upgrade if not already talking utf8.
+ if ($client['Value'] != 'utf8' && $connection['Value'] != 'utf8') {
+ $qs = array();
+ $qs[] = "SET NAMES utf8";
+
+ $qs[] = "ALTER TABLE {$CONFIG->dbprefix}metastrings DISABLE KEYS";
+ $qs[] = "REPLACE INTO {$CONFIG->dbprefix}metastrings (id, string)
+ SELECT id, unhex(hex(convert(string using latin1)))
+ FROM {$CONFIG->dbprefix}metastrings";
+ $qs[] = "ALTER TABLE {$CONFIG->dbprefix}metastrings ENABLE KEYS";
+
+ $qs[] = "ALTER TABLE {$CONFIG->dbprefix}groups_entity DISABLE KEYS";
+ $qs[] = "REPLACE INTO {$CONFIG->dbprefix}groups_entity (guid, name, description)
+ SELECT guid, unhex(hex(convert(name using latin1))), unhex(hex(convert(description using latin1)))
+ FROM {$CONFIG->dbprefix}groups_entity";
+ $qs[] = "ALTER TABLE {$CONFIG->dbprefix}groups_entity ENABLE KEYS";
+
+ $qs[] = "ALTER TABLE {$CONFIG->dbprefix}objects_entity DISABLE KEYS";
+ $qs[] = "REPLACE INTO {$CONFIG->dbprefix}objects_entity (guid, title, description)
+ SELECT guid, unhex(hex(convert(title using latin1))), unhex(hex(convert(description using latin1)))
+ FROM {$CONFIG->dbprefix}objects_entity";
+ $qs[] = "ALTER TABLE {$CONFIG->dbprefix}objects_entity ENABLE KEYS";
+
+ $qs[] = "ALTER TABLE {$CONFIG->dbprefix}users_entity DISABLE KEYS";
+ $qs[] = "REPLACE INTO {$CONFIG->dbprefix}users_entity (guid, name, username, password, salt, email, language, code,
+ banned, last_action, prev_last_action, last_login, prev_last_login)
+ SELECT guid, unhex(hex(convert(name using latin1))), username, password, salt, email, language, code,
+ banned, last_action, prev_last_action, last_login, prev_last_login
+ FROM {$CONFIG->dbprefix}users_entity";
+ $qs[] = "ALTER TABLE {$CONFIG->dbprefix}users_entity ENABLE KEYS";
+
+ foreach ($qs as $q) {
+ if (!update_data($q)) {
+ throw new Exception('Couldn\'t execute upgrade query: ' . $q);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/engine/lib/upgrades/2010040201.php b/engine/lib/upgrades/2010040201.php
new file mode 100644
index 000000000..22eee15f8
--- /dev/null
+++ b/engine/lib/upgrades/2010040201.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Pull admin metadata setting into users_entity table column
+ */
+
+$siteadmin = get_metastring_id('siteadmin');
+$admin = get_metastring_id('admin');
+$yes = get_metastring_id('yes');
+$one = get_metastring_id('1');
+
+$qs = array();
+
+$qs[] = "ALTER TABLE {$CONFIG->dbprefix}users_entity DISABLE KEYS";
+
+$qs[] = "ALTER TABLE {$CONFIG->dbprefix}users_entity
+ ADD admin ENUM('yes', 'no') NOT NULL DEFAULT 'no' AFTER `banned`";
+
+$qs[] = "UPDATE {$CONFIG->dbprefix}users_entity SET admin = 'yes' where guid IN (select x.guid FROM(
+SELECT * FROM {$CONFIG->dbprefix}users_entity as e,
+ {$CONFIG->dbprefix}metadata as md
+ WHERE (
+ md.name_id IN ('$admin', '$siteadmin')
+ AND md.value_id IN ('$yes', '$one')
+ AND e.guid = md.entity_guid
+ AND e.banned = 'no'
+ )) as x)";
+
+$qs[] = "ALTER TABLE {$CONFIG->dbprefix}users_entity ADD KEY admin (admin)";
+
+$qs[] = "ALTER TABLE {$CONFIG->dbprefix}users_entity ENABLE KEYS";
+
+$qs[] = "DELETE FROM {$CONFIG->dbprefix}metadata
+ WHERE (
+ name_id IN ('$admin', '$siteadmin')
+ AND value_id IN ('$yes', '$one')
+ )";
+
+foreach ($qs as $q) {
+ update_data($q);
+} \ No newline at end of file
diff --git a/engine/lib/users.php b/engine/lib/users.php
index 45c281d23..778b072a1 100644
--- a/engine/lib/users.php
+++ b/engine/lib/users.php
@@ -43,6 +43,7 @@ class ElggUser extends ElggEntity
$this->attributes['language'] = "";
$this->attributes['code'] = "";
$this->attributes['banned'] = "no";
+ $this->attributes['admin'] = 'no';
$this->attributes['tables_split'] = 2;
}
@@ -200,6 +201,46 @@ class ElggUser extends ElggEntity
}
/**
+ * Is this user admin?
+ *
+ * @return bool
+ */
+ public function isAdmin() {
+
+ // for backward compatibility we need to pull this directly
+ // from the attributes instead of using the magic methods.
+ // this can be removed in 1.9
+ // return $this->admin == 'yes';
+ return $this->attributes['admin'] == 'yes';
+ }
+
+ /**
+ * Make the user an admin
+ *
+ * @return bool
+ */
+ public function makeAdmin() {
+ if (make_user_admin($this->guid)) {
+ $this->attributes['admin'] = 'yes';
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Remove the admin flag for user
+ *
+ * @return bool
+ */
+ public function removeAdmin() {
+ if (remove_user_admin($this->guid)) {
+ $this->attributes['admin'] = 'no';
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
* Get sites that this user is a member of
*
* @param string $subtype Optionally, the subtype of result we want to limit to
@@ -375,6 +416,30 @@ class ElggUser extends ElggEntity
'language',
));
}
+
+ // backward compatibility with admin flag
+ // remove for 1.9
+ public function __set($name, $value) {
+ if ($name == 'admin' || $name == 'siteadmin') {
+ elgg_deprecated_notice('The admin/siteadmin metadata are not longer used. Use ElggUser->makeAdmin() and ElggUser->removeAdmin().', '1.7.1');
+
+ if ($value == 'yes' || $value == '1') {
+ $this->makeAdmin();
+ } else {
+ $this->removeAdmin();
+ }
+ }
+ return parent::__set($name, $value);
+ }
+
+ public function __get($name) {
+ if ($name == 'admin' || $name == 'siteadmin') {
+ elgg_deprecated_notice('The admin/siteadmin metadata are not longer used. Use ElggUser->isAdmin().', '1.7.1');
+ return $this->isAdmin();
+ }
+
+ return parent::__get($name);
+ }
}
/**
@@ -501,9 +566,11 @@ function ban_user($user_guid, $reason = "") {
// Set ban flag
return update_data("UPDATE {$CONFIG->dbprefix}users_entity set banned='yes' where guid=$user_guid");
}
+
+ return FALSE;
}
- return false;
+ return FALSE;
}
/**
@@ -534,9 +601,81 @@ function unban_user($user_guid) {
return update_data("UPDATE {$CONFIG->dbprefix}users_entity set banned='no' where guid=$user_guid");
}
+
+ return FALSE;
}
- return false;
+ return FALSE;
+}
+
+/**
+ * Makes user $guid an admin.
+ *
+ * @param int $guid
+ * @return bool
+ */
+function make_user_admin($user_guid) {
+ global $CONFIG;
+
+ $user = get_entity((int)$user_guid);
+
+ if (($user) && ($user instanceof ElggUser) && ($user->canEdit())) {
+ if (trigger_elgg_event('make_admin', 'user', $user)) {
+
+ // invalidate memcache for this user
+ static $newentity_cache;
+ if ((!$newentity_cache) && (is_memcache_available())) {
+ $newentity_cache = new ElggMemcache('new_entity_cache');
+ }
+
+ if ($newentity_cache) {
+ $newentity_cache->delete($user_guid);
+ }
+
+ $r = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='yes' where guid=$user_guid");
+ invalidate_cache_for_entity($user_guid);
+ return $r;
+ }
+
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Removes user $guid's admin flag.
+ *
+ * @param int $guid
+ * @return bool
+ */
+function remove_user_admin($user_guid) {
+ global $CONFIG;
+
+ $user = get_entity((int)$user_guid);
+
+ if (($user) && ($user instanceof ElggUser) && ($user->canEdit())) {
+ if (trigger_elgg_event('remove_admin', 'user', $user)) {
+
+ // invalidate memcache for this user
+ static $newentity_cache;
+ if ((!$newentity_cache) && (is_memcache_available())) {
+ $newentity_cache = new ElggMemcache('new_entity_cache');
+ }
+
+ if ($newentity_cache) {
+ $newentity_cache->delete($user_guid);
+ }
+
+ $r = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='no' where guid=$user_guid");
+ invalidate_cache_for_entity($user_guid);
+ return $r;
+ }
+
+ return FALSE;
+ }
+
+ return FALSE;
}
/**
@@ -1398,10 +1537,6 @@ function register_user($username, $password, $name, $email, $allow_multiple_emai
access_show_hidden_entities($access_status);
- // Check to see if we've registered the first admin yet.
- // If not, this is the first admin user!
- $have_admin = datalist_get('admin_registered');
-
// Otherwise ...
$user = new ElggUser();
$user->username = $username;
@@ -1428,9 +1563,13 @@ function register_user($username, $password, $name, $email, $allow_multiple_emai
}
}
+ // Check to see if we've registered the first admin yet.
+ // If not, this is the first admin user!
+ $have_admin = datalist_get('admin_registered');
global $registering_admin;
+
if (!$have_admin) {
- $user->admin = true;
+ $user->makeAdmin();
set_user_validation_status($user->getGUID(), TRUE, 'first_run');
datalist_set('admin_registered', 1);
$registering_admin = true;
diff --git a/engine/lib/widgets.php b/engine/lib/widgets.php
index a450d6223..7884f263a 100644
--- a/engine/lib/widgets.php
+++ b/engine/lib/widgets.php
@@ -254,7 +254,6 @@ function add_widget($user_guid, $handler, $context, $order = 0, $column = 1, $ac
* @param string $position A comma-separated list of positions on the page (side or main) where this widget is allowed (default: "side,main")
* @return true|false Depending on success
*/
-
function add_widget_type($handler, $name, $description, $context = "all", $multiple = false, $positions = "side,main") {
if (!empty($handler) && !empty($name)) {
global $CONFIG;
@@ -283,6 +282,27 @@ function add_widget_type($handler, $name, $description, $context = "all", $multi
}
/**
+ * Remove a widget type
+ *
+ * @param string $handler The identifier for the widget handler
+ */
+function remove_widget_type($handler) {
+ global $CONFIG;
+
+ if (!isset($CONFIG->widgets)) {
+ return;
+ }
+
+ if (!isset($CONFIG->widgets->handlers)) {
+ return;
+ }
+
+ if (isset($CONFIG->widgets->handlers[$handler])) {
+ unset($CONFIG->widgets->handlers[$handler]);
+ }
+}
+
+/**
* Determines whether or not widgets with the specified handler have been defined
*
* @param string $handler The widget handler identifying string
diff --git a/engine/schema/upgrades/2009100701.sql b/engine/schema/upgrades/2009100701.sql
index 0c89441d4..dbf52b4da 100644
--- a/engine/schema/upgrades/2009100701.sql
+++ b/engine/schema/upgrades/2009100701.sql
@@ -1,27 +1,2 @@
-SET NAMES utf8;
-
-ALTER TABLE `prefix_metastrings` DISABLE KEYS;
-REPLACE INTO `prefix_metastrings` (id, string)
- SELECT id, unhex(hex(convert(string using latin1)))
- FROM `prefix_metastrings`;
-ALTER TABLE `prefix_metastrings` ENABLE KEYS;
-
-ALTER TABLE `prefix_groups_entity` DISABLE KEYS;
-REPLACE INTO `prefix_groups_entity` (guid, name, description)
- SELECT guid, unhex(hex(convert(name using latin1))), unhex(hex(convert(description using latin1)))
- FROM `prefix_groups_entity`;
-ALTER TABLE `prefix_groups_entity` ENABLE KEYS;
-
-ALTER TABLE `prefix_objects_entity` DISABLE KEYS;
-REPLACE INTO `prefix_objects_entity` (guid, title, description)
- SELECT guid, unhex(hex(convert(title using latin1))), unhex(hex(convert(description using latin1)))
- FROM `prefix_objects_entity`;
-ALTER TABLE `prefix_objects_entity` ENABLE KEYS;
-
-ALTER TABLE `prefix_users_entity` DISABLE KEYS;
-REPLACE INTO `prefix_users_entity` (guid, name, username, password, salt, email, language, code,
- banned, last_action, prev_last_action, last_login, prev_last_login)
- SELECT guid, unhex(hex(convert(name using latin1))), username, password, salt, email, language, code,
- banned, last_action, prev_last_action, last_login, prev_last_login
- FROM `prefix_users_entity`;
-ALTER TABLE `prefix_users_entity` ENABLE KEYS;
+-- Previously was the UTF8 migration that is now in code at 2010033101.
+-- Keeping this file to force an overwrite and to avoid confusion with missing migrations.
diff --git a/engine/tests/api/entity_getter_functions.php b/engine/tests/api/entity_getter_functions.php
index 49fd4ec0d..1d7261c0d 100644
--- a/engine/tests/api/entity_getter_functions.php
+++ b/engine/tests/api/entity_getter_functions.php
@@ -1365,6 +1365,262 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest {
}
}
+ function testElggApiGettersEntityMetadataNVPValidNValidVEqualsTriple() {
+ $subtypes = $this->getRandomValidSubtypes(array('object'), 1);
+ $subtype = $subtypes[0];
+ $md_name = 'test_metadata_name_' . rand();
+ $md_value = 'test_metadata_value_' . rand();
+
+ $md_name2 = 'test_metadata_name_' . rand();
+ $md_value2 = 'test_metadata_value_' . rand();
+
+ $md_name3 = 'test_metadata_name_' . rand();
+ $md_value3 = 'test_metadata_value_' . rand();
+
+ $guids = array();
+
+ // our target
+ $valid = new ElggObject();
+ $valid->subtype = $subtype;
+ $valid->$md_name = $md_value;
+ $valid->$md_name2 = $md_value2;
+ $valid->$md_name3 = $md_value3;
+ $valid->save();
+ $guids[] = $valid->getGUID();
+
+ // make some bad ones
+ $invalid_md_name = 'test_metadata_name_' . rand();
+ $e = new ElggObject();
+ $e->subtype = $subtype;
+ $e->$md_name = $invalid_md_value;
+ $e->$md_name2 = $invalid_md_value;
+ $e->$md_name3 = $invalid_md_value;
+ $e->save();
+ $guids[] = $e->getGUID();
+
+ $invalid_md_value = 'test_metadata_value_' . rand();
+ $e = new ElggObject();
+ $e->subtype = $subtype;
+ $e->$md_name = $invalid_md_value;
+ $e->$md_name2 = $invalid_md_value;
+ $e->$md_name3 = $invalid_md_value;
+ $e->save();
+ $guids[] = $e->getGUID();
+
+ $md_invalid_names = array();
+
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => $subtype,
+ 'metadata_name_value_pairs' => array(
+ array(
+ 'name' => $md_name,
+ 'value' => $md_value
+ ),
+ array(
+ 'name' => $md_name2,
+ 'value' => $md_value2
+ ),
+ array(
+ 'name' => $md_name3,
+ 'value' => $md_value3
+ )
+ )
+ );
+
+ $entities = elgg_get_entities_from_metadata($options);
+
+ $this->assertIsa($entities, 'array');
+ $this->assertEqual(count($entities), 1);
+
+ foreach ($entities as $entity) {
+ $this->assertEqual($entity->getGUID(), $valid->getGUID());
+ $this->assertEqual($entity->$md_name, $md_value);
+ $entity->delete();
+ }
+
+ foreach ($guids as $guid) {
+ if ($e = get_entity($guid)) {
+ $e->delete();
+ }
+ }
+ }
+
+ function testElggApiGettersEntityMetadataNVPValidNValidVEqualsDouble() {
+ $subtypes = $this->getRandomValidSubtypes(array('object'), 1);
+ $subtype = $subtypes[0];
+ $md_name = 'test_metadata_name_' . rand();
+ $md_value = 'test_metadata_value_' . rand();
+
+ $md_name2 = 'test_metadata_name_' . rand();
+ $md_value2 = 'test_metadata_value_' . rand();
+
+ $guids = array();
+
+ // our target
+ $valid = new ElggObject();
+ $valid->subtype = $subtype;
+ $valid->$md_name = $md_value;
+ $valid->$md_name2 = $md_value2;
+ $valid->save();
+ $guids[] = $valid->getGUID();
+
+ // make some bad ones
+ $invalid_md_name = 'test_metadata_name_' . rand();
+ $e = new ElggObject();
+ $e->subtype = $subtype;
+ $e->$md_name = $invalid_md_value;
+ $e->$md_name2 = $invalid_md_value;
+ $e->save();
+ $guids[] = $e->getGUID();
+
+ $invalid_md_value = 'test_metadata_value_' . rand();
+ $e = new ElggObject();
+ $e->subtype = $subtype;
+ $e->$md_name = $invalid_md_value;
+ $e->$md_name2 = $invalid_md_value;
+ $e->save();
+ $guids[] = $e->getGUID();
+
+ $md_invalid_names = array();
+
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => $subtype,
+ 'metadata_name_value_pairs' => array(
+ array(
+ 'name' => $md_name,
+ 'value' => $md_value
+ ),
+ array(
+ 'name' => $md_name2,
+ 'value' => $md_value2
+ )
+ )
+ );
+
+ $entities = elgg_get_entities_from_metadata($options);
+
+ $this->assertIsa($entities, 'array');
+ $this->assertEqual(count($entities), 1);
+
+ foreach ($entities as $entity) {
+ $this->assertEqual($entity->getGUID(), $valid->getGUID());
+ $this->assertEqual($entity->$md_name, $md_value);
+ $entity->delete();
+ }
+
+ foreach ($guids as $guid) {
+ if ($e = get_entity($guid)) {
+ $e->delete();
+ }
+ }
+ }
+
+ function testElggApiGettersEntityMetadataNVPValidNValidVEqualsStupid() {
+ $subtypes = $this->getRandomValidSubtypes(array('object'), 1);
+ $subtype = $subtypes[0];
+ $md_name = 'test_metadata_name_' . rand();
+ $md_value = 'test_metadata_value_' . rand();
+
+ $md_name2 = 'test_metadata_name_' . rand();
+ $md_value2 = 'test_metadata_value_' . rand();
+
+ $md_name3 = 'test_metadata_name_' . rand();
+ $md_value3 = 'test_metadata_value_' . rand();
+
+ $md_name3 = 'test_metadata_name_' . rand();
+ $md_value3 = 'test_metadata_value_' . rand();
+
+ $md_name4 = 'test_metadata_name_' . rand();
+ $md_value4 = 'test_metadata_value_' . rand();
+
+ $md_name5 = 'test_metadata_name_' . rand();
+ $md_value5 = 'test_metadata_value_' . rand();
+
+ $guids = array();
+
+ // our target
+ $valid = new ElggObject();
+ $valid->subtype = $subtype;
+ $valid->$md_name = $md_value;
+ $valid->$md_name2 = $md_value2;
+ $valid->$md_name3 = $md_value3;
+ $valid->$md_name4 = $md_value4;
+ $valid->$md_name5 = $md_value5;
+ $valid->save();
+ $guids[] = $valid->getGUID();
+
+ // make some bad ones
+ $invalid_md_name = 'test_metadata_name_' . rand();
+ $e = new ElggObject();
+ $e->subtype = $subtype;
+ $e->$md_name = $invalid_md_value;
+ $e->$md_name2 = $invalid_md_value;
+ $e->$md_name3 = $invalid_md_value;
+ $e->$md_name4 = $invalid_md_value;
+ $e->$md_name5 = $invalid_md_value;
+ $e->save();
+ $guids[] = $e->getGUID();
+
+ $invalid_md_value = 'test_metadata_value_' . rand();
+ $e = new ElggObject();
+ $e->subtype = $subtype;
+ $e->$md_name = $invalid_md_value;
+ $e->$md_name2 = $invalid_md_value;
+ $e->$md_name3 = $invalid_md_value;
+ $e->$md_name4 = $invalid_md_value;
+ $e->$md_name5 = $invalid_md_value;
+ $e->save();
+ $guids[] = $e->getGUID();
+
+ $md_invalid_names = array();
+
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => $subtype,
+ 'metadata_name_value_pairs' => array(
+ array(
+ 'name' => $md_name,
+ 'value' => $md_value
+ ),
+ array(
+ 'name' => $md_name2,
+ 'value' => $md_value2
+ ),
+ array(
+ 'name' => $md_name3,
+ 'value' => $md_value3
+ ),
+ array(
+ 'name' => $md_name4,
+ 'value' => $md_value4
+ ),
+ array(
+ 'name' => $md_name5,
+ 'value' => $md_value5
+ ),
+ )
+ );
+
+ $entities = elgg_get_entities_from_metadata($options);
+
+ $this->assertIsa($entities, 'array');
+ $this->assertEqual(count($entities), 1);
+
+ foreach ($entities as $entity) {
+ $this->assertEqual($entity->getGUID(), $valid->getGUID());
+ $this->assertEqual($entity->$md_name, $md_value);
+ $entity->delete();
+ }
+
+ foreach ($guids as $guid) {
+ if ($e = get_entity($guid)) {
+ $e->delete();
+ }
+ }
+ }
+
function testElggApiGettersEntityMetadataNVPValidNInvalidV() {
$subtypes = $this->getRandomValidSubtypes(array('object'), 1);
$subtype = $subtypes[0];
@@ -1730,4 +1986,59 @@ class ElggCoreEntityGetterFunctionsTest extends ElggCoreUnitTest {
}
}
}
+
+ /**
+ * Annotations
+ */
+ public function testElggApiGettersEntitiesFromAnnotation() {
+
+ // grab a few different users to annotation
+ // there will always be at least 2 here because of the construct.
+ $users = elgg_get_entities(array('type' => 'user', 'limit' => 2));
+
+ // create some test annotations
+ $subtypes = $this->getRandomValidSubtypes(array('object'), 1);
+ $subtype = $subtypes[0];
+ $annotation_name = 'test_annotation_name_' . rand();
+ $annotation_value = rand(1000, 9999);
+ $annotation_name2 = 'test_annotation_name_' . rand();
+ $annotation_value2 = rand(1000, 9999);
+ $guids = array();
+
+ // our targets
+ $valid = new ElggObject();
+ $valid->subtype = $subtype;
+ $valid->save();
+ $guids[] = $valid->getGUID();
+ create_annotation($valid->getGUID(), $annotation_name, $annotation_value, 'integer', $users[0]->getGUID());
+
+ $valid2 = new ElggObject();
+ $valid2->subtype = $subtype;
+ $valid2->save();
+ $guids[] = $valid2->getGUID();
+ create_annotation($valid2->getGUID(), $annotation_name2, $annotation_value2, 'integer', $users[1]->getGUID());
+
+ $options = array(
+ 'annotation_owner_guid' => $users[0]->getGUID(),
+ 'annotation_name' => $annotation_name
+ );
+
+ $entities = elgg_get_entities_from_annotations($options);
+
+ foreach ($entities as $entity) {
+ $this->assertTrue(in_array($entity->getGUID(), $guids));
+ $annotations = $entity->getAnnotations($annotation_name);
+ $this->assertEqual(count($annotations), 1);
+
+ $this->assertEqual($annotations[0]->name, $annotation_name);
+ $this->assertEqual($annotations[0]->value, $annotation_value);
+ $this->assertEqual($annotations[0]->owner_guid, $users[0]->getGUID());
+ }
+
+ foreach ($guids as $guid) {
+ if ($e = get_entity($guid)) {
+ $e->delete();
+ }
+ }
+ }
}
diff --git a/engine/tests/objects/users.php b/engine/tests/objects/users.php
index c03091a91..d6d73a37b 100644
--- a/engine/tests/objects/users.php
+++ b/engine/tests/objects/users.php
@@ -14,7 +14,7 @@ class ElggCoreUserTest extends ElggCoreUnitTest {
*/
public function __construct() {
parent::__construct();
-
+
// all code should come after here
}
@@ -31,7 +31,7 @@ class ElggCoreUserTest extends ElggCoreUnitTest {
public function tearDown() {
// do not allow SimpleTest to interpret Elgg notices as exceptions
$this->swallowErrors();
-
+
unset($this->user);
}
@@ -68,17 +68,18 @@ class ElggCoreUserTest extends ElggCoreUnitTest {
$attributes['language'] = '';
$attributes['code'] = '';
$attributes['banned'] = 'no';
-
+ $attributes['admin'] = 'no';
+
$this->assertIdentical($this->user->expose_attributes(), $attributes);
}
-
+
public function testElggUserLoad() {
// new object
$object = new ElggObject();
$this->AssertEqual($object->getGUID(), 0);
$guid = $object->save();
$this->AssertNotEqual($guid, 0);
-
+
// fail on wrong type
try {
$error = new ElggUserTest($guid);
@@ -88,15 +89,15 @@ class ElggCoreUserTest extends ElggCoreUnitTest {
$message = sprintf(elgg_echo('InvalidClassException:NotValidElggStar'), $guid, 'ElggUser');
$this->assertIdentical($e->getMessage(), $message);
}
-
+
// clean up
$object->delete();
}
-
+
public function testElggUserConstructorByGuid() {
$user = new ElggUser(get_loggedin_userid());
$this->assertIdentical($user, $_SESSION['user']);
-
+
// fail with garbage
try {
$error = new ElggUserTest(array('invalid'));
@@ -107,57 +108,141 @@ class ElggCoreUserTest extends ElggCoreUnitTest {
$this->assertIdentical($e->getMessage(), $message);
}
}
-
+
public function testElggUserConstructorByDbRow() {
$row = $this->fetchUser(get_loggedin_userid());
$user = new ElggUser($row);
$this->assertIdentical($user, $_SESSION['user']);
}
-
+
public function testElggUserConstructorByUsername() {
$row = $this->fetchUser(get_loggedin_userid());
$user = new ElggUser($row->username);
$this->assertIdentical($user, $_SESSION['user']);
}
-
+
public function testElggUserSave() {
// new object
$this->AssertEqual($this->user->getGUID(), 0);
$guid = $this->user->save();
$this->AssertNotEqual($guid, 0);
-
+
// clean up
$this->user->delete();
}
-
+
public function testElggUserDelete() {
$guid = $this->user->save();
-
+
// delete object
$this->assertTrue($this->user->delete());
-
+
// check GUID not in database
$this->assertFalse($this->fetchUser($guid));
}
-
+
public function testElggUserNameCache() {
// Trac #1305
-
+
// very unlikely a user would have this username
$name = (string)time();
$this->user->username = $name;
-
+
$guid = $this->user->save();
-
- $user = get_user_by_username($name);
- $user->delete();
+
+ $user = get_user_by_username($name);
+ $user->delete();
$user = get_user_by_username($name);
$this->assertFalse($user);
}
-
+
+
+ public function testElggUserMakeAdmin() {
+ global $CONFIG;
+
+ // need to save user to have a guid
+ $guid = $this->user->save();
+
+ $this->assertTrue($this->user->makeAdmin());
+
+ $q = "SELECT admin FROM {$CONFIG->dbprefix}users_entity WHERE guid = $guid";
+ $r = mysql_query($q);
+
+ $admin = mysql_fetch_assoc($r);
+ $this->assertEqual($admin['admin'], 'yes');
+
+ $this->user->delete();
+ }
+
+ public function testElggUserRemoveAdmin() {
+ global $CONFIG;
+
+ // need to save user to have a guid
+ $guid = $this->user->save();
+
+ $this->assertTrue($this->user->removeAdmin());
+
+ $q = "SELECT admin FROM {$CONFIG->dbprefix}users_entity WHERE guid = $guid";
+ $r = mysql_query($q);
+
+ $admin = mysql_fetch_assoc($r);
+ $this->assertEqual($admin['admin'], 'no');
+
+ $this->user->delete();
+ }
+
+ public function testElggUserIsAdmin() {
+ // need to grab a real user with a guid and everything.
+ $guid = $this->user->save();
+
+ $this->assertTrue($this->user->makeAdmin());
+
+ // this is testing the function, not the SQL.
+ // that's been tested above.
+ $this->assertTrue($this->user->isAdmin());
+
+ $this->user->delete();
+ }
+
+ public function testElggUserIsNotAdmin() {
+ // need to grab a real user with a guid and everything.
+ $guid = $this->user->save();
+
+ $this->assertTrue($this->user->removeAdmin());
+
+ // this is testing the function, not the SQL.
+ // that's been tested above.
+ $this->assertFalse($this->user->isAdmin());
+
+ $this->user->delete();
+ }
+
+ // remove in 1.9
+ public function testElggUserIsAdminLegacy() {
+ $this->user->save();
+ $this->user->makeAdmin();
+
+ $this->assertTrue($this->user->admin);
+ $this->assertTrue($this->user->siteadmin);
+
+ $this->user->removeAdmin();
+ $this->user->delete();
+ }
+
+ public function testElggUserIsNotAdminLegacy() {
+ $this->user->save();
+ $this->user->removeAdmin();
+
+ $this->assertFalse($this->user->admin);
+ $this->assertFalse($this->user->siteadmin);
+
+ $this->user->removeAdmin();
+ $this->user->delete();
+ }
+
protected function fetchUser($guid) {
global $CONFIG;
-
+
return get_data_row("SELECT * FROM {$CONFIG->dbprefix}users_entity WHERE guid = '$guid'");
}
}