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;
}