1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* The dynamic Google Sitemap builder. |
4
|
|
|
* |
5
|
|
|
* http://[...]/sitemap.xml.php |
6
|
|
|
* http://[...]/sitemap.xml.php?gz=1 |
7
|
|
|
* http://[...]/sitemap.xml |
8
|
|
|
* http://[...]/sitemap.gz |
9
|
|
|
* http://[...]/sitemap.xml.gz |
10
|
|
|
* |
11
|
|
|
* The Google Sitemap protocol is described here: |
12
|
|
|
* http://www.google.com/webmasters/sitemaps/docs/en/protocol.html |
13
|
|
|
* |
14
|
|
|
* PHP Version 5.4 |
15
|
|
|
* |
16
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public License, |
17
|
|
|
* v. 2.0. If a copy of the MPL was not distributed with this file, You can |
18
|
|
|
* obtain one at http://mozilla.org/MPL/2.0/. |
19
|
|
|
* |
20
|
|
|
* @category phpMyFAQ |
21
|
|
|
* @package SEO |
22
|
|
|
* @author Matteo Scaramuccia <[email protected]> |
23
|
|
|
* @copyright 2006-2014 phpMyFAQ Team |
24
|
|
|
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 |
25
|
|
|
* @link http://www.phpmyfaq.de |
26
|
|
|
* @since 2006-06-26 |
27
|
|
|
*/ |
28
|
|
|
|
29
|
|
|
use Symfony\Component\HttpFoundation\Response; |
30
|
|
|
|
31
|
|
|
define('PMF_SITEMAP_GOOGLE_CHANGEFREQ_ALWAYS', 'always'); |
32
|
|
|
define('PMF_SITEMAP_GOOGLE_CHANGEFREQ_HOURLY', 'hourly'); |
33
|
|
|
define('PMF_SITEMAP_GOOGLE_CHANGEFREQ_DAILY', 'daily'); |
34
|
|
|
define('PMF_SITEMAP_GOOGLE_CHANGEFREQ_WEEKLY', 'weekly'); |
35
|
|
|
define('PMF_SITEMAP_GOOGLE_CHANGEFREQ_MONTHLY', 'monthly'); |
36
|
|
|
define('PMF_SITEMAP_GOOGLE_CHANGEFREQ_YEARLY', 'yearly'); |
37
|
|
|
define('PMF_SITEMAP_GOOGLE_CHANGEFREQ_NEVER', 'never'); |
38
|
|
|
define('PMF_SITEMAP_GOOGLE_MAX_URL_LENGTH', 2048); |
39
|
|
|
define('PMF_SITEMAP_GOOGLE_MAX_URLS', 50000); |
40
|
|
|
define('PMF_SITEMAP_GOOGLE_MAX_FILE_LENGTH', 10485760); // 10MB |
41
|
|
|
define('PMF_SITEMAP_GOOGLE_PRIORITY_MIN', '0.0'); |
42
|
|
|
define('PMF_SITEMAP_GOOGLE_PRIORITY_MAX', '1.0'); |
43
|
|
|
define('PMF_SITEMAP_GOOGLE_PRIORITY_DEFAULT', '0.5'); |
44
|
|
|
|
45
|
|
|
|
46
|
|
|
define('PMF_SITEMAP_GOOGLE_GET_GZIP', 'gz'); |
47
|
|
|
define('PMF_SITEMAP_GOOGLE_GET_INDEX', 'idx'); |
48
|
|
|
define('PMF_SITEMAP_GOOGLE_FILENAME', 'sitemap.xml'); |
49
|
|
|
define('PMF_SITEMAP_GOOGLE_FILENAME_GZ', 'sitemap.xml.gz'); |
50
|
|
|
define('PMF_SITEMAP_GOOGLE_INDEX_FILENAME', 'sitemap_index.xml'); |
51
|
|
|
|
52
|
|
|
define('PMF_ROOT_DIR', __DIR__); |
53
|
|
|
define('IS_VALID_PHPMYFAQ', null); |
54
|
|
|
|
55
|
|
|
// |
56
|
|
|
// Bootstrapping |
57
|
|
|
// |
58
|
|
|
require 'inc/Bootstrap.php'; |
59
|
|
|
|
60
|
|
|
// |
61
|
|
|
// Initalizing static string wrapper |
62
|
|
|
// |
63
|
|
|
PMF_String::init('en'); |
64
|
|
|
|
65
|
|
|
// {{{ Functions |
|
|
|
|
66
|
|
|
function buildSitemapNode($location, $lastmod = null, $changeFreq = null, $priority = null) |
67
|
|
|
{ |
68
|
|
|
if (!isset($lastmod)) { |
69
|
|
|
$lastmod = PMF_Date::createIsoDate($_SERVER['REQUEST_TIME'], DATE_W3C, false); |
70
|
|
|
} |
71
|
|
|
if (!isset($changeFreq)) { |
72
|
|
|
$changeFreq = PMF_SITEMAP_GOOGLE_CHANGEFREQ_DAILY; |
73
|
|
|
} |
74
|
|
|
$node = |
75
|
|
|
'<url>' |
76
|
|
|
.'<loc>'.PMF_String::htmlspecialchars($location).'</loc>' |
77
|
|
|
.'<lastmod>'.$lastmod.'</lastmod>' |
78
|
|
|
.'<changefreq>'.$changeFreq.'</changefreq>' |
79
|
|
|
.(isset($priority) ? '<priority>'.$priority.'</priority>' : '') |
80
|
|
|
.'</url>'; |
81
|
|
|
|
82
|
|
|
return $node; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
// |
86
|
|
|
// Future improvements |
87
|
|
|
// WHEN a User PMF Sitemap will be: |
88
|
|
|
// a. bigger than 10MB (!) |
89
|
|
|
// b. w/ more than 50K URLs (!) |
90
|
|
|
// we'll manage this issue using a Sitemap Index Files produced by this PHP code |
91
|
|
|
// including Sitemap URLs always produced by this same PHP code (see PMF_SITEMAP_GOOGLE_GET_INDEX) |
92
|
|
|
// |
93
|
|
|
|
94
|
|
|
$oFaq = new PMF_Faq($faqConfig); |
95
|
|
|
// Load the faq |
96
|
|
|
$items = $oFaq->getTopTenData(PMF_SITEMAP_GOOGLE_MAX_URLS - 1); |
97
|
|
|
$visitsMax = 0; |
98
|
|
|
$visitMin = 0; |
99
|
|
|
if (count($items) > 0) { |
100
|
|
|
$visitsMax = $items[0]['visits']; |
101
|
|
|
$visitMin = $items[count($items)-1]['visits']; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
// Sitemap header |
105
|
|
|
$sitemap = |
106
|
|
|
'<?xml version="1.0" encoding="UTF-8"?>' |
107
|
|
|
.'<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"' |
108
|
|
|
.' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' |
109
|
|
|
.' xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.84' |
110
|
|
|
.' http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">'; |
111
|
|
|
// 1st entry: the faq server itself |
112
|
|
|
$sitemap .= buildSitemapNode( |
113
|
|
|
$faqConfig->get('main.referenceURL'), |
114
|
|
|
PMF_Date::createIsoDate($_SERVER['REQUEST_TIME'], DATE_W3C, false), |
115
|
|
|
PMF_SITEMAP_GOOGLE_CHANGEFREQ_DAILY, |
116
|
|
|
PMF_SITEMAP_GOOGLE_PRIORITY_MAX |
117
|
|
|
); |
118
|
|
|
|
119
|
|
|
// nth entry: each faq |
120
|
|
|
foreach ($items as $item) { |
121
|
|
|
$priority = PMF_SITEMAP_GOOGLE_PRIORITY_DEFAULT; |
122
|
|
|
if (($visitsMax - $visitMin) > 0) { |
123
|
|
|
$priority = sprintf('%.1f', PMF_SITEMAP_GOOGLE_PRIORITY_DEFAULT * (1 + (($item['visits'] - $visitMin)/($visitsMax - $visitMin)))); |
124
|
|
|
} |
125
|
|
|
// a. We use plain PMF urls w/o any SEO schema |
126
|
|
|
$link = str_replace($_SERVER['SCRIPT_NAME'], '/index.php', $item['url']); |
127
|
|
|
// b. We use SEO PMF urls |
128
|
|
View Code Duplication |
if (PMF_SITEMAP_GOOGLE_USE_SEO) { |
129
|
|
|
if (isset($item['thema'])) { |
130
|
|
|
$oL = new PMF_Link($link, $faqConfig); |
131
|
|
|
$oL->itemTitle = $item['thema']; |
132
|
|
|
$link = $oL->toString(); |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
$sitemap .= buildSitemapNode( |
136
|
|
|
$faqConfig->get('main.referenceURL').$link, |
137
|
|
|
PMF_Date::createIsoDate($item['date'], DATE_W3C), |
138
|
|
|
// @todo: manage changefreq node with the info provided by faqchanges, |
139
|
|
|
// if this will not add a big load to the server (+1 query/faq) |
140
|
|
|
PMF_SITEMAP_GOOGLE_CHANGEFREQ_DAILY, |
141
|
|
|
$priority |
142
|
|
|
); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
$sitemap .= '</urlset>'; |
146
|
|
|
|
147
|
|
|
$response = new Response; |
148
|
|
|
|
149
|
|
|
$getgezip = PMF_Filter::filterInput(INPUT_GET, PMF_SITEMAP_GOOGLE_GET_GZIP, FILTER_VALIDATE_INT); |
150
|
|
|
if (!is_null($getgezip) && (1 == $getgezip)) { |
151
|
|
|
if (function_exists('gzencode')) { |
152
|
|
|
$sitemapGz = gzencode($sitemap); |
153
|
|
|
$response->headers->set('Content-Type', 'application/x-gzip'); |
154
|
|
|
$response->headers->set('Content-Disposition', 'attachment; filename="' . PMF_SITEMAP_GOOGLE_FILENAME_GZ . '"'); |
155
|
|
|
$response->headers->set('Content-Length', strlen($sitemapGz)); |
156
|
|
|
$response->setContent($sitemapGz); |
157
|
|
|
} else { |
158
|
|
|
$response->setStatusCode(404); |
159
|
|
|
} |
160
|
|
|
} else { |
161
|
|
|
$response->headers->set('Content-Type', 'text/xml'); |
162
|
|
|
$response->headers->set('Content-Disposition', 'inline; filename="' . PMF_SITEMAP_GOOGLE_FILENAME . '"'); |
163
|
|
|
$response->headers->set('Content-Length', PMF_String::strlen($sitemap)); |
164
|
|
|
$response->setContent($sitemap); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
$response->send(); |
168
|
|
|
|
169
|
|
|
$faqConfig->getDb()->close(); |
170
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.