diff options
Diffstat (limited to 'engine/lib')
31 files changed, 1271 insertions, 326 deletions
| diff --git a/engine/lib/access.php b/engine/lib/access.php index dba1e1ec6..6be252c6a 100644 --- a/engine/lib/access.php +++ b/engine/lib/access.php @@ -671,8 +671,10 @@ function add_user_to_access_collection($user_guid, $collection_id) {  		return false;  	} +	// if someone tries to insert the same data twice, we do a no-op on duplicate key  	$q = "INSERT INTO {$CONFIG->dbprefix}access_collection_membership -			SET access_collection_id = {$collection_id}, user_guid = {$user_guid}"; +			SET access_collection_id = $collection_id, user_guid = $user_guid +			ON DUPLICATE KEY UPDATE user_guid = user_guid";  	$result = insert_data($q);  	return $result !== false; diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index 5049d455b..f32dee0f0 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -209,9 +209,11 @@ function elgg_get_annotations(array $options = array()) {   * Deletes annotations based on $options.   *   * @warning Unlike elgg_get_annotations() this will not accept an empty options array! + *          This requires at least one constraint: annotation_owner_guid(s), + *          annotation_name(s), annotation_value(s), or guid(s) must be set.   *   * @param array $options An options array. {@See elgg_get_annotations()} - * @return mixed + * @return mixed Null if the metadata name is invalid. Bool on success or fail.   * @since 1.8.0   */  function elgg_delete_annotations(array $options) { diff --git a/engine/lib/cache.php b/engine/lib/cache.php index e71ef332d..c117b9ec9 100644 --- a/engine/lib/cache.php +++ b/engine/lib/cache.php @@ -10,15 +10,14 @@  /* Filepath Cache */  /** - * Returns an ElggCache object suitable for caching view - * file load paths to disk under $CONFIG->dataroot. + * Returns an ElggCache object suitable for caching system information   *   * @todo Can this be done in a cleaner way?   * @todo Swap to memcache etc?   * - * @return ElggFileCache A cache object suitable for caching file load paths. + * @return ElggFileCache   */ -function elgg_get_filepath_cache() { +function elgg_get_system_cache() {  	global $CONFIG;  	/** @@ -27,36 +26,34 @@ function elgg_get_filepath_cache() {  	static $FILE_PATH_CACHE;  	if (!$FILE_PATH_CACHE) { -		$FILE_PATH_CACHE = new ElggFileCache($CONFIG->dataroot); +		$FILE_PATH_CACHE = new ElggFileCache($CONFIG->dataroot . 'system_cache/');  	}  	return $FILE_PATH_CACHE;  }  /** - * Reset the file path cache. + * Reset the system cache by deleting the caches   * - * @return bool + * @return void   */ -function elgg_filepath_cache_reset() { -	$cache = elgg_get_filepath_cache(); -	$view_types_result = $cache->delete('view_types'); -	$views_result = $cache->delete('views'); -	return $view_types_result && $views_result; +function elgg_reset_system_cache() { +	$cache = elgg_get_system_cache(); +	$cache->clear();  }  /** - * Saves a filepath cache. + * Saves a system cache.   *   * @param string $type The type or identifier of the cache   * @param string $data The data to be saved   * @return bool   */ -function elgg_filepath_cache_save($type, $data) { +function elgg_save_system_cache($type, $data) {  	global $CONFIG; -	if ($CONFIG->viewpath_cache_enabled) { -		$cache = elgg_get_filepath_cache(); +	if ($CONFIG->system_cache_enabled) { +		$cache = elgg_get_system_cache();  		return $cache->save($type, $data);  	} @@ -64,16 +61,16 @@ function elgg_filepath_cache_save($type, $data) {  }  /** - * Retrieve the contents of the filepath cache. + * Retrieve the contents of a system cache.   *   * @param string $type The type of cache to load   * @return string   */ -function elgg_filepath_cache_load($type) { +function elgg_load_system_cache($type) {  	global $CONFIG; -	if ($CONFIG->viewpath_cache_enabled) { -		$cache = elgg_get_filepath_cache(); +	if ($CONFIG->system_cache_enabled) { +		$cache = elgg_get_system_cache();  		$cached_data = $cache->load($type);  		if ($cached_data) { @@ -85,35 +82,74 @@ function elgg_filepath_cache_load($type) {  }  /** - * Enables the views file paths disk cache. + * Enables the system disk cache.   * - * Uses the 'viewpath_cache_enabled' datalist with a boolean value. - * Resets the views paths cache. + * Uses the 'system_cache_enabled' datalist with a boolean value. + * Resets the system cache.   *   * @return void   */ -function elgg_enable_filepath_cache() { +function elgg_enable_system_cache() {  	global $CONFIG; -	datalist_set('viewpath_cache_enabled', 1); -	$CONFIG->viewpath_cache_enabled = 1; -	elgg_filepath_cache_reset(); +	datalist_set('system_cache_enabled', 1); +	$CONFIG->system_cache_enabled = 1; +	elgg_reset_system_cache();  }  /** - * Disables the views file paths disk cache. + * Disables the system disk cache.   * - * Uses the 'viewpath_cache_enabled' datalist with a boolean value. - * Resets the views paths cache. + * Uses the 'system_cache_enabled' datalist with a boolean value. + * Resets the system cache.   *   * @return void   */ -function elgg_disable_filepath_cache() { +function elgg_disable_system_cache() {  	global $CONFIG; -	datalist_set('viewpath_cache_enabled', 0); -	$CONFIG->viewpath_cache_enabled = 0; -	elgg_filepath_cache_reset(); +	datalist_set('system_cache_enabled', 0); +	$CONFIG->system_cache_enabled = 0; +	elgg_reset_system_cache(); +} + +/** @todo deprecate in Elgg 1.9 **/ + +/** + * @access private + */ +function elgg_get_filepath_cache() { +	return elgg_get_system_cache(); +} +/** + * @access private + */ +function elgg_filepath_cache_reset() { +	return elgg_reset_system_cache(); +} +/** + * @access private + */ +function elgg_filepath_cache_save($type, $data) { +	return elgg_save_system_cache($type, $data); +} +/** + * @access private + */ +function elgg_filepath_cache_load($type) { +	return elgg_load_system_cache($type); +} +/** + * @access private + */ +function elgg_enable_filepath_cache() { +	return elgg_enable_system_cache(); +} +/** + * @access private + */ +function elgg_disable_filepath_cache() { +	return elgg_disable_system_cache();  }  /* Simplecache */ @@ -333,7 +369,7 @@ function elgg_invalidate_simplecache() {  	$return = true;  	while (false !== ($file = readdir($handle))) {  		if ($file != "." && $file != "..") { -			$return = $return && unlink($CONFIG->dataroot . 'views_simplecache/' . $file); +			$return &= unlink($CONFIG->dataroot . 'views_simplecache/' . $file);  		}  	}  	closedir($handle); @@ -346,9 +382,70 @@ function elgg_invalidate_simplecache() {  	}  	foreach ($viewtypes as $viewtype) { -		$return = $return && datalist_set("simplecache_lastupdate_$viewtype", 0); -		$return = $return && datalist_set("simplecache_lastcached_$viewtype", 0); +		$return &= datalist_set("simplecache_lastupdate_$viewtype", 0); +		$return &= datalist_set("simplecache_lastcached_$viewtype", 0);  	}  	return $return;  } + +/** + * @see elgg_reset_system_cache() + * @access private + */ +function _elgg_load_cache() { +	global $CONFIG; + +	$CONFIG->system_cache_loaded = false; + +	$CONFIG->views = new stdClass(); +	$data = elgg_load_system_cache('view_locations'); +	if (!is_string($data)) { +		return; +	} +	$CONFIG->views->locations = unserialize($data); +	 +	$data = elgg_load_system_cache('view_types'); +	if (!is_string($data)) { +		return; +	} +	$CONFIG->view_types = unserialize($data); + +	$CONFIG->system_cache_loaded = true; +} + +/** + * @access private + */ +function _elgg_cache_init() { +	global $CONFIG; + +	$viewtype = elgg_get_viewtype(); + +	// Regenerate the simple cache if expired. +	// Don't do it on upgrade because upgrade does it itself. +	// @todo - move into function and perhaps run off init system event +	if (!defined('UPGRADING')) { +		$lastupdate = datalist_get("simplecache_lastupdate_$viewtype"); +		$lastcached = datalist_get("simplecache_lastcached_$viewtype"); +		if ($lastupdate == 0 || $lastcached < $lastupdate) { +			elgg_regenerate_simplecache($viewtype); +			$lastcached = datalist_get("simplecache_lastcached_$viewtype"); +		} +		$CONFIG->lastcache = $lastcached; +	} + +	// cache system data if enabled and not loaded +	if ($CONFIG->system_cache_enabled && !$CONFIG->system_cache_loaded) { +		elgg_save_system_cache('view_locations', serialize($CONFIG->views->locations)); +		elgg_save_system_cache('view_types', serialize($CONFIG->view_types)); +	} + +	if ($CONFIG->system_cache_enabled && !$CONFIG->i18n_loaded_from_cache) { +		foreach ($CONFIG->translations as $lang => $map) { +			elgg_save_system_cache("$lang.php", serialize($map)); +		} +	} +} + +elgg_register_event_handler('ready', 'system', '_elgg_cache_init'); diff --git a/engine/lib/calendar.php b/engine/lib/calendar.php new file mode 100644 index 000000000..9a06c5292 --- /dev/null +++ b/engine/lib/calendar.php @@ -0,0 +1,571 @@ +<?php +/** + * Elgg calendar / entity / event functions. + * + * @package    Elgg.Core + * @subpackage Calendar + * + * @todo Implement or remove + */ + +/** + * Return a timestamp for the start of a given day (defaults today). + * + * @param int $day   Day + * @param int $month Month + * @param int $year  Year + * + * @return int + * @access private + */ +function get_day_start($day = null, $month = null, $year = null) { +	return mktime(0, 0, 0, $month, $day, $year); +} + +/** + * Return a timestamp for the end of a given day (defaults today). + * + * @param int $day   Day + * @param int $month Month + * @param int $year  Year + * + * @return int + * @access private + */ +function get_day_end($day = null, $month = null, $year = null) { +	return mktime(23, 59, 59, $month, $day, $year); +} + +/** + * Return the notable entities for a given time period. + * + * @param int     $start_time     The start time as a unix timestamp. + * @param int     $end_time       The end time as a unix timestamp. + * @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          Set to true to get a count instead of entities. Defaults to false. + * @param int     $site_guid      Site to get entities for. Default 0 = current site. -1 = any. + * @param mixed   $container_guid Container or containers to get entities from (default: any). + * + * @return array|false + * @access private + */ +function get_notable_entities($start_time, $end_time, $type = "", $subtype = "", $owner_guid = 0, +$order_by = "asc", $limit = 10, $offset = 0, $count = false, $site_guid = 0, +$container_guid = null) { +	global $CONFIG; + +	if ($subtype === false || $subtype === null || $subtype === 0) { +		return false; +	} + +	$start_time = (int)$start_time; +	$end_time = (int)$end_time; +	$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; +	} + +	$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)) { +						$subtypeval = (int) get_subtype_id($typekey, $subtypeval); +					} 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); +		$subtype = get_subtype_id($type, $subtype); + +		if ($type != "") { +			$where[] = "e.type='$type'"; +		} + +		if ($subtype !== "") { +			$where[] = "e.subtype=$subtype"; +		} +	} + +	if ($owner_guid != "") { +		if (!is_array($owner_guid)) { +			$owner_array = array($owner_guid); +			$owner_guid = (int) $owner_guid; +			$where[] = "e.owner_guid = '$owner_guid'"; +		} else if (sizeof($owner_guid) > 0) { +			$owner_array = array_map('sanitise_int', $owner_guid); +			// Cast every element to the owner_guid array to int +			$owner_guid = implode(",", $owner_guid); +			$where[] = "e.owner_guid in ({$owner_guid})"; +		} +		if (is_null($container_guid)) { +			$container_guid = $owner_array; +		} +	} + +	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; +			} +			$where[] = "e.container_guid in (" . implode(",", $container_guid) . ")"; +		} else { +			$container_guid = (int) $container_guid; +			$where[] = "e.container_guid = {$container_guid}"; +		} +	} + +	// Add the calendar stuff +	$cal_join = " +		JOIN {$CONFIG->dbprefix}metadata cal_start on e.guid=cal_start.entity_guid +		JOIN {$CONFIG->dbprefix}metastrings cal_start_name on cal_start.name_id=cal_start_name.id +		JOIN {$CONFIG->dbprefix}metastrings cal_start_value on cal_start.value_id=cal_start_value.id + +		JOIN {$CONFIG->dbprefix}metadata cal_end on e.guid=cal_end.entity_guid +		JOIN {$CONFIG->dbprefix}metastrings cal_end_name on cal_end.name_id=cal_end_name.id +		JOIN {$CONFIG->dbprefix}metastrings cal_end_value on cal_end.value_id=cal_end_value.id +	"; +	$where[] = "cal_start_name.string='calendar_start'"; +	$where[] = "cal_start_value.string>=$start_time"; +	$where[] = "cal_end_name.string='calendar_end'"; +	$where[] = "cal_end_value.string <= $end_time"; + + +	if (!$count) { +		$query = "SELECT e.* from {$CONFIG->dbprefix}entities e $cal_join where "; +	} else { +		$query = "SELECT count(e.guid) as total from {$CONFIG->dbprefix}entities e $cal_join where "; +	} +	foreach ($where as $w) { +		$query .= " $w and "; +	} + +	$query .= get_access_sql_suffix('e'); // Add access controls + +	if (!$count) { +		$query .= " order by n.calendar_start $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 the notable entities for a given time period based on an item of metadata. + * + * @param int    $start_time     The start time as a unix timestamp. + * @param int    $end_time       The end time as a unix timestamp. + * @param mixed  $meta_name      Metadata name + * @param mixed  $meta_value     Metadata value + * @param string $entity_type    The type of entity to look for, eg 'site' or 'object' + * @param string $entity_subtype The subtype of the entity. + * @param int    $owner_guid     Owner GUID + * @param int    $limit          Limit + * @param int    $offset         Offset + * @param string $order_by       Optional ordering. + * @param int    $site_guid      Site to get entities for. Default 0 = current site. -1 = any. + * @param bool   $count          If true, returns count instead of entities. (Default: false) + * + * @return int|array A list of entities, or a count if $count is set to true + * @access private + */ +function get_notable_entities_from_metadata($start_time, $end_time, $meta_name, $meta_value = "", +$entity_type = "", $entity_subtype = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "", +$site_guid = 0, $count = false) { + +	global $CONFIG; + +	$meta_n = get_metastring_id($meta_name); +	$meta_v = get_metastring_id($meta_value); + +	$start_time = (int)$start_time; +	$end_time = (int)$end_time; +	$entity_type = sanitise_string($entity_type); +	$entity_subtype = get_subtype_id($entity_type, $entity_subtype); +	$limit = (int)$limit; +	$offset = (int)$offset; +	if ($order_by == "") { +		$order_by = "e.time_created desc"; +	} +	$order_by = sanitise_string($order_by); +	$site_guid = (int) $site_guid; +	if ((is_array($owner_guid) && (count($owner_guid)))) { +		foreach ($owner_guid as $key => $guid) { +			$owner_guid[$key] = (int) $guid; +		} +	} else { +		$owner_guid = (int) $owner_guid; +	} + +	if ($site_guid == 0) { +		$site_guid = $CONFIG->site_guid; +	} + +	//$access = get_access_list(); + +	$where = array(); + +	if ($entity_type != "") { +		$where[] = "e.type='$entity_type'"; +	} + +	if ($entity_subtype) { +		$where[] = "e.subtype=$entity_subtype"; +	} + +	if ($meta_name != "") { +		$where[] = "m.name_id='$meta_n'"; +	} + +	if ($meta_value != "") { +		$where[] = "m.value_id='$meta_v'"; +	} + +	if ($site_guid > 0) { +		$where[] = "e.site_guid = {$site_guid}"; +	} + +	if (is_array($owner_guid)) { +		$where[] = "e.container_guid in (" . implode(",", $owner_guid) . ")"; +	} else if ($owner_guid > 0) { +		$where[] = "e.container_guid = {$owner_guid}"; +	} + +	// Add the calendar stuff +	$cal_join = " +		JOIN {$CONFIG->dbprefix}metadata cal_start on e.guid=cal_start.entity_guid +		JOIN {$CONFIG->dbprefix}metastrings cal_start_name on cal_start.name_id=cal_start_name.id +		JOIN {$CONFIG->dbprefix}metastrings cal_start_value on cal_start.value_id=cal_start_value.id + +		JOIN {$CONFIG->dbprefix}metadata cal_end on e.guid=cal_end.entity_guid +		JOIN {$CONFIG->dbprefix}metastrings cal_end_name on cal_end.name_id=cal_end_name.id +		JOIN {$CONFIG->dbprefix}metastrings cal_end_value on cal_end.value_id=cal_end_value.id +	"; + +	$where[] = "cal_start_name.string='calendar_start'"; +	$where[] = "cal_start_value.string>=$start_time"; +	$where[] = "cal_end_name.string='calendar_end'"; +	$where[] = "cal_end_value.string <= $end_time"; + +	if (!$count) { +		$query = "SELECT distinct e.* "; +	} else { +		$query = "SELECT count(distinct e.guid) as total "; +	} + +	$query .= "from {$CONFIG->dbprefix}entities e" +	. " JOIN {$CONFIG->dbprefix}metadata m on e.guid = m.entity_guid $cal_join where"; + +	foreach ($where as $w) { +		$query .= " $w and "; +	} + +	// Add access controls +	$query .= get_access_sql_suffix("e"); +	$query .= ' and ' . get_access_sql_suffix("m"); + +	if (!$count) { +		// Add order and limit +		$query .= " order by $order_by limit $offset, $limit"; +		return get_data($query, "entity_row_to_elggstar"); +	} else { +		if ($row = get_data_row($query)) { +			return $row->total; +		} +	} + +	return false; +} + +/** + * Return the notable entities for a given time period based on their relationship. + * + * @param int     $start_time           The start time as a unix timestamp. + * @param int     $end_time             The end time as a unix timestamp. + * @param string  $relationship         The relationship eg "friends_of" + * @param int     $relationship_guid    The guid of the entity to use query + * @param bool    $inverse_relationship Reverse the normal function of the query to say + *                                      "give me all entities for whom $relationship_guid is a + *                                      $relationship of" + * @param string  $type                 Entity type + * @param string  $subtype              Entity subtype + * @param int     $owner_guid           Owner GUID + * @param string  $order_by             Optional Order by + * @param int     $limit                Limit + * @param int     $offset               Offset + * @param boolean $count                If true returns a count of entities (default false) + * @param int     $site_guid            Site to get entities for. Default 0 = current site. -1 = any + * + * @return array|int|false An array of entities, or the number of entities, or false on failure + * @access private + */ +function get_noteable_entities_from_relationship($start_time, $end_time, $relationship, +$relationship_guid, $inverse_relationship = false, $type = "", $subtype = "", $owner_guid = 0, +$order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0) { + +	global $CONFIG; + +	$start_time = (int)$start_time; +	$end_time = (int)$end_time; +	$relationship = sanitise_string($relationship); +	$relationship_guid = (int)$relationship_guid; +	$inverse_relationship = (bool)$inverse_relationship; +	$type = sanitise_string($type); +	$subtype = get_subtype_id($type, $subtype); +	$owner_guid = (int)$owner_guid; +	if ($order_by == "") { +		$order_by = "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; +	} + +	//$access = get_access_list(); + +	$where = array(); + +	if ($relationship != "") { +		$where[] = "r.relationship='$relationship'"; +	} +	if ($relationship_guid) { +		$where[] = $inverse_relationship ? +			"r.guid_two='$relationship_guid'" : "r.guid_one='$relationship_guid'"; +	} +	if ($type != "") { +		$where[] = "e.type='$type'"; +	} +	if ($subtype) { +		$where[] = "e.subtype=$subtype"; +	} +	if ($owner_guid != "") { +		$where[] = "e.container_guid='$owner_guid'"; +	} +	if ($site_guid > 0) { +		$where[] = "e.site_guid = {$site_guid}"; +	} + +	// Add the calendar stuff +	$cal_join = " +		JOIN {$CONFIG->dbprefix}metadata cal_start on e.guid=cal_start.entity_guid +		JOIN {$CONFIG->dbprefix}metastrings cal_start_name on cal_start.name_id=cal_start_name.id +		JOIN {$CONFIG->dbprefix}metastrings cal_start_value on cal_start.value_id=cal_start_value.id + +		JOIN {$CONFIG->dbprefix}metadata cal_end on e.guid=cal_end.entity_guid +		JOIN {$CONFIG->dbprefix}metastrings cal_end_name on cal_end.name_id=cal_end_name.id +		JOIN {$CONFIG->dbprefix}metastrings cal_end_value on cal_end.value_id=cal_end_value.id +	"; +	$where[] = "cal_start_name.string='calendar_start'"; +	$where[] = "cal_start_value.string>=$start_time"; +	$where[] = "cal_end_name.string='calendar_end'"; +	$where[] = "cal_end_value.string <= $end_time"; + +	// Select what we're joining based on the options +	$joinon = "e.guid = r.guid_one"; +	if (!$inverse_relationship) { +		$joinon = "e.guid = r.guid_two"; +	} + +	if ($count) { +		$query = "SELECT count(distinct e.guid) as total "; +	} else { +		$query = "SELECT distinct e.* "; +	} +	$query .= " from {$CONFIG->dbprefix}entity_relationships r" +	. " JOIN {$CONFIG->dbprefix}entities e on $joinon $cal_join where "; + +	foreach ($where as $w) { +		$query .= " $w and "; +	} +	// Add access controls +	$query .= get_access_sql_suffix("e"); +	if (!$count) { +		$query .= " order by $order_by limit $offset, $limit"; // Add order and limit +		return get_data($query, "entity_row_to_elggstar"); +	} else { +		if ($count = get_data_row($query)) { +			return $count->total; +		} +	} +	return false; +} + +/** + * Get all entities for today. + * + * @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          If true returns a count of entities (default false) + * @param int     $site_guid      Site to get entities for. Default 0 = current site. -1 = any + * @param mixed   $container_guid Container(s) to get entities from (default: any). + * + * @return array|false + * @access private + */ +function get_todays_entities($type = "", $subtype = "", $owner_guid = 0, $order_by = "", +$limit = 10, $offset = 0, $count = false, $site_guid = 0, $container_guid = null) { + +	$day_start = get_day_start(); +	$day_end = get_day_end(); + +	return get_notable_entities($day_start, $day_end, $type, $subtype, $owner_guid, $order_by, +		$limit, $offset, $count, $site_guid, $container_guid); +} + +/** + * Get entities for today from metadata. + * + * @param mixed  $meta_name      Metadata name + * @param mixed  $meta_value     Metadata value + * @param string $entity_type    The type of entity to look for, eg 'site' or 'object' + * @param string $entity_subtype The subtype of the entity. + * @param int    $owner_guid     Owner GUID + * @param int    $limit          Limit + * @param int    $offset         Offset + * @param string $order_by       Optional ordering. + * @param int    $site_guid      Site to get entities for. Default 0 = current site. -1 = any. + * @param bool   $count          If true, returns count instead of entities. (Default: false) + * + * @return int|array A list of entities, or a count if $count is set to true + * @access private + */ +function get_todays_entities_from_metadata($meta_name, $meta_value = "", $entity_type = "", +$entity_subtype = "", $owner_guid = 0, $limit = 10, $offset = 0, $order_by = "", $site_guid = 0, +$count = false) { + +	$day_start = get_day_start(); +	$day_end = get_day_end(); + +	return get_notable_entities_from_metadata($day_start, $day_end, $meta_name, $meta_value, +		$entity_type, $entity_subtype, $owner_guid, $limit, $offset, $order_by, $site_guid, $count); +} + +/** + * Get entities for today from a relationship + * + * @param string  $relationship         The relationship eg "friends_of" + * @param int     $relationship_guid    The guid of the entity to use query + * @param bool    $inverse_relationship Reverse the normal function of the query to say + *                                      "give me all entities for whom $relationship_guid is a + *                                      $relationship of" + * @param string  $type                 Entity type + * @param string  $subtype              Entity subtype + * @param int     $owner_guid           Owner GUID + * @param string  $order_by             Optional Order by + * @param int     $limit                Limit + * @param int     $offset               Offset + * @param boolean $count                If true returns a count of entities (default false) + * @param int     $site_guid            Site to get entities for. Default 0 = current site. -1 = any + * + * @return array|int|false An array of entities, or the number of entities, or false on failure + * @access private + */ +function get_todays_entities_from_relationship($relationship, $relationship_guid, +$inverse_relationship = false, $type = "", $subtype = "", $owner_guid = 0, +$order_by = "", $limit = 10, $offset = 0, $count = false, $site_guid = 0) { + +	$day_start = get_day_start(); +	$day_end = get_day_end(); + +	return get_notable_entities_from_relationship($day_start, $day_end, $relationship, +		$relationship_guid,	$inverse_relationship, $type, $subtype, $owner_guid, $order_by, +		$limit, $offset, $count, $site_guid); +} + +/** + * Returns a viewable list of entities for a given time period. + * + * @see elgg_view_entity_list + * + * @param int     $start_time     The start time as a unix timestamp. + * @param int     $end_time       The end time as a unix timestamp. + * @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 int     $limit          The number of entities to return; 10 by default + * @param boolean $fullview       Whether or not to display the full view (default: true) + * @param boolean $listtypetoggle Whether or not to allow gallery view + * @param boolean $navigation     Display pagination? Default: true + * + * @return string A viewable list of entities + * @access private + */ +function list_notable_entities($start_time, $end_time, $type= "", $subtype = "", $owner_guid = 0, +$limit = 10, $fullview = true, $listtypetoggle = false, $navigation = true) { + +	$offset = (int) get_input('offset'); +	$count = get_notable_entities($start_time, $end_time, $type, $subtype, +		$owner_guid, "", $limit, $offset, true); + +	$entities = get_notable_entities($start_time, $end_time, $type, $subtype, +		$owner_guid, "", $limit, $offset); + +	return elgg_view_entity_list($entities, $count, $offset, $limit, +		$fullview, $listtypetoggle, $navigation); +} + +/** + * Return a list of today's entities. + * + * @see list_notable_entities + * + * @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 int     $limit          The number of entities to return; 10 by default + * @param boolean $fullview       Whether or not to display the full view (default: true) + * @param boolean $listtypetoggle Whether or not to allow gallery view + * @param boolean $navigation     Display pagination? Default: true + * + * @return string A viewable list of entities + * @access private + */ +function list_todays_entities($type= "", $subtype = "", $owner_guid = 0, $limit = 10, +$fullview = true, $listtypetoggle = false, $navigation = true) { + +	$day_start = get_day_start(); +	$day_end = get_day_end(); + +	return list_notable_entities($day_start, $day_end, $type, $subtype, $owner_guid, $limit, +		$fullview, $listtypetoggle, $navigation); +} diff --git a/engine/lib/configuration.php b/engine/lib/configuration.php index 3fade8155..9bf1529d6 100644 --- a/engine/lib/configuration.php +++ b/engine/lib/configuration.php @@ -3,8 +3,9 @@   * Elgg configuration procedural code.   *   * Includes functions for manipulating the configuration values stored in the database - * Plugin authors should use the {@link get_config()}, {@link set_config()}, - * and {@unset_config()} functions to access or update config values. + * Plugin authors should use the {@link elgg_get_config()}, {@link elgg_set_config()}, + * {@link elgg_save_config()}, and {@unset_config()} functions to access or update + * config values.   *   * Elgg's configuration is split among 2 tables and 1 file:   * - dbprefix_config @@ -302,7 +303,7 @@ function datalist_set($name, $value) {  		. " set name = '{$sanitised_name}', value = '{$sanitised_value}'"  		. " ON DUPLICATE KEY UPDATE value='{$sanitised_value}'"); -	if ($success) { +	if ($success !== FALSE) {  		$DATALIST_CACHE[$name] = $value;  		return true;  	} else { @@ -517,10 +518,10 @@ function get_all_config($site_guid = 0) {  	$site_guid = (int) $site_guid;  	if ($site_guid == 0) { -		$site_guid = (int) $CONFIG->site_id; +		$site_guid = (int) $CONFIG->site_guid;  	} -	if ($result = get_data("SELECT * from {$CONFIG->dbprefix}config where site_guid = {$site_guid}")) { +	if ($result = get_data("SELECT * FROM {$CONFIG->dbprefix}config WHERE site_guid = $site_guid")) {  		foreach ($result as $r) {  			$name = $r->name;  			$value = $r->value; @@ -533,37 +534,49 @@ function get_all_config($site_guid = 0) {  }  /** - * Sets defaults for or attempts to autodetect some common config values and - * loads them into $CONFIG. + * Loads configuration related to this site   * - * @return true + * This loads from the config database table and the site entity   * @access private   */ -function set_default_config() { +function _elgg_load_site_config() {  	global $CONFIG; -	$install_root = str_replace("\\", "/", dirname(dirname(dirname(__FILE__)))); - -	// @todo this seldom works right. -	$pathpart = str_replace("//", "/", str_replace($_SERVER['DOCUMENT_ROOT'], "", $install_root)); -	if (substr($pathpart, 0, 1) != "/") { -		$pathpart = "/" . $pathpart; +	$CONFIG->site_guid = (int) datalist_get('default_site'); +	$CONFIG->site_id = $CONFIG->site_guid; +	$CONFIG->site = get_entity($CONFIG->site_guid); +	if (!$CONFIG->site) { +		throw new InstallationException(elgg_echo('InstallationException:SiteNotInstalled'));  	} -	$www_root = "http://" . $_SERVER['HTTP_HOST'] . $pathpart; +	$CONFIG->wwwroot = $CONFIG->site->url; +	$CONFIG->sitename = $CONFIG->site->name; +	$CONFIG->sitedescription = $CONFIG->site->description; +	$CONFIG->siteemail = $CONFIG->site->email; +	$CONFIG->url = $CONFIG->wwwroot; + +	get_all_config(); +} + +/** + * Loads configuration related to Elgg as an application + * + * This loads from the datalists database table + * @access private + */ +function _elgg_load_application_config() { +	global $CONFIG; + +	$install_root = str_replace("\\", "/", dirname(dirname(dirname(__FILE__))));  	$defaults = array(  		'path'			=>	"$install_root/",  		'view_path'		=>	"$install_root/views/",  		'plugins_path'	=>	"$install_root/mod/", -		'wwwroot'		=>	$www_root, -		'url'			=>	$www_root, -		'site_name'		=>	'New Elgg site',  		'language'		=>	'en', -		// compatibility with old names for ppl not using get_config() +		// compatibility with old names for plugins not using elgg_get_config()  		'viewpath'		=>	"$install_root/views/",  		'pluginspath'	=>	"$install_root/mod/", -		'sitename'		=>	'New Elgg site',  	);  	foreach ($defaults as $name => $value) { @@ -572,25 +585,6 @@ function set_default_config() {  		}  	} -	$CONFIG->context = array(); - -	return true; -} - -/** - * Loads values into $CONFIG. - * - * If Elgg is installed, this function pulls all rows from dbprefix_config - * and cherry picks some values from dbprefix_datalists.  This also extracts - * some commonly used values from the default site object. - * - * @elgg_event boot system - * @return true|null - * @access private - */ -function configuration_boot() { -	global $CONFIG; -  	$path = datalist_get('path');  	if (!empty($path)) {  		$CONFIG->path = $path; @@ -605,22 +599,23 @@ function configuration_boot() {  	} else {  		$CONFIG->simplecache_enabled = 1;  	} -	$viewpath_cache_enabled = datalist_get('viewpath_cache_enabled'); -	if ($viewpath_cache_enabled !== false) { -		$CONFIG->viewpath_cache_enabled = $viewpath_cache_enabled; +	$system_cache_enabled = datalist_get('system_cache_enabled'); +	if ($system_cache_enabled !== false) { +		$CONFIG->system_cache_enabled = $system_cache_enabled;  	} else { -		$CONFIG->viewpath_cache_enabled = 1; +		$CONFIG->system_cache_enabled = 1;  	} -	if (isset($CONFIG->site) && ($CONFIG->site instanceof ElggSite)) { -		$CONFIG->wwwroot = $CONFIG->site->url; -		$CONFIG->sitename = $CONFIG->site->name; -		$CONFIG->sitedescription = $CONFIG->site->description; -		$CONFIG->siteemail = $CONFIG->site->email; -	} -	$CONFIG->url = $CONFIG->wwwroot; -	// Load default settings from database -	get_all_config(); -} +	// initialize context here so it is set before the get_input call +	$CONFIG->context = array(); + +	// needs to be set before system, init for links in html head +	$viewtype = get_input('view', 'default'); +	$lastcached = datalist_get("simplecache_lastcached_$viewtype"); +	$CONFIG->lastcache = $lastcached; -elgg_register_event_handler('boot', 'system', 'configuration_boot', 10); +	$CONFIG->i18n_loaded_from_cache = false; + +	// this must be synced with the enum for the entities table +	$CONFIG->entity_types = array('group', 'object', 'site', 'user'); +} diff --git a/engine/lib/database.php b/engine/lib/database.php index 444bb7cc4..cc2b99f6a 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -189,22 +189,6 @@ function db_delayedexecution_shutdown_hook() {  }  /** - * Registers shutdown functions for database profiling and delayed queries. - * - * @note Database connections are established upon first call to database. - * - * @return true - * @elgg_event_handler boot system - * @access private - */ -function init_db() { -	register_shutdown_function('db_delayedexecution_shutdown_hook'); -	register_shutdown_function('db_profiling_shutdown_hook'); - -	return true; -} - -/**   * Returns (if required, also creates) a database link resource.   *   * Database link resources are stored in the {@link $dblink} global.  These @@ -757,6 +741,13 @@ function sanitize_int($int, $signed = true) {  }  /** - * @elgg_register_event boot system init_db + * Registers shutdown functions for database profiling and delayed queries. + * + * @access private   */ -elgg_register_event_handler('boot', 'system', 'init_db', 0); +function init_db() { +	register_shutdown_function('db_delayedexecution_shutdown_hook'); +	register_shutdown_function('db_profiling_shutdown_hook'); +} + +elgg_register_event_handler('init', 'system', 'init_db'); diff --git a/engine/lib/deprecated-1.8.php b/engine/lib/deprecated-1.8.php index e1866498b..4b9d41543 100644 --- a/engine/lib/deprecated-1.8.php +++ b/engine/lib/deprecated-1.8.php @@ -1674,7 +1674,7 @@ function get_plugin_list() {   * otherwise you may experience view display artifacts. Do this with the following code:   *   * 		elgg_regenerate_simplecache(); - *		elgg_filepath_cache_reset(); + *		elgg_reset_system_cache();   *   * @deprecated 1.8 Use elgg_generate_plugin_entities() and elgg_set_plugin_priorities()   * @@ -1841,7 +1841,7 @@ function get_installed_plugins($status = 'all') {   * otherwise you may experience view display artifacts. Do this with the following code:   *   * 		elgg_regenerate_simplecache(); - *		elgg_filepath_cache_reset(); + *		elgg_reset_system_cache();   *   * @deprecated 1.8 Use ElggPlugin->activate()   * @@ -1882,7 +1882,7 @@ function enable_plugin($plugin, $site_guid = null) {   * otherwise you may experience view display artifacts. Do this with the following code:   *   * 		elgg_regenerate_simplecache(); - *		elgg_filepath_cache_reset(); + *		elgg_reset_system_cache();   *   * @deprecated 1.8 Use ElggPlugin->deactivate()   * diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index 9035d95f2..b55958a6c 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -995,7 +995,8 @@ function elgg_trigger_plugin_hook($hook, $type, $params = null, $returnvalue = n   * @access private   */  function _elgg_php_exception_handler($exception) { -	error_log("*** FATAL EXCEPTION *** : " . $exception); +	$timestamp = time(); +	error_log("Exception #$timestamp: $exception");  	// Wipe any existing output buffer  	ob_end_clean(); @@ -1011,7 +1012,17 @@ function _elgg_php_exception_handler($exception) {  		$CONFIG->pagesetupdone = true;  		elgg_set_viewtype('failsafe'); -		$body = elgg_view("messages/exceptions/exception", array('object' => $exception)); +		if (elgg_is_admin_logged_in()) { +			$body = elgg_view("messages/exceptions/admin_exception", array( +				'object' => $exception, +				'ts' => $timestamp +			)); +		} else { +			$body = elgg_view("messages/exceptions/exception", array( +				'object' => $exception, +				'ts' => $timestamp +			)); +		}  		echo elgg_view_page(elgg_echo('exception:title'), $body);  	} catch (Exception $e) {  		$timestamp = time(); @@ -1959,7 +1970,7 @@ function elgg_is_valid_options_for_batch_operation($options, $type) {  	// at least one of these is required.  	$required = array(  		// generic restraints -		'guid', 'guids', 'limit' +		'guid', 'guids'  	);  	switch ($type) { @@ -2010,8 +2021,14 @@ function elgg_walled_garden_index() {  	elgg_load_css('elgg.walled_garden');  	elgg_load_js('elgg.walled_garden'); -	$body = elgg_view('core/walled_garden/body'); +	$content = elgg_view('core/walled_garden/login'); +	$params = array( +		'content' => $content, +		'class' => 'elgg-walledgarden-double', +		'id' => 'elgg-walledgarden-login', +	); +	$body = elgg_view_layout('walled_garden', $params);  	echo elgg_view_page('', $body, 'walled_garden');  	// return true to prevent other plugins from adding a front page @@ -2019,6 +2036,24 @@ function elgg_walled_garden_index() {  }  /** + * Serve walled garden sections + * + * @param array $page Array of URL segments + * @return string + * @access private + */ +function _elgg_walled_garden_ajax_handler($page) { +	$view = $page[0]; +	$params = array( +		'content' => elgg_view("core/walled_garden/$view"), +		'class' => 'elgg-walledgarden-single hidden', +		'id' => str_replace('_', '-', "elgg-walledgarden-$view"), +	); +	echo elgg_view_layout('walled_garden', $params); +	return true; +} + +/**   * Checks the status of the Walled Garden and forwards to a login page   * if required.   * @@ -2038,6 +2073,8 @@ function elgg_walled_garden() {  	elgg_register_css('elgg.walled_garden', '/css/walled_garden.css');  	elgg_register_js('elgg.walled_garden', '/js/walled_garden.js'); +	elgg_register_page_handler('walled_garden', '_elgg_walled_garden_ajax_handler'); +  	// check for external page view  	if (isset($CONFIG->site) && $CONFIG->site instanceof ElggSite) {  		$CONFIG->site->checkWalledGarden(); @@ -2045,6 +2082,36 @@ function elgg_walled_garden() {  }  /** + * Boots the engine + * + * 1. sets error handlers + * 2. connects to database + * 3. verifies the installation suceeded + * 4. loads application configuration + * 5. loads i18n data + * 6. loads site configuration + * + * @access private + */ +function _elgg_engine_boot() { +	// Register the error handlers +	set_error_handler('_elgg_php_error_handler'); +	set_exception_handler('_elgg_php_exception_handler'); + +	setup_db_connections(); + +	verify_installation(); + +	_elgg_load_application_config(); + +	register_translations(dirname(dirname(dirname(__FILE__))) . "/languages/"); + +	_elgg_load_site_config(); + +	_elgg_load_cache(); +} + +/**   * Elgg's main init.   *   * Handles core actions for comments, the JS pagehandler, and the shutdown function. @@ -2167,6 +2234,7 @@ define('REFERRER', -1);  define('REFERER', -1);  elgg_register_event_handler('init', 'system', 'elgg_init'); +elgg_register_event_handler('boot', 'system', '_elgg_engine_boot', 1);  elgg_register_plugin_hook_handler('unit_test', 'system', 'elgg_api_test');  elgg_register_event_handler('init', 'system', 'add_custom_menu_items', 1000); diff --git a/engine/lib/entities.php b/engine/lib/entities.php index 82452fba1..4875b2c2f 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -738,6 +738,7 @@ function elgg_entity_exists($guid) {   *           Joined with subtypes by AND. See below)   *   * 	subtypes => NULL|STR entity subtype (SQL: subtype IN ('subtype1', 'subtype2)) + *              Use ELGG_ENTITIES_NO_VALUE for no subtype.   *   * 	type_subtype_pairs => NULL|ARR (array('type' => 'subtype'))   *                        (type = '$type' AND subtype = '$subtype') pairs @@ -960,8 +961,8 @@ function elgg_get_entity_type_subtype_where_sql($table, $types, $subtypes, $pair  		return '';  	} -	// these are the only valid types for entities in elgg as defined in the DB. -	$valid_types = array('object', 'user', 'group', 'site'); +	// these are the only valid types for entities in elgg +	$valid_types = elgg_get_config('entity_types');  	// pairs override  	$wheres = array(); @@ -1378,6 +1379,10 @@ function disable_entity($guid, $reason = "", $recursive = true) {  				}  				if ($recursive) { +					$hidden = access_get_show_hidden_status(); +					access_show_hidden_entities(true); +					$ia = elgg_set_ignore_access(true); +					  					$sub_entities = get_data("SELECT * FROM {$CONFIG->dbprefix}entities  						WHERE (  						container_guid = $guid @@ -1391,6 +1396,8 @@ function disable_entity($guid, $reason = "", $recursive = true) {  							$e->disable($reason);  						}  					} +					access_show_hidden_entities($hidden); +					elgg_set_ignore_access($ia);  				}  				$entity->disableMetadata(); @@ -1514,18 +1521,23 @@ function delete_entity($guid, $recursive = true) {  					$entity_disable_override = access_get_show_hidden_status();  					access_show_hidden_entities(true);  					$ia = elgg_set_ignore_access(true); -					$sub_entities = get_data("SELECT * from {$CONFIG->dbprefix}entities -						WHERE container_guid=$guid -							or owner_guid=$guid -							or site_guid=$guid", 'entity_row_to_elggstar'); -					if ($sub_entities) { -						foreach ($sub_entities as $e) { -							// check for equality so that an entity that is its own -							// owner or container does not cause infinite loop -							if ($e->guid != $guid) { -								$e->delete(true); -							} -						} + +					// @todo there was logic in the original code that ignored +					// entities with owner or container guids of themselves. +					// this should probably be prevented in ElggEntity instead of checked for here +					$options = array( +						'wheres' => array( +							"((container_guid = $guid OR owner_guid = $guid OR site_guid = $guid)" +							. " AND guid != $guid)" +							), +						'limit' => 0 +					); + +					$batch = new ElggBatch('elgg_get_entities', $options); +					$batch->setIncrementOffset(false); + +					foreach ($batch as $e) { +						$e->delete(true);  					}  					access_show_hidden_entities($entity_disable_override); @@ -1959,7 +1971,7 @@ function elgg_register_entity_type($type, $subtype = null) {  	global $CONFIG;  	$type = strtolower($type); -	if (!in_array($type, array('object', 'site', 'group', 'user'))) { +	if (!in_array($type, $CONFIG->entity_types)) {  		return FALSE;  	} @@ -1994,7 +2006,7 @@ function unregister_entity_type($type, $subtype) {  	global $CONFIG;  	$type = strtolower($type); -	if (!in_array($type, array('object', 'site', 'group', 'user'))) { +	if (!in_array($type, $CONFIG->entity_types)) {  		return FALSE;  	} @@ -2162,31 +2174,8 @@ function elgg_list_registered_entities(array $options = array()) {  		$entities = array();  	} -	return elgg_view_entity_list($entities, $count, $options['offset'], -		$options['limit'], $options['full_view'], $options['list_type_toggle'], $options['pagination']); -} - -/** - * Check the recursive delete permissions token. - * - * If an entity is deleted recursively, a permissions override is required to allow - * contained or owned entities to be removed. - * - * @return bool - * @elgg_plugin_hook_handler permissions_check all - * @elgg_plugin_hook_handler permissions_check:metadata all - * @access private - */ -function recursive_delete_permissions_check() { -	static $__RECURSIVE_DELETE_TOKEN; - -	if ((elgg_is_logged_in()) && ($__RECURSIVE_DELETE_TOKEN) -	&& (strcmp($__RECURSIVE_DELETE_TOKEN, md5(elgg_get_logged_in_user_guid())))) { -		return true; -	} - -	// consult next function -	return NULL; +	$options['count'] = $count; +	return elgg_view_entity_list($entities, $options);  }  /** @@ -2303,11 +2292,6 @@ function entities_init() {  	elgg_register_plugin_hook_handler('unit_test', 'system', 'entities_test'); -	// Allow a permission override for recursive entity deletion -	// @todo Can this be done better? -	elgg_register_plugin_hook_handler('permissions_check', 'all', 'recursive_delete_permissions_check'); -	elgg_register_plugin_hook_handler('permissions_check:metadata', 'all', 'recursive_delete_permissions_check'); -  	elgg_register_plugin_hook_handler('gc', 'system', 'entities_gc');  } diff --git a/engine/lib/group.php b/engine/lib/group.php index 29330eeca..feb1f1e7f 100644 --- a/engine/lib/group.php +++ b/engine/lib/group.php @@ -261,16 +261,24 @@ function group_gatekeeper($forward = true) {  	if ($group = elgg_get_page_owner_entity()) {  		if ($group instanceof ElggGroup) {  			$url = $group->getURL(); -			if ( -				((!elgg_is_logged_in()) && (!$group->isPublicMembership())) || -				((!$group->isMember(elgg_get_logged_in_user_entity()) && (!$group->isPublicMembership()))) -			) { -				$allowed = false; -			} +			if (!$group->isPublicMembership()) { +				// closed group so must be member or an admin + +				if (!elgg_is_logged_in()) { +					$allowed = false; +					if ($forward == true) { +						$_SESSION['last_forward_from'] = current_page_url(); +						register_error(elgg_echo('loggedinrequired')); +						forward('', 'login'); +					} +				} else if (!$group->isMember(elgg_get_logged_in_user_entity())) { +					$allowed = false; +				} -			// Admin override -			if (elgg_is_admin_logged_in()) { -				$allowed = true; +				// Admin override +				if (elgg_is_admin_logged_in()) { +					$allowed = true; +				}  			}  		}  	} diff --git a/engine/lib/languages.php b/engine/lib/languages.php index 0400843af..bf6829a39 100644 --- a/engine/lib/languages.php +++ b/engine/lib/languages.php @@ -145,9 +145,16 @@ function elgg_echo($message_key, $args = array(), $language = "") {  function register_translations($path, $load_all = false) {  	global $CONFIG; +	static $load_from_cache; +	static $cache_loaded_langs; +	if (!isset($load_from_cache)) { +		$load_from_cache = $CONFIG->system_cache_enabled; +		$cache_loaded_langs = array(); +	} +  	$path = sanitise_filepath($path); -	// Make a note of this path just incase we need to register this language later +	// Make a note of this path just in case we need to register this language later  	if (!isset($CONFIG->language_paths)) {  		$CONFIG->language_paths = array();  	} @@ -155,7 +162,6 @@ function register_translations($path, $load_all = false) {  	// Get the current language based on site defaults and user preference  	$current_language = get_current_language(); -	elgg_log("Translations loaded from: $path");  	// only load these files unless $load_all is true.  	$load_language_files = array( @@ -165,6 +171,32 @@ function register_translations($path, $load_all = false) {  	$load_language_files = array_unique($load_language_files); +	if ($load_from_cache && !$load_all) { +		// load language files from cache +		$data = array(); +		foreach ($load_language_files as $lang_file) { +			$lang = substr($lang_file, 0, strpos($lang_file, '.')); +			if (!isset($cache_loaded_langs[$lang])) { +				$data[$lang] = elgg_load_system_cache($lang_file); +				if ($data[$lang]) { +					$cache_loaded_langs[$lang] = true; +				} else { +					// this language file not cached yet +					$load_from_cache = false; +				} +			} +		} + +		// are we still suppose to load from cache +		if ($load_from_cache) { +			foreach ($data as $lang => $map) { +				add_translation($lang, unserialize($map)); +			} +			$CONFIG->i18n_loaded_from_cache = true; +			return true; +		} +	} +  	$handle = opendir($path);  	if (!$handle) {  		elgg_log("Could not open language path: $path", 'ERROR'); @@ -186,6 +218,11 @@ function register_translations($path, $load_all = false) {  		}  	} +	elgg_log("Translations loaded from: $path"); + +	// make sure caching code saves language data if system cache is on +	$CONFIG->i18n_loaded_from_cache = false; +  	return $return;  } @@ -311,5 +348,3 @@ function elgg_languages_init() {  }  elgg_register_event_handler('init', 'system', 'elgg_languages_init'); - -register_translations(dirname(dirname(dirname(__FILE__))) . "/languages/"); diff --git a/engine/lib/metadata.php b/engine/lib/metadata.php index 19e8aa3c8..34a36d86e 100644 --- a/engine/lib/metadata.php +++ b/engine/lib/metadata.php @@ -294,11 +294,11 @@ function elgg_get_metadata(array $options = array()) {   * Deletes metadata based on $options.   *   * @warning Unlike elgg_get_metadata() this will not accept an empty options array! - *          This requires some constraints: metadata_owner_guid(s), - *          metadata_name(s), metadata_value(s), or limit must be set. + *          This requires at least one constraint: metadata_owner_guid(s), + *          metadata_name(s), metadata_value(s), or guid(s) must be set.   * - * @param array $options An options array. {@See elgg_get_metadata()} - * @return mixed + * @param array $options An options array. {@see elgg_get_metadata()} + * @return mixed Null if the metadata name is invalid. Bool on success or fail.   * @since 1.8.0   */  function elgg_delete_metadata(array $options) { @@ -307,7 +307,8 @@ function elgg_delete_metadata(array $options) {  	}  	$options['metastring_type'] = 'metadata'; -	return elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback'); +	$result = elgg_batch_metastring_based_objects($options, 'elgg_batch_delete_callback'); +	return $result;  }  /** @@ -745,7 +746,7 @@ function export_metadata_plugin_hook($hook, $entity_type, $returnvalue, $params)  /**   * Takes in a comma-separated string and returns an array of tags - * which have been trimmed and set to lower case + * which have been trimmed   *   * @param string $string Comma-separated tag string   * @@ -754,12 +755,7 @@ function export_metadata_plugin_hook($hook, $entity_type, $returnvalue, $params)  function string_to_tag_array($string) {  	if (is_string($string)) {  		$ar = explode(",", $string); -		// trim blank spaces  		$ar = array_map('trim', $ar); -		// make lower case : [Marcus Povey 20090605 - Using mb wrapper function -		// using UTF8 safe function where available] -		$ar = array_map('elgg_strtolower', $ar); -		// Remove null values  		$ar = array_filter($ar, 'is_not_null');  		return $ar;  	} diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php index 62b60e279..d7cc4e0bc 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -727,38 +727,11 @@ function elgg_batch_metastring_based_objects(array $options, $callback) {  		return false;  	} -	switch($options['metastring_type']) { -		case 'metadata': -			$objects = elgg_get_metadata($options); -			break; - -		case 'annotations': -			$objects = elgg_get_annotations($options); -			break; - -		default: -			return false; -	} - -	if (!is_array($objects)) { -		$r = false; -	} elseif (empty($objects)) { -		// ElggBatch returns null if the results are an empty array -		$r = null; -	} else { -		$r = true; -		foreach($objects as $object) { -			$r = $r && $callback($object); -		} -	} +	// @todo restore once ElggBatch supports callbacks that delete rows. +	$batch = new ElggBatch('elgg_get_metastring_based_objects', $options, $callback, 50, false); +	$r = $batch->callbackResult;  	return $r; - -//	// @todo restore once ElggBatch supports callbacks that delete rows. -//	$batch = new ElggBatch('elgg_get_metastring_based_objects', $options, $callback); -//	$r = $batch->callbackResult; -// -//	return $r;  }  /** diff --git a/engine/lib/navigation.php b/engine/lib/navigation.php index dcbd7b397..a7984ce5a 100644 --- a/engine/lib/navigation.php +++ b/engine/lib/navigation.php @@ -78,7 +78,11 @@   *                          link_class  => STR  A class or classes for the <a> tag   *                          item_class  => STR  A class or classes for the <li> tag   * - *                          Custom options can be added as key value pairs. + *                          Additional options that the view output/url takes can be + *							passed in the array. If the 'confirm' key is passed, the + *							menu link uses the 'output/confirmlink' view. Custom + *							options can be added by using the 'data' key with the + *							value being an associative array.   *   * @return bool   * @since 1.8.0 diff --git a/engine/lib/output.php b/engine/lib/output.php index b96cf354c..b1245a924 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -310,15 +310,19 @@ function elgg_get_friendly_title($title) {  		return $result;  	} +	// @todo not using this because of locale concerns  	//$title = iconv('UTF-8', 'ASCII//TRANSLIT', $title); +	// @todo this uses a utf8 character class. can use if +	// we want to support utf8 in the url. +	//$title = preg_replace('/[^\p{L}\- ]/u', '', $title); +  	// use A-Za-z0-9_ instead of \w because \w is locale sensitive -	$title = preg_replace("/[^A-Za-z0-9_ ]/", "", $title); -	$title = preg_replace("/[^\w ]/", "", $title); +	$title = preg_replace("/[^A-Za-z0-9_\- ]/", "", $title);  	$title = str_replace(" ", "-", $title);  	$title = str_replace("--", "-", $title);  	$title = trim($title); -	$title = strtolower($title); +	$title = elgg_strtolower($title);  	return $title;  } diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index 7968f4a6e..123fb18d8 100644 --- a/engine/lib/plugins.php +++ b/engine/lib/plugins.php @@ -62,7 +62,7 @@ function elgg_get_plugin_ids_in_dir($dir = null) {  		$dir = elgg_get_plugins_path();  	} -	$plugin_idss = array(); +	$plugin_ids = array();  	$handle = opendir($dir);  	if ($handle) { @@ -298,19 +298,13 @@ function elgg_load_plugins() {  	// temporary disable all plugins if there is a file called 'disabled' in the plugin dir  	if (file_exists("$plugins_path/disabled")) { +		if (elgg_is_admin_logged_in() && elgg_in_context('admin')) { +			system_message(elgg_echo('plugins:disabled')); +		}  		return false;  	} -	// Load view caches if available -	$cached_view_paths = elgg_filepath_cache_load('views'); -	$cached_view_types = elgg_filepath_cache_load('view_types'); -	$cached_view_info = is_string($cached_view_paths) && is_string($cached_view_types); - -	if ($cached_view_info) { -		$CONFIG->views = unserialize($cached_view_paths); -		$CONFIG->view_types = unserialize($cached_view_types); - -		// don't need to register views +	if (elgg_get_config('system_cache_loaded')) {  		$start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_VIEWS;  	} @@ -332,12 +326,6 @@ function elgg_load_plugins() {  		}  	} -	// Cache results -	if (!$cached_view_info) { -		elgg_filepath_cache_save('views', serialize($CONFIG->views)); -		elgg_filepath_cache_save('view_types', serialize($CONFIG->view_types)); -	} -  	return $return;  } diff --git a/engine/lib/relationships.php b/engine/lib/relationships.php index fabe2d2d6..f50c4a485 100644 --- a/engine/lib/relationships.php +++ b/engine/lib/relationships.php @@ -290,7 +290,7 @@ function elgg_get_entities_from_relationship($options) {  			$options['selects'] = array();  		} -		$select = array('r.*'); +		$select = array('r.id');  		$options['selects'] = array_merge($options['selects'], $select);  	} diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php index 97a05e2e8..419d36707 100644 --- a/engine/lib/sessions.php +++ b/engine/lib/sessions.php @@ -127,6 +127,10 @@ function elgg_is_admin_user($user_guid) {  /**   * Perform user authentication with a given username and password.   * + * @warning This returns an error message on failure. Use the identical operator to check + * for access: if (true === elgg_authenticate()) { ... }. + * + *   * @see login   *   * @param string $username The username @@ -355,7 +359,7 @@ function logout() {  	session_destroy();  	// starting a default session to store any post-logout messages. -	session_init(NULL, NULL, NULL); +	_elgg_session_boot(NULL, NULL, NULL);  	$_SESSION['msg'] = $old_msg;  	return TRUE; @@ -379,7 +383,7 @@ function logout() {   * @return bool   * @access private   */ -function session_init($event, $object_type, $object) { +function _elgg_session_boot($event, $object_type, $object) {  	global $DB_PREFIX, $CONFIG;  	// Use database for sessions @@ -444,8 +448,8 @@ function session_init($event, $object_type, $object) {  		set_last_action($_SESSION['guid']);  	} -	elgg_register_action("login", '', 'public'); -	elgg_register_action("logout"); +	elgg_register_action('login', '', 'public'); +	elgg_register_action('logout');  	// Register a default PAM handler  	register_pam_handler('pam_auth_userpass'); @@ -655,4 +659,4 @@ function _elgg_session_gc($maxlifetime) {  	return true;  } -elgg_register_event_handler("boot", "system", "session_init", 20); +elgg_register_event_handler('boot', 'system', '_elgg_session_boot', 2); diff --git a/engine/lib/sites.php b/engine/lib/sites.php index 337b2d180..850092cad 100644 --- a/engine/lib/sites.php +++ b/engine/lib/sites.php @@ -231,43 +231,6 @@ function get_site_domain($guid) {  }  /** - * Initialise site handling - * - * Called at the beginning of system running, to set the ID of the current site. - * This is 0 by default, but plugins may alter this behaviour by attaching functions - * to the sites init event and changing $CONFIG->site_id. - * - * @uses $CONFIG - * - * @param string $event       Event API required parameter - * @param string $object_type Event API required parameter - * @param null   $object      Event API required parameter - * - * @return true - * @access private - */ -function sites_boot($event, $object_type, $object) { -	global $CONFIG; - -	$site = elgg_trigger_plugin_hook("siteid", "system"); -	if ($site === null || $site === false) { -		$CONFIG->site_id = (int) datalist_get('default_site'); -	} else { -		$CONFIG->site_id = $site; -	} -	$CONFIG->site_guid = $CONFIG->site_id; -	$CONFIG->site = get_entity($CONFIG->site_guid); - -	return true; -} - -// Register event handlers -elgg_register_event_handler('boot', 'system', 'sites_boot', 2); - -// Register with unit test -elgg_register_plugin_hook_handler('unit_test', 'system', 'sites_test'); - -/**   * Unit tests for sites   *   * @param sting  $hook   unit_test @@ -283,3 +246,6 @@ function sites_test($hook, $type, $value, $params) {  	$value[] = "{$CONFIG->path}engine/tests/objects/sites.php";  	return $value;  } + +// Register with unit test +elgg_register_plugin_hook_handler('unit_test', 'system', 'sites_test'); diff --git a/engine/lib/statistics.php b/engine/lib/statistics.php index 7c170f3bb..e1f95ed97 100644 --- a/engine/lib/statistics.php +++ b/engine/lib/statistics.php @@ -95,14 +95,12 @@ function get_number_users($show_deactivated = false) {   * @return string    */  function get_online_users() { -	$offset = get_input('offset', 0);  	$count = find_active_users(600, 10, $offset, true);  	$objects = find_active_users(600, 10, $offset);  	if ($objects) {  		return elgg_view_entity_list($objects, array(  			'count' => $count, -			'offset' => $offset,  			'limit' => 10  		));  	} diff --git a/engine/lib/system_log.php b/engine/lib/system_log.php index fd5644135..28d90be56 100644 --- a/engine/lib/system_log.php +++ b/engine/lib/system_log.php @@ -11,6 +11,7 @@   * Retrieve the system log based on a number of parameters.   *   * @param int|array $by_user    The guid(s) of the user(s) who initiated the event. + *                              Use 0 for unowned entries. Anything else falsey means anyone.   * @param string    $event      The event you are searching on.   * @param string    $class      The class of object it effects.   * @param string    $type       The type @@ -21,11 +22,12 @@   * @param int       $timebefore Lower time limit   * @param int       $timeafter  Upper time limit   * @param int       $object_id  GUID of an object - * + * @param str       $ip_address The IP address.   * @return mixed   */  function get_system_log($by_user = "", $event = "", $class = "", $type = "", $subtype = "", -$limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $object_id = 0) { +$limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $object_id = 0, +$ip_address = false) {  	global $CONFIG; @@ -37,16 +39,18 @@ $limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $obje  	} else {  		$by_user = (int)$by_user;  	} +	  	$event = sanitise_string($event);  	$class = sanitise_string($class);  	$type = sanitise_string($type);  	$subtype = sanitise_string($subtype); +	$ip_address = sanitise_string($ip_address);  	$limit = (int)$limit;  	$offset = (int)$offset;  	$where = array(); -	if ($by_user_orig !== "") { +	if ($by_user_orig !== "" && $by_user_orig !== false && $by_user_orig !== null) {  		if (is_int($by_user)) {  			$where[] = "performed_by_guid=$by_user";  		} else if (is_array($by_user)) { @@ -75,6 +79,9 @@ $limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $obje  	if ($object_id) {  		$where[] = "object_id = " . ((int) $object_id);  	} +	if ($ip_address) { +		$where[] = "ip_address = '$ip_address'"; +	}  	$select = "*";  	if ($count) { @@ -91,7 +98,8 @@ $limit = 10, $offset = 0, $count = false, $timebefore = 0, $timeafter = 0, $obje  	}  	if ($count) { -		if ($numrows = get_data_row($query)) { +		$numrows = get_data_row($query); +		if ($numrows) {  			return $numrows->count;  		}  	} else { @@ -171,6 +179,7 @@ function system_log($object, $event) {  		$object_subtype = $object->getSubtype();  		$event = sanitise_string($event);  		$time = time(); +		$ip_address = sanitise_string($_SERVER['REMOTE_ADDR']);  		$performed_by = elgg_get_logged_in_user_guid();  		if (isset($object->access_id)) { @@ -194,10 +203,10 @@ function system_log($object, $event) {  		if (!isset($log_cache[$time][$object_id][$event])) {  			$query = "INSERT DELAYED into {$CONFIG->dbprefix}system_log  				(object_id, object_class, object_type, object_subtype, event, -				performed_by_guid, owner_guid, access_id, enabled, time_created) +				performed_by_guid, owner_guid, access_id, enabled, time_created, ip_address)  			VALUES  				('$object_id','$object_class','$object_type', '$object_subtype', '$event', -				$performed_by, $owner_guid, $access_id, '$enabled', '$time')"; +				$performed_by, $owner_guid, $access_id, '$enabled', '$time', '$ip_address')";  			insert_data($query); diff --git a/engine/lib/upgrades/2011010101.php b/engine/lib/upgrades/2011010101.php index b063c249b..a1ee92622 100644 --- a/engine/lib/upgrades/2011010101.php +++ b/engine/lib/upgrades/2011010101.php @@ -66,7 +66,7 @@ if ($old_enabled_plugins) {  // invalidate caches  elgg_invalidate_simplecache(); -elgg_filepath_cache_reset(); +elgg_reset_system_cache();  // clean up.  remove_metadata($site->guid, 'pluginorder'); diff --git a/engine/lib/upgrades/2012012000-1.8.3-ip_in_syslog-87fe0f068cf62428.php b/engine/lib/upgrades/2012012000-1.8.3-ip_in_syslog-87fe0f068cf62428.php new file mode 100644 index 000000000..b9514e156 --- /dev/null +++ b/engine/lib/upgrades/2012012000-1.8.3-ip_in_syslog-87fe0f068cf62428.php @@ -0,0 +1,12 @@ +<?php +/** + * Elgg 1.8.3 upgrade 2012012000 + * ip_in_syslog + * + * Adds a field for an IP address in the system log table + */ + +$db_prefix = elgg_get_config('dbprefix'); +$q = "ALTER TABLE {$db_prefix}system_log ADD ip_address VARCHAR(15) NOT NULL AFTER time_created"; + +update_data($q);
\ No newline at end of file diff --git a/engine/lib/upgrades/2012012100-1.8.3-system_cache-93100e7d55a24a11.php b/engine/lib/upgrades/2012012100-1.8.3-system_cache-93100e7d55a24a11.php new file mode 100644 index 000000000..3a9aae2a1 --- /dev/null +++ b/engine/lib/upgrades/2012012100-1.8.3-system_cache-93100e7d55a24a11.php @@ -0,0 +1,13 @@ +<?php +/** + * Elgg 1.8.3 upgrade 2012012100 + * system_cache + * + * Convert viewpath cache to system cache + */ + +$value = datalist_get('viewpath_cache_enabled'); +datalist_set('system_cache_enabled', $value); + +$query = "DELETE FROM {$CONFIG->dbprefix}datalists WHERE name='viewpath_cache_enabled'"; +delete_data($query); diff --git a/engine/lib/upgrades/2012041800-1.8.3-dont_filter_passwords-c0ca4a18b38ae2bc.php b/engine/lib/upgrades/2012041800-1.8.3-dont_filter_passwords-c0ca4a18b38ae2bc.php new file mode 100644 index 000000000..b82ffbebf --- /dev/null +++ b/engine/lib/upgrades/2012041800-1.8.3-dont_filter_passwords-c0ca4a18b38ae2bc.php @@ -0,0 +1,11 @@ +<?php +/** + * Elgg 1.8.3 upgrade 2012041800 + * dont_filter_passwords + * + * Add admin notice that password handling has changed and if  + * users can't login to have them reset their passwords. + */ +elgg_add_admin_notice('dont_filter_passwords', 'Password handling has been updated to be more secure and flexible. ' +	. 'This change may prevent a small number of users from logging in with their existing passwords. ' +	. 'If a user is unable to log in, please advise him or her to reset their password, or reset it as an admin user.'); diff --git a/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php b/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php new file mode 100644 index 000000000..07732f261 --- /dev/null +++ b/engine/lib/upgrades/2012041801-1.8.3-multiple_user_tokens-852225f7fd89f6c5.php @@ -0,0 +1,13 @@ +<?php +/** + * Elgg 1.8.3 upgrade 2012041801 + * multiple_user_tokens + * + * Fixes http://trac.elgg.org/ticket/4291 + * Removes the unique index on users_apisessions for user_guid and site_guid + */ + +$db_prefix = elgg_get_config('dbprefix'); +$q = "ALTER TABLE {$db_prefix}users_apisessions DROP INDEX user_guid, +	ADD INDEX user_guid (user_guid, site_guid)"; +update_data($q);
\ No newline at end of file diff --git a/engine/lib/user_settings.php b/engine/lib/user_settings.php index af30d8f0d..e4069fb53 100644 --- a/engine/lib/user_settings.php +++ b/engine/lib/user_settings.php @@ -33,9 +33,9 @@ function users_settings_save() {   * @access private   */  function elgg_set_user_password() { -	$current_password = get_input('current_password'); -	$password = get_input('password'); -	$password2 = get_input('password2'); +	$current_password = get_input('current_password', null, false); +	$password = get_input('password', null, false); +	$password2 = get_input('password2', null, false);  	$user_guid = get_input('guid');  	if (!$user_guid) { diff --git a/engine/lib/users.php b/engine/lib/users.php index c38bb676e..6a881777e 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -497,20 +497,26 @@ $timelower = 0, $timeupper = 0) {   * @param int    $timelower      The earliest time the entity can have been created. Default: all   * @param int    $timeupper      The latest time the entity can have been created. Default: all   * - * @return string The list in a form suitable to display + * @return string   */  function list_user_friends_objects($user_guid, $subtype = "", $limit = 10, $full_view = true,  $listtypetoggle = true, $pagination = true, $timelower = 0, $timeupper = 0) { -	$offset = (int) get_input('offset'); -	$limit = (int) $limit; -	$count = (int) count_user_friends_objects($user_guid, $subtype, $timelower, $timeupper); +	$offset = (int)get_input('offset'); +	$limit = (int)$limit; +	$count = (int)count_user_friends_objects($user_guid, $subtype, $timelower, $timeupper);  	$entities = get_user_friends_objects($user_guid, $subtype, $limit, $offset,  		$timelower, $timeupper); -	return elgg_view_entity_list($entities, $count, $offset, $limit, $full_view, -		$listtypetoggle, $pagination); +	return elgg_view_entity_list($entities, array( +		'count' => $count, +		'offset' => $offset, +		'limit' => $limit, +		'full_view' => $full_view, +		'list_type_toggle' => $listtypetoggle, +		'pagination' => $pagination, +	));  }  /** @@ -606,11 +612,11 @@ function get_user_by_code($code) {  }  /** - * Get an array of users from their email addresses + * Get an array of users from an email address   *   * @param string $email Email address.   * - * @return Array of users + * @return array   */  function get_user_by_email($email) {  	global $CONFIG; @@ -963,8 +969,8 @@ $allow_multiple_emails = false, $friend_guid = 0, $invitecode = '') {  				$friend_user->addFriend($user->guid);  				// @todo Should this be in addFriend? -				add_to_river('friends/river/create', 'friend', $user->getGUID(), $friend_guid); -				add_to_river('friends/river/create', 'friend', $friend_guid, $user->getGUID()); +				add_to_river('river/relationship/friend/create', 'friend', $user->getGUID(), $friend_guid); +				add_to_river('river/relationship/friend/create', 'friend', $friend_guid, $user->getGUID());  			}  		}  	} diff --git a/engine/lib/views.php b/engine/lib/views.php index e59edac96..ca0ce7196 100644 --- a/engine/lib/views.php +++ b/engine/lib/views.php @@ -560,7 +560,7 @@ function elgg_view($view, $vars = array(), $bypass = false, $debug = false, $vie   *   * @return void   * @since 1.7.0 - * @link http://docs.elgg.org/Views/Ejxtend + * @link http://docs.elgg.org/Views/Extend   * @example views/extend.php   */  function elgg_extend_view($view, $view_extension, $priority = 501, $viewtype = '') { @@ -969,12 +969,7 @@ function elgg_view_annotation(ElggAnnotation $annotation, array $vars = array(),  		return elgg_view($view, $vars, $bypass, $debug);  	} -	// @todo would be better to always make sure name is initialized properly  	$name = $annotation->name; -	$intname = (int) $name; -	if ("{$intname}" == "{$name}") { -		$name = get_metastring($intname); -	}  	if (empty($name)) {  		return false;  	} @@ -1330,21 +1325,18 @@ function elgg_view_form($action, $form_vars = array(), $body_vars = array()) {   * @access private   */  function elgg_view_list_item($item, array $vars = array()) { +	global $CONFIG; -	switch ($item->getType()) { -		case 'user': -		case 'object': -		case 'group': -		case 'site': -			return elgg_view_entity($item, $vars); -		case 'annotation': -			return elgg_view_annotation($item, $vars); -		case 'river': -			return elgg_view_river_item($item, $vars); -		default: -			return false; -			break; +	$type = $item->getType(); +	if (in_array($type, $CONFIG->entity_types)) { +		return elgg_view_entity($item, $vars); +	} else if ($type == 'annotation') { +		return elgg_view_annotation($item, $vars); +	} else if ($type == 'river') { +		return elgg_view_river_item($item, $vars);  	} + +	return false;  }  /** @@ -1671,5 +1663,5 @@ function elgg_views_boot() {  	}  } -elgg_register_event_handler('boot', 'system', 'elgg_views_boot', 1000); +elgg_register_event_handler('boot', 'system', 'elgg_views_boot');  elgg_register_event_handler('init', 'system', 'elgg_views_handle_deprecated_views'); diff --git a/engine/lib/web_services.php b/engine/lib/web_services.php index 07be76ec6..da3ed76a9 100644 --- a/engine/lib/web_services.php +++ b/engine/lib/web_services.php @@ -1165,7 +1165,7 @@ function list_all_apis() {   * @access private   */  function auth_gettoken($username, $password) { -	if (elgg_authenticate($username, $password)) { +	if (true === elgg_authenticate($username, $password)) {  		$token = create_user_token($username);  		if ($token) {  			return $token; diff --git a/engine/lib/xml-rpc.php b/engine/lib/xml-rpc.php new file mode 100644 index 000000000..bfe1a8645 --- /dev/null +++ b/engine/lib/xml-rpc.php @@ -0,0 +1,203 @@ +<?php +/** + * Elgg XML-RPC library. + * Contains functions and classes to handle XML-RPC services, currently only server only. + * + * @package Elgg.Core + * @subpackage XMLRPC + */ + +/** + * parse XMLRPCCall parameters + * + * Convert an XMLRPCCall result array into native data types + * + * @param array $parameters An array of params + * + * @return array + * @access private + */ +function xmlrpc_parse_params($parameters) { +	$result = array(); + +	foreach ($parameters as $parameter) { +		$result[] = xmlrpc_scalar_value($parameter); +	} + +	return $result; +} + +/** + * Extract the scalar value of an XMLObject type result array + * + * @param XMLObject $object And object + * + * @return mixed + * @access private + */ +function xmlrpc_scalar_value($object) { +	if ($object->name == 'param') { +		$object = $object->children[0]->children[0]; +	} + +	switch ($object->name) { +		case 'string': +			return $object->content; + +		case 'array': +			foreach ($object->children[0]->children as $child) { +				$value[] = xmlrpc_scalar_value($child); +			} +			return $value; + +		case 'struct': +			foreach ($object->children as $child) { +				if (isset($child->children[1]->children[0])) { +					$value[$child->children[0]->content] = xmlrpc_scalar_value($child->children[1]->children[0]); +				} else { +					$value[$child->children[0]->content] = $child->children[1]->content; +				} +			} +			return $value; + +		case 'boolean': +			return (boolean) $object->content; + +		case 'i4': +		case 'int': +			return (int) $object->content; + +		case 'double': +			return (double) $object->content; + +		case 'dateTime.iso8601': +			return (int) strtotime($object->content); + +		case 'base64': +			return base64_decode($object->content); + +		case 'value': +			return xmlrpc_scalar_value($object->children[0]); + +		default: +			// @todo unsupported, throw an error +			return false; +	} +} + +// Functions for adding handlers ////////////////////////////////////////////////////////// + +/** XML-RPC Handlers */ +global $XML_RPC_HANDLERS; +$XML_RPC_HANDLERS = array(); + +/** + * Register a method handler for a given XML-RPC method. + * + * @param string $method  Method parameter. + * @param string $handler The handler function. This function accepts + *                        one XMLRPCCall object and must return a XMLRPCResponse object. + * + * @return bool + */ +function register_xmlrpc_handler($method, $handler) { +	global $XML_RPC_HANDLERS; + +	$XML_RPC_HANDLERS[$method] = $handler; +} + +/** + * Trigger a method call and pass the relevant parameters to the funciton. + * + * @param XMLRPCCall $parameters The call and parameters. + * + * @return XMLRPCCall + * @access private + */ +function trigger_xmlrpc_handler(XMLRPCCall $parameters) { +	global $XML_RPC_HANDLERS; + +	// Go through and see if we have a handler +	if (isset($XML_RPC_HANDLERS[$parameters->getMethodName()])) { +		$handler = $XML_RPC_HANDLERS[$parameters->getMethodName()]; +		$result  = $handler($parameters); + +		if (!($result instanceof XMLRPCResponse)) { +			$msg = elgg_echo('InvalidParameterException:UnexpectedReturnFormat', +				array($parameters->getMethodName())); +			throw new InvalidParameterException($msg); +		} + +		// Result in right format, return it. +		return $result; +	} + +	// if no handler then throw exception +	$msg = elgg_echo('NotImplementedException:XMLRPCMethodNotImplemented', +		array($parameters->getMethodName())); +	throw new NotImplementedException($msg); +} + +/** + * PHP Error handler function. + * This function acts as a wrapper to catch and report PHP error messages. + * + * @see http://uk3.php.net/set-error-handler + * + * @param int    $errno    Error number + * @param string $errmsg   Human readable message + * @param string $filename Filename + * @param int    $linenum  Line number + * @param array  $vars     Vars + * + * @return void + * @access private + */ +function _php_xmlrpc_error_handler($errno, $errmsg, $filename, $linenum, $vars) { +	$error = date("Y-m-d H:i:s (T)") . ": \"" . $errmsg . "\" in file " +		. $filename . " (line " . $linenum . ")"; + +	switch ($errno) { +		case E_USER_ERROR: +				error_log("ERROR: " . $error); + +				// Since this is a fatal error, we want to stop any further execution but do so gracefully. +				throw new Exception("ERROR: " . $error); +			break; + +		case E_WARNING : +		case E_USER_WARNING : +				error_log("WARNING: " . $error); +			break; + +		default: +			error_log("DEBUG: " . $error); +	} +} + +/** + * PHP Exception handler for XMLRPC. + * + * @param Exception $exception The exception + * + * @return void + * @access private + */ +function _php_xmlrpc_exception_handler($exception) { + +	error_log("*** FATAL EXCEPTION (XML-RPC) *** : " . $exception); + +	$code = $exception->getCode(); + +	if ($code == 0) { +		$code = -32400; +	} + +	$result = new XMLRPCErrorResponse($exception->getMessage(), $code); + +	$vars = array('result' => $result); + +	$content = elgg_view("xml-rpc/output", $vars); + +	echo elgg_view_page($exception->getMessage(), $content); +} | 
