diff options
-rw-r--r-- | engine/classes/ElggPlugin.php | 7 | ||||
-rw-r--r-- | engine/lib/admin.php | 5 | ||||
-rw-r--r-- | engine/lib/configuration.php | 26 | ||||
-rw-r--r-- | engine/lib/entities.php | 202 | ||||
-rw-r--r-- | engine/lib/plugins.php | 21 | ||||
-rw-r--r-- | js/lib/ui.js | 2 | ||||
-rw-r--r-- | js/tests/ElggLibTest.js | 2 | ||||
-rw-r--r-- | languages/en.php | 2 | ||||
-rw-r--r-- | views/default/admin/users/admins.php | 12 | ||||
-rw-r--r-- | views/default/js/admin.php | 11 | ||||
-rw-r--r-- | views/default/js/elgg.php | 1 | ||||
-rw-r--r-- | views/default/js/initialize_elgg.php | 1 | ||||
-rw-r--r-- | views/default/js/lightbox.php | 1 | ||||
-rw-r--r-- | views/default/js/walled_garden.php | 5 |
14 files changed, 194 insertions, 104 deletions
diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php index 3e43c8e81..c6ce2905f 100644 --- a/engine/classes/ElggPlugin.php +++ b/engine/classes/ElggPlugin.php @@ -36,8 +36,9 @@ class ElggPlugin extends ElggObject { * @warning Unlike other ElggEntity objects, you cannot null instantiate * ElggPlugin. You must point it to an actual plugin GUID or location. * - * @param mixed $plugin The GUID of the ElggPlugin object or the path of - * the plugin to load. + * @param mixed $plugin The GUID of the ElggPlugin object or the path of the plugin to load. + * + * @throws PluginException */ public function __construct($plugin) { if (!$plugin) { @@ -76,6 +77,8 @@ class ElggPlugin extends ElggObject { // load the rest of the plugin parent::__construct($existing_guid); } + + _elgg_cache_plugin_by_id($this); } /** diff --git a/engine/lib/admin.php b/engine/lib/admin.php index b65d98c95..3f23f079c 100644 --- a/engine/lib/admin.php +++ b/engine/lib/admin.php @@ -268,8 +268,9 @@ function admin_init() { // users elgg_register_admin_menu_item('administer', 'users', null, 20); elgg_register_admin_menu_item('administer', 'online', 'users', 10); - elgg_register_admin_menu_item('administer', 'newest', 'users', 20); - elgg_register_admin_menu_item('administer', 'add', 'users', 30); + elgg_register_admin_menu_item('administer', 'admins', 'users', 20); + elgg_register_admin_menu_item('administer', 'newest', 'users', 30); + elgg_register_admin_menu_item('administer', 'add', 'users', 40); // configure // plugins diff --git a/engine/lib/configuration.php b/engine/lib/configuration.php index 305aa00b6..b10e51130 100644 --- a/engine/lib/configuration.php +++ b/engine/lib/configuration.php @@ -91,23 +91,29 @@ function elgg_get_config($name, $site_guid = 0) { return $CONFIG->$name; } - if ($site_guid === NULL) { + if ($site_guid === null) { // installation wide setting $value = datalist_get($name); } else { - // site specific setting - if ($site_guid == 0) { - $site_guid = (int) $CONFIG->site_id; + // hit DB only if we're not sure if value exists or not + if (!isset($CONFIG->site_config_loaded)) { + // site specific setting + if ($site_guid == 0) { + $site_guid = (int) $CONFIG->site_id; + } + $value = get_config($name, $site_guid); + } else { + $value = null; } - $value = get_config($name, $site_guid); } - if ($value !== false) { - $CONFIG->$name = $value; - return $value; + // @todo document why we don't cache false + if ($value === false) { + return null; } - return null; + $CONFIG->$name = $value; + return $value; } /** @@ -558,6 +564,8 @@ function _elgg_load_site_config() { $CONFIG->url = $CONFIG->wwwroot; get_all_config(); + // gives hint to elgg_get_config function how to approach missing values + $CONFIG->site_config_loaded = true; } /** diff --git a/engine/lib/entities.php b/engine/lib/entities.php index a14160e14..e9c96a596 100644 --- a/engine/lib/entities.php +++ b/engine/lib/entities.php @@ -17,13 +17,13 @@ global $ENTITY_CACHE; $ENTITY_CACHE = array(); /** - * Cache subtypes and related class names once loaded. + * Cache subtypes and related class names. * - * @global array $SUBTYPE_CACHE + * @global array|null $SUBTYPE_CACHE array once populated from DB, initially null * @access private */ global $SUBTYPE_CACHE; -$SUBTYPE_CACHE = NULL; +$SUBTYPE_CACHE = null; /** * Invalidate this class's entry in the cache. @@ -68,7 +68,15 @@ function cache_entity(ElggEntity $entity) { // Don't store too many or we'll have memory problems // TODO(evan): Pick a less arbitrary limit if (count($ENTITY_CACHE) > 256) { - unset($ENTITY_CACHE[array_rand($ENTITY_CACHE)]); + $random_guid = array_rand($ENTITY_CACHE); + + unset($ENTITY_CACHE[$random_guid]); + + // Purge separate metadata cache. Original idea was to do in entity destructor, but that would + // have caused a bunch of unnecessary purges at every shutdown. Doing it this way we have no way + // to know that the expunged entity will be GCed (might be another reference living), but that's + // OK; the metadata will reload if necessary. + elgg_get_metadata_cache()->clear($random_guid); } $ENTITY_CACHE[$entity->guid] = $entity; @@ -87,8 +95,6 @@ function cache_entity(ElggEntity $entity) { function retrieve_cached_entity($guid) { global $ENTITY_CACHE; - $guid = (int)$guid; - if (isset($ENTITY_CACHE[$guid])) { if ($ENTITY_CACHE[$guid]->isFullyLoaded()) { return $ENTITY_CACHE[$guid]; @@ -148,29 +154,23 @@ function retrieve_cached_entity_row($guid) { * @access private */ function get_subtype_id($type, $subtype) { - global $CONFIG, $SUBTYPE_CACHE; + global $SUBTYPE_CACHE; - $type = sanitise_string($type); - $subtype = sanitise_string($subtype); - - if ($subtype == "") { - return FALSE; + if (!$subtype) { + return false; } - // @todo use the cache before hitting database - $result = get_data_row("SELECT * from {$CONFIG->dbprefix}entity_subtypes - where type='$type' and subtype='$subtype'"); - - if ($result) { - if (!$SUBTYPE_CACHE) { - $SUBTYPE_CACHE = array(); - } + if ($SUBTYPE_CACHE === null) { + _elgg_populate_subtype_cache(); + } - $SUBTYPE_CACHE[$result->id] = $result; + // use the cache before hitting database + $result = _elgg_retrieve_cached_subtype($type, $subtype); + if ($result !== null) { return $result->id; } - return FALSE; + return false; } /** @@ -178,35 +178,67 @@ function get_subtype_id($type, $subtype) { * * @param int $subtype_id Subtype ID * - * @return string Subtype name + * @return string|false Subtype name, false if subtype not found * @link http://docs.elgg.org/DataModel/Entities/Subtypes * @see get_subtype_from_id() * @access private */ function get_subtype_from_id($subtype_id) { - global $CONFIG, $SUBTYPE_CACHE; - - $subtype_id = (int)$subtype_id; + global $SUBTYPE_CACHE; if (!$subtype_id) { return false; } + if ($SUBTYPE_CACHE === null) { + _elgg_populate_subtype_cache(); + } + if (isset($SUBTYPE_CACHE[$subtype_id])) { return $SUBTYPE_CACHE[$subtype_id]->subtype; } - $result = get_data_row("SELECT * from {$CONFIG->dbprefix}entity_subtypes where id=$subtype_id"); - if ($result) { - if (!$SUBTYPE_CACHE) { - $SUBTYPE_CACHE = array(); - } + return false; +} + +/** + * Retrieve subtype from the cache. + * + * @param string $type + * @param string $subtype + * @return stdClass|null + * + * @access private + */ +function _elgg_retrieve_cached_subtype($type, $subtype) { + global $SUBTYPE_CACHE; - $SUBTYPE_CACHE[$subtype_id] = $result; - return $result->subtype; + if ($SUBTYPE_CACHE === null) { + _elgg_populate_subtype_cache(); } - return false; + foreach ($SUBTYPE_CACHE as $obj) { + if ($obj->type === $type && $obj->subtype === $subtype) { + return $obj; + } + } + return null; +} + +/** + * Fetch all suptypes from DB to local cache. + * + * @access private + */ +function _elgg_populate_subtype_cache() { + global $CONFIG, $SUBTYPE_CACHE; + + $results = get_data("SELECT * FROM {$CONFIG->dbprefix}entity_subtypes"); + + $SUBTYPE_CACHE = array(); + foreach ($results as $row) { + $SUBTYPE_CACHE[$row->id] = $row; + } } /** @@ -225,25 +257,19 @@ function get_subtype_from_id($subtype_id) { * @access private */ function get_subtype_class($type, $subtype) { - global $CONFIG, $SUBTYPE_CACHE; - - $type = sanitise_string($type); - $subtype = sanitise_string($subtype); - - // @todo use the cache before going to the database - $result = get_data_row("SELECT * from {$CONFIG->dbprefix}entity_subtypes - where type='$type' and subtype='$subtype'"); + global $SUBTYPE_CACHE; - if ($result) { - if (!$SUBTYPE_CACHE) { - $SUBTYPE_CACHE = array(); - } - - $SUBTYPE_CACHE[$result->id] = $result; - return $result->class; + if ($SUBTYPE_CACHE === null) { + _elgg_populate_subtype_cache(); + } + + // use the cache before going to the database + $obj = _elgg_retrieve_cached_subtype($type, $subtype); + if ($obj) { + return $obj->class; } - return NULL; + return null; } /** @@ -257,29 +283,21 @@ function get_subtype_class($type, $subtype) { * @access private */ function get_subtype_class_from_id($subtype_id) { - global $CONFIG, $SUBTYPE_CACHE; - - $subtype_id = (int)$subtype_id; + global $SUBTYPE_CACHE; if (!$subtype_id) { - return false; + return null; } + if ($SUBTYPE_CACHE === null) { + _elgg_populate_subtype_cache(); + } + if (isset($SUBTYPE_CACHE[$subtype_id])) { return $SUBTYPE_CACHE[$subtype_id]->class; } - $result = get_data_row("SELECT * from {$CONFIG->dbprefix}entity_subtypes where id=$subtype_id"); - - if ($result) { - if (!$SUBTYPE_CACHE) { - $SUBTYPE_CACHE = array(); - } - $SUBTYPE_CACHE[$subtype_id] = $result; - return $result->class; - } - - return NULL; + return null; } /** @@ -305,21 +323,32 @@ function get_subtype_class_from_id($subtype_id) { * @see get_entity() */ function add_subtype($type, $subtype, $class = "") { - global $CONFIG; - $type = sanitise_string($type); - $subtype = sanitise_string($subtype); - $class = sanitise_string($class); + global $CONFIG, $SUBTYPE_CACHE; - // Short circuit if no subtype is given - if ($subtype == "") { + if (!$subtype) { return 0; } $id = get_subtype_id($type, $subtype); - if ($id == 0) { - return insert_data("insert into {$CONFIG->dbprefix}entity_subtypes" - . " (type, subtype, class) values ('$type','$subtype','$class')"); + if (!$id) { + // In cache we store non-SQL-escaped strings because that's what's returned by query + $cache_obj = (object) array( + 'type' => $type, + 'subtype' => $subtype, + 'class' => $class, + ); + + $type = sanitise_string($type); + $subtype = sanitise_string($subtype); + $class = sanitise_string($class); + + $id = insert_data("INSERT INTO {$CONFIG->dbprefix}entity_subtypes" + . " (type, subtype, class) VALUES ('$type', '$subtype', '$class')"); + + // add entry to cache + $cache_obj->id = $id; + $SUBTYPE_CACHE[$id] = $cache_obj; } return $id; @@ -361,22 +390,31 @@ function remove_subtype($type, $subtype) { function update_subtype($type, $subtype, $class = '') { global $CONFIG, $SUBTYPE_CACHE; - if (!$id = get_subtype_id($type, $subtype)) { - return FALSE; + $id = get_subtype_id($type, $subtype); + if (!$id) { + return false; } + + if ($SUBTYPE_CACHE === null) { + _elgg_populate_subtype_cache(); + } + + $unescaped_class = $class; + $type = sanitise_string($type); $subtype = sanitise_string($subtype); - - $result = update_data("UPDATE {$CONFIG->dbprefix}entity_subtypes + $class = sanitise_string($class); + + $success = update_data("UPDATE {$CONFIG->dbprefix}entity_subtypes SET type = '$type', subtype = '$subtype', class = '$class' WHERE id = $id "); - if ($result && isset($SUBTYPE_CACHE[$id])) { - $SUBTYPE_CACHE[$id]->class = $class; + if ($success && isset($SUBTYPE_CACHE[$id])) { + $SUBTYPE_CACHE[$id]->class = $unescaped_class; } - return $result; + return $success; } /** @@ -1772,7 +1810,7 @@ function oddentity_to_elggentity(ODDEntity $element) { if (!$tmp) { // Construct new class with owner from session $classname = get_subtype_class($class, $subclass); - if ($classname != "") { + if ($classname) { if (class_exists($classname)) { $tmp = new $classname(); diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index d5cd4fe76..ca4a957f4 100644 --- a/engine/lib/plugins.php +++ b/engine/lib/plugins.php @@ -176,6 +176,19 @@ function elgg_generate_plugin_entities() { } /** + * Cache a reference to this plugin by its ID + * + * @param ElggPlugin $plugin + * + * @access private + */ +function _elgg_cache_plugin_by_id(ElggPlugin $plugin) { + $map = (array) elgg_get_config('plugins_by_id_map'); + $map[$plugin->getID()] = $plugin; + elgg_set_config('plugins_by_id_map', $map); +} + +/** * Returns an ElggPlugin object with the path $path. * * @param string $plugin_id The id (dir name) of the plugin. NOT the guid. @@ -183,6 +196,11 @@ function elgg_generate_plugin_entities() { * @since 1.8.0 */ function elgg_get_plugin_from_id($plugin_id) { + $map = (array) elgg_get_config('plugins_by_id_map'); + if (isset($map[$plugin_id])) { + return $map[$plugin_id]; + } + $plugin_id = sanitize_string($plugin_id); $db_prefix = get_config('dbprefix'); @@ -512,6 +530,8 @@ function elgg_namespace_plugin_private_setting($type, $name, $id = null) { * @return string|false Plugin name, or false if no plugin name was called * @since 1.8.0 * @access private + * + * @todo get rid of this */ function elgg_get_calling_plugin_id($mainfilename = false) { if (!$mainfilename) { @@ -920,6 +940,7 @@ function elgg_set_plugin_setting($name, $value, $plugin_id = null) { * * @return mixed * @since 1.8.0 + * @todo make $plugin_id required in future version */ function elgg_get_plugin_setting($name, $plugin_id = null) { if ($plugin_id) { diff --git a/js/lib/ui.js b/js/lib/ui.js index 616e71d54..2a4d269d6 100644 --- a/js/lib/ui.js +++ b/js/lib/ui.js @@ -283,7 +283,7 @@ elgg.ui.initDatePicker = function() { dataType: "script", cache: true, success: loadDatePicker, - error: loadDatePicker, // english language is already loaded. + error: loadDatePicker // english language is already loaded. }); } }; diff --git a/js/tests/ElggLibTest.js b/js/tests/ElggLibTest.js index a29ebf743..2a676e22a 100644 --- a/js/tests/ElggLibTest.js +++ b/js/tests/ElggLibTest.js @@ -99,7 +99,7 @@ ElggLibTest.prototype.testNormalizeUrl = function() { ['/mod/plugin/file.php', elgg.config.wwwroot + 'mod/plugin/file.php'], ['/mod/plugin/file.php?p=v&p2=v2', elgg.config.wwwroot + 'mod/plugin/file.php?p=v&p2=v2'], ['/rootfile.php', elgg.config.wwwroot + 'rootfile.php'], - ['/rootfile.php?p=v&p2=v2', elgg.config.wwwroot + 'rootfile.php?p=v&p2=v2'], + ['/rootfile.php?p=v&p2=v2', elgg.config.wwwroot + 'rootfile.php?p=v&p2=v2'] ].forEach(function(args) { assertEquals(args[1], elgg.normalize_url(args[0])); diff --git a/languages/en.php b/languages/en.php index 62b35dd81..2b5ba00fd 100644 --- a/languages/en.php +++ b/languages/en.php @@ -582,6 +582,7 @@ $english = array( 'admin:users' => "Users", 'admin:users:online' => 'Currently Online', 'admin:users:newest' => 'Newest', + 'admin:users:admins' => 'Administrators', 'admin:users:add' => 'Add New User', 'admin:users:description' => "This admin panel allows you to control user settings for your site. Choose an option below to get started.", 'admin:users:adduser:label' => "Click here to add a new user...", @@ -733,6 +734,7 @@ $english = array( 'admin:statistics:label:numusers' => "Number of users", 'admin:statistics:label:numonline' => "Number of users online", 'admin:statistics:label:onlineusers' => "Users online now", + 'admin:statistics:label:admins'=>"Admins", 'admin:statistics:label:version' => "Elgg version", 'admin:statistics:label:version:release' => "Release", 'admin:statistics:label:version:version' => "Version", diff --git a/views/default/admin/users/admins.php b/views/default/admin/users/admins.php new file mode 100644 index 000000000..9b175d437 --- /dev/null +++ b/views/default/admin/users/admins.php @@ -0,0 +1,12 @@ +<?php +$admins = elgg_list_entities(array(), 'elgg_get_admins'); + +?> +<div class="elgg-module elgg-module-inline"> + <div class="elgg-head"> + <h3><?php echo elgg_echo('admin:statistics:label:admins'); ?></h3> + </div> + <div class="elgg-body"> + <?php echo $admins; ?> + </div> +</div> diff --git a/views/default/js/admin.php b/views/default/js/admin.php index 5cefba512..e8aa0d2ed 100644 --- a/views/default/js/admin.php +++ b/views/default/js/admin.php @@ -4,8 +4,9 @@ * * @since 1.8 */ + +if (0) { ?><script><?php } ?> -//<script> elgg.provide('elgg.admin'); elgg.admin.init = function () { @@ -47,7 +48,7 @@ elgg.admin.init = function () { // admin notices delete ajax $('a.elgg-admin-notice').click(elgg.admin.deleteNotice); -} +}; /** * Save the plugin order after a move event. @@ -88,7 +89,7 @@ elgg.admin.editProfileField = function(value, settings) { elgg.action('profile/fields/edit', data); return value; -} +}; /** * Save the plugin profile order after a move event. @@ -104,7 +105,7 @@ elgg.admin.moveProfileField = function(e, ui) { elgg.action('profile/fields/reorder', { fieldorder: orderStr }); -} +}; /** * Fires the ajax action to delete the admin notice then hides the notice. @@ -120,6 +121,6 @@ elgg.admin.deleteNotice = function(e) { $container.slideUp('medium'); } }); -} +}; elgg.register_hook_handler('init', 'system', elgg.admin.init, 1000);
\ No newline at end of file diff --git a/views/default/js/elgg.php b/views/default/js/elgg.php index 6460e93d6..b82d98ce4 100644 --- a/views/default/js/elgg.php +++ b/views/default/js/elgg.php @@ -50,6 +50,7 @@ foreach ($libs as $file) { /** * Set some values that are cacheable */ +if (0) { ?><script><?php } ?> elgg.version = '<?php echo get_version(); ?>'; diff --git a/views/default/js/initialize_elgg.php b/views/default/js/initialize_elgg.php index f8234f84f..b45c33463 100644 --- a/views/default/js/initialize_elgg.php +++ b/views/default/js/initialize_elgg.php @@ -3,6 +3,7 @@ * Initialize Elgg's js lib with the uncacheable data */ +if (0) { ?><script><?php } ?> /** * Don't want to cache these -- they could change for every request diff --git a/views/default/js/lightbox.php b/views/default/js/lightbox.php index c45d46098..d2bceaf90 100644 --- a/views/default/js/lightbox.php +++ b/views/default/js/lightbox.php @@ -16,6 +16,7 @@ * @todo add support for passing options: $('#myplugin-lightbox').elgg.ui.lightbox(options); */ +if (0) { ?><script><?php } ?> /** diff --git a/views/default/js/walled_garden.php b/views/default/js/walled_garden.php index 13ec83c04..7a482fe23 100644 --- a/views/default/js/walled_garden.php +++ b/views/default/js/walled_garden.php @@ -12,6 +12,7 @@ $cancel_button = elgg_view('input/button', array( )); $cancel_button = trim($cancel_button); +if (0) { ?><script><?php } ?> elgg.provide('elgg.walled_garden'); @@ -47,10 +48,10 @@ elgg.walled_garden.load = function(view) { $(id).find('input.elgg-button-submit').after('<?php echo $cancel_button; ?>'); $('#elgg-walledgarden-login').fadeToggle(); $(id).fadeToggle(); - }, + } }); event.preventDefault(); - }; + }; }; elgg.register_hook_handler('init', 'system', elgg.walled_garden.init);
\ No newline at end of file |