$sitemaps Sitemap files. */ public function index( array $sitemaps ): string { $xml = $this->header() . '' . "\n"; foreach ( $sitemaps as $sitemap ) { $xml .= "\t\n\t\t" . esc_xml( $sitemap['loc'] ) . "\n"; if ( ! empty( $sitemap['lastmod'] ) ) { $xml .= "\t\t" . esc_xml( $sitemap['lastmod'] ) . "\n"; } $xml .= "\t\n"; } return $xml . "\n"; } /** * URL set. * * @param list> $entries Entries: loc, lastmod, images, news, videos. */ public function urlset( array $entries ): string { $xml = $this->header() . '' . "\n"; foreach ( $entries as $entry ) { $xml .= "\t\n\t\t" . esc_xml( $entry['loc'] ) . "\n"; if ( ! empty( $entry['lastmod'] ) ) { $xml .= "\t\t" . esc_xml( $entry['lastmod'] ) . "\n"; } // Language versions (hreflang), including the page itself. foreach ( $entry['alternates'] ?? array() as $alternate ) { $xml .= "\t\t\n"; } foreach ( array_slice( $entry['images'] ?? array(), 0, 1000 ) as $image ) { $xml .= "\t\t\n\t\t\t" . esc_xml( $image ) . "\n\t\t\n"; } if ( ! empty( $entry['news'] ) ) { $news = $entry['news']; $xml .= "\t\t\n\t\t\t\n" . "\t\t\t\t" . esc_xml( (string) $news['name'] ) . "\n" . "\t\t\t\t" . esc_xml( (string) $news['language'] ) . "\n" . "\t\t\t\n" . "\t\t\t" . esc_xml( (string) $news['date'] ) . "\n" . "\t\t\t" . esc_xml( (string) $news['title'] ) . "\n" . "\t\t\n"; } foreach ( $entry['videos'] ?? array() as $video ) { $xml .= "\t\t\n" . "\t\t\t" . esc_xml( (string) $video['thumbnail'] ) . "\n" . "\t\t\t" . esc_xml( (string) $video['title'] ) . "\n" . "\t\t\t" . esc_xml( mb_substr( (string) $video['description'], 0, 2048 ) ) . "\n"; if ( ! empty( $video['content_loc'] ) ) { $xml .= "\t\t\t" . esc_xml( (string) $video['content_loc'] ) . "\n"; } if ( ! empty( $video['player_loc'] ) ) { $xml .= "\t\t\t" . esc_xml( (string) $video['player_loc'] ) . "\n"; } if ( ! empty( $video['duration'] ) && (int) $video['duration'] <= 28800 ) { $xml .= "\t\t\t" . (int) $video['duration'] . "\n"; } $xml .= "\t\t\n"; } $xml .= "\t\n"; } return $xml . "\n"; } /** * XSL stylesheet that makes sitemaps readable in a browser. */ public function stylesheet(): string { $title = esc_xml( __( 'XML Sitemap', 'wpinterface-seo' ) ); $intro = esc_xml( Branding::credit() /* translators: %s: plugin name. */ ? sprintf( __( 'This sitemap lists the pages search engines may index. It is generated by %s.', 'wpinterface-seo' ), Branding::name() ) : __( 'This sitemap lists the pages search engines may index.', 'wpinterface-seo' ) ); $col_url = esc_xml( __( 'URL', 'wpinterface-seo' ) ); $col_images = esc_xml( __( 'Images', 'wpinterface-seo' ) ); $col_updated = esc_xml( __( 'Last modified', 'wpinterface-seo' ) ); $col_sitemap = esc_xml( __( 'Sitemap', 'wpinterface-seo' ) ); $count_label = esc_xml( __( 'Number of URLs:', 'wpinterface-seo' ) ); $template = implode( "\n", array( '', '', '', '', '', '', '', '', '{title}', '', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet -- XSL for the XML sitemap, not a WordPress page: wp_enqueue_style() cannot reach it. '', '
', '

{title}

', '

{intro}

', '', '', '

{count_label}

', '', '', '', '', '
{col_sitemap}{col_updated}
', '
', '', '

{count_label}

', '', '', '', '', '
{col_url}{col_images}{col_updated}
', '
', '
', '
', '', '
', '
', ) ); return strtr( $template, array( '{css}' => esc_url( add_query_arg( 'ver', WPISEO_VERSION, WPISEO_URL . 'assets/css/sitemap.css' ) ), '{title}' => $title, '{intro}' => $intro, '{col_url}' => $col_url, '{col_images}' => $col_images, '{col_updated}' => $col_updated, '{col_sitemap}' => $col_sitemap, '{count_label}' => $count_label, ) ); } /** * XML declaration and stylesheet reference. */ private function header(): string { return '' . "\n" . '' . "\n"; } }