Passed
Push — 3.x ( 589a0f...691809 )
by Jerome
65:54 queued 11s
created

WidgetsService   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 315
Duplicated Lines 0 %

Test Coverage

Coverage 72.72%

Importance

Changes 0
Metric Value
eloc 107
dl 0
loc 315
ccs 80
cts 110
cp 0.7272
rs 9.36
c 0
b 0
f 0
wmc 38

9 Methods

Rating   Name   Duplication   Size   Complexity  
A registerType() 0 13 3
A getAllTypes() 0 2 1
B createWidget() 0 27 7
A canEditLayout() 0 22 4
B getTypes() 0 31 7
B getWidgets() 0 53 9
A unregisterType() 0 6 2
A getNameById() 0 9 2
A validateType() 0 13 3
1
<?php
2
namespace Elgg;
3
4
use Elgg\Database\EntityTable\UserFetchFailureException;
5
6
/**
7
 * WARNING: API IN FLUX. DO NOT USE DIRECTLY.
8
 *
9
 * Use the elgg_* versions instead.
10
 *
11
 * @access private
12
 *
13
 * @package    Elgg.Core
14
 * @subpackage Widgets
15
 * @since      1.9.0
16
 */
17
class WidgetsService {
18
19
	/**
20
	 * @var WidgetDefinition[]
21
	 */
22
	private $widgets = [];
23
24
	/**
25
	 * @see \Elgg\WidgetsService::getWidgets()
26
	 * @var array
27
	 */
28
	private $widgetCache = [];
29
30
	/**
31
	 * Get widgets for a particular context
32
	 *
33
	 * The widgets are ordered for display and grouped in columns.
34
	 * $widgets = elgg_get_widgets(elgg_get_logged_in_user_guid(), 'dashboard');
35
	 * $first_column_widgets = $widgets[1];
36
	 *
37
	 * @param int    $owner_guid The owner GUID of the layout
38
	 * @param string $context    The context (profile, dashboard, etc)
39
	 *
40
	 * @return \ElggWidget[] An 2D array of \ElggWidget objects
41
	 *
42
	 * @see elgg_get_widgets()
43
	 * @access private
44
	 * @since 1.9.0
45
	 */
46 6
	public function getWidgets($owner_guid, $context) {
47 6
		$widget_cache_key = "$context-$owner_guid";
48
49 6
		if (isset($this->widgetCache[$widget_cache_key])) {
50
			return $this->widgetCache[$widget_cache_key];
51
		}
52
53 6
		$widgets = elgg_get_entities([
54 6
			'type' => 'object',
55 6
			'subtype' => 'widget',
56 6
			'owner_guid' => $owner_guid,
57 6
			'private_setting_name' => 'context',
58 6
			'private_setting_value' => $context,
59 6
			'limit' => 0,
60
			'preload_private_settings' => true,
61
		]);
62
		
63 6
		if (!$widgets) {
64 6
			$this->widgetCache[$widget_cache_key] = [];
65 6
			return [];
66
		}
67
68
		$sorted_widgets = [];
69
		foreach ($widgets as $widget) {
70
			$widget_column = (int) $widget->column;
71
			
72
			if (!isset($sorted_widgets[$widget_column])) {
73
				$sorted_widgets[$widget_column] = [];
74
			}
75
			
76
			if (!isset($sorted_widgets[$widget_column][$widget->order])) {
77
				$sorted_widgets[$widget_column][$widget->order] = [];
78
			}
79
			
80
			$sorted_widgets[$widget_column][$widget->order][] = $widget;
81
		}
82
83
		foreach ($sorted_widgets as $col => $orders) {
84
			ksort($orders);
85
			$sorted_col = [];
86
			
87
			foreach ($orders as $widgets) {
88
				foreach ($widgets as $widget) {
89
					$sorted_col[] = $widget;
90
				}
91
			}
92
			
93
			$sorted_widgets[$col] = $sorted_col;
94
		}
95
96
		$this->widgetCache[$widget_cache_key] = $sorted_widgets;
97
98
		return $sorted_widgets;
99
	}
100
101
	/**
102
	 * Create a new widget instance
103
	 *
104
	 * @param int    $owner_guid GUID of entity that owns this widget
105
	 * @param string $handler    The handler for this widget
106
	 * @param string $context    The context for this widget
107
	 * @param int    $access_id  If not specified, it is set to the default access level
108
	 *
109
	 * @return int|false Widget GUID or false on failure
110
	 *
111
	 * @see elgg_create_widget()
112
	 * @access private
113
	 * @since 1.9.0
114
	 */
115 9
	public function createWidget($owner_guid, $handler, $context, $access_id = null) {
116 9
		if (empty($owner_guid) || empty($handler)) {
117 2
			return false;
118
		}
119
120 7
		$owner = get_entity($owner_guid);
121 7
		if (!$owner) {
1 ignored issue
show
introduced by
$owner is of type ElggEntity, thus it always evaluated to true.
Loading history...
122
			return false;
123
		}
124 7
		if (!$this->validateType($handler, $context, $owner)) {
125
			return false;
126
		}
127
128 7
		$widget = new \ElggWidget;
129 7
		$widget->owner_guid = $owner_guid;
130 7
		$widget->container_guid = $owner_guid;
131 7
		$widget->access_id = isset($access_id) ? $access_id : get_default_access();
132
		
133 7
		if (!$widget->save()) {
134
			return false;
135
		}
136
137
		// private settings cannot be set until \ElggWidget saved
138 7
		$widget->handler = $handler;
139 7
		$widget->context = $context;
140
141 7
		return $widget->getGUID();
142
	}
143
144
	/**
145
	 * Can the user edit the widget layout
146
	 *
147
	 * @param string $context   The widget context
148
	 * @param int    $user_guid The GUID of the user (0 for logged in user)
149
	 *
150
	 * @return bool
151
	 *
152
	 * @see elgg_can_edit_widget_layout()
153
	 * @access private
154
	 * @since 1.9.0
155
	 */
156 8
	public function canEditLayout($context, $user_guid = 0) {
157
		try {
158 8
			$user = _elgg_services()->entityTable->getUserForPermissionsCheck($user_guid);
159
		} catch (UserFetchFailureException $e) {
160
			return false;
161
		}
162
163 8
		$page_owner = elgg_get_page_owner_entity();
164 8
		$default = false;
165
		
166 8
		if ($page_owner) {
167 8
			$default = $page_owner->canEdit($user_guid);
168
		} elseif ($user) {
1 ignored issue
show
introduced by
$user is of type ElggUser, thus it always evaluated to true.
Loading history...
169
			$default = $user->isAdmin();
170
		}
171
		
172
		$params = [
173 8
			'user' => $user,
174 8
			'context' => $context,
175 8
			'page_owner' => $page_owner,
176
		];
177 8
		return _elgg_services()->hooks->trigger('permissions_check', 'widget_layout', $params, $default);
178
	}
179
180
	/**
181
	 * Register a widget type
182
	 *
183
	 * @param WidgetDefinition $definition Definition of the widget
184
	 *
185
	 * @return bool
186
	 *
187
	 * @see elgg_register_widget_type()
188
	 * @access private
189
	 * @since 1.9.0
190
	 */
191 183
	public function registerType(WidgetDefinition $definition) {
192 183
		if (!($definition instanceof WidgetDefinition)) {
0 ignored issues
show
introduced by
$definition is always a sub-type of Elgg\WidgetDefinition.
Loading history...
193
			return false;
194
		}
195
		
196 183
		$id = $definition->id;
197 183
		if (!$id) {
198 1
			return false;
199
		}
200
		
201 183
		$this->widgets[$id] = $definition;
202
203 183
		return true;
204
	}
205
206
	/**
207
	 * Remove a widget type
208
	 *
209
	 * @param string $id The identifier for the widget
210
	 *
211
	 * @return bool
212
	 *
213
	 * @see elgg_unregister_widget_type()
214
	 * @access private
215
	 * @since 1.9.0
216
	 */
217 3
	public function unregisterType($id) {
218 3
		if (isset($this->widgets[$id])) {
219 2
			unset($this->widgets[$id]);
220 2
			return true;
221
		}
222 3
		return false;
223
	}
224
225
	/**
226
	 * Checks if a widget type exists for a given id
227
	 *
228
	 * @param string      $id        Widget identifier
229
	 * @param string      $context   Optional context to check
230
	 * @param \ElggEntity $container Optional limit widget definitions to a container
231
	 *
232
	 * @return bool
233
	 *
234
	 * @see elgg_is_widget_type()
235
	 * @access private
236
	 * @since 1.9.0
237
	 */
238 11
	public function validateType($id, $context = null, \ElggEntity $container = null) {
239 11
		$types = $this->getTypes([
240 11
			'context' => $context,
241 11
			'container' => $container,
242
		]);
243 11
		$found = array_key_exists($id, $types);
244
		
245 11
		if (!$found && ($context === null)) {
246
			// Pre Elgg 2.2 this function returned true if a widget was registered regardless of context
247 4
			$found = array_key_exists($id, $this->widgets);
248
		}
249
		
250 11
		return $found;
251
	}
252
253
	/**
254
	 * Get all widgets
255
	 *
256
	 * @return \Elgg\WidgetDefinition[]
257
	 *
258
	 * @access private
259
	 * @since 1.9.0
260
	 */
261
	public function getAllTypes() {
262
		return $this->widgets;
263
	}
264
	
265
	/**
266
	 * Returns widget name based on id
267
	 *
268
	 * @param string      $id        Widget identifier
269
	 * @param string      $context   Context to check
270
	 * @param \ElggEntity $container Optional limit widget definitions to a container
271
	 *
272
	 * @return string|boolean
273
	 *
274
	 * @access private
275
	 * @since 2.2.0
276
	 */
277 3
	public function getNameById($id, $context = '', \ElggEntity $container = null) {
278 3
		$types = $this->getTypes([
279 3
			'context' => $context,
280 3
			'container' => $container,
281
		]);
282 3
		if (isset($types[$id])) {
283 2
			return $types[$id]->name;
284
		}
285 1
		return false;
286
	}
287
288
	/**
289
	 * @param array $params Associative array of params used to determine what to return
290
	 *
291
	 * array (
292
	 *     'context' => string (defaults to elgg_get_context()),
293
	 *     'container' => \ElggEntity (defaults to null)
294
	 * )
295
	 *
296
	 * @return \Elgg\WidgetDefinition[]
297
	 *
298
	 * @access private
299
	 * @since 1.9.0
300
	 */
301 21
	public function getTypes(array $params = []) {
302 21
		$context = elgg_extract('context', $params, '');
303 21
		if (!$context) {
304 8
			$context = elgg_get_context();
305 8
			$params['context'] = $context;
306
		}
307
		
308 21
		$available_widgets = _elgg_services()->hooks->trigger('handlers', 'widgets', $params, $this->widgets);
309 21
		if (!is_array($available_widgets)) {
310
			return [];
311
		}
312
		
313 21
		$widgets = [];
314
		/* @var $widget_definition \Elgg\WidgetDefinition */
315 21
		foreach ($available_widgets as $widget_definition) {
316 20
			if (!($widget_definition instanceof WidgetDefinition)) {
317
				continue;
318
			}
319
320 20
			if (!in_array($context, $widget_definition->context)) {
321 17
				continue;
322
			}
323
			
324 14
			if (!$widget_definition->isValid()) {
325 1
				continue;
326
			}
327
			
328 14
			$widgets[$widget_definition->id] = $widget_definition;
329
		}
330
331 21
		return $widgets;
332
	}
333
}
334
335