1 | <?php |
||
2 | namespace Elgg\Menu; |
||
3 | |||
4 | use Elgg\PluginHooksService; |
||
5 | use Elgg\Config; |
||
6 | use ElggMenuBuilder; |
||
7 | use ElggMenuItem; |
||
8 | |||
9 | /** |
||
10 | * Methods to construct and prepare menus for rendering |
||
11 | */ |
||
12 | class Service { |
||
13 | |||
14 | /** |
||
15 | * @var PluginHooksService |
||
16 | */ |
||
17 | private $hooks; |
||
18 | |||
19 | /** |
||
20 | * @var Config |
||
21 | */ |
||
22 | private $config; |
||
23 | |||
24 | /** |
||
25 | * Constructor |
||
26 | * |
||
27 | * @param PluginHooksService $hooks Plugin hooks |
||
28 | * @param Config $config Elgg config |
||
29 | * @access private |
||
30 | * @internal Do not use. Use `elgg()->menus`. |
||
31 | */ |
||
32 | 3 | public function __construct(PluginHooksService $hooks, Config $config) { |
|
33 | 3 | $this->hooks = $hooks; |
|
34 | 3 | $this->config = $config; |
|
35 | 3 | } |
|
36 | |||
37 | /** |
||
38 | * Build a full menu, pulling items from configuration and the "register" menu hooks. |
||
39 | * |
||
40 | * Parameters are filtered by the "parameters" hook. |
||
41 | * |
||
42 | * @param string $name Menu name |
||
43 | * @param array $params Hook/view parameters |
||
44 | * |
||
45 | * @return Menu |
||
46 | */ |
||
47 | 33 | public function getMenu($name, array $params = []) { |
|
48 | 33 | return $this->prepareMenu($this->getUnpreparedMenu($name, $params)); |
|
49 | } |
||
50 | |||
51 | /** |
||
52 | * Build an unprepared menu. |
||
53 | * |
||
54 | * @param string $name Menu name |
||
55 | * @param array $params Hook/view parameters |
||
56 | * |
||
57 | * @return UnpreparedMenu |
||
58 | */ |
||
59 | 33 | public function getUnpreparedMenu($name, array $params = []) { |
|
60 | 33 | $menus = $this->config->menus; |
|
61 | |||
62 | 33 | $items = $this->prepareMenuItems(elgg_extract('items', $params, [])); |
|
63 | 33 | unset($params['items']); |
|
64 | |||
65 | 33 | if ($menus && isset($menus[$name])) { |
|
66 | 12 | $registered_items = elgg_extract($name, $menus, []); |
|
67 | 12 | $items = array_merge($items, $registered_items); |
|
68 | } |
||
69 | |||
70 | 33 | $params['name'] = $name; |
|
71 | |||
72 | 33 | $params = $this->hooks->trigger('parameters', "menu:$name", $params, $params); |
|
73 | |||
74 | 33 | if (!isset($params['sort_by'])) { |
|
75 | 17 | $params['sort_by'] = 'text'; |
|
76 | } |
||
77 | |||
78 | 33 | $items = $this->hooks->trigger('register', "menu:$name", $params, $items); |
|
79 | |||
80 | 33 | return new UnpreparedMenu($params, $items); |
|
81 | } |
||
82 | |||
83 | /** |
||
84 | * Split a menu into sections, and pass it through the "prepare" hook |
||
85 | * |
||
86 | * @param UnpreparedMenu $menu Menu |
||
87 | * |
||
88 | * @return Menu |
||
89 | */ |
||
90 | 33 | public function prepareMenu(UnpreparedMenu $menu) { |
|
91 | 33 | $name = $menu->getName(); |
|
92 | 33 | $params = $menu->getParams(); |
|
93 | 33 | $sort_by = $menu->getSortBy(); |
|
94 | |||
95 | 33 | $builder = new ElggMenuBuilder($menu->getItems()); |
|
96 | 33 | $params['menu'] = $builder->getMenu($sort_by); |
|
97 | 33 | $params['selected_item'] = $builder->getSelected(); |
|
98 | |||
99 | 33 | $params['menu'] = $this->hooks->trigger('prepare', "menu:$name", $params, $params['menu']); |
|
100 | |||
101 | 33 | return new Menu($params); |
|
102 | } |
||
103 | |||
104 | /** |
||
105 | * Combine several menus into one |
||
106 | * |
||
107 | * Unprepared menus will be built separately, then combined, with items reassigned to sections |
||
108 | * named after their origin menu. The returned menu must be prepared before display. |
||
109 | * |
||
110 | * @param string[] $names Menu names |
||
111 | * @param array $params Menu params |
||
112 | * @param string $new_name Combined menu name (used for the prepare hook) |
||
113 | * |
||
114 | * @return UnpreparedMenu |
||
115 | */ |
||
116 | function combineMenus(array $names = [], array $params = [], $new_name = '') { |
||
0 ignored issues
–
show
|
|||
117 | if (!$new_name) { |
||
118 | $new_name = implode('__', $names); |
||
119 | } |
||
120 | |||
121 | $all_items = []; |
||
122 | foreach ($names as $name) { |
||
123 | $items = $this->getUnpreparedMenu($name, $params)->getItems(); |
||
124 | |||
125 | foreach ($items as $item) { |
||
126 | $section = $item->getSection(); |
||
127 | if ($section == 'default') { |
||
128 | $item->setSection($name); |
||
129 | } |
||
130 | $item->setData('menu_name', $name); |
||
131 | $all_items[] = $item; |
||
132 | } |
||
133 | } |
||
134 | |||
135 | $params['name'] = $new_name; |
||
136 | |||
137 | return new UnpreparedMenu($params, $all_items); |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * Prepare menu items |
||
142 | * |
||
143 | * @param array $items An array of ElggMenuItem instances or menu item factory options |
||
144 | * @return ElggMenuItem[] |
||
145 | */ |
||
146 | 33 | public function prepareMenuItems(array $items = []) { |
|
147 | 33 | $prepared_items = []; |
|
148 | |||
149 | 33 | foreach ($items as $item) { |
|
150 | 2 | if (is_array($item)) { |
|
151 | 2 | $options = $item; |
|
152 | 2 | $item = ElggMenuItem::factory($options); |
|
153 | } |
||
154 | |||
155 | 2 | if (!$item instanceof ElggMenuItem) { |
|
156 | continue; |
||
157 | } |
||
158 | |||
159 | 2 | $prepared_items[] = $item; |
|
160 | } |
||
161 | |||
162 | 33 | return $prepared_items; |
|
163 | } |
||
164 | } |
||
165 |
Adding explicit visibility (
private
,protected
, orpublic
) is generally recommend to communicate to other developers how, and from where this method is intended to be used.