Файл: concrete5.7.5.6/concrete/jobs/generate_sitemap.php
Строк: 299
<?php
namespace ConcreteJob;
use ConcreteCoreCacheCache;
use Config;
use Job as AbstractJob;
use Core;
use Database;
use PermissionKey;
use Group;
use DateTime;
use CollectionAttributeKey;
use ConcreteCorePermissionAccessEntityGroupEntity as GroupPermissionAccessEntity;
use ConcreteCoreMultilingualPageSectionSection as MultilingualSection;
use SimpleXMLElement;
use Page;
use Events;
class GenerateSitemap extends AbstractJob
{
/** The end-of-line terminator.
* @var string
*/
const EOL = "n";
/** Returns the job name.
* @return string
*/
public function getJobName()
{
return t('Generate the sitemap.xml file');
}
/** Returns the job description.
* @return string
*/
public function getJobDescription()
{
return t('Generate the sitemap.xml file that search engines use to crawl your site.');
}
/** Executes the job.
* @throws Exception Throws an exception in case of errors.
*
* @return string Returns a string describing the job result in case of success.
*/
public function run()
{
Cache::disableAll();
try {
$instances = array(
'navigation' => Core::make('helper/navigation'),
'dashboard' => Core::make('helper/concrete/dashboard'),
'view_page' => PermissionKey::getByHandle('view_page'),
'guestGroup' => Group::getByID(GUEST_GROUP_ID),
'now' => new DateTime('now'),
'ak_exclude_sitemapxml' => CollectionAttributeKey::getByHandle('exclude_sitemapxml'),
'ak_sitemap_changefreq' => CollectionAttributeKey::getByHandle('sitemap_changefreq'),
'ak_sitemap_priority' => CollectionAttributeKey::getByHandle('sitemap_priority'),
);
$instances['guestGroupAE'] = array(GroupPermissionAccessEntity::getOrCreate($instances['guestGroup']));
if (Core::make('multilingual/detector')->isEnabled()) {
$instances['multilingualSections'] = MultilingualSection::getList();
} else {
$instances['multilingualSections'] = array();
}
$xml = '<?xml version="1.0" encoding="' . APP_CHARSET . '"?>';
$xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"';
if ($instances['multilingualSections']) {
$xml .= ' xmlns:x="http://www.w3.org/1999/xhtml"';
}
$xml .= ' />';
$xmlDoc = new SimpleXMLElement($xml);
$rs = Database::get()->query('SELECT cID FROM Pages');
while ($row = $rs->FetchRow()) {
self::addPage($xmlDoc, intval($row['cID']), $instances);
}
$rs->Close();
$event = new SymfonyComponentEventDispatcherGenericEvent();
$event->setArgument('xmlDoc', $xmlDoc);
Events::dispatch('on_sitemap_xml_ready', $event);
$dom = dom_import_simplexml($xmlDoc)->ownerDocument;
$dom->formatOutput = true;
$addedPages = count($xmlDoc->url);
$relName = ltrim(Config::get('concrete.sitemap_xml.file'), '\/');
$osName = rtrim(DIR_BASE, '\/') . '/' . $relName;
$urlName = rtrim(Core::getApplicationURL(), '\/') . '/' . $relName;
if (!file_exists($osName)) {
@touch($osName);
}
if (!is_writable($osName)) {
throw new Exception(t('The file %s is not writable', $osName));
}
if (!$hFile = @fopen($osName, 'w')) {
throw new Exception(t('Cannot open file %s', $osName));
}
if (!@fwrite($hFile, $dom->saveXML())) {
throw new Exception(t('Error writing to file %s', $osName));
}
@fflush($hFile);
@fclose($hFile);
unset($hFile);
return t(
'%1$s file saved (%2$d pages).',
sprintf('<a href="%s" target="_blank">%s</a>', $urlName, preg_replace('/^https?:///i', '', $urlName)),
$addedPages
);
} catch (Exception $x) {
if (isset($hFile) && $hFile) {
@fflush($hFile);
@ftruncate($hFile, 0);
@fclose($hFile);
$hFile = null;
}
throw $x;
}
}
/** Check if the specified page should be included in the sitemap.xml file; if so adds it to the XML document.
* @param SimpleXMLElement $xmlDoc The xml document containing the sitemap nodes.
* @param int $cID The page collection id.
* @param array $instances An array with some already instantiated helpers, models, ...
*
* @throws Exception Throws an exception in case of errors.
*/
private static function addPage($xmlDoc, $cID, $instances)
{
$page = Page::getByID($cID, 'ACTIVE');
if (!static::canIncludePageInSitemap($page, $instances)) {
return;
}
$lastmod = new DateTime($page->getCollectionDateLastModified());
$changefreq = $page->getAttribute($instances['ak_sitemap_changefreq']);
$priority = $page->getAttribute($instances['ak_sitemap_priority']);
$xmlNode = $xmlDoc->addChild('url');
$xmlNode->addChild(
'loc',
$instances['navigation']->getLinkToCollection($page)
);
$xmlNode->addChild('lastmod', $lastmod->format(DateTime::ATOM));
$xmlNode->addChild(
'changefreq',
empty($changefreq) ? Config::get('concrete.sitemap_xml.frequency') : $changefreq
);
$xmlNode->addChild(
'priority',
is_numeric($priority) ? $priority : Config::get('concrete.sitemap_xml.priority')
);
if ($instances['multilingualSections']) {
$thisSection = MultilingualSection::getBySectionOfSite($page);
if (is_object($thisSection) && !$thisSection->isError()) {
foreach ($instances['multilingualSections'] as $section) {
$relatedPageID = $section->getTranslatedPageID($page);
if ($relatedPageID) {
$relatedPage = Page::getByID($relatedPageID);
if (static::canIncludePageInSitemap($relatedPage, $instances)) {
$xmlAltNode = $xmlNode->addChild('link', null, 'http://www.w3.org/1999/xhtml');
$xmlAltNode->addAttribute('rel', 'alternate');
$xmlAltNode->addAttribute('hreflang', strtolower(str_replace('_', '-', $section->getLocale())));
$xmlAltNode->addAttribute('href', $instances['navigation']->getLinkToCollection($relatedPage));
}
}
}
}
}
$event = new SymfonyComponentEventDispatcherGenericEvent();
$event->setArgument('xmlNode', $xmlNode);
$event->setArgument('page', $page);
Events::dispatch('on_sitemap_xml_addingpage', $event);
if ((!empty($ret)) && ($ret < 0)) {
for ($i = count($xmlDoc->url) - 1; $i >= 0; $i--) {
if ($xmlDoc->url[$i] == $xmlNode) {
unset($xmlDoc->url[$i]);
break;
}
}
}
}
protected static function canIncludePageInSitemap($page, $instances)
{
if (!is_object($page) || $page->isError()) {
return false;
}
/* @var $page Page */
if ($page->isSystemPage()) {
return false;
}
if ($page->isExternalLink()) {
return false;
}
if ($instances['dashboard']->inDashboard($page)) {
return false;
}
if ($page->isInTrash()) {
return false;
}
$pageVersion = $page->getVersionObject();
if ($pageVersion && !$pageVersion->isApproved()) {
return false;
}
$pubDate = new DateTime($page->getCollectionDatePublic());
if ($pubDate > $instances['now']) {
return false;
}
if ($page->getAttribute($instances['ak_exclude_sitemapxml'])) {
return false;
}
$instances['view_page']->setPermissionObject($page);
$pa = $instances['view_page']->getPermissionAccessObject();
if (!is_object($pa)) {
return false;
}
if (!$pa->validateAccessEntities($instances['guestGroupAE'])) {
return false;
}
return true;
}
}