/htdocs/wp-content/plugins/_gecka-submenu/models/Submenu.php

https://bitbucket.org/dkrzos/phc · PHP · 319 lines · 198 code · 98 blank · 23 comment · 56 complexity · 0acaa08674cd81db045b3e9eee3fab50 MD5 · raw file

  1. <?php
  2. Class Gecka_Submenu_Submenu {
  3. private $Options;
  4. private $DefaultOptions = array( 'menu' => '',
  5. 'container' => 'div',
  6. 'container_class' => 'submenu',
  7. 'container_id' => '',
  8. 'menu_class' => 'menu',
  9. 'menu_id' => '',
  10. 'echo' => false,
  11. 'fallback_cb' => 'wp_page_menu',
  12. 'before' => '',
  13. 'after' => '',
  14. 'link_before' => '',
  15. 'link_after' => '',
  16. 'depth' => 0,
  17. 'walker' => '',
  18. 'theme_location' => '',
  19. 'is_gk_submenu' => true,
  20. 'submenu' => null,
  21. 'child_of'=> null,
  22. 'start_from'=>null,
  23. 'type' => 'post_type',
  24. 'title' => '',
  25. 'auto_title' => false,
  26. 'show_description' => false,
  27. 'thumbnail' => null,
  28. 'auto_title' => false
  29. );
  30. // Always holds the latest Top level menu Item
  31. private $top_level_item;
  32. public function __construct ($Options = array())
  33. {
  34. $this->Options = wp_parse_args($Options, $this->DefaultOptions);
  35. }
  36. public function Show($Options = null)
  37. {
  38. echo $this->Build($Options);
  39. }
  40. public function Get($Options = null)
  41. {
  42. return $this->Build($Options);
  43. }
  44. public function get_top_level_item ()
  45. {
  46. return $this->top_level_item;
  47. }
  48. public function Widget($args, $instance)
  49. {
  50. extract( wp_parse_args($args, $this->DefaultOptions), EXTR_SKIP);
  51. $instance['container_class'] = 'submenu-widget';
  52. $instance['is_gk_submenu'] = 'widget';
  53. $out = $this->Get($instance);
  54. if($out) {
  55. $auto_title = isset($instance['auto_title']) && $instance['auto_title'] ? true : false;
  56. $title = '';
  57. if( $auto_title && $this->top_level_item) {
  58. $title = $this->top_level_item->title;
  59. }
  60. else $title = $instance['title'];
  61. $title = apply_filters('widget_title', $title, $instance);
  62. echo $before_widget;
  63. if($title) {
  64. echo $before_title . apply_filters('widget_title', $title, $instance) . $after_title;
  65. }
  66. echo $out;
  67. echo $after_widget;
  68. }
  69. }
  70. private function Build($Options = null)
  71. {
  72. if( $Options !== null ) $Options = wp_parse_args($Options, $this->Options) ;
  73. else $Options = $this->Options;
  74. $Options = wp_parse_args($Options, $this->DefaultOptions);
  75. extract($Options);
  76. $depth = (int)$depth;
  77. if(isset($child_of) && $child_of) $submenu = $child_of;
  78. if(isset($start_from) && $start_from) $submenu = $start_from;
  79. // if no menu specified, gets the lowest ID menu
  80. if(!$menu || !is_nav_menu($menu)) {
  81. $menus = wp_get_nav_menus();
  82. foreach ( $menus as $menu_maybe ) {
  83. if ( $menu_items = wp_get_nav_menu_items($menu_maybe->term_id) ) {
  84. $menu = $menu_maybe->term_id;
  85. break;
  86. }
  87. }
  88. }
  89. // still can't find a menu, we exit
  90. if(!$menu || !is_nav_menu($menu)) return;
  91. /* WPML support */
  92. if( function_exists('icl_object_id') ) {
  93. global $sitepress;
  94. /* not default language */
  95. if(ICL_LANGUAGE_CODE !== $sitepress->get_default_language() ) {
  96. $translated_menu_id = icl_object_id($menu, 'nav_menu');
  97. $menu = $translated_menu_id ? $translated_menu_id : $menu;
  98. }
  99. }
  100. /* */
  101. $menu_items = wp_get_nav_menu_items($menu);
  102. if(is_tax() || is_category()) $_type = 'taxonomy';
  103. else $_type = 'post_type';
  104. // current page is top level element
  105. if( $submenu === 'current' ) {
  106. global $wp_query;
  107. $submenu = $this->get_associated_nav_menu_item($wp_query->get_queried_object_id(), $menu_items, $_type);
  108. }
  109. // top parent page is the top level element
  110. else if( $submenu === 'top' ) {
  111. global $post, $wp_query;
  112. if( is_a($post, 'stdClass') && (int)$post->ID ) {
  113. if( $submenu = $this->get_top_ancestor ($wp_query->get_queried_object_id(), $menu_items, $_type) )
  114. $submenu = $submenu->ID;
  115. }
  116. }
  117. // a submenu has been specified
  118. if( $submenu !== 0 ) {
  119. if(!$submenu) return;
  120. $submenu_item = $submenu;
  121. if( !is_object($submenu) ) {
  122. $submenu_item = $this->get_menu_item ($submenu, $menu_items);
  123. if( !$submenu_item ) $submenu_item = $this->get_associated_nav_menu_item($submenu, $menu_items, $type);
  124. if(!$submenu_item) return;
  125. }
  126. if( !$this->menu_item_has_child($submenu_item->ID, $menu_items)) return;
  127. $submenu_id = $submenu_item->ID;
  128. $this->top_level_item = $submenu_item;
  129. global $GKSM_ID, $GKSM_MENUID;
  130. $menu_object = wp_get_nav_menu_object($menu);
  131. $GKSM_ID = $submenu_id; $GKSM_MENUID = $menu_object->term_id;
  132. }
  133. if(!strpos($container_class, ' ')) {
  134. $slug = '';
  135. if( !empty($GLOBALS['wp_query']->get_queried_object()->post_name) ) $slug = $GLOBALS['wp_query']->get_queried_object()->post_name;
  136. else if( !empty($GLOBALS['wp_query']->get_queried_object()->$slug) ) $slug = $GLOBALS['wp_query']->get_queried_object()->slug;
  137. $container_class .= " $container_class-" . $slug ;
  138. }// gets the nav menu
  139. $args = array( 'container_class' => $container_class,
  140. 'menu'=> $menu,
  141. 'show_description'=> $show_description,
  142. 'depth'=>$depth,
  143. 'is_gk_submenu'=>$is_gk_submenu );
  144. $out = wp_nav_menu( wp_parse_args($args, $Options) );
  145. // reset global variables
  146. $GKSM_ID = $GKSM_MENUID = null;
  147. return $out;
  148. }
  149. /**
  150. * Gets a menu item from a list of menu items, avoiding SQL queries
  151. * @param int $item_id id of item to retreive
  152. * @param array $menu_items array of menu items
  153. * @return object $Item a menu item object or false
  154. */
  155. private function get_menu_item ($item_id, $menu_items) {
  156. if(!is_array($menu_items)) return false;
  157. foreach($menu_items as $Item) {
  158. if($Item->ID == $item_id) return $Item;
  159. }
  160. return false;
  161. }
  162. private function menu_item_has_child ($item_id, $menu_items) {
  163. if(!is_array($menu_items)) return false;
  164. foreach($menu_items as $Item) {
  165. if($Item->menu_item_parent == $item_id) return true;
  166. }
  167. return false;
  168. }
  169. public function get_associated_nav_menu_item($object_id, $menu_items, $type='post_type', $offset=0) {
  170. $offset = abs( (int)$offset );
  171. $AssociatedMenuItems = $this->get_associated_nav_menu_items( $object_id, $menu_items, $type );
  172. if( !$num = sizeof($AssociatedMenuItems) ) return false;
  173. if($offset>$num) $offset = $num-1;
  174. return $AssociatedMenuItems[$offset];
  175. }
  176. function get_associated_nav_menu_items( $object_id, $menu_items, $object_type = 'post_type') {
  177. $object_id = (int) $object_id;
  178. $_menu_items = array();
  179. foreach( $menu_items as $menu_item ) {
  180. if($menu_item->object_id == $object_id && $menu_item->type === $object_type) {
  181. $_menu_items[] = $menu_item;
  182. }
  183. }
  184. if( !empty($_menu_items) || $object_type !== 'post_type' ) return $_menu_items;
  185. // no associated 'post_type' menu item found, looking for associated 'taxonomy' menu item
  186. return $this->get_associated_nav_menu_terms_items ( $object_id, $menu_items );
  187. }
  188. function get_associated_nav_menu_terms_items ( $object_id, $menu_items ) {
  189. $post = get_post($object_id);
  190. if(!$post) return array();
  191. $_menu_items = array();
  192. $taxonomies = get_object_taxonomies($post->post_type);
  193. foreach ($taxonomies as $taxonomy) {
  194. if( !$terms = get_the_terms( $object_id, $taxonomy ) ) continue;
  195. foreach ($terms as $term) {
  196. $_menu_items = $this->get_associated_nav_menu_items($term->term_id, $menu_items, 'taxonomy');
  197. if( !empty($_menu_items) ) return $_menu_items;
  198. }
  199. }
  200. return $_menu_items;
  201. }
  202. /**
  203. * Gets the top parent menu item of a given post from a specific menu
  204. * @param int $menu menu ID to seach for post
  205. * @param int $postID post ID to look for
  206. * @return object $Item a menu item object or false
  207. */
  208. private function get_top_ancestor ($postID, $menu_items, $type='post_type') {
  209. $Item = $this->get_associated_nav_menu_item($postID, $menu_items, $type);
  210. if(!$Item) return;
  211. $Ancestror = $Item;
  212. while(1) {
  213. if($Item->menu_item_parent) {
  214. $Item = $this->get_menu_item($Item->menu_item_parent, $menu_items);
  215. continue;
  216. }
  217. break;
  218. }
  219. return $Item;
  220. }
  221. }