1 | <?php |
||
30 | class Sitemap extends \yii\base\Component |
||
31 | { |
||
32 | const ALWAYS = 'always'; |
||
33 | const HOURLY = 'hourly'; |
||
34 | const DAILY = 'daily'; |
||
35 | const WEEKLY = 'weekly'; |
||
36 | const MONTHLY = 'monthly'; |
||
37 | const YEARLY = 'yearly'; |
||
38 | const NEVER = 'never'; |
||
39 | private $schemas = [ |
||
40 | 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9', |
||
41 | 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1', |
||
42 | 'xmlns:news' => 'http://www.google.com/schemas/sitemap-news/0.9', |
||
43 | ]; |
||
44 | |||
45 | /** @var int Cache expiration time */ |
||
46 | public $cacheExpire = 86400; |
||
47 | |||
48 | /** @var string Cache key */ |
||
49 | public $cacheKey = 'sitemap'; |
||
50 | |||
51 | /** @var boolean Use php's gzip compressing. */ |
||
52 | public $enableGzip = false; |
||
53 | |||
54 | /** @var array Model list for sitemap */ |
||
55 | public $models = []; |
||
56 | |||
57 | /** @var array Url list for sitemap */ |
||
58 | public $urls = []; |
||
59 | |||
60 | /** @var int */ |
||
61 | public $maxSectionUrl = 20000; |
||
62 | |||
63 | /** @var bool Sort urls by priority. Top priority urls first */ |
||
64 | public $sortByPriority = false; |
||
65 | /** |
||
66 | * Build site map. |
||
67 | * @return array |
||
68 | */ |
||
69 | 5 | public function render() |
|
70 | { |
||
71 | 5 | $result = Yii::$app->cache->get($this->cacheKey); |
|
72 | 5 | if ($result) { |
|
73 | 1 | return $result; |
|
74 | } |
||
75 | 5 | $urls = $this->generateUrls(); |
|
76 | 5 | if ($this->sortByPriority) { |
|
77 | 1 | $this->sortUrlsByPriority($urls); |
|
78 | 1 | } |
|
79 | |||
80 | 5 | $parts = ceil(count($urls) / $this->maxSectionUrl); |
|
81 | 5 | if ($parts > 1) { |
|
82 | 1 | $xml = new XMLWriter(); |
|
83 | 1 | $xml->openMemory(); |
|
84 | 1 | $xml->startDocument('1.0', 'UTF-8'); |
|
85 | 1 | $xml->startElement('sitemapindex'); |
|
86 | 1 | $xml->writeAttribute('xmlns', $this->schemas['xmlns']); |
|
87 | 1 | for ($i = 1; $i <= $parts; $i++) { |
|
88 | 1 | $xml->startElement('sitemap'); |
|
89 | 1 | $xml->writeElement('loc', Url::to(['/sitemap/default/index', 'id' =>$i], true)); |
|
90 | 1 | $xml->writeElement('lastmod', static::dateToW3C(time())); |
|
91 | 1 | $xml->endElement(); |
|
92 | 1 | $result[$i]['file'] = Url::to(['/sitemap/default/index', 'id' =>$i], false); |
|
93 | 1 | } |
|
94 | 1 | $xml->endElement(); |
|
95 | 1 | $result[0]['xml'] = $xml->outputMemory(); |
|
96 | 1 | $result[0]['file'] = Url::to(['/sitemap/default/index']); |
|
97 | 1 | } |
|
98 | 5 | $urlItem = 0; |
|
99 | 5 | for ($i = 1; $i <= $parts; $i++) { |
|
100 | 5 | $xml = new XMLWriter(); |
|
101 | 5 | $xml->openMemory(); |
|
102 | 5 | $xml->startDocument('1.0', 'UTF-8'); |
|
103 | 5 | $xml->startElement('urlset'); |
|
104 | 5 | foreach ($this->schemas as $attr => $schemaUrl) { |
|
105 | 5 | $xml->writeAttribute($attr, $schemaUrl); |
|
106 | 5 | } |
|
107 | 5 | for (; ($urlItem < $i * $this->maxSectionUrl) && ($urlItem < count($urls)); $urlItem++) { |
|
108 | 5 | $xml->startElement('url'); |
|
109 | 5 | foreach ($urls[$urlItem] as $urlKey => $urlValue) { |
|
110 | 5 | if (is_array($urlValue)) { |
|
111 | switch ($urlKey) { |
||
112 | 1 | case 'news': |
|
113 | 1 | $namespace = 'news:'; |
|
114 | 1 | $xml->startElement($namespace.$urlKey); |
|
115 | 1 | static::hashToXML($urlValue, $xml, $namespace); |
|
116 | 1 | $xml->endElement(); |
|
117 | 1 | break; |
|
118 | 1 | case 'images': |
|
119 | 1 | $namespace = 'image:'; |
|
120 | 1 | foreach ($urlValue as $image) { |
|
121 | 1 | $xml->startElement($namespace.'image'); |
|
122 | 1 | static::hashToXML($image, $xml, $namespace); |
|
123 | 1 | $xml->endElement(); |
|
124 | 1 | } |
|
125 | 1 | break; |
|
126 | } |
||
127 | 1 | } else { |
|
128 | 5 | $xml->writeElement($urlKey, $urlValue); |
|
129 | } |
||
130 | 5 | } |
|
131 | 5 | $xml->endElement(); |
|
132 | 5 | } |
|
133 | |||
134 | 5 | $xml->endElement(); // urlset |
|
135 | 5 | $xml->endElement(); // document |
|
136 | 5 | $result[$i]['xml'] = $xml->outputMemory(); |
|
137 | 5 | } |
|
138 | |||
139 | 5 | if ($parts == 1) { |
|
140 | 4 | $result[0] = $result[1]; |
|
141 | 4 | unset($result[1]); |
|
142 | 4 | } |
|
143 | 5 | Yii::$app->cache->set($this->cacheKey, $result, $this->cacheExpire); |
|
144 | 5 | return $result; |
|
145 | } |
||
146 | |||
147 | /** |
||
148 | * Generate url's array from properties $url and $models |
||
149 | * |
||
150 | * @access protected |
||
151 | * @return array |
||
152 | */ |
||
153 | 5 | protected function generateUrls() |
|
185 | |||
186 | /** |
||
187 | * Convert associative arrays to XML |
||
188 | * |
||
189 | * @param array $hash |
||
190 | * @param XMLWriter $xml |
||
191 | * @param string $namespace |
||
192 | * @static |
||
193 | * @access protected |
||
194 | * @return XMLWriter |
||
195 | */ |
||
196 | 1 | protected static function hashToXML($hash, $xml, $namespace = '') |
|
209 | /** |
||
210 | * Convert date to W3C format |
||
211 | * |
||
212 | * @param mixed $date |
||
213 | * @static |
||
214 | * @access protected |
||
215 | * @return string |
||
216 | */ |
||
217 | 3 | public static function dateToW3C($date) |
|
225 | |||
226 | /** |
||
227 | * @return mixed |
||
228 | */ |
||
229 | protected function sortUrlsByPriority(&$urls) |
||
249 | } |
||
250 |