diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5dfbb4c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/* +node_modules/* \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..7c84238 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,50 @@ +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + copy: { + main: { + files: [ + {expand: true, src: ['assets/**'], dest: 'build/'}, + {expand: true, src: ['views/**'], dest: 'build/'}, + {expand: true, src: ['walkers/**'], dest: 'build/'}, + {expand: false, src: ['readme.txt'], dest: 'build/readme.txt'}, + {expand: false, src: ['screenshot-1.png'], dest: 'build/screenshot-1.png'}, + {expand: false, src: ['screenshot-2.png'], dest: 'build/screenshot-2.png'}, + {expand: false, src: ['screenshot-3.png'], dest: 'build/screenshot-3.png'}, + {expand: false, src: ['screenshot-4.png'], dest: 'build/screenshot-4.png'}, + {expand: false, src: ['submenu.php'], dest: 'build/submenu.php'}, + {expand: false, src: ['SubmenuAdmin.php'], dest: 'build/SubmenuAdmin.php'}, + {expand: false, src: ['SubmenuModel.php'], dest: 'build/SubmenuModel.php'} + ] + } + }, + clean: ["build"], + uglify: { + my_target: { + files: { + 'build/assets/js/ajax.js': ['assets/js/ajax.js'], + 'build/assets/js/main.js': ['assets/js/main.js'] + } + } + }, + cssmin: { + my_target: { + files: { + 'build/assets/css/admin.css': ['assets/css/admin.css'] + } + } + } + }); + + // grunt modules + grunt.loadNpmTasks('grunt-contrib-copy'); + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-contrib-cssmin'); + + // Default task(s). + grunt.registerTask('default', ['clean', 'copy', 'uglify', 'cssmin']); + +}; \ No newline at end of file diff --git a/SubmenuAdmin.php b/SubmenuAdmin.php new file mode 100644 index 0000000..f9e077c --- /dev/null +++ b/SubmenuAdmin.php @@ -0,0 +1,230 @@ + + * @version 0.0.1 + */ +class SubmenuAdmin{ + + /** + * Plugin config + * @var stdClass + */ + private $config = null; + + /** + * Setup class + * @param stdClass $config + * @return void + */ + public function __construct(&$config){ + $this->config = $config; + + // include js/css + add_action( 'admin_enqueue_scripts', array($this, 'load_scripts')); + + // on menu save + add_action( 'wp_update_nav_menu_item', array($this, 'save_nav_menu'), 10, 3); + + add_action( 'admin_notices', array( $this , 'display_admin_notification' ) ); + add_action( 'admin_init', array( $this, 'hide_admin_notification' ) ); + + // register admin settings + add_action( 'admin_init', array($this, 'register_settings' )); + + // add settings page + add_action( 'admin_menu', array($this, 'settings_menu' )); + + // load settings + $options = get_option( 'jcs-general_settings' ); + $this->config->edit_walker = isset($options['enable_walker']) && $options['enable_walker'] == 1 ? 1 : 0; + + if($this->config->edit_walker == 1){ + add_filter( 'wp_edit_nav_menu_walker', array($this, 'set_edit_walker')); + }else{ + add_action( 'wp_ajax_jcs_get_menu_item', array( $this, 'ajax_get_menu_item' ) ); + } + } + + /** + * Attach plugin assets + * @return void + */ + public function load_scripts(){ + + // attach files + wp_enqueue_script('jc-submenu-scripts', $this->config->plugin_url .'/assets/js/main.js', array('jquery'), $this->config->version, true); + wp_enqueue_style('jc-submenu-admin-css', $this->config->plugin_url .'/assets/css/admin.css', array(), $this->config->version); + + // ajax files + if($this->config->edit_walker == 0){ + wp_enqueue_script( 'jc-submenu-ajax', $this->config->plugin_url .'/assets/js/ajax.js', array('jquery'), $this->config->version ); + wp_localize_script( 'jc-submenu-ajax', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'we_value' => 1234 ) ); + } + } + + public function settings_menu(){ + // add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function ); + add_submenu_page( 'options-general.php', 'JC Submenu', 'JC Submenu', 'manage_options', 'jc-submenu', array($this, 'admin_settings_view') ); + } + + public function admin_settings_view(){ + include $this->config->plugin_dir . 'views/settings.php'; + } + + /** + * Save custom menu item options + * @param int $menu_id + * @param int $menu_item_db_id + * @param array $args + * @return void + */ + public function save_nav_menu($menu_id, $menu_item_db_id, $args){ + + if(!isset($_POST['menu-item-title']) || empty($_POST['menu-item-title'])) + return false; + + foreach($_POST['menu-item-title'] as $menu_item_id => $menu_item_title){ + + if(isset($_POST[$this->config->prefix.'-admin']) && array_key_exists($menu_item_id, $_POST[$this->config->prefix.'-admin'])){ + SubmenuModel::save_meta($menu_item_id, 'admin', 1); + }elseif(isset($_POST[$this->config->prefix.'-active']) && array_key_exists($menu_item_id, $_POST[$this->config->prefix.'-active'])){ + SubmenuModel::save_meta($menu_item_id, 'admin', 0); + } + + if(isset($_POST[$this->config->prefix.'-autopop']) && array_key_exists($menu_item_id, $_POST[$this->config->prefix.'-autopop'])){ + // save post meta for active items + SubmenuModel::save_menu_item($menu_item_id); + + }elseif(isset($_POST[$this->config->prefix.'-active']) && array_key_exists($menu_item_id, $_POST[$this->config->prefix.'-active'])){ + // clear post meta for inactive items + SubmenuModel::clear_menu_item($menu_item_id); + } + } + } + + /** + * Output Usage Notification + * @return void + */ + public function display_admin_notification(){ + + global $current_user; + global $pagenow; + + $user_id = $current_user->ID; + $response = get_user_meta($user_id, 'jcs-show_notification', true); + + if ( current_user_can( 'manage_options' ) && (!$response || $response < $this->config->version_check) && $pagenow == 'nav-menus.php'): ?> + +
+

Need help with using JC Submenu? view the documentation here | Hide this notice

+
+ + ID; + + if(isset($_GET['jc_hide_notice']) && $_GET['jc_hide_notice'] == 1){ + + delete_user_meta($user_id, 'jcs-show_notification'); + add_user_meta( $user_id, 'jcs-show_notification', $this->config->version_check, true); + } + + } + + /** + * Change nav-menu.php walker + * @return string + */ + public function set_edit_walker(){ + return 'JC_Submenu_Admin_Walker'; + } + + /** + * Load menu admin edit view + * @return void + */ + public function ajax_get_menu_item(){ + $item_id = intval($_POST['id']); + include $this->config->plugin_dir . 'views/edit.php'; + die(); + } + + public function register_settings(){ + + // Settings + register_setting('jcs_settings', 'jcs'. '-general_settings', array($this, 'save_settings')); + + add_settings_section('settings', 'General Settings', array($this, 'section_settings'), 'tab_settings'); + + add_settings_field('enable_walker', 'Enable Admin Walker', array($this, 'field_callback'), 'tab_settings', 'settings', array( + 'type' => 'checkbox', + 'field_id' => 'enable_walker', + 'section_id' => 'settings', + 'setting_id' => 'jcs'. '-general_settings' + )); + + } + + /** + * Settings Section Text + * + * @return void + */ + public function section_settings($section) + { + switch($section['id']){ + case 'settings': + echo 'Enable Admin Walker, only do this if you are having problems with editing your menus.'; + break; + } + + } + + /** + * Create Settings Fields + * + * @param array $args + * @return void + */ + public function field_callback($args){ + $multiple = false; + extract($args); + $options = get_option($setting_id); + switch($args['type']) + { + case 'checkbox':{ + $checked = isset($options[$field_id]) && $options[$field_id] == 1 ? 'checked="checked"' : ''; + ?> + /> + + * @version 0.0.1 + */ +class SubmenuModel{ + + /** + * Plugin config + * @var stdClass + */ + static $config; + + /** + * Order by options + * @var array + */ + private static $order_options = array( + 'tax' => array( + 'name' => 'Name', + 'slug' => ' Slug', + 'count' => 'Tax Count', + 'id' => 'ID', + 'none' => 'None', + ), + 'post' => array( + 'title' => 'Post Name', + 'name' => 'Post Slug', + 'none' => 'None', + 'ID' => 'ID', + 'date' => 'Date', + 'comment_count' => 'Total Comments', + 'menu_order' => 'Menu Order' + ), + 'page' => array( + 'post_title' => 'Page Name', + 'menu_order' => 'Menu Order', + 'post_date' => 'Created', + 'post_modified' => 'Last Modified', + 'ID' => 'Page ID', + 'post_author' => 'Author', + 'post_name' => 'Page Slug' + ) + ); + + /** + * Setup class + * @param stdClass $config + * @return void + */ + static function init(&$config){ + self::$config = $config; + } + + /** + * Save Menu item from wp admin navigation page + * @param int $menu_item_id + * @param array $args + * @return void + */ + static function save_menu_item($menu_item_id = null, $args = array()){ + $type = self::get_post_data($menu_item_id, 'populate-type'); + $value = self::get_post_data($menu_item_id, 'populate-'.$type); + + $childpop = self::get_post_data($menu_item_id, 'childpop'); + $childpop = $childpop == 0 ? 0 : 1; + + if($type && $value){ + + // validate population type + if(!in_array($type, array('post','tax', 'page', 'archive'))){ + return 0; + } + + if($type == 'post'){ + $post_limit = self::get_post_data($menu_item_id, 'post-limit'); + $post_order = self::get_post_data($menu_item_id, 'post-order'); + $post_orderby = self::get_post_data($menu_item_id, 'post-orderby'); + $post_tax = self::get_post_data($menu_item_id, 'post-tax'); + $post_term = self::get_post_data($menu_item_id, 'post-term'); + + $post_tax = !empty($post_tax) ? $post_tax : 0; + $post_term = !empty($post_term) ? $post_term : 0; + + + $post_limit = intval($post_limit); + + // validate order + if(!array_key_exists($post_orderby, self::get_order_options('post'))){ + echo $post_orderby; + echo 'A'; + return 0; + } + if(!in_array($post_order, array('ASC', 'DESC'))){ + echo 'B'; + return 0; + } + + self::save_meta($menu_item_id, 'post-limit', $post_limit); + self::save_meta($menu_item_id, 'post-order', $post_order); + self::save_meta($menu_item_id, 'post-orderby', $post_orderby); + self::save_meta($menu_item_id, 'post-tax', $post_tax); + self::save_meta($menu_item_id, 'post-term', $post_term); + // self::save_post_tax($menu_item_id, $post_tax); + }elseif($type == 'tax'){ + $tax_order = self::get_post_data($menu_item_id, 'tax-order'); + $tax_orderby = self::get_post_data($menu_item_id, 'tax-orderby'); + $tax_empty = self::get_post_data($menu_item_id, 'tax-empty'); + $tax_depth = self::get_post_data($menu_item_id, 'tax-depth'); + $tax_term = self::get_post_data($menu_item_id, 'tax-term'); + + $tax_term = !empty($tax_term) ? $tax_term : 0; + + $tax_exclude = self::get_post_data($menu_item_id, 'tax-exclude'); + if(!empty($tax_exclude)){ + + $temp = array(); + $tax_exclude = explode(',', str_replace(' ', '', $tax_exclude)); + + foreach($tax_exclude as $id){ + if(intval($id) > 0 && !in_array(intval($id), $temp)){ + $temp[] = intval($id); + } + } + $tax_exclude = $temp; + }else{ + $tax_exclude = array(); + } + + + $tax_empty = $tax_empty == 1 ? 1 : 0; + + // validate order + if(!array_key_exists($tax_orderby, self::get_order_options('tax'))){ + return 0; + } + if(!in_array($tax_order, array('ASC', 'DESC'))){ + return 0; + } + + self::save_meta($menu_item_id, 'tax-order', $tax_order); + self::save_meta($menu_item_id, 'tax-orderby', $tax_orderby); + self::save_meta($menu_item_id, 'tax-empty', $tax_empty); + self::save_meta($menu_item_id, 'tax-depth', intval($tax_depth)); + self::save_meta($menu_item_id, 'tax-exclude', $tax_exclude); + self::save_meta($menu_item_id, 'tax-term', $tax_term); + }elseif($type == 'page'){ + + $page_order = self::get_post_data($menu_item_id, 'page-order'); + $page_orderby = self::get_post_data($menu_item_id, 'page-orderby'); + $page_exclude = self::get_post_data($menu_item_id, 'page-exclude'); + + // validate order + if(!array_key_exists($page_orderby, self::get_order_options('page'))){ + return 0; + } + if(!in_array($page_order, array('ASC', 'DESC'))){ + return 0; + } + + self::save_meta($menu_item_id, 'page-order', $page_order); + self::save_meta($menu_item_id, 'page-orderby', $page_orderby); + self::save_meta($menu_item_id, 'page-exclude', $page_exclude); + }elseif($type == 'archive'){ + + $archive_group = self::get_post_data($menu_item_id, 'archive-group'); + $archive_group = $archive_group == 1 ? 1 : 0; + self::save_meta($menu_item_id, 'archive-group', $archive_group); + } + + // all validated save rest + self::save_meta($menu_item_id, 'populate-type', $type); + self::save_meta($menu_item_id, 'populate-value', $value); + self::save_meta($menu_item_id, 'autopopulate', 1); + self::save_meta($menu_item_id, 'childpop', $childpop); + } + + } + + /** + * Save post type taxonomy filter + * @param $menu_item_id + * @param $string + */ + static function save_post_tax($menu_item_id = 0, $string = ''){ + + // no string to parse + if(empty($string)){ + self::save_meta($menu_item_id, 'post-tax', 0); + self::save_meta($menu_item_id, 'post-term', 0); + return false; + } + + + // save tax only + if(strpos($string, '-') === false && (taxonomy_exists( $string ) || $string == 0 ) ){ + self::save_meta($menu_item_id, 'post-tax', $string); + self::save_meta($menu_item_id, 'post-term', 0); + return true; + } + + // save term and tax + $split = explode('-', $string); + + if(count($split) == 2){ + $term_id = intval($split[1]); + $tax = $split[0]; + + if(taxonomy_exists( $tax ) && (get_term_by( 'id', $term_id, $tax) || $term_id == 0) ){ + self::save_meta($menu_item_id, 'post-tax', $tax); + self::save_meta($menu_item_id, 'post-term', $term_id); + return true; + } + } + + return false; + } + + /** + * Capture menu item $_POST data + * @param $menu_item_id + * @param $key + */ + static function get_post_data($menu_item_id = 0, $key = ''){ + if(isset($_POST[self::$config->prefix.'-'.$key][$menu_item_id]) + && !empty($_POST[self::$config->prefix.'-'.$key][$menu_item_id])){ + return $_POST[self::$config->prefix.'-'.$key][$menu_item_id]; + }else{ + return ''; + }; + } + + /** + * Update post meta data + * @param int $menu_item_id + * @param string $meta_key + * @param string $new_value + */ + static function save_meta($menu_item_id = 0, $meta_key = '', $new_value = ''){ + + $key = self::$config->prefix.'-'.$meta_key; + + $old_value = get_post_meta( $menu_item_id, $key, true ); + if($old_value == ''){ + + // fix to remove multiple saved values as add_post_meta was not set to unique... woops + global $wpdb; + $wpdb->query( $wpdb->prepare( "DELETE pm FROM {$wpdb->prefix}postmeta as pm WHERE pm.post_id = %d AND meta_key=%s ", $menu_item_id , $key ) ); + + // add value + add_post_meta( $menu_item_id, $key, $new_value, true ); + }else{ + // update value + update_post_meta( $menu_item_id, $key, $new_value, $old_value ); + } + } + + /** + * Remove menu item settings + * @param int $menu_item_id + * @return void + */ + static function clear_menu_item($menu_item_id = null){ + $keys = array( + 'populate-type', + 'populate-value', + 'autopopulate', + 'post-limit', + 'post-order', + 'post-orderby', + 'tax-order', + 'tax-orderby', + 'tax-empty', + 'post-tax', + 'post-term', + 'childpop', + 'archive-group' + ); + + foreach($keys as $meta_key){ + $old_value = get_post_meta( $menu_item_id, self::$config->prefix.'-'.$meta_key, true ); + if($old_value != ''){ + delete_post_meta( $menu_item_id, self::$config->prefix.'-'.$meta_key, $old_value ); + } + } + } + + /** + * Retrieve orderby options + * @param string $type tax | post + */ + static function get_order_options($type){ + + switch($type){ + case 'tax': + return self::$order_options['tax']; + break; + case 'post': + return self::$order_options['post']; + break; + case 'page': + return self::$order_options['page']; + break; + } + } + + /** + * Get plugin meta item + * @param int $menu_item_id + * @param string $key + * @return string + */ + static function get_meta($menu_item_id, $key){ + return get_post_meta( $menu_item_id, self::$config->prefix.'-'.$key, true ); + } +} +?> \ No newline at end of file diff --git a/assets/css/admin.css b/assets/css/admin.css new file mode 100644 index 0000000..6d60238 --- /dev/null +++ b/assets/css/admin.css @@ -0,0 +1,79 @@ +.jc-submenu-populate-block{ + color: #777; + border: #DFDFDF 1px solid; + /*border-bottom: none;*/ + /*padding: 10px 0 10px 10px;*/ + padding:0; + width: 367px; +} + +.jc-submenu-populate-block label{ + display: block; +} + +.jc-submenu-populate-block input[type=text], .jc-submenu-populate-block select{ + width:100%; +} + +.jc-submenu-row{ + clear: both; + margin:10px 0 10px 10px; +} + +.jc-submenu-row p{ + padding-right: 4%; + width:96%; + margin-bottom: 5px; + margin-top: 5px; +} + +.jc-submenu-row .jc_two_cols{ + overflow: hidden; +} + +.jc-submenu-row.jc_two_cols p{ + width:46%; + float:left; + padding-right:4%; +} + +.jc-accord-heading input{ + position: absolute; + top: -9999px; + left: -9999px; +} +p.jc-accord-heading{ + margin: 0; + padding: 0; + width:100% !important; + float:left; + border-bottom: 1px solid #dfdfdf; +} +.jc-accord-heading label{ + padding:9px; + background: #ededed; + color:#737373; +} + +.jc-accord-heading.active label{ + background: #737373; + color:#FFF; +} + +.jc-accord-heading.jc-submenu-populate-archive{ + border-bottom: none; +} +.jc-accord-heading.jc-submenu-populate-archive.active{ + border-bottom: 1px solid #dfdfdf; +} + +#jc-submenu-loading{ + height:38px; + border: 1px solid #dfdfdf; + background: #ededed; + color:#737373; + line-height: 40px; + text-indent: 10px; + float:left; + width:367px; +} \ No newline at end of file diff --git a/assets/js/ajax.js b/assets/js/ajax.js new file mode 100644 index 0000000..981449c --- /dev/null +++ b/assets/js/ajax.js @@ -0,0 +1,240 @@ +/** + * Admin Ajax Function + */ +(function($){ + + $.fn.jc_edit_menu = function(){ + + var id = JC_Submenu.get_menu_id($(this).attr('id')); + var _menu_item = $('#menu-item-'+id); + + if(_menu_item.hasClass('menu-item-edit-inactive') && !_menu_item.hasClass('jc-submenu-populated')){ + + var id = JC_Submenu.get_menu_id(_menu_item.attr('id')); + var data = { + action: 'jcs_get_menu_item', + id: id + }; + + // show loading + $("
JC Submenu... Loading
").insertBefore(_menu_item.find('.menu-item-actions')); + + jQuery.post(ajax_object.ajax_url, data, function(response) { + + _menu_item.find("#jc-submenu-loading").remove(); + + $(response).insertBefore(_menu_item.find('.menu-item-actions')); + + /** + * Display Active Menu Population Options + * @since 0.6 + */ + _menu_item.find('.jc-accord-heading').each(function(){ + + var accord_heading = $(this); + var id = JC_Submenu.get_menu_id(accord_heading.attr('id')); + var btn_handle = $('input', accord_heading); + var btn_label = $('label', accord_heading); + + btn_handle.live('change', function(){ + + $('.jc-accord-heading', $('#menu-item-'+id)).removeClass('active'); + $('.item-edit-panel', $('#menu-item-'+id)).hide(); + + if($(this).attr('checked') == 'checked'){ + $( '.show-'+$(this).val() , $('#menu-item-'+id) ).show(); + accord_heading.addClass('active'); + } + }); + + btn_label.click(function(event){ + $('.jc-accord-heading input:checked', $('#menu-item-'+id)).attr('checked', false); + btn_handle.attr('checked', 'checked').trigger('change'); + event.preventDefault(); + }); + + btn_handle.filter(":checked").trigger('change'); + }); + + /** + * Display JC Submenu Options + * @since 0.6 + */ + _menu_item.find('input.jc-submenu-autopopulate').each(function(index){ + + var options_handle = $(this); + var id = JC_Submenu.get_menu_id(options_handle.attr('id')); + + options_handle.live('change', function(){ + if($(this).attr('checked') == 'checked'){ + $( '#jc-submenu-populate-block-'+id).show(); + $('.jc-submenu-active').show(); + }else{ + $( '#jc-submenu-populate-block-'+id).hide(); + $('.jc-submenu-active').hide(); + } + }); + + options_handle.filter(':checked').trigger('change'); + }); + + /** + * Filter Taxonomy via selected Post Type + * @since 0.6 + */ + _menu_item.find('select[id^="edit-jc-submenu-populate-post"]').each(function(){ + + var post_select = $(this); + var id = JC_Submenu.get_menu_id(post_select.attr('id')); + var tax_select = $('select[id^="edit-jc-submenu-post-tax"]', $('#menu-item-'+id)); + var term_select = $('select[id^="edit-jc-submenu-post-term"]', $('#menu-item-'+id)); + var taxs = tax_select.clone(); + + + post_select.live('change', function(){ + var show_taxs = post_select.find(':selected').data('taxs').split(' '); + var selected = tax_select.find(':selected').val(); + + // tax_select = taxs.clone(); + tax_select.empty(); + + $('option', taxs).each(function(index){ + + var val = $(this).val(); + + if($.inArray(val, show_taxs) != -1 || val == 0){ + + var clone_option = $(this).clone().attr('selected', false); + + if(val == selected){ + tax_select.append(clone_option.attr('selected', 'selected')); + }else{ + tax_select.append(clone_option); + } + }else{ + tax_select.find('option[value='+val+']').remove(); + } + }); + + // hide taxonomy filters if no options + /*if(tax_select.find('option').size() == 1){ + tax_select.parent().hide(); + }else{ + tax_select.parent().show(); + }*/ + + tax_select.trigger('change'); + }); + + post_select.trigger('change'); + + }); + + /** + * Filter Terms depending on chosen taxonomy + * @since 0.6 + */ + _menu_item.find('select[id^="edit-jc-submenu-post-tax"]').each(function(){ + + var tax_select = $(this); + var id = JC_Submenu.get_menu_id(tax_select.attr('id')); + var term_select = $('select[id^="edit-jc-submenu-post-term"]', $('#menu-item-'+id)); + var terms = term_select.clone(); + + tax_select.live('change', function(){ + + var tax = tax_select.find(':selected').val(); + var selected = term_select.find(':selected').val(); + + term_select.empty(); + + $('option', terms).each(function(index){ + var val = $(this).val(); + + if(tax == $(this).data('tax')){ + var clone_option = $(this).clone().attr('selected', false); + if(val == selected){ + term_select.append(clone_option.attr('selected', 'selected')); + }else{ + term_select.append(clone_option); + } + }else{ + term_select.find('option[value='+val+']').remove(); + } + }); + + /*if(term_select.find('option').size() == 1){ + term_select.parent().hide(); + }else{ + term_select.parent().show(); + }*/ + + }); + + tax_select.trigger('change'); + }); + + /** + * Filter Taxonomy Terms depending on chosen taxonomy + * @since 0.6 + */ + _menu_item.find('select[id^="edit-jc-submenu-populate-tax"]').each(function(){ + + var tax_select = $(this); + var id = JC_Submenu.get_menu_id(tax_select.attr('id')); + var term_select = $('select[id^="edit-jc-submenu-tax-term"]', $('#menu-item-'+id)); + var terms = term_select.clone(); + + tax_select.live('change', function(){ + + var tax = tax_select.find(':selected').val(); + var selected = term_select.find(':selected').val(); + + term_select.empty(); + + $('option', terms).each(function(index){ + var val = $(this).val(); + + if(tax == $(this).data('tax') || $(this).data('tax') == 0){ + var clone_option = $(this).clone().attr('selected', false); + if(val == selected){ + term_select.append(clone_option.attr('selected', 'selected')); + }else{ + term_select.append(clone_option); + } + }else{ + term_select.find('option[value='+val+']').remove(); + } + }); + + /*if(term_select.find('option').size() == 1){ + term_select.parent().hide(); + }else{ + term_select.parent().show(); + }*/ + + }); + + tax_select.trigger('change'); + }); + }); + + _menu_item.addClass('jc-submenu-populated'); + } + } + + /** + * JS Attach Item Template + * + * add before .menu-item-actions + */ + $(document).ready(function(){ + + $('#menu-to-edit').on('click', 'a.item-edit', function(){ + $(this).jc_edit_menu(); + }); + + }); + + +})(jQuery); \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..9e43396 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,219 @@ +/** +* JC Submenu Javascript +*/ + +var JC_Submenu = { + + get_menu_id: function (id){ + id= id.split("-"); + id = id[id.length-1]; + return id; + } + +}; + +(function($){ + + + /** + * Display Active Menu Population Options + * @since 0.2 + */ + $('.jc-accord-heading').each(function(){ + + var accord_heading = $(this); + var id = JC_Submenu.get_menu_id(accord_heading.attr('id')); + var btn_handle = $('input', accord_heading); + var btn_label = $('label', accord_heading); + + btn_handle.live('change', function(){ + + $('.jc-accord-heading', $('#menu-item-'+id)).removeClass('active'); + $('.item-edit-panel', $('#menu-item-'+id)).hide(); + + if($(this).attr('checked') == 'checked'){ + $( '.show-'+$(this).val() , $('#menu-item-'+id) ).show(); + accord_heading.addClass('active'); + } + }); + + btn_label.click(function(event){ + $('.jc-accord-heading input:checked', $('#menu-item-'+id)).attr('checked', false); + btn_handle.attr('checked', 'checked').trigger('change'); + event.preventDefault(); + }); + + btn_handle.filter(":checked").trigger('change'); + }); + + /** + * Display JC Submenu Options + * @since 0.2 + */ + $('input.jc-submenu-autopopulate').each(function(index){ + + var options_handle = $(this); + var id = JC_Submenu.get_menu_id(options_handle.attr('id')); + + options_handle.live('change', function(){ + if($(this).attr('checked') == 'checked'){ + $( '#jc-submenu-populate-block-'+id).show(); + $('.jc-submenu-active').show(); + }else{ + $( '#jc-submenu-populate-block-'+id).hide(); + $('.jc-submenu-active').hide(); + } + }); + + options_handle.filter(':checked').trigger('change'); + }); + + /** + * Filter Taxonomy via selected Post Type + * @since 0.2 + */ + $('select[id^="edit-jc-submenu-populate-post"]').each(function(){ + + var post_select = $(this); + var id = JC_Submenu.get_menu_id(post_select.attr('id')); + var tax_select = $('select[id^="edit-jc-submenu-post-tax"]', $('#menu-item-'+id)); + var term_select = $('select[id^="edit-jc-submenu-post-term"]', $('#menu-item-'+id)); + var taxs = tax_select.clone(); + + + post_select.live('change', function(){ + var show_taxs = post_select.find(':selected').data('taxs').split(' '); + var selected = tax_select.find(':selected').val(); + + // tax_select = taxs.clone(); + tax_select.empty(); + + $('option', taxs).each(function(index){ + + var val = $(this).val(); + + if($.inArray(val, show_taxs) != -1 || val == 0){ + + var clone_option = $(this).clone().attr('selected', false); + + if(val == selected){ + tax_select.append(clone_option.attr('selected', 'selected')); + }else{ + tax_select.append(clone_option); + } + }else{ + tax_select.find('option[value='+val+']').remove(); + } + }); + + // hide taxonomy filters if no options + /*if(tax_select.find('option').size() == 1){ + tax_select.parent().hide(); + }else{ + tax_select.parent().show(); + }*/ + + tax_select.trigger('change'); + }); + + post_select.trigger('change'); + + }); + + /** + * Filter Terms depending on chosen taxonomy + * @since 0.2 + */ + $('select[id^="edit-jc-submenu-post-tax"]').each(function(){ + + var tax_select = $(this); + var id = JC_Submenu.get_menu_id(tax_select.attr('id')); + var term_select = $('select[id^="edit-jc-submenu-post-term"]', $('#menu-item-'+id)); + var terms = term_select.clone(); + + tax_select.live('change', function(){ + + var tax = tax_select.find(':selected').val(); + var selected = term_select.find(':selected').val(); + + term_select.empty(); + + $('option', terms).each(function(index){ + var val = $(this).val(); + + if(tax == $(this).data('tax')){ + var clone_option = $(this).clone().attr('selected', false); + if(val == selected){ + term_select.append(clone_option.attr('selected', 'selected')); + }else{ + term_select.append(clone_option); + } + }else{ + term_select.find('option[value='+val+']').remove(); + } + }); + + /*if(term_select.find('option').size() == 1){ + term_select.parent().hide(); + }else{ + term_select.parent().show(); + }*/ + + }); + + tax_select.trigger('change'); + }); + + /** + * Filter Taxonomy Terms depending on chosen taxonomy + * @since 0.5.4 + */ + $('select[id^="edit-jc-submenu-populate-tax"]').each(function(){ + + var tax_select = $(this); + var id = JC_Submenu.get_menu_id(tax_select.attr('id')); + var term_select = $('select[id^="edit-jc-submenu-tax-term"]', $('#menu-item-'+id)); + var terms = term_select.clone(); + + tax_select.live('change', function(){ + + var tax = tax_select.find(':selected').val(); + var selected = term_select.find(':selected').val(); + + term_select.empty(); + + $('option', terms).each(function(index){ + var val = $(this).val(); + + if(tax == $(this).data('tax') || $(this).data('tax') == 0){ + var clone_option = $(this).clone().attr('selected', false); + if(val == selected){ + term_select.append(clone_option.attr('selected', 'selected')); + }else{ + term_select.append(clone_option); + } + }else{ + term_select.find('option[value='+val+']').remove(); + } + }); + + /*if(term_select.find('option').size() == 1){ + term_select.parent().hide(); + }else{ + term_select.parent().show(); + }*/ + + }); + + tax_select.trigger('change'); + }); + + + /** + * Document Ready + */ + $(document).ready(function(){ + $('.item-edit-panel').hide(); + }); + +})(jQuery); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..1118caf --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "jc-submenu", + "version": "0.8.3", + "devDependencies": { + "grunt": "^0.4.5", + "grunt-contrib-clean": "^0.6.0", + "grunt-contrib-copy": "^0.7.0", + "grunt-contrib-cssmin": "^0.10.0", + "grunt-contrib-jshint": "~0.10.0", + "grunt-contrib-nodeunit": "~0.4.1", + "grunt-contrib-uglify": "^0.6.0" + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..c4ce129 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,19 @@ + + + + + + ./tests/ + + + \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..24690df --- /dev/null +++ b/readme.txt @@ -0,0 +1,175 @@ +=== JC Submenu === +Contributors: jcollings +Donate link: +Tags: submenu, menu, dynamic, custom post type, taxonomy, child pages +Requires at least: 3.0.1 +Tested up to: 4 +Stable tag: 0.8.3 +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +JC Submenu plugin allows you to automatically populate your navigation menus with custom post_types, taxonomies, or child pages. + +== Description == + +JC Submenu plugin allows you to automatically populate your navigation menus with custom post_types, taxonomies, or child pages. An easy to use plugin created to be a lightweight menu extension. + +Also output a selected section of your dynamic menu through our advanced submenu widget. + +== Installation == + +1. First grab a copy from [wordpress.org](http://downloads.wordpress.org/plugin/jc-submenu.zip). +1. Extract the plugin to your wordpress plugins folder. +1. Activate the plugin from your wordpress administration area (under the plugins section). +1. You should thee should now be able to use JC Submenu Plugin. +1. Optional - If your theme already has a custom walker specified for outputing your menu, JC Submenu will not automatically override it, to do this locate the file your theme outputs the menu (usually header.php) and look for "wp\_nav\_menu()", and pass an extra argument so it looks similar: + +`wp_nav_menu(array('walker' => new JC_Submenu_Nav_Walker()));` + +For further documentation on installing and using JC Submneu features can be found [here](http://jamescollings.co.uk/wordpress-plugins/jc-submenu/). + +== Frequently asked questions == + += How do i use the split menu functionality = + +The documentation for using the split menu functionality (widget, shortcode, action) can be found [here](http://jamescollings.co.uk/jc-submenu/resources/output-split-menu-section/) + += How do i output a section of menu = + +The documentation for displaying a section of menu (widget, shortcode, action) can be found [here](http://jamescollings.co.uk/jc-submenu/resources/how-to-output-a-section-of-a-wordpress-menu/) + += How do i automatically populate menu items = + +The documentation for automatically populating menu items can be found [here](http://jamescollings.co.uk/jc-submenu/resources/how-to-automatically-populate-wordpress-submenus/) + += What Actions and filters are avaliable in this plugin = + +A list of all actions and filters can be found [here](http://jamescollings.co.uk/jc-submenu/sections/actions-filters/) + + +== Screenshots == + +1. JC Submenu, Post population options +2. JC Submenu, Taxonomy population options +3. JC Submenu, Page children population options +4. JC Submenu, Advanced Submenu Widget Options + +== Changelog == + +**0.8.3** + +* Fix add_post_meta not set to unique when saving menu items, causing multiple entries to be saved. + +**0.8.2** + +* Fix filter jcs/enable_public_walker to actually be used, as before it was not able to be overwritten by themes only plugins + +**0.8.1** + +* Added jcs/split_menu/populated_elements, jcs/section_menu/populated_elements, jcs/populated_elements to allow modification of populated menu elements +* Updated Readme to be tested upto wp 4 + +**0.8** + +* Fix error when populating with an empty array of posts +* Add jcs/enable_public_walker filter to disable/enable the public walker to allow jc submenu be used with other custom walkers. +* Add jcs/split_widget_title to overwrite split menu title +* Add {{PARENT_TITLE}} template tags to show the active parent item in the split menu widget. + +**0.7.2** + +* Added filter to change submenu level class jcs/menu_level_class, return array of classes +* Added the option to populate by post date archive +* Added post date archive grouping by year + +**0.7.1** + +* Fixed infinite loop error when passed badly formed menu items. + +**0.7** + +* Simplified dynamic menu population +* Added the ability to replace the current item with dynamically populated items + +**0.6.2** + +* Fixed clone() warning +* Added trigger_depth to split menu +* Fixed Menu Ordering +* Updated FAQ Section + +**0.6.1** + +* Renamed filter from jci/menu_item_args to jcs/menu_item_args + +**0.6** + +* Add menu item filters jcs/item_title, jcs/item_url, jcs/page_item_title, jcs/page_item_url, jcs/post_item_title, jcs/post_item_url, jcs/term_item_title, jcs/term_item_url +* Add admin-menu notice to show if item is dynamically populated +* Add compatability to other plugins who use a custom admin walker +* Add setting to disable ajax menu edit +* Add menu item argument filters jci/menu_item_args to allow customisation of output per item + +**0.5.5** + +* Add class filter jcs/item_classes +* Add class filter jcs/term_item_classes +* Add class filter jcs/post_item_classes +* Add class filter jcs/page_item_classes +* Add WP_Query arguments filter jcs/post_query_args, jcs/post_$menu-item-id_query_args +* Add get_pages arguments filter jcs/page_query_args, jcs/page_$menu-item-id_query_args +* Add get_terms arguments filter jcs/term_query_args, jcs/term_$menu-item-id_query_args +* Ouput post_type with hierarchy +* Removed php strict warnings + +**0.5.4** + +* Added option into populate by taxonomy to set the term parent + +**0.5.3** + +* Removed PHP Warning for imploding false in exclude terms list +* Remove PHP Warning for missing array in exclude pages list + +**0.5.2** + +* Fixed SubmenuWalker replaces order_by with orderby +* Added in basic CSV input taxonomy term exclusion. + +**0.5** + +* Added option to limit taxonomy depth +* Added option to exclude child pages +* Added Split menu shortcode +* Added Menu section shortcode +* Fixed possible function conflict +* Fixed menu depth +* Fixed split menu +* Fixed menu section +* Fixed post_type / page with taxonomy not highlighting menu item + +**0.4.1** + +* Added child page order support +* Fixed Javascript jumping bug +* Added version to js,css to fix cache problem +* Added documentation notification link on plugin update +* Added Menu Section Widget + +**0.4** + +* Added Split menu output action jcs/split_menu, Menu Section output action jcs/split_menu to allow theme developers to output submenus. + +**0.3** + +* Split Menu Widget Added + +**0.2** + +* Interface update +* Custom post type population can now be filtered by a Taxonomy +* Javascript update +* Compatability with wordpress 3.6 + + +== Upgrade notice == diff --git a/screenshot-1.png b/screenshot-1.png new file mode 100644 index 0000000..d8fab11 Binary files /dev/null and b/screenshot-1.png differ diff --git a/screenshot-2.png b/screenshot-2.png new file mode 100644 index 0000000..eea7d1c Binary files /dev/null and b/screenshot-2.png differ diff --git a/screenshot-3.png b/screenshot-3.png new file mode 100644 index 0000000..4f9cbcc Binary files /dev/null and b/screenshot-3.png differ diff --git a/screenshot-4.png b/screenshot-4.png new file mode 100644 index 0000000..8166e51 Binary files /dev/null and b/screenshot-4.png differ diff --git a/submenu.php b/submenu.php new file mode 100644 index 0000000..e45bdff --- /dev/null +++ b/submenu.php @@ -0,0 +1,279 @@ + + * @version 0.8.3 + */ +class JCSubmenu{ + + var $version = '0.8.3'; + var $version_check = 70; + var $plugin_dir = false; + var $plugin_url = false; + var $prefix = 'jc-submenu'; + var $edit_walker = false; + var $public_walker = true; + + /** + * Setup plugin + * @return void + */ + function __construct(){ + + $this->plugin_dir = plugin_dir_path( __FILE__ ); + $this->plugin_url = plugins_url( '/', __FILE__ ); + + $this->load_modules(); + + // add plugin hooks + add_action('jcs/menu_section', array($this, 'output_menu_section'), 10, 2); + add_action('jcs/split_menu', array($this, 'output_split_menu'), 10, 2); + + // add plugin shortcodes + add_shortcode( 'jcs_split_menu', array($this, 'split_menu_shortcode') ); + add_shortcode( 'jcs_menu_section', array($this, 'menu_section_shortcode') ); + + // init menu attachment + add_action('init', array($this, 'init')); + } + + /** + * Set which type of attachment is used + * @return void + */ + public function init(){ + + $this->public_walker = apply_filters('jcs/enable_public_walker', false ); + + if(!$this->public_walker){ + add_filter( 'wp_nav_menu_objects', array( $this, 'populate_menu_items' )); + }else{ + add_filter( 'wp_nav_menu_args', array( $this, 'attach_menu_walker' )); + } + } + + /** + * Attach custom nav walker + * + * Hook into theme menu, attach custom walker + * + * @param array $args + * @return array + */ + function attach_menu_walker($args){ + if(empty($args['walker'])){ + $args['walker'] = new JC_Submenu_Nav_Walker(); + } + return $args; + } + + /** + * Add menu items without using a custom walker + * + * @param array $menu_items + * @return array new menu items + */ + function populate_menu_items($menu_items = array()){ + + $walker = new JC_Submenu_Nav_Walker(); + $menu_items = $walker->attach_elements($menu_items); + $menu_items = $walker->_process_menu($menu_items); + + return $menu_items; + } + + /** + * Load Required Modules + * @return void + */ + function load_modules(){ + + include 'walkers/AdminMenuWalker.php'; + include 'walkers/SubmenuWalker.php'; + include 'walkers/DropdownWalker.php'; + include 'widgets/SectionMenuWidget.php'; + include 'widgets/SplitMenuWidget.php'; + include 'SubmenuModel.php'; + SubmenuModel::init($this); + + include 'SubmenuAdmin.php'; + new SubmenuAdmin($this); + } + + /** + * Slit Menu Section Shortcode + * + * Display a dynamic split menu section via wordpress shortcode tags + * + * @param array $atts + * @return string + */ + function split_menu_shortcode($atts){ + extract(shortcode_atts( array( + 'hierarchy' => 1, + 'start' => 0, + 'depth' => 5, + 'show_parent' => 0, + 'menu' => false, + 'trigger_depth' => 0 + ), $atts )); + + if(!$menu) + return false; + + ob_start(); + + do_action('jcs/split_menu', $menu, array( + 'hierarchy' => $hierarchy, + 'start' => $start, + 'depth' => $depth, + 'show_parent' => $show_parent, + 'trigger_depth' => $trigger_depth + )); + + $output = ob_get_contents(); + ob_end_clean(); + return $output; + } + + /** + * Menu Section Shortcode + * + * Display section of menu via wordpress shortcode tags + * + * @param array $atts + * @return string + */ + function menu_section_shortcode($atts){ + extract(shortcode_atts( array( + 'hierarchy' => 1, + 'start' => 0, + 'depth' => 5, + 'show_parent' => 0, + 'menu' => false + ), $atts )); + + if(!$menu) + return false; + + ob_start(); + + do_action('jcs/menu_section', $menu, array( + 'hierarchy' => $hierarchy, + 'start' => $start, + 'depth' => $depth, + 'show_parent' => $show_parent, + )); + + $output = ob_get_contents(); + ob_end_clean(); + return $output; + } + + /** + * Output menu section + * + * Display a section of the selected menu in your theme + * + * @param string $menu + * @param array $args + * @return void + */ + function output_menu_section($menu, $args = array()){ + + $debug = isset($args['debug']) ? $args['debug'] : false; + $hierarchical = isset($args['hierarchy']) ? $args['hierarchy'] : 1; + $start = isset($args['start']) ? $args['start'] : 0; + $depth = isset($args['depth']) ? $args['depth'] : 5; + $show_parent = isset($args['show_parent']) ? $args['show_parent'] : 0; + + $options = array('menu' => $menu, 'walker' => new JC_Submenu_Nav_Walker(array( + 'debug' => $debug, + 'section_menu' => true, + 'menu_item' => $start, + 'menu_depth' => $depth, + 'show_parent' => $show_parent + )) + ); + + if(isset($args['menu_class'])) + $options['menu_class'] = $args['menu_class']; + + if(isset($args['menu_id'])) + $options['menu_id'] = $args['menu_id']; + + if(isset($args['container'])) + $options['container'] = $args['container']; + + if(isset($args['container_id'])) + $options['container_id'] = $args['container_id']; + + if(isset($args['container_class'])) + $options['container_class'] = $args['container_class']; + + wp_nav_menu($options); + } + + /** + * Output Split Menu + * + * Display a dynamic section of the selected menu in your theme relative to your current page + * + * @param string $menu + * @param array $args + * @return void + */ + function output_split_menu($menu, $args = array()){ + + $hierarchical = isset($args['hierarchy']) ? $args['hierarchy'] : 1; + $menu_start = isset($args['start']) ? $args['start'] : 1; + $menu_depth = isset($args['depth']) ? $args['depth'] : 5; + $show_parent = isset($args['show_parent']) ? $args['show_parent'] : 0; + $trigger_depth = isset($args['trigger_depth']) ? $args['trigger_depth'] : 0; + $parent_label = isset($args['parent_label']) ? $args['parent_label'] : false; + + $options = array( + 'menu' => $menu, 'walker' => new JC_Submenu_Nav_Walker(array( + 'hierarchical' => $hierarchical, + 'menu_start' => $menu_start, + 'menu_depth' => $menu_depth, + 'show_parent' => $show_parent, + 'trigger_depth' => $trigger_depth, + 'parent_label' => $parent_label, + 'split_menu' => true + )) + ); + + if(isset($args['menu_class'])) + $options['menu_class'] = $args['menu_class']; + + if(isset($args['menu_id'])) + $options['menu_id'] = $args['menu_id']; + + if(isset($args['container'])) + $options['container'] = $args['container']; + + if(isset($args['container_id'])) + $options['container_id'] = $args['container_id']; + + if(isset($args['container_class'])) + $options['container_class'] = $args['container_class']; + + wp_nav_menu($options); + } +} + +$GLOBALS['jcsubmenu'] = new JCSubmenu(); +?> \ No newline at end of file diff --git a/tests/DynamicItemsTest.php b/tests/DynamicItemsTest.php new file mode 100644 index 0000000..67330df --- /dev/null +++ b/tests/DynamicItemsTest.php @@ -0,0 +1,510 @@ +submenu = $GLOBALS['jcsubmenu']; + } + + function testElementDepths(){ + $walker = new JC_Submenu_Nav_Walker(); + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + ); + + $output = $walker->set_elements_depth($elements); + $this->assertEquals(8, count($elements)); + $this->assertEquals($elements[0]->depth, 0); + $this->assertEquals($elements[1]->depth, 1); + $this->assertEquals($elements[2]->depth, 1); + $this->assertEquals($elements[3]->depth, 1); + $this->assertEquals($elements[4]->depth, 2); + $this->assertEquals($elements[5]->depth, 2); + $this->assertEquals($elements[6]->depth, 3); + $this->assertEquals($elements[7]->depth, 3); + } + + function testElementState01(){ + + $walker = new JC_Submenu_Nav_Walker(); + + /** + * Top level parent + */ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1 + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + ); + + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1, + 'split_section' => 1 + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + ); + + $output = $walker->_set_elements_state($elements); + $this->assertEquals($result, $output); + } + + function testElementState02(){ + + $walker = new JC_Submenu_Nav_Walker(); + + /** + * Second level parent + */ + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + ); + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'classes' => array('current-menu-parent', 'current-menu-ancestor'), + 'current_item_ancestor' => 1, + 'current_item_parent' => 1, + 'split_section' => 1 + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + 'current' => 1, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + ); + + $output = $walker->_set_elements_state($elements); + $this->assertEquals($result, $output); + } + + function testElementState03(){ + + $walker = new JC_Submenu_Nav_Walker(); + + /** + * Third level parent + */ + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + ); + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'classes' => array('current-menu-ancestor'), + 'split_section' => 1, + 'current_item_ancestor' => 1, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + 'classes' => array('current-menu-parent', 'current-menu-ancestor'), + 'current_item_parent' => 1, + 'current_item_ancestor' => 1, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + 'current' => 1, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + ); + + $output = $walker->_set_elements_state($elements); + $this->assertEquals($result, $output); + + } + + function testElementState04(){ + + $walker = new JC_Submenu_Nav_Walker(); + /** + * Fourth Level Parent + */ + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + // no parent + (object)array( + 'menu_item_parent' => 9, + 'db_id' => 9, + ), + ); + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'classes' => array('current-menu-ancestor'), + 'current_item_ancestor' => 1, + 'split_section' => 1 + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 2, + 'classes' => array('current-menu-ancestor'), + 'current_item_ancestor' => 1, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + // lvl 2 + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + 'classes' => array('current-menu-parent', 'current-menu-ancestor'), + 'current_item_ancestor' => 1, + 'current_item_parent' => 1, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + // lvl 3 + (object)array( + 'menu_item_parent' => 5, + 'db_id' => 7, + 'current' => 1, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 6, + 'db_id' => 8, + ), + // no parent + (object)array( + 'menu_item_parent' => 9, + 'db_id' => 9, + ), + ); + + $output = $walker->_set_elements_state($elements); + $this->assertEquals($result, $output); + } + + /** + * Test Single Menu Item who is current + */ + function testElementState05(){ + + $walker = new JC_Submenu_Nav_Walker(); + /** + * Fourth Level Parent + */ + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1 + ) + ); + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1, + 'split_section' => 1 + ) + ); + + $output = $walker->_set_elements_state($elements); + $this->assertEquals($result, $output); + } + + /** + * Test Single Menu Item not current + */ + function testElementState06(){ + + $walker = new JC_Submenu_Nav_Walker(); + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ) + ); + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ) + ); + + $output = $walker->_set_elements_state($elements); + $this->assertEquals($result, $output); + } +} + +?> \ No newline at end of file diff --git a/tests/SectionMenuTest.php b/tests/SectionMenuTest.php new file mode 100644 index 0000000..f80c3e5 --- /dev/null +++ b/tests/SectionMenuTest.php @@ -0,0 +1,177 @@ +submenu = $GLOBALS['jcsubmenu']; + } + + /** + * Basic Menu Section 1/2 + */ + function testSectionMenu01(){ + + $walker = new JC_Submenu_Nav_Walker(array('menu_item' => 1, 'menu_depth' => 1)); + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 4, + ), + ); + $result = array( + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + 'menu_depth' => 1 + ), + ); + + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_menu_section($elements); + $this->assertEquals($result, $output); + } + + /** + * Basic Menu Section 2/2 + */ + function testSectionMenu02(){ + + $walker = new JC_Submenu_Nav_Walker(array('menu_item' => 2, 'menu_depth' => 1)); + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 4, + ), + ); + $result = array( + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 4, + 'menu_depth' => 1 + ), + ); + + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_menu_section($elements); + $this->assertEquals($result, $output); + } + + /** + * Test Show Parent 1/2 + */ + function testSectionMenu03(){ + + $walker = new JC_Submenu_Nav_Walker(array('menu_item' => 1, 'menu_depth' => 1, 'show_parent' => 1)); + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 4, + ), + ); + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1, + 'menu_depth' => 0 + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + 'menu_depth' => 1 + ), + ); + + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_menu_section($elements); + $this->assertEquals($result, $output); + } + + /** + * Test Show Parent 2/2 + */ + function testSectionMenu04(){ + + $walker = new JC_Submenu_Nav_Walker(array('menu_item' => 2, 'menu_depth' => 1, 'show_parent' => 1)); + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 4, + ), + ); + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + 'menu_depth' => 0 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 4, + 'menu_depth' => 1 + ), + ); + + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_menu_section($elements); + $this->assertEquals($result, $output); + } +} + +?> \ No newline at end of file diff --git a/tests/SplitMenuTest.php b/tests/SplitMenuTest.php new file mode 100644 index 0000000..200e524 --- /dev/null +++ b/tests/SplitMenuTest.php @@ -0,0 +1,577 @@ +submenu = $GLOBALS['jcsubmenu']; + } + + public function stripResults($elements){ + foreach($elements as $elm){ + if(isset($elm->classes)){ + unset($elm->classes); + } + if(isset($elm->current_item_ancestor)){ + unset($elm->current_item_ancestor); + } + if(isset($elm->current_item_parent)){ + unset($elm->current_item_parent); + } + } + return $elements; + } + + public function orderItems($elements){ + usort($elements, array($this, 'usortElement')); + return $elements; + } + + public function usortElement($a, $b){ + return $a->db_id - $b->db_id; + } + + /** + * Top Level Split Test 1/2 + * Test a basic split menu from menu item 1 + */ + public function testSplitMenu01(){ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + ), + ); + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'current' => 1, + 'split_section' => 1, + 'menu_depth' => 0 + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + 'menu_depth' => 1 + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + 'menu_depth' => 1 + ), + ); + + $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'menu_start' => 1 )); + + $elements = $walker->_set_elements_state($elements); + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_split_menu($elements); + + $this->assertEquals($this->orderItems($result), $this->orderItems($output)); + } + + /** + * Top Leve Split Test 2/2 + * Test a basic split menu from menu item 2 + */ + public function testSplitMenu02(){ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + 'current' => 1 + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + ), + ); + + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + 'current' => 1, + 'menu_depth' => 0, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + 'menu_depth' => 1, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + 'menu_depth' => 1, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + 'menu_depth' => 1, + ), + ); + + $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'menu_start' => 1 )); + + $elements = $walker->_set_elements_state($elements); + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_split_menu($elements); + + $this->assertEquals($this->orderItems($result), $this->orderItems($output)); + } + + /** + * Top Level Split Test with parent 1/2 + * Test a basic split menu from menu item 1 + */ + public function testSplitMenu03(){ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + ), + ); + + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'split_section' => 1, + 'menu_depth' => 0, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + 'menu_depth' => 1, + 'current' => 1, + 'split_section' => 1, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + 'menu_depth' => 1 + ), + ); + + $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'menu_start' => 1 )); + + $elements = $walker->_set_elements_state($elements); + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_split_menu($elements); + + $output = $this->stripResults($output); + $this->assertEquals($this->orderItems($result), $this->orderItems($output)); + + } + + /** + * Top Leve Split Test with parent 2/2 + * Test a basic split menu from menu item 2 + */ + public function testSplitMenu04(){ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + ), + ); + + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + 'menu_depth' => 0, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + 'menu_depth' => 1, + 'current' => 1, + 'split_section' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + 'menu_depth' => 1, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + 'menu_depth' => 1, + ), + ); + + $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'menu_start' => 1 )); + + $elements = $walker->_set_elements_state($elements); + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_split_menu($elements); + + $output = $this->stripResults($output); + $this->assertEquals($this->orderItems($result), $this->orderItems($output)); + + } + + /** + * First child split menu test 1/2 + */ + public function testSplitMenu05(){ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + ), + ); + + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + 'split_section' => 1, + 'menu_depth' => 0, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + 'menu_depth' => 1, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + 'current' => 1, + 'split_section' => 1, + 'menu_depth' => 1, + ), + ); + + $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'trigger_depth' => 0, 'menu_start' => 1, 'menu_depth' => 1, 'show_parent' => false)); + + $elements = $walker->_set_elements_state($elements); + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_split_menu($elements); + + $output = $this->stripResults($output); + $this->assertEquals($this->orderItems($result), $this->orderItems($output)); + + } + + /** + * First child split menu test 2/2 + */ + public function testSplitMenu06(){ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + 'current' => 1 + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + ), + ); + + $result = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + 'split_section' => 1, + 'menu_depth' => 0, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + 'menu_depth' => 1, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + 'current' => 1, + 'split_section' => 1, + 'menu_depth' => 1, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + 'menu_depth' => 1, + ), + ); + + $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'trigger_depth' => 0, 'menu_start' => 1, 'menu_depth' => 1, 'show_parent' => false)); + + $elements = $walker->_set_elements_state($elements); + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_split_menu($elements); + + $output = $this->stripResults($output); + $this->assertEquals($this->orderItems($result), $this->orderItems($output)); + + } + + /** + * Empty Split Menu Test + */ + public function testSplitMenu07(){ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + ), + ); + + $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'trigger_depth' => 0, 'menu_start' => 1, 'menu_depth' => 1, 'show_parent' => false)); + + $elements = $walker->_set_elements_state($elements); + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_split_menu($elements); + $this->assertEmpty($output); + } + + /** + * Test current item with missing parent item + */ + public function testSplitMenu08(){ + + $elements = array( + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 1, + ), + (object)array( + 'menu_item_parent' => 0, + 'db_id' => 2, + ), + // lvl 1 + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 3, + ), + (object)array( + 'menu_item_parent' => 1, + 'db_id' => 4, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 5, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 6, + ), + (object)array( + 'menu_item_parent' => 2, + 'db_id' => 7, + ), + (object)array( + 'menu_item_parent' => 8, + 'db_id' => 8, + 'current' => 1 + ), + ); + + $result = array( + (object)array( + 'menu_item_parent' => 8, + 'db_id' => 8, + 'current' => 1, + 'split_section' => 1 + ), + ); + + $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'trigger_depth' => 0, 'menu_start' => 1, 'menu_depth' => 1, 'show_parent' => false)); + + $elements = $walker->_set_elements_state($elements); + $elements = $walker->set_elements_depth($elements, 0, true); + $output = $walker->_process_split_menu($elements); + + $output = $this->stripResults($output); + $this->assertEquals($this->orderItems($result), $this->orderItems($output)); + } +} + +?> \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..733ef39 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,16 @@ + array("jc-submenu/submenu.php" ), +); + +if( file_exists( $path ) ) { + require_once $path; +} else { + exit( "Couldn't find path to wordpress-tests/bootstrap.php\n" ); +} \ No newline at end of file diff --git a/views/edit.php b/views/edit.php new file mode 100644 index 0000000..bd26b77 --- /dev/null +++ b/views/edit.php @@ -0,0 +1,268 @@ +

+ +

+

+ +

+ + + + + \ No newline at end of file diff --git a/views/settings.php b/views/settings.php new file mode 100644 index 0000000..532f232 --- /dev/null +++ b/views/settings.php @@ -0,0 +1,16 @@ +
+

+

JC Submenu

+ +
+ +

+ +

+
+ +
\ No newline at end of file diff --git a/walkers/AdminMenuWalker.php b/walkers/AdminMenuWalker.php new file mode 100644 index 0000000..64086c4 --- /dev/null +++ b/walkers/AdminMenuWalker.php @@ -0,0 +1,205 @@ + $_wp_nav_menu_max_depth ? $depth : $_wp_nav_menu_max_depth; + + $indent = ( $depth ) ? str_repeat( "\t", $depth ) : ''; + + ob_start(); + $item_id = esc_attr( $item->ID ); + $removed_args = array( + 'action', + 'customlink-tab', + 'edit-menu-item', + 'menu-item', + 'page-tab', + '_wpnonce', + ); + + $original_title = ''; + if ( 'taxonomy' == $item->type ) { + $original_title = get_term_field( 'name', $item->object_id, $item->object, 'raw' ); + if ( is_wp_error( $original_title ) ) + $original_title = false; + } elseif ( 'post_type' == $item->type ) { + $original_object = get_post( $item->object_id ); + $original_title = $original_object->post_title; + } + + $classes = array( + 'menu-item menu-item-depth-' . $depth, + 'menu-item-' . esc_attr( $item->object ), + 'menu-item-edit-' . ( ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? 'active' : 'inactive'), + ); + + $title = $item->title; + + if ( ! empty( $item->_invalid ) ) { + $classes[] = 'menu-item-invalid'; + /* translators: %s: title of menu item which is invalid */ + $title = sprintf( __( '%s (Invalid)' ), $item->title ); + } elseif ( isset( $item->post_status ) && 'draft' == $item->post_status ) { + $classes[] = 'pending'; + /* translators: %s: title of menu item in draft status */ + $title = sprintf( __('%s (Pending)'), $item->title ); + } + + $title = empty( $item->label ) ? $title : $item->label; + + ?> +