diff options
Diffstat (limited to 'engine')
-rw-r--r-- | engine/classes/ElggEntity.php | 7 | ||||
-rw-r--r-- | engine/classes/ElggMenuItem.php | 22 | ||||
-rw-r--r-- | engine/classes/ElggPlugin.php | 81 | ||||
-rw-r--r-- | engine/classes/ElggPluginPackage.php | 28 | ||||
-rw-r--r-- | engine/classes/ElggSite.php | 11 | ||||
-rw-r--r-- | engine/lib/actions.php | 22 | ||||
-rw-r--r-- | engine/lib/admin.php | 70 | ||||
-rw-r--r-- | engine/lib/database.php | 38 | ||||
-rw-r--r-- | engine/lib/deprecated-1.8.php | 436 | ||||
-rw-r--r-- | engine/lib/elgglib.php | 14 | ||||
-rw-r--r-- | engine/lib/extender.php | 8 | ||||
-rw-r--r-- | engine/lib/group.php | 5 | ||||
-rw-r--r-- | engine/lib/output.php | 2 | ||||
-rw-r--r-- | engine/lib/pagehandler.php | 14 | ||||
-rw-r--r-- | engine/lib/plugins.php | 41 | ||||
-rw-r--r-- | engine/lib/river.php | 206 | ||||
-rw-r--r-- | engine/lib/sessions.php | 9 | ||||
-rw-r--r-- | engine/lib/upgrades/2011052801.php | 45 | ||||
-rw-r--r-- | engine/lib/upgrades/2011061200-1.8b1-sites_need_a_site_guid-6d9dcbf46c0826cc.php | 30 | ||||
-rw-r--r-- | engine/lib/users.php | 117 |
20 files changed, 867 insertions, 339 deletions
diff --git a/engine/classes/ElggEntity.php b/engine/classes/ElggEntity.php index 79b8c2a4e..8fc1e46cb 100644 --- a/engine/classes/ElggEntity.php +++ b/engine/classes/ElggEntity.php @@ -850,12 +850,11 @@ abstract class ElggEntity extends ElggData implements * @since 1.8.0 */ function countComments() { - $type = $this->getType(); $params = array('entity' => $this); - $number = elgg_trigger_plugin_hook('comments:count', $type, $params, false); + $num = trigger_plugin_hook('comments:count', $this->getType(), $params); - if ($number) { - return $number; + if (is_int($num)) { + return $num; } else { return $this->getAnnotationCalculation('generic_comment', 'count'); } diff --git a/engine/classes/ElggMenuItem.php b/engine/classes/ElggMenuItem.php index 61dbf539e..157ed9ceb 100644 --- a/engine/classes/ElggMenuItem.php +++ b/engine/classes/ElggMenuItem.php @@ -325,7 +325,16 @@ class ElggMenuItem { * @return string */ public function getItemClass() { - return implode(' ', $this->itemClass); + //allow people to specify name with underscores and colons + $name = str_replace('_', '-', $this->getName()); + $name = str_replace(':', '-', $name); + + $class = implode(' ', $this->itemClass); + if ($class) { + return "elgg-menu-item-$name $class"; + } else { + return "elgg-menu-item-$name"; + } } /** @@ -420,6 +429,17 @@ class ElggMenuItem { } /** + * Set the menu item's children + * + * @param array $children Array of ElggMenuItems + * + * @return void + */ + public function setChildren($children) { + $this->children = $children; + } + + /** * Get the children menu items * * @return array diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php index 20a8673de..95a7362e2 100644 --- a/engine/classes/ElggPlugin.php +++ b/engine/classes/ElggPlugin.php @@ -9,8 +9,8 @@ * @subpackage Plugins.Settings */ class ElggPlugin extends ElggObject { - public $package; - public $manifest; + private $package; + private $manifest; private $path; private $pluginID; @@ -76,18 +76,6 @@ class ElggPlugin extends ElggObject { // load the rest of the plugin parent::__construct($existing_guid); } - - // We have to let the entity load so we can manipulate it with the API. - // If the path is wrong or would cause an exception, catch it, - // disable the plugin, and emit an error. - try { - $this->package = new ElggPluginPackage($this->path, false); - $this->manifest = $this->package->getManifest(); - } catch (Exception $e) { - // we always have to allow the entity to load. - elgg_log("Failed to load $this->guid as a plugin. " . $e->getMessage(), 'WARNING'); - $this->errorMsg = $e->getmessage(); - } } /** @@ -152,7 +140,7 @@ class ElggPlugin extends ElggObject { * @return array */ public function getAvailableTextFiles() { - $filenames = $this->package->getTextFilenames(); + $filenames = $this->getPackage()->getTextFilenames(); $files = array(); foreach ($filenames as $filename) { @@ -562,13 +550,13 @@ class ElggPlugin extends ElggObject { return false; } - if (!$this->package instanceof ElggPluginPackage) { + if (!$this->getPackage() instanceof ElggPluginPackage) { $this->errorMsg = elgg_echo('ElggPlugin:NoPluginPackagePackage', array($this->getID(), $this->guid)); return false; } - if (!$this->package->isValid()) { - $this->errorMsg = $this->package->getError(); + if (!$this->getPackage()->isValid()) { + $this->errorMsg = $this->getPackage()->getError(); return false; } @@ -607,8 +595,8 @@ class ElggPlugin extends ElggObject { * @return bool */ public function canActivate($site_guid = null) { - if ($this->package) { - return $this->package->isValid() && $this->package->checkDependencies(); + if ($this->getPackage()) { + return $this->getPackage()->isValid() && $this->getPackage()->checkDependencies(); } return false; @@ -708,9 +696,9 @@ class ElggPlugin extends ElggObject { * @throws PluginException */ public function start($flags) { - if (!$this->canActivate()) { - return false; - } +// if (!$this->canActivate()) { +// return false; +// } // include start file if ($flags & ELGG_PLUGIN_INCLUDE_START) { @@ -851,12 +839,7 @@ class ElggPlugin extends ElggObject { return true; } - // but need to have working ones. - if (!elgg_register_classes($classes_path)) { - $msg = elgg_echo('ElggPlugin:Exception:CannotRegisterClasses', - array($this->getID(), $this->guid, $classes_path)); - throw new PluginException($msg); - } + elgg_register_classes($classes_path); return true; } @@ -958,4 +941,44 @@ class ElggPlugin extends ElggObject { public function getError() { return $this->errorMsg; } + + /** + * Returns this plugin's ElggPluginManifest object + * + * @return ElggPluginManifest + */ + public function getManifest() { + if ($this->manifest instanceof ElggPluginManifest) { + return $this->manifest; + } + + try { + $this->manifest = $this->getPackage()->getManifest(); + } catch (Exception $e) { + elgg_log("Failed to load manifest for plugin $this->guid. " . $e->getMessage(), 'WARNING'); + $this->errorMsg = $e->getmessage(); + } + + return $this->manifest; + } + + /** + * Returns this plugin's ElggPluginPackage object + * + * @return ElggPluginPackage + */ + public function getPackage() { + if ($this->package instanceof ElggPluginPackage) { + return $this->package; + } + + try { + $this->package = new ElggPluginPackage($this->path, false); + } catch (Exception $e) { + elgg_log("Failed to load package for $this->guid. " . $e->getMessage(), 'WARNING'); + $this->errorMsg = $e->getmessage(); + } + + return $this->package; + } } diff --git a/engine/classes/ElggPluginPackage.php b/engine/classes/ElggPluginPackage.php index 4daab381e..977b72d76 100644 --- a/engine/classes/ElggPluginPackage.php +++ b/engine/classes/ElggPluginPackage.php @@ -334,13 +334,13 @@ class ElggPluginPackage { // first, check if any active plugin conflicts with us. foreach ($enabled_plugins as $plugin) { - $temp_conflicts = $plugin->manifest->getConflicts(); + $temp_conflicts = $plugin->getManifest()->getConflicts(); foreach ($temp_conflicts as $conflict) { if ($conflict['type'] == 'plugin' && $conflict['name'] == $this_id) { $result = $this->checkDepPlugin($conflict, $enabled_plugins, false); // rewrite the conflict to show the originating plugin - $conflict['name'] = $plugin->manifest->getName(); + $conflict['name'] = $plugin->getManifest()->getName(); if (!$full_report && !$result['status']) { return $result['status']; @@ -455,19 +455,13 @@ class ElggPluginPackage { */ private function checkDepPriority(array $dep, array $plugins, $inverse = false) { // grab the ElggPlugin using this package. - $this_plugin = elgg_get_plugin_from_id($this->getID()); - $this_priority = $this_plugin->getPriority(); + $plugin_package = elgg_get_plugin_from_id($this->getID()); + $plugin_priority = $plugin_package->getPriority(); + $test_plugin = elgg_get_plugin_from_id($dep['plugin']); - foreach ($plugins as $test_plugin) { - if ($test_plugin->getID() == $dep['plugin']) { - break; - } - } - - // If this isn't a plugin or there are no active plugins, - // we can't satisfy this dep. - // Assume everything is ok. See #2946. - if (!$this->plugin || !$plugins) { + // If this isn't a plugin or the plugin isn't installed or active + // priority doesn't matter. Use requires to check if a plugin is active. + if (!$plugin_package || !$test_plugin || !$test_plugin->isActive()) { return array( 'status' => true, 'value' => 'uninstalled' @@ -478,11 +472,11 @@ class ElggPluginPackage { switch ($dep['priority']) { case 'before': - $status = $this_priority < $test_plugin_priority; + $status = $plugin_priority < $test_plugin_priority; break; case 'after': - $status = $this_priority > $test_plugin_priority; + $status = $plugin_priority > $test_plugin_priority; break; default; @@ -490,7 +484,7 @@ class ElggPluginPackage { } // get the current value - if ($this_priority < $test_plugin_priority) { + if ($plugin_priority < $test_plugin_priority) { $value = 'before'; } else { $value = 'after'; diff --git a/engine/classes/ElggSite.php b/engine/classes/ElggSite.php index d3cb0d488..e3b8b8f1a 100644 --- a/engine/classes/ElggSite.php +++ b/engine/classes/ElggSite.php @@ -148,11 +148,20 @@ class ElggSite extends ElggEntity { * @return bool */ public function save() { + global $CONFIG; + // Save generic stuff if (!parent::save()) { return false; } + // make sure the site guid is set (if not, set to self) + if (!$this->get('site_guid')) { + $guid = $this->get('guid'); + update_data("UPDATE {$CONFIG->dbprefix}entities SET site_guid=$guid + WHERE guid=$guid"); + } + // Now save specific stuff return create_site_entity($this->get('guid'), $this->get('name'), $this->get('description'), $this->get('url')); @@ -400,7 +409,7 @@ class ElggSite extends ElggEntity { 'action/login', 'register', 'action/register', - 'pages/account/forgotten_password\.php', + 'forgotpassword', 'action/user/requestnewpassword', 'resetpassword', 'upgrade\.php', diff --git a/engine/lib/actions.php b/engine/lib/actions.php index 47e4dd4a4..ff598916f 100644 --- a/engine/lib/actions.php +++ b/engine/lib/actions.php @@ -152,6 +152,7 @@ function action($action, $forwarder = "") { * @param string $filename Optionally, the filename where this action is located. If not specified, * will assume the action is in elgg/actions/<action>.php * @param string $access Who is allowed to execute this action: admin, public, or logged_in. + * (default: logged_in) * * @see action() * @see http://docs.elgg.org/Actions @@ -411,6 +412,16 @@ function elgg_is_xhr() { */ function ajax_forward_hook($hook, $type, $reason, $params) { if (elgg_is_xhr()) { + // always pass the full structure to avoid boilerplate JS code. + $params = array( + 'output' => '', + 'status' => 0, + 'system_messages' => array( + 'error' => array(), + 'success' => array() + ) + ); + //grab any data echo'd in the action $output = ob_get_clean(); @@ -423,12 +434,15 @@ function ajax_forward_hook($hook, $type, $reason, $params) { } //Grab any system messages so we can inject them via ajax too - $params['system_messages'] = system_messages(NULL, ""); + $system_messages = system_messages(NULL, ""); + + if (isset($system_messages['success'])) { + $params['system_messages']['success'] = $system_messages['success']; + } - if (isset($params['system_messages']['error'])) { + if (isset($system_messages['error'])) { + $params['system_messages']['error'] = $system_messages['error']; $params['status'] = -1; - } else { - $params['status'] = 0; } header("Content-type: application/json"); diff --git a/engine/lib/admin.php b/engine/lib/admin.php index 06418c44f..3bfb69102 100644 --- a/engine/lib/admin.php +++ b/engine/lib/admin.php @@ -183,7 +183,7 @@ function elgg_admin_notice_exists($id) { function elgg_register_admin_menu_item($section, $menu_id, $parent_id = NULL, $priority = 100) { // make sure parent is registered - if ($parent_id && !elgg_is_menu_item_registered($menu_id, $parent_id)) { + if ($parent_id && !elgg_is_menu_item_registered('page', $parent_id)) { elgg_register_admin_menu_item($section, $parent_id); } @@ -211,7 +211,7 @@ function elgg_register_admin_menu_item($section, $menu_id, $parent_id = NULL, $p } /** - * Initialise the admin backend. + * Initialize the admin backend. * * @return void */ @@ -262,11 +262,18 @@ function admin_init() { // configure // plugins - elgg_register_admin_menu_item('configure', 'plugins', null, 10); - elgg_register_admin_menu_item('configure', 'simple', 'plugins', 10); - elgg_register_admin_menu_item('configure', 'advanced', 'plugins', 20); + elgg_register_menu_item('page', array( + 'name' => 'plugins', + 'href' => 'admin/plugins', + 'text' => elgg_echo('admin:plugins'), + 'context' => 'admin', + 'priority' => 75, + 'section' => 'configure' + )); // settings + elgg_register_admin_menu_item('configure', 'appearance', null, 50); + elgg_register_admin_menu_item('configure', 'settings', null, 100); elgg_register_admin_menu_item('configure', 'basic', 'settings', 10); elgg_register_admin_menu_item('configure', 'advanced', 'settings', 20); elgg_register_admin_menu_item('configure', 'menu_items', 'appearance', 30); @@ -277,6 +284,11 @@ function admin_init() { // plugin settings are added in elgg_admin_add_plugin_settings_menu() via the admin page handler // for performance reasons. + // we want plugin settings menu items to be sorted alphabetical + if (elgg_in_context('admin')) { + elgg_register_plugin_hook_handler('prepare', 'menu:page', 'elgg_admin_sort_page_menu'); + } + if (elgg_is_admin_logged_in()) { elgg_register_menu_item('topbar', array( 'name' => 'administration', @@ -314,6 +326,7 @@ function admin_init() { * * @return void * @access private + * @since 1.8.0 */ function elgg_admin_add_plugin_settings_menu() { @@ -325,11 +338,13 @@ function elgg_admin_add_plugin_settings_menu() { foreach ($active_plugins as $plugin) { $plugin_id = $plugin->getID(); - if (elgg_view_exists("settings/$plugin_id/edit")) { + $settings_view_old = 'settings/' . $plugin_id . '/edit'; + $settings_view_new = 'plugins/' . $plugin_id . '/settings'; + if (elgg_view_exists($settings_view_new) || elgg_view_exists($settings_view_old)) { elgg_register_menu_item('page', array( 'name' => $plugin_id, 'href' => "admin/plugin_settings/$plugin_id", - 'text' => $plugin->manifest->getName(), + 'text' => $plugin->getManifest()->getName(), 'parent_name' => 'settings', 'context' => 'admin', 'section' => 'configure', @@ -339,6 +354,33 @@ function elgg_admin_add_plugin_settings_menu() { } /** + * Sort the plugin settings menu items + * + * @param string $hook + * @param string $type + * @param array $return + * @param array $params + * + * @return void + * @since 1.8.0 + */ +function elgg_admin_sort_page_menu($hook, $type, $return, $params) { + $configure_items = $return['configure']; + foreach ($configure_items as $menu_item) { + if ($menu_item->getName() == 'settings') { + $settings = $menu_item; + } + } + + // keep the basic and advanced settings at the top + $children = $settings->getChildren(); + $site_settings = array_splice($children, 0, 2); + usort($children, array('ElggMenuBuilder', 'compareByText')); + array_splice($children, 0, 0, $site_settings); + $settings->setChildren($children); +} + +/** * Handles any set up required for administration pages * * @return void @@ -413,8 +455,8 @@ function admin_settings_page_handler($page) { $vars = array('page' => $page); // special page for plugin settings since we create the form for them - if ($page[0] == 'plugin_settings' && isset($page[1]) - && elgg_view_exists("settings/{$page[1]}/edit")) { + if ($page[0] == 'plugin_settings' && isset($page[1]) && + (elgg_view_exists("settings/{$page[1]}/edit") || elgg_view_exists("plugins/{$page[1]}/settings"))) { $view = 'admin/plugin_settings'; $plugin = elgg_get_plugin_from_id($page[1]); @@ -516,9 +558,11 @@ function admin_markdown_page_handler($pages) { $filename = elgg_extract(1, $pages); $error = false; - if (!$plugin) { $error = elgg_echo('admin:plugins:markdown:unknown_plugin'); + $body = elgg_view_layout('admin', array('content' => $error, 'title' => $error)); + echo elgg_view_page($title, $body, 'admin'); + return true; } $text_files = $plugin->getAvailableTextFiles(); @@ -541,11 +585,13 @@ function admin_markdown_page_handler($pages) { return true; } - $title = $plugin->manifest->getName() . ": $filename"; + $title = $plugin->getManifest()->getName() . ": $filename"; $text = Markdown($file_contents); $body = elgg_view_layout('admin', array( - 'content' => $text, + // setting classes here because there's no way to pass classes + // to the layout + 'content' => '<div class="elgg-markdown">' . $text . '</div>', 'title' => $title )); diff --git a/engine/lib/database.php b/engine/lib/database.php index 6b1b494b9..7747eb0d5 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -250,8 +250,6 @@ function explain_query($query, $link) { function execute_query($query, $dblink) { global $CONFIG, $dbcalls; - // remove newlines so logs are easier to read - $query = preg_replace("/[\r\n]/", "", $query); if ($query == NULL) { throw new DatabaseException(elgg_echo('DatabaseException:InvalidQuery')); } @@ -362,7 +360,7 @@ function get_data_row($query, $callback = "") { /** * Handles returning data from a query, running it through a callback function, - * and caching the results. + * and caching the results. This is for R queries (from CRUD). * * @access private * @@ -377,6 +375,8 @@ function get_data_row($query, $callback = "") { function elgg_query_runner($query, $callback = null, $single = false) { global $CONFIG, $DB_QUERY_CACHE; + $query = elgg_format_query($query); + // since we want to cache results of running the callback, we need to // need to namespace the query with the callback, and single result request. $hash = (string)$callback . (string)$single . $query; @@ -386,7 +386,7 @@ function elgg_query_runner($query, $callback = null, $single = false) { $cached_query = $DB_QUERY_CACHE[$hash]; if ($cached_query !== FALSE) { - elgg_log("$query results returned from cache (hash: $hash)"); + elgg_log("DB query $query results returned from cache (hash: $hash)", 'NOTICE'); return $cached_query; } } @@ -415,13 +415,13 @@ function elgg_query_runner($query, $callback = null, $single = false) { } if (empty($return)) { - elgg_log("DB query \"$query\" returned no results."); + elgg_log("DB query $query returned no results.", 'NOTICE'); } // Cache result if ($DB_QUERY_CACHE) { $DB_QUERY_CACHE[$hash] = $return; - elgg_log("$query results cached (hash: $hash)"); + elgg_log("DB query $query results cached (hash: $hash)", 'NOTICE'); } return $return; @@ -440,6 +440,9 @@ function elgg_query_runner($query, $callback = null, $single = false) { function insert_data($query) { global $CONFIG, $DB_QUERY_CACHE; + $query = elgg_format_query($query); + elgg_log("DB query $query", 'NOTICE'); + $dblink = get_db_link('write'); // Invalidate query cache @@ -447,7 +450,7 @@ function insert_data($query) { $DB_QUERY_CACHE->clear(); } - elgg_log("Query cache invalidated"); + elgg_log("Query cache invalidated", 'NOTICE'); if (execute_query("$query", $dblink)) { return mysql_insert_id($dblink); @@ -468,12 +471,15 @@ function insert_data($query) { function update_data($query) { global $CONFIG, $DB_QUERY_CACHE; + $query = elgg_format_query($query); + elgg_log("DB query $query", 'NOTICE'); + $dblink = get_db_link('write'); // Invalidate query cache if ($DB_QUERY_CACHE) { $DB_QUERY_CACHE->clear(); - elgg_log("Query cache invalidated"); + elgg_log("Query cache invalidated", 'NOTICE'); } if (execute_query("$query", $dblink)) { @@ -495,12 +501,15 @@ function update_data($query) { function delete_data($query) { global $CONFIG, $DB_QUERY_CACHE; + $query = elgg_format_query($query); + elgg_log("DB query $query", 'NOTICE'); + $dblink = get_db_link('write'); // Invalidate query cache if ($DB_QUERY_CACHE) { $DB_QUERY_CACHE->clear(); - elgg_log("Query cache invalidated"); + elgg_log("Query cache invalidated", 'NOTICE'); } if (execute_query("$query", $dblink)) { @@ -635,6 +644,17 @@ function run_sql_script($scriptlocation) { } /** + * Format a query string for logging + * + * @param string $query Query string + * @return string + */ +function elgg_format_query($query) { + // remove newlines and extra spaces so logs are easier to read + return preg_replace('/\s\s+/', ' ', $query); +} + +/** * Sanitise a string for database use, but with the option of escaping extra characters. * * @param string $string The string to sanitise diff --git a/engine/lib/deprecated-1.8.php b/engine/lib/deprecated-1.8.php index bb52881cd..d92257a09 100644 --- a/engine/lib/deprecated-1.8.php +++ b/engine/lib/deprecated-1.8.php @@ -1,7 +1,83 @@ <?php /** - * @return str + * *************************************************************************** + * NOTE: If this is ever removed from Elgg, sites lose the ability to upgrade + * from 1.7.x and earlier to the latest version of Elgg without upgrading to + * 1.8 first. + * *************************************************************************** + * + * Upgrade the database schema in an ordered sequence. + * + * Executes all upgrade files in elgg/engine/schema/upgrades/ in sequential order. + * Upgrade files must be in the standard Elgg release format of YYYYMMDDII.sql + * where II is an incrementor starting from 01. + * + * Files that are < $version will be ignored. + * + * @warning Plugin authors should not call this function directly. + * + * @param int $version The version you are upgrading from in the format YYYYMMDDII. + * @param string $fromdir Optional directory to load upgrades from. default: engine/schema/upgrades/ + * @param bool $quiet If true, suppress all error messages. Only use for the upgrade from <=1.6. + * + * @return bool + * @see upgrade.php + * @see version.php + * @deprecated 1.8 Use PHP upgrades for sql changes. + */ +function db_upgrade($version, $fromdir = "", $quiet = FALSE) { + global $CONFIG; + + elgg_deprecated_notice('db_upgrade() is deprecated by using PHP upgrades.', 1.8); + + $version = (int) $version; + + if (!$fromdir) { + $fromdir = $CONFIG->path . 'engine/schema/upgrades/'; + } + + if ($handle = opendir($fromdir)) { + $sqlupgrades = array(); + + while ($sqlfile = readdir($handle)) { + if (!is_dir($fromdir . $sqlfile)) { + if (preg_match('/^([0-9]{10})\.(sql)$/', $sqlfile, $matches)) { + $sql_version = (int) $matches[1]; + if ($sql_version > $version) { + $sqlupgrades[] = $sqlfile; + } + } + } + } + + asort($sqlupgrades); + + if (sizeof($sqlupgrades) > 0) { + foreach ($sqlupgrades as $sqlfile) { + + // hide all errors. + if ($quiet) { + try { + run_sql_script($fromdir . $sqlfile); + } catch (DatabaseException $e) { + error_log($e->getmessage()); + } + } else { + run_sql_script($fromdir . $sqlfile); + } + } + } + } + + return TRUE; +} + +/** + * Lists entities from an access collection + * * @deprecated 1.8 Use elgg_list_entities_from_access_id() + * + * @return str */ function list_entities_from_access_id($access_id, $entity_type = "", $entity_subtype = "", $owner_guid = 0, $limit = 10, $fullview = true, $listtypetoggle = true, $pagination = true) { @@ -14,7 +90,14 @@ function list_entities_from_access_id($access_id, $entity_type = "", $entity_sub } /** + * Registers a particular action in memory + * * @deprecated 1.8 Use {@link elgg_register_action()} instead + * + * @param string $action The name of the action (eg "register", "account/settings/save") + * @param boolean $public Can this action be accessed by people not logged into the system? + * @param string $filename Optionally, the filename where this action is located + * @param boolean $admin_only Whether this action is only available to admin users. */ function register_action($action, $public = false, $filename = "", $admin_only = false) { elgg_deprecated_notice("register_action() was deprecated by elgg_register_action()", 1.8); @@ -35,6 +118,8 @@ function register_action($action, $public = false, $filename = "", $admin_only = * This function extends the view "admin/main" with the provided view. * This view should provide a description and either a control or a link to. * + * @deprecated 1.8 Extend admin views manually + * * Usage: * - To add a control to the main admin panel then extend admin/main * - To add a control to a new page create a page which renders a view admin/subpage @@ -48,8 +133,6 @@ function register_action($action, $public = false, $filename = "", $admin_only = * @param string $view The view to extend, by default this is 'admin/main'. * @param int $priority Optional priority to govern the appearance in the list. * - * @deprecated 1.8 Extend admin views manually - * * @return void */ function extend_elgg_admin_page($new_admin_view, $view = 'admin/main', $priority = 500) { @@ -115,7 +198,7 @@ function get_entities_from_annotations_calculate_x($sum = "sum", $entity_type = $options['limit'] = $limit; $options['offset'] = $offset; - $options['order_by'] = "calculation $orderdir"; + $options['order_by'] = "annotation_calculation $orderdir"; $options['count'] = $count; @@ -125,6 +208,12 @@ function get_entities_from_annotations_calculate_x($sum = "sum", $entity_type = /** * Returns entities ordered by the sum of an annotation * + * @warning This is function uses sum instead of count. THIS IS SLOW. See #3366. + * This should be used when you have annotations with different values and you + * want a list of entities ordered by the sum of all of those values. + * If you want a list of entities ordered by the number of annotations on each entity, + * use __get_entities_from_annotations_calculate_x() and pass 'count' as the first param. + * * @deprecated 1.8 Use elgg_get_entities_from_annotation_calculation() * * @param string $entity_type Type of Entity @@ -179,7 +268,7 @@ function get_entities_from_annotation_count($entity_type = "", $entity_subtype = $options['limit'] = $limit; $options['offset'] = $offset; - $options['order_by'] = "calculation $orderdir"; + $options['order_by'] = "annotation_calculation $orderdir"; $options['count'] = $count; @@ -241,7 +330,7 @@ function list_entities_from_annotation_count($entity_type = "", $entity_subtype $options['limit'] = $limit; - $options['order_by'] = "calculation $orderdir"; + $options['order_by'] = "annotation_calculation $orderdir"; return elgg_get_entities_from_annotation_calculation($options); } @@ -249,6 +338,8 @@ function list_entities_from_annotation_count($entity_type = "", $entity_subtype /** * Adds an entry in $CONFIG[$register_name][$subregister_name]. * + * @deprecated 1.8 Use the new menu system. + * * This is only used for the site-wide menu. See {@link add_menu()}. * * @param string $register_name The name of the top-level register @@ -257,7 +348,6 @@ function list_entities_from_annotation_count($entity_type = "", $entity_subtype * @param array $children_array Optionally, an array of children * * @return true|false Depending on success - * @deprecated 1.8 */ function add_to_register($register_name, $subregister_name, $subregister_value, $children_array = array()) { elgg_deprecated_notice("add_to_register() has been deprecated", 1.8); @@ -290,6 +380,8 @@ function add_to_register($register_name, $subregister_name, $subregister_value, /** * Removes a register entry from $CONFIG[register_name][subregister_name] * + * @deprecated 1.8 Use the new menu system. + * * This is used to by {@link remove_menu()} to remove site-wide menu items. * * @param string $register_name The name of the top-level register @@ -297,7 +389,6 @@ function add_to_register($register_name, $subregister_name, $subregister_value, * * @return true|false Depending on success * @since 1.7.0 - * @deprecated 1.8 */ function remove_from_register($register_name, $subregister_name) { elgg_deprecated_notice("remove_from_register() has been deprecated", 1.8); @@ -326,10 +417,11 @@ function remove_from_register($register_name, $subregister_name) { /** * If it exists, returns a particular register as an array * + * @deprecated 1.8 Use the new menu system + * * @param string $register_name The name of the register * * @return array|false Depending on success - * @deprecated 1.8 */ function get_register($register_name) { elgg_deprecated_notice("get_register() has been deprecated", 1.8); @@ -363,6 +455,8 @@ function get_register($register_name) { * Deprecated events core function. Code divided between elgg_register_event_handler() * and trigger_elgg_event(). * + * @deprecated 1.8 Use explicit register/trigger event functions + * * @param string $event The type of event (eg 'init', 'update', 'delete') * @param string $object_type The type of object (eg 'system', 'blog', 'user') * @param string $function The name of the function that will handle the event @@ -371,7 +465,6 @@ function get_register($register_name) { * @param mixed $object Optionally, the object the event is being performed on (eg a user) * * @return true|false Depending on success - * @deprecated 1.8 Use explicit register/trigger event functions */ function events($event = "", $object_type = "", $function = "", $priority = 500, $call = false, $object = null) { @@ -386,7 +479,14 @@ function events($event = "", $object_type = "", $function = "", $priority = 500, } /** + * Alias function for events, that registers a function to a particular kind of event + * * @deprecated 1.8 Use elgg_register_event_handler() instead + * + * @param string $event The event type + * @param string $object_type The object type + * @param string $function The function name + * @return true|false Depending on success */ function register_elgg_event_handler($event, $object_type, $callback, $priority = 500) { elgg_deprecated_notice("register_elgg_event_handler() was deprecated by elgg_register_event_handler()", 1.8); @@ -394,7 +494,14 @@ function register_elgg_event_handler($event, $object_type, $callback, $priority } /** + * Unregisters a function to a particular kind of event + * * @deprecated 1.8 Use elgg_unregister_event_handler instead + * + * @param string $event The event type + * @param string $object_type The object type + * @param string $function The function name + * @since 1.7.0 */ function unregister_elgg_event_handler($event, $object_type, $callback) { elgg_deprecated_notice('unregister_elgg_event_handler => elgg_unregister_event_handler', 1.8); @@ -402,7 +509,14 @@ function unregister_elgg_event_handler($event, $object_type, $callback) { } /** + * Alias function for events, that triggers a particular kind of event + * * @deprecated 1.8 Use elgg_trigger_event() instead + * + * @param string $event The event type + * @param string $object_type The object type + * @param string $function The function name + * @return true|false Depending on success */ function trigger_elgg_event($event, $object_type, $object = null) { elgg_deprecated_notice('trigger_elgg_event() was deprecated by elgg_trigger_event()', 1.8); @@ -410,7 +524,29 @@ function trigger_elgg_event($event, $object_type, $object = null) { } /** + * Register a function to a plugin hook for a particular entity type, with a given priority. + * * @deprecated 1.8 Use elgg_register_plugin_hook_handler() instead + * + * eg if you want the function "export_user" to be called when the hook "export" for "user" entities + * is run, use: + * + * register_plugin_hook("export", "user", "export_user"); + * + * "all" is a valid value for both $hook and $entity_type. "none" is a valid value for $entity_type. + * + * The export_user function would then be defined as: + * + * function export_user($hook, $entity_type, $returnvalue, $params); + * + * Where $returnvalue is the return value returned by the last function returned by the hook, and + * $params is an array containing a set of parameters (or nothing). + * + * @param string $hook The name of the hook + * @param string $entity_type The name of the type of entity (eg "user", "object" etc) + * @param string $function The name of a valid function to be run + * @param string $priority The priority - 0 is first, 1000 last, default is 500 + * @return true|false Depending on success */ function register_plugin_hook($hook, $type, $callback, $priority = 500) { elgg_deprecated_notice("register_plugin_hook() was deprecated by elgg_register_plugin_hook_handler()", 1.8); @@ -418,7 +554,14 @@ function register_plugin_hook($hook, $type, $callback, $priority = 500) { } /** + * Unregister a function to a plugin hook for a particular entity type + * * @deprecated 1.8 Use elgg_unregister_plugin_hook_handler() instead + * + * @param string $hook The name of the hook + * @param string $entity_type The name of the type of entity (eg "user", "object" etc) + * @param string $function The name of a valid function to be run + * @since 1.7.0 */ function unregister_plugin_hook($hook, $entity_type, $callback) { elgg_deprecated_notice("unregister_plugin_hook() was deprecated by elgg_unregister_plugin_hook_handler()", 1.8); @@ -426,7 +569,20 @@ function unregister_plugin_hook($hook, $entity_type, $callback) { } /** + * Triggers a plugin hook, with various parameters as an array. For example, to provide + * a 'foo' hook that concerns an entity of type 'bar', with a parameter called 'param1' + * with value 'value1', that by default returns true, you'd call: + * * @deprecated 1.8 Use elgg_trigger_plugin_hook() instead + * + * trigger_plugin_hook('foo', 'bar', array('param1' => 'value1'), true); + * + * @see register_plugin_hook + * @param string $hook The name of the hook to trigger + * @param string $entity_type The name of the entity type to trigger it for (or "all", or "none") + * @param array $params Any parameters. It's good practice to name the keys, i.e. by using array('name' => 'value', 'name2' => 'value2') + * @param mixed $returnvalue An initial return value + * @return mixed|null The cumulative return value for the plugin hook functions */ function trigger_plugin_hook($hook, $type, $params = null, $returnvalue = null) { elgg_deprecated_notice("trigger_plugin_hook() was deprecated by elgg_trigger_plugin_hook()", 1.8); @@ -1667,7 +1823,7 @@ function get_installed_plugins($status = 'all') { if ($include) { $installed_plugins[$plugin->getID()] = array( 'active' => $plugin->isActive(), - 'manifest' => $plugin->manifest->getManifest() + 'manifest' => $plugin->getManifest()->getManifest() ); } } @@ -2844,6 +3000,13 @@ $priority = 500) { } /** + * Returns a representation of a full 'page' (which might be an HTML page, + * RSS file, etc, depending on the current viewtype) + * + * @param string $title + * @param string $body + * @return string + * * @deprecated 1.8 Use elgg_view_page() */ function page_draw($title, $body, $sidebar = "") { @@ -3504,14 +3667,18 @@ $asc = false, $fullview = true, $listtypetoggle = false, $pagination = true, $or $options['limit'] = $limit; - $options['order_by'] = "calculation $orderdir"; + $options['order_by'] = "annotation_calculation $orderdir"; return elgg_get_entities_from_annotation_calculation($options); } /** - * @deprecated 1.8 - * @see elgg_set_view_location() + * Set an alternative base location for a view (as opposed to the default of $CONFIG->viewpath) + * + * @param string $view The name of the view + * @param string $location The base location path + * + * @deprecated 1.8 Use elgg_set_view_location() */ function set_view_location($view, $location, $viewtype = '') { elgg_deprecated_notice("set_view_location() was deprecated by elgg_set_view_location()", 1.8); @@ -3519,8 +3686,14 @@ function set_view_location($view, $location, $viewtype = '') { } /** - * @deprecated 1.8 - * @see elgg_register_entity_url_handler() + * Sets the URL handler for a particular entity type and subtype + * + * @param string $function_name The function to register + * @param string $entity_type The entity type + * @param string $entity_subtype The entity subtype + * @return true|false Depending on success + * + * @deprecated 1.8 Use elgg_register_entity_url_handler() */ function register_entity_url_handler($function_name, $entity_type = "all", $entity_subtype = "all") { elgg_deprecated_notice("register_entity_url_handler() was deprecated by elgg_register_entity_url_handler()", 1.8); @@ -3807,6 +3980,27 @@ function clear_annotations_by_owner($owner_guid) { } /** + * Registers a page handler for a particular identifier + * + * For example, you can register a function called 'blog_page_handler' for handler type 'blog' + * Now for all URLs of type http://yoururl/pg/blog/*, the blog_page_handler() function will be called. + * The part of the URL marked with * above will be exploded on '/' characters and passed as an + * array to that function. + * For example, the URL http://yoururl/blog/username/friends/ would result in the call: + * blog_page_handler(array('username','friends'), blog); + * + * Page handler functions should return true or the default page handler will be called. + * + * A request to register a page handler with the same identifier as previously registered + * handler will replace the previous one. + * + * The context is set to the page handler identifier before the registered + * page handler function is called. For the above example, the context is set to 'blog'. + * + * @param string $handler The page type to handle + * @param string $function Your function name + * @return true|false Depending on success + * * @deprecated 1.8 Use {@link elgg_register_page_handler()} */ function register_page_handler($handler, $function){ @@ -3815,6 +4009,13 @@ function register_page_handler($handler, $function){ } /** + * Unregister a page handler for an identifier + * + * Note: to replace a page handler, call register_page_handler() + * + * @param string $handler The page type identifier + * @since 1.7.2 + * * @deprecated 1.8 Use {@link elgg_unregister_page_handler()} */ function unregister_page_handler($handler) { @@ -3823,6 +4024,11 @@ function unregister_page_handler($handler) { } /** + * Register an annotation url handler. + * + * @param string $function_name The function. + * @param string $extender_name The name, default 'all'. + * * @deprecated 1.8 Use {@link elgg_register_annotation_url_handler()} */ function register_annotation_url_handler($function, $extender_name) { @@ -3831,6 +4037,15 @@ function register_annotation_url_handler($function, $extender_name) { } /** + * Sets the URL handler for a particular extender type and name. + * It is recommended that you do not call this directly, instead use one of the wrapper functions in the + * subtype files. + * + * @param string $function_name The function to register + * @param string $extender_type Extender type + * @param string $extender_name The name of the extender + * @return true|false Depending on success + * * @deprecated 1.8 Use {@link elgg_register_extender_url_handler()} */ function register_extender_url_handler($function, $type = "all", $name = "all") { @@ -3839,6 +4054,14 @@ function register_extender_url_handler($function, $type = "all", $name = "all") } /** + * Registers and entity type and subtype to return in search and other places. + * A description in the elgg_echo languages file of the form item:type:subtype + * is also expected. + * + * @param string $type The type of entity (object, site, user, group) + * @param string $subtype The subtype to register (may be blank) + * @return true|false Depending on success + * * @deprecated 1.8 Use {@link elgg_register_entity_type()} */ function register_entity_type($type, $subtype = null) { @@ -3847,6 +4070,11 @@ function register_entity_type($type, $subtype = null) { } /** + * Register a metadata url handler. + * + * @param string $function_name The function. + * @param string $extender_name The name, default 'all'. + * * @deprecated 1.8 Use {@link elgg_register_metadata_url_handler()} */ function register_metadata_url_handler($function, $extender_name = "all") { @@ -3854,7 +4082,12 @@ function register_metadata_url_handler($function, $extender_name = "all") { } /** + * Sets the URL handler for a particular relationship type * + * @param string $function_name The function to register + * @param string $relationship_type The relationship type. + * @return true|false Depending on success + * * @deprecated 1.8 Use {@link elgg_register_relationship_url_handler()} */ function register_relationship_url_handler($function_name, $relationship_type = "all") { @@ -3863,6 +4096,15 @@ function register_relationship_url_handler($function_name, $relationship_type = } /** + * Registers a view to be simply cached + * + * Views cached in this manner must take no parameters and be login agnostic - + * that is to say, they look the same no matter who is logged in (or logged out). + * + * CSS and the basic jS views are automatically cached like this. + * + * @param string $viewname View name + * * @deprecated 1.8 Use {@link elgg_register_simplecache_view()} */ function elgg_view_register_simplecache($viewname) { @@ -3871,6 +4113,11 @@ function elgg_view_register_simplecache($viewname) { } /** + * Regenerates the simple cache. + * + * @param string $viewtype Optional viewtype to regenerate + * @see elgg_view_register_simplecache() + * * @deprecated 1.8 Use {@link elgg_regenerate_simplecache()} */ function elgg_view_regenerate_simplecache($viewtype = NULL) { @@ -3879,6 +4126,10 @@ function elgg_view_regenerate_simplecache($viewtype = NULL) { } /** + * Enables the simple cache. + * + * @see elgg_view_register_simplecache() + * * @deprecated 1.8 Use {@link elgg_enable_simplecache()} */ function elgg_view_enable_simplecache() { @@ -3887,6 +4138,10 @@ function elgg_view_enable_simplecache() { } /** + * Disables the simple cache. + * + * @see elgg_view_register_simplecache() + * * @deprecated 1.8 Use {@link elgg_disable_simplecache()} */ function elgg_view_disable_simplecache() { @@ -3912,6 +4167,22 @@ function is_installed() { } /** + * Attempt to authenticate. + * This function will process all registered PAM handlers or stop when the first + * handler fails. A handler fails by either returning false or throwing an + * exception. The advantage of throwing an exception is that it returns a message + * through the global $_PAM_HANDLERS_MSG which can be used in communication with + * a user. The order that handlers are processed is determined by the order that + * they were registered. + * + * If $credentials are provided the PAM handler should authenticate using the + * provided credentials, if not then credentials should be prompted for or + * otherwise retrieved (eg from the HTTP header or $_SESSION). + * + * @param mixed $credentials Mixed PAM handler specific credentials (e.g. username, password) + * @param string $policy - the policy type, default is "user" + * @return bool true if authenticated, false if not. + * * @deprecated 1.8 See {@link ElggPAM} */ function pam_authenticate($credentials = NULL, $policy = "user") { @@ -4375,6 +4646,11 @@ function using_widgets() { } /** + * Displays a particular widget + * + * @param ElggObject $widget The widget to display + * @return string The HTML for the widget, including JavaScript wrapper + * * @deprecated 1.8 */ function display_widget(ElggObject $widget) { @@ -4382,92 +4658,76 @@ function display_widget(ElggObject $widget) { return elgg_view_entity($widget); } - /** - * *************************************************************************** - * NOTE: If this is ever removed from Elgg, sites lose the ability to upgrade - * from 1.7.x and earlier to the latest version of Elgg without upgrading to - * 1.8 first. - * *************************************************************************** - * - * Upgrade the database schema in an ordered sequence. - * - * Executes all upgrade files in elgg/engine/schema/upgrades/ in sequential order. - * Upgrade files must be in the standard Elgg release format of YYYYMMDDII.sql - * where II is an incrementor starting from 01. - * - * Files that are < $version will be ignored. - * - * @warning Plugin authors should not call this function directly. - * - * @param int $version The version you are upgrading from in the format YYYYMMDDII. - * @param string $fromdir Optional directory to load upgrades from. default: engine/schema/upgrades/ - * @param bool $quiet If true, suppress all error messages. Only use for the upgrade from <=1.6. + * Count the number of comments attached to an entity * - * @return bool - * @see upgrade.php - * @see version.php - * @deprecated 1.8 Use PHP upgrades for sql changes. + * @param ElggEntity $entity + * @return int Number of comments */ -function db_upgrade($version, $fromdir = "", $quiet = FALSE) { - global $CONFIG; - - elgg_deprecated_notice('db_upgrade() is deprecated by using PHP upgrades.', 1.8); - - $version = (int) $version; +function elgg_count_comments($entity) { + elgg_deprecated_notice('elgg_count_comments() is deprecated by ElggEntity->countComments()', 1.8); - if (!$fromdir) { - $fromdir = $CONFIG->path . 'engine/schema/upgrades/'; + if ($entity instanceof ElggEntity) { + return $entity->countComments(); } - if ($handle = opendir($fromdir)) { - $sqlupgrades = array(); - - while ($sqlfile = readdir($handle)) { - if (!is_dir($fromdir . $sqlfile)) { - if (preg_match('/^([0-9]{10})\.(sql)$/', $sqlfile, $matches)) { - $sql_version = (int) $matches[1]; - if ($sql_version > $version) { - $sqlupgrades[] = $sqlfile; - } - } - } - } + return 0; +} - asort($sqlupgrades); +/** + * Removes all items relating to a particular acting entity from the river + * + * @param int $subject_guid The GUID of the entity + * + * @return bool Depending on success + * @deprecated 1.8 Use elgg_delete_river() + */ +function remove_from_river_by_subject($subject_guid) { + elgg_deprecated_notice("remove_from_river_by_subject() deprecated by elgg_delete_river()", 1.8); - if (sizeof($sqlupgrades) > 0) { - foreach ($sqlupgrades as $sqlfile) { + return elgg_delete_river(array('subject_guid' => $subject_guid)); +} - // hide all errors. - if ($quiet) { - try { - run_sql_script($fromdir . $sqlfile); - } catch (DatabaseException $e) { - error_log($e->getmessage()); - } - } else { - run_sql_script($fromdir . $sqlfile); - } - } - } - } +/** + * Removes all items relating to a particular entity being acted upon from the river + * + * @param int $object_guid The GUID of the entity + * + * @return bool Depending on success + * @deprecated 1.8 Use elgg_delete_river() + */ +function remove_from_river_by_object($object_guid) { + elgg_deprecated_notice("remove_from_river_by_object() deprecated by elgg_delete_river()", 1.8); - return TRUE; + return elgg_delete_river(array('object_guid' => $object_guid)); } /** - * Count the number of comments attached to an entity + * Removes all items relating to a particular annotation being acted upon from the river * - * @param ElggEntity $entity - * @return int Number of comments + * @param int $annotation_id The ID of the annotation + * + * @return bool Depending on success + * @since 1.7.0 + * @deprecated 1.8 Use elgg_delete_river() */ -function elgg_count_comments($entity) { - elgg_deprecated_notice('elgg_count_comments() is deprecated by ElggEntity->countComments()', 1.8); +function remove_from_river_by_annotation($annotation_id) { + elgg_deprecated_notice("remove_from_river_by_annotation() deprecated by elgg_delete_river()", 1.8); - if ($entity instanceof ElggEntity) { - return $entity->countComments(); - } + return elgg_delete_river(array('annotation_id' => $annotation_id)); +} - return 0; -}
\ No newline at end of file +/** + * Removes a single river entry + * + * @param int $id The ID of the river entry + * + * @return bool Depending on success + * @since 1.7.2 + * @deprecated 1.8 Use elgg_delete_river() + */ +function remove_from_river_by_id($id) { + elgg_deprecated_notice("remove_from_river_by_id() deprecated by elgg_delete_river()", 1.8); + + return elgg_delete_river(array('id' => $id)); +} diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index e67f8b627..df78515f2 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -33,21 +33,15 @@ function _elgg_autoload($class) { * * @param string $dir The dir to look in * - * @return true + * @return void * @since 1.8.0 */ function elgg_register_classes($dir) { $classes = elgg_get_file_list($dir, array(), array(), array('.php')); - if (!$classes) { - return false; - } - foreach ($classes as $class) { elgg_register_class(basename($class, '.php'), $class); } - - return true; } /** @@ -1795,8 +1789,9 @@ function elgg_cacheable_view_page_handler($page, $type) { // translates to the url /js/calendars/jquery.fullcalendar.min.<ts>.js // and the view js/calendars/jquery.fullcalendar.min // we ignore the last two dots for the ts and the ext. + // Additionally, the timestamp is optional. $page = implode('/', $page); - $regex = '|(.+)\.([^\.]+)\.([^.]+)$|'; + $regex = '|(.+?)\.([\d]+\.)?\w+$|'; preg_match($regex, $page, $matches); $view = $matches[1]; $return = elgg_view("$type/$view"); @@ -2008,8 +2003,9 @@ function elgg_init() { elgg_register_menu_item('topbar', array( 'name' => 'elgg_logo', 'href' => 'http://www.elgg.org/', - 'text' => "<img src=\"$logo_url\" alt=\"Elgg logo\" />", + 'text' => "<img src=\"$logo_url\" alt=\"Elgg logo\" width=\"38\" height=\"20\" />", 'priority' => 1, + 'link_class' => 'elgg-topbar-logo', )); // Sets a blacklist of words in the current language. diff --git a/engine/lib/extender.php b/engine/lib/extender.php index a017c9eec..50b05579b 100644 --- a/engine/lib/extender.php +++ b/engine/lib/extender.php @@ -132,7 +132,7 @@ function can_edit_extender($extender_id, $type, $user_guid = 0) { $user = elgg_get_logged_in_user_entity(); } - $functionname = "get_{$type}"; + $functionname = "elgg_get_{$type}_from_id"; if (is_callable($functionname)) { $extender = $functionname($extender_id); } else { @@ -161,13 +161,13 @@ function can_edit_extender($extender_id, $type, $user_guid = 0) { /** * Sets the URL handler for a particular extender type and name. * It is recommended that you do not call this directly, instead use - * one of the wrapper functions in the subtype files. + * one of the wrapper functions such as elgg_register_annotation_url_handler(). * * @param string $function_name The function to register - * @param string $extender_type Extender type + * @param string $extender_type Extender type ('annotation', 'metadata') * @param string $extender_name The name of the extender * - * @return true|false Depending on success + * @return bool */ function elgg_register_extender_url_handler($extender_type, $extender_name, $function_name) { diff --git a/engine/lib/group.php b/engine/lib/group.php index d78274961..755482b00 100644 --- a/engine/lib/group.php +++ b/engine/lib/group.php @@ -276,8 +276,9 @@ function group_gatekeeper($forward = true) { if ($forward && $allowed == false) { register_error(elgg_echo('membershiprequired')); - forward($url, 'member'); - exit; + if (!forward($url, 'member')) { + throw new SecurityException(elgg_echo('SecurityException:UnexpectedOutputInGatekeeper')); + } } return $allowed; diff --git a/engine/lib/output.php b/engine/lib/output.php index 3f35a1576..04c737062 100644 --- a/engine/lib/output.php +++ b/engine/lib/output.php @@ -170,7 +170,7 @@ function elgg_format_attributes(array $attrs) { } // ignore $vars['entity'] => ElggEntity stuff - if (is_not_null($val) && (is_array($val) || !is_object($val))) { + if ($val !== NULL && $val !== false && (is_array($val) || !is_object($val))) { // allow $vars['class'] => array('one', 'two'); // @todo what about $vars['style']? Needs to be semi-colon separated... diff --git a/engine/lib/pagehandler.php b/engine/lib/pagehandler.php index e598d6821..31d73b18c 100644 --- a/engine/lib/pagehandler.php +++ b/engine/lib/pagehandler.php @@ -27,6 +27,20 @@ function page_handler($handler, $page) { array_pop($page); } + // return false to stop processing the request (because you handled it) + // return a new $params array if you want to route the request differently + $params = array( + 'handler' => $handler, + 'segments' => $page, + ); + $params = elgg_trigger_plugin_hook('route', $handler, NULL, $params); + if ($params === false) { + return true; + } + + $handler = $params['handler']; + $page = $params['segments']; + if (!isset($CONFIG->pagehandler) || empty($handler)) { $result = false; } else if (isset($CONFIG->pagehandler[$handler]) && is_callable($CONFIG->pagehandler[$handler])) { diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index 0947b7a8e..88217b782 100644 --- a/engine/lib/plugins.php +++ b/engine/lib/plugins.php @@ -266,9 +266,9 @@ function elgg_is_active_plugin($plugin_id, $site_guid = null) { /** * Loads all active plugins in the order specified in the tool admin panel. * - * @note This is called on every page load and includes additional checking that plugins - * are fit to be loaded. If a plugin is active and problematic, it will be disabled - * and a visible error emitted. + * @note This is called on every page load. If a plugin is active and problematic, it + * will be disabled and a visible error emitted. This does not check the deps system because + * that was too slow. * * @return bool */ @@ -307,17 +307,6 @@ function elgg_load_plugins() { $plugins = elgg_get_plugins('active'); if ($plugins) { foreach ($plugins as $plugin) { - // check if plugin can be started and try to start it. - // if anything is bad, disable it and emit a message. - if (!$plugin->isValid()) { - $plugin->deactivate(); - $msg = elgg_echo('PluginException:MisconfiguredPlugin', array($plugin->getID(), $plugin->guid)); - register_error($msg); - $return = false; - - continue; - } - try { $plugin->start($start_flags); } catch (Exception $e) { @@ -345,11 +334,10 @@ function elgg_load_plugins() { * Returns an ordered list of plugins * * @param string $status The status of the plugins. active, inactive, or all. - * @param bool $include_bad Include physically deleted and invalid plugins? * @param mixed $site_guid Optional site guid * @return array */ -function elgg_get_plugins($status = 'active', $include_bad = false, $site_guid = NULL) { +function elgg_get_plugins($status = 'active', $site_guid = null) { $db_prefix = get_config('dbprefix'); $priority = elgg_namespace_plugin_private_setting('internal', 'priority'); @@ -388,22 +376,9 @@ function elgg_get_plugins($status = 'active', $include_bad = false, $site_guid = break; } - if ($include_bad) { - $old_ia = elgg_set_ignore_access(true); - } - + $old_ia = elgg_set_ignore_access(true); $plugins = elgg_get_entities_from_relationship($options); - - if ($include_bad) { - elgg_set_ignore_access($old_ia); - } else { - // remove bad plugins - foreach ($plugins as $i => $plugin) { - if (!$plugin->isValid()) { - unset ($plugins[$i]); - } - } - } + elgg_set_ignore_access($old_ia); return $plugins; } @@ -422,7 +397,7 @@ function elgg_get_plugins($status = 'active', $include_bad = false, $site_guid = function elgg_set_plugin_priorities(array $order) { $name = elgg_namespace_plugin_private_setting('internal', 'priority'); - $plugins = elgg_get_plugins('any', true); + $plugins = elgg_get_plugins('any'); if (!$plugins) { return false; } @@ -573,7 +548,7 @@ function elgg_get_plugins_provides($type = null, $name = null) { $provides = array(); foreach ($active_plugins as $plugin) { - if ($plugin_provides = $plugin->manifest->getProvides()) { + if ($plugin_provides = $plugin->getManifest()->getProvides()) { foreach ($plugin_provides as $provided) { $provides[$provided['type']][$provided['name']] = array( 'version' => $provided['version'], diff --git a/engine/lib/river.php b/engine/lib/river.php index 80f285e50..36dde7f05 100644 --- a/engine/lib/river.php +++ b/engine/lib/river.php @@ -18,12 +18,14 @@ * @param int $posted The UNIX epoch timestamp of the river item (default: now) * @param int $annotation_id The annotation ID associated with this river entry * - * @return bool Depending on success + * @return int/bool River ID or false on failure */ function add_to_river($view, $action_type, $subject_guid, $object_guid, $access_id = "", $posted = 0, $annotation_id = 0) { - // use default viewtype for when called from REST api + global $CONFIG; + + // use default viewtype for when called from web services api if (!elgg_view_exists($view, 'default')) { return false; } @@ -60,7 +62,7 @@ $posted = 0, $annotation_id = 0) { ); // return false to stop insert - $params = elgg_trigger_plugin_hook('add', 'river', null, $params); + $params = elgg_trigger_plugin_hook('creating', 'river', null, $params); if ($params == false) { // inserting did not fail - it was just prevented return true; @@ -68,11 +70,8 @@ $posted = 0, $annotation_id = 0) { extract($params); - // Load config - global $CONFIG; - // Attempt to save river item; return success status - $insert_data = insert_data("insert into {$CONFIG->dbprefix}river " . + $id = insert_data("insert into {$CONFIG->dbprefix}river " . " set type = '$type', " . " subtype = '$subtype', " . " action_type = '$action_type', " . @@ -83,89 +82,130 @@ $posted = 0, $annotation_id = 0) { " annotation_id = $annotation_id, " . " posted = $posted"); - //update the entities which had the action carried out on it - if ($insert_data) { + // update the entities which had the action carried out on it + // @todo shouldn't this be down elsewhere? Like when an annotation is saved? + if ($id) { update_entity_last_action($object_guid, $posted); - return $insert_data; + + $river_items = elgg_get_river(array('id' => $id)); + if ($river_items) { + elgg_trigger_event('created', 'river', $river_items[0]); + } + return $id; + } else { + return false; } } /** - * Removes all items relating to a particular acting entity from the river + * Delete river items * - * @param int $subject_guid The GUID of the entity + * @warning not checking access (should we?) * - * @return bool Depending on success + * @param array $options + * ids => INT|ARR River item id(s) + * subject_guids => INT|ARR Subject guid(s) + * object_guids => INT|ARR Object guid(s) + * annotation_ids => INT|ARR The identifier of the annotation(s) + * action_types => STR|ARR The river action type(s) identifier + * views => STR|ARR River view(s) + * + * types => STR|ARR Entity type string(s) + * subtypes => STR|ARR Entity subtype string(s) + * type_subtype_pairs => ARR Array of type => subtype pairs where subtype + * can be an array of subtype strings + * + * posted_time_lower => INT The lower bound on the time posted + * posted_time_upper => INT The upper bound on the time posted + * + * @return bool + * @since 1.8.0 */ -function remove_from_river_by_subject($subject_guid) { - // Sanitise - $subject_guid = (int) $subject_guid; - - // Load config +function elgg_delete_river(array $options = array()) { global $CONFIG; - // Remove - return delete_data("delete from {$CONFIG->dbprefix}river where subject_guid = {$subject_guid}"); -} + $defaults = array( + 'ids' => ELGG_ENTITIES_ANY_VALUE, -/** - * Removes all items relating to a particular entity being acted upon from the river - * - * @param int $object_guid The GUID of the entity - * - * @return bool Depending on success - */ -function remove_from_river_by_object($object_guid) { - // Sanitise - $object_guid = (int) $object_guid; + 'subject_guids' => ELGG_ENTITIES_ANY_VALUE, + 'object_guids' => ELGG_ENTITIES_ANY_VALUE, + 'annotation_ids' => ELGG_ENTITIES_ANY_VALUE, - // Load config - global $CONFIG; + 'views' => ELGG_ENTITIES_ANY_VALUE, + 'action_types' => ELGG_ENTITIES_ANY_VALUE, - // Remove - return delete_data("delete from {$CONFIG->dbprefix}river where object_guid = {$object_guid}"); -} + 'types' => ELGG_ENTITIES_ANY_VALUE, + 'subtypes' => ELGG_ENTITIES_ANY_VALUE, + 'type_subtype_pairs' => ELGG_ENTITIES_ANY_VALUE, -/** - * Removes all items relating to a particular annotation being acted upon from the river - * - * @param int $annotation_id The ID of the annotation - * - * @return bool Depending on success - * @since 1.7.0 - */ -function remove_from_river_by_annotation($annotation_id) { - // Sanitise - $annotation_id = (int) $annotation_id; + 'posted_time_lower' => ELGG_ENTITIES_ANY_VALUE, + 'posted_time_upper' => ELGG_ENTITIES_ANY_VALUE, - // Load config - global $CONFIG; + 'wheres' => array(), + 'joins' => array(), - // Remove - return delete_data("delete from {$CONFIG->dbprefix}river where annotation_id = {$annotation_id}"); -} + ); -/** - * Removes a single river entry - * - * @param int $id The ID of the river entry - * - * @return bool Depending on success - * @since 1.7.2 - */ -function remove_from_river_by_id($id) { - global $CONFIG; + $options = array_merge($defaults, $options); - // Sanitise - $id = (int) $id; + $singulars = array('id', 'subject_guid', 'object_guid', 'annotation_id', 'action_type', 'view', 'type', 'subtype'); + $options = elgg_normalise_plural_options_array($options, $singulars); + + $wheres = $options['wheres']; + + $wheres[] = elgg_get_guid_based_where_sql('rv.id', $options['ids']); + $wheres[] = elgg_get_guid_based_where_sql('rv.subject_guid', $options['subject_guids']); + $wheres[] = elgg_get_guid_based_where_sql('rv.object_guid', $options['object_guids']); + $wheres[] = elgg_get_guid_based_where_sql('rv.annotation_id', $options['annotation_ids']); + $wheres[] = elgg_river_get_action_where_sql($options['action_types']); + $wheres[] = elgg_river_get_view_where_sql($options['views']); + $wheres[] = elgg_get_river_type_subtype_where_sql('rv', $options['types'], + $options['subtypes'], $options['type_subtype_pairs']); + + if ($options['posted_time_lower'] && is_int($options['posted_time_lower'])) { + $wheres[] = "rv.posted >= {$options['posted_time_lower']}"; + } + + if ($options['posted_time_upper'] && is_int($options['posted_time_upper'])) { + $wheres[] = "rv.posted <= {$options['posted_time_upper']}"; + } + + // remove identical where clauses + $wheres = array_unique($wheres); + + // see if any functions failed + // remove empty strings on successful functions + foreach ($wheres as $i => $where) { + if ($where === FALSE) { + return FALSE; + } elseif (empty($where)) { + unset($wheres[$i]); + } + } + + $query = "DELETE rv.* FROM {$CONFIG->dbprefix}river rv "; + + // add joins + foreach ($joins as $j) { + $query .= " $j "; + } - return delete_data("delete from {$CONFIG->dbprefix}river where id = {$id}"); + // add wheres + $query .= ' WHERE '; + + foreach ($wheres as $w) { + $query .= " $w AND "; + } + $query .= "1=1"; + + return delete_data($query); } /** * Get river items * * @param array $options + * ids => INT|ARR River item id(s) * subject_guids => INT|ARR Subject guid(s) * object_guids => INT|ARR Object guid(s) * annotation_ids => INT|ARR The identifier of the annotation(s) @@ -195,6 +235,8 @@ function elgg_get_river(array $options = array()) { global $CONFIG; $defaults = array( + 'ids' => ELGG_ENTITIES_ANY_VALUE, + 'subject_guids' => ELGG_ENTITIES_ANY_VALUE, 'object_guids' => ELGG_ENTITIES_ANY_VALUE, 'annotation_ids' => ELGG_ENTITIES_ANY_VALUE, @@ -224,11 +266,12 @@ function elgg_get_river(array $options = array()) { $options = array_merge($defaults, $options); - $singulars = array('subject_guid', 'object_guid', 'annotation_id', 'action_type', 'type', 'subtype'); + $singulars = array('id', 'subject_guid', 'object_guid', 'annotation_id', 'action_type', 'type', 'subtype'); $options = elgg_normalise_plural_options_array($options, $singulars); $wheres = $options['wheres']; + $wheres[] = elgg_get_guid_based_where_sql('rv.id', $options['ids']); $wheres[] = elgg_get_guid_based_where_sql('rv.subject_guid', $options['subject_guids']); $wheres[] = elgg_get_guid_based_where_sql('rv.object_guid', $options['object_guids']); $wheres[] = elgg_get_guid_based_where_sql('rv.annotation_id', $options['annotation_ids']); @@ -471,7 +514,7 @@ function elgg_river_get_action_where_sql($types) { if (!is_array($types)) { $types = sanitise_string($types); - return "'(rv.action_type = '$types')"; + return "(rv.action_type = '$types')"; } // sanitize types array @@ -485,6 +528,35 @@ function elgg_river_get_action_where_sql($types) { } /** + * Get the where clause based on river view strings + * + * @param array $types Array of view strings + * + * @return string + * @since 1.8.0 + * @access private + */ +function elgg_river_get_view_where_sql($views) { + if (!$views) { + return ''; + } + + if (!is_array($views)) { + $views = sanitise_string($views); + return "(rv.view = '$views')"; + } + + // sanitize views array + $views_sanitized = array(); + foreach ($views as $view) { + $views_sanitized[] = sanitise_string($view); + } + + $view_str = implode("','", $views_sanitized); + return "(rv.view IN ('$view_str'))"; +} + +/** * Sets the access ID on river items for a particular object * * @param int $object_guid The GUID of the entity diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php index ae42956a9..407bb69c5 100644 --- a/engine/lib/sessions.php +++ b/engine/lib/sessions.php @@ -472,7 +472,10 @@ function gatekeeper() { if (!elgg_is_logged_in()) { $_SESSION['last_forward_from'] = current_page_url(); register_error(elgg_echo('loggedinrequired')); - forward('', 'login'); + + if (!forward('', 'login')) { + throw new SecurityException(elgg_echo('SecurityException:UnexpectedOutputInGatekeeper')); + } } } @@ -487,7 +490,9 @@ function admin_gatekeeper() { if (!elgg_is_admin_logged_in()) { $_SESSION['last_forward_from'] = current_page_url(); register_error(elgg_echo('adminrequired')); - forward('', 'admin'); + if (!forward('', 'admin')) { + throw new SecurityException(elgg_echo('SecurityException:UnexpectedOutputInGatekeeper')); + } } } diff --git a/engine/lib/upgrades/2011052801.php b/engine/lib/upgrades/2011052801.php new file mode 100644 index 000000000..8084bc06c --- /dev/null +++ b/engine/lib/upgrades/2011052801.php @@ -0,0 +1,45 @@ +<?php +/** + * Make sure all users have the relationship member_of_site + */ +global $DB_QUERY_CACHE, $DB_PROFILE, $ENTITY_CACHE, $CONFIG; +$db_prefix = get_config('dbprefix'); + +$limit = 100; + +$q = "SELECT e.* FROM {$db_prefix}entities e + WHERE e.type = 'user' AND e.guid NOT IN ( + SELECT guid_one FROM {$db_prefix}entity_relationships + WHERE guid_two = 1 AND relationship = 'member_of_site' + ) + LIMIT $limit"; + +$users = get_data($q); + +while ($users) { + $DB_QUERY_CACHE = $DB_PROFILE = $ENTITY_CACHE = array(); + + // do manually to not trigger any events because these aren't new users. + foreach ($users as $user) { + $rel_q = "INSERT INTO {$db_prefix}entity_relationships VALUES ( + '', + '$user->guid', + 'member_of_site', + '$user->site_guid', + '$user->time_created' + )"; + + insert_data($rel_q); + } + + // every time we run this query we've just reduced the rows it returns by $limit + // so don't pass an offset. + $q = "SELECT e.* FROM {$db_prefix}entities e + WHERE e.type = 'user' AND e.guid NOT IN ( + SELECT guid_one FROM {$db_prefix}entity_relationships + WHERE guid_two = 1 AND relationship = 'member_of_site' + ) + LIMIT $limit"; + + $users = get_data($q); +}
\ No newline at end of file diff --git a/engine/lib/upgrades/2011061200-1.8b1-sites_need_a_site_guid-6d9dcbf46c0826cc.php b/engine/lib/upgrades/2011061200-1.8b1-sites_need_a_site_guid-6d9dcbf46c0826cc.php new file mode 100644 index 000000000..4fc59ac41 --- /dev/null +++ b/engine/lib/upgrades/2011061200-1.8b1-sites_need_a_site_guid-6d9dcbf46c0826cc.php @@ -0,0 +1,30 @@ +<?php +/** + * Elgg 1.8b1 upgrade 2011061200 + * sites_need_a_site_guid + * + * Sites did not have a site guid. This causes problems with getting + * metadata on site objects since we default to the current site. + */ + +global $CONFIG; + +$ia = elgg_set_ignore_access(true); +$access_status = access_get_show_hidden_status(); +access_show_hidden_entities(true); + +$options = array( + 'type' => 'site', + 'site_guid' => 0, +); +$batch = new ElggBatch('elgg_get_entities', $options); + +foreach ($batch as $entity) { + if (!$entity->site_guid) { + update_data("UPDATE {$CONFIG->dbprefix}entities SET site_guid=$entity->guid + WHERE guid=$entity->guid"); + } +} + +access_show_hidden_entities($access_status); +elgg_set_ignore_access($ia); diff --git a/engine/lib/users.php b/engine/lib/users.php index dcec36ba5..59bfa1259 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -748,40 +748,6 @@ function execute_new_password_request($user_guid, $conf_code) { } /** - * Handles pages for password reset requests. - * - * @param array $page Pages array - * - * @return void - */ -function elgg_user_resetpassword_page_handler($page) { - - $user_guid = get_input('u'); - $code = get_input('c'); - - $user = get_entity($user_guid); - - // don't check code here to avoid automated attacks - if (!$user instanceof ElggUser) { - register_error(elgg_echo('user:passwordreset:unknown_user')); - forward(); - } - - $params = array( - 'guid' => $user_guid, - 'code' => $code, - ); - $form = elgg_view_form('user/passwordreset', array(), $params); - - $title = elgg_echo('resetpassword'); - $content = elgg_view_title(elgg_echo('resetpassword')) . $form; - - $body = elgg_view_layout('one_column', array('content' => $content)); - - echo elgg_view_page($title, $body); -} - -/** * Simple function that will generate a random clear text password * suitable for feeding into generate_user_password(). * @@ -1074,7 +1040,7 @@ function collections_submenu_items() { */ function friends_page_handler($page_elements) { if (isset($page_elements[0]) && $user = get_user_by_username($page_elements[0])) { - set_page_owner($user->getGUID()); + elgg_set_page_owner_guid($user->getGUID()); } if (elgg_get_logged_in_user_guid() == elgg_get_page_owner_guid()) { collections_submenu_items(); @@ -1129,26 +1095,27 @@ function collections_page_handler($page_elements) { } /** - * Page handler for dashboard + * Page handler for account related pages * - * @param array $page_elements Page elements + * @param array $page_elements Page elements + * @param string $handler The handler string * * @return void */ -function dashboard_page_handler($page_elements) { - require_once(dirname(dirname(dirname(__FILE__))) . "/pages/dashboard.php"); -} - - -/** - * Page handler for registration - * - * @param array $page_elements Page elements - * - * @return void - */ -function registration_page_handler($page_elements) { - require_once(dirname(dirname(dirname(__FILE__))) . "/pages/account/register.php"); +function elgg_user_account_page_handler($page_elements, $handler) { + + $base_dir = elgg_get_root_path() . 'pages/account'; + switch ($handler) { + case 'forgotpassword': + require_once("$base_dir/forgotten_password.php"); + break; + case 'resetpassword': + require_once("$base_dir/reset_password.php"); + break; + case 'register': + require_once("$base_dir/register.php"); + break; + } } /** @@ -1309,6 +1276,41 @@ function elgg_user_hover_menu($hook, $type, $return, $params) { return $return; } +function elgg_users_setup_entity_menu($hook, $type, $return, $params) { + if (elgg_in_context('widgets')) { + return $return; + } + + $entity = $params['entity']; + if (!elgg_instanceof($entity, 'user')) { + return $return; + } + + if ($entity->isBanned()) { + $banned = elgg_echo('banned'); + $options = array( + 'name' => 'banned', + 'text' => "<span>$banned</span>", + 'href' => false, + 'priority' => 0, + ); + $return = array(ElggMenuItem::factory($options)); + } else { + $return = array(); + if (isset($entity->location)) { + $options = array( + 'name' => 'location', + 'text' => "<span>$entity->location</span>", + 'href' => false, + 'priority' => 150, + ); + $return[] = ElggMenuItem::factory($options); + } + } + + return $return; +} + /** * This function loads a set of default fields into the profile, then triggers a hook letting other plugins to edit * add and delete fields. @@ -1322,7 +1324,7 @@ function elgg_profile_fields_setup() { $profile_defaults = array ( 'description' => 'longtext', 'briefdescription' => 'text', - 'location' => 'tags', + 'location' => 'location', 'interests' => 'tags', 'skills' => 'tags', 'contactemail' => 'email', @@ -1356,7 +1358,7 @@ function elgg_profile_fields_setup() { // register any tag metadata names foreach ($CONFIG->profile_fields as $name => $type) { - if ($type == 'tags') { + if ($type == 'tags' || $type == 'location' || $type == 'tag') { elgg_register_tag_metadata_name($name); // register a tag name translation add_translation(get_current_language(), array("tag_names:$name" => elgg_echo("profile:$name"))); @@ -1451,6 +1453,7 @@ function users_pagesetup() { 'href' => $user->getURL(), 'text' => "<img src=\"$icon_url\" alt=\"$user->name\" title=\"$title\" class=\"$class\" />", 'priority' => 100, + 'link_class' => 'elgg-topbar-avatar', )); elgg_register_menu_item('topbar', array( @@ -1490,9 +1493,9 @@ function users_init() { elgg_register_page_handler('friends', 'friends_page_handler'); elgg_register_page_handler('friendsof', 'friends_of_page_handler'); - elgg_register_page_handler('dashboard', 'dashboard_page_handler'); - elgg_register_page_handler('register', 'registration_page_handler'); - elgg_register_page_handler('resetpassword', 'elgg_user_resetpassword_page_handler'); + elgg_register_page_handler('register', 'elgg_user_account_page_handler'); + elgg_register_page_handler('forgotpassword', 'elgg_user_account_page_handler'); + elgg_register_page_handler('resetpassword', 'elgg_user_account_page_handler'); elgg_register_page_handler('login', 'elgg_user_login_page_handler'); elgg_register_page_handler('avatar', 'elgg_avatar_page_handler'); elgg_register_page_handler('profile', 'elgg_profile_page_handler'); @@ -1529,6 +1532,8 @@ function users_init() { // Register the user type elgg_register_entity_type('user', ''); + elgg_register_plugin_hook_handler('register', 'menu:entity', 'elgg_users_setup_entity_menu', 501); + elgg_register_event_handler('create', 'user', 'user_create_hook_add_site_relationship'); } |