Permalink
Browse files

feature(widgets): widget types can now be extended with a hook

fixes #9496 and fixes #7274
  • Loading branch information...
jdalsem committed Mar 22, 2016
1 parent 3c61e2f commit 3c76194c02274c09a3097168280950e7d6699456
@@ -0,0 +1,112 @@
<?php
namespace Elgg;
/**
* WidgetDefinition
*
* Helper class for defining a widget
*
*/
class WidgetDefinition {
/**
* @var string Identifier of the widget
*/
public $id;
/**
* @var string Readable name of the widget
*/
public $name;
/**
* @var string Description of the widget
*/
public $description;
/**
* @var array In which contexts is the widget available
*/
public $context;
/**
* @var bool Can the widget be added multiple times
*/
public $multiple;
/**
* WidgetDefinition constructor
*
* @param string $id Identifier of the widget
*/
public function __construct($id) {
if (empty($id)) {
throw new \InvalidParameterException('Id missing for WidgetDefinition');
}
$this->id = $id;
}
/**
* Create an WidgetDefinition from an associative array. Required key is id.
*
* @param array $options Option array of key value pairs
*
* id => STR Widget identifier (required)
* name => STR Name of the widget
* description => STR Description of the widget
* context => ARRAY contexts in which the widget is available
* multiple => BOOL can the widget be added multiple times
*
* @throws InvalidParameterException
* @return \Elgg\WidgetDefinition
*/
public static function factory(array $options) {
$id = elgg_extract('id', $options);
$definition = new WidgetDefinition($id);
$name = elgg_extract('name', $options);
if (empty($name)) {
if (elgg_language_key_exists("widgets:{$id}:name")) {
$definition->name = elgg_echo("widgets:{$id}:name");
} elseif (elgg_language_key_exists($id)) {
$definition->name = elgg_echo($id);
} else {
$definition->name = $id;
}
} else {
$definition->name = $name;
}
$description = elgg_extract('description', $options);
if (empty($description)) {
if (elgg_language_key_exists("widgets:{$id}:description")) {
$definition->description = elgg_echo("widgets:{$id}:description");
}
} else {
$definition->description = $description;
}
$definition->context = (array) elgg_extract('context', $options, []);
$definition->multiple = (bool) elgg_extract('multiple', $options, false);
return $definition;
}
/**
* Magic getter to return the deprecated attribute 'handler'
*
* @param string $name attribute to get
*
* @return mixed
*/
public function __get($name) {
if ($name === 'handler') {
// before Elgg 2.2 the widget definitions had the handler attribute as the id
return $this->id;
}
return $this->$name;
}
}
@@ -17,9 +17,9 @@
class WidgetsService {
/**
* @var \stdClass
* @var WidgetDefinition[]
*/
private $widgets;
private $widgets = [];
/**
* @see \Elgg\WidgetsService::getWidgets()
@@ -75,14 +75,17 @@ public function getWidgets($owner_guid, $context) {
* @since 1.9.0
*/
public function createWidget($owner_guid, $handler, $context, $access_id = null) {
if (empty($owner_guid) || empty($handler) || !$this->validateType($handler)) {
if (empty($owner_guid) || empty($handler)) {
return false;
}
$owner = get_entity($owner_guid);
if (!$owner) {
return false;
}
if (!$this->validateType($handler, $context, $owner)) {
return false;
}
$widget = new \ElggWidget;
$widget->owner_guid = $owner_guid;
@@ -131,129 +134,141 @@ public function canEditLayout($context, $user_guid = 0) {
}
/**
* @param WidgetDefinition Definition of the widget
*
* @return bool
*
* @see elgg_register_widget_type
* @access private
* @since 1.9.0
*/
public function registerType(\ElggWidgetDefinition $definition) {
public function registerType(WidgetDefinition $definition) {
if (!$definition) {
return false;
}
$handler = $definition->handler;
if (!$handler) {
$id = $definition->id;
if (!$id) {
return false;
}
if (!isset($this->widgets)) {
$this->widgets = new \stdClass;
}
if (!isset($this->widgets->handlers)) {
$this->widgets->handlers = [];
}
$this->widgets->handlers[$handler] = $definition;
$this->widgets[$id] = $definition;
return true;
}
/**
* @param string $handler
* @param string $id
* @return bool
* @see elgg_unregister_widget_type
* @access private
* @since 1.9.0
*/
public function unregisterType($handler) {
if (!isset($this->widgets)) {
return false;
}
if (!isset($this->widgets->handlers)) {
return false;
}
if (isset($this->widgets->handlers[$handler])) {
unset($this->widgets->handlers[$handler]);
public function unregisterType($id) {
if (isset($this->widgets[$id])) {
unset($this->widgets[$id]);
return true;
}
return false;
}
/**
* Checks if a widget type exists for a given id
*
* @param string $id Widget identifier
* @param string $context Optional context to check
* @param \ElggEntity $container Optional limit widget definitions to a container
*
* @see elgg_is_widget_type
* @access private
* @since 1.9.0
*/
public function validateType($handler) {
if (!empty($this->widgets) &&
!empty($this->widgets->handlers) &&
is_array($this->widgets->handlers) &&
array_key_exists($handler, $this->widgets->handlers)) {
return true;
public function validateType($id, $context = null, \ElggEntity $container = null) {
$types = $this->getTypes([
'context' => $context,
'container' => $container,
]);
$found = array_key_exists($id, $types);
if (!$found && ($context === null)) {
// Pre Elgg 2.2 this function returned true if a widget was registered regardless of context
$found = array_key_exists($id, $this->widgets);
}
return false;
return $found;
}
/**
* @access private
* @since 1.9.0
*/
public function getAllTypes() {
if (empty($this->widgets) ||
empty($this->widgets->handlers) ||
!is_array($this->widgets->handlers)) {
// no widgets
return array();
}
$widgets = array();
foreach ($this->widgets->handlers as $key => $handler) {
$widgets[$key] = $handler;
}
return $widgets;
return $this->widgets;
}
/**
* Returns widget name based on id
*
* @param string $id Widget identifier
* @param string $context Context to check
* @param \ElggEntity $container Optional limit widget definitions to a container
*
* @return string|boolean
*
* @access private
* @since 1.9.0
* @since 2.2.0
*/
public function getNameByType($handler) {
if (isset($this->widgets->handlers[$handler])) {
return $this->widgets->handlers[$handler]->name;
public function getNameById($id, $context = '', \ElggEntity $container = null) {
$types = $this->getTypes([
'context' => $context,
'container' => $container,
]);
if (isset($types[$id])) {
return $types[$id]->name;
}
return false;
}
/**
* @see elgg_get_widget_types
* @param $params Associative array of params used to determine what to return
*
* array (
* 'context' => string (defaults to elgg_get_context()),
* 'exact' => bool (defaults to false),
* 'container' => \ElggEntity (defaults to null)
* )
*
* @return \Elgg\WidgetDefinition[]
*
* @access private
* @since 1.9.0
*/
public function getTypes($context = "", $exact = false) {
if (empty($this->widgets) ||
empty($this->widgets->handlers) ||
!is_array($this->widgets->handlers)) {
// no widgets
return array();
}
public function getTypes(array $params = []) {
$exact = (bool) elgg_extract('exact', $params, false);
$context = elgg_extract('context', $params, '');
if (!$context) {
$context = elgg_get_context();
$params['context'] = $context;
}
$widgets = array();
foreach ($this->widgets->handlers as $key => $handler) {
$available_widgets = _elgg_services()->hooks->trigger('handlers', 'widgets', $params, $this->widgets);
if (!is_array($available_widgets)) {
return [];
}
$widgets = [];
foreach ($available_widgets as $widget_definition) {
if (!($widget_definition instanceof WidgetDefinition)) {
continue;
}
if ($exact) {
if (in_array($context, $handler->context)) {
$widgets[$key] = $handler;
if (in_array($context, $widget_definition->context)) {
$widgets[$widget_definition->id] = $widget_definition;
}
} else {
if (in_array('all', $handler->context) || in_array($context, $handler->context)) {
$widgets[$key] = $handler;
if (in_array('all', $widget_definition->context) || in_array($context, $widget_definition->context)) {
$widgets[$widget_definition->id] = $widget_definition;
}
}
}
@@ -165,7 +165,7 @@ public function getContext() {
public function getTitle() {
$title = $this->title;
if (!$title) {
$title = _elgg_services()->widgets->getNameByType($this->handler);
$title = _elgg_services()->widgets->getNameById($this->handler, $this->getContext(), $this->getContainerEntity());
}
return $title;
}
@@ -199,7 +199,10 @@ public function move($column, $rank) {
usort($widgets, create_function('$a,$b','return (int)$a->order > (int)$b->order;'));
// remove widgets from inactive plugins
$widget_types = elgg_get_widget_types($this->context);
$widget_types = elgg_get_widget_types([
'context' => $this->context,
'container' => $this->getContainerEntity(),
]);
$inactive_widgets = array();
foreach ($widgets as $index => $widget) {
if (!array_key_exists($widget->handler, $widget_types)) {
Oops, something went wrong.

0 comments on commit 3c76194

Please sign in to comment.