This commit is contained in:
2026-03-11 15:57:27 +01:00
parent 481271c972
commit b4b460fd21
10775 changed files with 2071579 additions and 26409 deletions

View File

@@ -0,0 +1,87 @@
<?php
namespace GRIM_SG\Vendor;
use GRIM_SG\Settings;
class Controller {
public static $slug = 'xml-sitemap-generator-for-google';
public function get_settings() {
$settings = new Settings();
$saved_options = get_option( self::$slug );
// TODO Remove this after Refactoring
if ( is_array( $saved_options ) ) {
$saved_options = (object) $saved_options;
}
if ( ! empty( $saved_options ) ) {
foreach ( $settings as $key => &$option ) {
if ( isset( $saved_options->{$key} ) ) {
if ( in_array( $key, array( 'cpt', 'taxonomies' ), true ) ) {
if ( is_array( $saved_options->{$key} ) ) {
foreach ( $saved_options->{$key} as $inner_key => $value ) {
$option[ $inner_key ] = is_array( $value )
? (object) $value // TODO Remove this after Refactoring
: $value;
}
}
} else {
$option = ( is_object( $option ) && is_array( $saved_options->{$key} ) )
? (object) $saved_options->{$key} // TODO Remove this after Refactoring
: $saved_options->{$key};
}
}
}
}
return $settings;
}
/**
* Get Custom Post Types
* @return string[]|\WP_Post_Type[]
*/
public function get_cpt( $output = 'names' ) {
$args = array(
'public' => true,
'_builtin' => false,
);
return get_post_types( $args, $output );
}
/**
* Get Taxonomy Types
* @return string[]|\WP_Taxonomy[]
*/
public function get_taxonomy_types( $output = 'names' ) {
$args = array(
'public' => true,
'show_ui' => true,
);
return get_taxonomies( $args, $output );
}
/**
* Get Allowed Post Types List
* @return array
*/
public function get_post_types_list( $post_types, $settings ) {
foreach ( $post_types as $key => $post_type ) {
if ( isset( $settings->{$post_type}->include ) && ! $settings->{$post_type}->include ) {
unset( $post_types[ $key ] );
}
}
foreach ( $this->get_cpt() as $cpt ) {
if ( ! empty( $settings->cpt[ $cpt ] ) && ! empty( $settings->cpt[ $cpt ]->include ) ) {
$post_types[] = $cpt;
}
}
return $post_types;
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace GRIM_SG\vendor;
class Migration extends Controller {
const DB_VERSION_KEY = 'sgg_version';
/**
* Database updates and callbacks that need to be run per Migration version.
*/
private $migrations = array(
'1.8.4' => array(
'migrate_settings_dynamic_created_objects',
),
'1.9.9' => array(
'migrate_video_settings',
),
);
public function __construct() {
add_action( 'admin_init', array( $this, 'run_migrations' ) );
}
/**
* Runs all the necessary migrations.
*/
public function run_migrations() {
$current_db_version = get_option( self::DB_VERSION_KEY, '' );
if ( version_compare( $current_db_version, GRIM_SG_VERSION, '>=' ) ) {
return;
}
foreach ( $this->migrations as $version => $update_callbacks ) {
if ( version_compare( $current_db_version, $version, '<' ) ) {
foreach ( $update_callbacks as $update_callback ) {
$this->{$update_callback}();
}
}
}
self::update_version();
}
/**
* Update Version in Database
*/
public static function update_version() {
update_option( self::DB_VERSION_KEY, GRIM_SG_VERSION );
}
/**
* Migrate Dynamic created CPT and Taxonomies to array
*/
public function migrate_settings_dynamic_created_objects() {
$settings = get_option( self::$slug, array() );
if ( ! empty( $settings ) ) {
$settings->cpt = array();
$settings->taxonomies = array();
foreach ( $this->get_cpt() as $cpt ) {
if ( ! empty( $settings->{$cpt} ) ) {
$settings->cpt[ $cpt ] = $settings->{$cpt};
}
}
foreach ( $this->get_taxonomy_types() as $taxonomy ) {
if ( ! empty( $settings->{$taxonomy} ) ) {
$settings->taxonomies[ $taxonomy ] = $settings->{$taxonomy};
}
}
update_option( Controller::$slug, $settings );
}
}
/**
* Migrate Video Sitemap Settings
*/
public function migrate_video_settings() {
$settings = get_option( self::$slug, array() );
if ( ! empty( $settings ) ) {
$settings->enable_video_api_cache = $settings->enable_youtube_cache ?? true;
update_option( Controller::$slug, $settings );
}
// Migrate YouTube Data to Video API Data
$youtube_data = get_option( 'sgg_youtube_data', array() );
if ( ! empty( $youtube_data ) ) {
update_option( 'sgg_video_api_data', $youtube_data );
}
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace GRIM_SG;
class PTSettings {
public $include = true;
public $priority = 3;
public $frequency = 'weekly';
public $google_news = false;
public $image_sitemap = true;
public $video_sitemap = true;
// Frequencies
public static $ALWAYS = 'always';
public static $HOURLY = 'hourly';
public static $DAILY = 'daily';
public static $WEEKLY = 'weekly';
public static $MONTHLY = 'monthly';
public static $YEARLY = 'yearly';
public static $NEVER = 'never';
/**
* DefaultSettings constructor.
*
* @param int $priority
* @param int $frequency
*/
public function __construct( $priority = 3, $frequency = 1, $google_news = false, $image_sitemap = false, $video_sitemap = false ) {
$this->priority = $priority;
$this->frequency = $frequency;
$this->google_news = $google_news;
$this->image_sitemap = $image_sitemap;
$this->video_sitemap = $video_sitemap;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace GRIM_SG\Vendor;
class QueryBuilder {
/**
* Run SQL Query
*
* @param $sql
* @return array|null|object
*/
public static function run_query( $sql ) {
global $wpdb;
return $wpdb->get_results( $sql );
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
class Settings extends Controller {
// Global Settings
public $sitemap_url = 'sitemap.xml';
public $html_sitemap_url = 'sitemap.html';
public $enable_sitemap = true;
public $links_per_page = 1000;
public $enable_html_sitemap = false;
public $sitemap_to_robots = true;
public $enable_indexnow = true;
public $sitemap_view = 'sitemap-index';
// Sitemap Data Settings
public $home;
public $page;
public $post;
public $archive;
public $archive_older;
public $authors;
public $media;
public $exclude_posts;
public $exclude_terms;
public $include_only_terms;
public $posts_priority;
public $custom_sitemaps = array();
public $additional_pages = array();
public $cpt = array();
public $taxonomies = array();
// Google News Data Settings
public $enable_google_news = false;
public $google_news_old_posts = false;
public $google_news_name = '';
public $google_news_url = 'google-news.xml';
public $google_news_keywords = '';
public $google_news_stocks = false;
public $google_news_exclude;
public $google_news_exclude_terms;
public $google_news_include_only_terms;
// Media Sitemap Data Settings
public $enable_image_sitemap = false;
public $enable_video_sitemap = false;
public $image_sitemap_url = 'image-sitemap.xml';
public $video_sitemap_url = 'video-sitemap.xml';
public $hide_image_previews = false;
public $hide_image_sitemap_xsl = false;
public $hide_video_sitemap_xsl = false;
public $image_mime_types = array(
'image/jpeg' => true,
'image/png' => true,
'image/gif' => true,
'image/bmp' => true,
'image/webp' => true,
'image/avif' => true,
);
public $youtube_api_key = '';
public $vimeo_api_key = '';
public $exclude_broken_images = false;
public $include_featured_images = false;
public $include_woo_gallery = false;
// Cache Settings
public $enable_cache = false;
public $cache_timeout = 24;
public $cache_timeout_period = 3600;
public $clear_cache_on_save_post = false;
public $enable_video_api_cache = true;
public $disable_media_sitemap_cache = false;
public $minimize_sitemap = false;
public $hide_branding = true;
public $enable_cronjob = false;
public $cronjob_runtime = 'daily';
public $colors = array(
'header_background_color' => '#82a745',
'header_text_color' => '#ffffff',
'sitemap_background_color' => '#ecf4db',
'sitemap_text_color' => '#444444',
'sitemap_link_color' => '#2d89c7',
'footer_text_color' => '#666666',
);
/**
* Settings constructor.
*/
public function __construct() {
$this->home = new PTSettings( 10, PTSettings::$DAILY );
$this->page = new PTSettings( 6, PTSettings::$WEEKLY, false, true, true );
$this->post = new PTSettings( 6, PTSettings::$MONTHLY, true, true, true );
$this->archive = new PTSettings( 6, PTSettings::$DAILY );
$this->archive_older = new PTSettings( 3, PTSettings::$YEARLY );
$this->authors = new PTSettings( 3, PTSettings::$WEEKLY );
$this->media = new PTSettings( 3, PTSettings::$WEEKLY );
// Media Pages are disabled by default
$this->media->include = false;
foreach ( $this->get_cpt() as $cpt ) {
$this->cpt[ $cpt ] = new PTSettings( 6, PTSettings::$MONTHLY );
}
foreach ( $this->get_taxonomy_types() as $taxonomy ) {
$this->taxonomies[ $taxonomy ] = new PTSettings( 3, PTSettings::$WEEKLY );
}
}
/**
* Get Default Settings
* @param $option
* @return PTSettings
*/
public function get_row_value( $option ) {
$settings = new PTSettings();
$settings->include = isset( $_POST[ $option . '_include' ] ) ? sanitize_text_field( $_POST[ $option . '_include' ] ) : false;
$settings->priority = isset( $_POST[ $option . '_priority' ] ) ? sanitize_text_field( $_POST[ $option . '_priority' ] ) : 0;
$settings->frequency = isset( $_POST[ $option . '_frequency' ] ) ? sanitize_text_field( $_POST[ $option . '_frequency' ] ) : $settings->frequency;
$settings->google_news = isset( $_POST[ $option . '_google_news' ] ) ? sanitize_text_field( $_POST[ $option . '_google_news' ] ) : 0;
$settings->image_sitemap = isset( $_POST[ $option . '_image_sitemap' ] ) ? sanitize_text_field( $_POST[ $option . '_image_sitemap' ] ) : 0;
$settings->video_sitemap = isset( $_POST[ $option . '_video_sitemap' ] ) ? sanitize_text_field( $_POST[ $option . '_video_sitemap' ] ) : 0;
return $settings;
}
}

View File

@@ -0,0 +1,636 @@
<?php
namespace GRIM_SG\Vendor;
use GRIM_SG\GoogleNews;
use GRIM_SG\ImageSitemap;
use GRIM_SG\MultilingualSitemap;
use GRIM_SG\VideoSitemap;
class SitemapGenerator {
public $sitemapFileName = 'sitemap.xml';
public $sitemapIndexFileName = 'sitemap-index.xml';
public $robotsFileName = 'robots.txt';
public $maxURLsPerSitemap = 50000;
public $createGZipFile = false;
private $baseURL;
private $searchEngines = array(
array(
'https://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=USERID&url=',
'https://search.yahooapis.com/SiteExplorerService/V1/ping?sitemap=',
),
'https://www.google.com/webmasters/tools/ping?sitemap=',
'https://submissions.ask.com/ping?sitemap=',
'https://www.bing.com/webmaster/ping.aspx?siteMap=',
);
private $urls = array();
private $sitemaps;
private $sitemapIndex;
private $sitemapFullURL;
/**
* Constructor.
*
* @param string $baseURL You site URL, with / at the end.
*/
public function __construct( $baseURL ) {
$this->baseURL = $baseURL;
}
public function addUrls( $urls_array, $callback = 'addUrl', $template = 'sitemap' ) {
if ( ! is_array( $urls_array ) ) {
throw new \InvalidArgumentException( 'Array as argument should be given.' );
}
if ( sgg_is_sitemap_index( $template ) ) {
foreach ( $urls_array as $sitemap => $inner_urls ) {
foreach ( $inner_urls as $url ) {
$this->{$callback}( $url, $sitemap );
}
}
} else {
foreach ( $urls_array as $url ) {
$this->{$callback}( $url );
}
}
}
/**
* Use this to add single URL to Google News Sitemap.
*/
public function addNewsUrl( $item ) {
$url = $item[0] ?? null;
$this->validateUrl( $url );
$tmp = array();
$tmp['loc'] = $url;
$tmp['publication_name'] = $item[1] ?? null;
$tmp['language'] = $item[2] ?? null;
$tmp['title'] = $item[3] ?? null;
if ( isset( $item[4] ) ) {
$tmp['lastmod'] = $item[4];
}
if ( sgg_pro_enabled() ) {
$tmp['keywords'] = implode( ', ', apply_filters( 'sgg_news_keywords', array(), $item[5] ?? null ) );
$tmp['stock_tickers'] = implode( ', ', apply_filters( 'sgg_news_stock_tickers', array(), $item[5] ?? null ) );
}
$this->urls[] = $tmp;
}
/**
* Use this to add single URL to Sitemap.
*/
public function addMediaUrl( $item, $sitemap = null ) {
$url = $item[0] ?? null;
$this->validateUrl( $url );
$tmp = array();
$tmp['loc'] = $url;
if ( isset( $item[1] ) ) {
$tmp['media'] = $item[1];
}
if ( ! empty( $sitemap ) ) {
$tmp['lastmod'] = gmdate( 'c' );
$this->urls[ $sitemap ][] = $tmp;
} else {
$this->urls[] = $tmp;
}
}
/**
* Use this to add single URL to Sitemap.
*/
public function addUrl( $item, $sitemap = null ) {
$url = $item[0] ?? null;
$this->validateUrl( $url );
$tmp = array();
$tmp['loc'] = $url;
if ( isset( $item[1] ) ) {
$tmp['lastmod'] = $item[1];
}
if ( isset( $item[2] ) ) {
$tmp['changefreq'] = $item[2];
}
if ( isset( $item[3] ) ) {
$tmp['priority'] = $item[3];
}
if ( ! empty( $sitemap ) ) {
$this->urls[ $sitemap ][] = $tmp;
} else {
$this->urls[] = $tmp;
}
}
/**
* Validate Sitemap Item URL
*/
public function validateUrl( $url ) {
if ( null === $url ) {
throw new \InvalidArgumentException( 'URL is mandatory. At least one argument should be given.' );
}
$urlLenght = extension_loaded( 'mbstring' ) ? mb_strlen( $url ) : strlen( $url );
if ( $urlLenght > 2048 ) {
throw new \InvalidArgumentException(
"URL lenght can't be bigger than 2048 characters.
Note, that precise url length check is guaranteed only using mb_string extension.
Make sure Your server allow to use mbstring extension."
);
}
}
/**
* Create sitemap in memory.
*/
public function createSitemap( $template = 'sitemap', $headers = array(), $is_xml = true ) {
if ( ! isset( $this->urls ) ) {
throw new \BadMethodCallException( 'To create sitemap, call addUrl or addUrls function first.' );
}
if ( $this->maxURLsPerSitemap > 50000 ) {
throw new \InvalidArgumentException( 'More than 50,000 URLs per single sitemap is not allowed.' );
}
$settings = ( new Controller() )->get_settings();
$stylesheet_template = sgg_maybe_remove_inner_suffix( $template );
$stylesheet_path = apply_filters( 'sitemap_xsl_template_path', 'sitemap-stylesheet.xsl' );
$stylesheet_url = sgg_get_sitemap_url( "{$stylesheet_path}?template={$stylesheet_template}", "sitemap_xsl={$stylesheet_template}", false );
$stylesheet_url = strtok( $stylesheet_url, '&' ); // remove & query string
$is_sitemap_index = sgg_is_sitemap_index( $template, $settings );
$is_media_template = in_array( $template, array( 'image-sitemap', 'video-sitemap' ), true );
$is_index_template = $is_media_template || 'sitemap' === $template;
$sitemap_urls = $is_sitemap_index
? $this->urls
: array_chunk( $this->urls, $this->maxURLsPerSitemap );
foreach ( $sitemap_urls as $sitemap_key => $sitemap ) {
$dom = $this->create_sitemap_dom( $stylesheet_url, $template, $settings );
$urlset = $this->create_sitemap_urlset( $dom, $headers );
$dom->appendChild( $urlset );
foreach ( $sitemap as $url ) {
$url_element = $dom->createElement( 'url' );
$url_element->appendChild(
$dom->createElement( 'loc', htmlspecialchars( $url['loc'], ENT_QUOTES, 'UTF-8' ) )
);
if ( GoogleNews::$template === $template ) {
if ( $settings->google_news_old_posts && GoogleNews::is_older_than_48h( $url['lastmod'] ) ) {
$url_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] )
);
} else {
$news = $url_element->appendChild( $dom->createElement( 'news:news' ) );
if ( isset( $url['publication_name'] ) ) {
$publication = $dom->createElement( 'news:publication' );
$news->appendChild( $publication );
$publication->appendChild(
$dom->createElement( 'news:name', esc_html( $url['publication_name'] ) )
);
$publication->appendChild(
$dom->createElement( 'news:language', $url['language'] )
);
}
if ( isset( $url['lastmod'] ) ) {
$news->appendChild(
$dom->createElement( 'news:publication_date', $url['lastmod'] )
);
}
if ( isset( $url['title'] ) ) {
$news->appendChild(
$dom->createElement( 'news:title', esc_html( $url['title'] ) )
);
}
if ( sgg_pro_enabled() ) {
$news->appendChild(
$dom->createElement( 'news:keywords', $url['keywords'] )
);
$news->appendChild(
$dom->createElement( 'news:stock_tickers', $url['stock_tickers'] )
);
}
}
} elseif ( strpos( $template, ImageSitemap::$template ) !== false ) {
if ( isset( $url['lastmod'] ) ) {
$url_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] )
);
} else {
if ( ! empty( $url['media'] ) ) {
foreach ( $url['media'] as $image ) {
$image_element = $url_element->appendChild( $dom->createElement( 'image:image' ) );
$image_element->appendChild(
$dom->createElement( 'image:loc', $image )
);
}
}
}
} elseif ( strpos( $template, VideoSitemap::$template ) !== false ) {
if ( isset( $url['lastmod'] ) ) {
$url_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] )
);
} else {
if ( ! empty( $url['media'] ) ) {
foreach ( $url['media'] as $video ) {
$video_element = $url_element->appendChild( $dom->createElement( 'video:video' ) );
$video_element->appendChild(
$dom->createElement( 'video:thumbnail_loc', esc_url( $video['thumbnail'] ?? '' ) )
);
// Decode HTML entities first, then DOMDocument will handle XML escaping properly
$video_title = html_entity_decode( $video['title'] ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8' );
$video_element->appendChild(
$dom->createElement( 'video:title', $video_title )
);
// Decode HTML entities first, then DOMDocument will handle XML escaping properly
$video_description = html_entity_decode( $video['description'] ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8' );
$video_element->appendChild(
$dom->createElement( 'video:description', $video_description )
);
$video_element->appendChild(
$dom->createElement( 'video:player_loc', esc_url( $video['player_loc'] ?? '' ) )
);
// Decode HTML entities first, then DOMDocument will handle XML escaping properly
$video_duration = html_entity_decode( $video['duration'] ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8' );
$video_element->appendChild(
$dom->createElement( 'video:duration', $video_duration )
);
}
}
}
} else {
if ( isset( $url['lastmod'] ) ) {
$url_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] )
);
}
if ( isset( $url['changefreq'] ) ) {
$url_element->appendChild(
$dom->createElement( 'changefreq', $url['changefreq'] )
);
}
if ( isset( $url['priority'] ) ) {
$url_element->appendChild(
$dom->createElement( 'priority', $url['priority'] )
);
}
}
$urlset->appendChild( $url_element );
if ( $is_sitemap_index && $is_index_template ) {
$this->sitemaps[ $sitemap_key ][] = array(
'loc' => $url['loc'],
'lastmod' => $url['lastmod'],
);
}
}
if ( ! sgg_pro_enabled() || ! $settings->minimize_sitemap ) {
$dom->formatOutput = true;
}
if ( ! $is_index_template || ! $is_sitemap_index ) {
$ready_sitemap = $dom->saveXML();
if ( $is_sitemap_index ) {
$this->sitemaps[ $sitemap_key ][] = $ready_sitemap;
$this->sitemaps[ $sitemap_key ]['lastmod'] = $url['lastmod'] ?? gmdate( 'c' );
} else {
$this->sitemaps[] = $ready_sitemap;
}
}
}
if ( null === $this->sitemaps ) {
$dom = $this->create_sitemap_dom( $stylesheet_url, $template, $settings );
$urlset = $this->create_sitemap_urlset( $dom, $headers );
$dom->appendChild( $urlset );
$this->sitemaps[] = $dom->saveXML();
}
if ( count( $this->sitemaps ) > 1000 ) {
throw new \LengthException( 'Sitemap index can contains 1000 single sitemaps. Perhaps You trying to submit too many URLs.' );
}
$is_media_index = $is_media_template && $is_sitemap_index;
if ( ! empty( $settings->sitemap_view ) && ( ( 'sitemap' === $template && count( $this->sitemaps ) > 0 ) || $is_media_index ) ) {
$stylesheet_url = sgg_get_sitemap_url( "{$stylesheet_path}?template=sitemap-index", 'sitemap_xsl=sitemap-index', false );
$stylesheet_url = strtok( $stylesheet_url, '&' ); // remove & query string
$dom = $this->create_sitemap_dom( $stylesheet_url, $template, $settings );
$sitemapindex = $dom->createElement( 'sitemapindex' );
$sitemapindex->setAttribute( 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance' );
$sitemapindex->setAttribute( 'xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd' );
$sitemapindex->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
$dom->appendChild( $sitemapindex );
foreach ( $this->sitemaps as $sitemap_key => $sitemap ) {
if ( ! empty( $sitemap ) && is_array( $sitemap ) ) {
if ( 'page' === $sitemap_key && sgg_get_home_url_with_trailing_slash() === ( $sitemap[0]['loc'] ?? '' ) && 1 < count( $sitemap ) ) {
$sitemap[0] = array(
'loc' => $sitemap[0]['loc'],
'lastmod' => max( $sitemap[0]['lastmod'] ?? '', $sitemap[1]['lastmod'] ?? '' ),
);
if ( ! empty( $sitemap[1] ) ) {
unset( $sitemap[1] );
}
$sitemap = array_values( $sitemap );
}
foreach ( $sitemap as $index => $url ) {
$sitemap_element = $dom->createElement( 'sitemap' );
$sitemap_type = $is_xml ? 'xml' : 'html';
$default_number = $is_media_template ? 1 : '';
$sitemap_number = 0 < $index ? intval( $index ) + 1 : $default_number;
$page_param = 0 < $sitemap_number ? "&page={$sitemap_number}" : '';
$sitemap_element->appendChild(
$dom->createElement(
'loc',
esc_url( sgg_get_sitemap_url( "{$sitemap_key}-sitemap{$sitemap_number}.{$sitemap_type}", "sitemap_{$sitemap_type}=true&inner_sitemap={$sitemap_key}{$page_param}", false ) )
)
);
$sitemap_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] ?? gmdate( 'c' ) )
);
$sitemapindex->appendChild( $sitemap_element );
}
}
}
if ( $is_xml && 'sitemap' === $template ) {
$additional_sitemaps = apply_filters( 'sgg_additional_index_sitemaps', $settings->custom_sitemaps ?? array() );
if ( $settings->enable_image_sitemap ) {
$additional_sitemaps[] = array(
'url' => sgg_get_sitemap_url( $settings->image_sitemap_url, 'image_sitemap' ),
);
}
if ( $settings->enable_video_sitemap ) {
$additional_sitemaps[] = array(
'url' => sgg_get_sitemap_url( $settings->video_sitemap_url, 'video_sitemap' ),
);
}
foreach ( $additional_sitemaps as $additional_sitemap ) {
$sitemap_element = $dom->createElement( 'sitemap' );
$sitemap_url = ! empty( $additional_sitemap['url'] ) ? esc_url( $additional_sitemap['url'] ) : $additional_sitemap;
if ( ! is_string( $sitemap_url ) ) {
continue;
}
$sitemap_element->appendChild(
$dom->createElement( 'loc', $sitemap_url )
);
$sitemap_element->appendChild(
$dom->createElement(
'lastmod',
! empty( $additional_sitemap['lastmod'] ) ? $additional_sitemap['lastmod'] : gmdate( 'c' )
)
);
$sitemapindex->appendChild( $sitemap_element );
}
}
if ( ! sgg_pro_enabled() || ! $settings->minimize_sitemap ) {
$dom->formatOutput = true;
}
$this->sitemapFullURL = $this->baseURL . $this->sitemapIndexFileName;
$this->sitemapIndex = array(
$this->sitemapIndexFileName,
$dom->saveXML(),
);
} else {
if ( $this->createGZipFile ) {
$this->sitemapFullURL = $this->baseURL . $this->sitemapFileName . '.gz';
} else {
$this->sitemapFullURL = $this->baseURL . $this->sitemapFileName;
}
if ( ! empty( $this->sitemaps[0] ) ) {
$this->sitemaps[0] = array(
$this->sitemapFileName,
$this->sitemaps[0],
);
}
}
}
/**
* Create Multilingual Sitemap in memory.
*/
public function createMultilingualSitemap( $urls = array(), $is_xml = true ) {
if ( ! isset( $this->urls ) ) {
throw new \BadMethodCallException( 'To create sitemap, call addUrl or addUrls function first.' );
}
if ( $this->maxURLsPerSitemap > 50000 ) {
throw new \InvalidArgumentException( 'More than 50,000 URLs per single sitemap is not allowed.' );
}
$stylesheet_path = apply_filters( 'sitemap_xsl_template_path', 'sitemap-stylesheet.xsl' );
$settings = ( new Controller() )->get_settings();
$dom = $this->create_sitemap_dom(
sgg_get_sitemap_url( "{$stylesheet_path}?template=multilingual-sitemap", 'sitemap_xsl=sitemap-index', false ),
'',
$settings
);
$sitemapindex = $dom->createElement( 'sitemapindex' );
$sitemapindex->setAttribute( 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance' );
$sitemapindex->setAttribute( 'xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd' );
$sitemapindex->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
$dom->appendChild( $sitemapindex );
foreach ( $urls as $url ) {
$sitemap_element = $dom->createElement( 'sitemap' );
$sitemap_element->appendChild(
$dom->createElement(
'loc',
esc_url( $url )
)
);
$sitemap_element->appendChild(
$dom->createElement( 'lastmod', gmdate( DATE_W3C ) )
);
$sitemapindex->appendChild( $sitemap_element );
}
if ( ! sgg_pro_enabled() || ! $settings->minimize_sitemap ) {
$dom->formatOutput = true;
}
$this->sitemapFullURL = $this->baseURL . $this->sitemapIndexFileName;
$this->sitemapIndex = array(
$this->sitemapIndexFileName,
$dom->saveXML(),
);
}
public function create_sitemap_dom( $stylesheet_url, $template = '', $settings = null ) {
$generator_info = 'sitemap-generator-url="https://wpgrim.com" sitemap-generator-version="' . GRIM_SG_VERSION . '"';
$dom = new \DOMDocument( '1.0', 'UTF-8' );
// Get settings if not provided
if ( null === $settings ) {
$settings = ( new Controller() )->get_settings();
}
// Skip XSL stylesheet reference based on settings
$is_index_sitemap = strpos( $stylesheet_url, 'sitemap-index' ) !== false;
$skip_xsl = false;
if ( ! $is_index_sitemap ) {
if ( strpos( $template, VideoSitemap::$template ) !== false ) {
$skip_xsl = ! empty( $settings->hide_video_sitemap_xsl );
} elseif ( strpos( $template, ImageSitemap::$template ) !== false ) {
$skip_xsl = ! empty( $settings->hide_image_sitemap_xsl );
}
}
if ( ! $skip_xsl ) {
$dom->appendChild(
$dom->createProcessingInstruction(
'xml-stylesheet',
'type="text/xsl" href="' . $stylesheet_url . '"'
)
);
}
$dom->appendChild( $dom->createComment( $generator_info ) );
return $dom;
}
public function create_sitemap_urlset( $dom, $headers = array() ) {
$urlset = $dom->createElement( 'urlset' );
$urlset->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
if ( ! empty( $headers ) ) {
foreach ( $headers as $key => $header ) {
$urlset->setAttribute( $key, $header );
}
}
return $urlset;
}
/**
* Returns created sitemaps as array of strings.
* Use it You want to work with sitemap without saving it as files.
* @return array of strings
* @access public
*/
public function toArray() {
if ( isset( $this->sitemapIndex ) ) {
return array_merge( array( $this->sitemapIndex ), $this->sitemaps );
} else {
return $this->sitemaps;
}
}
/**
* Will print sitemaps.
* @access public
*/
public function outputSitemap( $template, $is_xml, $inner_sitemap = null ) {
add_filter( 'trp_stop_translating_page', '__return_true' );
ob_get_clean();
if ( $is_xml ) {
header( 'Content-Type: text/xml; charset=utf-8' );
} else {
ob_start();
}
if ( ! empty( $inner_sitemap ) && sgg_is_sitemap_index( $template ) && ! empty( $this->sitemaps[ $inner_sitemap ][0] ) ) {
echo $this->sitemaps[ $inner_sitemap ][0];
} else {
if ( ! empty( $this->sitemapIndex[1] ) ) {
$template = 'sitemap-index';
echo $this->sitemapIndex[1];
} else {
echo $this->sitemaps[0][1] ?? '';
}
}
if ( ! $is_xml ) {
$xml_source = ob_get_clean();
$xml = new \DOMDocument();
$xml->loadXML( $xml_source );
ob_start();
load_template(
GRIM_SG_PATH . '/templates/xsl/sitemap.php',
false,
compact( 'template', 'is_xml' )
);
$xsl_content = ob_get_clean();
$xsl = new \DOMDocument();
$xsl->loadXML( $xsl_content );
$proc = new \XSLTProcessor();
$proc->importStyleSheet( $xsl );
$dom_tran_obj = $proc->transformToDoc( $xml );
foreach ( $dom_tran_obj->childNodes as $node ) {
echo $dom_tran_obj->saveXML( $node ) . "\n";
}
}
if ( ob_get_contents() ) {
ob_end_flush();
}
}
}