Simple History - Version 2.8

Version Description

(August 2016) =

  • Theme installs are now logged
  • ...and so are theme updates
  • ...and theme deletions. Awesome!
  • Support for plugin Limit Login Attempts. Failed login attempts, lockouts and configuration changes will be logged.
  • Correct message is now used when a plugin update fails, i.e. the message for key plugin_update_failed.
  • The original untranslated strings for plugin name and so on are stored when storing info for plugin installs and updates and similar.
  • Default number of events to show is now 10 instead of 5.
Download this release

Release Info

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

Code changes from version 2.7.5 to 2.8

inc/SimpleHistory.php CHANGED
@@ -629,7 +629,7 @@ class SimpleHistory {
629
 
630
  } else {
631
 
632
- $data["logRows"] = $logRows;
633
  }
634
 
635
  break;
@@ -841,7 +841,8 @@ class SimpleHistory {
841
  // Loggers for third party plugins
842
  $loggersDir . "PluginUserSwitchingLogger.php",
843
  $loggersDir . "PluginEnableMediaReplaceLogger.php",
844
- $loggersDir . "Plugin_UltimateMembers_Logger.php"
 
845
  );
846
 
847
  // SimpleLogger.php must be loaded first and always since the other loggers extend it
@@ -1131,7 +1132,7 @@ class SimpleHistory {
1131
  */
1132
  function get_pager_size() {
1133
 
1134
- $pager_size = get_option( "simple_history_pager_size", 5 );
1135
 
1136
  /**
1137
  * Filter the pager size setting
629
 
630
  } else {
631
 
632
+ // $data["logRows"] = $logRows;
633
  }
634
 
635
  break;
841
  // Loggers for third party plugins
842
  $loggersDir . "PluginUserSwitchingLogger.php",
843
  $loggersDir . "PluginEnableMediaReplaceLogger.php",
844
+ $loggersDir . "Plugin_UltimateMembers_Logger.php",
845
+ $loggersDir . "Plugin_LimitLoginAttempts.php"
846
  );
847
 
848
  // SimpleLogger.php must be loaded first and always since the other loggers extend it
1132
  */
1133
  function get_pager_size() {
1134
 
1135
+ $pager_size = get_option( "simple_history_pager_size", 10 );
1136
 
1137
  /**
1138
  * Filter the pager size setting
index.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://simple-history.com
5
  Text Domain: simple-history
6
  Domain Path: /languages
7
  Description: Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.
8
- Version: 2.7.5
9
  Author: Pär Thernström
10
  Author URI: http://simple-history.com/
11
  License: GPL2
@@ -42,7 +42,7 @@ if ( version_compare( phpversion(), "5.3", ">=") ) {
42
  // register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
43
 
44
  if ( ! defined( 'SIMPLE_HISTORY_VERSION' ) ) {
45
- define( 'SIMPLE_HISTORY_VERSION', '2.7.5' );
46
  }
47
 
48
  if ( ! defined( 'SIMPLE_HISTORY_PATH' ) ) {
5
  Text Domain: simple-history
6
  Domain Path: /languages
7
  Description: Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.
8
+ Version: 2.8
9
  Author: Pär Thernström
10
  Author URI: http://simple-history.com/
11
  License: GPL2
42
  // register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
43
 
44
  if ( ! defined( 'SIMPLE_HISTORY_VERSION' ) ) {
45
+ define( 'SIMPLE_HISTORY_VERSION', '2.8' );
46
  }
47
 
48
  if ( ! defined( 'SIMPLE_HISTORY_PATH' ) ) {
loggers/Plugin_LimitLoginAttempts.php ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die();
4
+
5
+ /**
6
+ * Logger for the (old but still) very popular plugin Limit Login Attempts
7
+ * https://sv.wordpress.org/plugins/limit-login-attempts/
8
+ */
9
+ if ( ! class_exists("Plugin_LimitLoginAttempts") ) {
10
+
11
+ class Plugin_LimitLoginAttempts extends SimpleLogger {
12
+
13
+ public $slug = __CLASS__;
14
+
15
+ function getInfo() {
16
+
17
+ $arr_info = array(
18
+ "name" => "Plugin Limit Login Attempts",
19
+ "description" => _x("Logs failed login attempts, lockouts, and configuration changes made in the plugin Limit Login Attempts", "Logger: Plugin Limit Login Attempts", "simple-history"),
20
+ "name_via" => _x("Using plugin Limit Login Attempts", "Logger: Plugin Limit Login Attempts", "simple-history"),
21
+ "capability" => "manage_options",
22
+ "messages" => array(
23
+ //'user_locked_out' => _x( 'User locked out', "Logger: Plugin Limit Login Attempts", "simple-history" ),
24
+ 'failed_login_whitelisted' => _x( 'Failed login attempt from whitelisted IP', "Logger: Plugin Limit Login Attempts", 'simple-history' ),
25
+ 'failed_login' => _x( 'Was locked out because too many failed login attempts', "Logger: Plugin Limit Login Attempts", 'simple-history' ),
26
+ "cleared_ip_log" => _x( 'Cleared IP log', "Logger: Plugin Limit Login Attempts", "simple-history" ),
27
+ "reseted_lockout_count" => _x( 'Reseted lockout count', "Logger: Plugin Limit Login Attempts", "simple-history" ),
28
+ "cleared_current_lockouts" => _x( 'Cleared current lockouts', "Logger: Plugin Limit Login Attempts", "simple-history" ),
29
+ "updated_options" => _x( 'Updated options', "Logger: Plugin Limit Login Attempts", "simple-history" ),
30
+ ),
31
+ /*"labels" => array(
32
+ "search" => array(
33
+ "label" => _x( "Limit Login Attempts", "Logger: Plugin Limit Login Attempts", "simple-history" ),
34
+ "options" => array(
35
+ _x( "xxxPages not found", "User logger: 404", "simple-history" ) => array(
36
+ "page_not_found",
37
+ ),
38
+ ),
39
+ ), // end search
40
+ ),*/ // end labels
41
+ );
42
+
43
+ return $arr_info;
44
+
45
+ }
46
+
47
+ function loaded() {
48
+
49
+ add_filter( "pre_option_limit_login_lockouts_total", array( $this, "on_option_limit_login_lockouts_total" ), 10, 1 );
50
+
51
+ add_action( "load-settings_page_limit-login-attempts", array( $this, "on_load_settings_page" ), 10, 1 );
52
+
53
+ }
54
+
55
+ /**
56
+ * Fired when plugin options screen is loaded
57
+ */
58
+ function on_load_settings_page($a) {
59
+
60
+ if ( $_POST && wp_verify_nonce($_POST["_wpnonce"], "limit-login-attempts-options") ) {
61
+
62
+ // Settings saved
63
+ if (isset($_POST['clear_log'])) {
64
+ $this->noticeMessage( "cleared_ip_log" );
65
+ }
66
+
67
+ if (isset($_POST['reset_total'])) {
68
+ $this->noticeMessage( "reseted_lockout_count" );
69
+ }
70
+
71
+ if (isset($_POST['reset_current'])) {
72
+ $this->noticeMessage( "cleared_current_lockouts" );
73
+ }
74
+
75
+ if (isset($_POST['update_options'])) {
76
+
77
+ $options = array(
78
+ "client_type" => sanitize_text_field( $_POST['client_type'] ),
79
+ "allowed_retries" => sanitize_text_field( $_POST['allowed_retries'] ),
80
+ "lockout_duration" => sanitize_text_field( $_POST['lockout_duration'] ) * 60 ,
81
+ "valid_duration" => sanitize_text_field( $_POST['valid_duration'] ) * 3600,
82
+ "allowed_lockouts" => sanitize_text_field( $_POST['allowed_lockouts'] ),
83
+ "long_duration" => sanitize_text_field( $_POST['long_duration'] ) * 3600,
84
+ "email_after" => sanitize_text_field( $_POST['email_after'] ),
85
+ "cookies" => (isset($_POST['cookies']) && $_POST['cookies'] == '1') ? "yes" : "no"
86
+ );
87
+
88
+ $v = array();
89
+ if (isset($_POST['lockout_notify_log'])) {
90
+ $v[] = 'log';
91
+ }
92
+ if (isset($_POST['lockout_notify_email'])) {
93
+ $v[] = 'email';
94
+ }
95
+ $lockout_notify = implode(',', $v);
96
+ $options["lockout_notify"] = $lockout_notify;
97
+
98
+ $this->noticeMessage("updated_options", array(
99
+ "options" => $options
100
+ ));
101
+
102
+ }
103
+
104
+ }
105
+
106
+ }
107
+
108
+ /**
109
+ * When option value is updated
110
+ * do same checks as plugin itself does
111
+ * and log if we match something
112
+ */
113
+ function on_option_limit_login_lockouts_total( $value ) {
114
+
115
+ global $limit_login_just_lockedout;
116
+
117
+ if ( ! $limit_login_just_lockedout ) {
118
+ return $value;
119
+ }
120
+
121
+ $ip = limit_login_get_address();
122
+ $whitelisted = is_limit_login_ip_whitelisted( $ip );
123
+
124
+ $retries = get_option( 'limit_login_retries' );
125
+ if ( ! is_array( $retries ) ) {
126
+ $retries = array();
127
+ }
128
+
129
+ if ( isset( $retries[$ip] ) && ( ( $retries[$ip] / limit_login_option( 'allowed_retries' ) ) % limit_login_option( 'notify_email_after' ) ) != 0 ) {
130
+
131
+ // $this->notice( "user locked out but don't log" );
132
+ //return;
133
+
134
+ }
135
+
136
+ /* Format message. First current lockout duration */
137
+ $lockout_type = "";
138
+ if ( ! isset( $retries[$ip] ) ) {
139
+ /* longer lockout */
140
+ $lockout_type = "longer";
141
+ $count = limit_login_option( 'allowed_retries' ) * limit_login_option( 'allowed_lockouts' );
142
+ $lockouts = limit_login_option( 'allowed_lockouts' );
143
+ $time = round( limit_login_option( 'long_duration' ) / 3600 );
144
+ #$when = sprintf( _n( '%d hour', '%d hours', $time, "Logger: Plugin Limit Login Attempts", 'limit-login-attempts' ), $time );
145
+ } else {
146
+ /* normal lockout */
147
+ $lockout_type = "normal";
148
+ $count = $retries[$ip];
149
+ $lockouts = floor( $count / limit_login_option( 'allowed_retries' ) );
150
+ $time = round( limit_login_option( 'lockout_duration' ) / 60 );
151
+ //$when = sprintf( _n( '%d minute', '%d minutes', $time, 'limit-login-attempts' ), $time );
152
+ }
153
+
154
+ if ( $whitelisted ) {
155
+ // $subject = __( "Failed login attempts from whitelisted IP", 'limit-login-attempts' );
156
+ $message_key = "failed_login_whitelisted";
157
+ } else {
158
+ // $subject = __( "Too many failed login attempts", 'limit-login-attempts' );
159
+ $message_key = "failed_login";
160
+ }
161
+
162
+ $this->noticeMessage( $message_key, array(
163
+ "_initiator" => SimpleLoggerLogInitiators::WEB_USER,
164
+ "value" => $value,
165
+ "limit_login_just_lockedout" => $limit_login_just_lockedout,
166
+ //"retries" => $retries,
167
+ //"whitelisted" => $whitelisted, // bool, true | false
168
+ //"subject" => $subject,
169
+ //"message" => $message,
170
+ "count" => $count, // num of failed login attempts before block
171
+ "time" => $time, // duration in minutes for block
172
+ "lockouts" => $lockouts,
173
+ "ip" => $ip,
174
+ "lockout_type" => $lockout_type
175
+ ) );
176
+
177
+ return $value;
178
+
179
+ }
180
+
181
+
182
+ /**
183
+ * Add some extra info
184
+ */
185
+ function getLogRowDetailsOutput( $row ) {
186
+
187
+ $output = "";
188
+
189
+ $context = isset( $row->context ) ? $row->context : array();
190
+
191
+ $message_key = $row->context_message_key;
192
+
193
+ if ( "failed_login" == $message_key ) {
194
+
195
+ $count = $context["count"];
196
+ $lockouts = $context["lockouts"];
197
+ $ip = $context["ip"];
198
+ #$whitelisted = $context["whitelisted"];
199
+ $lockout_type = $context["lockout_type"];
200
+ $time = $context["time"];
201
+
202
+ $output .= sprintf(
203
+ "<p>" . _x( '%1$d failed login attempts (%2$d lockout(s)) from IP: %3$s', 'Logger: Plugin Limit Login Attempts', 'simple-history' ) . "</p>",
204
+ $count, // 1
205
+ $lockouts, // 2
206
+ $ip // 3
207
+ );
208
+
209
+ if ( "longer" == $lockout_type ) {
210
+
211
+ $when = sprintf( _nx( '%d hour', '%d hours', $time, 'Logger: Plugin Limit Login Attempts', 'limit-login-attempts' ), $time );
212
+
213
+ } else if ( "normal" == $lockout_type ) {
214
+
215
+ $when = sprintf( _nx( '%d minute', '%d minutes', $time, 'Logger: Plugin Limit Login Attempts', 'limit-login-attempts' ), $time );
216
+
217
+ }
218
+
219
+ $output .= "<p>" . sprintf(
220
+ _x( 'IP was blocked for %1$s', 'Logger: Plugin Limit Login Attempts', 'simple-history' ),
221
+ $when // 1
222
+ ) . "</p>";
223
+
224
+ }
225
+
226
+ return $output;
227
+
228
+ }
229
+
230
+ } // class
231
+
232
+ } // class exists
loggers/SimplePluginLogger.php CHANGED
@@ -55,7 +55,7 @@ class SimplePluginLogger extends SimpleLogger
55
  ),
56
 
57
  'plugin_update_failed' => _x(
58
- 'Updated plugin "{plugin_name}"',
59
  'Plugin update failed',
60
  'simple-history'
61
  ),
@@ -543,19 +543,30 @@ class SimplePluginLogger extends SimpleLogger
543
 
544
  /**
545
  * Called when plugins is updated or installed
 
 
 
 
 
 
 
546
  */
547
  function on_upgrader_process_complete( $plugin_upgrader_instance, $arr_data ) {
548
 
549
  // Can't use get_plugins() here to get version of plugins updated from
550
  // Tested that, and it will get the new version (and that's the correct answer I guess. but too bad for us..)
551
  // $plugs = get_plugins();
552
- // $context["_debug_get_plugins"] = SimpleHistory::json_encode( $plugs );
553
- /*
554
 
555
- Try with these instead:
556
- $current = get_site_transient( 'update_plugins' );
557
- add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4);
 
 
 
 
 
558
 
 
559
  */
560
 
561
  /*
@@ -703,7 +714,7 @@ class SimplePluginLogger extends SimpleLogger
703
 
704
  $plugin_data = array();
705
  if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_info ) ) {
706
- $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_info );
707
  }
708
 
709
  $context["plugin_name"] = isset( $plugin_data["Name"] ) ? $plugin_data["Name"] : "";
@@ -739,7 +750,7 @@ class SimplePluginLogger extends SimpleLogger
739
  // No plugin info in instance, so get it ourself
740
  $plugin_data = array();
741
  if ( file_exists( WP_PLUGIN_DIR . '/' . $arr_data["plugin"] ) ) {
742
- $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $arr_data["plugin"] );
743
  }
744
 
745
  // autoptimize/autoptimize.php
@@ -851,7 +862,7 @@ class SimplePluginLogger extends SimpleLogger
851
 
852
  foreach ($plugins_updated as $plugin_name) {
853
 
854
- $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name );
855
 
856
  $plugin_slug = dirname( $plugin_name );
857
 
@@ -1051,7 +1062,7 @@ class SimplePluginLogger extends SimpleLogger
1051
  'DomainPath' - Plugin's relative directory path to .mo files.
1052
  'Network' - Boolean. Whether the plugin can only be activated network wide.
1053
  */
1054
- $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name );
1055
 
1056
  $plugin_slug = dirname( $plugin_name );
1057
 
@@ -1079,7 +1090,7 @@ class SimplePluginLogger extends SimpleLogger
1079
  */
1080
  function on_deactivated_plugin($plugin_name) {
1081
 
1082
- $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name );
1083
  $plugin_slug = dirname( $plugin_name );
1084
 
1085
  $context = array(
55
  ),
56
 
57
  'plugin_update_failed' => _x(
58
+ 'Failed to update plugin "{plugin_name}"',
59
  'Plugin update failed',
60
  'simple-history'
61
  ),
543
 
544
  /**
545
  * Called when plugins is updated or installed
546
+ * Called from class-wp-upgrader.php
547
+ *
548
+ * @param Plugin_Upgrader $this Plugin_Upgrader instance. In other contexts, $this, might
549
+ * be a Theme_Upgrader or Core_Upgrade instance.
550
+ * @param array $data {
551
+ * Array of bulk item update data.
552
+
553
  */
554
  function on_upgrader_process_complete( $plugin_upgrader_instance, $arr_data ) {
555
 
556
  // Can't use get_plugins() here to get version of plugins updated from
557
  // Tested that, and it will get the new version (and that's the correct answer I guess. but too bad for us..)
558
  // $plugs = get_plugins();
 
 
559
 
560
+ /*
561
+ If an update fails then $plugin_upgrader_instance->skin->result->errors contains something like:
562
+ Array
563
+ (
564
+ [remove_old_failed] => Array
565
+ (
566
+ [0] => Could not remove the old plugin.
567
+ )
568
 
569
+ )
570
  */
571
 
572
  /*
714
 
715
  $plugin_data = array();
716
  if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_info ) ) {
717
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_info, true, false );
718
  }
719
 
720
  $context["plugin_name"] = isset( $plugin_data["Name"] ) ? $plugin_data["Name"] : "";
750
  // No plugin info in instance, so get it ourself
751
  $plugin_data = array();
752
  if ( file_exists( WP_PLUGIN_DIR . '/' . $arr_data["plugin"] ) ) {
753
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $arr_data["plugin"], true, false );
754
  }
755
 
756
  // autoptimize/autoptimize.php
862
 
863
  foreach ($plugins_updated as $plugin_name) {
864
 
865
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name, true, false );
866
 
867
  $plugin_slug = dirname( $plugin_name );
868
 
1062
  'DomainPath' - Plugin's relative directory path to .mo files.
1063
  'Network' - Boolean. Whether the plugin can only be activated network wide.
1064
  */
1065
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name, true, false );
1066
 
1067
  $plugin_slug = dirname( $plugin_name );
1068
 
1090
  */
1091
  function on_deactivated_plugin($plugin_name) {
1092
 
1093
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name, true, false );
1094
  $plugin_slug = dirname( $plugin_name );
1095
 
1096
  $context = array(
loggers/SimpleThemeLogger.php CHANGED
@@ -25,6 +25,9 @@ class SimpleThemeLogger extends SimpleLogger {
25
  "capability" => "edit_theme_options",
26
  "messages" => array(
27
  'theme_switched' => __('Switched theme to "{theme_name}" from "{prev_theme_name}"', "simple-history"),
 
 
 
28
  'appearance_customized' => __('Customized theme appearance "{setting_id}"', "simple-history"),
29
  'widget_removed' => __('Removed widget "{widget_id_base}" from sidebar "{sidebar_id}"', "simple-history"),
30
  'widget_added' => __('Added widget "{widget_id_base}" to sidebar "{sidebar_id}"', "simple-history"),
@@ -37,6 +40,15 @@ class SimpleThemeLogger extends SimpleLogger {
37
  "label" => _x("Themes & Widgets", "Theme logger: search", "simple-history"),
38
  "label_all" => _x("All theme activity", "Theme logger: search", "simple-history"),
39
  "options" => array(
 
 
 
 
 
 
 
 
 
40
  _x("Switched themes", "Theme logger: search", "simple-history") => array(
41
  "theme_switched"
42
  ),
@@ -89,6 +101,233 @@ class SimpleThemeLogger extends SimpleLogger {
89
 
90
  add_action( "load-appearance_page_custom-background", array( $this, "on_page_load_custom_background" ) );
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  }
94
 
@@ -121,8 +360,6 @@ class SimpleThemeLogger extends SimpleLogger {
121
 
122
  }
123
 
124
-
125
-
126
  }
127
 
128
  /*
25
  "capability" => "edit_theme_options",
26
  "messages" => array(
27
  'theme_switched' => __('Switched theme to "{theme_name}" from "{prev_theme_name}"', "simple-history"),
28
+ 'theme_installed' => __('Installed theme "{theme_name}"', "simple-history"),
29
+ 'theme_deleted' => __('Deleted theme with slug "{theme_slug}"', "simple-history"),
30
+ 'theme_updated' => __('Updated theme "{theme_name}"', "simple-history"),
31
  'appearance_customized' => __('Customized theme appearance "{setting_id}"', "simple-history"),
32
  'widget_removed' => __('Removed widget "{widget_id_base}" from sidebar "{sidebar_id}"', "simple-history"),
33
  'widget_added' => __('Added widget "{widget_id_base}" to sidebar "{sidebar_id}"', "simple-history"),
40
  "label" => _x("Themes & Widgets", "Theme logger: search", "simple-history"),
41
  "label_all" => _x("All theme activity", "Theme logger: search", "simple-history"),
42
  "options" => array(
43
+ _x("Updated themes", "Theme logger: search", "simple-history") => array(
44
+ "theme_updated"
45
+ ),
46
+ _x("Deleted themes", "Theme logger: search", "simple-history") => array(
47
+ "theme_deleted"
48
+ ),
49
+ _x("Installed themes", "Theme logger: search", "simple-history") => array(
50
+ "theme_installed"
51
+ ),
52
  _x("Switched themes", "Theme logger: search", "simple-history") => array(
53
  "theme_switched"
54
  ),
101
 
102
  add_action( "load-appearance_page_custom-background", array( $this, "on_page_load_custom_background" ) );
103
 
104
+ add_action( "upgrader_process_complete", array( $this, "on_upgrader_process_complete_theme_install" ), 10, 2 );
105
+ add_action( "upgrader_process_complete", array( $this, "on_upgrader_process_complete_theme_update" ), 10, 2 );
106
+
107
+ // delete_site_transient( 'update_themes' );
108
+ //do_action( 'deleted_site_transient', $transient );
109
+ add_action( 'deleted_site_transient', array( $this, "on_deleted_site_transient_theme_deleted" ), 10, 1 );
110
+
111
+ }
112
+
113
+ /*
114
+ * Fires after a transient is deleted.
115
+ * WP function delete_theme() does not have any actions or filters we can use to detect
116
+ * a theme deletion, but the last thing that is done in delete_theme() is that the
117
+ * "update_themes" transient is deleted. So use that info to catch theme deletions.
118
+ *
119
+ * @param string $transient Deleted transient name.
120
+ */
121
+ function on_deleted_site_transient_theme_deleted( $transient = null ) {
122
+
123
+ if ( "update_themes" !== $transient ) {
124
+ return;
125
+ }
126
+
127
+ /*
128
+ When a theme is deleted we have this info:
129
+
130
+ $_GET:
131
+ {
132
+ "action": "delete",
133
+ "stylesheet": "CherryFramework",
134
+ "_wpnonce": "1c1571004e"
135
+ }
136
+
137
+
138
+ */
139
+
140
+ if ( empty( $_GET["action"] ) || $_GET["action"] !== "delete" ) {
141
+ return;
142
+ }
143
+
144
+ if ( empty( $_GET["stylesheet"] ) ) {
145
+ return;
146
+ }
147
+
148
+ $theme_deleted_slug = (string) $_GET["stylesheet"];
149
+
150
+ $this->infoMessage(
151
+ "theme_deleted",
152
+ array(
153
+ "theme_slug" => $theme_deleted_slug
154
+ )
155
+ );
156
+
157
+ }
158
+
159
+
160
+ function on_upgrader_process_complete_theme_update( $upgrader_instance = null, $arr_data = null ) {
161
+
162
+ /*
163
+ For theme updates $arr_data looks like
164
+
165
+ // From core update/bulk
166
+ Array
167
+ (
168
+ [action] => update
169
+ [type] => theme
170
+ [bulk] => 1
171
+ [themes] => Array
172
+ (
173
+ [0] => baskerville
174
+ )
175
+
176
+ )
177
+
178
+ // From themes.php/single
179
+ Array
180
+ (
181
+ [action] => update
182
+ [theme] => baskerville
183
+ [type] => theme
184
+ )
185
+ */
186
+
187
+ // Both args must be set
188
+ if ( empty( $upgrader_instance ) || empty( $arr_data ) ) {
189
+ return;
190
+ }
191
+
192
+ // Must be type theme and action install
193
+ if ( $arr_data["type"] !== "theme" || $arr_data["action"] !== "update" ) {
194
+ return;
195
+ }
196
+
197
+ // Skin contains the nice info
198
+ if ( empty( $upgrader_instance->skin ) ) {
199
+ return;
200
+ }
201
+
202
+ $skin = $upgrader_instance->skin;
203
+
204
+ $arr_themes = array();
205
+
206
+ // If single install make an array so it look like bulk and we can use same code
207
+ if ( isset( $arr_data["bulk"] ) && $arr_data["bulk"] && isset( $arr_data["themes"] ) ) {
208
+ $arr_themes = (array) $arr_data["themes"];
209
+ } else {
210
+ $arr_themes = array(
211
+ $arr_data["theme"]
212
+ );
213
+ }
214
+
215
+ /*
216
+ ob_start();
217
+ print_r($skin);
218
+ $skin_str = ob_get_clean();
219
+ echo "<pre>";
220
+ print_r($arr_data);
221
+ print_r($skin);
222
+ // */
223
+
224
+ // $one_updated_theme is the theme slug
225
+ foreach ( $arr_themes as $one_updated_theme ) {
226
+
227
+ $theme_info_object = wp_get_theme( $one_updated_theme );
228
+
229
+ if ( ! is_a( $theme_info_object, "WP_Theme" ) ) {
230
+ continue;
231
+ }
232
+
233
+ $theme_name = $theme_info_object->get("Name");
234
+ $theme_version = $theme_info_object->get("Version");
235
+
236
+ if ( ! $theme_name || ! $theme_version ) {
237
+ continue;
238
+ }
239
+
240
+ $this->infoMessage(
241
+ "theme_updated",
242
+ array(
243
+ "theme_name" => $theme_name,
244
+ "theme_version" => $theme_version,
245
+ )
246
+ );
247
+
248
+ }
249
+
250
+ }
251
+
252
+ function on_upgrader_process_complete_theme_install( $upgrader_instance = null, $arr_data = null ) {
253
+
254
+ /*
255
+
256
+ For theme installs $arr_data looks like:
257
+
258
+ Array
259
+ (
260
+ [type] => theme
261
+ [action] => install
262
+ )
263
+
264
+ */
265
+
266
+ // Both args must be set
267
+ if ( empty( $upgrader_instance ) || empty( $arr_data ) ) {
268
+ return;
269
+ }
270
+
271
+ // Must be type theme and action install
272
+ if ( $arr_data["type"] !== "theme" || $arr_data["action"] !== "install" ) {
273
+ return;
274
+ }
275
+
276
+ // Skin contains the nice info
277
+ if ( empty( $upgrader_instance->skin ) ) {
278
+ return;
279
+ }
280
+
281
+ $skin = $upgrader_instance->skin;
282
+
283
+ /*
284
+ ob_start();
285
+ print_r($skin);
286
+ $skin_str = ob_get_clean();
287
+ */
288
+
289
+ /*
290
+ Interesting parts in $skin:
291
+
292
+ // type can be "web" or nnn
293
+ [type] => web
294
+
295
+ // api seems to contains theme info and description
296
+ [api] => stdClass Object
297
+ (
298
+ [name] => Hemingway
299
+ [slug] => hemingway
300
+ [version] => 1.56
301
+ [preview_url] => https://wp-themes.com/hemingway
302
+ [author] => anlino
303
+ [screenshot_url] => //ts.w.org/wp-content/themes/hemingway/screenshot.png?ver=1.56
304
+ [rating] => 94
305
+ [num_ratings] => 35
306
+ [downloaded] => 282236
307
+ [last_updated] => 2016-07-03
308
+ [homepage] => https://wordpress.org/themes/hemingway/
309
+ [download_link] => https://downloads.wordpress.org/theme/hemingway.1.56.zip
310
+ )
311
+
312
+ */
313
+
314
+ $type = empty( $skin->type ) ? null : $skin->type ;
315
+ $theme_name = empty( $skin->api->name ) ? null : $skin->api->name;
316
+ $theme_slug = empty( $skin->api->slug ) ? null : $skin->api->slug;
317
+ $theme_version = empty( $skin->api->version ) ? null : $skin->api->version;
318
+ #$theme_screenshot_url = $skin->api->screenshot_url;
319
+ #$theme_last_updated = $skin->api->last_updated;
320
+ #$theme_last_homepage = $skin->api->last_homepage;
321
+ #$theme_download_link = $skin->api->last_download_link;
322
+
323
+ $this->infoMessage(
324
+ "theme_installed",
325
+ array(
326
+ "theme_name" => $theme_name,
327
+ "theme_version" => $theme_version,
328
+ // "debug_skin" => $skin_str
329
+ )
330
+ );
331
 
332
  }
333
 
360
 
361
  }
362
 
 
 
363
  }
364
 
365
  /*
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://eskapism.se/sida/donate/
4
  Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, dashboard, admin, syslog, feed, activity, stream, audit trail, brute-force
5
  Requires at least: 4.5.1
6
  Tested up to: 4.5.2
7
- Stable tag: 2.7.5
8
 
9
  View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
10
 
@@ -38,17 +38,23 @@ see when someone has tried to log in, but failed. The log will then include ip a
38
  * **Option screens**<br>
39
  view details about changes made in the differnt settings sections of WordPress. Things like changes to the site title and the permalink structure will be logged.
40
 
 
41
  #### Support for third party plugins
42
 
43
- By default Simple History comes with support for these third party plugins:
44
 
45
  **User Switching**
46
- The [User Switching plugin](https://wordpress.org/plugins/user-switching/) allows you to quickly swap between user accounts in WordPress at the click of a button. Simple History will log each user switch being made.
 
47
 
48
  **Enable Media Replace**
49
- The [Enable Media Replace plugin](https://wordpress.org/plugins/enable-media-replace/) allows you to replace a file in your media library by uploading a new file in its place. Simple history will log details about the file being replaced and details about the new file.
 
50
 
51
- Support for more plugins are coming.
 
 
 
52
 
53
  #### RSS feed available
54
 
@@ -147,6 +153,17 @@ A simple way to see any uncommon activity, for example an increased number of lo
147
 
148
  ## Changelog
149
 
 
 
 
 
 
 
 
 
 
 
 
150
  = 2.7.5 (August 2016) =
151
 
152
  - User logins using e-mail are now logged correctly. Previously the user would be logged in successfully but the log said that they failed.
4
  Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, dashboard, admin, syslog, feed, activity, stream, audit trail, brute-force
5
  Requires at least: 4.5.1
6
  Tested up to: 4.5.2
7
+ Stable tag: 2.8
8
 
9
  View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
10
 
38
  * **Option screens**<br>
39
  view details about changes made in the differnt settings sections of WordPress. Things like changes to the site title and the permalink structure will be logged.
40
 
41
+
42
  #### Support for third party plugins
43
 
44
+ By default Simple History comes with built in support for the following plugins:
45
 
46
  **User Switching**
47
+ The [User Switching plugin](https://wordpress.org/plugins/user-switching/) allows you to quickly swap between user accounts in WordPress at the click of a button.
48
+ Simple History will log each user switch being made.
49
 
50
  **Enable Media Replace**
51
+ The [Enable Media Replace plugin](https://wordpress.org/plugins/enable-media-replace/) allows you to replace a file in your media library by uploading a new file in its place.
52
+ Simple history will log details about the file being replaced and details about the new file.
53
 
54
+ **Limit Login Attempts**
55
+ The plugin [Limit Login Attempts](https://sv.wordpress.org/plugins/limit-login-attempts/) is old
56
+ and has not been updated for 4 years. However it still has +1 million installs, so many users will benefit from
57
+ Simple History logging login attempts, lockouts, and configuration changes made in the plugin Limit Login Attempts.
58
 
59
  #### RSS feed available
60
 
153
 
154
  ## Changelog
155
 
156
+ = 2.8 (August 2016) =
157
+
158
+ - Theme installs are now logged
159
+ - ...and so are theme updates
160
+ - ...and theme deletions. Awesome!
161
+ - Support for plugin [Limit Login Attempts](https://wordpress.org/plugins/limit-login-attempts/).
162
+ Failed login attempts, lockouts and configuration changes will be logged.
163
+ - Correct message is now used when a plugin update fails, i.e. the message for key `plugin_update_failed`.
164
+ - The original untranslated strings for plugin name and so on are stored when storing info for plugin installs and updates and similar.
165
+ - Default number of events to show is now 10 instead of 5.
166
+
167
  = 2.7.5 (August 2016) =
168
 
169
  - User logins using e-mail are now logged correctly. Previously the user would be logged in successfully but the log said that they failed.