diff options
Diffstat (limited to 'engine/lib/widgets.php')
| -rw-r--r-- | engine/lib/widgets.php | 690 |
1 files changed, 302 insertions, 388 deletions
diff --git a/engine/lib/widgets.php b/engine/lib/widgets.php index a450d6223..699462a1b 100644 --- a/engine/lib/widgets.php +++ b/engine/lib/widgets.php @@ -3,504 +3,418 @@ * Elgg widgets library. * Contains code for handling widgets. * - * @package Elgg - * @subpackage Core - * @link http://elgg.org/ + * @package Elgg.Core + * @subpackage Widgets */ /** - * Override ElggObject in order to store widget data in ultra-private stores. + * Get widgets for a particular context + * + * The widgets are ordered for display and grouped in columns. + * $widgets = elgg_get_widgets(elgg_get_logged_in_user_guid(), 'dashboard'); + * $first_column_widgets = $widgets[1]; + * + * @param int $user_guid The owner user GUID + * @param string $context The context (profile, dashboard, etc) + * + * @return array An 2D array of ElggWidget objects + * @since 1.8.0 */ -class ElggWidget extends ElggObject { - protected function initialise_attributes() { - parent::initialise_attributes(); - - $this->attributes['subtype'] = "widget"; - } - - public function __construct($guid = null) { - parent::__construct($guid); +function elgg_get_widgets($user_guid, $context) { + $options = array( + 'type' => 'object', + 'subtype' => 'widget', + 'owner_guid' => $user_guid, + 'private_setting_name' => 'context', + 'private_setting_value' => $context, + 'limit' => 0 + ); + $widgets = elgg_get_entities_from_private_settings($options); + if (!$widgets) { + return array(); } - /** - * Override entity get and sets in order to save data to private data store. - */ - public function get($name) { - // See if its in our base attribute - if (isset($this->attributes[$name])) { - return $this->attributes[$name]; - } - - // No, so see if its in the private data store. - $meta = get_private_setting($this->guid, $name); - if ($meta) { - return $meta; + $sorted_widgets = array(); + foreach ($widgets as $widget) { + if (!isset($sorted_widgets[(int)$widget->column])) { + $sorted_widgets[(int)$widget->column] = array(); } - - // Can't find it, so return null - return null; + $sorted_widgets[(int)$widget->column][$widget->order] = $widget; } - /** - * Override entity get and sets in order to save data to private data store. - */ - public function set($name, $value) { - if (array_key_exists($name, $this->attributes)) { - // Check that we're not trying to change the guid! - if ((array_key_exists('guid', $this->attributes)) && ($name=='guid')) { - return false; - } - - $this->attributes[$name] = $value; - } else { - return set_private_setting($this->guid, $name, $value); - } - - return true; + foreach ($sorted_widgets as $col => $widgets) { + ksort($sorted_widgets[$col]); } + + return $sorted_widgets; } /** - * Register a particular context for use with widgets. + * Create a new widget instance + * + * @param int $owner_guid GUID of entity that owns this widget + * @param string $handler The handler for this widget + * @param string $context The context for this widget + * @param int $access_id If not specified, it is set to the default access level * - * @param string $context The context we wish to enable context for + * @return int|false Widget GUID or false on failure + * @since 1.8.0 */ -function use_widgets($context) { - global $CONFIG; +function elgg_create_widget($owner_guid, $handler, $context, $access_id = null) { + if (empty($owner_guid) || empty($handler) || !elgg_is_widget_type($handler)) { + return false; + } - if (!isset($CONFIG->widgets)) { - $CONFIG->widgets = new stdClass; + $owner = get_entity($owner_guid); + if (!$owner) { + return false; } - if (!isset($CONFIG->widgets->contexts)) { - $CONFIG->widgets->contexts = array(); + $widget = new ElggWidget; + $widget->owner_guid = $owner_guid; + $widget->container_guid = $owner_guid; // @todo - will this work for group widgets + if (isset($access_id)) { + $widget->access_id = $access_id; + } else { + $widget->access_id = get_default_access(); } - if (!empty($context)) { - $CONFIG->widgets->contexts[] = $context; + if (!$widget->save()) { + return false; } + + // private settings cannot be set until ElggWidget saved + $widget->handler = $handler; + $widget->context = $context; + + return $widget->getGUID(); } /** - * Determines whether or not the current context is using widgets + * Can the user edit the widget layout * - * @return true|false Depending on widget status + * Triggers a 'permissions_check', 'widget_layout' plugin hook + * + * @param string $context The widget context + * @param int $user_guid The GUID of the user (0 for logged in user) + * + * @return bool + * @since 1.8.0 */ -function using_widgets() { - global $CONFIG; +function elgg_can_edit_widget_layout($context, $user_guid = 0) { - $context = get_context(); - if (isset($CONFIG->widgets->contexts) && is_array($CONFIG->widgets->contexts)) { - if (in_array($context, $CONFIG->widgets->contexts)) return true; + $user = get_entity((int)$user_guid); + if (!$user) { + $user = elgg_get_logged_in_user_entity(); } - return false; + $return = false; + if (elgg_is_admin_logged_in()) { + $return = true; + } + if (elgg_get_page_owner_guid() == $user->guid) { + $return = true; + } + + $params = array( + 'user' => $user, + 'context' => $context, + 'page_owner' => elgg_get_page_owner_entity() + ); + return elgg_trigger_plugin_hook('permissions_check', 'widget_layout', $params, $return); } /** - * When given a widget entity and a new requested location, saves the new location - * and also provides a sensible ordering for all widgets in that column + * Regsiter a widget type + * + * This should be called by plugins in their init function. * - * @param ElggObject $widget The widget entity - * @param int $order The order within the column - * @param int $column The column (1, 2 or 3) - * @return true|false Depending on success + * @param string $handler The identifier for the widget handler + * @param string $name The name of the widget type + * @param string $description A description for the widget type + * @param string $context A comma-separated list of contexts where this + * widget is allowed (default: 'all') + * @param bool $multiple Whether or not multiple instances of this widget + * are allowed in a single layout (default: false) + * + * @return bool + * @since 1.8.0 */ -function save_widget_location(ElggObject $widget, $order, $column) { - if ($widget instanceof ElggObject) { - if ($widget->subtype == "widget") { - // If you can't move the widget, don't save a new location - if (!$widget->draggable) { - return false; - } - - // Sanitise the column value - if ($column != 1 || $column != 2 || $column != 3) { - $column = 1; - } +function elgg_register_widget_type($handler, $name, $description, $context = "all", $multiple = false) { - $widget->column = (int) $column; - - $ordertmp = array(); - $params = array( - 'context' => $widget->context, - 'column' => $column, - ); - - if ($entities = get_entities_from_metadata_multi($params,'object','widget')) { - foreach($entities as $entity) { - $entityorder = $entity->order; - if ($entityorder < $order) { - $ordertmp[$entityorder] = $entity; - } - if ($entityorder >= $order) { - $ordertmp[$entityorder + 10000] = $entity; - } - } - } + if (!$handler || !$name) { + return false; + } - $ordertmp[$order] = $widget; - ksort($ordertmp); + global $CONFIG; - $orderticker = 10; - foreach($ordertmp as $orderval => $entity) { - $entity->order = $orderticker; - $orderticker += 10; - } + if (!isset($CONFIG->widgets)) { + $CONFIG->widgets = new stdClass; + } + if (!isset($CONFIG->widgets->handlers)) { + $CONFIG->widgets->handlers = array(); + } - return true; - } else { - register_error($widget->subtype); - } + $handlerobj = new stdClass; + $handlerobj->name = $name; + $handlerobj->description = $description; + $handlerobj->context = explode(",", $context); + $handlerobj->multiple = $multiple; - } + $CONFIG->widgets->handlers[$handler] = $handlerobj; - return false; + return true; } /** - * Get widgets for a particular context and column, in order of display + * Remove a widget type + * + * @param string $handler The identifier for the widget * - * @param int $user_guid The owner user GUID - * @param string $context The context (profile, dashboard etc) - * @param int $column The column (1 or 2) - * @return array|false An array of widget ElggObjects, or false + * @return void + * @since 1.8.0 */ -function get_widgets($user_guid, $context, $column) { - $params = array( - 'column' => $column, - 'context' => $context - ); - $widgets = get_entities_from_private_setting_multi($params, "object", "widget", $user_guid, "", 10000); - if ($widgets) { - $widgetorder = array(); - foreach($widgets as $widget) { - $order = $widget->order; - while(isset($widgetorder[$order])) { - $order++; - } - $widgetorder[$order] = $widget; - } +function elgg_unregister_widget_type($handler) { + global $CONFIG; - ksort($widgetorder); + if (!isset($CONFIG->widgets)) { + return; + } - return $widgetorder; + if (!isset($CONFIG->widgets->handlers)) { + return; } - return false; + if (isset($CONFIG->widgets->handlers[$handler])) { + unset($CONFIG->widgets->handlers[$handler]); + } } /** - * Displays a particular widget + * Has a widget type with the specified handler been registered * - * @param ElggObject $widget The widget to display - * @return string The HTML for the widget, including JavaScript wrapper - */ -function display_widget(ElggObject $widget) { - return elgg_view_entity($widget); -} - -/** - * Add a new widget + * @param string $handler The widget handler identifying string * - * @param int $user_guid User GUID to associate this widget with - * @param string $handler The handler for this widget - * @param string $context The page context for this widget - * @param int $order The order to display this widget in - * @param int $column The column to display this widget in (1, 2 or 3) - * @param int $access_id If not specified, it is set to the default access level - * @return true|false Depending on success + * @return bool Whether or not that widget type exists + * @since 1.8.0 */ -function add_widget($user_guid, $handler, $context, $order = 0, $column = 1, $access_id = null) { - if (empty($user_guid) || empty($context) || empty($handler) || !widget_type_exists($handler)) { - return false; - } - - if ($user = get_user($user_guid)) { - $widget = new ElggWidget; - $widget->owner_guid = $user_guid; - $widget->container_guid = $user_guid; - if (isset($access_id)) { - $widget->access_id = $access_id; - } else { - $widget->access_id = get_default_access(); - } - - if (!$widget->save()) { - return false; - } +function elgg_is_widget_type($handler) { + global $CONFIG; - $widget->handler = $handler; - $widget->context = $context; - $widget->column = $column; - $widget->order = $order; + if (!empty($CONFIG->widgets) && + !empty($CONFIG->widgets->handlers) && + is_array($CONFIG->widgets->handlers) && + array_key_exists($handler, $CONFIG->widgets->handlers)) { - // save_widget_location($widget, $order, $column); return true; - } return false; } /** - * Define a new widget type + * Get the widget types for a context * - * @param string $handler The identifier for the widget handler - * @param string $name The name of the widget type - * @param string $description A description for the widget type - * @param string $context A comma-separated list of contexts where this widget is allowed (default: 'all') - * @param true|false $multiple Whether or not multiple instances of this widget are allowed on a single dashboard (default: false) - * @param string $position A comma-separated list of positions on the page (side or main) where this widget is allowed (default: "side,main") - * @return true|false Depending on success + * The widget types are stdClass objects. + * + * @param string $context The widget context or empty string for current context + * @param bool $exact Only return widgets registered for this context (false) + * + * @return array + * @since 1.8.0 */ +function elgg_get_widget_types($context = "", $exact = false) { + global $CONFIG; -function add_widget_type($handler, $name, $description, $context = "all", $multiple = false, $positions = "side,main") { - if (!empty($handler) && !empty($name)) { - global $CONFIG; + if (empty($CONFIG->widgets) || + empty($CONFIG->widgets->handlers) || + !is_array($CONFIG->widgets->handlers)) { + // no widgets + return array(); + } - if (!isset($CONFIG->widgets)) { - $CONFIG->widgets = new stdClass; - } + if (!$context) { + $context = elgg_get_context(); + } - if (!isset($CONFIG->widgets->handlers)) { - $CONFIG->widgets->handlers = array(); + $widgets = array(); + foreach ($CONFIG->widgets->handlers as $key => $handler) { + if ($exact) { + if (in_array($context, $handler->context)) { + $widgets[$key] = $handler; + } + } else { + if (in_array('all', $handler->context) || in_array($context, $handler->context)) { + $widgets[$key] = $handler; + } } - - $handlerobj = new stdClass; - $handlerobj->name = $name; - $handlerobj->description = $description; - $handlerobj->context = explode(",",$context); - $handlerobj->multiple = $multiple; - $handlerobj->positions = explode(",",$positions); - - $CONFIG->widgets->handlers[$handler] = $handlerobj; - - return true; } - return false; + return $widgets; } /** - * Determines whether or not widgets with the specified handler have been defined + * Regsiter entity of object, widget as ElggWidget objects * - * @param string $handler The widget handler identifying string - * @return true|false Whether or not those widgets exist + * @return void + * @access private */ -function widget_type_exists($handler) { - global $CONFIG; - - if (!empty($CONFIG->widgets) - && !empty($CONFIG->widgets->handlers) - && is_array($CONFIG->widgets->handlers) - && array_key_exists($handler, $CONFIG->widgets->handlers)) { - return true; - } - - return false; +function elgg_widget_run_once() { + add_subtype("object", "widget", "ElggWidget"); } /** - * Returns an array of stdClass objects representing the defined widget types + * Function to initialize widgets functionality * - * @return array A list of types defined (if any) + * @return void + * @access private */ -function get_widget_types() { - global $CONFIG; - - if (!empty($CONFIG->widgets) - && !empty($CONFIG->widgets->handlers) - && is_array($CONFIG->widgets->handlers)) { - - $context = get_context(); - - foreach($CONFIG->widgets->handlers as $key => $handler) { - if (!in_array('all',$handler->context) && - !in_array($context,$handler->context)) { - unset($CONFIG->widgets->handlers[$key]); - } - } - - return $CONFIG->widgets->handlers; - } - - return array(); +function elgg_widgets_init() { + elgg_register_action('widgets/save'); + elgg_register_action('widgets/add'); + elgg_register_action('widgets/move'); + elgg_register_action('widgets/delete'); + elgg_register_action('widgets/upgrade', '', 'admin'); + + run_function_once("elgg_widget_run_once"); } /** - * Saves a widget's settings (by passing an array of (name => value) pairs to save_{$handler}_widget) + * Gets a list of events to create default widgets for and + * register menu items for default widgets with the admin section. + * + * A plugin that wants to register a new context for default widgets should + * register for the plugin hook 'get_list', 'default_widgets'. The handler + * can register the new type of default widgets by adding an associate array to + * the return value array like this: + * array( + * 'name' => elgg_echo('profile'), + * 'widget_context' => 'profile', + * 'widget_columns' => 3, * - * @param int $widget_guid The GUID of the widget we're saving to - * @param array $params An array of name => value parameters + * 'event' => 'create', + * 'entity_type' => 'user', + * 'entity_subtype' => ELGG_ENTITIES_ANY_VALUE, + * ); + * + * The first set of keys define information about the new type of default + * widgets and the second set determine what event triggers the creation of the + * new widgets. + * + * @return void + * @access private */ -function save_widget_info($widget_guid, $params) { - if ($widget = get_entity($widget_guid)) { +function elgg_default_widgets_init() { + global $CONFIG; + $default_widgets = elgg_trigger_plugin_hook('get_list', 'default_widgets', null, array()); - $subtype = $widget->getSubtype(); + $CONFIG->default_widget_info = $default_widgets; - if ($subtype != "widget") { - return false; - } - $handler = $widget->handler; - if (empty($handler) || !widget_type_exists($handler)) { - return false; - } + if ($default_widgets) { + elgg_register_admin_menu_item('configure', 'default_widgets', 'appearance'); - if (!$widget->canEdit()) { - return false; - } + // override permissions for creating widget on logged out / just created entities + elgg_register_plugin_hook_handler('container_permissions_check', 'object', 'elgg_default_widgets_permissions_override'); - // Save the params to the widget - if (is_array($params) && sizeof($params) > 0) { - foreach($params as $name => $value) { - - if (!empty($name) && !in_array($name, array( - 'guid','owner_guid','site_guid' - ))) { - if (is_array($value)) { - // TODO: Handle arrays securely - $widget->setMetaData($name, $value, "", true); - } else { - $widget->$name = $value; - } - } - } - $widget->save(); + // only register the callback once per event + $events = array(); + foreach ($default_widgets as $info) { + $events[$info['event'] . ',' . $info['entity_type']] = $info; } - - $function = "save_{$handler}_widget"; - if (is_callable($function)) { - return $function($params); + foreach ($events as $info) { + elgg_register_event_handler($info['event'], $info['entity_type'], 'elgg_create_default_widgets'); } - - return true; } - - return false; } -function reorder_widgets_from_panel($panelstring1, $panelstring2, $panelstring3, $context, $owner) { - $return = true; - - $mainwidgets = explode('::',$panelstring1); - $sidewidgets = explode('::',$panelstring2); - $rightwidgets = explode('::',$panelstring3); - - $handlers = array(); - $guids = array(); - - if (is_array($mainwidgets) && sizeof($mainwidgets) > 0) { - foreach($mainwidgets as $widget) { - - $guid = (int) $widget; - - if ("{$guid}" == "{$widget}") { - $guids[1][] = $widget; - } else { - $handlers[1][] = $widget; - } - } - } - if (is_array($sidewidgets) && sizeof($sidewidgets) > 0) { - foreach($sidewidgets as $widget) { - - $guid = (int) $widget; - - if ("{$guid}" == "{$widget}") { - $guids[2][] = $widget; - } else { - $handlers[2][] = $widget; - } - - } - } - if (is_array($rightwidgets) && sizeof($rightwidgets) > 0) { - foreach($rightwidgets as $widget) { - - $guid = (int) $widget; - - if ("{$guid}" == "{$widget}") { - $guids[3][] = $widget; - } else { - $handlers[3][] = $widget; - } +/** + * Creates default widgets + * + * This plugin hook handler is registered for events based on what kinds of + * default widgets have been registered. See elgg_default_widgets_init() for + * information on registering new default widget contexts. + * + * @param string $event The event + * @param string $type The type of object + * @param ElggEntity $entity The entity being created + * @return void + * @access private + */ +function elgg_create_default_widgets($event, $type, $entity) { + $default_widget_info = elgg_get_config('default_widget_info'); - } + if (!$default_widget_info || !$entity) { + return; } - // Reorder existing widgets or delete ones that have vanished - foreach (array(1,2,3) as $column) { - if ($dbwidgets = get_widgets($owner,$context,$column)) { - - foreach($dbwidgets as $dbwidget) { - if (in_array($dbwidget->getGUID(),$guids[1]) || in_array($dbwidget->getGUID(),$guids[2]) || in_array($dbwidget->getGUID(),$guids[3])) { - if (in_array($dbwidget->getGUID(),$guids[1])) { - $pos = array_search($dbwidget->getGUID(),$guids[1]); - $col = 1; - } else if (in_array($dbwidget->getGUID(),$guids[2])) { - $pos = array_search($dbwidget->getGUID(),$guids[2]); - $col = 2; - } else { - $pos = array_search($dbwidget->getGUID(),$guids[3]); - $col = 3; + $type = $entity->getType(); + $subtype = $entity->getSubtype(); + + // event is already guaranteed by the hook registration. + // need to check subtype and type. + foreach ($default_widget_info as $info) { + if ($info['entity_type'] == $type) { + if ($info['entity_subtype'] == ELGG_ENTITIES_ANY_VALUE || $info['entity_subtype'] == $subtype) { + + // need to be able to access everything + $old_ia = elgg_set_ignore_access(true); + elgg_push_context('create_default_widgets'); + + // pull in by widget context with widget owners as the site + // not using elgg_get_widgets() because it sorts by columns and we don't care right now. + $options = array( + 'type' => 'object', + 'subtype' => 'widget', + 'owner_guid' => elgg_get_site_entity()->guid, + 'private_setting_name' => 'context', + 'private_setting_value' => $info['widget_context'], + 'limit' => 0 + ); + + $widgets = elgg_get_entities_from_private_settings($options); + /* @var ElggWidget[] $widgets */ + + foreach ($widgets as $widget) { + // change the container and owner + $new_widget = clone $widget; + $new_widget->container_guid = $entity->guid; + $new_widget->owner_guid = $entity->guid; + + // pull in settings + $settings = get_all_private_settings($widget->guid); + + foreach ($settings as $name => $value) { + $new_widget->$name = $value; } - $pos = ($pos + 1) * 10; - $dbwidget->column = $col; - $dbwidget->order = $pos; - } else { - $dbguid = $dbwidget->getGUID(); - if (!$dbwidget->delete()) { - $return = false; - } else { - // Remove state cookie - setcookie('widget' + $dbguid, null); - } - } - } - } - // Add new ones - if (sizeof($guids[$column]) > 0) { - foreach($guids[$column] as $key => $guid) { - if ($guid == 0) { - $pos = ($key + 1) * 10; - $handler = $handlers[$column][$key]; - if (!add_widget($owner,$handler,$context,$pos,$column)) { - $return = false; - } + $new_widget->save(); } + + elgg_set_ignore_access($old_ia); + elgg_pop_context(); } } } - - return $return; -} - -/** - * Run some things once. - * - */ -function widget_run_once() { - // Register a class - add_subtype("object", "widget", "ElggWidget"); } /** - * Function to initialise widgets functionality on Elgg init + * Overrides permissions checks when creating widgets for logged out users. * + * @param string $hook The permissions hook. + * @param string $type The type of entity being created. + * @param string $return Value + * @param mixed $params Params + * @return true|null + * @access private */ -function widgets_init() { - register_action('widgets/reorder'); - register_action('widgets/save'); - register_action('widgets/add'); +function elgg_default_widgets_permissions_override($hook, $type, $return, $params) { + if ($type == 'object' && $params['subtype'] == 'widget') { + return elgg_in_context('create_default_widgets') ? true : null; + } - // Now run this stuff, but only once - run_function_once("widget_run_once"); + return null; } -// Register event -register_elgg_event_handler('init','system','widgets_init'); - -// Use widgets on the dashboard -use_widgets('dashboard');
\ No newline at end of file +elgg_register_event_handler('init', 'system', 'elgg_widgets_init'); +// register default widget hooks from plugins +elgg_register_event_handler('ready', 'system', 'elgg_default_widgets_init'); |
