Skip to content

Commit

Permalink
Return posts sorted by hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
oandregal committed Nov 29, 2024
1 parent 6a73104 commit 32013a6
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
108 changes: 108 additions & 0 deletions lib/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php
/**
* A custom REST server for Gutenberg.
*
* @package gutenberg
* @since 6.8.0
*/

add_filter( 'rest_page_collection_params', function ( $params ) {

Check failure on line 9 in lib/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Opening parenthesis of a multi-line function call must be the last content on the line

Check failure on line 9 in lib/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Only one argument is allowed per line in a multi-line function call
$params['orderby_hierarchy'] = array(
'description' => 'Sort pages by hierarchy.',
'type' => 'boolean',
'default' => false,
);
return $params;
} );

Check failure on line 16 in lib/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Closing parenthesis of a multi-line function call must be on a line by itself

add_filter( 'rest_page_query', function ( $args, $request ) {

Check failure on line 18 in lib/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Opening parenthesis of a multi-line function call must be the last content on the line

Check failure on line 18 in lib/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Only one argument is allowed per line in a multi-line function call
if ( $request['orderby_hierarchy'] ) {
// Build the list of post ids to be displayed.
$new_args = array_merge( $args, array(

Check failure on line 21 in lib/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Opening parenthesis of a multi-line function call must be the last content on the line

Check failure on line 21 in lib/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Only one argument is allowed per line in a multi-line function call
'fields' => 'id=>parent',
'posts_per_page' => -1,
) );
$query = new WP_Query( $new_args );
$posts = $query->posts;
$post_ids = sort_ids_by_hierarchy( $posts, $args );

// Reconfigure the args to display only the ids in the list.
$args['paged'] = 1;
$args['post__in'] = $post_ids;
}
return $args;
}, 10, 2 );

/**
* Sort the post ids by hierarchy.
*
* @param array $posts The posts to sort.
* @param array $args The arguments to sort the posts by.
* @return array The sorted post ids.
*/
function sort_ids_by_hierarchy( $posts, $args = array() ) {
/**
* $posts is:
* [
* ['ID' => 2, 'post_parent' => 0],
* ['ID' => 3, 'post_parent' => 2],
* ['ID' => 4, 'post_parent' => 2],
* ]
*
* $args is:
* [
* 'posts_per_page' => 20,
* 'paged' => 1,
* ]
*/
if ( isset( $args['posts_per_page'] ) && $args['posts_per_page'] === 0 ) {
return array();
}

$per_page = isset( $args['posts_per_page'] ) && is_int( $args['posts_per_page'] ) ? $args['posts_per_page'] : -1;
$page = isset( $args['paged'] ) && is_int( $args['paged'] ) ? $args['paged'] : 1;
$start = 0;
$end = count( $posts );
if ( $per_page > 0 ) {
$start = ( $page - 1 ) * $per_page;
$end = $start + $per_page;
}

/*
* Arrange pages in two arrays:
*
* - $top_level: posts whose parent is 0
* - $parent_children: post ID as the key and an array of children post IDs as the value.
* Example: parent_children[10][] contains all sub-pages whose parent is 10.
*
*/

$top_level = array();
$parent_children = array();
foreach ( $posts as $post ) {
if ( $post->post_parent === 0 ) {
$top_level[] = $post->ID;
} else {
$parent_children[ $post->post_parent ][] = $post->ID;
}
}

$ids = array();
$count = 0;
add_hierarchical_ids( $ids, $top_level, $count, $start, $end, $parent_children );

return $ids;
}

function add_hierarchical_ids( &$ids, $to_process, &$count, $start, $end, $parent_children ) {
foreach ( $to_process as $id ) {
if ( $count >= $start && $count < $end ) {
$ids[] = $id;
}
$count++;

if ( isset( $parent_children[ $id ] ) ) {
add_hierarchical_ids( $ids, $parent_children[ $id ], $count, $start, $end, $parent_children );
}
}
}
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-6.8/block-comments.php';
require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php';
require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-post-types-controller-6-8.php';
require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-posts-controller-6-8.php';
require __DIR__ . '/compat/wordpress-6.8/rest-api.php';

// Plugin specific code.
Expand Down
1 change: 1 addition & 0 deletions packages/edit-site/src/components/post-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ export default function PostList( { postType } ) {
_embed: 'author',
order: view.sort?.direction,
orderby: view.sort?.field,
orderby_hierarchy: true,
search: view.search,
...filters,
};
Expand Down
81 changes: 81 additions & 0 deletions phpunit/build-post-ids-to-display-test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

/**
* Test the build_post_ids_to_display function.
*
* @package Gutenberg
*/
class SortIdsByHierarchyTest extends WP_UnitTestCase {

/*
* Keep this updated as the input array changes.
* The sorted hierarchy would be as follows:
*
* 2
* - 3
* -- 5
* -- 6
* - 4
* -- 7
* 8
* - 9
* -- 11
* - 10
*
*/
private $input = array(
array(
'ID' => 11,

Check warning on line 28 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 9,
),
array(
'ID' => 2,

Check warning on line 32 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 0,
),
array(
'ID' => 8,

Check warning on line 36 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 0,
),
array(
'ID' => 3,

Check warning on line 40 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 2,
),
array(
'ID' => 5,

Check warning on line 44 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 3,
),
array(
'ID' => 7,

Check warning on line 48 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 4,
),
array(
'ID' => 9,

Check warning on line 52 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 8,
),
array(
'ID' => 4,

Check warning on line 56 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 2,
),
array(
'ID' => 6,

Check warning on line 60 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 3,
),
array(
'ID' => 10,

Check warning on line 64 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Array double arrow not aligned correctly; expected 10 space(s) between "'ID'" and double arrow, but found 1.
'post_parent' => 8,
),
);

public function test_return_all_post_ids() {
$output = sort_ids_by_hierarchy( $this->input );
$this->assertEquals( array( 2, 3, 5, 6, 4, 7, 8, 9, 11, 10 ), $output );
}

public function test_return_first_page() {
$output = sort_ids_by_hierarchy( $this->input, array(

Check failure on line 75 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Opening parenthesis of a multi-line function call must be the last content on the line

Check failure on line 75 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Only one argument is allowed per line in a multi-line function call
'posts_per_page' => 3,
'paged' => 1,
) );

Check failure on line 78 in phpunit/build-post-ids-to-display-test.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Closing parenthesis of a multi-line function call must be on a line by itself
$this->assertEquals( array( 2, 3, 5 ), $output );
}
}

0 comments on commit 32013a6

Please sign in to comment.