1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * @package toolkit |
||||
5 | */ |
||||
6 | /** |
||||
7 | * The ResourcesManager is a class used to collect some methods for both |
||||
8 | * Datasources and Events. |
||||
9 | * |
||||
10 | * @since Symphony 2.3 |
||||
11 | */ |
||||
12 | |||||
13 | class ResourceManager |
||||
14 | { |
||||
15 | /** |
||||
16 | * The integer value for event-type resources. |
||||
17 | * @var integer |
||||
18 | */ |
||||
19 | const RESOURCE_TYPE_EVENT = 20; |
||||
20 | |||||
21 | /** |
||||
22 | * The integer value for datasource-type resources. |
||||
23 | * @var integer |
||||
24 | */ |
||||
25 | const RESOURCE_TYPE_DS = 21; |
||||
26 | |||||
27 | /** |
||||
28 | * A private method used to return the `tbl_pages` column related to |
||||
29 | * the given resource type. |
||||
30 | * |
||||
31 | * @param integer $type |
||||
32 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
33 | * @return string |
||||
34 | * A string representing the `tbl_pages` column to target. |
||||
35 | */ |
||||
36 | private static function getColumnFromType($type) |
||||
37 | { |
||||
38 | switch ($type) { |
||||
39 | case ResourceManager::RESOURCE_TYPE_EVENT: |
||||
40 | return 'events'; |
||||
41 | case ResourceManager::RESOURCE_TYPE_DS: |
||||
42 | return 'data_sources'; |
||||
43 | } |
||||
44 | } |
||||
45 | |||||
46 | /** |
||||
47 | * A method used to return the Manager for the given resource type. |
||||
48 | * |
||||
49 | * @param integer $type |
||||
50 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
51 | * @return string |
||||
52 | * An string representing the name of the Manager class that handles the resource. |
||||
53 | */ |
||||
54 | public static function getManagerFromType($type) |
||||
55 | { |
||||
56 | switch ($type) { |
||||
57 | case ResourceManager::RESOURCE_TYPE_EVENT: |
||||
58 | return 'EventManager'; |
||||
59 | case ResourceManager::RESOURCE_TYPE_DS: |
||||
60 | return 'DatasourceManager'; |
||||
61 | } |
||||
62 | } |
||||
63 | |||||
64 | /** |
||||
65 | * Returns the axis a given resource type will be sorted by. |
||||
66 | * The following handles are available: `name`, `source`, `release-date` |
||||
67 | * and `author`. Defaults to 'name'. |
||||
68 | * |
||||
69 | * @param integer $type |
||||
70 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
71 | * @return string |
||||
72 | * The axis handle. |
||||
73 | */ |
||||
74 | public static function getSortingField($type) |
||||
75 | { |
||||
76 | $result = Symphony::Configuration()->get(self::getColumnFromType($type) . '_index_sortby', 'sorting'); |
||||
77 | |||||
78 | return (is_null($result) ? 'name' : $result); |
||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||
79 | } |
||||
80 | |||||
81 | /** |
||||
82 | * Returns the sort order for a given resource type. Defaults to 'asc'. |
||||
83 | * |
||||
84 | * @param integer $type |
||||
85 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
86 | * @return string |
||||
87 | * Either 'asc' or 'desc'. |
||||
88 | */ |
||||
89 | public static function getSortingOrder($type) |
||||
90 | { |
||||
91 | $result = Symphony::Configuration()->get(self::getColumnFromType($type) . '_index_order', 'sorting'); |
||||
92 | |||||
93 | return (is_null($result) ? 'asc' : $result); |
||||
0 ignored issues
–
show
|
|||||
94 | } |
||||
95 | |||||
96 | /** |
||||
97 | * Saves the new axis a given resource type will be sorted by. |
||||
98 | * |
||||
99 | * @param integer $type |
||||
100 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
101 | * @param string $sort |
||||
102 | * The axis handle. |
||||
103 | * @param boolean $write |
||||
104 | * If false, the new settings won't be written on the configuration file. |
||||
105 | * Defaults to true. |
||||
106 | */ |
||||
107 | public static function setSortingField($type, $sort, $write = true) |
||||
0 ignored issues
–
show
|
|||||
108 | { |
||||
109 | Symphony::Configuration()->set(self::getColumnFromType($type) . '_index_sortby', $sort, 'sorting'); |
||||
0 ignored issues
–
show
|
|||||
110 | |||||
111 | if ($write) { |
||||
112 | Symphony::Configuration()->write(); |
||||
113 | } |
||||
114 | } |
||||
115 | |||||
116 | /** |
||||
117 | * Saves the new sort order for a given resource type. |
||||
118 | * |
||||
119 | * @param integer $type |
||||
120 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
121 | * @param string $order |
||||
122 | * Either 'asc' or 'desc'. |
||||
123 | * @param boolean $write |
||||
124 | * If false, the new settings won't be written on the configuration file. |
||||
125 | * Defaults to true. |
||||
126 | */ |
||||
127 | public static function setSortingOrder($type, $order, $write = true) |
||||
0 ignored issues
–
show
|
|||||
128 | { |
||||
129 | Symphony::Configuration()->set(self::getColumnFromType($type) . '_index_order', $order, 'sorting'); |
||||
130 | |||||
131 | if ($write) { |
||||
132 | Symphony::Configuration()->write(); |
||||
133 | } |
||||
134 | } |
||||
135 | |||||
136 | /** |
||||
137 | * This function will return an associative array of resource information. The |
||||
138 | * information returned is defined by the `$select` parameter, which will allow |
||||
139 | * a developer to restrict what information is returned about the resource. |
||||
140 | * Optionally, `$where` (not implemented) and `$order_by` parameters allow a developer to |
||||
141 | * further refine their query. |
||||
142 | * |
||||
143 | * @param integer $type |
||||
144 | * The type of the resource (needed to retrieve the correct Manager) |
||||
145 | * @param array $select (optional) |
||||
146 | * Accepts an array of keys to return from the manager's `listAll()` method. If omitted, |
||||
147 | * all keys will be returned. |
||||
148 | * @param array $where (optional) |
||||
149 | * Not implemented. |
||||
150 | * @param string $order_by (optional) |
||||
151 | * Allows a developer to return the resources in a particular order. The syntax is the |
||||
152 | * same as other `fetch` methods. If omitted this will return resources ordered by `name`. |
||||
153 | * @throws SymphonyErrorPage |
||||
154 | * @throws Exception |
||||
155 | * @return array |
||||
156 | * An associative array of resource information, formatted in the same way as the resource's |
||||
157 | * manager `listAll()` method. |
||||
158 | */ |
||||
159 | public static function fetch($type, array $select = array(), array $where = array(), $order_by = null) |
||||
0 ignored issues
–
show
|
|||||
160 | { |
||||
161 | $manager = self::getManagerFromType($type); |
||||
162 | |||||
163 | if (!isset($manager)) { |
||||
164 | throw new Exception(__('Unable to find a Manager class for this resource.')); |
||||
165 | } |
||||
166 | |||||
167 | $resources = call_user_func(array($manager, 'listAll')); |
||||
168 | |||||
169 | foreach ($resources as &$r) { |
||||
170 | // If source is numeric, it's considered to be a Symphony Section |
||||
171 | if (isset($r['source']) && General::intval($r['source']) > 0) { |
||||
172 | $section = SectionManager::fetch($r['source']); |
||||
173 | |||||
174 | if ($section !== false) { |
||||
175 | $r['source'] = array( |
||||
176 | 'name' => General::sanitize($section->get('name')), |
||||
0 ignored issues
–
show
It seems like
$section->get('name') can also be of type array ; however, parameter $source of General::sanitize() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
177 | 'handle' => General::sanitize($section->get('handle')), |
||||
178 | 'id' => $r['source'] |
||||
179 | ); |
||||
180 | } else { |
||||
181 | unset($r['source']); |
||||
182 | } |
||||
183 | |||||
184 | // If source is set but no numeric, it's considered to be a Symphony Type (e.g. authors or navigation) |
||||
185 | } elseif (isset($r['source'])) { |
||||
186 | $r['source'] = array( |
||||
187 | 'name' => ucwords(General::sanitize($r['source'])), |
||||
188 | 'handle' => General::sanitize($r['source']), |
||||
189 | ); |
||||
190 | |||||
191 | // Resource provided by extension? |
||||
192 | } else { |
||||
193 | $extension = self::__getExtensionFromHandle($type, $r['handle']); |
||||
194 | |||||
195 | if (!empty($extension)) { |
||||
196 | $extension = Symphony::ExtensionManager()->about($extension); |
||||
197 | $r['source'] = array( |
||||
198 | 'name' => General::sanitize($extension['name']), |
||||
199 | 'handle' => Lang::createHandle($extension['name']) |
||||
200 | ); |
||||
201 | } |
||||
202 | } |
||||
203 | } |
||||
204 | |||||
205 | if (empty($select) && empty($where) && is_null($order_by)) { |
||||
206 | return $resources; |
||||
207 | } |
||||
208 | |||||
209 | if (!is_null($order_by) && !empty($resources)) { |
||||
210 | $author = $label = $source = $name = array(); |
||||
211 | $order_by = array_map('strtolower', explode(' ', $order_by)); |
||||
212 | $order = ($order_by[1] == 'desc') ? SORT_DESC : SORT_ASC; |
||||
213 | $sort = $order_by[0]; |
||||
214 | |||||
215 | if ($sort == 'author') { |
||||
216 | foreach ($resources as $key => $about) { |
||||
217 | $author[$key] = $about['author']['name']; |
||||
218 | $label[$key] = $key; |
||||
219 | } |
||||
220 | |||||
221 | array_multisort($author, $order, $label, SORT_ASC, $resources); |
||||
222 | } elseif ($sort == 'release-date') { |
||||
223 | foreach ($resources as $key => $about) { |
||||
224 | $author[$key] = $about['release-date']; |
||||
225 | $label[$key] = $key; |
||||
226 | } |
||||
227 | |||||
228 | array_multisort($author, $order, $label, SORT_ASC, $resources); |
||||
229 | } elseif ($sort == 'source') { |
||||
230 | foreach ($resources as $key => $about) { |
||||
231 | $source[$key] = $about['source']['handle']; |
||||
232 | $label[$key] = $key; |
||||
233 | } |
||||
234 | |||||
235 | array_multisort($source, $order, $label, SORT_ASC, $resources); |
||||
236 | } elseif ($sort == 'name') { |
||||
237 | foreach ($resources as $key => $about) { |
||||
238 | $name[$key] = strtolower($about['name']); |
||||
239 | $label[$key] = $key; |
||||
240 | } |
||||
241 | |||||
242 | array_multisort($name, $order, $label, SORT_ASC, $resources); |
||||
243 | } |
||||
244 | } |
||||
245 | |||||
246 | $data = array(); |
||||
247 | |||||
248 | foreach ($resources as $i => $res) { |
||||
249 | $data[$i] = array(); |
||||
250 | |||||
251 | foreach ($res as $key => $value) { |
||||
252 | // If $select is empty, we assume every field is requested |
||||
253 | if (in_array($key, $select) || empty($select)) { |
||||
254 | $data[$i][$key] = $value; |
||||
255 | } |
||||
256 | } |
||||
257 | } |
||||
258 | |||||
259 | return $data; |
||||
260 | } |
||||
261 | |||||
262 | /** |
||||
263 | * Given the type and handle of a resource, return the extension it belongs to. |
||||
264 | * |
||||
265 | * @param integer $type |
||||
266 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
267 | * @param string $r_handle |
||||
268 | * The handle of the resource. |
||||
269 | * @throws Exception |
||||
270 | * @return string |
||||
271 | * The extension handle. |
||||
272 | */ |
||||
273 | public static function __getExtensionFromHandle($type, $r_handle) |
||||
274 | { |
||||
275 | $manager = self::getManagerFromType($type); |
||||
276 | |||||
277 | if (!isset($manager)) { |
||||
278 | throw new Exception(__('Unable to find a Manager class for this resource.')); |
||||
279 | } |
||||
280 | |||||
281 | $type = str_replace('_', '-', self::getColumnFromType($type)); |
||||
282 | preg_match('/extensions\/(.*)\/' . $type . '/', call_user_func(array($manager, '__getClassPath'), $r_handle), $data); |
||||
283 | |||||
284 | $data = array_splice($data, 1); |
||||
285 | |||||
286 | if (empty($data)) { |
||||
287 | return null; |
||||
288 | } else { |
||||
289 | return $data[0]; |
||||
290 | } |
||||
291 | } |
||||
292 | |||||
293 | /** |
||||
294 | * Given the resource handle, this function will return an associative |
||||
295 | * array of Page information, filtered by the pages the resource is attached to. |
||||
296 | * |
||||
297 | * @param integer $type |
||||
298 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
299 | * @param string $r_handle |
||||
300 | * The handle of the resource. |
||||
301 | * @return array |
||||
302 | * An associative array of Page information, according to the pages the resource is attached to. |
||||
303 | */ |
||||
304 | public static function getAttachedPages($type, $r_handle) |
||||
305 | { |
||||
306 | $col = self::getColumnFromType($type); |
||||
307 | |||||
308 | $pages = PageManager::fetch(false, array('id'), array(sprintf( |
||||
309 | '`%s` = "%s" OR `%s` REGEXP "%s"', |
||||
310 | $col, |
||||
311 | $r_handle, |
||||
312 | $col, |
||||
313 | '^' . $r_handle . ',|,' . $r_handle . ',|,' . $r_handle . '$' |
||||
314 | ))); |
||||
315 | |||||
316 | if (is_array($pages)) { |
||||
0 ignored issues
–
show
|
|||||
317 | foreach ($pages as $key => &$page) { |
||||
318 | $pages[$key] = array( |
||||
319 | 'id' => $page['id'], |
||||
320 | 'title' => PageManager::resolvePageTitle($page['id']) |
||||
321 | ); |
||||
322 | } |
||||
323 | } |
||||
324 | |||||
325 | return (is_null($pages) ? array() : $pages); |
||||
0 ignored issues
–
show
|
|||||
326 | } |
||||
327 | |||||
328 | /** |
||||
329 | * Given a resource type, a handle and a page, this function will attach |
||||
330 | * the given handle (which represents either a datasource or event) to that page. |
||||
331 | * |
||||
332 | * @param integer $type |
||||
333 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
334 | * @param string $r_handle |
||||
335 | * The handle of the resource. |
||||
336 | * @param integer $page_id |
||||
337 | * The ID of the page. |
||||
338 | * @return boolean |
||||
339 | */ |
||||
340 | public static function attach($type, $r_handle, $page_id) |
||||
341 | { |
||||
342 | $col = self::getColumnFromType($type); |
||||
343 | |||||
344 | $pages = PageManager::fetch(false, array($col), array(sprintf( |
||||
345 | '`id` = %d', |
||||
346 | $page_id |
||||
347 | ))); |
||||
348 | |||||
349 | if (is_array($pages) && count($pages) == 1) { |
||||
350 | $result = $pages[0][$col]; |
||||
351 | |||||
352 | if (!in_array($r_handle, explode(',', $result))) { |
||||
353 | if (strlen($result) > 0) { |
||||
354 | $result .= ','; |
||||
355 | } |
||||
356 | |||||
357 | $result .= $r_handle; |
||||
358 | |||||
359 | return PageManager::edit($page_id, array( |
||||
360 | $col => MySQL::cleanValue($result) |
||||
361 | )); |
||||
362 | } |
||||
363 | } |
||||
364 | |||||
365 | return false; |
||||
366 | } |
||||
367 | |||||
368 | /** |
||||
369 | * Given a resource type, a handle and a page, this function detaches |
||||
370 | * the given handle (which represents either a datasource or event) to that page. |
||||
371 | * |
||||
372 | * @param integer $type |
||||
373 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
374 | * @param string $r_handle |
||||
375 | * The handle of the resource. |
||||
376 | * @param integer $page_id |
||||
377 | * The ID of the page. |
||||
378 | * @return boolean |
||||
379 | */ |
||||
380 | public static function detach($type, $r_handle, $page_id) |
||||
381 | { |
||||
382 | $col = self::getColumnFromType($type); |
||||
383 | |||||
384 | $pages = PageManager::fetch(false, array($col), array(sprintf( |
||||
385 | '`id` = %d', |
||||
386 | $page_id |
||||
387 | ))); |
||||
388 | |||||
389 | if (is_array($pages) && count($pages) == 1) { |
||||
390 | $result = $pages[0][$col]; |
||||
391 | |||||
392 | $values = explode(',', $result); |
||||
393 | $idx = array_search($r_handle, $values, false); |
||||
394 | |||||
395 | if ($idx !== false) { |
||||
396 | array_splice($values, $idx, 1); |
||||
0 ignored issues
–
show
It seems like
$idx can also be of type string ; however, parameter $offset of array_splice() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
397 | $result = implode(',', $values); |
||||
398 | |||||
399 | return PageManager::edit($page_id, array( |
||||
400 | $col => MySQL::cleanValue($result) |
||||
401 | )); |
||||
402 | } |
||||
403 | } |
||||
404 | |||||
405 | return false; |
||||
406 | } |
||||
407 | |||||
408 | /** |
||||
409 | * Given a resource type, a handle and an array of pages, this function will |
||||
410 | * ensure that the resource is attached to the given pages. Note that this |
||||
411 | * function will also remove the resource from all pages that are not provided |
||||
412 | * in the `$pages` parameter. |
||||
413 | * |
||||
414 | * @since Symphony 2.4 |
||||
415 | * @param integer $type |
||||
416 | * The resource type, either `RESOURCE_TYPE_EVENT` or `RESOURCE_TYPE_DS` |
||||
417 | * @param string $r_handle |
||||
418 | * The handle of the resource. |
||||
419 | * @param array $pages |
||||
420 | * An array of Page ID's to attach this resource to. |
||||
421 | * @return boolean |
||||
422 | */ |
||||
423 | public static function setPages($type, $r_handle, $pages = array()) |
||||
0 ignored issues
–
show
|
|||||
424 | { |
||||
425 | if (!is_array($pages)) { |
||||
0 ignored issues
–
show
|
|||||
426 | $pages = array(); |
||||
427 | } |
||||
428 | |||||
429 | // Get attached pages |
||||
430 | $attached_pages = ResourceManager::getAttachedPages($type, $r_handle); |
||||
431 | $currently_attached_pages = array(); |
||||
432 | |||||
433 | foreach ($attached_pages as $page) { |
||||
434 | $currently_attached_pages[] = $page['id']; |
||||
435 | } |
||||
436 | |||||
437 | // Attach this datasource to any page that is should be attached to |
||||
438 | $diff_to_attach = array_diff($pages, $currently_attached_pages); |
||||
439 | |||||
440 | foreach ($diff_to_attach as $diff_page) { |
||||
441 | ResourceManager::attach($type, $r_handle, $diff_page); |
||||
442 | } |
||||
443 | |||||
444 | // Remove this datasource from any page where it once was, but shouldn't be anymore |
||||
445 | $diff_to_detach = array_diff($currently_attached_pages, $pages); |
||||
446 | |||||
447 | foreach ($diff_to_detach as $diff_page) { |
||||
448 | ResourceManager::detach($type, $r_handle, $diff_page); |
||||
449 | } |
||||
450 | |||||
451 | return true; |
||||
452 | } |
||||
453 | } |
||||
454 |