'rot-link', 'plural' => 'rot-links', 'ajax' => false, ) ); } /** * @since 1.0.0 * * @return array */ public function get_columns(): array { return array( 'post_id' => __( 'Source Post', 'postlinkly' ), 'url' => __( 'Broken URL', 'postlinkly' ), 'anchor' => __( 'Anchor', 'postlinkly' ), 'rot_reason' => __( 'Reason', 'postlinkly' ), ); } /** * @since 1.0.0 * * @return void */ public function prepare_items(): void { $detector = new InternalRotDetector(); $this->items = $detector->detect( 500 ); $this->set_pagination_args( array( 'total_items' => count( $this->items ), 'per_page' => 500, 'total_pages' => 1, ) ); $this->_column_headers = array( $this->get_columns(), array(), array() ); } /** * @since 1.0.0 * @since 1.9.0 Names the target's actual post status for `not_published` rows. * * @param object $item Row data. * @param string $column_name Column key. * * @return string */ public function column_default( $item, $column_name ): string { switch ( $column_name ) { case 'post_id': $title = get_the_title( (int) $item->post_id ); $link = get_edit_post_link( (int) $item->post_id ); return '' . esc_html( '' !== $title ? $title : (string) $item->post_id ) . ''; case 'url': return '' . esc_html( (string) $item->url ) . ''; case 'anchor': return esc_html( (string) $item->anchor ); case 'rot_reason': $reasons = array( 'deleted' => __( 'Target deleted', 'postlinkly' ), 'not_published' => __( 'Target not published', 'postlinkly' ), ); $reason = (string) ( $item->rot_reason ?? 'unknown' ); $label = $reasons[ $reason ] ?? ucfirst( $reason ); // Name the actual status so a scheduled post (nothing wrong) is // distinguishable from a draft (genuinely broken). get_post_status_object() // covers custom statuses and supplies the translated label; it // returns null for a status no longer registered. if ( 'not_published' === $reason ) { $status = (string) ( $item->target_status ?? '' ); $status_obj = '' !== $status ? get_post_status_object( $status ) : null; if ( null !== $status_obj && isset( $status_obj->label ) ) { $label = sprintf( /* translators: 1: generic reason, 2: post status label (e.g. Scheduled, Draft). */ __( '%1$s (%2$s)', 'postlinkly' ), $label, $status_obj->label ); } } return esc_html( $label ); default: return ''; } } /** * Shown when there are no rot links. * * @since 1.0.0 * * @return void */ public function no_items(): void { esc_html_e( 'No internal-link rot detected. All internal links resolve to published content.', 'postlinkly' ); } }