Instantly share code, notes, and snippets.
Last active
August 29, 2015 13:55
-
Save hypeJunction/8739467 to your computer and use it in GitHub Desktop.
Build a tree of Elgg menu items
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace hypeJunction\Util; | |
require_once __DIR__ . '/MenuScraper.php'; | |
MenuScraper::setContexts(array('profile', 'profile_edit', 'projects', 'groups', 'group_profile', 'friends')); | |
MenuScraper::setMenus(array('topbar', 'page', 'project')); | |
$items = MenuScraper::getItems(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @author Ismayil Khayredinov <ismayil.khayredinov@gmail.com> | |
* @package hypeJunction | |
* @subpackage Util | |
* | |
* This class attemps to build a tree of menu items that are registered | |
* throught the plugins | |
* The list of items is not definitive | |
* @todo: add logic for scraping 'title' menu | |
* | |
* You can get a tree of scraped items by calling \hypeJunction\Util\MenuScraper::getTree() | |
*/ | |
namespace hypeJunction\Util; | |
class MenuScraper { | |
private static $instance; | |
protected $priorContextStack; | |
protected $posteriorContextStack; | |
protected $includeContextStack; | |
protected $ignoreContextStack; | |
protected $registeredHooks; | |
protected $registeredMenuHooks; | |
protected $originalMenuRegister; | |
protected $menuRegister; | |
protected $menuTree; | |
protected $menuNames; | |
public function scrape() { | |
$this->constructContextStack(); | |
$this->constructMenuRegister(); | |
$this->fillMenuRegister(); | |
$this->buildTree(); | |
$this->reconstructContextStack(); | |
return $this->menuTree; | |
} | |
private function constructContextStack() { | |
$this->priorContextStack = elgg_get_config('context'); | |
if (!isset($this->ignoreContextStack)) { | |
$this->ignoreContextStack = array(); | |
} | |
if (!isset($this->posteriorContextStack)) { | |
$this->posteriorContextStack = array(); | |
$pageHandlers = elgg_get_config('pagehandler'); | |
foreach ($pageHandlers as $pagename => $p) { | |
array_push($this->posteriorContextStack, $pagename); | |
} | |
$inlineContexts = array( | |
'main', 'profile_edit', 'widgets', 'default_widgets', 'create_default_widgets', 'input', 'group_profile', 'owner_block' | |
); | |
foreach ($inlineContexts as $context) { | |
array_push($this->posteriorContextStack, $context); | |
} | |
} | |
$this->posteriorContextStack = array_diff($this->posteriorContextStack, $this->ignoreContextStack); | |
if (is_array($this->includeContextStack)) { | |
$this->posteriorContextStack = array_merge($this->posteriorContextStack, $this->includeContextStack); | |
} | |
elgg_set_config('context', $this->posteriorContextStack); | |
} | |
private function reconstructContextStack() { | |
elgg_set_config('context', $this->priorContextStack); | |
} | |
private function constructMenuRegister() { | |
$this->menuRegister = elgg_get_config('menus'); | |
$this->registeredHooks = elgg_get_config('hooks'); | |
$this->registeredMenuHooks = $this->registeredHooks['register']; | |
foreach ($this->registeredMenuHooks as $hook_name => $params) { | |
// get the hooks for 'register','menu:$menu_name' | |
list($namespace, $menu_name) = explode(':', $hook_name); | |
if ($namespace == 'menu' && !isset($this->menuRegister[$menu_name])) { | |
$this->menuRegister[$menu_name] = array(); | |
} | |
} | |
foreach ($this->menuRegister as $menuName => $menuItems) { | |
if (isset($this->menuNames) && is_array($this->menuNames) && !in_array($menuName, $this->menuNames)) { | |
unset($this->menuRegister[$menuName]); | |
continue; | |
} | |
$this->menuRegister[$menuName] = $this->prepareMenuItems($menuItems); | |
} | |
foreach ($this->menuNames as $menuName) { | |
if (!array_key_exists($menuName, $this->menuRegister)) { | |
$this->menuRegister[$menu_name] = array(); | |
} | |
} | |
} | |
private function fillMenuRegister() { | |
foreach ($this->menuRegister as $menuName => $menuItems) { | |
switch ($menuName) { | |
case 'river' : | |
$entities = self::getUniqueRiverItems(); | |
break; | |
case 'annotation' : | |
$entities = self::getUniqueAnnotations(); | |
break; | |
default : | |
$entities = self::getUniqueEntities(); | |
break; | |
} | |
foreach ($entities as $entity) { | |
$hookParams = self::getHookParams($menuName, $entity); | |
if (!$hookParams) | |
continue; | |
$hookCallList = $this->registeredMenuHooks["menu:$menuName"]; | |
if (is_array($hookCallList)) { | |
foreach ($hookCallList as $hookCallBack) { | |
if (is_callable($hookCallBack)) { | |
$args = array('register', "menu:$menuName", array(), $hookParams); | |
$hookMenuItems = call_user_func_array($hookCallBack, $args); | |
if (is_array($hookMenuItems)) { | |
$menu = $this->prepareMenuItems($hookMenuItems); | |
$menuItems += $menu; | |
} | |
} | |
} | |
} | |
} | |
$this->menuRegister[$menuName] = $menuItems; | |
} | |
} | |
private function buildTree() { | |
foreach ($this->menuRegister as $menuName => $menuItems) { | |
$menu = new \ElggMenuBuilder($menuItems); | |
//$tree = elgg_trigger_plugin_hook('prepare', "menu:$menuName", array(), $menu->getMenu('text')); | |
$this->menuTree[$menuName] = $menu->getMenu('text'); | |
} | |
return ($menuName) ? $this->menuTree[$menuName] : $this->menuTree; | |
} | |
private function prepareMenuItems($menuArray) { | |
if (!is_array($menuArray)) { | |
$menuArray = array(); | |
} | |
$formattedArray = array(); | |
foreach ($menuArray as $item) { | |
if (!($item instanceof \ElggMenuItem)) { | |
continue; | |
} | |
$itemName = $item->getName(); | |
$formattedArray[$itemName] = $item; | |
} | |
return $formattedArray; | |
} | |
private static function getUniqueEntities() { | |
$ia = elgg_set_ignore_access(); | |
$entities = elgg_get_entities(array( | |
'group_by' => 'e.subtype', | |
'limit' => 0 | |
)); | |
elgg_set_ignore_access($ia); | |
return $entities; | |
} | |
private static function getUniqueRiverItems() { | |
$ia = elgg_set_ignore_access(); | |
$river = elgg_get_river(array( | |
'group_by' => 'rv.action_type', | |
'limit' => 0 | |
)); | |
elgg_set_ignore_access($ia); | |
return $river; | |
} | |
private static function getUniqueAnnotations() { | |
$ia = elgg_set_ignore_access(); | |
$annotations = elgg_get_annotations(array( | |
'group_by' => 'name', | |
'limit' => 0, | |
)); | |
elgg_set_ignore_access($ia); | |
return $annotations; | |
} | |
private static function getHookParams($menuName, $entity) { | |
$hookParams = array( | |
'entity' => $entity, | |
); | |
switch ($menuName) { | |
case 'river' : | |
$hookParams = array( | |
'item' => $entity | |
); | |
break; | |
case 'annotation' : | |
$hookParams = array( | |
'annotation' => $entity | |
); | |
break; | |
case 'entity' : | |
if (!elgg_instanceof($entity)) { | |
$hookParams = null; | |
} else { | |
$hookParams['handler'] = $entity->getSubtype(); | |
} | |
break; | |
case 'user_hover' : | |
if (!elgg_instanceof($entity, 'user')) { | |
$hookParams = null; | |
} | |
break; | |
case 'widget' : | |
if (!elgg_instanceof($entity, 'object', 'widget')) { | |
$hookParams = null; | |
} | |
break; | |
} | |
return $hookParams; | |
} | |
public static function getInstance() { | |
if (!isset(self::$instance)) { | |
$class = __CLASS__; | |
self::$instance = new $class; | |
} | |
return self::$instance; | |
} | |
public static function setMenus($names) { | |
$instance = self::getInstance(); | |
$instance->menuNames = $names; | |
} | |
public static function includeContexts($contexts) { | |
$instance = self::getInstance(); | |
$instance->includeContextStack = $contexts; | |
} | |
public static function setContexts($contexts) { | |
$instance = self::getInstance(); | |
$instance->posteriorContextStack = $contexts; | |
} | |
public static function setIgnoreContexts($contexts) { | |
$instance = self::getInstance(); | |
$instance->ignoreContextStack = $contexts; | |
} | |
public static function getItems($menuName = null) { | |
$instance = self::getInstance(); | |
$instance->scrape(); | |
return ($menuName) ? $instance->menuRegister[$menuName] : $instance->menuRegister; | |
} | |
public static function getTree($menuName = null) { | |
$instance = self::getInstance(); | |
$instance->scrape(); | |
return ($menuName) ? $instance->menuTree[$menuName] : $instance->menuTree; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment