224 lines
5.6 KiB
PHP
224 lines
5.6 KiB
PHP
<?php namespace RainLab\Sitemap\Models;
|
|
|
|
use Url;
|
|
use Model;
|
|
use Event;
|
|
use Request;
|
|
use DOMDocument;
|
|
use Cms\Classes\Theme;
|
|
use RainLab\Sitemap\Classes\DefinitionItem;
|
|
|
|
/**
|
|
* Definition Model
|
|
*/
|
|
class Definition extends Model
|
|
{
|
|
/**
|
|
* Maximum URLs allowed (Protocol limit is 50k)
|
|
*/
|
|
const MAX_URLS = 50000;
|
|
|
|
/**
|
|
* Maximum generated URLs per type
|
|
*/
|
|
const MAX_GENERATED = 10000;
|
|
|
|
/**
|
|
* @var string The database table used by the model.
|
|
*/
|
|
public $table = 'rainlab_sitemap_definitions';
|
|
|
|
/**
|
|
* @var array Guarded fields
|
|
*/
|
|
protected $guarded = [];
|
|
|
|
/**
|
|
* @var array Fillable fields
|
|
*/
|
|
protected $fillable = [];
|
|
|
|
/**
|
|
* @var integer A tally of URLs added to the sitemap
|
|
*/
|
|
protected $urlCount = 0;
|
|
|
|
/**
|
|
* @var array List of attribute names which are json encoded and decoded from the database.
|
|
*/
|
|
protected $jsonable = ['data'];
|
|
|
|
/**
|
|
* @var array The sitemap items.
|
|
* Items are objects of the \RainLab\Sitemap\Classes\DefinitionItem class.
|
|
*/
|
|
public $items;
|
|
|
|
/**
|
|
* @var DOMDocument element
|
|
*/
|
|
protected $urlSet;
|
|
|
|
/**
|
|
* @var DOMDocument
|
|
*/
|
|
protected $xmlObject;
|
|
|
|
public function beforeSave()
|
|
{
|
|
$this->data = (array) $this->items;
|
|
}
|
|
|
|
public function afterFetch()
|
|
{
|
|
$this->items = DefinitionItem::initFromArray($this->data);
|
|
}
|
|
|
|
public function generateSitemap()
|
|
{
|
|
if (!$this->items) {
|
|
return;
|
|
}
|
|
|
|
$currentUrl = Request::path();
|
|
$theme = Theme::load($this->theme);
|
|
|
|
/*
|
|
* Cycle each page and add its URL
|
|
*/
|
|
foreach ($this->items as $item) {
|
|
|
|
/*
|
|
* Explicit URL
|
|
*/
|
|
if ($item->type == 'url') {
|
|
$this->addItemToSet($item, Url::to($item->url));
|
|
}
|
|
/*
|
|
* Registered sitemap type
|
|
*/
|
|
else {
|
|
|
|
$apiResult = Event::fire('pages.menuitem.resolveItem', [$item->type, $item, $currentUrl, $theme]);
|
|
|
|
if (!is_array($apiResult)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($apiResult as $itemInfo) {
|
|
if (!is_array($itemInfo)) {
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* Single item
|
|
*/
|
|
if (isset($itemInfo['url'])) {
|
|
$this->addItemToSet($item, $itemInfo['url'], array_get($itemInfo, 'mtime'));
|
|
}
|
|
|
|
/*
|
|
* Multiple items
|
|
*/
|
|
if (isset($itemInfo['items'])) {
|
|
|
|
$parentItem = $item;
|
|
|
|
$itemIterator = function($items) use (&$itemIterator, $parentItem)
|
|
{
|
|
foreach ($items as $item) {
|
|
if (isset($item['url'])) {
|
|
$this->addItemToSet($parentItem, $item['url'], array_get($item, 'mtime'));
|
|
}
|
|
|
|
if (isset($item['items'])) {
|
|
$itemIterator($item['items']);
|
|
}
|
|
}
|
|
};
|
|
|
|
$itemIterator($itemInfo['items']);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$urlSet = $this->makeUrlSet();
|
|
$xml = $this->makeXmlObject();
|
|
$xml->appendChild($urlSet);
|
|
|
|
return $xml->saveXML();
|
|
}
|
|
|
|
protected function makeXmlObject()
|
|
{
|
|
if ($this->xmlObject !== null) {
|
|
return $this->xmlObject;
|
|
}
|
|
|
|
$xml = new DOMDocument;
|
|
$xml->encoding = 'UTF-8';
|
|
|
|
return $this->xmlObject = $xml;
|
|
}
|
|
|
|
protected function makeUrlSet()
|
|
{
|
|
if ($this->urlSet !== null) {
|
|
return $this->urlSet;
|
|
}
|
|
|
|
$xml = $this->makeXmlObject();
|
|
$urlSet = $xml->createElement('urlset');
|
|
$urlSet->setAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
|
|
$urlSet->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
|
$urlSet->setAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');
|
|
|
|
return $this->urlSet = $urlSet;
|
|
}
|
|
|
|
protected function addItemToSet($item, $url, $mtime = null)
|
|
{
|
|
if ($mtime instanceof \DateTime) {
|
|
$mtime = $mtime->getTimestamp();
|
|
}
|
|
|
|
$xml = $this->makeXmlObject();
|
|
$urlSet = $this->makeUrlSet();
|
|
$mtime = $mtime ? date('c', $mtime) : date('c');
|
|
|
|
$urlElement = $this->makeUrlElement(
|
|
$xml,
|
|
$url,
|
|
$mtime,
|
|
$item->changefreq,
|
|
$item->priority
|
|
);
|
|
|
|
if ($urlElement) {
|
|
$urlSet->appendChild($urlElement);
|
|
}
|
|
|
|
return $urlSet;
|
|
}
|
|
|
|
protected function makeUrlElement($xml, $pageUrl, $lastModified, $frequency, $priority)
|
|
{
|
|
if ($this->urlCount >= self::MAX_URLS) {
|
|
return false;
|
|
}
|
|
|
|
$this->urlCount++;
|
|
|
|
$url = $xml->createElement('url');
|
|
$url->appendChild($xml->createElement('loc', $pageUrl));
|
|
$url->appendChild($xml->createElement('lastmod', $lastModified));
|
|
$url->appendChild($xml->createElement('changefreq', $frequency));
|
|
$url->appendChild($xml->createElement('priority', $priority));
|
|
|
|
return $url;
|
|
}
|
|
}
|