Version Description
(May 2018) =
- Added support for Advanced Custom Fields (ACF): when a ACF Field or ACF Field Group is created or modified or deleted you will now get more details in the activity feed.
- Changes to taxonomies/categories/tags now include a link to the modified term and to the category that the term belongs to.
- The post types in the
skip_posttypes
filter are now also applied to trashed and untrashed posts (not only post edits, as before). - Don't log Jetpack sitemap updates. (Don't log updates to posttypes
jp_sitemap
,jp_sitemap_master
andjp_img_sitemap
, i.e. the post types used by Jetpack's Sitemap function.) Should fix https://wordpress.org/support/topic/jetpack-sitemap-logging/. - Don't log the taxonomies
post_translations
orterm_translations
, that are used by Polylang to store translation mappings. That contained md5-hashed strings and was not of any benefit (a separate logger for Polylang will come soon anyway). - Fix notice in theme logger because did not check if
$_POST['sidebar']
was set. Fixes https://github.com/bonny/WordPress-Simple-History/issues/136. - Fix thumbnail title missing notice in post logger.
- Fix PHP warning when a plugin was checked by WordPress for an update, but your WordPress install did not have the plugin folder for that plugin.
- Fix unexpected single-quotations included in file name in Internet Explorer 11 (and possibly other versions) when exporting CSV/JSON file.
- Fix filter/search log by specific users not working. Fixes https://wordpress.org/support/topic/show-activity-from-other-authors-only/.
- Fix a notice in SimpleOptionsLogger.
- Better CSS styling on dashboard.
- Add filter
simple_history/post_logger/post_updated/context
that can be used to modify the context added by SimplePostLogger. - Add filter
simple_history/post_logger/post_updated/ok_to_log
that can be used to skip logging a post update. - Add filter
simple_history/categories_logger/skip_taxonomies
that can be used to modify what taxonomies to skip when logging updates to taxonomy terms.
Download this release
Release Info
Developer | eskapism |
Plugin | Simple History |
Version | 2.21 |
Comparing to | |
See all releases |
Code changes from version 2.20 to 2.21
- dropins/SimpleHistoryDonateDropin.php +3 -4
- dropins/SimpleHistoryExportDropin.php +21 -13
- dropins/SimpleHistoryFilterDropin.css +6 -4
- dropins/SimpleHistoryFilterDropin.js +266 -269
- dropins/SimpleHistoryPluginPatchesDropin.php +0 -7
- inc/SimpleHistory.php +17 -31
- inc/SimpleHistoryLogQuery.php +6 -2
- index.php +3 -3
- loggers/AvailableUpdatesLogger.php +13 -3
- loggers/FileEditsLogger.php +0 -3
- loggers/Plugin_ACF.php +1032 -0
- loggers/SimpleCategoriesLogger.php +129 -64
- loggers/SimpleLogger.php +74 -38
- loggers/SimplePluginLogger.php +148 -144
- loggers/SimplePostLogger.php +93 -30
- loggers/SimpleThemeLogger.php +11 -7
- loggers/SimpleUserLogger.php +0 -3
- readme.txt +21 -4
- templates/settings-style-example.php +16 -10
dropins/SimpleHistoryDonateDropin.php
CHANGED
@@ -35,7 +35,7 @@ class SimpleHistoryDonateDropin {
|
|
35 |
|
36 |
$links = array_merge(
|
37 |
$links,
|
38 |
-
array( sprintf( '<a href="
|
39 |
);
|
40 |
|
41 |
}
|
@@ -71,9 +71,8 @@ class SimpleHistoryDonateDropin {
|
|
71 |
function settings_section_output() {
|
72 |
|
73 |
printf(
|
74 |
-
__( 'If you find Simple History useful please <a href="%1$s">donate</a>.',
|
75 |
-
'
|
76 |
-
'http://www.amazon.co.uk/registry/wishlist/IAEZWNLQQICG'
|
77 |
);
|
78 |
|
79 |
}
|
35 |
|
36 |
$links = array_merge(
|
37 |
$links,
|
38 |
+
array( sprintf( '<a href="https://www.paypal.me/eskapism">%1$s</a>', __('Donate', "simple-history") ) )
|
39 |
);
|
40 |
|
41 |
}
|
71 |
function settings_section_output() {
|
72 |
|
73 |
printf(
|
74 |
+
__( 'If you find Simple History useful please <a href="%1$s">donate</a>.', "simple-history"),
|
75 |
+
'https://www.paypal.me/eskapism'
|
|
|
76 |
);
|
77 |
|
78 |
}
|
dropins/SimpleHistoryExportDropin.php
CHANGED
@@ -1,23 +1,30 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
Dropin Name: Export
|
5 |
-
Dropin Description: Adds a tab with export options
|
6 |
-
Dropin URI: http://simple-history.com/
|
7 |
-
Author: Pär Thernström
|
8 |
-
*/
|
9 |
-
|
10 |
class SimpleHistoryExportDropin {
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
13 |
private $sh;
|
14 |
|
|
|
|
|
|
|
|
|
|
|
15 |
public function __construct( $sh ) {
|
16 |
|
17 |
-
// Set simple history variable
|
18 |
$this->sh = $sh;
|
19 |
|
20 |
-
// Add tab to settings page
|
21 |
$sh->registerSettingsTab(array(
|
22 |
'slug' => 'export',
|
23 |
'name' => _x( 'Export', 'Export dropin: Tab name on settings page', 'simple-history' ),
|
@@ -64,18 +71,19 @@ class SimpleHistoryExportDropin {
|
|
64 |
|
65 |
$fp = fopen( 'php://output', 'w' );
|
66 |
|
67 |
-
|
|
|
68 |
if ( 'csv' == $export_format ) {
|
69 |
|
70 |
$filename = 'simple-history-export-' . time() . '.csv';
|
71 |
header( 'Content-Type: text/plain' );
|
72 |
-
header(
|
73 |
|
74 |
} elseif ( 'json' == $export_format ) {
|
75 |
|
76 |
$filename = 'simple-history-export-' . time() . '.json';
|
77 |
header( 'Content-Type: application/json' );
|
78 |
-
header(
|
79 |
|
80 |
} elseif ( 'html' == $export_format ) {
|
81 |
|
1 |
<?php
|
2 |
|
3 |
+
/**
|
4 |
+
* Dropin Name: Export
|
5 |
+
* Dropin Description: Adds a tab with export options
|
6 |
+
* Dropin URI: http://simple-history.com/
|
7 |
+
* Author: Pär Thernström
|
8 |
+
*/
|
|
|
9 |
class SimpleHistoryExportDropin {
|
10 |
|
11 |
+
/**
|
12 |
+
* Simple History instance.
|
13 |
+
*
|
14 |
+
* @var $sh
|
15 |
+
*/
|
16 |
private $sh;
|
17 |
|
18 |
+
/**
|
19 |
+
* Constructor.
|
20 |
+
*
|
21 |
+
* @param instance $sh Simple History instance.
|
22 |
+
*/
|
23 |
public function __construct( $sh ) {
|
24 |
|
|
|
25 |
$this->sh = $sh;
|
26 |
|
27 |
+
// Add tab to settings page.
|
28 |
$sh->registerSettingsTab(array(
|
29 |
'slug' => 'export',
|
30 |
'name' => _x( 'Export', 'Export dropin: Tab name on settings page', 'simple-history' ),
|
71 |
|
72 |
$fp = fopen( 'php://output', 'w' );
|
73 |
|
74 |
+
$attachment_header_template = 'Content-Disposition: attachment; filename="%1$s"';
|
75 |
+
|
76 |
if ( 'csv' == $export_format ) {
|
77 |
|
78 |
$filename = 'simple-history-export-' . time() . '.csv';
|
79 |
header( 'Content-Type: text/plain' );
|
80 |
+
header( sprintf( $attachment_header_template, $filename ) );
|
81 |
|
82 |
} elseif ( 'json' == $export_format ) {
|
83 |
|
84 |
$filename = 'simple-history-export-' . time() . '.json';
|
85 |
header( 'Content-Type: application/json' );
|
86 |
+
header( sprintf( $attachment_header_template, $filename ) );
|
87 |
|
88 |
} elseif ( 'html' == $export_format ) {
|
89 |
|
dropins/SimpleHistoryFilterDropin.css
CHANGED
@@ -62,12 +62,12 @@
|
|
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 |
}
|
@@ -83,6 +83,8 @@
|
|
83 |
margin-left: 0;
|
84 |
}
|
85 |
|
|
|
|
|
86 |
/**
|
87 |
* Search results in filter
|
88 |
*/
|
@@ -159,7 +161,6 @@
|
|
159 |
visibility: hidden;
|
160 |
opacity: 0;
|
161 |
margin-left: 155px;
|
162 |
-
margin-top: 1em;
|
163 |
max-height: 0;
|
164 |
overflow: hidden;
|
165 |
transition: max-height .25s ease-in-out, opacity .25s ease-in-out, visibility 0s 1s;
|
@@ -169,6 +170,7 @@
|
|
169 |
visibility: visible;
|
170 |
opacity: 1;
|
171 |
max-height: 150px;
|
|
|
172 |
transition: max-height .25s ease-in-out, opacity .25s ease-in-out, visibility 0s 0s;
|
173 |
}
|
174 |
|
@@ -196,4 +198,4 @@
|
|
196 |
|
197 |
.SimpleHistory__filters .select2-results__option {
|
198 |
margin: 0;
|
199 |
-
}
|
62 |
|
63 |
@media (min-width: 600px) {
|
64 |
/* prevent "jump" during page load because of select elm changing to select2 */
|
65 |
+
.SimpleHistoryWrap .SimpleHistory__filters__filterRow {
|
66 |
height: 41px;
|
67 |
line-height: 41px;
|
68 |
}
|
69 |
|
70 |
+
.SimpleHistoryWrap .wp-admin select[multiple].SimpleHistory__filters__filter--date {
|
71 |
height: 2.25em;
|
72 |
overflow: hidden;
|
73 |
}
|
83 |
margin-left: 0;
|
84 |
}
|
85 |
|
86 |
+
|
87 |
+
|
88 |
/**
|
89 |
* Search results in filter
|
90 |
*/
|
161 |
visibility: hidden;
|
162 |
opacity: 0;
|
163 |
margin-left: 155px;
|
|
|
164 |
max-height: 0;
|
165 |
overflow: hidden;
|
166 |
transition: max-height .25s ease-in-out, opacity .25s ease-in-out, visibility 0s 1s;
|
170 |
visibility: visible;
|
171 |
opacity: 1;
|
172 |
max-height: 150px;
|
173 |
+
margin-top: 1em;
|
174 |
transition: max-height .25s ease-in-out, opacity .25s ease-in-out, visibility 0s 0s;
|
175 |
}
|
176 |
|
198 |
|
199 |
.SimpleHistory__filters .select2-results__option {
|
200 |
margin: 0;
|
201 |
+
}
|
dropins/SimpleHistoryFilterDropin.js
CHANGED
@@ -2,272 +2,269 @@
|
|
2 |
*
|
3 |
*/
|
4 |
|
5 |
-
var SimpleHistoryFilterDropin = (function($) {
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
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 |
-
SimpleHistoryFilterDropin.
|
270 |
-
|
271 |
-
jQuery(document).ready(function() {
|
272 |
-
SimpleHistoryFilterDropin.onDomReadyInit();
|
273 |
-
});
|
2 |
*
|
3 |
*/
|
4 |
|
5 |
+
var SimpleHistoryFilterDropin = (function ($) {
|
6 |
+
var $elms = {}
|
7 |
+
var isFilteringActive = false
|
8 |
+
var activeFilters = {}
|
9 |
+
|
10 |
+
function init () {
|
11 |
+
addElements()
|
12 |
+
addFetchListener()
|
13 |
+
}
|
14 |
+
|
15 |
+
function onDomReadyInit () {
|
16 |
+
enhanceSelects()
|
17 |
+
addListeners()
|
18 |
+
}
|
19 |
+
|
20 |
+
function addElements () {
|
21 |
+
$elms.filter_container = $('.SimpleHistory__filters')
|
22 |
+
$elms.filter_user = $elms.filter_container.find(
|
23 |
+
'.SimpleHistory__filters__filter--user'
|
24 |
+
)
|
25 |
+
$elms.filter_button = $elms.filter_container.find(
|
26 |
+
'.js-SimpleHistoryFilterDropin-doFilter'
|
27 |
+
)
|
28 |
+
$elms.filter_form = $elms.filter_container.find(
|
29 |
+
'.js-SimpleHistory__filters__form'
|
30 |
+
)
|
31 |
+
$elms.show_more_filters_button = $elms.filter_container.find(
|
32 |
+
'.js-SimpleHistoryFilterDropin-showMoreFilters'
|
33 |
+
)
|
34 |
+
$elms.more_filters_container = $elms.filter_container.find(
|
35 |
+
'.js-SimpleHistory__filters__moreFilters'
|
36 |
+
)
|
37 |
+
}
|
38 |
+
|
39 |
+
function addListeners () {
|
40 |
+
$elms.filter_form.on('submit', onSubmitForm)
|
41 |
+
$elms.show_more_filters_button.on('click', onClickMoreFilters)
|
42 |
+
}
|
43 |
+
|
44 |
+
function onClickMoreFilters () {
|
45 |
+
// $elms.more_filters_container.toggleClass("is-visible");
|
46 |
+
$elms.filter_container.toggleClass('is-showingMoreFilters')
|
47 |
+
}
|
48 |
+
|
49 |
+
function updateFilters () {
|
50 |
+
// form serialize
|
51 |
+
// search=apa&loglevels=critical&loglevels=alert&loggers=SimpleMediaLogger&loggers=SimpleMenuLogger&user=1&dates=2014-09 SimpleHistoryFilterDropin.js?ver=2.0:40
|
52 |
+
var $search = $elms.filter_form.find("[name='search']")
|
53 |
+
var $loglevels = $elms.filter_form.find("[name='loglevels']")
|
54 |
+
var $messages = $elms.filter_form.find("[name='messages']")
|
55 |
+
var $users = $elms.filter_form.find("[name='users']")
|
56 |
+
var $dates = $elms.filter_form.find("[name='dates']")
|
57 |
+
|
58 |
+
// Custom date range
|
59 |
+
var $customDateRangeFromMM = $elms.filter_form.find("[name='from_mm']")
|
60 |
+
var $customDateRangeFromJJ = $elms.filter_form.find("[name='from_jj']")
|
61 |
+
var $customDateRangeFromAA = $elms.filter_form.find("[name='from_aa']")
|
62 |
+
var $customDateRangeToMM = $elms.filter_form.find("[name='to_mm']")
|
63 |
+
var $customDateRangeToJJ = $elms.filter_form.find("[name='to_jj']")
|
64 |
+
var $customDateRangeToAA = $elms.filter_form.find("[name='to_aa']")
|
65 |
+
|
66 |
+
// If any of our search boxes are filled in we consider ourself to be in search mode
|
67 |
+
isFilteringActive = false
|
68 |
+
activeFilters = {}
|
69 |
+
|
70 |
+
if ($.trim($search.val())) {
|
71 |
+
isFilteringActive = true
|
72 |
+
activeFilters.search = $search.val()
|
73 |
+
}
|
74 |
+
|
75 |
+
if ($loglevels.val() && $loglevels.val().length) {
|
76 |
+
isFilteringActive = true
|
77 |
+
activeFilters.loglevels = $loglevels.val()
|
78 |
+
}
|
79 |
+
|
80 |
+
if ($messages.val() && $messages.val().length) {
|
81 |
+
isFilteringActive = true
|
82 |
+
activeFilters.messages = $messages.val()
|
83 |
+
}
|
84 |
+
|
85 |
+
if ($.trim($users.val())) {
|
86 |
+
isFilteringActive = true
|
87 |
+
activeFilters.users = $users.val()
|
88 |
+
}
|
89 |
+
|
90 |
+
// Something is selected in the Dates dropdown
|
91 |
+
if ($dates.val() && $dates.val().length) {
|
92 |
+
isFilteringActive = true
|
93 |
+
|
94 |
+
// if dates val is selected but is "customRange" then dates is not active, but dateRange is
|
95 |
+
if ($dates.val() == 'customRange') {
|
96 |
+
activeFilters.date_from =
|
97 |
+
$customDateRangeFromAA.val() +
|
98 |
+
'-' +
|
99 |
+
$customDateRangeFromMM.val() +
|
100 |
+
'-' +
|
101 |
+
$customDateRangeFromJJ.val() +
|
102 |
+
' 00:00:00'
|
103 |
+
activeFilters.date_to =
|
104 |
+
$customDateRangeToAA.val() +
|
105 |
+
'-' +
|
106 |
+
$customDateRangeToMM.val() +
|
107 |
+
'-' +
|
108 |
+
$customDateRangeToJJ.val() +
|
109 |
+
' 23:59:59'
|
110 |
+
} else {
|
111 |
+
activeFilters.dates = $dates.val()
|
112 |
+
}
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
function onSubmitForm (e) {
|
117 |
+
e.preventDefault()
|
118 |
+
|
119 |
+
// updateFilters();
|
120 |
+
|
121 |
+
// Reload the log rows collection
|
122 |
+
simple_history.logRowsCollection.reload()
|
123 |
+
}
|
124 |
+
|
125 |
+
function addFetchListener () {
|
126 |
+
$(document).on('SimpleHistory:mainViewInitBeforeLoadRows', function () {
|
127 |
+
// Modify query string parameters before the log rows collection fetches/syncs
|
128 |
+
simple_history.logRowsCollection.on('before_fetch', modifyFetchData)
|
129 |
+
})
|
130 |
+
|
131 |
+
// Alter api args used by new log rows notifier
|
132 |
+
$(document).on(
|
133 |
+
'SimpleHistory:NewRowsNotifier:apiArgs',
|
134 |
+
modifyNewRowsNotifierApiArgs
|
135 |
+
)
|
136 |
+
}
|
137 |
+
|
138 |
+
function modifyNewRowsNotifierApiArgs (e, apiArgs) {
|
139 |
+
if (isFilteringActive) {
|
140 |
+
apiArgs = _.extend(apiArgs, activeFilters)
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
// called each time the log is reloaded
|
145 |
+
function modifyFetchData (collection, url_data) {
|
146 |
+
updateFilters()
|
147 |
+
|
148 |
+
if (isFilteringActive) {
|
149 |
+
url_data = _.extend(url_data, activeFilters)
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
function enhanceSelects () {
|
154 |
+
$elms.filter_user.select2({
|
155 |
+
minimumInputLength: 2,
|
156 |
+
allowClear: true,
|
157 |
+
placeholder: 'All users',
|
158 |
+
ajax: {
|
159 |
+
url: ajaxurl,
|
160 |
+
dataType: 'json',
|
161 |
+
cache: true,
|
162 |
+
data: function (term, page) {
|
163 |
+
return {
|
164 |
+
q: term.term, // search term
|
165 |
+
page_limit: 10,
|
166 |
+
action: 'simple_history_filters_search_user'
|
167 |
+
}
|
168 |
+
},
|
169 |
+
// parse the results into the format expected by Select2.
|
170 |
+
processResults: function (data, page) {
|
171 |
+
// since we are using custom formatting functions we do not need to alter remote JSON data
|
172 |
+
return data.data
|
173 |
+
}
|
174 |
+
},
|
175 |
+
templateResult: formatUsers,
|
176 |
+
initSelection: function (elm, callback) {
|
177 |
+
// called on init if value attribute on input is set
|
178 |
+
var $elm = $(elm)
|
179 |
+
var value = $elm.val()
|
180 |
+
var default_user_data = $elms.filter_user.data('default-user-data')
|
181 |
+
|
182 |
+
callback(default_user_data)
|
183 |
+
},
|
184 |
+
templateSelection: formatUsers,
|
185 |
+
escapeMarkup: function (m) {
|
186 |
+
return m
|
187 |
+
},
|
188 |
+
multiple: true
|
189 |
+
})
|
190 |
+
|
191 |
+
$('.SimpleHistory__filters__filter--logger').select2()
|
192 |
+
|
193 |
+
var $filterDate = $('.SimpleHistory__filters__filter--date')
|
194 |
+
$filterDate.select2()
|
195 |
+
$filterDate.on('select2-selecting change', onDatesFilterSelect)
|
196 |
+
|
197 |
+
$('.SimpleHistory__filters__filter--loglevel').select2({
|
198 |
+
templateResult: formatLoglevel,
|
199 |
+
templateSelection: formatLoglevel,
|
200 |
+
escapeMarkup: function (m) {
|
201 |
+
return m
|
202 |
+
}
|
203 |
+
})
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Fired when something is selected in the date filter
|
208 |
+
* When "Custom range..." is selected then we show the "from" .. "to" date fields
|
209 |
+
*/
|
210 |
+
function onDatesFilterSelect (e, elm) {
|
211 |
+
var $filterDate = $('select.SimpleHistory__filters__filter--date')
|
212 |
+
var val = $filterDate.val()
|
213 |
+
|
214 |
+
if (val === 'customRange') {
|
215 |
+
// show custom date fields
|
216 |
+
$elms.filter_container.addClass('is-customDateFilterActive')
|
217 |
+
} else {
|
218 |
+
// hide custom date fields
|
219 |
+
$elms.filter_container.removeClass('is-customDateFilterActive')
|
220 |
+
}
|
221 |
+
}
|
222 |
+
|
223 |
+
function formatUsers (userdata) {
|
224 |
+
if (userdata.loading) {
|
225 |
+
return userdata.text
|
226 |
+
}
|
227 |
+
|
228 |
+
var html = ''
|
229 |
+
|
230 |
+
html += "<div class='SimpleHistory__filters__userfilter__gravatar'>"
|
231 |
+
html += userdata.gravatar
|
232 |
+
html += '</div>'
|
233 |
+
html += "<div class='SimpleHistory__filters__userfilter__primary'>"
|
234 |
+
html += userdata.user_email
|
235 |
+
html += '</div>'
|
236 |
+
html += "<div class='SimpleHistory__filters__userfilter__secondary'>"
|
237 |
+
html += userdata.user_login
|
238 |
+
html += '</div>'
|
239 |
+
|
240 |
+
return html
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Used by templateResult and templateSelection
|
245 |
+
*/
|
246 |
+
function formatLoglevel (loglevel) {
|
247 |
+
var originalOption = loglevel.element
|
248 |
+
var $originalOption = $(originalOption)
|
249 |
+
var color = $originalOption.data('color')
|
250 |
+
|
251 |
+
var html =
|
252 |
+
'<span style="border-radius: 50%; border: 1px solid rgba(0,0,0,.1); margin-right: 5px; width: .75em; height: .75em; line-height: 1; display: inline-block; background-color: ' +
|
253 |
+
$originalOption.data('color') +
|
254 |
+
"; '\"></span>" +
|
255 |
+
loglevel.text
|
256 |
+
return html
|
257 |
+
}
|
258 |
+
|
259 |
+
return {
|
260 |
+
init: init,
|
261 |
+
onDomReadyInit: onDomReadyInit,
|
262 |
+
$elms: $elms
|
263 |
+
}
|
264 |
+
})(jQuery)
|
265 |
+
|
266 |
+
SimpleHistoryFilterDropin.init()
|
267 |
+
|
268 |
+
jQuery(document).ready(function () {
|
269 |
+
SimpleHistoryFilterDropin.onDomReadyInit()
|
270 |
+
})
|
|
|
|
|
|
dropins/SimpleHistoryPluginPatchesDropin.php
CHANGED
@@ -52,7 +52,6 @@ class SimpleHistoryPluginPatchesDropin {
|
|
52 |
}
|
53 |
|
54 |
// ok, this is a non-admin, cron-running post update for the ai1ec_event post type, so cancel the logging
|
55 |
-
error_log( 'ok, cancel ai1ec_event log' );
|
56 |
$doLog = false;
|
57 |
|
58 |
return $doLog;
|
@@ -108,15 +107,9 @@ class SimpleHistoryPluginPatchesDropin {
|
|
108 |
}
|
109 |
|
110 |
// There. All checked. Now cancel the logging.
|
111 |
-
error_log( 'ok, cancel nextgen gallery log' );
|
112 |
$doLog = false;
|
113 |
|
114 |
-
// error_log(simpleHistory::json_encode( $context ));
|
115 |
-
// error_log(simpleHistory::json_encode( $loggerInstance ));
|
116 |
-
// error_log(simpleHistory::json_encode( is_admin() ));
|
117 |
-
// error_log( __METHOD__ . " canceled logging" );
|
118 |
return $doLog;
|
119 |
-
|
120 |
}
|
121 |
|
122 |
|
52 |
}
|
53 |
|
54 |
// ok, this is a non-admin, cron-running post update for the ai1ec_event post type, so cancel the logging
|
|
|
55 |
$doLog = false;
|
56 |
|
57 |
return $doLog;
|
107 |
}
|
108 |
|
109 |
// There. All checked. Now cancel the logging.
|
|
|
110 |
$doLog = false;
|
111 |
|
|
|
|
|
|
|
|
|
112 |
return $doLog;
|
|
|
113 |
}
|
114 |
|
115 |
|
inc/SimpleHistory.php
CHANGED
@@ -516,9 +516,7 @@ class SimpleHistory {
|
|
516 |
|
517 |
if ( ! wp_next_scheduled( 'simple_history/maybe_purge_db' ) ) {
|
518 |
wp_schedule_event( time(), 'daily', 'simple_history/maybe_purge_db' );
|
519 |
-
// error_log("not scheduled, so do schedule");
|
520 |
} else {
|
521 |
-
// error_log("is scheduled");
|
522 |
}
|
523 |
|
524 |
// Remove old schedule (only author dev sites should have it)
|
@@ -989,13 +987,14 @@ class SimpleHistory {
|
|
989 |
$loggersDir . 'FileEditsLogger.php',
|
990 |
|
991 |
// Loggers for third party plugins
|
992 |
-
$loggersDir .
|
993 |
-
$loggersDir .
|
994 |
-
$loggersDir .
|
995 |
-
$loggersDir .
|
996 |
-
|
997 |
-
$loggersDir .
|
998 |
-
|
|
|
999 |
|
1000 |
// SimpleLogger.php must be loaded first and always since the other loggers extend it
|
1001 |
// Include it manually so risk of anyone using filters or similar disables it
|
@@ -2362,6 +2361,7 @@ Because Simple History was just recently installed, this feed does not contain m
|
|
2362 |
$message = _nx(
|
2363 |
'Simple History removed one event that were older than {days} days',
|
2364 |
'Simple History removed {num_rows} events that were older than {days} days',
|
|
|
2365 |
'Database is being cleared automagically',
|
2366 |
'simple-history'
|
2367 |
);
|
@@ -2658,32 +2658,14 @@ Because Simple History was just recently installed, this feed does not contain m
|
|
2658 |
}
|
2659 |
|
2660 |
$logRowContextKeysToShow = array_fill_keys( array_keys( (array) $oneLogRow->context ), true );
|
2661 |
-
|
2662 |
-
error_log($this->json_encode($logRowContextKeysToShow));
|
2663 |
-
Marker - 2 maj 2015 20:51:54
|
2664 |
-
[02-May-2015 18:51:57 UTC] {
|
2665 |
-
"post_id": true,
|
2666 |
-
"post_type": true,
|
2667 |
-
"post_title": true,
|
2668 |
-
"post_prev_post_title": true,
|
2669 |
-
"post_new_post_title": true,
|
2670 |
-
"post_prev_post_name": true,
|
2671 |
-
"post_new_post_name": true,
|
2672 |
-
"_message_key": true,
|
2673 |
-
"_user_id": true,
|
2674 |
-
"_user_login": true,
|
2675 |
-
"_user_email": true,
|
2676 |
-
"_server_remote_addr": true,
|
2677 |
-
"_server_http_referer": true
|
2678 |
-
}
|
2679 |
-
*/
|
2680 |
/**
|
2681 |
* Filter what keys to show from the row context
|
2682 |
*
|
2683 |
* Array is in format
|
2684 |
*
|
2685 |
-
|
2686 |
-
|
2687 |
* [plugin_slug] => 1
|
2688 |
* [plugin_name] => 1
|
2689 |
* [plugin_title] => 1
|
@@ -2902,7 +2884,11 @@ Because Simple History was just recently installed, this feed does not contain m
|
|
2902 |
}
|
2903 |
|
2904 |
|
2905 |
-
|
|
|
|
|
|
|
|
|
2906 |
|
2907 |
if ( empty( $slug ) ) {
|
2908 |
return false;
|
516 |
|
517 |
if ( ! wp_next_scheduled( 'simple_history/maybe_purge_db' ) ) {
|
518 |
wp_schedule_event( time(), 'daily', 'simple_history/maybe_purge_db' );
|
|
|
519 |
} else {
|
|
|
520 |
}
|
521 |
|
522 |
// Remove old schedule (only author dev sites should have it)
|
987 |
$loggersDir . 'FileEditsLogger.php',
|
988 |
|
989 |
// Loggers for third party plugins
|
990 |
+
$loggersDir . "PluginUserSwitchingLogger.php",
|
991 |
+
$loggersDir . "PluginEnableMediaReplaceLogger.php",
|
992 |
+
$loggersDir . "Plugin_UltimateMembers_Logger.php",
|
993 |
+
$loggersDir . "Plugin_LimitLoginAttempts.php",
|
994 |
+
$loggersDir . "Plugin_Redirection.php",
|
995 |
+
$loggersDir . "Plugin_DuplicatePost.php",
|
996 |
+
$loggersDir . "Plugin_ACF.php"
|
997 |
+
);
|
998 |
|
999 |
// SimpleLogger.php must be loaded first and always since the other loggers extend it
|
1000 |
// Include it manually so risk of anyone using filters or similar disables it
|
2361 |
$message = _nx(
|
2362 |
'Simple History removed one event that were older than {days} days',
|
2363 |
'Simple History removed {num_rows} events that were older than {days} days',
|
2364 |
+
sizeof( $ids_to_delete ),
|
2365 |
'Database is being cleared automagically',
|
2366 |
'simple-history'
|
2367 |
);
|
2658 |
}
|
2659 |
|
2660 |
$logRowContextKeysToShow = array_fill_keys( array_keys( (array) $oneLogRow->context ), true );
|
2661 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2662 |
/**
|
2663 |
* Filter what keys to show from the row context
|
2664 |
*
|
2665 |
* Array is in format
|
2666 |
*
|
2667 |
+
* Array
|
2668 |
+
* (
|
2669 |
* [plugin_slug] => 1
|
2670 |
* [plugin_name] => 1
|
2671 |
* [plugin_title] => 1
|
2884 |
}
|
2885 |
|
2886 |
|
2887 |
+
/**
|
2888 |
+
* @param string $slug
|
2889 |
+
* @return mixed logger instance if found, bool false if logger not found
|
2890 |
+
*/
|
2891 |
+
public function getInstantiatedLoggerBySlug( $slug = "" ) {
|
2892 |
|
2893 |
if ( empty( $slug ) ) {
|
2894 |
return false;
|
inc/SimpleHistoryLogQuery.php
CHANGED
@@ -20,7 +20,6 @@ class SimpleHistoryLogQuery {
|
|
20 |
}
|
21 |
|
22 |
public function query( $args ) {
|
23 |
-
|
24 |
$defaults = array(
|
25 |
|
26 |
// overview | occasions
|
@@ -638,7 +637,12 @@ class SimpleHistoryLogQuery {
|
|
638 |
|
639 |
}
|
640 |
|
641 |
-
// users, comma separated
|
|
|
|
|
|
|
|
|
|
|
642 |
if ( ! empty( $args['users'] ) && is_string( $args['users'] ) ) {
|
643 |
|
644 |
$users = explode( ',', $args['users'] );
|
20 |
}
|
21 |
|
22 |
public function query( $args ) {
|
|
|
23 |
$defaults = array(
|
24 |
|
25 |
// overview | occasions
|
637 |
|
638 |
}
|
639 |
|
640 |
+
// If users is array, make it comma separated.
|
641 |
+
if ( isset( $args['users'] ) && is_array( $args['users'] ) ) {
|
642 |
+
$args['users'] = implode( ',', $args['users'] );
|
643 |
+
}
|
644 |
+
|
645 |
+
// Users, comma separated.
|
646 |
if ( ! empty( $args['users'] ) && is_string( $args['users'] ) ) {
|
647 |
|
648 |
$users = explode( ',', $args['users'] );
|
index.php
CHANGED
@@ -4,8 +4,8 @@
|
|
4 |
* 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
|
8 |
-
* Version: 2.
|
9 |
* Author: Pär Thernström
|
10 |
* Author URI: http://simple-history.com/
|
11 |
* License: GPL2
|
@@ -48,7 +48,7 @@ if ( $ok_php_version && $ok_wp_version ) {
|
|
48 |
*/
|
49 |
|
50 |
if ( ! defined( 'SIMPLE_HISTORY_VERSION' ) ) {
|
51 |
-
define( 'SIMPLE_HISTORY_VERSION', '2.
|
52 |
}
|
53 |
|
54 |
if ( ! defined( 'SIMPLE_HISTORY_PATH' ) ) {
|
4 |
* 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.21
|
9 |
* Author: Pär Thernström
|
10 |
* Author URI: http://simple-history.com/
|
11 |
* License: GPL2
|
48 |
*/
|
49 |
|
50 |
if ( ! defined( 'SIMPLE_HISTORY_VERSION' ) ) {
|
51 |
+
define( 'SIMPLE_HISTORY_VERSION', '2.21' );
|
52 |
}
|
53 |
|
54 |
if ( ! defined( 'SIMPLE_HISTORY_PATH' ) ) {
|
loggers/AvailableUpdatesLogger.php
CHANGED
@@ -143,11 +143,22 @@ if ( ! class_exists( 'AvailableUpdatesLogger' ) ) {
|
|
143 |
// For each available update
|
144 |
foreach ( $updates->response as $key => $data ) {
|
145 |
|
146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
$plugin_new_version = isset( $data->new_version ) ? $data->new_version : '';
|
149 |
|
150 |
-
//
|
151 |
if ( ! array_key_exists( $key, $checked_updates ) ) {
|
152 |
$checked_updates[ $key ] = array(
|
153 |
'checked_version' => null,
|
@@ -178,7 +189,6 @@ if ( ! class_exists( 'AvailableUpdatesLogger' ) ) {
|
|
178 |
|
179 |
} // function
|
180 |
|
181 |
-
|
182 |
function on_setted_update_update_themes( $updates ) {
|
183 |
|
184 |
if ( empty( $updates->response ) || ! is_array( $updates->response ) ) {
|
143 |
// For each available update
|
144 |
foreach ( $updates->response as $key => $data ) {
|
145 |
|
146 |
+
// Make sure plugin directory exists or get_plugin_data will
|
147 |
+
// give warning like
|
148 |
+
// "PHP Warning: fread() expects parameter 1 to be resource, boolean given in /wp/wp-includes/functions.php on line 4837"
|
149 |
+
$file = WP_PLUGIN_DIR . '/' . $key;
|
150 |
+
$fp = fopen( $file, 'r' );
|
151 |
+
|
152 |
+
// Continue with next plugin if plugin file did not exist.
|
153 |
+
if (false === $fp) {
|
154 |
+
continue;
|
155 |
+
}
|
156 |
+
|
157 |
+
$plugin_info = get_plugin_data( $file, true, false );
|
158 |
|
159 |
$plugin_new_version = isset( $data->new_version ) ? $data->new_version : '';
|
160 |
|
161 |
+
// Check if this plugin and this version has been checked/logged already.
|
162 |
if ( ! array_key_exists( $key, $checked_updates ) ) {
|
163 |
$checked_updates[ $key ] = array(
|
164 |
'checked_version' => null,
|
189 |
|
190 |
} // function
|
191 |
|
|
|
192 |
function on_setted_update_update_themes( $updates ) {
|
193 |
|
194 |
if ( empty( $updates->response ) || ! is_array( $updates->response ) ) {
|
loggers/FileEditsLogger.php
CHANGED
@@ -78,11 +78,8 @@ class FileEditsLogger extends SimpleLogger {
|
|
78 |
'_occasionsID' => __CLASS__ . '/' . __FUNCTION__ . "/file-edit/$plugin_file/$file",
|
79 |
);
|
80 |
|
81 |
-
// ddd($_POST, $context, $action, $file, $plugin, $phperror, $fileNewContents, $scrollto);
|
82 |
$loggerInstance = $this;
|
83 |
add_filter( 'wp_redirect', function ( $location, $status ) use ( $context, $loggerInstance ) {
|
84 |
-
error_log( $location );
|
85 |
-
|
86 |
$locationParsed = parse_url( $location );
|
87 |
|
88 |
if ( $locationParsed === false || empty( $locationParsed['query'] ) ) {
|
78 |
'_occasionsID' => __CLASS__ . '/' . __FUNCTION__ . "/file-edit/$plugin_file/$file",
|
79 |
);
|
80 |
|
|
|
81 |
$loggerInstance = $this;
|
82 |
add_filter( 'wp_redirect', function ( $location, $status ) use ( $context, $loggerInstance ) {
|
|
|
|
|
83 |
$locationParsed = parse_url( $location );
|
84 |
|
85 |
if ( $locationParsed === false || empty( $locationParsed['query'] ) ) {
|
loggers/Plugin_ACF.php
ADDED
@@ -0,0 +1,1032 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
defined( 'ABSPATH' ) || die();
|
4 |
+
|
5 |
+
// Only enable in development mode.
|
6 |
+
if ( ! defined( 'SIMPLE_HISTORY_DEV' ) || ! SIMPLE_HISTORY_DEV ) {
|
7 |
+
return;
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Logger for the Advanced Custom Fields (ACF) plugin
|
12 |
+
* https://sv.wordpress.org/plugins/advanced-custom-fields/
|
13 |
+
*
|
14 |
+
* @package SimpleHistory
|
15 |
+
* @since 2.21
|
16 |
+
*/
|
17 |
+
if ( ! class_exists( 'Plugin_ACF' ) ) {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Class for ACF logging.
|
21 |
+
*/
|
22 |
+
class Plugin_ACF extends SimpleLogger {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* The slug for this logger.
|
26 |
+
*
|
27 |
+
* @var string $slug
|
28 |
+
*/
|
29 |
+
public $slug = __CLASS__;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Will contain field groups and fields, before and after post save.
|
33 |
+
*
|
34 |
+
* @var string $oldAndNewFieldGroupsAndFields
|
35 |
+
*/
|
36 |
+
private $oldAndNewFieldGroupsAndFields = array(
|
37 |
+
'fieldGroup' => array(
|
38 |
+
'old' => null,
|
39 |
+
'new' => null,
|
40 |
+
),
|
41 |
+
'modifiedFields' => array(
|
42 |
+
'old' => null,
|
43 |
+
'new' => null,
|
44 |
+
),
|
45 |
+
'addedFields' => array(),
|
46 |
+
'deletedFields' => array(),
|
47 |
+
);
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Will contain the post data before save, i.e. the previous version of the post.
|
51 |
+
*
|
52 |
+
* @var string $oldPostData
|
53 |
+
*/
|
54 |
+
private $oldPostData = array();
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Get info for this logger.
|
58 |
+
*
|
59 |
+
* @return array Array with info about the logger.
|
60 |
+
*/
|
61 |
+
public function getInfo() {
|
62 |
+
$arr_info = array(
|
63 |
+
'name' => 'Plugin ACF',
|
64 |
+
'description' => _x( 'Logs ACF stuff', 'Logger: Plugin ACF', 'simple-history' ),
|
65 |
+
'name_via' => _x( 'Using plugin ACF', 'Logger: Plugin ACF', 'simple-history' ),
|
66 |
+
'capability' => 'manage_options',
|
67 |
+
);
|
68 |
+
|
69 |
+
return $arr_info;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Method called when logger is loaded.
|
74 |
+
*/
|
75 |
+
public function loaded() {
|
76 |
+
|
77 |
+
// Bail if no ACF found.
|
78 |
+
if ( ! function_exists( 'acf_verify_nonce' ) ) {
|
79 |
+
return;
|
80 |
+
}
|
81 |
+
|
82 |
+
// Remove ACF Fields from the post types that postlogger logs.
|
83 |
+
add_filter( 'simple_history/post_logger/skip_posttypes', array( $this, 'remove_acf_from_postlogger') );
|
84 |
+
|
85 |
+
// Get prev version of acf field group.
|
86 |
+
// This is called before transition_post_status.
|
87 |
+
add_filter( 'wp_insert_post_data', array( $this, 'on_wp_insert_post_data' ), 10, 2 );
|
88 |
+
|
89 |
+
// Store old and new field data when a post is saved.
|
90 |
+
add_action( 'transition_post_status', array( $this, 'on_transition_post_status' ), 5, 3 );
|
91 |
+
|
92 |
+
// Append ACF data to post context
|
93 |
+
add_filter( 'simple_history/post_logger/post_updated/context', array( $this, 'on_post_updated_context' ), 10, 2 );
|
94 |
+
|
95 |
+
// Add ACF diff data to activity feed detailed output.
|
96 |
+
add_filter( 'simple_history/post_logger/post_updated/diff_table_output', array( $this, 'on_diff_table_output_field_group' ), 10, 2 );
|
97 |
+
|
98 |
+
// Store prev ACF field values before new values are added.
|
99 |
+
// Called from filter admin_action_editpost that is fired at top of admin.php
|
100 |
+
add_action( 'admin_action_editpost', array( $this, 'on_admin_action_editpost' ) );
|
101 |
+
|
102 |
+
// Fired when ACF saves a post. Adds ACF context to logged row.
|
103 |
+
add_filter( 'acf/save_post', array( $this, 'on_acf_save_post' ), 50 );
|
104 |
+
|
105 |
+
// Fired after a log row is inserted. Add filter so field group save is is not logged again.
|
106 |
+
add_action( 'simple_history/log/inserted', array( $this, 'on_log_inserted' ), 10, 3 );
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Fired after a log row is inserted.
|
111 |
+
*/
|
112 |
+
public function on_log_inserted( $context, $data_parent_row, $simple_history_instance ) {
|
113 |
+
$message_key = ! empty( $context['_message_key'] ) ? $context['_message_key'] : false;
|
114 |
+
$logger = ! empty( $data_parent_row['logger'] ) ? $data_parent_row['logger'] : false;
|
115 |
+
$post_id = ! empty( $context['post_id'] ) ? $context['post_id'] : false;
|
116 |
+
$post_type = ! empty( $context['post_type'] ) ? $context['post_type'] : false;
|
117 |
+
|
118 |
+
// Bail if not all required vars are set.
|
119 |
+
if ( ! $message_key || ! $logger || ! $post_id || ! $post_type ) {
|
120 |
+
return;
|
121 |
+
}
|
122 |
+
|
123 |
+
// Only act when logger was SimplePostLogger.
|
124 |
+
if ( $logger !== 'SimplePostLogger' ) {
|
125 |
+
return;
|
126 |
+
}
|
127 |
+
|
128 |
+
// Only act when the saved type was a ACF Field Group.
|
129 |
+
if ( $post_type !== 'acf-field-group' ) {
|
130 |
+
return;
|
131 |
+
}
|
132 |
+
|
133 |
+
// Ok, a row was inserted using the log function on SimplePostLogger,
|
134 |
+
// now ACF will call save_post again and trigger
|
135 |
+
// another log of the same row. To prevent this we
|
136 |
+
// now add a filter to prevent the next log.
|
137 |
+
add_filter( 'simple_history/post_logger/post_updated/ok_to_log', array( $this, 'prevent_second_acf_field_group_post_save_log' ), 10, 4 );
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Fired from SimpleLogger action 'simple_history/post_logger/post_updated/ok_to_log' and added only after
|
142 |
+
* a row already has been logged.
|
143 |
+
*
|
144 |
+
* This function checks if post type logged by SimplePostLogger is a ACF Field Group, and if it is
|
145 |
+
* then don't log that log. This way we prevent the post logger from logging the field group changes twice.
|
146 |
+
*/
|
147 |
+
public function prevent_second_acf_field_group_post_save_log($ok_to_log, $new_status, $old_status, $post) {
|
148 |
+
if (isset($post->post_type) && $post->post_type === 'acf-field-group') {
|
149 |
+
$ok_to_log = false;
|
150 |
+
}
|
151 |
+
|
152 |
+
return $ok_to_log;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Append info about changes in ACF fields input,
|
157 |
+
* i.e. store all info we later use to show changes that a user has done.
|
158 |
+
*
|
159 |
+
* Called when ACF saves a post.
|
160 |
+
*
|
161 |
+
* @param int $post_id ID of post that is being saved.
|
162 |
+
*/
|
163 |
+
public function on_acf_save_post( $post_id ) {
|
164 |
+
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
|
165 |
+
return;
|
166 |
+
}
|
167 |
+
|
168 |
+
// Don't act on post revision.
|
169 |
+
if ( wp_is_post_revision( $post_id ) ) {
|
170 |
+
return;
|
171 |
+
}
|
172 |
+
|
173 |
+
/*
|
174 |
+
Meta values look like
|
175 |
+
[product_images_0_image] => 625
|
176 |
+
[_product_images_0_image] => field_59a091044812e
|
177 |
+
[product_images_0_image_caption] => Image row yes
|
178 |
+
[_product_images_0_image_caption] => field_59a0910f4812f
|
179 |
+
[product_images_0_image_related_0_related_name] => Related one
|
180 |
+
[_product_images_0_image_related_0_related_name] => field_59aaedd43ae11
|
181 |
+
[product_images_0_image_related_0_related_item_post] =>
|
182 |
+
[_product_images_0_image_related_0_related_item_post] => field_59aaede43ae12
|
183 |
+
[product_images_0_image_related_1_related_name] => Another related
|
184 |
+
[_product_images_0_image_related_1_related_name] => field_59aaedd43ae11
|
185 |
+
[product_images_0_image_related_1_related_item_post] =>
|
186 |
+
[_product_images_0_image_related_1_related_item_post] => field_59aaede43ae12
|
187 |
+
[product_images_0_image_related] => 2
|
188 |
+
[_product_images_0_image_related] => field_59aaedbc3ae10
|
189 |
+
[product_images_1_image] => 574
|
190 |
+
*/
|
191 |
+
$prev_post_meta = $this->oldPostData['prev_post_meta'];
|
192 |
+
$new_post_meta = get_post_custom( $post_id );
|
193 |
+
$new_post_meta = array_map( 'reset', $new_post_meta );
|
194 |
+
|
195 |
+
// New and old post meta can contain different amount of keys,
|
196 |
+
// join them so we have the name of all post meta thaf have been added, removed, or modified.
|
197 |
+
$new_and_old_post_meta = array_merge( $prev_post_meta, $new_post_meta );
|
198 |
+
ksort( $new_and_old_post_meta, SORT_REGULAR );
|
199 |
+
|
200 |
+
// array1 - The array to compare from
|
201 |
+
// array2 - An array to compare against
|
202 |
+
// Returns an array containing all the values from array1 that are not present in any of the other arrays.
|
203 |
+
// Keep only ACF fields in prev and new post meta.
|
204 |
+
$prev_post_meta = $this->keep_only_acf_stuff_in_array( $prev_post_meta, $new_and_old_post_meta );
|
205 |
+
$new_post_meta = $this->keep_only_acf_stuff_in_array( $new_post_meta, $new_and_old_post_meta );
|
206 |
+
$new_and_old_post_meta_acf_fields = array_merge( $prev_post_meta, $new_post_meta );
|
207 |
+
|
208 |
+
// Map field name with fieldkey so we can get field objects when needed.
|
209 |
+
// Final array have values like:
|
210 |
+
// [product_images_0_image] => field_59a091044812e
|
211 |
+
// [product_images_0_image_caption] => field_59a0910f4812f
|
212 |
+
// [product_images_0_image_related_0_related_name] => field_59aaedd43ae11.
|
213 |
+
$fieldnames_to_field_keys = array();
|
214 |
+
foreach ( $new_and_old_post_meta_acf_fields as $meta_key => $meta_value ) {
|
215 |
+
// $key is like [product_images_0_image_related_1_related_name].
|
216 |
+
// Get ACF fieldkey for that value. Will be in $new_and_old_post_meta
|
217 |
+
// as the same as key but with underscore first
|
218 |
+
$meta_key_to_look_for = "_{$meta_key}";
|
219 |
+
if ( isset( $new_and_old_post_meta[ $meta_key_to_look_for ] ) ) {
|
220 |
+
$fieldnames_to_field_keys[ $meta_key ] = $new_and_old_post_meta[ $meta_key_to_look_for ];
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
// Compare old with new = get only changed, not added, deleted are here.
|
225 |
+
$post_meta_diff1 = array_diff_assoc( $prev_post_meta, $new_post_meta );
|
226 |
+
|
227 |
+
// Compare new with old = get an diff with added and changed stuff.
|
228 |
+
$post_meta_diff2 = array_diff_assoc( $new_post_meta, $prev_post_meta );
|
229 |
+
|
230 |
+
// Compare keys, gets added fields.
|
231 |
+
$post_meta_added_fields = array_diff( array_keys( $post_meta_diff2 ), array_keys( $post_meta_diff1 ) );
|
232 |
+
$post_meta_added_fields = array_values( $post_meta_added_fields );
|
233 |
+
|
234 |
+
// Keys that exist in diff1 but not in diff2 = deleted.
|
235 |
+
$post_meta_removed_fields = array_diff_assoc( array_keys( $post_meta_diff1 ), array_keys( $post_meta_diff2 ) );
|
236 |
+
$post_meta_removed_fields = array_values( $post_meta_removed_fields );
|
237 |
+
|
238 |
+
$post_meta_changed_fields = array_keys( $post_meta_diff1 );
|
239 |
+
|
240 |
+
/*
|
241 |
+
* value is changed: added to both diff and diff2
|
242 |
+
* value is added, like in repeater: added to diff2 (not to diff)
|
243 |
+
* $diff3: contains only added things.
|
244 |
+
* Compare old and new values
|
245 |
+
* Loop all keys in $new_and_old_post_meta
|
246 |
+
* But act only on those whose keys begins with "_" and where the value begins with "field_" and ends with alphanum.
|
247 |
+
*/
|
248 |
+
|
249 |
+
/*
|
250 |
+
* We have the diff, now add it to the context
|
251 |
+
* This is called after Simple History already has added its row
|
252 |
+
* So... we must add to the context late somehow
|
253 |
+
* Get the latest inserted row from the SimplePostLogger, check if that postID is
|
254 |
+
* same as the
|
255 |
+
*/
|
256 |
+
$post_logger = $this->simpleHistory->getInstantiatedLoggerBySlug( 'SimplePostLogger' );
|
257 |
+
|
258 |
+
// Save ACF diff if detected post here is same as the last one used in Postlogger.
|
259 |
+
if ( $post_id === $post_logger->lastInsertContext['post_id'] ) {
|
260 |
+
$last_insert_id = $post_logger->lastInsertID;
|
261 |
+
|
262 |
+
// Append new info to the context of history item with id $post_logger->lastInsertID.
|
263 |
+
$acf_context = array();
|
264 |
+
$acf_context = $this->add_acf_context( $acf_context, 'added', $post_meta_added_fields, $prev_post_meta, $new_post_meta, $fieldnames_to_field_keys );
|
265 |
+
$acf_context = $this->add_acf_context( $acf_context, 'changed', $post_meta_changed_fields, $prev_post_meta, $new_post_meta, $fieldnames_to_field_keys );
|
266 |
+
$acf_context = $this->add_acf_context( $acf_context, 'removed', $post_meta_removed_fields, $prev_post_meta, $new_post_meta, $fieldnames_to_field_keys );
|
267 |
+
|
268 |
+
$post_logger->append_context( $last_insert_id, $acf_context );
|
269 |
+
|
270 |
+
// Prev and new post meta for testing.
|
271 |
+
/*
|
272 |
+
$post_logger->append_context(
|
273 |
+
$last_insert_id,
|
274 |
+
array(
|
275 |
+
'prev_post_meta' => $prev_post_meta,
|
276 |
+
)
|
277 |
+
);
|
278 |
+
$post_logger->append_context(
|
279 |
+
$last_insert_id,
|
280 |
+
array(
|
281 |
+
'new_post_meta' => $new_post_meta,
|
282 |
+
)
|
283 |
+
);
|
284 |
+
*/
|
285 |
+
} // End if().
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Add ACF context for added, removed, or changed fields.
|
290 |
+
*
|
291 |
+
* @param array $context Context.
|
292 |
+
* @param string $modify_type Type. added | removed | changed.
|
293 |
+
* @param array $relevant_acf_fields Fields.
|
294 |
+
* @param array $prev_post_meta Prev meta.
|
295 |
+
* @param array $new_post_meta New meta.
|
296 |
+
* @param array $fieldnames_to_field_keys Fieldnames to field keys mapping.
|
297 |
+
* @return array Modified context.
|
298 |
+
*/
|
299 |
+
public function add_acf_context( $context = array(), $modify_type = '', $relevant_acf_fields = array(), $prev_post_meta, $new_post_meta, $fieldnames_to_field_keys ) {
|
300 |
+
if ( ! is_array( $context ) || empty( $modify_type ) || empty( $relevant_acf_fields ) ) {
|
301 |
+
return $context;
|
302 |
+
}
|
303 |
+
|
304 |
+
$loopnum = 0;
|
305 |
+
foreach ( $relevant_acf_fields as $field_slug ) {
|
306 |
+
/*
|
307 |
+
Store just the names to begin with
|
308 |
+
acf_field_added_0 = url.
|
309 |
+
acf_field_added_1 = first_name.
|
310 |
+
|
311 |
+
If field slug contains a number, like in "product_images_2_image"
|
312 |
+
that probably means that that field is a repeater with name "product_images"
|
313 |
+
with a sub field called "image" and that the image is the 2:nd among it's selected sub fields.
|
314 |
+
|
315 |
+
Example of how fields can look:
|
316 |
+
acf_field_added_0 product_images_2_image
|
317 |
+
acf_field_added_1 product_images_2_image_caption
|
318 |
+
acf_field_added_2 product_images_2_image_related
|
319 |
+
acf_field_changed_0 my_field_in_acf
|
320 |
+
acf_field_changed_1 product_images
|
321 |
+
acf_field_changed_2 price
|
322 |
+
acf_field_changed_3 description
|
323 |
+
*/
|
324 |
+
$context_key = "acf_field_{$modify_type}_{$loopnum}";
|
325 |
+
$context[ "{$context_key}/slug" ] = $field_slug;
|
326 |
+
|
327 |
+
/*
|
328 |
+
* Try to get som extra info, like display name and type for this field.
|
329 |
+
* For a nice context in the feed we want: parent field group name and type?
|
330 |
+
*/
|
331 |
+
if ( isset( $fieldnames_to_field_keys[ $field_slug ] ) ) {
|
332 |
+
$field_key = $fieldnames_to_field_keys[ $field_slug ];
|
333 |
+
$context[ "{$context_key}/key" ] = $field_key;
|
334 |
+
|
335 |
+
// Interesting stuff in field object:
|
336 |
+
// - Label = the human readable name of the field
|
337 |
+
// - Type = the type of the field
|
338 |
+
// - Parent = id of parent field post id.
|
339 |
+
$field_object = get_field_object( $field_key );
|
340 |
+
if ( is_array( $field_object ) ) {
|
341 |
+
$context[ "{$context_key}/label" ] = $field_object['label'];
|
342 |
+
if ( ! empty( $field_object['type'] ) ) {
|
343 |
+
$context[ "{$context_key}/type" ] = $field_object['type'];
|
344 |
+
}
|
345 |
+
|
346 |
+
// If no parent just continue to next field.
|
347 |
+
if ( empty( $field_object['parent'] ) ) {
|
348 |
+
continue;
|
349 |
+
}
|
350 |
+
|
351 |
+
// We have at least one parent, get them all, including the field group
|
352 |
+
// $context[ "{$context_key}/field_parent_object" ] = $parent_field;
|
353 |
+
$field_parents = array();
|
354 |
+
$field_field_group = null;
|
355 |
+
|
356 |
+
// Begin with the direct parent.
|
357 |
+
$parent_field = $field_object;
|
358 |
+
|
359 |
+
while ( ! empty( $parent_field['parent'] ) ) {
|
360 |
+
// acf-field | acf-field-group.
|
361 |
+
$parent_field_post_type = get_post_type( $parent_field['parent'] );
|
362 |
+
|
363 |
+
if ( false === $parent_field_post_type ) {
|
364 |
+
break;
|
365 |
+
}
|
366 |
+
|
367 |
+
if ( 'acf-field' === $parent_field_post_type ) {
|
368 |
+
$parent_field = _acf_get_field_by_id( $parent_field['parent'] );
|
369 |
+
} elseif ( 'acf-field-group' === $parent_field_post_type ) {
|
370 |
+
$parent_field = acf_get_field_group( $parent_field['parent'] );
|
371 |
+
} else {
|
372 |
+
// Unknown post type.
|
373 |
+
break;
|
374 |
+
}
|
375 |
+
|
376 |
+
if ( false === $parent_field ) {
|
377 |
+
break;
|
378 |
+
}
|
379 |
+
|
380 |
+
if ( 'acf-field' === $parent_field_post_type ) {
|
381 |
+
$field_parents[] = $parent_field;
|
382 |
+
} elseif ( 'acf-field-group' === $parent_field_post_type ) {
|
383 |
+
$field_field_group = $parent_field;
|
384 |
+
} // End if().
|
385 |
+
} // End while().
|
386 |
+
|
387 |
+
$field_parents = array_reverse( $field_parents );
|
388 |
+
|
389 |
+
// Array with info about each parent.
|
390 |
+
$arr_field_path = array();
|
391 |
+
|
392 |
+
if ( ! empty( $field_field_group['title'] ) ) {
|
393 |
+
$arr_field_path[] = array(
|
394 |
+
'name' => $field_field_group['title'],
|
395 |
+
'type' => 'field_group',
|
396 |
+
);
|
397 |
+
}
|
398 |
+
|
399 |
+
foreach ( $field_parents as $one_field_parent ) {
|
400 |
+
$arr_field_path[] = array(
|
401 |
+
'name' => $one_field_parent['label'],
|
402 |
+
'type' => 'field',
|
403 |
+
'field_type' => $one_field_parent['type'],
|
404 |
+
);
|
405 |
+
}
|
406 |
+
|
407 |
+
if ( ! empty( $arr_field_path ) ) {
|
408 |
+
$path_loop_num = 0;
|
409 |
+
foreach ( $arr_field_path as $one_field_path ) {
|
410 |
+
$context[ "{$context_key}/path_{$path_loop_num}/name" ] = $one_field_path['name'];
|
411 |
+
$context[ "{$context_key}/path_{$path_loop_num}/type" ] = $one_field_path['type'];
|
412 |
+
if ( ! empty( $one_field_path['field_type'] ) ) {
|
413 |
+
$context[ "{$context_key}/path_{$path_loop_num}/field_type" ] = $one_field_path['field_type'];
|
414 |
+
}
|
415 |
+
$path_loop_num++;
|
416 |
+
}
|
417 |
+
}
|
418 |
+
|
419 |
+
// Add value of fields if they are not part of
|
420 |
+
// repeatable or flexible fields or similar.
|
421 |
+
// error_log( "Final parents" . print_r( $field_parents, 1 ) );
|
422 |
+
// error_log( "Final field group" . print_r( $field_field_group['title'], 1 ) );
|
423 |
+
// error_log( "context" . print_r( $context, 1 ) );
|
424 |
+
} // End if().
|
425 |
+
} // End if().
|
426 |
+
|
427 |
+
$loopnum++;
|
428 |
+
} // End foreach().
|
429 |
+
|
430 |
+
// error_log( "---------------------------" );
|
431 |
+
// error_log( "field_path_string: $field_path_string");
|
432 |
+
// error_log( "context" . print_r( $context, 1 ) );
|
433 |
+
return $context;
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Clean array and keep only ACF related things.
|
438 |
+
*
|
439 |
+
* Remove
|
440 |
+
* - underscore fields
|
441 |
+
* - fields with value field_*
|
442 |
+
*
|
443 |
+
* Keep
|
444 |
+
* - vals that are acf
|
445 |
+
*
|
446 |
+
* @param array $arr Array.
|
447 |
+
* @param array $all_fields Array fields.
|
448 |
+
*/
|
449 |
+
public function keep_only_acf_stuff_in_array( $arr, $all_fields ) {
|
450 |
+
$new_arr = array();
|
451 |
+
|
452 |
+
foreach ( $arr as $key => $val ) {
|
453 |
+
|
454 |
+
// Don't keep keys that begin with underscore "_".
|
455 |
+
if ( strpos( $key, '_' ) === 0 ) {
|
456 |
+
continue;
|
457 |
+
}
|
458 |
+
|
459 |
+
// Don't keep keys that begin with "field_".
|
460 |
+
if ( strpos( $val, 'field_' ) === 0 ) {
|
461 |
+
continue;
|
462 |
+
}
|
463 |
+
|
464 |
+
// Don't keep fields that does not have a corresponding _field value.
|
465 |
+
// Each key has both the name, for example 'color' and another
|
466 |
+
// key called '_color'. We check that the underscore version exists
|
467 |
+
// and contains 'field_'. After this check only ACF fields should exist
|
468 |
+
// in the array..
|
469 |
+
if ( ! isset( $all_fields[ "_{$key}" ] ) ) {
|
470 |
+
continue;
|
471 |
+
}
|
472 |
+
|
473 |
+
if ( strpos( $all_fields[ "_{$key}" ], 'field_' ) !== 0 ) {
|
474 |
+
continue;
|
475 |
+
}
|
476 |
+
|
477 |
+
$new_arr[ $key ] = $val;
|
478 |
+
}
|
479 |
+
|
480 |
+
return $new_arr;
|
481 |
+
}
|
482 |
+
|
483 |
+
/**
|
484 |
+
* Store prev post meta when post is saved.
|
485 |
+
* Stores data in $this->oldPostData.
|
486 |
+
*/
|
487 |
+
public function on_admin_action_editpost() {
|
488 |
+
$post_ID = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
|
489 |
+
|
490 |
+
if ( ! $post_ID ) {
|
491 |
+
return;
|
492 |
+
}
|
493 |
+
|
494 |
+
$prev_post = get_post( $post_ID );
|
495 |
+
|
496 |
+
if ( is_wp_error( $prev_post ) ) {
|
497 |
+
return;
|
498 |
+
}
|
499 |
+
|
500 |
+
$post_meta = get_post_custom( $post_ID );
|
501 |
+
|
502 |
+
// Meta is array of arrays, get first value of each array value.
|
503 |
+
$post_meta = array_map( 'reset', $post_meta );
|
504 |
+
|
505 |
+
$this->oldPostData['prev_post_meta'] = $post_meta;
|
506 |
+
}
|
507 |
+
|
508 |
+
/**
|
509 |
+
* Called from PostLogger and its diff table output using filter 'simple_history/post_logger/post_updated/diff_table_output'.
|
510 |
+
* Diff table is generated only for post type 'acf-field-group'.
|
511 |
+
*
|
512 |
+
* @param string $diff_table_output
|
513 |
+
* @param array $context
|
514 |
+
* @return string
|
515 |
+
*/
|
516 |
+
public function on_diff_table_output_field_group( $diff_table_output, $context ) {
|
517 |
+
$post_type = !empty($context['post_type']) ? $context['post_type'] : false;
|
518 |
+
|
519 |
+
// Bail if not ACF Field Group.
|
520 |
+
if ($post_type !== 'acf-field-group') {
|
521 |
+
return '';
|
522 |
+
}
|
523 |
+
|
524 |
+
// Field group fields to check for and output if found
|
525 |
+
$arrKeys = array(
|
526 |
+
'instruction_placement' => array(
|
527 |
+
'name' => _x('Instruction placement', 'Logger: Plugin ACF', 'simple-history'),
|
528 |
+
),
|
529 |
+
'label_placement' => array(
|
530 |
+
'name' => _x('Label placement', 'Logger: Plugin ACF', 'simple-history'),
|
531 |
+
),
|
532 |
+
'description' => array(
|
533 |
+
'name' => _x('Description', 'Logger: Plugin ACF', 'simple-history'),
|
534 |
+
),
|
535 |
+
'menu_order' => array(
|
536 |
+
'name' => _x('Menu order', 'Logger: Plugin ACF', 'simple-history'),
|
537 |
+
),
|
538 |
+
'position' => array(
|
539 |
+
'name' => _x('Position', 'Logger: Plugin ACF', 'simple-history'),
|
540 |
+
),
|
541 |
+
'active' => array(
|
542 |
+
'name' => _x('Active', 'Logger: Plugin ACF', 'simple-history'),
|
543 |
+
),
|
544 |
+
'style' => array(
|
545 |
+
'name' => _x('Style', 'Logger: Plugin ACF', 'simple-history'),
|
546 |
+
),
|
547 |
+
);
|
548 |
+
|
549 |
+
foreach ( $arrKeys as $acfKey => $acfVals ) {
|
550 |
+
if ( isset( $context[ "acf_new_$acfKey" ] ) && isset( $context[ "acf_prev_$acfKey" ] ) ) {
|
551 |
+
$diff_table_output .= sprintf(
|
552 |
+
'<tr>
|
553 |
+
<td>%1$s</td>
|
554 |
+
<td>
|
555 |
+
<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%2$s</ins>
|
556 |
+
<del class="SimpleHistoryLogitem__keyValueTable__removedThing">%3$s</del>
|
557 |
+
</td>
|
558 |
+
</tr>',
|
559 |
+
$acfVals['name'],
|
560 |
+
esc_html( $context[ "acf_new_$acfKey" ] ),
|
561 |
+
esc_html( $context[ "acf_prev_$acfKey" ] )
|
562 |
+
);
|
563 |
+
}
|
564 |
+
}
|
565 |
+
|
566 |
+
// If only acf_hide_on_screen_removed exists nothing is outputed.
|
567 |
+
$acf_hide_on_screen_added = empty( $context['acf_hide_on_screen_added'] ) ? null : $context['acf_hide_on_screen_added'];
|
568 |
+
$acf_hide_on_screen_removed = empty( $context['acf_hide_on_screen_removed'] ) ? null : $context['acf_hide_on_screen_removed'];
|
569 |
+
|
570 |
+
if ( $acf_hide_on_screen_added || $acf_hide_on_screen_removed ) {
|
571 |
+
$strCheckedHideOnScreen = '';
|
572 |
+
$strUncheckedHideOnScreen = '';
|
573 |
+
|
574 |
+
if ( $acf_hide_on_screen_added ) {
|
575 |
+
$strCheckedHideOnScreen = sprintf(
|
576 |
+
'%1$s %2$s',
|
577 |
+
_x( 'Checked', 'Logger: Plugin ACF', 'simple-history' ), // 1
|
578 |
+
esc_html( $acf_hide_on_screen_added ) // 2
|
579 |
+
);
|
580 |
+
}
|
581 |
+
|
582 |
+
if ( $acf_hide_on_screen_removed ) {
|
583 |
+
$strUncheckedHideOnScreen = sprintf(
|
584 |
+
'%1$s %2$s',
|
585 |
+
_x( 'Unchecked', 'Logger: Plugin ACF', 'simple-history' ), // 1
|
586 |
+
esc_html( $acf_hide_on_screen_removed ) // 2
|
587 |
+
);
|
588 |
+
}
|
589 |
+
|
590 |
+
$diff_table_output .= sprintf(
|
591 |
+
'<tr>
|
592 |
+
<td>%1$s</td>
|
593 |
+
<td>
|
594 |
+
%2$s
|
595 |
+
%3$s
|
596 |
+
</td>
|
597 |
+
</tr>',
|
598 |
+
_x( 'Hide on screen', 'Logger: Plugin ACF', 'simple-history' ), // 1
|
599 |
+
$strCheckedHideOnScreen, // 2
|
600 |
+
$strUncheckedHideOnScreen // 3
|
601 |
+
);
|
602 |
+
}
|
603 |
+
|
604 |
+
// Check for deleted fields.
|
605 |
+
if ( isset( $context['acf_deleted_fields_0_key'] ) ) {
|
606 |
+
// 1 or more deleted fields exist in context.
|
607 |
+
$loopnum = 0;
|
608 |
+
$strDeletedFields = '';
|
609 |
+
|
610 |
+
while ( isset( $context[ "acf_deleted_fields_{$loopnum}_key" ] ) ) {
|
611 |
+
$strDeletedFields .= sprintf(
|
612 |
+
'%1$s (%3$s), ',
|
613 |
+
esc_html( $context[ "acf_deleted_fields_{$loopnum}_label" ] ),
|
614 |
+
esc_html( $context[ "acf_deleted_fields_{$loopnum}_name" ] ),
|
615 |
+
esc_html( $context[ "acf_deleted_fields_{$loopnum}_type" ] )
|
616 |
+
);
|
617 |
+
|
618 |
+
$loopnum++;
|
619 |
+
}
|
620 |
+
|
621 |
+
$strDeletedFields = trim( $strDeletedFields, ', ' );
|
622 |
+
|
623 |
+
$diff_table_output .= sprintf(
|
624 |
+
'<tr>
|
625 |
+
<td>%1$s</td>
|
626 |
+
<td>%2$s</td>
|
627 |
+
</tr>',
|
628 |
+
_nx( 'Deleted field', 'Deleted fields', $loopnum, 'Logger: Plugin ACF', 'simple-history' ), // 1
|
629 |
+
$strDeletedFields
|
630 |
+
);
|
631 |
+
} // if deleted fields
|
632 |
+
|
633 |
+
// Check for added fields
|
634 |
+
if ( isset( $context['acf_added_fields_0_key'] ) ) {
|
635 |
+
// 1 or more deleted fields exist in context
|
636 |
+
$loopnum = 0;
|
637 |
+
$strAddedFields = '';
|
638 |
+
|
639 |
+
while ( isset( $context[ "acf_added_fields_{$loopnum}_key" ] ) ) {
|
640 |
+
$strAddedFields .= sprintf(
|
641 |
+
'%1$s (%3$s), ',
|
642 |
+
esc_html( $context[ "acf_added_fields_{$loopnum}_label" ] ), // 1
|
643 |
+
esc_html( $context[ "acf_added_fields_{$loopnum}_name" ] ), // 2
|
644 |
+
esc_html( $context[ "acf_added_fields_{$loopnum}_type" ] ) // 3
|
645 |
+
);
|
646 |
+
|
647 |
+
$loopnum++;
|
648 |
+
}
|
649 |
+
|
650 |
+
$strAddedFields = trim( $strAddedFields, ', ' );
|
651 |
+
|
652 |
+
$diff_table_output .= sprintf(
|
653 |
+
'<tr>
|
654 |
+
<td>%1$s</td>
|
655 |
+
<td>%2$s</td>
|
656 |
+
</tr>',
|
657 |
+
_nx( 'Added field', 'Added fields', $loopnum, 'Logger: Plugin ACF', 'simple-history' ), // 1
|
658 |
+
$strAddedFields
|
659 |
+
);
|
660 |
+
} // if deleted fields
|
661 |
+
|
662 |
+
// Check for modified fields
|
663 |
+
if ( isset( $context['acf_modified_fields_0_ID_prev'] ) ) {
|
664 |
+
// 1 or more modifiedfields exist in context
|
665 |
+
$loopnum = 0;
|
666 |
+
$strModifiedFields = '';
|
667 |
+
$arrAddedFieldsKeysToCheck = array(
|
668 |
+
'name' => array(
|
669 |
+
'name' => _x('Name: ', 'Logger: Plugin ACF', 'simple-history'),
|
670 |
+
),
|
671 |
+
'parent' => array(
|
672 |
+
'name' => _x('Parent: ', 'Logger: Plugin ACF', 'simple-history'),
|
673 |
+
),
|
674 |
+
'key' => array(
|
675 |
+
'name' => _x('Key: ', 'Logger: Plugin ACF', 'simple-history'),
|
676 |
+
),
|
677 |
+
'label' => array(
|
678 |
+
'name' => _x('Label: ', 'Logger: Plugin ACF', 'simple-history'),
|
679 |
+
),
|
680 |
+
'type' => array(
|
681 |
+
'name' => _x('Type: ', 'Logger: Plugin ACF', 'simple-history'),
|
682 |
+
),
|
683 |
+
);
|
684 |
+
|
685 |
+
while ( isset( $context[ "acf_modified_fields_{$loopnum}_name_prev" ] ) ) {
|
686 |
+
// One modified field, with one or more changed things
|
687 |
+
$strOneModifiedField = '';
|
688 |
+
|
689 |
+
// Add the field name manually, if it is not among the changed field,
|
690 |
+
// or we don't know what field the other changed values belongs to.
|
691 |
+
/*
|
692 |
+
if (empty($context["acf_modified_fields_{$loopnum}_name_new"])) {
|
693 |
+
$strOneModifiedField .= sprintf(
|
694 |
+
_x('Name: %1$s', 'Logger: Plugin ACF', 'simple-history'), // 1
|
695 |
+
esc_html($context["acf_modified_fields_{$loopnum}_name_prev"]) // 2
|
696 |
+
);
|
697 |
+
}
|
698 |
+
*/
|
699 |
+
|
700 |
+
// Add the label name manually, if it is not among the changed field,
|
701 |
+
// or we don't know what field the other changed values belongs to.
|
702 |
+
if ( empty( $context[ "acf_modified_fields_{$loopnum}_label_new" ] ) ) {
|
703 |
+
$strOneModifiedField .= sprintf(
|
704 |
+
_x( 'Label: %1$s', 'Logger: Plugin ACF', 'simple-history' ), // 1
|
705 |
+
esc_html( $context[ "acf_modified_fields_{$loopnum}_label_prev" ] ) // 2
|
706 |
+
);
|
707 |
+
}
|
708 |
+
|
709 |
+
// Check for other keys changed for this field
|
710 |
+
foreach ( $arrAddedFieldsKeysToCheck as $oneAddedFieldKeyToCheck => $oneAddedFieldKeyToCheckVals ) {
|
711 |
+
$newAndOldValsExists = isset( $context[ "acf_modified_fields_{$loopnum}_{$oneAddedFieldKeyToCheck}_new" ] ) && isset( $context[ "acf_modified_fields_{$loopnum}_{$oneAddedFieldKeyToCheck}_new" ] );
|
712 |
+
if ( $newAndOldValsExists ) {
|
713 |
+
$strOneModifiedField .= sprintf(
|
714 |
+
'
|
715 |
+
%4$s
|
716 |
+
%3$s
|
717 |
+
<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>
|
718 |
+
<del class="SimpleHistoryLogitem__keyValueTable__removedThing">%2$s</del>
|
719 |
+
',
|
720 |
+
esc_html( $context[ "acf_modified_fields_{$loopnum}_{$oneAddedFieldKeyToCheck}_new" ] ), // 1
|
721 |
+
esc_html( $context[ "acf_modified_fields_{$loopnum}_{$oneAddedFieldKeyToCheck}_prev" ] ), // 2
|
722 |
+
esc_html( $oneAddedFieldKeyToCheckVals['name'] ), // 3
|
723 |
+
empty( $strOneModifiedField ) ? '' : '<br>' // 4 new line
|
724 |
+
);
|
725 |
+
}
|
726 |
+
}
|
727 |
+
|
728 |
+
$strOneModifiedField = trim( $strOneModifiedField, ", \n\r\t" );
|
729 |
+
|
730 |
+
if ( $strOneModifiedField ) {
|
731 |
+
$strModifiedFields .= sprintf(
|
732 |
+
'<tr>
|
733 |
+
<td>%1$s</td>
|
734 |
+
<td>%2$s</td>
|
735 |
+
</tr>',
|
736 |
+
_x( 'Modified field', 'Logger: Plugin ACF', 'simple-history' ), // 1
|
737 |
+
$strOneModifiedField
|
738 |
+
);
|
739 |
+
}
|
740 |
+
|
741 |
+
$loopnum++;
|
742 |
+
}
|
743 |
+
|
744 |
+
/*
|
745 |
+
if ($strModifiedFields) {
|
746 |
+
$strModifiedFields = sprintf(
|
747 |
+
'<tr>
|
748 |
+
<td>%1$s</td>
|
749 |
+
<td>%2$s</td>
|
750 |
+
</tr>',
|
751 |
+
_nx('Modified field', 'Modified fields', $loopnum, 'Logger: Plugin ACF', 'simple-history'), // 1
|
752 |
+
$strModifiedFields
|
753 |
+
) . $strModifiedFields;
|
754 |
+
}*/
|
755 |
+
|
756 |
+
$diff_table_output .= $strModifiedFields;
|
757 |
+
} // if deleted fields
|
758 |
+
|
759 |
+
return $diff_table_output;
|
760 |
+
}
|
761 |
+
|
762 |
+
/**
|
763 |
+
* Append ACF data to post context.
|
764 |
+
*
|
765 |
+
* Called via filter `simple_history/post_logger/post_updated/context`.
|
766 |
+
*
|
767 |
+
* @param array $context
|
768 |
+
* @param WP_Post $post
|
769 |
+
*/
|
770 |
+
public function on_post_updated_context( $context, $post ) {
|
771 |
+
|
772 |
+
// Only act if this is a ACF field group that is saved
|
773 |
+
if ( $post->post_type !== 'acf-field-group' ) {
|
774 |
+
return $context;
|
775 |
+
}
|
776 |
+
|
777 |
+
// Remove some keys that we don't want,
|
778 |
+
// for example the content because that's just a json string
|
779 |
+
// in acf-field-group posts.
|
780 |
+
unset(
|
781 |
+
$context['post_prev_post_content'],
|
782 |
+
$context['post_new_post_content'],
|
783 |
+
$context['post_prev_post_name'],
|
784 |
+
$context['post_new_post_name'],
|
785 |
+
$context['post_prev_post_date'],
|
786 |
+
$context['post_new_post_date'],
|
787 |
+
$context['post_prev_post_date_gmt'],
|
788 |
+
$context['post_new_post_date_gmt']
|
789 |
+
);
|
790 |
+
|
791 |
+
$acf_data_diff = array();
|
792 |
+
|
793 |
+
// 'fieldGroup' fields to check.
|
794 |
+
$arr_field_group_keys_to_diff = array(
|
795 |
+
'menu_order',
|
796 |
+
'position',
|
797 |
+
'style',
|
798 |
+
'label_placement',
|
799 |
+
'instruction_placement',
|
800 |
+
'active',
|
801 |
+
'description',
|
802 |
+
);
|
803 |
+
|
804 |
+
$fieldGroup = $this->oldAndNewFieldGroupsAndFields['fieldGroup'];
|
805 |
+
|
806 |
+
foreach ( $arr_field_group_keys_to_diff as $key ) {
|
807 |
+
if ( isset( $fieldGroup['old'][ $key ] ) && isset( $fieldGroup['new'][ $key ] ) ) {
|
808 |
+
$acf_data_diff = $this->add_diff( $acf_data_diff, $key, (string) $fieldGroup['old'][ $key ], (string) $fieldGroup['new'][ $key ] );
|
809 |
+
}
|
810 |
+
}
|
811 |
+
|
812 |
+
foreach ( $acf_data_diff as $diff_key => $diff_values ) {
|
813 |
+
$context[ "acf_prev_{$diff_key}" ] = $diff_values['old'];
|
814 |
+
$context[ "acf_new_{$diff_key}" ] = $diff_values['new'];
|
815 |
+
}
|
816 |
+
|
817 |
+
// Add checked or uncheckd hide on screen-items to context
|
818 |
+
$arrhHideOnScreenAdded = array();
|
819 |
+
$arrHideOnScreenRemoved = array();
|
820 |
+
|
821 |
+
$fieldGroup['new']['hide_on_screen'] = isset( $fieldGroup['new']['hide_on_screen'] ) && is_array( $fieldGroup['new']['hide_on_screen'] ) ? $fieldGroup['new']['hide_on_screen'] : array();
|
822 |
+
$fieldGroup['old']['hide_on_screen'] = isset( $fieldGroup['old']['hide_on_screen'] ) && is_array( $fieldGroup['old']['hide_on_screen'] ) ? $fieldGroup['old']['hide_on_screen'] : array();
|
823 |
+
|
824 |
+
// dd($fieldGroup['old']['hide_on_screen'], $fieldGroup['new']['hide_on_screen']);
|
825 |
+
// Act when new or old hide_on_screen is set
|
826 |
+
if ( ! empty( $fieldGroup['new']['hide_on_screen'] ) || ! empty( $fieldGroup['old']['hide_on_screen'] ) ) {
|
827 |
+
$arrhHideOnScreenAdded = array_diff( $fieldGroup['new']['hide_on_screen'], $fieldGroup['old']['hide_on_screen'] );
|
828 |
+
$arrHideOnScreenRemoved = array_diff( $fieldGroup['old']['hide_on_screen'], $fieldGroup['new']['hide_on_screen'] );
|
829 |
+
|
830 |
+
// ddd($arrhHideOnScreenAdded, $arrHideOnScreenRemoved);
|
831 |
+
if ( $arrhHideOnScreenAdded ) {
|
832 |
+
$context['acf_hide_on_screen_added'] = implode( ',', $arrhHideOnScreenAdded );
|
833 |
+
}
|
834 |
+
|
835 |
+
if ( $arrHideOnScreenRemoved ) {
|
836 |
+
$context['acf_hide_on_screen_removed'] = implode( ',', $arrHideOnScreenRemoved );
|
837 |
+
}
|
838 |
+
}
|
839 |
+
|
840 |
+
// ddd($context, $arrhHideOnScreenAdded, $arrHideOnScreenRemoved);
|
841 |
+
// Add removed fields to context
|
842 |
+
if ( ! empty( $this->oldAndNewFieldGroupsAndFields['deletedFields'] ) && is_array( $this->oldAndNewFieldGroupsAndFields['deletedFields'] ) ) {
|
843 |
+
$loopnum = 0;
|
844 |
+
foreach ( $this->oldAndNewFieldGroupsAndFields['deletedFields'] as $oneDeletedField ) {
|
845 |
+
$context[ "acf_deleted_fields_{$loopnum}_key" ] = $oneDeletedField['key'];
|
846 |
+
$context[ "acf_deleted_fields_{$loopnum}_name" ] = $oneDeletedField['name'];
|
847 |
+
$context[ "acf_deleted_fields_{$loopnum}_label" ] = $oneDeletedField['label'];
|
848 |
+
$context[ "acf_deleted_fields_{$loopnum}_type" ] = $oneDeletedField['type'];
|
849 |
+
$loopnum++;
|
850 |
+
}
|
851 |
+
}
|
852 |
+
|
853 |
+
// Add added fields to context
|
854 |
+
if ( ! empty( $this->oldAndNewFieldGroupsAndFields['addedFields'] ) && is_array( $this->oldAndNewFieldGroupsAndFields['addedFields'] ) ) {
|
855 |
+
$loopnum = 0;
|
856 |
+
|
857 |
+
foreach ( $this->oldAndNewFieldGroupsAndFields['addedFields'] as $oneAddedField ) {
|
858 |
+
// Id not available here, wold be nice to have
|
859 |
+
// $context["acf_added_fields_{$loopnum}_ID"] = $oneAddedField['ID'];
|
860 |
+
$context[ "acf_added_fields_{$loopnum}_key" ] = $oneAddedField['key'];
|
861 |
+
$context[ "acf_added_fields_{$loopnum}_name" ] = $oneAddedField['name'];
|
862 |
+
$context[ "acf_added_fields_{$loopnum}_label" ] = $oneAddedField['label'];
|
863 |
+
$context[ "acf_added_fields_{$loopnum}_type" ] = $oneAddedField['type'];
|
864 |
+
$loopnum++;
|
865 |
+
}
|
866 |
+
}
|
867 |
+
|
868 |
+
// Add modified fields to context
|
869 |
+
// dd('on_post_updated_context', $context, $this->oldAndNewFieldGroupsAndFields);
|
870 |
+
if ( ! empty( $this->oldAndNewFieldGroupsAndFields['modifiedFields']['old'] ) && ! empty( $this->oldAndNewFieldGroupsAndFields['modifiedFields']['new'] ) ) {
|
871 |
+
$modifiedFields = $this->oldAndNewFieldGroupsAndFields['modifiedFields'];
|
872 |
+
|
873 |
+
$arrAddedFieldsKeysToAdd = array(
|
874 |
+
'parent',
|
875 |
+
'key',
|
876 |
+
'label',
|
877 |
+
'name',
|
878 |
+
'type',
|
879 |
+
);
|
880 |
+
|
881 |
+
$loopnum = 0;
|
882 |
+
|
883 |
+
foreach ( $modifiedFields['old'] as $modifiedFieldId => $modifiedFieldValues ) {
|
884 |
+
// Both old and new values mest exist
|
885 |
+
if ( empty( $modifiedFields['new'][ $modifiedFieldId ] ) ) {
|
886 |
+
continue;
|
887 |
+
}
|
888 |
+
|
889 |
+
// Always add ID, name, and lavel
|
890 |
+
$context[ "acf_modified_fields_{$loopnum}_ID_prev" ] = $modifiedFields['old'][ $modifiedFieldId ]['ID'];
|
891 |
+
$context[ "acf_modified_fields_{$loopnum}_name_prev" ] = $modifiedFields['old'][ $modifiedFieldId ]['name'];
|
892 |
+
$context[ "acf_modified_fields_{$loopnum}_label_prev" ] = $modifiedFields['old'][ $modifiedFieldId ]['label'];
|
893 |
+
|
894 |
+
foreach ( $arrAddedFieldsKeysToAdd as $oneKeyToAdd ) {
|
895 |
+
// dd($modifiedFields);
|
896 |
+
// Only add to context if modified
|
897 |
+
if ( $modifiedFields['new'][ $modifiedFieldId ][ $oneKeyToAdd ] != $modifiedFields['old'][ $modifiedFieldId ][ $oneKeyToAdd ] ) {
|
898 |
+
$context[ "acf_modified_fields_{$loopnum}_{$oneKeyToAdd}_prev" ] = $modifiedFields['old'][ $modifiedFieldId ][ $oneKeyToAdd ];
|
899 |
+
$context[ "acf_modified_fields_{$loopnum}_{$oneKeyToAdd}_new" ] = $modifiedFields['new'][ $modifiedFieldId ][ $oneKeyToAdd ];
|
900 |
+
}
|
901 |
+
}
|
902 |
+
|
903 |
+
$loopnum++;
|
904 |
+
}
|
905 |
+
}
|
906 |
+
|
907 |
+
return $context;
|
908 |
+
}
|
909 |
+
|
910 |
+
public function add_diff( $post_data_diff, $key, $old_value, $new_value ) {
|
911 |
+
if ( $old_value != $new_value ) {
|
912 |
+
$post_data_diff[ $key ] = array(
|
913 |
+
'old' => $old_value,
|
914 |
+
'new' => $new_value,
|
915 |
+
);
|
916 |
+
}
|
917 |
+
|
918 |
+
return $post_data_diff;
|
919 |
+
}
|
920 |
+
|
921 |
+
/**
|
922 |
+
* Store a version of the field group as it was before the save
|
923 |
+
* Called before field group post/values is added to db
|
924 |
+
*/
|
925 |
+
public function on_wp_insert_post_data( $data, $postarr ) {
|
926 |
+
|
927 |
+
// Only do this if ACF field group is being saved
|
928 |
+
if ( $postarr['post_type'] !== 'acf-field-group' ) {
|
929 |
+
return $data;
|
930 |
+
}
|
931 |
+
|
932 |
+
if ( empty( $postarr['ID'] ) ) {
|
933 |
+
return $data;
|
934 |
+
}
|
935 |
+
|
936 |
+
$this->oldAndNewFieldGroupsAndFields['fieldGroup']['old'] = acf_get_field_group( $postarr['ID'] );
|
937 |
+
|
938 |
+
$this->oldAndNewFieldGroupsAndFields['fieldGroup']['new'] = acf_get_valid_field_group( $_POST['acf_field_group'] );
|
939 |
+
|
940 |
+
return $data;
|
941 |
+
}
|
942 |
+
|
943 |
+
/**
|
944 |
+
* ACF field group is saved
|
945 |
+
* Called before ACF calls its save_post filter
|
946 |
+
* Here we save the new fields values and also get the old values so we can compare
|
947 |
+
*/
|
948 |
+
public function on_transition_post_status( $new_status, $old_status, $post ) {
|
949 |
+
static $isCalled = false;
|
950 |
+
|
951 |
+
if ( $isCalled ) {
|
952 |
+
return;
|
953 |
+
}
|
954 |
+
|
955 |
+
$isCalled = true;
|
956 |
+
|
957 |
+
$post_id = $post->ID;
|
958 |
+
|
959 |
+
// do not act if this is an auto save routine
|
960 |
+
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
|
961 |
+
return;
|
962 |
+
}
|
963 |
+
|
964 |
+
// bail early if not acf-field-group
|
965 |
+
if ( $post->post_type !== 'acf-field-group' ) {
|
966 |
+
return;
|
967 |
+
}
|
968 |
+
|
969 |
+
// only save once! WordPress save's a revision as well.
|
970 |
+
if ( wp_is_post_revision( $post_id ) ) {
|
971 |
+
return;
|
972 |
+
}
|
973 |
+
|
974 |
+
// Store info about fields that are going to be deleted
|
975 |
+
if ( ! empty( $_POST['_acf_delete_fields'] ) ) {
|
976 |
+
$deletedFieldsIDs = explode( '|', $_POST['_acf_delete_fields'] );
|
977 |
+
$deletedFieldsIDs = array_map( 'intval', $deletedFieldsIDs );
|
978 |
+
|
979 |
+
foreach ( $deletedFieldsIDs as $id ) {
|
980 |
+
if ( ! $id ) {
|
981 |
+
continue;
|
982 |
+
}
|
983 |
+
|
984 |
+
$field_info = acf_get_field( $id );
|
985 |
+
|
986 |
+
if ( ! $field_info ) {
|
987 |
+
continue;
|
988 |
+
}
|
989 |
+
|
990 |
+
$this->oldAndNewFieldGroupsAndFields['deletedFields'][ $id ] = $field_info;
|
991 |
+
}
|
992 |
+
}
|
993 |
+
|
994 |
+
// Store info about added or modified fields
|
995 |
+
if ( ! empty( $_POST['acf_fields'] ) && is_array( $_POST['acf_fields'] ) ) {
|
996 |
+
foreach ( $_POST['acf_fields'] as $oneFieldAddedOrUpdated ) {
|
997 |
+
if ( empty( $oneFieldAddedOrUpdated['ID'] ) ) {
|
998 |
+
// New fields have no id
|
999 |
+
// 'ID' => string(0) ""
|
1000 |
+
$this->oldAndNewFieldGroupsAndFields['addedFields'][] = $oneFieldAddedOrUpdated;
|
1001 |
+
} else {
|
1002 |
+
// Existing fields have an id
|
1003 |
+
// 'ID' => string(3) "383"
|
1004 |
+
$this->oldAndNewFieldGroupsAndFields['modifiedFields']['old'][ $oneFieldAddedOrUpdated['ID'] ] = acf_get_field( $oneFieldAddedOrUpdated['ID'] );
|
1005 |
+
|
1006 |
+
$this->oldAndNewFieldGroupsAndFields['modifiedFields']['new'][ $oneFieldAddedOrUpdated['ID'] ] = $oneFieldAddedOrUpdated;
|
1007 |
+
}
|
1008 |
+
}
|
1009 |
+
}
|
1010 |
+
|
1011 |
+
// We don't do anything else here, but we make the actual logging
|
1012 |
+
// in filter 'acf/update_field_group' beacuse it's safer because
|
1013 |
+
// ACF has done it's validation and it's after ACF has saved the fields,
|
1014 |
+
// so less likely that we make some critical error
|
1015 |
+
}
|
1016 |
+
|
1017 |
+
|
1018 |
+
/**
|
1019 |
+
* Add the post types that ACF uses for fields to the array of post types
|
1020 |
+
* that the default post logger should not log. If not each field will cause one
|
1021 |
+
* post update log message.
|
1022 |
+
*/
|
1023 |
+
public function remove_acf_from_postlogger( $skip_posttypes ) {
|
1024 |
+
array_push(
|
1025 |
+
$skip_posttypes,
|
1026 |
+
'acf-field'
|
1027 |
+
);
|
1028 |
+
|
1029 |
+
return $skip_posttypes;
|
1030 |
+
}
|
1031 |
+
} // Class.
|
1032 |
+
} // End if().
|
loggers/SimpleCategoriesLogger.php
CHANGED
@@ -43,61 +43,30 @@ class SimpleCategoriesLogger extends SimpleLogger {
|
|
43 |
|
44 |
}
|
45 |
|
46 |
-
|
47 |
-
*
|
48 |
-
|
49 |
-
* @since 2.3.0
|
50 |
-
*
|
51 |
-
* @param int $term_id Term ID.
|
52 |
-
* @param int $tt_id Term taxonomy ID.
|
53 |
-
* @param string $taxonomy Taxonomy slug.
|
54 |
-
do_action( 'created_term', $term_id, $tt_id, $taxonomy );
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
* Fires after a term has been updated, and the term cache has been cleaned.
|
59 |
-
*
|
60 |
-
* @since 2.3.0
|
61 |
-
*
|
62 |
-
* @param int $term_id Term ID.
|
63 |
-
* @param int $tt_id Term taxonomy ID.
|
64 |
-
* @param string $taxonomy Taxonomy slug.
|
65 |
-
do_action( "edited_term", $term_id, $tt_id, $taxonomy );
|
66 |
-
|
67 |
-
* Filter the term parent.
|
68 |
-
*
|
69 |
-
* Hook to this filter to see if it will cause a hierarchy loop.
|
70 |
-
*
|
71 |
-
* @since 3.1.0
|
72 |
-
*
|
73 |
-
* @param int $parent ID of the parent term.
|
74 |
-
* @param int $term_id Term ID.
|
75 |
-
* @param string $taxonomy Taxonomy slug.
|
76 |
-
* @param array $parsed_args An array of potentially altered update arguments for the given term.
|
77 |
-
* @param array $args An array of update arguments for the given term.
|
78 |
-
$parent = apply_filters( 'wp_update_term_parent', $args['parent'], $term_id, $taxonomy, $parsed_args, $args );
|
79 |
-
|
80 |
-
*/
|
81 |
-
|
82 |
public function loaded() {
|
83 |
-
|
84 |
add_action( 'created_term', array( $this, 'on_created_term' ), 10, 3 );
|
|
|
|
|
85 |
add_action( 'delete_term', array( $this, 'on_delete_term' ), 10, 4 );
|
86 |
-
add_action( 'wp_update_term_parent', array( $this, 'on_wp_update_term_parent' ), 10, 5 );
|
87 |
|
88 |
-
//
|
89 |
-
|
90 |
}
|
91 |
|
92 |
-
|
93 |
* Filter the term parent.
|
94 |
-
* Only way for Simple History to get both old and new term name
|
|
|
95 |
*
|
96 |
* @param int $parent ID of the parent term.
|
97 |
* @param int $term_id Term ID.
|
98 |
* @param string $taxonomy Taxonomy slug.
|
99 |
* @param array $parsed_args An array of potentially altered update arguments for the given term.
|
100 |
-
* @param array $
|
101 |
*/
|
102 |
function on_wp_update_term_parent( $parent = null, $term_id = null, $taxonomy = null, $parsed_args = null, $term_update_args = null ) {
|
103 |
|
@@ -119,6 +88,12 @@ class SimpleCategoriesLogger extends SimpleLogger {
|
|
119 |
$to_term_slug = $term_update_args['slug'];
|
120 |
$to_term_description = $term_update_args['description'];
|
121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
$this->infoMessage(
|
123 |
'edited_term',
|
124 |
array(
|
@@ -131,12 +106,6 @@ class SimpleCategoriesLogger extends SimpleLogger {
|
|
131 |
'to_term_taxonomy' => $to_term_taxonomy,
|
132 |
'to_term_slug' => $to_term_slug,
|
133 |
'to_term_description' => $to_term_description,
|
134 |
-
// "term_update_args" => $term_update_args,
|
135 |
-
// "term_before_edited" => $term_before_edited
|
136 |
-
// "parent" => $parent,
|
137 |
-
// "taxonomy" => $taxonomy,
|
138 |
-
// "parsed_args" => $parsed_args,
|
139 |
-
// "term_update_args" => $term_update_args
|
140 |
)
|
141 |
);
|
142 |
|
@@ -144,6 +113,46 @@ class SimpleCategoriesLogger extends SimpleLogger {
|
|
144 |
|
145 |
}
|
146 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
/*
|
148 |
* Fires after a new term is created, and after the term cache has been cleaned.
|
149 |
*
|
@@ -165,6 +174,12 @@ class SimpleCategoriesLogger extends SimpleLogger {
|
|
165 |
$term_taxonomy = $term->taxonomy;
|
166 |
$term_id = $term->term_id;
|
167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
$this->infoMessage(
|
169 |
'created_term',
|
170 |
array(
|
@@ -177,13 +192,13 @@ class SimpleCategoriesLogger extends SimpleLogger {
|
|
177 |
}
|
178 |
|
179 |
|
180 |
-
|
181 |
* Fires after a term is deleted from the database and the cache is cleaned.
|
182 |
*
|
183 |
-
* @param int
|
184 |
-
* @param int
|
185 |
-
* @param string
|
186 |
-
* @param mixed
|
187 |
* by the parent function. WP_Error otherwise.
|
188 |
*/
|
189 |
function on_delete_term( $term = null, $tt_id = null, $taxonomy = null, $deleted_term = null ) {
|
@@ -196,32 +211,82 @@ class SimpleCategoriesLogger extends SimpleLogger {
|
|
196 |
$term_taxonomy = $deleted_term->taxonomy;
|
197 |
$term_id = $deleted_term->term_id;
|
198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
$this->infoMessage(
|
200 |
'deleted_term',
|
201 |
array(
|
202 |
'term_id' => $term_id,
|
203 |
'term_name' => $term_name,
|
204 |
'term_taxonomy' => $term_taxonomy,
|
205 |
-
// "deleted_term" => $deleted_term,
|
206 |
)
|
207 |
);
|
208 |
|
209 |
}
|
210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
|
212 |
-
|
213 |
-
|
|
|
|
|
|
|
214 |
|
215 |
-
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
array(
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
)
|
222 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
|
|
224 |
}
|
225 |
-
*/
|
226 |
|
227 |
}
|
43 |
|
44 |
}
|
45 |
|
46 |
+
/**
|
47 |
+
* Called when the logger is loaded.
|
48 |
+
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
public function loaded() {
|
50 |
+
// Fires after a new term is created, and after the term cache has been cleaned..
|
51 |
add_action( 'created_term', array( $this, 'on_created_term' ), 10, 3 );
|
52 |
+
|
53 |
+
// Hook to this filter to see if it will cause a hierarchy loop.
|
54 |
add_action( 'delete_term', array( $this, 'on_delete_term' ), 10, 4 );
|
|
|
55 |
|
56 |
+
// Filter the term parent.
|
57 |
+
add_action( 'wp_update_term_parent', array( $this, 'on_wp_update_term_parent' ), 10, 5 );
|
58 |
}
|
59 |
|
60 |
+
/**
|
61 |
* Filter the term parent.
|
62 |
+
* Only way for Simple History to get both old and new term name.
|
63 |
+
* For example 'edited_term' does not contain enough info to know what the term was called before the update.
|
64 |
*
|
65 |
* @param int $parent ID of the parent term.
|
66 |
* @param int $term_id Term ID.
|
67 |
* @param string $taxonomy Taxonomy slug.
|
68 |
* @param array $parsed_args An array of potentially altered update arguments for the given term.
|
69 |
+
* @param array $term_update_args An array of update arguments for the given term.
|
70 |
*/
|
71 |
function on_wp_update_term_parent( $parent = null, $term_id = null, $taxonomy = null, $parsed_args = null, $term_update_args = null ) {
|
72 |
|
88 |
$to_term_slug = $term_update_args['slug'];
|
89 |
$to_term_description = $term_update_args['description'];
|
90 |
|
91 |
+
$do_log_term = $this->ok_to_log_taxonomy( $from_term_taxonomy );
|
92 |
+
|
93 |
+
if ( ! $do_log_term ) {
|
94 |
+
return $parent;
|
95 |
+
}
|
96 |
+
|
97 |
$this->infoMessage(
|
98 |
'edited_term',
|
99 |
array(
|
106 |
'to_term_taxonomy' => $to_term_taxonomy,
|
107 |
'to_term_slug' => $to_term_slug,
|
108 |
'to_term_description' => $to_term_description,
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
)
|
110 |
);
|
111 |
|
113 |
|
114 |
}
|
115 |
|
116 |
+
/**
|
117 |
+
* Check if it's ok to log a taxonomy.
|
118 |
+
* We skip some taxonomies, for example Polylang translation terms that fill the log with
|
119 |
+
* messages like 'Edited term "pll_5a3643a142c80" in taxonomy "post_translations"' otherwise.
|
120 |
+
*
|
121 |
+
* @since 2.21
|
122 |
+
* @param string $from_term_taxonomy Slug of taxonomy.
|
123 |
+
* @return bool True or false.
|
124 |
+
*/
|
125 |
+
function ok_to_log_taxonomy( $from_term_taxonomy = '' ) {
|
126 |
+
if ( empty( $from_term_taxonomy ) ) {
|
127 |
+
return false;
|
128 |
+
}
|
129 |
+
|
130 |
+
$skip_taxonomies = $this->get_skip_taxonomies();
|
131 |
+
|
132 |
+
$do_log = ! in_array( $from_term_taxonomy, $skip_taxonomies, true );
|
133 |
+
|
134 |
+
return $do_log;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Get taxonomies to skip.
|
139 |
+
*
|
140 |
+
* @since 2.21
|
141 |
+
* @return array Array with taxonomies.
|
142 |
+
*/
|
143 |
+
function get_skip_taxonomies() {
|
144 |
+
|
145 |
+
$taxonomies_to_skip = array(
|
146 |
+
// Polylang taxonomies used to store translation mappings.
|
147 |
+
'post_translations',
|
148 |
+
'term_translations',
|
149 |
+
);
|
150 |
+
|
151 |
+
$taxonomies_to_skip = apply_filters( 'simple_history/categories_logger/skip_taxonomies', $taxonomies_to_skip );
|
152 |
+
|
153 |
+
return $taxonomies_to_skip;
|
154 |
+
}
|
155 |
+
|
156 |
/*
|
157 |
* Fires after a new term is created, and after the term cache has been cleaned.
|
158 |
*
|
174 |
$term_taxonomy = $term->taxonomy;
|
175 |
$term_id = $term->term_id;
|
176 |
|
177 |
+
$do_log_term = $this->ok_to_log_taxonomy( $term_taxonomy );
|
178 |
+
|
179 |
+
if ( ! $do_log_term ) {
|
180 |
+
return;
|
181 |
+
}
|
182 |
+
|
183 |
$this->infoMessage(
|
184 |
'created_term',
|
185 |
array(
|
192 |
}
|
193 |
|
194 |
|
195 |
+
/**
|
196 |
* Fires after a term is deleted from the database and the cache is cleaned.
|
197 |
*
|
198 |
+
* @param int $term Term ID.
|
199 |
+
* @param int $tt_id Term taxonomy ID.
|
200 |
+
* @param string $taxonomy Taxonomy slug.
|
201 |
+
* @param mixed $deleted_term Copy of the already-deleted term, in the form specified
|
202 |
* by the parent function. WP_Error otherwise.
|
203 |
*/
|
204 |
function on_delete_term( $term = null, $tt_id = null, $taxonomy = null, $deleted_term = null ) {
|
211 |
$term_taxonomy = $deleted_term->taxonomy;
|
212 |
$term_id = $deleted_term->term_id;
|
213 |
|
214 |
+
$do_log_term = $this->ok_to_log_taxonomy( $term_taxonomy );
|
215 |
+
|
216 |
+
if ( ! $do_log_term ) {
|
217 |
+
return;
|
218 |
+
}
|
219 |
+
|
220 |
$this->infoMessage(
|
221 |
'deleted_term',
|
222 |
array(
|
223 |
'term_id' => $term_id,
|
224 |
'term_name' => $term_name,
|
225 |
'term_taxonomy' => $term_taxonomy,
|
|
|
226 |
)
|
227 |
);
|
228 |
|
229 |
}
|
230 |
|
231 |
+
/**
|
232 |
+
* Modify plain output to include link to term and taxonomy.
|
233 |
+
*
|
234 |
+
* @param array $row Row data.
|
235 |
+
*/
|
236 |
+
public function getLogRowPlainTextOutput( $row ) {
|
237 |
+
$context = $row->context;
|
238 |
+
$message_key = isset( $context['_message_key'] ) ? $context['_message_key'] : null;
|
239 |
|
240 |
+
// Default to original log message.
|
241 |
+
$message = $row->message;
|
242 |
+
|
243 |
+
// Get term that was created, edited, or removed.
|
244 |
+
$term_id = isset( $context['term_id'] ) ? (int) $context['term_id'] : null;
|
245 |
|
246 |
+
// Get taxonomy for term.
|
247 |
+
if ( 'created_term' === $message_key || 'deleted_term' === $message_key ) {
|
248 |
+
$term_taxonomy = isset( $context['term_taxonomy'] ) ? (string) $context['term_taxonomy'] : null;
|
249 |
+
} elseif ( 'edited_term' === $message_key ) {
|
250 |
+
$term_taxonomy = isset( $context['from_term_taxonomy'] ) ? (string) $context['from_term_taxonomy'] : null;
|
251 |
+
}
|
252 |
+
|
253 |
+
if ( is_wp_error( $term_object ) ) {
|
254 |
+
return $this->interpolate( $message, $context, $row );
|
255 |
+
}
|
256 |
+
|
257 |
+
$tax_edit_link = add_query_arg(
|
258 |
array(
|
259 |
+
'taxonomy' => $term_taxonomy,
|
260 |
+
),
|
261 |
+
admin_url( 'term.php' )
|
|
|
262 |
);
|
263 |
+
$context['tax_edit_link'] = $tax_edit_link;
|
264 |
+
|
265 |
+
$term_object = get_term( $term_id, $term_taxonomy );
|
266 |
+
$term_edit_link = get_edit_tag_link( $term_id, $term_object->taxonomy );
|
267 |
+
$context['term_edit_link'] = $term_edit_link;
|
268 |
+
|
269 |
+
if ( 'created_term' === $message_key && ! empty( $term_edit_link ) && ! empty( $tax_edit_link ) ) {
|
270 |
+
$message = _x(
|
271 |
+
'Added term <a href="{term_edit_link}">"{term_name}"</a> in taxonomy <a href="{tax_edit_link}">"{term_taxonomy}"</a>',
|
272 |
+
'Categories logger: detailed plain text output for created term',
|
273 |
+
'simple-history'
|
274 |
+
);
|
275 |
+
} elseif ( 'deleted_term' === $message_key && ! empty( $tax_edit_link ) ) {
|
276 |
+
$message = _x(
|
277 |
+
'Deleted term "{term_name}" from taxonomy <a href="{tax_edit_link}">"{term_taxonomy}"</a>',
|
278 |
+
'Categories logger: detailed plain text output for deleted term',
|
279 |
+
'simple-history'
|
280 |
+
);
|
281 |
+
} elseif ( 'edited_term' === $message_key && ! empty( $term_edit_link ) && ! empty( $tax_edit_link ) ) {
|
282 |
+
$message = _x(
|
283 |
+
'Edited term <a href="{term_edit_link}">"{to_term_name}"</a> in taxonomy <a href="{tax_edit_link}">"{to_term_taxonomy}"</a>',
|
284 |
+
'Categories logger: detailed plain text output for edited term',
|
285 |
+
'simple-history'
|
286 |
+
);
|
287 |
+
}
|
288 |
|
289 |
+
return $this->interpolate( $message, $context, $row );
|
290 |
}
|
|
|
291 |
|
292 |
}
|
loggers/SimpleLogger.php
CHANGED
@@ -36,10 +36,27 @@ class SimpleLogger {
|
|
36 |
public $messages;
|
37 |
|
38 |
/**
|
39 |
-
* ID of last inserted row
|
|
|
|
|
40 |
*/
|
41 |
public $lastInsertID;
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
/**
|
44 |
* Constructor. Remember to call this as parent constructor if making a childlogger
|
45 |
*
|
@@ -931,9 +948,9 @@ class SimpleLogger {
|
|
931 |
/**
|
932 |
* Logs with an arbitrary level.
|
933 |
*
|
934 |
-
* @param mixed $level The log level.
|
935 |
-
* @param string $message The log message.
|
936 |
-
* @param array $context The log context.
|
937 |
* @return class SimpleLogger instance
|
938 |
*/
|
939 |
public function log( $level = 'info', $message = '', $context = array() ) {
|
@@ -1049,7 +1066,7 @@ class SimpleLogger {
|
|
1049 |
|
1050 |
// No occasions id specified, create one bases on the data array
|
1051 |
$occasions_data = $data + $context;
|
1052 |
-
|
1053 |
// Don't include date in context data
|
1054 |
unset( $occasions_data['date'] );
|
1055 |
|
@@ -1188,8 +1205,7 @@ class SimpleLogger {
|
|
1188 |
}
|
1189 |
}
|
1190 |
|
1191 |
-
// Add remote addr to context
|
1192 |
-
// Good to always have
|
1193 |
if ( ! isset( $context['_server_remote_addr'] ) ) {
|
1194 |
|
1195 |
$context['_server_remote_addr'] = empty( $_SERVER['REMOTE_ADDR'] ) ? '' : $_SERVER['REMOTE_ADDR'];
|
@@ -1232,8 +1248,7 @@ class SimpleLogger {
|
|
1232 |
}
|
1233 |
}// End if().
|
1234 |
|
1235 |
-
// Append http referer
|
1236 |
-
// Also good to always have!
|
1237 |
if ( ! isset( $context['_server_http_referer'] ) && isset( $_SERVER['HTTP_REFERER'] ) ) {
|
1238 |
$context['_server_http_referer'] = $_SERVER['HTTP_REFERER'];
|
1239 |
}
|
@@ -1250,31 +1265,12 @@ class SimpleLogger {
|
|
1250 |
$context = apply_filters( 'simple_history/log_insert_context', $context, $data, $this );
|
1251 |
$data_parent_row = $data;
|
1252 |
|
1253 |
-
// Insert all context values into db
|
1254 |
-
|
1255 |
-
|
1256 |
-
// If value is array or object then use json_encode to store it
|
1257 |
-
// if ( is_object( $value ) || is_array( $value ) ) {
|
1258 |
-
// $value = simpleHistory::json_encode($value);
|
1259 |
-
// }
|
1260 |
-
// Any reason why the check is not the other way around?
|
1261 |
-
// Everything except strings should be json_encoded
|
1262 |
-
if ( ! is_string( $value ) ) {
|
1263 |
-
$value = simpleHistory::json_encode( $value );
|
1264 |
-
}
|
1265 |
-
|
1266 |
-
$data = array(
|
1267 |
-
'history_id' => $history_inserted_id,
|
1268 |
-
'key' => $key,
|
1269 |
-
'value' => $value,
|
1270 |
-
);
|
1271 |
-
|
1272 |
-
$result = $wpdb->insert( $db_table_contexts, $data );
|
1273 |
-
|
1274 |
-
}
|
1275 |
}// End if().
|
1276 |
|
1277 |
$this->lastInsertID = $history_inserted_id;
|
|
|
1278 |
|
1279 |
$this->simpleHistory->get_cache_incrementor( true );
|
1280 |
|
@@ -1283,17 +1279,52 @@ class SimpleLogger {
|
|
1283 |
*
|
1284 |
* @since 2.5.1
|
1285 |
*
|
1286 |
-
* @param array $context Array with all context data
|
1287 |
* @param array $data Array with data used for parent row.
|
1288 |
* @param array $this Reference to this logger instance
|
1289 |
*/
|
1290 |
do_action( 'simple_history/log/inserted', $context, $data_parent_row, $this );
|
1291 |
|
1292 |
-
// Return $this so we can chain methods
|
1293 |
return $this;
|
1294 |
|
1295 |
} // log
|
1296 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1297 |
/**
|
1298 |
* Returns array with headers that may contain user IP
|
1299 |
*
|
@@ -1318,6 +1349,8 @@ class SimpleLogger {
|
|
1318 |
* Returns additional headers with ip number from context
|
1319 |
*
|
1320 |
* @since 2.0.29
|
|
|
|
|
1321 |
*/
|
1322 |
function get_event_ip_number_headers( $row ) {
|
1323 |
|
@@ -1346,6 +1379,9 @@ class SimpleLogger {
|
|
1346 |
/**
|
1347 |
* Ensures an ip address is both a valid IP and does not fall within
|
1348 |
* a private network range.
|
|
|
|
|
|
|
1349 |
*/
|
1350 |
function validate_ip( $ip ) {
|
1351 |
|
@@ -1397,21 +1433,21 @@ class SimpleLogger {
|
|
1397 |
class SimpleLoggerLogInitiators {
|
1398 |
|
1399 |
// A wordpress user that at the log event created did exist in the wp database
|
1400 |
-
// May have been deleted when the log is viewed
|
1401 |
const WP_USER = 'wp_user';
|
1402 |
|
1403 |
// Cron job run = wordpress initiated
|
1404 |
// Email sent to customer on webshop = system/wordpress/anonymous web user
|
1405 |
-
// Javascript error occured on website = anonymous web user
|
1406 |
const WEB_USER = 'web_user';
|
1407 |
|
1408 |
-
// WordPress core or plugins updated automatically via wp-cron
|
1409 |
const WORDPRESS = 'wp';
|
1410 |
|
1411 |
-
// WP CLI / terminal
|
1412 |
const WP_CLI = 'wp_cli';
|
1413 |
|
1414 |
-
// I dunno
|
1415 |
const OTHER = 'other';
|
1416 |
}
|
1417 |
|
36 |
public $messages;
|
37 |
|
38 |
/**
|
39 |
+
* ID of last inserted row
|
40 |
+
*
|
41 |
+
* @var int $lastInsertID Database row primary key.
|
42 |
*/
|
43 |
public $lastInsertID;
|
44 |
|
45 |
+
/**
|
46 |
+
* Context of last inserted row.
|
47 |
+
*
|
48 |
+
* @var int $lastInsertContext Context used for the last insert.
|
49 |
+
* @since 2.2x
|
50 |
+
*/
|
51 |
+
public $lastInsertContext;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Simple History instance.
|
55 |
+
*
|
56 |
+
* @var object $simpleHistory Simple history instance.
|
57 |
+
*/
|
58 |
+
public $simpleHistory;
|
59 |
+
|
60 |
/**
|
61 |
* Constructor. Remember to call this as parent constructor if making a childlogger
|
62 |
*
|
948 |
/**
|
949 |
* Logs with an arbitrary level.
|
950 |
*
|
951 |
+
* @param mixed $level The log level. Default "info".
|
952 |
+
* @param string $message The log message. Default "".
|
953 |
+
* @param array $context The log context. Default empty array.
|
954 |
* @return class SimpleLogger instance
|
955 |
*/
|
956 |
public function log( $level = 'info', $message = '', $context = array() ) {
|
1066 |
|
1067 |
// No occasions id specified, create one bases on the data array
|
1068 |
$occasions_data = $data + $context;
|
1069 |
+
|
1070 |
// Don't include date in context data
|
1071 |
unset( $occasions_data['date'] );
|
1072 |
|
1205 |
}
|
1206 |
}
|
1207 |
|
1208 |
+
// Add remote addr to context.
|
|
|
1209 |
if ( ! isset( $context['_server_remote_addr'] ) ) {
|
1210 |
|
1211 |
$context['_server_remote_addr'] = empty( $_SERVER['REMOTE_ADDR'] ) ? '' : $_SERVER['REMOTE_ADDR'];
|
1248 |
}
|
1249 |
}// End if().
|
1250 |
|
1251 |
+
// Append http referer.
|
|
|
1252 |
if ( ! isset( $context['_server_http_referer'] ) && isset( $_SERVER['HTTP_REFERER'] ) ) {
|
1253 |
$context['_server_http_referer'] = $_SERVER['HTTP_REFERER'];
|
1254 |
}
|
1265 |
$context = apply_filters( 'simple_history/log_insert_context', $context, $data, $this );
|
1266 |
$data_parent_row = $data;
|
1267 |
|
1268 |
+
// Insert all context values into db.
|
1269 |
+
$this->append_context( $history_inserted_id, $context );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1270 |
}// End if().
|
1271 |
|
1272 |
$this->lastInsertID = $history_inserted_id;
|
1273 |
+
$this->lastInsertContext = $context;
|
1274 |
|
1275 |
$this->simpleHistory->get_cache_incrementor( true );
|
1276 |
|
1279 |
*
|
1280 |
* @since 2.5.1
|
1281 |
*
|
1282 |
+
* @param array $context Array with all context data that was used to log event.
|
1283 |
* @param array $data Array with data used for parent row.
|
1284 |
* @param array $this Reference to this logger instance
|
1285 |
*/
|
1286 |
do_action( 'simple_history/log/inserted', $context, $data_parent_row, $this );
|
1287 |
|
1288 |
+
// Return $this so we can chain methods.
|
1289 |
return $this;
|
1290 |
|
1291 |
} // log
|
1292 |
|
1293 |
+
/**
|
1294 |
+
* Append new info to the contextof history item with id $post_logger->lastInsertID..
|
1295 |
+
*
|
1296 |
+
* @param int $history_id The id of the history row to add context to.
|
1297 |
+
* @param array $context Context to append to existing context for the row.
|
1298 |
+
* @return bool True if context was added, false if not (beacuse row_id or context is empty).
|
1299 |
+
*/
|
1300 |
+
public function append_context( $history_id, $context ) {
|
1301 |
+
if ( empty( $history_id ) || empty( $context ) ) {
|
1302 |
+
return false;
|
1303 |
+
}
|
1304 |
+
|
1305 |
+
global $wpdb;
|
1306 |
+
|
1307 |
+
$db_table_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
|
1308 |
+
|
1309 |
+
foreach ( $context as $key => $value ) {
|
1310 |
+
|
1311 |
+
// Everything except strings should be json_encoded, ie. arrays and objects.
|
1312 |
+
if ( ! is_string( $value ) ) {
|
1313 |
+
$value = simpleHistory::json_encode( $value );
|
1314 |
+
}
|
1315 |
+
|
1316 |
+
$data = array(
|
1317 |
+
'history_id' => $history_id,
|
1318 |
+
'key' => $key,
|
1319 |
+
'value' => $value,
|
1320 |
+
);
|
1321 |
+
|
1322 |
+
$result = $wpdb->insert( $db_table_contexts, $data );
|
1323 |
+
}
|
1324 |
+
|
1325 |
+
return true;
|
1326 |
+
}
|
1327 |
+
|
1328 |
/**
|
1329 |
* Returns array with headers that may contain user IP
|
1330 |
*
|
1349 |
* Returns additional headers with ip number from context
|
1350 |
*
|
1351 |
* @since 2.0.29
|
1352 |
+
* @param array $row Row with info.
|
1353 |
+
* @return array Headers
|
1354 |
*/
|
1355 |
function get_event_ip_number_headers( $row ) {
|
1356 |
|
1379 |
/**
|
1380 |
* Ensures an ip address is both a valid IP and does not fall within
|
1381 |
* a private network range.
|
1382 |
+
*
|
1383 |
+
* @param string $ip IP number.
|
1384 |
+
* @return bool
|
1385 |
*/
|
1386 |
function validate_ip( $ip ) {
|
1387 |
|
1433 |
class SimpleLoggerLogInitiators {
|
1434 |
|
1435 |
// A wordpress user that at the log event created did exist in the wp database
|
1436 |
+
// May have been deleted when the log is viewed.
|
1437 |
const WP_USER = 'wp_user';
|
1438 |
|
1439 |
// Cron job run = wordpress initiated
|
1440 |
// Email sent to customer on webshop = system/wordpress/anonymous web user
|
1441 |
+
// Javascript error occured on website = anonymous web user.
|
1442 |
const WEB_USER = 'web_user';
|
1443 |
|
1444 |
+
// WordPress core or plugins updated automatically via wp-cron.
|
1445 |
const WORDPRESS = 'wp';
|
1446 |
|
1447 |
+
// WP CLI / terminal.
|
1448 |
const WP_CLI = 'wp_cli';
|
1449 |
|
1450 |
+
// I dunno.
|
1451 |
const OTHER = 'other';
|
1452 |
}
|
1453 |
|
loggers/SimplePluginLogger.php
CHANGED
@@ -3,12 +3,12 @@
|
|
3 |
defined( 'ABSPATH' ) || die();
|
4 |
|
5 |
/**
|
6 |
-
* Logs plugin installs, updates, and deletions
|
7 |
*/
|
8 |
class SimplePluginLogger extends SimpleLogger {
|
9 |
|
10 |
/**
|
11 |
-
* The logger slug. Defaulting to the class name is nice and logical I think
|
12 |
*
|
13 |
* @var string $slug
|
14 |
*/
|
@@ -28,58 +28,58 @@ class SimplePluginLogger extends SimpleLogger {
|
|
28 |
*
|
29 |
* @return array
|
30 |
*/
|
31 |
-
function getInfo() {
|
32 |
|
33 |
$arr_info = array(
|
34 |
-
'name'
|
35 |
'description' => 'Logs plugin installs, uninstalls and updates',
|
36 |
-
'capability'
|
37 |
-
'messages'
|
38 |
|
39 |
-
'plugin_activated'
|
40 |
'Activated plugin "{plugin_name}"',
|
41 |
'Plugin was non-silently activated by a user',
|
42 |
'simple-history'
|
43 |
),
|
44 |
|
45 |
-
'plugin_deactivated'
|
46 |
'Deactivated plugin "{plugin_name}"',
|
47 |
'Plugin was non-silently deactivated by a user',
|
48 |
'simple-history'
|
49 |
),
|
50 |
|
51 |
-
'plugin_installed'
|
52 |
'Installed plugin "{plugin_name}"',
|
53 |
'Plugin was installed',
|
54 |
'simple-history'
|
55 |
),
|
56 |
|
57 |
-
'plugin_installed_failed'
|
58 |
'Failed to install plugin "{plugin_name}"',
|
59 |
'Plugin failed to install',
|
60 |
'simple-history'
|
61 |
),
|
62 |
|
63 |
-
'plugin_updated'
|
64 |
'Updated plugin "{plugin_name}" to version {plugin_version} from {plugin_prev_version}',
|
65 |
'Plugin was updated',
|
66 |
'simple-history'
|
67 |
),
|
68 |
|
69 |
-
'plugin_update_failed'
|
70 |
'Failed to update plugin "{plugin_name}"',
|
71 |
'Plugin update failed',
|
72 |
'simple-history'
|
73 |
),
|
74 |
|
75 |
-
'plugin_deleted'
|
76 |
'Deleted plugin "{plugin_name}"',
|
77 |
'Plugin files was deleted',
|
78 |
'simple-history'
|
79 |
),
|
80 |
|
81 |
// Bulk versions.
|
82 |
-
'plugin_bulk_updated'
|
83 |
'Updated plugin "{plugin_name}" to {plugin_version} from {plugin_prev_version}',
|
84 |
'Plugin was updated in bulk',
|
85 |
'simple-history'
|
@@ -93,33 +93,33 @@ class SimplePluginLogger extends SimpleLogger {
|
|
93 |
),
|
94 |
|
95 |
), // Messages.
|
96 |
-
'labels'
|
97 |
'search' => array(
|
98 |
-
'label'
|
99 |
'label_all' => _x( 'All plugin activity', 'Plugin logger: search', 'simple-history' ),
|
100 |
-
'options'
|
101 |
_x( 'Activated plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
102 |
-
'plugin_activated'
|
103 |
),
|
104 |
_x( 'Deactivated plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
105 |
'plugin_deactivated',
|
106 |
'plugin_disabled_because_error',
|
107 |
),
|
108 |
_x( 'Installed plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
109 |
-
'plugin_installed'
|
110 |
),
|
111 |
_x( 'Failed plugin installs', 'Plugin logger: search', 'simple-history' ) => array(
|
112 |
-
'plugin_installed_failed'
|
113 |
),
|
114 |
_x( 'Updated plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
115 |
'plugin_updated',
|
116 |
'plugin_bulk_updated',
|
117 |
),
|
118 |
_x( 'Failed plugin updates', 'Plugin logger: search', 'simple-history' ) => array(
|
119 |
-
'plugin_update_failed'
|
120 |
),
|
121 |
_x( 'Deleted plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
122 |
-
'plugin_deleted'
|
123 |
),
|
124 |
),
|
125 |
), // search array.
|
@@ -154,24 +154,26 @@ class SimplePluginLogger extends SimpleLogger {
|
|
154 |
// this hook does not fire.
|
155 |
add_action( 'deactivated_plugin', array( $this, 'on_deactivated_plugin' ), 10, 2 );
|
156 |
|
157 |
-
// Fires after the upgrades has done it's thing
|
158 |
-
// Check hook extra for upgrader initiator
|
159 |
add_action( 'upgrader_process_complete', array( $this, 'on_upgrader_process_complete' ), 10, 2 );
|
160 |
|
161 |
-
// Detect files removed
|
162 |
add_action( 'setted_transient', array( $this, 'on_setted_transient_for_remove_files' ), 10, 2 );
|
163 |
|
164 |
add_action( 'admin_action_delete-selected', array( $this, 'on_action_delete_selected' ), 10, 1 );
|
165 |
|
166 |
-
// Ajax function to get info from GitHub repo. Used by "View plugin info"-link for plugin installs
|
167 |
add_action( 'wp_ajax_SimplePluginLogger_GetGitHubPluginInfo', array( $this, 'ajax_GetGitHubPluginInfo' ) );
|
168 |
|
169 |
// If the Github Update plugin is not installed we need to get extra fields used by it.
|
170 |
// So need to hook filter "extra_plugin_headers" ourself.
|
171 |
-
add_filter(
|
172 |
-
$arr_headers
|
173 |
-
|
174 |
-
|
|
|
|
|
175 |
|
176 |
// There is no way to use a filter and detect a plugin that is disabled because it can't be found or similar error.
|
177 |
// So we hook into gettext and look for the usage of the error that is returned when this happens.
|
@@ -229,7 +231,7 @@ class SimplePluginLogger extends SimpleLogger {
|
|
229 |
* we hook into gettext and look for the usage of the error that is returned when this happens.
|
230 |
*
|
231 |
* A plugin gets deactivated when plugins.php is visited function validate_active_plugins()
|
232 |
-
*
|
233 |
* and if invalid plugin is found then this is outputed
|
234 |
* printf(
|
235 |
* /* translators: 1: plugin file 2: error message
|
@@ -246,7 +248,7 @@ class SimplePluginLogger extends SimpleLogger {
|
|
246 |
global $pagenow;
|
247 |
|
248 |
// We only act on page plugins.php.
|
249 |
-
if ( ! isset( $pagenow ) ||
|
250 |
return $translation;
|
251 |
}
|
252 |
|
@@ -254,7 +256,7 @@ class SimplePluginLogger extends SimpleLogger {
|
|
254 |
// (Literally these, no translation)
|
255 |
$untranslated_texts = array(
|
256 |
// This string is called later than the above
|
257 |
-
'The plugin %1$s has been <strong>deactivated</strong> due to an error: %2$s'
|
258 |
);
|
259 |
|
260 |
if ( ! in_array( $text, $untranslated_texts ) ) {
|
@@ -267,28 +269,30 @@ class SimplePluginLogger extends SimpleLogger {
|
|
267 |
// stuff the first time it's called (directly after the gettet for the plugin disabled-error..).
|
268 |
$logger_instance = $this;
|
269 |
|
270 |
-
add_filter(
|
271 |
-
|
|
|
272 |
|
273 |
-
|
274 |
-
|
275 |
|
276 |
-
|
277 |
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
|
290 |
-
|
291 |
-
|
|
|
292 |
|
293 |
return $translation;
|
294 |
|
@@ -315,18 +319,20 @@ class SimplePluginLogger extends SimpleLogger {
|
|
315 |
}
|
316 |
|
317 |
$repo_username = $repo_parts[3];
|
318 |
-
$repo_repo
|
319 |
|
320 |
// https://developer.github.com/v3/repos/contents/
|
321 |
// https://api.github.com/repos/<username>/<repo>/readme
|
322 |
$api_url = sprintf( 'https://api.github.com/repos/%1$s/%2$s/readme', urlencode( $repo_username ), urlencode( $repo_repo ) );
|
323 |
|
324 |
// Get file. Use accept-header to get file as HTML instead of JSON
|
325 |
-
$response = wp_remote_get(
|
326 |
-
|
327 |
-
'
|
328 |
-
|
329 |
-
|
|
|
|
|
330 |
|
331 |
$response_body = wp_remote_retrieve_body( $response );
|
332 |
|
@@ -458,28 +464,28 @@ class SimplePluginLogger extends SimpleLogger {
|
|
458 |
) {
|
459 |
|
460 |
/*
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
|
467 |
-
$plugins_deleted
|
468 |
$plugins_before_update = json_decode( get_option( $this->slug . '_plugin_info_before_update', false ), true );
|
469 |
|
470 |
foreach ( $plugins_deleted as $plugin ) {
|
471 |
|
472 |
$context = array(
|
473 |
-
'plugin' => $plugin
|
474 |
);
|
475 |
|
476 |
if ( is_array( $plugins_before_update ) && isset( $plugins_before_update[ $plugin ] ) ) {
|
477 |
-
$context['plugin_name']
|
478 |
-
$context['plugin_title']
|
479 |
$context['plugin_description'] = $plugins_before_update[ $plugin ]['Description'];
|
480 |
-
$context['plugin_author']
|
481 |
-
$context['plugin_version']
|
482 |
-
$context['plugin_url']
|
483 |
}
|
484 |
|
485 |
$this->infoMessage(
|
@@ -565,10 +571,10 @@ class SimplePluginLogger extends SimpleLogger {
|
|
565 |
If an update fails then $plugin_upgrader_instance->skin->result->errors contains something like:
|
566 |
Array
|
567 |
(
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
|
573 |
)
|
574 |
*/
|
@@ -581,8 +587,8 @@ class SimplePluginLogger extends SimpleLogger {
|
|
581 |
$arr_data:
|
582 |
Array
|
583 |
(
|
584 |
-
|
585 |
-
|
586 |
)
|
587 |
|
588 |
|
@@ -591,8 +597,8 @@ class SimplePluginLogger extends SimpleLogger {
|
|
591 |
$arr_data:
|
592 |
Array
|
593 |
(
|
594 |
-
|
595 |
-
|
596 |
)
|
597 |
|
598 |
|
@@ -601,8 +607,8 @@ class SimplePluginLogger extends SimpleLogger {
|
|
601 |
$arr_data:
|
602 |
Array
|
603 |
(
|
604 |
-
|
605 |
-
|
606 |
)
|
607 |
|
608 |
## Bulk actions
|
@@ -626,24 +632,24 @@ class SimplePluginLogger extends SimpleLogger {
|
|
626 |
if ( isset( $arr_data['action'] ) && 'install' == $arr_data['action'] && ! $plugin_upgrader_instance->bulk ) {
|
627 |
|
628 |
$upgrader_skin_options = isset( $plugin_upgrader_instance->skin->options ) && is_array( $plugin_upgrader_instance->skin->options ) ? $plugin_upgrader_instance->skin->options : array();
|
629 |
-
$upgrader_skin_result
|
630 |
-
$upgrader_skin_api
|
631 |
|
632 |
$plugin_slug = isset( $upgrader_skin_result['destination_name'] ) ? $upgrader_skin_result['destination_name'] : '';
|
633 |
|
634 |
// Upgrader contains current info
|
635 |
$context = array(
|
636 |
-
'plugin_slug'
|
637 |
-
'plugin_name'
|
638 |
-
'plugin_version'
|
639 |
-
'plugin_author'
|
640 |
'plugin_last_updated' => isset( $upgrader_skin_api->last_updated ) ? $upgrader_skin_api->last_updated : '',
|
641 |
-
'plugin_requires'
|
642 |
-
'plugin_tested'
|
643 |
-
'plugin_rating'
|
644 |
-
'plugin_num_ratings'
|
645 |
-
'plugin_downloaded'
|
646 |
-
'plugin_added'
|
647 |
'plugin_source_files' => $this->simpleHistory->json_encode( $plugin_upgrader_instance->result['source_files'] ),
|
648 |
|
649 |
// To debug comment out these:
|
@@ -674,18 +680,18 @@ class SimplePluginLogger extends SimpleLogger {
|
|
674 |
/*
|
675 |
_debug_files
|
676 |
{
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
}
|
685 |
*/
|
686 |
|
687 |
if ( isset( $_FILES['pluginzip']['name'] ) ) {
|
688 |
-
$plugin_upload_name
|
689 |
$context['plugin_upload_name'] = $plugin_upload_name;
|
690 |
}
|
691 |
}
|
@@ -695,7 +701,7 @@ class SimplePluginLogger extends SimpleLogger {
|
|
695 |
// Add errors
|
696 |
// Errors is in original wp admin language
|
697 |
$context['error_messages'] = $this->simpleHistory->json_encode( $plugin_upgrader_instance->skin->result->errors );
|
698 |
-
$context['error_data']
|
699 |
|
700 |
$this->infoMessage(
|
701 |
'plugin_installed_failed',
|
@@ -720,11 +726,11 @@ class SimplePluginLogger extends SimpleLogger {
|
|
720 |
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_info, true, false );
|
721 |
}
|
722 |
|
723 |
-
$context['plugin_name']
|
724 |
$context['plugin_description'] = isset( $plugin_data['Description'] ) ? $plugin_data['Description'] : '';
|
725 |
-
$context['plugin_url']
|
726 |
-
$context['plugin_version']
|
727 |
-
$context['plugin_author']
|
728 |
|
729 |
// Comment out these to debug plugin installs
|
730 |
// $context["debug_plugin_data"] = $this->simpleHistory->json_encode( $plugin_data );
|
@@ -757,14 +763,14 @@ class SimplePluginLogger extends SimpleLogger {
|
|
757 |
$plugin_slug = dirname( $arr_data['plugin'] );
|
758 |
|
759 |
$context = array(
|
760 |
-
'plugin_slug'
|
761 |
-
'request'
|
762 |
-
'plugin_name'
|
763 |
-
'plugin_title'
|
764 |
-
'plugin_description'
|
765 |
-
'plugin_author'
|
766 |
-
'plugin_version'
|
767 |
-
'plugin_url'
|
768 |
'plugin_source_files' => $this->simpleHistory->json_encode( $plugin_upgrader_instance->result['source_files'] ),
|
769 |
);
|
770 |
|
@@ -813,7 +819,7 @@ class SimplePluginLogger extends SimpleLogger {
|
|
813 |
// Add errors
|
814 |
// Errors is in original wp admin language
|
815 |
$context['error_messages'] = json_encode( $plugin_upgrader_instance->skin->result->errors );
|
816 |
-
$context['error_data']
|
817 |
|
818 |
$this->infoMessage(
|
819 |
'plugin_update_failed',
|
@@ -862,13 +868,13 @@ class SimplePluginLogger extends SimpleLogger {
|
|
862 |
$plugin_slug = dirname( $plugin_name );
|
863 |
|
864 |
$context = array(
|
865 |
-
'plugin_slug'
|
866 |
-
'plugin_name'
|
867 |
-
'plugin_title'
|
868 |
'plugin_description' => $plugin_data['Description'],
|
869 |
-
'plugin_author'
|
870 |
-
'plugin_version'
|
871 |
-
'plugin_url'
|
872 |
);
|
873 |
|
874 |
// get url and package
|
@@ -954,13 +960,13 @@ class SimplePluginLogger extends SimpleLogger {
|
|
954 |
$plugin_slug = dirname( $plugin_name );
|
955 |
|
956 |
$context = array(
|
957 |
-
'plugin_name'
|
958 |
-
'plugin_slug'
|
959 |
-
'plugin_title'
|
960 |
'plugin_description' => $plugin_data['Description'],
|
961 |
-
'plugin_author'
|
962 |
-
'plugin_version'
|
963 |
-
'plugin_url'
|
964 |
);
|
965 |
|
966 |
if ( ! empty( $plugin_data['GitHub Plugin URI'] ) ) {
|
@@ -981,13 +987,13 @@ class SimplePluginLogger extends SimpleLogger {
|
|
981 |
$plugin_slug = dirname( $plugin_name );
|
982 |
|
983 |
$context = array(
|
984 |
-
'plugin_name'
|
985 |
-
'plugin_slug'
|
986 |
-
'plugin_title'
|
987 |
'plugin_description' => $plugin_data['Description'],
|
988 |
-
'plugin_author'
|
989 |
-
'plugin_version'
|
990 |
-
'plugin_url'
|
991 |
);
|
992 |
|
993 |
if ( ! empty( $plugin_data['GitHub Plugin URI'] ) ) {
|
@@ -1004,9 +1010,9 @@ class SimplePluginLogger extends SimpleLogger {
|
|
1004 |
*/
|
1005 |
function getLogRowDetailsOutput( $row ) {
|
1006 |
|
1007 |
-
$context
|
1008 |
$message_key = $context['_message_key'];
|
1009 |
-
$output
|
1010 |
|
1011 |
// When a plugin is installed we show a bit more information
|
1012 |
// We do it only on install because we don't want to clutter to log,
|
@@ -1018,19 +1024,19 @@ class SimplePluginLogger extends SimpleLogger {
|
|
1018 |
|
1019 |
// Description includes a link to author, remove that, i.e. all text after and including <cite>
|
1020 |
$plugin_description = $context['plugin_description'];
|
1021 |
-
$cite_pos
|
1022 |
if ( $cite_pos ) {
|
1023 |
$plugin_description = substr( $plugin_description, 0, $cite_pos );
|
1024 |
}
|
1025 |
|
1026 |
// Keys to show
|
1027 |
$arr_plugin_keys = array(
|
1028 |
-
'plugin_description'
|
1029 |
-
'plugin_install_source'
|
1030 |
'plugin_install_source_file' => _x( 'Source file name', 'plugin logger - detailed output install source', 'simple-history' ),
|
1031 |
-
'plugin_version'
|
1032 |
-
'plugin_author'
|
1033 |
-
'plugin_url'
|
1034 |
// "plugin_downloaded" => _x("Downloads", "plugin logger - detailed output downloaded", "simple-history"),
|
1035 |
// "plugin_requires" => _x("Requires", "plugin logger - detailed output author", "simple-history"),
|
1036 |
// "plugin_tested" => _x("Compatible up to", "plugin logger - detailed output compatible", "simple-history"),
|
@@ -1067,7 +1073,6 @@ class SimplePluginLogger extends SimpleLogger {
|
|
1067 |
break;
|
1068 |
|
1069 |
case 'plugin_install_source':
|
1070 |
-
|
1071 |
if ( ! isset( $context[ $key ] ) ) {
|
1072 |
continue;
|
1073 |
}
|
@@ -1086,14 +1091,13 @@ class SimplePluginLogger extends SimpleLogger {
|
|
1086 |
break;
|
1087 |
|
1088 |
case 'plugin_install_source_file':
|
1089 |
-
|
1090 |
if ( ! isset( $context['plugin_upload_name'] ) || ! isset( $context['plugin_install_source'] ) ) {
|
1091 |
continue;
|
1092 |
}
|
1093 |
|
1094 |
if ( 'upload' == $context['plugin_install_source'] ) {
|
1095 |
$plugin_upload_name = $context['plugin_upload_name'];
|
1096 |
-
$desc_output
|
1097 |
}
|
1098 |
|
1099 |
break;
|
@@ -1169,7 +1173,7 @@ class SimplePluginLogger extends SimpleLogger {
|
|
1169 |
if ( $plugin_slug && empty( $context['plugin_github_url'] ) ) {
|
1170 |
|
1171 |
$link_title = esc_html_x( 'View plugin info', 'plugin logger: plugin info thickbox title', 'simple-history' );
|
1172 |
-
$url
|
1173 |
|
1174 |
if ( 'plugin_updated' == $message_key || 'plugin_bulk_updated' == $message_key ) {
|
1175 |
|
@@ -1201,7 +1205,7 @@ class SimplePluginLogger extends SimpleLogger {
|
|
1201 |
esc_html_x( 'View plugin info', 'plugin logger: plugin info thickbox title view all info', 'simple-history' )
|
1202 |
);
|
1203 |
|
1204 |
-
}// End if().
|
1205 |
} // End if().
|
1206 |
|
1207 |
return $output;
|
3 |
defined( 'ABSPATH' ) || die();
|
4 |
|
5 |
/**
|
6 |
+
* Logs plugin installs, updates, and deletions.
|
7 |
*/
|
8 |
class SimplePluginLogger extends SimpleLogger {
|
9 |
|
10 |
/**
|
11 |
+
* The logger slug. Defaulting to the class name is nice and logical I think.
|
12 |
*
|
13 |
* @var string $slug
|
14 |
*/
|
28 |
*
|
29 |
* @return array
|
30 |
*/
|
31 |
+
public function getInfo() {
|
32 |
|
33 |
$arr_info = array(
|
34 |
+
'name' => 'Plugin Logger',
|
35 |
'description' => 'Logs plugin installs, uninstalls and updates',
|
36 |
+
'capability' => 'activate_plugins',
|
37 |
+
'messages' => array(
|
38 |
|
39 |
+
'plugin_activated' => _x(
|
40 |
'Activated plugin "{plugin_name}"',
|
41 |
'Plugin was non-silently activated by a user',
|
42 |
'simple-history'
|
43 |
),
|
44 |
|
45 |
+
'plugin_deactivated' => _x(
|
46 |
'Deactivated plugin "{plugin_name}"',
|
47 |
'Plugin was non-silently deactivated by a user',
|
48 |
'simple-history'
|
49 |
),
|
50 |
|
51 |
+
'plugin_installed' => _x(
|
52 |
'Installed plugin "{plugin_name}"',
|
53 |
'Plugin was installed',
|
54 |
'simple-history'
|
55 |
),
|
56 |
|
57 |
+
'plugin_installed_failed' => _x(
|
58 |
'Failed to install plugin "{plugin_name}"',
|
59 |
'Plugin failed to install',
|
60 |
'simple-history'
|
61 |
),
|
62 |
|
63 |
+
'plugin_updated' => _x(
|
64 |
'Updated plugin "{plugin_name}" to version {plugin_version} from {plugin_prev_version}',
|
65 |
'Plugin was updated',
|
66 |
'simple-history'
|
67 |
),
|
68 |
|
69 |
+
'plugin_update_failed' => _x(
|
70 |
'Failed to update plugin "{plugin_name}"',
|
71 |
'Plugin update failed',
|
72 |
'simple-history'
|
73 |
),
|
74 |
|
75 |
+
'plugin_deleted' => _x(
|
76 |
'Deleted plugin "{plugin_name}"',
|
77 |
'Plugin files was deleted',
|
78 |
'simple-history'
|
79 |
),
|
80 |
|
81 |
// Bulk versions.
|
82 |
+
'plugin_bulk_updated' => _x(
|
83 |
'Updated plugin "{plugin_name}" to {plugin_version} from {plugin_prev_version}',
|
84 |
'Plugin was updated in bulk',
|
85 |
'simple-history'
|
93 |
),
|
94 |
|
95 |
), // Messages.
|
96 |
+
'labels' => array(
|
97 |
'search' => array(
|
98 |
+
'label' => _x( 'Plugins', 'Plugin logger: search', 'simple-history' ),
|
99 |
'label_all' => _x( 'All plugin activity', 'Plugin logger: search', 'simple-history' ),
|
100 |
+
'options' => array(
|
101 |
_x( 'Activated plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
102 |
+
'plugin_activated',
|
103 |
),
|
104 |
_x( 'Deactivated plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
105 |
'plugin_deactivated',
|
106 |
'plugin_disabled_because_error',
|
107 |
),
|
108 |
_x( 'Installed plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
109 |
+
'plugin_installed',
|
110 |
),
|
111 |
_x( 'Failed plugin installs', 'Plugin logger: search', 'simple-history' ) => array(
|
112 |
+
'plugin_installed_failed',
|
113 |
),
|
114 |
_x( 'Updated plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
115 |
'plugin_updated',
|
116 |
'plugin_bulk_updated',
|
117 |
),
|
118 |
_x( 'Failed plugin updates', 'Plugin logger: search', 'simple-history' ) => array(
|
119 |
+
'plugin_update_failed',
|
120 |
),
|
121 |
_x( 'Deleted plugins', 'Plugin logger: search', 'simple-history' ) => array(
|
122 |
+
'plugin_deleted',
|
123 |
),
|
124 |
),
|
125 |
), // search array.
|
154 |
// this hook does not fire.
|
155 |
add_action( 'deactivated_plugin', array( $this, 'on_deactivated_plugin' ), 10, 2 );
|
156 |
|
157 |
+
// Fires after the upgrades has done it's thing.
|
158 |
+
// Check hook extra for upgrader initiator.
|
159 |
add_action( 'upgrader_process_complete', array( $this, 'on_upgrader_process_complete' ), 10, 2 );
|
160 |
|
161 |
+
// Detect files removed.
|
162 |
add_action( 'setted_transient', array( $this, 'on_setted_transient_for_remove_files' ), 10, 2 );
|
163 |
|
164 |
add_action( 'admin_action_delete-selected', array( $this, 'on_action_delete_selected' ), 10, 1 );
|
165 |
|
166 |
+
// Ajax function to get info from GitHub repo. Used by "View plugin info"-link for plugin installs.
|
167 |
add_action( 'wp_ajax_SimplePluginLogger_GetGitHubPluginInfo', array( $this, 'ajax_GetGitHubPluginInfo' ) );
|
168 |
|
169 |
// If the Github Update plugin is not installed we need to get extra fields used by it.
|
170 |
// So need to hook filter "extra_plugin_headers" ourself.
|
171 |
+
add_filter(
|
172 |
+
'extra_plugin_headers', function( $arr_headers ) {
|
173 |
+
$arr_headers[] = 'GitHub Plugin URI';
|
174 |
+
return $arr_headers;
|
175 |
+
}
|
176 |
+
);
|
177 |
|
178 |
// There is no way to use a filter and detect a plugin that is disabled because it can't be found or similar error.
|
179 |
// So we hook into gettext and look for the usage of the error that is returned when this happens.
|
231 |
* we hook into gettext and look for the usage of the error that is returned when this happens.
|
232 |
*
|
233 |
* A plugin gets deactivated when plugins.php is visited function validate_active_plugins()
|
234 |
+
* return new WP_Error('plugin_not_found', __('Plugin file does not exist.'));
|
235 |
* and if invalid plugin is found then this is outputed
|
236 |
* printf(
|
237 |
* /* translators: 1: plugin file 2: error message
|
248 |
global $pagenow;
|
249 |
|
250 |
// We only act on page plugins.php.
|
251 |
+
if ( ! isset( $pagenow ) || 'plugins.php' !== $pagenow ) {
|
252 |
return $translation;
|
253 |
}
|
254 |
|
256 |
// (Literally these, no translation)
|
257 |
$untranslated_texts = array(
|
258 |
// This string is called later than the above
|
259 |
+
'The plugin %1$s has been <strong>deactivated</strong> due to an error: %2$s',
|
260 |
);
|
261 |
|
262 |
if ( ! in_array( $text, $untranslated_texts ) ) {
|
269 |
// stuff the first time it's called (directly after the gettet for the plugin disabled-error..).
|
270 |
$logger_instance = $this;
|
271 |
|
272 |
+
add_filter(
|
273 |
+
'esc_html', function( $safe_text, $text ) use ( $logger_instance ) {
|
274 |
+
static $is_called = false;
|
275 |
|
276 |
+
if ( false === $is_called ) {
|
277 |
+
$is_called = true;
|
278 |
|
279 |
+
$deactivation_reason = array_shift( $logger_instance->latest_plugin_deactivation_because_of_error_reason );
|
280 |
|
281 |
+
// We don't know what plugin that was that got this error and currently there does not seem to be a way to determine that.
|
282 |
+
// So that's why we use such generic log messages.
|
283 |
+
$logger_instance->warningMessage(
|
284 |
+
'plugin_disabled_because_error',
|
285 |
+
array(
|
286 |
+
'_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
|
287 |
+
'plugin_slug' => $text,
|
288 |
+
'deactivation_reason' => $deactivation_reason,
|
289 |
+
)
|
290 |
+
);
|
291 |
+
}
|
292 |
|
293 |
+
return $safe_text;
|
294 |
+
}, 10, 2
|
295 |
+
);
|
296 |
|
297 |
return $translation;
|
298 |
|
319 |
}
|
320 |
|
321 |
$repo_username = $repo_parts[3];
|
322 |
+
$repo_repo = $repo_parts[4];
|
323 |
|
324 |
// https://developer.github.com/v3/repos/contents/
|
325 |
// https://api.github.com/repos/<username>/<repo>/readme
|
326 |
$api_url = sprintf( 'https://api.github.com/repos/%1$s/%2$s/readme', urlencode( $repo_username ), urlencode( $repo_repo ) );
|
327 |
|
328 |
// Get file. Use accept-header to get file as HTML instead of JSON
|
329 |
+
$response = wp_remote_get(
|
330 |
+
$api_url, array(
|
331 |
+
'headers' => array(
|
332 |
+
'accept' => 'application/vnd.github.VERSION.html',
|
333 |
+
),
|
334 |
+
)
|
335 |
+
);
|
336 |
|
337 |
$response_body = wp_remote_retrieve_body( $response );
|
338 |
|
464 |
) {
|
465 |
|
466 |
/*
|
467 |
+
[checked] => Array
|
468 |
+
(
|
469 |
+
[0] => the-events-calendar/the-events-calendar.php
|
470 |
+
)
|
471 |
+
*/
|
472 |
|
473 |
+
$plugins_deleted = $_POST['checked'];
|
474 |
$plugins_before_update = json_decode( get_option( $this->slug . '_plugin_info_before_update', false ), true );
|
475 |
|
476 |
foreach ( $plugins_deleted as $plugin ) {
|
477 |
|
478 |
$context = array(
|
479 |
+
'plugin' => $plugin, // plugin-name-folder/plugin-main-file.php
|
480 |
);
|
481 |
|
482 |
if ( is_array( $plugins_before_update ) && isset( $plugins_before_update[ $plugin ] ) ) {
|
483 |
+
$context['plugin_name'] = $plugins_before_update[ $plugin ]['Name'];
|
484 |
+
$context['plugin_title'] = $plugins_before_update[ $plugin ]['Title'];
|
485 |
$context['plugin_description'] = $plugins_before_update[ $plugin ]['Description'];
|
486 |
+
$context['plugin_author'] = $plugins_before_update[ $plugin ]['Author'];
|
487 |
+
$context['plugin_version'] = $plugins_before_update[ $plugin ]['Version'];
|
488 |
+
$context['plugin_url'] = $plugins_before_update[ $plugin ]['PluginURI'];
|
489 |
}
|
490 |
|
491 |
$this->infoMessage(
|
571 |
If an update fails then $plugin_upgrader_instance->skin->result->errors contains something like:
|
572 |
Array
|
573 |
(
|
574 |
+
[remove_old_failed] => Array
|
575 |
+
(
|
576 |
+
[0] => Could not remove the old plugin.
|
577 |
+
)
|
578 |
|
579 |
)
|
580 |
*/
|
587 |
$arr_data:
|
588 |
Array
|
589 |
(
|
590 |
+
[action] => update
|
591 |
+
[type] => core
|
592 |
)
|
593 |
|
594 |
|
597 |
$arr_data:
|
598 |
Array
|
599 |
(
|
600 |
+
[type] => plugin
|
601 |
+
[action] => install
|
602 |
)
|
603 |
|
604 |
|
607 |
$arr_data:
|
608 |
Array
|
609 |
(
|
610 |
+
[type] => plugin
|
611 |
+
[action] => install
|
612 |
)
|
613 |
|
614 |
## Bulk actions
|
632 |
if ( isset( $arr_data['action'] ) && 'install' == $arr_data['action'] && ! $plugin_upgrader_instance->bulk ) {
|
633 |
|
634 |
$upgrader_skin_options = isset( $plugin_upgrader_instance->skin->options ) && is_array( $plugin_upgrader_instance->skin->options ) ? $plugin_upgrader_instance->skin->options : array();
|
635 |
+
$upgrader_skin_result = isset( $plugin_upgrader_instance->skin->result ) && is_array( $plugin_upgrader_instance->skin->result ) ? $plugin_upgrader_instance->skin->result : array();
|
636 |
+
$upgrader_skin_api = isset( $plugin_upgrader_instance->skin->api ) ? $plugin_upgrader_instance->skin->api : (object) array();
|
637 |
|
638 |
$plugin_slug = isset( $upgrader_skin_result['destination_name'] ) ? $upgrader_skin_result['destination_name'] : '';
|
639 |
|
640 |
// Upgrader contains current info
|
641 |
$context = array(
|
642 |
+
'plugin_slug' => $plugin_slug,
|
643 |
+
'plugin_name' => isset( $upgrader_skin_api->name ) ? $upgrader_skin_api->name : '',
|
644 |
+
'plugin_version' => isset( $upgrader_skin_api->version ) ? $upgrader_skin_api->version : '',
|
645 |
+
'plugin_author' => isset( $upgrader_skin_api->author ) ? $upgrader_skin_api->author : '',
|
646 |
'plugin_last_updated' => isset( $upgrader_skin_api->last_updated ) ? $upgrader_skin_api->last_updated : '',
|
647 |
+
'plugin_requires' => isset( $upgrader_skin_api->requires ) ? $upgrader_skin_api->requires : '',
|
648 |
+
'plugin_tested' => isset( $upgrader_skin_api->tested ) ? $upgrader_skin_api->tested : '',
|
649 |
+
'plugin_rating' => isset( $upgrader_skin_api->rating ) ? $upgrader_skin_api->rating : '',
|
650 |
+
'plugin_num_ratings' => isset( $upgrader_skin_api->num_ratings ) ? $upgrader_skin_api->num_ratings : '',
|
651 |
+
'plugin_downloaded' => isset( $upgrader_skin_api->downloaded ) ? $upgrader_skin_api->downloaded : '',
|
652 |
+
'plugin_added' => isset( $upgrader_skin_api->added ) ? $upgrader_skin_api->added : '',
|
653 |
'plugin_source_files' => $this->simpleHistory->json_encode( $plugin_upgrader_instance->result['source_files'] ),
|
654 |
|
655 |
// To debug comment out these:
|
680 |
/*
|
681 |
_debug_files
|
682 |
{
|
683 |
+
"pluginzip": {
|
684 |
+
"name": "WPThumb-master.zip",
|
685 |
+
"type": "application\/zip",
|
686 |
+
"tmp_name": "\/Applications\/MAMP\/tmp\/php\/phpnThImc",
|
687 |
+
"error": 0,
|
688 |
+
"size": 2394625
|
689 |
+
}
|
690 |
}
|
691 |
*/
|
692 |
|
693 |
if ( isset( $_FILES['pluginzip']['name'] ) ) {
|
694 |
+
$plugin_upload_name = $_FILES['pluginzip']['name'];
|
695 |
$context['plugin_upload_name'] = $plugin_upload_name;
|
696 |
}
|
697 |
}
|
701 |
// Add errors
|
702 |
// Errors is in original wp admin language
|
703 |
$context['error_messages'] = $this->simpleHistory->json_encode( $plugin_upgrader_instance->skin->result->errors );
|
704 |
+
$context['error_data'] = $this->simpleHistory->json_encode( $plugin_upgrader_instance->skin->result->error_data );
|
705 |
|
706 |
$this->infoMessage(
|
707 |
'plugin_installed_failed',
|
726 |
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_info, true, false );
|
727 |
}
|
728 |
|
729 |
+
$context['plugin_name'] = isset( $plugin_data['Name'] ) ? $plugin_data['Name'] : '';
|
730 |
$context['plugin_description'] = isset( $plugin_data['Description'] ) ? $plugin_data['Description'] : '';
|
731 |
+
$context['plugin_url'] = isset( $plugin_data['PluginURI'] ) ? $plugin_data['PluginURI'] : '';
|
732 |
+
$context['plugin_version'] = isset( $plugin_data['Version'] ) ? $plugin_data['Version'] : '';
|
733 |
+
$context['plugin_author'] = isset( $plugin_data['AuthorName'] ) ? $plugin_data['AuthorName'] : '';
|
734 |
|
735 |
// Comment out these to debug plugin installs
|
736 |
// $context["debug_plugin_data"] = $this->simpleHistory->json_encode( $plugin_data );
|
763 |
$plugin_slug = dirname( $arr_data['plugin'] );
|
764 |
|
765 |
$context = array(
|
766 |
+
'plugin_slug' => $plugin_slug,
|
767 |
+
'request' => $this->simpleHistory->json_encode( $_REQUEST ),
|
768 |
+
'plugin_name' => $plugin_data['Name'],
|
769 |
+
'plugin_title' => $plugin_data['Title'],
|
770 |
+
'plugin_description' => $plugin_data['Description'],
|
771 |
+
'plugin_author' => $plugin_data['Author'],
|
772 |
+
'plugin_version' => $plugin_data['Version'],
|
773 |
+
'plugin_url' => $plugin_data['PluginURI'],
|
774 |
'plugin_source_files' => $this->simpleHistory->json_encode( $plugin_upgrader_instance->result['source_files'] ),
|
775 |
);
|
776 |
|
819 |
// Add errors
|
820 |
// Errors is in original wp admin language
|
821 |
$context['error_messages'] = json_encode( $plugin_upgrader_instance->skin->result->errors );
|
822 |
+
$context['error_data'] = json_encode( $plugin_upgrader_instance->skin->result->error_data );
|
823 |
|
824 |
$this->infoMessage(
|
825 |
'plugin_update_failed',
|
868 |
$plugin_slug = dirname( $plugin_name );
|
869 |
|
870 |
$context = array(
|
871 |
+
'plugin_slug' => $plugin_slug,
|
872 |
+
'plugin_name' => $plugin_data['Name'],
|
873 |
+
'plugin_title' => $plugin_data['Title'],
|
874 |
'plugin_description' => $plugin_data['Description'],
|
875 |
+
'plugin_author' => $plugin_data['Author'],
|
876 |
+
'plugin_version' => $plugin_data['Version'],
|
877 |
+
'plugin_url' => $plugin_data['PluginURI'],
|
878 |
);
|
879 |
|
880 |
// get url and package
|
960 |
$plugin_slug = dirname( $plugin_name );
|
961 |
|
962 |
$context = array(
|
963 |
+
'plugin_name' => $plugin_data['Name'],
|
964 |
+
'plugin_slug' => $plugin_slug,
|
965 |
+
'plugin_title' => $plugin_data['Title'],
|
966 |
'plugin_description' => $plugin_data['Description'],
|
967 |
+
'plugin_author' => $plugin_data['Author'],
|
968 |
+
'plugin_version' => $plugin_data['Version'],
|
969 |
+
'plugin_url' => $plugin_data['PluginURI'],
|
970 |
);
|
971 |
|
972 |
if ( ! empty( $plugin_data['GitHub Plugin URI'] ) ) {
|
987 |
$plugin_slug = dirname( $plugin_name );
|
988 |
|
989 |
$context = array(
|
990 |
+
'plugin_name' => $plugin_data['Name'],
|
991 |
+
'plugin_slug' => $plugin_slug,
|
992 |
+
'plugin_title' => $plugin_data['Title'],
|
993 |
'plugin_description' => $plugin_data['Description'],
|
994 |
+
'plugin_author' => $plugin_data['Author'],
|
995 |
+
'plugin_version' => $plugin_data['Version'],
|
996 |
+
'plugin_url' => $plugin_data['PluginURI'],
|
997 |
);
|
998 |
|
999 |
if ( ! empty( $plugin_data['GitHub Plugin URI'] ) ) {
|
1010 |
*/
|
1011 |
function getLogRowDetailsOutput( $row ) {
|
1012 |
|
1013 |
+
$context = $row->context;
|
1014 |
$message_key = $context['_message_key'];
|
1015 |
+
$output = '';
|
1016 |
|
1017 |
// When a plugin is installed we show a bit more information
|
1018 |
// We do it only on install because we don't want to clutter to log,
|
1024 |
|
1025 |
// Description includes a link to author, remove that, i.e. all text after and including <cite>
|
1026 |
$plugin_description = $context['plugin_description'];
|
1027 |
+
$cite_pos = strpos( $plugin_description, '<cite>' );
|
1028 |
if ( $cite_pos ) {
|
1029 |
$plugin_description = substr( $plugin_description, 0, $cite_pos );
|
1030 |
}
|
1031 |
|
1032 |
// Keys to show
|
1033 |
$arr_plugin_keys = array(
|
1034 |
+
'plugin_description' => _x( 'Description', 'plugin logger - detailed output', 'simple-history' ),
|
1035 |
+
'plugin_install_source' => _x( 'Source', 'plugin logger - detailed output install source', 'simple-history' ),
|
1036 |
'plugin_install_source_file' => _x( 'Source file name', 'plugin logger - detailed output install source', 'simple-history' ),
|
1037 |
+
'plugin_version' => _x( 'Version', 'plugin logger - detailed output version', 'simple-history' ),
|
1038 |
+
'plugin_author' => _x( 'Author', 'plugin logger - detailed output author', 'simple-history' ),
|
1039 |
+
'plugin_url' => _x( 'URL', 'plugin logger - detailed output url', 'simple-history' ),
|
1040 |
// "plugin_downloaded" => _x("Downloads", "plugin logger - detailed output downloaded", "simple-history"),
|
1041 |
// "plugin_requires" => _x("Requires", "plugin logger - detailed output author", "simple-history"),
|
1042 |
// "plugin_tested" => _x("Compatible up to", "plugin logger - detailed output compatible", "simple-history"),
|
1073 |
break;
|
1074 |
|
1075 |
case 'plugin_install_source':
|
|
|
1076 |
if ( ! isset( $context[ $key ] ) ) {
|
1077 |
continue;
|
1078 |
}
|
1091 |
break;
|
1092 |
|
1093 |
case 'plugin_install_source_file':
|
|
|
1094 |
if ( ! isset( $context['plugin_upload_name'] ) || ! isset( $context['plugin_install_source'] ) ) {
|
1095 |
continue;
|
1096 |
}
|
1097 |
|
1098 |
if ( 'upload' == $context['plugin_install_source'] ) {
|
1099 |
$plugin_upload_name = $context['plugin_upload_name'];
|
1100 |
+
$desc_output = esc_html( $plugin_upload_name );
|
1101 |
}
|
1102 |
|
1103 |
break;
|
1173 |
if ( $plugin_slug && empty( $context['plugin_github_url'] ) ) {
|
1174 |
|
1175 |
$link_title = esc_html_x( 'View plugin info', 'plugin logger: plugin info thickbox title', 'simple-history' );
|
1176 |
+
$url = admin_url( "plugin-install.php?tab=plugin-information&plugin={$plugin_slug}&section=&TB_iframe=true&width=640&height=550" );
|
1177 |
|
1178 |
if ( 'plugin_updated' == $message_key || 'plugin_bulk_updated' == $message_key ) {
|
1179 |
|
1205 |
esc_html_x( 'View plugin info', 'plugin logger: plugin info thickbox title view all info', 'simple-history' )
|
1206 |
);
|
1207 |
|
1208 |
+
} // End if().
|
1209 |
} // End if().
|
1210 |
|
1211 |
return $output;
|
loggers/SimplePostLogger.php
CHANGED
@@ -2,7 +2,6 @@
|
|
2 |
|
3 |
defined( 'ABSPATH' ) or die();
|
4 |
|
5 |
-
|
6 |
/**
|
7 |
* Logs changes to posts and pages, including custom post types
|
8 |
*/
|
@@ -175,9 +174,13 @@ class SimplePostLogger extends SimpleLogger {
|
|
175 |
|
176 |
$prev_post_data = get_post( $post_ID );
|
177 |
|
178 |
-
|
179 |
-
|
180 |
-
|
|
|
|
|
|
|
|
|
181 |
);
|
182 |
|
183 |
}
|
@@ -255,6 +258,10 @@ class SimplePostLogger extends SimpleLogger {
|
|
255 |
|
256 |
$post = get_post( $post_id );
|
257 |
|
|
|
|
|
|
|
|
|
258 |
$this->infoMessage(
|
259 |
'post_restored',
|
260 |
array(
|
@@ -315,13 +322,52 @@ class SimplePostLogger extends SimpleLogger {
|
|
315 |
|
316 |
}
|
317 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
|
319 |
/**
|
320 |
-
*
|
321 |
-
*
|
322 |
-
* because when always enabled it catches a lots of edits made by plugins during cron jobs etc,
|
323 |
-
* which by definition is not wrong, but perhaps not wanted/annoying
|
324 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
function on_transition_post_status( $new_status, $old_status, $post ) {
|
326 |
|
327 |
$ok_to_log = true;
|
@@ -344,25 +390,23 @@ class SimplePostLogger extends SimpleLogger {
|
|
344 |
$ok_to_log = false;
|
345 |
}
|
346 |
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
'nav_menu_item',
|
351 |
-
// Don't log jetpack migration-things.
|
352 |
-
// https://wordpress.org/support/topic/updated-jetpack_migration-sidebars_widgets/.
|
353 |
-
'jetpack_migration',
|
354 |
-
);
|
355 |
|
356 |
/**
|
357 |
-
* Filter to
|
358 |
*
|
359 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
*/
|
361 |
-
$
|
362 |
-
|
363 |
-
if ( in_array( get_post_type( $post ), $skip_posttypes, true ) ) {
|
364 |
-
$ok_to_log = false;
|
365 |
-
}
|
366 |
|
367 |
if ( ! $ok_to_log ) {
|
368 |
return;
|
@@ -421,7 +465,15 @@ class SimplePostLogger extends SimpleLogger {
|
|
421 |
|
422 |
$context['_occasionsID'] = __CLASS__ . '/' . __FUNCTION__ . "/post_updated/{$post->ID}";
|
423 |
|
424 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
|
426 |
}// End if().
|
427 |
|
@@ -654,7 +706,7 @@ class SimplePostLogger extends SimpleLogger {
|
|
654 |
}
|
655 |
|
656 |
/**
|
657 |
-
* Modify plain output to include link to post
|
658 |
*
|
659 |
* @param array $row Row data.
|
660 |
*/
|
@@ -960,6 +1012,15 @@ class SimplePostLogger extends SimpleLogger {
|
|
960 |
// post_new_thumb, int of new thumb, empty if no new thumb.
|
961 |
$diff_table_output .= $this->getLogRowDetailsOutputForPostThumb( $context );
|
962 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
963 |
if ( $has_diff_values || $diff_table_output ) {
|
964 |
|
965 |
$diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
|
@@ -1060,6 +1121,8 @@ class SimplePostLogger extends SimpleLogger {
|
|
1060 |
// Check if images still exists and if so get their thumbnails.
|
1061 |
$prev_thumb_id = empty( $context['post_prev_thumb_id'] ) ? null : $context['post_prev_thumb_id'];
|
1062 |
$new_thumb_id = empty( $context['post_new_thumb_id'] ) ? null : $context['post_new_thumb_id'];
|
|
|
|
|
1063 |
|
1064 |
$prev_attached_file = get_attached_file( $prev_thumb_id );
|
1065 |
$prev_thumb_src = wp_get_attachment_image_src( $prev_thumb_id, 'small' );
|
@@ -1077,13 +1140,13 @@ class SimplePostLogger extends SimpleLogger {
|
|
1077 |
</div>
|
1078 |
',
|
1079 |
$prev_thumb_src[0],
|
1080 |
-
esc_html( $
|
1081 |
);
|
1082 |
} else {
|
1083 |
// Fallback if image does not exist.
|
1084 |
$prev_thumb_html = sprintf(
|
1085 |
'<div>%1$s</div>',
|
1086 |
-
esc_html( $
|
1087 |
);
|
1088 |
}
|
1089 |
|
@@ -1097,13 +1160,13 @@ class SimplePostLogger extends SimpleLogger {
|
|
1097 |
</div>
|
1098 |
',
|
1099 |
$new_thumb_src[0],
|
1100 |
-
esc_html( $
|
1101 |
);
|
1102 |
} else {
|
1103 |
// Fallback if image does not exist.
|
1104 |
$prev_thumb_html = sprintf(
|
1105 |
'<div>%1$s</div>',
|
1106 |
-
esc_html( $
|
1107 |
);
|
1108 |
}
|
1109 |
|
@@ -1131,7 +1194,7 @@ class SimplePostLogger extends SimpleLogger {
|
|
1131 |
</td>
|
1132 |
</tr>',
|
1133 |
esc_html( __( 'Featured image', 'simple-history' ) ), // 1
|
1134 |
-
$prev_thumb_html
|
1135 |
$new_thumb_html // 3
|
1136 |
);
|
1137 |
} // End if().
|
2 |
|
3 |
defined( 'ABSPATH' ) or die();
|
4 |
|
|
|
5 |
/**
|
6 |
* Logs changes to posts and pages, including custom post types
|
7 |
*/
|
174 |
|
175 |
$prev_post_data = get_post( $post_ID );
|
176 |
|
177 |
+
if (is_wp_error($prev_post_data)) {
|
178 |
+
return;
|
179 |
+
}
|
180 |
+
|
181 |
+
$this->old_post_data[$post_ID] = array(
|
182 |
+
"post_data" => $prev_post_data,
|
183 |
+
"post_meta" => get_post_custom( $post_ID )
|
184 |
);
|
185 |
|
186 |
}
|
258 |
|
259 |
$post = get_post( $post_id );
|
260 |
|
261 |
+
if ( ! $this->ok_to_log_post_posttype( $post ) ) {
|
262 |
+
return;
|
263 |
+
}
|
264 |
+
|
265 |
$this->infoMessage(
|
266 |
'post_restored',
|
267 |
array(
|
322 |
|
323 |
}
|
324 |
|
325 |
+
/**
|
326 |
+
* Get an array of post types that should not be logged by this logger.
|
327 |
+
*/
|
328 |
+
public function get_skip_posttypes() {
|
329 |
+
$skip_posttypes = array(
|
330 |
+
// Don't log nav_menu_updates.
|
331 |
+
'nav_menu_item',
|
332 |
+
// Don't log jetpack migration-things.
|
333 |
+
// https://wordpress.org/support/topic/updated-jetpack_migration-sidebars_widgets/.
|
334 |
+
'jetpack_migration',
|
335 |
+
'jp_sitemap',
|
336 |
+
'jp_img_sitemap',
|
337 |
+
'jp_sitemap_master',
|
338 |
+
);
|
339 |
+
|
340 |
+
/**
|
341 |
+
* Filter to log what post types not to log
|
342 |
+
*
|
343 |
+
* @since 2.18
|
344 |
+
*/
|
345 |
+
$skip_posttypes = apply_filters( 'simple_history/post_logger/skip_posttypes', $skip_posttypes );
|
346 |
+
|
347 |
+
return $skip_posttypes;
|
348 |
+
}
|
349 |
|
350 |
/**
|
351 |
+
* Check if post type is ok to log by logger
|
352 |
+
* @return bool
|
|
|
|
|
353 |
*/
|
354 |
+
public function ok_to_log_post_posttype( $post ) {
|
355 |
+
$ok_to_log = true;
|
356 |
+
$skip_posttypes = $this->get_skip_posttypes();
|
357 |
+
|
358 |
+
if ( in_array( get_post_type( $post ), $skip_posttypes, true ) ) {
|
359 |
+
$ok_to_log = false;
|
360 |
+
}
|
361 |
+
|
362 |
+
return $ok_to_log;
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Fired when a post has changed status
|
367 |
+
* Only run in certain cases,
|
368 |
+
* because when always enabled it catches a lots of edits made by plugins during cron jobs etc,
|
369 |
+
* which by definition is not wrong, but perhaps not wanted/annoying
|
370 |
+
*/
|
371 |
function on_transition_post_status( $new_status, $old_status, $post ) {
|
372 |
|
373 |
$ok_to_log = true;
|
390 |
$ok_to_log = false;
|
391 |
}
|
392 |
|
393 |
+
if ( ! $this->ok_to_log_post_posttype( $post ) ) {
|
394 |
+
$ok_to_log = false;
|
395 |
+
}
|
|
|
|
|
|
|
|
|
|
|
396 |
|
397 |
/**
|
398 |
+
* Filter to control logging.
|
399 |
*
|
400 |
+
* @param bool $ok_to_log
|
401 |
+
* @param $new_status
|
402 |
+
* @param $old_status
|
403 |
+
* @param $post
|
404 |
+
*
|
405 |
+
* @return bool True to log, false to not log.
|
406 |
+
*
|
407 |
+
* @since 2.21
|
408 |
*/
|
409 |
+
$ok_to_log = apply_filters( 'simple_history/post_logger/post_updated/ok_to_log', $ok_to_log, $new_status, $old_status, $post );
|
|
|
|
|
|
|
|
|
410 |
|
411 |
if ( ! $ok_to_log ) {
|
412 |
return;
|
465 |
|
466 |
$context['_occasionsID'] = __CLASS__ . '/' . __FUNCTION__ . "/post_updated/{$post->ID}";
|
467 |
|
468 |
+
/**
|
469 |
+
* Modify the context saved.
|
470 |
+
*
|
471 |
+
* @param array $context
|
472 |
+
* @param WP_Post $post
|
473 |
+
*/
|
474 |
+
$context = apply_filters( 'simple_history/post_logger/post_updated/context', $context, $post );
|
475 |
+
|
476 |
+
$this->infoMessage( "post_updated", $context );
|
477 |
|
478 |
}// End if().
|
479 |
|
706 |
}
|
707 |
|
708 |
/**
|
709 |
+
* Modify plain output to include link to post.
|
710 |
*
|
711 |
* @param array $row Row data.
|
712 |
*/
|
1012 |
// post_new_thumb, int of new thumb, empty if no new thumb.
|
1013 |
$diff_table_output .= $this->getLogRowDetailsOutputForPostThumb( $context );
|
1014 |
|
1015 |
+
/**
|
1016 |
+
* Modify the formatted diff output of a saved/modified post
|
1017 |
+
*
|
1018 |
+
* @param string $diff_table_output
|
1019 |
+
* @param array $context
|
1020 |
+
* @return string
|
1021 |
+
*/
|
1022 |
+
$diff_table_output = apply_filters( 'simple_history/post_logger/post_updated/diff_table_output', $diff_table_output, $context );
|
1023 |
+
|
1024 |
if ( $has_diff_values || $diff_table_output ) {
|
1025 |
|
1026 |
$diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
|
1121 |
// Check if images still exists and if so get their thumbnails.
|
1122 |
$prev_thumb_id = empty( $context['post_prev_thumb_id'] ) ? null : $context['post_prev_thumb_id'];
|
1123 |
$new_thumb_id = empty( $context['post_new_thumb_id'] ) ? null : $context['post_new_thumb_id'];
|
1124 |
+
$post_new_thumb_title = empty( $context['post_new_thumb_title'] ) ? null : $context['post_new_thumb_title'];
|
1125 |
+
$post_prev_thumb_title = empty( $context['post_prev_thumb_title'] ) ? null : $context['post_prev_thumb_title'];
|
1126 |
|
1127 |
$prev_attached_file = get_attached_file( $prev_thumb_id );
|
1128 |
$prev_thumb_src = wp_get_attachment_image_src( $prev_thumb_id, 'small' );
|
1140 |
</div>
|
1141 |
',
|
1142 |
$prev_thumb_src[0],
|
1143 |
+
esc_html( $post_prev_thumb_title )
|
1144 |
);
|
1145 |
} else {
|
1146 |
// Fallback if image does not exist.
|
1147 |
$prev_thumb_html = sprintf(
|
1148 |
'<div>%1$s</div>',
|
1149 |
+
esc_html( $post_prev_thumb_title )
|
1150 |
);
|
1151 |
}
|
1152 |
|
1160 |
</div>
|
1161 |
',
|
1162 |
$new_thumb_src[0],
|
1163 |
+
esc_html( $post_new_thumb_title )
|
1164 |
);
|
1165 |
} else {
|
1166 |
// Fallback if image does not exist.
|
1167 |
$prev_thumb_html = sprintf(
|
1168 |
'<div>%1$s</div>',
|
1169 |
+
esc_html( $post_new_thumb_title )
|
1170 |
);
|
1171 |
}
|
1172 |
|
1194 |
</td>
|
1195 |
</tr>',
|
1196 |
esc_html( __( 'Featured image', 'simple-history' ) ), // 1
|
1197 |
+
$prev_thumb_html, // 2
|
1198 |
$new_thumb_html // 3
|
1199 |
);
|
1200 |
} // End if().
|
loggers/SimpleThemeLogger.php
CHANGED
@@ -963,22 +963,22 @@ class SimpleThemeLogger extends SimpleLogger {
|
|
963 |
|
964 |
$context = array();
|
965 |
|
966 |
-
// Add widget info
|
967 |
$context['widget_id_base'] = $widget_id_base;
|
968 |
$widget = $this->getWidgetByIdBase( $widget_id_base );
|
969 |
if ( $widget ) {
|
970 |
$context['widget_name_translated'] = $widget->name;
|
971 |
}
|
972 |
|
973 |
-
// Add sidebar info
|
974 |
-
$sidebar_id = $_POST['sidebar'];
|
975 |
$context['sidebar_id'] = $sidebar_id;
|
976 |
$sidebar = $this->getSidebarById( $sidebar_id );
|
977 |
if ( $sidebar ) {
|
978 |
$context['sidebar_name_translated'] = $sidebar['name'];
|
979 |
}
|
980 |
|
981 |
-
// Calculate changes
|
982 |
$context['old_instance'] = $this->simpleHistory->json_encode( $old_instance );
|
983 |
$context['new_instance'] = $this->simpleHistory->json_encode( $new_instance );
|
984 |
|
@@ -1099,18 +1099,22 @@ class SimpleThemeLogger extends SimpleLogger {
|
|
1099 |
/**
|
1100 |
* Get a sidebar by id
|
1101 |
*
|
1102 |
-
* @param string $sidebar_id
|
1103 |
-
* @return sidebar info or false on failure
|
1104 |
*/
|
1105 |
function getSidebarById( $sidebar_id ) {
|
1106 |
|
|
|
|
|
|
|
|
|
1107 |
$sidebars = isset( $GLOBALS['wp_registered_sidebars'] ) ? $GLOBALS['wp_registered_sidebars'] : false;
|
1108 |
|
1109 |
if ( ! $sidebars ) {
|
1110 |
return false;
|
1111 |
}
|
1112 |
|
1113 |
-
// Add sidebar info
|
1114 |
if ( isset( $sidebars[ $sidebar_id ] ) ) {
|
1115 |
|
1116 |
return $sidebars[ $sidebar_id ];
|
963 |
|
964 |
$context = array();
|
965 |
|
966 |
+
// Add widget info.
|
967 |
$context['widget_id_base'] = $widget_id_base;
|
968 |
$widget = $this->getWidgetByIdBase( $widget_id_base );
|
969 |
if ( $widget ) {
|
970 |
$context['widget_name_translated'] = $widget->name;
|
971 |
}
|
972 |
|
973 |
+
// Add sidebar info.
|
974 |
+
$sidebar_id = isset( $_POST['sidebar'] ) ? $_POST['sidebar'] : null;
|
975 |
$context['sidebar_id'] = $sidebar_id;
|
976 |
$sidebar = $this->getSidebarById( $sidebar_id );
|
977 |
if ( $sidebar ) {
|
978 |
$context['sidebar_name_translated'] = $sidebar['name'];
|
979 |
}
|
980 |
|
981 |
+
// Calculate changes.
|
982 |
$context['old_instance'] = $this->simpleHistory->json_encode( $old_instance );
|
983 |
$context['new_instance'] = $this->simpleHistory->json_encode( $new_instance );
|
984 |
|
1099 |
/**
|
1100 |
* Get a sidebar by id
|
1101 |
*
|
1102 |
+
* @param string $sidebar_id ID of sidebar.
|
1103 |
+
* @return sidebar info or false on failure.
|
1104 |
*/
|
1105 |
function getSidebarById( $sidebar_id ) {
|
1106 |
|
1107 |
+
if ( empty( $sidebar_id ) ) {
|
1108 |
+
return false;
|
1109 |
+
}
|
1110 |
+
|
1111 |
$sidebars = isset( $GLOBALS['wp_registered_sidebars'] ) ? $GLOBALS['wp_registered_sidebars'] : false;
|
1112 |
|
1113 |
if ( ! $sidebars ) {
|
1114 |
return false;
|
1115 |
}
|
1116 |
|
1117 |
+
// Add sidebar info.
|
1118 |
if ( isset( $sidebars[ $sidebar_id ] ) ) {
|
1119 |
|
1120 |
return $sidebars[ $sidebar_id ];
|
loggers/SimpleUserLogger.php
CHANGED
@@ -5,7 +5,6 @@
|
|
5 |
*/
|
6 |
class SimpleUserLogger extends SimpleLogger {
|
7 |
|
8 |
-
|
9 |
public $slug = __CLASS__;
|
10 |
|
11 |
/**
|
@@ -466,8 +465,6 @@ class SimpleUserLogger extends SimpleLogger {
|
|
466 |
|
467 |
$use_you = apply_filters( 'simple_history/user_logger/plain_text_output_use_you', true );
|
468 |
|
469 |
-
// error_log( serialize($current_user_id) ); // int 1
|
470 |
-
// error_log( serialize($context["_user_id"]) ); // string 1
|
471 |
// User still exist, so link to their profile
|
472 |
if ( (int) $current_user_id === (int) $context['_user_id'] && $use_you ) {
|
473 |
// User that is viewing the log is the same as the edited user
|
5 |
*/
|
6 |
class SimpleUserLogger extends SimpleLogger {
|
7 |
|
|
|
8 |
public $slug = __CLASS__;
|
9 |
|
10 |
/**
|
465 |
|
466 |
$use_you = apply_filters( 'simple_history/user_logger/plain_text_output_use_you', true );
|
467 |
|
|
|
|
|
468 |
// User still exist, so link to their profile
|
469 |
if ( (int) $current_user_id === (int) $context['_user_id'] && $use_you ) {
|
470 |
// User that is viewing the log is the same as the edited user
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: history, log, changes, changelog, audit, trail, pages, attachments, users,
|
|
5 |
Requires at least: 4.5.1
|
6 |
Tested up to: 4.9
|
7 |
Requires PHP: 5.3
|
8 |
-
Stable tag: 2.
|
9 |
|
10 |
View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
|
11 |
|
@@ -159,11 +159,28 @@ initiated by a specific user.
|
|
159 |
7. A chart with some quick statistics is available, so you can see the number of events that has been logged each day.
|
160 |
A simple way to see any uncommon activity, for example an increased number of logins or similar.
|
161 |
|
162 |
-
==
|
163 |
-
==
|
164 |
|
165 |
## Changelog
|
166 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
= 2.20 (November 2017) =
|
168 |
|
169 |
- Add logging of post thumbnails.
|
@@ -172,7 +189,7 @@ A simple way to see any uncommon activity, for example an increased number of lo
|
|
172 |
- Update Select2 to latest version. Fixes https://wordpress.org/support/topic/select2-js-is-outdated/.
|
173 |
- Show a message if user is running to old WordPress version, and don't continue running the code of this plugin.
|
174 |
Should fix stuff like https://wordpress.org/support/topic/simple-history-i-cannot-login/.
|
175 |
-
|
176 |
|
177 |
= 2.19 (November 2017) =
|
178 |
|
5 |
Requires at least: 4.5.1
|
6 |
Tested up to: 4.9
|
7 |
Requires PHP: 5.3
|
8 |
+
Stable tag: 2.21
|
9 |
|
10 |
View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
|
11 |
|
159 |
7. A chart with some quick statistics is available, so you can see the number of events that has been logged each day.
|
160 |
A simple way to see any uncommon activity, for example an increased number of logins or similar.
|
161 |
|
162 |
+
== Changelog ==
|
|
|
163 |
|
164 |
## Changelog
|
165 |
|
166 |
+
= 2.21 (May 2018) =
|
167 |
+
|
168 |
+
- Added support for Advanced Custom Fields (ACF): when a ACF Field or ACF Field Group is created or modified or deleted you will now get more details in the activity feed.
|
169 |
+
- Changes to taxonomies/categories/tags now include a link to the modified term and to the category that the term belongs to.
|
170 |
+
- The post types in the `skip_posttypes` filter are now also applied to trashed and untrashed posts (not only post edits, as before).
|
171 |
+
- Don't log Jetpack sitemap updates. (Don't log updates to posttypes `jp_sitemap`, `jp_sitemap_master` and `jp_img_sitemap`, i.e. the post types used by Jetpack's Sitemap function.) Should fix https://wordpress.org/support/topic/jetpack-sitemap-logging/.
|
172 |
+
- Don't log the taxonomies `post_translations` or `term_translations`, that are used by Polylang to store translation mappings. That contained md5-hashed strings and was not of any benefit (a separate logger for Polylang will come soon anyway).
|
173 |
+
- Fix notice in theme logger because did not check if `$_POST['sidebar']` was set. Fixes https://github.com/bonny/WordPress-Simple-History/issues/136.
|
174 |
+
- Fix thumbnail title missing notice in post logger.
|
175 |
+
- Fix PHP warning when a plugin was checked by WordPress for an update, but your WordPress install did not have the plugin folder for that plugin.
|
176 |
+
- Fix unexpected single-quotations included in file name in Internet Explorer 11 (and possibly other versions) when exporting CSV/JSON file.
|
177 |
+
- Fix filter/search log by specific users not working. Fixes https://wordpress.org/support/topic/show-activity-from-other-authors-only/.
|
178 |
+
- Fix a notice in SimpleOptionsLogger.
|
179 |
+
- Better CSS styling on dashboard.
|
180 |
+
- Add filter `simple_history/post_logger/post_updated/context` that can be used to modify the context added by SimplePostLogger.
|
181 |
+
- Add filter `simple_history/post_logger/post_updated/ok_to_log` that can be used to skip logging a post update.
|
182 |
+
- Add filter `simple_history/categories_logger/skip_taxonomies` that can be used to modify what taxonomies to skip when logging updates to taxonomy terms.
|
183 |
+
|
184 |
= 2.20 (November 2017) =
|
185 |
|
186 |
- Add logging of post thumbnails.
|
189 |
- Update Select2 to latest version. Fixes https://wordpress.org/support/topic/select2-js-is-outdated/.
|
190 |
- Show a message if user is running to old WordPress version, and don't continue running the code of this plugin.
|
191 |
Should fix stuff like https://wordpress.org/support/topic/simple-history-i-cannot-login/.
|
192 |
+
- Fix an error with PHP 7.1.
|
193 |
|
194 |
= 2.19 (November 2017) =
|
195 |
|
templates/settings-style-example.php
CHANGED
@@ -1,5 +1,11 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
?>
|
4 |
|
5 |
<div class="SimpleHistoryGuiExample">
|
@@ -23,7 +29,7 @@ defined( 'ABSPATH' ) or die();
|
|
23 |
</div>
|
24 |
|
25 |
<div class="SimpleHistoryLogitem__text">
|
26 |
-
Short message descriping the thing that happened.
|
27 |
</div>
|
28 |
|
29 |
<div class="SimpleHistoryLogitem__details">
|
@@ -31,7 +37,7 @@ defined( 'ABSPATH' ) or die();
|
|
31 |
<p>More information about the event goes here. Add links, tables, text, lists, etc.</p>
|
32 |
|
33 |
<p>Some build in styles you can use:</p>
|
34 |
-
|
35 |
<p>
|
36 |
<a href="http://playground-root.ep/wp-admin/post.php?post=25097&action=edit&lang=en">
|
37 |
<div class="SimpleHistoryLogitemThumbnail">
|
@@ -43,16 +49,16 @@ defined( 'ABSPATH' ) or die();
|
|
43 |
<p>The <code>inlineDivided</code> class is used to group short pieces of information together, for example meta data:</p>
|
44 |
|
45 |
<p>
|
46 |
-
<span class="SimpleHistoryLogitem__inlineDivided">34 kB</span>
|
47 |
-
<span class="SimpleHistoryLogitem__inlineDivided">PNG</span>
|
48 |
<span class="SimpleHistoryLogitem__inlineDivided">420 × 420</span>
|
49 |
</p>
|
50 |
|
51 |
<p>
|
52 |
-
<span class="SimpleHistoryLogitem__inlineDivided"><em>Filesize</em> 34 kB</span>
|
53 |
-
<span class="SimpleHistoryLogitem__inlineDivided"><em>Format</em> PNG</span>
|
54 |
<span class="SimpleHistoryLogitem__inlineDivided"><em>Dimensions</em> 420 × 420</span>
|
55 |
-
</p>
|
56 |
|
57 |
<p>Tables can be used if you have more data to show, like the meta data for a plugin:</p>
|
58 |
|
@@ -93,7 +99,7 @@ defined( 'ABSPATH' ) or die();
|
|
93 |
|
94 |
<p>
|
95 |
<span class="SimpleHistoryLogitem__inlineDivided">
|
96 |
-
<em>Author:</em>
|
97 |
<a href="http://bbpress.org">The bbPress Community</a>
|
98 |
</span>
|
99 |
|
@@ -131,7 +137,7 @@ defined( 'ABSPATH' ) or die();
|
|
131 |
</li>
|
132 |
|
133 |
<?php
|
134 |
-
// All debug levels
|
135 |
$template = '
|
136 |
<li class="SimpleHistoryLogitem SimpleHistoryLogitem--loglevel-%1$s SimpleHistoryLogitem--logger-SimpleMediaLogger SimpleHistoryLogitem--initiator-wp_user">
|
137 |
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Style example.
|
4 |
+
*
|
5 |
+
* @package SimpleHistory
|
6 |
+
*/
|
7 |
+
|
8 |
+
defined( 'ABSPATH' ) || die();
|
9 |
?>
|
10 |
|
11 |
<div class="SimpleHistoryGuiExample">
|
29 |
</div>
|
30 |
|
31 |
<div class="SimpleHistoryLogitem__text">
|
32 |
+
Short message descriping the thing that happened.
|
33 |
</div>
|
34 |
|
35 |
<div class="SimpleHistoryLogitem__details">
|
37 |
<p>More information about the event goes here. Add links, tables, text, lists, etc.</p>
|
38 |
|
39 |
<p>Some build in styles you can use:</p>
|
40 |
+
|
41 |
<p>
|
42 |
<a href="http://playground-root.ep/wp-admin/post.php?post=25097&action=edit&lang=en">
|
43 |
<div class="SimpleHistoryLogitemThumbnail">
|
49 |
<p>The <code>inlineDivided</code> class is used to group short pieces of information together, for example meta data:</p>
|
50 |
|
51 |
<p>
|
52 |
+
<span class="SimpleHistoryLogitem__inlineDivided">34 kB</span>
|
53 |
+
<span class="SimpleHistoryLogitem__inlineDivided">PNG</span>
|
54 |
<span class="SimpleHistoryLogitem__inlineDivided">420 × 420</span>
|
55 |
</p>
|
56 |
|
57 |
<p>
|
58 |
+
<span class="SimpleHistoryLogitem__inlineDivided"><em>Filesize</em> 34 kB</span>
|
59 |
+
<span class="SimpleHistoryLogitem__inlineDivided"><em>Format</em> PNG</span>
|
60 |
<span class="SimpleHistoryLogitem__inlineDivided"><em>Dimensions</em> 420 × 420</span>
|
61 |
+
</p>
|
62 |
|
63 |
<p>Tables can be used if you have more data to show, like the meta data for a plugin:</p>
|
64 |
|
99 |
|
100 |
<p>
|
101 |
<span class="SimpleHistoryLogitem__inlineDivided">
|
102 |
+
<em>Author:</em>
|
103 |
<a href="http://bbpress.org">The bbPress Community</a>
|
104 |
</span>
|
105 |
|
137 |
</li>
|
138 |
|
139 |
<?php
|
140 |
+
// All debug levels.
|
141 |
$template = '
|
142 |
<li class="SimpleHistoryLogitem SimpleHistoryLogitem--loglevel-%1$s SimpleHistoryLogitem--logger-SimpleMediaLogger SimpleHistoryLogitem--initiator-wp_user">
|
143 |
|