/** * Add a menu item as a template. * * @param array $wpItem * @param int $position * @param string|null $parent */ private function addItem($wpItem, $position, $parent = null) { $item = ameMenuItem::fromWpItem($wpItem, $position, $parent); //Skip separators. if ($item['separator']) { $this->wasPreviousItemSeparated = true; return; } //Skip blacklisted menus. if (isset($item['url'], $this->blacklist[$item['url']])) { return; } $name = $this->sanitizeMenuTitle($item['menu_title']); if ($parent === null) { $this->parentNames[$item['file']] = $name; } else { $name = $this->parentNames[$parent] . ' -> ' . $name; } $templateId = ameMenuItem::template_id($item); $this->templates[$templateId] = array('name' => $name, 'used' => false, 'defaults' => $item); //Remember the relative order of menu items. It's a bit like a linked list. $this->templateOrder[$templateId] = array('previous_item' => $this->previousItemId, 'was_previous_item_separated' => $this->wasPreviousItemSeparated); $this->previousItemId = $templateId; $this->wasPreviousItemSeparated = false; }
/** * Merge a custom menu with the current default WordPress menu. Adds/replaces defaults, * inserts new items and removes missing items. * * @uses self::$item_templates * * @param array $tree A menu in plugin's internal form * @return array Updated menu tree */ function menu_merge($tree) { //Iterate over all menus and submenus and look up default values //Also flag used and missing items. $orphans = array(); foreach ($tree as &$topmenu) { if (!ameMenuItem::get($topmenu, 'custom')) { $template_id = ameMenuItem::template_id($topmenu); //Is this menu present in the default WP menu? if (isset($this->item_templates[$template_id])) { //Yes, load defaults from that item $topmenu['defaults'] = $this->item_templates[$template_id]['defaults']; //Note that the original item was used $this->item_templates[$template_id]['used'] = true; } else { //Record the menu as missing, unless it's a menu separator if (empty($topmenu['separator'])) { $topmenu['missing'] = true; $temp = ameMenuItem::apply_defaults($topmenu); $temp = $this->set_final_menu_capability($temp); $this->add_access_lookup($temp, 'menu', true); } } } if (is_array($topmenu['items'])) { //Iterate over submenu items foreach ($topmenu['items'] as &$item) { if (!ameMenuItem::get($item, 'custom')) { $template_id = ameMenuItem::template_id($item); //Is this item present in the default WP menu? if (isset($this->item_templates[$template_id])) { //Yes, load defaults from that item $item['defaults'] = $this->item_templates[$template_id]['defaults']; $this->item_templates[$template_id]['used'] = true; //We must move orphaned items elsewhere. Use the default location if possible. if (isset($topmenu['missing']) && $topmenu['missing']) { $orphans[] = $item; } } else { if (empty($item['separator'])) { //Record as missing, unless it's a menu separator $item['missing'] = true; $temp = ameMenuItem::apply_defaults($item); $temp = $this->set_final_menu_capability($temp); $this->add_access_lookup($temp, 'submenu', true); } } } else { //What if the parent of this custom item is missing? //Right now the custom item will just disappear. } } } } //If we don't unset these they will f**k up the next two loops where the same names are used. unset($topmenu); unset($item); //Now we have some items marked as missing, and some items in lookup arrays //that are not marked as used. Lets remove the missing items from the tree. $tree = ameMenu::remove_missing_items($tree); //Lets merge in the unused items. foreach ($this->item_templates as $template_id => $template) { //Skip used menus and separators if (!empty($template['used']) || !empty($template['defaults']['separator'])) { continue; } //Found an unused item. Build the tree entry. $entry = ameMenuItem::blank_menu(); $entry['template_id'] = $template_id; $entry['defaults'] = $template['defaults']; $entry['unused'] = true; //Note that this item is unused //Add the new entry to the menu tree if (!empty($template['defaults']['parent'])) { if (isset($tree[$template['defaults']['parent']])) { //Okay, insert the item. $tree[$template['defaults']['parent']]['items'][] = $entry; } else { //This can happen if the original parent menu has been moved to a submenu. $tree[$template['defaults']['file']] = $entry; } } else { $tree[$template['defaults']['file']] = $entry; } } //Move orphaned items back to their original parents. foreach ($orphans as $item) { $defaultParent = !empty($item['defaults']['parent']) ? $item['defaults']['parent'] : null; if (isset($defaultParent) && isset($tree[$defaultParent])) { $tree[$defaultParent]['items'][] = $item; } else { //This can happen if the parent has been moved to a submenu. //Just put the orphan at the bottom of the menu. $tree[$item['defaults']['file']] = $item; } } //Resort the tree to ensure the found items are in the right spots $tree = ameMenu::sort_menu_tree($tree); return $tree; }
/** * Merge a custom menu with the current default WordPress menu. Adds/replaces defaults, * inserts new items and removes missing items. * * @uses self::$item_templates * * @param array $tree A menu in plugin's internal form * @return array Updated menu tree */ function menu_merge($tree) { //Iterate over all menus and submenus and look up default values foreach ($tree as &$topmenu) { if (!ameMenuItem::get($topmenu, 'custom')) { $template_id = ameMenuItem::template_id($topmenu); //Is this menu present in the default WP menu? if (isset($this->item_templates[$template_id])) { //Yes, load defaults from that item $topmenu['defaults'] = $this->item_templates[$template_id]['defaults']; //Note that the original item was used $this->item_templates[$template_id]['used'] = true; } else { //Record the menu as missing, unless it's a menu separator if (empty($topmenu['separator'])) { $topmenu['missing'] = true; $temp = ameMenuItem::apply_defaults($topmenu); $temp['access_level'] = $this->get_menu_capability($temp); $this->add_access_lookup($temp, 'menu', true); } } } if (is_array($topmenu['items'])) { //Iterate over submenu items foreach ($topmenu['items'] as &$item) { if (!ameMenuItem::get($item, 'custom')) { $template_id = ameMenuItem::template_id($item); //Is this item present in the default WP menu? if (isset($this->item_templates[$template_id])) { //Yes, load defaults from that item $item['defaults'] = $this->item_templates[$template_id]['defaults']; $this->item_templates[$template_id]['used'] = true; } else { if (empty($item['separator'])) { //Record as missing, unless it's a menu separator $item['missing'] = true; $temp = ameMenuItem::apply_defaults($item); $temp['access_level'] = $this->get_menu_capability($temp); $this->add_access_lookup($temp, 'submenu', true); } } } } } } //If we don't unset these they will f**k up the next two loops where the same names are used. unset($topmenu); unset($item); //Now we have some items marked as missing, and some items in lookup arrays //that are not marked as used. Lets remove the missing items from the tree. $filteredTree = array(); foreach ($tree as $file => $topmenu) { if ($topmenu['missing']) { continue; } $filteredSubmenu = array(); if (is_array($topmenu['items'])) { foreach ($topmenu['items'] as $index => $item) { if (!$item['missing']) { $filteredSubmenu[$index] = $item; } } } $topmenu['items'] = $filteredSubmenu; $filteredTree[$file] = $topmenu; } $tree = $filteredTree; //Lets merge in the unused items. foreach ($this->item_templates as $template_id => $template) { //Skip used menus and separators if (!empty($template['used']) || !empty($template['defaults']['separator'])) { continue; } //Found an unused item. Build the tree entry. $entry = ameMenuItem::blank_menu(); $entry['template_id'] = $template_id; $entry['defaults'] = $template['defaults']; $entry['unused'] = true; //Note that this item is unused //Add the new entry to the menu tree if (!empty($template['defaults']['parent'])) { if (isset($tree[$template['defaults']['parent']])) { //Okay, insert the item. $tree[$template['defaults']['parent']]['items'][] = $entry; } else { //This can happen if the original parent menu has been moved to a submenu. //Todo: Handle this unusual situation. } } else { $tree[$template['defaults']['file']] = $entry; } } //Resort the tree to ensure the found items are in the right spots $tree = ameMenu::sort_menu_tree($tree); return $tree; }