Skip to content
127 changes: 115 additions & 12 deletions hm-post-repeat.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@
} );

// Display only Repeatable Posts in admin table view for registered view links.
add_filter( 'pre_get_posts', __NAMESPACE__ . '\admin_table_repeat_type_posts_query' );
add_filter( 'pre_get_posts', __NAMESPACE__ . '\admin_table_repeat_type_posts_query' );

// Add a row link to view all Repeat posts for the current Repeating post.
add_filter( 'post_row_actions', __NAMESPACE__ . '\admin_table_row_actions_view_repeat_posts', 10, 2 );

/**
* Enqueue the scripts and styles that are needed by this plugin.
Expand Down Expand Up @@ -368,17 +371,21 @@ function get_repeating_schedule( $post_id ) {
*
* A repeating post is defined as the original post that was set to repeat.
*
* @param int $post_id The id of the post you want to check.
* @param int $post_id The ID of the post you want to check.
*
* @return bool Whether the passed post_id is a repeating post or not.
*/
function is_repeating_post( $post_id ) {

// We check $_POST data so that this function works inside a `save_post` hook when the post_meta hasn't yet been saved
// We check $_POST data so that this function works inside a `save_post` hook when the post_meta hasn't yet been saved.
if ( isset( $_POST['hm-post-repeat'] ) && isset( $_POST['ID'] ) && $_POST['ID'] === $post_id ) {
return true;
}

if ( get_post_meta( $post_id, 'hm-post-repeat', true ) ) {
// For saved posts - Repeating post has meta key and does NOT have a parent.
$post_parent = get_post_field( 'post_parent', $post_id );

if ( ! $post_parent && get_post_meta( $post_id, 'hm-post-repeat', true ) ) {
return true;
}

Expand All @@ -391,11 +398,13 @@ function is_repeating_post( $post_id ) {
*
* A repeat post is defined as any post which is a repeat of the original repeating post.
*
* @param int $post_id The id of the post you want to check.
* @param int $post_id The ID of the post you want to check.
*
* @return bool Whether the passed post_id is a repeat post or not.
*/
function is_repeat_post( $post_id ) {

// Repeat post has meta key and has a parent.
$post_parent = get_post_field( 'post_parent', $post_id );

if ( $post_parent && get_post_meta( $post_parent, 'hm-post-repeat', true ) ) {
Expand Down Expand Up @@ -479,8 +488,18 @@ function admin_table_views_links( $views ) {
esc_html( number_format_i18n( $repeat_type_query->post_count ) )
);

// Add current class to the link to highlight it when it's selected.
$class_html = ( get_repeat_type_url_param() === $repeat_type ) ? ' class="current"' : '';
/**
* Add current class to the view link to highlight it when it's selected.
* NB: do not highlight the view link when displaying subsection of results
* (i.e. Repeat posts for a specific Repeating post).
*/
$class_html = '';
if (
get_repeat_type_url_param() === $repeat_type &&
! isset( $_GET['post_parent'] )
) {
$class_html = ' class="current"';
}

$link_html = sprintf(
'<a href="%s"%s>%s</a>',
Expand All @@ -496,9 +515,13 @@ function admin_table_views_links( $views ) {
}

/**
* Customizes main admin query to get posts of specified repeat type
* Customise main admin query to get posts of specified repeat type
* to be displayed in the admin table.
*
* The main admin query only displays requested posts in the main table view!
* It does NOT do the post count for table view links see `admin_table_views_links()` -
* it has got a separate query for the total post count for view links.
*
* @param \WP_Query $wp_query Main admin query.
*
* @return mixed Main admin query with edited params to get posts of specified repeat type.
Expand All @@ -517,8 +540,11 @@ function admin_table_repeat_type_posts_query( $wp_query ) {
return $wp_query;
}

// Add a table view link per each repeat type.
foreach ( get_repeat_type_query_params( $repeat_type ) as $key => $value ) {
// Repeat post display - only displaying Repeat posts for a specific Repeating post.
$post_parent_id = isset( $_GET['post_parent'] ) ? intval( $_GET['post_parent'] ) : 0;

// Add WP_Query param depending on displayed repeat type.
foreach ( get_repeat_type_query_params( $repeat_type, $post_parent_id ) as $key => $value ) {
$wp_query->set( $key, $value );
}

Expand All @@ -529,11 +555,12 @@ function admin_table_repeat_type_posts_query( $wp_query ) {
* Returns array of custom WP_Query params to get posts of specified repeat type.
* Works for all CPT that support Repeatable Posts.
*
* @param string $repeat_type Repeat type of posts to get.
* @param string $repeat_type Repeat type of posts to get.
* @param int $post_parent_id Post parent ID - to find Repeat posts for.
*
* @return array Array of custom WP_Query params.
*/
function get_repeat_type_query_params( $repeat_type ) {
function get_repeat_type_query_params( $repeat_type, $post_parent_id = 0 ) {

$query['post_type'] = get_current_screen()->post_type;

Expand All @@ -552,6 +579,13 @@ function get_repeat_type_query_params( $repeat_type ) {
$query['post_parent__in'] = array( 0 );
}

// Repeat post display - only displaying Repeat posts for specific Repeating post.
if ( $post_parent_id ) {
$query['post_parent'] = $post_parent_id;
$query['post_parent__not_in'] = '';
$query['post_parent__in'] = '';
}

return $query;
}

Expand Down Expand Up @@ -588,3 +622,72 @@ function get_available_repeat_types() {
function is_allowed_repeat_type( $repeat_type ) {
return in_array( $repeat_type, array_keys( get_available_repeat_types() ) );
}

/**
* Add a row link to view all Repeat posts for the current Repeating post.
*
* The link text is `# repeat posts` where # is the number of corresponding Repeat posts.
*
* The filter is evaluated only for non-hierarchical post types.
*
* @param array $actions An array of row action links.
* @param WP_Post $post The post object to display row links for.
*
* @return array An array of row action links with added link to view Repeat posts and there count.
*/
function admin_table_row_actions_view_repeat_posts( $actions, $post ) {

if ( ! is_repeating_post( $post->ID ) ) {
return $actions;
}

// Get associated Repeat posts for the current Repeating post.
$url_args = array(
'post_type' => get_current_screen()->post_type,
'hm-post-repeat' => 'repeat',
'post_parent' => $post->ID,
);

// TODO: I think this is an expensive thing to do per each post. Maybe we can store Repeat post count in meta data?
$repeat_posts_query = new \WP_Query( get_repeat_type_query_params( 'repeat', $post->ID ) );
$repeat_posts_count = $repeat_posts_query->post_count;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@willmot is there a better approach to store the count of repeat posts to make it quicker? Maybe a maintained meta data?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I'd be tempted to just skip showing the number in that list, I'm not sure it's worth the complexity. Especially as you'll see the count one you click the link.

@dashaluna dashaluna Jan 11, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I've chatted to @johnbillion and he suggested to run a query with all parents IDs that currently on the page, that sounds like a good solution - I'm working on it atm.

When you click to see a specific post's Repeat posts, the overall number in the view link does not change! It shows count for all Repeating and Repeat posts overall. This is similar to core WP, when you click a specific author (not yourself) the view link looses the bold focus, but the count stays the same. Hope that makes sense.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good point, and nice idea!


if ( $repeat_posts_count ) {
$actions['view_repeat'] = sprintf(
'<a href="%s" aria-label="%s">%s</a>',
esc_url( add_query_arg( $url_args, 'edit.php' ) ),
esc_attr( sprintf(
_n(
'View %d repeat post',
'View %d repeat posts',
$repeat_posts_count,
'hm-post-repeat'
),
number_format_i18n( $repeat_posts_count )
) ),
esc_html( sprintf(
_n(
'%d repeat post',
'%d repeat posts',
$repeat_posts_count,
'hm-post-repeat'
),
number_format_i18n( $repeat_posts_count )
) )
);
} else {

// 0 Repeat post - display text, not a link.
$actions['view_repeat'] = esc_html( sprintf(
_n(
'%d repeat post',
'%d repeat posts',
$repeat_posts_count,
'hm-post-repeat'
),
number_format_i18n( $repeat_posts_count )
) );
}

return $actions;
}