Simple History - Version 3.2.0

Version Description

(February 2022) =

  • Refactored detection of user profile updates. Order of updated user fields are now shown in the same order as they are in the edit user screen. Also the texts are updated to be more user friendly. And those "show toolbar"-messages that showed up at random times should be gone too.
  • Added: Creation and deletion (revoke) of Application Passwords are now logged.
  • Added: Role changes from users overview page are now logged.
  • Fixed: Password reset links was always attributed to "Anonymous web user", even those that was sent from the users listing in the WordPress admin area.
  • Fixed: Increase contrast ratio on some texts.
  • Changed: sh_d() now tell you if a value is integer or numeric string or an empty string.
  • Changed: The log message "Found an update to WordPress" had a dot in it. No other log message had a dot so the dot is no more.
Download this release

Release Info

Developer eskapism
Plugin Icon 128x128 Simple History
Version 3.2.0
Comparing to
See all releases

Code changes from version 3.1.1 to 3.2.0

css/styles.css CHANGED
@@ -304,9 +304,8 @@ Style different log levels.
304
 
305
  .SimpleHistoryLogitem__keyValueTable tr > td:first-child {
306
  text-align: right;
307
- /*font-weight: bold;*/
308
  padding-right: 1em;
309
- color: #aaa;
310
  white-space: nowrap;
311
  }
312
 
@@ -316,6 +315,7 @@ Style different log levels.
316
 
317
  .SimpleHistoryLogitem__keyValueTable__addedThing {
318
  text-decoration: none;
 
319
  }
320
 
321
  .SimpleHistoryLogitem__keyValueTable__removedThing {
@@ -724,7 +724,6 @@ Modal window with detailss
724
  background: inherit;
725
  }
726
 
