Skip to content

Instantly share code, notes, and snippets.

@hypeJunction
Last active August 29, 2015 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hypeJunction/8739467 to your computer and use it in GitHub Desktop.
Save hypeJunction/8739467 to your computer and use it in GitHub Desktop.
Build a tree of Elgg menu items
<?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();
<?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