'post',
'plural' => 'posts',
'ajax' => false,
)
);
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only query argument for view selection.
$this->current_view = ( isset( $_GET['view'] ) && 'excluded' === sanitize_key( wp_unslash( $_GET['view'] ) ) ) ? 'excluded' : 'stale';
}
/**
* Get views links (All Outdated / Excluded).
*
* @return array
*/
protected function get_views() {
$views = array();
// Count stale items.
$stale_query = new OCAP_Query( array( 'view' => 'stale' ) );
$stale_count = $stale_query->get_count();
// Count excluded items.
$excluded_query = new OCAP_Query( array( 'view' => 'excluded' ) );
$excluded_count = $excluded_query->get_count();
$current_view = $this->current_view;
$stale_class = ( 'stale' === $current_view ) ? ' class="current"' : '';
$excluded_class = ( 'excluded' === $current_view ) ? ' class="current"' : '';
$views['stale'] = sprintf(
'%s (%s)',
esc_url( ocap_get_report_url( array( 'view' => 'stale' ) ) ),
$stale_class,
esc_html__( 'All Outdated', 'contentcortex' ),
number_format_i18n( $stale_count )
);
$views['excluded'] = sprintf(
'%s (%s)',
esc_url( ocap_get_report_url( array( 'view' => 'excluded' ) ) ),
$excluded_class,
esc_html__( 'Excluded items', 'contentcortex' ),
number_format_i18n( $excluded_count )
);
return $views;
}
/**
* Define columns.
*
* @return array
*/
public function get_columns() {
return array(
'cb' => '',
'title' => __( 'Title', 'contentcortex' ),
'type' => __( 'Post Type', 'contentcortex' ),
'date' => ( 'published' === ocap_get_setting( 'date_basis', 'modified' ) ) ? __( 'Published', 'contentcortex' ) : __( 'Last Updated', 'contentcortex' ),
'days' => __( 'Days Since Update', 'contentcortex' ),
'limit' => __( 'Day Limit', 'contentcortex' ),
'author' => __( 'Author', 'contentcortex' ),
);
}
/**
* Define sortable columns.
*
* @return array
*/
public function get_sortable_columns() {
return array(
'title' => array( 'title', false ),
'type' => array( 'type', false ),
'date' => array( 'modified', false ),
'days' => array( 'days', false ),
'author' => array( 'author', false ),
);
}
/**
* Define bulk actions.
*
* @return array
*/
protected function get_bulk_actions() {
if ( 'excluded' === $this->current_view ) {
return array(
'include' => __( 'Include again', 'contentcortex' ),
);
}
return array(
'mark_reviewed' => __( 'Mark as reviewed', 'contentcortex' ),
// phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- False positive: Bulk action identifier, not get_posts() parameter.
'exclude' => __( 'Exclude from report', 'contentcortex' ),
);
}
/**
* Checkbox column.
*
* @param array $item Current row item.
* @return string
*/
protected function column_cb( $item ) {
return sprintf(
'',
absint( $item['ID'] )
);
}
/**
* Title column with row actions.
*
* @param array $item Current row item.
* @return string
*/
protected function column_title( $item ) {
$post_id = absint( $item['ID'] );
$edit_link = get_edit_post_link( $post_id );
$title = esc_html( $item['title'] );
if ( $edit_link && current_user_can( 'edit_post', $post_id ) ) {
$title_output = sprintf(
'%s',
esc_url( $edit_link ),
$title
);
} else {
$title_output = sprintf( '%s', $title );
}
$actions = array();
if ( current_user_can( 'edit_post', $post_id ) ) {
if ( $edit_link ) {
$actions['edit'] = sprintf(
'%s',
esc_url( $edit_link ),
esc_html__( 'Edit', 'contentcortex' )
);
}
$actions['view'] = sprintf(
'%s',
esc_url( get_permalink( $post_id ) ),
esc_html__( 'View', 'contentcortex' )
);
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
$redirect = rawurlencode( $request_uri );
if ( 'excluded' === $this->current_view ) {
$include_url = wp_nonce_url(
admin_url( 'admin-post.php?action=ocap_include_post&post_id=' . $post_id . '&redirect_to=' . $redirect ),
'ocap_include_post_' . $post_id
);
$actions['include'] = sprintf(
'%s',
esc_url( $include_url ),
esc_html__( 'Include again', 'contentcortex' )
);
} else {
$review_url = wp_nonce_url(
admin_url( 'admin-post.php?action=ocap_mark_reviewed&post_id=' . $post_id . '&redirect_to=' . $redirect ),
'ocap_mark_reviewed_' . $post_id
);
$exclude_url = wp_nonce_url(
admin_url( 'admin-post.php?action=ocap_exclude_post&post_id=' . $post_id . '&redirect_to=' . $redirect ),
'ocap_exclude_post_' . $post_id
);
$actions['mark_reviewed'] = sprintf(
'%s',
esc_url( $review_url ),
esc_html__( 'Mark as reviewed', 'contentcortex' )
);
// phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- False positive: Row action array key, not WP_Query parameter.
$actions['exclude'] = sprintf(
'%s',
esc_url( $exclude_url ),
esc_html__( 'Exclude', 'contentcortex' )
);
}
}
return $title_output . $this->row_actions( $actions );
}
/**
* Post type column.
*
* @param array $item Current row item.
* @return string
*/
protected function column_type( $item ) {
return sprintf(
'%s',
esc_html( $item['post_type_label'] )
);
}
/**
* Date column (Last updated or published date).
*
* @param array $item Current row item.
* @return string
*/
protected function column_date( $item ) {
$basis = ocap_get_setting( 'date_basis', 'modified' );
$date_gmt = ( 'published' === $basis ) ? $item['post_date_gmt'] : $item['post_modified_gmt'];
$timestamp = strtotime( $date_gmt . ' GMT' );
if ( ! $timestamp ) {
return '—';
}
$date_formatted = get_date_from_gmt( $date_gmt, get_option( 'date_format' ) );
$time_diff = human_time_diff( $timestamp, time() );
$output = sprintf(
'%s
%s',
esc_html( $date_formatted ),
sprintf(
/* translators: %s: Human-readable time difference e.g. 95 days */
esc_html__( '%s ago', 'contentcortex' ),
esc_html( $time_diff )
)
);
if ( ! empty( $item['last_reviewed'] ) ) {
$reviewed_ts = strtotime( $item['last_reviewed'] . ' GMT' );
if ( $reviewed_ts ) {
$output .= sprintf(
'
%s: %s',
esc_html__( 'Reviewed', 'contentcortex' ),
esc_html( get_date_from_gmt( $item['last_reviewed'], get_option( 'date_format' ) ) )
);
}
}
return $output;
}
/**
* Days since update column with colored badge.
*
* @param array $item Current row item.
* @return string
*/
protected function column_days( $item ) {
$days = absint( $item['days_since_update'] );
$severity = ( 'high' === $item['severity'] ) ? 'ocap-badge-red' : 'ocap-badge-amber';
return sprintf(
'%s',
esc_attr( $severity ),
sprintf(
/* translators: %s: number of days */
_n( '%s day', '%s days', $days, 'contentcortex' ),
number_format_i18n( $days )
)
);
}
/**
* Day limit column.
*
* @param array $item Current row item.
* @return string
*/
protected function column_limit( $item ) {
return sprintf(
/* translators: %s: number of days */
esc_html__( '%s days', 'contentcortex' ),
number_format_i18n( absint( $item['day_limit'] ) )
);
}
/**
* Author column.
*
* @param array $item Current row item.
* @return string
*/
protected function column_author( $item ) {
return esc_html( $item['author_name'] ? $item['author_name'] : __( 'Unknown', 'contentcortex' ) );
}
/**
* Extra controls between bulk actions and pagination (filters).
*
* @param string $which Location: 'top' or 'bottom'.
*/
protected function extra_tablenav( $which ) {
if ( 'top' !== $which ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filter parameters for list table view.
$current_type = isset( $_GET['post_type_filter'] ) ? sanitize_key( wp_unslash( $_GET['post_type_filter'] ) ) : '';
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filter parameters for list table view.
$current_author = isset( $_GET['author_filter'] ) ? absint( $_GET['author_filter'] ) : 0;
$settings = ocap_get_settings();
$enabled_types = isset( $settings['post_types'] ) ? $settings['post_types'] : array();
echo '