/** * Handles reordering for sections that contain children that have updated post_parent or menu_order fields * * @todo write unit tests */ public function run() { // error_log('======== Navman Reordering ========='); // error_log('Already moved: ' . print_r( $this->already_moved, true ) ); global $wpdb; if (!$this->has_moves()) { return; } $result = true; // Fetch all posts in sections marked for reordering $sections = array_keys($this->already_moved); $posts = bu_navigation_get_pages(array('sections' => $sections, 'suppress_filter_pages' => true, 'post_status' => array('publish', 'private'), 'post_types' => $this->post_types)); $posts_by_parent = bu_navigation_pages_by_parent($posts); // error_log('Sections for reordering: ' . print_r( $posts_by_parent, true ) ); // Loop through affected sections, reordering children as needed foreach ($posts_by_parent as $parent_id => $children) { $position = 1; foreach ($children as $child) { // Skip reorder for posts that were already moved if (!$this->post_already_moved($child)) { // Skip any positions that were previously set for a moved post while ($this->position_already_set($position, $parent_id)) { // Skip over any positions that were set for previously updated children // error_log('Position has already been set, skipping ' . $position ); $position++; } // Only update if menu order has actually changed if ($child->menu_order != $position) { $stmt = $wpdb->prepare('UPDATE ' . $wpdb->posts . ' SET menu_order = %d WHERE ID = %d', $position, $child->ID); $rc = $wpdb->query($stmt); if (false === $rc) { $error_msg = sprintf('Error updating menu order (%s) for post (%s): %s', $position, $child->post_title, $wpdb->last_error); error_log($error_msg); array_push($this->errors, new WP_Error('bu_navigation_reorder_error', $error_msg)); } else { wp_cache_delete($child->ID, 'posts'); } // Temporary logging // error_log('Setting menu order for post "' . $child->post_title . '": ' . $position ); } else { /* noop */ // error_log('Skipping menu order update, already correct for post ' . $child->post_title . ' (' . $position . ')' ); } $position++; } else { /* noop */ // error_log('Child already has correct menu order, skipping myself (' . $child->post_title . ')'); } } } // Global caches wp_cache_delete('get_pages', 'posts'); if ($this->has_errors()) { $result = false; } return $result; }
/** * Generate page parent select menu * * @uses bu_filter_pages_parent_dropdown(). * * @param string $post_type required -- post type to filter posts for * @param int $selected post ID of the selected post * @param array $args optional configuration object * * @return string the resulting dropdown markup */ function bu_navigation_page_parent_dropdown($post_type, $selected = 0, $args = array()) { $defaults = array('echo' => 1, 'select_id' => 'bu_filter_pages', 'select_name' => 'post_parent', 'select_classes' => '', 'post_status' => array('publish', 'private')); $r = wp_parse_args($args, $defaults); // Grab top level pages for current post type $args = array('direction' => 'down', 'depth' => 1, 'post_types' => (array) $post_type); $sections = bu_navigation_gather_sections(0, $args); $args = array('suppress_filter_pages' => TRUE, 'sections' => $sections, 'post_types' => (array) $post_type, 'post_status' => (array) $r['post_status']); $pages = bu_navigation_get_pages($args); $pages_by_parent = bu_navigation_pages_by_parent($pages); $options = "\n\t<option value=\"0\">" . __('Show all sections') . "</option>\r"; // Get options ob_start(); bu_filter_pages_parent_dropdown($pages_by_parent, $selected); $options .= ob_get_contents(); ob_end_clean(); $classes = !empty($r['select_classes']) ? " class=\"{$r['select_classes']}\"" : ''; $dropdown = sprintf("<select id=\"%s\" name=\"%s\"%s>\r%s\r</select>\r", $r['select_id'], $r['select_name'], $classes, $options); if ($r['echo']) { echo $dropdown; } return $dropdown; }
/** * Covers bu_filter_pages_parent_dropdown() */ public function test_bu_filter_pages_parent_dropdown() { $parent = $this->posts['parent']; $child = $this->posts['child']; $grandchild_one = $this->posts['grandchild_one']; $pages = bu_navigation_get_pages(); $pages_by_parent = bu_navigation_pages_by_parent($pages); $page_options_expected = "\n\t" . '<option value="' . $child . '" >Child Page</option>' . "\r" . "\n\t" . '<option value="' . $grandchild_one . '" > Grand Child Page 1</option>' . "\r"; ob_start(); bu_filter_pages_parent_dropdown($pages_by_parent, 0, $parent); $page_options_results = ob_get_contents(); ob_end_clean(); $this->assertEquals($page_options_results, $page_options_expected); /** * Test Default Function */ $page_options_default_expected = "\n\t" . '<option value="' . $child . '" selected="selected">Child Page</option>' . "\r" . "\n\t" . '<option value="' . $grandchild_one . '" > Grand Child Page 1</option>' . "\r"; ob_start(); bu_filter_pages_parent_dropdown($pages_by_parent, $child, $parent); $page_options_default_results = ob_get_contents(); ob_end_clean(); $this->assertEquals($page_options_default_expected, $page_options_default_results); /** * Test Parent Function */ $page_options_parent_expected = "\n\t" . '<option value="' . $grandchild_one . '" >Grand Child Page 1</option>' . "\r"; ob_start(); bu_filter_pages_parent_dropdown($pages_by_parent, 0, $child); $page_options_parent_results = ob_get_contents(); ob_end_clean(); $this->assertEquals($page_options_parent_expected, $page_options_parent_results); /** * Test Level Function */ $page_options_level_expected = "\n\t" . '<option value="' . $child . '" selected="selected"> Child Page</option>' . "\r" . "\n\t" . '<option value="' . $grandchild_one . '" > Grand Child Page 1</option>' . "\r"; ob_start(); bu_filter_pages_parent_dropdown($pages_by_parent, $child, $parent, 2); $page_options_level_results = ob_get_contents(); ob_end_clean(); $this->assertEquals($page_options_level_expected, $page_options_level_results); }
function bu_navigation_breadcrumbs($args = '') { global $post; $defaults = array('post' => $post, 'glue' => ' » ', 'container_tag' => 'div', 'container_id' => 'breadcrumbs', 'container_class' => '', 'anchor_class' => 'crumb', 'crumb_tag' => '', 'crumb_current' => 1, 'anchor_current' => 0, 'echo' => 0, 'home' => false, 'home_label' => 'Home', 'prefix' => '', 'suffix' => '', 'include_statuses' => 'publish', 'include_hidden' => false, 'show_links' => true); $r = wp_parse_args($args, $defaults); if ($r['post']) { $p = null; if (is_numeric($r['post'])) { $p = get_post($r['post']); } else { if (is_object($r['post'])) { $p = $r['post']; } } if (is_null($p)) { error_log('bu_navigation_breadcrumbs - invalid post argument: ' . $r['post']); return false; } } // Grab ancestors $ancestors = bu_navigation_gather_sections($p->ID, array('post_types' => $p->post_type)); if (!in_array($p->ID, $ancestors)) { array_push($ancestors, $p->ID); } $exclude_filter_removed = false; if ($r['include_hidden'] && has_filter('bu_navigation_filter_pages', 'bu_navigation_filter_pages_exclude')) { $exclude_filter_removed = remove_filter('bu_navigation_filter_pages', 'bu_navigation_filter_pages_exclude'); } $pages = bu_navigation_get_pages(array('pages' => $ancestors, 'post_types' => $p->post_type, 'post_status' => $r['include_statuses'])); if ($r['include_hidden'] && $exclude_filter_removed) { add_filter('bu_navigation_filter_pages', 'bu_navigation_filter_pages_exclude'); } // Container markup $attrs = ''; if ($r['container_id']) { $attrs .= sprintf(' id="%s"', $r['container_id']); } if ($r['container_class']) { $attrs .= sprintf(' class="%s"', $r['container_class']); } $html = sprintf('<%s%s>%s', $r['container_tag'], $attrs, $r['prefix']); // Build crumb markup $crumbs = array(); if (is_array($pages) && count($pages) > 0) { foreach ($ancestors as $page_id) { if (!$page_id && $r['home']) { $anchor_open = sprintf('<a href="%s" class="%s">', get_bloginfo('url'), $r['anchor_class']); $anchor_close = '</a>'; if ($r['show_links']) { $crumb = $anchor_open . $r['home_label'] . $anchor_close; } else { $crumb = $r['home_label']; } array_push($crumbs, $crumb); continue; } else { if (!array_key_exists($page_id, $pages)) { continue; } } $current = $pages[$page_id]; if (!isset($current->navigation_label)) { $current->navigation_label = apply_filters('the_title', $current->post_title); } $title = esc_attr($current->navigation_label); $href = $current->url; $classname = $r['anchor_class']; $crumb = $anchor_open = $anchor_close = ''; if ($current->ID == $p->ID) { $classname .= ' active'; } if ($r['show_links']) { if ($current->ID == $p->ID && !$r['anchor_current']) { $anchor_open = sprintf('<a class="%s">', $classname); } else { $anchor_open = sprintf('<a href="%s" class="%s">', $href, $classname); } $anchor_close = '</a>'; } $before_crumb = $after_crumb = ''; if ($r['crumb_tag']) { $before_crumb = $current->ID == $p->ID ? sprintf('<%s class="current">', $r['crumb_tag']) : sprintf('<%s>', $r['crumb_tag']); $after_crumb = sprintf('</%s>', $r['crumb_tag']); } $crumb = $before_crumb . $anchor_open . $title . $anchor_close . $after_crumb; $crumb = apply_filters('bu_navigation_filter_crumb_html', $crumb, $current, $r); // Only crumb if not current page or if we're crumbing the current page if ($current->ID != $p->ID || $r['crumb_current']) { array_push($crumbs, $crumb); } } $html .= implode($r['glue'], $crumbs); } $html .= sprintf('%s</%s>', $r['suffix'], $r['container_tag']); if ($r['echo']) { echo $html; } return $html; }