<?php
class XenForo_Model_Sitemap extends XenForo_Model
{
public function insertPendingSitemap($id, $fileCount, $entryCount)
{
$this->_getDb()->query("
INSERT INTO xf_sitemap
(sitemap_id, is_active, file_count, entry_count, is_compressed, complete_date)
VALUES
(?, 0, ?, ?, 0, NULL)
ON DUPLICATE KEY UPDATE
is_active = VALUES(is_active),
file_count = VALUES(file_count),
entry_count = VALUES(entry_count),
is_compressed = VALUES(is_compressed),
complete_date = VALUES(complete_date)
", array($id, $fileCount, $entryCount));
}
public function completeSitemap($id, $isCompressed, $fileCount, $entryCount)
{
$res = $this->_getDb()->query("
UPDATE xf_sitemap
SET is_active = 1,
is_compressed = ?,
file_count = ?,
entry_count = ?,
complete_date = ?
WHERE sitemap_id = ?
", array(
$isCompressed ? 1 : 0,
$fileCount,
$entryCount,
XenForo_Application::$time,
$id
));
return $res->rowCount() ? true : false;
}
public function getCurrentSitemap()
{
return $this->_getDb()->fetchRow("
SELECT *
FROM xf_sitemap
WHERE is_active = 1
ORDER BY sitemap_id DESC
LIMIT 1
");
}
public function getSitemapHistory()
{
return $this->fetchAllKeyed("
SELECT *
FROM xf_sitemap
ORDER BY sitemap_id DESC
", 'sitemap_id');
}
public function cleanUpOldSitemaps($skipId = null)
{
$sitemaps = $this->fetchAllKeyed("
SELECT *
FROM xf_sitemap
WHERE is_active = 1
ORDER BY sitemap_id
", 'sitemap_id');
if ($skipId)
{
unset($sitemaps[$skipId]);
}
foreach ($sitemaps AS $sitemap)
{
$this->cleanUpSitemap($sitemap);
}
return $sitemaps;
}
public function cleanUpSitemap(array $sitemap)
{
$this->_getDb()->query("
UPDATE xf_sitemap
SET is_active = 0
WHERE sitemap_id = ?
", $sitemap['sitemap_id']);
for ($i = 1; $i <= $sitemap['file_count']; $i++)
{
$fileName = $this->getSitemapFileName($sitemap['sitemap_id'], $i);
@unlink($fileName);
$compressedFileName = $this->getSitemapFileName($sitemap['sitemap_id'], $i, true);
@unlink($compressedFileName);
}
}
public function deleteOldSitemapLogs($cutOff = null)
{
if ($cutOff === null)
{
$cutOff = XenForo_Application::$time - 86400 * 30;
}
$res = $this->_getDb()->query("
DELETE
FROM xf_sitemap
WHERE sitemap_id < ?
AND is_active = 0
", $cutOff);
return $res->rowCount();
}
public function getSitemapContentTypes($includeDisabled = false)
{
$types = array('core' => 'XenForo_SitemapHandler_Core');
$excluded = XenForo_Application::getOptions()->sitemapExclude;
foreach ($this->getContentTypesWithField('sitemap_handler_class') AS $type => $class)
{
if (empty($excluded[$type]) || $includeDisabled)
{
if (!class_exists($class))
{
continue;
}
$types[$type] = $class;
}
}
return $types;
}
public function getSitemapFileName($setId, $counter, $compressed = false)
{
$path = XenForo_Helper_File::getInternalDataPath() . '/sitemaps';
if (!XenForo_Helper_File::createDirectory($path, true))
{
throw new XenForo_Exception("Sitemap directory $path could not be created");
}
return "$path/sitemap-{$setId}-{$counter}.xml" . ($compressed ? '.gz' : '');
}
public function compressSitemapFile($setId, $counter)
{
$readFileName = $this->getSitemapFileName($setId, $counter);
if (!file_exists($readFileName))
{
return false;
}
$readFile = fopen($readFileName, 'rb');
$compressedFileName = $this->getSitemapFileName($setId, $counter, true);
$compressedFile = gzopen($compressedFileName, 'wb1');
$blockSize = 512 * 1024;
while (!feof($readFile))
{
gzwrite($compressedFile, fread($readFile, $blockSize));
}
fclose($readFile);
gzclose($compressedFile);
unlink($readFileName);
return $compressedFileName;
}
public function getSitemapPreamble()
{
return '<?xml version="1.0" encoding="UTF-8"?>'
. "\n" . '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"'
. ' xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">' . "\n";
}
public function getSitemapSuffix()
{
return '</urlset>';
}
public function buildSitemapEntry(array $result)
{
$content = '<url>'
. '<loc>' . htmlspecialchars($result['loc'], ENT_QUOTES, 'UTF-8') . '</loc>';
if (!empty($result['lastmod']))
{
$content .= '<lastmod>' . gmdate(DateTime::W3C, $result['lastmod']) . '</lastmod>';
}
if (isset($result['priority']))
{
$content .= '<priority>' . htmlspecialchars($result['priority'], ENT_QUOTES, 'UTF-8') . '</priority>';
}
if (isset($result['changefreq']))
{
$content .= '<changefreq>' . htmlspecialchars($result['changefreq'], ENT_QUOTES, 'UTF-8') . '</changefreq>';
}
if (!empty($result['image']))
{
if (!is_array($result['image']) || isset($result['image']['loc']))
{
$result['image'] = array($result['image']);
}
foreach ($result['image'] AS $image)
{
if (!is_array($image))
{
$image = array('loc' => $image);
}
$content .= '<image:image>';
foreach ($image AS $tag => $value)
{
$content .= "<image:$tag>" . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . "</image:$tag>";
}
$content .= '</image:image>';
}
}
$content .= '</url>';
return $content;
}
public function buildSitemapIndex(array $sitemap)
{
$output = '<?xml version="1.0" encoding="UTF-8"?>' . "\n"
. '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
$sitemapBase = XenForo_Application::getOptions()->boardUrl . '/sitemap.php?c=';
for ($i = 1; $i <= $sitemap['file_count']; $i++)
{
$url = $sitemapBase . $i;
$output .= "\t" . '<sitemap><loc>' . htmlspecialchars($url) . '</loc><lastmod>' . gmdate(DateTime::W3C, $sitemap['complete_date']) . '</lastmod></sitemap>' . "\n";
}
$output .= '</sitemapindex>';
return $output;
}
protected $_sitemapPingUrls = array(
'Google' => 'https://www.google.com/webmasters/tools/ping?sitemap=%s',
'Bing' => 'https://www.bing.com/ping?sitemap=%s'
);
public function sendSitemapPing()
{
$sitemapUrl = urlencode(XenForo_Application::getOptions()->boardUrl . '/sitemap.php');
foreach ($this->_sitemapPingUrls AS $serviceName => $pingUrl)
{
$url = sprintf($pingUrl, $sitemapUrl);
$client = XenForo_Helper_Http::getClient($url);
try
{
$client->request('GET');
}
catch (Exception $e)
{
XenForo_Error::logException($e, false, "Error submitting sitemap to $serviceName: ");
}
}
}
}