This repository has been archived by the owner on Nov 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ProcessSitemapSubmit.module.php
203 lines (168 loc) · 5.73 KB
/
ProcessSitemapSubmit.module.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
<?php namespace ProcessWire;
/**
* Module that submits sitemap.xml to search engines to trigger re-indexing
*/
require_once __DIR__ . '/classes/MarkupSitemapTools.php';
class ProcessSitemapSubmit extends Wire implements Module {
/**
* Name of ProcessWire log to write to
* @var string
*/
private const LOG_FILENAME = 'sitemap-submit';
/**
* Holds full URL of sitemap.xml
* Set on module ready
* @var string
*/
private $sitemapUrl;
/**
* Holds state of sitemap.xml presence.
* Set on module ready
* @var bool
*/
private $sitemapExists = false;
/**
* URLs to ping with sitemap data
* @var array
*/
private $searchEngines = [
'Google' => 'https://www.google.com/ping?sitemap=%{SITEMAP_URL}',
'Bing' => 'https://www.bing.com/webmaster/ping.aspx?siteMap=%{SITEMAP_URL}'
];
/**
* Hook the hooks, do the pings
* @return void
*/
public function ready(): void {
if ($this->moduleShouldInit()) {
$eventHookSelector = $this->createEventHookSelector();
// Published, unpublished, saved, moved, restored, deleted
$this->addHookAfter("Pages::published({$eventHookSelector})", $this, 'pushSitemap');
$this->addHookAfter("Pages::unpublished({$eventHookSelector})", $this, 'pushSitemap');
$this->addHookAfter("Pages::saved({$eventHookSelector})", $this, 'pushSitemapUnlessUnpublished');
$this->addHookAfter("Pages::moved({$eventHookSelector})", $this, 'pushSitemapUnlessUnpublished');
$this->addHookAfter("Pages::restored({$eventHookSelector})", $this, 'pushSitemapUnlessUnpublished');
$this->addHookAfter("Pages::deleted({$eventHookSelector})", $this, 'pushSitemapUnlessUnpublished');
}
}
/**
* This creates a hook event modifier string to be used with hook definitions
* @return string
*/
private function createEventHookSelector(): string {
$excludedTemplates = $this->sitemap_submit_excluded_templates;
// Add system templates to the excluded templates from module config
foreach ($this->templates as $template) {
if ($template->flags & Template::flagSystem) {
$excludedTemplates[] = $template->name;
}
}
return 'template!=' . implode('|', $excludedTemplates);
}
/**
* Handles logic determining if this module should initialize for the current page
* @return bool
*/
private function moduleShouldInit(): bool {
$debug = $this->config->debug;
return !$debug || ($debug && $this->sitemap_submit_when_debug_active);
}
/**
* Handles a page publish hook call
* @param HookEvent $e Publish hook event
* @return void
*/
public function pushSitemap(HookEvent $e): void {
if ($this->sitemap_url_exists) {
$this->pushSitemapXml($e->arguments('page'));
}
if (!$this->sitemap_url_exists) {
$this->noSitemapError();
}
}
/**
* Handles a page save hook call
* @param HookEvent $e Save hook event
* @return void
*/
public function pushSitemapUnlessUnpublished(HookEvent $e): void {
$page = $e->arguments('page');
if (!$page->hasStatus('unpublished') && $this->sitemap_url_exists) {
$this->pushSitemapXml($page);
}
if (!$this->sitemap_url_exists) {
$this->noSitemapError();
}
}
/**
* Executes a sitemap push.
* Handles cache clearing if supposed to
* Warns user on error if supposed to
* Logs result
* @return void
*/
public function pushSitemapXml(Page $page): void {
$this->clearSitemapCacheIfConfigured();
$logMsg = [
"ID: {$page->id}",
"URL: {$page->url}"
];
foreach ($this->searchEngines as $name => $url) {
$url = str_replace('%{SITEMAP_URL}', $this->sitemap_location_url, $url);
$result = $this->pingUrl($url);
$logMsg[] = $result->success ? "{$name} - Success" : "{$name} - ERROR: {$result->message}";
}
$this->logMsg(implode(', ', $logMsg));
}
/**
* Pings a URL, checks for 200 status, or optional specified status
* @param string $url URL to ping
* @param int $expectedStatus HTTP status to expect
* @return bool
*/
public function pingUrl(string $url, int $expectedStatus = 200): object {
$http = new WireHttp;
$request = $http->get($url, [], ['use' => 'curl']);
$requestStatus = $http->getHttpCode();
$success = $requestStatus === $expectedStatus;
// Translate in case needed
$errorMsg = sprintf(__('Expected HTTP %1$d but received %2$d'), $expectedStatus, $requestStatus);
return (object) [
'success' => $success,
'httpStatus' => $requestStatus,
'content' => $request,
'message' => !$success ? $errorMsg : null
];
}
/**
* Triggers a message or error
* @param Page $page Page error occurred on
* @return void
*/
private function noSitemapError(Page $page): void {
if ($this->sitemap_show_warning_if_not_submitted) {
$msg = sprintf(__('%s does not exist. Sitemap was not submitted to search engines.'), $this->sitemap_location_url);
$this->warning($msg);
}
$this->logMsg("ID: {$page->id}, URL: {$page->url}, ERROR: Sitemap not submitted, no valid sitemap URL configured");
}
/**
* Logs module activity
* @param string $message Message to be logged
* @return void
*/
private function logMsg(string $message): void {
$this->log->save(self::LOG_FILENAME, $message);
}
/**
* Clears sitemap cache if configured
* @return void
*/
private function clearSitemapCacheIfConfigured(): void {
$markupSitemapTools = new MarkupSitemapTools;
if ($markupSitemapTools->moduleInstalled() && $this->sitemap_module_clear_cache_on_save) {
$result = $markupSitemapTools->clearSitemapCache();
$this->logmsg($result ? 'Sitemap cache cleared' : 'Failed to clear sitemap cache');
}
}
}