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_posttypesfilter 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_masterandjp_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_translationsorterm_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/contextthat can be used to modify the context added by SimplePostLogger. - Add filter
simple_history/post_logger/post_updated/ok_to_logthat can be used to skip logging a post update. - Add filter
simple_history/categories_logger/skip_taxonomiesthat can be used to modify what taxonomies to skip when logging updates to taxonomy terms.
Download this release
Release Info
| Developer | eskapism |
| Plugin | |
| 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 |
|
