Skip to content
← Back to Functions
Code

Sitemap Url Builder

Builds sitemap URL entries with loc, lastmod, priority, and changefreq.

Function signature

ogBuildSitemapUrlSet(url_rows = array(), options = array())

Categories

  • Import and Export

Parameters

url_rowsURL rows containing loc, lastmod, priority, and changefreq values.optionsSitemap policy options. Recognized keys: `allow_query_strings`, `max_urls`.

Return value

Short public-safe status message.

  • urls
  • url_count
  • warnings

Compatibility

Existing function name and call order preserved; metadata signature corrected to source.

Minimum PHP version: 7.4

Security notes

Validate request method, identity, permissions, policy arrays, URLs, signatures, and caller-owned allowlists before use; keep secrets and internal paths out of public output.

Code

<?php

/*
 * Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
 * Free for personal and internal use. Paid project use requires visible credit
 * to Jeffery L. Paris. Corporate use requires a paid license fee unless a
 * separate written license states otherwise.
 */

/**
 * Builds sitemap URL entries with loc, lastmod, priority, and changefreq.
 *
 * Only canonical SEF URLs are accepted. Query-string URLs and insecure URLs are skipped unless
 * explicitly allowed by policy.
 *
 * @param array $url_rows URL rows containing loc, lastmod, priority, and changefreq values.
 * @param array $options Sitemap policy options.
 * @return array Sitemap URL-set data and skipped-row warnings.
 */
function ogBuildSitemapUrlSet($url_rows = array(), $options = array()) {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	if (!is_array($url_rows)) {
		$result['message'] = 'URL rows must be an array.';
		return $result;
	}
	if (!is_array($options)) {
		$options = array();
	}

	$allow_query_strings = false;
	if (!empty($options['allow_query_strings'])) {
		$allow_query_strings = true;
	}

	$max_urls = 50000;
	if (!empty($options['max_urls'])) {
		$max_urls = (int)$options['max_urls'];
	}
	if ($max_urls < 1 || $max_urls > 50000) {
		$max_urls = 50000;
	}

	$allowed_changefreq = array('always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never');
	$urls = array();
	$warnings = array();

	foreach ($url_rows as $index => $row) {
		if (!is_array($row)) {
			$warnings[] = 'Row ' . $index . ' skipped because it is not an array.';
			continue;
		}
		$loc = '';
		if (!empty($row['loc'])) {
			$loc = trim((string)$row['loc']);
		}
		if (empty($loc)) {
			$warnings[] = 'Row ' . $index . ' skipped because loc is missing.';
			continue;
		}
		if (stripos($loc, 'http://') === 0 || stripos($loc, 'https://www.') === 0 || stripos($loc, '//www.') === 0) {
			$warnings[] = 'Row ' . $index . ' skipped because URL violates canonical URL policy.';
			continue;
		}
		if (!$allow_query_strings && strpos($loc, '?') !== false) {
			$warnings[] = 'Row ' . $index . ' skipped because query strings are not allowed.';
			continue;
		}

		$lastmod = '';
		if (!empty($row['lastmod'])) {
			$time = strtotime((string)$row['lastmod']);
			if (!empty($time)) {
				$lastmod = gmdate('Y-m-d', $time);
			}
		}

		$priority = '0.5';
		if (isset($row['priority']) && is_numeric($row['priority'])) {
			$priority_float = (float)$row['priority'];
			if ($priority_float < 0) {
				$priority_float = 0;
			}
			if ($priority_float > 1) {
				$priority_float = 1;
			}
			$priority = number_format($priority_float, 1, '.', '');
		}

		$changefreq = 'weekly';
		if (!empty($row['changefreq'])) {
			$candidate = strtolower(trim((string)$row['changefreq']));
			if (in_array($candidate, $allowed_changefreq, true)) {
				$changefreq = $candidate;
			}
		}

		$urls[] = array(
			'loc' => $loc,
			'lastmod' => $lastmod,
			'priority' => $priority,
			'changefreq' => $changefreq
		);
		if (count($urls) >= $max_urls) {
			break;
		}
	}

	$result['success'] = true;
	$result['message'] = 'Sitemap URL set built.';
	$result['data'] = array(
		'urls' => $urls,
		'url_count' => count($urls),
		'warnings' => $warnings
	);

	return $result;
}