727
-
728
  .SimpleHistoryLogitem__moreDetails {
729
  border-top: 1px solid rgb(229, 229, 229);
730
  margin-top: 20px;
304
 
305
  .SimpleHistoryLogitem__keyValueTable tr > td:first-child {
306
  text-align: right;
 
307
  padding-right: 1em;
308
+ color: #757575;
309
  white-space: nowrap;
310
  }
311
 
315
 
316
  .SimpleHistoryLogitem__keyValueTable__addedThing {
317
  text-decoration: none;
318
+ margin-right: 0.5em;
319
  }
320
 
321
  .SimpleHistoryLogitem__keyValueTable__removedThing {
724
  background: inherit;
725
  }
726
 
 
727
  .SimpleHistoryLogitem__moreDetails {
728
  border-top: 1px solid rgb(229, 229, 229);
729
  margin-top: 20px;
docker-compose.yml CHANGED
@@ -13,9 +13,14 @@ services:
13
  WORDPRESS_DB_NAME: wp_test_site
14
  WORDPRESS_DB_USER: dbuser
15
  WORDPRESS_DB_PASSWORD: examplepass
 
 
 
 
16
  volumes:
17
  - wordpress:/var/www/html
18
  - ./:/var/www/html/wp-content/plugins/simple-history
 
19
  - "${WP_UPLOADS_DIR:-./data/wp-uploads}:/var/www/html/wp-content/uploads"
20
 
21
  db:
13
  WORDPRESS_DB_NAME: wp_test_site
14
  WORDPRESS_DB_USER: dbuser
15
  WORDPRESS_DB_PASSWORD: examplepass
16
+ WORDPRESS_CONFIG_EXTRA: |
17
+ define( 'WP_AUTO_UPDATE_CORE', false );
18
+ define( 'AUTOMATIC_UPDATER_DISABLED', true );
19
+ define( 'WP_ENVIRONMENT_TYPE', 'local' );
20
  volumes:
21
  - wordpress:/var/www/html
22
  - ./:/var/www/html/wp-content/plugins/simple-history
23
+ - ./tests/mu-plugin.php:/var/www/html/wp-content/mu-plugins/mu-plugin.php
24
  - "${WP_UPLOADS_DIR:-./data/wp-uploads}:/var/www/html/wp-content/uploads"
25
 
26
  db:
inc/helpers.php CHANGED
@@ -200,6 +200,12 @@ function sh_d() {
200
  $loopOutput = "$bool_string (boolean value)";
201
  } elseif ( is_null( $var ) ) {
202
  $loopOutput = ( 'null (null value)' );
 
 
 
 
 
 
203
  } else {
204
  $loopOutput = print_r( $var, true );
205
  }
@@ -268,3 +274,34 @@ function sh_ucwords( $str, $separator = ' ' ) {
268
  $str = str_replace( ' ', $separator, $str );
269
  return $str;
270
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  $loopOutput = "$bool_string (boolean value)";
201
  } elseif ( is_null( $var ) ) {
202
  $loopOutput = ( 'null (null value)' );
203
+ } elseif ( is_int( $var ) ) {
204
+ $loopOutput = "$var (integer value)";
205
+ } elseif ( is_numeric( $var ) ) {
206
+ $loopOutput = "$var (numeric string)";
207
+ } elseif ( is_string( $var ) && $var === '' ) {
208
+ $loopOutput = "'' (empty string)";
209
  } else {
210
  $loopOutput = print_r( $var, true );
211
  }
274
  $str = str_replace( ' ', $separator, $str );
275
  return $str;
276
  }
277
+
278
+ /**
279
+ * Get the current screen object.
280
+ * Returns an object with all attributes empty if functions is not found or if function
281
+ * returns null. Makes it easier to use get_current_screen when we don't have to
282
+ * check for function existance and or null.
283
+ *
284
+ * @return WP_Screen|Object Current screen object or object with empty attributes when screen not defined.
285
+ */
286
+ function simple_history_get_current_screen() {
287
+ if ( function_exists( 'get_current_screen' ) ) {
288
+ $current_screen = get_current_screen();
289
+ if ( $current_screen instanceof WP_Screen ) {
290
+ return (object) $current_screen;
291
+ }
292
+ }
293
+
294
+ // No screen found.
295
+ return (object) array(
296
+ 'action' => null,
297
+ 'base' => null,
298
+ 'id' => null,
299
+ 'is_network' => null,
300
+ 'is_user' => null,
301
+ 'parent_base' => null,
302
+ 'parent_file' => null,
303
+ 'post_type' => null,
304
+ 'taxonomy' => null,
305
+ 'is_block_editor' => null,
306
+ );
307
+ }
index.php CHANGED
@@ -6,7 +6,7 @@
6
  * Text Domain: simple-history
7
  * Domain Path: /languages
8
  * Description: Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.
9
- * Version: 3.1.1
10
  * Author: Pär Thernström
11
  * Author URI: http://simple-history.com/
12
  * License: GPL2
@@ -45,7 +45,7 @@ if ( $ok_php_version && $ok_wp_version ) {
45
  * @TODO: make activation multi site aware, as in https://github.com/scribu/wp-proper-network-activation
46
  * register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
47
  */
48
- define( 'SIMPLE_HISTORY_VERSION', '3.1.1' );
49
  define( 'SIMPLE_HISTORY_PATH', plugin_dir_path( __FILE__ ) );
50
  define( 'SIMPLE_HISTORY_BASENAME', plugin_basename( __FILE__ ) );
51
  define( 'SIMPLE_HISTORY_DIR_URL', plugin_dir_url( __FILE__ ) );
6
  * Text Domain: simple-history
7
  * Domain Path: /languages
8
  * Description: Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.
9
+ * Version: 3.2.0
10
  * Author: Pär Thernström
11
  * Author URI: http://simple-history.com/
12
  * License: GPL2
45
  * @TODO: make activation multi site aware, as in https://github.com/scribu/wp-proper-network-activation
46
  * register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
47
  */
48
+ define( 'SIMPLE_HISTORY_VERSION', '3.2.0' );
49
  define( 'SIMPLE_HISTORY_PATH', plugin_dir_path( __FILE__ ) );
50
  define( 'SIMPLE_HISTORY_BASENAME', plugin_basename( __FILE__ ) );
51
  define( 'SIMPLE_HISTORY_DIR_URL', plugin_dir_url( __FILE__ ) );
loggers/AvailableUpdatesLogger.php CHANGED
@@ -33,7 +33,7 @@ if ( ! class_exists( 'AvailableUpdatesLogger' ) ) {
33
  'description' => 'Logs found updates to WordPress, plugins, and themes',
34
  'capability' => 'manage_options',
35
  'messages' => array(
36
- 'core_update_available' => __( 'Found an update to WordPress.', 'simple-history' ),
37
  'plugin_update_available' => __( 'Found an update to plugin "{plugin_name}"', 'simple-history' ),
38
  'theme_update_available' => __( 'Found an update to theme "{theme_name}"', 'simple-history' ),
39
  ),
33
  'description' => 'Logs found updates to WordPress, plugins, and themes',
34
  'capability' => 'manage_options',
35
  'messages' => array(
36
+ 'core_update_available' => __( 'Found an update to WordPress', 'simple-history' ),
37
  'plugin_update_available' => __( 'Found an update to plugin "{plugin_name}"', 'simple-history' ),
38
  'theme_update_available' => __( 'Found an update to theme "{theme_name}"', 'simple-history' ),
39
  ),
loggers/SimpleUserLogger.php CHANGED
@@ -5,7 +5,6 @@
5
  */
6
  class SimpleUserLogger extends SimpleLogger {
7
 
8
-
9
  public $slug = __CLASS__;
10
 
11
  /**
@@ -32,7 +31,7 @@ class SimpleUserLogger extends SimpleLogger {
32
  'user_unknown_logged_in' => __( 'Unknown user logged in', 'simple-history' ),
33
  'user_logged_out' => __( 'Logged out', 'simple-history' ),
34
  'user_updated_profile' => __(
35
- 'Edited the profile for user {edited_user_login} ({edited_user_email})',
36
  'simple-history'
37
  ),
38
  'user_created' => __(
@@ -45,49 +44,36 @@ class SimpleUserLogger extends SimpleLogger {
45
  "Requested a password reset link for user with login '{user_login}' and email '{user_email}'",
46
  'simple-history'
47
  ),
48
-
49
- /*
50
- Text used in admin:
51
- Log Out of All Other Sessions
52
- Left your account logged in at a public computer?
53
- Lost your phone? This will log you out everywhere except your current browser
54
- */
55
  'user_session_destroy_others' => _x(
56
  'Logged out from all other sessions',
57
  'User destroys other login sessions for themself',
58
  'simple-history'
59
  ),
60
- /*
61
- Text used in admin:
62
- 'Log %s out of all sessions' ), $profileuser->display_name );
63
- */
64
  'user_session_destroy_everywhere' => _x(
65
  'Logged out "{user_display_name}" from all sessions',
66
  'User destroys all login sessions for a user',
67
  'simple-history'
68
  ),
69
-
70
- 'user_admin_email_confirm_screen_view' => _x(
71
- 'Viewed admin email confirm screen',
72
- 'User sees user admin email confirm screen',
73
- 'simple-history'
74
- ),
75
- // 'user_admin_email_confirm_update_clicked' => _x(
76
- // 'Clicked "Update" button on admin email confirm screen',
77
- // 'User clicks update admin email on admin email confirm screen',
78
- // 'simple-history'
79
- // ),
80
  'user_admin_email_confirm_correct_clicked' => _x(
81
  'Verified that administration email for website is correct',
82
  'User clicks confirm admin email on admin email confirm screen',
83
  'simple-history'
84
  ),
85
- // 'user_admin_email_confirm_remind_clicked' => _x(
86
- // 'Clicked "Remind me later" on admin email confirm screen',
87
- // 'User clicks remind me later on admin email confirm screen',
88
- // 'simple-history'
89
- // ),
90
-
 
 
 
 
 
 
 
 
 
91
  ),
92
 
93
  'labels' => array(
@@ -115,12 +101,20 @@ class SimpleUserLogger extends SimpleLogger {
115
  _x( 'User deletions', 'User logger: search', 'simple-history' ) => array(
116
  'user_deleted',
117
  ),
 
 
 
 
 
 
 
 
 
118
 
119
  ),
120
  ), // end search
121
 
122
  ), // end labels
123
-
124
  );
125
 
126
  return $arr_info;
@@ -144,7 +138,7 @@ class SimpleUserLogger extends SimpleLogger {
144
  add_filter( 'authenticate', array( $this, 'onAuthenticate' ), 30, 3 );
145
 
146
  // User is created
147
- add_action( 'user_register', array( $this, 'onUserRegister' ), 10, 2 );
148
 
149
  // User is deleted
150
  add_action( 'delete_user', array( $this, 'onDeleteUser' ), 10, 2 );
@@ -156,7 +150,10 @@ class SimpleUserLogger extends SimpleLogger {
156
  add_action( 'validate_password_reset', array( $this, 'onValidatePasswordReset' ), 10, 2 );
157
  add_action( 'retrieve_password_message', array( $this, 'onRetrievePasswordMessage' ), 10, 4 );
158
 
159
- add_filter( 'insert_user_meta', array( $this, 'onInsertUserMeta' ), 10, 3 );
 
 
 
160
 
161
  // Administration email verification-screen
162
 
@@ -170,42 +167,114 @@ class SimpleUserLogger extends SimpleLogger {
170
  // 2
171
  // );
172
 
173
- /* add_action(
174
- 'admin_email_confirm',
175
- array( $this, 'on_action_admin_email_confirm' )
176
- ); */
177
 
178
- /* add_action(
179
- 'load-options-general.php',
180
- array( $this, 'on_action_load_options_general' )
181
- ); */
182
 
183
- add_action(
184
- 'login_form_confirm_admin_email',
185
- array( $this, 'on_action_login_form_confirm_admin_email' )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  );
 
 
 
 
 
187
 
188
- /* add_action(
189
- 'login_form_confirm_admin_email',
190
- array( $this, 'on_action_login_form_confirm_admin_email_remind_later' )
191
- ); */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  }
193
 
194
- /* public function on_action_login_form_confirm_admin_email_remind_later() {
195
- // Bail if button with name "correct-admin-email" was not clicked or if no nonce field exists.
196
- if ( empty( $_GET['remind_me_later'] ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  return;
198
  }
199
 
200
- // Bail if nonce not valid.
201
- $nonce_valid = wp_verify_nonce( $_GET['remind_me_later'], 'remind_me_later_nonce' );
202
- if ( $nonce_valid === false ) {
203
- return;
204
  }
205
 
206
- $this->infoMessage( 'user_admin_email_confirm_remind_clicked' );
 
 
 
 
 
 
 
 
 
 
 
207
  }
208
- */
209
 
210
  public function on_action_login_form_confirm_admin_email() {
211
  // Bail if button with name "correct-admin-email" was not clicked or if no nonce field exists.
@@ -219,171 +288,95 @@ class SimpleUserLogger extends SimpleLogger {
219
  return;
220
  }
221
 
222
- // sh_error_log( 'User clicked "The email is correct"' );
223
  $this->infoMessage( 'user_admin_email_confirm_correct_clicked' );
224
  }
225
 
226
- /* public function on_action_load_options_general() {
227
- $referer = wp_get_referer();
228
- $referer_parts = wp_parse_url( $referer );
229
-
230
- $login_url = wp_login_url();
231
- $login_url_parts = wp_parse_url( $login_url );
232
-
233
- // Bail if referer is not login page.
234
- if ( $referer_parts['path'] !== $login_url_parts['path'] ) {
235
- return;
236
- }
237
-
238
- // If page was wp-login.php and action was confirm_admin_email then user came from confirm email screen
239
- // http://wordpress-stable.test/wordpress/wp-login.php?redirect_to=http%3A%2F%2Fwordpress-stable.test%2Fwordpress%2Fwp-admin%2F&action=confirm_admin_email&wp_lang=sv_SE
240
- $referer_parts_query_parts = wp_parse_args( $referer_parts['query'] );
241
-
242
- // Bail if action was not to show confirm_admin_email-page.
243
- if ( $referer_parts_query_parts['action'] !== 'confirm_admin_email' ) {
244
- return;
245
- }
246
-
247
- // We are at options-general.php and user got here from the confirm admin email page.
248
- // sh_error_log( 'User clicked on "Update" button' );
249
- $this->infoMessage( 'user_admin_email_confirm_update_clicked' );
250
- } */
251
-
252
- /* public function on_action_admin_email_confirm( $errors ) {
253
- if ( is_wp_error( $errors ) && $errors->has_errors() ) {
254
- return;
255
- }
256
- $this->infoMessage( 'user_admin_email_confirm_screen_view' );
257
- } */
258
-
259
- /*
260
- * Called before the user is updated
261
  *
262
- * Filter a user's meta values and keys before the user is created or updated.
263
  *
264
- * Does not include contact methods. These are added using `wp_get_user_contact_methods($user )`.
 
265
  *
266
- * @param array $meta {
267
- * Default meta values and keys for the user.
268
  *
269
- * @type string $nickname The user's nickname. Default is the user's username.
270
- * @type string $first_name The user's first name.
271
- * @type string $last_name The user's last name.
272
- * @type string $description The user's description.
273
- * @type bool $rich_editing Whether to enable the rich-editor for the user. False if not empty.
274
- * @type bool $comment_shortcuts Whether to enable keyboard shortcuts for the user. Default false.
275
- * @type string $admin_color The color scheme for a user's admin screen. Default 'fresh'.
276
- * @type int|bool $use_ssl Whether to force SSL on the user's admin area. 0|false if SSL is
277
- * not forced.
278
- * @type bool $show_admin_bar_front Whether to show the admin bar on the front end for the user.
279
- * Default true.
280
  * }
281
- * @param WP_User $user User object.
282
- * @param bool $update Whether the user is being updated rather than created.
 
283
  */
284
- public function onInsertUserMeta( $meta, $user, $update ) {
285
-
286
- // We only log updates here
287
  if ( ! $update ) {
288
- return $meta;
289
  }
290
 
291
- // $user should be set, but check just in case
292
- if ( empty( $user ) || ! is_object( $user ) ) {
293
- return $meta;
294
  }
295
 
296
- // Make of copy of the posted data, because we change the keys
297
- // PHPCS:ignore WordPress.Security.NonceVerification.Missing
298
- $posted_data = $_POST;
299
- $posted_data = stripslashes_deep( $posted_data );
300
 
301
- // Paranoid mode, just in case some other plugin fires the "insert_user_meta"
302
- // filter and the user.php file is not loaded for some super wierd reason
303
- if ( ! function_exists( '_get_additional_user_keys' ) ) {
304
- return $meta;
305
  }
306
 
307
- // Get the default fields to include.
308
- // This includes contact methods (including filter, so more could have been added)
309
- $arr_keys_to_check = _get_additional_user_keys( $user );
310
-
311
- // Somehow some fields are not include above, so add them manually
312
- $arr_keys_to_check = array_merge(
313
- $arr_keys_to_check,
314
- array( 'user_email', 'user_url', 'display_name' )
315
- );
316
-
317
- // Skip some keys, because to much info or I don't know what they are
318
- $arr_keys_to_check = array_diff( $arr_keys_to_check, array( 'use_ssl' ) );
319
-
320
- // Some keys have different ways of getting data from user
321
- // so change posted object to match those
322
- $posted_data['user_url'] = isset( $posted_data['url'] ) ? $posted_data['url'] : null;
323
- $posted_data['show_admin_bar_front'] = isset( $posted_data['admin_bar_front'] ) ? true : null;
324
- $posted_data['user_email'] = isset( $posted_data['email'] ) ? $posted_data['email'] : null;
325
-
326
- // Display name publicly as = POST "display_name"
327
- // var_dump($user->display_name);
328
- // Set vals for Enable keyboard shortcuts for comment moderation
329
- $posted_data['comment_shortcuts'] = isset( $posted_data['comment_shortcuts'] ) ? 'true' : 'false';
330
-
331
- // Set vals for Disable the visual editor when writing
332
- // posted val = string "false" = yes, disable
333
- $posted_data['rich_editing'] = isset( $posted_data['rich_editing'] ) ? 'false' : 'true';
334
 
335
- // Set vals for Show Toolbar when viewing site
336
- $posted_data['show_admin_bar_front'] = isset( $posted_data['admin_bar_front'] ) ? 'true' : 'false';
337
 
338
- // if checkbox is checked in admin then this is the saved value on the user object
339
- // @todo:
340
- // Check if password was updated
341
  $password_changed = false;
342
- if ( ! empty( $posted_data['pass1'] ) && ! empty( $posted_data['pass2'] ) && $posted_data['pass1'] == $posted_data['pass2'] ) {
343
- $password_changed = 1;
344
- }
345
-
346
- // Check if role was changed
347
- // [role] => bbp_moderator
348
- $role_changed = false;
349
-
350
- // if user is network admin then role dropdown does not exist and role is not posted here
351
- $new_role = isset( $posted_data['role'] ) ? $posted_data['role'] : null;
352
 
353
- if ( $new_role ) {
354
- // as done in user-edit.php
355
- // Compare user role against currently editable roles
356
- $user_roles = array_intersect( array_values( $user->roles ), array_keys( get_editable_roles() ) );
357
- $old_role = reset( $user_roles );
358
-
359
- $role_changed = $new_role != $old_role;
360
- }
361
-
362
- // Will contain the differences
363
- $user_data_diff = array();
364
-
365
- // locale: sv_SE, empty = english, site-default = site....default!
366
- // Check all keys for diff values
367
- foreach ( $arr_keys_to_check as $one_key_to_check ) {
368
- $old_val = $user->$one_key_to_check;
369
- $new_val = isset( $posted_data[ $one_key_to_check ] ) ? $posted_data[ $one_key_to_check ] : null;
370
-
371
- // echo "<hr>key: $one_key_to_check";
372
- // echo "<br>old val: $old_val";
373
- // echo "<br>new val: $new_val";
374
- // new val must be set, because otherwise we are not setting anything
375
- if ( ! isset( $new_val ) ) {
376
- continue;
377
  }
378
 
379
- $user_data_diff = $this->addDiff( $user_data_diff, $one_key_to_check, $old_val, $new_val );
 
 
380
  }
381
 
382
- // Setup basic context
383
  $context = array(
384
- 'edited_user_id' => $user->ID,
385
- 'edited_user_email' => $user->user_email,
386
- 'edited_user_login' => $user->user_login,
387
  'server_http_user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
388
  );
389
 
@@ -391,21 +384,9 @@ class SimpleUserLogger extends SimpleLogger {
391
  $context['edited_user_password_changed'] = '1';
392
  }
393
 
394
- if ( $role_changed ) {
395
- $context['user_prev_role'] = $old_role;
396
- $context['user_new_role'] = $new_role;
397
- }
398
-
399
  // Add diff to context
400
  if ( $user_data_diff ) {
401
  foreach ( $user_data_diff as $one_diff_key => $one_diff_vals ) {
402
- /*
403
- One diff looks like:
404
- "nickname": {
405
- "old": "MyOldNick",
406
- "new": "MyNewNick"
407
- }
408
- */
409
  $context[ "user_prev_{$one_diff_key}" ] = $one_diff_vals['old'];
410
  $context[ "user_new_{$one_diff_key}" ] = $one_diff_vals['new'];
411
  }
@@ -413,7 +394,7 @@ class SimpleUserLogger extends SimpleLogger {
413
 
414
  $this->infoMessage( 'user_updated_profile', $context );
415
 
416
- return $meta;
417
  }
418
 
419
  /**
@@ -427,13 +408,29 @@ class SimpleUserLogger extends SimpleLogger {
427
  */
428
  public function onRetrievePasswordMessage( $message, $key, $user_login, $user_data = null ) {
429
  $context = array(
430
- '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
431
  'message' => $message,
432
- 'key' => $key,
433
  'user_login' => $user_login,
434
  'user_email' => $user_data->user_email,
435
  );
436
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  $this->noticeMessage( 'user_requested_password_reset_link', $context );
438
 
439
  return $message;
@@ -470,13 +467,6 @@ class SimpleUserLogger extends SimpleLogger {
470
  * @since 2.0.6
471
  */
472
  public function onDestroyUserSession() {
473
- /*
474
- Post params:
475
- nonce: a14df12195
476
- user_id: 1
477
- action: destroy-sessions
478
- */
479
-
480
  // PHPCS:ignore WordPress.Security.NonceVerification.Missing
481
  $user = get_userdata( (int) $_POST['user_id'] );
482
 
@@ -667,12 +657,13 @@ class SimpleUserLogger extends SimpleLogger {
667
  }
668
 
669
  /**
670
- * User is created
 
671
  *
672
- * "This action hook allows you to access data for a new user immediately after they are added to the database.
673
- * The user id is passed to hook as an argument."
674
  */
675
- public function onUserRegister( $user_id ) {
676
 
677
  if ( ! $user_id || ! is_numeric( $user_id ) ) {
678
  return;
@@ -821,9 +812,15 @@ class SimpleUserLogger extends SimpleLogger {
821
  }
822
 
823
  /**
824
- * Add diff to array if old and new values are different
825
  *
826
  * Since 2.0.29
 
 
 
 
 
 
827
  */
828
  public function addDiff( $post_data_diff, $key, $old_value, $new_value ) {
829
  if ( $old_value != $new_value ) {
@@ -837,8 +834,9 @@ class SimpleUserLogger extends SimpleLogger {
837
  }
838
 
839
  /**
840
- * Return more info about an logged event
841
- * Supports so far:
 
842
  */
843
  public function getLogRowDetailsOutput( $row ) {
844
  $context = $row->context;
@@ -848,8 +846,35 @@ class SimpleUserLogger extends SimpleLogger {
848
  $diff_table_output = '';
849
 
850
  if ( 'user_updated_profile' == $message_key ) {
851
- // Find all user_prev_ and user_new_ values and show them
852
  $arr_user_keys_to_show_diff_for = array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
  'first_name' => array(
854
  'title' => _x( 'First name', 'User logger', 'simple-history' ),
855
  ),
@@ -859,24 +884,17 @@ class SimpleUserLogger extends SimpleLogger {
859
  'nickname' => array(
860
  'title' => _x( 'Nickname', 'User logger', 'simple-history' ),
861
  ),
862
- 'description' => array(
863
- 'title' => _x( 'Description', 'User logger', 'simple-history' ),
864
- ),
865
- 'rich_editing' => array(
866
- // Disable visual editor
867
- 'title' => _x( 'Visual editor', 'User logger', 'simple-history' ),
868
  ),
869
- 'comment_shortcuts' => array(
870
- // Enable keyboard shortcuts for comment moderation
871
- 'title' => _x( 'Keyboard shortcuts', 'User logger', 'simple-history' ),
872
  ),
873
- 'show_admin_bar_front' => array(
874
- // Show Toolbar when viewing site
875
- 'title' => _x( 'Show Toolbar', 'User logger', 'simple-history' ),
876
  ),
877
- 'admin_color' => array(
878
- // Admin Colour Scheme
879
- 'title' => _x( 'Colour Scheme', 'User logger', 'simple-history' ),
880
  ),
881
  'aim' => array(
882
  'title' => _x( 'AIM', 'User logger', 'simple-history' ),
@@ -887,33 +905,47 @@ class SimpleUserLogger extends SimpleLogger {
887
  'jabber' => array(
888
  'title' => _x( 'Jabber / Google Talk ', 'User logger', 'simple-history' ),
889
  ),
890
- /*
891
- "user_nicename" => array(
892
- "title" => _x("Nicename", "User logger", "simple-history")
893
- ),*/
894
- 'user_email' => array(
895
- 'title' => _x( 'Email', 'User logger', 'simple-history' ),
896
- ),
897
- 'display_name' => array(
898
- // "title" => _x("Display name publicly as", "User logger", "simple-history")
899
- 'title' => _x( 'Display name', 'User logger', 'simple-history' ),
900
- ),
901
- 'user_url' => array(
902
- 'title' => _x( 'Website', 'User logger', 'simple-history' ),
903
- ),
904
- 'role' => array(
905
- 'title' => _x( 'Role', 'User logger', 'simple-history' ),
906
- ),
907
- 'locale' => array(
908
- 'title' => _x( 'Locale', 'User logger', 'simple-history' ),
909
- ),
910
  );
911
 
 
 
 
 
 
 
 
 
 
 
 
912
  foreach ( $arr_user_keys_to_show_diff_for as $key => $val ) {
913
  if ( isset( $context[ "user_prev_{$key}" ] ) && isset( $context[ "user_new_{$key}" ] ) ) {
914
  $user_old_value = $context[ "user_prev_{$key}" ];
915
  $user_new_value = $context[ "user_new_{$key}" ];
916
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
917
  $diff_table_output .= sprintf(
918
  '<tr>
919
  <td>%1$s</td>
@@ -929,7 +961,7 @@ class SimpleUserLogger extends SimpleLogger {
929
  }
930
  }
931
 
932
- // check if password was changed
933
  if ( isset( $context['edited_user_password_changed'] ) ) {
934
  $diff_table_output .= sprintf(
935
  '<tr>
@@ -973,8 +1005,6 @@ class SimpleUserLogger extends SimpleLogger {
973
  'simple-history'
974
  );
975
  } else {
976
- // $sent_status =
977
- // _x("No, no email with account details was sent", "User logger", "simple-history");
978
  $sent_status = '';
979
  }
980
 
5
  */
6
  class SimpleUserLogger extends SimpleLogger {
7
 
 
8
  public $slug = __CLASS__;
9
 
10
  /**
31
  'user_unknown_logged_in' => __( 'Unknown user logged in', 'simple-history' ),
32
  'user_logged_out' => __( 'Logged out', 'simple-history' ),
33
  'user_updated_profile' => __(
34
+ 'Edited the profile for user "{edited_user_login}" ({edited_user_email})',
35
  'simple-history'
36
  ),
37
  'user_created' => __(
44
  "Requested a password reset link for user with login '{user_login}' and email '{user_email}'",
45
  'simple-history'
46
  ),
 
 
 
 
 
 
 
47
  'user_session_destroy_others' => _x(
48
  'Logged out from all other sessions',
49
  'User destroys other login sessions for themself',
50
  'simple-history'
51
  ),
 
 
 
 
52
  'user_session_destroy_everywhere' => _x(
53
  'Logged out "{user_display_name}" from all sessions',
54
  'User destroys all login sessions for a user',
55
  'simple-history'
56
  ),
 
 
 
 
 
 
 
 
 
 
 
57
  'user_admin_email_confirm_correct_clicked' => _x(
58
  'Verified that administration email for website is correct',
59
  'User clicks confirm admin email on admin email confirm screen',
60
  'simple-history'
61
  ),
62
+ 'user_role_updated' => _x(
63
+ 'Changed role for user "{edited_user_login}" to "{new_role}" from "{old_role}"',
64
+ 'User updates the role for a user',
65
+ 'simple-history'
66
+ ),
67
+ 'user_application_password_created' => _x(
68
+ 'Added application password "{application_password_name}" for user "{edited_user_login}"',
69
+ 'User add new application password',
70
+ 'simple-history'
71
+ ),
72
+ 'user_application_password_deleted' => _x(
73
+ 'Deleted application password "{application_password_name}" for user "{edited_user_login}"',
74
+ 'User deletes application password',
75
+ 'simple-history'
76
+ ),
77
  ),
78
 
79
  'labels' => array(
101
  _x( 'User deletions', 'User logger: search', 'simple-history' ) => array(
102
  'user_deleted',
103
  ),
104
+ _x( 'User role changes', 'User logger: search', 'simple-history' ) => array(
105
+ 'user_role_updated',
106
+ ),
107
+ _x( 'User application password created', 'User logger: search', 'simple-history' ) => array(
108
+ 'user_application_password_created',
109
+ ),
110
+ _x( 'User application password deletion', 'User logger: search', 'simple-history' ) => array(
111
+ 'user_application_password_deleted',
112
+ ),
113
 
114
  ),
115
  ), // end search
116
 
117
  ), // end labels
 
118
  );
119
 
120
  return $arr_info;
138
  add_filter( 'authenticate', array( $this, 'onAuthenticate' ), 30, 3 );
139
 
140
  // User is created
141
+ add_action( 'user_register', array( $this, 'on_user_register' ), 10, 2 );
142
 
143
  // User is deleted
144
  add_action( 'delete_user', array( $this, 'onDeleteUser' ), 10, 2 );
150
  add_action( 'validate_password_reset', array( $this, 'onValidatePasswordReset' ), 10, 2 );
151
  add_action( 'retrieve_password_message', array( $this, 'onRetrievePasswordMessage' ), 10, 4 );
152
 
153
+ // New way, fired before update so we can get old user data.
154
+ add_filter( 'wp_pre_insert_user_data', array( $this, 'on_pre_insert_user_data' ), 10, 4 );
155
+
156
+ add_action( 'set_user_role', array( $this, 'on_set_user_role' ), 10, 3 );
157
 
158
  // Administration email verification-screen
159
 
167
  // 2
168
  // );
169
 
170
+ add_action( 'login_form_confirm_admin_email', array( $this, 'on_action_login_form_confirm_admin_email' ) );
 
 
 
171
 
172
+ add_action( 'wp_create_application_password', array( $this, 'on_action_wp_create_application_password' ), 10, 4 );
173
+ add_action( 'wp_delete_application_password', array( $this, 'on_action_wp_delete_application_password' ), 10, 2 );
174
+ }
 
175
 
176
+ /**
177
+ * Log when an Application Password is created for a user.
178
+ *
179
+ * Fired from action `wp_create_application_password`.
180
+ *
181
+ * @param int $user_id The user ID.
182
+ * @param array $item {
183
+ * The details about the created password.
184
+ *
185
+ * @type string $uuid The unique identifier for the application password.
186
+ * @type string $app_id A UUID provided by the application to uniquely identify it.
187
+ * @type string $name The name of the application password.
188
+ * @type string $password A one-way hash of the password.
189
+ * @type int $created Unix timestamp of when the password was created.
190
+ * @type null $last_used Null.
191
+ * @type null $last_ip Null.
192
+ * }
193
+ * @param string $new_password The unhashed generated application password.
194
+ * @param array $args {
195
+ * Arguments used to create the application password.
196
+ *
197
+ * @type string $name The name of the application password.
198
+ * @type string $app_id A UUID provided by the application to uniquely identify it.
199
+ * }
200
+ */
201
+ public function on_action_wp_create_application_password( $user_id, $item, $new_password, $args ) {
202
+ $user = get_user_by( 'ID', $user_id );
203
+
204
+ $this->infoMessage(
205
+ 'user_application_password_created',
206
+ array(
207
+ 'edited_user_id' => $user_id,
208
+ 'edited_user_email' => $user->user_email,
209
+ 'edited_user_login' => $user->user_login,
210
+ 'application_password_name' => $item['name'],
211
+ )
212
  );
213
+ }
214
+
215
+
216
+ /**
217
+ * Log when an Application password is deleted (revoked).
218
 
219
+ * Fired from action `wp_delete_application_password`.
220
+ *
221
+ * @since 5.6.0
222
+ *
223
+ * @param int $user_id The user ID.
224
+ * @param array $item The data about the application password.
225
+ */
226
+ public function on_action_wp_delete_application_password( $user_id, $item ) {
227
+ $user = get_user_by( 'ID', $user_id );
228
+
229
+ $this->infoMessage(
230
+ 'user_application_password_deleted',
231
+ array(
232
+ 'edited_user_id' => $user_id,
233
+ 'edited_user_email' => $user->user_email,
234
+ 'edited_user_login' => $user->user_login,
235
+ 'application_password_name' => $item['name'],
236
+ )
237
+ );
238
  }
239
 
240
+
241
+ /**
242
+ * Fires after the user's role has changed.
243
+ *
244
+ * @since 2.9.0
245
+ * @since 3.6.0 Added $old_roles to include an array of the user's previous roles.
246
+ *
247
+ * @param int $user_id The user ID.
248
+ * @param string $role The new role.
249
+ * @param string[] $old_roles An array of the user's previous roles.
250
+ */
251
+ public function on_set_user_role( $user_id, $role, $old_roles ) {
252
+ $current_screen = simple_history_get_current_screen();
253
+
254
+ // Bail if we are not on the users screen.
255
+ if ( $current_screen->id !== 'users' ) {
256
  return;
257
  }
258
 
259
+ $changed_user = get_user_by( 'ID', $user_id );
260
+
261
+ if ( ! is_array( $old_roles ) ) {
262
+ $old_roles = array();
263
  }
264
 
265
+ $old_role = (string) reset( $old_roles );
266
+
267
+ $this->noticeMessage(
268
+ 'user_role_updated',
269
+ array(
270
+ 'edited_user_id' => $user_id,
271
+ 'edited_user_email' => $changed_user->user_email,
272
+ 'edited_user_login' => $changed_user->user_login,
273
+ 'new_role' => $role,
274
+ 'old_role' => $old_role,
275
+ )
276
+ );
277
  }
 
278
 
279
  public function on_action_login_form_confirm_admin_email() {
280
  // Bail if button with name "correct-admin-email" was not clicked or if no nonce field exists.
288
  return;
289
  }
290
 
 
291
  $this->infoMessage( 'user_admin_email_confirm_correct_clicked' );
292
  }
293
 
294
+ /**
295
+ * Filters user data before the record is created or updated.
296
+ * Used to log user profile updates.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  *
298
+ * It only includes data in the users table, not any user metadata.
299
  *
300
+ * @since 4.9.0
301
+ * @since 5.8.0 The `$userdata` parameter was added.
302
  *
303
+ * @param array $data {
304
+ * Values and keys for the user.
305
  *
306
+ * @type string $user_login The user's login. Only included if $update == false
307
+ * @type string $user_pass The user's password.
308
+ * @type string $user_email The user's email.
309
+ * @type string $user_url The user's url.
310
+ * @type string $user_nicename The user's nice name. Defaults to a URL-safe version of user's login
311
+ * @type string $display_name The user's display name.
312
+ * @type string $user_registered MySQL timestamp describing the moment when the user registered. Defaults to
313
+ * the current UTC timestamp.
 
 
 
314
  * }
315
+ * @param bool $update Whether the user is being updated rather than created.
316
+ * @param int|null $user_id ID of the user to be updated, or NULL if the user is being created.
317
+ * @param array $userdata The raw array of data passed to wp_insert_user().
318
  */
319
+ public function on_pre_insert_user_data( $data, $update, $user_id, $userdata = array() ) {
320
+ // Bail if this is not a user update.
 
321
  if ( ! $update ) {
322
+ return $data;
323
  }
324
 
325
+ // Bail if we don't have all needed data.
326
+ if ( ! $data || ! $user_id ) {
327
+ return $data;
328
  }
329
 
330
+ $current_screen = simple_history_get_current_screen();
 
 
 
331
 
332
+ // Bail if we are not on the user-edit screen (edit other user) or profile screen (edit own user).
333
+ if ( ! in_array( $current_screen->id, array( 'user-edit', 'profile' ) ) ) {
334
+ return $data;
 
335
  }
336
 
337
+ // Array with differences between old and new values.
338
+ $user_data_diff = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
 
340
+ // Get user object that contains old/existing values.
341
+ $user_before_update = get_user_by( 'ID', $user_id );
342
 
 
 
 
343
  $password_changed = false;
 
 
 
 
 
 
 
 
 
 
344
 
345
+ foreach ( $userdata as $option_key => $one_maybe_updated_option_value ) {
346
+ $prev_option_value = $user_before_update->$option_key;
347
+ $add_diff = true;
348
+
349
+ // Some options need special treatment.
350
+ if ( $option_key === 'role' ) {
351
+ // Get text name of previous role.
352
+ $user_roles = array_intersect( array_values( $user_before_update->roles ), array_keys( get_editable_roles() ) );
353
+ $prev_option_value = reset( $user_roles );
354
+ } else if ( $option_key === 'user_pass' ) {
355
+ $password_changed = $one_maybe_updated_option_value !== $prev_option_value;
356
+ $add_diff = false;
357
+ } else if ( $option_key === 'comment_shortcuts' ) {
358
+ if ( empty( $one_maybe_updated_option_value ) ) {
359
+ $one_maybe_updated_option_value = 'false';
360
+ }
361
+ } else if ( $option_key === 'locale' ) {
362
+ if ( $one_maybe_updated_option_value === '' ) {
363
+ $one_maybe_updated_option_value = 'SITE_DEFAULT';
364
+ }
365
+ if ( $prev_option_value === '' ) {
366
+ $prev_option_value = 'SITE_DEFAULT';
367
+ }
 
368
  }
369
 
370
+ if ( $add_diff ) {
371
+ $user_data_diff = $this->addDiff( $user_data_diff, $option_key, $prev_option_value, $one_maybe_updated_option_value );
372
+ }
373
  }
374
 
375
+ // Setup basic context.
376
  $context = array(
377
+ 'edited_user_id' => $user_id,
378
+ 'edited_user_email' => $user_before_update->user_email,
379
+ 'edited_user_login' => $user_before_update->user_login,
380
  'server_http_user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
381
  );
382
 
384
  $context['edited_user_password_changed'] = '1';
385
  }
386
 
 
 
 
 
 
387
  // Add diff to context
388
  if ( $user_data_diff ) {
389
  foreach ( $user_data_diff as $one_diff_key => $one_diff_vals ) {
 
 
 
 
 
 
 
390
  $context[ "user_prev_{$one_diff_key}" ] = $one_diff_vals['old'];
391
  $context[ "user_new_{$one_diff_key}" ] = $one_diff_vals['new'];
392
  }
394
 
395
  $this->infoMessage( 'user_updated_profile', $context );
396
 
397
+ return $data;
398
  }
399
 
400
  /**
408
  */
409
  public function onRetrievePasswordMessage( $message, $key, $user_login, $user_data = null ) {
410
  $context = array(
 
411
  'message' => $message,
 
412
  'user_login' => $user_login,
413
  'user_email' => $user_data->user_email,
414
  );
415
 
416
+ // Request to send reset password link
417
+ // can be initiated from login screen or from users-listing-page in admin.
418
+ // Detect where from the request is coming.
419
+ $request_origin = 'unknown';
420
+
421
+ if ( function_exists( 'get_current_screen' ) ) {
422
+ $screen = get_current_screen();
423
+ if ( $screen && $screen->base === 'users' ) {
424
+ $request_origin = 'wp_admin_users_admin';
425
+ }
426
+ } else if ( ! empty( $_POST['user_login'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
427
+ $request_origin = 'login_screen';
428
+ }
429
+
430
+ if ( 'login_screen' === $request_origin ) {
431
+ $context['_initiator'] = SimpleLoggerLogInitiators::WEB_USER;
432
+ }
433
+
434
  $this->noticeMessage( 'user_requested_password_reset_link', $context );
435
 
436
  return $message;
467
  * @since 2.0.6
468
  */
469
  public function onDestroyUserSession() {
 
 
 
 
 
 
 
470
  // PHPCS:ignore WordPress.Security.NonceVerification.Missing
471
  $user = get_userdata( (int) $_POST['user_id'] );
472
 
657
  }
658
 
659
  /**
660
+ * User is created. Fired from action user_register.
661
+ * Fires immediately after a new user is registered.
662
  *
663
+ * @param int $user_id User ID.
664
+ * (@param array $userdata The raw array of data passed to wp_insert_user(). Since WP 5.8.0.)
665
  */
666
+ public function on_user_register( $user_id, $userdata = array() ) {
667
 
668
  if ( ! $user_id || ! is_numeric( $user_id ) ) {
669
  return;
812
  }
813
 
814
  /**
815
+ * Add diff to diff array if old and new values are different.
816
  *
817
  * Since 2.0.29
818
+ *
819
+ * @param array $post_data_diff
820
+ * @param string $key
821
+ * @param string $old_value
822
+ * @param string $new_value
823
+ * @return array
824
  */
825
  public function addDiff( $post_data_diff, $key, $old_value, $new_value ) {
826
  if ( $old_value != $new_value ) {
834
  }
835
 
836
  /**
837
+ * Return more info about an logged event.
838
+ *
839
+ * @param object $row
840
  */
841
  public function getLogRowDetailsOutput( $row ) {
842
  $context = $row->context;
846
  $diff_table_output = '';
847
 
848
  if ( 'user_updated_profile' == $message_key ) {
849
+ // Find all user_prev_ and user_new_ values and show them.
850
  $arr_user_keys_to_show_diff_for = array(
851
+ 'rich_editing' => array(
852
+ 'title' => _x( 'Visual editor', 'User logger', 'simple-history' ),
853
+ 'type' => 'checkbox',
854
+ 'value_true' => _x( 'Enable', 'User logger', 'simple-history' ),
855
+ 'value_false' => _x( 'Disable', 'User logger', 'simple-history' ),
856
+ ),
857
+ 'admin_color' => array(
858
+ 'title' => _x( 'Colour scheme', 'User logger', 'simple-history' ),
859
+ ),
860
+ 'comment_shortcuts' => array(
861
+ 'title' => _x( 'Keyboard shortcuts', 'User logger', 'simple-history' ),
862
+ 'type' => 'checkbox',
863
+ 'value_true' => _x( 'Enable', 'User logger', 'simple-history' ),
864
+ 'value_false' => _x( 'Disable', 'User logger', 'simple-history' ),
865
+ ),
866
+ 'show_admin_bar_front' => array(
867
+ 'title' => _x( 'Toolbar', 'User logger', 'simple-history' ),
868
+ 'type' => 'checkbox',
869
+ 'value_true' => _x( 'Show', 'User logger', 'simple-history' ),
870
+ 'value_false' => _x( "Don't show", 'User logger', 'simple-history' ),
871
+ ),
872
+ 'locale' => array(
873
+ 'title' => _x( 'Language', 'User logger', 'simple-history' ),
874
+ ),
875
+ 'role' => array(
876
+ 'title' => _x( 'Role', 'User logger', 'simple-history' ),
877
+ ),
878
  'first_name' => array(
879
  'title' => _x( 'First name', 'User logger', 'simple-history' ),
880
  ),
884
  'nickname' => array(
885
  'title' => _x( 'Nickname', 'User logger', 'simple-history' ),
886
  ),
887
+ 'display_name' => array(
888
+ 'title' => _x( 'Display name', 'User logger', 'simple-history' ),
 
 
 
 
889
  ),
890
+ 'user_email' => array(
891
+ 'title' => _x( 'Email', 'User logger', 'simple-history' ),
 
892
  ),
893
+ 'user_url' => array(
894
+ 'title' => _x( 'Website', 'User logger', 'simple-history' ),
 
895
  ),
896
+ 'description' => array(
897
+ 'title' => _x( 'Description', 'User logger', 'simple-history' ),
 
898
  ),
899
  'aim' => array(
900
  'title' => _x( 'AIM', 'User logger', 'simple-history' ),
905
  'jabber' => array(
906
  'title' => _x( 'Jabber / Google Talk ', 'User logger', 'simple-history' ),
907
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
908
  );
909
 
910
+ require_once ABSPATH . 'wp-admin/includes/translation-install.php';
911
+ $translations = wp_get_available_translations();
912
+
913
+ // English (United States) is not included in translations_array, add manually.
914
+ if ( ! isset( $translations['en_US'] ) ) {
915
+ $translations['en_US'] = array(
916
+ 'language' => 'en_US',
917
+ 'english_name' => 'English',
918
+ );
919
+ }
920
+
921
  foreach ( $arr_user_keys_to_show_diff_for as $key => $val ) {
922
  if ( isset( $context[ "user_prev_{$key}" ] ) && isset( $context[ "user_new_{$key}" ] ) ) {
923
  $user_old_value = $context[ "user_prev_{$key}" ];
924
  $user_new_value = $context[ "user_new_{$key}" ];
925
 
926
+ if ( $key === 'locale' ) {
927
+ if ( isset( $translations[ $user_old_value ] ) ) {
928
+ $language_english_name = $translations[ $user_old_value ]['english_name'];
929
+ $user_old_value = "{$language_english_name} ({$user_old_value})";
930
+ } else if ( $user_old_value === 'SITE_DEFAULT' ) {
931
+ $user_old_value = __( 'Site Default', 'simple-history' );
932
+ }
933
+
934
+ if ( isset( $translations[ $user_new_value ] ) ) {
935
+ $language_english_name = $translations[ $user_new_value ]['english_name'];
936
+ $user_new_value = "{$language_english_name} ({$user_new_value})";
937
+ } else if ( $user_new_value === 'SITE_DEFAULT' ) {
938
+ $user_new_value = __( 'Site Default', 'simple-history' );
939
+ }
940
+ }
941
+
942
+ // Change naming for checkbox items from "true" or "false" to
943
+ // something more user friendly "Checked" and "Unchecked".
944
+ if ( isset( $val['type'] ) && $val['type'] === 'checkbox' ) {
945
+ $user_old_value = ( $user_old_value === 'true' ) ? $val['value_true'] : $val['value_false'];
946
+ $user_new_value = ( $user_new_value === 'true' ) ? $val['value_true'] : $val['value_false'];
947
+ }
948
+
949
  $diff_table_output .= sprintf(
950
  '<tr>
951
  <td>%1$s</td>
961
  }
962
  }
963
 
964
+ // Check if password was changed.
965
  if ( isset( $context['edited_user_password_changed'] ) ) {
966
  $diff_table_output .= sprintf(
967
  '<tr>
1005
  'simple-history'
1006
  );
1007
  } else {
 
 
1008
  $sent_status = '';
1009
  }
1010
 
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: history, log, changes, changelog, audit, audit log, event log, user tracki
5
  Requires at least: 5.2
6
  Tested up to: 5.8.2
7
  Requires PHP: 5.6
8
- Stable tag: 3.1.1
9
 
10
  View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
11
 
@@ -193,6 +193,16 @@ Events in the log are stored for 60 days by default. Events older than this will
193
 
194
  == Changelog ==
195
 
 
 
 
 
 
 
 
 
 
 
196
  = 3.1.1 (January 2022) =
197
 
198
  - Fixed: Error when uploading images when using WordPress 5.7.0 or earlier.
5
  Requires at least: 5.2
6
  Tested up to: 5.8.2
7
  Requires PHP: 5.6
8
+ Stable tag: 3.2.0
9
 
10
  View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
11
 
193
 
194
  == Changelog ==
195
 
196
+ = 3.2.0 (February 2022) =
197
+
198
+ - Refactored detection of user profile updates. Order of updated user fields are now shown in the same order as they are in the edit user screen. Also the texts are updated to be more user friendly. And those "show toolbar"-messages that showed up at random times should be gone too. 🤞
199
+ - Added: Creation and deletion (revoke) of Application Passwords are now logged.
200
+ - Added: Role changes from users overview page are now logged.
201
+ - Fixed: Password reset links was always attributed to "Anonymous web user", even those that was sent from the users listing in the WordPress admin area.
202
+ - Fixed: Increase contrast ratio on some texts.
203
+ - Changed: `sh_d()` now tell you if a value is integer or numeric string or an empty string.
204
+ - Changed: The log message "Found an update to WordPress" had a dot in it. No other log message had a dot so the dot is no more.
205
+
206
  = 3.1.1 (January 2022) =
207
 
208
  - Fixed: Error when uploading images when using WordPress 5.7.0 or earlier.