Elgg  Version 1.9
ElggMenuBuilder.php
Go to the documentation of this file.
1 <?php
10 
14  protected $menu = array();
15 
16  protected $selected = null;
17 
23  public function __construct(array $menu) {
24  $this->menu = $menu;
25  }
26 
33  public function getMenu($sort_by = 'text') {
34 
35  $this->selectFromContext();
36 
37  $this->selected = $this->findSelected();
38 
39  $this->setupSections();
40 
41  $this->setupTrees();
42 
43  $this->sort($sort_by);
44 
45  return $this->menu;
46  }
47 
53  public function getSelected() {
54  return $this->selected;
55  }
56 
62  protected function selectFromContext() {
63  if (!isset($this->menu)) {
64  $this->menu = array();
65  return;
66  }
67 
68  // get menu items for this context
69  $selected_menu = array();
70  foreach ($this->menu as $menu_item) {
71  if (!is_object($menu_item)) {
72  elgg_log("A non-object was passed to ElggMenuBuilder", "ERROR");
73  continue;
74  }
75  if ($menu_item->inContext()) {
76  $selected_menu[] = $menu_item;
77  }
78  }
79 
80  $this->menu = $selected_menu;
81  }
82 
88  protected function setupSections() {
89  $sectioned_menu = array();
90  foreach ($this->menu as $menu_item) {
91  if (!isset($sectioned_menu[$menu_item->getSection()])) {
92  $sectioned_menu[$menu_item->getSection()] = array();
93  }
94  $sectioned_menu[$menu_item->getSection()][] = $menu_item;
95  }
96  $this->menu = $sectioned_menu;
97  }
98 
105  protected function setupTrees() {
106  $menu_tree = array();
107 
108  foreach ($this->menu as $key => $section) {
109  $parents = array();
110  $children = array();
111  // divide base nodes from children
112  foreach ($section as $menu_item) {
113  /* @var ElggMenuItem $menu_item */
114  $parent_name = $menu_item->getParentName();
115  if (!$parent_name) {
116  $parents[$menu_item->getName()] = $menu_item;
117  } else {
118  $children[] = $menu_item;
119  }
120  }
121 
122  // attach children to parents
123  $iteration = 0;
124  $current_gen = $parents;
125  $next_gen = null;
126  while (count($children) && $iteration < 20) {
127  foreach ($children as $index => $menu_item) {
128  $parent_name = $menu_item->getParentName();
129  if (array_key_exists($parent_name, $current_gen)) {
130  $next_gen[$menu_item->getName()] = $menu_item;
131  if (!in_array($menu_item, $current_gen[$parent_name]->getData('children'))) {
132  $current_gen[$parent_name]->addChild($menu_item);
133  $menu_item->setParent($current_gen[$parent_name]);
134  }
135  unset($children[$index]);
136  }
137  }
138  $current_gen = $next_gen;
139  $iteration += 1;
140  }
141 
142  // convert keys to indexes for first level of tree
143  $parents = array_values($parents);
144 
145  $menu_tree[$key] = $parents;
146  }
147 
148  $this->menu = $menu_tree;
149  }
150 
156  protected function findSelected() {
157 
158  // do we have a selected menu item already
159  foreach ($this->menu as $menu_item) {
160  if ($menu_item->getSelected()) {
161  return $menu_item;
162  }
163  }
164 
165  // scan looking for a selected item
166  foreach ($this->menu as $menu_item) {
167  if ($menu_item->getHref()) {
168  if (elgg_http_url_is_identical(current_page_url(), $menu_item->getHref())) {
169  $menu_item->setSelected(true);
170  return $menu_item;
171  }
172  }
173  }
174 
175  return null;
176  }
177 
184  protected function sort($sort_by) {
185 
186  // sort sections
187  ksort($this->menu);
188 
189  switch ($sort_by) {
190  case 'text':
191  $sort_callback = array('ElggMenuBuilder', 'compareByText');
192  break;
193  case 'name':
194  $sort_callback = array('ElggMenuBuilder', 'compareByName');
195  break;
196  case 'priority':
197  $sort_callback = array('ElggMenuBuilder', 'compareByPriority');
198  break;
199  case 'register':
200  // use registration order - usort breaks this
201  return;
202  break;
203  default:
204  if (is_callable($sort_by)) {
205  $sort_callback = $sort_by;
206  } else {
207  return;
208  }
209  break;
210  }
211 
212  // sort each section
213  foreach ($this->menu as $index => $section) {
214  foreach ($section as $key => $node) {
215  $section[$key]->setData('original_order', $key);
216  }
217  usort($section, $sort_callback);
218  $this->menu[$index] = $section;
219 
220  // depth first traversal of tree
221  foreach ($section as $root) {
222  $stack = array();
223  array_push($stack, $root);
224  while (!empty($stack)) {
225  $node = array_pop($stack);
226  /* @var ElggMenuItem $node */
227  $node->sortChildren($sort_callback);
228  $children = $node->getChildren();
229  if ($children) {
230  $stack = array_merge($stack, $children);
231  }
232  }
233  }
234  }
235  }
236 
244  public static function compareByText($a, $b) {
245  $at = $a->getText();
246  $bt = $b->getText();
247 
248  $result = strnatcmp($at, $bt);
249  if ($result === 0) {
250  return $a->getData('original_order') - $b->getData('original_order');
251  }
252  return $result;
253  }
254 
262  public static function compareByName($a, $b) {
263  $an = $a->getName();
264  $bn = $b->getName();
265 
266  $result = strnatcmp($an, $bn);
267  if ($result === 0) {
268  return $a->getData('original_order') - $b->getData('original_order');
269  }
270  return $result;
271  }
272 
281  public static function compareByPriority($a, $b) {
282  $aw = $a->getPriority();
283  $bw = $b->getPriority();
284 
285  if ($aw == $bw) {
286  return $a->getData('original_order') - $b->getData('original_order');
287  }
288  return $aw - $bw;
289  }
290 
299  public static function compareByWeight($a, $b) {
300  elgg_deprecated_notice("ElggMenuBuilder::compareByWeight() deprecated by ElggMenuBuilder::compareByPriority", 1.9);
301  $aw = $a->getPriority();
302  $bw = $b->getPriority();
303 
304  if ($aw == $bw) {
305  return $a->getData('original_order') - $b->getData('original_order');
306  }
307  return $aw - $bw;
308  }
309 }
elgg icon hover menu
Definition: admin.php:1303
__construct(array $menu)
ElggMenuBuilder constructor.
current_page_url()
Returns the current page&#39;s complete URL.
Definition: input.php:106
elgg_http_url_is_identical($url1, $url2, $ignore_params=array('offset', 'limit'))
Test if two URLs are functionally identical.
Definition: elgglib.php:1369
static compareByWeight($a, $b)
Compare two menu items by their priority.
static compareByText($a, $b)
Compare two menu items by their display text.
setupTrees()
Create trees for each menu section.
getMenu($sort_by= 'text')
Get a prepared menu array.
getSelected()
Get the selected menu item.
$key
Definition: summary.php:34
static compareByName($a, $b)
Compare two menu items by their identifiers.
elgg_deprecated_notice($msg, $dep_version, $backtrace_level=1)
Sends a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:1171
findSelected()
Find the menu item that is currently selected.
sort($sort_by)
Sort the menu sections and trees.
elgg_log($message, $level= 'NOTICE')
Display or log a message.
Definition: elgglib.php:1083
if($item->getSelected()) $children
Definition: item.php:21
setupSections()
Group the menu items into sections.
static compareByPriority($a, $b)
Compare two menu items by their priority.
selectFromContext()
Select menu items for the current context.