settings = $settings; $this->resolver = $resolver; } /** * Dependencies of one post. * * @param WP_Post $post Post. * @return array */ public function for_post( WP_Post $post ) { global $wpdb; $url = Url::normalize( (string) get_permalink( $post ), home_url( '/' ) ); $indexing = $this->resolver->indexing_for_post( $post ); $result = array( 'post_id' => $post->ID, 'title' => get_the_title( $post ), 'url' => $url, 'published' => 'publish' === $post->post_status, 'inbound' => 0, 'sources' => array(), 'menus' => array(), 'menu_items' => 0, 'redirects_to' => 0, 'children' => 0, 'noindex' => $indexing ? (bool) $indexing['noindex'] : false, 'canonical_elsewhere' => $indexing ? Url::normalize( $indexing['canonical'], home_url( '/' ) ) !== $url : false, 'in_sitemap' => false, 'limits' => __( 'Links in widgets, page-builder layouts, other websites and bookmarks are not included.', 'orbitstem-seo' ), ); $result['in_sitemap'] = $result['published'] && ! $result['noindex'] && ! $result['canonical_elsewhere'] && '' === $post->post_password && $this->settings->get( 'sitemap_enabled' ) && $this->settings->post_type( $post->post_type, 'sitemap' ) && ! ( new \Orbitstem\SEO\Content\MetaRepository() )->get_post( $post->ID, 'sitemap_exclude' ); if ( Tables::exist_cached() ) { // phpcs:disable WordPress.DB.DirectDatabaseQuery $sources = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT l.source_id, p.post_title FROM %i l INNER JOIN %i p ON p.ID = l.source_id WHERE l.target_id = %d AND l.kind = 'link' AND l.source_id <> %d ORDER BY l.source_id DESC", Tables::links(), $wpdb->posts, $post->ID, $post->ID ), ARRAY_A ); // phpcs:enable $result['inbound'] = count( $sources ); foreach ( array_slice( $sources, 0, 10 ) as $s ) { $result['sources'][] = array( 'id' => (int) $s['source_id'], 'title' => $s['post_title'], ); } } // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- menu items reference posts through meta; no core lookup by target. $items = array_map( 'intval', $wpdb->get_col( $wpdb->prepare( "SELECT m.post_id FROM {$wpdb->postmeta} m INNER JOIN {$wpdb->postmeta} t ON t.post_id = m.post_id AND t.meta_key = '_menu_item_type' AND t.meta_value = 'post_type' WHERE m.meta_key = '_menu_item_object_id' AND m.meta_value = %s", (string) $post->ID ) ) ); if ( $items ) { $result['menu_items'] = count( $items ); $menus = wp_get_object_terms( $items, 'nav_menu', array( 'fields' => 'names' ) ); $result['menus'] = is_array( $menus ) ? array_values( array_unique( $menus ) ) : array(); } if ( Tables::v3_ready() ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery $result['redirects_to'] = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE target IN (%s, %s)', Tables::redirects(), $url, untrailingslashit( $url ) ) ); } if ( is_post_type_hierarchical( $post->post_type ) ) { $result['children'] = count( get_children( array( 'post_parent' => $post->ID, 'post_type' => $post->post_type, 'post_status' => 'publish', 'fields' => 'ids', ) ) ); } return $result; } /** * Plain-language consequences of removing a post, one per line. * * @param array $impact Result of for_post(). * @return string[] */ public static function removal_consequences( array $impact ) { $lines = array(); if ( $impact['inbound'] ) { /* translators: %d: number of posts */ $lines[] = sprintf( _n( '%d post links to this page; those links will lead to a "page not found" unless you add a redirect.', '%d posts link to this page; those links will lead to a "page not found" unless you add a redirect.', $impact['inbound'], 'orbitstem-seo' ), $impact['inbound'] ); } if ( $impact['menu_items'] ) { /* translators: %s: menu names */ $lines[] = sprintf( __( 'It appears in navigation menus (%s); WordPress removes those menu items.', 'orbitstem-seo' ), implode( ', ', $impact['menus'] ) ); } if ( $impact['redirects_to'] ) { /* translators: %d: number of redirects */ $lines[] = sprintf( _n( '%d redirect points here and will then lead to a missing page.', '%d redirects point here and will then lead to a missing page.', $impact['redirects_to'], 'orbitstem-seo' ), $impact['redirects_to'] ); } if ( $impact['children'] ) { /* translators: %d: number of child pages */ $lines[] = sprintf( _n( '%d child page sits under it. Its address contains this page\'s slug, which WordPress renames in the trash, so links to the child page break too.', '%d child pages sit under it. Their addresses contain this page\'s slug, which WordPress renames in the trash, so links to them break too.', $impact['children'], 'orbitstem-seo' ), $impact['children'] ); } if ( $impact['in_sitemap'] ) { $lines[] = __( 'It leaves the sitemap; search engines will drop it from results over the next weeks.', 'orbitstem-seo' ); } return $lines; } }