Version Description
(April 2016) =
- Added support for plugin Duplicate Post. Now when a user clones a post or page you will se this in the history log, with links to both the original post and the new copy.
- Removed log level info from title in RSS feed
- Make date dropdown less "jumpy" when loading page (due to select element switching to Select2)
- Only add filters for plugin Limit Login Attempts if plugin is active. This fixes problem with Limit Login Attempts Reloaded and possibly other forks of the plugin.
- Debug page now displays installed plugins.
Download this release
Release Info
Developer | eskapism |
Plugin | Simple History |
Version | 2.14 |
Comparing to | |
See all releases |
Code changes from version 2.13 to 2.14
- dropins/SimpleHistoryFilterDropin.css +22 -6
- dropins/SimpleHistoryFilterDropin.php +1 -1
- dropins/SimpleHistoryRSSDropin.php +432 -431
- examples/examples.php +17 -0
- inc/SimpleHistory.php +2 -1
- index.php +2 -2
- loggers/Plugin_DuplicatePost.php +130 -0
- loggers/Plugin_LimitLoginAttempts.php +12 -0
- loggers/SimplePostLogger.php +3 -3
- loggers/SimpleUserLogger.php +960 -1007
- readme.txt +16 -2
- templates/template-settings-tab-debug.php +47 -3
dropins/SimpleHistoryFilterDropin.css
CHANGED
@@ -10,6 +10,13 @@
|
|
10 |
transition: all .25s ease-out;
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
.SimpleHistory--isLoaded .SimpleHistory__filters {
|
14 |
opacity: 1;
|
15 |
}
|
@@ -33,6 +40,7 @@
|
|
33 |
.SimpleHistory__filters__filterLabel {
|
34 |
display: inline-block;
|
35 |
width: 150px;
|
|
|
36 |
}
|
37 |
|
38 |
.SimpleHistory__filters__filterSubmitWrap {
|
@@ -52,6 +60,20 @@
|
|
52 |
|
53 |
}
|
54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
/* always label as blocks on dashboard because we don't know the width beacuse of columns */
|
56 |
.postbox .SimpleHistory__filters__filterLabel {
|
57 |
display: block;
|
@@ -61,12 +83,6 @@
|
|
61 |
margin-left: 0;
|
62 |
}
|
63 |
|
64 |
-
/* set height on date input or it will "jump" during page load */
|
65 |
-
.wp-admin select[multiple].SimpleHistory__filters__filter--date {
|
66 |
-
height: 2.25em;
|
67 |
-
overflow: hidden;
|
68 |
-
}
|
69 |
-
|
70 |
/**
|
71 |
* Search results in filter
|
72 |
*/
|
10 |
transition: all .25s ease-out;
|
11 |
}
|
12 |
|
13 |
+
.SimpleHistory__filters__filter--date {
|
14 |
+
}
|
15 |
+
|
16 |
+
.SimpleHistory__filters__filter--date.select2-container {
|
17 |
+
}
|
18 |
+
|
19 |
+
|
20 |
.SimpleHistory--isLoaded .SimpleHistory__filters {
|
21 |
opacity: 1;
|
22 |
}
|
40 |
.SimpleHistory__filters__filterLabel {
|
41 |
display: inline-block;
|
42 |
width: 150px;
|
43 |
+
vertical-align: middle;
|
44 |
}
|
45 |
|
46 |
.SimpleHistory__filters__filterSubmitWrap {
|
60 |
|
61 |
}
|
62 |
|
63 |
+
@media (min-width: 600px) {
|
64 |
+
/* prevent "jump" during page load because of select elm changing to select2 */
|
65 |
+
.SimpleHistory__filters__filterRow {
|
66 |
+
height: 41px;
|
67 |
+
line-height: 41px;
|
68 |
+
}
|
69 |
+
|
70 |
+
.wp-admin select[multiple].SimpleHistory__filters__filter--date {
|
71 |
+
height: 2.25em;
|
72 |
+
overflow: hidden;
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
|
77 |
/* always label as blocks on dashboard because we don't know the width beacuse of columns */
|
78 |
.postbox .SimpleHistory__filters__filterLabel {
|
79 |
display: block;
|
83 |
margin-left: 0;
|
84 |
}
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
/**
|
87 |
* Search results in filter
|
88 |
*/
|
dropins/SimpleHistoryFilterDropin.php
CHANGED
@@ -163,7 +163,7 @@ class SimpleHistoryFilterDropin {
|
|
163 |
|
164 |
?>
|
165 |
|
166 |
-
<p data-debug-daysAndPages='<?php echo json_encode( $arr_days_and_pages ) ?>'>
|
167 |
|
168 |
<label class="SimpleHistory__filters__filterLabel"><?php _ex("Dates:", "Filter label", "simple-history") ?></label>
|
169 |
|
163 |
|
164 |
?>
|
165 |
|
166 |
+
<p class="SimpleHistory__filters__filterRow" data-debug-daysAndPages='<?php echo json_encode( $arr_days_and_pages ) ?>'>
|
167 |
|
168 |
<label class="SimpleHistory__filters__filterLabel"><?php _ex("Dates:", "Filter label", "simple-history") ?></label>
|
169 |
|
dropins/SimpleHistoryRSSDropin.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
defined(
|
4 |
|
5 |
/*
|
6 |
Dropin Name: Global RSS Feed
|
@@ -11,434 +11,435 @@ Author: Pär Thernström
|
|
11 |
/**
|
12 |
* Simple History RSS Feed drop-in
|
13 |
*/
|
14 |
-
class SimpleHistoryRSSDropin
|
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 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
|
|
444 |
} // end rss class
|
1 |
<?php
|
2 |
|
3 |
+
// defined('ABSPATH') or die();
|
4 |
|
5 |
/*
|
6 |
Dropin Name: Global RSS Feed
|
11 |
/**
|
12 |
* Simple History RSS Feed drop-in
|
13 |
*/
|
14 |
+
class SimpleHistoryRSSDropin
|
15 |
+
{
|
16 |
+
|
17 |
+
public function __construct($sh)
|
18 |
+
{
|
19 |
+
|
20 |
+
$this->sh = $sh;
|
21 |
+
|
22 |
+
if (! function_exists('get_editable_roles')) {
|
23 |
+
require_once(ABSPATH . '/wp-admin/includes/user.php');
|
24 |
+
}
|
25 |
+
|
26 |
+
//Check the status of the RSS feed
|
27 |
+
$this->isRssEnabled();
|
28 |
+
|
29 |
+
// Generate a rss secret, if it does not exist
|
30 |
+
if (! get_option("simple_history_rss_secret")) {
|
31 |
+
$this->updateRssSecret();
|
32 |
+
}
|
33 |
+
|
34 |
+
add_action('init', array($this, 'checkForRssFeedRequest'));
|
35 |
+
|
36 |
+
// Add settings with prio 11 so it' added after the main Simple History settings
|
37 |
+
add_action('admin_menu', array($this, 'addSettings'), 11);
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Add settings for the RSS feed
|
42 |
+
* + also regenerates the secret if requested
|
43 |
+
*/
|
44 |
+
public function addSettings()
|
45 |
+
{
|
46 |
+
|
47 |
+
//we register a setting to keep track of the RSS feed status (enabled/disabled)
|
48 |
+
register_setting(
|
49 |
+
SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP,
|
50 |
+
'simple_history_enable_rss_feed',
|
51 |
+
array($this, 'public updateRssStatus'
|
52 |
+
)
|
53 |
+
);
|
54 |
+
/**
|
55 |
+
* Start new section for RSS feed
|
56 |
+
*/
|
57 |
+
$settings_section_rss_id = "simple_history_settings_section_rss";
|
58 |
+
|
59 |
+
add_settings_section(
|
60 |
+
$settings_section_rss_id,
|
61 |
+
_x("RSS feed", "rss settings headline", "simple-history"), // No title __("General", "simple-history"),
|
62 |
+
array($this, "settingsSectionOutput"),
|
63 |
+
SimpleHistory::SETTINGS_MENU_SLUG // same slug as for options menu page
|
64 |
+
);
|
65 |
+
|
66 |
+
// Enable/Disabled RSS feed
|
67 |
+
add_settings_field(
|
68 |
+
"simple_history_enable_rss_feed",
|
69 |
+
__("Enable", "simple-history"),
|
70 |
+
array($this, "settingsFieldRssEnable"),
|
71 |
+
SimpleHistory::SETTINGS_MENU_SLUG,
|
72 |
+
$settings_section_rss_id
|
73 |
+
);
|
74 |
+
|
75 |
+
//if RSS is activated we display other fields
|
76 |
+
if ($this->isRssEnabled()) {
|
77 |
+
// RSS address
|
78 |
+
add_settings_field(
|
79 |
+
"simple_history_rss_feed",
|
80 |
+
__("Address", "simple-history"),
|
81 |
+
array($this, "settingsFieldRss"),
|
82 |
+
SimpleHistory::SETTINGS_MENU_SLUG,
|
83 |
+
$settings_section_rss_id
|
84 |
+
);
|
85 |
+
|
86 |
+
// Regnerate address
|
87 |
+
add_settings_field(
|
88 |
+
"simple_history_rss_feed_regenerate_secret",
|
89 |
+
__("Regenerate", "simple-history"),
|
90 |
+
array($this, "settingsFieldRssRegenerate"),
|
91 |
+
SimpleHistory::SETTINGS_MENU_SLUG,
|
92 |
+
$settings_section_rss_id
|
93 |
+
);
|
94 |
+
}
|
95 |
+
|
96 |
+
// Create new RSS secret
|
97 |
+
$create_new_secret = false;
|
98 |
+
$create_secret_nonce_name = "simple_history_rss_secret_regenerate_nonce";
|
99 |
+
$createNonceOk = isset($_GET[$create_secret_nonce_name]) && wp_verify_nonce($_GET[$create_secret_nonce_name], 'simple_history_rss_update_secret');
|
100 |
+
|
101 |
+
if ($createNonceOk) {
|
102 |
+
$create_new_secret = true;
|
103 |
+
$this->updateRssSecret();
|
104 |
+
|
105 |
+
// Add updated-message and store in transient and then redirect
|
106 |
+
// This is the way options.php does it.
|
107 |
+
$msg = __("Created new secret RSS address", 'simple-history');
|
108 |
+
add_settings_error("simple_history_rss_feed_regenerate_secret", "simple_history_rss_feed_regenerate_secret", $msg, "updated");
|
109 |
+
set_transient('settings_errors', get_settings_errors(), 30);
|
110 |
+
|
111 |
+
$goback = esc_url_raw(add_query_arg('settings-updated', 'true', wp_get_referer()));
|
112 |
+
wp_redirect($goback);
|
113 |
+
exit;
|
114 |
+
}
|
115 |
+
} // settings
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Check if RSS feed is enabled or disabled
|
119 |
+
*/
|
120 |
+
public function isRssEnabled()
|
121 |
+
{
|
122 |
+
|
123 |
+
// User has never used the plugin we disable RSS feed
|
124 |
+
if (get_option("simple_history_rss_secret") === false && get_option("simple_history_enable_rss_feed") === false) {
|
125 |
+
//We disable RSS by default, we use 0/1 to prevent fake disabled with bools from functions returning false for unset
|
126 |
+
update_option("simple_history_enable_rss_feed", "0");
|
127 |
+
} elseif (get_option("simple_history_enable_rss_feed") === false) {
|
128 |
+
// User was using the plugin before RSS feed became disabled by default
|
129 |
+
// We activate RSS to prevent a "breaking change"
|
130 |
+
update_option("simple_history_enable_rss_feed", "1");
|
131 |
+
return true;
|
132 |
+
} elseif (get_option("simple_history_enable_rss_feed") === "1") {
|
133 |
+
return true;
|
134 |
+
}
|
135 |
+
|
136 |
+
return false;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Output for settings field that show current RSS address
|
141 |
+
*/
|
142 |
+
public function settingsFieldRssEnable()
|
143 |
+
{
|
144 |
+
?>
|
145 |
+
<input value="1" type="checkbox" id="simple_history_enable_rss_feed" name="simple_history_enable_rss_feed" <?php checked($this->isRssEnabled(), 1); ?> />
|
146 |
+
<label for="simple_history_enable_rss_feed"><?php _e("Enable RSS feed", 'simple-history') ?></label>
|
147 |
+
<?php
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Sanitize RSS enabled/disabled status on update settings
|
152 |
+
*/
|
153 |
+
public function updateRssStatus($field)
|
154 |
+
{
|
155 |
+
|
156 |
+
if ($field === "1") {
|
157 |
+
return "1";
|
158 |
+
}
|
159 |
+
|
160 |
+
return "0";
|
161 |
+
}
|
162 |
+
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Check if current request is a request for the RSS feed
|
166 |
+
*/
|
167 |
+
public function checkForRssFeedRequest()
|
168 |
+
{
|
169 |
+
// check for RSS
|
170 |
+
// don't know if this is the right way to do this, but it seems to work!
|
171 |
+
if (isset($_GET["simple_history_get_rss"])) {
|
172 |
+
$this->outputRss();
|
173 |
+
exit;
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Modify capability check so all users reading rss feed (logged in or not) can read all loggers
|
179 |
+
*/
|
180 |
+
public function onCanReadSingleLogger($user_can_read_logger, $logger_instance, $user_id)
|
181 |
+
{
|
182 |
+
$user_can_read_logger = true;
|
183 |
+
|
184 |
+
return $user_can_read_logger;
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Output RSS
|
189 |
+
*/
|
190 |
+
public function outputRss()
|
191 |
+
{
|
192 |
+
|
193 |
+
$rss_secret_option = get_option("simple_history_rss_secret");
|
194 |
+
$rss_secret_get = isset($_GET["rss_secret"]) ? $_GET["rss_secret"] : "";
|
195 |
+
|
196 |
+
if (empty($rss_secret_option) || empty($rss_secret_get)) {
|
197 |
+
die();
|
198 |
+
}
|
199 |
+
|
200 |
+
$rss_show = true;
|
201 |
+
$rss_show = apply_filters("simple_history/rss_feed_show", $rss_show);
|
202 |
+
if (! $rss_show || ! $this->isRssEnabled()) {
|
203 |
+
wp_die('Nothing here.');
|
204 |
+
}
|
205 |
+
|
206 |
+
header("Content-Type: text/xml; charset=utf-8");
|
207 |
+
echo '<?xml version="1.0" encoding="UTF-8"?>';
|
208 |
+
$self_link = $this->getRssAddress();
|
209 |
+
|
210 |
+
if ($rss_secret_option === $rss_secret_get) {
|
211 |
+
?>
|
212 |
+
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
213 |
+
<channel>
|
214 |
+
<title><![CDATA[<?php printf(__("History for %s", 'simple-history'), get_bloginfo("name")) ?>]]></title>
|
215 |
+
<description><![CDATA[<?php printf(__("WordPress History for %s", 'simple-history'), get_bloginfo("name")) ?>]]></description>
|
216 |
+
<link><?php echo get_bloginfo("url") ?></link>
|
217 |
+
<atom:link href="<?php echo $self_link; ?>" rel="self" type="application/atom+xml" />
|
218 |
+
<?php
|
219 |
+
|
220 |
+
// Override capability check: if you have a valid rss_secret_key you can read it all
|
221 |
+
$action_tag = "simple_history/loggers_user_can_read/can_read_single_logger";
|
222 |
+
add_action($action_tag, array($this, "onCanReadSingleLogger"), 10, 3);
|
223 |
+
|
224 |
+
// Modify header time output so it does not show relative date or time ago-format
|
225 |
+
// Because we don't know when a user reads the RSS feed, time ago format may be very inaccurate
|
226 |
+
add_action("simple_history/header_just_now_max_time", "__return_zero");
|
227 |
+
add_action("simple_history/header_time_ago_max_time", "__return_zero");
|
228 |
+
|
229 |
+
// Get log rows
|
230 |
+
$args = array(
|
231 |
+
"posts_per_page" => 10
|
232 |
+
);
|
233 |
+
|
234 |
+
$args = apply_filters("simple_history/rss_feed_args", $args);
|
235 |
+
|
236 |
+
$logQuery = new SimpleHistoryLogQuery();
|
237 |
+
$queryResults = $logQuery->query($args);
|
238 |
+
|
239 |
+
// Remove capability override after query is done
|
240 |
+
// remove_action( $action_tag, array($this, "onCanReadSingleLogger") );
|
241 |
+
|
242 |
+
foreach ($queryResults["log_rows"] as $row) {
|
243 |
+
$header_output = $this->sh->getLogRowHeaderOutput($row);
|
244 |
+
$text_output = $this->sh->getLogRowPlainTextOutput($row);
|
245 |
+
$details_output = $this->sh->getLogRowDetailsOutput($row);
|
246 |
+
|
247 |
+
// http://cyber.law.harvard.edu/rss/rss.html#ltguidgtSubelementOfLtitemgt
|
248 |
+
//$item_guid = home_url() . "?SimpleHistoryGuid=" . $row->id;
|
249 |
+
$item_guid = esc_url(add_query_arg("SimpleHistoryGuid", $row->id, home_url()));
|
250 |
+
$item_link = esc_url(add_query_arg("SimpleHistoryGuid", $row->id, home_url()));
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Filter the guid/link URL used in RSS feed.
|
254 |
+
* Link will be esc_url'ed by simple history, so no need to do that in your filter
|
255 |
+
*
|
256 |
+
* @since 2.0.23
|
257 |
+
*
|
258 |
+
* @param string $item_guid link.
|
259 |
+
* @param array $row
|
260 |
+
*/
|
261 |
+
$item_link = apply_filters("simple_history/rss_item_link", $item_link, $row);
|
262 |
+
$item_link = esc_url($item_link);
|
263 |
+
|
264 |
+
$item_title = sprintf(
|
265 |
+
'%2$s',
|
266 |
+
$this->sh->getLogLevelTranslated($row->level),
|
267 |
+
wp_kses($text_output, array())
|
268 |
+
);
|
269 |
+
|
270 |
+
$level_output = sprintf(__('Severity level: %1$s'), $this->sh->getLogLevelTranslated($row->level));
|
271 |
+
|
272 |
+
?>
|
273 |
+
<item>
|
274 |
+
<title><![CDATA[<?php echo $item_title; ?>]]></title>
|
275 |
+
<description><![CDATA[
|
276 |
+
<p><?php echo $header_output ?></p>
|
277 |
+
<p><?php echo $text_output ?></p>
|
278 |
+
<div><?php echo $details_output ?></div>
|
279 |
+
<p><?php echo $level_output ?></p>
|
280 |
+
<?php
|
281 |
+
$occasions = $row->subsequentOccasions - 1;
|
282 |
+
if ($occasions) {
|
283 |
+
printf(
|
284 |
+
_n('+%1$s occasion', '+%1$s occasions', $occasions, 'simple-history'),
|
285 |
+
$occasions
|
286 |
+
);
|
287 |
+
}
|
288 |
+
?>
|
289 |
+
]]></description>
|
290 |
+
<?php
|
291 |
+
// author must be email to validate, but the field is optional, so we skip it
|
292 |
+
/* <author><?php echo $row->initiator ?></author> */
|
293 |
+
?>
|
294 |
+
<pubDate><?php echo date("D, d M Y H:i:s", strtotime($row->date)) ?> GMT</pubDate>
|
295 |
+
<guid isPermaLink="false"><![CDATA[<?php echo $item_guid ?>]]></guid>
|
296 |
+
<link><![CDATA[<?php echo $item_link ?>]]></link>
|
297 |
+
</item>
|
298 |
+
<?php
|
299 |
+
/*
|
300 |
+
[0] => stdClass Object
|
301 |
+
(
|
302 |
+
[id] => 27324
|
303 |
+
[logger] => SimplePluginLogger
|
304 |
+
[level] => info
|
305 |
+
[date] => 2014-10-15 06:50:01
|
306 |
+
[message] => Updated plugin "{plugin_name}" from {plugin_prev_version} to {plugin_version}
|
307 |
+
[type] =>
|
308 |
+
[initiator] => wp_user
|
309 |
+
[occasionsID] => 75e8aeab3e43b37f8a458f3744c4995f
|
310 |
+
[subsequentOccasions] => 1
|
311 |
+
[rep] => 1
|
312 |
+
[repeated] => 1
|
313 |
+
[occasionsIDType] => 75e8aeab3e43b37f8a458f3744c4995f
|
314 |
+
[context] => Array
|
315 |
+
(
|
316 |
+
[plugin_slug] => google-analytics-for-wordpress
|
317 |
+
[plugin_name] => Google Analytics by Yoast
|
318 |
+
[plugin_title] => <a href="https://yoast.com/wordpress/plugins/google-analytics/#utm_source=wordpress&#038;utm_medium=plugin&#038;utm_campaign=wpgaplugin&#038;utm_content=v504">Google Analytics by Yoast</a>
|
319 |
+
[plugin_description] => This plugin makes it simple to add Google Analytics to your WordPress blog, adding lots of features, eg. error page, search result and automatic clickout and download tracking. <cite>By <a href="https://yoast.com/">Team Yoast</a>.</cite>
|
320 |
+
[plugin_author] => <a href="https://yoast.com/">Team Yoast</a>
|
321 |
+
[plugin_version] => 5.0.7
|
322 |
+
[plugin_url] => https://yoast.com/wordpress/plugins/google-analytics/#utm_source=wordpress&#038;utm_medium=plugin&#038;utm_campaign=wpgaplugin&#038;utm_content=v504
|
323 |
+
[plugin_update_info_plugin] => google-analytics-for-wordpress/googleanalytics.php
|
324 |
+
[plugin_update_info_package] => https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.5.0.7.zip
|
325 |
+
[plugin_prev_version] => 5.0.6
|
326 |
+
[_message_key] => plugin_bulk_updated
|
327 |
+
[_user_id] => 1
|
328 |
+
[_user_login] => admin
|
329 |
+
[_user_email] => par.thernstrom@gmail.com
|
330 |
+
[_server_remote_addr] => ::1
|
331 |
+
[_server_http_referer] => http://playground-root.ep/wp-admin/update-core.php?action=do-plugin-upgrade
|
332 |
+
)
|
333 |
+
|
334 |
+
)
|
335 |
+
*/
|
336 |
+
} // foreach
|
337 |
+
|
338 |
+
?>
|
339 |
+
</channel>
|
340 |
+
</rss>
|
341 |
+
<?php
|
342 |
+
} else {
|
343 |
+
// RSS secret was not ok
|
344 |
+
?>
|
345 |
+
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
346 |
+
<channel>
|
347 |
+
<title><?php printf(__("History for %s", 'simple-history'), get_bloginfo("name")) ?></title>
|
348 |
+
<description><?php printf(__("WordPress History for %s", 'simple-history'), get_bloginfo("name")) ?></description>
|
349 |
+
<link><?php echo home_url() ?></link>
|
350 |
+
<item>
|
351 |
+
<title><?php _e("Wrong RSS secret", 'simple-history')?></title>
|
352 |
+
<description><?php _e("Your RSS secret for Simple History RSS feed is wrong. Please see WordPress settings for current link to the RSS feed.", 'simple-history')?></description>
|
353 |
+
<pubDate><?php echo date("D, d M Y H:i:s", time()) ?> GMT</pubDate>
|
354 |
+
<guid><?php echo home_url() . "?SimpleHistoryGuid=wrong-secret" ?></guid>
|
355 |
+
</item>
|
356 |
+
</channel>
|
357 |
+
</rss>
|
358 |
+
<?php
|
359 |
+
}
|
360 |
+
} // rss
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Create a new RSS secret
|
364 |
+
*
|
365 |
+
* @return string new secret
|
366 |
+
*/
|
367 |
+
public function updateRssSecret()
|
368 |
+
{
|
369 |
+
|
370 |
+
$rss_secret = "";
|
371 |
+
|
372 |
+
for ($i=0; $i<20; $i++) {
|
373 |
+
$rss_secret .= chr(rand(97, 122));
|
374 |
+
}
|
375 |
+
|
376 |
+
update_option("simple_history_rss_secret", $rss_secret);
|
377 |
+
|
378 |
+
return $rss_secret;
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Output for settings field that show current RSS address
|
383 |
+
*/
|
384 |
+
public function settingsFieldRss()
|
385 |
+
{
|
386 |
+
|
387 |
+
$rss_address = $this->getRssAddress();
|
388 |
+
|
389 |
+
echo "<p><code><a href='$rss_address'>$rss_address</a></code></p>";
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* Output for settings field that regenerates the RSS adress/secret
|
394 |
+
*/
|
395 |
+
public function settingsFieldRssRegenerate()
|
396 |
+
{
|
397 |
+
|
398 |
+
$update_link = esc_url(add_query_arg("", ""));
|
399 |
+
$update_link = wp_nonce_url($update_link, "simple_history_rss_update_secret", "simple_history_rss_secret_regenerate_nonce");
|
400 |
+
|
401 |
+
echo "<p>";
|
402 |
+
_e("You can generate a new address for the RSS feed. This is useful if you think that the address has fallen into the wrong hands.", 'simple-history');
|
403 |
+
echo "</p>";
|
404 |
+
|
405 |
+
echo "<p>";
|
406 |
+
printf(
|
407 |
+
'<a class="button" href="%1$s">%2$s</a>',
|
408 |
+
$update_link, // 1
|
409 |
+
__('Generate new address', "simple-history") // 2
|
410 |
+
);
|
411 |
+
|
412 |
+
echo "</p>";
|
413 |
+
}
|
414 |
+
|
415 |
+
/**
|
416 |
+
* Get the URL to the RSS feed
|
417 |
+
*
|
418 |
+
* @return string URL
|
419 |
+
*/
|
420 |
+
public function getRssAddress()
|
421 |
+
{
|
422 |
+
|
423 |
+
$rss_secret = get_option("simple_history_rss_secret");
|
424 |
+
$rss_address = add_query_arg(
|
425 |
+
array("simple_history_get_rss" => "1", "rss_secret" => $rss_secret),
|
426 |
+
get_bloginfo("url") . "/"
|
427 |
+
);
|
428 |
+
$rss_address = esc_url($rss_address);
|
429 |
+
// $rss_address = htmlspecialchars($rss_address, ENT_COMPAT, "UTF-8");
|
430 |
+
|
431 |
+
return $rss_address;
|
432 |
+
}
|
433 |
+
|
434 |
+
/**
|
435 |
+
* Content for section intro. Leave it be, even if empty.
|
436 |
+
* Called from add_sections_setting.
|
437 |
+
*/
|
438 |
+
public function settingsSectionOutput()
|
439 |
+
{
|
440 |
+
|
441 |
+
echo "<p>";
|
442 |
+
_e("Simple History has a RSS feed which you can subscribe to and receive log updates. Make sure you only share the feed with people you trust, since it can contain sensitive or confidential information.", 'simple-history');
|
443 |
+
echo "</p>";
|
444 |
+
}
|
445 |
} // end rss class
|
examples/examples.php
CHANGED
@@ -16,6 +16,23 @@ define("SIMPLE_HISTORY_LOG_DEBUG", true);
|
|
16 |
* Some examples of filter usage and so on
|
17 |
*/
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
// Do not log some post types, for example pages and attachments in this case
|
20 |
add_filter( "simple_history/log/do_log", function( $do_log = null, $level = null, $message = null, $context = null, $logger = null) {
|
21 |
|
16 |
* Some examples of filter usage and so on
|
17 |
*/
|
18 |
|
19 |
+
// Modify who can read a logger
|
20 |
+
// Modify the if part to give users access or no access to a logger
|
21 |
+
add_filter( 'simple_history/loggers_user_can_read/can_read_single_logger', function( $user_can_read_logger, $logger_instance, $user_id ) {
|
22 |
+
|
23 |
+
// in this example user with id 3 gets access to the post logger
|
24 |
+
// while user with id 8 does not get any access to it
|
25 |
+
if ( $logger_instance->slug == "SimplePostLogger" && $user_id === 3 ) {
|
26 |
+
$user_can_read_logger = true;
|
27 |
+
} else if ( $logger_instance->slug == "SimplePostLogger" && $user_id === 9 ) {
|
28 |
+
$user_can_read_logger = false;
|
29 |
+
}
|
30 |
+
|
31 |
+
return $user_can_read_logger;
|
32 |
+
|
33 |
+
}, 10, 3 );
|
34 |
+
|
35 |
+
|
36 |
// Do not log some post types, for example pages and attachments in this case
|
37 |
add_filter( "simple_history/log/do_log", function( $do_log = null, $level = null, $message = null, $context = null, $logger = null) {
|
38 |
|
inc/SimpleHistory.php
CHANGED
@@ -887,7 +887,8 @@ class SimpleHistory {
|
|
887 |
$loggersDir . "PluginEnableMediaReplaceLogger.php",
|
888 |
$loggersDir . "Plugin_UltimateMembers_Logger.php",
|
889 |
$loggersDir . "Plugin_LimitLoginAttempts.php",
|
890 |
-
|
|
|
891 |
);
|
892 |
|
893 |
// SimpleLogger.php must be loaded first and always since the other loggers extend it
|
887 |
$loggersDir . "PluginEnableMediaReplaceLogger.php",
|
888 |
$loggersDir . "Plugin_UltimateMembers_Logger.php",
|
889 |
$loggersDir . "Plugin_LimitLoginAttempts.php",
|
890 |
+
$loggersDir . "Plugin_Redirection.php",
|
891 |
+
$loggersDir . "Plugin_DuplicatePost.php",
|
892 |
);
|
893 |
|
894 |
// SimpleLogger.php must be loaded first and always since the other loggers extend it
|
index.php
CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://simple-history.com
|
|
5 |
Text Domain: simple-history
|
6 |
Domain Path: /languages
|
7 |
Description: Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.
|
8 |
-
Version: 2.
|
9 |
Author: Pär Thernström
|
10 |
Author URI: http://simple-history.com/
|
11 |
License: GPL2
|
@@ -42,7 +42,7 @@ if ( version_compare( phpversion(), "5.3", ">=") ) {
|
|
42 |
// register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
|
43 |
|
44 |
if ( ! defined( 'SIMPLE_HISTORY_VERSION' ) ) {
|
45 |
-
define( 'SIMPLE_HISTORY_VERSION', '2.
|
46 |
}
|
47 |
|
48 |
if ( ! defined( 'SIMPLE_HISTORY_PATH' ) ) {
|
5 |
Text Domain: simple-history
|
6 |
Domain Path: /languages
|
7 |
Description: Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.
|
8 |
+
Version: 2.14
|
9 |
Author: Pär Thernström
|
10 |
Author URI: http://simple-history.com/
|
11 |
License: GPL2
|
42 |
// register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
|
43 |
|
44 |
if ( ! defined( 'SIMPLE_HISTORY_VERSION' ) ) {
|
45 |
+
define( 'SIMPLE_HISTORY_VERSION', '2.14' );
|
46 |
}
|
47 |
|
48 |
if ( ! defined( 'SIMPLE_HISTORY_PATH' ) ) {
|
loggers/Plugin_DuplicatePost.php
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
defined('ABSPATH') or die();
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Logger for the Duplicate Post plugin
|
7 |
+
* Post Duplicator (https://sv.wordpress.org/plugins/duplicate-post/)
|
8 |
+
*
|
9 |
+
* @package SimpleHistory
|
10 |
+
* @since 2.13
|
11 |
+
*/
|
12 |
+
if (! class_exists("Plugin_DuplicatePost")) {
|
13 |
+
|
14 |
+
class Plugin_DuplicatePost extends SimpleLogger
|
15 |
+
{
|
16 |
+
public $slug = __CLASS__;
|
17 |
+
|
18 |
+
public function getInfo()
|
19 |
+
{
|
20 |
+
$arr_info = array(
|
21 |
+
"name" => "Plugin Duplicate Posts",
|
22 |
+
"description" => _x("Logs posts and pages cloned using plugin Duplicate Post", "Logger: Plugin Duplicate Post", "simple-history"),
|
23 |
+
"name_via" => _x("Using plugin Duplicate Posts", "Logger: Plugin Duplicate Post", "simple-history"),
|
24 |
+
"capability" => "manage_options",
|
25 |
+
"messages" => array(
|
26 |
+
'post_duplicated' => _x('Cloned "{duplicated_post_title}" to a new post', "Logger: Plugin Duplicate Post", 'simple-history')
|
27 |
+
),
|
28 |
+
);
|
29 |
+
|
30 |
+
return $arr_info;
|
31 |
+
}
|
32 |
+
|
33 |
+
public function loaded()
|
34 |
+
{
|
35 |
+
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
36 |
+
|
37 |
+
$pluginFilePath = 'duplicate-post/duplicate-post.php';
|
38 |
+
$isPluginActive = is_plugin_active('duplicate-post/duplicate-post.php');
|
39 |
+
|
40 |
+
if (!$isPluginActive) {
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
|
44 |
+
// When a copy have been made of a post or page
|
45 |
+
// the action 'dp_duplicate_page' or 'dp_duplicate_post'
|
46 |
+
// is fired with args $new_post_id, $post, $status.
|
47 |
+
// We add actions with prio 20 so we probably run after
|
48 |
+
// the plugins own
|
49 |
+
add_action('dp_duplicate_post', array($this, 'onDpDuplicatePost'), 100, 3);
|
50 |
+
add_action('dp_duplicate_page', array($this, 'onDpDuplicatePost'), 100, 3);
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* A post or page was duplicated
|
55 |
+
*
|
56 |
+
* @param $new_post_id
|
57 |
+
* @param $post old post that a copy was made of
|
58 |
+
* @param $status
|
59 |
+
*/
|
60 |
+
public function onDpDuplicatePost($newPostID, $post, $status)
|
61 |
+
{
|
62 |
+
$new_post = get_post($newPostID);
|
63 |
+
|
64 |
+
$context = [
|
65 |
+
"new_post_title" => $new_post->post_title,
|
66 |
+
"new_post_id" => $new_post->ID,
|
67 |
+
"duplicated_post_title" => $post->post_title,
|
68 |
+
"duplicated_post_id" => $post->ID,
|
69 |
+
// "duplicate_new_post_id" => $newPostID,
|
70 |
+
// "status" => $status
|
71 |
+
];
|
72 |
+
|
73 |
+
$this->infoMessage(
|
74 |
+
"post_duplicated",
|
75 |
+
$context
|
76 |
+
);
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Modify plain output to include link to post
|
81 |
+
*/
|
82 |
+
public function getLogRowPlainTextOutput($row) {
|
83 |
+
|
84 |
+
$context = $row->context;
|
85 |
+
$new_post_id = isset($context["new_post_id"]) ? $context["new_post_id"] : null;
|
86 |
+
$duplicated_post_id = isset($context["duplicated_post_id"]) ? $context["duplicated_post_id"] : null;
|
87 |
+
$duplicated_post_title = isset($context["duplicated_post_title"]) ? $context["duplicated_post_title"] : null;
|
88 |
+
$message_key = isset($context["_message_key"]) ? $context["_message_key"] : null;
|
89 |
+
|
90 |
+
$message = $row->message;
|
91 |
+
|
92 |
+
// Check if post still is available
|
93 |
+
// It will return a WP_Post Object if post still is in system
|
94 |
+
// If post is deleted from trash (not just moved there), then null is returned
|
95 |
+
$postDuplicated = get_post($duplicated_post_id);
|
96 |
+
$post_is_available = is_a($postDuplicated, "WP_Post");
|
97 |
+
|
98 |
+
// Try to get singular name
|
99 |
+
$post_type = isset($postDuplicated->post_type) ? $postDuplicated->post_type : "";
|
100 |
+
$post_type_obj = get_post_type_object($post_type);
|
101 |
+
|
102 |
+
if (!is_null($post_type_obj)) {
|
103 |
+
if (!empty ($post_type_obj->labels->singular_name) ) {
|
104 |
+
$context["duplicated_post_post_type_singular_name"] = strtolower($post_type_obj->labels->singular_name);
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
$context["duplicated_post_edit_link"] = get_edit_post_link($duplicated_post_id);
|
109 |
+
$context["new_post_edit_link"] = get_edit_post_link($new_post_id);
|
110 |
+
|
111 |
+
// If post is not available any longer then we can't link to it, so keep plain message then
|
112 |
+
// Also keep plain format if user is not allowed to edit post (edit link is empty)
|
113 |
+
if ($post_is_available && $context["duplicated_post_edit_link"]) {
|
114 |
+
$message = _x('Cloned {duplicated_post_post_type_singular_name} <a href="{duplicated_post_edit_link}">"{duplicated_post_title}"</a> to <a href="{new_post_edit_link}">a new {duplicated_post_post_type_singular_name}</a>', "Logger: Plugin Duplicate Post", "simple-history");
|
115 |
+
} // post still available
|
116 |
+
|
117 |
+
$context["new_post_edit_link"] = isset($context["new_post_edit_link"]) ? esc_html($context["new_post_edit_link"]) : "";
|
118 |
+
|
119 |
+
$context["duplicated_post_edit_link"] = isset($context["duplicated_post_edit_link"]) ? esc_html($context["duplicated_post_edit_link"]) : "";
|
120 |
+
|
121 |
+
$context["duplicated_post_title"] = isset($context["duplicated_post_title"]) ? esc_html($context["duplicated_post_title"]) : "";
|
122 |
+
|
123 |
+
$context["duplicated_post_title"] = isset($context["duplicated_post_title"]) ? esc_html($context["duplicated_post_title"]) : "";
|
124 |
+
|
125 |
+
$context["duplicated_post_post_type_singular_name"] = isset($context["duplicated_post_post_type_singular_name"]) ? esc_html($context["duplicated_post_post_type_singular_name"]) : "";
|
126 |
+
|
127 |
+
return $this->interpolate($message, $context, $row);
|
128 |
+
}
|
129 |
+
} // class
|
130 |
+
} // class exists
|
loggers/Plugin_LimitLoginAttempts.php
CHANGED
@@ -46,6 +46,18 @@ if ( ! class_exists("Plugin_LimitLoginAttempts") ) {
|
|
46 |
|
47 |
function loaded() {
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
add_filter( "pre_option_limit_login_lockouts_total", array( $this, "on_option_limit_login_lockouts_total" ), 10, 1 );
|
50 |
|
51 |
add_action( "load-settings_page_limit-login-attempts", array( $this, "on_load_settings_page" ), 10, 1 );
|
46 |
|
47 |
function loaded() {
|
48 |
|
49 |
+
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
50 |
+
|
51 |
+
$pluginFilePath = 'limit-login-attempts/limit-login-attempts.php';
|
52 |
+
$isPluginActive = is_plugin_active($pluginFilePath);
|
53 |
+
|
54 |
+
// Only continue to add filters if plugin is active.
|
55 |
+
// This minimise the risk of plugin errors, because plugin
|
56 |
+
// has been forked to new versions.
|
57 |
+
if (!$isPluginActive) {
|
58 |
+
return;
|
59 |
+
}
|
60 |
+
|
61 |
add_filter( "pre_option_limit_login_lockouts_total", array( $this, "on_option_limit_login_lockouts_total" ), 10, 1 );
|
62 |
|
63 |
add_action( "load-settings_page_limit-login-attempts", array( $this, "on_load_settings_page" ), 10, 1 );
|
loggers/SimplePostLogger.php
CHANGED
@@ -302,7 +302,7 @@ class SimplePostLogger extends SimpleLogger
|
|
302 |
|
303 |
/**
|
304 |
* Fired when a post has changed status
|
305 |
-
* Only run in certain cases,
|
306 |
* because when always enabled it catches a lots of edits made by plugins during cron jobs etc,
|
307 |
* which by definition is not wrong, but perhaps not wanted/annoying
|
308 |
*/
|
@@ -660,7 +660,7 @@ class SimplePostLogger extends SimpleLogger
|
|
660 |
}
|
661 |
|
662 |
/**
|
663 |
-
* Modify plain output to
|
664 |
*/
|
665 |
public function getLogRowPlainTextOutput($row) {
|
666 |
|
@@ -671,7 +671,7 @@ class SimplePostLogger extends SimpleLogger
|
|
671 |
$message = $row->message;
|
672 |
|
673 |
// Check if post still is available
|
674 |
-
// It
|
675 |
// If post is deleted from trash (not just moved there), then null is returned
|
676 |
$post = get_post( $post_id );
|
677 |
$post_is_available = is_a($post, "WP_Post");
|
302 |
|
303 |
/**
|
304 |
* Fired when a post has changed status
|
305 |
+
* Only run in certain cases,
|
306 |
* because when always enabled it catches a lots of edits made by plugins during cron jobs etc,
|
307 |
* which by definition is not wrong, but perhaps not wanted/annoying
|
308 |
*/
|
660 |
}
|
661 |
|
662 |
/**
|
663 |
+
* Modify plain output to include link to post
|
664 |
*/
|
665 |
public function getLogRowPlainTextOutput($row) {
|
666 |
|
671 |
$message = $row->message;
|
672 |
|
673 |
// Check if post still is available
|
674 |
+
// It will return a WP_Post Object if post still is in system
|
675 |
// If post is deleted from trash (not just moved there), then null is returned
|
676 |
$post = get_post( $post_id );
|
677 |
$post_is_available = is_a($post, "WP_Post");
|
loggers/SimpleUserLogger.php
CHANGED
@@ -1,1013 +1,966 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
defined( 'ABSPATH' ) or die();
|
4 |
-
|
5 |
/**
|
6 |
* Logs changes to user logins (and logouts)
|
7 |
*/
|
8 |
-
class SimpleUserLogger extends SimpleLogger
|
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 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
<td>%1$s</td>
|
969 |
-
<td>%2$s</td>
|
970 |
-
</tr>',
|
971 |
-
_x("Notification", "User logger", "simple-history"),
|
972 |
-
sprintf(
|
973 |
-
'<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>',
|
974 |
-
esc_html( $sent_status ) // 1
|
975 |
-
)
|
976 |
-
);
|
977 |
-
|
978 |
-
}
|
979 |
-
|
980 |
-
} else {
|
981 |
-
|
982 |
-
$diff_table_output .= sprintf(
|
983 |
-
'<tr>
|
984 |
-
<td>%1$s</td>
|
985 |
-
<td>%2$s</td>
|
986 |
-
</tr>',
|
987 |
-
$val["title"],
|
988 |
-
sprintf(
|
989 |
-
'<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>',
|
990 |
-
esc_html( $context[ $key ] ) // 1
|
991 |
-
)
|
992 |
-
);
|
993 |
-
|
994 |
-
}
|
995 |
-
|
996 |
-
}
|
997 |
-
|
998 |
-
}
|
999 |
-
|
1000 |
-
if ( $diff_table_output ) {
|
1001 |
-
$diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
|
1002 |
-
}
|
1003 |
-
|
1004 |
-
$out .= $diff_table_output;
|
1005 |
-
|
1006 |
-
} // message key
|
1007 |
-
|
1008 |
-
return $out;
|
1009 |
-
|
1010 |
-
|
1011 |
-
}
|
1012 |
-
|
1013 |
}
|
1 |
<?php
|
2 |
|
|
|
|
|
3 |
/**
|
4 |
* Logs changes to user logins (and logouts)
|
5 |
*/
|
6 |
+
class SimpleUserLogger extends SimpleLogger
|
7 |
+
{
|
8 |
+
|
9 |
+
public $slug = __CLASS__;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Get array with information about this logger
|
13 |
+
*
|
14 |
+
* @return array
|
15 |
+
*/
|
16 |
+
public function getInfo()
|
17 |
+
{
|
18 |
+
|
19 |
+
$arr_info = array(
|
20 |
+
"name" => __("User Logger", "simple-history"),
|
21 |
+
"description" => __("Logs user logins, logouts, and failed logins", "simple-history"),
|
22 |
+
"capability" => "edit_users",
|
23 |
+
"messages" => array(
|
24 |
+
'user_login_failed' => __(
|
25 |
+
'Failed to login with username "{login}" (incorrect password entered)',
|
26 |
+
"simple-history"
|
27 |
+
),
|
28 |
+
'user_unknown_login_failed' => __(
|
29 |
+
'Failed to login with username "{failed_username}" (username does not exist)',
|
30 |
+
"simple-history"
|
31 |
+
),
|
32 |
+
'user_logged_in' => __('Logged in', "simple-history"),
|
33 |
+
'user_unknown_logged_in' => __("Unknown user logged in", "simple-history"),
|
34 |
+
'user_logged_out' => __("Logged out", "simple-history"),
|
35 |
+
'user_updated_profile' => __(
|
36 |
+
"Edited the profile for user {edited_user_login} ({edited_user_email})",
|
37 |
+
"simple-history"
|
38 |
+
),
|
39 |
+
'user_created' => __(
|
40 |
+
"Created user {created_user_login} ({created_user_email}) with role {created_user_role}",
|
41 |
+
"simple-history"
|
42 |
+
),
|
43 |
+
'user_deleted' => __("Deleted user {deleted_user_login} ({deleted_user_email})", "simple-history"),
|
44 |
+
"user_password_reseted" => __("Reset their password", "simple-history"),
|
45 |
+
"user_requested_password_reset_link" => __(
|
46 |
+
"Requested a password reset link for user with login '{user_login}' and email '{user_email}'",
|
47 |
+
"simple-history"
|
48 |
+
),
|
49 |
+
|
50 |
+
/*
|
51 |
+
Text used in admin:
|
52 |
+
Log Out of All Other Sessions
|
53 |
+
Left your account logged in at a public computer?
|
54 |
+
Lost your phone? This will log you out everywhere except your current browser
|
55 |
+
*/
|
56 |
+
'user_session_destroy_others' => _x(
|
57 |
+
'Logged out from all other sessions',
|
58 |
+
'User destroys other login sessions for themself',
|
59 |
+
'simple-history'
|
60 |
+
),
|
61 |
+
/*
|
62 |
+
Text used in admin:
|
63 |
+
'Log %s out of all sessions' ), $profileuser->display_name );
|
64 |
+
*/
|
65 |
+
'user_session_destroy_everywhere' => _x(
|
66 |
+
'Logged out "{user_display_name}" from all sessions',
|
67 |
+
'User destroys all login sessions for a user',
|
68 |
+
'simple-history'
|
69 |
+
),
|
70 |
+
),
|
71 |
+
|
72 |
+
"labels" => array(
|
73 |
+
"search" => array(
|
74 |
+
"label" => _x("Users", "User logger: search", "simple-history"),
|
75 |
+
"label_all" => _x("All user activity", "User logger: search", "simple-history"),
|
76 |
+
"options" => array(
|
77 |
+
_x("Successful user logins", "User logger: search", "simple-history") => array(
|
78 |
+
"user_logged_in",
|
79 |
+
"user_unknown_logged_in",
|
80 |
+
),
|
81 |
+
_x("Failed user logins", "User logger: search", "simple-history") => array(
|
82 |
+
'user_login_failed',
|
83 |
+
'user_unknown_login_failed',
|
84 |
+
),
|
85 |
+
_x('User logouts', 'User logger: search', 'simple-history') => array(
|
86 |
+
"user_logged_out",
|
87 |
+
),
|
88 |
+
_x('Created users', 'User logger: search', 'simple-history') => array(
|
89 |
+
"user_created",
|
90 |
+
),
|
91 |
+
_x("User profile updates", "User logger: search", "simple-history") => array(
|
92 |
+
"user_updated_profile",
|
93 |
+
),
|
94 |
+
_x('User deletions', 'User logger: search', 'simple-history') => array(
|
95 |
+
"user_deleted",
|
96 |
+
),
|
97 |
+
|
98 |
+
),
|
99 |
+
), // end search
|
100 |
+
|
101 |
+
), // end labels
|
102 |
+
|
103 |
+
);
|
104 |
+
|
105 |
+
return $arr_info;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Add actions and filters when logger is loaded by Simple History
|
110 |
+
*/
|
111 |
+
public function loaded()
|
112 |
+
{
|
113 |
+
|
114 |
+
// Plain logins and logouts
|
115 |
+
add_action("wp_login", array($this, "onWpLogin"), 10, 3);
|
116 |
+
add_action("wp_logout", array($this, "onWpLogout"));
|
117 |
+
|
118 |
+
// Failed login attempt to username that exists
|
119 |
+
add_action("wp_authenticate_user", array($this, "onWpAuthenticateUser"), 10, 2);
|
120 |
+
|
121 |
+
// Failed to login to user that did not exist (perhaps brute force)
|
122 |
+
// run this later than 10 because wordpress own email login check is done with prio 20
|
123 |
+
// so if we run at 10 we just get null
|
124 |
+
add_filter('authenticate', array($this, "onAuthenticate"), 30, 3);
|
125 |
+
|
126 |
+
// User is changed
|
127 |
+
#add_action("profile_update", array($this, "on_profile_update"), 10, 2);
|
128 |
+
|
129 |
+
// User is created
|
130 |
+
add_action("user_register", array($this, "onUserRegister"), 10, 2);
|
131 |
+
|
132 |
+
// User is deleted
|
133 |
+
add_action('delete_user', array($this, "onDeleteUser"), 10, 2);
|
134 |
+
|
135 |
+
// User sessions is destroyed. AJAX call that we hook onto early.
|
136 |
+
add_action("wp_ajax_destroy-sessions", array($this, "onDestroyUserSession"), 0);
|
137 |
+
|
138 |
+
// User reaches reset password (from link or only from user created link)
|
139 |
+
add_action('validate_password_reset', array($this, "onValidatePasswordReset" ), 10, 2);
|
140 |
+
|
141 |
+
add_action('retrieve_password_message', array($this, "onRetrievePasswordMessage" ), 10, 4);
|
142 |
+
|
143 |
+
add_filter('insert_user_meta', array($this, "onInsertUserMeta" ), 10, 3);
|
144 |
+
}
|
145 |
+
|
146 |
+
/*
|
147 |
+
* Called before the user is updated
|
148 |
+
*
|
149 |
+
* Filter a user's meta values and keys before the user is created or updated.
|
150 |
+
*
|
151 |
+
* Does not include contact methods. These are added using `wp_get_user_contact_methods($user )`.
|
152 |
+
*
|
153 |
+
* @param array $meta {
|
154 |
+
* Default meta values and keys for the user.
|
155 |
+
*
|
156 |
+
* @type string $nickname The user's nickname. Default is the user's username.
|
157 |
+
* @type string $first_name The user's first name.
|
158 |
+
* @type string $last_name The user's last name.
|
159 |
+
* @type string $description The user's description.
|
160 |
+
* @type bool $rich_editing Whether to enable the rich-editor for the user. False if not empty.
|
161 |
+
* @type bool $comment_shortcuts Whether to enable keyboard shortcuts for the user. Default false.
|
162 |
+
* @type string $admin_color The color scheme for a user's admin screen. Default 'fresh'.
|
163 |
+
* @type int|bool $use_ssl Whether to force SSL on the user's admin area. 0|false if SSL is
|
164 |
+
* not forced.
|
165 |
+
* @type bool $show_admin_bar_front Whether to show the admin bar on the front end for the user.
|
166 |
+
* Default true.
|
167 |
+
* }
|
168 |
+
* @param WP_User $user User object.
|
169 |
+
* @param bool $update Whether the user is being updated rather than created.
|
170 |
+
*/
|
171 |
+
public function onInsertUserMeta($meta, $user, $update)
|
172 |
+
{
|
173 |
+
|
174 |
+
// We only log updates here
|
175 |
+
if (! $update) {
|
176 |
+
return $meta;
|
177 |
+
}
|
178 |
+
|
179 |
+
// $user should be set, but check just in case
|
180 |
+
if (empty($user) || ! is_object($user)) {
|
181 |
+
return $meta;
|
182 |
+
}
|
183 |
+
|
184 |
+
// Make of copy of the posted data, because we change the keys
|
185 |
+
$posted_data = $_POST;
|
186 |
+
$posted_data = stripslashes_deep($posted_data);
|
187 |
+
|
188 |
+
// Paranoid mode, just in case some other plugin fires the "insert_user_meta"
|
189 |
+
// filter and the user.php file is not loaded for some super wierd reason
|
190 |
+
if (! function_exists("_get_additional_user_keys")) {
|
191 |
+
return $meta;
|
192 |
+
}
|
193 |
+
|
194 |
+
// Get the default fields to include.
|
195 |
+
// This includes contact methods (including filter, so more could have been added)
|
196 |
+
$arr_keys_to_check = _get_additional_user_keys($user);
|
197 |
+
|
198 |
+
// Somehow some fields are not include above, so add them manually
|
199 |
+
$arr_keys_to_check = array_merge($arr_keys_to_check, array("user_email", "user_url", "display_name"));
|
200 |
+
|
201 |
+
// Skip some keys, because to much info or I don't know what they are
|
202 |
+
$arr_keys_to_check = array_diff($arr_keys_to_check, array("use_ssl"));
|
203 |
+
|
204 |
+
// Some keys have different ways of getting data from user
|
205 |
+
// so change posted object to match those
|
206 |
+
$posted_data["user_url"] = isset($posted_data["url"]) ? $posted_data["url"] : null;
|
207 |
+
$posted_data["show_admin_bar_front"] = isset($posted_data["admin_bar_front"]) ? true : null;
|
208 |
+
$posted_data["user_email"] = isset($posted_data["email"]) ? $posted_data["email"] : null;
|
209 |
+
|
210 |
+
// Display name publicly as = POST "display_name"
|
211 |
+
#var_dump($user->display_name);
|
212 |
+
|
213 |
+
// Set vals for Enable keyboard shortcuts for comment moderation
|
214 |
+
$posted_data['comment_shortcuts'] = isset($posted_data['comment_shortcuts']) ? "true" : "false";
|
215 |
+
|
216 |
+
// Set vals for Disable the visual editor when writing
|
217 |
+
// posted val = string "false" = yes, disable
|
218 |
+
$posted_data['rich_editing'] = isset($posted_data['rich_editing']) ? "false" : "true";
|
219 |
+
|
220 |
+
// Set vals for Show Toolbar when viewing site
|
221 |
+
$posted_data['show_admin_bar_front'] = isset($posted_data['admin_bar_front']) ? "true" : "false";
|
222 |
+
|
223 |
+
// if checkbox is checked in admin then this is the saved value on the user object
|
224 |
+
// @todo:
|
225 |
+
|
226 |
+
// Check if password was updated
|
227 |
+
$password_changed = false;
|
228 |
+
if (! empty($posted_data['pass1']) && ! empty($posted_data['pass2']) && $posted_data['pass1'] == $posted_data['pass2']) {
|
229 |
+
$password_changed = 1;
|
230 |
+
}
|
231 |
+
|
232 |
+
// Check if role was changed
|
233 |
+
//[role] => bbp_moderator
|
234 |
+
$role_changed = false;
|
235 |
+
|
236 |
+
// if user is network admin then role dropdown does not exist and role is not posted here
|
237 |
+
$new_role = isset($posted_data["role"]) ? $posted_data["role"] : null;
|
238 |
+
|
239 |
+
if ($new_role) {
|
240 |
+
// as done in user-edit.php
|
241 |
+
// Compare user role against currently editable roles
|
242 |
+
$user_roles = array_intersect(array_values($user->roles), array_keys(get_editable_roles()));
|
243 |
+
$old_role = reset($user_roles);
|
244 |
+
|
245 |
+
$role_changed = $new_role != $old_role;
|
246 |
+
}
|
247 |
+
|
248 |
+
// Will contain the differences
|
249 |
+
$user_data_diff = array();
|
250 |
+
|
251 |
+
// Check all keys for diff values
|
252 |
+
foreach ($arr_keys_to_check as $one_key_to_check) {
|
253 |
+
$old_val = $user->$one_key_to_check;
|
254 |
+
$new_val = isset($posted_data[$one_key_to_check]) ? $posted_data[$one_key_to_check] : null;
|
255 |
+
|
256 |
+
#echo "<hr>key: $one_key_to_check";
|
257 |
+
#echo "<br>old val: $old_val";
|
258 |
+
#echo "<br>new val: $new_val";
|
259 |
+
|
260 |
+
// new val must be set, because otherwise we are not setting anything
|
261 |
+
if (! isset($new_val)) {
|
262 |
+
continue;
|
263 |
+
}
|
264 |
+
|
265 |
+
$user_data_diff = $this->addDiff($user_data_diff, $one_key_to_check, $old_val, $new_val);
|
266 |
+
}
|
267 |
+
|
268 |
+
// Setup basic context
|
269 |
+
$context = array(
|
270 |
+
"edited_user_id" => $user->ID,
|
271 |
+
"edited_user_email" => $user->user_email,
|
272 |
+
"edited_user_login" => $user->user_login,
|
273 |
+
"server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null,
|
274 |
+
);
|
275 |
+
|
276 |
+
if ($password_changed) {
|
277 |
+
$context["edited_user_password_changed"] = "1";
|
278 |
+
}
|
279 |
+
|
280 |
+
if ($role_changed) {
|
281 |
+
$context["user_prev_role"] = $old_role;
|
282 |
+
$context["user_new_role"] = $new_role;
|
283 |
+
}
|
284 |
+
|
285 |
+
// Add diff to context
|
286 |
+
if ($user_data_diff) {
|
287 |
+
foreach ($user_data_diff as $one_diff_key => $one_diff_vals) {
|
288 |
+
/*
|
289 |
+
One diff looks like:
|
290 |
+
"nickname": {
|
291 |
+
"old": "MyOldNick",
|
292 |
+
"new": "MyNewNick"
|
293 |
+
}
|
294 |
+
*/
|
295 |
+
$context["user_prev_{$one_diff_key}"] = $one_diff_vals["old"];
|
296 |
+
$context["user_new_{$one_diff_key}"] = $one_diff_vals["new"];
|
297 |
+
}
|
298 |
+
}
|
299 |
+
|
300 |
+
|
301 |
+
$this->infoMessage("user_updated_profile", $context);
|
302 |
+
|
303 |
+
return $meta;
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
*
|
308 |
+
* user requests a reset password link
|
309 |
+
*
|
310 |
+
*/
|
311 |
+
public function onRetrievePasswordMessage($message, $key, $user_login, $user_data)
|
312 |
+
{
|
313 |
+
|
314 |
+
if (isset($_GET["action"]) && ("lostpassword" == $_GET["action"])) {
|
315 |
+
$context = array(
|
316 |
+
"_initiator" => SimpleLoggerLogInitiators::WEB_USER,
|
317 |
+
"message" => $message,
|
318 |
+
"key" => $key,
|
319 |
+
"user_login" => $user_login,
|
320 |
+
);
|
321 |
+
|
322 |
+
if (is_a($user_data, "WP_User")) {
|
323 |
+
$context["user_email"] = $user_data->user_email;
|
324 |
+
}
|
325 |
+
|
326 |
+
$this->noticeMessage("user_requested_password_reset_link", $context);
|
327 |
+
}
|
328 |
+
|
329 |
+
return $message;
|
330 |
+
}
|
331 |
+
|
332 |
+
/**
|
333 |
+
* Fired before the password reset procedure is validated.
|
334 |
+
*
|
335 |
+
* @param object $errors WP Error object.
|
336 |
+
* @param WP_User|WP_Error $user WP_User object if the login and reset key match. WP_Error object otherwise.
|
337 |
+
*/
|
338 |
+
public function onValidatePasswordReset($errors, $user)
|
339 |
+
{
|
340 |
+
|
341 |
+
/*
|
342 |
+
User visits the forgot password screen
|
343 |
+
$errors object are empty
|
344 |
+
$user contains a user
|
345 |
+
$_post is empty
|
346 |
+
|
347 |
+
User resets password
|
348 |
+
$errors empty
|
349 |
+
$user user object
|
350 |
+
$_post
|
351 |
+
|
352 |
+
*/
|
353 |
+
|
354 |
+
$context = array();
|
355 |
+
|
356 |
+
if (is_a($user, "WP_User")) {
|
357 |
+
$context["_initiator"] = SimpleLoggerLogInitiators::WP_USER;
|
358 |
+
$context["_user_id"] = $user->ID;
|
359 |
+
$context["_user_login"] = $user->user_login;
|
360 |
+
$context["_user_email"] = $user->user_email;
|
361 |
+
}
|
362 |
+
|
363 |
+
if (isset($_POST['pass1']) && $_POST['pass1'] != $_POST['pass2']) {
|
364 |
+
// $errors->add( 'password_reset_mismatch', __( 'The passwords do not match.' ) );
|
365 |
+
// user failed to reset password
|
366 |
+
}
|
367 |
+
|
368 |
+
|
369 |
+
if ((! $errors->get_error_code()) && isset($_POST['pass1']) && !empty($_POST['pass1'])) {
|
370 |
+
// login_header( __( 'Password Reset' ), '<p class="message reset-pass">'
|
371 |
+
// . __( 'Your password has been reset.' ) . ' <a href="' . esc_url(
|
372 |
+
$this->infoMessage("user_password_reseted", $context);
|
373 |
+
}
|
374 |
+
}
|
375 |
+
|
376 |
+
/**
|
377 |
+
* Called when user dessions are destroyed from admin
|
378 |
+
* Can be called for current logged in user = destroy all other sessions
|
379 |
+
* or for another user = destroy alla sessions for that user
|
380 |
+
* Fires from AJAX call
|
381 |
+
*
|
382 |
+
* @since 2.0.6
|
383 |
+
*/
|
384 |
+
public function onDestroyUserSession()
|
385 |
+
{
|
386 |
+
|
387 |
+
/*
|
388 |
+
Post params:
|
389 |
+
nonce: a14df12195
|
390 |
+
user_id: 1
|
391 |
+
action: destroy-sessions
|
392 |
+
*/
|
393 |
+
|
394 |
+
$user = get_userdata((int) $_POST['user_id']);
|
395 |
+
|
396 |
+
if ($user) {
|
397 |
+
if (!current_user_can('edit_user', $user->ID)) {
|
398 |
+
$user = false;
|
399 |
+
} elseif (!wp_verify_nonce($_POST['nonce'], 'update-user_' . $user->ID)) {
|
400 |
+
$user = false;
|
401 |
+
}
|
402 |
+
}
|
403 |
+
|
404 |
+
if (!$user) {
|
405 |
+
// Could not log out user sessions. Please try again.
|
406 |
+
return;
|
407 |
+
}
|
408 |
+
|
409 |
+
$sessions = WP_Session_Tokens::get_instance($user->ID);
|
410 |
+
|
411 |
+
$context = array();
|
412 |
+
|
413 |
+
if ($user->ID === get_current_user_id()) {
|
414 |
+
$this->infoMessage("user_session_destroy_others");
|
415 |
+
} else {
|
416 |
+
$context["user_id"] = $user->ID;
|
417 |
+
$context["user_login"] = $user->user_login;
|
418 |
+
$context["user_display_name"] = $user->display_name;
|
419 |
+
|
420 |
+
$this->infoMessage("user_session_destroy_everywhere", $context);
|
421 |
+
}
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Fires before a user is deleted from the database.
|
426 |
+
*
|
427 |
+
* @param int $user_id ID of the deleted user.
|
428 |
+
* @param int|null $reassign ID of the user to reassign posts and links to.
|
429 |
+
* Default null, for no reassignment.
|
430 |
+
*/
|
431 |
+
public function onDeleteUser($user_id, $reassign)
|
432 |
+
{
|
433 |
+
|
434 |
+
$wp_user_to_delete = get_userdata($user_id);
|
435 |
+
|
436 |
+
// wp_user->roles (array) - the roles the user is part of.
|
437 |
+
$role = null;
|
438 |
+
if (is_array($wp_user_to_delete->roles) && !empty($wp_user_to_delete->roles[0])) {
|
439 |
+
$role = $wp_user_to_delete->roles[0];
|
440 |
+
}
|
441 |
+
|
442 |
+
$context = array(
|
443 |
+
"deleted_user_id" => $wp_user_to_delete->ID,
|
444 |
+
"deleted_user_email" => $wp_user_to_delete->user_email,
|
445 |
+
"deleted_user_login" => $wp_user_to_delete->user_login,
|
446 |
+
"deleted_user_role" => $role,
|
447 |
+
"reassign_user_id" => $reassign,
|
448 |
+
"server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null
|
449 |
+
);
|
450 |
+
|
451 |
+
// Let's log this as a little bit more significant that just "message"
|
452 |
+
$this->noticeMessage("user_deleted", $context);
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* Modify plain text row output
|
457 |
+
* - adds link to user profil
|
458 |
+
* - change to "your profile" if you're looking at your own edit
|
459 |
+
*/
|
460 |
+
public function getLogRowPlainTextOutput($row)
|
461 |
+
{
|
462 |
+
|
463 |
+
$context = $row->context;
|
464 |
+
|
465 |
+
$output = parent::getLogRowPlainTextOutput($row);
|
466 |
+
$current_user_id = get_current_user_id();
|
467 |
+
|
468 |
+
if ("user_updated_profile" == $context["_message_key"]) {
|
469 |
+
$wp_user = get_user_by("id", $context["edited_user_id"]);
|
470 |
+
|
471 |
+
// If edited_user_id and _user_id is the same then a user edited their own profile
|
472 |
+
// Note: it's not the same thing as the currently logged in user (but.. it can be!)
|
473 |
+
if (! empty($context["_user_id"]) && $context["edited_user_id"] === $context["_user_id"]) {
|
474 |
+
if ($wp_user) {
|
475 |
+
$context["edit_profile_link"] = get_edit_user_link($wp_user->ID);
|
476 |
+
|
477 |
+
$use_you = apply_filters("simple_history/user_logger/plain_text_output_use_you", true);
|
478 |
+
|
479 |
+
//error_log( serialize($current_user_id) ); // int 1
|
480 |
+
//error_log( serialize($context["_user_id"]) ); // string 1
|
481 |
+
|
482 |
+
// User still exist, so link to their profile
|
483 |
+
if ((int) $current_user_id === (int) $context["_user_id"] && $use_you) {
|
484 |
+
// User that is viewing the log is the same as the edited user
|
485 |
+
$msg = __('Edited <a href="{edit_profile_link}">your profile</a>', "simple-history");
|
486 |
+
} else {
|
487 |
+
$msg = __('Edited <a href="{edit_profile_link}">their profile</a>', "simple-history");
|
488 |
+
}
|
489 |
+
|
490 |
+
$output = $this->interpolate($msg, $context, $row);
|
491 |
+
} else {
|
492 |
+
// User does not exist any longer
|
493 |
+
$output = __("Edited your profile", "simple-history");
|
494 |
+
}
|
495 |
+
} else {
|
496 |
+
// User edited another users profile
|
497 |
+
if ($wp_user) {
|
498 |
+
// Edited user still exist, so link to their profile
|
499 |
+
$context["edit_profile_link"] = get_edit_user_link($wp_user->ID);
|
500 |
+
$msg = __('Edited the profile for user <a href="{edit_profile_link}">{edited_user_login} ({edited_user_email})</a>', "simple-history");
|
501 |
+
$output = $this->interpolate($msg, $context, $row);
|
502 |
+
} else {
|
503 |
+
// Edited user does not exist any longer
|
504 |
+
}
|
505 |
+
}
|
506 |
+
// if user_updated_profile
|
507 |
+
} elseif ("user_created" == $context["_message_key"]) {
|
508 |
+
// A user was created. Create link of username that goes to user profile.
|
509 |
+
$wp_user = get_user_by("id", $context["created_user_id"]);
|
510 |
+
|
511 |
+
// If edited_user_id and _user_id is the same then a user edited their own profile
|
512 |
+
// Note: it's not the same thing as the currently logged in user (but.. it can be!)
|
513 |
+
|
514 |
+
if ($wp_user) {
|
515 |
+
$context["edit_profile_link"] = get_edit_user_link($wp_user->ID);
|
516 |
+
|
517 |
+
// User that is viewing the log is the same as the edited user
|
518 |
+
$msg = __(
|
519 |
+
'Created user <a href="{edit_profile_link}">{created_user_login} ({created_user_email})</a> with role {created_user_role}',
|
520 |
+
"simple-history"
|
521 |
+
);
|
522 |
+
|
523 |
+
$output = $this->interpolate(
|
524 |
+
$msg,
|
525 |
+
$context,
|
526 |
+
$row
|
527 |
+
);
|
528 |
+
} else {
|
529 |
+
// User does not exist any longer, keep original message
|
530 |
+
}
|
531 |
+
}
|
532 |
+
|
533 |
+
return $output;
|
534 |
+
}
|
535 |
+
|
536 |
+
/**
|
537 |
+
* User logs in
|
538 |
+
*
|
539 |
+
* @param string $user_login
|
540 |
+
* @param object $user
|
541 |
+
*/
|
542 |
+
public function onWpLogin($user_login = null, $user = null)
|
543 |
+
{
|
544 |
+
|
545 |
+
$context = array(
|
546 |
+
"user_login" => $user_login
|
547 |
+
);
|
548 |
+
|
549 |
+
if (isset($user_login)) {
|
550 |
+
$user_obj = get_user_by("login", $user_login);
|
551 |
+
} elseif (isset($user) && isset($user->ID)) {
|
552 |
+
$user_obj = get_user_by("id", $user->ID);
|
553 |
+
}
|
554 |
+
|
555 |
+
if (is_a($user_obj, "WP_User")) {
|
556 |
+
$context = array(
|
557 |
+
"user_id" => $user_obj->ID,
|
558 |
+
"user_email" => $user_obj->user_email,
|
559 |
+
"user_login" => $user_obj->user_login,
|
560 |
+
);
|
561 |
+
|
562 |
+
// Override some data that is usually set automagically by Simple History
|
563 |
+
// Because wp_get_current_user() does not return any data yet at this point
|
564 |
+
$context["_initiator"] = SimpleLoggerLogInitiators::WP_USER;
|
565 |
+
$context["_user_id"] = $user_obj->ID;
|
566 |
+
$context["_user_login"] = $user_obj->user_login;
|
567 |
+
$context["_user_email"] = $user_obj->user_email;
|
568 |
+
$context["server_http_user_agent"] = isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null;
|
569 |
+
|
570 |
+
$this->infoMessage("user_logged_in", $context);
|
571 |
+
} else {
|
572 |
+
// Could not get any info about the user logging in
|
573 |
+
$this->warningMessage("user_unknown_logged_in", $context);
|
574 |
+
}
|
575 |
+
}
|
576 |
+
|
577 |
+
/**
|
578 |
+
* User logs out
|
579 |
+
* http://codex.wordpress.org/Plugin_API/Action_Reference/wp_logout
|
580 |
+
*/
|
581 |
+
public function onWpLogout()
|
582 |
+
{
|
583 |
+
$this->infoMessage("user_logged_out");
|
584 |
+
}
|
585 |
+
|
586 |
+
/**
|
587 |
+
* User is edited
|
588 |
+
*
|
589 |
+
* Called immediately after an existing user is updated.
|
590 |
+
* @param int $user_id User ID.
|
591 |
+
* @param object $old_user_data Object containing user's data prior to update.
|
592 |
+
*/
|
593 |
+
// public function on_profile_update($user_id, $old_user_data) {
|
594 |
+
/*
|
595 |
+
if (!$user_id || !is_numeric($user_id)) {
|
596 |
+
return;
|
597 |
+
}
|
598 |
+
|
599 |
+
$wp_user_edited = get_userdata($user_id);
|
600 |
+
|
601 |
+
$context = array(
|
602 |
+
"edited_user_id" => $wp_user_edited->ID,
|
603 |
+
"edited_user_email" => $wp_user_edited->user_email,
|
604 |
+
"edited_user_login" => $wp_user_edited->user_login,
|
605 |
+
"server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"] ) ? $_SERVER["HTTP_USER_AGENT"] : null,
|
606 |
+
"old_user_data" => $old_user_data
|
607 |
+
);
|
608 |
+
|
609 |
+
|
610 |
+
$this->infoMessage("user_updated_profile", $context);
|
611 |
+
*/
|
612 |
+
// }
|
613 |
+
|
614 |
+
/**
|
615 |
+
* User is created
|
616 |
+
*
|
617 |
+
* "This action hook allows you to access data for a new user immediately after they are added to the database.
|
618 |
+
* The user id is passed to hook as an argument."
|
619 |
+
*
|
620 |
+
*/
|
621 |
+
public function onUserRegister($user_id)
|
622 |
+
{
|
623 |
+
|
624 |
+
if (! $user_id || ! is_numeric($user_id)) {
|
625 |
+
return;
|
626 |
+
}
|
627 |
+
|
628 |
+
$wp_user_added = get_userdata($user_id);
|
629 |
+
|
630 |
+
// wp_user->roles (array) - the roles the user is part of.
|
631 |
+
$role = null;
|
632 |
+
if (is_array($wp_user_added->roles) && ! empty($wp_user_added->roles[0])) {
|
633 |
+
$role = $wp_user_added->roles[0];
|
634 |
+
}
|
635 |
+
|
636 |
+
$send_user_notification = (int) (isset($_POST["send_user_notification"]) && $_POST["send_user_notification"] );
|
637 |
+
|
638 |
+
$context = array(
|
639 |
+
"created_user_id" => $wp_user_added->ID,
|
640 |
+
"created_user_email" => $wp_user_added->user_email,
|
641 |
+
"created_user_login" => $wp_user_added->user_login, // username
|
642 |
+
"created_user_role" => $role,
|
643 |
+
"created_user_first_name" => $wp_user_added->first_name,
|
644 |
+
"created_user_last_name" => $wp_user_added->last_name,
|
645 |
+
"created_user_url" => $wp_user_added->user_url,
|
646 |
+
"send_user_notification" => $send_user_notification,
|
647 |
+
"server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null
|
648 |
+
);
|
649 |
+
|
650 |
+
$this->infoMessage("user_created", $context);
|
651 |
+
}
|
652 |
+
|
653 |
+
/**
|
654 |
+
* Log failed login attempt to username that exists
|
655 |
+
*
|
656 |
+
* @param WP_User or WP_Error
|
657 |
+
* $user The WP_User() object of the user being edited,
|
658 |
+
* or a WP_Error() object if validation has already failed.
|
659 |
+
* @param string password used
|
660 |
+
*/
|
661 |
+
public function onWpAuthenticateUser($userOrError, $password)
|
662 |
+
{
|
663 |
+
|
664 |
+
// Only continue if $userOrError is a WP_user object
|
665 |
+
if (! is_a($userOrError, "WP_User")) {
|
666 |
+
return $userOrError;
|
667 |
+
}
|
668 |
+
|
669 |
+
// Only log failed attempts
|
670 |
+
if (! wp_check_password($password, $userOrError->user_pass, $userOrError->ID)) {
|
671 |
+
// Overwrite some vars that Simple History set automagically
|
672 |
+
$context = array(
|
673 |
+
"_initiator" => SimpleLoggerLogInitiators::WEB_USER,
|
674 |
+
"login_id" => $userOrError->ID,
|
675 |
+
"login_email" => $userOrError->user_email,
|
676 |
+
"login" => $userOrError->user_login,
|
677 |
+
"server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null,
|
678 |
+
"_occasionsID" => __CLASS__ . '/failed_user_login',
|
679 |
+
);
|
680 |
+
|
681 |
+
/**
|
682 |
+
* Maybe store password too
|
683 |
+
* Default is to not do this because of privacy and security
|
684 |
+
*
|
685 |
+
* @since 2.0
|
686 |
+
*
|
687 |
+
* @param bool $log_password
|
688 |
+
*/
|
689 |
+
$log_password = false;
|
690 |
+
$log_password = apply_filters("simple_history/comments_logger/log_failed_password", $log_password);
|
691 |
+
|
692 |
+
if ($log_password) {
|
693 |
+
$context["login_user_password"] = $password;
|
694 |
+
}
|
695 |
+
|
696 |
+
$this->warningMessage("user_login_failed", $context);
|
697 |
+
}
|
698 |
+
|
699 |
+
return $userOrError;
|
700 |
+
}
|
701 |
+
|
702 |
+
/**
|
703 |
+
* Attempt to login to user that does not exist
|
704 |
+
*
|
705 |
+
* @param $user (null or WP_User or WP_Error) (required)
|
706 |
+
* null indicates no process has authenticated the user yet.
|
707 |
+
* A WP_Error object indicates another process has failed the authentication.
|
708 |
+
* A WP_User object indicates another process has authenticated the user.
|
709 |
+
* @param $username The user's username. since 4.5.0 `$username` now accepts an email address.
|
710 |
+
* @param $password The user's password (encrypted)
|
711 |
+
*/
|
712 |
+
public function onAuthenticate($user, $username, $password)
|
713 |
+
{
|
714 |
+
|
715 |
+
// Don't log empty usernames
|
716 |
+
if (! trim($username)) {
|
717 |
+
return $user;
|
718 |
+
}
|
719 |
+
|
720 |
+
// If null then no auth done yet. Wierd. But what can we do.
|
721 |
+
if (is_null($user)) {
|
722 |
+
return $user;
|
723 |
+
}
|
724 |
+
|
725 |
+
// If auth ok then $user is a wp_user object
|
726 |
+
if (is_a($user, 'WP_User')) {
|
727 |
+
return $user;
|
728 |
+
}
|
729 |
+
|
730 |
+
// If user is a WP_Error object then auth failed
|
731 |
+
// Error codes can be:
|
732 |
+
// "incorrect_password" | "empty_password" | "invalid_email" | "invalid_username"
|
733 |
+
// We only act on invalid emails and invalid usernames
|
734 |
+
if (is_a($user, 'WP_Error') && ($user->get_error_code() == "invalid_username" || $user->get_error_code() == "invalid_email")) {
|
735 |
+
$context = array(
|
736 |
+
"_initiator" => SimpleLoggerLogInitiators::WEB_USER,
|
737 |
+
"failed_username" => $username,
|
738 |
+
"server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null,
|
739 |
+
// count all failed logins to unknown users as the same occasions,
|
740 |
+
// to prevent log being flooded with login/hack attempts
|
741 |
+
// "_occasionsID" => __CLASS__ . '/' . __FUNCTION__
|
742 |
+
// Use same occasionsID as for failed login attempts to existing users,
|
743 |
+
// because log can flood otherwise if hacker is rotating existing and non-existing usernames
|
744 |
+
//"_occasionsID" => __CLASS__ . '/' . __FUNCTION__ . "/failed_user_login/userid:{$user->ID}"
|
745 |
+
"_occasionsID" => __CLASS__ . '/failed_user_login',
|
746 |
+
);
|
747 |
+
|
748 |
+
/**
|
749 |
+
* Maybe store password too
|
750 |
+
* Default is to not do this because of privacy and security
|
751 |
+
*
|
752 |
+
* @since 2.0
|
753 |
+
*
|
754 |
+
* @param bool $log_password
|
755 |
+
*/
|
756 |
+
$log_password = false;
|
757 |
+
$log_password = apply_filters(
|
758 |
+
"simple_history/comments_logger/log_not_existing_user_password",
|
759 |
+
$log_password
|
760 |
+
);
|
761 |
+
if ($log_password) {
|
762 |
+
$context["failed_login_password"] = $password;
|
763 |
+
}
|
764 |
+
|
765 |
+
$this->warningMessage("user_unknown_login_failed", $context);
|
766 |
+
}
|
767 |
+
|
768 |
+
return $user;
|
769 |
+
}
|
770 |
+
|
771 |
+
/**
|
772 |
+
* Add diff to array if old and new values are different
|
773 |
+
*
|
774 |
+
* Since 2.0.29
|
775 |
+
*/
|
776 |
+
public function addDiff($post_data_diff, $key, $old_value, $new_value)
|
777 |
+
{
|
778 |
+
if ($old_value != $new_value) {
|
779 |
+
$post_data_diff[$key] = array(
|
780 |
+
"old" => $old_value,
|
781 |
+
"new" => $new_value
|
782 |
+
);
|
783 |
+
}
|
784 |
+
|
785 |
+
return $post_data_diff;
|
786 |
+
}
|
787 |
+
|
788 |
+
/**
|
789 |
+
* Return more info about an logged event
|
790 |
+
* Supports so far:
|
791 |
+
*/
|
792 |
+
public function getLogRowDetailsOutput($row)
|
793 |
+
{
|
794 |
+
$context = $row->context;
|
795 |
+
$message_key = $context["_message_key"];
|
796 |
+
|
797 |
+
$out = "";
|
798 |
+
$diff_table_output = "";
|
799 |
+
|
800 |
+
if ("user_updated_profile" == $message_key) {
|
801 |
+
// Find all user_prev_ and user_new_ values and show them
|
802 |
+
$arr_user_keys_to_show_diff_for = array(
|
803 |
+
"first_name" => array(
|
804 |
+
"title" => _x("First name", "User logger", "simple-history")
|
805 |
+
),
|
806 |
+
"last_name" => array(
|
807 |
+
"title" => _x("Last name", "User logger", "simple-history")
|
808 |
+
),
|
809 |
+
"nickname" => array(
|
810 |
+
"title" => _x("Nickname", "User logger", "simple-history")
|
811 |
+
),
|
812 |
+
"description" => array(
|
813 |
+
"title" => _x("Description", "User logger", "simple-history"),
|
814 |
+
),
|
815 |
+
"rich_editing" => array(
|
816 |
+
// Disable visual editor
|
817 |
+
"title" => _x("Visual editor", "User logger", "simple-history")
|
818 |
+
),
|
819 |
+
"comment_shortcuts" => array(
|
820 |
+
// Enable keyboard shortcuts for comment moderation
|
821 |
+
"title" => _x("Keyboard shortcuts", "User logger", "simple-history")
|
822 |
+
),
|
823 |
+
"show_admin_bar_front" => array(
|
824 |
+
// Show Toolbar when viewing site
|
825 |
+
"title" => _x("Show Toolbar", "User logger", "simple-history")
|
826 |
+
),
|
827 |
+
"admin_color" => array(
|
828 |
+
// Admin Colour Scheme
|
829 |
+
"title" => _x("Colour Scheme", "User logger", "simple-history")
|
830 |
+
),
|
831 |
+
"aim" => array(
|
832 |
+
"title" => _x("AIM", "User logger", "simple-history")
|
833 |
+
),
|
834 |
+
"yim" => array(
|
835 |
+
"title" => _x("Yahoo IM", "User logger", "simple-history")
|
836 |
+
),
|
837 |
+
"jabber" => array(
|
838 |
+
"title" => _x("Jabber / Google Talk ", "User logger", "simple-history")
|
839 |
+
),
|
840 |
+
/*"user_nicename" => array(
|
841 |
+
"title" => _x("Nicename", "User logger", "simple-history")
|
842 |
+
),*/
|
843 |
+
"user_email" => array(
|
844 |
+
"title" => _x("Email", "User logger", "simple-history")
|
845 |
+
),
|
846 |
+
"display_name" => array(
|
847 |
+
//"title" => _x("Display name publicly as", "User logger", "simple-history")
|
848 |
+
"title" => _x("Display name", "User logger", "simple-history")
|
849 |
+
),
|
850 |
+
"user_url" => array(
|
851 |
+
"title" => _x("Website", "User logger", "simple-history")
|
852 |
+
),
|
853 |
+
"role" => array(
|
854 |
+
//"title" => _x("Display name publicly as", "User logger", "simple-history")
|
855 |
+
"title" => _x("Role", "User logger", "simple-history")
|
856 |
+
)
|
857 |
+
);
|
858 |
+
|
859 |
+
foreach ($arr_user_keys_to_show_diff_for as $key => $val) {
|
860 |
+
if (isset($context["user_prev_{$key}"]) && isset($context["user_new_{$key}"])) {
|
861 |
+
$user_old_value = $context["user_prev_{$key}"];
|
862 |
+
$user_new_value = $context["user_new_{$key}"];
|
863 |
+
|
864 |
+
$diff_table_output .= sprintf(
|
865 |
+
'<tr>
|
866 |
+
<td>%1$s</td>
|
867 |
+
<td>%2$s</td>
|
868 |
+
</tr>',
|
869 |
+
$val["title"],
|
870 |
+
sprintf(
|
871 |
+
'<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins> <del class="SimpleHistoryLogitem__keyValueTable__removedThing">%2$s</del>',
|
872 |
+
esc_html($user_new_value), // 1
|
873 |
+
esc_html($user_old_value) // 2
|
874 |
+
)
|
875 |
+
);
|
876 |
+
}
|
877 |
+
}
|
878 |
+
|
879 |
+
// check if password was changed
|
880 |
+
if (isset($context["edited_user_password_changed"])) {
|
881 |
+
$diff_table_output .= sprintf(
|
882 |
+
'<tr>
|
883 |
+
<td>%1$s</td>
|
884 |
+
<td>%2$s</td>
|
885 |
+
</tr>',
|
886 |
+
_x("Password", "User logger", "simple-history"),
|
887 |
+
_x("Changed", "User logger", "simple-history")
|
888 |
+
);
|
889 |
+
}
|
890 |
+
|
891 |
+
if ($diff_table_output) {
|
892 |
+
$diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
|
893 |
+
}
|
894 |
+
|
895 |
+
$out .= $diff_table_output;
|
896 |
+
} elseif ("user_created" == $message_key) {
|
897 |
+
// Show fields for created users
|
898 |
+
$arr_user_keys_to_show_diff_for = array(
|
899 |
+
"created_user_first_name" => array(
|
900 |
+
"title" => _x("First name", "User logger", "simple-history")
|
901 |
+
),
|
902 |
+
"created_user_last_name" => array(
|
903 |
+
"title" => _x("Last name", "User logger", "simple-history")
|
904 |
+
),
|
905 |
+
"created_user_url" => array(
|
906 |
+
"title" => _x("Website", "User logger", "simple-history")
|
907 |
+
),
|
908 |
+
"send_user_notification" => array(
|
909 |
+
"title" => _x("User notification email sent", "User logger", "simple-history")
|
910 |
+
)
|
911 |
+
);
|
912 |
+
|
913 |
+
foreach ($arr_user_keys_to_show_diff_for as $key => $val) {
|
914 |
+
if (isset($context[$key]) && trim($context[$key])) {
|
915 |
+
if ("send_user_notification" == $key) {
|
916 |
+
if (intval($context[$key]) == 1) {
|
917 |
+
$sent_status = _x(
|
918 |
+
"Yes, email with account details was sent",
|
919 |
+
"User logger",
|
920 |
+
"simple-history"
|
921 |
+
);
|
922 |
+
} else {
|
923 |
+
// $sent_status =
|
924 |
+
// _x("No, no email with account details was sent", "User logger", "simple-history");
|
925 |
+
$sent_status = "";
|
926 |
+
}
|
927 |
+
|
928 |
+
if ($sent_status) {
|
929 |
+
$diff_table_output .= sprintf(
|
930 |
+
'<tr>
|
931 |
+
<td>%1$s</td>
|
932 |
+
<td>%2$s</td>
|
933 |
+
</tr>',
|
934 |
+
_x("Notification", "User logger", "simple-history"),
|
935 |
+
sprintf(
|
936 |
+
'<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>',
|
937 |
+
esc_html($sent_status) // 1
|
938 |
+
)
|
939 |
+
);
|
940 |
+
}
|
941 |
+
} else {
|
942 |
+
$diff_table_output .= sprintf(
|
943 |
+
'<tr>
|
944 |
+
<td>%1$s</td>
|
945 |
+
<td>%2$s</td>
|
946 |
+
</tr>',
|
947 |
+
$val["title"],
|
948 |
+
sprintf(
|
949 |
+
'<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>',
|
950 |
+
esc_html($context[$key]) // 1
|
951 |
+
)
|
952 |
+
);
|
953 |
+
}
|
954 |
+
}
|
955 |
+
}
|
956 |
+
|
957 |
+
if ($diff_table_output) {
|
958 |
+
$diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
|
959 |
+
}
|
960 |
+
|
961 |
+
$out .= $diff_table_output;
|
962 |
+
} // message key
|
963 |
+
|
964 |
+
return $out;
|
965 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
966 |
}
|
readme.txt
CHANGED
@@ -3,8 +3,8 @@ Contributors: eskapism
|
|
3 |
Donate link: http://eskapism.se/sida/donate/
|
4 |
Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, dashboard, admin, syslog, feed, activity, stream, audit trail, brute-force
|
5 |
Requires at least: 4.5.1
|
6 |
-
Tested up to: 4.
|
7 |
-
Stable tag: 2.
|
8 |
|
9 |
View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
|
10 |
|
@@ -60,6 +60,11 @@ Simple History logging login attempts, lockouts, and configuration changes made
|
|
60 |
The [redirection plugin](https://sv.wordpress.org/plugins/redirection/) manages url redirections, using a nice GUI.
|
61 |
Simple History will log redirects and groups that are created, changed, enabled or disabled and also when the global plugin settings have been modified.
|
62 |
|
|
|
|
|
|
|
|
|
|
|
63 |
#### RSS feed available
|
64 |
|
65 |
There is also a **RSS feed of changes** available, so you can keep track of the changes made via your favorite RSS reader on your phone, on your iPad, or on your computer.
|
@@ -157,6 +162,15 @@ A simple way to see any uncommon activity, for example an increased number of lo
|
|
157 |
|
158 |
## Changelog
|
159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
= 2.13 (November 2016) =
|
161 |
|
162 |
- Added filter `simple_history_log` that is a simplified way to add message to the log, without the need to check for the existance of Simple History or its SimpleLogger function. Use it like this: `apply_filters("simple_history_log", "This is a logged message");` See the [examples file](https://github.com/bonny/WordPress-Simple-History/blob/master/examples/examples.php) for more examples.
|
3 |
Donate link: http://eskapism.se/sida/donate/
|
4 |
Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, dashboard, admin, syslog, feed, activity, stream, audit trail, brute-force
|
5 |
Requires at least: 4.5.1
|
6 |
+
Tested up to: 4.7
|
7 |
+
Stable tag: 2.14
|
8 |
|
9 |
View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
|
10 |
|
60 |
The [redirection plugin](https://sv.wordpress.org/plugins/redirection/) manages url redirections, using a nice GUI.
|
61 |
Simple History will log redirects and groups that are created, changed, enabled or disabled and also when the global plugin settings have been modified.
|
62 |
|
63 |
+
**Duplicate Post**
|
64 |
+
Tjhe plugin [Duplicate Post](https://wordpress.org/plugins/duplicate-post/) allows users to
|
65 |
+
clone posts of any type.
|
66 |
+
Simple History will log when a clone of a post or page is done.
|
67 |
+
|
68 |
#### RSS feed available
|
69 |
|
70 |
There is also a **RSS feed of changes** available, so you can keep track of the changes made via your favorite RSS reader on your phone, on your iPad, or on your computer.
|
162 |
|
163 |
## Changelog
|
164 |
|
165 |
+
= 2.14 (April 2016) =
|
166 |
+
|
167 |
+
- Added support for plugin [Duplicate Post](https://wordpress.org/plugins/duplicate-post/).
|
168 |
+
Now when a user clones a post or page you will se this in the history log, with links to both the original post and the new copy.
|
169 |
+
- Removed log level info from title in RSS feed
|
170 |
+
- Make date dropdown less "jumpy" when loading page (due to select element switching to Select2)
|
171 |
+
- Only add filters for plugin Limit Login Attempts if plugin is active. This fixes problem with Limit Login Attempts Reloaded and possibly other forks of the plugin.
|
172 |
+
- Debug page now displays installed plugins.
|
173 |
+
|
174 |
= 2.13 (November 2016) =
|
175 |
|
176 |
- Added filter `simple_history_log` that is a simplified way to add message to the log, without the need to check for the existance of Simple History or its SimpleLogger function. Use it like this: `apply_filters("simple_history_log", "This is a logged message");` See the [examples file](https://github.com/bonny/WordPress-Simple-History/blob/master/examples/examples.php) for more examples.
|
templates/template-settings-tab-debug.php
CHANGED
@@ -1,6 +1,11 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
-
defined( 'ABSPATH' )
|
4 |
|
5 |
global $wpdb;
|
6 |
|
@@ -15,9 +20,9 @@ $period_end_date = DateTime::createFromFormat( 'U', time() );
|
|
15 |
* Size of database in both number or rows and table size
|
16 |
*/
|
17 |
|
18 |
-
echo
|
19 |
|
20 |
-
// Get table sizes in mb
|
21 |
$sql_table_size = sprintf( '
|
22 |
SELECT table_name AS "table_name",
|
23 |
round(((data_length + index_length) / 1024 / 1024), 2) "size_in_mb"
|
@@ -256,3 +261,42 @@ foreach ( $logger_rows_count as $one_logger_slug => $one_logger_val ) {
|
|
256 |
}
|
257 |
|
258 |
echo "</table>";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Undocumented class
|
4 |
+
*
|
5 |
+
* @package SimpleHistory
|
6 |
+
**/
|
7 |
|
8 |
+
defined( 'ABSPATH' ) || die();
|
9 |
|
10 |
global $wpdb;
|
11 |
|
20 |
* Size of database in both number or rows and table size
|
21 |
*/
|
22 |
|
23 |
+
echo '<h3>Database size</h3>';
|
24 |
|
25 |
+
// Get table sizes in mb.
|
26 |
$sql_table_size = sprintf( '
|
27 |
SELECT table_name AS "table_name",
|
28 |
round(((data_length + index_length) / 1024 / 1024), 2) "size_in_mb"
|
261 |
}
|
262 |
|
263 |
echo "</table>";
|
264 |
+
|
265 |
+
// List installed plugins
|
266 |
+
echo '<h2>Plugins</h2>';
|
267 |
+
echo '<p>As returned from <code>get_plugins()</code></p>';
|
268 |
+
|
269 |
+
$plugins = get_plugins();
|
270 |
+
|
271 |
+
echo "<table class='widefat'>";
|
272 |
+
printf(
|
273 |
+
'<thead>
|
274 |
+
<tr>
|
275 |
+
<th>%1$s</th>
|
276 |
+
<th>%2$s</th>
|
277 |
+
<th>%3$s</th>
|
278 |
+
</tr>
|
279 |
+
</thead>
|
280 |
+
',
|
281 |
+
_x("Plugin name", "debug dropin", "simple-history"),
|
282 |
+
_x("Plugin file path", "debug dropin", "simple-history"),
|
283 |
+
_x("Active", "debug dropin", "simple-history")
|
284 |
+
);
|
285 |
+
|
286 |
+
foreach ($plugins as $pluginFilePath => $onePlugin) {
|
287 |
+
$isPluginActive = is_plugin_active($pluginFilePath);
|
288 |
+
printf(
|
289 |
+
'
|
290 |
+
<tr>
|
291 |
+
<td><strong>%1$s</strong></td>
|
292 |
+
<td>%2$s</td>
|
293 |
+
<td>%3$s</td>
|
294 |
+
</tr>
|
295 |
+
',
|
296 |
+
esc_html($onePlugin["Name"]),
|
297 |
+
esc_html($pluginFilePath),
|
298 |
+
$isPluginActive ? "Yes" : "No" // 3
|
299 |
+
);
|
300 |
+
}
|
301 |
+
|
302 |
+
echo "</table>";
|