ORIENT/plugins/rainlab/sitemap/models/Definition.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;
}
}