/** * 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); }
public function posts_by_parent() { return bu_navigation_pages_by_parent($this->posts); }