Simple History - Version 2.19

Version Description

(November 2017) =

  • Add filter simple_history/user_can_clear_log. Return false from this filter to disable the "Clear blog" button.
  • Remove static keyword from some methods in SimpleLogger, so now calls like SimpleLogger()->critical('Doh!'); works.
  • Don't show link to WordPress updates if user is not allowed to view the updates page.
  • Fix notice error in SimpleOptionsLogger.
  • Fix for fatal errors when using the lost password form in Membership 2. Fixes https://wordpress.org/support/topic/conflict-with-simple-history-plugin-and-php-7/.
  • Code (a little bit) better formatted according to WordPress coding standard.
Download this release

Release Info

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

Code changes from version 2.18 to 2.19

Files changed (55) hide show
  1. dropins/SimpleHistoryDonateDropin.php +12 -12
  2. dropins/SimpleHistoryExportDropin.php +74 -82
  3. dropins/SimpleHistoryFilterDropin.php +137 -148
  4. dropins/SimpleHistoryIpInfoDropin.php +17 -17
  5. dropins/SimpleHistoryNewRowsNotifier.php +28 -24
  6. dropins/SimpleHistoryPluginPatchesDropin.php +58 -66
  7. dropins/SimpleHistoryRSSDropin.php +385 -396
  8. dropins/SimpleHistorySettingsDebugDropin.php +4 -5
  9. dropins/SimpleHistorySettingsLogtestDropin.php +75 -77
  10. dropins/SimpleHistorySettingsStatsDropin.php +20 -20
  11. dropins/SimpleHistorySidebarDropin.php +51 -59
  12. dropins/SimpleHistorySidebarStats.php +44 -43
  13. dropins/SimpleHistoryWPCLIDropin.php +69 -73
  14. examples/example-dropin.php +27 -27
  15. examples/example-logger.php +73 -73
  16. examples/examples.php +116 -100
  17. inc/SimpleHistory.php +609 -616
  18. inc/SimpleHistoryLogQuery.php +163 -184
  19. index.php +43 -49
  20. loggers/AvailableUpdatesLogger.php +238 -217
  21. loggers/FileEditsLogger.php +108 -114
  22. loggers/PluginEnableMediaReplaceLogger.php +19 -19
  23. loggers/PluginUserSwitchingLogger.php +43 -43
  24. loggers/Plugin_DuplicatePost.php +117 -120
  25. loggers/Plugin_LimitLoginAttempts.php +205 -206
  26. loggers/Plugin_Redirection.php +77 -78
  27. loggers/Plugin_UltimateMembers_Logger.php +8 -8
  28. loggers/SimpleCategoriesLogger.php +41 -42
  29. loggers/SimpleCommentsLogger.php +174 -184
  30. loggers/SimpleCoreUpdatesLogger.php +53 -54
  31. loggers/SimpleExportLogger.php +26 -26
  32. loggers/SimpleLegacyLogger.php +30 -34
  33. loggers/SimpleLogger.php +266 -291
  34. loggers/SimpleMediaLogger.php +99 -107
  35. loggers/SimpleMenuLogger.php +86 -93
  36. loggers/SimpleOptionsLogger.php +92 -100
  37. loggers/SimplePluginLogger.php +223 -252
  38. loggers/SimplePostLogger.php +286 -322
  39. loggers/SimpleThemeLogger.php +287 -319
  40. loggers/SimpleUserLogger.php +855 -881
  41. phpcs.xml.dist +39 -0
  42. readme.txt +27 -16
  43. templates/settings-general.php +4 -4
  44. templates/settings-log.php +1 -1
  45. templates/settings-statsForGeeks.php +54 -54
  46. templates/settings-statsInitiators.php +13 -14
  47. templates/settings-statsIntro.php +6 -6
  48. templates/settings-statsLogLevels.php +18 -18
  49. templates/settings-statsLoggers.php +29 -30
  50. templates/settings-statsRowsPerDay.php +24 -22
  51. templates/settings-statsUsers.php +40 -41
  52. templates/settings-style-example.php +99 -99
  53. templates/template-settings-tab-debug.php +57 -59
  54. tests/test-simplehistory.php +116 -119
  55. uninstall.php +14 -12
dropins/SimpleHistoryDonateDropin.php CHANGED
@@ -17,11 +17,11 @@ class SimpleHistoryDonateDropin {
17
  // Simple History instance
18
  private $sh;
19
 
20
- function __construct($sh) {
21
 
22
  $this->sh = $sh;
23
- add_action( 'admin_menu', array($this, 'add_settings'), 50 );
24
- add_action( 'plugin_row_meta', array($this, 'action_plugin_row_meta'), 10, 2);
25
 
26
  }
27
 
@@ -29,13 +29,13 @@ class SimpleHistoryDonateDropin {
29
  * Add link to the donate page in the Plugins » Installed plugins screen
30
  * Called from filter 'plugin_row_meta'
31
  */
32
- function action_plugin_row_meta($links, $file) {
33
 
34
- if ($file == $this->sh->plugin_basename) {
35
 
36
  $links = array_merge(
37
  $links,
38
- array( sprintf( '<a href="http://eskapism.se/sida/donate/?utm_source=wordpress&utm_medium=pluginpage&utm_campaign=simplehistory">%1$s</a>', __('Donate', "simple-history") ) )
39
  );
40
 
41
  }
@@ -46,12 +46,12 @@ class SimpleHistoryDonateDropin {
46
 
47
  public function add_settings() {
48
 
49
- $settings_section_id = "simple_history_settings_section_donate";
50
 
51
  add_settings_section(
52
  $settings_section_id,
53
- _x("Donate", "donate settings headline", "simple-history"), // No title __("General", "simple-history"),
54
- array($this, "settings_section_output"),
55
  SimpleHistory::SETTINGS_MENU_SLUG // same slug as for options menu page
56
  );
57
 
@@ -71,9 +71,9 @@ class SimpleHistoryDonateDropin {
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
- "http://eskapism.se/sida/donate/?utm_source=wordpress&utm_medium=pluginpage&utm_campaign=simplehistory",
76
- "http://www.amazon.co.uk/registry/wishlist/IAEZWNLQQICG"
77
  );
78
 
79
  }
17
  // Simple History instance
18
  private $sh;
19
 
20
+ function __construct( $sh ) {
21
 
22
  $this->sh = $sh;
23
+ add_action( 'admin_menu', array( $this, 'add_settings' ), 50 );
24
+ add_action( 'plugin_row_meta', array( $this, 'action_plugin_row_meta' ), 10, 2 );
25
 
26
  }
27
 
29
  * Add link to the donate page in the Plugins » Installed plugins screen
30
  * Called from filter 'plugin_row_meta'
31
  */
32
+ function action_plugin_row_meta( $links, $file ) {
33
 
34
+ if ( $file == $this->sh->plugin_basename ) {
35
 
36
  $links = array_merge(
37
  $links,
38
+ array( sprintf( '<a href="http://eskapism.se/sida/donate/?utm_source=wordpress&utm_medium=pluginpage&utm_campaign=simplehistory">%1$s</a>', __( 'Donate', 'simple-history' ) ) )
39
  );
40
 
41
  }
46
 
47
  public function add_settings() {
48
 
49
+ $settings_section_id = 'simple_history_settings_section_donate';
50
 
51
  add_settings_section(
52
  $settings_section_id,
53
+ _x( 'Donate', 'donate settings headline', 'simple-history' ), // No title __("General", "simple-history"),
54
+ array( $this, 'settings_section_output' ),
55
  SimpleHistory::SETTINGS_MENU_SLUG // same slug as for options menu page
56
  );
57
 
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
+ 'http://eskapism.se/sida/donate/?utm_source=wordpress&utm_medium=pluginpage&utm_campaign=simplehistory',
76
+ 'http://www.amazon.co.uk/registry/wishlist/IAEZWNLQQICG'
77
  );
78
 
79
  }
dropins/SimpleHistoryExportDropin.php CHANGED
@@ -12,19 +12,19 @@ class SimpleHistoryExportDropin {
12
  // Simple History instance
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"),
24
- "function" => array($this, "output")
25
  ));
26
 
27
- add_action("init", array($this, "downloadExport"));
28
 
29
  }
30
 
@@ -35,72 +35,71 @@ class SimpleHistoryExportDropin {
35
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
36
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
37
 
38
- if ( isset($_POST["simple-history-action"]) && $_POST["simple-history-action"] === "export-history" ) {
39
 
40
  // Will die if nonce not valid
41
- check_admin_referer( __CLASS__ . "-action-export" );
42
 
43
- $export_format = isset( $_POST["format"] ) ? $_POST["format"] : "json";
44
 
45
  // Disable relative time output in header
46
- add_filter("simple_history/header_time_ago_max_time", "__return_zero");
47
- add_filter("simple_history/header_just_now_max_time", "__return_zero");
48
 
49
  // Don't use "You" if event is initiated by the same user that does the export
50
- add_filter("simple_history/header_initiator_use_you", "__return_false");
51
 
52
  $query = new SimpleHistoryLogQuery();
53
 
54
  $query_args = array(
55
- "paged" => 1,
56
- "posts_per_page" => 3000
57
  );
58
 
59
- $events = $query->query($query_args);
60
 
61
  // $events->total_row_count;
62
- $pages_count = $events["pages_count"];
63
- $page_current = $events["page_current"];
64
 
65
- $fp = fopen('php://output', 'w');
66
 
67
- #header("Content-Type: application/octet-stream");
68
- if ( "csv" == $export_format ) {
69
 
70
- $filename = "simple-history-export-" . time() . ".csv";
71
- header("Content-Type: text/plain");
72
- header("Content-Disposition: attachment; filename='{$filename}'");
73
 
74
- } else if ( "json" == $export_format ) {
75
 
76
- $filename = "simple-history-export-" . time() . ".json";
77
- header("Content-Type: application/json");
78
- header("Content-Disposition: attachment; filename='{$filename}'");
79
 
80
- } else if ( "html" == $export_format ) {
81
-
82
- $filename = "simple-history-export-" . time() . ".html";
83
- header("Content-Type: text/html");
84
- #header("Content-Disposition: attachment; filename='{$filename}'");
85
 
 
 
 
86
  }
87
 
88
  // Some formats need to output some stuff before the actual loops
89
- if ( "json" == $export_format ) {
90
 
91
- $json_row = "[";
92
- fwrite($fp, $json_row);
93
 
94
- } else if ( "html" == $export_format ) {
95
 
96
  $html = sprintf(
97
- '
98
  <!doctype html>
99
  <meta charset="utf-8">
100
  <title>Simple History export</title>
101
  <ul>
102
  ');
103
- fwrite($fp, $html);
104
 
105
  }
106
 
@@ -109,19 +108,17 @@ class SimpleHistoryExportDropin {
109
  while ( $page_current <= $pages_count + 1 ) {
110
 
111
  // if ($page_current > 1) { break; } # To debug/test
112
-
113
- foreach ( $events["log_rows"] as $one_row ) {
114
 
115
  // if ( $row_loop > 10) { break; } # To debug/test
 
116
 
117
- set_time_limit(30);
118
-
119
- if ( "csv" == $export_format ) {
120
 
121
- $header_output = strip_tags( html_entity_decode( $this->sh->getLogRowHeaderOutput( $one_row ), ENT_QUOTES, 'UTF-8') );
122
- $header_output = trim(preg_replace('/\s\s+/', ' ', $header_output));
123
 
124
- $message_output = strip_tags( html_entity_decode( $this->sh->getLogRowPlainTextOutput( $one_row ), ENT_QUOTES, 'UTF-8') );
125
 
126
  fputcsv($fp, array(
127
  $one_row->date,
@@ -131,10 +128,10 @@ class SimpleHistoryExportDropin {
131
  $one_row->context_message_key,
132
  $header_output,
133
  $message_output,
134
- $one_row->subsequentOccasions
135
  ));
136
 
137
- } else if ( "json" == $export_format ) {
138
 
139
  // If not first loop then add a comma between all json objects
140
  if ( $row_loop == 0 ) {
@@ -143,10 +140,10 @@ class SimpleHistoryExportDropin {
143
  $comma = ",\n";
144
  }
145
 
146
- $json_row = $comma . $this->sh->json_encode($one_row);
147
- fwrite($fp, $json_row);
148
 
149
- } else if ( "html" == $export_format ) {
150
 
151
  $html = sprintf(
152
  '
@@ -161,80 +158,75 @@ class SimpleHistoryExportDropin {
161
  $this->sh->getLogRowDetailsOutput( $one_row )
162
  );
163
 
164
- fwrite($fp, $html);
165
 
166
- }
167
 
168
  $row_loop++;
169
 
170
- }
171
-
172
- #echo "<br>memory_get_usage:<br>"; print_r(memory_get_usage());
173
- #echo "<br>memory_get_peak_usage:<br>"; print_r(memory_get_peak_usage());
174
- #echo "<br>fetch next page";
175
 
 
 
 
176
  flush();
177
 
178
  // Fetch next page
179
  // @TODO: must take into consideration that new items can be added while we do the fetch
180
  $page_current++;
181
- $query_args["paged"] = $page_current;
182
- $events = $query->query($query_args);
183
 
184
- #echo "<br>did fetch next page";
185
- #echo "<br>memory_get_usage:<br>"; print_r(memory_get_usage());
186
- #echo "<br>memory_get_peak_usage:<br>"; print_r(memory_get_peak_usage());
 
187
 
 
188
 
189
- }
 
190
 
191
- if ("json" == $export_format) {
192
 
193
- $json_row = "]";
194
- fwrite($fp, $json_row);
195
-
196
- } else if ("html" == $export_format) {
197
-
198
- $html = sprintf('</ul>');
199
- fwrite($fp, $html);
200
 
201
  }
202
 
203
- fclose($fp);
204
  flush();
205
 
206
  exit;
207
 
208
- #echo "<br>done";
209
-
210
- }
211
 
212
  }
213
 
214
 
215
  public function output() {
216
 
217
-
218
  ?>
219
  <!-- <h2>Export</h2> -->
220
 
221
- <p><?php _ex("The export function will export the full history.", "Export dropin: introtext", "simple-history" ) ?></p>
222
 
223
  <form method="post">
224
 
225
- <h3><?php _ex("Choose format to export to", "Export dropin: format", "simple-history" ) ?></h3>
226
 
227
  <p>
228
  <label>
229
  <input type="radio" name="format" value="json" checked>
230
- <?php _ex("JSON", "Export dropin: export format", "simple-history" ) ?>
231
  </label>
232
  </p>
233
 
234
  <p>
235
  <label>
236
  <input type="radio" name="format" value="csv">
237
- <?php _ex("CSV", "Export dropin: export format", "simple-history" ) ?>
238
  </label>
239
  </p>
240
 
@@ -252,12 +244,12 @@ class SimpleHistoryExportDropin {
252
  </label> -->
253
 
254
  <p>
255
- <button type="submit" class="button button-primary"><?php _ex("Download Export File", "Export dropin: submit button", "simple-history" ) ?></button>
256
  <input type="hidden" name="simple-history-action" value="export-history">
257
  </p>
258
 
259
  <?php
260
- wp_nonce_field( __CLASS__ . "-action-export" );
261
  ?>
262
 
263
  </form>
12
  // Simple History instance
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' ),
24
+ 'function' => array( $this, 'output' ),
25
  ));
26
 
27
+ add_action( 'init', array( $this, 'downloadExport' ) );
28
 
29
  }
30
 
35
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
36
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
37
 
38
+ if ( isset( $_POST['simple-history-action'] ) && $_POST['simple-history-action'] === 'export-history' ) {
39
 
40
  // Will die if nonce not valid
41
+ check_admin_referer( __CLASS__ . '-action-export' );
42
 
43
+ $export_format = isset( $_POST['format'] ) ? $_POST['format'] : 'json';
44
 
45
  // Disable relative time output in header
46
+ add_filter( 'simple_history/header_time_ago_max_time', '__return_zero' );
47
+ add_filter( 'simple_history/header_just_now_max_time', '__return_zero' );
48
 
49
  // Don't use "You" if event is initiated by the same user that does the export
50
+ add_filter( 'simple_history/header_initiator_use_you', '__return_false' );
51
 
52
  $query = new SimpleHistoryLogQuery();
53
 
54
  $query_args = array(
55
+ 'paged' => 1,
56
+ 'posts_per_page' => 3000,
57
  );
58
 
59
+ $events = $query->query( $query_args );
60
 
61
  // $events->total_row_count;
62
+ $pages_count = $events['pages_count'];
63
+ $page_current = $events['page_current'];
64
 
65
+ $fp = fopen( 'php://output', 'w' );
66
 
67
+ // header("Content-Type: application/octet-stream");
68
+ if ( 'csv' == $export_format ) {
69
 
70
+ $filename = 'simple-history-export-' . time() . '.csv';
71
+ header( 'Content-Type: text/plain' );
72
+ header( "Content-Disposition: attachment; filename='{$filename}'" );
73
 
74
+ } elseif ( 'json' == $export_format ) {
75
 
76
+ $filename = 'simple-history-export-' . time() . '.json';
77
+ header( 'Content-Type: application/json' );
78
+ header( "Content-Disposition: attachment; filename='{$filename}'" );
79
 
80
+ } elseif ( 'html' == $export_format ) {
 
 
 
 
81
 
82
+ $filename = 'simple-history-export-' . time() . '.html';
83
+ header( 'Content-Type: text/html' );
84
+ // header("Content-Disposition: attachment; filename='{$filename}'");
85
  }
86
 
87
  // Some formats need to output some stuff before the actual loops
88
+ if ( 'json' == $export_format ) {
89
 
90
+ $json_row = '[';
91
+ fwrite( $fp, $json_row );
92
 
93
+ } elseif ( 'html' == $export_format ) {
94
 
95
  $html = sprintf(
96
+ '
97
  <!doctype html>
98
  <meta charset="utf-8">
99
  <title>Simple History export</title>
100
  <ul>
101
  ');
102
+ fwrite( $fp, $html );
103
 
104
  }
105
 
108
  while ( $page_current <= $pages_count + 1 ) {
109
 
110
  // if ($page_current > 1) { break; } # To debug/test
111
+ foreach ( $events['log_rows'] as $one_row ) {
 
112
 
113
  // if ( $row_loop > 10) { break; } # To debug/test
114
+ set_time_limit( 30 );
115
 
116
+ if ( 'csv' == $export_format ) {
 
 
117
 
118
+ $header_output = strip_tags( html_entity_decode( $this->sh->getLogRowHeaderOutput( $one_row ), ENT_QUOTES, 'UTF-8' ) );
119
+ $header_output = trim( preg_replace( '/\s\s+/', ' ', $header_output ) );
120
 
121
+ $message_output = strip_tags( html_entity_decode( $this->sh->getLogRowPlainTextOutput( $one_row ), ENT_QUOTES, 'UTF-8' ) );
122
 
123
  fputcsv($fp, array(
124
  $one_row->date,
128
  $one_row->context_message_key,
129
  $header_output,
130
  $message_output,
131
+ $one_row->subsequentOccasions,
132
  ));
133
 
134
+ } elseif ( 'json' == $export_format ) {
135
 
136
  // If not first loop then add a comma between all json objects
137
  if ( $row_loop == 0 ) {
140
  $comma = ",\n";
141
  }
142
 
143
+ $json_row = $comma . $this->sh->json_encode( $one_row );
144
+ fwrite( $fp, $json_row );
145
 
146
+ } elseif ( 'html' == $export_format ) {
147
 
148
  $html = sprintf(
149
  '
158
  $this->sh->getLogRowDetailsOutput( $one_row )
159
  );
160
 
161
+ fwrite( $fp, $html );
162
 
163
+ }// End if().
164
 
165
  $row_loop++;
166
 
167
+ }// End foreach().
 
 
 
 
168
 
169
+ // echo "<br>memory_get_usage:<br>"; print_r(memory_get_usage());
170
+ // echo "<br>memory_get_peak_usage:<br>"; print_r(memory_get_peak_usage());
171
+ // echo "<br>fetch next page";
172
  flush();
173
 
174
  // Fetch next page
175
  // @TODO: must take into consideration that new items can be added while we do the fetch
176
  $page_current++;
177
+ $query_args['paged'] = $page_current;
178
+ $events = $query->query( $query_args );
179
 
180
+ // echo "<br>did fetch next page";
181
+ // echo "<br>memory_get_usage:<br>"; print_r(memory_get_usage());
182
+ // echo "<br>memory_get_peak_usage:<br>"; print_r(memory_get_peak_usage());
183
+ }// End while().
184
 
185
+ if ( 'json' == $export_format ) {
186
 
187
+ $json_row = ']';
188
+ fwrite( $fp, $json_row );
189
 
190
+ } elseif ( 'html' == $export_format ) {
191
 
192
+ $html = sprintf( '</ul>' );
193
+ fwrite( $fp, $html );
 
 
 
 
 
194
 
195
  }
196
 
197
+ fclose( $fp );
198
  flush();
199
 
200
  exit;
201
 
202
+ // echo "<br>done";
203
+ }// End if().
 
204
 
205
  }
206
 
207
 
208
  public function output() {
209
 
 
210
  ?>
211
  <!-- <h2>Export</h2> -->
212
 
213
+ <p><?php _ex( 'The export function will export the full history.', 'Export dropin: introtext', 'simple-history' ) ?></p>
214
 
215
  <form method="post">
216
 
217
+ <h3><?php _ex( 'Choose format to export to', 'Export dropin: format', 'simple-history' ) ?></h3>
218
 
219
  <p>
220
  <label>
221
  <input type="radio" name="format" value="json" checked>
222
+ <?php _ex( 'JSON', 'Export dropin: export format', 'simple-history' ) ?>
223
  </label>
224
  </p>
225
 
226
  <p>
227
  <label>
228
  <input type="radio" name="format" value="csv">
229
+ <?php _ex( 'CSV', 'Export dropin: export format', 'simple-history' ) ?>
230
  </label>
231
  </p>
232
 
244
  </label> -->
245
 
246
  <p>
247
+ <button type="submit" class="button button-primary"><?php _ex( 'Download Export File', 'Export dropin: submit button', 'simple-history' ) ?></button>
248
  <input type="hidden" name="simple-history-action" value="export-history">
249
  </p>
250
 
251
  <?php
252
+ wp_nonce_field( __CLASS__ . '-action-export' );
253
  ?>
254
 
255
  </form>
dropins/SimpleHistoryFilterDropin.php CHANGED
@@ -13,24 +13,24 @@ class SimpleHistoryFilterDropin {
13
  // Simple History instance
14
  private $sh;
15
 
16
- function __construct($sh) {
17
 
18
  $this->sh = $sh;
19
 
20
- add_action("simple_history/enqueue_admin_scripts", array($this, "enqueue_admin_scripts"));
21
- add_action("simple_history/history_page/before_gui", array( $this, "gui_page_filters") );
22
- add_action("simple_history/dashboard/before_gui", array( $this, "gui_page_filters") );
23
- add_action("wp_ajax_simple_history_filters_search_user", array( $this, "ajax_simple_history_filters_search_user") );
24
 
25
  }
26
 
27
  public function enqueue_admin_scripts() {
28
 
29
- $file_url = plugin_dir_url(__FILE__);
30
 
31
- wp_enqueue_script("simple_history_FilterDropin", $file_url . "SimpleHistoryFilterDropin.js", array("jquery"), SIMPLE_HISTORY_VERSION, true);
32
 
33
- wp_enqueue_style("simple_history_FilterDropin", $file_url . "SimpleHistoryFilterDropin.css", null, SIMPLE_HISTORY_VERSION);
34
 
35
  }
36
 
@@ -50,24 +50,24 @@ class SimpleHistoryFilterDropin {
50
  * @param bool $show_more_filters_on_load Default false
51
  */
52
  $show_more_filters_on_load = false;
53
- $show_more_filters_on_load = apply_filters("SimpleHistoryFilterDropin/show_more_filters_on_load" , $show_more_filters_on_load);
54
 
55
  ?>
56
- <div class="SimpleHistory__filters <?php echo $show_more_filters_on_load ? "is-showingMoreFilters" : "" ?>">
57
 
58
  <form class="SimpleHistory__filters__form js-SimpleHistory__filters__form">
59
 
60
- <!-- <h3><?php _e("Filter history", "simple-history") ?></h3> -->
61
 
62
  <?php
63
 
64
  // Start months filter
65
  global $wpdb;
66
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
67
- $loggers_user_can_read_sql_in = $this->sh->getLoggersThatUserCanRead(null, "sql");
68
 
69
  // Get unique months
70
- $cache_key = "sh_filter_unique_months";
71
  $result_months = get_transient( $cache_key );
72
 
73
  if ( false === $result_months ) {
@@ -81,7 +81,7 @@ class SimpleHistoryFilterDropin {
81
  $loggers_user_can_read_sql_in // 2
82
  );
83
 
84
- $result_months = $wpdb->get_results($sql_dates);
85
 
86
  set_transient( $cache_key, $result_months, HOUR_IN_SECONDS );
87
 
@@ -93,83 +93,76 @@ class SimpleHistoryFilterDropin {
93
  // Mainly for performance reasons, since often
94
  // it's not the users intention to view all events,
95
  // but just the latest
96
- $this_month = date("Y-m");
97
 
98
  // Determine if we limit the date range by default
99
  $daysToShow = 1;
100
 
101
  // Start with the latest day
102
- $numEvents = $this->sh->get_unique_events_for_days($daysToShow);
103
  $numPages = $numEvents / $this->sh->get_pager_size();
104
 
105
  $arr_days_and_pages[] = array(
106
- "daysToShow" => $daysToShow,
107
- "numPages" => $numPages
108
  );
109
 
110
  // Example on my server with lots of brute force attacks (causing log to not load)
111
  // 166434 / 15 = 11 000 pages for last 7 days
112
  // 1 day = 3051 / 15 = 203 pages = still much but better than 11000 pages!
113
-
114
  if ( $numPages < 20 ) {
115
 
116
  // Not that many things the last day. Let's try to expand to 7 days instead.
117
  $daysToShow = 7;
118
- $numEvents = $this->sh->get_unique_events_for_days($daysToShow);
119
  $numPages = $numEvents / $this->sh->get_pager_size();
120
 
121
  $arr_days_and_pages[] = array(
122
- "daysToShow" => $daysToShow,
123
- "numPages" => $numPages
124
  );
125
 
126
  if ( $numPages < 20 ) {
127
 
128
  // Not that many things the last 7 days. Let's try to expand to 14 days instead.
129
  $daysToShow = 14;
130
- $numEvents = $this->sh->get_unique_events_for_days($daysToShow);
131
  $numPages = $numEvents / $this->sh->get_pager_size();
132
 
133
  $arr_days_and_pages[] = array(
134
- "daysToShow" => $daysToShow,
135
- "numPages" => $numPages
136
  );
137
 
138
  if ( $numPages < 20 ) {
139
 
140
  // Not many things the last 14 days either. Let try with 30 days.
141
  $daysToShow = 30;
142
- $numEvents = $this->sh->get_unique_events_for_days($daysToShow);
143
  $numPages = $numEvents / $this->sh->get_pager_size();
144
 
145
  $arr_days_and_pages[] = array(
146
- "daysToShow" => $daysToShow,
147
- "numPages" => $numPages
148
  );
149
 
150
  // If 30 days gives a big amount of pages, go back to 14 days
151
  if ( $numPages > 1000 ) {
152
  $daysToShow = 14;
153
  }
154
-
155
- // @TODO: for sites with very low activity,
156
- // if they have no events for the last 30 days should we just show all?
157
-
158
  }
159
-
160
  }
161
-
162
- }
163
 
164
  ?>
165
 
166
  <p class="SimpleHistory__filters__filterRow SimpleHistory__filters__filterRow--date" data-debug-daysAndPages='<?php echo json_encode( $arr_days_and_pages ) ?>'>
167
 
168
- <label class="SimpleHistory__filters__filterLabel"><?php _ex("Dates:", "Filter label", "simple-history") ?></label>
169
 
170
  <select class="SimpleHistory__filters__filter SimpleHistory__filters__filter--date"
171
  name="dates"
172
- placeholder="<?php echo _e("All dates", "simple-history") ?>"
173
  NOTmultiple
174
  >
175
  <?php
@@ -178,45 +171,44 @@ class SimpleHistoryFilterDropin {
178
  // since 2.8.1
179
  printf(
180
  '<option value="%1$s" %3$s>%2$s</option>',
181
- "customRange", // 1 - value
182
- _x("Custom date range...", "Filter dropin: filter custom range", "simple-history"), // 2 text
183
- selected( $daysToShow, "customRange", 0 )
184
  );
185
 
186
  // One day+ Last week + two weeks back + 30 days back
187
-
188
  printf(
189
  '<option value="%1$s" %3$s>%2$s</option>',
190
- "lastdays:1", // 1 - value
191
- _x("Last day", "Filter dropin: filter week", "simple-history"), // 2 text
192
  selected( $daysToShow, 1, 0 )
193
  );
194
 
195
  printf(
196
  '<option value="%1$s" %3$s>%2$s</option>',
197
- "lastdays:7", // 1 - value
198
- _x("Last 7 days", "Filter dropin: filter week", "simple-history"), // 2 text
199
  selected( $daysToShow, 7, 0 )
200
  );
201
 
202
  printf(
203
  '<option value="%1$s" %3$s>%2$s</option>',
204
- "lastdays:14", // 1 - value
205
- _x("Last 14 days", "Filter dropin: filter week", "simple-history"), // 2 text
206
  selected( $daysToShow, 14, 0 )
207
  );
208
 
209
  printf(
210
  '<option value="%1$s" %3$s>%2$s</option>',
211
- "lastdays:30", // 1 - value
212
- _x("Last 30 days", "Filter dropin: filter week", "simple-history"), // 2 text
213
  selected( $daysToShow, 30, 0 )
214
  );
215
 
216
  printf(
217
  '<option value="%1$s" %3$s>%2$s</option>',
218
- "lastdays:60", // 1 - value
219
- _x("Last 60 days", "Filter dropin: filter week", "simple-history"), // 2 text
220
  selected( $daysToShow, 60, 0 )
221
  );
222
 
@@ -225,9 +217,9 @@ class SimpleHistoryFilterDropin {
225
 
226
  printf(
227
  '<option value="%1$s" %3$s>%2$s</option>',
228
- "month:" . $row->yearMonth,
229
- date_i18n( "F Y", strtotime($row->yearMonth) ),
230
- "" // selected( $this_month, $row->yearMonth, false )
231
  );
232
 
233
  }
@@ -236,11 +228,11 @@ class SimpleHistoryFilterDropin {
236
  </select>
237
 
238
  <!-- <p> -->
239
- <!-- <label class="SimpleHistory__filters__filterLabel"><?php _ex("Between dates:", "Filter label", "simple-history") ?></label> -->
240
  <span class="SimpleHistory__filters__filter--dayValuesWrap">
241
  <?php
242
- $this->touch_time("from");
243
- $this->touch_time("to");
244
  ?>
245
  </span>
246
  <!-- </p> -->
@@ -255,26 +247,26 @@ class SimpleHistoryFilterDropin {
255
  *
256
  * @param string Default search string
257
  */
258
- $default_search_string = apply_filters("SimpleHistoryFilterDropin/filter_default_search_string" , "");
259
  ?>
260
 
261
  <p>
262
 
263
- <label class="SimpleHistory__filters__filterLabel"><?php _ex("Containing words:", "Filter label", "simple-history") ?></label>
264
 
265
  <input
266
  type="search"
267
  class="SimpleHistoryFilterDropin-searchInput"
268
  placeholder="<?php /* _e("Containing words", "simple-history"); */ ?>"
269
  name="search"
270
- value="<?php echo esc_attr($default_search_string); ?>"
271
  >
272
 
273
  </p>
274
 
275
  <p class="SimpleHistory__filters__filterSubmitWrap">
276
- <button class="button SimpleHistoryFilterDropin-doFilterButton SimpleHistoryFilterDropin-doFilterButton--first js-SimpleHistoryFilterDropin-doFilter"><?php _e("Search events", "simple-history") ?></button>
277
- <button type="button" class="SimpleHistoryFilterDropin-showMoreFilters SimpleHistoryFilterDropin-showMoreFilters--first js-SimpleHistoryFilterDropin-showMoreFilters"><?php _ex("Show search options", "Filter dropin: button to show more search options", "simple-history") ?></button>
278
  </p>
279
 
280
  <?php
@@ -285,23 +277,23 @@ class SimpleHistoryFilterDropin {
285
  *
286
  * @param array Array with loglevel sugs. Default empty = show all.
287
  */
288
- $arr_default_loglevels = apply_filters("SimpleHistoryFilterDropin/filter_default_loglevel", array());
289
  ?>
290
  <div class="SimpleHistory__filters__moreFilters js-SimpleHistory__filters__moreFilters">
291
 
292
  <p>
293
 
294
- <label class="SimpleHistory__filters__filterLabel"><?php _ex("Log levels:", "Filter label", "simple-history") ?></label>
295
-
296
- <select name="loglevels" class="SimpleHistory__filters__filter SimpleHistory__filters__filter--loglevel" style="width: 300px" placeholder="<?php _e("All log levels", "simple-history") ?>" multiple>
297
- <option <?php selected(in_array("debug", $arr_default_loglevels)) ?> value="debug" data-color="#CEF6D8"><?php echo $this->sh->getLogLevelTranslated("Debug") ?></option>
298
- <option <?php selected(in_array("info", $arr_default_loglevels)) ?> value="info" data-color="white"><?php echo $this->sh->getLogLevelTranslated("Info") ?></option>
299
- <option <?php selected(in_array("notice", $arr_default_loglevels)) ?> value="notice" data-color="rgb(219, 219, 183)"><?php echo $this->sh->getLogLevelTranslated("Notice") ?></option>
300
- <option <?php selected(in_array("warning", $arr_default_loglevels)) ?> value="warning" data-color="#F7D358"><?php echo $this->sh->getLogLevelTranslated("Warning") ?></option>
301
- <option <?php selected(in_array("error", $arr_default_loglevels)) ?> value="error" data-color="#F79F81"><?php echo $this->sh->getLogLevelTranslated("Error") ?></option>
302
- <option <?php selected(in_array("critical", $arr_default_loglevels)) ?> value="critical" data-color="#FA5858"><?php echo $this->sh->getLogLevelTranslated("Critical") ?></option>
303
- <option <?php selected(in_array("alert", $arr_default_loglevels)) ?> value="alert" data-color="rgb(199, 69, 69)"><?php echo $this->sh->getLogLevelTranslated("Alert") ?></option>
304
- <option <?php selected(in_array("emergency", $arr_default_loglevels)) ?> value="emergency" data-color="#DF0101"><?php echo $this->sh->getLogLevelTranslated("Emergency") ?></option>
305
  </select>
306
 
307
  </p>
@@ -323,58 +315,57 @@ class SimpleHistoryFilterDropin {
323
  ?>
324
  <p>
325
 
326
- <label class="SimpleHistory__filters__filterLabel"><?php _ex("Message types:", "Filter label", "simple-history") ?></label>
327
 
328
  <select name="messages" class="SimpleHistory__filters__filter SimpleHistory__filters__filter--logger" style="width: 300px"
329
- placeholder="<?php _e("All messages", "simple-history") ?>" multiple>
330
  <?php
331
- foreach ($loggers_user_can_read as $logger) {
332
 
333
- $logger_info = $logger["instance"]->getInfo();
334
- $logger_slug = $logger["instance"]->slug;
335
 
336
  // Get labels for logger
337
- if ( isset( $logger_info["labels"]["search"] ) ) {
338
 
339
- printf('<optgroup label="%1$s">', esc_attr( $logger_info["labels"]["search"]["label"] ) );
340
 
341
  // If all activity
342
- if ( ! empty( $logger_info["labels"]["search"]["label_all"] ) ) {
343
 
344
  $arr_all_search_messages = array();
345
- foreach ( $logger_info["labels"]["search"]["options"] as $option_key => $option_messages ) {
346
- $arr_all_search_messages = array_merge($arr_all_search_messages, $option_messages);
347
  }
348
 
349
- foreach ($arr_all_search_messages as $key => $val) {
350
- $arr_all_search_messages[ $key ] = $logger_slug . ":" . $val;
351
  }
352
 
353
- printf('<option value="%2$s">%1$s</option>', esc_attr( $logger_info["labels"]["search"]["label_all"] ), esc_attr( implode(",", $arr_all_search_messages) ));
354
 
355
  }
356
 
357
  // For each specific search option
358
- foreach ( $logger_info["labels"]["search"]["options"] as $option_key => $option_messages ) {
359
 
360
- foreach ($option_messages as $key => $val) {
361
- $option_messages[ $key ] = $logger_slug . ":" . $val;
362
  }
363
 
364
- $str_option_messages = implode(",", $option_messages);
365
  printf(
366
- '<option value="%2$s">%1$s</option>',
367
- esc_attr( $option_key ), // 1
368
- esc_attr( $str_option_messages ) // 2
369
- );
370
 
371
  }
372
 
373
- printf('</optgroup>');
374
-
375
- }
376
 
377
- }
 
378
  ?>
379
  </select>
380
  </p>
@@ -403,26 +394,26 @@ class SimpleHistoryFilterDropin {
403
  });
404
  //*/
405
 
406
- $default_user_ids = apply_filters("SimpleHistoryFilterDropin/filter_default_user_ids", array());
407
  $arr_default_user_data = array();
408
 
409
- foreach ($default_user_ids as $user_id) {
410
- $arr_default_user_data[] = $this->get_data_for_user($user_id);
411
  }
412
 
413
- if ( current_user_can("list_users") ) {
414
  ?>
415
  <p>
416
 
417
- <label class="SimpleHistory__filters__filterLabel"><?php _ex("Users:", "Filter label", "simple-history") ?></label>
418
 
419
  <input type="text"
420
  name = "users"
421
  class="SimpleHistory__filters__filter SimpleHistory__filters__filter--user"
422
  style="width: 300px"
423
- placeholder="<?php _e("All users", "simple-history") ?>"
424
- value="<?php echo esc_attr(implode(",",$default_user_ids)) ?>"
425
- data-default-user-data="<?php echo esc_attr( json_encode($arr_default_user_data) ) ?>"
426
  />
427
 
428
  </p>
@@ -432,15 +423,15 @@ class SimpleHistoryFilterDropin {
432
  ?>
433
 
434
  <p class="SimpleHistory__filters__filterSubmitWrap">
435
- <button class="button SimpleHistoryFilterDropin-doFilterButton SimpleHistoryFilterDropin-doFilterButton--second js-SimpleHistoryFilterDropin-doFilter"><?php _e("Search events", "simple-history") ?></button>
436
- <button type="button" class="SimpleHistoryFilterDropin-showMoreFilters SimpleHistoryFilterDropin-showMoreFilters--second js-SimpleHistoryFilterDropin-showMoreFilters"><?php _ex("Hide search options", "Filter dropin: button to hide more search options", "simple-history") ?></button>
437
  </p>
438
 
439
  </div><!-- // more filters -->
440
 
441
  <!--
442
  <p>
443
- <button class="button js-SimpleHistoryFilterDropin-doFilter"><?php _e("Search", "simple-history") ?></button>
444
  </p>
445
  -->
446
 
@@ -458,26 +449,26 @@ class SimpleHistoryFilterDropin {
458
  * @param int $userID
459
  * @return array Array with each user as an object
460
  */
461
- public function get_data_for_user($userID) {
462
 
463
- if ( ! $userID || ! is_numeric($userID) ) {
464
  return false;
465
  }
466
 
467
- $user = get_user_by( "id", $userID );
468
 
469
  if ( false == $user ) {
470
  return false;
471
  }
472
 
473
  $userdata = (object) array(
474
- "id" => $user->ID,
475
- "user_email" => $user->user_email,
476
- "user_login" => $user->user_login,
477
- "user_nicename" => $user->user_nicename
478
  );
479
 
480
- $this->add_gravatar_to_user_array($userdata);
481
 
482
  return $userdata;
483
 
@@ -488,8 +479,8 @@ class SimpleHistoryFilterDropin {
488
  */
489
  public function ajax_simple_history_filters_search_user() {
490
 
491
- $q = isset( $_GET["q"] ) ? $_GET["q"] : "";
492
- $page_limit = isset( $_GET["page_limit"] ) ? (int) $_GET["page_limit"] : "";
493
 
494
  // query and page limit must be set
495
  if ( ! $q || ! $page_limit ) {
@@ -497,7 +488,7 @@ class SimpleHistoryFilterDropin {
497
  }
498
 
499
  // user must have list_users capability (default super admin + administrators have this)
500
- if ( ! current_user_can("list_users") ) {
501
  wp_send_json_error();
502
  }
503
 
@@ -505,12 +496,11 @@ class SimpleHistoryFilterDropin {
505
  // because a user can change email
506
  // search in context: user_id, user_email, user_login
507
  // search in wp_users: login, nicename, user_email
508
-
509
  // search and get users. make sure to use "fields" and "number" or we can get timeout/use lots of memory if we have a large amount of users
510
  $results_user = get_users( array(
511
- "search" => "*{$q}*",
512
- "fields" => array("ID", "user_login", "user_nicename", "user_email", "display_name"),
513
- "number" => 20
514
  ) );
515
 
516
  // add lower case id to user array
@@ -519,30 +509,29 @@ class SimpleHistoryFilterDropin {
519
  } );
520
 
521
  // add gravatars to user array
522
- array_walk( $results_user, array( $this, "add_gravatar_to_user_array" ) );
523
 
524
  $data = array(
525
- "results" => array(
526
- ),
527
- "more" => false,
528
- "context" => array(),
529
- "count" => sizeof( $results_user )
530
  );
531
 
532
- $data["results"] = array_merge( $data["results"], $results_user );
533
 
534
  wp_send_json_success( $data );
535
 
536
  } // function
537
 
538
- function add_gravatar_to_user_array(& $val, $index = null) {
539
  $val->text = sprintf(
540
  '%1$s - %2$s',
541
  $val->user_login,
542
  $val->user_email
543
  );
544
 
545
- $val->gravatar = $this->sh->get_avatar( $val->user_email, "18", "mm");
546
 
547
  }
548
 
@@ -565,18 +554,18 @@ class SimpleHistoryFilterDropin {
565
  global $wp_locale;
566
 
567
  // Prefix = text before the inputs
568
- $prefix = "";
569
- $input_prefix = "";
570
- if ( "from" == $from_or_to ) {
571
- $prefix = _x("From", "Filter dropin, custom date range", "simple-history");
572
- $input_prefix = "from_";
573
- } else if ( "to" == $from_or_to ) {
574
- $prefix = _x("To", "Filter dropin, custom date range", "simple-history");
575
- $input_prefix = "to_";
576
  }
577
 
578
  // The default date to show in the inputs
579
- $date = date("Y-m-d");
580
 
581
  $jj = mysql2date( 'd', $date, false );
582
  $mm = mysql2date( 'm', $date, false );
@@ -584,8 +573,8 @@ class SimpleHistoryFilterDropin {
584
 
585
  $month = "<select name='{$input_prefix}mm'>";
586
 
587
- for ( $i = 1; $i < 13; $i = $i +1 ) {
588
- $monthnum = zeroise($i, 2);
589
  $monthtext = $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) );
590
  $month .= "\t\t\t" . '<option value="' . $monthnum . '" data-text="' . $monthtext . '" ' . selected( $monthnum, $mm, false ) . '>';
591
  /* translators: 1: month number (01, 02, etc.), 2: month abbreviation */
@@ -594,12 +583,12 @@ class SimpleHistoryFilterDropin {
594
  $month .= '</select>';
595
  $month .= '</label>';
596
 
597
- $day = '<label><span class="screen-reader-text">' . __( 'Day' ) . '</span><input type="text" name="'.$input_prefix.'jj" value="' . $jj . '" size="2" maxlength="2" autocomplete="off" /></label>';
598
- $year = '<label><span class="screen-reader-text">' . __( 'Year' ) . '</span><input type="text" name="'.$input_prefix.'aa" value="' . $aa . '" size="4" maxlength="4" autocomplete="off" /></label>';
599
 
600
  echo '<span class="SimpleHistory__filters__filter SimpleHistory__filters__filter--day">';
601
 
602
- echo $prefix . "<br>";
603
 
604
  /* translators: 1: month, 2: day, 3: year, 4: hour, 5: minute */
605
  printf( __( '%1$s %2$s, %3$s ' ), $month, $day, $year );
13
  // Simple History instance
14
  private $sh;
15
 
16
+ function __construct( $sh ) {
17
 
18
  $this->sh = $sh;
19
 
20
+ add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'enqueue_admin_scripts' ) );
21
+ add_action( 'simple_history/history_page/before_gui', array( $this, 'gui_page_filters' ) );
22
+ add_action( 'simple_history/dashboard/before_gui', array( $this, 'gui_page_filters' ) );
23
+ add_action( 'wp_ajax_simple_history_filters_search_user', array( $this, 'ajax_simple_history_filters_search_user' ) );
24
 
25
  }
26
 
27
  public function enqueue_admin_scripts() {
28
 
29
+ $file_url = plugin_dir_url( __FILE__ );
30
 
31
+ wp_enqueue_script( 'simple_history_FilterDropin', $file_url . 'SimpleHistoryFilterDropin.js', array( 'jquery' ), SIMPLE_HISTORY_VERSION, true );
32
 
33
+ wp_enqueue_style( 'simple_history_FilterDropin', $file_url . 'SimpleHistoryFilterDropin.css', null, SIMPLE_HISTORY_VERSION );
34
 
35
  }
36
 
50
  * @param bool $show_more_filters_on_load Default false
51
  */
52
  $show_more_filters_on_load = false;
53
+ $show_more_filters_on_load = apply_filters( 'SimpleHistoryFilterDropin/show_more_filters_on_load' , $show_more_filters_on_load );
54
 
55
  ?>
56
+ <div class="SimpleHistory__filters <?php echo $show_more_filters_on_load ? 'is-showingMoreFilters' : '' ?>">
57
 
58
  <form class="SimpleHistory__filters__form js-SimpleHistory__filters__form">
59
 
60
+ <!-- <h3><?php _e( 'Filter history', 'simple-history' ) ?></h3> -->
61
 
62
  <?php
63
 
64
  // Start months filter
65
  global $wpdb;
66
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
67
+ $loggers_user_can_read_sql_in = $this->sh->getLoggersThatUserCanRead( null, 'sql' );
68
 
69
  // Get unique months
70
+ $cache_key = 'sh_filter_unique_months';
71
  $result_months = get_transient( $cache_key );
72
 
73
  if ( false === $result_months ) {
81
  $loggers_user_can_read_sql_in // 2
82
  );
83
 
84
+ $result_months = $wpdb->get_results( $sql_dates );
85
 
86
  set_transient( $cache_key, $result_months, HOUR_IN_SECONDS );
87
 
93
  // Mainly for performance reasons, since often
94
  // it's not the users intention to view all events,
95
  // but just the latest
96
+ $this_month = date( 'Y-m' );
97
 
98
  // Determine if we limit the date range by default
99
  $daysToShow = 1;
100
 
101
  // Start with the latest day
102
+ $numEvents = $this->sh->get_unique_events_for_days( $daysToShow );
103
  $numPages = $numEvents / $this->sh->get_pager_size();
104
 
105
  $arr_days_and_pages[] = array(
106
+ 'daysToShow' => $daysToShow,
107
+ 'numPages' => $numPages,
108
  );
109
 
110
  // Example on my server with lots of brute force attacks (causing log to not load)
111
  // 166434 / 15 = 11 000 pages for last 7 days
112
  // 1 day = 3051 / 15 = 203 pages = still much but better than 11000 pages!
 
113
  if ( $numPages < 20 ) {
114
 
115
  // Not that many things the last day. Let's try to expand to 7 days instead.
116
  $daysToShow = 7;
117
+ $numEvents = $this->sh->get_unique_events_for_days( $daysToShow );
118
  $numPages = $numEvents / $this->sh->get_pager_size();
119
 
120
  $arr_days_and_pages[] = array(
121
+ 'daysToShow' => $daysToShow,
122
+ 'numPages' => $numPages,
123
  );
124
 
125
  if ( $numPages < 20 ) {
126
 
127
  // Not that many things the last 7 days. Let's try to expand to 14 days instead.
128
  $daysToShow = 14;
129
+ $numEvents = $this->sh->get_unique_events_for_days( $daysToShow );
130
  $numPages = $numEvents / $this->sh->get_pager_size();
131
 
132
  $arr_days_and_pages[] = array(
133
+ 'daysToShow' => $daysToShow,
134
+ 'numPages' => $numPages,
135
  );
136
 
137
  if ( $numPages < 20 ) {
138
 
139
  // Not many things the last 14 days either. Let try with 30 days.
140
  $daysToShow = 30;
141
+ $numEvents = $this->sh->get_unique_events_for_days( $daysToShow );
142
  $numPages = $numEvents / $this->sh->get_pager_size();
143
 
144
  $arr_days_and_pages[] = array(
145
+ 'daysToShow' => $daysToShow,
146
+ 'numPages' => $numPages,
147
  );
148
 
149
  // If 30 days gives a big amount of pages, go back to 14 days
150
  if ( $numPages > 1000 ) {
151
  $daysToShow = 14;
152
  }
 
 
 
 
153
  }
 
154
  }
155
+ }// End if().
 
156
 
157
  ?>
158
 
159
  <p class="SimpleHistory__filters__filterRow SimpleHistory__filters__filterRow--date" data-debug-daysAndPages='<?php echo json_encode( $arr_days_and_pages ) ?>'>
160
 
161
+ <label class="SimpleHistory__filters__filterLabel"><?php _ex( 'Dates:', 'Filter label', 'simple-history' ) ?></label>
162
 
163
  <select class="SimpleHistory__filters__filter SimpleHistory__filters__filter--date"
164
  name="dates"
165
+ placeholder="<?php echo _e( 'All dates', 'simple-history' ) ?>"
166
  NOTmultiple
167
  >
168
  <?php
171
  // since 2.8.1
172
  printf(
173
  '<option value="%1$s" %3$s>%2$s</option>',
174
+ 'customRange', // 1 - value
175
+ _x( 'Custom date range...', 'Filter dropin: filter custom range', 'simple-history' ), // 2 text
176
+ selected( $daysToShow, 'customRange', 0 )
177
  );
178
 
179
  // One day+ Last week + two weeks back + 30 days back
 
180
  printf(
181
  '<option value="%1$s" %3$s>%2$s</option>',
182
+ 'lastdays:1', // 1 - value
183
+ _x( 'Last day', 'Filter dropin: filter week', 'simple-history' ), // 2 text
184
  selected( $daysToShow, 1, 0 )
185
  );
186
 
187
  printf(
188
  '<option value="%1$s" %3$s>%2$s</option>',
189
+ 'lastdays:7', // 1 - value
190
+ _x( 'Last 7 days', 'Filter dropin: filter week', 'simple-history' ), // 2 text
191
  selected( $daysToShow, 7, 0 )
192
  );
193
 
194
  printf(
195
  '<option value="%1$s" %3$s>%2$s</option>',
196
+ 'lastdays:14', // 1 - value
197
+ _x( 'Last 14 days', 'Filter dropin: filter week', 'simple-history' ), // 2 text
198
  selected( $daysToShow, 14, 0 )
199
  );
200
 
201
  printf(
202
  '<option value="%1$s" %3$s>%2$s</option>',
203
+ 'lastdays:30', // 1 - value
204
+ _x( 'Last 30 days', 'Filter dropin: filter week', 'simple-history' ), // 2 text
205
  selected( $daysToShow, 30, 0 )
206
  );
207
 
208
  printf(
209
  '<option value="%1$s" %3$s>%2$s</option>',
210
+ 'lastdays:60', // 1 - value
211
+ _x( 'Last 60 days', 'Filter dropin: filter week', 'simple-history' ), // 2 text
212
  selected( $daysToShow, 60, 0 )
213
  );
214
 
217
 
218
  printf(
219
  '<option value="%1$s" %3$s>%2$s</option>',
220
+ 'month:' . $row->yearMonth,
221
+ date_i18n( 'F Y', strtotime( $row->yearMonth ) ),
222
+ '' // selected( $this_month, $row->yearMonth, false )
223
  );
224
 
225
  }
228
  </select>
229
 
230
  <!-- <p> -->
231
+ <!-- <label class="SimpleHistory__filters__filterLabel"><?php _ex( 'Between dates:', 'Filter label', 'simple-history' ) ?></label> -->
232
  <span class="SimpleHistory__filters__filter--dayValuesWrap">
233
  <?php
234
+ $this->touch_time( 'from' );
235
+ $this->touch_time( 'to' );
236
  ?>
237
  </span>
238
  <!-- </p> -->
247
  *
248
  * @param string Default search string
249
  */
250
+ $default_search_string = apply_filters( 'SimpleHistoryFilterDropin/filter_default_search_string' , '' );
251
  ?>
252
 
253
  <p>
254
 
255
+ <label class="SimpleHistory__filters__filterLabel"><?php _ex( 'Containing words:', 'Filter label', 'simple-history' ) ?></label>
256
 
257
  <input
258
  type="search"
259
  class="SimpleHistoryFilterDropin-searchInput"
260
  placeholder="<?php /* _e("Containing words", "simple-history"); */ ?>"
261
  name="search"
262
+ value="<?php echo esc_attr( $default_search_string ); ?>"
263
  >
264
 
265
  </p>
266
 
267
  <p class="SimpleHistory__filters__filterSubmitWrap">
268
+ <button class="button SimpleHistoryFilterDropin-doFilterButton SimpleHistoryFilterDropin-doFilterButton--first js-SimpleHistoryFilterDropin-doFilter"><?php _e( 'Search events', 'simple-history' ) ?></button>
269
+ <button type="button" class="SimpleHistoryFilterDropin-showMoreFilters SimpleHistoryFilterDropin-showMoreFilters--first js-SimpleHistoryFilterDropin-showMoreFilters"><?php _ex( 'Show search options', 'Filter dropin: button to show more search options', 'simple-history' ) ?></button>
270
  </p>
271
 
272
  <?php
277
  *
278
  * @param array Array with loglevel sugs. Default empty = show all.
279
  */
280
+ $arr_default_loglevels = apply_filters( 'SimpleHistoryFilterDropin/filter_default_loglevel', array() );
281
  ?>
282
  <div class="SimpleHistory__filters__moreFilters js-SimpleHistory__filters__moreFilters">
283
 
284
  <p>
285
 
286
+ <label class="SimpleHistory__filters__filterLabel"><?php _ex( 'Log levels:', 'Filter label', 'simple-history' ) ?></label>
287
+
288
+ <select name="loglevels" class="SimpleHistory__filters__filter SimpleHistory__filters__filter--loglevel" style="width: 300px" placeholder="<?php _e( 'All log levels', 'simple-history' ) ?>" multiple>
289
+ <option <?php selected( in_array( 'debug', $arr_default_loglevels ) ) ?> value="debug" data-color="#CEF6D8"><?php echo $this->sh->getLogLevelTranslated( 'Debug' ) ?></option>
290
+ <option <?php selected( in_array( 'info', $arr_default_loglevels ) ) ?> value="info" data-color="white"><?php echo $this->sh->getLogLevelTranslated( 'Info' ) ?></option>
291
+ <option <?php selected( in_array( 'notice', $arr_default_loglevels ) ) ?> value="notice" data-color="rgb(219, 219, 183)"><?php echo $this->sh->getLogLevelTranslated( 'Notice' ) ?></option>
292
+ <option <?php selected( in_array( 'warning', $arr_default_loglevels ) ) ?> value="warning" data-color="#F7D358"><?php echo $this->sh->getLogLevelTranslated( 'Warning' ) ?></option>
293
+ <option <?php selected( in_array( 'error', $arr_default_loglevels ) ) ?> value="error" data-color="#F79F81"><?php echo $this->sh->getLogLevelTranslated( 'Error' ) ?></option>
294
+ <option <?php selected( in_array( 'critical', $arr_default_loglevels ) ) ?> value="critical" data-color="#FA5858"><?php echo $this->sh->getLogLevelTranslated( 'Critical' ) ?></option>
295
+ <option <?php selected( in_array( 'alert', $arr_default_loglevels ) ) ?> value="alert" data-color="rgb(199, 69, 69)"><?php echo $this->sh->getLogLevelTranslated( 'Alert' ) ?></option>
296
+ <option <?php selected( in_array( 'emergency', $arr_default_loglevels ) ) ?> value="emergency" data-color="#DF0101"><?php echo $this->sh->getLogLevelTranslated( 'Emergency' ) ?></option>
297
  </select>
298
 
299
  </p>
315
  ?>
316
  <p>
317
 
318
+ <label class="SimpleHistory__filters__filterLabel"><?php _ex( 'Message types:', 'Filter label', 'simple-history' ) ?></label>
319
 
320
  <select name="messages" class="SimpleHistory__filters__filter SimpleHistory__filters__filter--logger" style="width: 300px"
321
+ placeholder="<?php _e( 'All messages', 'simple-history' ) ?>" multiple>
322
  <?php
323
+ foreach ( $loggers_user_can_read as $logger ) {
324
 
325
+ $logger_info = $logger['instance']->getInfo();
326
+ $logger_slug = $logger['instance']->slug;
327
 
328
  // Get labels for logger
329
+ if ( isset( $logger_info['labels']['search'] ) ) {
330
 
331
+ printf( '<optgroup label="%1$s">', esc_attr( $logger_info['labels']['search']['label'] ) );
332
 
333
  // If all activity
334
+ if ( ! empty( $logger_info['labels']['search']['label_all'] ) ) {
335
 
336
  $arr_all_search_messages = array();
337
+ foreach ( $logger_info['labels']['search']['options'] as $option_key => $option_messages ) {
338
+ $arr_all_search_messages = array_merge( $arr_all_search_messages, $option_messages );
339
  }
340
 
341
+ foreach ( $arr_all_search_messages as $key => $val ) {
342
+ $arr_all_search_messages[ $key ] = $logger_slug . ':' . $val;
343
  }
344
 
345
+ printf( '<option value="%2$s">%1$s</option>', esc_attr( $logger_info['labels']['search']['label_all'] ), esc_attr( implode( ',', $arr_all_search_messages ) ) );
346
 
347
  }
348
 
349
  // For each specific search option
350
+ foreach ( $logger_info['labels']['search']['options'] as $option_key => $option_messages ) {
351
 
352
+ foreach ( $option_messages as $key => $val ) {
353
+ $option_messages[ $key ] = $logger_slug . ':' . $val;
354
  }
355
 
356
+ $str_option_messages = implode( ',', $option_messages );
357
  printf(
358
+ '<option value="%2$s">%1$s</option>',
359
+ esc_attr( $option_key ), // 1
360
+ esc_attr( $str_option_messages ) // 2
361
+ );
362
 
363
  }
364
 
365
+ printf( '</optgroup>' );
 
 
366
 
367
+ }// End if().
368
+ }// End foreach().
369
  ?>
370
  </select>
371
  </p>
394
  });
395
  //*/
396
 
397
+ $default_user_ids = apply_filters( 'SimpleHistoryFilterDropin/filter_default_user_ids', array() );
398
  $arr_default_user_data = array();
399
 
400
+ foreach ( $default_user_ids as $user_id ) {
401
+ $arr_default_user_data[] = $this->get_data_for_user( $user_id );
402
  }
403
 
404
+ if ( current_user_can( 'list_users' ) ) {
405
  ?>
406
  <p>
407
 
408
+ <label class="SimpleHistory__filters__filterLabel"><?php _ex( 'Users:', 'Filter label', 'simple-history' ) ?></label>
409
 
410
  <input type="text"
411
  name = "users"
412
  class="SimpleHistory__filters__filter SimpleHistory__filters__filter--user"
413
  style="width: 300px"
414
+ placeholder="<?php _e( 'All users', 'simple-history' ) ?>"
415
+ value="<?php echo esc_attr( implode( ',',$default_user_ids ) ) ?>"
416
+ data-default-user-data="<?php echo esc_attr( json_encode( $arr_default_user_data ) ) ?>"
417
  />
418
 
419
  </p>
423
  ?>
424
 
425
  <p class="SimpleHistory__filters__filterSubmitWrap">
426
+ <button class="button SimpleHistoryFilterDropin-doFilterButton SimpleHistoryFilterDropin-doFilterButton--second js-SimpleHistoryFilterDropin-doFilter"><?php _e( 'Search events', 'simple-history' ) ?></button>
427
+ <button type="button" class="SimpleHistoryFilterDropin-showMoreFilters SimpleHistoryFilterDropin-showMoreFilters--second js-SimpleHistoryFilterDropin-showMoreFilters"><?php _ex( 'Hide search options', 'Filter dropin: button to hide more search options', 'simple-history' ) ?></button>
428
  </p>
429
 
430
  </div><!-- // more filters -->
431
 
432
  <!--
433
  <p>
434
+ <button class="button js-SimpleHistoryFilterDropin-doFilter"><?php _e( 'Search', 'simple-history' ) ?></button>
435
  </p>
436
  -->
437
 
449
  * @param int $userID
450
  * @return array Array with each user as an object
451
  */
452
+ public function get_data_for_user( $userID ) {
453
 
454
+ if ( ! $userID || ! is_numeric( $userID ) ) {
455
  return false;
456
  }
457
 
458
+ $user = get_user_by( 'id', $userID );
459
 
460
  if ( false == $user ) {
461
  return false;
462
  }
463
 
464
  $userdata = (object) array(
465
+ 'id' => $user->ID,
466
+ 'user_email' => $user->user_email,
467
+ 'user_login' => $user->user_login,
468
+ 'user_nicename' => $user->user_nicename,
469
  );
470
 
471
+ $this->add_gravatar_to_user_array( $userdata );
472
 
473
  return $userdata;
474
 
479
  */
480
  public function ajax_simple_history_filters_search_user() {
481
 
482
+ $q = isset( $_GET['q'] ) ? $_GET['q'] : '';
483
+ $page_limit = isset( $_GET['page_limit'] ) ? (int) $_GET['page_limit'] : '';
484
 
485
  // query and page limit must be set
486
  if ( ! $q || ! $page_limit ) {
488
  }
489
 
490
  // user must have list_users capability (default super admin + administrators have this)
491
+ if ( ! current_user_can( 'list_users' ) ) {
492
  wp_send_json_error();
493
  }
494
 
496
  // because a user can change email
497
  // search in context: user_id, user_email, user_login
498
  // search in wp_users: login, nicename, user_email
 
499
  // search and get users. make sure to use "fields" and "number" or we can get timeout/use lots of memory if we have a large amount of users
500
  $results_user = get_users( array(
501
+ 'search' => "*{$q}*",
502
+ 'fields' => array( 'ID', 'user_login', 'user_nicename', 'user_email', 'display_name' ),
503
+ 'number' => 20,
504
  ) );
505
 
506
  // add lower case id to user array
509
  } );
510
 
511
  // add gravatars to user array
512
+ array_walk( $results_user, array( $this, 'add_gravatar_to_user_array' ) );
513
 
514
  $data = array(
515
+ 'results' => array(),
516
+ 'more' => false,
517
+ 'context' => array(),
518
+ 'count' => sizeof( $results_user ),
 
519
  );
520
 
521
+ $data['results'] = array_merge( $data['results'], $results_user );
522
 
523
  wp_send_json_success( $data );
524
 
525
  } // function
526
 
527
+ function add_gravatar_to_user_array( & $val, $index = null ) {
528
  $val->text = sprintf(
529
  '%1$s - %2$s',
530
  $val->user_login,
531
  $val->user_email
532
  );
533
 
534
+ $val->gravatar = $this->sh->get_avatar( $val->user_email, '18', 'mm' );
535
 
536
  }
537
 
554
  global $wp_locale;
555
 
556
  // Prefix = text before the inputs
557
+ $prefix = '';
558
+ $input_prefix = '';
559
+ if ( 'from' == $from_or_to ) {
560
+ $prefix = _x( 'From', 'Filter dropin, custom date range', 'simple-history' );
561
+ $input_prefix = 'from_';
562
+ } elseif ( 'to' == $from_or_to ) {
563
+ $prefix = _x( 'To', 'Filter dropin, custom date range', 'simple-history' );
564
+ $input_prefix = 'to_';
565
  }
566
 
567
  // The default date to show in the inputs
568
+ $date = date( 'Y-m-d' );
569
 
570
  $jj = mysql2date( 'd', $date, false );
571
  $mm = mysql2date( 'm', $date, false );
573
 
574
  $month = "<select name='{$input_prefix}mm'>";
575
 
576
+ for ( $i = 1; $i < 13; $i = $i + 1 ) {
577
+ $monthnum = zeroise( $i, 2 );
578
  $monthtext = $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) );
579
  $month .= "\t\t\t" . '<option value="' . $monthnum . '" data-text="' . $monthtext . '" ' . selected( $monthnum, $mm, false ) . '>';
580
  /* translators: 1: month number (01, 02, etc.), 2: month abbreviation */
583
  $month .= '</select>';
584
  $month .= '</label>';
585
 
586
+ $day = '<label><span class="screen-reader-text">' . __( 'Day' ) . '</span><input type="text" name="' . $input_prefix . 'jj" value="' . $jj . '" size="2" maxlength="2" autocomplete="off" /></label>';
587
+ $year = '<label><span class="screen-reader-text">' . __( 'Year' ) . '</span><input type="text" name="' . $input_prefix . 'aa" value="' . $aa . '" size="4" maxlength="4" autocomplete="off" /></label>';
588
 
589
  echo '<span class="SimpleHistory__filters__filter SimpleHistory__filters__filter--day">';
590
 
591
+ echo $prefix . '<br>';
592
 
593
  /* translators: 1: month, 2: day, 3: year, 4: hour, 5: minute */
594
  printf( __( '%1$s %2$s, %3$s ' ), $month, $day, $year );
dropins/SimpleHistoryIpInfoDropin.php CHANGED
@@ -12,28 +12,28 @@ class SimpleHistoryIpInfoDropin {
12
 
13
  private $sh;
14
 
15
- function __construct($sh) {
16
 
17
  $this->sh = $sh;
18
 
19
  // Since it's not quite done yet, it's for da devs only for now
20
- /*if ( ! defined("SIMPLE_HISTORY_DEV") || ! SIMPLE_HISTORY_DEV ) {
 
21
  return;
22
  }*/
23
 
24
- add_action("simple_history/enqueue_admin_scripts", array($this, "enqueue_admin_scripts"));
25
- add_action("simple_history/admin_footer", array($this, "add_js_template"));
26
-
27
 
28
  }
29
 
30
  public function enqueue_admin_scripts() {
31
 
32
- $file_url = plugin_dir_url(__FILE__);
33
 
34
- wp_enqueue_script("simple_history_IpInfoDropin", $file_url . "SimpleHistoryIpInfoDropin.js", array("jquery"), SIMPLE_HISTORY_VERSION, true);
35
 
36
- wp_enqueue_style("simple_history_IpInfoDropin", $file_url . "SimpleHistoryIpInfoDropin.css", null, SIMPLE_HISTORY_VERSION);
37
 
38
  }
39
 
@@ -65,7 +65,7 @@ class SimpleHistoryIpInfoDropin {
65
  -->
66
  <# if ( typeof(data.bogon) != "undefined" ) { #>
67
 
68
- <p><?php _ex("That IP address does not seem like a public one.", "IP Info Dropin", "simple-history"); ?></p>
69
 
70
  <# } else { #>
71
 
@@ -86,7 +86,7 @@ class SimpleHistoryIpInfoDropin {
86
  <# if ( typeof(data.ip) != "undefined" && data.ip ) { #>
87
  <tr>
88
  <td>
89
- <?php _ex("IP address", "IP Info Dropin", "simple-history"); ?>
90
  </td>
91
  <td>
92
  {{ data.ip }}
@@ -97,7 +97,7 @@ class SimpleHistoryIpInfoDropin {
97
  <# if ( typeof(data.hostname) != "undefined" && data.hostname ) { #>
98
  <tr>
99
  <td>
100
- <?php _ex("Hostname", "IP Info Dropin", "simple-history"); ?>
101
  </td>
102
  <td>
103
  {{ data.hostname }}
@@ -108,7 +108,7 @@ class SimpleHistoryIpInfoDropin {
108
  <# if ( typeof(data.org) != "undefined" && data.org ) { #>
109
  <tr>
110
  <td>
111
- <?php _ex("Network", "IP Info Dropin", "simple-history"); ?>
112
  </td>
113
  <td>
114
  {{ data.org }}
@@ -119,7 +119,7 @@ class SimpleHistoryIpInfoDropin {
119
  <# if ( typeof(data.network) != "undefined" && data.network ) { #>
120
  <tr>
121
  <td>
122
- <?php _ex("Network", "IP Info Dropin", "simple-history"); ?>
123
  </td>
124
  <td>
125
  {{ data.network }}
@@ -130,7 +130,7 @@ class SimpleHistoryIpInfoDropin {
130
  <# if ( typeof(data.city) != "undefined" && data.city ) { #>
131
  <tr>
132
  <td>
133
- <?php _ex("City", "IP Info Dropin", "simple-history"); ?>
134
  </td>
135
  <td>
136
  {{ data.city }}
@@ -141,7 +141,7 @@ class SimpleHistoryIpInfoDropin {
141
  <# if ( typeof(data.region) != "undefined" && data.region ) { #>
142
  <tr>
143
  <td>
144
- <?php _ex("Region", "IP Info Dropin", "simple-history"); ?>
145
  </td>
146
  <td>
147
  {{ data.region }}
@@ -152,7 +152,7 @@ class SimpleHistoryIpInfoDropin {
152
  <# if ( typeof(data.country) != "undefined" && data.country ) { #>
153
  <tr>
154
  <td>
155
- <?php _ex("Country", "IP Info Dropin", "simple-history"); ?>
156
  </td>
157
  <td>
158
  {{ data.country }}
@@ -163,7 +163,7 @@ class SimpleHistoryIpInfoDropin {
163
  </table>
164
 
165
  <p class="SimpleHistoryIpInfoDropin__provider">
166
- <?php printf( _x('IP info provided by %1$s ipinfo.io %2$s', "IP Info Dropin", "simple-history"), "<a href='https://ipinfo.io/{{ data.ip }}' target='_blank'>", "</a>" ); ?>
167
  </p>
168
 
169
  <# } #>
12
 
13
  private $sh;
14
 
15
+ function __construct( $sh ) {
16
 
17
  $this->sh = $sh;
18
 
19
  // Since it's not quite done yet, it's for da devs only for now
20
+ /*
21
+ if ( ! defined("SIMPLE_HISTORY_DEV") || ! SIMPLE_HISTORY_DEV ) {
22
  return;
23
  }*/
24
 
25
+ add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'enqueue_admin_scripts' ) );
26
+ add_action( 'simple_history/admin_footer', array( $this, 'add_js_template' ) );
 
27
 
28
  }
29
 
30
  public function enqueue_admin_scripts() {
31
 
32
+ $file_url = plugin_dir_url( __FILE__ );
33
 
34
+ wp_enqueue_script( 'simple_history_IpInfoDropin', $file_url . 'SimpleHistoryIpInfoDropin.js', array( 'jquery' ), SIMPLE_HISTORY_VERSION, true );
35
 
36
+ wp_enqueue_style( 'simple_history_IpInfoDropin', $file_url . 'SimpleHistoryIpInfoDropin.css', null, SIMPLE_HISTORY_VERSION );
37
 
38
  }
39
 
65
  -->
66
  <# if ( typeof(data.bogon) != "undefined" ) { #>
67
 
68
+ <p><?php _ex( 'That IP address does not seem like a public one.', 'IP Info Dropin', 'simple-history' ); ?></p>
69
 
70
  <# } else { #>
71
 
86
  <# if ( typeof(data.ip) != "undefined" && data.ip ) { #>
87
  <tr>
88
  <td>
89
+ <?php _ex( 'IP address', 'IP Info Dropin', 'simple-history' ); ?>
90
  </td>
91
  <td>
92
  {{ data.ip }}
97
  <# if ( typeof(data.hostname) != "undefined" && data.hostname ) { #>
98
  <tr>
99
  <td>
100
+ <?php _ex( 'Hostname', 'IP Info Dropin', 'simple-history' ); ?>
101
  </td>
102
  <td>
103
  {{ data.hostname }}
108
  <# if ( typeof(data.org) != "undefined" && data.org ) { #>
109
  <tr>
110
  <td>
111
+ <?php _ex( 'Network', 'IP Info Dropin', 'simple-history' ); ?>
112
  </td>
113
  <td>
114
  {{ data.org }}
119
  <# if ( typeof(data.network) != "undefined" && data.network ) { #>
120
  <tr>
121
  <td>
122
+ <?php _ex( 'Network', 'IP Info Dropin', 'simple-history' ); ?>
123
  </td>
124
  <td>
125
  {{ data.network }}
130
  <# if ( typeof(data.city) != "undefined" && data.city ) { #>
131
  <tr>
132
  <td>
133
+ <?php _ex( 'City', 'IP Info Dropin', 'simple-history' ); ?>
134
  </td>
135
  <td>
136
  {{ data.city }}
141
  <# if ( typeof(data.region) != "undefined" && data.region ) { #>
142
  <tr>
143
  <td>
144
+ <?php _ex( 'Region', 'IP Info Dropin', 'simple-history' ); ?>
145
  </td>
146
  <td>
147
  {{ data.region }}
152
  <# if ( typeof(data.country) != "undefined" && data.country ) { #>
153
  <tr>
154
  <td>
155
+ <?php _ex( 'Country', 'IP Info Dropin', 'simple-history' ); ?>
156
  </td>
157
  <td>
158
  {{ data.country }}
163
  </table>
164
 
165
  <p class="SimpleHistoryIpInfoDropin__provider">
166
+ <?php printf( _x( 'IP info provided by %1$s ipinfo.io %2$s', 'IP Info Dropin', 'simple-history' ), "<a href='https://ipinfo.io/{{ data.ip }}' target='_blank'>", '</a>' ); ?>
167
  </p>
168
 
169
  <# } #>
dropins/SimpleHistoryNewRowsNotifier.php CHANGED
@@ -7,7 +7,7 @@ defined( 'ABSPATH' ) or die();
7
  * Dropin Description: Checks for new rows and displays a info bar when new items are available
8
  * Dropin URI: http://simple-history.com/
9
  * Author: Pär Thernström
10
- */
11
 
12
  class SimpleHistoryNewRowsNotifier {
13
 
@@ -17,54 +17,59 @@ class SimpleHistoryNewRowsNotifier {
17
  // How often we should check for new rows, in ms
18
  private $interval = 10000;
19
 
20
- function __construct($sh) {
21
 
22
  $this->sh = $sh;
23
 
24
  // How often the script checks for new rows
25
- $this->interval = (int) apply_filters("SimpleHistoryNewRowsNotifier/interval", $this->interval);
26
 
27
- add_action( 'wp_ajax_SimpleHistoryNewRowsNotifier', array($this, 'ajax') );
28
- add_action( "simple_history/enqueue_admin_scripts", array($this, "enqueue_admin_scripts") );
29
 
30
  }
31
 
32
  public function enqueue_admin_scripts() {
33
 
34
- $file_url = plugin_dir_url(__FILE__);
35
 
36
- wp_enqueue_script("simple_history_NewRowsNotifierDropin", $file_url . "SimpleHistoryNewRowsNotifierDropin.js", array("jquery"), SIMPLE_HISTORY_VERSION, true);
37
 
38
  $arr_localize_data = array(
39
- "interval" => $this->interval,
40
- "errorCheck" =>_x('An error occured while checking for new events', 'New rows notifier: error while checking for new rows', 'simple-history')
41
  );
42
 
43
- wp_localize_script( "simple_history_NewRowsNotifierDropin", "simple_history_NewRowsNotifierDropin", $arr_localize_data );
44
 
45
- wp_enqueue_style( "simple_history_NewRowsNotifierDropin", $file_url . "SimpleHistoryNewRowsNotifierDropin.css", null, SIMPLE_HISTORY_VERSION);
46
 
47
  }
48
 
49
  public function ajax() {
50
 
51
- $apiArgs = isset( $_GET["apiArgs"] ) ? $_GET["apiArgs"] : array();
52
 
53
  if ( ! $apiArgs ) {
54
- wp_send_json_error( array("error" => "MISSING_APIARGS") );
 
 
55
  }
56
 
57
- if ( empty( $apiArgs["since_id"] ) || ! is_numeric( $apiArgs["since_id"] ) ) {
58
- wp_send_json_error( array("error" => "MISSING_SINCE_ID") );
 
 
59
  }
60
 
61
  // User must have capability to view the history page
62
  if ( ! current_user_can( $this->sh->get_view_history_capability() ) ) {
63
- wp_send_json_error( array("error" => "CAPABILITY_ERROR") );
 
 
64
  }
65
 
66
  // $since_id = isset( $_GET["since_id"] ) ? absint($_GET["since_id"]) : null;
67
-
68
  $logQueryArgs = $apiArgs;
69
 
70
  $logQuery = new SimpleHistoryLogQuery();
@@ -73,18 +78,17 @@ class SimpleHistoryNewRowsNotifier {
73
  // Use our own response array instead of $answer to keep size down
74
  $json_data = array();
75
 
76
- $numNewRows = isset( $answer["total_row_count"] ) ? $answer["total_row_count"] : 0;
77
- $json_data["num_new_rows"] = $numNewRows;
78
- $json_data["num_mysql_queries"] = get_num_queries();
79
 
80
- if ($numNewRows) {
81
 
82
  // We have new rows
83
-
84
  // Append strings
85
  $textRowsFound = sprintf( _n( '1 new event', '%d new events', $numNewRows, 'simple-history' ), $numNewRows );
86
- $json_data["strings"] = array(
87
- "newRowsFound" => $textRowsFound
88
  );
89
 
90
  }
7
  * Dropin Description: Checks for new rows and displays a info bar when new items are available
8
  * Dropin URI: http://simple-history.com/
9
  * Author: Pär Thernström
10
+ */
11
 
12
  class SimpleHistoryNewRowsNotifier {
13
 
17
  // How often we should check for new rows, in ms
18
  private $interval = 10000;
19
 
20
+ function __construct( $sh ) {
21
 
22
  $this->sh = $sh;
23
 
24
  // How often the script checks for new rows
25
+ $this->interval = (int) apply_filters( 'SimpleHistoryNewRowsNotifier/interval', $this->interval );
26
 
27
+ add_action( 'wp_ajax_SimpleHistoryNewRowsNotifier', array( $this, 'ajax' ) );
28
+ add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'enqueue_admin_scripts' ) );
29
 
30
  }
31
 
32
  public function enqueue_admin_scripts() {
33
 
34
+ $file_url = plugin_dir_url( __FILE__ );
35
 
36
+ wp_enqueue_script( 'simple_history_NewRowsNotifierDropin', $file_url . 'SimpleHistoryNewRowsNotifierDropin.js', array( 'jquery' ), SIMPLE_HISTORY_VERSION, true );
37
 
38
  $arr_localize_data = array(
39
+ 'interval' => $this->interval,
40
+ 'errorCheck' => _x( 'An error occured while checking for new events', 'New rows notifier: error while checking for new rows', 'simple-history' ),
41
  );
42
 
43
+ wp_localize_script( 'simple_history_NewRowsNotifierDropin', 'simple_history_NewRowsNotifierDropin', $arr_localize_data );
44
 
45
+ wp_enqueue_style( 'simple_history_NewRowsNotifierDropin', $file_url . 'SimpleHistoryNewRowsNotifierDropin.css', null, SIMPLE_HISTORY_VERSION );
46
 
47
  }
48
 
49
  public function ajax() {
50
 
51
+ $apiArgs = isset( $_GET['apiArgs'] ) ? $_GET['apiArgs'] : array();
52
 
53
  if ( ! $apiArgs ) {
54
+ wp_send_json_error( array(
55
+ 'error' => 'MISSING_APIARGS',
56
+ ) );
57
  }
58
 
59
+ if ( empty( $apiArgs['since_id'] ) || ! is_numeric( $apiArgs['since_id'] ) ) {
60
+ wp_send_json_error( array(
61
+ 'error' => 'MISSING_SINCE_ID',
62
+ ) );
63
  }
64
 
65
  // User must have capability to view the history page
66
  if ( ! current_user_can( $this->sh->get_view_history_capability() ) ) {
67
+ wp_send_json_error( array(
68
+ 'error' => 'CAPABILITY_ERROR',
69
+ ) );
70
  }
71
 
72
  // $since_id = isset( $_GET["since_id"] ) ? absint($_GET["since_id"]) : null;
 
73
  $logQueryArgs = $apiArgs;
74
 
75
  $logQuery = new SimpleHistoryLogQuery();
78
  // Use our own response array instead of $answer to keep size down
79
  $json_data = array();
80
 
81
+ $numNewRows = isset( $answer['total_row_count'] ) ? $answer['total_row_count'] : 0;
82
+ $json_data['num_new_rows'] = $numNewRows;
83
+ $json_data['num_mysql_queries'] = get_num_queries();
84
 
85
+ if ( $numNewRows ) {
86
 
87
  // We have new rows
 
88
  // Append strings
89
  $textRowsFound = sprintf( _n( '1 new event', '%d new events', $numNewRows, 'simple-history' ), $numNewRows );
90
+ $json_data['strings'] = array(
91
+ 'newRowsFound' => $textRowsFound,
92
  );
93
 
94
  }
dropins/SimpleHistoryPluginPatchesDropin.php CHANGED
@@ -12,16 +12,14 @@ class SimpleHistoryPluginPatchesDropin {
12
 
13
  private $sh;
14
 
15
- function __construct($sh) {
16
-
17
  $this->sh = $sh;
18
 
19
  $this->patch_captcha_on_login();
20
 
21
- #$this->patch_nextgen_gallery();
22
-
23
- #$this->patch_aio_events_calendar();
24
-
25
  }
26
 
27
  /**
@@ -31,30 +29,30 @@ class SimpleHistoryPluginPatchesDropin {
31
  function patch_aio_events_calendar() {
32
 
33
  // feature/fix-AIOEventsCalendar
34
- add_action( "simple_history/log/do_log", array( $this, "patch_aio_events_calendar_on_log" ), 10, 5 );
35
 
36
  }
37
 
38
-
39
  function patch_aio_events_calendar_on_log( $doLog, $level = null, $message = null, $context = null, $loggerInstance = null ) {
40
 
41
  // this happens when posts are updated
42
- if ( ! isset( $context["_message_key"]) || $context["_message_key"] !== "post_updated" ) {
43
  return $doLog;
44
  }
45
 
46
  // this happens when post type is ai1ec_event
47
- if ( ! isset( $context["post_type"]) || $context["post_type"] !== "ai1ec_event" ) {
48
  return $doLog;
49
  }
50
 
51
  // we don't log when is happens in admin, only when it's a cron job
52
- if ( ! defined('DOING_CRON') || ! DOING_CRON || is_admin() ) {
53
  return $doLog;
54
  }
55
 
56
  // ok, this is a non-admin, cron-running post update for the ai1ec_event post type, so cancel the logging
57
- error_log("ok, cancel ai1ec_event log");
58
  $doLog = false;
59
 
60
  return $doLog;
@@ -66,37 +64,36 @@ class SimpleHistoryPluginPatchesDropin {
66
  *
67
  * Nextgen Gallery and Nextgen Gallery Plus updates posts every 30 minutes or so when accessing
68
  * posts with galleries on the front
69
- *
70
  * Logged messages are like "Updated nextgen gallery - display type "NextGen Pro Mosaic""
71
  * and it can be a lot of them.
72
- *
73
  * Support forum thread:
74
  * https://wordpress.org/support/topic/non-stop-logging-nextgen-gallery-items
75
- *
76
  * Note that Simple History does nothing wrong, the posts are updated, but it's just annoying
77
  * and unneeded/unwanted info.
78
  *
79
  * We solve this by canceling logging of these events.
80
- *
81
  */
82
  function patch_nextgen_gallery() {
83
 
84
- add_action( "simple_history/log/do_log", array( $this, "patch_nextgen_gallery_on_log" ), 10, 5 );
85
 
86
  }
87
 
88
  function patch_nextgen_gallery_on_log( $doLog, $level = null, $message = null, $context = null, $loggerInstance = null ) {
89
 
90
  // Check that NextGen is installed
91
- if ( ! defined("NGG_PLUGIN") ) {
92
  return $doLog;
93
  }
94
 
95
- if ( ! isset( $context["_message_key"]) || $context["_message_key"] !== "post_updated" ) {
96
  return $doLog;
97
  }
98
 
99
- if ( ! isset( $context["post_type"]) || $context["post_type"] !== "display_type" ) {
100
  return $doLog;
101
  }
102
 
@@ -106,19 +103,18 @@ class SimpleHistoryPluginPatchesDropin {
106
  }
107
 
108
  // The calls must come from logger SimplePostLogger
109
- if ( $loggerInstance->slug !== "SimplePostLogger" ) {
110
  return $doLog;
111
  }
112
 
113
  // There. All checked. Now cancel the logging.
114
- error_log("ok, cancel nextgen gallery log");
115
  $doLog = false;
116
 
117
- #error_log(simpleHistory::json_encode( $context ));
118
- #error_log(simpleHistory::json_encode( $loggerInstance ));
119
- #error_log(simpleHistory::json_encode( is_admin() ));
120
  // error_log( __METHOD__ . " canceled logging" );
121
-
122
  return $doLog;
123
 
124
  }
@@ -127,7 +123,7 @@ class SimpleHistoryPluginPatchesDropin {
127
  /**
128
  * Captcha on Login
129
  *
130
- * Calls wp_logut() wrongly when
131
  * - a user IP is blocked
132
  * - when max num of tries is reached
133
  * - or when the capcha is not correct
@@ -138,23 +134,22 @@ class SimpleHistoryPluginPatchesDropin {
138
  *
139
  * Plugin also gives lots of errors, reported by me here:
140
  * https://wordpress.org/support/topic/errors-has_cap-deprecated-strict-standards-warning
141
- *
142
  */
143
  function patch_captcha_on_login() {
144
 
145
- add_action( "simple_history/log/do_log", array( $this, "patch_captcha_on_login_on_log" ), 10, 5 );
146
 
147
  }
148
 
149
  // Detect that this log message is being called from Captha on login
150
  // and that the message is "user_logged_out"
151
- function patch_captcha_on_login_on_log( $doLog, $level = null, $message = null, $context = null, $loggerInstance = null ) {
152
 
153
- if ( empty( $context ) || ! isset( $context["_message_key"] ) || "user_logged_out" != $context["_message_key"] ) {
154
  // Message key did not exist or was not "user_logged_out"
155
  return $doLog;
156
  }
157
-
158
  // 22 nov 2015: disabled this check beacuse for example robots/scripts don't pass all args
159
  // instead they only post "log" and "pwd"
160
  // codiga is the input with the captcha
@@ -168,10 +163,10 @@ class SimpleHistoryPluginPatchesDropin {
168
  // The Captcha on login uses a class called 'Anderson_Makiyama_Captcha_On_Login'
169
  // and also a global variable called $global $anderson_makiyama
170
  global $anderson_makiyama;
171
- if ( ! class_exists("Anderson_Makiyama_Captcha_On_Login") || ! isset( $anderson_makiyama ) ) {
172
  return $doLog;
173
  }
174
-
175
  // We must come from wp-login
176
  // Disabled 22 nov 2015 because robots/scripts dont send referer
177
  /*
@@ -187,15 +182,15 @@ class SimpleHistoryPluginPatchesDropin {
187
 
188
  // File must be wp-login.php (can it even be another?)
189
  $request_uri = basename( wp_unslash( $_SERVER['REQUEST_URI'] ) );
190
- if ( "wp-login.php" !== $request_uri ) {
191
  return $doLog;
192
  }
193
 
194
  $anderson_makiyama_indice = Anderson_Makiyama_Captcha_On_Login::PLUGIN_ID;
195
- $capcha_on_login_class_name = $anderson_makiyama[$anderson_makiyama_indice]::CLASS_NAME;
196
-
197
- $capcha_on_login_options = (array) get_option( $capcha_on_login_class_name . "_options", array());
198
- $last_100_logins = isset( $capcha_on_login_options["last_100_logins"] ) ? (array) $capcha_on_login_options["last_100_logins"] : array();
199
  $last_100_logins = array_reverse( $last_100_logins );
200
 
201
  // Possible messages
@@ -204,70 +199,67 @@ class SimpleHistoryPluginPatchesDropin {
204
  // - Failed: image code did not match
205
  // - Failed: Login or Password did not match
206
  // - Success
207
- $last_login_status = isset( $last_100_logins[0][2] ) ? $last_100_logins[0][2] : "";
208
 
209
  // If we get here we're pretty sure we come from Captcha on login
210
  // and that we should cancel the wp_logout message and log an failed login instead
211
-
212
  // Get the user logger
213
- $userLogger = $this->sh->getInstantiatedLoggerBySlug( "SimpleUserLogger" );
214
 
215
  if ( ! $userLogger ) {
216
  return $doLog;
217
  }
218
 
219
  // $userLogger->warningMessage("user_unknown_login_failed", $context);
220
-
221
  // Same context as in SimpleUserLogger
222
  $context = array(
223
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER,
224
- #"login_user_id" => $user->ID,
225
- #"login_user_email" => $user->user_email,
226
- #"login_user_login" => $user->user_login,
227
- "server_http_user_agent" => isset( $_SERVER["HTTP_USER_AGENT"] ) ? $_SERVER["HTTP_USER_AGENT"] : null,
228
- "_occasionsID" => "SimpleUserLogger" . '/failed_user_login',
229
- "patch_using_patch" => true,
230
- "patch_name" => "captcha_on_login"
231
  );
232
 
233
  // Append capcha message
234
  if ( $last_login_status ) {
235
- $context["patch_last_login_status"] = $last_login_status;
236
  }
237
 
238
  // Get user id and email and login
239
  // Not passed to filter, but we have it in $_POST
240
- $login_username = isset( $_POST["log"] ) ? $_POST["log"] : null;
241
-
242
  if ( $login_username ) {
243
 
244
- $context["login_user_login"] = $login_username;
245
 
246
- $user = get_user_by( "login", $login_username );
247
 
248
- if ( is_a( $user, "WP_User") ) {
249
 
250
- $context["login_user_id"] = $user->ID;
251
- $context["login_user_email"] = $user->user_email;
252
-
253
- }
254
 
 
255
  }
256
 
257
- $userLogger->warningMessage("user_login_failed", $context);
258
 
259
  // Cancel original log event
260
  $doLog = false;
261
 
262
  return $doLog;
263
-
264
  }
265
-
266
  /**
267
  * Log misc useful things to the system log. Useful when developing/testing/debuging etc.
268
  */
269
  function system_debug_log() {
270
-
271
  error_log( '$_GET: ' . SimpleHistory::json_encode( $_GET ) );
272
  error_log( '$_POST: ' . SimpleHistory::json_encode( $_POST ) );
273
  error_log( '$_FILES: ' . SimpleHistory::json_encode( $_FILES ) );
@@ -277,7 +269,7 @@ class SimpleHistoryPluginPatchesDropin {
277
  $i = 0;
278
 
279
  foreach ( $args as $arg ) {
280
- error_log( "\$arg $i: " . SimpleHistory::json_encode( $arg ) );
281
  $i++;
282
  }
283
 
12
 
13
  private $sh;
14
 
15
+ function __construct( $sh ) {
16
+
17
  $this->sh = $sh;
18
 
19
  $this->patch_captcha_on_login();
20
 
21
+ // $this->patch_nextgen_gallery();
22
+ // $this->patch_aio_events_calendar();
 
 
23
  }
24
 
25
  /**
29
  function patch_aio_events_calendar() {
30
 
31
  // feature/fix-AIOEventsCalendar
32
+ add_action( 'simple_history/log/do_log', array( $this, 'patch_aio_events_calendar_on_log' ), 10, 5 );
33
 
34
  }
35
 
36
+
37
  function patch_aio_events_calendar_on_log( $doLog, $level = null, $message = null, $context = null, $loggerInstance = null ) {
38
 
39
  // this happens when posts are updated
40
+ if ( ! isset( $context['_message_key'] ) || $context['_message_key'] !== 'post_updated' ) {
41
  return $doLog;
42
  }
43
 
44
  // this happens when post type is ai1ec_event
45
+ if ( ! isset( $context['post_type'] ) || $context['post_type'] !== 'ai1ec_event' ) {
46
  return $doLog;
47
  }
48
 
49
  // we don't log when is happens in admin, only when it's a cron job
50
+ if ( ! defined( 'DOING_CRON' ) || ! DOING_CRON || is_admin() ) {
51
  return $doLog;
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;
64
  *
65
  * Nextgen Gallery and Nextgen Gallery Plus updates posts every 30 minutes or so when accessing
66
  * posts with galleries on the front
67
+ *
68
  * Logged messages are like "Updated nextgen gallery - display type "NextGen Pro Mosaic""
69
  * and it can be a lot of them.
70
+ *
71
  * Support forum thread:
72
  * https://wordpress.org/support/topic/non-stop-logging-nextgen-gallery-items
73
+ *
74
  * Note that Simple History does nothing wrong, the posts are updated, but it's just annoying
75
  * and unneeded/unwanted info.
76
  *
77
  * We solve this by canceling logging of these events.
 
78
  */
79
  function patch_nextgen_gallery() {
80
 
81
+ add_action( 'simple_history/log/do_log', array( $this, 'patch_nextgen_gallery_on_log' ), 10, 5 );
82
 
83
  }
84
 
85
  function patch_nextgen_gallery_on_log( $doLog, $level = null, $message = null, $context = null, $loggerInstance = null ) {
86
 
87
  // Check that NextGen is installed
88
+ if ( ! defined( 'NGG_PLUGIN' ) ) {
89
  return $doLog;
90
  }
91
 
92
+ if ( ! isset( $context['_message_key'] ) || $context['_message_key'] !== 'post_updated' ) {
93
  return $doLog;
94
  }
95
 
96
+ if ( ! isset( $context['post_type'] ) || $context['post_type'] !== 'display_type' ) {
97
  return $doLog;
98
  }
99
 
103
  }
104
 
105
  // The calls must come from logger SimplePostLogger
106
+ if ( $loggerInstance->slug !== 'SimplePostLogger' ) {
107
  return $doLog;
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
  }
123
  /**
124
  * Captcha on Login
125
  *
126
+ * Calls wp_logut() wrongly when
127
  * - a user IP is blocked
128
  * - when max num of tries is reached
129
  * - or when the capcha is not correct
134
  *
135
  * Plugin also gives lots of errors, reported by me here:
136
  * https://wordpress.org/support/topic/errors-has_cap-deprecated-strict-standards-warning
 
137
  */
138
  function patch_captcha_on_login() {
139
 
140
+ add_action( 'simple_history/log/do_log', array( $this, 'patch_captcha_on_login_on_log' ), 10, 5 );
141
 
142
  }
143
 
144
  // Detect that this log message is being called from Captha on login
145
  // and that the message is "user_logged_out"
146
+ function patch_captcha_on_login_on_log( $doLog, $level = null, $message = null, $context = null, $loggerInstance = null ) {
147
 
148
+ if ( empty( $context ) || ! isset( $context['_message_key'] ) || 'user_logged_out' != $context['_message_key'] ) {
149
  // Message key did not exist or was not "user_logged_out"
150
  return $doLog;
151
  }
152
+
153
  // 22 nov 2015: disabled this check beacuse for example robots/scripts don't pass all args
154
  // instead they only post "log" and "pwd"
155
  // codiga is the input with the captcha
163
  // The Captcha on login uses a class called 'Anderson_Makiyama_Captcha_On_Login'
164
  // and also a global variable called $global $anderson_makiyama
165
  global $anderson_makiyama;
166
+ if ( ! class_exists( 'Anderson_Makiyama_Captcha_On_Login' ) || ! isset( $anderson_makiyama ) ) {
167
  return $doLog;
168
  }
169
+
170
  // We must come from wp-login
171
  // Disabled 22 nov 2015 because robots/scripts dont send referer
172
  /*
182
 
183
  // File must be wp-login.php (can it even be another?)
184
  $request_uri = basename( wp_unslash( $_SERVER['REQUEST_URI'] ) );
185
+ if ( 'wp-login.php' !== $request_uri ) {
186
  return $doLog;
187
  }
188
 
189
  $anderson_makiyama_indice = Anderson_Makiyama_Captcha_On_Login::PLUGIN_ID;
190
+ $capcha_on_login_class_name = $anderson_makiyama[ $anderson_makiyama_indice ]::CLASS_NAME;
191
+
192
+ $capcha_on_login_options = (array) get_option( $capcha_on_login_class_name . '_options', array() );
193
+ $last_100_logins = isset( $capcha_on_login_options['last_100_logins'] ) ? (array) $capcha_on_login_options['last_100_logins'] : array();
194
  $last_100_logins = array_reverse( $last_100_logins );
195
 
196
  // Possible messages
199
  // - Failed: image code did not match
200
  // - Failed: Login or Password did not match
201
  // - Success
202
+ $last_login_status = isset( $last_100_logins[0][2] ) ? $last_100_logins[0][2] : '';
203
 
204
  // If we get here we're pretty sure we come from Captcha on login
205
  // and that we should cancel the wp_logout message and log an failed login instead
 
206
  // Get the user logger
207
+ $userLogger = $this->sh->getInstantiatedLoggerBySlug( 'SimpleUserLogger' );
208
 
209
  if ( ! $userLogger ) {
210
  return $doLog;
211
  }
212
 
213
  // $userLogger->warningMessage("user_unknown_login_failed", $context);
 
214
  // Same context as in SimpleUserLogger
215
  $context = array(
216
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
217
+ // "login_user_id" => $user->ID,
218
+ // "login_user_email" => $user->user_email,
219
+ // "login_user_login" => $user->user_login,
220
+ 'server_http_user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
221
+ '_occasionsID' => 'SimpleUserLogger' . '/failed_user_login',
222
+ 'patch_using_patch' => true,
223
+ 'patch_name' => 'captcha_on_login',
224
  );
225
 
226
  // Append capcha message
227
  if ( $last_login_status ) {
228
+ $context['patch_last_login_status'] = $last_login_status;
229
  }
230
 
231
  // Get user id and email and login
232
  // Not passed to filter, but we have it in $_POST
233
+ $login_username = isset( $_POST['log'] ) ? $_POST['log'] : null;
234
+
235
  if ( $login_username ) {
236
 
237
+ $context['login_user_login'] = $login_username;
238
 
239
+ $user = get_user_by( 'login', $login_username );
240
 
241
+ if ( is_a( $user, 'WP_User' ) ) {
242
 
243
+ $context['login_user_id'] = $user->ID;
244
+ $context['login_user_email'] = $user->user_email;
 
 
245
 
246
+ }
247
  }
248
 
249
+ $userLogger->warningMessage( 'user_login_failed', $context );
250
 
251
  // Cancel original log event
252
  $doLog = false;
253
 
254
  return $doLog;
255
+
256
  }
257
+
258
  /**
259
  * Log misc useful things to the system log. Useful when developing/testing/debuging etc.
260
  */
261
  function system_debug_log() {
262
+
263
  error_log( '$_GET: ' . SimpleHistory::json_encode( $_GET ) );
264
  error_log( '$_POST: ' . SimpleHistory::json_encode( $_POST ) );
265
  error_log( '$_FILES: ' . SimpleHistory::json_encode( $_FILES ) );
269
  $i = 0;
270
 
271
  foreach ( $args as $arg ) {
272
+ error_log( "\$arg $i: " . SimpleHistory::json_encode( $arg ) );
273
  $i++;
274
  }
275
 
dropins/SimpleHistoryRSSDropin.php CHANGED
@@ -1,7 +1,6 @@
1
  <?php
2
 
3
  // defined('ABSPATH') or die();
4
-
5
  /*
6
  Dropin Name: Global RSS Feed
7
  Dropin URI: http://simple-history.com/
@@ -11,292 +10,285 @@ Author: Pär Thernström
11
  /**
12
  * Simple History RSS Feed drop-in
13
  */
14
- class SimpleHistoryRSSDropin
15
- {
16
-
17
- public function __construct($sh)
18
- {
19
-
20
- $this->sh = $sh;
21
-
22
- if (! function_exists('get_editable_roles')) {
23
- require_once(ABSPATH . '/wp-admin/includes/user.php');
24
- }
25
-
26
- //Check the status of the RSS feed
27
- $this->isRssEnabled();
28
-
29
- // Generate a rss secret, if it does not exist
30
- if (! get_option("simple_history_rss_secret")) {
31
- $this->updateRssSecret();
32
- }
33
-
34
- add_action('init', array($this, 'checkForRssFeedRequest'));
35
-
36
- // Add settings with prio 11 so it' added after the main Simple History settings
37
- add_action('admin_menu', array($this, 'addSettings'), 11);
38
- }
39
-
40
- /**
41
- * Add settings for the RSS feed
42
- * + also regenerates the secret if requested
43
- */
44
- public function addSettings()
45
- {
46
-
47
- //we register a setting to keep track of the RSS feed status (enabled/disabled)
48
- register_setting(
49
- SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP,
50
- 'simple_history_enable_rss_feed',
51
- array($this, 'public updateRssStatus'
52
- )
53
- );
54
- /**
55
- * Start new section for RSS feed
56
- */
57
- $settings_section_rss_id = "simple_history_settings_section_rss";
58
-
59
- add_settings_section(
60
- $settings_section_rss_id,
61
- _x("RSS feed", "rss settings headline", "simple-history"), // No title __("General", "simple-history"),
62
- array($this, "settingsSectionOutput"),
63
- SimpleHistory::SETTINGS_MENU_SLUG // same slug as for options menu page
64
- );
65
-
66
- // Enable/Disabled RSS feed
67
- add_settings_field(
68
- "simple_history_enable_rss_feed",
69
- __("Enable", "simple-history"),
70
- array($this, "settingsFieldRssEnable"),
71
- SimpleHistory::SETTINGS_MENU_SLUG,
72
- $settings_section_rss_id
73
- );
74
-
75
- //if RSS is activated we display other fields
76
- if ($this->isRssEnabled()) {
77
- // RSS address
78
- add_settings_field(
79
- "simple_history_rss_feed",
80
- __("Address", "simple-history"),
81
- array($this, "settingsFieldRss"),
82
- SimpleHistory::SETTINGS_MENU_SLUG,
83
- $settings_section_rss_id
84
- );
85
-
86
- // Regnerate address
87
- add_settings_field(
88
- "simple_history_rss_feed_regenerate_secret",
89
- __("Regenerate", "simple-history"),
90
- array($this, "settingsFieldRssRegenerate"),
91
- SimpleHistory::SETTINGS_MENU_SLUG,
92
- $settings_section_rss_id
93
- );
94
- }
95
-
96
- // Create new RSS secret
97
- $create_new_secret = false;
98
- $create_secret_nonce_name = "simple_history_rss_secret_regenerate_nonce";
99
- $createNonceOk = isset($_GET[$create_secret_nonce_name]) && wp_verify_nonce($_GET[$create_secret_nonce_name], 'simple_history_rss_update_secret');
100
-
101
- if ($createNonceOk) {
102
- $create_new_secret = true;
103
- $this->updateRssSecret();
104
-
105
- // Add updated-message and store in transient and then redirect
106
- // This is the way options.php does it.
107
- $msg = __("Created new secret RSS address", 'simple-history');
108
- add_settings_error("simple_history_rss_feed_regenerate_secret", "simple_history_rss_feed_regenerate_secret", $msg, "updated");
109
- set_transient('settings_errors', get_settings_errors(), 30);
110
-
111
- $goback = esc_url_raw(add_query_arg('settings-updated', 'true', wp_get_referer()));
112
- wp_redirect($goback);
113
- exit;
114
- }
115
- } // settings
116
-
117
- /**
118
- * Check if RSS feed is enabled or disabled
119
- */
120
- public function isRssEnabled()
121
- {
122
-
123
- // User has never used the plugin we disable RSS feed
124
- if (get_option("simple_history_rss_secret") === false && get_option("simple_history_enable_rss_feed") === false) {
125
- //We disable RSS by default, we use 0/1 to prevent fake disabled with bools from functions returning false for unset
126
- update_option("simple_history_enable_rss_feed", "0");
127
- } elseif (get_option("simple_history_enable_rss_feed") === false) {
128
- // User was using the plugin before RSS feed became disabled by default
129
- // We activate RSS to prevent a "breaking change"
130
- update_option("simple_history_enable_rss_feed", "1");
131
- return true;
132
- } elseif (get_option("simple_history_enable_rss_feed") === "1") {
133
- return true;
134
- }
135
-
136
- return false;
137
- }
138
-
139
- /**
140
- * Output for settings field that show current RSS address
141
- */
142
- public function settingsFieldRssEnable()
143
- {
144
- ?>
145
- <input value="1" type="checkbox" id="simple_history_enable_rss_feed" name="simple_history_enable_rss_feed" <?php checked($this->isRssEnabled(), 1); ?> />
146
- <label for="simple_history_enable_rss_feed"><?php _e("Enable RSS feed", 'simple-history') ?></label>
147
- <?php
148
- }
149
-
150
- /**
151
- * Sanitize RSS enabled/disabled status on update settings
152
- */
153
- public function updateRssStatus($field)
154
- {
155
-
156
- if ($field === "1") {
157
- return "1";
158
- }
159
-
160
- return "0";
161
- }
162
-
163
-
164
- /**
165
- * Check if current request is a request for the RSS feed
166
- */
167
- public function checkForRssFeedRequest()
168
- {
169
- // check for RSS
170
- // don't know if this is the right way to do this, but it seems to work!
171
- if (isset($_GET["simple_history_get_rss"])) {
172
- $this->outputRss();
173
- exit;
174
- }
175
- }
176
-
177
- /**
178
- * Modify capability check so all users reading rss feed (logged in or not) can read all loggers
179
- */
180
- public function onCanReadSingleLogger($user_can_read_logger, $logger_instance, $user_id)
181
- {
182
- $user_can_read_logger = true;
183
-
184
- return $user_can_read_logger;
185
- }
186
-
187
- /**
188
- * Output RSS
189
- */
190
- public function outputRss()
191
- {
192
-
193
- $rss_secret_option = get_option("simple_history_rss_secret");
194
- $rss_secret_get = isset($_GET["rss_secret"]) ? $_GET["rss_secret"] : "";
195
-
196
- if (empty($rss_secret_option) || empty($rss_secret_get)) {
197
- die();
198
- }
199
-
200
- $rss_show = true;
201
- $rss_show = apply_filters("simple_history/rss_feed_show", $rss_show);
202
- if (! $rss_show || ! $this->isRssEnabled()) {
203
- wp_die('Nothing here.');
204
- }
205
-
206
- header("Content-Type: text/xml; charset=utf-8");
207
- echo '<?xml version="1.0" encoding="UTF-8"?>';
208
- $self_link = $this->getRssAddress();
209
-
210
- if ($rss_secret_option === $rss_secret_get) {
211
- ?>
212
- <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
213
- <channel>
214
- <title><![CDATA[<?php printf(__("History for %s", 'simple-history'), get_bloginfo("name")) ?>]]></title>
215
- <description><![CDATA[<?php printf(__("WordPress History for %s", 'simple-history'), get_bloginfo("name")) ?>]]></description>
216
- <link><?php echo get_bloginfo("url") ?></link>
217
- <atom:link href="<?php echo $self_link; ?>" rel="self" type="application/atom+xml" />
218
- <?php
219
-
220
- // Override capability check: if you have a valid rss_secret_key you can read it all
221
- $action_tag = "simple_history/loggers_user_can_read/can_read_single_logger";
222
- add_action($action_tag, array($this, "onCanReadSingleLogger"), 10, 3);
223
-
224
- // Modify header time output so it does not show relative date or time ago-format
225
- // Because we don't know when a user reads the RSS feed, time ago format may be very inaccurate
226
- add_action("simple_history/header_just_now_max_time", "__return_zero");
227
- add_action("simple_history/header_time_ago_max_time", "__return_zero");
228
-
229
- // Get log rows
230
- $args = array(
231
- "posts_per_page" => 10
232
- );
233
-
234
- $args = apply_filters("simple_history/rss_feed_args", $args);
235
-
236
- $logQuery = new SimpleHistoryLogQuery();
237
- $queryResults = $logQuery->query($args);
238
-
239
- // Remove capability override after query is done
240
- // remove_action( $action_tag, array($this, "onCanReadSingleLogger") );
241
-
242
- foreach ($queryResults["log_rows"] as $row) {
243
- $header_output = $this->sh->getLogRowHeaderOutput($row);
244
- $text_output = $this->sh->getLogRowPlainTextOutput($row);
245
- $details_output = $this->sh->getLogRowDetailsOutput($row);
246
-
247
- // http://cyber.law.harvard.edu/rss/rss.html#ltguidgtSubelementOfLtitemgt
248
- //$item_guid = home_url() . "?SimpleHistoryGuid=" . $row->id;
249
- $item_guid = esc_url(add_query_arg("SimpleHistoryGuid", $row->id, home_url()));
250
- $item_link = esc_url(add_query_arg("SimpleHistoryGuid", $row->id, home_url()));
251
-
252
- /**
253
- * Filter the guid/link URL used in RSS feed.
254
- * Link will be esc_url'ed by simple history, so no need to do that in your filter
255
- *
256
- * @since 2.0.23
257
- *
258
- * @param string $item_guid link.
259
- * @param array $row
260
- */
261
- $item_link = apply_filters("simple_history/rss_item_link", $item_link, $row);
262
- $item_link = esc_url($item_link);
263
-
264
- $item_title = sprintf(
265
- '%2$s',
266
- $this->sh->getLogLevelTranslated($row->level),
267
- wp_kses($text_output, array())
268
- );
269
-
270
- $level_output = sprintf(__('Severity level: %1$s'), $this->sh->getLogLevelTranslated($row->level));
271
-
272
- ?>
273
- <item>
274
- <title><![CDATA[<?php echo $item_title; ?>]]></title>
275
- <description><![CDATA[
276
- <p><?php echo $header_output ?></p>
277
- <p><?php echo $text_output ?></p>
278
- <div><?php echo $details_output ?></div>
279
- <p><?php echo $level_output ?></p>
280
- <?php
281
- $occasions = $row->subsequentOccasions - 1;
282
- if ($occasions) {
283
- printf(
284
- _n('+%1$s occasion', '+%1$s occasions', $occasions, 'simple-history'),
285
- $occasions
286
- );
287
- }
288
- ?>
289
- ]]></description>
290
- <?php
291
- // author must be email to validate, but the field is optional, so we skip it
292
- /* <author><?php echo $row->initiator ?></author> */
293
- ?>
294
- <pubDate><?php echo date("D, d M Y H:i:s", strtotime($row->date)) ?> GMT</pubDate>
295
- <guid isPermaLink="false"><![CDATA[<?php echo $item_guid ?>]]></guid>
296
- <link><![CDATA[<?php echo $item_link ?>]]></link>
297
- </item>
298
- <?php
299
- /*
300
  [0] =&gt; stdClass Object
301
  (
302
  [id] =&gt; 27324
@@ -333,113 +325,110 @@ class SimpleHistoryRSSDropin
333
 
334
  )
335
  */
336
- } // foreach
337
-
338
- ?>
339
- </channel>
340
- </rss>
341
- <?php
342
- } else {
343
- // RSS secret was not ok
344
- ?>
345
- <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
346
- <channel>
347
- <title><?php printf(__("History for %s", 'simple-history'), get_bloginfo("name")) ?></title>
348
- <description><?php printf(__("WordPress History for %s", 'simple-history'), get_bloginfo("name")) ?></description>
349
- <link><?php echo home_url() ?></link>
350
- <item>
351
- <title><?php _e("Wrong RSS secret", 'simple-history')?></title>
352
- <description><?php _e("Your RSS secret for Simple History RSS feed is wrong. Please see WordPress settings for current link to the RSS feed.", 'simple-history')?></description>
353
- <pubDate><?php echo date("D, d M Y H:i:s", time()) ?> GMT</pubDate>
354
- <guid><?php echo home_url() . "?SimpleHistoryGuid=wrong-secret" ?></guid>
355
- </item>
356
- </channel>
357
- </rss>
358
- <?php
359
- }
360
- } // rss
361
-
362
- /**
363
- * Create a new RSS secret
364
- *
365
- * @return string new secret
366
- */
367
- public function updateRssSecret()
368
- {
369
-
370
- $rss_secret = "";
371
-
372
- for ($i=0; $i<20; $i++) {
373
- $rss_secret .= chr(rand(97, 122));
374
- }
375
-
376
- update_option("simple_history_rss_secret", $rss_secret);
377
-
378
- return $rss_secret;
379
- }
380
-
381
- /**
382
- * Output for settings field that show current RSS address
383
- */
384
- public function settingsFieldRss()
385
- {
386
-
387
- $rss_address = $this->getRssAddress();
388
-
389
- echo "<p><code><a href='$rss_address'>$rss_address</a></code></p>";
390
- }
391
-
392
- /**
393
- * Output for settings field that regenerates the RSS adress/secret
394
- */
395
- public function settingsFieldRssRegenerate()
396
- {
397
-
398
- $update_link = esc_url(add_query_arg("", ""));
399
- $update_link = wp_nonce_url($update_link, "simple_history_rss_update_secret", "simple_history_rss_secret_regenerate_nonce");
400
-
401
- echo "<p>";
402
- _e("You can generate a new address for the RSS feed. This is useful if you think that the address has fallen into the wrong hands.", 'simple-history');
403
- echo "</p>";
404
-
405
- echo "<p>";
406
- printf(
407
- '<a class="button" href="%1$s">%2$s</a>',
408
- $update_link, // 1
409
- __('Generate new address', "simple-history") // 2
410
- );
411
-
412
- echo "</p>";
413
- }
414
-
415
- /**
416
- * Get the URL to the RSS feed
417
- *
418
- * @return string URL
419
- */
420
- public function getRssAddress()
421
- {
422
-
423
- $rss_secret = get_option("simple_history_rss_secret");
424
- $rss_address = add_query_arg(
425
- array("simple_history_get_rss" => "1", "rss_secret" => $rss_secret),
426
- get_bloginfo("url") . "/"
427
- );
428
- $rss_address = esc_url($rss_address);
429
- // $rss_address = htmlspecialchars($rss_address, ENT_COMPAT, "UTF-8");
430
-
431
- return $rss_address;
432
- }
433
-
434
- /**
435
- * Content for section intro. Leave it be, even if empty.
436
- * Called from add_sections_setting.
437
- */
438
- public function settingsSectionOutput()
439
- {
440
-
441
- echo "<p>";
442
- _e("Simple History has a RSS feed which you can subscribe to and receive log updates. Make sure you only share the feed with people you trust, since it can contain sensitive or confidential information.", 'simple-history');
443
- echo "</p>";
444
- }
445
  } // end rss class
1
  <?php
2
 
3
  // defined('ABSPATH') or die();
 
4
  /*
5
  Dropin Name: Global RSS Feed
6
  Dropin URI: http://simple-history.com/
10
  /**
11
  * Simple History RSS Feed drop-in
12
  */
13
+ class SimpleHistoryRSSDropin {
14
+
15
+
16
+ public function __construct( $sh ) {
17
+
18
+ $this->sh = $sh;
19
+
20
+ if ( ! function_exists( 'get_editable_roles' ) ) {
21
+ require_once( ABSPATH . '/wp-admin/includes/user.php' );
22
+ }
23
+
24
+ // Check the status of the RSS feed
25
+ $this->isRssEnabled();
26
+
27
+ // Generate a rss secret, if it does not exist
28
+ if ( ! get_option( 'simple_history_rss_secret' ) ) {
29
+ $this->updateRssSecret();
30
+ }
31
+
32
+ add_action( 'init', array( $this, 'checkForRssFeedRequest' ) );
33
+
34
+ // Add settings with prio 11 so it' added after the main Simple History settings
35
+ add_action( 'admin_menu', array( $this, 'addSettings' ), 11 );
36
+ }
37
+
38
+ /**
39
+ * Add settings for the RSS feed
40
+ * + also regenerates the secret if requested
41
+ */
42
+ public function addSettings() {
43
+
44
+ // we register a setting to keep track of the RSS feed status (enabled/disabled)
45
+ register_setting(
46
+ SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP,
47
+ 'simple_history_enable_rss_feed',
48
+ array(
49
+ $this,
50
+ 'public updateRssStatus',
51
+ )
52
+ );
53
+ /**
54
+ * Start new section for RSS feed
55
+ */
56
+ $settings_section_rss_id = 'simple_history_settings_section_rss';
57
+
58
+ add_settings_section(
59
+ $settings_section_rss_id,
60
+ _x( 'RSS feed', 'rss settings headline', 'simple-history' ), // No title __("General", "simple-history"),
61
+ array( $this, 'settingsSectionOutput' ),
62
+ SimpleHistory::SETTINGS_MENU_SLUG // same slug as for options menu page
63
+ );
64
+
65
+ // Enable/Disabled RSS feed
66
+ add_settings_field(
67
+ 'simple_history_enable_rss_feed',
68
+ __( 'Enable', 'simple-history' ),
69
+ array( $this, 'settingsFieldRssEnable' ),
70
+ SimpleHistory::SETTINGS_MENU_SLUG,
71
+ $settings_section_rss_id
72
+ );
73
+
74
+ // if RSS is activated we display other fields
75
+ if ( $this->isRssEnabled() ) {
76
+ // RSS address
77
+ add_settings_field(
78
+ 'simple_history_rss_feed',
79
+ __( 'Address', 'simple-history' ),
80
+ array( $this, 'settingsFieldRss' ),
81
+ SimpleHistory::SETTINGS_MENU_SLUG,
82
+ $settings_section_rss_id
83
+ );
84
+
85
+ // Regnerate address
86
+ add_settings_field(
87
+ 'simple_history_rss_feed_regenerate_secret',
88
+ __( 'Regenerate', 'simple-history' ),
89
+ array( $this, 'settingsFieldRssRegenerate' ),
90
+ SimpleHistory::SETTINGS_MENU_SLUG,
91
+ $settings_section_rss_id
92
+ );
93
+ }
94
+
95
+ // Create new RSS secret
96
+ $create_new_secret = false;
97
+ $create_secret_nonce_name = 'simple_history_rss_secret_regenerate_nonce';
98
+ $createNonceOk = isset( $_GET[ $create_secret_nonce_name ] ) && wp_verify_nonce( $_GET[ $create_secret_nonce_name ], 'simple_history_rss_update_secret' );
99
+
100
+ if ( $createNonceOk ) {
101
+ $create_new_secret = true;
102
+ $this->updateRssSecret();
103
+
104
+ // Add updated-message and store in transient and then redirect
105
+ // This is the way options.php does it.
106
+ $msg = __( 'Created new secret RSS address', 'simple-history' );
107
+ add_settings_error( 'simple_history_rss_feed_regenerate_secret', 'simple_history_rss_feed_regenerate_secret', $msg, 'updated' );
108
+ set_transient( 'settings_errors', get_settings_errors(), 30 );
109
+
110
+ $goback = esc_url_raw( add_query_arg( 'settings-updated', 'true', wp_get_referer() ) );
111
+ wp_redirect( $goback );
112
+ exit;
113
+ }
114
+ } // settings
115
+
116
+ /**
117
+ * Check if RSS feed is enabled or disabled
118
+ */
119
+ public function isRssEnabled() {
120
+
121
+ // User has never used the plugin we disable RSS feed
122
+ if ( get_option( 'simple_history_rss_secret' ) === false && get_option( 'simple_history_enable_rss_feed' ) === false ) {
123
+ // We disable RSS by default, we use 0/1 to prevent fake disabled with bools from functions returning false for unset
124
+ update_option( 'simple_history_enable_rss_feed', '0' );
125
+ } elseif ( get_option( 'simple_history_enable_rss_feed' ) === false ) {
126
+ // User was using the plugin before RSS feed became disabled by default
127
+ // We activate RSS to prevent a "breaking change"
128
+ update_option( 'simple_history_enable_rss_feed', '1' );
129
+ return true;
130
+ } elseif ( get_option( 'simple_history_enable_rss_feed' ) === '1' ) {
131
+ return true;
132
+ }
133
+
134
+ return false;
135
+ }
136
+
137
+ /**
138
+ * Output for settings field that show current RSS address
139
+ */
140
+ public function settingsFieldRssEnable() {
141
+ ?>
142
+ <input value="1" type="checkbox" id="simple_history_enable_rss_feed" name="simple_history_enable_rss_feed" <?php checked( $this->isRssEnabled(), 1 ); ?> />
143
+ <label for="simple_history_enable_rss_feed"><?php _e( 'Enable RSS feed', 'simple-history' ) ?></label>
144
+ <?php
145
+ }
146
+
147
+ /**
148
+ * Sanitize RSS enabled/disabled status on update settings
149
+ */
150
+ public function updateRssStatus( $field ) {
151
+
152
+ if ( $field === '1' ) {
153
+ return '1';
154
+ }
155
+
156
+ return '0';
157
+ }
158
+
159
+
160
+ /**
161
+ * Check if current request is a request for the RSS feed
162
+ */
163
+ public function checkForRssFeedRequest() {
164
+ // check for RSS
165
+ // don't know if this is the right way to do this, but it seems to work!
166
+ if ( isset( $_GET['simple_history_get_rss'] ) ) {
167
+ $this->outputRss();
168
+ exit;
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Modify capability check so all users reading rss feed (logged in or not) can read all loggers
174
+ */
175
+ public function onCanReadSingleLogger( $user_can_read_logger, $logger_instance, $user_id ) {
176
+ $user_can_read_logger = true;
177
+
178
+ return $user_can_read_logger;
179
+ }
180
+
181
+ /**
182
+ * Output RSS
183
+ */
184
+ public function outputRss() {
185
+
186
+ $rss_secret_option = get_option( 'simple_history_rss_secret' );
187
+ $rss_secret_get = isset( $_GET['rss_secret'] ) ? $_GET['rss_secret'] : '';
188
+
189
+ if ( empty( $rss_secret_option ) || empty( $rss_secret_get ) ) {
190
+ die();
191
+ }
192
+
193
+ $rss_show = true;
194
+ $rss_show = apply_filters( 'simple_history/rss_feed_show', $rss_show );
195
+ if ( ! $rss_show || ! $this->isRssEnabled() ) {
196
+ wp_die( 'Nothing here.' );
197
+ }
198
+
199
+ header( 'Content-Type: text/xml; charset=utf-8' );
200
+ echo '<?xml version="1.0" encoding="UTF-8"?>';
201
+ $self_link = $this->getRssAddress();
202
+
203
+ if ( $rss_secret_option === $rss_secret_get ) {
204
+ ?>
205
+ <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
206
+ <channel>
207
+ <title><![CDATA[<?php printf( __( 'History for %s', 'simple-history' ), get_bloginfo( 'name' ) ) ?>]]></title>
208
+ <description><![CDATA[<?php printf( __( 'WordPress History for %s', 'simple-history' ), get_bloginfo( 'name' ) ) ?>]]></description>
209
+ <link><?php echo get_bloginfo( 'url' ) ?></link>
210
+ <atom:link href="<?php echo $self_link; ?>" rel="self" type="application/atom+xml" />
211
+ <?php
212
+
213
+ // Override capability check: if you have a valid rss_secret_key you can read it all
214
+ $action_tag = 'simple_history/loggers_user_can_read/can_read_single_logger';
215
+ add_action( $action_tag, array( $this, 'onCanReadSingleLogger' ), 10, 3 );
216
+
217
+ // Modify header time output so it does not show relative date or time ago-format
218
+ // Because we don't know when a user reads the RSS feed, time ago format may be very inaccurate
219
+ add_action( 'simple_history/header_just_now_max_time', '__return_zero' );
220
+ add_action( 'simple_history/header_time_ago_max_time', '__return_zero' );
221
+
222
+ // Get log rows
223
+ $args = array(
224
+ 'posts_per_page' => 10,
225
+ );
226
+
227
+ $args = apply_filters( 'simple_history/rss_feed_args', $args );
228
+
229
+ $logQuery = new SimpleHistoryLogQuery();
230
+ $queryResults = $logQuery->query( $args );
231
+
232
+ // Remove capability override after query is done
233
+ // remove_action( $action_tag, array($this, "onCanReadSingleLogger") );
234
+ foreach ( $queryResults['log_rows'] as $row ) {
235
+ $header_output = $this->sh->getLogRowHeaderOutput( $row );
236
+ $text_output = $this->sh->getLogRowPlainTextOutput( $row );
237
+ $details_output = $this->sh->getLogRowDetailsOutput( $row );
238
+
239
+ // http://cyber.law.harvard.edu/rss/rss.html#ltguidgtSubelementOfLtitemgt
240
+ // $item_guid = home_url() . "?SimpleHistoryGuid=" . $row->id;
241
+ $item_guid = esc_url( add_query_arg( 'SimpleHistoryGuid', $row->id, home_url() ) );
242
+ $item_link = esc_url( add_query_arg( 'SimpleHistoryGuid', $row->id, home_url() ) );
243
+
244
+ /**
245
+ * Filter the guid/link URL used in RSS feed.
246
+ * Link will be esc_url'ed by simple history, so no need to do that in your filter
247
+ *
248
+ * @since 2.0.23
249
+ *
250
+ * @param string $item_guid link.
251
+ * @param array $row
252
+ */
253
+ $item_link = apply_filters( 'simple_history/rss_item_link', $item_link, $row );
254
+ $item_link = esc_url( $item_link );
255
+
256
+ $item_title = sprintf(
257
+ '%2$s',
258
+ $this->sh->getLogLevelTranslated( $row->level ),
259
+ wp_kses( $text_output, array() )
260
+ );
261
+
262
+ $level_output = sprintf( __( 'Severity level: %1$s' ), $this->sh->getLogLevelTranslated( $row->level ) );
263
+
264
+ ?>
265
+ <item>
266
+ <title><![CDATA[<?php echo $item_title; ?>]]></title>
267
+ <description><![CDATA[
268
+ <p><?php echo $header_output ?></p>
269
+ <p><?php echo $text_output ?></p>
270
+ <div><?php echo $details_output ?></div>
271
+ <p><?php echo $level_output ?></p>
272
+ <?php
273
+ $occasions = $row->subsequentOccasions - 1;
274
+ if ( $occasions ) {
275
+ printf(
276
+ _n( '+%1$s occasion', '+%1$s occasions', $occasions, 'simple-history' ),
277
+ $occasions
278
+ );
279
+ }
280
+ ?>
281
+ ]]></description>
282
+ <?php
283
+ // author must be email to validate, but the field is optional, so we skip it
284
+ /* <author><?php echo $row->initiator ?></author> */
285
+ ?>
286
+ <pubDate><?php echo date( 'D, d M Y H:i:s', strtotime( $row->date ) ) ?> GMT</pubDate>
287
+ <guid isPermaLink="false"><![CDATA[<?php echo $item_guid ?>]]></guid>
288
+ <link><![CDATA[<?php echo $item_link ?>]]></link>
289
+ </item>
290
+ <?php
291
+ /*
 
 
 
 
 
 
 
292
  [0] =&gt; stdClass Object
293
  (
294
  [id] =&gt; 27324
325
 
326
  )
327
  */
328
+ } // End foreach().
329
+
330
+ ?>
331
+ </channel>
332
+ </rss>
333
+ <?php
334
+ } else {
335
+ // RSS secret was not ok
336
+ ?>
337
+ <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
338
+ <channel>
339
+ <title><?php printf( __( 'History for %s', 'simple-history' ), get_bloginfo( 'name' ) ) ?></title>
340
+ <description><?php printf( __( 'WordPress History for %s', 'simple-history' ), get_bloginfo( 'name' ) ) ?></description>
341
+ <link><?php echo home_url() ?></link>
342
+ <item>
343
+ <title><?php _e( 'Wrong RSS secret', 'simple-history' )?></title>
344
+ <description><?php _e( 'Your RSS secret for Simple History RSS feed is wrong. Please see WordPress settings for current link to the RSS feed.', 'simple-history' )?></description>
345
+ <pubDate><?php echo date( 'D, d M Y H:i:s', time() ) ?> GMT</pubDate>
346
+ <guid><?php echo home_url() . '?SimpleHistoryGuid=wrong-secret' ?></guid>
347
+ </item>
348
+ </channel>
349
+ </rss>
350
+ <?php
351
+ }// End if().
352
+ } // rss
353
+
354
+ /**
355
+ * Create a new RSS secret
356
+ *
357
+ * @return string new secret
358
+ */
359
+ public function updateRssSecret() {
360
+
361
+ $rss_secret = '';
362
+
363
+ for ( $i = 0; $i < 20; $i++ ) {
364
+ $rss_secret .= chr( rand( 97, 122 ) );
365
+ }
366
+
367
+ update_option( 'simple_history_rss_secret', $rss_secret );
368
+
369
+ return $rss_secret;
370
+ }
371
+
372
+ /**
373
+ * Output for settings field that show current RSS address
374
+ */
375
+ public function settingsFieldRss() {
376
+
377
+ $rss_address = $this->getRssAddress();
378
+
379
+ echo "<p><code><a href='$rss_address'>$rss_address</a></code></p>";
380
+ }
381
+
382
+ /**
383
+ * Output for settings field that regenerates the RSS adress/secret
384
+ */
385
+ public function settingsFieldRssRegenerate() {
386
+
387
+ $update_link = esc_url( add_query_arg( '', '' ) );
388
+ $update_link = wp_nonce_url( $update_link, 'simple_history_rss_update_secret', 'simple_history_rss_secret_regenerate_nonce' );
389
+
390
+ echo '<p>';
391
+ _e( 'You can generate a new address for the RSS feed. This is useful if you think that the address has fallen into the wrong hands.', 'simple-history' );
392
+ echo '</p>';
393
+
394
+ echo '<p>';
395
+ printf(
396
+ '<a class="button" href="%1$s">%2$s</a>',
397
+ $update_link, // 1
398
+ __( 'Generate new address', 'simple-history' ) // 2
399
+ );
400
+
401
+ echo '</p>';
402
+ }
403
+
404
+ /**
405
+ * Get the URL to the RSS feed
406
+ *
407
+ * @return string URL
408
+ */
409
+ public function getRssAddress() {
410
+
411
+ $rss_secret = get_option( 'simple_history_rss_secret' );
412
+ $rss_address = add_query_arg(
413
+ array(
414
+ 'simple_history_get_rss' => '1',
415
+ 'rss_secret' => $rss_secret,
416
+ ),
417
+ get_bloginfo( 'url' ) . '/'
418
+ );
419
+ $rss_address = esc_url( $rss_address );
420
+ // $rss_address = htmlspecialchars($rss_address, ENT_COMPAT, "UTF-8");
421
+ return $rss_address;
422
+ }
423
+
424
+ /**
425
+ * Content for section intro. Leave it be, even if empty.
426
+ * Called from add_sections_setting.
427
+ */
428
+ public function settingsSectionOutput() {
429
+
430
+ echo '<p>';
431
+ _e( 'Simple History has a RSS feed which you can subscribe to and receive log updates. Make sure you only share the feed with people you trust, since it can contain sensitive or confidential information.', 'simple-history' );
432
+ echo '</p>';
433
+ }
 
 
 
434
  } // end rss class
dropins/SimpleHistorySettingsDebugDropin.php CHANGED
@@ -19,13 +19,12 @@ class SimpleHistorySettingsDebugDropin {
19
 
20
  // How do we register this to the settings array?
21
  $sh->registerSettingsTab( array(
22
- "slug" => "debug",
23
- "name" => __( "Debug", "simple-history" ),
24
- "function" => array( $this, "output" )
25
  ) );
26
 
27
  // add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'on_admin_enqueue_scripts' ) );
28
-
29
  }
30
 
31
  /*
@@ -41,7 +40,7 @@ class SimpleHistorySettingsDebugDropin {
41
 
42
  public function output() {
43
 
44
- include SIMPLE_HISTORY_PATH . "templates/template-settings-tab-debug.php";
45
 
46
  }
47
 
19
 
20
  // How do we register this to the settings array?
21
  $sh->registerSettingsTab( array(
22
+ 'slug' => 'debug',
23
+ 'name' => __( 'Debug', 'simple-history' ),
24
+ 'function' => array( $this, 'output' ),
25
  ) );
26
 
27
  // add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'on_admin_enqueue_scripts' ) );
 
28
  }
29
 
30
  /*
40
 
41
  public function output() {
42
 
43
+ include SIMPLE_HISTORY_PATH . 'templates/template-settings-tab-debug.php';
44
 
45
  }
46
 
dropins/SimpleHistorySettingsLogtestDropin.php CHANGED
@@ -7,10 +7,10 @@ class SimpleHistorySettingsLogtestDropin {
7
  // Simple History instance
8
  private $sh;
9
 
10
- public function __construct($sh) {
11
 
12
  // Since it's not quite done yet, it's for da devs only for now
13
- if ( ! defined("SIMPLE_HISTORY_DEV") || ! SIMPLE_HISTORY_DEV ) {
14
  return;
15
  }
16
 
@@ -18,14 +18,14 @@ class SimpleHistorySettingsLogtestDropin {
18
 
19
  // How do we register this to the settings array?
20
  $sh->registerSettingsTab(array(
21
- "slug" => "testLog",
22
- "name" => __("Test data (debug)", "simple-history"),
23
- "function" => array($this, "output")
24
  ));
25
 
26
- #add_action( 'admin_enqueue_scripts', array( $this, 'on_admin_enqueue_scripts') );
27
- add_action( 'admin_head', array( $this, "on_admin_head" ) );
28
- add_action( 'wp_ajax_SimpleHistoryAddLogTest', array( $this, "on_ajax_add_logtests" ) );
29
 
30
  }
31
 
@@ -34,7 +34,7 @@ class SimpleHistorySettingsLogtestDropin {
34
  $this->doLogTestThings();
35
 
36
  $arr = array(
37
- "message" => "did it!"
38
  );
39
 
40
  wp_send_json_success( $arr );
@@ -102,130 +102,133 @@ class SimpleHistorySettingsLogtestDropin {
102
  public function doLogTestThings() {
103
 
104
  // Add some data random back in time, to fill up the log to test much data
105
- for ($j = 0; $j < 50; $j++) {
106
  // between yesteday and a month back in time
107
- for ($i = 0; $i < rand(1,30); $i++) {
108
- $str_date = date('Y-m-d H:i:s', strtotime("now -{$i}days"));
109
  SimpleLogger()->info(
110
  'Entry with date in the past', array(
111
- "_date" => $str_date,
112
- "_occasionsID" => "past_date:{$str_date}"
113
  ));
114
  }
115
  }
116
 
117
- SimpleLogger()->info("This is a message sent to the log");
118
 
119
  // Second log entry with same info will make these two become an occasionGroup,
120
  // collapsing their entries into one expandable log item
121
- SimpleLogger()->info("This is a message sent to the log");
122
 
123
  // Log entries can be of different severity
124
- SimpleLogger()->info("User admin edited page 'About our company'");
125
- SimpleLogger()->warning("User 'Jessie' deleted user 'Kim'");
126
- SimpleLogger()->debug("Ok, cron job is running!");
127
 
128
  // Log entries can have placeholders and context
129
  // This makes log entried translatable and filterable
130
- for ($i = 0; $i < rand(1, 50); $i++) {
131
  SimpleLogger()->notice(
132
- "User {username} edited page {pagename}",
133
  array(
134
- "username" => "bonnyerden",
135
- "pagename" => "My test page",
136
- "_initiator" => SimpleLoggerLogInitiators::WP_USER,
137
- "_user_id" => rand(1,20),
138
- "_user_login" => "loginname" . rand(1,20),
139
- "_user_email" => "user" . rand(1,20) . "@example.com"
140
  )
141
  );
142
  }
143
- #return;
144
-
145
  // Log entried can have custom occasionsID
146
  // This will group items together and a log entry will only be shown once
147
  // in the log overview
148
- for ($i = 0; $i < rand(1, 50); $i++) {
149
- SimpleLogger()->notice("User {username} edited page {pagename}", array(
150
- "username" => "admin",
151
- "pagename" => "My test page",
152
- "_occasionsID" => "username:1,postID:24884,action:edited"
153
  ));
154
  }
155
 
156
  SimpleLogger()->info(
157
- "WordPress updated itself from version {from_version} to {to_version}",
158
  array(
159
- "from_version" => "3.8",
160
- "to_version" => "3.8.1",
161
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS
162
  )
163
  );
164
 
165
  SimpleLogger()->info(
166
- "Plugin {plugin_name} was updated from version {plugin_from_version} to version {plugin_to_version}",
167
  array(
168
- "plugin_name" => "CMS Tree Page View",
169
- "plugin_from_version" => "4.0",
170
- "plugin_to_version" => "4.2",
171
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS
172
  )
173
  );
174
 
175
  SimpleLogger()->info(
176
- "Updated plugin {plugin_name} from version {plugin_from_version} to version {plugin_to_version}",
177
  array(
178
- "plugin_name" => "Ninja Forms",
179
- "plugin_from_version" => "1.1",
180
- "plugin_to_version" => "1.1.2",
181
- "_initiator" => SimpleLoggerLogInitiators::WP_USER
182
  )
183
  );
184
 
185
  SimpleLogger()->warning("An attempt to login as user 'administrator' failed to login because the wrong password was entered", array(
186
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER
187
  ));
188
 
189
  SimpleLogger()->info(
190
- "Updated plugin {plugin_name} from version {plugin_from_version} to version {plugin_to_version}",
191
  array(
192
- "plugin_name" => "Simple Fields",
193
- "plugin_from_version" => "1.3.7",
194
- "plugin_to_version" => "1.3.8",
195
- "_initiator" => SimpleLoggerLogInitiators::WP_USER
196
  )
197
  );
198
 
199
  SimpleLogger()->error("A JavaScript error was detected on page 'About us'", array(
200
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER
201
  ));
202
 
203
  SimpleLogger()->debug("WP Cron 'my_test_cron_job' finished in 0.012 seconds", array(
204
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS
205
  ));
206
 
207
- for ($i = 0; $i < rand(50,1000); $i++) {
208
  SimpleLogger()->warning(
209
  'An attempt to login as user "{user_login}" failed to login because the wrong password was entered', array(
210
- "user_login" => "admin",
211
- "_userID" => null,
212
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER
213
  ));
214
  }
215
 
216
  // Add more data to context array. Data can be used later on to show detailed info about a log entry.
217
  SimpleLogger()->info("Edited product '{pagename}'", array(
218
- "pagename" => "We are hiring!",
219
- "_postType" => "product",
220
- "_userID" => 1,
221
- "_userLogin" => "jessie",
222
- "_userEmail" => "jessie@example.com",
223
- "_occasionsID" => "username:1,postID:24885,action:edited"
224
  ));
225
 
226
- SimpleLogger()->debug( "This is a message with no translation" );
227
- SimpleLogger()->debug( __("Plugin"), array( "comment" => "This message is 'Plugin' and should contain text domain 'default' since it's a translation that comes with WordPress" ) );
228
- SimpleLogger()->debug( __("Enter title of new page", "cms-tree-page-view"), array("comment" => "A translation used in CMS Tree Page View"));
 
 
 
 
229
 
230
  }
231
 
@@ -288,11 +291,6 @@ add_action("init", function() {
288
 
289
 
290
  // Log testing beloe
291
- #return;
292
- //*
293
-
294
-
295
-
296
-
297
-
298
- //*/
7
  // Simple History instance
8
  private $sh;
9
 
10
+ public function __construct( $sh ) {
11
 
12
  // Since it's not quite done yet, it's for da devs only for now
13
+ if ( ! defined( 'SIMPLE_HISTORY_DEV' ) || ! SIMPLE_HISTORY_DEV ) {
14
  return;
15
  }
16
 
18
 
19
  // How do we register this to the settings array?
20
  $sh->registerSettingsTab(array(
21
+ 'slug' => 'testLog',
22
+ 'name' => __( 'Test data (debug)', 'simple-history' ),
23
+ 'function' => array( $this, 'output' ),
24
  ));
25
 
26
+ // add_action( 'admin_enqueue_scripts', array( $this, 'on_admin_enqueue_scripts') );
27
+ add_action( 'admin_head', array( $this, 'on_admin_head' ) );
28
+ add_action( 'wp_ajax_SimpleHistoryAddLogTest', array( $this, 'on_ajax_add_logtests' ) );
29
 
30
  }
31
 
34
  $this->doLogTestThings();
35
 
36
  $arr = array(
37
+ 'message' => 'did it!',
38
  );
39
 
40
  wp_send_json_success( $arr );
102
  public function doLogTestThings() {
103
 
104
  // Add some data random back in time, to fill up the log to test much data
105
+ for ( $j = 0; $j < 50; $j++ ) {
106
  // between yesteday and a month back in time
107
+ for ( $i = 0; $i < rand( 1,30 ); $i++ ) {
108
+ $str_date = date( 'Y-m-d H:i:s', strtotime( "now -{$i}days" ) );
109
  SimpleLogger()->info(
110
  'Entry with date in the past', array(
111
+ '_date' => $str_date,
112
+ '_occasionsID' => "past_date:{$str_date}",
113
  ));
114
  }
115
  }
116
 
117
+ SimpleLogger()->info( 'This is a message sent to the log' );
118
 
119
  // Second log entry with same info will make these two become an occasionGroup,
120
  // collapsing their entries into one expandable log item
121
+ SimpleLogger()->info( 'This is a message sent to the log' );
122
 
123
  // Log entries can be of different severity
124
+ SimpleLogger()->info( "User admin edited page 'About our company'" );
125
+ SimpleLogger()->warning( "User 'Jessie' deleted user 'Kim'" );
126
+ SimpleLogger()->debug( 'Ok, cron job is running!' );
127
 
128
  // Log entries can have placeholders and context
129
  // This makes log entried translatable and filterable
130
+ for ( $i = 0; $i < rand( 1, 50 ); $i++ ) {
131
  SimpleLogger()->notice(
132
+ 'User {username} edited page {pagename}',
133
  array(
134
+ 'username' => 'bonnyerden',
135
+ 'pagename' => 'My test page',
136
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
137
+ '_user_id' => rand( 1,20 ),
138
+ '_user_login' => 'loginname' . rand( 1,20 ),
139
+ '_user_email' => 'user' . rand( 1,20 ) . '@example.com',
140
  )
141
  );
142
  }
143
+ // return;
 
144
  // Log entried can have custom occasionsID
145
  // This will group items together and a log entry will only be shown once
146
  // in the log overview
147
+ for ( $i = 0; $i < rand( 1, 50 ); $i++ ) {
148
+ SimpleLogger()->notice('User {username} edited page {pagename}', array(
149
+ 'username' => 'admin',
150
+ 'pagename' => 'My test page',
151
+ '_occasionsID' => 'username:1,postID:24884,action:edited',
152
  ));
153
  }
154
 
155
  SimpleLogger()->info(
156
+ 'WordPress updated itself from version {from_version} to {to_version}',
157
  array(
158
+ 'from_version' => '3.8',
159
+ 'to_version' => '3.8.1',
160
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
161
  )
162
  );
163
 
164
  SimpleLogger()->info(
165
+ 'Plugin {plugin_name} was updated from version {plugin_from_version} to version {plugin_to_version}',
166
  array(
167
+ 'plugin_name' => 'CMS Tree Page View',
168
+ 'plugin_from_version' => '4.0',
169
+ 'plugin_to_version' => '4.2',
170
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
171
  )
172
  );
173
 
174
  SimpleLogger()->info(
175
+ 'Updated plugin {plugin_name} from version {plugin_from_version} to version {plugin_to_version}',
176
  array(
177
+ 'plugin_name' => 'Ninja Forms',
178
+ 'plugin_from_version' => '1.1',
179
+ 'plugin_to_version' => '1.1.2',
180
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
181
  )
182
  );
183
 
184
  SimpleLogger()->warning("An attempt to login as user 'administrator' failed to login because the wrong password was entered", array(
185
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
186
  ));
187
 
188
  SimpleLogger()->info(
189
+ 'Updated plugin {plugin_name} from version {plugin_from_version} to version {plugin_to_version}',
190
  array(
191
+ 'plugin_name' => 'Simple Fields',
192
+ 'plugin_from_version' => '1.3.7',
193
+ 'plugin_to_version' => '1.3.8',
194
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
195
  )
196
  );
197
 
198
  SimpleLogger()->error("A JavaScript error was detected on page 'About us'", array(
199
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
200
  ));
201
 
202
  SimpleLogger()->debug("WP Cron 'my_test_cron_job' finished in 0.012 seconds", array(
203
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
204
  ));
205
 
206
+ for ( $i = 0; $i < rand( 50,1000 ); $i++ ) {
207
  SimpleLogger()->warning(
208
  'An attempt to login as user "{user_login}" failed to login because the wrong password was entered', array(
209
+ 'user_login' => 'admin',
210
+ '_userID' => null,
211
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
212
  ));
213
  }
214
 
215
  // Add more data to context array. Data can be used later on to show detailed info about a log entry.
216
  SimpleLogger()->info("Edited product '{pagename}'", array(
217
+ 'pagename' => 'We are hiring!',
218
+ '_postType' => 'product',
219
+ '_userID' => 1,
220
+ '_userLogin' => 'jessie',
221
+ '_userEmail' => 'jessie@example.com',
222
+ '_occasionsID' => 'username:1,postID:24885,action:edited',
223
  ));
224
 
225
+ SimpleLogger()->debug( 'This is a message with no translation' );
226
+ SimpleLogger()->debug( __( 'Plugin' ), array(
227
+ 'comment' => "This message is 'Plugin' and should contain text domain 'default' since it's a translation that comes with WordPress",
228
+ ) );
229
+ SimpleLogger()->debug( __( 'Enter title of new page', 'cms-tree-page-view' ), array(
230
+ 'comment' => 'A translation used in CMS Tree Page View',
231
+ ) );
232
 
233
  }
234
 
291
 
292
 
293
  // Log testing beloe
294
+ // return;
295
+ // *
296
+ // */
 
 
 
 
 
dropins/SimpleHistorySettingsStatsDropin.php CHANGED
@@ -14,10 +14,10 @@ class SimpleHistorySettingsStatsDropin {
14
  // Simple History instance
15
  private $sh;
16
 
17
- public function __construct($sh) {
18
 
19
  // Since it's not quite done yet, it's for da devs only for now
20
- if ( ! defined("SIMPLE_HISTORY_DEV") || ! SIMPLE_HISTORY_DEV ) {
21
  return;
22
  }
23
 
@@ -25,21 +25,21 @@ class SimpleHistorySettingsStatsDropin {
25
 
26
  // How do we register this to the settings array?
27
  $sh->registerSettingsTab(array(
28
- "slug" => "stats",
29
- "name" => __("Stats", "simple-history"),
30
- "function" => array($this, "output")
31
  ));
32
 
33
- add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'on_admin_enqueue_scripts') );
34
 
35
  }
36
 
37
  public function on_admin_enqueue_scripts() {
38
 
39
- $file_url = plugin_dir_url(__FILE__);
40
 
41
- wp_enqueue_script( "google-ajax-api", "https://www.google.com/jsapi");
42
- wp_enqueue_style( "simple_history_SettingsStatsDropin", $file_url . "SimpleHistorySettingsStatsDropin.css", null, SIMPLE_HISTORY_VERSION);
43
 
44
  }
45
 
@@ -49,14 +49,14 @@ class SimpleHistorySettingsStatsDropin {
49
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
50
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
51
 
52
- #$period_days = (int) 28;
53
  $period_days = (int) 14;
54
- $period_start_date = DateTime::createFromFormat('U', strtotime("-$period_days days"));
55
- $period_end_date = DateTime::createFromFormat('U', time());
56
 
57
  // Colors taken from the gogole chart example that was found in this Stack Overflow thread:
58
  // http://stackoverflow.com/questions/236936/how-pick-colors-for-a-pie-chart
59
- $arr_colors = explode(",", "8a56e2,cf56e2,e256ae,e25668,e28956,e2cf56,aee256,68e256,56e289,56e2cf,56aee2,5668e2");
60
 
61
  // Load google charts libraries
62
  ?>
@@ -69,7 +69,7 @@ class SimpleHistorySettingsStatsDropin {
69
  <!-- Overview, larger text -->
70
  <div class='SimpleHistoryStats__intro'>
71
  <?php
72
- include(SIMPLE_HISTORY_PATH . "templates/settings-statsIntro.php");
73
  ?>
74
  </div>
75
 
@@ -78,24 +78,24 @@ class SimpleHistorySettingsStatsDropin {
78
 
79
  <!-- bar chart with rows per day -->
80
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--rowsPerDay'>
81
- <?php include(SIMPLE_HISTORY_PATH . "templates/settings-statsRowsPerDay.php") ?>
82
  </div><!-- // end bar chart rows per day -->
83
 
84
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--loggersPie'>
85
- <?php include(SIMPLE_HISTORY_PATH . "templates/settings-statsLoggers.php") ?>
86
  </div>
87
 
88
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--logLevels'>
89
- <?php include(SIMPLE_HISTORY_PATH . "templates/settings-statsLogLevels.php") ?>
90
  </div>
91
 
92
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--users'>
93
- <?php include(SIMPLE_HISTORY_PATH . "templates/settings-statsUsers.php") ?>
94
  </div>
95
 
96
  <!--
97
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--initiators'>
98
- <?php include(SIMPLE_HISTORY_PATH . "templates/settings-statsInitiators.php") ?>
99
  </div>
100
  -->
101
 
@@ -104,7 +104,7 @@ class SimpleHistorySettingsStatsDropin {
104
 
105
  <?php
106
 
107
- include(SIMPLE_HISTORY_PATH . "templates/settings-statsForGeeks.php");
108
 
109
  }
110
 
14
  // Simple History instance
15
  private $sh;
16
 
17
+ public function __construct( $sh ) {
18
 
19
  // Since it's not quite done yet, it's for da devs only for now
20
+ if ( ! defined( 'SIMPLE_HISTORY_DEV' ) || ! SIMPLE_HISTORY_DEV ) {
21
  return;
22
  }
23
 
25
 
26
  // How do we register this to the settings array?
27
  $sh->registerSettingsTab(array(
28
+ 'slug' => 'stats',
29
+ 'name' => __( 'Stats', 'simple-history' ),
30
+ 'function' => array( $this, 'output' ),
31
  ));
32
 
33
+ add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'on_admin_enqueue_scripts' ) );
34
 
35
  }
36
 
37
  public function on_admin_enqueue_scripts() {
38
 
39
+ $file_url = plugin_dir_url( __FILE__ );
40
 
41
+ wp_enqueue_script( 'google-ajax-api', 'https://www.google.com/jsapi' );
42
+ wp_enqueue_style( 'simple_history_SettingsStatsDropin', $file_url . 'SimpleHistorySettingsStatsDropin.css', null, SIMPLE_HISTORY_VERSION );
43
 
44
  }
45
 
49
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
50
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
51
 
52
+ // $period_days = (int) 28;
53
  $period_days = (int) 14;
54
+ $period_start_date = DateTime::createFromFormat( 'U', strtotime( "-$period_days days" ) );
55
+ $period_end_date = DateTime::createFromFormat( 'U', time() );
56
 
57
  // Colors taken from the gogole chart example that was found in this Stack Overflow thread:
58
  // http://stackoverflow.com/questions/236936/how-pick-colors-for-a-pie-chart
59
+ $arr_colors = explode( ',', '8a56e2,cf56e2,e256ae,e25668,e28956,e2cf56,aee256,68e256,56e289,56e2cf,56aee2,5668e2' );
60
 
61
  // Load google charts libraries
62
  ?>
69
  <!-- Overview, larger text -->
70
  <div class='SimpleHistoryStats__intro'>
71
  <?php
72
+ include( SIMPLE_HISTORY_PATH . 'templates/settings-statsIntro.php' );
73
  ?>
74
  </div>
75
 
78
 
79
  <!-- bar chart with rows per day -->
80
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--rowsPerDay'>
81
+ <?php include( SIMPLE_HISTORY_PATH . 'templates/settings-statsRowsPerDay.php' ) ?>
82
  </div><!-- // end bar chart rows per day -->
83
 
84
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--loggersPie'>
85
+ <?php include( SIMPLE_HISTORY_PATH . 'templates/settings-statsLoggers.php' ) ?>
86
  </div>
87
 
88
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--logLevels'>
89
+ <?php include( SIMPLE_HISTORY_PATH . 'templates/settings-statsLogLevels.php' ) ?>
90
  </div>
91
 
92
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--users'>
93
+ <?php include( SIMPLE_HISTORY_PATH . 'templates/settings-statsUsers.php' ) ?>
94
  </div>
95
 
96
  <!--
97
  <div class='SimpleHistoryStats__graph SimpleHistoryStats__graph--initiators'>
98
+ <?php include( SIMPLE_HISTORY_PATH . 'templates/settings-statsInitiators.php' ) ?>
99
  </div>
100
  -->
101
 
104
 
105
  <?php
106
 
107
+ include( SIMPLE_HISTORY_PATH . 'templates/settings-statsForGeeks.php' );
108
 
109
  }
110
 
dropins/SimpleHistorySidebarDropin.php CHANGED
@@ -13,73 +13,71 @@ class SimpleHistorySidebarDropin {
13
 
14
  private $sh;
15
 
16
- function __construct($sh) {
17
 
18
  $this->sh = $sh;
19
 
20
- add_action("simple_history/enqueue_admin_scripts", array($this, "enqueue_admin_scripts"));
21
- add_action("simple_history/history_page/after_gui", array($this, "output_sidebar_html"));
22
 
23
  // add_action("simple_history/dropin/sidebar/sidebar_html", array($this, "example_output"));
24
-
25
- add_action("simple_history/dropin/sidebar/sidebar_html", array($this, "default_sidebar_contents"));
26
 
27
  }
28
 
29
  public function default_sidebar_contents() {
30
 
31
  // Boxes that will appear randomly
32
-
33
  // Box about GitHub
34
- $headline = _x("Simple History is on GitHub", 'Sidebar box', 'simple-history');
35
-
36
  $body = sprintf(
37
- _x('You can star, fork, or report issues with this plugin over at the <a href="%1$s">GitHub page</a>.', 'Sidebar box', 'simple-history'),
38
- 'https://github.com/bonny/WordPress-Simple-History'
39
- );
40
 
41
  $boxGithub = '
42
  <div class="postbox">
43
- <h3 class="hndle">'.$headline.'</h3>
44
  <div class="inside">
45
- <p>'.$body.'</p>
46
  </div>
47
  </div>
48
  ';
49
 
50
  // Box about donation
51
- $headline = _x('Donate to support development', 'Sidebar box', 'simple-history');
52
 
53
  $body = sprintf(
54
- _x('If you like and use Simple History you should <a href="%1$s">donate to keep this plugin free</a>.', 'Sidebar box', 'simple-history'),
55
- 'http://eskapism.se/sida/donate/'
56
- );
57
-
58
  $boxDonate = '
59
  <div class="postbox">
60
- <h3 class="hndle">'.$headline.'</h3>
61
  <div class="inside">
62
- <p>'.$body.'</p>
63
  </div>
64
  </div>
65
  ';
66
 
67
  // Box about review
68
- $headline = _x('Review this plugin if you like it', 'Sidebar box', 'simple-history');
69
 
70
  $body1 = sprintf(
71
- _x('If you like Simple History then please <a href="%1$s">give it a nice review over at wordpress.org</a>.', 'Sidebar box', 'simple-history'),
72
- 'https://wordpress.org/support/view/plugin-reviews/simple-history'
73
- );
74
 
75
- $body2 = _x('A good review will help new users find this plugin. And it will make the plugin author very happy :)', 'Sidebar box', 'simple-history');
76
 
77
  $boxReview = '
78
  <div class="postbox">
79
- <h3 class="hndle">'.$headline.'</h3>
80
  <div class="inside">
81
- <p>'.$body1.'</p>
82
- <p>'.$body2.'</p>
83
  </div>
84
  </div>
85
  ';
@@ -105,12 +103,11 @@ class SimpleHistorySidebarDropin {
105
  <p><a href="hello@simple-history.com">hello@simple-history.com</a></p>
106
  </div>
107
  </div>
108
- ',
109
- _x("Add more to the log", "Sidebar box", "simple-history"), // 1
110
- _x("Are there things you miss in the history log?", "Sidebar box", "simple-history") // 2
111
  );
112
 
113
-
114
  // Box about support
115
  $boxSupport = sprintf( '
116
  <div class="postbox">
@@ -119,17 +116,16 @@ class SimpleHistorySidebarDropin {
119
  <p>%2$s</p>
120
  </div>
121
  </div>
122
- ',
123
- _x("Support", "Sidebar box", "simple-history"), // 1
124
- sprintf( _x('<a href="%1$s">Visit the support forum</a> if you need help or have questions.', "Sidebar box", "simple-history"), 'https://wordpress.org/support/plugin/simple-history' ) // 2
125
  );
126
 
127
-
128
  $arrBoxes = array(
129
- "boxReview" => $boxReview,
130
- "boxSupport" => $boxSupport,
131
  // "boxMissingEvents" => $boxMissingEvents,
132
- "boxDonate" => $boxDonate,
133
  // "boxGithub" => $boxGithub,
134
  );
135
 
@@ -140,23 +136,22 @@ class SimpleHistorySidebarDropin {
140
  *
141
  * @param array $arrBoxes array with boxes to output. Check the key to determine which box is which.
142
  */
143
- $arrBoxes = apply_filters("simple_history/SidebarDropin/default_sidebar_boxes", $arrBoxes);
144
 
145
- //echo $arrBoxes[array_rand($arrBoxes)];
146
- echo implode("", $arrBoxes); // show all
147
 
148
  // Box to encourage people translate plugin
149
  $current_locale = get_locale();
150
 
151
  /** WordPress Translation Install API. This file exists only since 4.0. */
152
  $translation_install_file = ABSPATH . 'wp-admin/includes/translation-install.php';
153
-
154
- // Show only the translation box if current language is not an english language
155
 
156
- if ( in_array( $current_locale, array("en_US", "en_GB", "en_CA", "en_NZ", "en_AU") ) != $current_locale && file_exists( $translation_install_file ) ) {
 
157
 
158
  require_once $translation_install_file;
159
-
160
  $translations = wp_get_available_translations();
161
 
162
  // This text does not need translation since is's only shown in English
@@ -181,19 +176,17 @@ class SimpleHistorySidebarDropin {
181
  </div>
182
  ';
183
 
184
- if (isset($translations[$current_locale])) {
185
 
186
  // Check if an existing text string returns something else, and that current lang is not en
187
- $teststring_translated = __("Just now", "simple-history");
188
- $teststring_untranslated = "Just now";
189
- if ($teststring_untranslated == $teststring_translated) {
190
  // strings are the same, so plugin probably not translated
191
- printf($boxTranslationTmpl, $translations[$current_locale]["english_name"]);
192
  }
193
-
194
  }
195
-
196
- } // if not en_US + translation install file exists
197
 
198
  }
199
 
@@ -210,9 +203,9 @@ class SimpleHistorySidebarDropin {
210
 
211
  public function enqueue_admin_scripts() {
212
 
213
- $file_url = plugin_dir_url(__FILE__);
214
 
215
- wp_enqueue_style("simple_history_SidebarDropin", $file_url . "SimpleHistorySidebarDropin.css", null, SIMPLE_HISTORY_VERSION);
216
 
217
  }
218
 
@@ -227,7 +220,6 @@ class SimpleHistorySidebarDropin {
227
  * <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Inquit, dasne adolescenti veniam? Non laboro, inquit, de nomine. In quibus doctissimi illi veteres inesse quiddam caeleste et divinum putaverunt. Duo Reges: constructio interrete. Indicant pueri, in quibus ut in speculis natura cernitur. Quod ea non occurrentia fingunt, vincunt Aristonem; Quod quidem iam fit etiam in Academia. Aliter enim nosmet ipsos nosse non possumus.</p>
228
  * </div>
229
  * </div>
230
- *
231
  */
232
  public function output_sidebar_html() {
233
 
@@ -242,7 +234,7 @@ class SimpleHistorySidebarDropin {
242
  *
243
  * @since 2.0.16
244
  */
245
- do_action("simple_history/dropin/sidebar/sidebar_html");
246
  ?>
247
  </div>
248
 
@@ -251,4 +243,4 @@ class SimpleHistorySidebarDropin {
251
 
252
  }
253
 
254
- }// end class
13
 
14
  private $sh;
15
 
16
+ function __construct( $sh ) {
17
 
18
  $this->sh = $sh;
19
 
20
+ add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'enqueue_admin_scripts' ) );
21
+ add_action( 'simple_history/history_page/after_gui', array( $this, 'output_sidebar_html' ) );
22
 
23
  // add_action("simple_history/dropin/sidebar/sidebar_html", array($this, "example_output"));
24
+ add_action( 'simple_history/dropin/sidebar/sidebar_html', array( $this, 'default_sidebar_contents' ) );
 
25
 
26
  }
27
 
28
  public function default_sidebar_contents() {
29
 
30
  // Boxes that will appear randomly
 
31
  // Box about GitHub
32
+ $headline = _x( 'Simple History is on GitHub', 'Sidebar box', 'simple-history' );
33
+
34
  $body = sprintf(
35
+ _x( 'You can star, fork, or report issues with this plugin over at the <a href="%1$s">GitHub page</a>.', 'Sidebar box', 'simple-history' ),
36
+ 'https://github.com/bonny/WordPress-Simple-History'
37
+ );
38
 
39
  $boxGithub = '
40
  <div class="postbox">
41
+ <h3 class="hndle">' . $headline . '</h3>
42
  <div class="inside">
43
+ <p>' . $body . '</p>
44
  </div>
45
  </div>
46
  ';
47
 
48
  // Box about donation
49
+ $headline = _x( 'Donate to support development', 'Sidebar box', 'simple-history' );
50
 
51
  $body = sprintf(
52
+ _x( 'If you like and use Simple History you should <a href="%1$s">donate to keep this plugin free</a>.', 'Sidebar box', 'simple-history' ),
53
+ 'http://eskapism.se/sida/donate/'
54
+ );
55
+
56
  $boxDonate = '
57
  <div class="postbox">
58
+ <h3 class="hndle">' . $headline . '</h3>
59
  <div class="inside">
60
+ <p>' . $body . '</p>
61
  </div>
62
  </div>
63
  ';
64
 
65
  // Box about review
66
+ $headline = _x( 'Review this plugin if you like it', 'Sidebar box', 'simple-history' );
67
 
68
  $body1 = sprintf(
69
+ _x( 'If you like Simple History then please <a href="%1$s">give it a nice review over at wordpress.org</a>.', 'Sidebar box', 'simple-history' ),
70
+ 'https://wordpress.org/support/view/plugin-reviews/simple-history'
71
+ );
72
 
73
+ $body2 = _x( 'A good review will help new users find this plugin. And it will make the plugin author very happy :)', 'Sidebar box', 'simple-history' );
74
 
75
  $boxReview = '
76
  <div class="postbox">
77
+ <h3 class="hndle">' . $headline . '</h3>
78
  <div class="inside">
79
+ <p>' . $body1 . '</p>
80
+ <p>' . $body2 . '</p>
81
  </div>
82
  </div>
83
  ';
103
  <p><a href="hello@simple-history.com">hello@simple-history.com</a></p>
104
  </div>
105
  </div>
106
+ ',
107
+ _x( 'Add more to the log', 'Sidebar box', 'simple-history' ), // 1
108
+ _x( 'Are there things you miss in the history log?', 'Sidebar box', 'simple-history' ) // 2
109
  );
110
 
 
111
  // Box about support
112
  $boxSupport = sprintf( '
113
  <div class="postbox">
116
  <p>%2$s</p>
117
  </div>
118
  </div>
119
+ ',
120
+ _x( 'Support', 'Sidebar box', 'simple-history' ), // 1
121
+ sprintf( _x( '<a href="%1$s">Visit the support forum</a> if you need help or have questions.', 'Sidebar box', 'simple-history' ), 'https://wordpress.org/support/plugin/simple-history' ) // 2
122
  );
123
 
 
124
  $arrBoxes = array(
125
+ 'boxReview' => $boxReview,
126
+ 'boxSupport' => $boxSupport,
127
  // "boxMissingEvents" => $boxMissingEvents,
128
+ 'boxDonate' => $boxDonate,
129
  // "boxGithub" => $boxGithub,
130
  );
131
 
136
  *
137
  * @param array $arrBoxes array with boxes to output. Check the key to determine which box is which.
138
  */
139
+ $arrBoxes = apply_filters( 'simple_history/SidebarDropin/default_sidebar_boxes', $arrBoxes );
140
 
141
+ // echo $arrBoxes[array_rand($arrBoxes)];
142
+ echo implode( '', $arrBoxes ); // show all
143
 
144
  // Box to encourage people translate plugin
145
  $current_locale = get_locale();
146
 
147
  /** WordPress Translation Install API. This file exists only since 4.0. */
148
  $translation_install_file = ABSPATH . 'wp-admin/includes/translation-install.php';
 
 
149
 
150
+ // Show only the translation box if current language is not an english language
151
+ if ( in_array( $current_locale, array( 'en_US', 'en_GB', 'en_CA', 'en_NZ', 'en_AU' ) ) != $current_locale && file_exists( $translation_install_file ) ) {
152
 
153
  require_once $translation_install_file;
154
+
155
  $translations = wp_get_available_translations();
156
 
157
  // This text does not need translation since is's only shown in English
176
  </div>
177
  ';
178
 
179
+ if ( isset( $translations[ $current_locale ] ) ) {
180
 
181
  // Check if an existing text string returns something else, and that current lang is not en
182
+ $teststring_translated = __( 'Just now', 'simple-history' );
183
+ $teststring_untranslated = 'Just now';
184
+ if ( $teststring_untranslated == $teststring_translated ) {
185
  // strings are the same, so plugin probably not translated
186
+ printf( $boxTranslationTmpl, $translations[ $current_locale ]['english_name'] );
187
  }
 
188
  }
189
+ } // End if().
 
190
 
191
  }
192
 
203
 
204
  public function enqueue_admin_scripts() {
205
 
206
+ $file_url = plugin_dir_url( __FILE__ );
207
 
208
+ wp_enqueue_style( 'simple_history_SidebarDropin', $file_url . 'SimpleHistorySidebarDropin.css', null, SIMPLE_HISTORY_VERSION );
209
 
210
  }
211
 
220
  * <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Inquit, dasne adolescenti veniam? Non laboro, inquit, de nomine. In quibus doctissimi illi veteres inesse quiddam caeleste et divinum putaverunt. Duo Reges: constructio interrete. Indicant pueri, in quibus ut in speculis natura cernitur. Quod ea non occurrentia fingunt, vincunt Aristonem; Quod quidem iam fit etiam in Academia. Aliter enim nosmet ipsos nosse non possumus.</p>
221
  * </div>
222
  * </div>
 
223
  */
224
  public function output_sidebar_html() {
225
 
234
  *
235
  * @since 2.0.16
236
  */
237
+ do_action( 'simple_history/dropin/sidebar/sidebar_html' );
238
  ?>
239
  </div>
240
 
243
 
244
  }
245
 
246
+ }//end class
dropins/SimpleHistorySidebarStats.php CHANGED
@@ -22,17 +22,17 @@ class SimpleHistorySidebarStats {
22
 
23
  $this->sh = $sh;
24
 
25
- add_action("simple_history/dropin/sidebar/sidebar_html", array( $this, "on_sidebar_html" ), 5 );
26
 
27
- add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'on_admin_enqueue_scripts') );
28
 
29
- add_action( "simple_history/admin_footer", array($this, "on_admin_footer") );
30
 
31
  }
32
 
33
  public function on_admin_enqueue_scripts() {
34
 
35
- wp_enqueue_script( "simple_history_chart.js", SIMPLE_HISTORY_DIR_URL . "js/Chart.js", array( "jquery" ), SIMPLE_HISTORY_VERSION, true );
36
 
37
  }
38
 
@@ -59,31 +59,31 @@ class SimpleHistorySidebarStats {
59
  var chartDatasetData = JSON.parse( $(".SimpleHistory_SidebarChart_ChartDatasetData").val() );
60
 
61
  var myChart = new Simple_History_Chart(ctx, {
62
- type: 'bar',
63
- data: {
64
- labels: chartLabels,
65
- datasets: [{
66
- data: chartDatasetData,
67
- backgroundColor: "rgb(210,210,210)",
68
- hoverBackgroundColor: "rgb(175,175,175)",
69
- }]
70
- },
71
- options: {
72
- legend: {
73
- display: false
74
- },
75
- scales: {
76
- yAxes: [{
77
- ticks: {
78
- beginAtZero:true
79
- },
80
- }],
81
- xAxes: [{
82
- display: false
83
- }]
84
- },
85
  onClick: clickChart
86
- },
87
  });
88
 
89
 
@@ -147,16 +147,16 @@ class SimpleHistorySidebarStats {
147
  $num_events_per_day_for_period = $this->sh->get_num_events_per_day_last_n_days( $num_days );
148
 
149
  // Period = all dates, so empty ones don't get lost
150
- $period_start_date = DateTime::createFromFormat('U', strtotime("-$num_days days"));
151
- $period_end_date = DateTime::createFromFormat('U', time());
152
- $interval = DateInterval::createFromDateString('1 day');
153
- $period = new DatePeriod($period_start_date, $interval, $period_end_date->add( date_interval_create_from_date_string('1 days') ) );
154
 
155
  ?>
156
 
157
  <div class="postbox">
158
 
159
- <h3 class="hndle"><?php _e("Stats", "simple-history") ?></h3>
160
 
161
  <div class="inside">
162
 
@@ -164,7 +164,7 @@ class SimpleHistorySidebarStats {
164
  <?php
165
 
166
  printf(
167
- __('<b>%1$s events</b> have been logged the last <b>%2$s days</b>.', "simple-history"),
168
  $this->sh->get_num_events_last_n_days( $num_days ),
169
  number_format_i18n( $num_days )
170
  );
@@ -178,7 +178,7 @@ class SimpleHistorySidebarStats {
178
  </div>
179
 
180
  <p class="SimpleHistory_SidebarChart_ChartDescription" style="font-style: italic; color: #777; text-align: center;">
181
- <?php _e("Number of events per day.", "simple-history") ?>
182
  </p>
183
 
184
  <?php
@@ -189,20 +189,22 @@ class SimpleHistorySidebarStats {
189
 
190
  foreach ( $period as $dt ) {
191
 
192
- $datef = _x( 'M j', "stats: date in rows per day chart", "simple-history" );
193
  $str_date = date_i18n( $datef, $dt->getTimestamp() );
194
- $str_date_ymd = date("Y-m-d", $dt->getTimestamp() );
195
 
196
  // Get data for this day, if exist
197
  // Day in object is in format '2014-09-07'
198
- $yearDate = $dt->format( "Y-m-d" );
199
- $day_data = wp_filter_object_list( $num_events_per_day_for_period, array("yearDate" => $yearDate) );
 
 
200
 
201
  $arr_labels[] = $str_date;
202
 
203
  $arr_labels_to_datetime[] = array(
204
- "label" => $str_date,
205
- "date" => $str_date_ymd
206
  );
207
 
208
  if ( $day_data ) {
@@ -213,7 +215,6 @@ class SimpleHistorySidebarStats {
213
  } else {
214
  $arr_dataset_data[] = 0;
215
  }
216
-
217
  }
218
 
219
  ?>
@@ -221,7 +222,7 @@ class SimpleHistorySidebarStats {
221
  <input
222
  type="hidden"
223
  class="SimpleHistory_SidebarChart_ChartLabels"
224
- value="<?php esc_attr_e( json_encode( $arr_labels ) ) ?>"
225
  />
226
 
227
  <input
22
 
23
  $this->sh = $sh;
24
 
25
+ add_action( 'simple_history/dropin/sidebar/sidebar_html', array( $this, 'on_sidebar_html' ), 5 );
26
 
27
+ add_action( 'simple_history/enqueue_admin_scripts', array( $this, 'on_admin_enqueue_scripts' ) );
28
 
29
+ add_action( 'simple_history/admin_footer', array( $this, 'on_admin_footer' ) );
30
 
31
  }
32
 
33
  public function on_admin_enqueue_scripts() {
34
 
35
+ wp_enqueue_script( 'simple_history_chart.js', SIMPLE_HISTORY_DIR_URL . 'js/Chart.js', array( 'jquery' ), SIMPLE_HISTORY_VERSION, true );
36
 
37
  }
38
 
59
  var chartDatasetData = JSON.parse( $(".SimpleHistory_SidebarChart_ChartDatasetData").val() );
60
 
61
  var myChart = new Simple_History_Chart(ctx, {
62
+ type: 'bar',
63
+ data: {
64
+ labels: chartLabels,
65
+ datasets: [{
66
+ data: chartDatasetData,
67
+ backgroundColor: "rgb(210,210,210)",
68
+ hoverBackgroundColor: "rgb(175,175,175)",
69
+ }]
70
+ },
71
+ options: {
72
+ legend: {
73
+ display: false
74
+ },
75
+ scales: {
76
+ yAxes: [{
77
+ ticks: {
78
+ beginAtZero:true
79
+ },
80
+ }],
81
+ xAxes: [{
82
+ display: false
83
+ }]
84
+ },
85
  onClick: clickChart
86
+ },
87
  });
88
 
89
 
147
  $num_events_per_day_for_period = $this->sh->get_num_events_per_day_last_n_days( $num_days );
148
 
149
  // Period = all dates, so empty ones don't get lost
150
+ $period_start_date = DateTime::createFromFormat( 'U', strtotime( "-$num_days days" ) );
151
+ $period_end_date = DateTime::createFromFormat( 'U', time() );
152
+ $interval = DateInterval::createFromDateString( '1 day' );
153
+ $period = new DatePeriod( $period_start_date, $interval, $period_end_date->add( date_interval_create_from_date_string( '1 days' ) ) );
154
 
155
  ?>
156
 
157
  <div class="postbox">
158
 
159
+ <h3 class="hndle"><?php _e( 'Stats', 'simple-history' ) ?></h3>
160
 
161
  <div class="inside">
162
 
164
  <?php
165
 
166
  printf(
167
+ __( '<b>%1$s events</b> have been logged the last <b>%2$s days</b>.', 'simple-history' ),
168
  $this->sh->get_num_events_last_n_days( $num_days ),
169
  number_format_i18n( $num_days )
170
  );
178
  </div>
179
 
180
  <p class="SimpleHistory_SidebarChart_ChartDescription" style="font-style: italic; color: #777; text-align: center;">
181
+ <?php _e( 'Number of events per day.', 'simple-history' ) ?>
182
  </p>
183
 
184
  <?php
189
 
190
  foreach ( $period as $dt ) {
191
 
192
+ $datef = _x( 'M j', 'stats: date in rows per day chart', 'simple-history' );
193
  $str_date = date_i18n( $datef, $dt->getTimestamp() );
194
+ $str_date_ymd = date( 'Y-m-d', $dt->getTimestamp() );
195
 
196
  // Get data for this day, if exist
197
  // Day in object is in format '2014-09-07'
198
+ $yearDate = $dt->format( 'Y-m-d' );
199
+ $day_data = wp_filter_object_list( $num_events_per_day_for_period, array(
200
+ 'yearDate' => $yearDate,
201
+ ) );
202
 
203
  $arr_labels[] = $str_date;
204
 
205
  $arr_labels_to_datetime[] = array(
206
+ 'label' => $str_date,
207
+ 'date' => $str_date_ymd,
208
  );
209
 
210
  if ( $day_data ) {
215
  } else {
216
  $arr_dataset_data[] = 0;
217
  }
 
218
  }
219
 
220
  ?>
222
  <input
223
  type="hidden"
224
  class="SimpleHistory_SidebarChart_ChartLabels"
225
+ value="<?php esc_attr_e( json_encode( $arr_labels ) ) ?>"
226
  />
227
 
228
  <input
dropins/SimpleHistoryWPCLIDropin.php CHANGED
@@ -13,12 +13,11 @@ class SimpleHistoryWPCLIDropin {
13
  // Simple History instance
14
  private $sh;
15
 
16
- function __construct($sh) {
17
 
18
  $this->sh = $sh;
19
- #add_action( 'admin_menu', array($this, 'add_settings'), 50 );
20
- #add_action( 'plugin_row_meta', array($this, 'action_plugin_row_meta'), 10, 2);
21
-
22
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
23
  $this->register_commands();
24
  }
@@ -27,53 +26,52 @@ class SimpleHistoryWPCLIDropin {
27
 
28
  private function register_commands() {
29
  $commandConfigurationOptions = array(
30
- 'shortdesc' => 'Lists the history log',
31
- 'synopsis' => array(
32
- array(
33
- 'type' => 'assoc',
34
- 'name' => 'format',
35
- 'optional' => true,
36
- 'default' => 'table',
37
- 'options' => array( 'table', 'json', 'csv', 'yaml' ),
38
- ),
39
- array(
40
- 'type' => 'assoc',
41
- 'name' => 'count',
42
- 'optional' => true,
43
- 'default' => '10',
44
- ),
45
- ),
46
- 'when' => 'after_wp_load',
47
  );
48
 
49
- WP_CLI::add_command( 'simple-history list', array($this, 'commandList'), $commandConfigurationOptions );
50
  }
51
 
52
  private function getInitiatorTextFromRow( $row ) {
53
- if (! isset( $row->initiator )) {
54
  return false;
55
  }
56
 
57
  $initiator = $row->initiator;
58
  $initiatorText = '';
59
 
60
- switch ($initiator) {
61
- case "wp":
62
  $initiatorText = 'WordPress';
63
  break;
64
- case "wp_cli":
65
  $initiatorText = 'WP-CLI';
66
  break;
67
- case "wp_user":
68
- $user_id = isset($row->context["_user_id"]) ? $row->context["_user_id"] : null;
69
 
70
- if ( $user_id > 0 && $user = get_user_by("id", $user_id) ) {
71
  // User still exists
72
-
73
  // Get user role, as done in user-edit.php
74
- $wp_roles = $GLOBALS["wp_roles"];
75
  $all_roles = (array) $wp_roles->roles;
76
- $user_roles = array_intersect( array_values( (array) $user->roles ), array_keys( (array) $wp_roles->roles ));
77
  $user_role = array_shift( $user_roles );
78
 
79
  $initiatorText = sprintf(
@@ -82,25 +80,25 @@ class SimpleHistoryWPCLIDropin {
82
  $user->user_email // 2
83
  );
84
 
85
- } else if ($user_id > 0) {
86
  // Sender was a user, but user is deleted now
87
  $initiatorText = sprintf(
88
- __('Deleted user (had id %1$s, email %2$s, login %3$s)', "simple-history"),
89
- $context["_user_id"], // 1
90
- $context["_user_email"], // 2
91
- $context["_user_login"] // 3
92
  );
93
- } // if user exists or not
94
  break;
95
- case "web_user":
96
- $initiatorText = __("Anonymous web user", "simple-history");
97
  break;
98
- case "other":
99
- $initiatorText = _x("Other", "Event header output, when initiator is unknown", "simple-history");
100
  break;
101
  default:
102
  $initiatorText = $initiator;
103
- }
104
 
105
  return $initiatorText;
106
  }
@@ -110,20 +108,19 @@ class SimpleHistoryWPCLIDropin {
110
  */
111
  public function commandList( $args, $assoc_args ) {
112
 
113
- if ( ! is_numeric($assoc_args["count"]) ) {
114
- WP_CLI::error( __('Error: parameter "count" must be a number', 'simple-history' ) );
115
  }
116
 
117
- // Override capability check: if you can run wp cli commands you can read all loggers
118
- add_action( 'simple_history/loggers_user_can_read/can_read_single_logger', '__return_true', 10, 3);
119
 
120
  // WP_CLI::log( sprintf( 'Showing %1$d events from Simple History', $assoc_args["count"] ) );
121
-
122
  $query = new SimpleHistoryLogQuery();
123
 
124
  $query_args = array(
125
- "paged" => 1,
126
- "posts_per_page" => $assoc_args["count"]
127
  );
128
 
129
  $events = $query->query( $query_args );
@@ -131,31 +128,30 @@ class SimpleHistoryWPCLIDropin {
131
  // A cleaned version of the events, formatted for wp cli table output
132
  $eventsCleaned = array();
133
 
134
- foreach ($events["log_rows"] as $row) {
135
- $header_output = $this->sh->getLogRowHeaderOutput($row);
136
- $text_output = $this->sh->getLogRowPlainTextOutput($row);
137
- // $details_output = $this->sh->getLogRowDetailsOutput($row);
138
-
139
- $header_output = strip_tags( html_entity_decode( $header_output, ENT_QUOTES, 'UTF-8') );
140
- $header_output = trim(preg_replace('/\s\s+/', ' ', $header_output));
141
-
142
- $text_output = strip_tags( html_entity_decode( $text_output, ENT_QUOTES, 'UTF-8') );
143
-
144
- $eventsCleaned[] = array(
145
- "date" => get_date_from_gmt( $row->date ),
146
- // "initiator" => $row->initiator,
147
- "initiator" => $this->getInitiatorTextFromRow( $row ),
148
- "logger" => $row->logger,
149
- "level" => $row->level,
150
- "who_when" => $header_output,
151
- "description" => $text_output,
152
- "count" => $row->subsequentOccasions,
153
- // "details" => $details_output
154
- );
155
  }
156
 
157
- #print_r($events);
158
- #print_r($eventsCleaned);
159
  /*
160
  [9] => stdClass Object
161
  (
13
  // Simple History instance
14
  private $sh;
15
 
16
+ function __construct( $sh ) {
17
 
18
  $this->sh = $sh;
19
+ // add_action( 'admin_menu', array($this, 'add_settings'), 50 );
20
+ // add_action( 'plugin_row_meta', array($this, 'action_plugin_row_meta'), 10, 2);
 
21
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
22
  $this->register_commands();
23
  }
26
 
27
  private function register_commands() {
28
  $commandConfigurationOptions = array(
29
+ 'shortdesc' => 'Lists the history log',
30
+ 'synopsis' => array(
31
+ array(
32
+ 'type' => 'assoc',
33
+ 'name' => 'format',
34
+ 'optional' => true,
35
+ 'default' => 'table',
36
+ 'options' => array( 'table', 'json', 'csv', 'yaml' ),
37
+ ),
38
+ array(
39
+ 'type' => 'assoc',
40
+ 'name' => 'count',
41
+ 'optional' => true,
42
+ 'default' => '10',
43
+ ),
44
+ ),
45
+ 'when' => 'after_wp_load',
46
  );
47
 
48
+ WP_CLI::add_command( 'simple-history list', array( $this, 'commandList' ), $commandConfigurationOptions );
49
  }
50
 
51
  private function getInitiatorTextFromRow( $row ) {
52
+ if ( ! isset( $row->initiator ) ) {
53
  return false;
54
  }
55
 
56
  $initiator = $row->initiator;
57
  $initiatorText = '';
58
 
59
+ switch ( $initiator ) {
60
+ case 'wp':
61
  $initiatorText = 'WordPress';
62
  break;
63
+ case 'wp_cli':
64
  $initiatorText = 'WP-CLI';
65
  break;
66
+ case 'wp_user':
67
+ $user_id = isset( $row->context['_user_id'] ) ? $row->context['_user_id'] : null;
68
 
69
+ if ( $user_id > 0 && $user = get_user_by( 'id', $user_id ) ) {
70
  // User still exists
 
71
  // Get user role, as done in user-edit.php
72
+ $wp_roles = $GLOBALS['wp_roles'];
73
  $all_roles = (array) $wp_roles->roles;
74
+ $user_roles = array_intersect( array_values( (array) $user->roles ), array_keys( (array) $wp_roles->roles ) );
75
  $user_role = array_shift( $user_roles );
76
 
77
  $initiatorText = sprintf(
80
  $user->user_email // 2
81
  );
82
 
83
+ } elseif ( $user_id > 0 ) {
84
  // Sender was a user, but user is deleted now
85
  $initiatorText = sprintf(
86
+ __( 'Deleted user (had id %1$s, email %2$s, login %3$s)', 'simple-history' ),
87
+ $context['_user_id'], // 1
88
+ $context['_user_email'], // 2
89
+ $context['_user_login'] // 3
90
  );
91
+ } // End if().
92
  break;
93
+ case 'web_user':
94
+ $initiatorText = __( 'Anonymous web user', 'simple-history' );
95
  break;
96
+ case 'other':
97
+ $initiatorText = _x( 'Other', 'Event header output, when initiator is unknown', 'simple-history' );
98
  break;
99
  default:
100
  $initiatorText = $initiator;
101
+ }// End switch().
102
 
103
  return $initiatorText;
104
  }
108
  */
109
  public function commandList( $args, $assoc_args ) {
110
 
111
+ if ( ! is_numeric( $assoc_args['count'] ) ) {
112
+ WP_CLI::error( __( 'Error: parameter "count" must be a number', 'simple-history' ) );
113
  }
114
 
115
+ // Override capability check: if you can run wp cli commands you can read all loggers
116
+ add_action( 'simple_history/loggers_user_can_read/can_read_single_logger', '__return_true', 10, 3 );
117
 
118
  // WP_CLI::log( sprintf( 'Showing %1$d events from Simple History', $assoc_args["count"] ) );
 
119
  $query = new SimpleHistoryLogQuery();
120
 
121
  $query_args = array(
122
+ 'paged' => 1,
123
+ 'posts_per_page' => $assoc_args['count'],
124
  );
125
 
126
  $events = $query->query( $query_args );
128
  // A cleaned version of the events, formatted for wp cli table output
129
  $eventsCleaned = array();
130
 
131
+ foreach ( $events['log_rows'] as $row ) {
132
+ $header_output = $this->sh->getLogRowHeaderOutput( $row );
133
+ $text_output = $this->sh->getLogRowPlainTextOutput( $row );
134
+ // $details_output = $this->sh->getLogRowDetailsOutput($row);
135
+ $header_output = strip_tags( html_entity_decode( $header_output, ENT_QUOTES, 'UTF-8' ) );
136
+ $header_output = trim( preg_replace( '/\s\s+/', ' ', $header_output ) );
137
+
138
+ $text_output = strip_tags( html_entity_decode( $text_output, ENT_QUOTES, 'UTF-8' ) );
139
+
140
+ $eventsCleaned[] = array(
141
+ 'date' => get_date_from_gmt( $row->date ),
142
+ // "initiator" => $row->initiator,
143
+ 'initiator' => $this->getInitiatorTextFromRow( $row ),
144
+ 'logger' => $row->logger,
145
+ 'level' => $row->level,
146
+ 'who_when' => $header_output,
147
+ 'description' => $text_output,
148
+ 'count' => $row->subsequentOccasions,
149
+ // "details" => $details_output
150
+ );
 
151
  }
152
 
153
+ // print_r($events);
154
+ // print_r($eventsCleaned);
155
  /*
156
  [9] => stdClass Object
157
  (
examples/example-dropin.php CHANGED
@@ -11,9 +11,9 @@ exit;
11
 
12
  // We use the function "register_logger" to tell tell SimpleHistory that our custom logger exists.
13
  // We call it from inside the filter "simple_history/add_custom_logger".
14
- add_action("simple_history/add_custom_dropin", function( $simpleHistory ) {
15
 
16
- $simpleHistory->register_dropin("AddSettingsPageTab");
17
 
18
  });
19
 
@@ -23,45 +23,45 @@ add_action("simple_history/add_custom_dropin", function( $simpleHistory ) {
23
  */
24
  class AddSettingsPageTab {
25
 
26
- // This will hold a reference to the simple history instance
27
- private $sh;
28
 
29
- // simple history will pass itself to the constructor
30
- function __construct( $sh ) {
31
 
32
- $this->sh = $sh;
33
 
34
- $this->init();
35
 
36
- }
37
 
38
- function init() {
39
-
40
- add_action( "init", array( $this, "add_settings_tab" ) );
41
 
42
- }
43
 
44
- function add_settings_tab() {
45
 
46
- $this->sh->registerSettingsTab( array(
47
- "slug" => "my_unique_settings_tab_slug",
48
- "name" => __( "Example tab", "simple-history" ),
49
- "function" => array( $this, "settings_tab_output" ),
50
- ) );
51
 
52
- }
 
 
 
 
53
 
54
- function settings_tab_output() {
55
 
56
- ?>
57
 
58
- <h3>Hi there!</h3>
59
 
60
- <p>I'm the output from on settings tab.</p>
61
-
62
- <?php
63
 
64
- }
 
 
 
 
65
 
66
  } // end class
67
 
11
 
12
  // We use the function "register_logger" to tell tell SimpleHistory that our custom logger exists.
13
  // We call it from inside the filter "simple_history/add_custom_logger".
14
+ add_action('simple_history/add_custom_dropin', function( $simpleHistory ) {
15
 
16
+ $simpleHistory->register_dropin( 'AddSettingsPageTab' );
17
 
18
  });
19
 
23
  */
24
  class AddSettingsPageTab {
25
 
26
+ // This will hold a reference to the simple history instance
27
+ private $sh;
28
 
29
+ // simple history will pass itself to the constructor
30
+ function __construct( $sh ) {
31
 
32
+ $this->sh = $sh;
33
 
34
+ $this->init();
35
 
36
+ }
37
 
38
+ function init() {
 
 
39
 
40
+ add_action( 'init', array( $this, 'add_settings_tab' ) );
41
 
42
+ }
43
 
44
+ function add_settings_tab() {
 
 
 
 
45
 
46
+ $this->sh->registerSettingsTab( array(
47
+ 'slug' => 'my_unique_settings_tab_slug',
48
+ 'name' => __( 'Example tab', 'simple-history' ),
49
+ 'function' => array( $this, 'settings_tab_output' ),
50
+ ) );
51
 
52
+ }
53
 
54
+ function settings_tab_output() {
55
 
56
+ ?>
57
 
58
+ <h3>Hi there!</h3>
 
 
59
 
60
+ <p>I'm the output from on settings tab.</p>
61
+
62
+ <?php
63
+
64
+ }
65
 
66
  } // end class
67
 
examples/example-logger.php CHANGED
@@ -11,86 +11,86 @@ exit;
11
 
12
  // We use the function "register_logger" to tell tell SimpleHistory that our custom logger exists.
13
  // We call it from inside the filter "simple_history/add_custom_logger".
14
- add_action("simple_history/add_custom_logger", function($simpleHistory) {
15
 
16
- $simpleHistory->register_logger("FourOhFourLogger");
17
 
18
  });
19
 
20
  // We make sure that the SimpleLogger class exists before trying to extend it.
21
  // This prevents error if the Simple History plugin gets inactivated.
22
- if (class_exists("SimpleLogger")) {
23
 
24
  /**
25
  * This is the class that does the main work!
26
  */
27
- class FourOhFourLogger extends SimpleLogger {
28
-
29
- /**
30
- * The slug is ised to identify this logger in various places.
31
- * We use the name of the class too keep it simple.
32
- */
33
- public $slug = __CLASS__;
34
-
35
- /**
36
- * Return information about this logger.
37
- * Used to show info about the logger at various places.
38
- */
39
- function getInfo() {
40
-
41
- $arr_info = array(
42
- "name" => "404 Logger",
43
- "description" => "Logs access to pages that result in page not found errors (error code 404)",
44
- "capability" => "edit_pages",
45
- "messages" => array(
46
- 'page_not_found' => __('Got a 404-page when trying to visit "{request_uri}"', "simple-history"),
47
- ),
48
- "labels" => array(
49
- "search" => array(
50
- "label" => _x("Pages not found (404 errors)", "User logger: 404", "simple-history"),
51
- "options" => array(
52
- _x("Pages not found", "User logger: 404", "simple-history") => array(
53
- "page_not_found",
54
- ),
55
- ),
56
- ), // end search
57
- ), // end labels
58
- );
59
-
60
- return $arr_info;
61
-
62
- }
63
-
64
- /**
65
- * When Simple History has loaded this logger it automagically
66
- * calls a loaded() function. This is where you add your actions
67
- * and other logger functionality.
68
- */
69
- function loaded() {
70
-
71
- // Call a function when WordPress finds a 404 page
72
- add_action("404_template", array($this, "on_404_template"), 10, 1);
73
-
74
- }
75
-
76
- /**
77
- * Function that is called when WordPress finds a 404 page.
78
- * It collects some info and then it logs a warning message
79
- * to the log.
80
- */
81
- function on_404_template($template) {
82
-
83
- $context = array(
84
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER,
85
- 'request_uri' => isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : "",
86
- 'http_referer' => isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : "",
87
- );
88
-
89
- $this->warningMessage("page_not_found", $context);
90
-
91
- return $template;
92
-
93
- }
94
-
95
- }
96
- }
11
 
12
  // We use the function "register_logger" to tell tell SimpleHistory that our custom logger exists.
13
  // We call it from inside the filter "simple_history/add_custom_logger".
14
+ add_action('simple_history/add_custom_logger', function( $simpleHistory ) {
15
 
16
+ $simpleHistory->register_logger( 'FourOhFourLogger' );
17
 
18
  });
19
 
20
  // We make sure that the SimpleLogger class exists before trying to extend it.
21
  // This prevents error if the Simple History plugin gets inactivated.
22
+ if ( class_exists( 'SimpleLogger' ) ) {
23
 
24
  /**
25
  * This is the class that does the main work!
26
  */
27
+ class FourOhFourLogger extends SimpleLogger {
28
+
29
+ /**
30
+ * The slug is ised to identify this logger in various places.
31
+ * We use the name of the class too keep it simple.
32
+ */
33
+ public $slug = __CLASS__;
34
+
35
+ /**
36
+ * Return information about this logger.
37
+ * Used to show info about the logger at various places.
38
+ */
39
+ function getInfo() {
40
+
41
+ $arr_info = array(
42
+ 'name' => '404 Logger',
43
+ 'description' => 'Logs access to pages that result in page not found errors (error code 404)',
44
+ 'capability' => 'edit_pages',
45
+ 'messages' => array(
46
+ 'page_not_found' => __( 'Got a 404-page when trying to visit "{request_uri}"', 'simple-history' ),
47
+ ),
48
+ 'labels' => array(
49
+ 'search' => array(
50
+ 'label' => _x( 'Pages not found (404 errors)', 'User logger: 404', 'simple-history' ),
51
+ 'options' => array(
52
+ _x( 'Pages not found', 'User logger: 404', 'simple-history' ) => array(
53
+ 'page_not_found',
54
+ ),
55
+ ),
56
+ ), // end search
57
+ ), // end labels
58
+ );
59
+
60
+ return $arr_info;
61
+
62
+ }
63
+
64
+ /**
65
+ * When Simple History has loaded this logger it automagically
66
+ * calls a loaded() function. This is where you add your actions
67
+ * and other logger functionality.
68
+ */
69
+ function loaded() {
70
+
71
+ // Call a function when WordPress finds a 404 page
72
+ add_action( '404_template', array( $this, 'on_404_template' ), 10, 1 );
73
+
74
+ }
75
+
76
+ /**
77
+ * Function that is called when WordPress finds a 404 page.
78
+ * It collects some info and then it logs a warning message
79
+ * to the log.
80
+ */
81
+ function on_404_template( $template ) {
82
+
83
+ $context = array(
84
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
85
+ 'request_uri' => isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '',
86
+ 'http_referer' => isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '',
87
+ );
88
+
89
+ $this->warningMessage( 'page_not_found', $context );
90
+
91
+ return $template;
92
+
93
+ }
94
+
95
+ }
96
+ }// End if().
examples/examples.php CHANGED
@@ -1,30 +1,43 @@
1
  <?php
 
 
 
 
 
2
 
3
- // No external calls allowed
4
  exit;
5
 
6
-
7
  /**
8
  * Misc
9
  */
10
 
11
- // Add $_GET, $_POST, and more info to each logged event
12
- define("SIMPLE_HISTORY_LOG_DEBUG", true);
13
 
14
 
15
  /**
16
  * Some examples of filter usage and so on
17
  */
18
 
19
- // Modify who can read a logger
20
- // Modify the if part to give users access or no access to a logger
 
 
 
 
 
 
 
 
 
21
  add_filter( 'simple_history/loggers_user_can_read/can_read_single_logger', function( $user_can_read_logger, $logger_instance, $user_id ) {
22
 
23
  // in this example user with id 3 gets access to the post logger
24
  // while user with id 8 does not get any access to it
25
- if ( $logger_instance->slug == "SimplePostLogger" && $user_id === 3 ) {
26
  $user_can_read_logger = true;
27
- } else if ( $logger_instance->slug == "SimplePostLogger" && $user_id === 9 ) {
28
  $user_can_read_logger = false;
29
  }
30
 
@@ -34,14 +47,14 @@ add_filter( 'simple_history/loggers_user_can_read/can_read_single_logger', funct
34
 
35
 
36
  // Do not log some post types, for example pages and attachments in this case
37
- add_filter( "simple_history/log/do_log", function( $do_log = null, $level = null, $message = null, $context = null, $logger = null) {
38
 
39
  $post_types_to_not_log = array(
40
- "page",
41
- "attachment"
42
  );
43
 
44
- if ( ( isset($logger->slug) && ($logger->slug === "SimplePostLogger" || $logger->slug === "SimpleMediaLogger") ) && ( isset($context["post_type"]) && in_array($context["post_type"], $post_types_to_not_log ) ) ) {
45
 
46
  $do_log = false;
47
 
@@ -52,23 +65,23 @@ add_filter( "simple_history/log/do_log", function( $do_log = null, $level = null
52
  }, 10, 5);
53
 
54
  // Disable all logging
55
- add_filter( "simple_history/log/do_log", "__return_false" );
56
 
57
  /**
58
  * Example that modifies the parameters sent to the message template
59
  * This example will change the post type from "post" or "page" or similar to "my own page type"
60
  */
61
- add_filter( "simple_history/logger/interpolate/context", function($context, $message, $row) {
62
 
63
- if ( empty( $row ) ) {
64
- return $context;
65
- }
66
 
67
- if ( $row->logger == "SimplePostLogger" && $row->context_message_key == "post_updated" ) {
68
- $context["post_type"] = "my own page type";
69
- }
70
 
71
- return $context;
72
 
73
  }, 10, 3);
74
 
@@ -78,10 +91,10 @@ add_filter( "simple_history/logger/interpolate/context", function($context, $mes
78
  * Change capability required to manage the options page of simple history.
79
  * Default capability is "manage_options"
80
  */
81
- add_filter("simple_history/view_settings_capability", function($capability) {
82
 
83
- $capability = "manage_options";
84
- return $capability;
85
 
86
  });
87
 
@@ -91,10 +104,10 @@ add_filter("simple_history/view_settings_capability", function($capability) {
91
  * Default capability is "edit_pages". Change to for example "manage options"
92
  * to only allow admins to view the history log.
93
  */
94
- add_filter("simple_history/view_history_capability", function($capability) {
95
 
96
- $capability = "manage_options";
97
- return $capability;
98
 
99
  });
100
 
@@ -102,24 +115,24 @@ add_filter("simple_history/view_history_capability", function($capability) {
102
  // Skip adding things to the context table during logging.
103
  // Useful if you don't want to add cool and possible super useful info to your logged events.
104
  // Also nice to have if you want to make sure your database does not grow.
105
- add_filter("simple_history/log_insert_context", function($context, $data) {
106
 
107
- unset($context["_user_id"]);
108
- unset($context["_user_login"]);
109
- unset($context["_user_email"]);
110
- unset($context["server_http_user_agent"]);
111
 
112
  return $context;
113
 
114
  }, 10, 2);
115
 
116
  // Hide some columns from the detailed context view popup window
117
- add_filter("simple_history/log_html_output_details_table/row_keys_to_show", function($logRowKeysToShow, $oneLogRow) {
118
 
119
- $logRowKeysToShow["id"] = false;
120
- $logRowKeysToShow["logger"] = false;
121
- $logRowKeysToShow["level"] = false;
122
- $logRowKeysToShow["message"] = false;
123
 
124
  return $logRowKeysToShow;
125
 
@@ -127,12 +140,12 @@ add_filter("simple_history/log_html_output_details_table/row_keys_to_show", func
127
 
128
 
129
  // Hide some more columns from the detailed context view popup window
130
- add_filter("simple_history/log_html_output_details_table/context_keys_to_show", function($logRowContextKeysToShow, $oneLogRow) {
131
 
132
- $logRowContextKeysToShow["plugin_slug"] = false;
133
- $logRowContextKeysToShow["plugin_name"] = false;
134
- $logRowContextKeysToShow["plugin_title"] = false;
135
- $logRowContextKeysToShow["plugin_description"] = false;
136
 
137
  return $logRowContextKeysToShow;
138
 
@@ -141,14 +154,14 @@ add_filter("simple_history/log_html_output_details_table/context_keys_to_show",
141
 
142
 
143
  // Allow only the users specified in $allowed_users to show the history page, the history widget on the dashboard, or the history settings page
144
- add_filter("simple_history/show_dashboard_page", "function_show_history_dashboard_or_page");
145
- add_filter("simple_history/show_dashboard_widget", "function_show_history_dashboard_or_page");
146
- add_filter("simple_history/show_settings_page", "function_show_history_dashboard_or_page");
147
- function function_show_history_dashboard_or_page($show) {
148
 
149
  $allowed_users = array(
150
- "user1@example.com",
151
- "anotheruser@example.com"
152
  );
153
 
154
  $user = wp_get_current_user();
@@ -163,10 +176,10 @@ function function_show_history_dashboard_or_page($show) {
163
 
164
 
165
  // Skip loading of loggers
166
- add_filter("simple_history/logger/load_logger", function($load_logger, $oneLoggerFile) {
167
 
168
  // Don't load loggers for comments or menus, i.e. don't log changes to comments or to menus
169
- if ( in_array($oneLoggerFile, array("SimpleCommentsLogger", "SimpleMenuLogger")) ) {
170
  $load_logger = false;
171
  }
172
 
@@ -177,10 +190,10 @@ add_filter("simple_history/logger/load_logger", function($load_logger, $oneLogge
177
  /**
178
  * Load only the loggers that are specified in the $do_log_us array
179
  */
180
- add_filter("simple_history/logger/load_logger", function($load_logger, $logger_basename) {
181
 
182
  $load_logger = false;
183
- $do_log_us = array("SimplePostLogger", "SimplePluginLogger", "SimpleLogger");
184
 
185
  if ( in_array( $logger_basename, $do_log_us ) ) {
186
  $load_logger = true;
@@ -192,15 +205,15 @@ add_filter("simple_history/logger/load_logger", function($load_logger, $logger_b
192
 
193
 
194
  // Skip the loading of dropins
195
- add_filter("simple_history/dropin/load_dropin", function($load_dropin, $dropinFileBasename) {
196
 
197
  // Don't load the RSS feed dropin
198
- if ( $dropinFileBasename == "SimpleHistoryRSSDropin" ) {
199
  $load_dropin = false;
200
  }
201
 
202
  // Don't load the dropin that polls for changes
203
- if ( $dropinFileBasename == "SimpleHistoryNewRowsNotifier" ) {
204
  $load_dropin = false;
205
  }
206
 
@@ -210,15 +223,15 @@ add_filter("simple_history/dropin/load_dropin", function($load_dropin, $dropinFi
210
 
211
 
212
  // Don't log failed logins
213
- add_filter("simple_history/simple_logger/log_message_key", function($doLog, $loggerSlug, $messageKey, $SimpleLoggerLogLevelsLevel, $context) {
214
 
215
  // Don't log login attempts to non existing users
216
- if ( "SimpleUserLogger" == $loggerSlug && "user_unknown_login_failed" == $messageKey ) {
217
  $doLog = false;
218
  }
219
 
220
  // Don't log failed logins to existing users
221
- if ( "SimpleUserLogger" == $loggerSlug && "user_login_failed" == $messageKey ) {
222
  $doLog = false;
223
  }
224
 
@@ -227,10 +240,10 @@ add_filter("simple_history/simple_logger/log_message_key", function($doLog, $log
227
  }, 10, 5);
228
 
229
  // Never clear the log (default is 60 days)
230
- add_filter("simple_history/db_purge_days_interval", "__return_zero");
231
 
232
  // Clear items that are older than a 7 days (i.e. keep only the most recent 7 days in the log)
233
- add_filter( "simple_history/db_purge_days_interval", function( $days ) {
234
 
235
  $days = 7;
236
 
@@ -239,64 +252,67 @@ add_filter( "simple_history/db_purge_days_interval", function( $days ) {
239
  } );
240
 
241
  // Don't let anyone - even with the correct secret - view the RSS feed
242
- add_filter("simple_history/rss_feed_show", "__return_false");
243
 
244
  // Skip loading of a dropin completely (in this case the RSS dropin)
245
- add_filter("simple_history/dropin/load_dropin_SimpleHistoryRSSDropin", "__return_false");
246
 
247
  /**
248
  * Example of logging
249
  */
250
 
251
  // This is the easiest and safest way to add messages to the log:
252
- apply_filters("simple_history_log", "This is a logged message");
253
- apply_filters("simple_history_log", "This is a message with some context added", array("isATestMessage" => "yup", "debugRequestData" => $_REQUEST));
254
- apply_filters("simple_history_log", "This is another logged message, with another severity level", null, "debug");
 
 
 
255
 
256
  // Below is the function way of adding things to the log
257
  // Remember to check that the SimpleLogger function exists before trying to log anything,
258
  // or else your site will break if you disable the Simple History plugin
259
  // (Use the apply_filters method above if you want to stay safer!)
260
- if (function_exists("SimpleLogger")) {
261
- SimpleLogger()->info("This is a message added to the log");
262
  }
263
 
264
  // Add a message to the history log
265
- SimpleLogger()->info("This is a message sent to the log");
266
 
267
  // Add log entries with different severities
268
- SimpleLogger()->warning("User 'Jessie' deleted user 'Kim'");
269
- SimpleLogger()->debug("Ok, cron job is running!");
270
 
271
  // Add a message to the history log
272
  // and then add a second log entry with same info and Simple History
273
  // will make these two become an "occasionGroup",
274
  // i.e. collapsing their entries into one expandable log item
275
- SimpleLogger()->info("This is a message sent to the log");
276
- SimpleLogger()->info("This is a message sent to the log");
277
 
278
  // Log entries can have placeholders and context
279
  // This makes log entried translatable and filterable
280
  SimpleLogger()->notice(
281
- "User {username} edited page {pagename}",
282
  array(
283
- "username" => "jessie",
284
- "pagename" => "My test page",
285
- "_initiator" => SimpleLoggerLogInitiators::WP_USER,
286
- "_user_id" => 5,
287
- "_user_login" => "jess",
288
- "_user_email" => "jessie@example.com"
289
  )
290
  );
291
 
292
  // Log entried can have custom occasionsID
293
  // This will group items together and a log entry will only be shown once
294
  // in the log overview, even if the logged messages are different
295
- for ($i = 0; $i < rand(1, 50); $i++) {
296
- SimpleLogger()->notice("User {username} edited page {pagename}", array(
297
- "username" => "example_user_{$i}",
298
- "pagename" => "My test page",
299
- "_occasionsID" => "postID:24884,action:edited"
300
  ));
301
  }
302
 
@@ -304,28 +320,28 @@ for ($i = 0; $i < rand(1, 50); $i++) {
304
  // i.e. who was responsible for the logged event
305
  // Initiator "WORDPRESS" means that WordPress did something on it's own
306
  SimpleLogger()->info(
307
- "WordPress updated itself from version {from_version} to {to_version}",
308
  array(
309
- "from_version" => "3.8",
310
- "to_version" => "3.8.1",
311
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS
312
  )
313
  );
314
 
315
  // Initiator "WP_USER" means that a logged in user did someting
316
  SimpleLogger()->info(
317
- "Updated plugin {plugin_name} from version {plugin_from_version} to version {plugin_to_version}",
318
  array(
319
- "plugin_name" => "Ninja Forms",
320
- "plugin_from_version" => "1.1",
321
- "plugin_to_version" => "1.1.2",
322
- "_initiator" => SimpleLoggerLogInitiators::WP_USER
323
  )
324
  );
325
 
326
  // // Initiator "WEB_USER" means that an unknown internet user did something
327
  SimpleLogger()->warning("An attempt to login as user 'administrator' failed to login because the wrong password was entered", array(
328
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER
329
  ));
330
 
331
 
@@ -333,12 +349,12 @@ SimpleLogger()->warning("An attempt to login as user 'administrator' failed to l
333
  // Data can be used later on to show detailed info about a log entry
334
  // and does not need to be shown on the overview screen
335
  SimpleLogger()->info("Edited product '{pagename}'", array(
336
- "pagename" => "We are hiring!",
337
- "_postType" => "product",
338
- "_userID" => 1,
339
- "_userLogin" => "jessie",
340
- "_userEmail" => "jessie@example.com",
341
- "_occasionsID" => "username:1,postID:24885,action:edited"
342
  ));
343
 
344
 
1
  <?php
2
+ /**
3
+ * Examples on how to customize Simple History.
4
+ *
5
+ * @package SimpleHistory
6
+ */
7
 
8
+ // No external calls allowed.
9
  exit;
10
 
 
11
  /**
12
  * Misc
13
  */
14
 
15
+ // Add $_GET, $_POST, and more info to each logged even.
16
+ define( 'SIMPLE_HISTORY_LOG_DEBUG', true );
17
 
18
 
19
  /**
20
  * Some examples of filter usage and so on
21
  */
22
 
23
+ /**
24
+ * Remove the "Clear log"-button, so a user with admin access can not clear the log
25
+ * and wipe their mischievous behavior from the log.
26
+ */
27
+ add_filter( 'simple_history/user_can_clear_log', function ( $user_can_clear_log ) {
28
+ $user_can_clear_log = false;
29
+ return $user_can_clear_log;
30
+ });
31
+
32
+ // Modify who can read a logger.
33
+ // Modify the if part to give users access or no access to a logger.
34
  add_filter( 'simple_history/loggers_user_can_read/can_read_single_logger', function( $user_can_read_logger, $logger_instance, $user_id ) {
35
 
36
  // in this example user with id 3 gets access to the post logger
37
  // while user with id 8 does not get any access to it
38
+ if ( $logger_instance->slug == 'SimplePostLogger' && $user_id === 3 ) {
39
  $user_can_read_logger = true;
40
+ } elseif ( $logger_instance->slug == 'SimplePostLogger' && $user_id === 9 ) {
41
  $user_can_read_logger = false;
42
  }
43
 
47
 
48
 
49
  // Do not log some post types, for example pages and attachments in this case
50
+ add_filter( 'simple_history/log/do_log', function( $do_log = null, $level = null, $message = null, $context = null, $logger = null ) {
51
 
52
  $post_types_to_not_log = array(
53
+ 'page',
54
+ 'attachment',
55
  );
56
 
57
+ if ( ( isset( $logger->slug ) && ($logger->slug === 'SimplePostLogger' || $logger->slug === 'SimpleMediaLogger') ) && ( isset( $context['post_type'] ) && in_array( $context['post_type'], $post_types_to_not_log ) ) ) {
58
 
59
  $do_log = false;
60
 
65
  }, 10, 5);
66
 
67
  // Disable all logging
68
+ add_filter( 'simple_history/log/do_log', '__return_false' );
69
 
70
  /**
71
  * Example that modifies the parameters sent to the message template
72
  * This example will change the post type from "post" or "page" or similar to "my own page type"
73
  */
74
+ add_filter( 'simple_history/logger/interpolate/context', function( $context, $message, $row ) {
75
 
76
+ if ( empty( $row ) ) {
77
+ return $context;
78
+ }
79
 
80
+ if ( $row->logger == 'SimplePostLogger' && $row->context_message_key == 'post_updated' ) {
81
+ $context['post_type'] = 'my own page type';
82
+ }
83
 
84
+ return $context;
85
 
86
  }, 10, 3);
87
 
91
  * Change capability required to manage the options page of simple history.
92
  * Default capability is "manage_options"
93
  */
94
+ add_filter('simple_history/view_settings_capability', function( $capability ) {
95
 
96
+ $capability = 'manage_options';
97
+ return $capability;
98
 
99
  });
100
 
104
  * Default capability is "edit_pages". Change to for example "manage options"
105
  * to only allow admins to view the history log.
106
  */
107
+ add_filter('simple_history/view_history_capability', function( $capability ) {
108
 
109
+ $capability = 'manage_options';
110
+ return $capability;
111
 
112
  });
113
 
115
  // Skip adding things to the context table during logging.
116
  // Useful if you don't want to add cool and possible super useful info to your logged events.
117
  // Also nice to have if you want to make sure your database does not grow.
118
+ add_filter('simple_history/log_insert_context', function( $context, $data ) {
119
 
120
+ unset( $context['_user_id'] );
121
+ unset( $context['_user_login'] );
122
+ unset( $context['_user_email'] );
123
+ unset( $context['server_http_user_agent'] );
124
 
125
  return $context;
126
 
127
  }, 10, 2);
128
 
129
  // Hide some columns from the detailed context view popup window
130
+ add_filter('simple_history/log_html_output_details_table/row_keys_to_show', function( $logRowKeysToShow, $oneLogRow ) {
131
 
132
+ $logRowKeysToShow['id'] = false;
133
+ $logRowKeysToShow['logger'] = false;
134
+ $logRowKeysToShow['level'] = false;
135
+ $logRowKeysToShow['message'] = false;
136
 
137
  return $logRowKeysToShow;
138
 
140
 
141
 
142
  // Hide some more columns from the detailed context view popup window
143
+ add_filter('simple_history/log_html_output_details_table/context_keys_to_show', function( $logRowContextKeysToShow, $oneLogRow ) {
144
 
145
+ $logRowContextKeysToShow['plugin_slug'] = false;
146
+ $logRowContextKeysToShow['plugin_name'] = false;
147
+ $logRowContextKeysToShow['plugin_title'] = false;
148
+ $logRowContextKeysToShow['plugin_description'] = false;
149
 
150
  return $logRowContextKeysToShow;
151
 
154
 
155
 
156
  // Allow only the users specified in $allowed_users to show the history page, the history widget on the dashboard, or the history settings page
157
+ add_filter( 'simple_history/show_dashboard_page', 'function_show_history_dashboard_or_page' );
158
+ add_filter( 'simple_history/show_dashboard_widget', 'function_show_history_dashboard_or_page' );
159
+ add_filter( 'simple_history/show_settings_page', 'function_show_history_dashboard_or_page' );
160
+ function function_show_history_dashboard_or_page( $show ) {
161
 
162
  $allowed_users = array(
163
+ 'user1@example.com',
164
+ 'anotheruser@example.com',
165
  );
166
 
167
  $user = wp_get_current_user();
176
 
177
 
178
  // Skip loading of loggers
179
+ add_filter('simple_history/logger/load_logger', function( $load_logger, $oneLoggerFile ) {
180
 
181
  // Don't load loggers for comments or menus, i.e. don't log changes to comments or to menus
182
+ if ( in_array( $oneLoggerFile, array( 'SimpleCommentsLogger', 'SimpleMenuLogger' ) ) ) {
183
  $load_logger = false;
184
  }
185
 
190
  /**
191
  * Load only the loggers that are specified in the $do_log_us array
192
  */
193
+ add_filter('simple_history/logger/load_logger', function( $load_logger, $logger_basename ) {
194
 
195
  $load_logger = false;
196
+ $do_log_us = array( 'SimplePostLogger', 'SimplePluginLogger', 'SimpleLogger' );
197
 
198
  if ( in_array( $logger_basename, $do_log_us ) ) {
199
  $load_logger = true;
205
 
206
 
207
  // Skip the loading of dropins
208
+ add_filter('simple_history/dropin/load_dropin', function( $load_dropin, $dropinFileBasename ) {
209
 
210
  // Don't load the RSS feed dropin
211
+ if ( $dropinFileBasename == 'SimpleHistoryRSSDropin' ) {
212
  $load_dropin = false;
213
  }
214
 
215
  // Don't load the dropin that polls for changes
216
+ if ( $dropinFileBasename == 'SimpleHistoryNewRowsNotifier' ) {
217
  $load_dropin = false;
218
  }
219
 
223
 
224
 
225
  // Don't log failed logins
226
+ add_filter('simple_history/simple_logger/log_message_key', function( $doLog, $loggerSlug, $messageKey, $SimpleLoggerLogLevelsLevel, $context ) {
227
 
228
  // Don't log login attempts to non existing users
229
+ if ( 'SimpleUserLogger' == $loggerSlug && 'user_unknown_login_failed' == $messageKey ) {
230
  $doLog = false;
231
  }
232
 
233
  // Don't log failed logins to existing users
234
+ if ( 'SimpleUserLogger' == $loggerSlug && 'user_login_failed' == $messageKey ) {
235
  $doLog = false;
236
  }
237
 
240
  }, 10, 5);
241
 
242
  // Never clear the log (default is 60 days)
243
+ add_filter( 'simple_history/db_purge_days_interval', '__return_zero' );
244
 
245
  // Clear items that are older than a 7 days (i.e. keep only the most recent 7 days in the log)
246
+ add_filter( 'simple_history/db_purge_days_interval', function( $days ) {
247
 
248
  $days = 7;
249
 
252
  } );
253
 
254
  // Don't let anyone - even with the correct secret - view the RSS feed
255
+ add_filter( 'simple_history/rss_feed_show', '__return_false' );
256
 
257
  // Skip loading of a dropin completely (in this case the RSS dropin)
258
+ add_filter( 'simple_history/dropin/load_dropin_SimpleHistoryRSSDropin', '__return_false' );
259
 
260
  /**
261
  * Example of logging
262
  */
263
 
264
  // This is the easiest and safest way to add messages to the log:
265
+ apply_filters( 'simple_history_log', 'This is a logged message' );
266
+ apply_filters( 'simple_history_log', 'This is a message with some context added', array(
267
+ 'isATestMessage' => 'yup',
268
+ 'debugRequestData' => $_REQUEST,
269
+ ) );
270
+ apply_filters( 'simple_history_log', 'This is another logged message, with another severity level', null, 'debug' );
271
 
272
  // Below is the function way of adding things to the log
273
  // Remember to check that the SimpleLogger function exists before trying to log anything,
274
  // or else your site will break if you disable the Simple History plugin
275
  // (Use the apply_filters method above if you want to stay safer!)
276
+ if ( function_exists( 'SimpleLogger' ) ) {
277
+ SimpleLogger()->info( 'This is a message added to the log' );
278
  }
279
 
280
  // Add a message to the history log
281
+ SimpleLogger()->info( 'This is a message sent to the log' );
282
 
283
  // Add log entries with different severities
284
+ SimpleLogger()->warning( "User 'Jessie' deleted user 'Kim'" );
285
+ SimpleLogger()->debug( 'Ok, cron job is running!' );
286
 
287
  // Add a message to the history log
288
  // and then add a second log entry with same info and Simple History
289
  // will make these two become an "occasionGroup",
290
  // i.e. collapsing their entries into one expandable log item
291
+ SimpleLogger()->info( 'This is a message sent to the log' );
292
+ SimpleLogger()->info( 'This is a message sent to the log' );
293
 
294
  // Log entries can have placeholders and context
295
  // This makes log entried translatable and filterable
296
  SimpleLogger()->notice(
297
+ 'User {username} edited page {pagename}',
298
  array(
299
+ 'username' => 'jessie',
300
+ 'pagename' => 'My test page',
301
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
302
+ '_user_id' => 5,
303
+ '_user_login' => 'jess',
304
+ '_user_email' => 'jessie@example.com',
305
  )
306
  );
307
 
308
  // Log entried can have custom occasionsID
309
  // This will group items together and a log entry will only be shown once
310
  // in the log overview, even if the logged messages are different
311
+ for ( $i = 0; $i < rand( 1, 50 ); $i++ ) {
312
+ SimpleLogger()->notice('User {username} edited page {pagename}', array(
313
+ 'username' => "example_user_{$i}",
314
+ 'pagename' => 'My test page',
315
+ '_occasionsID' => 'postID:24884,action:edited',
316
  ));
317
  }
318
 
320
  // i.e. who was responsible for the logged event
321
  // Initiator "WORDPRESS" means that WordPress did something on it's own
322
  SimpleLogger()->info(
323
+ 'WordPress updated itself from version {from_version} to {to_version}',
324
  array(
325
+ 'from_version' => '3.8',
326
+ 'to_version' => '3.8.1',
327
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
328
  )
329
  );
330
 
331
  // Initiator "WP_USER" means that a logged in user did someting
332
  SimpleLogger()->info(
333
+ 'Updated plugin {plugin_name} from version {plugin_from_version} to version {plugin_to_version}',
334
  array(
335
+ 'plugin_name' => 'Ninja Forms',
336
+ 'plugin_from_version' => '1.1',
337
+ 'plugin_to_version' => '1.1.2',
338
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
339
  )
340
  );
341
 
342
  // // Initiator "WEB_USER" means that an unknown internet user did something
343
  SimpleLogger()->warning("An attempt to login as user 'administrator' failed to login because the wrong password was entered", array(
344
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
345
  ));
346
 
347
 
349
  // Data can be used later on to show detailed info about a log entry
350
  // and does not need to be shown on the overview screen
351
  SimpleLogger()->info("Edited product '{pagename}'", array(
352
+ 'pagename' => 'We are hiring!',
353
+ '_postType' => 'product',
354
+ '_userID' => 1,
355
+ '_userLogin' => 'jessie',
356
+ '_userEmail' => 'jessie@example.com',
357
+ '_occasionsID' => 'username:1,postID:24885,action:edited',
358
  ));
359
 
360
 
inc/SimpleHistory.php CHANGED
@@ -7,7 +7,7 @@ defined( 'ABSPATH' ) or die();
7
  */
8
  class SimpleHistory {
9
 
10
- const NAME = "Simple History";
11
 
12
  /**
13
  * For singleton
@@ -57,17 +57,17 @@ class SimpleHistory {
57
  */
58
  private $arr_settings_tabs = array();
59
 
60
- const DBTABLE = "simple_history";
61
- const DBTABLE_CONTEXTS = "simple_history_contexts";
62
 
63
  /** Slug for the settings menu */
64
- const SETTINGS_MENU_SLUG = "simple_history_settings_menu_slug";
65
 
66
- /** Slug for the settings menu */
67
- const SETTINGS_GENERAL_OPTION_GROUP = "simple_history_settings_group";
68
 
69
  /** ID for the general settings section */
70
- const SETTINGS_SECTION_GENERAL_ID = "simple_history_settings_section_general";
71
 
72
  function __construct() {
73
 
@@ -87,7 +87,7 @@ class SimpleHistory {
87
  *
88
  * @param SimpleHistory $SimpleHistory This class.
89
  */
90
- do_action( "simple_history/before_init", $this );
91
 
92
  $this->setup_variables();
93
 
@@ -161,33 +161,33 @@ class SimpleHistory {
161
  *
162
  * @param SimpleHistory $SimpleHistory This class.
163
  */
164
- do_action( "simple_history/after_init", $this );
165
 
166
  // Add some extra info to each logged context when SIMPLE_HISTORY_LOG_DEBUG is set and true
167
- if ( defined( "SIMPLE_HISTORY_LOG_DEBUG" ) && SIMPLE_HISTORY_LOG_DEBUG ) {
168
 
169
- add_filter( "simple_history/log_argument/context", function( $context, $level, $message, $logger ) {
170
 
171
  $sh = SimpleHistory::get_instance();
172
- $context["_debug_get"] = $sh->json_encode( $_GET );
173
- $context["_debug_post"] = $sh->json_encode( $_POST );
174
- $context["_debug_server"] = $sh->json_encode( $_SERVER );
175
- $context["_debug_files"] = $sh->json_encode( $_FILES );
176
- $context["_debug_php_sapi_name"] = php_sapi_name();
177
 
178
  global $argv;
179
- $context["_debug_argv"] = $sh->json_encode( $argv );
180
 
181
  $consts = get_defined_constants( true );
182
- $consts = $consts["user"];
183
- $context["_debug_user_constants"] = $sh->json_encode( $consts );
184
 
185
- $postdata = file_get_contents( "php://input" );
186
- $context["_debug_http_raw_post_data"] = $sh->json_encode( $postdata );
187
 
188
- $context["_debug_wp_debug_backtrace_summary"] = wp_debug_backtrace_summary();
189
- $context["_debug_is_admin"] = json_encode( is_admin() );
190
- $context["_debug_is_doing_cron"] = json_encode( defined('DOING_CRON') && DOING_CRON );
191
 
192
  global $wp_current_filter;
193
  $context['_debug_current_filter_array'] = $wp_current_filter;
@@ -303,23 +303,22 @@ class SimpleHistory {
303
  add_action( 'admin_menu', array( $this, 'add_admin_pages' ) );
304
  add_action( 'admin_menu', array( $this, 'add_settings' ) );
305
 
306
- add_action( 'admin_footer', array( $this, "add_js_templates" ) );
307
 
308
  add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widget' ) );
309
 
310
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
311
 
312
- add_action( 'admin_head', array( $this, "onAdminHead" ) );
313
- add_action( 'admin_footer', array( $this, "onAdminFooter" ) );
314
 
315
- add_action( 'simple_history/history_page/before_gui', array( $this, "output_quick_stats" ) );
316
- add_action( 'simple_history/dashboard/before_gui', array( $this, "output_quick_stats" ) );
317
 
318
  add_action( 'wp_ajax_simple_history_api', array( $this, 'api' ) );
319
 
320
  add_filter( 'plugin_action_links_simple-history/index.php', array( $this, 'plugin_action_links' ), 10, 4 );
321
 
322
-
323
  }
324
 
325
  /**
@@ -338,19 +337,21 @@ class SimpleHistory {
338
  *
339
  * @param bool Add item
340
  */
341
- $add_items = apply_filters( "simple_history/add_admin_bar_network_menu_item", true );
342
 
343
  if ( ! $add_items ) {
344
  return;
345
  }
346
 
347
  // Don't show for logged out users or single site mode.
348
- if ( ! is_user_logged_in() || ! is_multisite() )
349
  return;
 
350
 
351
  // Show only when the user has at least one site, or they're a super admin.
352
- if ( count( $wp_admin_bar->user->blogs ) < 1 && ! is_super_admin() )
353
  return;
 
354
 
355
  // Setting to show as page must be true
356
  if ( ! $this->setting_show_as_page() ) {
@@ -362,9 +363,10 @@ class SimpleHistory {
362
  return;
363
  }
364
 
365
- /* menu_page_url() is defined in the WordPress Plugin Administration API, which is not loaded here by default */
 
366
  /* dito for is_plugin_active() */
367
- require_once(ABSPATH . 'wp-admin/includes/plugin.php');
368
 
369
  foreach ( (array) $wp_admin_bar->user->blogs as $blog ) {
370
 
@@ -372,29 +374,29 @@ class SimpleHistory {
372
 
373
  if ( is_plugin_active( SIMPLE_HISTORY_BASENAME ) ) {
374
 
375
- $menu_id = "simple-history-blog-" . $blog->userblog_id;
376
  $parent_menu_id = 'blog-' . $blog->userblog_id;
377
- $url = admin_url( "index.php?page=simple_history_page" );
378
 
379
  // Each network site is added by WP core with id "blog-1", "blog-2" ... "blog-n"
380
  // https://codex.wordpress.org/Function_Reference/add_node
381
  $args = array(
382
  'id' => $menu_id,
383
  'parent' => $parent_menu_id,
384
- 'title' => _x("View History", "Admin bar network name", "simple-history"),
385
  'href' => $url,
386
  'meta' => array(
387
- 'class' => 'ab-item--simplehistory'
388
- )
389
  );
390
 
391
  $wp_admin_bar->add_node( $args );
392
 
393
- } // if plugin active
394
 
395
  restore_current_blog();
396
 
397
- } // foreach blog
398
 
399
  } // func
400
 
@@ -415,15 +417,16 @@ class SimpleHistory {
415
  *
416
  * @param bool Add item
417
  */
418
- $add_item = apply_filters( "simple_history/add_admin_bar_menu_item", true );
419
 
420
  if ( ! $add_item ) {
421
  return;
422
  }
423
 
424
  // Don't show for logged out users
425
- if ( ! is_user_logged_in() )
426
  return;
 
427
 
428
  // Setting to show as page must be true
429
  if ( ! $this->setting_show_as_page() ) {
@@ -435,22 +438,23 @@ class SimpleHistory {
435
  return;
436
  }
437
 
438
- /* menu_page_url() is defined in the WordPress Plugin Administration API, which is not loaded here by default */
 
439
  /* dito for is_plugin_active() */
440
- require_once(ABSPATH . 'wp-admin/includes/plugin.php');
441
 
442
- $menu_id = "simple-history-view-history";
443
  $parent_menu_id = 'site-name';
444
- $url = admin_url( "index.php?page=simple_history_page" );
445
 
446
  $args = array(
447
  'id' => $menu_id,
448
  'parent' => $parent_menu_id,
449
- 'title' => _x("Simple History", "Admin bar name", "simple-history"),
450
  'href' => $url,
451
  'meta' => array(
452
- 'class' => 'ab-item--simplehistory'
453
- )
454
  );
455
 
456
  $wp_admin_bar->add_node( $args );
@@ -459,6 +463,7 @@ class SimpleHistory {
459
 
460
  /**
461
  * Get singleton intance
 
462
  * @return SimpleHistory instance
463
  */
464
  public static function get_instance() {
@@ -488,10 +493,10 @@ class SimpleHistory {
488
  // global $sh_latest_translations;
489
  $sh_latest_translations = $this->gettextLatestTranslations;
490
 
491
- $sh_latest_translations[$translation] = array(
492
- "translation" => $translation,
493
- "text" => $text,
494
- "domain" => $domain,
495
  );
496
 
497
  $arr_length = sizeof( $sh_latest_translations );
@@ -507,13 +512,13 @@ class SimpleHistory {
507
 
508
  function setup_cron() {
509
 
510
- add_filter( "simple_history/maybe_purge_db", array( $this, "maybe_purge_db" ) );
511
 
512
  if ( ! wp_next_scheduled( 'simple_history/maybe_purge_db' ) ) {
513
  wp_schedule_event( time(), 'daily', 'simple_history/maybe_purge_db' );
514
- //error_log("not scheduled, so do schedule");
515
  } else {
516
- //error_log("is scheduled");
517
  }
518
 
519
  // Remove old schedule (only author dev sites should have it)
@@ -528,23 +533,23 @@ class SimpleHistory {
528
 
529
  // Log that an email has been sent
530
  simple_history_add( array(
531
- "object_type" => "Email",
532
- "object_name" => "Hi there",
533
- "action" => "was sent",
534
  ) );
535
 
536
  // Will show “Plugin your_plugin_name Edited” in the history log
537
- simple_history_add( "action=edited&object_type=plugin&object_name=your_plugin_name" );
538
 
539
  // Will show the history item "Starship USS Enterprise repaired"
540
- simple_history_add( "action=repaired&object_type=Starship&object_name=USS Enterprise" );
541
 
542
  // Log with some extra details about the email
543
  simple_history_add( array(
544
- "object_type" => "Email",
545
- "object_name" => "Hi there",
546
- "action" => "was sent",
547
- "description" => "The database query to generate the email took .3 seconds. This is email number 4 that is sent to this user",
548
  ) );
549
 
550
  }
@@ -553,7 +558,7 @@ class SimpleHistory {
553
 
554
  if ( $this->is_on_our_own_pages() ) {
555
 
556
- do_action( "simple_history/admin_head", $this );
557
 
558
  }
559
 
@@ -563,7 +568,7 @@ class SimpleHistory {
563
 
564
  if ( $this->is_on_our_own_pages() ) {
565
 
566
- do_action( "simple_history/admin_footer", $this );
567
 
568
  }
569
 
@@ -580,8 +585,8 @@ class SimpleHistory {
580
  <script type="text/html" id="tmpl-simple-history-base">
581
 
582
  <div class="SimpleHistory__waitingForFirstLoad">
583
- <img src="<?php echo admin_url( "/images/spinner.gif" );?>" alt="" width="20" height="20">
584
- <?php echo _x( "Loading history...", "Message visible while waiting for log to load from server the first time", "simple-history" )?>
585
  </div>
586
 
587
  <div class="SimpleHistoryLogitemsWrap">
@@ -618,7 +623,7 @@ class SimpleHistory {
618
  href="#">‹</a>
619
  <span class="SimpleHistoryPaginationInput">
620
  <input class="SimpleHistoryPaginationCurrentPage" title="{{ data.strings.currentPage }}" type="text" name="paged" value="{{ data.api_args.paged }}" size="4">
621
- <?php _x( "of", "page n of n", "simple-history" )?>
622
  <span class="total-pages">{{ data.pages_count }}</span>
623
  </span>
624
  <a
@@ -642,7 +647,7 @@ class SimpleHistory {
642
  <div class="SimpleHistory-modal__background"></div>
643
  <div class="SimpleHistory-modal__content">
644
  <div class="SimpleHistory-modal__contentInner">
645
- <img class="SimpleHistory-modal__contentSpinner" src="<?php echo admin_url( "/images/spinner.gif" );?>" alt="">
646
  </div>
647
  <div class="SimpleHistory-modal__contentClose">
648
  <button class="button">✕</button>
@@ -661,7 +666,7 @@ class SimpleHistory {
661
  <div class="SimpleHistoryLogitem__firstcol"></div>
662
  <div class="SimpleHistoryLogitem__secondcol">
663
  <div class="SimpleHistoryLogitem__text">
664
- <?php _e( 'Sorry, but there are too many similar events to show.', "simple-history" ); ?>
665
  <!-- <br>occasionsCount: {{ data.occasionsCount }}
666
  <br>occasionsCountMaxReturn: {{ data.occasionsCountMaxReturn }}
667
  <br>diff: {{ data.occasionsCount - data.occasionsCountMaxReturn }}
@@ -680,12 +685,11 @@ class SimpleHistory {
680
 
681
  // Call plugins so they can add their js
682
  foreach ( $this->instantiatedLoggers as $one_logger ) {
683
- if ( method_exists( $one_logger["instance"], "adminJS" ) ) {
684
- $one_logger["instance"]->adminJS();
685
  }
686
  }
687
-
688
- }
689
 
690
  }
691
 
@@ -695,37 +699,38 @@ class SimpleHistory {
695
  *
696
  * Examples:
697
  * http://playground-root.ep/wp-admin/admin-ajax.php?action=simple_history_api&posts_per_page=5&paged=1&format=html
698
- *
699
  */
700
  public function api() {
701
 
702
  global $wpdb;
703
 
704
  // Fake slow answers
705
- //sleep(2);
706
- //sleep(rand(0,3));
707
  $args = $_GET;
708
- unset( $args["action"] );
709
 
710
  // Type = overview | ...
711
- $type = isset( $_GET["type"] ) ? $_GET["type"] : null;
712
 
713
  if ( empty( $args ) || ! $type ) {
714
 
715
  wp_send_json_error( array(
716
- _x( "Not enough args specified", "API: not enought arguments passed", "simple-history" ),
717
  ) );
718
 
719
  }
720
 
721
  // User must have capability to view the history page
722
  if ( ! current_user_can( $this->get_view_history_capability() ) ) {
723
- wp_send_json_error( array("error" => "CAPABILITY_ERROR") );
 
 
724
  }
725
 
726
- if ( isset( $args["id"] ) ) {
727
- $args["post__in"] = array(
728
- $args["id"],
729
  );
730
  }
731
 
@@ -733,33 +738,32 @@ class SimpleHistory {
733
 
734
  switch ( $type ) {
735
 
736
- case "overview":
737
- case "occasions":
738
- case "single":
739
 
740
  // API use SimpleHistoryLogQuery, so simply pass args on to that
741
  $logQuery = new SimpleHistoryLogQuery();
742
  $data = $logQuery->query( $args );
743
 
744
- $data["api_args"] = $args;
745
 
746
  // Output can be array or HMTL
747
- if ( isset( $args["format"] ) && "html" === $args["format"] ) {
748
 
749
- $data["log_rows_raw"] = array();
750
 
751
- foreach ( $data["log_rows"] as $key => $oneLogRow ) {
752
 
753
  $args = array();
754
- if ( $type == "single" ) {
755
- $args["type"] = "single";
756
  }
757
 
758
- $data["log_rows"][$key] = $this->getLogRowHTMLOutput( $oneLogRow, $args );
759
- $data["num_queries"] = get_num_queries();
760
 
761
  }
762
-
763
  } else {
764
 
765
  // $data["logRows"] = $logRows;
@@ -768,9 +772,9 @@ class SimpleHistory {
768
  break;
769
 
770
  default:
771
- $data[] = "Nah.";
772
 
773
- }
774
 
775
  wp_send_json_success( $data );
776
 
@@ -786,10 +790,10 @@ class SimpleHistory {
786
  if ( isset( $this->doFilterGettext ) && $this->doFilterGettext ) {
787
 
788
  $this->doFilterGettext_currentLogger->messages[] = array(
789
- "untranslated_text" => $untranslated_text,
790
- "translated_text" => $translated_text,
791
- "domain" => $domain,
792
- "context" => null,
793
  );
794
 
795
  }
@@ -806,10 +810,10 @@ class SimpleHistory {
806
  if ( isset( $this->doFilterGettext ) && $this->doFilterGettext ) {
807
 
808
  $this->doFilterGettext_currentLogger->messages[] = array(
809
- "untranslated_text" => $untranslated_text,
810
- "translated_text" => $translated_text,
811
- "domain" => $domain,
812
- "context" => $context,
813
  );
814
 
815
  }
@@ -832,7 +836,7 @@ class SimpleHistory {
832
  // The "plugin_locale" filter is also used in load_plugin_textdomain()
833
  $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
834
  load_textdomain( $domain, WP_LANG_DIR . '/simple-history/' . $domain . '-' . $locale . '.mo' );
835
- load_plugin_textdomain( $domain, FALSE, dirname( $this->plugin_basename ) . '/languages/' );
836
 
837
  }
838
 
@@ -858,9 +862,9 @@ class SimpleHistory {
858
  */
859
  public function get_view_history_capability() {
860
 
861
- $view_history_capability = "edit_pages";
862
- $view_history_capability = apply_filters( "simple_history_view_history_capability", $view_history_capability );
863
- $view_history_capability = apply_filters( "simple_history/view_history_capability", $view_history_capability );
864
 
865
  return $view_history_capability;
866
 
@@ -874,14 +878,25 @@ class SimpleHistory {
874
  */
875
  public function get_view_settings_capability() {
876
 
877
- $view_settings_capability = "manage_options";
878
- $view_settings_capability = apply_filters( "simple_history_view_settings_capability", $view_settings_capability );
879
- $view_settings_capability = apply_filters( "simple_history/view_settings_capability", $view_settings_capability );
880
 
881
  return $view_settings_capability;
882
 
883
  }
884
 
 
 
 
 
 
 
 
 
 
 
 
885
  /**
886
  * Adds default tabs to settings
887
  */
@@ -891,25 +906,25 @@ class SimpleHistory {
891
  $this->arr_settings_tabs = array(
892
 
893
  array(
894
- "slug" => "settings",
895
- "name" => __( "Settings", "simple-history" ),
896
- "function" => array( $this, "settings_output_general" ),
897
  ),
898
 
899
  );
900
 
901
- if ( defined( "SIMPLE_HISTORY_DEV" ) && SIMPLE_HISTORY_DEV ) {
902
 
903
  $arr_dev_tabs = array(
904
  array(
905
- "slug" => "log",
906
- "name" => __( "Log (debug)", "simple-history" ),
907
- "function" => array( $this, "settings_output_log" ),
908
  ),
909
  array(
910
- "slug" => "styles-example",
911
- "name" => __( "Styles example (debug)", "simple-history" ),
912
- "function" => array( $this, "settings_output_styles_example" ),
913
  ),
914
 
915
  );
@@ -954,37 +969,37 @@ class SimpleHistory {
954
  */
955
  public function load_loggers() {
956
 
957
- $loggersDir = SIMPLE_HISTORY_PATH . "loggers/";
958
 
959
  $loggersFiles = array(
960
- $loggersDir . "SimpleCommentsLogger.php",
961
- $loggersDir . "SimpleCoreUpdatesLogger.php",
962
- $loggersDir . "SimpleExportLogger.php",
963
- $loggersDir . "SimpleLegacyLogger.php",
964
- $loggersDir . "SimpleLogger.php",
965
- $loggersDir . "SimpleMediaLogger.php",
966
- $loggersDir . "SimpleMenuLogger.php",
967
- $loggersDir . "SimpleOptionsLogger.php",
968
- $loggersDir . "SimplePluginLogger.php",
969
- $loggersDir . "SimplePostLogger.php",
970
- $loggersDir . "SimpleThemeLogger.php",
971
- $loggersDir . "SimpleUserLogger.php",
972
- $loggersDir . "SimpleCategoriesLogger.php",
973
- $loggersDir . "AvailableUpdatesLogger.php",
974
- $loggersDir . "FileEditsLogger.php",
975
 
976
  // Loggers for third party plugins
977
- $loggersDir . "PluginUserSwitchingLogger.php",
978
- $loggersDir . "PluginEnableMediaReplaceLogger.php",
979
- $loggersDir . "Plugin_UltimateMembers_Logger.php",
980
- $loggersDir . "Plugin_LimitLoginAttempts.php",
981
- $loggersDir . "Plugin_Redirection.php",
982
- $loggersDir . "Plugin_DuplicatePost.php",
983
- );
984
 
985
  // SimpleLogger.php must be loaded first and always since the other loggers extend it
986
  // Include it manually so risk of anyone using filters or similar disables it
987
- include_once $loggersDir . "SimpleLogger.php";
988
 
989
  /**
990
  * Filter the array with absolute paths to logger files to be loaded.
@@ -996,7 +1011,7 @@ class SimpleHistory {
996
  *
997
  * @param array $loggersFiles Array with filenames
998
  */
999
- $loggersFiles = apply_filters( "simple_history/loggers_files", $loggersFiles );
1000
 
1001
  // Array with slug of loggers to instantiate
1002
  // Slug of logger must also be the name of the logger class
@@ -1006,7 +1021,7 @@ class SimpleHistory {
1006
 
1007
  $load_logger = true;
1008
 
1009
- $basename_no_suffix = basename( $oneLoggerFile, ".php" );
1010
 
1011
  /**
1012
  * Filter to completely skip loading of a logger
@@ -1016,7 +1031,7 @@ class SimpleHistory {
1016
  * @param bool if to load the logger. return false to not load it.
1017
  * @param string slug of logger
1018
  */
1019
- $load_logger = apply_filters( "simple_history/logger/load_logger", $load_logger, $basename_no_suffix );
1020
 
1021
  if ( ! $load_logger ) {
1022
  continue;
@@ -1036,7 +1051,7 @@ class SimpleHistory {
1036
  *
1037
  * @param SimpleHistory instance
1038
  */
1039
- do_action( "simple_history/add_custom_logger", $this );
1040
 
1041
  $arrLoggersToInstantiate = array_merge( $arrLoggersToInstantiate, $this->externalLoggers );
1042
 
@@ -1045,16 +1060,16 @@ class SimpleHistory {
1045
  *
1046
  * Array
1047
  * (
1048
- * [0] => SimpleCommentsLogger
1049
- * [1] => SimpleCoreUpdatesLogger
1050
- * ...
1051
- * )
1052
  *
1053
  * @since 2.0
1054
  *
1055
  * @param array $arrLoggersToInstantiate Array with class names
1056
  */
1057
- $arrLoggersToInstantiate = apply_filters( "simple_history/loggers_to_instantiate", $arrLoggersToInstantiate );
1058
 
1059
  // Instantiate each logger
1060
  foreach ( $arrLoggersToInstantiate as $oneLoggerName ) {
@@ -1064,7 +1079,7 @@ class SimpleHistory {
1064
  }
1065
 
1066
  $loggerInstance = new $oneLoggerName( $this );
1067
- if ( ! is_subclass_of( $loggerInstance, "SimpleLogger" ) && ! is_a( $loggerInstance, "SimpleLogger" ) ) {
1068
  continue;
1069
  }
1070
 
@@ -1115,9 +1130,9 @@ class SimpleHistory {
1115
 
1116
  $arr_messages_by_message_key = array();
1117
 
1118
- if ( isset( $loggerInfo["messages"] ) ) {
1119
 
1120
- foreach ( (array) $loggerInfo["messages"] as $message_key => $message_translated ) {
1121
 
1122
  // Find message in array with both translated and non translated strings
1123
  foreach ( $loggerInstance->messages as $one_message_with_translation_info ) {
@@ -1131,27 +1146,25 @@ class SimpleHistory {
1131
  [context] => ...
1132
  )
1133
  */
1134
- if ( $message_translated == $one_message_with_translation_info["translated_text"] ) {
1135
  $arr_messages_by_message_key[ $message_key ] = $one_message_with_translation_info;
1136
  continue;
1137
  }
1138
-
1139
  }
1140
  }
1141
-
1142
  }
1143
 
1144
  $loggerInstance->messages = $arr_messages_by_message_key;
1145
 
1146
  // Add logger to array of loggers
1147
- $this->instantiatedLoggers[$loggerInstance->slug] = array(
1148
- "name" => $loggerInfo["name"],
1149
- "instance" => $loggerInstance,
1150
  );
1151
 
1152
- }
1153
 
1154
- do_action( "simple_history/loggers_loaded" );
1155
 
1156
  }
1157
 
@@ -1161,23 +1174,23 @@ class SimpleHistory {
1161
  */
1162
  public function load_dropins() {
1163
 
1164
- $dropinsDir = SIMPLE_HISTORY_PATH . "dropins/";
1165
 
1166
  $dropinsFiles = array(
1167
- $dropinsDir . "SimpleHistoryPluginPatchesDropin.php",
1168
- $dropinsDir . "SimpleHistoryDonateDropin.php",
1169
- $dropinsDir . "SimpleHistoryExportDropin.php",
1170
- $dropinsDir . "SimpleHistoryFilterDropin.php",
1171
- $dropinsDir . "SimpleHistoryIpInfoDropin.php",
1172
- $dropinsDir . "SimpleHistoryNewRowsNotifier.php",
1173
- $dropinsDir . "SimpleHistoryRSSDropin.php",
1174
- $dropinsDir . "SimpleHistorySettingsLogtestDropin.php",
1175
- $dropinsDir . "SimpleHistorySettingsStatsDropin.php",
1176
- $dropinsDir . "SimpleHistorySettingsDebugDropin.php",
1177
- $dropinsDir . "SimpleHistorySidebarDropin.php",
1178
- $dropinsDir . "SimpleHistorySidebarStats.php",
1179
- $dropinsDir . "SimpleHistorySidebarSettings.php",
1180
- $dropinsDir . "SimpleHistoryWPCLIDropin.php",
1181
  );
1182
 
1183
  /**
@@ -1189,14 +1202,14 @@ class SimpleHistory {
1189
  *
1190
  * @param array $dropinsFiles Array with filenames
1191
  */
1192
- $dropinsFiles = apply_filters( "simple_history/dropins_files", $dropinsFiles );
1193
 
1194
  $arrDropinsToInstantiate = array();
1195
 
1196
  foreach ( $dropinsFiles as $oneDropinFile ) {
1197
 
1198
  // path/path/simplehistory/dropins/SimpleHistoryDonateDropin.php => SimpleHistoryDonateDropin
1199
- $oneDropinFileBasename = basename( $oneDropinFile, ".php" );
1200
 
1201
  $load_dropin = true;
1202
 
@@ -1219,7 +1232,7 @@ class SimpleHistory {
1219
  * @param bool if to load the dropin. return false to not load it.
1220
  * @param string slug of dropin
1221
  */
1222
- $load_dropin = apply_filters( "simple_history/dropin/load_dropin", $load_dropin, $oneDropinFileBasename );
1223
 
1224
  if ( ! $load_dropin ) {
1225
  continue;
@@ -1229,7 +1242,7 @@ class SimpleHistory {
1229
 
1230
  $arrDropinsToInstantiate[] = $oneDropinFileBasename;
1231
 
1232
- }
1233
 
1234
  /**
1235
  * Action that dropins can use to add their custom loggers.
@@ -1239,7 +1252,7 @@ class SimpleHistory {
1239
  *
1240
  * @param array $arrDropinsToInstantiate Array with class names
1241
  */
1242
- do_action( "simple_history/add_custom_dropin", $this );
1243
 
1244
  /**
1245
  * Filter the array with names of dropin to instantiate.
@@ -1248,7 +1261,7 @@ class SimpleHistory {
1248
  *
1249
  * @param array $arrDropinsToInstantiate Array with class names
1250
  */
1251
- $arrDropinsToInstantiate = apply_filters( "simple_history/dropins_to_instantiate", $arrDropinsToInstantiate );
1252
 
1253
  $arrDropinsToInstantiate = array_merge( $arrDropinsToInstantiate, $this->externalDropins );
1254
 
@@ -1259,9 +1272,9 @@ class SimpleHistory {
1259
  continue;
1260
  }
1261
 
1262
- $this->instantiatedDropins[$oneDropinName] = array(
1263
- "name" => $oneDropinName,
1264
- "instance" => new $oneDropinName( $this ),
1265
  );
1266
 
1267
  }
@@ -1276,7 +1289,7 @@ class SimpleHistory {
1276
  */
1277
  function get_pager_size() {
1278
 
1279
- $pager_size = get_option( "simple_history_pager_size", 20 );
1280
 
1281
  /**
1282
  * Filter the pager size setting
@@ -1285,7 +1298,7 @@ class SimpleHistory {
1285
  *
1286
  * @param int $pager_size
1287
  */
1288
- $pager_size = apply_filters( "simple_history/pager_size", $pager_size );
1289
 
1290
  return $pager_size;
1291
 
@@ -1301,7 +1314,7 @@ class SimpleHistory {
1301
  */
1302
  function get_pager_size_dashboard() {
1303
 
1304
- $pager_size = get_option( "simple_history_pager_size_dashboard", 5 );
1305
 
1306
  /**
1307
  * Filter the pager size setting
@@ -1310,7 +1323,7 @@ class SimpleHistory {
1310
  *
1311
  * @param int $pager_size
1312
  */
1313
- $pager_size = apply_filters( "simple_history/pager_size_dashboard", $pager_size );
1314
 
1315
  return $pager_size;
1316
 
@@ -1328,7 +1341,7 @@ class SimpleHistory {
1328
 
1329
  $settings_page_url = menu_page_url( SimpleHistory::SETTINGS_MENU_SLUG, 0 );
1330
 
1331
- $actions[] = "<a href='$settings_page_url'>" . __( "Settings", "simple-history" ) . "</a>";
1332
 
1333
  return $actions;
1334
 
@@ -1350,12 +1363,11 @@ class SimpleHistory {
1350
  *
1351
  * @param bool Show the page or not
1352
  */
1353
- $show_dashboard_widget = apply_filters( "simple_history/show_dashboard_widget", true );
1354
 
1355
  if ( $show_dashboard_widget ) {
1356
- wp_add_dashboard_widget( "simple_history_dashboard_widget", __( "Simple History", 'simple-history' ), array( $this, "dashboard_widget_output" ) );
1357
  }
1358
-
1359
  }
1360
  }
1361
 
@@ -1373,9 +1385,9 @@ class SimpleHistory {
1373
  *
1374
  * @param int $pager_size
1375
  */
1376
- $pager_size = apply_filters( "simple_history/dashboard_pager_size", $pager_size );
1377
 
1378
- do_action( "simple_history/dashboard/before_gui", $this );
1379
 
1380
  ?>
1381
  <div class="SimpleHistoryGui"
@@ -1385,23 +1397,23 @@ class SimpleHistory {
1385
 
1386
  }
1387
 
1388
- function is_on_our_own_pages( $hook = "" ) {
1389
 
1390
  $current_screen = get_current_screen();
1391
 
1392
- if ( $current_screen && $current_screen->base == "settings_page_" . SimpleHistory::SETTINGS_MENU_SLUG ) {
1393
 
1394
  return true;
1395
 
1396
- } else if ( $current_screen && $current_screen->base == "dashboard_page_simple_history_page" ) {
1397
 
1398
  return true;
1399
 
1400
- } else if ( ( $hook == "settings_page_" . SimpleHistory::SETTINGS_MENU_SLUG ) || ( $this->setting_show_on_dashboard() && $hook == "index.php" ) || ( $this->setting_show_as_page() && $hook == "dashboard_page_simple_history_page" ) ) {
1401
 
1402
  return true;
1403
 
1404
- } else if ( $current_screen && $current_screen->base == "dashboard" && $this->setting_show_on_dashboard() ) {
1405
 
1406
  return true;
1407
 
@@ -1421,36 +1433,36 @@ class SimpleHistory {
1421
 
1422
  add_thickbox();
1423
 
1424
- wp_enqueue_style( "simple_history_styles", SIMPLE_HISTORY_DIR_URL . "css/styles.css", false, SIMPLE_HISTORY_VERSION );
1425
- wp_enqueue_script( "simple_history_script", SIMPLE_HISTORY_DIR_URL . "js/scripts.js", array( "jquery", "backbone", "wp-util" ), SIMPLE_HISTORY_VERSION, true );
1426
 
1427
- wp_enqueue_script( "select2", SIMPLE_HISTORY_DIR_URL . "js/select2/select2.min.js", array( "jquery" ) );
1428
- wp_enqueue_style( "select2", SIMPLE_HISTORY_DIR_URL . "js/select2/select2.css" );
1429
 
1430
  // Translations that we use in JavaScript
1431
  wp_localize_script( 'simple_history_script', 'simple_history_script_vars', array(
1432
- 'settingsConfirmClearLog' => __( "Remove all log items?", 'simple-history' ),
1433
  'pagination' => array(
1434
- 'goToTheFirstPage' => __( "Go to the first page", 'simple-history' ),
1435
- 'goToThePrevPage' => __( "Go to the previous page", 'simple-history' ),
1436
- 'goToTheNextPage' => __( "Go to the next page", 'simple-history' ),
1437
- 'goToTheLastPage' => __( "Go to the last page", 'simple-history' ),
1438
- 'currentPage' => __( "Current page", 'simple-history' ),
1439
  ),
1440
- "loadLogAPIError" => __( "Oups, the log could not be loaded right now.", 'simple-history' ),
1441
- "ajaxLoadError" => __( "Hm, the log could not be loaded right now. Perhaps another plugin is giving some errors. Anyway, below is the output I got from the server.", 'simple-history' ),
1442
- "logNoHits" => __( "Your search did not match any history events.", "simple-history" ),
1443
  ) );
1444
 
1445
  // Call plugins adminCSS-method, so they can add their CSS
1446
  foreach ( $this->instantiatedLoggers as $one_logger ) {
1447
- if ( method_exists( $one_logger["instance"], "adminCSS" ) ) {
1448
- $one_logger["instance"]->adminCSS();
1449
  }
1450
  }
1451
 
1452
  // Add timeago.js
1453
- wp_enqueue_script( 'timeago', SIMPLE_HISTORY_DIR_URL . 'js/timeago/jquery.timeago.js', array("jquery"), '1.5.2', true );
1454
 
1455
  // Determine current locale to load timeago locale
1456
  $locale = strtolower( substr( get_locale(), 0, 2 ) );
@@ -1459,20 +1471,18 @@ class SimpleHistory {
1459
 
1460
  // Only enqueue if locale-file exists on file system
1461
  if ( file_exists( sprintf( $locale_dir_path, $locale ) ) ) {
1462
- wp_enqueue_script( 'timeago-locale', sprintf( $locale_url_path, $locale ), array("jquery"), '1.5.2', true );
1463
  } else {
1464
- wp_enqueue_script( 'timeago-locale', sprintf( $locale_url_path, "en" ), array("jquery"), '1.5.2', true );
1465
  }
1466
  // end add timeago
1467
-
1468
  // Load Select2 locale
1469
  $locale_url_path = SIMPLE_HISTORY_DIR_URL . 'js/select2/select2_locale_%s.js';
1470
  $locale_dir_path = SIMPLE_HISTORY_PATH . 'js/select2/select2_locale_%s.js';
1471
  if ( file_exists( sprintf( $locale_dir_path, $locale ) ) ) {
1472
- wp_enqueue_script( 'select2-locale', sprintf( $locale_url_path, $locale ), array("jquery"), '3.5.1', true );
1473
  }
1474
 
1475
-
1476
  /**
1477
  * Fires when the admin scripts have been enqueued.
1478
  * Only fires on any of the pages where Simple History is used
@@ -1481,9 +1491,9 @@ class SimpleHistory {
1481
  *
1482
  * @param SimpleHistory $SimpleHistory This class.
1483
  */
1484
- do_action( "simple_history/enqueue_admin_scripts", $this );
1485
 
1486
- }
1487
 
1488
  }
1489
 
@@ -1499,7 +1509,7 @@ class SimpleHistory {
1499
 
1500
  global $wpdb;
1501
 
1502
- $db_version = get_option( "simple_history_db_version" );
1503
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
1504
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
1505
  $first_install = false;
@@ -1514,11 +1524,11 @@ class SimpleHistory {
1514
 
1515
  // Table creation, used to be in register_activation_hook
1516
  // We change the varchar size to add one num just to force update of encoding. dbdelta didn't see it otherwise.
1517
- $sql = "CREATE TABLE " . $table_name . " (
1518
- id bigint(20) NOT NULL AUTO_INCREMENT,
1519
- date datetime NOT NULL,
1520
- PRIMARY KEY (id)
1521
- ) CHARACTER SET=utf8;";
1522
 
1523
  // Upgrade db / fix utf for varchars
1524
  dbDelta( $sql );
@@ -1530,13 +1540,13 @@ class SimpleHistory {
1530
  $db_version_prev = $db_version;
1531
  $db_version = 1;
1532
 
1533
- update_option( "simple_history_db_version", $db_version );
1534
 
1535
  // We are not 100% sure that this is a first install,
1536
  // but it is at least a very old version that is being updated
1537
  $first_install = true;
1538
 
1539
- } // done pre db ver 1 things
1540
 
1541
  // If db version is 1 then upgrade to 2
1542
  // Version 2 added the action_description column
@@ -1544,11 +1554,10 @@ class SimpleHistory {
1544
 
1545
  // V2 used to add column "action_description"
1546
  // but it's not used any more so don't do i
1547
-
1548
  $db_version_prev = $db_version;
1549
  $db_version = 2;
1550
 
1551
- update_option( "simple_history_db_version", $db_version );
1552
 
1553
  }
1554
 
@@ -1556,21 +1565,21 @@ class SimpleHistory {
1556
  // Each option that is missing a value will make a sql call otherwise = unnecessary
1557
  $arr_options = array(
1558
  array(
1559
- "name" => "simple_history_show_as_page",
1560
- "default_value" => 1,
1561
  ),
1562
  array(
1563
- "name" => "simple_history_show_on_dashboard",
1564
- "default_value" => 1,
1565
  ),
1566
  );
1567
 
1568
  foreach ( $arr_options as $one_option ) {
1569
 
1570
- if ( false === ( $option_value = get_option( $one_option["name"] ) ) ) {
1571
 
1572
  // Value is not set in db, so set it to a default
1573
- update_option( $one_option["name"], $one_option["default_value"] );
1574
 
1575
  }
1576
  }
@@ -1620,7 +1629,7 @@ class SimpleHistory {
1620
 
1621
  $db_version_prev = $db_version;
1622
  $db_version = 3;
1623
- update_option( "simple_history_db_version", $db_version );
1624
 
1625
  // Update possible old items to use SimpleLegacyLogger
1626
  $sql = sprintf( '
@@ -1637,9 +1646,9 @@ class SimpleHistory {
1637
 
1638
  // Say welcome, however loggers are not added this early so we need to
1639
  // use a filter to load it later
1640
- add_action( "simple_history/loggers_loaded", array( $this, "addWelcomeLogMessage" ) );
1641
 
1642
- } // db version 2 » 3
1643
 
1644
  /**
1645
  * If db version = 3
@@ -1655,10 +1664,9 @@ class SimpleHistory {
1655
 
1656
  // If old columns exist = this is an old install, then modify the columns so we still can keep them
1657
  // we want to keep them because user may have logged items that they want to keep
1658
-
1659
  $db_cools = $wpdb->get_col( "DESCRIBE $table_name" );
1660
 
1661
- if ( in_array("action", $db_cools) ) {
1662
 
1663
  $sql = sprintf( '
1664
  ALTER TABLE %1$s
@@ -1678,9 +1686,9 @@ class SimpleHistory {
1678
  $db_version_prev = $db_version;
1679
  $db_version = 4;
1680
 
1681
- update_option( "simple_history_db_version", $db_version );
1682
 
1683
- } // end db version 3 » 4
1684
 
1685
  // Some installs on 2.2.2 got failed installs
1686
  // We detect these by checking for db_version and then running the install stuff again
@@ -1697,7 +1705,7 @@ class SimpleHistory {
1697
 
1698
  }
1699
 
1700
- update_option( "simple_history_db_version", $db_version );
1701
 
1702
  }
1703
 
@@ -1733,53 +1741,52 @@ class SimpleHistory {
1733
  public function addWelcomeLogMessage() {
1734
 
1735
  $db_data_exists = $this->does_database_have_data();
1736
- #$db_data_exists = false;
1737
-
1738
- $pluginLogger = $this->getInstantiatedLoggerBySlug( "SimplePluginLogger" );
1739
  if ( $pluginLogger ) {
1740
 
1741
  // Add plugin installed message
1742
  $context = array(
1743
- "plugin_name" => "Simple History",
1744
- "plugin_description" => "Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.",
1745
- "plugin_url" => "http://simple-history.com",
1746
- "plugin_version" => SIMPLE_HISTORY_VERSION,
1747
- "plugin_author" => "Pär Thernström"
1748
  );
1749
 
1750
- $pluginLogger->infoMessage( "plugin_installed", $context );
1751
 
1752
  // Add plugin activated message
1753
- $context["plugin_slug"] = "simple-history";
1754
- $context["plugin_title"] = '<a href="http://simple-history.com/">Simple History</a>';
1755
 
1756
- $pluginLogger->infoMessage( "plugin_activated", $context );
1757
 
1758
  }
1759
 
1760
  if ( ! $db_data_exists ) {
1761
 
1762
- $welcome_message_1 = "
1763
  Welcome to Simple History!
1764
 
1765
  This is the main history feed. It will contain events that this plugin has logged.
1766
- ";
1767
 
1768
- $welcome_message_2 ="
1769
  Because Simple History was just recently installed, this feed does not contain much events yet. But keep the plugin activated and soon you will see detailed information about page edits, plugin updates, user logins, and much more.
1770
- ";
1771
 
1772
  SimpleLogger()->info(
1773
  $welcome_message_2,
1774
  array(
1775
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS,
1776
  )
1777
  );
1778
 
1779
  SimpleLogger()->info(
1780
  $welcome_message_1,
1781
  array(
1782
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS,
1783
  )
1784
  );
1785
 
@@ -1812,11 +1819,11 @@ Because Simple History was just recently installed, this feed does not contain m
1812
 
1813
  <h1 class="SimpleHistoryPageHeadline">
1814
  <div class="dashicons dashicons-backup SimpleHistoryPageHeadline__icon"></div>
1815
- <?php _e( "Simple History Settings", "simple-history" )?>
1816
  </h1>
1817
 
1818
  <?php
1819
- $active_tab = isset( $_GET["selected-tab"] ) ? $_GET["selected-tab"] : "settings";
1820
  $settings_base_url = menu_page_url( SimpleHistory::SETTINGS_MENU_SLUG, 0 );
1821
  ?>
1822
 
@@ -1824,14 +1831,14 @@ Because Simple History was just recently installed, this feed does not contain m
1824
  <?php
1825
  foreach ( $arr_settings_tabs as $one_tab ) {
1826
 
1827
- $tab_slug = $one_tab["slug"];
1828
 
1829
  printf(
1830
  '<a href="%3$s" class="nav-tab %4$s">%1$s</a>',
1831
- $one_tab["name"], // 1
1832
  $tab_slug, // 2
1833
- esc_url( add_query_arg( "selected-tab", $tab_slug, $settings_base_url ) ), // 3
1834
- $active_tab == $tab_slug ? "nav-tab-active" : ""// 4
1835
  );
1836
 
1837
  }
@@ -1841,19 +1848,21 @@ Because Simple History was just recently installed, this feed does not contain m
1841
  <?php
1842
 
1843
  // Output contents for selected tab
1844
- $arr_active_tab = wp_filter_object_list( $arr_settings_tabs, array( "slug" => $active_tab ) );
 
 
1845
  $arr_active_tab = current( $arr_active_tab );
1846
 
1847
  // We must have found an active tab and it must have a callable function
1848
- if ( ! $arr_active_tab || ! is_callable( $arr_active_tab["function"] ) ) {
1849
- wp_die( __( "No valid callback found", "simple-history" ) );
1850
  }
1851
 
1852
  $args = array(
1853
- "arr_active_tab" => $arr_active_tab,
1854
  );
1855
 
1856
- call_user_func_array( $arr_active_tab["function"], $args );
1857
 
1858
  ?>
1859
 
@@ -1864,19 +1873,19 @@ Because Simple History was just recently installed, this feed does not contain m
1864
 
1865
  public function settings_output_log() {
1866
 
1867
- include SIMPLE_HISTORY_PATH . "templates/settings-log.php";
1868
 
1869
  }
1870
 
1871
  public function settings_output_general() {
1872
 
1873
- include SIMPLE_HISTORY_PATH . "templates/settings-general.php";
1874
 
1875
  }
1876
 
1877
  public function settings_output_styles_example() {
1878
 
1879
- include SIMPLE_HISTORY_PATH . "templates/settings-style-example.php";
1880
 
1881
  }
1882
 
@@ -1903,32 +1912,31 @@ Because Simple History was just recently installed, this feed does not contain m
1903
  *
1904
  * @param bool Show the page or not
1905
  */
1906
- $show_dashboard_page = apply_filters( "simple_history/show_dashboard_page", true );
1907
 
1908
  if ( $show_dashboard_page ) {
1909
 
1910
  add_dashboard_page(
1911
- _x( "Simple History", 'dashboard title name', 'simple-history' ),
1912
- _x( "Simple History", 'dashboard menu name', 'simple-history' ),
1913
  $this->get_view_history_capability(),
1914
- "simple_history_page",
1915
- array( $this, "history_page_output" )
1916
  );
1917
 
1918
  }
1919
-
1920
  }
1921
 
1922
  // Add a settings page
1923
  $show_settings_page = true;
1924
- $show_settings_page = apply_filters( "simple_history_show_settings_page", $show_settings_page );
1925
- $show_settings_page = apply_filters( "simple_history/show_settings_page", $show_settings_page );
1926
 
1927
  if ( $show_settings_page ) {
1928
 
1929
  add_options_page(
1930
- __( 'Simple History Settings', "simple-history" ),
1931
- _x( 'Simple History', "Options page menu title", "simple-history" ),
1932
  $this->get_view_settings_capability(),
1933
  SimpleHistory::SETTINGS_MENU_SLUG,
1934
  array( $this, 'settings_page_output' )
@@ -1938,87 +1946,91 @@ Because Simple History was just recently installed, this feed does not contain m
1938
 
1939
  }
1940
 
1941
- /*
1942
  * Add setting sections and settings for the settings page
1943
  * Also maybe save some settings before outputing them
1944
  */
1945
  function add_settings() {
1946
 
1947
- // Clear the log if clear button was clicked in settings
1948
- if ( isset( $_GET["simple_history_clear_log_nonce"] ) && wp_verify_nonce( $_GET["simple_history_clear_log_nonce"], 'simple_history_clear_log' ) ) {
 
 
 
 
 
 
 
 
1949
 
1950
- $this->clear_log();
1951
- $msg = __( "Cleared database", 'simple-history' );
1952
- add_settings_error( "simple_history_rss_feed_regenerate_secret", "simple_history_rss_feed_regenerate_secret", $msg, "updated" );
1953
  set_transient( 'settings_errors', get_settings_errors(), 30 );
1954
 
1955
  $goback = esc_url_raw( add_query_arg( 'settings-updated', 'true', wp_get_referer() ) );
1956
  wp_redirect( $goback );
1957
- exit;
1958
 
1959
  }
1960
 
1961
- // Section for general options
1962
- // Will contain settings like where to show simple history and number of items
1963
  $settings_section_general_id = self::SETTINGS_SECTION_GENERAL_ID;
1964
  add_settings_section(
1965
  $settings_section_general_id,
1966
- "", // No title __("General", "simple-history"),
1967
- array( $this, "settings_section_output" ),
1968
- SimpleHistory::SETTINGS_MENU_SLUG// same slug as for options menu page
1969
  );
1970
 
1971
  // Settings for the general settings section
1972
  // Each setting = one row in the settings section
1973
  // add_settings_field( $id, $title, $callback, $page, $section, $args );
1974
-
1975
  // Checkboxes for where to show simple history
1976
  add_settings_field(
1977
- "simple_history_show_where",
1978
- __( "Show history", "simple-history" ),
1979
- array( $this, "settings_field_where_to_show" ),
1980
  SimpleHistory::SETTINGS_MENU_SLUG,
1981
  $settings_section_general_id
1982
  );
1983
 
1984
- // Nonces for show where inputs
1985
- register_setting( SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP, "simple_history_show_on_dashboard" );
1986
- register_setting( SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP, "simple_history_show_as_page" );
1987
 
1988
- // Number if items to show on the history page
1989
  add_settings_field(
1990
- "simple_history_number_of_items",
1991
- __( "Number of items per page on the log page", "simple-history" ),
1992
- array( $this, "settings_field_number_of_items" ),
1993
  SimpleHistory::SETTINGS_MENU_SLUG,
1994
  $settings_section_general_id
1995
  );
1996
 
1997
- // Nonces for number of items inputs
1998
- register_setting( SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP, "simple_history_pager_size" );
1999
-
2000
 
2001
- // Number if items to show on dashboard
2002
  add_settings_field(
2003
- "simple_history_number_of_items_dashboard",
2004
- __( "Number of items per page on the dashboard", "simple-history" ),
2005
- array( $this, "settings_field_number_of_items_dashboard" ),
2006
  SimpleHistory::SETTINGS_MENU_SLUG,
2007
  $settings_section_general_id
2008
  );
2009
 
2010
- // Nonces for number of items inputs
2011
- register_setting( SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP, "simple_history_pager_size_dashboard" );
2012
 
2013
-
2014
- // Link to clear log
2015
- add_settings_field(
2016
- "simple_history_clear_log",
2017
- __( "Clear log", "simple-history" ),
2018
- array( $this, "settings_field_clear_log" ),
2019
- SimpleHistory::SETTINGS_MENU_SLUG,
2020
- $settings_section_general_id
2021
- );
 
2022
 
2023
  }
2024
 
@@ -2027,10 +2039,8 @@ Because Simple History was just recently installed, this feed does not contain m
2027
  */
2028
  function history_page_output() {
2029
 
2030
- //global $simple_history;
2031
-
2032
- //$this->purge_db();
2033
-
2034
  global $wpdb;
2035
 
2036
  $pager_size = $this->get_pager_size();
@@ -2042,7 +2052,7 @@ Because Simple History was just recently installed, this feed does not contain m
2042
  *
2043
  * @param int $pager_size
2044
  */
2045
- $pager_size = apply_filters( "simple_history/page_pager_size", $pager_size );
2046
 
2047
  ?>
2048
 
@@ -2050,7 +2060,7 @@ Because Simple History was just recently installed, this feed does not contain m
2050
 
2051
  <h1 class="SimpleHistoryPageHeadline">
2052
  <div class="dashicons dashicons-backup SimpleHistoryPageHeadline__icon"></div>
2053
- <?php echo _x( "Simple History", 'history page headline', 'simple-history' )?>
2054
  </h1>
2055
 
2056
  <?php
@@ -2061,7 +2071,7 @@ Because Simple History was just recently installed, this feed does not contain m
2061
  *
2062
  * @param SimpleHistory $SimpleHistory This class.
2063
  */
2064
- do_action( "simple_history/history_page/before_gui", $this );
2065
  ?>
2066
 
2067
  <div class="SimpleHistoryGuiWrap">
@@ -2072,14 +2082,14 @@ Because Simple History was just recently installed, this feed does not contain m
2072
 
2073
  <?php
2074
 
2075
- /**
2076
- * Fires after the gui div
2077
- *
2078
- * @since 2.0
2079
- *
2080
- * @param SimpleHistory $SimpleHistory This class.
2081
- */
2082
- do_action( "simple_history/history_page/after_gui", $this );
2083
 
2084
  ?>
2085
 
@@ -2099,8 +2109,8 @@ Because Simple History was just recently installed, this feed does not contain m
2099
  */
2100
  function setting_show_on_dashboard() {
2101
 
2102
- $show_on_dashboard = get_option( "simple_history_show_on_dashboard", 1 );
2103
- $show_on_dashboard = apply_filters( "simple_history_show_on_dashboard", $show_on_dashboard );
2104
  return (bool) $show_on_dashboard;
2105
 
2106
  }
@@ -2113,8 +2123,8 @@ Because Simple History was just recently installed, this feed does not contain m
2113
  */
2114
  function setting_show_as_page() {
2115
 
2116
- $setting = get_option( "simple_history_show_as_page", 1 );
2117
- $setting = apply_filters( "simple_history_show_as_page", $setting );
2118
 
2119
  return (bool) $setting;
2120
 
@@ -2129,16 +2139,16 @@ Because Simple History was just recently installed, this feed does not contain m
2129
 
2130
  ?>
2131
  <select name="simple_history_pager_size">
2132
- <option <?php echo $current_pager_size == 5 ? "selected" : ""?> value="5">5</option>
2133
- <option <?php echo $current_pager_size == 10 ? "selected" : ""?> value="10">10</option>
2134
- <option <?php echo $current_pager_size == 15 ? "selected" : ""?> value="15">15</option>
2135
- <option <?php echo $current_pager_size == 20 ? "selected" : ""?> value="20">20</option>
2136
- <option <?php echo $current_pager_size == 25 ? "selected" : ""?> value="25">25</option>
2137
- <option <?php echo $current_pager_size == 30 ? "selected" : ""?> value="30">30</option>
2138
- <option <?php echo $current_pager_size == 40 ? "selected" : ""?> value="40">40</option>
2139
- <option <?php echo $current_pager_size == 50 ? "selected" : ""?> value="50">50</option>
2140
- <option <?php echo $current_pager_size == 75 ? "selected" : ""?> value="75">75</option>
2141
- <option <?php echo $current_pager_size == 100 ? "selected" : ""?> value="100">100</option>
2142
  </select>
2143
  <?php
2144
 
@@ -2153,16 +2163,16 @@ Because Simple History was just recently installed, this feed does not contain m
2153
 
2154
  ?>
2155
  <select name="simple_history_pager_size_dashboard">
2156
- <option <?php echo $current_pager_size == 5 ? "selected" : ""?> value="5">5</option>
2157
- <option <?php echo $current_pager_size == 10 ? "selected" : ""?> value="10">10</option>
2158
- <option <?php echo $current_pager_size == 15 ? "selected" : ""?> value="15">15</option>
2159
- <option <?php echo $current_pager_size == 20 ? "selected" : ""?> value="20">20</option>
2160
- <option <?php echo $current_pager_size == 25 ? "selected" : ""?> value="25">25</option>
2161
- <option <?php echo $current_pager_size == 30 ? "selected" : ""?> value="30">30</option>
2162
- <option <?php echo $current_pager_size == 40 ? "selected" : ""?> value="40">40</option>
2163
- <option <?php echo $current_pager_size == 50 ? "selected" : ""?> value="50">50</option>
2164
- <option <?php echo $current_pager_size == 75 ? "selected" : ""?> value="75">75</option>
2165
- <option <?php echo $current_pager_size == 100 ? "selected" : ""?> value="100">100</option>
2166
  </select>
2167
  <?php
2168
 
@@ -2178,33 +2188,35 @@ Because Simple History was just recently installed, this feed does not contain m
2178
 
2179
  ?>
2180
 
2181
- <input <?php echo $show_on_dashboard ? "checked='checked'" : ""?> type="checkbox" value="1" name="simple_history_show_on_dashboard" id="simple_history_show_on_dashboard" class="simple_history_show_on_dashboard" />
2182
- <label for="simple_history_show_on_dashboard"><?php _e( "on the dashboard", 'simple-history' )?></label>
2183
 
2184
  <br />
2185
 
2186
- <input <?php echo $show_as_page ? "checked='checked'" : ""?> type="checkbox" value="1" name="simple_history_show_as_page" id="simple_history_show_as_page" class="simple_history_show_as_page" />
2187
- <label for="simple_history_show_as_page"><?php _e( "as a page under the dashboard menu", 'simple-history' )?></label>
2188
 
2189
  <?php
2190
- }
2191
 
2192
  /**
2193
  * Settings section to clear database
2194
  */
2195
  function settings_field_clear_log() {
2196
 
2197
- $clear_link = esc_url( add_query_arg( "", "" ) );
2198
- $clear_link = wp_nonce_url( $clear_link, "simple_history_clear_log", "simple_history_clear_log_nonce" );
2199
  $clear_days = $this->get_clear_history_interval();
2200
 
2201
- echo "<p>";
 
2202
  if ( $clear_days > 0 ) {
2203
- echo sprintf( __( 'Items in the database are automatically removed after %1$s days.', "simple-history" ), $clear_days );
2204
  } else {
2205
  _e( 'Items in the database are kept forever.', 'simple-history' );
2206
  }
2207
- echo "</p>";
 
2208
 
2209
  printf( '<p><a class="button js-SimpleHistory-Settings-ClearLog" href="%2$s">%1$s</a></p>', __( 'Clear log now', 'simple-history' ), $clear_link );
2210
  }
@@ -2225,8 +2237,8 @@ Because Simple History was just recently installed, this feed does not contain m
2225
  *
2226
  * @param $days Number of days of history to keep
2227
  */
2228
- $days = (int) apply_filters( "simple_history_db_purge_days_interval", $days );
2229
- $days = (int) apply_filters( "simple_history/db_purge_days_interval", $days );
2230
 
2231
  return $days;
2232
 
@@ -2244,23 +2256,22 @@ Because Simple History was just recently installed, this feed does not contain m
2244
  $simple_history_table = SimpleHistory::DBTABLE;
2245
  $simple_history_context_table = SimpleHistory::DBTABLE_CONTEXTS;
2246
 
2247
- // Get number of rows before delete
2248
  $sql_num_rows = "SELECT count(id) AS num_rows FROM {$tableprefix}{$simple_history_table}";
2249
  $num_rows = $wpdb->get_var( $sql_num_rows, 0 );
2250
 
2251
- //$sql = "DELETE FROM {$tableprefix}{$simple_history_table}";
2252
  $sql = "TRUNCATE {$tableprefix}{$simple_history_table}";
2253
  $wpdb->query( $sql );
2254
 
2255
- //$sql = "DELETE FROM {$tableprefix}{$simple_history_context_table}";
2256
  $sql = "TRUNCATE {$tableprefix}{$simple_history_context_table}";
2257
  $wpdb->query( $sql );
2258
 
2259
  // Zero state sucks
2260
  SimpleLogger()->info(
2261
- __( "The log for Simple History was cleared ({num_rows} rows were removed).", "simple-history" ),
2262
  array(
2263
- "num_rows" => $num_rows,
2264
  )
2265
  );
2266
 
@@ -2276,15 +2287,10 @@ Because Simple History was just recently installed, this feed does not contain m
2276
  */
2277
  function maybe_purge_db() {
2278
 
2279
- /*if ( ! is_admin() ) {
2280
- return;
2281
- }*/
2282
-
2283
  // How often should we try to do this?
2284
- // Once a day = a bit tiresome
2285
- // Let's go with sundays; purge the log on sundays
2286
-
2287
- // day of week, 1 = mon, 7 = sun
2288
  $day_of_week = date( 'N' );
2289
  if ( 7 === (int) $day_of_week ) {
2290
 
@@ -2299,12 +2305,10 @@ Because Simple History was just recently installed, this feed does not contain m
2299
  */
2300
  function purge_db() {
2301
 
2302
- // SimpleLogger()->debug("Simple History is running purge_db()");
2303
-
2304
  $do_purge_history = true;
2305
 
2306
- $do_purge_history = apply_filters( "simple_history_allow_db_purge", $do_purge_history );
2307
- $do_purge_history = apply_filters( "simple_history/allow_db_purge", $do_purge_history );
2308
 
2309
  if ( ! $do_purge_history ) {
2310
  return;
@@ -2335,12 +2339,12 @@ Because Simple History was just recently installed, this feed does not contain m
2335
  return;
2336
  }
2337
 
2338
- $sql_ids_in = implode( ",", $ids_to_delete );
2339
 
2340
  // Add number of deleted rows to total_rows option
2341
- $prev_total_rows = (int) get_option( "simple_history_total_rows", 0 );
2342
  $total_rows = $prev_total_rows + sizeof( $ids_to_delete );
2343
- update_option( "simple_history_total_rows", $total_rows );
2344
 
2345
  // Remove rows + contexts
2346
  $sql_delete_history = "DELETE FROM {$table_name} WHERE id IN ($sql_ids_in)";
@@ -2350,17 +2354,17 @@ Because Simple History was just recently installed, this feed does not contain m
2350
  $wpdb->query( $sql_delete_history_context );
2351
 
2352
  $message = _nx(
2353
- "Simple History removed one event that were older than {days} days",
2354
- "Simple History removed {num_rows} events that were older than {days} days",
2355
- "Database is being cleared automagically",
2356
- "simple-history"
2357
  );
2358
 
2359
  SimpleLogger()->info(
2360
  $message,
2361
  array(
2362
- "days" => $days,
2363
- "num_rows" => sizeof( $ids_to_delete ),
2364
  )
2365
  );
2366
 
@@ -2382,16 +2386,16 @@ Because Simple History was just recently installed, this feed does not contain m
2382
  $logger = null;
2383
  $row->context = isset( $row->context ) && is_array( $row->context ) ? $row->context : array();
2384
 
2385
- if ( ! isset( $row->context["_message_key"] ) ) {
2386
- $row->context["_message_key"] = null;
2387
  }
2388
 
2389
  // Fallback to SimpleLogger if no logger exists for row
2390
- if ( ! isset( $this->instantiatedLoggers[$row_logger] ) ) {
2391
- $row_logger = "SimpleLogger";
2392
  }
2393
 
2394
- $logger = $this->instantiatedLoggers[$row_logger]["instance"];
2395
 
2396
  return $logger->getLogRowPlainTextOutput( $row );
2397
 
@@ -2415,11 +2419,11 @@ Because Simple History was just recently installed, this feed does not contain m
2415
  $row->context = isset( $row->context ) && is_array( $row->context ) ? $row->context : array();
2416
 
2417
  // Fallback to SimpleLogger if no logger exists for row
2418
- if ( ! isset( $this->instantiatedLoggers[$row_logger] ) ) {
2419
- $row_logger = "SimpleLogger";
2420
  }
2421
 
2422
- $logger = $this->instantiatedLoggers[$row_logger]["instance"];
2423
 
2424
  return $logger->getLogRowHeaderOutput( $row );
2425
 
@@ -2438,11 +2442,11 @@ Because Simple History was just recently installed, this feed does not contain m
2438
  $row->context = isset( $row->context ) && is_array( $row->context ) ? $row->context : array();
2439
 
2440
  // Fallback to SimpleLogger if no logger exists for row
2441
- if ( ! isset( $this->instantiatedLoggers[$row_logger] ) ) {
2442
- $row_logger = "SimpleLogger";
2443
  }
2444
 
2445
- $logger = $this->instantiatedLoggers[$row_logger]["instance"];
2446
 
2447
  return $logger->getLogRowSenderImageOutput( $row );
2448
 
@@ -2455,11 +2459,11 @@ Because Simple History was just recently installed, this feed does not contain m
2455
  $row->context = isset( $row->context ) && is_array( $row->context ) ? $row->context : array();
2456
 
2457
  // Fallback to SimpleLogger if no logger exists for row
2458
- if ( ! isset( $this->instantiatedLoggers[$row_logger] ) ) {
2459
- $row_logger = "SimpleLogger";
2460
  }
2461
 
2462
- $logger = $this->instantiatedLoggers[$row_logger]["instance"];
2463
 
2464
  return $logger->getLogRowDetailsOutput( $row );
2465
 
@@ -2479,6 +2483,7 @@ Because Simple History was just recently installed, this feed does not contain m
2479
 
2480
  /**
2481
  * Returns true if $haystack ends with $needle
 
2482
  * @param string $haystack
2483
  * @param string $needle
2484
  */
@@ -2495,7 +2500,7 @@ Because Simple History was just recently installed, this feed does not contain m
2495
  public function getLogRowHTMLOutput( $oneLogRow, $args ) {
2496
 
2497
  $defaults = array(
2498
- "type" => "overview", // or "single" to include more stuff
2499
  );
2500
 
2501
  $args = wp_parse_args( $args, $defaults );
@@ -2517,7 +2522,7 @@ Because Simple History was just recently installed, this feed does not contain m
2517
 
2518
  // subsequentOccasions = including the current one
2519
  $occasions_count = $oneLogRow->subsequentOccasions - 1;
2520
- $occasions_html = "";
2521
 
2522
  if ( $occasions_count > 0 ) {
2523
 
@@ -2525,21 +2530,21 @@ Because Simple History was just recently installed, this feed does not contain m
2525
 
2526
  $occasions_html .= '<a href="#" class="SimpleHistoryLogitem__occasionsLink">';
2527
  $occasions_html .= sprintf(
2528
- _n( '+%1$s similar event', '+%1$s similar events', $occasions_count, "simple-history" ),
2529
  $occasions_count
2530
  );
2531
  $occasions_html .= '</a>';
2532
 
2533
  $occasions_html .= '<span class="SimpleHistoryLogitem__occasionsLoading">';
2534
  $occasions_html .= sprintf(
2535
- __( 'Loading…', "simple-history" ),
2536
  $occasions_count
2537
  );
2538
  $occasions_html .= '</span>';
2539
 
2540
  $occasions_html .= '<span class="SimpleHistoryLogitem__occasionsLoaded">';
2541
  $occasions_html .= sprintf(
2542
- __( 'Showing %1$s more', "simple-history" ),
2543
  $occasions_count
2544
  );
2545
  $occasions_html .= '</span>';
@@ -2549,16 +2554,16 @@ Because Simple History was just recently installed, this feed does not contain m
2549
  }
2550
 
2551
  // Add data atributes to log row, so plugins can do stuff
2552
- $data_attrs = "";
2553
  $data_attrs .= sprintf( ' data-row-id="%1$d" ', $oneLogRow->id );
2554
  $data_attrs .= sprintf( ' data-occasions-count="%1$d" ', $occasions_count );
2555
  $data_attrs .= sprintf( ' data-occasions-id="%1$s" ', esc_attr( $oneLogRow->occasionsID ) );
2556
 
2557
- if ( isset( $oneLogRow->context["_server_remote_addr"] ) ) {
2558
- $data_attrs .= sprintf( ' data-ip-address="%1$s" ', esc_attr( $oneLogRow->context["_server_remote_addr"] ) );
2559
  }
2560
 
2561
- $arr_found_additional_ip_headers = $this->instantiatedLoggers["SimpleLogger"]["instance"]->get_event_ip_number_headers( $oneLogRow );
2562
  if ( $arr_found_additional_ip_headers ) {
2563
  $data_attrs .= sprintf( ' data-ip-address-multiple="1" ' );
2564
  }
@@ -2568,26 +2573,26 @@ Because Simple History was just recently installed, this feed does not contain m
2568
  $data_attrs .= sprintf( ' data-date="%1$s" ', esc_attr( $oneLogRow->date ) );
2569
  $data_attrs .= sprintf( ' data-initiator="%1$s" ', esc_attr( $oneLogRow->initiator ) );
2570
 
2571
- if ( isset( $oneLogRow->context["_user_id"] ) ) {
2572
- $data_attrs .= sprintf( ' data-initiator-user-id="%1$d" ', $oneLogRow->context["_user_id"] );
2573
  }
2574
 
2575
  // If type is single then include more details
2576
- $more_details_html = "";
2577
- if ( $args["type"] == "single" ) {
2578
 
2579
- $more_details_html = apply_filters( "simple_history/log_html_output_details_single/html_before_context_table", $more_details_html, $oneLogRow );
2580
 
2581
- $more_details_html .= sprintf( '<h2 class="SimpleHistoryLogitem__moreDetailsHeadline">%1$s</h2>', __( "Context data", "simple-history" ) );
2582
- $more_details_html .= "<p>" . __( "This is potentially useful meta data that a logger has saved.", "simple-history" ) . "</p>";
2583
  $more_details_html .= "<table class='SimpleHistoryLogitem__moreDetailsContext'>";
2584
  $more_details_html .= sprintf(
2585
  '<tr>
2586
  <th>%1$s</th>
2587
  <th>%2$s</th>
2588
  </tr>',
2589
- "Key",
2590
- "Value"
2591
  );
2592
 
2593
  $logRowKeysToShow = array_fill_keys( array_keys( (array) $oneLogRow ), true );
@@ -2597,38 +2602,36 @@ Because Simple History was just recently installed, this feed does not contain m
2597
  *
2598
  * Array is in format
2599
  *
2600
- * Array
2601
- * (
2602
- * [id] => 1
2603
- * [logger] => 1
2604
- * [level] => 1
2605
- * ...
2606
- * )
2607
- *
2608
  *
2609
  * @since 2.0.29
2610
  *
2611
  * @param array with keys to show. key to show = key. value = boolean to show or not.
2612
  * @param object log row to show details from
2613
  */
2614
- $logRowKeysToShow = apply_filters( "simple_history/log_html_output_details_table/row_keys_to_show", $logRowKeysToShow, $oneLogRow );
2615
 
2616
  // Hide some keys by default
2617
  unset(
2618
- $logRowKeysToShow["occasionsID"],
2619
- $logRowKeysToShow["subsequentOccasions"],
2620
- $logRowKeysToShow["rep"],
2621
- $logRowKeysToShow["repeated"],
2622
- $logRowKeysToShow["occasionsIDType"],
2623
- $logRowKeysToShow["context"],
2624
- $logRowKeysToShow["type"]
2625
  );
2626
 
2627
-
2628
  foreach ( $oneLogRow as $rowKey => $rowVal ) {
2629
 
2630
  // Only columns from oneLogRow that exist in logRowKeysToShow will be outputed
2631
- if ( ! array_key_exists( $rowKey, $logRowKeysToShow ) || ! $logRowKeysToShow[$rowKey] ) {
2632
  continue;
2633
  }
2634
 
@@ -2648,7 +2651,6 @@ Because Simple History was just recently installed, this feed does not contain m
2648
 
2649
  }
2650
 
2651
-
2652
  $logRowContextKeysToShow = array_fill_keys( array_keys( (array) $oneLogRow->context ), true );
2653
  /*
2654
  error_log($this->json_encode($logRowContextKeysToShow));
@@ -2674,29 +2676,28 @@ Because Simple History was just recently installed, this feed does not contain m
2674
  *
2675
  * Array is in format
2676
  *
2677
- * Array
2678
- * (
2679
  * [plugin_slug] => 1
2680
  * [plugin_name] => 1
2681
  * [plugin_title] => 1
2682
  * [plugin_description] => 1
2683
  * [plugin_author] => 1
2684
  * [plugin_version] => 1
2685
- * ...
2686
- * )
2687
- *
2688
  *
2689
  * @since 2.0.29
2690
  *
2691
  * @param array with keys to show. key to show = key. value = boolean to show or not.
2692
  * @param object log row to show details from
2693
  */
2694
- $logRowContextKeysToShow = apply_filters( "simple_history/log_html_output_details_table/context_keys_to_show", $logRowContextKeysToShow, $oneLogRow );
2695
 
2696
  foreach ( $oneLogRow->context as $contextKey => $contextVal ) {
2697
 
2698
  // Only columns from context that exist in logRowContextKeysToShow will be outputed
2699
- if ( ! array_key_exists( $contextKey, $logRowContextKeysToShow ) || ! $logRowContextKeysToShow[$contextKey] ) {
2700
  continue;
2701
  }
2702
 
@@ -2711,30 +2712,30 @@ Because Simple History was just recently installed, this feed does not contain m
2711
 
2712
  }
2713
 
2714
- $more_details_html .= "</table>";
2715
 
2716
- $more_details_html = apply_filters( "simple_history/log_html_output_details_single/html_after_context_table", $more_details_html, $oneLogRow );
2717
 
2718
  $more_details_html = sprintf(
2719
  '<div class="SimpleHistoryLogitem__moreDetails">%1$s</div>',
2720
  $more_details_html
2721
  );
2722
 
2723
- }
2724
 
2725
  // Classes to add to log item li element
2726
  $classes = array(
2727
- "SimpleHistoryLogitem",
2728
  "SimpleHistoryLogitem--loglevel-{$oneLogRow->level}",
2729
  "SimpleHistoryLogitem--logger-{$oneLogRow->logger}",
2730
  );
2731
 
2732
  if ( isset( $oneLogRow->initiator ) && ! empty( $oneLogRow->initiator ) ) {
2733
- $classes[] = "SimpleHistoryLogitem--initiator-" . $oneLogRow->initiator;
2734
  }
2735
 
2736
  if ( $arr_found_additional_ip_headers ) {
2737
- $classes[] = "SimpleHistoryLogitem--IPAddress-multiple";
2738
  }
2739
 
2740
  // Always append the log level tag
@@ -2753,7 +2754,7 @@ Because Simple History was just recently installed, this feed does not contain m
2753
  *
2754
  * @param $classes Array with classes
2755
  */
2756
- $classes = apply_filters( "simple_history/logrowhtmloutput/classes", $classes );
2757
 
2758
  // Generate the HTML output for a row
2759
  $output = sprintf(
@@ -2780,18 +2781,16 @@ Because Simple History was just recently installed, this feed does not contain m
2780
  $oneLogRow->logger, // 7
2781
  $data_attrs, // 8 data attributes
2782
  $more_details_html, // 9
2783
- esc_attr( join( " ", $classes ) ) // 10
2784
  );
2785
 
2786
  // Get the main message row.
2787
  // Should be as plain as possible, like plain text
2788
  // but with links to for example users and posts
2789
- //SimpleLoggerFormatter::getRowTextOutput($oneLogRow);
2790
-
2791
  // Get detailed HTML-based output
2792
  // May include images, lists, any cool stuff needed to view
2793
- //SimpleLoggerFormatter::getRowHTMLOutput($oneLogRow);
2794
-
2795
  return trim( $output );
2796
 
2797
  }
@@ -2805,80 +2804,80 @@ Because Simple History was just recently installed, this feed does not contain m
2805
  */
2806
  function getLogLevelTranslated( $loglevel ) {
2807
 
2808
- $str_translated = "";
2809
 
2810
  switch ( $loglevel ) {
2811
 
2812
  // Lowercase
2813
- case "emergency":
2814
- $str_translated = _x( "emergency", "Log level in gui", "simple-history" );
2815
  break;
2816
 
2817
- case "alert":
2818
- $str_translated = _x( "alert", "Log level in gui", "simple-history" );
2819
  break;
2820
 
2821
- case "critical":
2822
- $str_translated = _x( "critical", "Log level in gui", "simple-history" );
2823
  break;
2824
 
2825
- case "error":
2826
- $str_translated = _x( "error", "Log level in gui", "simple-history" );
2827
  break;
2828
 
2829
- case "warning":
2830
- $str_translated = _x( "warning", "Log level in gui", "simple-history" );
2831
  break;
2832
 
2833
- case "notice":
2834
- $str_translated = _x( "notice", "Log level in gui", "simple-history" );
2835
  break;
2836
 
2837
- case "info":
2838
- $str_translated = _x( "info", "Log level in gui", "simple-history" );
2839
  break;
2840
 
2841
- case "debug":
2842
- $str_translated = _x( "debug", "Log level in gui", "simple-history" );
2843
  break;
2844
 
2845
  // Uppercase
2846
- case "Emergency":
2847
- $str_translated = _x( "Emergency", "Log level in gui", "simple-history" );
2848
  break;
2849
 
2850
- case "Alert":
2851
- $str_translated = _x( "Alert", "Log level in gui", "simple-history" );
2852
  break;
2853
 
2854
- case "Critical":
2855
- $str_translated = _x( "Critical", "Log level in gui", "simple-history" );
2856
  break;
2857
 
2858
- case "Error":
2859
- $str_translated = _x( "Error", "Log level in gui", "simple-history" );
2860
  break;
2861
 
2862
- case "Warning":
2863
- $str_translated = _x( "Warning", "Log level in gui", "simple-history" );
2864
  break;
2865
 
2866
- case "Notice":
2867
- $str_translated = _x( "Notice", "Log level in gui", "simple-history" );
2868
  break;
2869
 
2870
- case "Info":
2871
- $str_translated = _x( "Info", "Log level in gui", "simple-history" );
2872
  break;
2873
 
2874
- case "Debug":
2875
- $str_translated = _x( "Debug", "Log level in gui", "simple-history" );
2876
  break;
2877
 
2878
  default:
2879
  $str_translated = $loglevel;
2880
 
2881
- }
2882
 
2883
  return $str_translated;
2884
 
@@ -2897,7 +2896,7 @@ Because Simple History was just recently installed, this feed does not contain m
2897
  }
2898
 
2899
 
2900
- public function getInstantiatedLoggerBySlug( $slug = "" ) {
2901
 
2902
  if ( empty( $slug ) ) {
2903
  return false;
@@ -2905,10 +2904,9 @@ Because Simple History was just recently installed, this feed does not contain m
2905
 
2906
  foreach ( $this->getInstantiatedLoggers() as $one_logger ) {
2907
 
2908
- if ( $slug == $one_logger["instance"]->slug ) {
2909
- return $one_logger["instance"];
2910
  }
2911
-
2912
  }
2913
 
2914
  return false;
@@ -2919,11 +2917,11 @@ Because Simple History was just recently installed, this feed does not contain m
2919
  * Check which loggers a user has the right to read and return an array
2920
  * with all loggers they are allowed to read
2921
  *
2922
- * @param int $user_id Id of user to get loggers for. Defaults to current user id.
2923
  * @param string $format format to return loggers in. Default is array. Can also be "sql"
2924
  * @return array
2925
  */
2926
- public function getLoggersThatUserCanRead( $user_id = "", $format = "array" ) {
2927
 
2928
  $arr_loggers_user_can_view = array();
2929
 
@@ -2934,16 +2932,15 @@ Because Simple History was just recently installed, this feed does not contain m
2934
  $loggers = $this->getInstantiatedLoggers();
2935
  foreach ( $loggers as $one_logger ) {
2936
 
2937
- $logger_capability = $one_logger["instance"]->getCapability();
2938
 
2939
- //$arr_loggers_user_can_view = apply_filters("simple_history/loggers_user_can_read", $user_id, $arr_loggers_user_can_view);
2940
  $user_can_read_logger = user_can( $user_id, $logger_capability );
2941
- $user_can_read_logger = apply_filters( "simple_history/loggers_user_can_read/can_read_single_logger", $user_can_read_logger, $one_logger["instance"], $user_id );
2942
 
2943
  if ( $user_can_read_logger ) {
2944
  $arr_loggers_user_can_view[] = $one_logger;
2945
  }
2946
-
2947
  }
2948
 
2949
  /**
@@ -2954,12 +2951,12 @@ Because Simple History was just recently installed, this feed does not contain m
2954
  * @param array $arr_loggers_user_can_view Array with loggers that user $user_id can read
2955
  * @param int user_id ID of user to check read capability for
2956
  */
2957
- $arr_loggers_user_can_view = apply_filters( "simple_history/loggers_user_can_read", $arr_loggers_user_can_view, $user_id );
2958
 
2959
  // just return array with slugs in parenthesis suitable for sql-where
2960
- if ( "sql" == $format ) {
2961
 
2962
- $str_return = "(";
2963
 
2964
  if ( sizeof( $arr_loggers_user_can_view ) ) {
2965
 
@@ -2967,12 +2964,12 @@ Because Simple History was just recently installed, this feed does not contain m
2967
 
2968
  $str_return .= sprintf(
2969
  '"%1$s", ',
2970
- esc_sql( $one_logger["instance"]->slug )
2971
  );
2972
 
2973
  }
2974
 
2975
- $str_return = rtrim( $str_return, " ," );
2976
 
2977
  } else {
2978
 
@@ -2981,7 +2978,7 @@ Because Simple History was just recently installed, this feed does not contain m
2981
 
2982
  }
2983
 
2984
- $str_return .= ")";
2985
 
2986
  return $str_return;
2987
 
@@ -2999,7 +2996,7 @@ Because Simple History was just recently installed, this feed does not contain m
2999
  * @since 2.0
3000
  *
3001
  * @param string $email email address
3002
- * @param int $size Size of the avatar image
3003
  * @param string $default URL to a default image to use if no avatar is available
3004
  * @param string $alt Alternative text to use in image tag. Defaults to blank
3005
  * @return string <img> tag for the user's avatar
@@ -3016,7 +3013,6 @@ Because Simple History was just recently installed, this feed does not contain m
3016
  } else {
3017
 
3018
  // WP setting for avatar was to not show, but we do it anyway, using the same code as get_avatar() would have used
3019
-
3020
  if ( false === $alt ) {
3021
  $safe_alt = '';
3022
  } else {
@@ -3034,7 +3030,6 @@ Because Simple History was just recently installed, this feed does not contain m
3034
  } else {
3035
  $default = $avatar_default;
3036
  }
3037
-
3038
  }
3039
 
3040
  if ( ! empty( $email ) ) {
@@ -3045,17 +3040,15 @@ Because Simple History was just recently installed, this feed does not contain m
3045
  $host = 'https://secure.gravatar.com';
3046
  } else {
3047
  if ( ! empty( $email ) ) {
3048
- $host = sprintf( "http://%d.gravatar.com", ( hexdec( $email_hash[0] ) % 2 ) );
3049
  } else {
3050
  $host = 'http://0.gravatar.com';
3051
  }
3052
-
3053
  }
3054
 
3055
  if ( 'mystery' == $default ) {
3056
  $default = "$host/avatar/ad516503a11cd5ca435acc9bb6523536?s={$size}";
3057
- }
3058
- // ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com')
3059
  elseif ( 'blank' == $default ) {
3060
  $default = $email ? 'blank' : includes_url( 'images/blank.gif' );
3061
  } elseif ( ! empty( $email ) && 'gravatar_default' == $default ) {
@@ -3102,7 +3095,7 @@ Because Simple History was just recently installed, this feed does not contain m
3102
 
3103
  return $avatar;
3104
 
3105
- } // else
3106
 
3107
  }
3108
 
@@ -3117,14 +3110,14 @@ Because Simple History was just recently installed, this feed does not contain m
3117
  // Get number of events today
3118
  $logQuery = new SimpleHistoryLogQuery();
3119
  $logResults = $logQuery->query( array(
3120
- "posts_per_page" => 1,
3121
- "date_from" => strtotime( "today" ),
3122
  ) );
3123
 
3124
- $total_row_count = (int) $logResults["total_row_count"];
3125
 
3126
  // Get sql query for where to read only loggers current user is allowed to read/view
3127
- $sql_loggers_in = $this->getLoggersThatUserCanRead( get_current_user_id(), "sql" );
3128
 
3129
  // Get number of users today, i.e. events with wp_user as initiator
3130
  $sql_users_today = sprintf( '
@@ -3140,13 +3133,13 @@ Because Simple History was just recently installed, this feed does not contain m
3140
  AND date > "%2$s"
3141
  ',
3142
  $sql_loggers_in,
3143
- date( "Y-m-d H:i", strtotime( "today" ) ),
3144
  $wpdb->prefix . SimpleHistory::DBTABLE,
3145
  $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS
3146
  );
3147
 
3148
- $cache_key = "quick_stats_users_today_" . md5( serialize( $sql_loggers_in ) );
3149
- $cache_group = "simple-history-" . $this->get_cache_incrementor();
3150
  $results_users_today = wp_cache_get( $cache_key, $cache_group );
3151
 
3152
  if ( false === $results_users_today ) {
@@ -3164,12 +3157,12 @@ Because Simple History was just recently installed, this feed does not contain m
3164
  AND date > "%2$s"
3165
  ',
3166
  $sql_loggers_in,
3167
- date( "Y-m-d H:i", strtotime( "today" ) ),
3168
  $wpdb->prefix . SimpleHistory::DBTABLE,
3169
  $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS
3170
  );
3171
 
3172
- $sql_other_sources_where = apply_filters( "simple_history/quick_stats_where", $sql_other_sources_where );
3173
 
3174
  $sql_other_sources = sprintf( '
3175
  SELECT
@@ -3179,14 +3172,13 @@ Because Simple History was just recently installed, this feed does not contain m
3179
  %5$s
3180
  ',
3181
  $sql_loggers_in,
3182
- date( "Y-m-d H:i", strtotime( "today" ) ),
3183
  $wpdb->prefix . SimpleHistory::DBTABLE,
3184
  $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS,
3185
  $sql_other_sources_where // 5
3186
  );
3187
  // sf_d($sql_other_sources, '$sql_other_sources');
3188
-
3189
- $cache_key = "quick_stats_results_other_sources_today_" . md5( serialize( $sql_other_sources ) );
3190
  $results_other_sources_today = wp_cache_get( $cache_key, $cache_group );
3191
 
3192
  if ( false === $results_other_sources_today ) {
@@ -3198,21 +3190,20 @@ Because Simple History was just recently installed, this feed does not contain m
3198
 
3199
  $count_other_sources = sizeof( $results_other_sources_today );
3200
 
3201
- //sf_d($logResults, '$logResults');
3202
- //sf_d($results_users_today, '$sql_users_today');
3203
- //sf_d($results_other_sources_today, '$results_other_sources_today');
3204
-
3205
  ?>
3206
  <div class="SimpleHistoryQuickStats">
3207
  <p>
3208
  <?php
3209
 
3210
- $msg_tmpl = "";
3211
 
3212
  // No results today at all
3213
  if ( $total_row_count == 0 ) {
3214
 
3215
- $msg_tmpl = __( "No events today so far.", "simple-history" );
3216
 
3217
  } else {
3218
 
@@ -3231,73 +3222,72 @@ Because Simple History was just recently installed, this feed does not contain m
3231
  // A single event existed and was from a user
3232
  // 1 event today from 1 user.
3233
  if ( $total_row_count == 1 && $count_users_today == 1 ) {
3234
- $msg_tmpl .= __( 'One event today from one user.', "simple-history" );
3235
  }
3236
 
3237
  // A single event existed and was from another source
3238
  // 1 event today from 1 source.
3239
  if ( $total_row_count == 1 && ! $count_users_today ) {
3240
- $msg_tmpl .= __( 'One event today from one source.', "simple-history" );
3241
  }
3242
 
3243
  // Multiple events from a single user
3244
  // 3 events today from one user.
3245
  if ( $total_row_count > 1 && $count_users_today == 1 && ! $count_other_sources ) {
3246
- $msg_tmpl .= __( '%1$d events today from one user.', "simple-history" );
3247
  }
3248
 
3249
  // Multiple events from only users
3250
  // 2 events today from 2 users.
3251
  if ( $total_row_count > 1 && $count_users_today == $total_row_count ) {
3252
- $msg_tmpl .= __( '%1$d events today from %2$d users.', "simple-history" );
3253
  }
3254
 
3255
  // Multiple events from 1 single user and 1 single other source
3256
  // 2 events today from 1 user and 1 other source.
3257
  if ( $total_row_count && 1 == $count_users_today && 1 == $count_other_sources ) {
3258
- $msg_tmpl .= __( '%1$d events today from one user and one other source.', "simple-history" );
3259
  }
3260
 
3261
  // Multiple events from multple users but from only 1 single other source
3262
  // 3 events today from 2 users and 1 other source.
3263
  if ( $total_row_count > 1 && $count_users_today > 1 && $count_other_sources == 1 ) {
3264
- $msg_tmpl .= __( '%1$d events today from one user and one other source.', "simple-history" );
3265
  }
3266
 
3267
  // Multiple events from 1 user but from multiple other source
3268
  // 3 events today from 1 user and 2 other sources.
3269
  if ( $total_row_count > 1 && 1 == $count_users_today && $count_other_sources > 1 ) {
3270
- $msg_tmpl .= __( '%1$d events today from one user and %3$d other sources.', "simple-history" );
3271
  }
3272
 
3273
  // Multiple events from multiple user and from multiple other sources
3274
  // 4 events today from 2 users and 2 other sources.
3275
  if ( $total_row_count > 1 && $count_users_today > 1 && $count_other_sources > 1 ) {
3276
- $msg_tmpl .= __( '%1$s events today from %2$d users and %3$d other sources.', "simple-history" );
3277
  }
3278
-
3279
- }
3280
 
3281
  // only show stats if we have something to output
3282
  if ( $msg_tmpl ) {
3283
 
3284
  printf(
3285
  $msg_tmpl,
3286
- $logResults["total_row_count"], // 1
3287
  $count_users_today, // 2
3288
  $count_other_sources // 3
3289
  );
3290
 
3291
  // Space between texts
3292
  /*
3293
- echo " ";
3294
 
3295
- // http://playground-root.ep/wp-admin/options-general.php?page=simple_history_settings_menu_slug&selected-tab=stats
3296
- printf(
3297
- '<a href="%1$s">View more stats</a>.',
3298
- add_query_arg("selected-tab", "stats", menu_page_url(SimpleHistory::SETTINGS_MENU_SLUG, 0))
3299
- );
3300
- */
3301
 
3302
  }
3303
 
@@ -3324,7 +3314,7 @@ Because Simple History was just recently installed, this feed does not contain m
3324
  wp_cache_set( $incrementor_key, $incrementor_value );
3325
  }
3326
 
3327
- //echo "<br>incrementor_value: $incrementor_value";
3328
  return $incrementor_value;
3329
 
3330
  }
@@ -3333,16 +3323,15 @@ Because Simple History was just recently installed, this feed does not contain m
3333
  // Number of rows the last n days
3334
  function get_num_events_last_n_days( $period_days = 28 ) {
3335
 
3336
- $transient_key = "sh_" . md5( __METHOD__ . $period_days . "_2");
3337
 
3338
  $count = get_transient( $transient_key );
3339
 
3340
-
3341
  if ( false === $count ) {
3342
 
3343
  global $wpdb;
3344
 
3345
- $sqlStringLoggersUserCanRead = $this->getLoggersThatUserCanRead( null, "sql" );
3346
 
3347
  $sql = sprintf(
3348
  '
@@ -3352,7 +3341,7 @@ Because Simple History was just recently installed, this feed does not contain m
3352
  AND logger IN %3$s
3353
  ',
3354
  $wpdb->prefix . SimpleHistory::DBTABLE,
3355
- strtotime("-$period_days days"),
3356
  $sqlStringLoggersUserCanRead
3357
  );
3358
 
@@ -3369,7 +3358,7 @@ Because Simple History was just recently installed, this feed does not contain m
3369
 
3370
  function get_num_events_per_day_last_n_days( $period_days = 28 ) {
3371
 
3372
- $transient_key = "sh_" . md5( __METHOD__ . $period_days . "_2");
3373
 
3374
  $dates = get_transient( $transient_key );
3375
 
@@ -3377,7 +3366,7 @@ Because Simple History was just recently installed, this feed does not contain m
3377
 
3378
  global $wpdb;
3379
 
3380
- $sqlStringLoggersUserCanRead = $this->getLoggersThatUserCanRead( null, "sql" );
3381
 
3382
  $sql = sprintf(
3383
  '
@@ -3393,7 +3382,7 @@ Because Simple History was just recently installed, this feed does not contain m
3393
  ORDER BY yearDate ASC
3394
  ',
3395
  $wpdb->prefix . SimpleHistory::DBTABLE,
3396
- strtotime("-$period_days days"),
3397
  $sqlStringLoggersUserCanRead
3398
  );
3399
 
@@ -3401,7 +3390,6 @@ Because Simple History was just recently installed, this feed does not contain m
3401
 
3402
  set_transient( $transient_key, $dates, HOUR_IN_SECONDS );
3403
  // echo "set";exit;
3404
-
3405
  } else {
3406
  // echo "get";exit;
3407
  }
@@ -3419,7 +3407,7 @@ Because Simple History was just recently installed, this feed does not contain m
3419
 
3420
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
3421
 
3422
- $cache_key = "sh_" .md5( __METHOD__ . $days );
3423
 
3424
  $numEvents = get_transient( $cache_key );
3425
 
@@ -3431,7 +3419,7 @@ Because Simple History was just recently installed, this feed does not contain m
3431
  WHERE date >= DATE_ADD(CURDATE(), INTERVAL -%d DAY)
3432
  ", $days);
3433
 
3434
- $numEvents = $wpdb->get_var($sql);
3435
 
3436
  set_transient( $cache_key, $numEvents, HOUR_IN_SECONDS );
3437
 
@@ -3476,13 +3464,13 @@ function SimpleLogger() {
3476
  function simple_history_add( $args ) {
3477
 
3478
  $defaults = array(
3479
- "action" => null,
3480
- "object_type" => null,
3481
- "object_subtype" => null,
3482
- "object_id" => null,
3483
- "object_name" => null,
3484
- "user_id" => null,
3485
- "description" => null
3486
  );
3487
 
3488
  $context = wp_parse_args( $args, $defaults );
@@ -3520,8 +3508,8 @@ function simple_history_add( $args ) {
3520
  * @uses Text_Diff
3521
  * @uses WP_Text_Diff_Renderer_Table
3522
  *
3523
- * @param string $left_string "old" (left) version of string
3524
- * @param string $right_string "new" (right) version of string
3525
  * @param string|array $args Optional. Change 'title', 'title_left', and 'title_right' defaults. And leading_context_lines and trailing_context_lines.
3526
  * @return string Empty string if strings are equivalent or HTML with differences.
3527
  */
@@ -3531,14 +3519,15 @@ function simple_history_text_diff( $left_string, $right_string, $args = null ) {
3531
  'title' => '',
3532
  'title_left' => '',
3533
  'title_right' => '',
3534
- "leading_context_lines" => 1,
3535
- "trailing_context_lines" => 1
3536
  );
3537
 
3538
  $args = wp_parse_args( $args, $defaults );
3539
 
3540
- if ( ! class_exists( 'WP_Text_Diff_Renderer_Table' ) )
3541
  require ABSPATH . WPINC . '/wp-diff.php';
 
3542
 
3543
  $left_string = normalize_whitespace( $left_string );
3544
  $right_string = normalize_whitespace( $right_string );
@@ -3548,45 +3537,49 @@ function simple_history_text_diff( $left_string, $right_string, $args = null ) {
3548
  $text_diff = new Text_Diff( $left_lines, $right_lines );
3549
 
3550
  $renderer = new WP_Text_Diff_Renderer_Table( $args );
3551
- $renderer->_leading_context_lines = $args["leading_context_lines"];
3552
- $renderer->_trailing_context_lines = $args["trailing_context_lines"];
3553
 
3554
  $diff = $renderer->render( $text_diff );
3555
 
3556
- if ( ! $diff )
3557
  return '';
 
3558
 
3559
- $r = "";
3560
 
3561
  $r .= "<div class='SimpleHistory__diff__contents' tabindex='0'>";
3562
  $r .= "<div class='SimpleHistory__diff__contentsInner'>";
3563
 
3564
  $r .= "<table class='diff SimpleHistory__diff'>\n";
3565
 
3566
- if ( ! empty( $args[ 'show_split_view' ] ) ) {
3567
  $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
3568
  } else {
3569
  $r .= "<col class='content' />";
3570
  }
3571
 
3572
- if ( $args['title'] || $args['title_left'] || $args['title_right'] )
3573
- $r .= "<thead>";
3574
- if ( $args['title'] )
 
3575
  $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
 
3576
  if ( $args['title_left'] || $args['title_right'] ) {
3577
  $r .= "<tr class='diff-sub-title'>\n";
3578
  $r .= "\t<td></td><th>$args[title_left]</th>\n";
3579
  $r .= "\t<td></td><th>$args[title_right]</th>\n";
3580
  $r .= "</tr>\n";
3581
  }
3582
- if ( $args['title'] || $args['title_left'] || $args['title_right'] )
3583
  $r .= "</thead>\n";
 
3584
 
3585
  $r .= "<tbody>\n$diff</div>\n</tbody>\n";
3586
- $r .= "</table>";
3587
 
3588
- $r .= "</div>";
3589
- $r .= "</div>";
3590
 
3591
  return $r;
3592
  }
7
  */
8
  class SimpleHistory {
9
 
10
+ const NAME = 'Simple History';
11
 
12
  /**
13
  * For singleton
57
  */
58
  private $arr_settings_tabs = array();
59
 
60
+ const DBTABLE = 'simple_history';
61
+ const DBTABLE_CONTEXTS = 'simple_history_contexts';
62
 
63
  /** Slug for the settings menu */
64
+ const SETTINGS_MENU_SLUG = 'simple_history_settings_menu_slug';
65
 
66
+ /** Slug for the settings menu */
67
+ const SETTINGS_GENERAL_OPTION_GROUP = 'simple_history_settings_group';
68
 
69
  /** ID for the general settings section */
70
+ const SETTINGS_SECTION_GENERAL_ID = 'simple_history_settings_section_general';
71
 
72
  function __construct() {
73
 
87
  *
88
  * @param SimpleHistory $SimpleHistory This class.
89
  */
90
+ do_action( 'simple_history/before_init', $this );
91
 
92
  $this->setup_variables();
93
 
161
  *
162
  * @param SimpleHistory $SimpleHistory This class.
163
  */
164
+ do_action( 'simple_history/after_init', $this );
165
 
166
  // Add some extra info to each logged context when SIMPLE_HISTORY_LOG_DEBUG is set and true
167
+ if ( defined( 'SIMPLE_HISTORY_LOG_DEBUG' ) && SIMPLE_HISTORY_LOG_DEBUG ) {
168
 
169
+ add_filter( 'simple_history/log_argument/context', function( $context, $level, $message, $logger ) {
170
 
171
  $sh = SimpleHistory::get_instance();
172
+ $context['_debug_get'] = $sh->json_encode( $_GET );
173
+ $context['_debug_post'] = $sh->json_encode( $_POST );
174
+ $context['_debug_server'] = $sh->json_encode( $_SERVER );
175
+ $context['_debug_files'] = $sh->json_encode( $_FILES );
176
+ $context['_debug_php_sapi_name'] = php_sapi_name();
177
 
178
  global $argv;
179
+ $context['_debug_argv'] = $sh->json_encode( $argv );
180
 
181
  $consts = get_defined_constants( true );
182
+ $consts = $consts['user'];
183
+ $context['_debug_user_constants'] = $sh->json_encode( $consts );
184
 
185
+ $postdata = file_get_contents( 'php://input' );
186
+ $context['_debug_http_raw_post_data'] = $sh->json_encode( $postdata );
187
 
188
+ $context['_debug_wp_debug_backtrace_summary'] = wp_debug_backtrace_summary();
189
+ $context['_debug_is_admin'] = json_encode( is_admin() );
190
+ $context['_debug_is_doing_cron'] = json_encode( defined( 'DOING_CRON' ) && DOING_CRON );
191
 
192
  global $wp_current_filter;
193
  $context['_debug_current_filter_array'] = $wp_current_filter;
303
  add_action( 'admin_menu', array( $this, 'add_admin_pages' ) );
304
  add_action( 'admin_menu', array( $this, 'add_settings' ) );
305
 
306
+ add_action( 'admin_footer', array( $this, 'add_js_templates' ) );
307
 
308
  add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widget' ) );
309
 
310
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
311
 
312
+ add_action( 'admin_head', array( $this, 'onAdminHead' ) );
313
+ add_action( 'admin_footer', array( $this, 'onAdminFooter' ) );
314
 
315
+ add_action( 'simple_history/history_page/before_gui', array( $this, 'output_quick_stats' ) );
316
+ add_action( 'simple_history/dashboard/before_gui', array( $this, 'output_quick_stats' ) );
317
 
318
  add_action( 'wp_ajax_simple_history_api', array( $this, 'api' ) );
319
 
320
  add_filter( 'plugin_action_links_simple-history/index.php', array( $this, 'plugin_action_links' ), 10, 4 );
321
 
 
322
  }
323
 
324
  /**
337
  *
338
  * @param bool Add item
339
  */
340
+ $add_items = apply_filters( 'simple_history/add_admin_bar_network_menu_item', true );
341
 
342
  if ( ! $add_items ) {
343
  return;
344
  }
345
 
346
  // Don't show for logged out users or single site mode.
347
+ if ( ! is_user_logged_in() || ! is_multisite() ) {
348
  return;
349
+ }
350
 
351
  // Show only when the user has at least one site, or they're a super admin.
352
+ if ( count( $wp_admin_bar->user->blogs ) < 1 && ! is_super_admin() ) {
353
  return;
354
+ }
355
 
356
  // Setting to show as page must be true
357
  if ( ! $this->setting_show_as_page() ) {
363
  return;
364
  }
365
 
366
+ /*
367
+ menu_page_url() is defined in the WordPress Plugin Administration API, which is not loaded here by default */
368
  /* dito for is_plugin_active() */
369
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
370
 
371
  foreach ( (array) $wp_admin_bar->user->blogs as $blog ) {
372
 
374
 
375
  if ( is_plugin_active( SIMPLE_HISTORY_BASENAME ) ) {
376
 
377
+ $menu_id = 'simple-history-blog-' . $blog->userblog_id;
378
  $parent_menu_id = 'blog-' . $blog->userblog_id;
379
+ $url = admin_url( 'index.php?page=simple_history_page' );
380
 
381
  // Each network site is added by WP core with id "blog-1", "blog-2" ... "blog-n"
382
  // https://codex.wordpress.org/Function_Reference/add_node
383
  $args = array(
384
  'id' => $menu_id,
385
  'parent' => $parent_menu_id,
386
+ 'title' => _x( 'View History', 'Admin bar network name', 'simple-history' ),
387
  'href' => $url,
388
  'meta' => array(
389
+ 'class' => 'ab-item--simplehistory',
390
+ ),
391
  );
392
 
393
  $wp_admin_bar->add_node( $args );
394
 
395
+ } // End if().
396
 
397
  restore_current_blog();
398
 
399
+ } // End foreach().
400
 
401
  } // func
402
 
417
  *
418
  * @param bool Add item
419
  */
420
+ $add_item = apply_filters( 'simple_history/add_admin_bar_menu_item', true );
421
 
422
  if ( ! $add_item ) {
423
  return;
424
  }
425
 
426
  // Don't show for logged out users
427
+ if ( ! is_user_logged_in() ) {
428
  return;
429
+ }
430
 
431
  // Setting to show as page must be true
432
  if ( ! $this->setting_show_as_page() ) {
438
  return;
439
  }
440
 
441
+ /*
442
+ menu_page_url() is defined in the WordPress Plugin Administration API, which is not loaded here by default */
443
  /* dito for is_plugin_active() */
444
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
445
 
446
+ $menu_id = 'simple-history-view-history';
447
  $parent_menu_id = 'site-name';
448
+ $url = admin_url( 'index.php?page=simple_history_page' );
449
 
450
  $args = array(
451
  'id' => $menu_id,
452
  'parent' => $parent_menu_id,
453
+ 'title' => _x( 'Simple History', 'Admin bar name', 'simple-history' ),
454
  'href' => $url,
455
  'meta' => array(
456
+ 'class' => 'ab-item--simplehistory',
457
+ ),
458
  );
459
 
460
  $wp_admin_bar->add_node( $args );
463
 
464
  /**
465
  * Get singleton intance
466
+ *
467
  * @return SimpleHistory instance
468
  */
469
  public static function get_instance() {
493
  // global $sh_latest_translations;
494
  $sh_latest_translations = $this->gettextLatestTranslations;
495
 
496
+ $sh_latest_translations[ $translation ] = array(
497
+ 'translation' => $translation,
498
+ 'text' => $text,
499
+ 'domain' => $domain,
500
  );
501
 
502
  $arr_length = sizeof( $sh_latest_translations );
512
 
513
  function setup_cron() {
514
 
515
+ add_filter( 'simple_history/maybe_purge_db', array( $this, 'maybe_purge_db' ) );
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)
533
 
534
  // Log that an email has been sent
535
  simple_history_add( array(
536
+ 'object_type' => 'Email',
537
+ 'object_name' => 'Hi there',
538
+ 'action' => 'was sent',
539
  ) );
540
 
541
  // Will show “Plugin your_plugin_name Edited” in the history log
542
+ simple_history_add( 'action=edited&object_type=plugin&object_name=your_plugin_name' );
543
 
544
  // Will show the history item "Starship USS Enterprise repaired"
545
+ simple_history_add( 'action=repaired&object_type=Starship&object_name=USS Enterprise' );
546
 
547
  // Log with some extra details about the email
548
  simple_history_add( array(
549
+ 'object_type' => 'Email',
550
+ 'object_name' => 'Hi there',
551
+ 'action' => 'was sent',
552
+ 'description' => 'The database query to generate the email took .3 seconds. This is email number 4 that is sent to this user',
553
  ) );
554
 
555
  }
558
 
559
  if ( $this->is_on_our_own_pages() ) {
560
 
561
+ do_action( 'simple_history/admin_head', $this );
562
 
563
  }
564
 
568
 
569
  if ( $this->is_on_our_own_pages() ) {
570
 
571
+ do_action( 'simple_history/admin_footer', $this );
572
 
573
  }
574
 
585
  <script type="text/html" id="tmpl-simple-history-base">
586
 
587
  <div class="SimpleHistory__waitingForFirstLoad">
588
+ <img src="<?php echo admin_url( '/images/spinner.gif' );?>" alt="" width="20" height="20">
589
+ <?php echo _x( 'Loading history...', 'Message visible while waiting for log to load from server the first time', 'simple-history' )?>
590
  </div>
591
 
592
  <div class="SimpleHistoryLogitemsWrap">
623
  href="#">‹</a>
624
  <span class="SimpleHistoryPaginationInput">
625
  <input class="SimpleHistoryPaginationCurrentPage" title="{{ data.strings.currentPage }}" type="text" name="paged" value="{{ data.api_args.paged }}" size="4">
626
+ <?php _x( 'of', 'page n of n', 'simple-history' )?>
627
  <span class="total-pages">{{ data.pages_count }}</span>
628
  </span>
629
  <a
647
  <div class="SimpleHistory-modal__background"></div>
648
  <div class="SimpleHistory-modal__content">
649
  <div class="SimpleHistory-modal__contentInner">
650
+ <img class="SimpleHistory-modal__contentSpinner" src="<?php echo admin_url( '/images/spinner.gif' );?>" alt="">
651
  </div>
652
  <div class="SimpleHistory-modal__contentClose">
653
  <button class="button">✕</button>
666
  <div class="SimpleHistoryLogitem__firstcol"></div>
667
  <div class="SimpleHistoryLogitem__secondcol">
668
  <div class="SimpleHistoryLogitem__text">
669
+ <?php _e( 'Sorry, but there are too many similar events to show.', 'simple-history' ); ?>
670
  <!-- <br>occasionsCount: {{ data.occasionsCount }}
671
  <br>occasionsCountMaxReturn: {{ data.occasionsCountMaxReturn }}
672
  <br>diff: {{ data.occasionsCount - data.occasionsCountMaxReturn }}
685
 
686
  // Call plugins so they can add their js
687
  foreach ( $this->instantiatedLoggers as $one_logger ) {
688
+ if ( method_exists( $one_logger['instance'], 'adminJS' ) ) {
689
+ $one_logger['instance']->adminJS();
690
  }
691
  }
692
+ }// End if().
 
693
 
694
  }
695
 
699
  *
700
  * Examples:
701
  * http://playground-root.ep/wp-admin/admin-ajax.php?action=simple_history_api&posts_per_page=5&paged=1&format=html
 
702
  */
703
  public function api() {
704
 
705
  global $wpdb;
706
 
707
  // Fake slow answers
708
+ // sleep(2);
709
+ // sleep(rand(0,3));
710
  $args = $_GET;
711
+ unset( $args['action'] );
712
 
713
  // Type = overview | ...
714
+ $type = isset( $_GET['type'] ) ? $_GET['type'] : null;
715
 
716
  if ( empty( $args ) || ! $type ) {
717
 
718
  wp_send_json_error( array(
719
+ _x( 'Not enough args specified', 'API: not enought arguments passed', 'simple-history' ),
720
  ) );
721
 
722
  }
723
 
724
  // User must have capability to view the history page
725
  if ( ! current_user_can( $this->get_view_history_capability() ) ) {
726
+ wp_send_json_error( array(
727
+ 'error' => 'CAPABILITY_ERROR',
728
+ ) );
729
  }
730
 
731
+ if ( isset( $args['id'] ) ) {
732
+ $args['post__in'] = array(
733
+ $args['id'],
734
  );
735
  }
736
 
738
 
739
  switch ( $type ) {
740
 
741
+ case 'overview':
742
+ case 'occasions':
743
+ case 'single':
744
 
745
  // API use SimpleHistoryLogQuery, so simply pass args on to that
746
  $logQuery = new SimpleHistoryLogQuery();
747
  $data = $logQuery->query( $args );
748
 
749
+ $data['api_args'] = $args;
750
 
751
  // Output can be array or HMTL
752
+ if ( isset( $args['format'] ) && 'html' === $args['format'] ) {
753
 
754
+ $data['log_rows_raw'] = array();
755
 
756
+ foreach ( $data['log_rows'] as $key => $oneLogRow ) {
757
 
758
  $args = array();
759
+ if ( $type == 'single' ) {
760
+ $args['type'] = 'single';
761
  }
762
 
763
+ $data['log_rows'][ $key ] = $this->getLogRowHTMLOutput( $oneLogRow, $args );
764
+ $data['num_queries'] = get_num_queries();
765
 
766
  }
 
767
  } else {
768
 
769
  // $data["logRows"] = $logRows;
772
  break;
773
 
774
  default:
775
+ $data[] = 'Nah.';
776
 
777
+ }// End switch().
778
 
779
  wp_send_json_success( $data );
780
 
790
  if ( isset( $this->doFilterGettext ) && $this->doFilterGettext ) {
791
 
792
  $this->doFilterGettext_currentLogger->messages[] = array(
793
+ 'untranslated_text' => $untranslated_text,
794
+ 'translated_text' => $translated_text,
795
+ 'domain' => $domain,
796
+ 'context' => null,
797
  );
798
 
799
  }
810
  if ( isset( $this->doFilterGettext ) && $this->doFilterGettext ) {
811
 
812
  $this->doFilterGettext_currentLogger->messages[] = array(
813
+ 'untranslated_text' => $untranslated_text,
814
+ 'translated_text' => $translated_text,
815
+ 'domain' => $domain,
816
+ 'context' => $context,
817
  );
818
 
819
  }
836
  // The "plugin_locale" filter is also used in load_plugin_textdomain()
837
  $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
838
  load_textdomain( $domain, WP_LANG_DIR . '/simple-history/' . $domain . '-' . $locale . '.mo' );
839
+ load_plugin_textdomain( $domain, false, dirname( $this->plugin_basename ) . '/languages/' );
840
 
841
  }
842
 
862
  */
863
  public function get_view_history_capability() {
864
 
865
+ $view_history_capability = 'edit_pages';
866
+ $view_history_capability = apply_filters( 'simple_history_view_history_capability', $view_history_capability );
867
+ $view_history_capability = apply_filters( 'simple_history/view_history_capability', $view_history_capability );
868
 
869
  return $view_history_capability;
870
 
878
  */
879
  public function get_view_settings_capability() {
880
 
881
+ $view_settings_capability = 'manage_options';
882
+ $view_settings_capability = apply_filters( 'simple_history_view_settings_capability', $view_settings_capability );
883
+ $view_settings_capability = apply_filters( 'simple_history/view_settings_capability', $view_settings_capability );
884
 
885
  return $view_settings_capability;
886
 
887
  }
888
 
889
+ /**
890
+ * Check if the current user can clear the log
891
+ * @since 2.19
892
+ * @return bool
893
+ */
894
+ public function user_can_clear_log() {
895
+ $user_can_clear_log = apply_filters( 'simple_history/user_can_clear_log', true );
896
+
897
+ return $user_can_clear_log;
898
+ }
899
+
900
  /**
901
  * Adds default tabs to settings
902
  */
906
  $this->arr_settings_tabs = array(
907
 
908
  array(
909
+ 'slug' => 'settings',
910
+ 'name' => __( 'Settings', 'simple-history' ),
911
+ 'function' => array( $this, 'settings_output_general' ),
912
  ),
913
 
914
  );
915
 
916
+ if ( defined( 'SIMPLE_HISTORY_DEV' ) && SIMPLE_HISTORY_DEV ) {
917
 
918
  $arr_dev_tabs = array(
919
  array(
920
+ 'slug' => 'log',
921
+ 'name' => __( 'Log (debug)', 'simple-history' ),
922
+ 'function' => array( $this, 'settings_output_log' ),
923
  ),
924
  array(
925
+ 'slug' => 'styles-example',
926
+ 'name' => __( 'Styles example (debug)', 'simple-history' ),
927
+ 'function' => array( $this, 'settings_output_styles_example' ),
928
  ),
929
 
930
  );
969
  */
970
  public function load_loggers() {
971
 
972
+ $loggersDir = SIMPLE_HISTORY_PATH . 'loggers/';
973
 
974
  $loggersFiles = array(
975
+ $loggersDir . 'SimpleCommentsLogger.php',
976
+ $loggersDir . 'SimpleCoreUpdatesLogger.php',
977
+ $loggersDir . 'SimpleExportLogger.php',
978
+ $loggersDir . 'SimpleLegacyLogger.php',
979
+ $loggersDir . 'SimpleLogger.php',
980
+ $loggersDir . 'SimpleMediaLogger.php',
981
+ $loggersDir . 'SimpleMenuLogger.php',
982
+ $loggersDir . 'SimpleOptionsLogger.php',
983
+ $loggersDir . 'SimplePluginLogger.php',
984
+ $loggersDir . 'SimplePostLogger.php',
985
+ $loggersDir . 'SimpleThemeLogger.php',
986
+ $loggersDir . 'SimpleUserLogger.php',
987
+ $loggersDir . 'SimpleCategoriesLogger.php',
988
+ $loggersDir . 'AvailableUpdatesLogger.php',
989
+ $loggersDir . 'FileEditsLogger.php',
990
 
991
  // Loggers for third party plugins
992
+ $loggersDir . 'PluginUserSwitchingLogger.php',
993
+ $loggersDir . 'PluginEnableMediaReplaceLogger.php',
994
+ $loggersDir . 'Plugin_UltimateMembers_Logger.php',
995
+ $loggersDir . 'Plugin_LimitLoginAttempts.php',
996
+ $loggersDir . 'Plugin_Redirection.php',
997
+ $loggersDir . 'Plugin_DuplicatePost.php',
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
1002
+ include_once $loggersDir . 'SimpleLogger.php';
1003
 
1004
  /**
1005
  * Filter the array with absolute paths to logger files to be loaded.
1011
  *
1012
  * @param array $loggersFiles Array with filenames
1013
  */
1014
+ $loggersFiles = apply_filters( 'simple_history/loggers_files', $loggersFiles );
1015
 
1016
  // Array with slug of loggers to instantiate
1017
  // Slug of logger must also be the name of the logger class
1021
 
1022
  $load_logger = true;
1023
 
1024
+ $basename_no_suffix = basename( $oneLoggerFile, '.php' );
1025
 
1026
  /**
1027
  * Filter to completely skip loading of a logger
1031
  * @param bool if to load the logger. return false to not load it.
1032
  * @param string slug of logger
1033
  */
1034
+ $load_logger = apply_filters( 'simple_history/logger/load_logger', $load_logger, $basename_no_suffix );
1035
 
1036
  if ( ! $load_logger ) {
1037
  continue;
1051
  *
1052
  * @param SimpleHistory instance
1053
  */
1054
+ do_action( 'simple_history/add_custom_logger', $this );
1055
 
1056
  $arrLoggersToInstantiate = array_merge( $arrLoggersToInstantiate, $this->externalLoggers );
1057
 
1060
  *
1061
  * Array
1062
  * (
1063
+ * [0] => SimpleCommentsLogger
1064
+ * [1] => SimpleCoreUpdatesLogger
1065
+ * ...
1066
+ * )
1067
  *
1068
  * @since 2.0
1069
  *
1070
  * @param array $arrLoggersToInstantiate Array with class names
1071
  */
1072
+ $arrLoggersToInstantiate = apply_filters( 'simple_history/loggers_to_instantiate', $arrLoggersToInstantiate );
1073
 
1074
  // Instantiate each logger
1075
  foreach ( $arrLoggersToInstantiate as $oneLoggerName ) {
1079
  }
1080
 
1081
  $loggerInstance = new $oneLoggerName( $this );
1082
+ if ( ! is_subclass_of( $loggerInstance, 'SimpleLogger' ) && ! is_a( $loggerInstance, 'SimpleLogger' ) ) {
1083
  continue;
1084
  }
1085
 
1130
 
1131
  $arr_messages_by_message_key = array();
1132
 
1133
+ if ( isset( $loggerInfo['messages'] ) ) {
1134
 
1135
+ foreach ( (array) $loggerInfo['messages'] as $message_key => $message_translated ) {
1136
 
1137
  // Find message in array with both translated and non translated strings
1138
  foreach ( $loggerInstance->messages as $one_message_with_translation_info ) {
1146
  [context] => ...
1147
  )
1148
  */
1149
+ if ( $message_translated == $one_message_with_translation_info['translated_text'] ) {
1150
  $arr_messages_by_message_key[ $message_key ] = $one_message_with_translation_info;
1151
  continue;
1152
  }
 
1153
  }
1154
  }
 
1155
  }
1156
 
1157
  $loggerInstance->messages = $arr_messages_by_message_key;
1158
 
1159
  // Add logger to array of loggers
1160
+ $this->instantiatedLoggers[ $loggerInstance->slug ] = array(
1161
+ 'name' => $loggerInfo['name'],
1162
+ 'instance' => $loggerInstance,
1163
  );
1164
 
1165
+ }// End foreach().
1166
 
1167
+ do_action( 'simple_history/loggers_loaded' );
1168
 
1169
  }
1170
 
1174
  */
1175
  public function load_dropins() {
1176
 
1177
+ $dropinsDir = SIMPLE_HISTORY_PATH . 'dropins/';
1178
 
1179
  $dropinsFiles = array(
1180
+ $dropinsDir . 'SimpleHistoryPluginPatchesDropin.php',
1181
+ $dropinsDir . 'SimpleHistoryDonateDropin.php',
1182
+ $dropinsDir . 'SimpleHistoryExportDropin.php',
1183
+ $dropinsDir . 'SimpleHistoryFilterDropin.php',
1184
+ $dropinsDir . 'SimpleHistoryIpInfoDropin.php',
1185
+ $dropinsDir . 'SimpleHistoryNewRowsNotifier.php',
1186
+ $dropinsDir . 'SimpleHistoryRSSDropin.php',
1187
+ $dropinsDir . 'SimpleHistorySettingsLogtestDropin.php',
1188
+ $dropinsDir . 'SimpleHistorySettingsStatsDropin.php',
1189
+ $dropinsDir . 'SimpleHistorySettingsDebugDropin.php',
1190
+ $dropinsDir . 'SimpleHistorySidebarDropin.php',
1191
+ $dropinsDir . 'SimpleHistorySidebarStats.php',
1192
+ $dropinsDir . 'SimpleHistorySidebarSettings.php',
1193
+ $dropinsDir . 'SimpleHistoryWPCLIDropin.php',
1194
  );
1195
 
1196
  /**
1202
  *
1203
  * @param array $dropinsFiles Array with filenames
1204
  */
1205
+ $dropinsFiles = apply_filters( 'simple_history/dropins_files', $dropinsFiles );
1206
 
1207
  $arrDropinsToInstantiate = array();
1208
 
1209
  foreach ( $dropinsFiles as $oneDropinFile ) {
1210
 
1211
  // path/path/simplehistory/dropins/SimpleHistoryDonateDropin.php => SimpleHistoryDonateDropin
1212
+ $oneDropinFileBasename = basename( $oneDropinFile, '.php' );
1213
 
1214
  $load_dropin = true;
1215
 
1232
  * @param bool if to load the dropin. return false to not load it.
1233
  * @param string slug of dropin
1234
  */
1235
+ $load_dropin = apply_filters( 'simple_history/dropin/load_dropin', $load_dropin, $oneDropinFileBasename );
1236
 
1237
  if ( ! $load_dropin ) {
1238
  continue;
1242
 
1243
  $arrDropinsToInstantiate[] = $oneDropinFileBasename;
1244
 
1245
+ }// End foreach().
1246
 
1247
  /**
1248
  * Action that dropins can use to add their custom loggers.
1252
  *
1253
  * @param array $arrDropinsToInstantiate Array with class names
1254
  */
1255
+ do_action( 'simple_history/add_custom_dropin', $this );
1256
 
1257
  /**
1258
  * Filter the array with names of dropin to instantiate.
1261
  *
1262
  * @param array $arrDropinsToInstantiate Array with class names
1263
  */
1264
+ $arrDropinsToInstantiate = apply_filters( 'simple_history/dropins_to_instantiate', $arrDropinsToInstantiate );
1265
 
1266
  $arrDropinsToInstantiate = array_merge( $arrDropinsToInstantiate, $this->externalDropins );
1267
 
1272
  continue;
1273
  }
1274
 
1275
+ $this->instantiatedDropins[ $oneDropinName ] = array(
1276
+ 'name' => $oneDropinName,
1277
+ 'instance' => new $oneDropinName( $this ),
1278
  );
1279
 
1280
  }
1289
  */
1290
  function get_pager_size() {
1291
 
1292
+ $pager_size = get_option( 'simple_history_pager_size', 20 );
1293
 
1294
  /**
1295
  * Filter the pager size setting
1298
  *
1299
  * @param int $pager_size
1300
  */
1301
+ $pager_size = apply_filters( 'simple_history/pager_size', $pager_size );
1302
 
1303
  return $pager_size;
1304
 
1314
  */
1315
  function get_pager_size_dashboard() {
1316
 
1317
+ $pager_size = get_option( 'simple_history_pager_size_dashboard', 5 );
1318
 
1319
  /**
1320
  * Filter the pager size setting
1323
  *
1324
  * @param int $pager_size
1325
  */
1326
+ $pager_size = apply_filters( 'simple_history/pager_size_dashboard', $pager_size );
1327
 
1328
  return $pager_size;
1329
 
1341
 
1342
  $settings_page_url = menu_page_url( SimpleHistory::SETTINGS_MENU_SLUG, 0 );
1343
 
1344
+ $actions[] = "<a href='$settings_page_url'>" . __( 'Settings', 'simple-history' ) . '</a>';
1345
 
1346
  return $actions;
1347
 
1363
  *
1364
  * @param bool Show the page or not
1365
  */
1366
+ $show_dashboard_widget = apply_filters( 'simple_history/show_dashboard_widget', true );
1367
 
1368
  if ( $show_dashboard_widget ) {
1369
+ wp_add_dashboard_widget( 'simple_history_dashboard_widget', __( 'Simple History', 'simple-history' ), array( $this, 'dashboard_widget_output' ) );
1370
  }
 
1371
  }
1372
  }
1373
 
1385
  *
1386
  * @param int $pager_size
1387
  */
1388
+ $pager_size = apply_filters( 'simple_history/dashboard_pager_size', $pager_size );
1389
 
1390
+ do_action( 'simple_history/dashboard/before_gui', $this );
1391
 
1392
  ?>
1393
  <div class="SimpleHistoryGui"
1397
 
1398
  }
1399
 
1400
+ function is_on_our_own_pages( $hook = '' ) {
1401
 
1402
  $current_screen = get_current_screen();
1403
 
1404
+ if ( $current_screen && $current_screen->base == 'settings_page_' . SimpleHistory::SETTINGS_MENU_SLUG ) {
1405
 
1406
  return true;
1407
 
1408
+ } elseif ( $current_screen && $current_screen->base == 'dashboard_page_simple_history_page' ) {
1409
 
1410
  return true;
1411
 
1412
+ } elseif ( ( $hook == 'settings_page_' . SimpleHistory::SETTINGS_MENU_SLUG ) || ( $this->setting_show_on_dashboard() && $hook == 'index.php' ) || ( $this->setting_show_as_page() && $hook == 'dashboard_page_simple_history_page' ) ) {
1413
 
1414
  return true;
1415
 
1416
+ } elseif ( $current_screen && $current_screen->base == 'dashboard' && $this->setting_show_on_dashboard() ) {
1417
 
1418
  return true;
1419
 
1433
 
1434
  add_thickbox();
1435
 
1436
+ wp_enqueue_style( 'simple_history_styles', SIMPLE_HISTORY_DIR_URL . 'css/styles.css', false, SIMPLE_HISTORY_VERSION );
1437
+ wp_enqueue_script( 'simple_history_script', SIMPLE_HISTORY_DIR_URL . 'js/scripts.js', array( 'jquery', 'backbone', 'wp-util' ), SIMPLE_HISTORY_VERSION, true );
1438
 
1439
+ wp_enqueue_script( 'select2', SIMPLE_HISTORY_DIR_URL . 'js/select2/select2.min.js', array( 'jquery' ) );
1440
+ wp_enqueue_style( 'select2', SIMPLE_HISTORY_DIR_URL . 'js/select2/select2.css' );
1441
 
1442
  // Translations that we use in JavaScript
1443
  wp_localize_script( 'simple_history_script', 'simple_history_script_vars', array(
1444
+ 'settingsConfirmClearLog' => __( 'Remove all log items?', 'simple-history' ),
1445
  'pagination' => array(
1446
+ 'goToTheFirstPage' => __( 'Go to the first page', 'simple-history' ),
1447
+ 'goToThePrevPage' => __( 'Go to the previous page', 'simple-history' ),
1448
+ 'goToTheNextPage' => __( 'Go to the next page', 'simple-history' ),
1449
+ 'goToTheLastPage' => __( 'Go to the last page', 'simple-history' ),
1450
+ 'currentPage' => __( 'Current page', 'simple-history' ),
1451
  ),
1452
+ 'loadLogAPIError' => __( 'Oups, the log could not be loaded right now.', 'simple-history' ),
1453
+ 'ajaxLoadError' => __( 'Hm, the log could not be loaded right now. Perhaps another plugin is giving some errors. Anyway, below is the output I got from the server.', 'simple-history' ),
1454
+ 'logNoHits' => __( 'Your search did not match any history events.', 'simple-history' ),
1455
  ) );
1456
 
1457
  // Call plugins adminCSS-method, so they can add their CSS
1458
  foreach ( $this->instantiatedLoggers as $one_logger ) {
1459
+ if ( method_exists( $one_logger['instance'], 'adminCSS' ) ) {
1460
+ $one_logger['instance']->adminCSS();
1461
  }
1462
  }
1463
 
1464
  // Add timeago.js
1465
+ wp_enqueue_script( 'timeago', SIMPLE_HISTORY_DIR_URL . 'js/timeago/jquery.timeago.js', array( 'jquery' ), '1.5.2', true );
1466
 
1467
  // Determine current locale to load timeago locale
1468
  $locale = strtolower( substr( get_locale(), 0, 2 ) );
1471
 
1472
  // Only enqueue if locale-file exists on file system
1473
  if ( file_exists( sprintf( $locale_dir_path, $locale ) ) ) {
1474
+ wp_enqueue_script( 'timeago-locale', sprintf( $locale_url_path, $locale ), array( 'jquery' ), '1.5.2', true );
1475
  } else {
1476
+ wp_enqueue_script( 'timeago-locale', sprintf( $locale_url_path, 'en' ), array( 'jquery' ), '1.5.2', true );
1477
  }
1478
  // end add timeago
 
1479
  // Load Select2 locale
1480
  $locale_url_path = SIMPLE_HISTORY_DIR_URL . 'js/select2/select2_locale_%s.js';
1481
  $locale_dir_path = SIMPLE_HISTORY_PATH . 'js/select2/select2_locale_%s.js';
1482
  if ( file_exists( sprintf( $locale_dir_path, $locale ) ) ) {
1483
+ wp_enqueue_script( 'select2-locale', sprintf( $locale_url_path, $locale ), array( 'jquery' ), '3.5.1', true );
1484
  }
1485
 
 
1486
  /**
1487
  * Fires when the admin scripts have been enqueued.
1488
  * Only fires on any of the pages where Simple History is used
1491
  *
1492
  * @param SimpleHistory $SimpleHistory This class.
1493
  */
1494
+ do_action( 'simple_history/enqueue_admin_scripts', $this );
1495
 
1496
+ }// End if().
1497
 
1498
  }
1499
 
1509
 
1510
  global $wpdb;
1511
 
1512
+ $db_version = get_option( 'simple_history_db_version' );
1513
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
1514
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
1515
  $first_install = false;
1524
 
1525
  // Table creation, used to be in register_activation_hook
1526
  // We change the varchar size to add one num just to force update of encoding. dbdelta didn't see it otherwise.
1527
+ $sql = 'CREATE TABLE ' . $table_name . ' (
1528
+ id bigint(20) NOT NULL AUTO_INCREMENT,
1529
+ date datetime NOT NULL,
1530
+ PRIMARY KEY (id)
1531
+ ) CHARACTER SET=utf8;';
1532
 
1533
  // Upgrade db / fix utf for varchars
1534
  dbDelta( $sql );
1540
  $db_version_prev = $db_version;
1541
  $db_version = 1;
1542
 
1543
+ update_option( 'simple_history_db_version', $db_version );
1544
 
1545
  // We are not 100% sure that this is a first install,
1546
  // but it is at least a very old version that is being updated
1547
  $first_install = true;
1548
 
1549
+ } // End if().
1550
 
1551
  // If db version is 1 then upgrade to 2
1552
  // Version 2 added the action_description column
1554
 
1555
  // V2 used to add column "action_description"
1556
  // but it's not used any more so don't do i
 
1557
  $db_version_prev = $db_version;
1558
  $db_version = 2;
1559
 
1560
+ update_option( 'simple_history_db_version', $db_version );
1561
 
1562
  }
1563
 
1565
  // Each option that is missing a value will make a sql call otherwise = unnecessary
1566
  $arr_options = array(
1567
  array(
1568
+ 'name' => 'simple_history_show_as_page',
1569
+ 'default_value' => 1,
1570
  ),
1571
  array(
1572
+ 'name' => 'simple_history_show_on_dashboard',
1573
+ 'default_value' => 1,
1574
  ),
1575
  );
1576
 
1577
  foreach ( $arr_options as $one_option ) {
1578
 
1579
+ if ( false === ( $option_value = get_option( $one_option['name'] ) ) ) {
1580
 
1581
  // Value is not set in db, so set it to a default
1582
+ update_option( $one_option['name'], $one_option['default_value'] );
1583
 
1584
  }
1585
  }
1629
 
1630
  $db_version_prev = $db_version;
1631
  $db_version = 3;
1632
+ update_option( 'simple_history_db_version', $db_version );
1633
 
1634
  // Update possible old items to use SimpleLegacyLogger
1635
  $sql = sprintf( '
1646
 
1647
  // Say welcome, however loggers are not added this early so we need to
1648
  // use a filter to load it later
1649
+ add_action( 'simple_history/loggers_loaded', array( $this, 'addWelcomeLogMessage' ) );
1650
 
1651
+ } // End if().
1652
 
1653
  /**
1654
  * If db version = 3
1664
 
1665
  // If old columns exist = this is an old install, then modify the columns so we still can keep them
1666
  // we want to keep them because user may have logged items that they want to keep
 
1667
  $db_cools = $wpdb->get_col( "DESCRIBE $table_name" );
1668
 
1669
+ if ( in_array( 'action', $db_cools ) ) {
1670
 
1671
  $sql = sprintf( '
1672
  ALTER TABLE %1$s
1686
  $db_version_prev = $db_version;
1687
  $db_version = 4;
1688
 
1689
+ update_option( 'simple_history_db_version', $db_version );
1690
 
1691
+ } // End if().
1692
 
1693
  // Some installs on 2.2.2 got failed installs
1694
  // We detect these by checking for db_version and then running the install stuff again
1705
 
1706
  }
1707
 
1708
+ update_option( 'simple_history_db_version', $db_version );
1709
 
1710
  }
1711
 
1741
  public function addWelcomeLogMessage() {
1742
 
1743
  $db_data_exists = $this->does_database_have_data();
1744
+ // $db_data_exists = false;
1745
+ $pluginLogger = $this->getInstantiatedLoggerBySlug( 'SimplePluginLogger' );
 
1746
  if ( $pluginLogger ) {
1747
 
1748
  // Add plugin installed message
1749
  $context = array(
1750
+ 'plugin_name' => 'Simple History',
1751
+ 'plugin_description' => 'Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.',
1752
+ 'plugin_url' => 'http://simple-history.com',
1753
+ 'plugin_version' => SIMPLE_HISTORY_VERSION,
1754
+ 'plugin_author' => 'Pär Thernström',
1755
  );
1756
 
1757
+ $pluginLogger->infoMessage( 'plugin_installed', $context );
1758
 
1759
  // Add plugin activated message
1760
+ $context['plugin_slug'] = 'simple-history';
1761
+ $context['plugin_title'] = '<a href="http://simple-history.com/">Simple History</a>';
1762
 
1763
+ $pluginLogger->infoMessage( 'plugin_activated', $context );
1764
 
1765
  }
1766
 
1767
  if ( ! $db_data_exists ) {
1768
 
1769
+ $welcome_message_1 = '
1770
  Welcome to Simple History!
1771
 
1772
  This is the main history feed. It will contain events that this plugin has logged.
1773
+ ';
1774
 
1775
+ $welcome_message_2 = '
1776
  Because Simple History was just recently installed, this feed does not contain much events yet. But keep the plugin activated and soon you will see detailed information about page edits, plugin updates, user logins, and much more.
1777
+ ';
1778
 
1779
  SimpleLogger()->info(
1780
  $welcome_message_2,
1781
  array(
1782
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
1783
  )
1784
  );
1785
 
1786
  SimpleLogger()->info(
1787
  $welcome_message_1,
1788
  array(
1789
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
1790
  )
1791
  );
1792
 
1819
 
1820
  <h1 class="SimpleHistoryPageHeadline">
1821
  <div class="dashicons dashicons-backup SimpleHistoryPageHeadline__icon"></div>
1822
+ <?php _e( 'Simple History Settings', 'simple-history' )?>
1823
  </h1>
1824
 
1825
  <?php
1826
+ $active_tab = isset( $_GET['selected-tab'] ) ? $_GET['selected-tab'] : 'settings';
1827
  $settings_base_url = menu_page_url( SimpleHistory::SETTINGS_MENU_SLUG, 0 );
1828
  ?>
1829
 
1831
  <?php
1832
  foreach ( $arr_settings_tabs as $one_tab ) {
1833
 
1834
+ $tab_slug = $one_tab['slug'];
1835
 
1836
  printf(
1837
  '<a href="%3$s" class="nav-tab %4$s">%1$s</a>',
1838
+ $one_tab['name'], // 1
1839
  $tab_slug, // 2
1840
+ esc_url( add_query_arg( 'selected-tab', $tab_slug, $settings_base_url ) ), // 3
1841
+ $active_tab == $tab_slug ? 'nav-tab-active' : ''// 4
1842
  );
1843
 
1844
  }
1848
  <?php
1849
 
1850
  // Output contents for selected tab
1851
+ $arr_active_tab = wp_filter_object_list( $arr_settings_tabs, array(
1852
+ 'slug' => $active_tab,
1853
+ ) );
1854
  $arr_active_tab = current( $arr_active_tab );
1855
 
1856
  // We must have found an active tab and it must have a callable function
1857
+ if ( ! $arr_active_tab || ! is_callable( $arr_active_tab['function'] ) ) {
1858
+ wp_die( __( 'No valid callback found', 'simple-history' ) );
1859
  }
1860
 
1861
  $args = array(
1862
+ 'arr_active_tab' => $arr_active_tab,
1863
  );
1864
 
1865
+ call_user_func_array( $arr_active_tab['function'], $args );
1866
 
1867
  ?>
1868
 
1873
 
1874
  public function settings_output_log() {
1875
 
1876
+ include SIMPLE_HISTORY_PATH . 'templates/settings-log.php';
1877
 
1878
  }
1879
 
1880
  public function settings_output_general() {
1881
 
1882
+ include SIMPLE_HISTORY_PATH . 'templates/settings-general.php';
1883
 
1884
  }
1885
 
1886
  public function settings_output_styles_example() {
1887
 
1888
+ include SIMPLE_HISTORY_PATH . 'templates/settings-style-example.php';
1889
 
1890
  }
1891
 
1912
  *
1913
  * @param bool Show the page or not
1914
  */
1915
+ $show_dashboard_page = apply_filters( 'simple_history/show_dashboard_page', true );
1916
 
1917
  if ( $show_dashboard_page ) {
1918
 
1919
  add_dashboard_page(
1920
+ _x( 'Simple History', 'dashboard title name', 'simple-history' ),
1921
+ _x( 'Simple History', 'dashboard menu name', 'simple-history' ),
1922
  $this->get_view_history_capability(),
1923
+ 'simple_history_page',
1924
+ array( $this, 'history_page_output' )
1925
  );
1926
 
1927
  }
 
1928
  }
1929
 
1930
  // Add a settings page
1931
  $show_settings_page = true;
1932
+ $show_settings_page = apply_filters( 'simple_history_show_settings_page', $show_settings_page );
1933
+ $show_settings_page = apply_filters( 'simple_history/show_settings_page', $show_settings_page );
1934
 
1935
  if ( $show_settings_page ) {
1936
 
1937
  add_options_page(
1938
+ __( 'Simple History Settings', 'simple-history' ),
1939
+ _x( 'Simple History', 'Options page menu title', 'simple-history' ),
1940
  $this->get_view_settings_capability(),
1941
  SimpleHistory::SETTINGS_MENU_SLUG,
1942
  array( $this, 'settings_page_output' )
1946
 
1947
  }
1948
 
1949
+ /**
1950
  * Add setting sections and settings for the settings page
1951
  * Also maybe save some settings before outputing them
1952
  */
1953
  function add_settings() {
1954
 
1955
+ // Clear the log if clear button was clicked in settings.
1956
+ if ( isset( $_GET['simple_history_clear_log_nonce'] ) && wp_verify_nonce( $_GET['simple_history_clear_log_nonce'], 'simple_history_clear_log' ) ) {
1957
+
1958
+ if ( $this->user_can_clear_log() ) {
1959
+ $this->clear_log();
1960
+ }
1961
+
1962
+ $msg = __( 'Cleared database', 'simple-history' );
1963
+
1964
+ add_settings_error( 'simple_history_rss_feed_regenerate_secret', 'simple_history_rss_feed_regenerate_secret', $msg, 'updated' );
1965
 
 
 
 
1966
  set_transient( 'settings_errors', get_settings_errors(), 30 );
1967
 
1968
  $goback = esc_url_raw( add_query_arg( 'settings-updated', 'true', wp_get_referer() ) );
1969
  wp_redirect( $goback );
1970
+ exit();
1971
 
1972
  }
1973
 
1974
+ // Section for general options.
1975
+ // Will contain settings like where to show simple history and number of items.
1976
  $settings_section_general_id = self::SETTINGS_SECTION_GENERAL_ID;
1977
  add_settings_section(
1978
  $settings_section_general_id,
1979
+ '',
1980
+ array( $this, 'settings_section_output' ),
1981
+ SimpleHistory::SETTINGS_MENU_SLUG // Same slug as for options menu page.
1982
  );
1983
 
1984
  // Settings for the general settings section
1985
  // Each setting = one row in the settings section
1986
  // add_settings_field( $id, $title, $callback, $page, $section, $args );
 
1987
  // Checkboxes for where to show simple history
1988
  add_settings_field(
1989
+ 'simple_history_show_where',
1990
+ __( 'Show history', 'simple-history' ),
1991
+ array( $this, 'settings_field_where_to_show' ),
1992
  SimpleHistory::SETTINGS_MENU_SLUG,
1993
  $settings_section_general_id
1994
  );
1995
 
1996
+ // Nonces for show where inputs.
1997
+ register_setting( SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP, 'simple_history_show_on_dashboard' );
1998
+ register_setting( SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP, 'simple_history_show_as_page' );
1999
 
2000
+ // Number if items to show on the history page.
2001
  add_settings_field(
2002
+ 'simple_history_number_of_items',
2003
+ __( 'Number of items per page on the log page', 'simple-history' ),
2004
+ array( $this, 'settings_field_number_of_items' ),
2005
  SimpleHistory::SETTINGS_MENU_SLUG,
2006
  $settings_section_general_id
2007
  );
2008
 
2009
+ // Nonces for number of items inputs.
2010
+ register_setting( SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP, 'simple_history_pager_size' );
 
2011
 
2012
+ // Number if items to show on dashboard.
2013
  add_settings_field(
2014
+ 'simple_history_number_of_items_dashboard',
2015
+ __( 'Number of items per page on the dashboard', 'simple-history' ),
2016
+ array( $this, 'settings_field_number_of_items_dashboard' ),
2017
  SimpleHistory::SETTINGS_MENU_SLUG,
2018
  $settings_section_general_id
2019
  );
2020
 
2021
+ // Nonces for number of items inputs.
2022
+ register_setting( SimpleHistory::SETTINGS_GENERAL_OPTION_GROUP, 'simple_history_pager_size_dashboard' );
2023
 
2024
+ // Link/button to clear log.
2025
+ if ( $this->user_can_clear_log() ) {
2026
+ add_settings_field(
2027
+ 'simple_history_clear_log',
2028
+ __( 'Clear log', 'simple-history' ),
2029
+ array( $this, 'settings_field_clear_log' ),
2030
+ SimpleHistory::SETTINGS_MENU_SLUG,
2031
+ $settings_section_general_id
2032
+ );
2033
+ }
2034
 
2035
  }
2036
 
2039
  */
2040
  function history_page_output() {
2041
 
2042
+ // global $simple_history;
2043
+ // $this->purge_db();
 
 
2044
  global $wpdb;
2045
 
2046
  $pager_size = $this->get_pager_size();
2052
  *
2053
  * @param int $pager_size
2054
  */
2055
+ $pager_size = apply_filters( 'simple_history/page_pager_size', $pager_size );
2056
 
2057
  ?>
2058
 
2060
 
2061
  <h1 class="SimpleHistoryPageHeadline">
2062
  <div class="dashicons dashicons-backup SimpleHistoryPageHeadline__icon"></div>
2063
+ <?php echo _x( 'Simple History', 'history page headline', 'simple-history' )?>
2064
  </h1>
2065
 
2066
  <?php
2071
  *
2072
  * @param SimpleHistory $SimpleHistory This class.
2073
  */
2074
+ do_action( 'simple_history/history_page/before_gui', $this );
2075
  ?>
2076
 
2077
  <div class="SimpleHistoryGuiWrap">
2082
 
2083
  <?php
2084
 
2085
+ /**
2086
+ * Fires after the gui div
2087
+ *
2088
+ * @since 2.0
2089
+ *
2090
+ * @param SimpleHistory $SimpleHistory This class.
2091
+ */
2092
+ do_action( 'simple_history/history_page/after_gui', $this );
2093
 
2094
  ?>
2095
 
2109
  */
2110
  function setting_show_on_dashboard() {
2111
 
2112
+ $show_on_dashboard = get_option( 'simple_history_show_on_dashboard', 1 );
2113
+ $show_on_dashboard = apply_filters( 'simple_history_show_on_dashboard', $show_on_dashboard );
2114
  return (bool) $show_on_dashboard;
2115
 
2116
  }
2123
  */
2124
  function setting_show_as_page() {
2125
 
2126
+ $setting = get_option( 'simple_history_show_as_page', 1 );
2127
+ $setting = apply_filters( 'simple_history_show_as_page', $setting );
2128
 
2129
  return (bool) $setting;
2130
 
2139
 
2140
  ?>
2141
  <select name="simple_history_pager_size">
2142
+ <option <?php echo $current_pager_size == 5 ? 'selected' : ''?> value="5">5</option>
2143
+ <option <?php echo $current_pager_size == 10 ? 'selected' : ''?> value="10">10</option>
2144
+ <option <?php echo $current_pager_size == 15 ? 'selected' : ''?> value="15">15</option>
2145
+ <option <?php echo $current_pager_size == 20 ? 'selected' : ''?> value="20">20</option>
2146
+ <option <?php echo $current_pager_size == 25 ? 'selected' : ''?> value="25">25</option>
2147
+ <option <?php echo $current_pager_size == 30 ? 'selected' : ''?> value="30">30</option>
2148
+ <option <?php echo $current_pager_size == 40 ? 'selected' : ''?> value="40">40</option>
2149
+ <option <?php echo $current_pager_size == 50 ? 'selected' : ''?> value="50">50</option>
2150
+ <option <?php echo $current_pager_size == 75 ? 'selected' : ''?> value="75">75</option>
2151
+ <option <?php echo $current_pager_size == 100 ? 'selected' : ''?> value="100">100</option>
2152
  </select>
2153
  <?php
2154
 
2163
 
2164
  ?>
2165
  <select name="simple_history_pager_size_dashboard">
2166
+ <option <?php echo $current_pager_size == 5 ? 'selected' : ''?> value="5">5</option>
2167
+ <option <?php echo $current_pager_size == 10 ? 'selected' : ''?> value="10">10</option>
2168
+ <option <?php echo $current_pager_size == 15 ? 'selected' : ''?> value="15">15</option>
2169
+ <option <?php echo $current_pager_size == 20 ? 'selected' : ''?> value="20">20</option>
2170
+ <option <?php echo $current_pager_size == 25 ? 'selected' : ''?> value="25">25</option>
2171
+ <option <?php echo $current_pager_size == 30 ? 'selected' : ''?> value="30">30</option>
2172
+ <option <?php echo $current_pager_size == 40 ? 'selected' : ''?> value="40">40</option>
2173
+ <option <?php echo $current_pager_size == 50 ? 'selected' : ''?> value="50">50</option>
2174
+ <option <?php echo $current_pager_size == 75 ? 'selected' : ''?> value="75">75</option>
2175
+ <option <?php echo $current_pager_size == 100 ? 'selected' : ''?> value="100">100</option>
2176
  </select>
2177
  <?php
2178
 
2188
 
2189
  ?>
2190
 
2191
+ <input <?php echo $show_on_dashboard ? "checked='checked'" : ''?> type="checkbox" value="1" name="simple_history_show_on_dashboard" id="simple_history_show_on_dashboard" class="simple_history_show_on_dashboard" />
2192
+ <label for="simple_history_show_on_dashboard"><?php _e( 'on the dashboard', 'simple-history' )?></label>
2193
 
2194
  <br />
2195
 
2196
+ <input <?php echo $show_as_page ? "checked='checked'" : ''?> type="checkbox" value="1" name="simple_history_show_as_page" id="simple_history_show_as_page" class="simple_history_show_as_page" />
2197
+ <label for="simple_history_show_as_page"><?php _e( 'as a page under the dashboard menu', 'simple-history' )?></label>
2198
 
2199
  <?php
2200
+ }
2201
 
2202
  /**
2203
  * Settings section to clear database
2204
  */
2205
  function settings_field_clear_log() {
2206
 
2207
+ $clear_link = esc_url( add_query_arg( '', '' ) );
2208
+ $clear_link = wp_nonce_url( $clear_link, 'simple_history_clear_log', 'simple_history_clear_log_nonce' );
2209
  $clear_days = $this->get_clear_history_interval();
2210
 
2211
+ echo '<p>';
2212
+
2213
  if ( $clear_days > 0 ) {
2214
+ echo sprintf( __( 'Items in the database are automatically removed after %1$s days.', 'simple-history' ), $clear_days );
2215
  } else {
2216
  _e( 'Items in the database are kept forever.', 'simple-history' );
2217
  }
2218
+
2219
+ echo '</p>';
2220
 
2221
  printf( '<p><a class="button js-SimpleHistory-Settings-ClearLog" href="%2$s">%1$s</a></p>', __( 'Clear log now', 'simple-history' ), $clear_link );
2222
  }
2237
  *
2238
  * @param $days Number of days of history to keep
2239
  */
2240
+ $days = (int) apply_filters( 'simple_history_db_purge_days_interval', $days );
2241
+ $days = (int) apply_filters( 'simple_history/db_purge_days_interval', $days );
2242
 
2243
  return $days;
2244
 
2256
  $simple_history_table = SimpleHistory::DBTABLE;
2257
  $simple_history_context_table = SimpleHistory::DBTABLE_CONTEXTS;
2258
 
2259
+ // Get number of rows before delete.
2260
  $sql_num_rows = "SELECT count(id) AS num_rows FROM {$tableprefix}{$simple_history_table}";
2261
  $num_rows = $wpdb->get_var( $sql_num_rows, 0 );
2262
 
2263
+ // Use truncate instead of delete because it's much faster (I think, writing this much later).
2264
  $sql = "TRUNCATE {$tableprefix}{$simple_history_table}";
2265
  $wpdb->query( $sql );
2266
 
 
2267
  $sql = "TRUNCATE {$tableprefix}{$simple_history_context_table}";
2268
  $wpdb->query( $sql );
2269
 
2270
  // Zero state sucks
2271
  SimpleLogger()->info(
2272
+ __( 'The log for Simple History was cleared ({num_rows} rows were removed).', 'simple-history' ),
2273
  array(
2274
+ 'num_rows' => $num_rows,
2275
  )
2276
  );
2277
 
2287
  */
2288
  function maybe_purge_db() {
2289
 
 
 
 
 
2290
  // How often should we try to do this?
2291
+ // Once a day = a bit tiresome.
2292
+ // Let's go with sundays; purge the log on sundays.
2293
+ // Day of week, 1 = mon, 7 = sun.
 
2294
  $day_of_week = date( 'N' );
2295
  if ( 7 === (int) $day_of_week ) {
2296
 
2305
  */
2306
  function purge_db() {
2307
 
 
 
2308
  $do_purge_history = true;
2309
 
2310
+ $do_purge_history = apply_filters( 'simple_history_allow_db_purge', $do_purge_history );
2311
+ $do_purge_history = apply_filters( 'simple_history/allow_db_purge', $do_purge_history );
2312
 
2313
  if ( ! $do_purge_history ) {
2314
  return;
2339
  return;
2340
  }
2341
 
2342
+ $sql_ids_in = implode( ',', $ids_to_delete );
2343
 
2344
  // Add number of deleted rows to total_rows option
2345
+ $prev_total_rows = (int) get_option( 'simple_history_total_rows', 0 );
2346
  $total_rows = $prev_total_rows + sizeof( $ids_to_delete );
2347
+ update_option( 'simple_history_total_rows', $total_rows );
2348
 
2349
  // Remove rows + contexts
2350
  $sql_delete_history = "DELETE FROM {$table_name} WHERE id IN ($sql_ids_in)";
2354
  $wpdb->query( $sql_delete_history_context );
2355
 
2356
  $message = _nx(
2357
+ 'Simple History removed one event that were older than {days} days',
2358
+ 'Simple History removed {num_rows} events that were older than {days} days',
2359
+ 'Database is being cleared automagically',
2360
+ 'simple-history'
2361
  );
2362
 
2363
  SimpleLogger()->info(
2364
  $message,
2365
  array(
2366
+ 'days' => $days,
2367
+ 'num_rows' => sizeof( $ids_to_delete ),
2368
  )
2369
  );
2370
 
2386
  $logger = null;
2387
  $row->context = isset( $row->context ) && is_array( $row->context ) ? $row->context : array();
2388
 
2389
+ if ( ! isset( $row->context['_message_key'] ) ) {
2390
+ $row->context['_message_key'] = null;
2391
  }
2392
 
2393
  // Fallback to SimpleLogger if no logger exists for row
2394
+ if ( ! isset( $this->instantiatedLoggers[ $row_logger ] ) ) {
2395
+ $row_logger = 'SimpleLogger';
2396
  }
2397
 
2398
+ $logger = $this->instantiatedLoggers[ $row_logger ]['instance'];
2399
 
2400
  return $logger->getLogRowPlainTextOutput( $row );
2401
 
2419
  $row->context = isset( $row->context ) && is_array( $row->context ) ? $row->context : array();
2420
 
2421
  // Fallback to SimpleLogger if no logger exists for row
2422
+ if ( ! isset( $this->instantiatedLoggers[ $row_logger ] ) ) {
2423
+ $row_logger = 'SimpleLogger';
2424
  }
2425
 
2426
+ $logger = $this->instantiatedLoggers[ $row_logger ]['instance'];
2427
 
2428
  return $logger->getLogRowHeaderOutput( $row );
2429
 
2442
  $row->context = isset( $row->context ) && is_array( $row->context ) ? $row->context : array();
2443
 
2444
  // Fallback to SimpleLogger if no logger exists for row
2445
+ if ( ! isset( $this->instantiatedLoggers[ $row_logger ] ) ) {
2446
+ $row_logger = 'SimpleLogger';
2447
  }
2448
 
2449
+ $logger = $this->instantiatedLoggers[ $row_logger ]['instance'];
2450
 
2451
  return $logger->getLogRowSenderImageOutput( $row );
2452
 
2459
  $row->context = isset( $row->context ) && is_array( $row->context ) ? $row->context : array();
2460
 
2461
  // Fallback to SimpleLogger if no logger exists for row
2462
+ if ( ! isset( $this->instantiatedLoggers[ $row_logger ] ) ) {
2463
+ $row_logger = 'SimpleLogger';
2464
  }
2465
 
2466
+ $logger = $this->instantiatedLoggers[ $row_logger ]['instance'];
2467
 
2468
  return $logger->getLogRowDetailsOutput( $row );
2469
 
2483
 
2484
  /**
2485
  * Returns true if $haystack ends with $needle
2486
+ *
2487
  * @param string $haystack
2488
  * @param string $needle
2489
  */
2500
  public function getLogRowHTMLOutput( $oneLogRow, $args ) {
2501
 
2502
  $defaults = array(
2503
+ 'type' => 'overview', // or "single" to include more stuff
2504
  );
2505
 
2506
  $args = wp_parse_args( $args, $defaults );
2522
 
2523
  // subsequentOccasions = including the current one
2524
  $occasions_count = $oneLogRow->subsequentOccasions - 1;
2525
+ $occasions_html = '';
2526
 
2527
  if ( $occasions_count > 0 ) {
2528
 
2530
 
2531
  $occasions_html .= '<a href="#" class="SimpleHistoryLogitem__occasionsLink">';
2532
  $occasions_html .= sprintf(
2533
+ _n( '+%1$s similar event', '+%1$s similar events', $occasions_count, 'simple-history' ),
2534
  $occasions_count
2535
  );
2536
  $occasions_html .= '</a>';
2537
 
2538
  $occasions_html .= '<span class="SimpleHistoryLogitem__occasionsLoading">';
2539
  $occasions_html .= sprintf(
2540
+ __( 'Loading…', 'simple-history' ),
2541
  $occasions_count
2542
  );
2543
  $occasions_html .= '</span>';
2544
 
2545
  $occasions_html .= '<span class="SimpleHistoryLogitem__occasionsLoaded">';
2546
  $occasions_html .= sprintf(
2547
+ __( 'Showing %1$s more', 'simple-history' ),
2548
  $occasions_count
2549
  );
2550
  $occasions_html .= '</span>';
2554
  }
2555
 
2556
  // Add data atributes to log row, so plugins can do stuff
2557
+ $data_attrs = '';
2558
  $data_attrs .= sprintf( ' data-row-id="%1$d" ', $oneLogRow->id );
2559
  $data_attrs .= sprintf( ' data-occasions-count="%1$d" ', $occasions_count );
2560
  $data_attrs .= sprintf( ' data-occasions-id="%1$s" ', esc_attr( $oneLogRow->occasionsID ) );
2561
 
2562
+ if ( isset( $oneLogRow->context['_server_remote_addr'] ) ) {
2563
+ $data_attrs .= sprintf( ' data-ip-address="%1$s" ', esc_attr( $oneLogRow->context['_server_remote_addr'] ) );
2564
  }
2565
 
2566
+ $arr_found_additional_ip_headers = $this->instantiatedLoggers['SimpleLogger']['instance']->get_event_ip_number_headers( $oneLogRow );
2567
  if ( $arr_found_additional_ip_headers ) {
2568
  $data_attrs .= sprintf( ' data-ip-address-multiple="1" ' );
2569
  }
2573
  $data_attrs .= sprintf( ' data-date="%1$s" ', esc_attr( $oneLogRow->date ) );
2574
  $data_attrs .= sprintf( ' data-initiator="%1$s" ', esc_attr( $oneLogRow->initiator ) );
2575
 
2576
+ if ( isset( $oneLogRow->context['_user_id'] ) ) {
2577
+ $data_attrs .= sprintf( ' data-initiator-user-id="%1$d" ', $oneLogRow->context['_user_id'] );
2578
  }
2579
 
2580
  // If type is single then include more details
2581
+ $more_details_html = '';
2582
+ if ( $args['type'] == 'single' ) {
2583
 
2584
+ $more_details_html = apply_filters( 'simple_history/log_html_output_details_single/html_before_context_table', $more_details_html, $oneLogRow );
2585
 
2586
+ $more_details_html .= sprintf( '<h2 class="SimpleHistoryLogitem__moreDetailsHeadline">%1$s</h2>', __( 'Context data', 'simple-history' ) );
2587
+ $more_details_html .= '<p>' . __( 'This is potentially useful meta data that a logger has saved.', 'simple-history' ) . '</p>';
2588
  $more_details_html .= "<table class='SimpleHistoryLogitem__moreDetailsContext'>";
2589
  $more_details_html .= sprintf(
2590
  '<tr>
2591
  <th>%1$s</th>
2592
  <th>%2$s</th>
2593
  </tr>',
2594
+ 'Key',
2595
+ 'Value'
2596
  );
2597
 
2598
  $logRowKeysToShow = array_fill_keys( array_keys( (array) $oneLogRow ), true );
2602
  *
2603
  * Array is in format
2604
  *
2605
+ * Array
2606
+ * (
2607
+ * [id] => 1
2608
+ * [logger] => 1
2609
+ * [level] => 1
2610
+ * ...
2611
+ * )
 
2612
  *
2613
  * @since 2.0.29
2614
  *
2615
  * @param array with keys to show. key to show = key. value = boolean to show or not.
2616
  * @param object log row to show details from
2617
  */
2618
+ $logRowKeysToShow = apply_filters( 'simple_history/log_html_output_details_table/row_keys_to_show', $logRowKeysToShow, $oneLogRow );
2619
 
2620
  // Hide some keys by default
2621
  unset(
2622
+ $logRowKeysToShow['occasionsID'],
2623
+ $logRowKeysToShow['subsequentOccasions'],
2624
+ $logRowKeysToShow['rep'],
2625
+ $logRowKeysToShow['repeated'],
2626
+ $logRowKeysToShow['occasionsIDType'],
2627
+ $logRowKeysToShow['context'],
2628
+ $logRowKeysToShow['type']
2629
  );
2630
 
 
2631
  foreach ( $oneLogRow as $rowKey => $rowVal ) {
2632
 
2633
  // Only columns from oneLogRow that exist in logRowKeysToShow will be outputed
2634
+ if ( ! array_key_exists( $rowKey, $logRowKeysToShow ) || ! $logRowKeysToShow[ $rowKey ] ) {
2635
  continue;
2636
  }
2637
 
2651
 
2652
  }
2653
 
 
2654
  $logRowContextKeysToShow = array_fill_keys( array_keys( (array) $oneLogRow->context ), true );
2655
  /*
2656
  error_log($this->json_encode($logRowContextKeysToShow));
2676
  *
2677
  * Array is in format
2678
  *
2679
+ * Array
2680
+ * (
2681
  * [plugin_slug] => 1
2682
  * [plugin_name] => 1
2683
  * [plugin_title] => 1
2684
  * [plugin_description] => 1
2685
  * [plugin_author] => 1
2686
  * [plugin_version] => 1
2687
+ * ...
2688
+ * )
 
2689
  *
2690
  * @since 2.0.29
2691
  *
2692
  * @param array with keys to show. key to show = key. value = boolean to show or not.
2693
  * @param object log row to show details from
2694
  */
2695
+ $logRowContextKeysToShow = apply_filters( 'simple_history/log_html_output_details_table/context_keys_to_show', $logRowContextKeysToShow, $oneLogRow );
2696
 
2697
  foreach ( $oneLogRow->context as $contextKey => $contextVal ) {
2698
 
2699
  // Only columns from context that exist in logRowContextKeysToShow will be outputed
2700
+ if ( ! array_key_exists( $contextKey, $logRowContextKeysToShow ) || ! $logRowContextKeysToShow[ $contextKey ] ) {
2701
  continue;
2702
  }
2703
 
2712
 
2713
  }
2714
 
2715
+ $more_details_html .= '</table>';
2716
 
2717
+ $more_details_html = apply_filters( 'simple_history/log_html_output_details_single/html_after_context_table', $more_details_html, $oneLogRow );
2718
 
2719
  $more_details_html = sprintf(
2720
  '<div class="SimpleHistoryLogitem__moreDetails">%1$s</div>',
2721
  $more_details_html
2722
  );
2723
 
2724
+ }// End if().
2725
 
2726
  // Classes to add to log item li element
2727
  $classes = array(
2728
+ 'SimpleHistoryLogitem',
2729
  "SimpleHistoryLogitem--loglevel-{$oneLogRow->level}",
2730
  "SimpleHistoryLogitem--logger-{$oneLogRow->logger}",
2731
  );
2732
 
2733
  if ( isset( $oneLogRow->initiator ) && ! empty( $oneLogRow->initiator ) ) {
2734
+ $classes[] = 'SimpleHistoryLogitem--initiator-' . $oneLogRow->initiator;
2735
  }
2736
 
2737
  if ( $arr_found_additional_ip_headers ) {
2738
+ $classes[] = 'SimpleHistoryLogitem--IPAddress-multiple';
2739
  }
2740
 
2741
  // Always append the log level tag
2754
  *
2755
  * @param $classes Array with classes
2756
  */
2757
+ $classes = apply_filters( 'simple_history/logrowhtmloutput/classes', $classes );
2758
 
2759
  // Generate the HTML output for a row
2760
  $output = sprintf(
2781
  $oneLogRow->logger, // 7
2782
  $data_attrs, // 8 data attributes
2783
  $more_details_html, // 9
2784
+ esc_attr( join( ' ', $classes ) ) // 10
2785
  );
2786
 
2787
  // Get the main message row.
2788
  // Should be as plain as possible, like plain text
2789
  // but with links to for example users and posts
2790
+ // SimpleLoggerFormatter::getRowTextOutput($oneLogRow);
 
2791
  // Get detailed HTML-based output
2792
  // May include images, lists, any cool stuff needed to view
2793
+ // SimpleLoggerFormatter::getRowHTMLOutput($oneLogRow);
 
2794
  return trim( $output );
2795
 
2796
  }
2804
  */
2805
  function getLogLevelTranslated( $loglevel ) {
2806
 
2807
+ $str_translated = '';
2808
 
2809
  switch ( $loglevel ) {
2810
 
2811
  // Lowercase
2812
+ case 'emergency':
2813
+ $str_translated = _x( 'emergency', 'Log level in gui', 'simple-history' );
2814
  break;
2815
 
2816
+ case 'alert':
2817
+ $str_translated = _x( 'alert', 'Log level in gui', 'simple-history' );
2818
  break;
2819
 
2820
+ case 'critical':
2821
+ $str_translated = _x( 'critical', 'Log level in gui', 'simple-history' );
2822
  break;
2823
 
2824
+ case 'error':
2825
+ $str_translated = _x( 'error', 'Log level in gui', 'simple-history' );
2826
  break;
2827
 
2828
+ case 'warning':
2829
+ $str_translated = _x( 'warning', 'Log level in gui', 'simple-history' );
2830
  break;
2831
 
2832
+ case 'notice':
2833
+ $str_translated = _x( 'notice', 'Log level in gui', 'simple-history' );
2834
  break;
2835
 
2836
+ case 'info':
2837
+ $str_translated = _x( 'info', 'Log level in gui', 'simple-history' );
2838
  break;
2839
 
2840
+ case 'debug':
2841
+ $str_translated = _x( 'debug', 'Log level in gui', 'simple-history' );
2842
  break;
2843
 
2844
  // Uppercase
2845
+ case 'Emergency':
2846
+ $str_translated = _x( 'Emergency', 'Log level in gui', 'simple-history' );
2847
  break;
2848
 
2849
+ case 'Alert':
2850
+ $str_translated = _x( 'Alert', 'Log level in gui', 'simple-history' );
2851
  break;
2852
 
2853
+ case 'Critical':
2854
+ $str_translated = _x( 'Critical', 'Log level in gui', 'simple-history' );
2855
  break;
2856
 
2857
+ case 'Error':
2858
+ $str_translated = _x( 'Error', 'Log level in gui', 'simple-history' );
2859
  break;
2860
 
2861
+ case 'Warning':
2862
+ $str_translated = _x( 'Warning', 'Log level in gui', 'simple-history' );
2863
  break;
2864
 
2865
+ case 'Notice':
2866
+ $str_translated = _x( 'Notice', 'Log level in gui', 'simple-history' );
2867
  break;
2868
 
2869
+ case 'Info':
2870
+ $str_translated = _x( 'Info', 'Log level in gui', 'simple-history' );
2871
  break;
2872
 
2873
+ case 'Debug':
2874
+ $str_translated = _x( 'Debug', 'Log level in gui', 'simple-history' );
2875
  break;
2876
 
2877
  default:
2878
  $str_translated = $loglevel;
2879
 
2880
+ }// End switch().
2881
 
2882
  return $str_translated;
2883
 
2896
  }
2897
 
2898
 
2899
+ public function getInstantiatedLoggerBySlug( $slug = '' ) {
2900
 
2901
  if ( empty( $slug ) ) {
2902
  return false;
2904
 
2905
  foreach ( $this->getInstantiatedLoggers() as $one_logger ) {
2906
 
2907
+ if ( $slug == $one_logger['instance']->slug ) {
2908
+ return $one_logger['instance'];
2909
  }
 
2910
  }
2911
 
2912
  return false;
2917
  * Check which loggers a user has the right to read and return an array
2918
  * with all loggers they are allowed to read
2919
  *
2920
+ * @param int $user_id Id of user to get loggers for. Defaults to current user id.
2921
  * @param string $format format to return loggers in. Default is array. Can also be "sql"
2922
  * @return array
2923
  */
2924
+ public function getLoggersThatUserCanRead( $user_id = '', $format = 'array' ) {
2925
 
2926
  $arr_loggers_user_can_view = array();
2927
 
2932
  $loggers = $this->getInstantiatedLoggers();
2933
  foreach ( $loggers as $one_logger ) {
2934
 
2935
+ $logger_capability = $one_logger['instance']->getCapability();
2936
 
2937
+ // $arr_loggers_user_can_view = apply_filters("simple_history/loggers_user_can_read", $user_id, $arr_loggers_user_can_view);
2938
  $user_can_read_logger = user_can( $user_id, $logger_capability );
2939
+ $user_can_read_logger = apply_filters( 'simple_history/loggers_user_can_read/can_read_single_logger', $user_can_read_logger, $one_logger['instance'], $user_id );
2940
 
2941
  if ( $user_can_read_logger ) {
2942
  $arr_loggers_user_can_view[] = $one_logger;
2943
  }
 
2944
  }
2945
 
2946
  /**
2951
  * @param array $arr_loggers_user_can_view Array with loggers that user $user_id can read
2952
  * @param int user_id ID of user to check read capability for
2953
  */
2954
+ $arr_loggers_user_can_view = apply_filters( 'simple_history/loggers_user_can_read', $arr_loggers_user_can_view, $user_id );
2955
 
2956
  // just return array with slugs in parenthesis suitable for sql-where
2957
+ if ( 'sql' == $format ) {
2958
 
2959
+ $str_return = '(';
2960
 
2961
  if ( sizeof( $arr_loggers_user_can_view ) ) {
2962
 
2964
 
2965
  $str_return .= sprintf(
2966
  '"%1$s", ',
2967
+ esc_sql( $one_logger['instance']->slug )
2968
  );
2969
 
2970
  }
2971
 
2972
+ $str_return = rtrim( $str_return, ' ,' );
2973
 
2974
  } else {
2975
 
2978
 
2979
  }
2980
 
2981
+ $str_return .= ')';
2982
 
2983
  return $str_return;
2984
 
2996
  * @since 2.0
2997
  *
2998
  * @param string $email email address
2999
+ * @param int $size Size of the avatar image
3000
  * @param string $default URL to a default image to use if no avatar is available
3001
  * @param string $alt Alternative text to use in image tag. Defaults to blank
3002
  * @return string <img> tag for the user's avatar
3013
  } else {
3014
 
3015
  // WP setting for avatar was to not show, but we do it anyway, using the same code as get_avatar() would have used
 
3016
  if ( false === $alt ) {
3017
  $safe_alt = '';
3018
  } else {
3030
  } else {
3031
  $default = $avatar_default;
3032
  }
 
3033
  }
3034
 
3035
  if ( ! empty( $email ) ) {
3040
  $host = 'https://secure.gravatar.com';
3041
  } else {
3042
  if ( ! empty( $email ) ) {
3043
+ $host = sprintf( 'http://%d.gravatar.com', ( hexdec( $email_hash[0] ) % 2 ) );
3044
  } else {
3045
  $host = 'http://0.gravatar.com';
3046
  }
 
3047
  }
3048
 
3049
  if ( 'mystery' == $default ) {
3050
  $default = "$host/avatar/ad516503a11cd5ca435acc9bb6523536?s={$size}";
3051
+ } // End if().
 
3052
  elseif ( 'blank' == $default ) {
3053
  $default = $email ? 'blank' : includes_url( 'images/blank.gif' );
3054
  } elseif ( ! empty( $email ) && 'gravatar_default' == $default ) {
3095
 
3096
  return $avatar;
3097
 
3098
+ } // End if().
3099
 
3100
  }
3101
 
3110
  // Get number of events today
3111
  $logQuery = new SimpleHistoryLogQuery();
3112
  $logResults = $logQuery->query( array(
3113
+ 'posts_per_page' => 1,
3114
+ 'date_from' => strtotime( 'today' ),
3115
  ) );
3116
 
3117
+ $total_row_count = (int) $logResults['total_row_count'];
3118
 
3119
  // Get sql query for where to read only loggers current user is allowed to read/view
3120
+ $sql_loggers_in = $this->getLoggersThatUserCanRead( get_current_user_id(), 'sql' );
3121
 
3122
  // Get number of users today, i.e. events with wp_user as initiator
3123
  $sql_users_today = sprintf( '
3133
  AND date > "%2$s"
3134
  ',
3135
  $sql_loggers_in,
3136
+ date( 'Y-m-d H:i', strtotime( 'today' ) ),
3137
  $wpdb->prefix . SimpleHistory::DBTABLE,
3138
  $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS
3139
  );
3140
 
3141
+ $cache_key = 'quick_stats_users_today_' . md5( serialize( $sql_loggers_in ) );
3142
+ $cache_group = 'simple-history-' . $this->get_cache_incrementor();
3143
  $results_users_today = wp_cache_get( $cache_key, $cache_group );
3144
 
3145
  if ( false === $results_users_today ) {
3157
  AND date > "%2$s"
3158
  ',
3159
  $sql_loggers_in,
3160
+ date( 'Y-m-d H:i', strtotime( 'today' ) ),
3161
  $wpdb->prefix . SimpleHistory::DBTABLE,
3162
  $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS
3163
  );
3164
 
3165
+ $sql_other_sources_where = apply_filters( 'simple_history/quick_stats_where', $sql_other_sources_where );
3166
 
3167
  $sql_other_sources = sprintf( '
3168
  SELECT
3172
  %5$s
3173
  ',
3174
  $sql_loggers_in,
3175
+ date( 'Y-m-d H:i', strtotime( 'today' ) ),
3176
  $wpdb->prefix . SimpleHistory::DBTABLE,
3177
  $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS,
3178
  $sql_other_sources_where // 5
3179
  );
3180
  // sf_d($sql_other_sources, '$sql_other_sources');
3181
+ $cache_key = 'quick_stats_results_other_sources_today_' . md5( serialize( $sql_other_sources ) );
 
3182
  $results_other_sources_today = wp_cache_get( $cache_key, $cache_group );
3183
 
3184
  if ( false === $results_other_sources_today ) {
3190
 
3191
  $count_other_sources = sizeof( $results_other_sources_today );
3192
 
3193
+ // sf_d($logResults, '$logResults');
3194
+ // sf_d($results_users_today, '$sql_users_today');
3195
+ // sf_d($results_other_sources_today, '$results_other_sources_today');
 
3196
  ?>
3197
  <div class="SimpleHistoryQuickStats">
3198
  <p>
3199
  <?php
3200
 
3201
+ $msg_tmpl = '';
3202
 
3203
  // No results today at all
3204
  if ( $total_row_count == 0 ) {
3205
 
3206
+ $msg_tmpl = __( 'No events today so far.', 'simple-history' );
3207
 
3208
  } else {
3209
 
3222
  // A single event existed and was from a user
3223
  // 1 event today from 1 user.
3224
  if ( $total_row_count == 1 && $count_users_today == 1 ) {
3225
+ $msg_tmpl .= __( 'One event today from one user.', 'simple-history' );
3226
  }
3227
 
3228
  // A single event existed and was from another source
3229
  // 1 event today from 1 source.
3230
  if ( $total_row_count == 1 && ! $count_users_today ) {
3231
+ $msg_tmpl .= __( 'One event today from one source.', 'simple-history' );
3232
  }
3233
 
3234
  // Multiple events from a single user
3235
  // 3 events today from one user.
3236
  if ( $total_row_count > 1 && $count_users_today == 1 && ! $count_other_sources ) {
3237
+ $msg_tmpl .= __( '%1$d events today from one user.', 'simple-history' );
3238
  }
3239
 
3240
  // Multiple events from only users
3241
  // 2 events today from 2 users.
3242
  if ( $total_row_count > 1 && $count_users_today == $total_row_count ) {
3243
+ $msg_tmpl .= __( '%1$d events today from %2$d users.', 'simple-history' );
3244
  }
3245
 
3246
  // Multiple events from 1 single user and 1 single other source
3247
  // 2 events today from 1 user and 1 other source.
3248
  if ( $total_row_count && 1 == $count_users_today && 1 == $count_other_sources ) {
3249
+ $msg_tmpl .= __( '%1$d events today from one user and one other source.', 'simple-history' );
3250
  }
3251
 
3252
  // Multiple events from multple users but from only 1 single other source
3253
  // 3 events today from 2 users and 1 other source.
3254
  if ( $total_row_count > 1 && $count_users_today > 1 && $count_other_sources == 1 ) {
3255
+ $msg_tmpl .= __( '%1$d events today from one user and one other source.', 'simple-history' );
3256
  }
3257
 
3258
  // Multiple events from 1 user but from multiple other source
3259
  // 3 events today from 1 user and 2 other sources.
3260
  if ( $total_row_count > 1 && 1 == $count_users_today && $count_other_sources > 1 ) {
3261
+ $msg_tmpl .= __( '%1$d events today from one user and %3$d other sources.', 'simple-history' );
3262
  }
3263
 
3264
  // Multiple events from multiple user and from multiple other sources
3265
  // 4 events today from 2 users and 2 other sources.
3266
  if ( $total_row_count > 1 && $count_users_today > 1 && $count_other_sources > 1 ) {
3267
+ $msg_tmpl .= __( '%1$s events today from %2$d users and %3$d other sources.', 'simple-history' );
3268
  }
3269
+ }// End if().
 
3270
 
3271
  // only show stats if we have something to output
3272
  if ( $msg_tmpl ) {
3273
 
3274
  printf(
3275
  $msg_tmpl,
3276
+ $logResults['total_row_count'], // 1
3277
  $count_users_today, // 2
3278
  $count_other_sources // 3
3279
  );
3280
 
3281
  // Space between texts
3282
  /*
3283
+ echo " ";
3284
 
3285
+ // http://playground-root.ep/wp-admin/options-general.php?page=simple_history_settings_menu_slug&selected-tab=stats
3286
+ printf(
3287
+ '<a href="%1$s">View more stats</a>.',
3288
+ add_query_arg("selected-tab", "stats", menu_page_url(SimpleHistory::SETTINGS_MENU_SLUG, 0))
3289
+ );
3290
+ */
3291
 
3292
  }
3293
 
3314
  wp_cache_set( $incrementor_key, $incrementor_value );
3315
  }
3316
 
3317
+ // echo "<br>incrementor_value: $incrementor_value";
3318
  return $incrementor_value;
3319
 
3320
  }
3323
  // Number of rows the last n days
3324
  function get_num_events_last_n_days( $period_days = 28 ) {
3325
 
3326
+ $transient_key = 'sh_' . md5( __METHOD__ . $period_days . '_2' );
3327
 
3328
  $count = get_transient( $transient_key );
3329
 
 
3330
  if ( false === $count ) {
3331
 
3332
  global $wpdb;
3333
 
3334
+ $sqlStringLoggersUserCanRead = $this->getLoggersThatUserCanRead( null, 'sql' );
3335
 
3336
  $sql = sprintf(
3337
  '
3341
  AND logger IN %3$s
3342
  ',
3343
  $wpdb->prefix . SimpleHistory::DBTABLE,
3344
+ strtotime( "-$period_days days" ),
3345
  $sqlStringLoggersUserCanRead
3346
  );
3347
 
3358
 
3359
  function get_num_events_per_day_last_n_days( $period_days = 28 ) {
3360
 
3361
+ $transient_key = 'sh_' . md5( __METHOD__ . $period_days . '_2' );
3362
 
3363
  $dates = get_transient( $transient_key );
3364
 
3366
 
3367
  global $wpdb;
3368
 
3369
+ $sqlStringLoggersUserCanRead = $this->getLoggersThatUserCanRead( null, 'sql' );
3370
 
3371
  $sql = sprintf(
3372
  '
3382
  ORDER BY yearDate ASC
3383
  ',
3384
  $wpdb->prefix . SimpleHistory::DBTABLE,
3385
+ strtotime( "-$period_days days" ),
3386
  $sqlStringLoggersUserCanRead
3387
  );
3388
 
3390
 
3391
  set_transient( $transient_key, $dates, HOUR_IN_SECONDS );
3392
  // echo "set";exit;
 
3393
  } else {
3394
  // echo "get";exit;
3395
  }
3407
 
3408
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
3409
 
3410
+ $cache_key = 'sh_' . md5( __METHOD__ . $days );
3411
 
3412
  $numEvents = get_transient( $cache_key );
3413
 
3419
  WHERE date >= DATE_ADD(CURDATE(), INTERVAL -%d DAY)
3420
  ", $days);
3421
 
3422
+ $numEvents = $wpdb->get_var( $sql );
3423
 
3424
  set_transient( $cache_key, $numEvents, HOUR_IN_SECONDS );
3425
 
3464
  function simple_history_add( $args ) {
3465
 
3466
  $defaults = array(
3467
+ 'action' => null,
3468
+ 'object_type' => null,
3469
+ 'object_subtype' => null,
3470
+ 'object_id' => null,
3471
+ 'object_name' => null,
3472
+ 'user_id' => null,
3473
+ 'description' => null,
3474
  );
3475
 
3476
  $context = wp_parse_args( $args, $defaults );
3508
  * @uses Text_Diff
3509
  * @uses WP_Text_Diff_Renderer_Table
3510
  *
3511
+ * @param string $left_string "old" (left) version of string
3512
+ * @param string $right_string "new" (right) version of string
3513
  * @param string|array $args Optional. Change 'title', 'title_left', and 'title_right' defaults. And leading_context_lines and trailing_context_lines.
3514
  * @return string Empty string if strings are equivalent or HTML with differences.
3515
  */
3519
  'title' => '',
3520
  'title_left' => '',
3521
  'title_right' => '',
3522
+ 'leading_context_lines' => 1,
3523
+ 'trailing_context_lines' => 1,
3524
  );
3525
 
3526
  $args = wp_parse_args( $args, $defaults );
3527
 
3528
+ if ( ! class_exists( 'WP_Text_Diff_Renderer_Table' ) ) {
3529
  require ABSPATH . WPINC . '/wp-diff.php';
3530
+ }
3531
 
3532
  $left_string = normalize_whitespace( $left_string );
3533
  $right_string = normalize_whitespace( $right_string );
3537
  $text_diff = new Text_Diff( $left_lines, $right_lines );
3538
 
3539
  $renderer = new WP_Text_Diff_Renderer_Table( $args );
3540
+ $renderer->_leading_context_lines = $args['leading_context_lines'];
3541
+ $renderer->_trailing_context_lines = $args['trailing_context_lines'];
3542
 
3543
  $diff = $renderer->render( $text_diff );
3544
 
3545
+ if ( ! $diff ) {
3546
  return '';
3547
+ }
3548
 
3549
+ $r = '';
3550
 
3551
  $r .= "<div class='SimpleHistory__diff__contents' tabindex='0'>";
3552
  $r .= "<div class='SimpleHistory__diff__contentsInner'>";
3553
 
3554
  $r .= "<table class='diff SimpleHistory__diff'>\n";
3555
 
3556
+ if ( ! empty( $args['show_split_view'] ) ) {
3557
  $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
3558
  } else {
3559
  $r .= "<col class='content' />";
3560
  }
3561
 
3562
+ if ( $args['title'] || $args['title_left'] || $args['title_right'] ) {
3563
+ $r .= '<thead>';
3564
+ }
3565
+ if ( $args['title'] ) {
3566
  $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
3567
+ }
3568
  if ( $args['title_left'] || $args['title_right'] ) {
3569
  $r .= "<tr class='diff-sub-title'>\n";
3570
  $r .= "\t<td></td><th>$args[title_left]</th>\n";
3571
  $r .= "\t<td></td><th>$args[title_right]</th>\n";
3572
  $r .= "</tr>\n";
3573
  }
3574
+ if ( $args['title'] || $args['title_left'] || $args['title_right'] ) {
3575
  $r .= "</thead>\n";
3576
+ }
3577
 
3578
  $r .= "<tbody>\n$diff</div>\n</tbody>\n";
3579
+ $r .= '</table>';
3580
 
3581
+ $r .= '</div>';
3582
+ $r .= '</div>';
3583
 
3584
  return $r;
3585
  }
inc/SimpleHistoryLogQuery.php CHANGED
@@ -19,79 +19,77 @@ class SimpleHistoryLogQuery {
19
 
20
  }
21
 
22
- public function query($args) {
23
 
24
  $defaults = array(
25
 
26
  // overview | occasions
27
- "type" => "overview",
28
 
29
  // Number of posts to show per page. 0 to show all.
30
- "posts_per_page" => 0,
31
 
32
  // Page to show. 1 = first page
33
- "paged" => 1,
34
 
35
  // Array. Only get posts that are in array.
36
- "post__in" => null,
37
 
38
  // array or html
39
- "format" => "array",
40
 
41
  // If max_id_first_page is set then only get rows
42
  // that have id equal or lower than this, to make
43
- "max_id_first_page" => null,
44
 
45
  // if since_id is set the rows returned will only be rows with an ID greater than (i.e. more recent than) since_id
46
- "since_id" => null,
47
 
48
  // date range
49
  // in unix datetime or Y-m-d H:i (or format compatible with strtotime())
50
- "date_from" => null,
51
- "date_to" => null,
52
 
53
  // months in format "Y-m"
54
  // array or comma separated
55
- "months" => null,
56
 
57
  // dates in format
58
  // "month:2015-06" for june 2015
59
  // "lastdays:7" for the last 7 days
60
- "dates" => null,
61
 
62
  // search
63
- "search" => null,
64
 
65
  // log levels to include. comma separated or as array. defaults to all.
66
- "loglevels" => null,
67
 
68
  // loggers to include. comma separated. defaults to all the user can read
69
- "loggers" => null,
70
 
71
- "messages" => null,
72
 
73
  // userID as number
74
- "user" => null,
75
 
76
  // user ids, comma separated
77
- "users" => null,
78
 
79
  // Can also contain:
80
  // occasionsCount
81
  // occasionsCountMaxReturn
82
  // occasionsID
83
-
84
  // If rows should be returned, or the actualy sql query used
85
- "returnQuery" => false
86
 
87
  );
88
 
89
  $args = wp_parse_args( $args, $defaults );
90
  // sf_d($args, "Run log query with args");
91
-
92
- $cache_key = "SimpleHistoryLogQuery_" . md5(serialize( $args )) . "_get_" . md5(serialize( $_GET )) . "_userid_" . get_current_user_id();
93
- $cache_group = "simple-history-" . SimpleHistory::get_cache_incrementor();
94
- $arr_return = wp_cache_get($cache_key, $cache_group);
95
 
96
  if ( false !== $arr_return ) {
97
  return $arr_return;
@@ -114,11 +112,11 @@ class SimpleHistoryLogQuery {
114
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
115
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
116
 
117
- $where = "1 = 1";
118
- $limit = "";
119
- $inner_where = "1 = 1";
120
 
121
- if ( "overview" === $args["type"] || "single" === $args["type"] ) {
122
 
123
  // Set variables used by query
124
  $sql_set_var = "SET @a:='', @counter:=1, @groupby:=0";
@@ -180,10 +178,10 @@ class SimpleHistoryLogQuery {
180
 
181
  // Only include loggers that the current user can view
182
  // @TODO: this causes error if user has no access to any logger at all
183
- $sql_loggers_user_can_view = $sh->getLoggersThatUserCanRead(get_current_user_id(), "sql");
184
  $inner_where .= " AND logger IN {$sql_loggers_user_can_view}";
185
 
186
- } else if ( "occasions" === $args["type"] ) {
187
 
188
  // Query template
189
  // 1 = where
@@ -199,52 +197,47 @@ class SimpleHistoryLogQuery {
199
  %2$s
200
  ';
201
 
202
- $where .= " AND h.id < " . (int) $args["logRowID"];
203
- $where .= " AND h.occasionsID = '" . esc_sql( $args["occasionsID"] ) . "'";
204
 
205
- if ( isset( $args["occasionsCountMaxReturn"] ) && (int) $args["occasionsCountMaxReturn"] < (int) $args["occasionsCount"] ) {
206
 
207
  // Limit to max nn events if occasionsCountMaxReturn is set.
208
  // Used in gui to prevent top many events returned, that can stall the browser.
209
- $limit = "LIMIT " . (int) $args["occasionsCountMaxReturn"];
210
 
211
  } else {
212
 
213
  // Regular limit that gets all occasions
214
- $limit = "LIMIT " . (int) $args["occasionsCount"];
215
 
216
  }
217
-
218
- // [logRowID] =&gt; 353
219
- // [occasionsID] =&gt; 73b06d5740d15e35079b6aa024255cb3
220
- // [occasionsCount] =&gt; 18
221
-
222
- }
223
 
224
  // Determine limit
225
  // Both posts_per_page and paged must be set
226
- $is_limit_query = ( is_numeric( $args["posts_per_page"] ) && $args["posts_per_page"] > 0 );
227
- $is_limit_query = $is_limit_query && ( is_numeric( $args["paged"] ) && $args["paged"] > 0 );
228
- if ($is_limit_query) {
229
- $limit_offset = ($args["paged"] - 1) * $args["posts_per_page"];
230
- $limit .= sprintf('LIMIT %1$d, %2$d', $limit_offset, $args["posts_per_page"] );
231
  }
232
 
233
  // Determine where
234
- if ( $args["post__in"] && is_array( $args["post__in"] ) ) {
235
 
236
  // make sure all vals are integers
237
- $args["post__in"] = array_map("intval", $args["post__in"]);
238
 
239
- $inner_where .= sprintf(' AND id IN (%1$s)', implode(",", $args["post__in"]));
240
 
241
  }
242
 
243
  // If max_id_first_page is then then only include rows
244
  // with id equal to or earlier
245
- if ( isset($args["max_id_first_page"]) && is_numeric($args["max_id_first_page"]) ) {
246
 
247
- $max_id_first_page = (int) $args["max_id_first_page"];
248
  $inner_where .= sprintf(
249
  ' AND id <= %1$d',
250
  $max_id_first_page
@@ -252,9 +245,9 @@ class SimpleHistoryLogQuery {
252
 
253
  }
254
 
255
- if ( isset($args["since_id"]) && is_numeric($args["since_id"]) ) {
256
 
257
- $since_id = (int) $args["since_id"];
258
  /*
259
  $where .= sprintf(
260
  ' AND t.id > %1$d',
@@ -270,84 +263,80 @@ class SimpleHistoryLogQuery {
270
  }
271
 
272
  // Append date where
273
- if ( ! empty( $args["date_from"] ) ) {
274
 
275
  // date_from=2014-08-01
276
  // if date is not numeric assume Y-m-d H:i-format
277
- $date_from = $args["date_from"];
278
  if ( ! is_numeric( $date_from ) ) {
279
  $date_from = strtotime( $date_from );
280
  }
281
 
282
- $inner_where .= "\n" . sprintf(' AND date >= "%1$s"', esc_sql( date( 'Y-m-d H:i:s', $date_from ) ) );
283
 
284
  }
285
 
286
- if ( ! empty( $args["date_to"] ) ) {
287
 
288
  // date_to=2014-08-01
289
  // if date is not numeric assume Y-m-d H:i-format
290
- $date_to = $args["date_to"];
291
  if ( ! is_numeric( $date_to ) ) {
292
  $date_to = strtotime( $date_to );
293
  }
294
 
295
- $inner_where .= "\n" . sprintf(' AND date <= "%1$s"', date( 'Y-m-d H:i:s', $date_to ) );
296
 
297
  }
298
 
299
  /*
300
  AND date >= "2015-01-01 00:00:00" AND date <= "2015-01-31 00:00:00"
301
  */
302
- #echo $inner_where;exit;
303
-
304
  // dats
305
  // if months they translate to $args["months"] because we already have support for that
306
  // can't use months and dates and the same time
307
- if ( ! empty( $args["dates"] ) ) {
308
 
309
- if ( is_array( $args["dates"] ) ) {
310
- $arr_dates = $args["dates"];
311
  } else {
312
- $arr_dates = explode(",", $args["dates"]);
313
  }
314
 
315
- $args["months"] = array();
316
- $args["lastdays"] = 0;
317
 
318
  foreach ( $arr_dates as $one_date ) {
319
 
320
  // If begins with "month:" then strip string and keep only month numbers
321
- if ( strpos($one_date, "month:") === 0 ) {
322
- $args["months"][] = substr($one_date, strlen("month:"));
323
- } else if ( strpos($one_date, "lastdays:") === 0 ) {
324
  // Only keep largest lastdays value
325
- $args["lastdays"] = max($args["lastdays"], substr($one_date, strlen("lastdays:")));
326
- #$args["lastdays"][] = substr($one_date, strlen("lastdays:"));
327
  }
328
-
329
  }
330
-
331
-
332
  }
333
 
334
  // lastdays, as int
335
- if ( ! empty( $args["lastdays"] ) ) {
336
 
337
  $inner_where .= sprintf('
338
  # lastdays
339
  AND date >= DATE(NOW()) - INTERVAL %d DAY
340
- ', $args["lastdays"]);
341
 
342
  }
343
 
344
  // months, in format "Y-m"
345
- if ( ! empty( $args["months"] ) ) {
346
 
347
- if ( is_array( $args["months"] ) ) {
348
- $arr_months = $args["months"];
349
  } else {
350
- $arr_months = explode(",", $args["months"]);
351
  }
352
 
353
  $sql_months = '
@@ -378,13 +367,12 @@ class SimpleHistoryLogQuery {
378
  ',
379
  date( 'Y-m-d H:i:s', $date_month_beginning ), // 1
380
  date( 'Y-m-d H:i:s', $date_month_end ) // 2
381
-
382
  );
383
 
384
  }
385
 
386
- $sql_months = trim($sql_months);
387
- $sql_months = rtrim($sql_months, " OR ");
388
 
389
  $sql_months .= '
390
  # end sql_months and wrap
@@ -393,27 +381,26 @@ class SimpleHistoryLogQuery {
393
 
394
  $inner_where .= $sql_months;
395
  // echo $inner_where;exit;
396
-
397
- }
398
 
399
  // search
400
- if ( ! empty( $args["search"] ) ) {
401
 
402
- $search_words = $args["search"];
403
- $str_search_conditions = "";
404
- $arr_search_words = preg_split("/[\s,]+/", $search_words);
405
 
406
  // create array of all searched words
407
  // split both spaces and commas and such
408
- $arr_sql_like_cols = array("message", "logger", "level");
409
 
410
  foreach ( $arr_sql_like_cols as $one_col ) {
411
 
412
- $str_sql_search_words = "";
413
 
414
- foreach ($arr_search_words as $one_search_word) {
415
 
416
- if ( method_exists($wpdb, "esc_like") ) {
417
  $str_like = esc_sql( $wpdb->esc_like( $one_search_word ) );
418
  } else {
419
  $str_like = esc_sql( like_escape( $one_search_word ) );
@@ -427,7 +414,7 @@ class SimpleHistoryLogQuery {
427
 
428
  }
429
 
430
- $str_sql_search_words = ltrim($str_sql_search_words, ' AND ');
431
 
432
  $str_search_conditions .= "\n" . sprintf(
433
  ' OR ( %1$s ) ',
@@ -436,13 +423,13 @@ class SimpleHistoryLogQuery {
436
 
437
  }
438
 
439
- $str_search_conditions = preg_replace('/^OR /', " ", trim($str_search_conditions));
440
 
441
  // also search contexts
442
  $str_search_conditions .= "\n OR ( ";
443
- foreach ($arr_search_words as $one_search_word) {
444
 
445
- if ( method_exists($wpdb, "esc_like") ) {
446
  $str_like = esc_sql( $wpdb->esc_like( $one_search_word ) );
447
  } else {
448
  $str_like = esc_sql( like_escape( $one_search_word ) );
@@ -451,39 +438,38 @@ class SimpleHistoryLogQuery {
451
  $str_search_conditions .= "\n" . sprintf(
452
  ' id IN ( SELECT history_id FROM %1$s AS c WHERE c.value LIKE "%2$s" ) AND ',
453
  $table_name_contexts, // 1
454
- "%" . $str_like . "%" // 2
455
  );
456
 
457
  }
458
- $str_search_conditions = preg_replace('/ AND $/', "", $str_search_conditions);
459
 
460
  $str_search_conditions .= "\n ) "; // end or for contexts
461
 
462
  $inner_where .= "\n AND \n(\n {$str_search_conditions} \n ) ";
463
 
464
- #echo $inner_where;exit;
465
-
466
- }
467
 
468
  // log levels
469
  // comma separated
470
  // http://playground-root.ep/wp-admin/admin-ajax.php?action=simple_history_api&type=overview&format=&posts_per_page=10&paged=1&max_id_first_page=27273&SimpleHistoryLogQuery-showDebug=0&loglevel=error,warn
471
- if ( ! empty( $args["loglevels"] ) ) {
472
 
473
- $sql_loglevels = "";
474
 
475
- if ( is_array( $args["loglevels"] ) ) {
476
- $arr_loglevels = $args["loglevels"];
477
  } else {
478
- $arr_loglevels = explode(",", $args["loglevels"]);
479
  }
480
 
481
  foreach ( $arr_loglevels as $one_loglevel ) {
482
- $sql_loglevels .= sprintf(' "%s", ', esc_sql( $one_loglevel ));
483
  }
484
 
485
  if ( $sql_loglevels ) {
486
- $sql_loglevels = rtrim( $sql_loglevels, " ," );
487
  $sql_loglevels = "\n AND level IN ({$sql_loglevels}) ";
488
  }
489
 
@@ -492,9 +478,9 @@ class SimpleHistoryLogQuery {
492
  }
493
 
494
  // messages
495
- if ( ! empty( $args["messages"] ) ) {
496
 
497
- #print_r($args["messages"]);exit;
498
  /*
499
  Array
500
  (
@@ -507,36 +493,34 @@ class SimpleHistoryLogQuery {
507
  $arr_loggers_and_messages = array();
508
 
509
  // Tranform from get'et format to our own internal format
510
- foreach ( (array) $args["messages"] as $one_arr_messages_row ) {
511
 
512
- $arr_row_messages = explode(",", $one_arr_messages_row);
513
- #print_r($arr_row_messages);#exit;
514
  /*
515
-
516
  Array
517
  (
518
  [0] => SimpleCommentsLogger:anon_comment_added
519
  [1] => SimpleCommentsLogger:user_comment_added
520
  [2] => SimpleCommentsLogger:anon_trackback_added
521
  */
522
- foreach ($arr_row_messages as $one_row_logger_and_message) {
523
 
524
- $arr_one_logger_and_message = explode(":", $one_row_logger_and_message);
525
 
526
- if ( ! isset( $arr_loggers_and_messages[$arr_one_logger_and_message[0]] ) ) {
527
- $arr_loggers_and_messages[$arr_one_logger_and_message[0]] = array();
528
  }
529
 
530
  $arr_loggers_and_messages[ $arr_one_logger_and_message[0] ][] = $arr_one_logger_and_message[1];
531
 
532
  }
533
-
534
  }
535
 
536
  // Now create sql where based on loggers and messages
537
- $sql_messages_where = " AND (";
538
- #print_r($arr_loggers_and_messages);exit;
539
- foreach ($arr_loggers_and_messages as $logger_slug => $logger_messages) {
540
  $sql_messages_where .= sprintf(
541
  '
542
  (
@@ -545,14 +529,14 @@ class SimpleHistoryLogQuery {
545
  )
546
  OR ',
547
  esc_sql( $logger_slug ),
548
- "'" . implode("','", $logger_messages) . "'"
549
  );
550
  }
551
  // remove last or
552
- $sql_messages_where = preg_replace('/OR $/', "", $sql_messages_where);
553
 
554
  $sql_messages_where .= "\n )";
555
- #echo $sql_messages_where;exit;
556
  $where .= $sql_messages_where;
557
 
558
  /*
@@ -600,22 +584,22 @@ class SimpleHistoryLogQuery {
600
 
601
  */
602
 
603
- }
604
 
605
  // loggers
606
  // comma separated
607
  // http://playground-root.ep/wp-admin/admin-ajax.php?action=simple_history_api&type=overview&format=&posts_per_page=10&paged=1&max_id_first_page=27273&SimpleHistoryLogQuery-showDebug=0&loggers=SimpleCommentsLogger,SimpleCoreUpdatesLogger
608
- if ( ! empty( $args["loggers"] ) ) {
609
 
610
- $sql_loggers = "";
611
- if ( is_array( $args["loggers"] ) ) {
612
- $arr_loggers = $args["loggers"];
613
  } else {
614
- $arr_loggers = explode(",", $args["loggers"]);
615
  }
616
 
617
- #print_r($args["loggers"]);exit;
618
- #print_r($arr_loggers);exit;
619
  /*
620
  Example of version with logger + message keys
621
  Array
@@ -626,11 +610,11 @@ class SimpleHistoryLogQuery {
626
  */
627
 
628
  foreach ( $arr_loggers as $one_logger ) {
629
- $sql_loggers .= sprintf(' "%s", ', esc_sql( $one_logger ));
630
  }
631
 
632
  if ( $sql_loggers ) {
633
- $sql_loggers = rtrim( $sql_loggers, " ," );
634
  $sql_loggers = "\n AND logger IN ({$sql_loggers}) ";
635
  }
636
 
@@ -639,9 +623,9 @@ class SimpleHistoryLogQuery {
639
  }
640
 
641
  // user, a single userID
642
- if ( ! empty( $args["user"] ) && is_numeric( $args["user"] ) ) {
643
 
644
- $userID = (int) $args["user"];
645
  $sql_user = sprintf(
646
  '
647
  AND id IN ( SELECT history_id FROM %1$s AS c WHERE c.key = "_user_id" AND c.value = %2$s )
@@ -655,14 +639,14 @@ class SimpleHistoryLogQuery {
655
  }
656
 
657
  // users, comma separated
658
- if ( ! empty( $args["users"] ) && is_string( $args["users"] ) ) {
659
 
660
- $users = explode(",", $args["users"]);
661
- $users = array_map("intval", $users);
662
 
663
  if ( $users ) {
664
 
665
- $users_in = implode(",", $users);
666
 
667
  $sql_user = sprintf(
668
  '
@@ -674,12 +658,10 @@ class SimpleHistoryLogQuery {
674
 
675
  $inner_where .= $sql_user;
676
 
677
- #echo $inner_where;exit;
678
  }
679
-
680
  }
681
 
682
-
683
  /**
684
  * Filter the sql template
685
  *
@@ -687,7 +669,7 @@ class SimpleHistoryLogQuery {
687
  *
688
  * @param string $sql_tmpl
689
  */
690
- $sql_tmpl = apply_filters("simple_history/log_query_sql_template", $sql_tmpl);
691
 
692
  /**
693
  * Filter the sql template where clause
@@ -696,7 +678,7 @@ class SimpleHistoryLogQuery {
696
  *
697
  * @param string $where
698
  */
699
- $where = apply_filters("simple_history/log_query_sql_where", $where);
700
 
701
  /**
702
  * Filter the sql template limit
@@ -705,7 +687,7 @@ class SimpleHistoryLogQuery {
705
  *
706
  * @param string $limit
707
  */
708
- $limit = apply_filters("simple_history/log_query_limit", $limit);
709
 
710
  /**
711
  * Filter the sql template limit
@@ -714,7 +696,7 @@ class SimpleHistoryLogQuery {
714
  *
715
  * @param string $limit
716
  */
717
- $inner_where = apply_filters("simple_history/log_query_inner_where", $inner_where);
718
 
719
  $sql = sprintf(
720
  $sql_tmpl, // sprintf template
@@ -725,7 +707,6 @@ class SimpleHistoryLogQuery {
725
  $table_name_contexts // 5
726
  );
727
 
728
-
729
  /**
730
  * Filter the final sql query
731
  *
@@ -733,13 +714,13 @@ class SimpleHistoryLogQuery {
733
  *
734
  * @param string $sql
735
  */
736
- $sql = apply_filters("simple_history/log_query_sql", $sql);
737
 
738
  // Remove comments below to debug query (includes query in json result)
739
  // $include_query_in_result = true;
740
- if (isset($_GET["SimpleHistoryLogQuery-showDebug"]) && $_GET["SimpleHistoryLogQuery-showDebug"]) {
741
 
742
- echo "<pre>";
743
  echo $sql_set_var;
744
  echo $sql;
745
  exit;
@@ -747,12 +728,12 @@ class SimpleHistoryLogQuery {
747
  }
748
 
749
  // Only return sql query
750
- if ( $args["returnQuery"] ) {
751
  return $sql;
752
  }
753
 
754
- $log_rows = $wpdb->get_results($sql, OBJECT_K);
755
- $num_rows = sizeof($log_rows);
756
 
757
  // Find total number of rows that we would have gotten without pagination
758
  // This is the number of rows with occasions taken into consideration
@@ -760,13 +741,13 @@ class SimpleHistoryLogQuery {
760
  $total_found_rows = (int) $wpdb->get_var( $sql_found_rows );
761
 
762
  // Add context
763
- $post_ids = wp_list_pluck( $log_rows, "id" );
764
 
765
- if ( empty($post_ids) ) {
766
  $context_results = array();
767
  } else {
768
- $sql_context = sprintf('SELECT * FROM %2$s WHERE history_id IN (%1$s)', join(",", $post_ids), $table_name_contexts);
769
- $context_results = $wpdb->get_results($sql_context);
770
  }
771
 
772
  foreach ( $context_results as $context_row ) {
@@ -780,19 +761,19 @@ class SimpleHistoryLogQuery {
780
  }
781
 
782
  // Remove id from keys, because they are cumbersome when working with JSON
783
- $log_rows = array_values($log_rows);
784
  $min_id = null;
785
  $max_id = null;
786
 
787
- if ( sizeof($log_rows) ) {
788
 
789
  // Max id is simply the id of the first row
790
- $max_id = reset($log_rows)->id;
791
 
792
  // Min id = to find the lowest id we must take occasions into consideration
793
- $last_row = end($log_rows);
794
  $last_row_occasions_count = (int) $last_row->subsequentOccasions - 1;
795
- if ($last_row_occasions_count === 0) {
796
 
797
  // Last row did not have any more occasions, so get min_id directly from the row
798
  $min_id = $last_row->id;
@@ -817,15 +798,14 @@ class SimpleHistoryLogQuery {
817
  $results = $wpdb->get_results( $sql );
818
 
819
  // the last occasion has the id we consider last in this paged result
820
- $min_id = end($results)->id;
821
 
822
  }
823
-
824
- }
825
 
826
  // Calc pages
827
- if ( $args["posts_per_page"] ) {
828
- $pages_count = Ceil ( $total_found_rows / (int) $args["posts_per_page"] );
829
  } else {
830
  $pages_count = 1;
831
  }
@@ -833,23 +813,22 @@ class SimpleHistoryLogQuery {
833
  // Create array to return
834
  // Make all rows a sub key because we want to add some meta info too
835
  $log_rows_count = sizeof( $log_rows );
836
- $page_rows_from = ( (int) $args["paged"] * (int) $args["posts_per_page"] ) - (int) $args["posts_per_page"] + 1;
837
  $page_rows_to = $page_rows_from + $log_rows_count - 1;
838
  $arr_return = array(
839
- "total_row_count" => $total_found_rows,
840
- "pages_count" => $pages_count,
841
- "page_current" => (int) $args["paged"],
842
- "page_rows_from" => $page_rows_from,
843
- "page_rows_to" => $page_rows_to,
844
- "max_id" => (int) $max_id,
845
- "min_id" => (int) $min_id,
846
- "log_rows_count" => $log_rows_count,
847
- "log_rows" => $log_rows,
848
  );
849
 
850
- #sf_d($arr_return, '$arr_return');exit;
851
-
852
- wp_cache_set($cache_key, $arr_return, $cache_group);
853
 
854
  return $arr_return;
855
 
19
 
20
  }
21
 
22
+ public function query( $args ) {
23
 
24
  $defaults = array(
25
 
26
  // overview | occasions
27
+ 'type' => 'overview',
28
 
29
  // Number of posts to show per page. 0 to show all.
30
+ 'posts_per_page' => 0,
31
 
32
  // Page to show. 1 = first page
33
+ 'paged' => 1,
34
 
35
  // Array. Only get posts that are in array.
36
+ 'post__in' => null,
37
 
38
  // array or html
39
+ 'format' => 'array',
40
 
41
  // If max_id_first_page is set then only get rows
42
  // that have id equal or lower than this, to make
43
+ 'max_id_first_page' => null,
44
 
45
  // if since_id is set the rows returned will only be rows with an ID greater than (i.e. more recent than) since_id
46
+ 'since_id' => null,
47
 
48
  // date range
49
  // in unix datetime or Y-m-d H:i (or format compatible with strtotime())
50
+ 'date_from' => null,
51
+ 'date_to' => null,
52
 
53
  // months in format "Y-m"
54
  // array or comma separated
55
+ 'months' => null,
56
 
57
  // dates in format
58
  // "month:2015-06" for june 2015
59
  // "lastdays:7" for the last 7 days
60
+ 'dates' => null,
61
 
62
  // search
63
+ 'search' => null,
64
 
65
  // log levels to include. comma separated or as array. defaults to all.
66
+ 'loglevels' => null,
67
 
68
  // loggers to include. comma separated. defaults to all the user can read
69
+ 'loggers' => null,
70
 
71
+ 'messages' => null,
72
 
73
  // userID as number
74
+ 'user' => null,
75
 
76
  // user ids, comma separated
77
+ 'users' => null,
78
 
79
  // Can also contain:
80
  // occasionsCount
81
  // occasionsCountMaxReturn
82
  // occasionsID
 
83
  // If rows should be returned, or the actualy sql query used
84
+ 'returnQuery' => false,
85
 
86
  );
87
 
88
  $args = wp_parse_args( $args, $defaults );
89
  // sf_d($args, "Run log query with args");
90
+ $cache_key = 'SimpleHistoryLogQuery_' . md5( serialize( $args ) ) . '_get_' . md5( serialize( $_GET ) ) . '_userid_' . get_current_user_id();
91
+ $cache_group = 'simple-history-' . SimpleHistory::get_cache_incrementor();
92
+ $arr_return = wp_cache_get( $cache_key, $cache_group );
 
93
 
94
  if ( false !== $arr_return ) {
95
  return $arr_return;
112
  $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
113
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
114
 
115
+ $where = '1 = 1';
116
+ $limit = '';
117
+ $inner_where = '1 = 1';
118
 
119
+ if ( 'overview' === $args['type'] || 'single' === $args['type'] ) {
120
 
121
  // Set variables used by query
122
  $sql_set_var = "SET @a:='', @counter:=1, @groupby:=0";
178
 
179
  // Only include loggers that the current user can view
180
  // @TODO: this causes error if user has no access to any logger at all
181
+ $sql_loggers_user_can_view = $sh->getLoggersThatUserCanRead( get_current_user_id(), 'sql' );
182
  $inner_where .= " AND logger IN {$sql_loggers_user_can_view}";
183
 
184
+ } elseif ( 'occasions' === $args['type'] ) {
185
 
186
  // Query template
187
  // 1 = where
197
  %2$s
198
  ';
199
 
200
+ $where .= ' AND h.id < ' . (int) $args['logRowID'];
201
+ $where .= " AND h.occasionsID = '" . esc_sql( $args['occasionsID'] ) . "'";
202
 
203
+ if ( isset( $args['occasionsCountMaxReturn'] ) && (int) $args['occasionsCountMaxReturn'] < (int) $args['occasionsCount'] ) {
204
 
205
  // Limit to max nn events if occasionsCountMaxReturn is set.
206
  // Used in gui to prevent top many events returned, that can stall the browser.
207
+ $limit = 'LIMIT ' . (int) $args['occasionsCountMaxReturn'];
208
 
209
  } else {
210
 
211
  // Regular limit that gets all occasions
212
+ $limit = 'LIMIT ' . (int) $args['occasionsCount'];
213
 
214
  }
215
+ }// End if().
 
 
 
 
 
216
 
217
  // Determine limit
218
  // Both posts_per_page and paged must be set
219
+ $is_limit_query = ( is_numeric( $args['posts_per_page'] ) && $args['posts_per_page'] > 0 );
220
+ $is_limit_query = $is_limit_query && ( is_numeric( $args['paged'] ) && $args['paged'] > 0 );
221
+ if ( $is_limit_query ) {
222
+ $limit_offset = ($args['paged'] - 1) * $args['posts_per_page'];
223
+ $limit .= sprintf( 'LIMIT %1$d, %2$d', $limit_offset, $args['posts_per_page'] );
224
  }
225
 
226
  // Determine where
227
+ if ( $args['post__in'] && is_array( $args['post__in'] ) ) {
228
 
229
  // make sure all vals are integers
230
+ $args['post__in'] = array_map( 'intval', $args['post__in'] );
231
 
232
+ $inner_where .= sprintf( ' AND id IN (%1$s)', implode( ',', $args['post__in'] ) );
233
 
234
  }
235
 
236
  // If max_id_first_page is then then only include rows
237
  // with id equal to or earlier
238
+ if ( isset( $args['max_id_first_page'] ) && is_numeric( $args['max_id_first_page'] ) ) {
239
 
240
+ $max_id_first_page = (int) $args['max_id_first_page'];
241
  $inner_where .= sprintf(
242
  ' AND id <= %1$d',
243
  $max_id_first_page
245
 
246
  }
247
 
248
+ if ( isset( $args['since_id'] ) && is_numeric( $args['since_id'] ) ) {
249
 
250
+ $since_id = (int) $args['since_id'];
251
  /*
252
  $where .= sprintf(
253
  ' AND t.id > %1$d',
263
  }
264
 
265
  // Append date where
266
+ if ( ! empty( $args['date_from'] ) ) {
267
 
268
  // date_from=2014-08-01
269
  // if date is not numeric assume Y-m-d H:i-format
270
+ $date_from = $args['date_from'];
271
  if ( ! is_numeric( $date_from ) ) {
272
  $date_from = strtotime( $date_from );
273
  }
274
 
275
+ $inner_where .= "\n" . sprintf( ' AND date >= "%1$s"', esc_sql( date( 'Y-m-d H:i:s', $date_from ) ) );
276
 
277
  }
278
 
279
+ if ( ! empty( $args['date_to'] ) ) {
280
 
281
  // date_to=2014-08-01
282
  // if date is not numeric assume Y-m-d H:i-format
283
+ $date_to = $args['date_to'];
284
  if ( ! is_numeric( $date_to ) ) {
285
  $date_to = strtotime( $date_to );
286
  }
287
 
288
+ $inner_where .= "\n" . sprintf( ' AND date <= "%1$s"', date( 'Y-m-d H:i:s', $date_to ) );
289
 
290
  }
291
 
292
  /*
293
  AND date >= "2015-01-01 00:00:00" AND date <= "2015-01-31 00:00:00"
294
  */
295
+ // echo $inner_where;exit;
 
296
  // dats
297
  // if months they translate to $args["months"] because we already have support for that
298
  // can't use months and dates and the same time
299
+ if ( ! empty( $args['dates'] ) ) {
300
 
301
+ if ( is_array( $args['dates'] ) ) {
302
+ $arr_dates = $args['dates'];
303
  } else {
304
+ $arr_dates = explode( ',', $args['dates'] );
305
  }
306
 
307
+ $args['months'] = array();
308
+ $args['lastdays'] = 0;
309
 
310
  foreach ( $arr_dates as $one_date ) {
311
 
312
  // If begins with "month:" then strip string and keep only month numbers
313
+ if ( strpos( $one_date, 'month:' ) === 0 ) {
314
+ $args['months'][] = substr( $one_date, strlen( 'month:' ) );
315
+ } elseif ( strpos( $one_date, 'lastdays:' ) === 0 ) {
316
  // Only keep largest lastdays value
317
+ $args['lastdays'] = max( $args['lastdays'], substr( $one_date, strlen( 'lastdays:' ) ) );
318
+ // $args["lastdays"][] = substr($one_date, strlen("lastdays:"));
319
  }
 
320
  }
 
 
321
  }
322
 
323
  // lastdays, as int
324
+ if ( ! empty( $args['lastdays'] ) ) {
325
 
326
  $inner_where .= sprintf('
327
  # lastdays
328
  AND date >= DATE(NOW()) - INTERVAL %d DAY
329
+ ', $args['lastdays']);
330
 
331
  }
332
 
333
  // months, in format "Y-m"
334
+ if ( ! empty( $args['months'] ) ) {
335
 
336
+ if ( is_array( $args['months'] ) ) {
337
+ $arr_months = $args['months'];
338
  } else {
339
+ $arr_months = explode( ',', $args['months'] );
340
  }
341
 
342
  $sql_months = '
367
  ',
368
  date( 'Y-m-d H:i:s', $date_month_beginning ), // 1
369
  date( 'Y-m-d H:i:s', $date_month_end ) // 2
 
370
  );
371
 
372
  }
373
 
374
+ $sql_months = trim( $sql_months );
375
+ $sql_months = rtrim( $sql_months, ' OR ' );
376
 
377
  $sql_months .= '
378
  # end sql_months and wrap
381
 
382
  $inner_where .= $sql_months;
383
  // echo $inner_where;exit;
384
+ }// End if().
 
385
 
386
  // search
387
+ if ( ! empty( $args['search'] ) ) {
388
 
389
+ $search_words = $args['search'];
390
+ $str_search_conditions = '';
391
+ $arr_search_words = preg_split( '/[\s,]+/', $search_words );
392
 
393
  // create array of all searched words
394
  // split both spaces and commas and such
395
+ $arr_sql_like_cols = array( 'message', 'logger', 'level' );
396
 
397
  foreach ( $arr_sql_like_cols as $one_col ) {
398
 
399
+ $str_sql_search_words = '';
400
 
401
+ foreach ( $arr_search_words as $one_search_word ) {
402
 
403
+ if ( method_exists( $wpdb, 'esc_like' ) ) {
404
  $str_like = esc_sql( $wpdb->esc_like( $one_search_word ) );
405
  } else {
406
  $str_like = esc_sql( like_escape( $one_search_word ) );
414
 
415
  }
416
 
417
+ $str_sql_search_words = ltrim( $str_sql_search_words, ' AND ' );
418
 
419
  $str_search_conditions .= "\n" . sprintf(
420
  ' OR ( %1$s ) ',
423
 
424
  }
425
 
426
+ $str_search_conditions = preg_replace( '/^OR /', ' ', trim( $str_search_conditions ) );
427
 
428
  // also search contexts
429
  $str_search_conditions .= "\n OR ( ";
430
+ foreach ( $arr_search_words as $one_search_word ) {
431
 
432
+ if ( method_exists( $wpdb, 'esc_like' ) ) {
433
  $str_like = esc_sql( $wpdb->esc_like( $one_search_word ) );
434
  } else {
435
  $str_like = esc_sql( like_escape( $one_search_word ) );
438
  $str_search_conditions .= "\n" . sprintf(
439
  ' id IN ( SELECT history_id FROM %1$s AS c WHERE c.value LIKE "%2$s" ) AND ',
440
  $table_name_contexts, // 1
441
+ '%' . $str_like . '%' // 2
442
  );
443
 
444
  }
445
+ $str_search_conditions = preg_replace( '/ AND $/', '', $str_search_conditions );
446
 
447
  $str_search_conditions .= "\n ) "; // end or for contexts
448
 
449
  $inner_where .= "\n AND \n(\n {$str_search_conditions} \n ) ";
450
 
451
+ // echo $inner_where;exit;
452
+ }// End if().
 
453
 
454
  // log levels
455
  // comma separated
456
  // http://playground-root.ep/wp-admin/admin-ajax.php?action=simple_history_api&type=overview&format=&posts_per_page=10&paged=1&max_id_first_page=27273&SimpleHistoryLogQuery-showDebug=0&loglevel=error,warn
457
+ if ( ! empty( $args['loglevels'] ) ) {
458
 
459
+ $sql_loglevels = '';
460
 
461
+ if ( is_array( $args['loglevels'] ) ) {
462
+ $arr_loglevels = $args['loglevels'];
463
  } else {
464
+ $arr_loglevels = explode( ',', $args['loglevels'] );
465
  }
466
 
467
  foreach ( $arr_loglevels as $one_loglevel ) {
468
+ $sql_loglevels .= sprintf( ' "%s", ', esc_sql( $one_loglevel ) );
469
  }
470
 
471
  if ( $sql_loglevels ) {
472
+ $sql_loglevels = rtrim( $sql_loglevels, ' ,' );
473
  $sql_loglevels = "\n AND level IN ({$sql_loglevels}) ";
474
  }
475
 
478
  }
479
 
480
  // messages
481
+ if ( ! empty( $args['messages'] ) ) {
482
 
483
+ // print_r($args["messages"]);exit;
484
  /*
485
  Array
486
  (
493
  $arr_loggers_and_messages = array();
494
 
495
  // Tranform from get'et format to our own internal format
496
+ foreach ( (array) $args['messages'] as $one_arr_messages_row ) {
497
 
498
+ $arr_row_messages = explode( ',', $one_arr_messages_row );
499
+ // print_r($arr_row_messages);#exit;
500
  /*
 
501
  Array
502
  (
503
  [0] => SimpleCommentsLogger:anon_comment_added
504
  [1] => SimpleCommentsLogger:user_comment_added
505
  [2] => SimpleCommentsLogger:anon_trackback_added
506
  */
507
+ foreach ( $arr_row_messages as $one_row_logger_and_message ) {
508
 
509
+ $arr_one_logger_and_message = explode( ':', $one_row_logger_and_message );
510
 
511
+ if ( ! isset( $arr_loggers_and_messages[ $arr_one_logger_and_message[0] ] ) ) {
512
+ $arr_loggers_and_messages[ $arr_one_logger_and_message[0] ] = array();
513
  }
514
 
515
  $arr_loggers_and_messages[ $arr_one_logger_and_message[0] ][] = $arr_one_logger_and_message[1];
516
 
517
  }
 
518
  }
519
 
520
  // Now create sql where based on loggers and messages
521
+ $sql_messages_where = ' AND (';
522
+ // print_r($arr_loggers_and_messages);exit;
523
+ foreach ( $arr_loggers_and_messages as $logger_slug => $logger_messages ) {
524
  $sql_messages_where .= sprintf(
525
  '
526
  (
529
  )
530
  OR ',
531
  esc_sql( $logger_slug ),
532
+ "'" . implode( "','", $logger_messages ) . "'"
533
  );
534
  }
535
  // remove last or
536
+ $sql_messages_where = preg_replace( '/OR $/', '', $sql_messages_where );
537
 
538
  $sql_messages_where .= "\n )";
539
+ // echo $sql_messages_where;exit;
540
  $where .= $sql_messages_where;
541
 
542
  /*
584
 
585
  */
586
 
587
+ }// End if().
588
 
589
  // loggers
590
  // comma separated
591
  // http://playground-root.ep/wp-admin/admin-ajax.php?action=simple_history_api&type=overview&format=&posts_per_page=10&paged=1&max_id_first_page=27273&SimpleHistoryLogQuery-showDebug=0&loggers=SimpleCommentsLogger,SimpleCoreUpdatesLogger
592
+ if ( ! empty( $args['loggers'] ) ) {
593
 
594
+ $sql_loggers = '';
595
+ if ( is_array( $args['loggers'] ) ) {
596
+ $arr_loggers = $args['loggers'];
597
  } else {
598
+ $arr_loggers = explode( ',', $args['loggers'] );
599
  }
600
 
601
+ // print_r($args["loggers"]);exit;
602
+ // print_r($arr_loggers);exit;
603
  /*
604
  Example of version with logger + message keys
605
  Array
610
  */
611
 
612
  foreach ( $arr_loggers as $one_logger ) {
613
+ $sql_loggers .= sprintf( ' "%s", ', esc_sql( $one_logger ) );
614
  }
615
 
616
  if ( $sql_loggers ) {
617
+ $sql_loggers = rtrim( $sql_loggers, ' ,' );
618
  $sql_loggers = "\n AND logger IN ({$sql_loggers}) ";
619
  }
620
 
623
  }
624
 
625
  // user, a single userID
626
+ if ( ! empty( $args['user'] ) && is_numeric( $args['user'] ) ) {
627
 
628
+ $userID = (int) $args['user'];
629
  $sql_user = sprintf(
630
  '
631
  AND id IN ( SELECT history_id FROM %1$s AS c WHERE c.key = "_user_id" AND c.value = %2$s )
639
  }
640
 
641
  // users, comma separated
642
+ if ( ! empty( $args['users'] ) && is_string( $args['users'] ) ) {
643
 
644
+ $users = explode( ',', $args['users'] );
645
+ $users = array_map( 'intval', $users );
646
 
647
  if ( $users ) {
648
 
649
+ $users_in = implode( ',', $users );
650
 
651
  $sql_user = sprintf(
652
  '
658
 
659
  $inner_where .= $sql_user;
660
 
661
+ // echo $inner_where;exit;
662
  }
 
663
  }
664
 
 
665
  /**
666
  * Filter the sql template
667
  *
669
  *
670
  * @param string $sql_tmpl
671
  */
672
+ $sql_tmpl = apply_filters( 'simple_history/log_query_sql_template', $sql_tmpl );
673
 
674
  /**
675
  * Filter the sql template where clause
678
  *
679
  * @param string $where
680
  */
681
+ $where = apply_filters( 'simple_history/log_query_sql_where', $where );
682
 
683
  /**
684
  * Filter the sql template limit
687
  *
688
  * @param string $limit
689
  */
690
+ $limit = apply_filters( 'simple_history/log_query_limit', $limit );
691
 
692
  /**
693
  * Filter the sql template limit
696
  *
697
  * @param string $limit
698
  */
699
+ $inner_where = apply_filters( 'simple_history/log_query_inner_where', $inner_where );
700
 
701
  $sql = sprintf(
702
  $sql_tmpl, // sprintf template
707
  $table_name_contexts // 5
708
  );
709
 
 
710
  /**
711
  * Filter the final sql query
712
  *
714
  *
715
  * @param string $sql
716
  */
717
+ $sql = apply_filters( 'simple_history/log_query_sql', $sql );
718
 
719
  // Remove comments below to debug query (includes query in json result)
720
  // $include_query_in_result = true;
721
+ if ( isset( $_GET['SimpleHistoryLogQuery-showDebug'] ) && $_GET['SimpleHistoryLogQuery-showDebug'] ) {
722
 
723
+ echo '<pre>';
724
  echo $sql_set_var;
725
  echo $sql;
726
  exit;
728
  }
729
 
730
  // Only return sql query
731
+ if ( $args['returnQuery'] ) {
732
  return $sql;
733
  }
734
 
735
+ $log_rows = $wpdb->get_results( $sql, OBJECT_K );
736
+ $num_rows = sizeof( $log_rows );
737
 
738
  // Find total number of rows that we would have gotten without pagination
739
  // This is the number of rows with occasions taken into consideration
741
  $total_found_rows = (int) $wpdb->get_var( $sql_found_rows );
742
 
743
  // Add context
744
+ $post_ids = wp_list_pluck( $log_rows, 'id' );
745
 
746
+ if ( empty( $post_ids ) ) {
747
  $context_results = array();
748
  } else {
749
+ $sql_context = sprintf( 'SELECT * FROM %2$s WHERE history_id IN (%1$s)', join( ',', $post_ids ), $table_name_contexts );
750
+ $context_results = $wpdb->get_results( $sql_context );
751
  }
752
 
753
  foreach ( $context_results as $context_row ) {
761
  }
762
 
763
  // Remove id from keys, because they are cumbersome when working with JSON
764
+ $log_rows = array_values( $log_rows );
765
  $min_id = null;
766
  $max_id = null;
767
 
768
+ if ( sizeof( $log_rows ) ) {
769
 
770
  // Max id is simply the id of the first row
771
+ $max_id = reset( $log_rows )->id;
772
 
773
  // Min id = to find the lowest id we must take occasions into consideration
774
+ $last_row = end( $log_rows );
775
  $last_row_occasions_count = (int) $last_row->subsequentOccasions - 1;
776
+ if ( $last_row_occasions_count === 0 ) {
777
 
778
  // Last row did not have any more occasions, so get min_id directly from the row
779
  $min_id = $last_row->id;
798
  $results = $wpdb->get_results( $sql );
799
 
800
  // the last occasion has the id we consider last in this paged result
801
+ $min_id = end( $results )->id;
802
 
803
  }
804
+ }// End if().
 
805
 
806
  // Calc pages
807
+ if ( $args['posts_per_page'] ) {
808
+ $pages_count = Ceil( $total_found_rows / (int) $args['posts_per_page'] );
809
  } else {
810
  $pages_count = 1;
811
  }
813
  // Create array to return
814
  // Make all rows a sub key because we want to add some meta info too
815
  $log_rows_count = sizeof( $log_rows );
816
+ $page_rows_from = ( (int) $args['paged'] * (int) $args['posts_per_page'] ) - (int) $args['posts_per_page'] + 1;
817
  $page_rows_to = $page_rows_from + $log_rows_count - 1;
818
  $arr_return = array(
819
+ 'total_row_count' => $total_found_rows,
820
+ 'pages_count' => $pages_count,
821
+ 'page_current' => (int) $args['paged'],
822
+ 'page_rows_from' => $page_rows_from,
823
+ 'page_rows_to' => $page_rows_to,
824
+ 'max_id' => (int) $max_id,
825
+ 'min_id' => (int) $min_id,
826
+ 'log_rows_count' => $log_rows_count,
827
+ 'log_rows' => $log_rows,
828
  );
829
 
830
+ // sf_d($arr_return, '$arr_return');exit;
831
+ wp_cache_set( $cache_key, $arr_return, $cache_group );
 
832
 
833
  return $arr_return;
834
 
index.php CHANGED
@@ -1,48 +1,48 @@
1
  <?php
2
- /*
3
- Plugin Name: Simple History
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.18
9
- Author: Pär Thernström
10
- Author URI: http://simple-history.com/
11
- License: GPL2
12
- GitHub Plugin URI: https://github.com/bonny/WordPress-Simple-History
13
- */
14
-
15
- /* Copyright 2015 Pär Thernström (email: par.thernstrom@gmail.com)
16
-
17
- This program is free software; you can redistribute it and/or modify
18
- it under the terms of the GNU General Public License, version 2, as
19
- published by the Free Software Foundation.
20
-
21
- This program is distributed in the hope that it will be useful,
22
- but WITHOUT ANY WARRANTY; without even the implied warranty of
23
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
- GNU General Public License for more details.
25
-
26
- You should have received a copy of the GNU General Public License
27
- along with this program; if not, write to the Free Software
28
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29
- */
30
 
31
  if ( ! defined( 'WPINC' ) ) {
32
  die;
33
  }
34
 
35
- if ( version_compare( phpversion(), "5.3", ">=") ) {
36
 
37
  /**
38
  * Register function that is called when plugin is installed
39
  *
40
  * @TODO: make activatigon multi site aware, as in https://github.com/scribu/wp-proper-network-activation
 
41
  */
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.18' );
46
  }
47
 
48
  if ( ! defined( 'SIMPLE_HISTORY_PATH' ) ) {
@@ -62,18 +62,11 @@ if ( version_compare( phpversion(), "5.3", ">=") ) {
62
  }
63
 
64
  /** Load required files */
65
- require_once(__DIR__ . "/inc/SimpleHistory.php");
66
- require_once(__DIR__ . "/inc/SimpleHistoryLogQuery.php");
67
-
68
- // Prev behavior:
69
- /*
70
- define( 'SIMPLE_HISTORY_FILE', __FILE__ );
71
- define( 'SIMPLE_HISTORY_PATH', plugin_dir_path( SIMPLE_HISTORY_FILE ) );
72
- define( 'SIMPLE_HISTORY_BASENAME', plugin_basename( SIMPLE_HISTORY_FILE ) );
73
- */
74
 
75
- // Constants will be like:
76
- /*
77
  SIMPLE_HISTORY_FILE:
78
  Var is string with length 57: /Users/username/GIT/Simple-History/index.php
79
  SIMPLE_HISTORY_PATH:
@@ -87,23 +80,24 @@ if ( version_compare( phpversion(), "5.3", ">=") ) {
87
 
88
  } else {
89
 
90
- // user is running to old version of php, add admin notice about that
91
  add_action( 'admin_notices', 'simple_history_old_version_admin_notice' );
92
 
 
 
 
93
  function simple_history_old_version_admin_notice() {
94
  ?>
95
  <div class="updated error">
96
  <p><?php
97
-
98
  printf(
99
- __( 'Simple History is a great plugin, but to use it your server must have at least PHP 5.3 installed (you have version %s).', 'simple-history' ),
100
- phpversion()
 
101
  );
102
-
103
  ?></p>
104
  </div>
105
  <?php
106
 
107
  }
108
-
109
- }
1
  <?php
2
+ /**
3
+ * Plugin Name: Simple History
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.19
9
+ * Author: Pär Thernström
10
+ * Author URI: http://simple-history.com/
11
+ * License: GPL2
12
+ * GitHub Plugin URI: https://github.com/bonny/WordPress-Simple-History
13
+ *
14
+ * @package Simple History
15
+ */
16
+
17
+ /**
18
+ * Copyright 2015 Pär Thernström (email: par.thernstrom@gmail.com)
19
+ * This program is free software; you can redistribute it and/or modify
20
+ * it under the terms of the GNU General Public License, version 2, as
21
+ * published by the Free Software Foundation.
22
+ * This program is distributed in the hope that it will be useful,
23
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
+ * GNU General Public License for more details.
26
+ * You should have received a copy of the GNU General Public License
27
+ * along with this program; if not, write to the Free Software
28
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29
+ */
30
 
31
  if ( ! defined( 'WPINC' ) ) {
32
  die;
33
  }
34
 
35
+ if ( version_compare( phpversion(), '5.3', '>=' ) ) {
36
 
37
  /**
38
  * Register function that is called when plugin is installed
39
  *
40
  * @TODO: make activatigon multi site aware, as in https://github.com/scribu/wp-proper-network-activation
41
+ * register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
42
  */
 
43
 
44
  if ( ! defined( 'SIMPLE_HISTORY_VERSION' ) ) {
45
+ define( 'SIMPLE_HISTORY_VERSION', '2.19' );
46
  }
47
 
48
  if ( ! defined( 'SIMPLE_HISTORY_PATH' ) ) {
62
  }
63
 
64
  /** Load required files */
65
+ require_once( __DIR__ . '/inc/SimpleHistory.php' );
66
+ require_once( __DIR__ . '/inc/SimpleHistoryLogQuery.php' );
 
 
 
 
 
 
 
67
 
68
+ /**
69
+ Constants will be like:
70
  SIMPLE_HISTORY_FILE:
71
  Var is string with length 57: /Users/username/GIT/Simple-History/index.php
72
  SIMPLE_HISTORY_PATH:
80
 
81
  } else {
82
 
83
+ // User is running to old version of php, add admin notice about that.
84
  add_action( 'admin_notices', 'simple_history_old_version_admin_notice' );
85
 
86
+ /**
87
+ * Show an admin message if old PHP version.
88
+ */
89
  function simple_history_old_version_admin_notice() {
90
  ?>
91
  <div class="updated error">
92
  <p><?php
 
93
  printf(
94
+ /* translators: 1: PHP version */
95
+ esc_html( __( 'Simple History is a great plugin, but to use it your server must have at least PHP 5.3 installed (you have version %s).', 'simple-history' ),
96
+ phpversion() )
97
  );
 
98
  ?></p>
99
  </div>
100
  <?php
101
 
102
  }
103
+ }// End if().
 
loggers/AvailableUpdatesLogger.php CHANGED
@@ -2,276 +2,297 @@
2
 
3
  /**
4
  * Logs available updates to themes, plugins and WordPress core
 
 
5
  */
6
- if ( ! class_exists("AvailableUpdatesLogger") ) {
7
 
8
- class AvailableUpdatesLogger extends SimpleLogger {
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
- public $slug = __CLASS__;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- function getInfo() {
13
-
14
- $arr_info = array(
15
- "name" => "AvailableUpdatesLogger",
16
- "description" => "Logs found updates to WordPress, plugins, and themes",
17
- "capability" => "manage_options",
18
- "messages" => array(
19
- "core_update_available" => __( 'Found an update to WordPress.', "simple-history" ),
20
- "plugin_update_available" => __( 'Found an update to plugin "{plugin_name}"', "simple-history" ),
21
- "theme_update_available" => __( 'Found an update to theme "{theme_name}"', "simple-history" ),
22
- ),
23
- "labels" => array(
24
- "search" => array(
25
- "label" => _x("WordPress and plugins updates found", "Plugin logger: updates found", "simple-history"),
26
- "label_all" => _x("All found updates", "Plugin logger: updates found", "simple-history"),
27
- "options" => array(
28
- _x("WordPress updates found", "Plugin logger: updates found", "simple-history") => array(
29
- 'core_update_available'
30
- ),
31
- _x("Plugin updates found", "Plugin logger: updates found", "simple-history") => array(
32
- 'plugin_update_available',
33
- ),
34
- _x("Theme updates found", "Plugin logger: updates found", "simple-history") => array(
35
- 'theme_update_available'
36
- ),
37
- )
38
- ) // search array
39
- ) // labels
40
- );
41
-
42
- return $arr_info;
43
-
44
- }
45
-
46
- function loaded() {
47
-
48
- // When WP is done checking for core updates it sets a site transient called "update_core"
49
- // set_site_transient( 'update_core', null ); // Uncomment to test
50
- add_action( "set_site_transient_update_core", array( $this, "on_setted_update_core_transient" ), 10, 1 );
51
-
52
- // Dito for plugins
53
- // set_site_transient( 'update_plugins', null ); // Uncomment to test
54
- add_action( "set_site_transient_update_plugins", array( $this, "on_setted_update_plugins_transient" ), 10, 1 );
55
-
56
- add_action( "set_site_transient_update_themes", array( $this, "on_setted_update_update_themes" ), 10, 1 );
57
-
58
- }
59
-
60
- function on_setted_update_core_transient( $updates ) {
61
-
62
- global $wp_version;
63
-
64
- $last_version_checked = get_option( "simplehistory_{$this->slug}_wp_core_version_available" );
65
-
66
- // During update of network sites this was not set, so make sure to check
67
- if ( empty( $updates->updates[0]->current ) ) {
68
- return;
69
- }
70
-
71
- $new_wp_core_version = $updates->updates[0]->current; // The new WP core version
72
-
73
- // Some plugins can mess with version, so get fresh from the version file.
74
- require_once ABSPATH . WPINC . '/version.php';
75
-
76
- // If found version is same version as we have logged about before then don't continue
77
- if ( $last_version_checked == $new_wp_core_version ) {
78
- return;
79
- }
80
-
81
- // is WP core update available?
82
- if ( 'upgrade' == $updates->updates[0]->response ) {
83
-
84
- $this->noticeMessage( "core_update_available", array(
85
- "wp_core_current_version" => $wp_version,
86
- "wp_core_new_version" => $new_wp_core_version,
87
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS
88
- ) );
89
-
90
- // Store updated version available, so we don't log that version again
91
- update_option( "simplehistory_{$this->slug}_wp_core_version_available", $new_wp_core_version );
92
-
93
- }
94
-
95
- }
96
-
97
-
98
- function on_setted_update_plugins_transient( $updates ) {
99
-
100
- if ( empty( $updates->response ) || ! is_array( $updates->response ) ) {
101
- return;
102
- }
103
-
104
- // If we only want to notify about active plugins
105
- /*
106
  $active_plugins = get_option( 'active_plugins' );
107
  $active_plugins = array_flip( $active_plugins ); // find which plugins are active
108
  $plugins_need_update = array_intersect_key( $plugins_need_update, $active_plugins ); // only keep plugins that are active
109
  */
110
 
111
- //update_option( "simplehistory_{$this->slug}_wp_core_version_available", $new_wp_core_version );
112
- $option_key = "simplehistory_{$this->slug}_plugin_updates_available";
113
- $checked_updates = get_option( $option_key );
114
-
115
- if ( ! is_array( $checked_updates ) ) {
116
- $checked_updates = array();
117
- }
118
 
119
- // File needed plugin API
120
- if ( ! function_exists("get_plugin_data") ) {
121
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
122
- }
123
 
124
- // For each available update
125
- foreach ( $updates->response as $key => $data ) {
 
 
126
 
127
- $plugin_info = get_plugin_data( WP_PLUGIN_DIR . "/" . $key, true, false );
 
128
 
129
- $plugin_new_version = isset( $data->new_version ) ? $data->new_version : "";
130
 
131
- // check if this plugin and this version has been checked/logged already
132
- if ( ! array_key_exists( $key, $checked_updates ) ) {
133
- $checked_updates[ $key ] = array(
134
- "checked_version" => null
135
- );
136
- }
137
 
138
- if ( $checked_updates[ $key ]["checked_version"] == $plugin_new_version ) {
139
- // This version has been checked/logged already
140
- continue;
141
- }
 
 
142
 
143
- $checked_updates[ $key ]["checked_version"] = $plugin_new_version;
 
 
 
144
 
145
- $this->noticeMessage( "plugin_update_available", array(
146
- "plugin_name" => isset( $plugin_info['Name'] ) ? $plugin_info['Name'] : "",
147
- "plugin_current_version" => isset( $plugin_info['Version'] ) ? $plugin_info['Version'] : "",
148
- "plugin_new_version" => $plugin_new_version,
149
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS,
150
- //"plugin_info" => $plugin_info,
151
- // "remote_plugin_info" => $remote_plugin_info,
152
- // "active_plugins" => $active_plugins,
153
- // "updates" => $updates
154
- ) );
155
 
156
- } // foreach
 
 
 
 
 
 
 
 
 
157
 
158
- update_option( $option_key, $checked_updates );
159
 
160
- } // function
161
 
 
162
 
163
- function on_setted_update_update_themes( $updates ) {
164
 
165
- if ( empty( $updates->response ) || ! is_array( $updates->response ) ) {
166
- return;
167
- }
168
 
169
- //update_option( "simplehistory_{$this->slug}_wp_core_version_available", $new_wp_core_version );
170
- $option_key = "simplehistory_{$this->slug}_theme_updates_available";
171
- $checked_updates = get_option( $option_key );
172
 
173
- if ( ! is_array( $checked_updates ) ) {
174
- $checked_updates = array();
175
- }
176
 
177
- // For each available update
178
- foreach ( $updates->response as $key => $data ) {
 
179
 
180
- $theme_info = wp_get_theme( $key );
 
181
 
182
- #$message .= "\n" . sprintf( __( "Theme: %s is out of date. Please update from version %s to %s", "wp-updates-notifier" ), $theme_info['Name'], $theme_info['Version'], $data['new_version'] ) . "\n";
183
 
184
- $settings['notified']['theme'][$key] = $data['new_version']; // set theme version we are notifying about
 
185
 
186
- $theme_new_version = isset( $data["new_version"] ) ? $data["new_version"] : "";
187
 
188
- // check if this plugin and this version has been checked/logged already
189
- if ( ! array_key_exists( $key, $checked_updates ) ) {
190
- $checked_updates[ $key ] = array(
191
- "checked_version" => null
192
- );
193
- }
194
 
195
- if ( $checked_updates[ $key ]["checked_version"] == $theme_new_version ) {
196
- // This version has been checked/logged already
197
- continue;
198
- }
199
 
200
- $checked_updates[ $key ]["checked_version"] = $theme_new_version;
201
 
202
- $this->noticeMessage( "theme_update_available", array(
203
- "theme_name" => isset( $theme_info['Name'] ) ? $theme_info['Name'] : "" ,
204
- "theme_current_version" => isset( $theme_info['Version'] ) ? $theme_info['Version'] : "",
205
- "theme_new_version" => $theme_new_version,
206
- "_initiator" => SimpleLoggerLogInitiators::WORDPRESS
207
- //"plugin_info" => $plugin_info,
208
- // "remote_plugin_info" => $remote_plugin_info,
209
- // "active_plugins" => $active_plugins,
210
- // "updates" => $updates,
211
- ) );
212
 
213
- } // foreach
214
 
215
- update_option( $option_key, $checked_updates );
216
 
217
- } // function
218
 
219
- /**
220
- * Append prev and current version of update object as details in the output
221
- */
222
- function getLogRowDetailsOutput( $row ) {
223
 
224
- $output = "";
225
 
226
- $current_version = null;
227
- $new_version = null;
228
- $context_message_key = isset($row->context_message_key) ? $row->context_message_key : null;
229
 
230
- $context = isset( $row->context ) ? $row->context : array();
231
 
232
- switch ( $context_message_key ) {
233
 
234
- case "core_update_available":
235
- $current_version = isset( $context["wp_core_current_version"] ) ? $context["wp_core_current_version"] : null;
236
- $new_version = isset( $context["wp_core_new_version"] ) ? $context["wp_core_new_version"] : null;
237
- break;
238
 
239
- case "plugin_update_available":
240
- $current_version = isset( $context["plugin_current_version"] ) ? $context["plugin_current_version"] : null;
241
- $new_version = isset( $context["plugin_new_version"] ) ? $context["plugin_new_version"] : null;
242
- break;
243
 
244
- case "theme_update_available":
245
- $current_version = isset( $context["theme_current_version"] ) ? $context["theme_current_version"] : null;
246
- $new_version = isset( $context["theme_new_version"] ) ? $context["theme_new_version"] : null;
247
- break;
248
 
249
- }
250
 
251
- if ( $current_version && $new_version ) {
252
 
253
- $output .= '<p>';
254
- $output .= '<span class="SimpleHistoryLogitem__inlineDivided">';
255
- $output .= "<em>" . __( 'Available version', "simple-history" ) . "</em> " . esc_html( $new_version );
256
- $output .= '</span> ';
257
 
258
- $output .= '<span class="SimpleHistoryLogitem__inlineDivided">';
259
- $output .= "<em>" . __( 'Installed version', "simple-history" ) . "</em> " . esc_html( $current_version );
260
- $output .= '</span>';
261
 
262
- $output .= '</p>';
263
 
264
- // Add link to update-page
265
- $output .= sprintf( '<p><a href="%1$s">', admin_url("update-core.php") );
266
- $output .= __( 'View all updates', "simple-history" );
267
- $output .= '</a></p>';
268
 
269
- }
 
 
 
 
 
270
 
271
- return $output;
272
 
273
- }
274
 
275
- } // class
276
 
277
- } // class exists
2
 
3
  /**
4
  * Logs available updates to themes, plugins and WordPress core
5
+ *
6
+ * @package SimpleHistory
7
  */
 
8
 
9
+ if ( ! class_exists( 'AvailableUpdatesLogger' ) ) {
10
+
11
+ /**
12
+ * Class.
13
+ */
14
+ class AvailableUpdatesLogger extends SimpleLogger {
15
+
16
+ /**
17
+ * Slug for logger.
18
+ *
19
+ * @var $slug string
20
+ */
21
+ public $slug = __CLASS__;
22
 
23
+ /**
24
+ * Return logger info
25
+ *
26
+ * @return array
27
+ */
28
+ function getInfo() {
29
+
30
+ $arr_info = array(
31
+ 'name' => 'AvailableUpdatesLogger',
32
+ 'description' => 'Logs found updates to WordPress, plugins, and themes',
33
+ 'capability' => 'manage_options',
34
+ 'messages' => array(
35
+ 'core_update_available' => __( 'Found an update to WordPress.', 'simple-history' ),
36
+ 'plugin_update_available' => __( 'Found an update to plugin "{plugin_name}"', 'simple-history' ),
37
+ 'theme_update_available' => __( 'Found an update to theme "{theme_name}"', 'simple-history' ),
38
+ ),
39
+ 'labels' => array(
40
+ 'search' => array(
41
+ 'label' => _x( 'WordPress and plugins updates found', 'Plugin logger: updates found', 'simple-history' ),
42
+ 'label_all' => _x( 'All found updates', 'Plugin logger: updates found', 'simple-history' ),
43
+ 'options' => array(
44
+ _x( 'WordPress updates found', 'Plugin logger: updates found', 'simple-history' ) => array(
45
+ 'core_update_available'
46
+ ),
47
+ _x( 'Plugin updates found', 'Plugin logger: updates found', 'simple-history' ) => array(
48
+ 'plugin_update_available',
49
+ ),
50
+ _x( 'Theme updates found', 'Plugin logger: updates found', 'simple-history' ) => array(
51
+ 'theme_update_available'
52
+ ),
53
+ ),
54
+ ), // search array.
55
+ ), // labels.
56
+ );
57
+
58
+ return $arr_info;
59
+
60
+ }
61
+
62
+ /**
63
+ * Called when logger is loaded.
64
+ */
65
+ function loaded() {
66
+
67
+ // When WP is done checking for core updates it sets a site transient called "update_core"
68
+ // set_site_transient( 'update_core', null ); // Uncomment to test
69
+ add_action( 'set_site_transient_update_core', array( $this, 'on_setted_update_core_transient' ), 10, 1 );
70
+
71
+ // Dito for plugins
72
+ // set_site_transient( 'update_plugins', null ); // Uncomment to test
73
+ add_action( 'set_site_transient_update_plugins', array( $this, 'on_setted_update_plugins_transient' ), 10, 1 );
74
+
75
+ add_action( 'set_site_transient_update_themes', array( $this, 'on_setted_update_update_themes' ), 10, 1 );
76
+
77
+ }
78
+
79
+ function on_setted_update_core_transient( $updates ) {
80
+
81
+ global $wp_version;
82
+
83
+ $last_version_checked = get_option( "simplehistory_{$this->slug}_wp_core_version_available" );
84
+
85
+ // During update of network sites this was not set, so make sure to check
86
+ if ( empty( $updates->updates[0]->current ) ) {
87
+ return;
88
+ }
89
+
90
+ $new_wp_core_version = $updates->updates[0]->current; // The new WP core version
91
+
92
+ // Some plugins can mess with version, so get fresh from the version file.
93
+ require_once ABSPATH . WPINC . '/version.php';
94
+
95
+ // If found version is same version as we have logged about before then don't continue
96
+ if ( $last_version_checked == $new_wp_core_version ) {
97
+ return;
98
+ }
99
+
100
+ // is WP core update available?
101
+ if ( 'upgrade' == $updates->updates[0]->response ) {
102
+
103
+ $this->noticeMessage( 'core_update_available', array(
104
+ 'wp_core_current_version' => $wp_version,
105
+ 'wp_core_new_version' => $new_wp_core_version,
106
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
107
+ ) );
108
+
109
+ // Store updated version available, so we don't log that version again
110
+ update_option( "simplehistory_{$this->slug}_wp_core_version_available", $new_wp_core_version );
111
+
112
+ }
113
+
114
+ }
115
+
116
+
117
+ function on_setted_update_plugins_transient( $updates ) {
118
+
119
+ if ( empty( $updates->response ) || ! is_array( $updates->response ) ) {
120
+ return;
121
+ }
122
 
123
+ // If we only want to notify about active plugins
124
+ /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  $active_plugins = get_option( 'active_plugins' );
126
  $active_plugins = array_flip( $active_plugins ); // find which plugins are active
127
  $plugins_need_update = array_intersect_key( $plugins_need_update, $active_plugins ); // only keep plugins that are active
128
  */
129
 
130
+ // update_option( "simplehistory_{$this->slug}_wp_core_version_available", $new_wp_core_version );
131
+ $option_key = "simplehistory_{$this->slug}_plugin_updates_available";
132
+ $checked_updates = get_option( $option_key );
 
 
 
 
133
 
134
+ if ( ! is_array( $checked_updates ) ) {
135
+ $checked_updates = array();
136
+ }
 
137
 
138
+ // File needed plugin API
139
+ if ( ! function_exists( 'get_plugin_data' ) ) {
140
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
141
+ }
142
 
143
+ // For each available update
144
+ foreach ( $updates->response as $key => $data ) {
145
 
146
+ $plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $key, true, false );
147
 
148
+ $plugin_new_version = isset( $data->new_version ) ? $data->new_version : '';
 
 
 
 
 
149
 
150
+ // check if this plugin and this version has been checked/logged already
151
+ if ( ! array_key_exists( $key, $checked_updates ) ) {
152
+ $checked_updates[ $key ] = array(
153
+ 'checked_version' => null,
154
+ );
155
+ }
156
 
157
+ if ( $checked_updates[ $key ]['checked_version'] == $plugin_new_version ) {
158
+ // This version has been checked/logged already
159
+ continue;
160
+ }
161
 
162
+ $checked_updates[ $key ]['checked_version'] = $plugin_new_version;
 
 
 
 
 
 
 
 
 
163
 
164
+ $this->noticeMessage( 'plugin_update_available', array(
165
+ 'plugin_name' => isset( $plugin_info['Name'] ) ? $plugin_info['Name'] : '',
166
+ 'plugin_current_version' => isset( $plugin_info['Version'] ) ? $plugin_info['Version'] : '',
167
+ 'plugin_new_version' => $plugin_new_version,
168
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
169
+ // "plugin_info" => $plugin_info,
170
+ // "remote_plugin_info" => $remote_plugin_info,
171
+ // "active_plugins" => $active_plugins,
172
+ // "updates" => $updates
173
+ ) );
174
 
175
+ } // End foreach().
176
 
177
+ update_option( $option_key, $checked_updates );
178
 
179
+ } // function
180
 
 
181
 
182
+ function on_setted_update_update_themes( $updates ) {
 
 
183
 
184
+ if ( empty( $updates->response ) || ! is_array( $updates->response ) ) {
185
+ return;
186
+ }
187
 
188
+ // update_option( "simplehistory_{$this->slug}_wp_core_version_available", $new_wp_core_version );
189
+ $option_key = "simplehistory_{$this->slug}_theme_updates_available";
190
+ $checked_updates = get_option( $option_key );
191
 
192
+ if ( ! is_array( $checked_updates ) ) {
193
+ $checked_updates = array();
194
+ }
195
 
196
+ // For each available update
197
+ foreach ( $updates->response as $key => $data ) {
198
 
199
+ $theme_info = wp_get_theme( $key );
200
 
201
+ // $message .= "\n" . sprintf( __( "Theme: %s is out of date. Please update from version %s to %s", "wp-updates-notifier" ), $theme_info['Name'], $theme_info['Version'], $data['new_version'] ) . "\n";
202
+ $settings['notified']['theme'][ $key ] = $data['new_version']; // set theme version we are notifying about
203
 
204
+ $theme_new_version = isset( $data['new_version'] ) ? $data['new_version'] : '';
205
 
206
+ // check if this plugin and this version has been checked/logged already
207
+ if ( ! array_key_exists( $key, $checked_updates ) ) {
208
+ $checked_updates[ $key ] = array(
209
+ 'checked_version' => null,
210
+ );
211
+ }
212
 
213
+ if ( $checked_updates[ $key ]['checked_version'] == $theme_new_version ) {
214
+ // This version has been checked/logged already
215
+ continue;
216
+ }
217
 
218
+ $checked_updates[ $key ]['checked_version'] = $theme_new_version;
219
 
220
+ $this->noticeMessage( 'theme_update_available', array(
221
+ 'theme_name' => isset( $theme_info['Name'] ) ? $theme_info['Name'] : '',
222
+ 'theme_current_version' => isset( $theme_info['Version'] ) ? $theme_info['Version'] : '',
223
+ 'theme_new_version' => $theme_new_version,
224
+ '_initiator' => SimpleLoggerLogInitiators::WORDPRESS,
225
+ // "plugin_info" => $plugin_info,
226
+ // "remote_plugin_info" => $remote_plugin_info,
227
+ // "active_plugins" => $active_plugins,
228
+ // "updates" => $updates,
229
+ ) );
230
 
231
+ } // End foreach().
232
 
233
+ update_option( $option_key, $checked_updates );
234
 
235
+ } // function
236
 
237
+ /**
238
+ * Append prev and current version of update object as details in the output
239
+ */
240
+ function getLogRowDetailsOutput( $row ) {
241
 
242
+ $output = '';
243
 
244
+ $current_version = null;
245
+ $new_version = null;
246
+ $context_message_key = isset( $row->context_message_key ) ? $row->context_message_key : null;
247
 
248
+ $context = isset( $row->context ) ? $row->context : array();
249
 
250
+ switch ( $context_message_key ) {
251
 
252
+ case 'core_update_available':
253
+ $current_version = isset( $context['wp_core_current_version'] ) ? $context['wp_core_current_version'] : null;
254
+ $new_version = isset( $context['wp_core_new_version'] ) ? $context['wp_core_new_version'] : null;
255
+ break;
256
 
257
+ case 'plugin_update_available':
258
+ $current_version = isset( $context['plugin_current_version'] ) ? $context['plugin_current_version'] : null;
259
+ $new_version = isset( $context['plugin_new_version'] ) ? $context['plugin_new_version'] : null;
260
+ break;
261
 
262
+ case 'theme_update_available':
263
+ $current_version = isset( $context['theme_current_version'] ) ? $context['theme_current_version'] : null;
264
+ $new_version = isset( $context['theme_new_version'] ) ? $context['theme_new_version'] : null;
265
+ break;
266
 
267
+ }
268
 
269
+ if ( $current_version && $new_version ) {
270
 
271
+ $output .= '<p>';
272
+ $output .= '<span class="SimpleHistoryLogitem__inlineDivided">';
273
+ $output .= '<em>' . __( 'Available version', 'simple-history' ) . '</em> ' . esc_html( $new_version );
274
+ $output .= '</span> ';
275
 
276
+ $output .= '<span class="SimpleHistoryLogitem__inlineDivided">';
277
+ $output .= '<em>' . __( 'Installed version', 'simple-history' ) . '</em> ' . esc_html( $current_version );
278
+ $output .= '</span>';
279
 
280
+ $output .= '</p>';
281
 
282
+ // Add link to update-page, if user is allowed to that page.
283
+ $is_allowed_to_update_page = current_user_can( 'update_core' ) || current_user_can( 'update_themes' ) || current_user_can( 'update_plugins' );
 
 
284
 
285
+ if ( $is_allowed_to_update_page ) {
286
+ $output .= sprintf( '<p><a href="%1$s">', admin_url( 'update-core.php' ) );
287
+ $output .= __( 'View all updates', 'simple-history' );
288
+ $output .= '</a></p>';
289
+ }
290
+ }
291
 
292
+ return $output;
293
 
294
+ }
295
 
296
+ } // class
297
 
298
+ } // End if().
loggers/FileEditsLogger.php CHANGED
@@ -5,63 +5,62 @@
5
  */
6
  class FileEditsLogger extends SimpleLogger {
7
 
8
- public $slug = __CLASS__;
9
-
10
- function getInfo() {
11
-
12
- $arr_info = array(
13
- "name" => "FileEditsLogger",
14
- "description" => "Logs edits to theme and plugin files",
15
- "capability" => "manage_options",
16
- "messages" => array(
17
- "theme_file_edited" => __( 'Edited file "{file_name}" in theme "{theme_name}"', "simple-history" ),
18
- "plugin_file_edited" => __( 'Edited file "{file_name}" in plugin "{plugin_name}"', "simple-history" ),
19
- ),
20
- "labels" => array(
21
- "search" => array(
22
- "label" => _x("Edited theme and plugin files", "Plugin logger: file edits", "simple-history"),
23
- "label_all" => _x("All file edits", "Plugin logger: file edits", "simple-history"),
24
- "options" => array(
25
- _x("Edited theme files", "Plugin logger: file edits", "simple-history") => array(
26
  'theme_file_edited'
27
  ),
28
- _x("Edited plugin files", "Plugin logger: file edits", "simple-history") => array(
29
  'plugin_file_edited',
30
  ),
31
- )
32
- ) // search array
33
- ) // labels
34
- );
35
-
36
- return $arr_info;
37
-
38
- }
39
-
40
- function loaded() {
41
- add_action( 'load-theme-editor.php', array( $this, "on_load_theme_editor" ), 10, 1 );
42
- add_action( 'load-plugin-editor.php', array( $this, "on_load_plugin_editor" ), 10, 1 );
43
- }
44
-
45
- /**
46
- * Called when /wp/wp-admin/plugin-editor.php is loaded
47
- * Both using regular GET and during POST with updated file data
48
- *
49
- * todo:
50
- * - log edits
51
- * - log failed edits that result in error and plugin deactivation
52
- */
53
- public function on_load_plugin_editor() {
54
- if ( isset($_POST) && isset($_POST['action']) ) {
55
-
56
- $action = isset($_POST["action"]) ? $_POST["action"] : null;
57
- $file = isset($_POST["file"]) ? $_POST["file"] : null;
58
- $plugin_file = isset($_POST["plugin"]) ? $_POST["plugin"] : null;
59
- $fileNewContents = isset($_POST["newcontent"]) ? wp_unslash( $_POST["newcontent"] ) : null;
60
- $scrollto = isset($_POST["scrollto"]) ? (int) $_POST["scrollto"] : 0;
61
-
62
- // if 'phperror' is set then there was an error and an edit is done and wp tries to activate the plugin again
63
- // $phperror = isset($_POST["phperror"]) ? $_POST["phperror"] : null;
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  // Get info about the edited plugin
66
  $pluginInfo = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_file );
67
  $pluginName = isset( $pluginInfo['Name'] ) ? $pluginInfo['Name'] : null;
@@ -71,18 +70,18 @@ class FileEditsLogger extends SimpleLogger {
71
  $fileContentsBeforeEdit = file_get_contents( WP_PLUGIN_DIR . '/' . $file );
72
 
73
  $context = array(
74
- "file_name" => $plugin_file,
75
- "plugin_name" => $pluginName,
76
- "plugin_version" => $pluginVersion,
77
- "old_file_contents" => $fileContentsBeforeEdit,
78
- "new_file_contents" => $fileNewContents,
79
- "_occasionsID" => __CLASS__ . '/' . __FUNCTION__ . "/file-edit/$plugin_file/$file"
80
  );
81
 
82
- #ddd($_POST, $context, $action, $file, $plugin, $phperror, $fileNewContents, $scrollto);
83
  $loggerInstance = $this;
84
  add_filter( 'wp_redirect', function ( $location, $status ) use ( $context, $loggerInstance ) {
85
- error_log($location);
86
 
87
  $locationParsed = parse_url( $location );
88
 
@@ -90,64 +89,59 @@ class FileEditsLogger extends SimpleLogger {
90
  return $location;
91
  }
92
 
93
- parse_str( $locationParsed['query'], $queryStringParsed);
94
- #ddd($_POST, $context, $queryStringParsed, $location);
95
-
96
- if (empty($queryStringParsed)) {
97
  return $location;
98
  }
99
 
100
  // If query string "a=te" exists or "liveupdate=1" then plugin file was updated
101
- $teIsSet = isset($queryStringParsed['a']) && $queryStringParsed['a'] === 'te';
102
- $liveUpdateIsSet = isset($queryStringParsed['liveupdate']) && $queryStringParsed['liveupdate'] === '1';
103
  if ( $teIsSet || $liveUpdateIsSet ) {
104
  // File was updated
105
- $loggerInstance->infoMessage('plugin_file_edited', $context);
106
  }
107
 
108
  return $location;
109
 
110
  // location when successful edit to non-active plugin
111
  // http://wp-playground.dev/wp/wp-admin/plugin-editor.php?file=akismet/akismet.php&plugin=akismet/akismet.php&a=te&scrollto=0
112
-
113
  // locations when activated plugin edited successfully
114
  // plugin-editor.php?file=akismet%2Fakismet.php&plugin=akismet%2Fakismet.php&liveupdate=1&scrollto=0&networkwide&_wpnonce=b3f399fe94
115
  // plugin-editor.php?file=akismet%2Fakismet.php&phperror=1&_error_nonce=63511c266d
116
  // http://wp-playground.dev/wp/wp-admin/plugin-editor.php?file=akismet/akismet.php&plugin=akismet/akismet.php&a=te&scrollto=0
117
-
118
  // locations when editing active plugin and error occurs
119
  // plugin-editor.php?file=akismet%2Fakismet.php&plugin=akismet%2Fakismet.php&liveupdate=1&scrollto=0&networkwide&_wpnonce=b3f399fe94
120
  // plugin-editor.php?file=akismet%2Fakismet.php&phperror=1&_error_nonce=63511c266d
121
-
122
  // locations when error edit is fixed and saved and plugin is activated again
123
  // plugin-editor.php?file=akismet%2Fakismet.php&plugin=akismet%2Fakismet.php&liveupdate=1&scrollto=0&networkwide&_wpnonce=b3f399fe94
124
  // plugin-editor.php?file=akismet%2Fakismet.php&phperror=1&_error_nonce=63511c266d
125
  // http://wp-playground.dev/wp/wp-admin/plugin-editor.php?file=akismet/akismet.php&plugin=akismet/akismet.php&a=te&scrollto=0
126
-
127
  }, 10, 2 );
128
 
129
- }
130
- /*
131
  <?php if (isset($_GET['a'])) : ?>
132
  <div id="message" class="updated notice is-dismissible"><p><?php _e('File edited successfully.') ?></p></div>
133
  <?php elseif (isset($_GET['phperror'])) : ?>
134
  <div id="message" class="updated"><p><?php _e('This plugin has been deactivated because your changes resulted in a <strong>fatal error</strong>.') ?></p>
135
  */
136
- }
137
-
138
- /**
139
- * Called when /wp/wp-admin/theme-editor.php is loaded
140
- * Both using regular GET and during POST with updated file data
141
- *
142
- * When this action is fired we don't know if a file will be successfully saved or not.
143
- * There are no filters/actions fired when the edit is saved. On the end wp_redirect() is
144
- * called however and we know the location for the redirect and wp_redirect() has filters
145
- * so we hook onto that to save the edit.
146
- */
147
- public function on_load_theme_editor() {
148
- // Only continue if method is post and action is update
149
- if (isset($_POST) && isset($_POST["action"]) && $_POST["action"] === "update") {
150
- /*
151
  POST data is like
152
  array(8)
153
  '_wpnonce' => string(10) "9b5e46634f"
@@ -160,11 +154,11 @@ class FileEditsLogger extends SimpleLogger {
160
  'submit' => string(11) "Update File"
161
  */
162
 
163
- $action = isset($_POST["action"]) ? $_POST["action"] : null;
164
- $file = isset($_POST["file"]) ? $_POST["file"] : null;
165
- $theme = isset($_POST["theme"]) ? $_POST["theme"] : null;
166
- $fileNewContents = isset($_POST["newcontent"]) ? wp_unslash( $_POST["newcontent"] ) : null;
167
- $scrollto = isset($_POST["scrollto"]) ? (int) $_POST["scrollto"] : 0;
168
 
169
  // Same code as in theme-editor.php
170
  if ( $theme ) {
@@ -175,7 +169,7 @@ class FileEditsLogger extends SimpleLogger {
175
 
176
  $theme = wp_get_theme( $stylesheet );
177
 
178
- if (! is_a($theme, 'WP_Theme')) {
179
  return;
180
  }
181
 
@@ -184,17 +178,17 @@ class FileEditsLogger extends SimpleLogger {
184
  $file = $theme->get_stylesheet_directory() . '/' . $relative_file;
185
 
186
  // Get file contents, so we have something to compare with later
187
- $fileContentsBeforeEdit = file_get_contents($file);
188
 
189
  $context = array(
190
- "theme_name" => $theme->name,
191
- "theme_stylesheet_path" => $theme->get_stylesheet(),
192
- "theme_stylesheet_dir" => $theme->get_stylesheet_directory(),
193
- "file_name" => $relative_file,
194
- "file_dir" => $file,
195
- "old_file_contents" => $fileContentsBeforeEdit,
196
- "new_file_contents" => $fileNewContents,
197
- "_occasionsID" => __CLASS__ . '/' . __FUNCTION__ . "/file-edit/$file"
198
  );
199
 
200
  // Hook into wp_redirect
@@ -207,15 +201,15 @@ class FileEditsLogger extends SimpleLogger {
207
  return $location;
208
  }
209
 
210
- parse_str( $locationParsed['query'], $queryStringParsed);
211
 
212
- if (empty($queryStringParsed)) {
213
  return $location;
214
  }
215
 
216
- if (isset($queryStringParsed["updated"]) && $queryStringParsed["updated"]) {
217
  // File was updated
218
- $loggerInstance->infoMessage('theme_file_edited', $context);
219
  } else {
220
  // File was not updated. Unknown reason, but probably because could not be written.
221
  }
@@ -223,16 +217,16 @@ class FileEditsLogger extends SimpleLogger {
223
  return $location;
224
 
225
  }, 10, 2 ); // add_filter
226
- } // if post action update
227
- }
228
 
229
 
230
  public function getLogRowDetailsOutput( $row ) {
231
 
232
  $context = $row->context;
233
- $message_key = isset( $context["_message_key"] ) ? $context["_message_key"] : null;
234
 
235
- if (! $message_key) {
236
  return;
237
  }
238
 
@@ -240,12 +234,12 @@ class FileEditsLogger extends SimpleLogger {
240
 
241
  $diff_table_output = '';
242
 
243
- if ( ! empty($context['new_file_contents']) && ! empty($context['old_file_contents']) ) {
244
  if ( $context['new_file_contents'] !== $context['old_file_contents'] ) {
245
  $diff_table_output .= sprintf(
246
  '<tr><td>%1$s</td><td>%2$s</td></tr>',
247
- __("File contents", "simple-history"),
248
- simple_history_text_diff($context['old_file_contents'], $context['new_file_contents'])
249
  );
250
  }
251
  }
5
  */
6
  class FileEditsLogger extends SimpleLogger {
7
 
8
+ public $slug = __CLASS__;
9
+
10
+ function getInfo() {
11
+
12
+ $arr_info = array(
13
+ 'name' => 'FileEditsLogger',
14
+ 'description' => 'Logs edits to theme and plugin files',
15
+ 'capability' => 'manage_options',
16
+ 'messages' => array(
17
+ 'theme_file_edited' => __( 'Edited file "{file_name}" in theme "{theme_name}"', 'simple-history' ),
18
+ 'plugin_file_edited' => __( 'Edited file "{file_name}" in plugin "{plugin_name}"', 'simple-history' ),
19
+ ),
20
+ 'labels' => array(
21
+ 'search' => array(
22
+ 'label' => _x( 'Edited theme and plugin files', 'Plugin logger: file edits', 'simple-history' ),
23
+ 'label_all' => _x( 'All file edits', 'Plugin logger: file edits', 'simple-history' ),
24
+ 'options' => array(
25
+ _x( 'Edited theme files', 'Plugin logger: file edits', 'simple-history' ) => array(
26
  'theme_file_edited'
27
  ),
28
+ _x( 'Edited plugin files', 'Plugin logger: file edits', 'simple-history' ) => array(
29
  'plugin_file_edited',
30
  ),
31
+ ),
32
+ ),// search array
33
+ ),// labels
34
+ );
35
+
36
+ return $arr_info;
37
+
38
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
+ function loaded() {
41
+ add_action( 'load-theme-editor.php', array( $this, 'on_load_theme_editor' ), 10, 1 );
42
+ add_action( 'load-plugin-editor.php', array( $this, 'on_load_plugin_editor' ), 10, 1 );
43
+ }
44
+
45
+ /**
46
+ * Called when /wp/wp-admin/plugin-editor.php is loaded
47
+ * Both using regular GET and during POST with updated file data
48
+ *
49
+ * todo:
50
+ * - log edits
51
+ * - log failed edits that result in error and plugin deactivation
52
+ */
53
+ public function on_load_plugin_editor() {
54
+ if ( isset( $_POST ) && isset( $_POST['action'] ) ) {
55
+
56
+ $action = isset( $_POST['action'] ) ? $_POST['action'] : null;
57
+ $file = isset( $_POST['file'] ) ? $_POST['file'] : null;
58
+ $plugin_file = isset( $_POST['plugin'] ) ? $_POST['plugin'] : null;
59
+ $fileNewContents = isset( $_POST['newcontent'] ) ? wp_unslash( $_POST['newcontent'] ) : null;
60
+ $scrollto = isset( $_POST['scrollto'] ) ? (int) $_POST['scrollto'] : 0;
61
+
62
+ // if 'phperror' is set then there was an error and an edit is done and wp tries to activate the plugin again
63
+ // $phperror = isset($_POST["phperror"]) ? $_POST["phperror"] : null;
64
  // Get info about the edited plugin
65
  $pluginInfo = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_file );
66
  $pluginName = isset( $pluginInfo['Name'] ) ? $pluginInfo['Name'] : null;
70
  $fileContentsBeforeEdit = file_get_contents( WP_PLUGIN_DIR . '/' . $file );
71
 
72
  $context = array(
73
+ 'file_name' => $plugin_file,
74
+ 'plugin_name' => $pluginName,
75
+ 'plugin_version' => $pluginVersion,
76
+ 'old_file_contents' => $fileContentsBeforeEdit,
77
+ 'new_file_contents' => $fileNewContents,
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
 
89
  return $location;
90
  }
91
 
92
+ parse_str( $locationParsed['query'], $queryStringParsed );
93
+ // ddd($_POST, $context, $queryStringParsed, $location);
94
+ if ( empty( $queryStringParsed ) ) {
 
95
  return $location;
96
  }
97
 
98
  // If query string "a=te" exists or "liveupdate=1" then plugin file was updated
99
+ $teIsSet = isset( $queryStringParsed['a'] ) && $queryStringParsed['a'] === 'te';
100
+ $liveUpdateIsSet = isset( $queryStringParsed['liveupdate'] ) && $queryStringParsed['liveupdate'] === '1';
101
  if ( $teIsSet || $liveUpdateIsSet ) {
102
  // File was updated
103
+ $loggerInstance->infoMessage( 'plugin_file_edited', $context );
104
  }
105
 
106
  return $location;
107
 
108
  // location when successful edit to non-active plugin
109
  // http://wp-playground.dev/wp/wp-admin/plugin-editor.php?file=akismet/akismet.php&plugin=akismet/akismet.php&a=te&scrollto=0
 
110
  // locations when activated plugin edited successfully
111
  // plugin-editor.php?file=akismet%2Fakismet.php&plugin=akismet%2Fakismet.php&liveupdate=1&scrollto=0&networkwide&_wpnonce=b3f399fe94
112
  // plugin-editor.php?file=akismet%2Fakismet.php&phperror=1&_error_nonce=63511c266d
113
  // http://wp-playground.dev/wp/wp-admin/plugin-editor.php?file=akismet/akismet.php&plugin=akismet/akismet.php&a=te&scrollto=0
 
114
  // locations when editing active plugin and error occurs
115
  // plugin-editor.php?file=akismet%2Fakismet.php&plugin=akismet%2Fakismet.php&liveupdate=1&scrollto=0&networkwide&_wpnonce=b3f399fe94
116
  // plugin-editor.php?file=akismet%2Fakismet.php&phperror=1&_error_nonce=63511c266d
 
117
  // locations when error edit is fixed and saved and plugin is activated again
118
  // plugin-editor.php?file=akismet%2Fakismet.php&plugin=akismet%2Fakismet.php&liveupdate=1&scrollto=0&networkwide&_wpnonce=b3f399fe94
119
  // plugin-editor.php?file=akismet%2Fakismet.php&phperror=1&_error_nonce=63511c266d
120
  // http://wp-playground.dev/wp/wp-admin/plugin-editor.php?file=akismet/akismet.php&plugin=akismet/akismet.php&a=te&scrollto=0
 
121
  }, 10, 2 );
122
 
123
+ }// End if().
124
+ /*
125
  <?php if (isset($_GET['a'])) : ?>
126
  <div id="message" class="updated notice is-dismissible"><p><?php _e('File edited successfully.') ?></p></div>
127
  <?php elseif (isset($_GET['phperror'])) : ?>
128
  <div id="message" class="updated"><p><?php _e('This plugin has been deactivated because your changes resulted in a <strong>fatal error</strong>.') ?></p>
129
  */
130
+ }
131
+
132
+ /**
133
+ * Called when /wp/wp-admin/theme-editor.php is loaded
134
+ * Both using regular GET and during POST with updated file data
135
+ *
136
+ * When this action is fired we don't know if a file will be successfully saved or not.
137
+ * There are no filters/actions fired when the edit is saved. On the end wp_redirect() is
138
+ * called however and we know the location for the redirect and wp_redirect() has filters
139
+ * so we hook onto that to save the edit.
140
+ */
141
+ public function on_load_theme_editor() {
142
+ // Only continue if method is post and action is update
143
+ if ( isset( $_POST ) && isset( $_POST['action'] ) && $_POST['action'] === 'update' ) {
144
+ /*
145
  POST data is like
146
  array(8)
147
  '_wpnonce' => string(10) "9b5e46634f"
154
  'submit' => string(11) "Update File"
155
  */
156
 
157
+ $action = isset( $_POST['action'] ) ? $_POST['action'] : null;
158
+ $file = isset( $_POST['file'] ) ? $_POST['file'] : null;
159
+ $theme = isset( $_POST['theme'] ) ? $_POST['theme'] : null;
160
+ $fileNewContents = isset( $_POST['newcontent'] ) ? wp_unslash( $_POST['newcontent'] ) : null;
161
+ $scrollto = isset( $_POST['scrollto'] ) ? (int) $_POST['scrollto'] : 0;
162
 
163
  // Same code as in theme-editor.php
164
  if ( $theme ) {
169
 
170
  $theme = wp_get_theme( $stylesheet );
171
 
172
+ if ( ! is_a( $theme, 'WP_Theme' ) ) {
173
  return;
174
  }
175
 
178
  $file = $theme->get_stylesheet_directory() . '/' . $relative_file;
179
 
180
  // Get file contents, so we have something to compare with later
181
+ $fileContentsBeforeEdit = file_get_contents( $file );
182
 
183
  $context = array(
184
+ 'theme_name' => $theme->name,
185
+ 'theme_stylesheet_path' => $theme->get_stylesheet(),
186
+ 'theme_stylesheet_dir' => $theme->get_stylesheet_directory(),
187
+ 'file_name' => $relative_file,
188
+ 'file_dir' => $file,
189
+ 'old_file_contents' => $fileContentsBeforeEdit,
190
+ 'new_file_contents' => $fileNewContents,
191
+ '_occasionsID' => __CLASS__ . '/' . __FUNCTION__ . "/file-edit/$file",
192
  );
193
 
194
  // Hook into wp_redirect
201
  return $location;
202
  }
203
 
204
+ parse_str( $locationParsed['query'], $queryStringParsed );
205
 
206
+ if ( empty( $queryStringParsed ) ) {
207
  return $location;
208
  }
209
 
210
+ if ( isset( $queryStringParsed['updated'] ) && $queryStringParsed['updated'] ) {
211
  // File was updated
212
+ $loggerInstance->infoMessage( 'theme_file_edited', $context );
213
  } else {
214
  // File was not updated. Unknown reason, but probably because could not be written.
215
  }
217
  return $location;
218
 
219
  }, 10, 2 ); // add_filter
220
+ } // End if().
221
+ }
222
 
223
 
224
  public function getLogRowDetailsOutput( $row ) {
225
 
226
  $context = $row->context;
227
+ $message_key = isset( $context['_message_key'] ) ? $context['_message_key'] : null;
228
 
229
+ if ( ! $message_key ) {
230
  return;
231
  }
232
 
234
 
235
  $diff_table_output = '';
236
 
237
+ if ( ! empty( $context['new_file_contents'] ) && ! empty( $context['old_file_contents'] ) ) {
238
  if ( $context['new_file_contents'] !== $context['old_file_contents'] ) {
239
  $diff_table_output .= sprintf(
240
  '<tr><td>%1$s</td><td>%2$s</td></tr>',
241
+ __( 'File contents', 'simple-history' ),
242
+ simple_history_text_diff( $context['old_file_contents'], $context['new_file_contents'] )
243
  );
244
  }
245
  }
loggers/PluginEnableMediaReplaceLogger.php CHANGED
@@ -20,12 +20,12 @@ class PluginEnableMediaReplaceLogger extends SimpleLogger {
20
  function getInfo() {
21
 
22
  $arr_info = array(
23
- "name" => _x("Enable Media Replace Logger", "PluginEnableMediaReplaceLogger", "simple-history"),
24
- "description" => _x("Logs media updates made with the Enable Media Replace Plugin", "PluginEnableMediaReplaceLogger", "simple-history"),
25
- "name_via" => _x("Using plugin Enable Media Replace", "PluginUserSwitchingLogger", "simple-history"),
26
- "capability" => "upload_files",
27
- "messages" => array(
28
- 'replaced_file' => _x('Replaced attachment "{prev_attachment_title}" with new attachment "{new_attachment_title}"', "PluginEnableMediaReplaceLogger", "simple-history"),
29
  ),
30
  );
31
 
@@ -36,7 +36,7 @@ class PluginEnableMediaReplaceLogger extends SimpleLogger {
36
  function loaded() {
37
 
38
  // Action that is called when Enable Media Replace loads it's admin options page (both when viewing and when posting new file to it)
39
- add_action( 'load-media_page_enable-media-replace/enable-media-replace', array( $this, "on_load_plugin_admin_page" ), 10, 1 );
40
  }
41
 
42
  function on_load_plugin_admin_page() {
@@ -45,11 +45,11 @@ class PluginEnableMediaReplaceLogger extends SimpleLogger {
45
  return;
46
  }
47
 
48
- if ( isset( $_GET["action"] ) && $_GET["action"] == "media_replace_upload" ) {
49
 
50
- $attachment_id = empty( $_POST["ID"] ) ? null : (int) $_POST["ID"];
51
- $replace_type = empty( $_POST["replace_type"] ) ? null : sanitize_text_field( $_POST["replace_type"] );
52
- $new_file = empty( $_FILES["userfile"] ) ? null : (array) $_FILES["userfile"];
53
 
54
  $prev_attachment_post = get_post( $attachment_id );
55
 
@@ -82,13 +82,13 @@ class PluginEnableMediaReplaceLogger extends SimpleLogger {
82
  }
83
  */
84
 
85
- $this->infoMessage("replaced_file", array(
86
- "attachment_id" => $attachment_id,
87
- "prev_attachment_title" => get_the_title( $prev_attachment_post ),
88
- "new_attachment_title" => $new_file["name"],
89
- "new_attachment_type" => $new_file["type"],
90
- "new_attachment_size" => $new_file["size"],
91
- "replace_type" => $replace_type,
92
  /*
93
  "get" => $_GET,
94
  "post" => $_POST,
@@ -98,7 +98,7 @@ class PluginEnableMediaReplaceLogger extends SimpleLogger {
98
  */
99
  ));
100
 
101
- }
102
 
103
  }
104
 
20
  function getInfo() {
21
 
22
  $arr_info = array(
23
+ 'name' => _x( 'Enable Media Replace Logger', 'PluginEnableMediaReplaceLogger', 'simple-history' ),
24
+ 'description' => _x( 'Logs media updates made with the Enable Media Replace Plugin', 'PluginEnableMediaReplaceLogger', 'simple-history' ),
25
+ 'name_via' => _x( 'Using plugin Enable Media Replace', 'PluginUserSwitchingLogger', 'simple-history' ),
26
+ 'capability' => 'upload_files',
27
+ 'messages' => array(
28
+ 'replaced_file' => _x( 'Replaced attachment "{prev_attachment_title}" with new attachment "{new_attachment_title}"', 'PluginEnableMediaReplaceLogger', 'simple-history' ),
29
  ),
30
  );
31
 
36
  function loaded() {
37
 
38
  // Action that is called when Enable Media Replace loads it's admin options page (both when viewing and when posting new file to it)
39
+ add_action( 'load-media_page_enable-media-replace/enable-media-replace', array( $this, 'on_load_plugin_admin_page' ), 10, 1 );
40
  }
41
 
42
  function on_load_plugin_admin_page() {
45
  return;
46
  }
47
 
48
+ if ( isset( $_GET['action'] ) && $_GET['action'] == 'media_replace_upload' ) {
49
 
50
+ $attachment_id = empty( $_POST['ID'] ) ? null : (int) $_POST['ID'];
51
+ $replace_type = empty( $_POST['replace_type'] ) ? null : sanitize_text_field( $_POST['replace_type'] );
52
+ $new_file = empty( $_FILES['userfile'] ) ? null : (array) $_FILES['userfile'];
53
 
54
  $prev_attachment_post = get_post( $attachment_id );
55
 
82
  }
83
  */
84
 
85
+ $this->infoMessage('replaced_file', array(
86
+ 'attachment_id' => $attachment_id,
87
+ 'prev_attachment_title' => get_the_title( $prev_attachment_post ),
88
+ 'new_attachment_title' => $new_file['name'],
89
+ 'new_attachment_type' => $new_file['type'],
90
+ 'new_attachment_size' => $new_file['size'],
91
+ 'replace_type' => $replace_type,
92
  /*
93
  "get" => $_GET,
94
  "post" => $_POST,
98
  */
99
  ));
100
 
101
+ }// End if().
102
 
103
  }
104
 
loggers/PluginUserSwitchingLogger.php CHANGED
@@ -20,16 +20,16 @@ class PluginUserSwitchingLogger extends SimpleLogger {
20
  function getInfo() {
21
 
22
  $arr_info = array(
23
- "name" => _x("User Switching Logger", "PluginUserSwitchingLogger", "simple-history"),
24
- "description" => _x("Logs user switches", "PluginUserSwitchingLogger", "simple-history"),
25
  // Definition of via: by way of, through the medium or agency of; also : by means of
26
- "name_via" => _x("Using plugin User Switching", "PluginUserSwitchingLogger", "simple-history"),
27
- "capability" => "edit_users",
28
- "messages" => array(
29
- 'switched_to_user' => _x('Switched to user "{user_login_to}" from user "{user_login_from}"', "PluginUserSwitchingLogger", "simple-history"),
30
- 'switched_back_user' => _x('Switched back to user "{user_login_to}" from user "{user_login_from}"', "PluginUserSwitchingLogger", "simple-history"),
31
- 'switched_back_themself' => _x('Switched back to user "{user_login_to}"', "PluginUserSwitchingLogger", "simple-history"),
32
- 'switched_off_user' => _x('Switched off user "{user_login}"', "PluginUserSwitchingLogger", "simple-history"),
33
  ),
34
  );
35
 
@@ -39,31 +39,31 @@ class PluginUserSwitchingLogger extends SimpleLogger {
39
 
40
  function loaded() {
41
 
42
- add_action( 'switch_to_user', array( $this, "on_switch_to_user" ), 10, 2 );
43
- add_action( 'switch_back_user', array( $this, "on_switch_back_user" ), 10, 2 );
44
- add_action( 'switch_off_user', array( $this, "on_switch_off_user" ), 10, 1 );
45
 
46
  }
47
 
48
  function on_switch_to_user( $user_id, $old_user_id ) {
49
 
50
- $user_to = get_user_by( "id", $user_id );
51
- $user_from = get_user_by( "id", $old_user_id );
52
 
53
- if ( ! is_a($user_to, "WP_User") || ! is_a($user_from, "WP_User") ) {
54
  return;
55
  }
56
 
57
  $this->infoMessage(
58
- "switched_to_user",
59
  array(
60
  // It is the old user who initiates the switching
61
- "_initiator" => SimpleLoggerLogInitiators::WP_USER,
62
- "_user_id" => $old_user_id,
63
- "user_id" => $user_id,
64
- "old_user_id" => $old_user_id,
65
- "user_login_to" => $user_to->user_login,
66
- "user_login_from" => $user_from->user_login,
67
  )
68
  );
69
 
@@ -81,11 +81,11 @@ class PluginUserSwitchingLogger extends SimpleLogger {
81
  */
82
  function on_switch_back_user( $user_id, $old_user_id ) {
83
 
84
- $user_to = get_user_by( "id", $user_id );
85
 
86
- $user_from = $old_user_id == false ? null : get_user_by( "id", $old_user_id );
87
 
88
- if ( ! is_a( $user_to, "WP_User" ) ) {
89
  return;
90
  }
91
 
@@ -93,14 +93,14 @@ class PluginUserSwitchingLogger extends SimpleLogger {
93
 
94
  // User switched back from another user
95
  $this->infoMessage(
96
- "switched_back_user",
97
  array(
98
- "_initiator" => SimpleLoggerLogInitiators::WP_USER,
99
- "_user_id" => $old_user_id,
100
- "user_id" => $user_id,
101
- "old_user_id" => $old_user_id,
102
- "user_login_to" => $user_to->user_login,
103
- "user_login_from" => $user_from->user_login
104
  )
105
  );
106
 
@@ -108,11 +108,11 @@ class PluginUserSwitchingLogger extends SimpleLogger {
108
 
109
  // User switched back to themself (no prev user)
110
  $this->infoMessage(
111
- "switched_back_themself",
112
  array(
113
- "_initiator" => SimpleLoggerLogInitiators::WP_USER,
114
- "_user_id" => $user_id,
115
- "user_login_to" => $user_to->user_login,
116
  )
117
  );
118
 
@@ -122,20 +122,20 @@ class PluginUserSwitchingLogger extends SimpleLogger {
122
 
123
  function on_switch_off_user( $user_id ) {
124
 
125
- $user = get_user_by( "id", $user_id );
126
 
127
- if ( ! is_a($user, "WP_User") ) {
128
  return;
129
  }
130
 
131
  $this->infoMessage(
132
- "switched_off_user",
133
  array(
134
- "_initiator" => SimpleLoggerLogInitiators::WP_USER,
135
- "_user_id" => $user_id,
136
 
137
- "user_id" => $user_id,
138
- "user_login" => $user->user_login
139
  )
140
  );
141
 
20
  function getInfo() {
21
 
22
  $arr_info = array(
23
+ 'name' => _x( 'User Switching Logger', 'PluginUserSwitchingLogger', 'simple-history' ),
24
+ 'description' => _x( 'Logs user switches', 'PluginUserSwitchingLogger', 'simple-history' ),
25
  // Definition of via: by way of, through the medium or agency of; also : by means of
26
+ 'name_via' => _x( 'Using plugin User Switching', 'PluginUserSwitchingLogger', 'simple-history' ),
27
+ 'capability' => 'edit_users',
28
+ 'messages' => array(
29
+ 'switched_to_user' => _x( 'Switched to user "{user_login_to}" from user "{user_login_from}"', 'PluginUserSwitchingLogger', 'simple-history' ),
30
+ 'switched_back_user' => _x( 'Switched back to user "{user_login_to}" from user "{user_login_from}"', 'PluginUserSwitchingLogger', 'simple-history' ),
31
+ 'switched_back_themself' => _x( 'Switched back to user "{user_login_to}"', 'PluginUserSwitchingLogger', 'simple-history' ),
32
+ 'switched_off_user' => _x( 'Switched off user "{user_login}"', 'PluginUserSwitchingLogger', 'simple-history' ),
33
  ),
34
  );
35
 
39
 
40
  function loaded() {
41
 
42
+ add_action( 'switch_to_user', array( $this, 'on_switch_to_user' ), 10, 2 );
43
+ add_action( 'switch_back_user', array( $this, 'on_switch_back_user' ), 10, 2 );
44
+ add_action( 'switch_off_user', array( $this, 'on_switch_off_user' ), 10, 1 );
45
 
46
  }
47
 
48
  function on_switch_to_user( $user_id, $old_user_id ) {
49
 
50
+ $user_to = get_user_by( 'id', $user_id );
51
+ $user_from = get_user_by( 'id', $old_user_id );
52
 
53
+ if ( ! is_a( $user_to, 'WP_User' ) || ! is_a( $user_from, 'WP_User' ) ) {
54
  return;
55
  }
56
 
57
  $this->infoMessage(
58
+ 'switched_to_user',
59
  array(
60
  // It is the old user who initiates the switching
61
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
62
+ '_user_id' => $old_user_id,
63
+ 'user_id' => $user_id,
64
+ 'old_user_id' => $old_user_id,
65
+ 'user_login_to' => $user_to->user_login,
66
+ 'user_login_from' => $user_from->user_login,
67
  )
68
  );
69
 
81
  */
82
  function on_switch_back_user( $user_id, $old_user_id ) {
83
 
84
+ $user_to = get_user_by( 'id', $user_id );
85
 
86
+ $user_from = $old_user_id == false ? null : get_user_by( 'id', $old_user_id );
87
 
88
+ if ( ! is_a( $user_to, 'WP_User' ) ) {
89
  return;
90
  }
91
 
93
 
94
  // User switched back from another user
95
  $this->infoMessage(
96
+ 'switched_back_user',
97
  array(
98
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
99
+ '_user_id' => $old_user_id,
100
+ 'user_id' => $user_id,
101
+ 'old_user_id' => $old_user_id,
102
+ 'user_login_to' => $user_to->user_login,
103
+ 'user_login_from' => $user_from->user_login,
104
  )
105
  );
106
 
108
 
109
  // User switched back to themself (no prev user)
110
  $this->infoMessage(
111
+ 'switched_back_themself',
112
  array(
113
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
114
+ '_user_id' => $user_id,
115
+ 'user_login_to' => $user_to->user_login,
116
  )
117
  );
118
 
122
 
123
  function on_switch_off_user( $user_id ) {
124
 
125
+ $user = get_user_by( 'id', $user_id );
126
 
127
+ if ( ! is_a( $user, 'WP_User' ) ) {
128
  return;
129
  }
130
 
131
  $this->infoMessage(
132
+ 'switched_off_user',
133
  array(
134
+ '_initiator' => SimpleLoggerLogInitiators::WP_USER,
135
+ '_user_id' => $user_id,
136
 
137
+ 'user_id' => $user_id,
138
+ 'user_login' => $user->user_login,
139
  )
140
  );
141
 
loggers/Plugin_DuplicatePost.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- defined('ABSPATH') or die();
4
 
5
  /**
6
  * Logger for the Duplicate Post plugin
@@ -9,122 +9,119 @@ defined('ABSPATH') or die();
9
  * @package SimpleHistory
10
  * @since 2.13
11
  */
12
- if (! class_exists("Plugin_DuplicatePost")) {
13
-
14
- class Plugin_DuplicatePost extends SimpleLogger
15
- {
16
- public $slug = __CLASS__;
17
-
18
- public function getInfo()
19
- {
20
- $arr_info = array(
21
- "name" => "Plugin Duplicate Posts",
22
- "description" => _x("Logs posts and pages cloned using plugin Duplicate Post", "Logger: Plugin Duplicate Post", "simple-history"),
23
- "name_via" => _x("Using plugin Duplicate Posts", "Logger: Plugin Duplicate Post", "simple-history"),
24
- "capability" => "manage_options",
25
- "messages" => array(
26
- 'post_duplicated' => _x('Cloned "{duplicated_post_title}" to a new post', "Logger: Plugin Duplicate Post", 'simple-history')
27
- ),
28
- );
29
-
30
- return $arr_info;
31
- }
32
-
33
- public function loaded()
34
- {
35
- require_once(ABSPATH . 'wp-admin/includes/plugin.php');
36
-
37
- $pluginFilePath = 'duplicate-post/duplicate-post.php';
38
- $isPluginActive = is_plugin_active('duplicate-post/duplicate-post.php');
39
-
40
- if (!$isPluginActive) {
41
- return;
42
- }
43
-
44
- // When a copy have been made of a post or page
45
- // the action 'dp_duplicate_page' or 'dp_duplicate_post'
46
- // is fired with args $new_post_id, $post, $status.
47
- // We add actions with prio 20 so we probably run after
48
- // the plugins own
49
- add_action('dp_duplicate_post', array($this, 'onDpDuplicatePost'), 100, 3);
50
- add_action('dp_duplicate_page', array($this, 'onDpDuplicatePost'), 100, 3);
51
- }
52
-
53
- /**
54
- * A post or page was duplicated
55
- *
56
- * @param $new_post_id
57
- * @param $post old post that a copy was made of
58
- * @param $status
59
- */
60
- public function onDpDuplicatePost($newPostID, $post, $status)
61
- {
62
- $new_post = get_post($newPostID);
63
-
64
- $context = array(
65
- "new_post_title" => $new_post->post_title,
66
- "new_post_id" => $new_post->ID,
67
- "duplicated_post_title" => $post->post_title,
68
- "duplicated_post_id" => $post->ID,
69
- // "duplicate_new_post_id" => $newPostID,
70
- // "status" => $status
71
- );
72
-
73
- $this->infoMessage(
74
- "post_duplicated",
75
- $context
76
- );
77
- }
78
-
79
- /**
80
- * Modify plain output to include link to post
81
- */
82
- public function getLogRowPlainTextOutput($row) {
83
-
84
- $context = $row->context;
85
- $new_post_id = isset($context["new_post_id"]) ? $context["new_post_id"] : null;
86
- $duplicated_post_id = isset($context["duplicated_post_id"]) ? $context["duplicated_post_id"] : null;
87
- $duplicated_post_title = isset($context["duplicated_post_title"]) ? $context["duplicated_post_title"] : null;
88
- $message_key = isset($context["_message_key"]) ? $context["_message_key"] : null;
89
-
90
- $message = $row->message;
91
-
92
- // Check if post still is available
93
- // It will return a WP_Post Object if post still is in system
94
- // If post is deleted from trash (not just moved there), then null is returned
95
- $postDuplicated = get_post($duplicated_post_id);
96
- $post_is_available = is_a($postDuplicated, "WP_Post");
97
-
98
- // Try to get singular name
99
- $post_type = isset($postDuplicated->post_type) ? $postDuplicated->post_type : "";
100
- $post_type_obj = get_post_type_object($post_type);
101
-
102
- if (!is_null($post_type_obj)) {
103
- if (!empty ($post_type_obj->labels->singular_name) ) {
104
- $context["duplicated_post_post_type_singular_name"] = strtolower($post_type_obj->labels->singular_name);
105
- }
106
- }
107
-
108
- $context["duplicated_post_edit_link"] = get_edit_post_link($duplicated_post_id);
109
- $context["new_post_edit_link"] = get_edit_post_link($new_post_id);
110
-
111
- // If post is not available any longer then we can't link to it, so keep plain message then
112
- // Also keep plain format if user is not allowed to edit post (edit link is empty)
113
- if ($post_is_available && $context["duplicated_post_edit_link"]) {
114
- $message = _x('Cloned {duplicated_post_post_type_singular_name} <a href="{duplicated_post_edit_link}">"{duplicated_post_title}"</a> to <a href="{new_post_edit_link}">a new {duplicated_post_post_type_singular_name}</a>', "Logger: Plugin Duplicate Post", "simple-history");
115
- } // post still available
116
-
117
- $context["new_post_edit_link"] = isset($context["new_post_edit_link"]) ? esc_html($context["new_post_edit_link"]) : "";
118
-
119
- $context["duplicated_post_edit_link"] = isset($context["duplicated_post_edit_link"]) ? esc_html($context["duplicated_post_edit_link"]) : "";
120
-
121
- $context["duplicated_post_title"] = isset($context["duplicated_post_title"]) ? esc_html($context["duplicated_post_title"]) : "";
122
-
123
- $context["duplicated_post_title"] = isset($context["duplicated_post_title"]) ? esc_html($context["duplicated_post_title"]) : "";
124
-
125
- $context["duplicated_post_post_type_singular_name"] = isset($context["duplicated_post_post_type_singular_name"]) ? esc_html($context["duplicated_post_post_type_singular_name"]) : "";
126
-
127
- return $this->interpolate($message, $context, $row);
128
- }
129
- } // class
130
- } // class exists
1
  <?php
2
 
3
+ defined( 'ABSPATH' ) or die();
4
 
5
  /**
6
  * Logger for the Duplicate Post plugin
9
  * @package SimpleHistory
10
  * @since 2.13
11
  */
12
+ if ( ! class_exists( 'Plugin_DuplicatePost' ) ) {
13
+
14
+ class Plugin_DuplicatePost extends SimpleLogger {
15
+
16
+ public $slug = __CLASS__;
17
+
18
+ public function getInfo() {
19
+ $arr_info = array(
20
+ 'name' => 'Plugin Duplicate Posts',
21
+ 'description' => _x( 'Logs posts and pages cloned using plugin Duplicate Post', 'Logger: Plugin Duplicate Post', 'simple-history' ),
22
+ 'name_via' => _x( 'Using plugin Duplicate Posts', 'Logger: Plugin Duplicate Post', 'simple-history' ),
23
+ 'capability' => 'manage_options',
24
+ 'messages' => array(
25
+ 'post_duplicated' => _x( 'Cloned "{duplicated_post_title}" to a new post', 'Logger: Plugin Duplicate Post', 'simple-history' ),
26
+ ),
27
+ );
28
+
29
+ return $arr_info;
30
+ }
31
+
32
+ public function loaded() {
33
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
34
+
35
+ $pluginFilePath = 'duplicate-post/duplicate-post.php';
36
+ $isPluginActive = is_plugin_active( 'duplicate-post/duplicate-post.php' );
37
+
38
+ if ( ! $isPluginActive ) {
39
+ return;
40
+ }
41
+
42
+ // When a copy have been made of a post or page
43
+ // the action 'dp_duplicate_page' or 'dp_duplicate_post'
44
+ // is fired with args $new_post_id, $post, $status.
45
+ // We add actions with prio 20 so we probably run after
46
+ // the plugins own
47
+ add_action( 'dp_duplicate_post', array( $this, 'onDpDuplicatePost' ), 100, 3 );
48
+ add_action( 'dp_duplicate_page', array( $this, 'onDpDuplicatePost' ), 100, 3 );
49
+ }
50
+
51
+ /**
52
+ * A post or page was duplicated
53
+ *
54
+ * @param $new_post_id
55
+ * @param $post old post that a copy was made of
56
+ * @param $status
57
+ */
58
+ public function onDpDuplicatePost( $newPostID, $post, $status ) {
59
+ $new_post = get_post( $newPostID );
60
+
61
+ $context = array(
62
+ 'new_post_title' => $new_post->post_title,
63
+ 'new_post_id' => $new_post->ID,
64
+ 'duplicated_post_title' => $post->post_title,
65
+ 'duplicated_post_id' => $post->ID,
66
+ // "duplicate_new_post_id" => $newPostID,
67
+ // "status" => $status
68
+ );
69
+
70
+ $this->infoMessage(
71
+ 'post_duplicated',
72
+ $context
73
+ );
74
+ }
75
+
76
+ /**
77
+ * Modify plain output to include link to post
78
+ */
79
+ public function getLogRowPlainTextOutput( $row ) {
80
+
81
+ $context = $row->context;
82
+ $new_post_id = isset( $context['new_post_id'] ) ? $context['new_post_id'] : null;
83
+ $duplicated_post_id = isset( $context['duplicated_post_id'] ) ? $context['duplicated_post_id'] : null;
84
+ $duplicated_post_title = isset( $context['duplicated_post_title'] ) ? $context['duplicated_post_title'] : null;
85
+ $message_key = isset( $context['_message_key'] ) ? $context['_message_key'] : null;
86
+
87
+ $message = $row->message;
88
+
89
+ // Check if post still is available
90
+ // It will return a WP_Post Object if post still is in system
91
+ // If post is deleted from trash (not just moved there), then null is returned
92
+ $postDuplicated = get_post( $duplicated_post_id );
93
+ $post_is_available = is_a( $postDuplicated, 'WP_Post' );
94
+
95
+ // Try to get singular name
96
+ $post_type = isset( $postDuplicated->post_type ) ? $postDuplicated->post_type : '';
97
+ $post_type_obj = get_post_type_object( $post_type );
98
+
99
+ if ( ! is_null( $post_type_obj ) ) {
100
+ if ( ! empty( $post_type_obj->labels->singular_name ) ) {
101
+ $context['duplicated_post_post_type_singular_name'] = strtolower( $post_type_obj->labels->singular_name );
102
+ }
103
+ }
104
+
105
+ $context['duplicated_post_edit_link'] = get_edit_post_link( $duplicated_post_id );
106
+ $context['new_post_edit_link'] = get_edit_post_link( $new_post_id );
107
+
108
+ // If post is not available any longer then we can't link to it, so keep plain message then
109
+ // Also keep plain format if user is not allowed to edit post (edit link is empty)
110
+ if ( $post_is_available && $context['duplicated_post_edit_link'] ) {
111
+ $message = _x( 'Cloned {duplicated_post_post_type_singular_name} <a href="{duplicated_post_edit_link}">"{duplicated_post_title}"</a> to <a href="{new_post_edit_link}">a new {duplicated_post_post_type_singular_name}</a>', 'Logger: Plugin Duplicate Post', 'simple-history' );
112
+ } // End if().
113
+
114
+ $context['new_post_edit_link'] = isset( $context['new_post_edit_link'] ) ? esc_html( $context['new_post_edit_link'] ) : '';
115
+
116
+ $context['duplicated_post_edit_link'] = isset( $context['duplicated_post_edit_link'] ) ? esc_html( $context['duplicated_post_edit_link'] ) : '';
117
+
118
+ $context['duplicated_post_title'] = isset( $context['duplicated_post_title'] ) ? esc_html( $context['duplicated_post_title'] ) : '';
119
+
120
+ $context['duplicated_post_title'] = isset( $context['duplicated_post_title'] ) ? esc_html( $context['duplicated_post_title'] ) : '';
121
+
122
+ $context['duplicated_post_post_type_singular_name'] = isset( $context['duplicated_post_post_type_singular_name'] ) ? esc_html( $context['duplicated_post_post_type_singular_name'] ) : '';
123
+
124
+ return $this->interpolate( $message, $context, $row );
125
+ }
126
+ } // class
127
+ } // End if().
 
 
 
loggers/Plugin_LimitLoginAttempts.php CHANGED
@@ -6,29 +6,30 @@ defined( 'ABSPATH' ) or die();
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(
@@ -38,207 +39,205 @@ if ( ! class_exists("Plugin_LimitLoginAttempts") ) {
38
  ),
39
  ), // end search
40
  ),*/ // end labels
41
- );
42
 
43
- return $arr_info;
44
 
45
- }
46
 
47
- function loaded() {
48
 
49
- require_once(ABSPATH . 'wp-admin/includes/plugin.php');
50
 
51
- $pluginFilePath = 'limit-login-attempts/limit-login-attempts.php';
52
- $isPluginActive = is_plugin_active($pluginFilePath);
53
 
54
- // Only continue to add filters if plugin is active.
55
- // This minimise the risk of plugin errors, because plugin
56
- // has been forked to new versions.
57
- if (!$isPluginActive) {
58
- return;
59
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
- add_filter( "pre_option_limit_login_lockouts_total", array( $this, "on_option_limit_login_lockouts_total" ), 10, 1 );
62
 
63
- add_action( "load-settings_page_limit-login-attempts", array( $this, "on_load_settings_page" ), 10, 1 );
64
-
65
- }
66
 
67
- /**
68
- * Fired when plugin options screen is loaded
69
- */
70
- function on_load_settings_page($a) {
71
-
72
- if ( $_POST && wp_verify_nonce($_POST["_wpnonce"], "limit-login-attempts-options") ) {
73
-
74
- // Settings saved
75
- if (isset($_POST['clear_log'])) {
76
- $this->noticeMessage( "cleared_ip_log" );
77
- }
78
-
79
- if (isset($_POST['reset_total'])) {
80
- $this->noticeMessage( "reseted_lockout_count" );
81
- }
82
-
83
- if (isset($_POST['reset_current'])) {
84
- $this->noticeMessage( "cleared_current_lockouts" );
85
- }
86
-
87
- if (isset($_POST['update_options'])) {
88
-
89
- $options = array(
90
- "client_type" => sanitize_text_field( $_POST['client_type'] ),
91
- "allowed_retries" => sanitize_text_field( $_POST['allowed_retries'] ),
92
- "lockout_duration" => sanitize_text_field( $_POST['lockout_duration'] ) * 60 ,
93
- "valid_duration" => sanitize_text_field( $_POST['valid_duration'] ) * 3600,
94
- "allowed_lockouts" => sanitize_text_field( $_POST['allowed_lockouts'] ),
95
- "long_duration" => sanitize_text_field( $_POST['long_duration'] ) * 3600,
96
- "email_after" => sanitize_text_field( $_POST['email_after'] ),
97
- "cookies" => (isset($_POST['cookies']) && $_POST['cookies'] == '1') ? "yes" : "no"
98
- );
99
-
100
- $v = array();
101
- if (isset($_POST['lockout_notify_log'])) {
102
- $v[] = 'log';
103
- }
104
- if (isset($_POST['lockout_notify_email'])) {
105
- $v[] = 'email';
106
- }
107
- $lockout_notify = implode(',', $v);
108
- $options["lockout_notify"] = $lockout_notify;
109
-
110
- $this->noticeMessage("updated_options", array(
111
- "options" => $options
112
- ));
113
-
114
- }
115
-
116
- }
117
-
118
- }
119
-
120
- /**
121
- * When option value is updated
122
- * do same checks as plugin itself does
123
- * and log if we match something
124
- */
125
- function on_option_limit_login_lockouts_total( $value ) {
126
 
127
- global $limit_login_just_lockedout;
 
 
 
 
 
128
 
129
- if ( ! $limit_login_just_lockedout ) {
130
- return $value;
131
- }
 
 
 
132
 
133
- $ip = limit_login_get_address();
134
- $whitelisted = is_limit_login_ip_whitelisted( $ip );
135
 
136
- $retries = get_option( 'limit_login_retries' );
137
- if ( ! is_array( $retries ) ) {
138
- $retries = array();
139
- }
140
 
141
- if ( isset( $retries[$ip] ) && ( ( $retries[$ip] / limit_login_option( 'allowed_retries' ) ) % limit_login_option( 'notify_email_after' ) ) != 0 ) {
142
 
143
- // $this->notice( "user locked out but don't log" );
144
- //return;
145
 
146
- }
147
 
148
- /* Format message. First current lockout duration */
149
- $lockout_type = "";
150
- if ( ! isset( $retries[$ip] ) ) {
151
- /* longer lockout */
152
- $lockout_type = "longer";
153
- $count = limit_login_option( 'allowed_retries' ) * limit_login_option( 'allowed_lockouts' );
154
- $lockouts = limit_login_option( 'allowed_lockouts' );
155
- $time = round( limit_login_option( 'long_duration' ) / 3600 );
156
- #$when = sprintf( _n( '%d hour', '%d hours', $time, "Logger: Plugin Limit Login Attempts", 'limit-login-attempts' ), $time );
157
- } else {
158
- /* normal lockout */
159
- $lockout_type = "normal";
160
- $count = $retries[$ip];
161
- $lockouts = floor( $count / limit_login_option( 'allowed_retries' ) );
162
- $time = round( limit_login_option( 'lockout_duration' ) / 60 );
163
- //$when = sprintf( _n( '%d minute', '%d minutes', $time, 'limit-login-attempts' ), $time );
164
- }
165
-
166
- if ( $whitelisted ) {
167
- // $subject = __( "Failed login attempts from whitelisted IP", 'limit-login-attempts' );
168
- $message_key = "failed_login_whitelisted";
169
- } else {
170
- // $subject = __( "Too many failed login attempts", 'limit-login-attempts' );
171
- $message_key = "failed_login";
172
- }
173
-
174
- $this->noticeMessage( $message_key, array(
175
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER,
176
- "value" => $value,
177
- "limit_login_just_lockedout" => $limit_login_just_lockedout,
178
- //"retries" => $retries,
179
- //"whitelisted" => $whitelisted, // bool, true | false
180
- //"subject" => $subject,
181
- //"message" => $message,
182
- "count" => $count, // num of failed login attempts before block
183
- "time" => $time, // duration in minutes for block
184
- "lockouts" => $lockouts,
185
- "ip" => $ip,
186
- "lockout_type" => $lockout_type
187
- ) );
188
-
189
- return $value;
190
-
191
- }
192
-
193
-
194
- /**
195
- * Add some extra info
196
- */
197
- function getLogRowDetailsOutput( $row ) {
198
 
199
- $output = "";
 
 
200
 
201
- $context = isset( $row->context ) ? $row->context : array();
202
 
203
- $message_key = $row->context_message_key;
204
 
205
- if ( "failed_login" == $message_key ) {
206
-
207
- $count = $context["count"];
208
- $lockouts = $context["lockouts"];
209
- $ip = $context["ip"];
210
- #$whitelisted = $context["whitelisted"];
211
- $lockout_type = $context["lockout_type"];
212
- $time = $context["time"];
213
-
214
- $output .= sprintf(
215
- "<p>" . _x( '%1$d failed login attempts (%2$d lockout(s)) from IP: %3$s', 'Logger: Plugin Limit Login Attempts', 'simple-history' ) . "</p>",
216
- $count, // 1
217
- $lockouts, // 2
218
- $ip // 3
219
- );
220
-
221
- if ( "longer" == $lockout_type ) {
222
-
223
- $when = sprintf( _nx( '%d hour', '%d hours', $time, 'Logger: Plugin Limit Login Attempts', 'limit-login-attempts' ), $time );
224
-
225
- } else if ( "normal" == $lockout_type ) {
226
-
227
- $when = sprintf( _nx( '%d minute', '%d minutes', $time, 'Logger: Plugin Limit Login Attempts', 'limit-login-attempts' ), $time );
228
-
229
- }
230
-
231
- $output .= "<p>" . sprintf(
232
- _x( 'IP was blocked for %1$s', 'Logger: Plugin Limit Login Attempts', 'simple-history' ),
233
- $when // 1
234
- ) . "</p>";
235
-
236
- }
237
-
238
- return $output;
239
-
240
- }
241
-
242
- } // class
243
-
244
- } // class exists
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
+ /*
32
+ "labels" => array(
33
  "search" => array(
34
  "label" => _x( "Limit Login Attempts", "Logger: Plugin Limit Login Attempts", "simple-history" ),
35
  "options" => array(
39
  ),
40
  ), // end search
41
  ),*/ // end labels
42
+ );
43
 
44
+ return $arr_info;
45
 
46
+ }
47
 
48
+ function loaded() {
49
 
50
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
51
 
52
+ $pluginFilePath = 'limit-login-attempts/limit-login-attempts.php';
53
+ $isPluginActive = is_plugin_active( $pluginFilePath );
54
 
55
+ // Only continue to add filters if plugin is active.
56
+ // This minimise the risk of plugin errors, because plugin
57
+ // has been forked to new versions.
58
+ if ( ! $isPluginActive ) {
59
+ return;
60
+ }
61
+
62
+ add_filter( 'pre_option_limit_login_lockouts_total', array( $this, 'on_option_limit_login_lockouts_total' ), 10, 1 );
63
+
64
+ add_action( 'load-settings_page_limit-login-attempts', array( $this, 'on_load_settings_page' ), 10, 1 );
65
+
66
+ }
67
+
68
+ /**
69
+ * Fired when plugin options screen is loaded
70
+ */
71
+ function on_load_settings_page( $a ) {
72
+
73
+ if ( $_POST && wp_verify_nonce( $_POST['_wpnonce'], 'limit-login-attempts-options' ) ) {
74
+
75
+ // Settings saved
76
+ if ( isset( $_POST['clear_log'] ) ) {
77
+ $this->noticeMessage( 'cleared_ip_log' );
78
+ }
79
+
80
+ if ( isset( $_POST['reset_total'] ) ) {
81
+ $this->noticeMessage( 'reseted_lockout_count' );
82
+ }
83
+
84
+ if ( isset( $_POST['reset_current'] ) ) {
85
+ $this->noticeMessage( 'cleared_current_lockouts' );
86
+ }
87
+
88
+ if ( isset( $_POST['update_options'] ) ) {
89
+
90
+ $options = array(
91
+ 'client_type' => sanitize_text_field( $_POST['client_type'] ),
92
+ 'allowed_retries' => sanitize_text_field( $_POST['allowed_retries'] ),
93
+ 'lockout_duration' => sanitize_text_field( $_POST['lockout_duration'] ) * 60,
94
+ 'valid_duration' => sanitize_text_field( $_POST['valid_duration'] ) * 3600,
95
+ 'allowed_lockouts' => sanitize_text_field( $_POST['allowed_lockouts'] ),
96
+ 'long_duration' => sanitize_text_field( $_POST['long_duration'] ) * 3600,
97
+ 'email_after' => sanitize_text_field( $_POST['email_after'] ),
98
+ 'cookies' => (isset( $_POST['cookies'] ) && $_POST['cookies'] == '1') ? 'yes' : 'no',
99
+ );
100
+
101
+ $v = array();
102
+ if ( isset( $_POST['lockout_notify_log'] ) ) {
103
+ $v[] = 'log';
104
+ }
105
+ if ( isset( $_POST['lockout_notify_email'] ) ) {
106
+ $v[] = 'email';
107
+ }
108
+ $lockout_notify = implode( ',', $v );
109
+ $options['lockout_notify'] = $lockout_notify;
110
+
111
+ $this->noticeMessage('updated_options', array(
112
+ 'options' => $options,
113
+ ));
114
+
115
+ }
116
+ }// End if().
117
+
118
+ }
119
+
120
+ /**
121
+ * When option value is updated
122
+ * do same checks as plugin itself does
123
+ * and log if we match something
124
+ */
125
+ function on_option_limit_login_lockouts_total( $value ) {
126
+
127
+ global $limit_login_just_lockedout;
128
+
129
+ if ( ! $limit_login_just_lockedout ) {
130
+ return $value;
131
+ }
132
+
133
+ $ip = limit_login_get_address();
134
+ $whitelisted = is_limit_login_ip_whitelisted( $ip );
135
+
136
+ $retries = get_option( 'limit_login_retries' );
137
+ if ( ! is_array( $retries ) ) {
138
+ $retries = array();
139
+ }
140
 
141
+ if ( isset( $retries[ $ip ] ) && ( ( $retries[ $ip ] / limit_login_option( 'allowed_retries' ) ) % limit_login_option( 'notify_email_after' ) ) != 0 ) {
142
 
143
+ // $this->notice( "user locked out but don't log" );
144
+ // return;
145
+ }
146
 
147
+ /* Format message. First current lockout duration */
148
+ $lockout_type = '';
149
+ if ( ! isset( $retries[ $ip ] ) ) {
150
+ /* longer lockout */
151
+ $lockout_type = 'longer';
152
+ $count = limit_login_option( 'allowed_retries' ) * limit_login_option( 'allowed_lockouts' );
153
+ $lockouts = limit_login_option( 'allowed_lockouts' );
154
+ $time = round( limit_login_option( 'long_duration' ) / 3600 );
155
+ // $when = sprintf( _n( '%d hour', '%d hours', $time, "Logger: Plugin Limit Login Attempts", 'limit-login-attempts' ), $time );
156
+ } else {
157
+ /* normal lockout */
158
+ $lockout_type = 'normal';
159
+ $count = $retries[ $ip ];
160
+ $lockouts = floor( $count / limit_login_option( 'allowed_retries' ) );
161
+ $time = round( limit_login_option( 'lockout_duration' ) / 60 );
162
+ // $when = sprintf( _n( '%d minute', '%d minutes', $time, 'limit-login-attempts' ), $time );
163
+ }
164
+
165
+ if ( $whitelisted ) {
166
+ // $subject = __( "Failed login attempts from whitelisted IP", 'limit-login-attempts' );
167
+ $message_key = 'failed_login_whitelisted';
168
+ } else {
169
+ // $subject = __( "Too many failed login attempts", 'limit-login-attempts' );
170
+ $message_key = 'failed_login';
171
+ }
172
+
173
+ $this->noticeMessage( $message_key, array(
174
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
175
+ 'value' => $value,
176
+ 'limit_login_just_lockedout' => $limit_login_just_lockedout,
177
+ // "retries" => $retries,
178
+ // "whitelisted" => $whitelisted, // bool, true | false
179
+ // "subject" => $subject,
180
+ // "message" => $message,
181
+ 'count' => $count, // num of failed login attempts before block
182
+ 'time' => $time, // duration in minutes for block
183
+ 'lockouts' => $lockouts,
184
+ 'ip' => $ip,
185
+ 'lockout_type' => $lockout_type,
186
+ ) );
187
+
188
+ return $value;
189
+
190
+ }
191
+
192
+
193
+ /**
194
+ * Add some extra info
195
+ */
196
+ function getLogRowDetailsOutput( $row ) {
197
+
198
+ $output = '';
199
+
200
+ $context = isset( $row->context ) ? $row->context : array();
201
+
202
+ $message_key = $row->context_message_key;
203
+
204
+ if ( 'failed_login' == $message_key ) {
 
205
 
206
+ $count = $context['count'];
207
+ $lockouts = $context['lockouts'];
208
+ $ip = $context['ip'];
209
+ // $whitelisted = $context["whitelisted"];
210
+ $lockout_type = $context['lockout_type'];
211
+ $time = $context['time'];
212
 
213
+ $output .= sprintf(
214
+ '<p>' . _x( '%1$d failed login attempts (%2$d lockout(s)) from IP: %3$s', 'Logger: Plugin Limit Login Attempts', 'simple-history' ) . '</p>',
215
+ $count, // 1
216
+ $lockouts, // 2
217
+ $ip // 3
218
+ );
219
 
220
+ if ( 'longer' == $lockout_type ) {
 
221
 
222
+ $when = sprintf( _nx( '%d hour', '%d hours', $time, 'Logger: Plugin Limit Login Attempts', 'limit-login-attempts' ), $time );
 
 
 
223
 
224
+ } elseif ( 'normal' == $lockout_type ) {
225
 
226
+ $when = sprintf( _nx( '%d minute', '%d minutes', $time, 'Logger: Plugin Limit Login Attempts', 'limit-login-attempts' ), $time );
 
227
 
228
+ }
229
 
230
+ $output .= '<p>' . sprintf(
231
+ _x( 'IP was blocked for %1$s', 'Logger: Plugin Limit Login Attempts', 'simple-history' ),
232
+ $when // 1
233
+ ) . '</p>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
 
235
+ }
236
+
237
+ return $output;
238
 
239
+ }
240
 
241
+ } // class
242
 
243
+ } // End if().
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
loggers/Plugin_Redirection.php CHANGED
@@ -6,7 +6,7 @@ defined( 'ABSPATH' ) or die();
6
  * Logger for the Redirection plugin
7
  * https://sv.wordpress.org/plugins/redirection/
8
  */
9
- if ( ! class_exists("Plugin_Redirection") ) {
10
 
11
  class Plugin_Redirection extends SimpleLogger {
12
 
@@ -15,20 +15,20 @@ if ( ! class_exists("Plugin_Redirection") ) {
15
  function getInfo() {
16
 
17
  $arr_info = array(
18
- "name" => "Redirection",
19
- "description" => _x("Text", "Logger: Redirection", "simple-history"),
20
- "name_via" => _x("In plugin Redirection", "Logger: Redirection", "simple-history"),
21
- "capability" => "manage_options",
22
- "messages" => array(
23
- 'redirection_redirection_added' => _x( 'Added a redirection for URL "{source_url}"', "Logger: Redirection", 'simple-history' ),
24
- 'redirection_redirection_edited' => _x( 'Edited the redirection for URL "{source_url}', "Logger: Redirection", 'simple-history' ),
25
- 'redirection_redirection_enabled' => _x( 'Enabled the redirection for {items_count} URL(s)', "Logger: Redirection", 'simple-history' ),
26
- 'redirection_redirection_disabled' => _x( 'Disabled the redirection for {items_count} URL(s)', "Logger: Redirection", 'simple-history' ),
27
- 'redirection_redirection_removed' => _x( 'Removed redirection for {items_count} URL(s)', "Logger: Redirection", 'simple-history' ),
28
- 'redirection_options_saved' => _x( 'Updated options', "Logger: Redirection", 'simple-history' ),
29
- 'redirection_options_removed_all' => _x( 'Removed all options and deactivated plugin', "Logger: Redirection", 'simple-history' ),
30
- 'redirection_group_added' => _x( 'Added group "{group_name}"', "Logger: Redirection", 'simple-history' ),
31
- 'redirection_group_deleted' => _x( 'Deleted {items_count} group(s)', "Logger: Redirection", 'simple-history' ),
32
  ),
33
  /*
34
  "labels" => array(
@@ -65,10 +65,10 @@ if ( ! class_exists("Plugin_Redirection") ) {
65
  function loaded() {
66
 
67
  // Catch redirection create, enable, disable
68
- add_action( "admin_init", array( $this, "on_admin_init" ) );
69
 
70
  // Catch edit existing redirect
71
- add_action( "wp_ajax_red_redirect_save", array( $this, "on_edit_save_redirect" ) );
72
 
73
  } // loaded
74
 
@@ -103,7 +103,7 @@ if ( ! class_exists("Plugin_Redirection") ) {
103
  $referer = wp_get_raw_referer();
104
 
105
  // We only continue if referer contains page=redirection.php
106
- if ( false === strpos( $referer, "page=redirection.php" ) ) {
107
  return;
108
  }
109
 
@@ -124,7 +124,7 @@ if ( ! class_exists("Plugin_Redirection") ) {
124
  "_wp_http_referer": "\/wp-admin\/tools.php?page=redirection.php"
125
  }
126
  */
127
- if ( isset( $_REQUEST["action"] ) && $_REQUEST["action"] == "red_redirect_add" ) {
128
  $this->log_redirection_add( $_REQUEST );
129
  return;
130
  }
@@ -146,10 +146,10 @@ if ( ! class_exists("Plugin_Redirection") ) {
146
  "action2": "-1"
147
  }
148
  */
149
- if ( isset( $_REQUEST["action"] ) && $_REQUEST["action"] == "enable" && empty( $_REQUEST["sub"] ) ) {
150
  $this->log_redirection_enable_or_disable( $_REQUEST );
151
  return;
152
- } else if ( isset( $_REQUEST["action"] ) && $_REQUEST["action"] == "disable" && empty( $_REQUEST["sub"] )) {
153
  $this->log_redirection_enable_or_disable( $_REQUEST );
154
  return;
155
  }
@@ -170,7 +170,7 @@ if ( ! class_exists("Plugin_Redirection") ) {
170
  "action2": "-1"
171
  }
172
  */
173
- if ( isset( $_REQUEST["action"] ) && $_REQUEST["action"] == "delete" && empty( $_REQUEST["sub"] ) ) {
174
  $this->log_redirection_delete( $_REQUEST );
175
  return;
176
  }
@@ -186,7 +186,7 @@ if ( ! class_exists("Plugin_Redirection") ) {
186
  "delete": "Delete"
187
  }
188
  */
189
- if ( isset( $_REQUEST["sub"] ) && $_REQUEST["sub"] == "options" && isset( $_REQUEST["delete"] ) && $_REQUEST["delete"] == "Delete" ) {
190
  $this->log_options_delete_all( $_REQUEST );
191
  return;
192
  }
@@ -207,8 +207,8 @@ if ( ! class_exists("Plugin_Redirection") ) {
207
  }
208
  */
209
  if (
210
- isset( $_REQUEST["sub"] ) && $_REQUEST["sub"] == "options" &&
211
- isset( $_REQUEST["update"] ) && $_REQUEST["update"] == "Update"
212
 
213
  ) {
214
  $this->log_options_save( $_REQUEST );
@@ -228,14 +228,13 @@ if ( ! class_exists("Plugin_Redirection") ) {
228
  }
229
  */
230
  if (
231
- isset( $_REQUEST["sub"] ) && $_REQUEST["sub"] == "groups" &&
232
- isset( $_REQUEST["add"] ) && $_REQUEST["add"] == "Add"
233
  ) {
234
  $this->log_group_add( $_REQUEST );
235
  return;
236
  }
237
 
238
-
239
  /*
240
  Delete group(s)
241
  {
@@ -254,8 +253,8 @@ if ( ! class_exists("Plugin_Redirection") ) {
254
  }
255
  */
256
  if (
257
- isset( $_REQUEST["sub"] ) && $_REQUEST["sub"] == "groups" &&
258
- isset( $_REQUEST["action"] ) && $_REQUEST["action"] == "delete"
259
  ) {
260
  $this->log_group_delete( $_REQUEST );
261
  return;
@@ -282,14 +281,14 @@ if ( ! class_exists("Plugin_Redirection") ) {
282
  }
283
  */
284
  if (
285
- isset( $_REQUEST["sub"] ) && $_REQUEST["sub"] == "groups" &&
286
- isset( $_REQUEST["action"] ) && $_REQUEST["action"] == "enable"
287
  ) {
288
  $this->log_group_enable_or_disable( $_REQUEST );
289
  return;
290
- } else if (
291
- isset( $_REQUEST["sub"] ) && $_REQUEST["sub"] == "groups" &&
292
- isset( $_REQUEST["action"] ) && $_REQUEST["action"] == "disable"
293
  ) {
294
  $this->log_group_enable_or_disable( $_REQUEST );
295
  return;
@@ -304,15 +303,15 @@ if ( ! class_exists("Plugin_Redirection") ) {
304
 
305
  function log_group_delete( $req ) {
306
 
307
- $items = isset( $req["item"] ) ? (array) $req["item"] : array();
308
 
309
  $context = array(
310
- "items" => $items,
311
- "items_count" => count( $items ),
312
  );
313
 
314
  $this->infoMessage(
315
- "redirection_group_deleted",
316
  $context
317
  );
318
 
@@ -320,18 +319,18 @@ if ( ! class_exists("Plugin_Redirection") ) {
320
 
321
  function log_group_add( $req ) {
322
 
323
- $group_name = isset( $req["name"] ) ? $req["name"] : null;
324
 
325
  if ( ! $group_name ) {
326
  return;
327
  }
328
 
329
  $context = array(
330
- "group_name" => $group_name
331
  );
332
 
333
  $this->infoMessage(
334
- "redirection_group_added",
335
  $context
336
  );
337
 
@@ -339,26 +338,26 @@ if ( ! class_exists("Plugin_Redirection") ) {
339
 
340
  function log_options_save( $req ) {
341
 
342
- $this->infoMessage("redirection_options_saved");
343
 
344
  }
345
 
346
  function log_options_delete_all( $req ) {
347
 
348
- $this->infoMessage("redirection_options_removed_all");
349
 
350
  }
351
 
352
  function log_redirection_delete( $req ) {
353
 
354
- $items = isset( $req["item"] ) ? (array) $req["item"] : array();
355
 
356
  $context = array(
357
- "items" => $items,
358
- "items_count" => count( $items )
359
  );
360
 
361
- $message_key = "redirection_redirection_removed";
362
 
363
  $this->infoMessage(
364
  $message_key,
@@ -387,19 +386,19 @@ if ( ! class_exists("Plugin_Redirection") ) {
387
  */
388
 
389
  $context = array(
390
- "source_url" => isset( $req["old"] ) ? $req["old"] : null,
391
- "target_url" => isset( $req["target"] ) ? $req["target"] : null,
392
- "item_id" => isset( $req["id"] ) ? $req["id"] : null,
393
- "title" => isset( $req["title"] ) ? $req["title"] : null,
394
- "regex" => isset( $req["regex"] ) ? true : false,
395
- "group_id" => isset( $req["group_id"] ) ? $req["group_id"] : null,
396
- "user_agent" => isset( $req["user_agent"] ) ? $req["user_agent"] : null,
397
- "url_from" => isset( $req["url_from"] ) ? $req["url_from"] : null,
398
- "url_notfrom" => isset( $req["url_notfrom"] ) ? $req["url_notfrom"] : null,
399
- "action_code" => isset( $req["action_code"] ) ? $req["action_code"] : null,
400
  );
401
 
402
- $message_key = "redirection_redirection_edited";
403
 
404
  $this->infoMessage(
405
  $message_key,
@@ -410,13 +409,13 @@ if ( ! class_exists("Plugin_Redirection") ) {
410
 
411
  function log_redirection_enable_or_disable( $req ) {
412
 
413
- $message_key = $req["action"] == "enable" ? "redirection_redirection_enabled" : "redirection_redirection_disabled";
414
 
415
- $items = isset( $req["item"] ) ? (array) $req["item"] : array();
416
 
417
  $context = array(
418
- "items" => $items,
419
- "items_count" => count( $items )
420
  );
421
 
422
  $this->infoMessage(
@@ -428,30 +427,30 @@ if ( ! class_exists("Plugin_Redirection") ) {
428
 
429
  function log_redirection_add( $req ) {
430
 
431
- if ( ! isset( $req["group_id"] ) ) {
432
  return;
433
  }
434
 
435
- $source = isset( $req["source"] ) ? $req["source"] : null;
436
- $target = isset( $req["target"] ) ? $req["target"] : null;
437
- $match = isset( $req["match"] ) ? $req["match"] : null;
438
- $action = isset( $req["action"] ) ? $req["action"] : null;
439
- $group_id = isset( $req["group_id"] ) ? $req["group_id"] : null;
440
- $regex = isset( $req["regex"] ) ? true : false;
441
 
442
  $context = array(
443
- "source_url" => $source,
444
- "target_url" => $target,
445
- "match" => $match,
446
- "action" => $action,
447
- "group_id" => $group_id,
448
- "regex" => $regex,
449
  );
450
 
451
- $this->infoMessage("redirection_redirection_added", $context);
452
 
453
  }
454
 
455
  } // class
456
 
457
- } // class exists
6
  * Logger for the Redirection plugin
7
  * https://sv.wordpress.org/plugins/redirection/
8
  */
9
+ if ( ! class_exists( 'Plugin_Redirection' ) ) {
10
 
11
  class Plugin_Redirection extends SimpleLogger {
12
 
15
  function getInfo() {
16
 
17
  $arr_info = array(
18
+ 'name' => 'Redirection',
19
+ 'description' => _x( 'Text', 'Logger: Redirection', 'simple-history' ),
20
+ 'name_via' => _x( 'In plugin Redirection', 'Logger: Redirection', 'simple-history' ),
21
+ 'capability' => 'manage_options',
22
+ 'messages' => array(
23
+ 'redirection_redirection_added' => _x( 'Added a redirection for URL "{source_url}"', 'Logger: Redirection', 'simple-history' ),
24
+ 'redirection_redirection_edited' => _x( 'Edited the redirection for URL "{source_url}', 'Logger: Redirection', 'simple-history' ),
25
+ 'redirection_redirection_enabled' => _x( 'Enabled the redirection for {items_count} URL(s)', 'Logger: Redirection', 'simple-history' ),
26
+ 'redirection_redirection_disabled' => _x( 'Disabled the redirection for {items_count} URL(s)', 'Logger: Redirection', 'simple-history' ),
27
+ 'redirection_redirection_removed' => _x( 'Removed redirection for {items_count} URL(s)', 'Logger: Redirection', 'simple-history' ),
28
+ 'redirection_options_saved' => _x( 'Updated options', 'Logger: Redirection', 'simple-history' ),
29
+ 'redirection_options_removed_all' => _x( 'Removed all options and deactivated plugin', 'Logger: Redirection', 'simple-history' ),
30
+ 'redirection_group_added' => _x( 'Added group "{group_name}"', 'Logger: Redirection', 'simple-history' ),
31
+ 'redirection_group_deleted' => _x( 'Deleted {items_count} group(s)', 'Logger: Redirection', 'simple-history' ),
32
  ),
33
  /*
34
  "labels" => array(
65
  function loaded() {
66
 
67
  // Catch redirection create, enable, disable
68
+ add_action( 'admin_init', array( $this, 'on_admin_init' ) );
69
 
70
  // Catch edit existing redirect
71
+ add_action( 'wp_ajax_red_redirect_save', array( $this, 'on_edit_save_redirect' ) );
72
 
73
  } // loaded
74
 
103
  $referer = wp_get_raw_referer();
104
 
105
  // We only continue if referer contains page=redirection.php
106
+ if ( false === strpos( $referer, 'page=redirection.php' ) ) {
107
  return;
108
  }
109
 
124
  "_wp_http_referer": "\/wp-admin\/tools.php?page=redirection.php"
125
  }
126
  */
127
+ if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'red_redirect_add' ) {
128
  $this->log_redirection_add( $_REQUEST );
129
  return;
130
  }
146
  "action2": "-1"
147
  }
148
  */
149
+ if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'enable' && empty( $_REQUEST['sub'] ) ) {
150
  $this->log_redirection_enable_or_disable( $_REQUEST );
151
  return;
152
+ } elseif ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'disable' && empty( $_REQUEST['sub'] ) ) {
153
  $this->log_redirection_enable_or_disable( $_REQUEST );
154
  return;
155
  }
170
  "action2": "-1"
171
  }
172
  */
173
+ if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'delete' && empty( $_REQUEST['sub'] ) ) {
174
  $this->log_redirection_delete( $_REQUEST );
175
  return;
176
  }
186
  "delete": "Delete"
187
  }
188
  */
189
+ if ( isset( $_REQUEST['sub'] ) && $_REQUEST['sub'] == 'options' && isset( $_REQUEST['delete'] ) && $_REQUEST['delete'] == 'Delete' ) {
190
  $this->log_options_delete_all( $_REQUEST );
191
  return;
192
  }
207
  }
208
  */
209
  if (
210
+ isset( $_REQUEST['sub'] ) && $_REQUEST['sub'] == 'options' &&
211
+ isset( $_REQUEST['update'] ) && $_REQUEST['update'] == 'Update'
212
 
213
  ) {
214
  $this->log_options_save( $_REQUEST );
228
  }
229
  */
230
  if (
231
+ isset( $_REQUEST['sub'] ) && $_REQUEST['sub'] == 'groups' &&
232
+ isset( $_REQUEST['add'] ) && $_REQUEST['add'] == 'Add'
233
  ) {
234
  $this->log_group_add( $_REQUEST );
235
  return;
236
  }
237
 
 
238
  /*
239
  Delete group(s)
240
  {
253
  }
254
  */
255
  if (
256
+ isset( $_REQUEST['sub'] ) && $_REQUEST['sub'] == 'groups' &&
257
+ isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'delete'
258
  ) {
259
  $this->log_group_delete( $_REQUEST );
260
  return;
281
  }
282
  */
283
  if (
284
+ isset( $_REQUEST['sub'] ) && $_REQUEST['sub'] == 'groups' &&
285
+ isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'enable'
286
  ) {
287
  $this->log_group_enable_or_disable( $_REQUEST );
288
  return;
289
+ } elseif (
290
+ isset( $_REQUEST['sub'] ) && $_REQUEST['sub'] == 'groups' &&
291
+ isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'disable'
292
  ) {
293
  $this->log_group_enable_or_disable( $_REQUEST );
294
  return;
303
 
304
  function log_group_delete( $req ) {
305
 
306
+ $items = isset( $req['item'] ) ? (array) $req['item'] : array();
307
 
308
  $context = array(
309
+ 'items' => $items,
310
+ 'items_count' => count( $items ),
311
  );
312
 
313
  $this->infoMessage(
314
+ 'redirection_group_deleted',
315
  $context
316
  );
317
 
319
 
320
  function log_group_add( $req ) {
321
 
322
+ $group_name = isset( $req['name'] ) ? $req['name'] : null;
323
 
324
  if ( ! $group_name ) {
325
  return;
326
  }
327
 
328
  $context = array(
329
+ 'group_name' => $group_name,
330
  );
331
 
332
  $this->infoMessage(
333
+ 'redirection_group_added',
334
  $context
335
  );
336
 
338
 
339
  function log_options_save( $req ) {
340
 
341
+ $this->infoMessage( 'redirection_options_saved' );
342
 
343
  }
344
 
345
  function log_options_delete_all( $req ) {
346
 
347
+ $this->infoMessage( 'redirection_options_removed_all' );
348
 
349
  }
350
 
351
  function log_redirection_delete( $req ) {
352
 
353
+ $items = isset( $req['item'] ) ? (array) $req['item'] : array();
354
 
355
  $context = array(
356
+ 'items' => $items,
357
+ 'items_count' => count( $items ),
358
  );
359
 
360
+ $message_key = 'redirection_redirection_removed';
361
 
362
  $this->infoMessage(
363
  $message_key,
386
  */
387
 
388
  $context = array(
389
+ 'source_url' => isset( $req['old'] ) ? $req['old'] : null,
390
+ 'target_url' => isset( $req['target'] ) ? $req['target'] : null,
391
+ 'item_id' => isset( $req['id'] ) ? $req['id'] : null,
392
+ 'title' => isset( $req['title'] ) ? $req['title'] : null,
393
+ 'regex' => isset( $req['regex'] ) ? true : false,
394
+ 'group_id' => isset( $req['group_id'] ) ? $req['group_id'] : null,
395
+ 'user_agent' => isset( $req['user_agent'] ) ? $req['user_agent'] : null,
396
+ 'url_from' => isset( $req['url_from'] ) ? $req['url_from'] : null,
397
+ 'url_notfrom' => isset( $req['url_notfrom'] ) ? $req['url_notfrom'] : null,
398
+ 'action_code' => isset( $req['action_code'] ) ? $req['action_code'] : null,
399
  );
400
 
401
+ $message_key = 'redirection_redirection_edited';
402
 
403
  $this->infoMessage(
404
  $message_key,
409
 
410
  function log_redirection_enable_or_disable( $req ) {
411
 
412
+ $message_key = $req['action'] == 'enable' ? 'redirection_redirection_enabled' : 'redirection_redirection_disabled';
413
 
414
+ $items = isset( $req['item'] ) ? (array) $req['item'] : array();
415
 
416
  $context = array(
417
+ 'items' => $items,
418
+ 'items_count' => count( $items ),
419
  );
420
 
421
  $this->infoMessage(
427
 
428
  function log_redirection_add( $req ) {
429
 
430
+ if ( ! isset( $req['group_id'] ) ) {
431
  return;
432
  }
433
 
434
+ $source = isset( $req['source'] ) ? $req['source'] : null;
435
+ $target = isset( $req['target'] ) ? $req['target'] : null;
436
+ $match = isset( $req['match'] ) ? $req['match'] : null;
437
+ $action = isset( $req['action'] ) ? $req['action'] : null;
438
+ $group_id = isset( $req['group_id'] ) ? $req['group_id'] : null;
439
+ $regex = isset( $req['regex'] ) ? true : false;
440
 
441
  $context = array(
442
+ 'source_url' => $source,
443
+ 'target_url' => $target,
444
+ 'match' => $match,
445
+ 'action' => $action,
446
+ 'group_id' => $group_id,
447
+ 'regex' => $regex,
448
  );
449
 
450
+ $this->infoMessage( 'redirection_redirection_added', $context );
451
 
452
  }
453
 
454
  } // class
455
 
456
+ } // End if().
loggers/Plugin_UltimateMembers_Logger.php CHANGED
@@ -20,11 +20,11 @@ class Plugin_UltimateMembers_Logger extends SimpleLogger {
20
  function getInfo() {
21
 
22
  $arr_info = array(
23
- "name" => _x("Ultimate Members Logger", "PluginUltimateMembersLogger", "simple-history"),
24
- "description" => _x("Logs actions from the Ultimate Members plugin", "PluginUltimateMembersLogger", "simple-history"),
25
- "capability" => "edit_users",
26
- "messages" => array(
27
- 'logged_in' => _x('Logged in', "PluginUltimateMembersLogger", "simple-history"),
28
  ),
29
  );
30
 
@@ -35,13 +35,13 @@ class Plugin_UltimateMembers_Logger extends SimpleLogger {
35
  function loaded() {
36
 
37
  // Action that is called when Enable Media Replace loads it's admin options page (both when viewing and when posting new file to it)
38
- add_action( 'um_on_login_before_redirect', array( $this, "on_um_on_login_before_redirect" ), 10, 1 );
39
  }
40
 
41
  function on_um_on_login_before_redirect( $user_id ) {
42
 
43
- $this->infoMessage("logged_in", array(
44
- //"user_id" => $user_id,
45
  /*
46
  "get" => $_GET,
47
  "post" => $_POST,
20
  function getInfo() {
21
 
22
  $arr_info = array(
23
+ 'name' => _x( 'Ultimate Members Logger', 'PluginUltimateMembersLogger', 'simple-history' ),
24
+ 'description' => _x( 'Logs actions from the Ultimate Members plugin', 'PluginUltimateMembersLogger', 'simple-history' ),
25
+ 'capability' => 'edit_users',
26
+ 'messages' => array(
27
+ 'logged_in' => _x( 'Logged in', 'PluginUltimateMembersLogger', 'simple-history' ),
28
  ),
29
  );
30
 
35
  function loaded() {
36
 
37
  // Action that is called when Enable Media Replace loads it's admin options page (both when viewing and when posting new file to it)
38
+ add_action( 'um_on_login_before_redirect', array( $this, 'on_um_on_login_before_redirect' ), 10, 1 );
39
  }
40
 
41
  function on_um_on_login_before_redirect( $user_id ) {
42
 
43
+ $this->infoMessage('logged_in', array(
44
+ // "user_id" => $user_id,
45
  /*
46
  "get" => $_GET,
47
  "post" => $_POST,
loggers/SimpleCategoriesLogger.php CHANGED
@@ -17,14 +17,15 @@ class SimpleCategoriesLogger extends SimpleLogger {
17
  function getInfo() {
18
 
19
  $arr_info = array(
20
- "name" => __("Categories Logger", "simple-history"),
21
- "description" => "Logs changes to categories, tags, and taxonomies",
22
- "messages" => array(
23
- 'created_term' => __('Added term "{term_name}" in taxonomy "{term_taxonomy}"', 'simple-history'),
24
- 'deleted_term' => __('Deleted term "{term_name}" from taxonomy "{term_taxonomy}"', 'simple-history'),
25
- 'edited_term' => __('Edited term "{to_term_name}" in taxonomy "{to_term_taxonomy}"', 'simple-history'),
26
  ),
27
- /*"labels" => array(
 
28
  "search" => array(
29
  "label" => _x("WordPress Core", "User logger: search", "simple-history"),
30
  "options" => array(
@@ -43,7 +44,6 @@ class SimpleCategoriesLogger extends SimpleLogger {
43
  }
44
 
45
  /*
46
-
47
  * Fires after a new term is created, and after the term cache has been cleaned.
48
  *
49
  * @since 2.3.0
@@ -81,13 +81,12 @@ class SimpleCategoriesLogger extends SimpleLogger {
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
  // This action does not contain enough info to know what the term was called before the update
89
  // add_action( "edited_term", array( $this, "on_edited_term"), 10, 3 );
90
-
91
  }
92
 
93
  /*
@@ -102,7 +101,7 @@ class SimpleCategoriesLogger extends SimpleLogger {
102
  */
103
  function on_wp_update_term_parent( $parent = null, $term_id = null, $taxonomy = null, $parsed_args = null, $term_update_args = null ) {
104
 
105
- $term_before_edited = get_term_by( "id", $term_id, $taxonomy );
106
 
107
  if ( ! $term_before_edited || empty( $term_update_args ) ) {
108
  return $parent;
@@ -115,29 +114,29 @@ class SimpleCategoriesLogger extends SimpleLogger {
115
  $from_term_slug = $term_before_edited->slug;
116
  $from_term_description = $term_before_edited->description;
117
 
118
- $to_term_name = $term_update_args["name"];
119
- $to_term_taxonomy = $term_update_args["taxonomy"];
120
- $to_term_slug = $term_update_args["slug"];
121
- $to_term_description = $term_update_args["description"];
122
 
123
  $this->infoMessage(
124
- "edited_term",
125
  array(
126
- "term_id" => $term_id,
127
- "from_term_name" => $from_term_name,
128
- "from_term_taxonomy" => $from_term_taxonomy,
129
- "from_term_slug" => $from_term_slug,
130
- "from_term_description" => $from_term_description,
131
- "to_term_name" => $to_term_name,
132
- "to_term_taxonomy" => $to_term_taxonomy,
133
- "to_term_slug" => $to_term_slug,
134
- "to_term_description" => $to_term_description,
135
- #"term_update_args" => $term_update_args,
136
- #"term_before_edited" => $term_before_edited
137
- #"parent" => $parent,
138
- #"taxonomy" => $taxonomy,
139
- #"parsed_args" => $parsed_args,
140
- #"term_update_args" => $term_update_args
141
  )
142
  );
143
 
@@ -156,7 +155,7 @@ class SimpleCategoriesLogger extends SimpleLogger {
156
  */
157
  function on_created_term( $term_id = null, $tt_id = null, $taxonomy = null ) {
158
 
159
- $term = get_term_by( "id", $term_id, $taxonomy );
160
 
161
  if ( ! $term ) {
162
  return;
@@ -167,11 +166,11 @@ class SimpleCategoriesLogger extends SimpleLogger {
167
  $term_id = $term->term_id;
168
 
169
  $this->infoMessage(
170
- "created_term",
171
  array(
172
- "term_id" => $term_id,
173
- "term_name" => $term_name,
174
- "term_taxonomy" => $term_taxonomy,
175
  )
176
  );
177
 
@@ -198,11 +197,11 @@ class SimpleCategoriesLogger extends SimpleLogger {
198
  $term_id = $deleted_term->term_id;
199
 
200
  $this->infoMessage(
201
- "deleted_term",
202
  array(
203
- "term_id" => $term_id,
204
- "term_name" => $term_name,
205
- "term_taxonomy" => $term_taxonomy,
206
  // "deleted_term" => $deleted_term,
207
  )
208
  );
17
  function getInfo() {
18
 
19
  $arr_info = array(
20
+ 'name' => __( 'Categories Logger', 'simple-history' ),
21
+ 'description' => 'Logs changes to categories, tags, and taxonomies',
22
+ 'messages' => array(
23
+ 'created_term' => __( 'Added term "{term_name}" in taxonomy "{term_taxonomy}"', 'simple-history' ),
24
+ 'deleted_term' => __( 'Deleted term "{term_name}" from taxonomy "{term_taxonomy}"', 'simple-history' ),
25
+ 'edited_term' => __( 'Edited term "{to_term_name}" in taxonomy "{to_term_taxonomy}"', 'simple-history' ),
26
  ),
27
+ /*
28
+ "labels" => array(
29
  "search" => array(
30
  "label" => _x("WordPress Core", "User logger: search", "simple-history"),
31
  "options" => array(
44
  }
45
 
46
  /*
 
47
  * Fires after a new term is created, and after the term cache has been cleaned.
48
  *
49
  * @since 2.3.0
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
  // This action does not contain enough info to know what the term was called before the update
89
  // add_action( "edited_term", array( $this, "on_edited_term"), 10, 3 );
 
90
  }
91
 
92
  /*
101
  */
102
  function on_wp_update_term_parent( $parent = null, $term_id = null, $taxonomy = null, $parsed_args = null, $term_update_args = null ) {
103
 
104
+ $term_before_edited = get_term_by( 'id', $term_id, $taxonomy );
105
 
106
  if ( ! $term_before_edited || empty( $term_update_args ) ) {
107
  return $parent;
114
  $from_term_slug = $term_before_edited->slug;
115
  $from_term_description = $term_before_edited->description;
116
 
117
+ $to_term_name = $term_update_args['name'];
118
+ $to_term_taxonomy = $term_update_args['taxonomy'];
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(
125
+ 'term_id' => $term_id,
126
+ 'from_term_name' => $from_term_name,
127
+ 'from_term_taxonomy' => $from_term_taxonomy,
128
+ 'from_term_slug' => $from_term_slug,
129
+ 'from_term_description' => $from_term_description,
130
+ 'to_term_name' => $to_term_name,
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
 
155
  */
156
  function on_created_term( $term_id = null, $tt_id = null, $taxonomy = null ) {
157
 
158
+ $term = get_term_by( 'id', $term_id, $taxonomy );
159
 
160
  if ( ! $term ) {
161
  return;
166
  $term_id = $term->term_id;
167
 
168
  $this->infoMessage(
169
+ 'created_term',
170
  array(
171
+ 'term_id' => $term_id,
172
+ 'term_name' => $term_name,
173
+ 'term_taxonomy' => $term_taxonomy,
174
  )
175
  );
176
 
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
  );
loggers/SimpleCommentsLogger.php CHANGED
@@ -5,19 +5,19 @@ defined( 'ABSPATH' ) or die();
5
  /**
6
  * Logs things related to comments
7
  */
8
- class SimpleCommentsLogger extends SimpleLogger
9
- {
10
 
11
  public $slug = __CLASS__;
12
 
13
- function __construct($sh) {
14
 
15
- parent::__construct($sh);
16
 
17
  // Add option to not show spam comments, because to much things getting logged
18
- #add_filter("simple_history/log_query_sql_where", array($this, "maybe_modify_log_query_sql_where"));
19
- add_filter("simple_history/log_query_inner_where", array($this, "maybe_modify_log_query_sql_where"));
20
- add_filter("simple_history/quick_stats_where", array($this, "maybe_modify_log_query_sql_where"));
21
 
22
  }
23
 
@@ -26,7 +26,7 @@ class SimpleCommentsLogger extends SimpleLogger
26
  *
27
  * @param string $where sql query where
28
  */
29
- function maybe_modify_log_query_sql_where($where) {
30
 
31
  // since 19 sept 2016 we do include spam, to skip the subquery
32
  // spam comments should not be logged anyway since some time
@@ -41,7 +41,7 @@ class SimpleCommentsLogger extends SimpleLogger
41
  *
42
  * @param bool $include_spam Default false
43
  */
44
- $include_spam = apply_filters("simple_history/comments_logger/include_spam", $include_spam);
45
 
46
  if ( $include_spam ) {
47
  return $where;
@@ -76,8 +76,7 @@ class SimpleCommentsLogger extends SimpleLogger
76
  )
77
  ', $this->db_table, $this->db_table_contexts, $this->slug);
78
 
79
- #echo $where;
80
-
81
  return $where;
82
 
83
  }
@@ -90,10 +89,10 @@ class SimpleCommentsLogger extends SimpleLogger
90
  function getInfo() {
91
 
92
  $arr_info = array(
93
- "name" => "Comments Logger",
94
- "description" => "Logs comments, and modifications to them",
95
- "capability" => "moderate_comments",
96
- "messages" => array(
97
 
98
  // Comments
99
  'anon_comment_added' => _x(
@@ -262,59 +261,59 @@ class SimpleCommentsLogger extends SimpleLogger
262
 
263
  ), // end messages
264
 
265
- "labels" => array(
266
-
267
- "search" => array(
268
- "label" => _x("Comments", "Comments logger: search", "simple-history"),
269
- "label_all" => _x("All comments activity", "Comments logger: search", "simple-history"),
270
- "options" => array(
271
- _x("Added comments", "Comments logger: search", "simple-history") => array(
272
- "anon_comment_added",
273
- "user_comment_added",
274
- "anon_trackback_added",
275
- "user_trackback_added",
276
- "anon_pingback_added",
277
- "user_pingback_added"
278
  ),
279
- _x("Edited comments", "Comments logger: search", "simple-history") => array(
280
- "comment_edited",
281
- "trackback_edited",
282
- "pingback_edited"
283
  ),
284
- _x("Approved comments", "Comments logger: search", "simple-history") => array(
285
- "comment_status_approve",
286
- "trackback_status_approve",
287
- "pingback_status_approve"
288
  ),
289
- _x("Held comments", "Comments logger: search", "simple-history") => array(
290
- "comment_status_hold",
291
- "trackback_status_hold",
292
- "pingback_status_hold"
293
  ),
294
- _x("Comments status changed to spam", "Comments logger: search", "simple-history") => array(
295
- "comment_status_spam",
296
- "trackback_status_spam",
297
- "pingback_status_spam"
298
  ),
299
- _x("Trashed comments", "Comments logger: search", "simple-history") => array(
300
- "comment_status_trash",
301
- "trackback_status_trash",
302
- "pingback_status_trash"
303
  ),
304
- _x("Untrashed comments", "Comments logger: search", "simple-history") => array(
305
- "comment_untrashed",
306
- "trackback_untrashed",
307
- "pingback_untrashed"
308
  ),
309
- _x("Deleted comments", "Comments logger: search", "simple-history") => array(
310
- "comment_deleted",
311
- "trackback_deleted",
312
- "pingback_deleted"
313
  ),
314
- )
315
- ) // end search
316
 
317
- ) // labels
318
 
319
  );
320
 
@@ -327,30 +326,29 @@ class SimpleCommentsLogger extends SimpleLogger
327
  /**
328
  * Fires immediately after a comment is inserted into the database.
329
  */
330
- add_action( 'comment_post', array( $this, 'on_comment_post'), 10, 2 );
331
 
332
  /**
333
  * Fires after a comment status has been updated in the database.
334
  * The hook also fires immediately before comment status transition hooks are fired.
335
  */
336
- add_action( "wp_set_comment_status", array( $this, 'on_wp_set_comment_status'), 10, 2 );
337
 
338
  /**
339
  *Fires immediately after a comment is restored from the Trash.
340
  */
341
- add_action( "untrashed_comment", array( $this, 'on_untrashed_comment'), 10, 1 );
342
 
343
- /**
344
- * Fires immediately before a comment is deleted from the database.
345
- */
346
- add_action( "delete_comment", array( $this, 'on_delete_comment'), 10, 1 );
347
 
348
  /**
349
  * Fires immediately after a comment is updated in the database.
350
- * The hook also fires immediately before comment status transition hooks are fired.
351
- */
352
- add_action( "edit_comment", array( $this, 'on_edit_comment'), 10, 1 );
353
-
354
 
355
  }
356
 
@@ -360,7 +358,7 @@ class SimpleCommentsLogger extends SimpleLogger
360
  * @param int $comment_ID
361
  * @return mixed array with context if comment found, false if comment not found
362
  */
363
- public function get_context_for_comment($comment_ID) {
364
 
365
  // get_comment passes comment_ID by reference, so it can be unset by that function
366
  $comment_ID_original = $comment_ID;
@@ -373,33 +371,33 @@ class SimpleCommentsLogger extends SimpleLogger
373
  $comment_parent_post = get_post( $comment_data->comment_post_ID );
374
 
375
  $context = array(
376
- "comment_ID" => $comment_ID_original,
377
- "comment_author" => $comment_data->comment_author,
378
- "comment_author_email" => $comment_data->comment_author_email,
379
- "comment_author_url" => $comment_data->comment_author_url,
380
- "comment_author_IP" => $comment_data->comment_author_IP,
381
- "comment_content" => $comment_data->comment_content,
382
- "comment_approved" => $comment_data->comment_approved,
383
- "comment_agent" => $comment_data->comment_agent,
384
- "comment_type" => $comment_data->comment_type,
385
- "comment_parent" => $comment_data->comment_parent,
386
- "comment_post_ID" => $comment_data->comment_post_ID,
387
- "comment_post_title" => $comment_parent_post->post_title,
388
- "comment_post_type" => $comment_parent_post->post_type,
389
  );
390
 
391
  // Note: comment type is empty for normal comments
392
- if (empty( $context["comment_type"] ) ) {
393
- $context["comment_type"] = "comment";
394
  }
395
 
396
  return $context;
397
 
398
  }
399
 
400
- public function on_edit_comment($comment_ID) {
401
 
402
- $context = $this->get_context_for_comment($comment_ID);
403
  if ( ! $context ) {
404
  return;
405
  }
@@ -414,23 +412,21 @@ class SimpleCommentsLogger extends SimpleLogger
414
  public function on_delete_comment( $comment_ID ) {
415
 
416
  $context = $this->get_context_for_comment( $comment_ID );
417
-
418
  if ( ! $context ) {
419
  return;
420
  }
421
 
422
-
423
  $comment_data = get_comment( $comment_ID );
424
 
425
  // add occasions if comment was considered spam
426
  // if not added, spam comments can easily flood the log
427
  // Deletions of spam easiy flood log
428
- if ( isset( $comment_data->comment_approved ) && "spam" === $comment_data->comment_approved ) {
429
-
430
  // since 2.5.5: don't log deletion of spam comments
431
  return;
432
  // $context["_occasionsID"] = __CLASS__ . '/' . __FUNCTION__ . "/anon_{$context["comment_type"]}_deleted/type:spam";
433
-
434
  }
435
 
436
  $this->infoMessage(
@@ -440,9 +436,9 @@ class SimpleCommentsLogger extends SimpleLogger
440
 
441
  }
442
 
443
- public function on_untrashed_comment($comment_ID) {
444
 
445
- $context = $this->get_context_for_comment($comment_ID);
446
  if ( ! $context ) {
447
  return;
448
  }
@@ -457,6 +453,7 @@ class SimpleCommentsLogger extends SimpleLogger
457
  /**
458
  * Fires after a comment status has been updated in the database.
459
  * The hook also fires immediately before comment status transition hooks are fired.
 
460
  * @param int $comment_id The comment ID.
461
  * @param string|bool $comment_status The comment status. Possible values include 'hold',
462
  * 'approve', 'spam', 'trash', or false.
@@ -464,8 +461,8 @@ class SimpleCommentsLogger extends SimpleLogger
464
  */
465
  public function on_wp_set_comment_status( $comment_ID, $comment_status ) {
466
 
467
- $context = $this->get_context_for_comment($comment_ID);
468
-
469
  if ( ! $context ) {
470
  return;
471
  }
@@ -502,13 +499,13 @@ class SimpleCommentsLogger extends SimpleLogger
502
  }
503
 
504
  // since 2.5.5: no more logging of spam comments
505
- if ( isset( $comment_approved ) && "spam" === $comment_approved ) {
506
  return;
507
  }
508
 
509
  $comment_data = get_comment( $comment_ID );
510
 
511
- $message = "";
512
 
513
  if ( $comment_data->user_id ) {
514
 
@@ -519,14 +516,13 @@ class SimpleCommentsLogger extends SimpleLogger
519
 
520
  // comment was from a non-logged in user
521
  $message = "anon_{$context["comment_type"]}_added";
522
- $context["_initiator"] = SimpleLoggerLogInitiators::WEB_USER;
523
 
524
  // add occasions if comment is considered spam
525
  // if not added, spam comments can easily flood the log
526
- if ( isset( $comment_data->comment_approved ) && "spam" === $comment_data->comment_approved ) {
527
- $context["_occasionsID"] = __CLASS__ . '/' . __FUNCTION__ . "/anon_{$context["comment_type"]}_added/type:spam";
528
  }
529
-
530
  }
531
 
532
  $this->infoMessage(
@@ -541,20 +537,20 @@ class SimpleCommentsLogger extends SimpleLogger
541
  * Modify plain output to inlcude link to post
542
  * and link to comment
543
  */
544
- public function getLogRowPlainTextOutput($row) {
545
 
546
  $message = $row->message;
547
  $context = $row->context;
548
- $message_key = $context["_message_key"];
549
 
550
  // Message is untranslated here, so get translated text
551
  // Can't call parent __FUNCTION__ because it will interpolate too, which we don't want
552
  if ( ! empty( $message_key ) ) {
553
- $message = $this->messages[ $message_key ]["translated_text"];
554
  }
555
 
556
  // Wrap links around {comment_post_title}
557
- $comment_post_ID = isset( $context["comment_post_ID"] ) ? (int) $context["comment_post_ID"] : null;
558
  if ( $comment_post_ID && $comment_post = get_post( $comment_post_ID ) ) {
559
 
560
  $edit_post_link = get_edit_post_link( $comment_post_ID );
@@ -568,11 +564,9 @@ class SimpleCommentsLogger extends SimpleLogger
568
  );
569
 
570
  }
571
-
572
  }
573
 
574
-
575
- return $this->interpolate($message, $context, $row);
576
 
577
  }
578
 
@@ -580,81 +574,81 @@ class SimpleCommentsLogger extends SimpleLogger
580
  /**
581
  * Get output for detailed log section
582
  */
583
- function getLogRowDetailsOutput($row) {
584
 
585
  $context = $row->context;
586
- $message_key = $context["_message_key"];
587
- $output = "";
588
- #print_r($row);exit;
589
  /*
590
  if ( 'spam' !== $commentdata['comment_approved'] ) { // If it's spam save it silently for later crunching
591
  if ( '0' == $commentdata['comment_approved'] ) { // comment not spam, but not auto-approved
592
  wp_notify_moderator( $comment_ID );
593
  */
594
- /*if ( isset( $context["comment_approved"] ) && $context["comment_approved"] == '0' ) {
 
595
  $output .= "<br>comment was automatically approved";
596
  } else {
597
  $output .= "<br>comment was not automatically approved";
598
  }*/
599
 
600
- $comment_text = "";
601
- if ( isset( $context["comment_content"] ) && $context["comment_content"] ) {
602
- $comment_text = $context["comment_content"];
603
  $comment_text = wp_trim_words( $comment_text, 20 );
604
  $comment_text = wpautop( $comment_text );
605
  }
606
 
607
  // Keys to show
608
  $arr_plugin_keys = array();
609
- $comment_type = isset( $context["comment_type"] ) ? $context["comment_type"] : "";
610
 
611
  switch ( $comment_type ) {
612
 
613
- case "trackback";
614
 
615
  $arr_plugin_keys = array(
616
- "trackback_status" => _x("Status", "comments logger - detailed output comment status", "simple-history"),
617
- #"trackback_type" => _x("Trackback type", "comments logger - detailed output comment type", "simple-history"),
618
- "trackback_author" => _x("Name", "comments logger - detailed output author", "simple-history"),
619
- "trackback_author_email" => _x("Email", "comments logger - detailed output email", "simple-history"),
620
- "trackback_content" => _x("Content", "comments logger - detailed output content", "simple-history"),
621
  );
622
 
623
  break;
624
 
625
- case "pingback";
626
 
627
  $arr_plugin_keys = array(
628
 
629
- "pingback_status" => _x("Status", "comments logger - detailed output comment status", "simple-history"),
630
- #"pingback_type" => _x("Pingback type", "comments logger - detailed output comment type", "simple-history"),
631
- "pingback_author" => _x("Name", "comments logger - detailed output author", "simple-history"),
632
- "pingback_author_email" => _x("Email", "comments logger - detailed output email", "simple-history"),
633
- "pingback_content" => _x("Content", "comments logger - detailed output content", "simple-history"),
634
 
635
  );
636
 
637
  break;
638
 
639
- case "comment";
640
  default;
641
 
642
  $arr_plugin_keys = array(
643
- "comment_status" => _x("Status", "comments logger - detailed output comment status", "simple-history"),
644
- #"comment_type" => _x("Comment type", "comments logger - detailed output comment type", "simple-history"),
645
- "comment_author" => _x("Name", "comments logger - detailed output author", "simple-history"),
646
- "comment_author_email" => _x("Email", "comments logger - detailed output email", "simple-history"),
647
- "comment_content" => _x("Comment", "comments logger - detailed output content", "simple-history")
648
  );
649
 
650
  break;
651
 
652
- //"comment_author_url" => _x("Author URL", "comments logger - detailed output author", "simple-history"),
653
- //"comment_author_IP" => _x("IP number", "comments logger - detailed output IP", "simple-history"),
 
654
 
655
- }
656
-
657
- $arr_plugin_keys = apply_filters("simple_history/comments_logger/row_details_plugin_info_keys", $arr_plugin_keys);
658
 
659
  // Start output of plugin meta data table
660
  $output .= "<table class='SimpleHistoryLogitem__keyValueTable'>";
@@ -663,17 +657,17 @@ class SimpleCommentsLogger extends SimpleLogger
663
 
664
  switch ( $key ) {
665
 
666
- case "comment_content":
667
- case "trackback_content":
668
- case "pingback_content":
669
  $desc_output = $comment_text;
670
  break;
671
 
672
- case "comment_author":
673
- case "trackback_author":
674
- case "pingback_author":
675
 
676
- $desc_output = "";
677
 
678
  if ( isset( $context[ $key ] ) ) {
679
  $desc_output .= esc_html( $context[ $key ] );
@@ -691,52 +685,50 @@ class SimpleCommentsLogger extends SimpleLogger
691
 
692
  break;
693
 
694
- case "comment_status":
695
- case "trackback_status":
696
- case "pingback_status":
697
 
698
- if ( isset( $context["comment_approved"] ) ) {
699
 
700
- if ( $context["comment_approved"] === "spam" ) {
701
- $desc_output = __("Spam", "simple-history");
702
- } else if ( $context["comment_approved"] == 1 ) {
703
- $desc_output = __("Approved", "simple-history");
704
- } else if ( $context["comment_approved"] == 0 ) {
705
- $desc_output = __("Pending", "simple-history");
706
  }
707
-
708
  }
709
 
710
  break;
711
 
712
- case "comment_type":
713
- case "trackback_type":
714
- case "pingback_type":
715
 
716
- if ( isset( $context["comment_type"] ) ) {
717
 
718
- if ( $context["comment_type"] === "trackback" ) {
719
- $desc_output = __("Trackback", "simple-history");
720
- } else if ( $context["comment_type"] === "pingback" ) {
721
- $desc_output = __("Pingback", "simple-history");
722
- } else if ( $context["comment_type"] === "comment" ) {
723
- $desc_output = __("Comment", "simple-history");
724
  } else {
725
- $desc_output = "";
726
  }
727
-
728
  }
729
 
730
  break;
731
 
732
  default;
733
-
734
  if ( isset( $context[ $key ] ) ) {
735
  $desc_output = esc_html( $context[ $key ] );
736
  }
737
 
738
  break;
739
- }
740
 
741
  // Skip empty rows
742
  if ( empty( $desc_output ) ) {
@@ -750,14 +742,14 @@ class SimpleCommentsLogger extends SimpleLogger
750
  <td>%2$s</td>
751
  </tr>
752
  ',
753
- esc_html($desc),
754
  $desc_output
755
  );
756
 
757
- }
758
 
759
  // Add link to edit comment
760
- $comment_ID = isset( $context["comment_ID"] ) && is_numeric( $context["comment_ID"] ) ? (int) $context["comment_ID"] : false;
761
 
762
  if ( $comment_ID ) {
763
 
@@ -771,7 +763,7 @@ class SimpleCommentsLogger extends SimpleLogger
771
  // Edit link sometimes does not contain comment ID
772
  // Probably because comment has been removed or something
773
  // So only continue if link does not end with "=""
774
- if ( $edit_comment_link && $edit_comment_link[strlen($edit_comment_link)-1] !== "=" ) {
775
 
776
  $output .= sprintf(
777
  '
@@ -780,18 +772,16 @@ class SimpleCommentsLogger extends SimpleLogger
780
  <td><a href="%2$s">%1$s</a></td>
781
  </tr>
782
  ',
783
- _x("View/Edit", "comments logger - edit comment", "simple-history"),
784
  $edit_comment_link
785
  );
786
 
787
  }
788
-
789
- } // if comment
790
-
791
- } // if comment id
792
 
793
  // End table
794
- $output .= "</table>";
795
 
796
  return $output;
797
 
5
  /**
6
  * Logs things related to comments
7
  */
8
+ class SimpleCommentsLogger extends SimpleLogger {
9
+
10
 
11
  public $slug = __CLASS__;
12
 
13
+ function __construct( $sh ) {
14
 
15
+ parent::__construct( $sh );
16
 
17
  // Add option to not show spam comments, because to much things getting logged
18
+ // add_filter("simple_history/log_query_sql_where", array($this, "maybe_modify_log_query_sql_where"));
19
+ add_filter( 'simple_history/log_query_inner_where', array( $this, 'maybe_modify_log_query_sql_where' ) );
20
+ add_filter( 'simple_history/quick_stats_where', array( $this, 'maybe_modify_log_query_sql_where' ) );
21
 
22
  }
23
 
26
  *
27
  * @param string $where sql query where
28
  */
29
+ function maybe_modify_log_query_sql_where( $where ) {
30
 
31
  // since 19 sept 2016 we do include spam, to skip the subquery
32
  // spam comments should not be logged anyway since some time
41
  *
42
  * @param bool $include_spam Default false
43
  */
44
+ $include_spam = apply_filters( 'simple_history/comments_logger/include_spam', $include_spam );
45
 
46
  if ( $include_spam ) {
47
  return $where;
76
  )
77
  ', $this->db_table, $this->db_table_contexts, $this->slug);
78
 
79
+ // echo $where;
 
80
  return $where;
81
 
82
  }
89
  function getInfo() {
90
 
91
  $arr_info = array(
92
+ 'name' => 'Comments Logger',
93
+ 'description' => 'Logs comments, and modifications to them',
94
+ 'capability' => 'moderate_comments',
95
+ 'messages' => array(
96
 
97
  // Comments
98
  'anon_comment_added' => _x(
261
 
262
  ), // end messages
263
 
264
+ 'labels' => array(
265
+
266
+ 'search' => array(
267
+ 'label' => _x( 'Comments', 'Comments logger: search', 'simple-history' ),
268
+ 'label_all' => _x( 'All comments activity', 'Comments logger: search', 'simple-history' ),
269
+ 'options' => array(
270
+ _x( 'Added comments', 'Comments logger: search', 'simple-history' ) => array(
271
+ 'anon_comment_added',
272
+ 'user_comment_added',
273
+ 'anon_trackback_added',
274
+ 'user_trackback_added',
275
+ 'anon_pingback_added',
276
+ 'user_pingback_added',
277
  ),
278
+ _x( 'Edited comments', 'Comments logger: search', 'simple-history' ) => array(
279
+ 'comment_edited',
280
+ 'trackback_edited',
281
+ 'pingback_edited',
282
  ),
283
+ _x( 'Approved comments', 'Comments logger: search', 'simple-history' ) => array(
284
+ 'comment_status_approve',
285
+ 'trackback_status_approve',
286
+ 'pingback_status_approve',
287
  ),
288
+ _x( 'Held comments', 'Comments logger: search', 'simple-history' ) => array(
289
+ 'comment_status_hold',
290
+ 'trackback_status_hold',
291
+ 'pingback_status_hold',
292
  ),
293
+ _x( 'Comments status changed to spam', 'Comments logger: search', 'simple-history' ) => array(
294
+ 'comment_status_spam',
295
+ 'trackback_status_spam',
296
+ 'pingback_status_spam',
297
  ),
298
+ _x( 'Trashed comments', 'Comments logger: search', 'simple-history' ) => array(
299
+ 'comment_status_trash',
300
+ 'trackback_status_trash',
301
+ 'pingback_status_trash',
302
  ),
303
+ _x( 'Untrashed comments', 'Comments logger: search', 'simple-history' ) => array(
304
+ 'comment_untrashed',
305
+ 'trackback_untrashed',
306
+ 'pingback_untrashed',
307
  ),
308
+ _x( 'Deleted comments', 'Comments logger: search', 'simple-history' ) => array(
309
+ 'comment_deleted',
310
+ 'trackback_deleted',
311
+ 'pingback_deleted',
312
  ),
313
+ ),
314
+ ),// end search
315
 
316
+ ),// labels
317
 
318
  );
319
 
326
  /**
327
  * Fires immediately after a comment is inserted into the database.
328
  */
329
+ add_action( 'comment_post', array( $this, 'on_comment_post' ), 10, 2 );
330
 
331
  /**
332
  * Fires after a comment status has been updated in the database.
333
  * The hook also fires immediately before comment status transition hooks are fired.
334
  */
335
+ add_action( 'wp_set_comment_status', array( $this, 'on_wp_set_comment_status' ), 10, 2 );
336
 
337
  /**
338
  *Fires immediately after a comment is restored from the Trash.
339
  */
340
+ add_action( 'untrashed_comment', array( $this, 'on_untrashed_comment' ), 10, 1 );
341
 
342
+ /**
343
+ * Fires immediately before a comment is deleted from the database.
344
+ */
345
+ add_action( 'delete_comment', array( $this, 'on_delete_comment' ), 10, 1 );
346
 
347
  /**
348
  * Fires immediately after a comment is updated in the database.
349
+ * The hook also fires immediately before comment status transition hooks are fired.
350
+ */
351
+ add_action( 'edit_comment', array( $this, 'on_edit_comment' ), 10, 1 );
 
352
 
353
  }
354
 
358
  * @param int $comment_ID
359
  * @return mixed array with context if comment found, false if comment not found
360
  */
361
+ public function get_context_for_comment( $comment_ID ) {
362
 
363
  // get_comment passes comment_ID by reference, so it can be unset by that function
364
  $comment_ID_original = $comment_ID;
371
  $comment_parent_post = get_post( $comment_data->comment_post_ID );
372
 
373
  $context = array(
374
+ 'comment_ID' => $comment_ID_original,
375
+ 'comment_author' => $comment_data->comment_author,
376
+ 'comment_author_email' => $comment_data->comment_author_email,
377
+ 'comment_author_url' => $comment_data->comment_author_url,
378
+ 'comment_author_IP' => $comment_data->comment_author_IP,
379
+ 'comment_content' => $comment_data->comment_content,
380
+ 'comment_approved' => $comment_data->comment_approved,
381
+ 'comment_agent' => $comment_data->comment_agent,
382
+ 'comment_type' => $comment_data->comment_type,
383
+ 'comment_parent' => $comment_data->comment_parent,
384
+ 'comment_post_ID' => $comment_data->comment_post_ID,
385
+ 'comment_post_title' => $comment_parent_post->post_title,
386
+ 'comment_post_type' => $comment_parent_post->post_type,
387
  );
388
 
389
  // Note: comment type is empty for normal comments
390
+ if ( empty( $context['comment_type'] ) ) {
391
+ $context['comment_type'] = 'comment';
392
  }
393
 
394
  return $context;
395
 
396
  }
397
 
398
+ public function on_edit_comment( $comment_ID ) {
399
 
400
+ $context = $this->get_context_for_comment( $comment_ID );
401
  if ( ! $context ) {
402
  return;
403
  }
412
  public function on_delete_comment( $comment_ID ) {
413
 
414
  $context = $this->get_context_for_comment( $comment_ID );
415
+
416
  if ( ! $context ) {
417
  return;
418
  }
419
 
 
420
  $comment_data = get_comment( $comment_ID );
421
 
422
  // add occasions if comment was considered spam
423
  // if not added, spam comments can easily flood the log
424
  // Deletions of spam easiy flood log
425
+ if ( isset( $comment_data->comment_approved ) && 'spam' === $comment_data->comment_approved ) {
426
+
427
  // since 2.5.5: don't log deletion of spam comments
428
  return;
429
  // $context["_occasionsID"] = __CLASS__ . '/' . __FUNCTION__ . "/anon_{$context["comment_type"]}_deleted/type:spam";
 
430
  }
431
 
432
  $this->infoMessage(
436
 
437
  }
438
 
439
+ public function on_untrashed_comment( $comment_ID ) {
440
 
441
+ $context = $this->get_context_for_comment( $comment_ID );
442
  if ( ! $context ) {
443
  return;
444
  }
453
  /**
454
  * Fires after a comment status has been updated in the database.
455
  * The hook also fires immediately before comment status transition hooks are fired.
456
+ *
457
  * @param int $comment_id The comment ID.
458
  * @param string|bool $comment_status The comment status. Possible values include 'hold',
459
  * 'approve', 'spam', 'trash', or false.
461
  */
462
  public function on_wp_set_comment_status( $comment_ID, $comment_status ) {
463
 
464
+ $context = $this->get_context_for_comment( $comment_ID );
465
+
466
  if ( ! $context ) {
467
  return;
468
  }
499
  }
500
 
501
  // since 2.5.5: no more logging of spam comments
502
+ if ( isset( $comment_approved ) && 'spam' === $comment_approved ) {
503
  return;
504
  }
505
 
506
  $comment_data = get_comment( $comment_ID );
507
 
508
+ $message = '';
509
 
510
  if ( $comment_data->user_id ) {
511
 
516
 
517
  // comment was from a non-logged in user
518
  $message = "anon_{$context["comment_type"]}_added";
519
+ $context['_initiator'] = SimpleLoggerLogInitiators::WEB_USER;
520
 
521
  // add occasions if comment is considered spam
522
  // if not added, spam comments can easily flood the log
523
+ if ( isset( $comment_data->comment_approved ) && 'spam' === $comment_data->comment_approved ) {
524
+ $context['_occasionsID'] = __CLASS__ . '/' . __FUNCTION__ . "/anon_{$context["comment_type"]}_added/type:spam";
525
  }
 
526
  }
527
 
528
  $this->infoMessage(
537
  * Modify plain output to inlcude link to post
538
  * and link to comment
539
  */
540
+ public function getLogRowPlainTextOutput( $row ) {
541
 
542
  $message = $row->message;
543
  $context = $row->context;
544
+ $message_key = $context['_message_key'];
545
 
546
  // Message is untranslated here, so get translated text
547
  // Can't call parent __FUNCTION__ because it will interpolate too, which we don't want
548
  if ( ! empty( $message_key ) ) {
549
+ $message = $this->messages[ $message_key ]['translated_text'];
550
  }
551
 
552
  // Wrap links around {comment_post_title}
553
+ $comment_post_ID = isset( $context['comment_post_ID'] ) ? (int) $context['comment_post_ID'] : null;
554
  if ( $comment_post_ID && $comment_post = get_post( $comment_post_ID ) ) {
555
 
556
  $edit_post_link = get_edit_post_link( $comment_post_ID );
564
  );
565
 
566
  }
 
567
  }
568
 
569
+ return $this->interpolate( $message, $context, $row );
 
570
 
571
  }
572
 
574
  /**
575
  * Get output for detailed log section
576
  */
577
+ function getLogRowDetailsOutput( $row ) {
578
 
579
  $context = $row->context;
580
+ $message_key = $context['_message_key'];
581
+ $output = '';
582
+ // print_r($row);exit;
583
  /*
584
  if ( 'spam' !== $commentdata['comment_approved'] ) { // If it's spam save it silently for later crunching
585
  if ( '0' == $commentdata['comment_approved'] ) { // comment not spam, but not auto-approved
586
  wp_notify_moderator( $comment_ID );
587
  */
588
+ /*
589
+ if ( isset( $context["comment_approved"] ) && $context["comment_approved"] == '0' ) {
590
  $output .= "<br>comment was automatically approved";
591
  } else {
592
  $output .= "<br>comment was not automatically approved";
593
  }*/
594
 
595
+ $comment_text = '';
596
+ if ( isset( $context['comment_content'] ) && $context['comment_content'] ) {
597
+ $comment_text = $context['comment_content'];
598
  $comment_text = wp_trim_words( $comment_text, 20 );
599
  $comment_text = wpautop( $comment_text );
600
  }
601
 
602
  // Keys to show
603
  $arr_plugin_keys = array();
604
+ $comment_type = isset( $context['comment_type'] ) ? $context['comment_type'] : '';
605
 
606
  switch ( $comment_type ) {
607
 
608
+ case 'trackback';
609
 
610
  $arr_plugin_keys = array(
611
+ 'trackback_status' => _x( 'Status', 'comments logger - detailed output comment status', 'simple-history' ),
612
+ // "trackback_type" => _x("Trackback type", "comments logger - detailed output comment type", "simple-history"),
613
+ 'trackback_author' => _x( 'Name', 'comments logger - detailed output author', 'simple-history' ),
614
+ 'trackback_author_email' => _x( 'Email', 'comments logger - detailed output email', 'simple-history' ),
615
+ 'trackback_content' => _x( 'Content', 'comments logger - detailed output content', 'simple-history' ),
616
  );
617
 
618
  break;
619
 
620
+ case 'pingback';
621
 
622
  $arr_plugin_keys = array(
623
 
624
+ 'pingback_status' => _x( 'Status', 'comments logger - detailed output comment status', 'simple-history' ),
625
+ // "pingback_type" => _x("Pingback type", "comments logger - detailed output comment type", "simple-history"),
626
+ 'pingback_author' => _x( 'Name', 'comments logger - detailed output author', 'simple-history' ),
627
+ 'pingback_author_email' => _x( 'Email', 'comments logger - detailed output email', 'simple-history' ),
628
+ 'pingback_content' => _x( 'Content', 'comments logger - detailed output content', 'simple-history' ),
629
 
630
  );
631
 
632
  break;
633
 
634
+ case 'comment';
635
  default;
636
 
637
  $arr_plugin_keys = array(
638
+ 'comment_status' => _x( 'Status', 'comments logger - detailed output comment status', 'simple-history' ),
639
+ // "comment_type" => _x("Comment type", "comments logger - detailed output comment type", "simple-history"),
640
+ 'comment_author' => _x( 'Name', 'comments logger - detailed output author', 'simple-history' ),
641
+ 'comment_author_email' => _x( 'Email', 'comments logger - detailed output email', 'simple-history' ),
642
+ 'comment_content' => _x( 'Comment', 'comments logger - detailed output content', 'simple-history' ),
643
  );
644
 
645
  break;
646
 
647
+ // "comment_author_url" => _x("Author URL", "comments logger - detailed output author", "simple-history"),
648
+ // "comment_author_IP" => _x("IP number", "comments logger - detailed output IP", "simple-history"),
649
+ }// End switch().
650
 
651
+ $arr_plugin_keys = apply_filters( 'simple_history/comments_logger/row_details_plugin_info_keys', $arr_plugin_keys );
 
 
652
 
653
  // Start output of plugin meta data table
654
  $output .= "<table class='SimpleHistoryLogitem__keyValueTable'>";
657
 
658
  switch ( $key ) {
659
 
660
+ case 'comment_content':
661
+ case 'trackback_content':
662
+ case 'pingback_content':
663
  $desc_output = $comment_text;
664
  break;
665
 
666
+ case 'comment_author':
667
+ case 'trackback_author':
668
+ case 'pingback_author':
669
 
670
+ $desc_output = '';
671
 
672
  if ( isset( $context[ $key ] ) ) {
673
  $desc_output .= esc_html( $context[ $key ] );
685
 
686
  break;
687
 
688
+ case 'comment_status':
689
+ case 'trackback_status':
690
+ case 'pingback_status':
691
 
692
+ if ( isset( $context['comment_approved'] ) ) {
693
 
694
+ if ( $context['comment_approved'] === 'spam' ) {
695
+ $desc_output = __( 'Spam', 'simple-history' );
696
+ } elseif ( $context['comment_approved'] == 1 ) {
697
+ $desc_output = __( 'Approved', 'simple-history' );
698
+ } elseif ( $context['comment_approved'] == 0 ) {
699
+ $desc_output = __( 'Pending', 'simple-history' );
700
  }
 
701
  }
702
 
703
  break;
704
 
705
+ case 'comment_type':
706
+ case 'trackback_type':
707
+ case 'pingback_type':
708
 
709
+ if ( isset( $context['comment_type'] ) ) {
710
 
711
+ if ( $context['comment_type'] === 'trackback' ) {
712
+ $desc_output = __( 'Trackback', 'simple-history' );
713
+ } elseif ( $context['comment_type'] === 'pingback' ) {
714
+ $desc_output = __( 'Pingback', 'simple-history' );
715
+ } elseif ( $context['comment_type'] === 'comment' ) {
716
+ $desc_output = __( 'Comment', 'simple-history' );
717
  } else {
718
+ $desc_output = '';
719
  }
 
720
  }
721
 
722
  break;
723
 
724
  default;
725
+
726
  if ( isset( $context[ $key ] ) ) {
727
  $desc_output = esc_html( $context[ $key ] );
728
  }
729
 
730
  break;
731
+ }// End switch().
732
 
733
  // Skip empty rows
734
  if ( empty( $desc_output ) ) {
742
  <td>%2$s</td>
743
  </tr>
744
  ',
745
+ esc_html( $desc ),
746
  $desc_output
747
  );
748
 
749
+ }// End foreach().
750
 
751
  // Add link to edit comment
752
+ $comment_ID = isset( $context['comment_ID'] ) && is_numeric( $context['comment_ID'] ) ? (int) $context['comment_ID'] : false;
753
 
754
  if ( $comment_ID ) {
755
 
763
  // Edit link sometimes does not contain comment ID
764
  // Probably because comment has been removed or something
765
  // So only continue if link does not end with "=""
766
+ if ( $edit_comment_link && $edit_comment_link[ strlen( $edit_comment_link ) -1 ] !== '=' ) {
767
 
768
  $output .= sprintf(
769
  '
772
  <td><a href="%2$s">%1$s</a></td>
773
  </tr>
774
  ',
775
+ _x( 'View/Edit', 'comments logger - edit comment', 'simple-history' ),
776
  $edit_comment_link
777
  );
778
 
779
  }
780
+ }
781
+ } // End if().
 
 
782
 
783
  // End table
784
+ $output .= '</table>';
785
 
786
  return $output;
787
 
loggers/SimpleCoreUpdatesLogger.php CHANGED
@@ -10,76 +10,75 @@ class SimpleCoreUpdatesLogger extends SimpleLogger {
10
  public $slug = __CLASS__;
11
 
12
  public function loaded() {
13
-
14
- add_action( '_core_updated_successfully', array( $this, "on_core_updated" ) );
15
- add_action( 'update_feedback', array( $this, "on_update_feedback" ) );
16
 
17
- // Can't log db updates at the moment, because loaded() is not called yet when the action fires
18
- // add_action( 'wp_upgrade', array( $this, "on_wp_upgrade" ), 10, 2 );
19
 
20
- }
 
 
21
 
22
 
23
- /**
24
- * Fires after a site is fully upgraded.
25
- * The database, that is.
26
- *
27
- * @param int $wp_db_version The new $wp_db_version.
28
- * @param int $wp_current_db_version The old (current) $wp_db_version.
29
- */
30
- function on_wp_upgrade( $wp_db_version, $wp_current_db_version ) {
31
 
32
- $this->debugMessage(
33
- "core_db_version_updated",
34
- array(
35
- "new_version" => $wp_db_version,
36
- "prev_version" => $wp_current_db_version
37
- )
38
- );
39
 
40
  }
41
 
42
  /**
43
- * We need to store the WordPress version we are updating from.
44
  * 'update_feedback' is a suitable filter.
45
  */
46
  function on_update_feedback() {
47
 
48
- if ( ! empty( $GLOBALS['wp_version'] ) && ! isset( $GLOBALS['simple_history_' . $this->slug . '_wp_version'] ) ) {
49
- $GLOBALS['simple_history_' . $this->slug . '_wp_version'] = $GLOBALS['wp_version'];
50
  }
51
 
52
  }
53
 
54
  /**
55
  * Get array with information about this logger
56
- *
57
  * @return array
58
  */
59
  function getInfo() {
60
 
61
- $arr_info = array(
62
- "name" => "Core Updates Logger",
63
- "description" => "Logs the update of WordPress (manual and automatic updates)",
64
- "capability" => "update_core",
65
- "messages" => array(
66
- 'core_updated' => __('Updated WordPress to {new_version} from {prev_version}', 'simple-history'),
67
- 'core_auto_updated' => __('WordPress auto-updated to {new_version} from {prev_version}', 'simple-history'),
68
- "core_db_version_updated" => __('WordPress database version updated to {new_version} from {prev_version}', 'simple-history')
69
  ),
70
- "labels" => array(
71
- "search" => array(
72
- "label" => _x("WordPress Core", "User logger: search", "simple-history"),
73
- "options" => array(
74
- _x("WordPress core updates", "User logger: search", "simple-history") => array(
75
- "core_updated",
76
- "core_auto_updated"
77
- ),
78
- )
79
- ) // end search array
80
- ) // end labels
81
  );
82
-
83
  return $arr_info;
84
 
85
  }
@@ -89,26 +88,26 @@ class SimpleCoreUpdatesLogger extends SimpleLogger {
89
  *
90
  * @param string $new_wp_version
91
  */
92
- public function on_core_updated($new_wp_version) {
93
-
94
- $old_wp_version = empty( $GLOBALS['simple_history_' . $this->slug . '_wp_version'] ) ? $GLOBALS["wp_version"] : $GLOBALS['simple_history_' . $this->slug . '_wp_version'];
95
 
96
- $auto_update = true;
97
  if ( $GLOBALS['pagenow'] == 'update-core.php' ) {
98
  $auto_update = false;
99
  }
100
 
101
- if ($auto_update) {
102
- $message = "core_auto_updated";
103
  } else {
104
- $message = "core_updated";
105
  }
106
 
107
  $this->noticeMessage(
108
  $message,
109
  array(
110
- "prev_version" => $old_wp_version,
111
- "new_version" => $new_wp_version
112
  )
113
  );
114
 
10
  public $slug = __CLASS__;
11
 
12
  public function loaded() {
 
 
 
13
 
14
+ add_action( '_core_updated_successfully', array( $this, 'on_core_updated' ) );
15
+ add_action( 'update_feedback', array( $this, 'on_update_feedback' ) );
16
 
17
+ // Can't log db updates at the moment, because loaded() is not called yet when the action fires
18
+ // add_action( 'wp_upgrade', array( $this, "on_wp_upgrade" ), 10, 2 );
19
+ }
20
 
21
 
22
+ /**
23
+ * Fires after a site is fully upgraded.
24
+ * The database, that is.
25
+ *
26
+ * @param int $wp_db_version The new $wp_db_version.
27
+ * @param int $wp_current_db_version The old (current) $wp_db_version.
28
+ */
29
+ function on_wp_upgrade( $wp_db_version, $wp_current_db_version ) {
30
 
31
+ $this->debugMessage(
32
+ 'core_db_version_updated',
33
+ array(
34
+ 'new_version' => $wp_db_version,
35
+ 'prev_version' => $wp_current_db_version,
36
+ )
37
+ );
38
 
39
  }
40
 
41
  /**
42
+ * We need to store the WordPress version we are updating from.
43
  * 'update_feedback' is a suitable filter.
44
  */
45
  function on_update_feedback() {
46
 
47
+ if ( ! empty( $GLOBALS['wp_version'] ) && ! isset( $GLOBALS[ 'simple_history_' . $this->slug . '_wp_version' ] ) ) {
48
+ $GLOBALS[ 'simple_history_' . $this->slug . '_wp_version' ] = $GLOBALS['wp_version'];
49
  }
50
 
51
  }
52
 
53
  /**
54
  * Get array with information about this logger
55
+ *
56
  * @return array
57
  */
58
  function getInfo() {
59
 
60
+ $arr_info = array(
61
+ 'name' => 'Core Updates Logger',
62
+ 'description' => 'Logs the update of WordPress (manual and automatic updates)',
63
+ 'capability' => 'update_core',
64
+ 'messages' => array(
65
+ 'core_updated' => __( 'Updated WordPress to {new_version} from {prev_version}', 'simple-history' ),
66
+ 'core_auto_updated' => __( 'WordPress auto-updated to {new_version} from {prev_version}', 'simple-history' ),
67
+ 'core_db_version_updated' => __( 'WordPress database version updated to {new_version} from {prev_version}', 'simple-history' ),
68
  ),
69
+ 'labels' => array(
70
+ 'search' => array(
71
+ 'label' => _x( 'WordPress Core', 'User logger: search', 'simple-history' ),
72
+ 'options' => array(
73
+ _x( 'WordPress core updates', 'User logger: search', 'simple-history' ) => array(
74
+ 'core_updated',
75
+ 'core_auto_updated',
76
+ ),
77
+ ),
78
+ ),// end search array
79
+ ),// end labels
80
  );
81
+
82
  return $arr_info;
83
 
84
  }
88
  *
89
  * @param string $new_wp_version
90
  */
91
+ public function on_core_updated( $new_wp_version ) {
92
+
93
+ $old_wp_version = empty( $GLOBALS[ 'simple_history_' . $this->slug . '_wp_version' ] ) ? $GLOBALS['wp_version'] : $GLOBALS[ 'simple_history_' . $this->slug . '_wp_version' ];
94
 
95
+ $auto_update = true;
96
  if ( $GLOBALS['pagenow'] == 'update-core.php' ) {
97
  $auto_update = false;
98
  }
99
 
100
+ if ( $auto_update ) {
101
+ $message = 'core_auto_updated';
102
  } else {
103
+ $message = 'core_updated';
104
  }
105
 
106
  $this->noticeMessage(
107
  $message,
108
  array(
109
+ 'prev_version' => $old_wp_version,
110
+ 'new_version' => $new_wp_version,
111
  )
112
  );
113
 
loggers/SimpleExportLogger.php CHANGED
@@ -5,53 +5,53 @@ defined( 'ABSPATH' ) or die();
5
  /**
6
  * Logs WordPress exports
7
  */
8
- class SimpleExportLogger extends SimpleLogger
9
- {
10
 
11
  public $slug = __CLASS__;
12
 
13
  /**
14
  * Get array with information about this logger
15
- *
16
  * @return array
17
  */
18
  function getInfo() {
19
 
20
- $arr_info = array(
21
- "name" => __("Export Logger", "simple-history"),
22
- "description" => __("Logs updates to WordPress export", "simple-history"),
23
- "capability" => "export",
24
- "messages" => array(
25
- 'created_export' => __('Created XML export', "simple-history"),
26
  ),
27
- "labels" => array(
28
- "search" => array(
29
- "label" => _x("Export", "Export logger: search", "simple-history"),
30
- "options" => array(
31
- _x("Created exports", "Export logger: search", "simple-history") => array(
32
- "created_export"
33
- ),
34
- )
35
- ) // end search array
36
- ) // end labels
37
  );
38
-
39
  return $arr_info;
40
 
41
  }
42
 
43
  function loaded() {
44
 
45
- add_action( 'export_wp', array($this, "on_export_wp"), 10, 1 );
46
-
47
  }
48
 
49
- function on_export_wp($args) {
50
 
51
  $this->infoMessage(
52
- "created_export",
53
  array(
54
- "args" => $this->simpleHistory->json_encode( $args )
55
  )
56
  );
57
 
@@ -62,7 +62,7 @@ class SimpleExportLogger extends SimpleLogger
62
  */
63
  /*
64
  function getLogRowDetailsOutput($row) {
65
-
66
  $context = $row->context;
67
  $message_key = $context["_message_key"];
68
  $output = "";
5
  /**
6
  * Logs WordPress exports
7
  */
8
+ class SimpleExportLogger extends SimpleLogger {
9
+
10
 
11
  public $slug = __CLASS__;
12
 
13
  /**
14
  * Get array with information about this logger
15
+ *
16
  * @return array
17
  */
18
  function getInfo() {
19
 
20
+ $arr_info = array(
21
+ 'name' => __( 'Export Logger', 'simple-history' ),
22
+ 'description' => __( 'Logs updates to WordPress export', 'simple-history' ),
23
+ 'capability' => 'export',
24
+ 'messages' => array(
25
+ 'created_export' => __( 'Created XML export', 'simple-history' ),
26
  ),
27
+ 'labels' => array(
28
+ 'search' => array(
29
+ 'label' => _x( 'Export', 'Export logger: search', 'simple-history' ),
30
+ 'options' => array(
31
+ _x( 'Created exports', 'Export logger: search', 'simple-history' ) => array(
32
+ 'created_export'
33
+ ),
34
+ ),
35
+ ),// end search array
36
+ ),// end labels
37
  );
38
+
39
  return $arr_info;
40
 
41
  }
42
 
43
  function loaded() {
44
 
45
+ add_action( 'export_wp', array( $this, 'on_export_wp' ), 10, 1 );
46
+
47
  }
48
 
49
+ function on_export_wp( $args ) {
50
 
51
  $this->infoMessage(
52
+ 'created_export',
53
  array(
54
+ 'args' => $this->simpleHistory->json_encode( $args ),
55
  )
56
  );
57
 
62
  */
63
  /*
64
  function getLogRowDetailsOutput($row) {
65
+
66
  $context = $row->context;
67
  $message_key = $context["_message_key"];
68
  $output = "";
loggers/SimpleLegacyLogger.php CHANGED
@@ -8,63 +8,60 @@ defined( 'ABSPATH' ) or die();
8
  *
9
  * @since 2.0
10
  */
11
- class SimpleLegacyLogger extends SimpleLogger
12
- {
13
 
14
  /**
15
  * Unique slug for this logger
16
  * Will be saved in DB and used to associate each log row with its logger
17
  */
18
- public $slug = "SimpleLegacyLogger";
19
 
20
  public function __construct() {
21
-
22
- // $this->info(__CLASS__ . " construct()");
23
 
 
24
  }
25
 
26
  /**
27
  * Get array with information about this logger
28
- *
29
  * @return array
30
  */
31
  function getInfo() {
32
 
33
- $arr_info = array(
34
- "name" => "Legacy Logger",
35
- "description" => "Formats old events",
36
- "capability" => "edit_pages",
37
- "messages" => array(
38
- ),
39
  /*
40
-
41
  "labels" => array(
42
  "search" => array(
43
  "label" => _x("Export", "Export logger: search", "simple-history"),
44
  "options" => array(
45
  _x("Exports created", "Core updates logger: search", "simple-history") => array(
46
  "created_export"
47
- ),
48
  )
49
  ) // end search array
50
  ) // end labels
51
  */
52
 
53
  );
54
-
55
  return $arr_info;
56
 
57
  }
58
 
59
- public function getLogRowPlainTextOutput($row) {
60
-
61
  $message = $row->message;
62
  $context = $row->context;
63
-
64
- $out = "";
65
 
66
  global $wpdb;
67
-
68
  // Get old columns for this event
69
  $sql = sprintf('
70
  SELECT * FROM %1$s
@@ -74,30 +71,29 @@ class SimpleLegacyLogger extends SimpleLogger
74
  $row->id
75
  );
76
 
77
- $one_item = $wpdb->get_row($sql);
78
-
79
- #$out .= print_r($row, true);
80
 
 
81
  // Code mostly from version 1.x
82
- $object_type = ucwords($one_item->object_type);
83
- $object_name = esc_html($one_item->object_name);
84
- $user = get_user_by("id", $one_item->user_id);
85
- $user_nicename = esc_html(@$user->user_nicename);
86
- $user_email = esc_html(@$user->user_email);
87
- $description = "";
88
 
89
- if ($user_nicename) {
90
- $description .= sprintf(__("By %s", 'simple-history'), $user_nicename);
91
 
92
  }
93
 
94
  if ( isset( $one_item->occasions ) ) {
95
- $description .= sprintf(__("%d occasions", 'simple-history'), sizeof($one_item->occasions));
96
 
97
  }
98
 
99
- $item_title = esc_html($object_type) . " \"" . esc_html($object_name) . "\" {$one_item->action}";
100
- $item_title = html_entity_decode($item_title, ENT_COMPAT, "UTF-8");
101
 
102
  $out .= "$item_title";
103
  $out .= "<br>$description";
8
  *
9
  * @since 2.0
10
  */
11
+ class SimpleLegacyLogger extends SimpleLogger {
12
+
13
 
14
  /**
15
  * Unique slug for this logger
16
  * Will be saved in DB and used to associate each log row with its logger
17
  */
18
+ public $slug = 'SimpleLegacyLogger';
19
 
20
  public function __construct() {
 
 
21
 
22
+ // $this->info(__CLASS__ . " construct()");
23
  }
24
 
25
  /**
26
  * Get array with information about this logger
27
+ *
28
  * @return array
29
  */
30
  function getInfo() {
31
 
32
+ $arr_info = array(
33
+ 'name' => 'Legacy Logger',
34
+ 'description' => 'Formats old events',
35
+ 'capability' => 'edit_pages',
36
+ 'messages' => array(),
 
37
  /*
 
38
  "labels" => array(
39
  "search" => array(
40
  "label" => _x("Export", "Export logger: search", "simple-history"),
41
  "options" => array(
42
  _x("Exports created", "Core updates logger: search", "simple-history") => array(
43
  "created_export"
44
+ ),
45
  )
46
  ) // end search array
47
  ) // end labels
48
  */
49
 
50
  );
51
+
52
  return $arr_info;
53
 
54
  }
55
 
56
+ public function getLogRowPlainTextOutput( $row ) {
57
+
58
  $message = $row->message;
59
  $context = $row->context;
60
+
61
+ $out = '';
62
 
63
  global $wpdb;
64
+
65
  // Get old columns for this event
66
  $sql = sprintf('
67
  SELECT * FROM %1$s
71
  $row->id
72
  );
73
 
74
+ $one_item = $wpdb->get_row( $sql );
 
 
75
 
76
+ // $out .= print_r($row, true);
77
  // Code mostly from version 1.x
78
+ $object_type = ucwords( $one_item->object_type );
79
+ $object_name = esc_html( $one_item->object_name );
80
+ $user = get_user_by( 'id', $one_item->user_id );
81
+ $user_nicename = esc_html( @$user->user_nicename );
82
+ $user_email = esc_html( @$user->user_email );
83
+ $description = '';
84
 
85
+ if ( $user_nicename ) {
86
+ $description .= sprintf( __( 'By %s', 'simple-history' ), $user_nicename );
87
 
88
  }
89
 
90
  if ( isset( $one_item->occasions ) ) {
91
+ $description .= sprintf( __( '%d occasions', 'simple-history' ), sizeof( $one_item->occasions ) );
92
 
93
  }
94
 
95
+ $item_title = esc_html( $object_type ) . ' "' . esc_html( $object_name ) . "\" {$one_item->action}";
96
+ $item_title = html_entity_decode( $item_title, ENT_COMPAT, 'UTF-8' );
97
 
98
  $out .= "$item_title";
99
  $out .= "<br>$description";
loggers/SimpleLogger.php CHANGED
@@ -42,9 +42,10 @@ class SimpleLogger {
42
 
43
  /**
44
  * Constructor. Remember to call this as parent constructor if making a childlogger
 
45
  * @param $simpleHistory history class objectinstance
46
  */
47
- public function __construct( $simpleHistory = null ) {
48
 
49
  global $wpdb;
50
 
@@ -73,16 +74,16 @@ class SimpleLogger {
73
  $arr_info = array(
74
 
75
  // The logger slug. Defaulting to the class name is nice and logical I think
76
- "slug" => __CLASS__,
77
 
78
  // Shown on the info-tab in settings, use these fields to tell
79
  // an admin what your logger is used for
80
- "name" => "SimpleLogger",
81
- "description" => "The built in logger for Simple History",
82
 
83
  // Capability required to view log entries from this logger
84
- "capability" => "edit_pages",
85
- "messages" => array(
86
  // No pre-defined variants
87
  // when adding messages __() or _x() must be used
88
  ),
@@ -117,10 +118,10 @@ class SimpleLogger {
117
 
118
  $arr_info = $this->getInfo();
119
 
120
- $capability = "manage_options";
121
 
122
- if ( ! empty( $arr_info["capability"] ) ) {
123
- $capability = $arr_info["capability"];
124
  }
125
 
126
  return $capability;
@@ -131,8 +132,8 @@ class SimpleLogger {
131
  * Interpolates context values into the message placeholders.
132
  *
133
  * @param string $message
134
- * @param array $context
135
- * @param array $row Currently not always passed, because loggers need to be updated to support this...
136
  */
137
  function interpolate( $message, $context = array(), $row = null ) {
138
 
@@ -145,7 +146,7 @@ class SimpleLogger {
145
  *
146
  * @since 2.2.4
147
  */
148
- $context = apply_filters( "simple_history/logger/interpolate/context", $context, $message, $row );
149
 
150
  // Build a replacement array with braces around the context keys
151
  $replace = array();
@@ -163,7 +164,7 @@ class SimpleLogger {
163
  continue;
164
  }
165
 
166
- $replace['{' . $key . '}'] = $val;
167
 
168
  }
169
 
@@ -189,40 +190,41 @@ class SimpleLogger {
189
  * Returns header output for a log row
190
  * Format should be common for all log rows and should be like:
191
  * Username (user role) · Date
 
192
  * @return string HTML
193
  */
194
- function getLogRowHeaderOutput($row) {
195
 
196
  // HTML for initiator
197
- $initiator_html = "";
198
 
199
  $initiator = $row->initiator;
200
  $context = $row->context;
201
 
202
- switch ($initiator) {
203
 
204
- case "wp":
205
  $initiator_html .= '<strong class="SimpleHistoryLogitem__inlineDivided">WordPress</strong> ';
206
  break;
207
 
208
- case "wp_cli":
209
  $initiator_html .= '<strong class="SimpleHistoryLogitem__inlineDivided">WP-CLI</strong> ';
210
  break;
211
 
212
  // wp_user = wordpress uses, but user may have been deleted since log entry was added
213
- case "wp_user":
214
 
215
- $user_id = isset($row->context["_user_id"]) ? $row->context["_user_id"] : null;
216
 
217
- if ($user_id > 0 && $user = get_user_by("id", $user_id)) {
218
 
219
  // Sender is user and user still exists
220
  $is_current_user = ($user_id == get_current_user_id()) ? true : false;
221
 
222
  // get user role, as done in user-edit.php
223
- $wp_roles = $GLOBALS["wp_roles"];
224
  $all_roles = (array) $wp_roles->roles;
225
- $user_roles = array_intersect( array_values( (array) $user->roles ), array_keys( (array) $wp_roles->roles ));
226
  $user_role = array_shift( $user_roles );
227
 
228
  $user_display_name = $user->display_name;
@@ -234,7 +236,7 @@ class SimpleLogger {
234
  * @param bool If you should be used
235
  * @since 2.1
236
  */
237
- $use_you = apply_filters("simple_history/header_initiator_use_you", true);
238
 
239
  if ( $use_you && $is_current_user ) {
240
 
@@ -262,19 +264,19 @@ class SimpleLogger {
262
  *
263
  * @param string $format.
264
  */
265
- $tmpl_initiator_html = apply_filters("simple_history/header_initiator_html_existing_user", $tmpl_initiator_html);
266
 
267
  $initiator_html .= sprintf(
268
  $tmpl_initiator_html,
269
- esc_html($user->user_login), // 1
270
- esc_html($user->user_email), // 2
271
- esc_html($user_display_name), // 3
272
  $user_role, // 4
273
- _x("You", "header output when initiator is the currently logged in user", "simple-history"), // 5
274
  get_edit_user_link( $user_id ) // 6
275
  );
276
 
277
- } else if ($user_id > 0) {
278
 
279
  // Sender was a user, but user is deleted now
280
  // output all info we have
@@ -284,18 +286,18 @@ class SimpleLogger {
284
  // _user_email
285
  $initiator_html .= sprintf(
286
  '<strong class="SimpleHistoryLogitem__inlineDivided">' .
287
- __('Deleted user (had id %1$s, email %2$s, login %3$s)', "simple-history") .
288
  '</strong>',
289
- esc_html($context["_user_id"]), // 1
290
- esc_html($context["_user_email"]), // 2
291
- esc_html($context["_user_login"]) // 3
292
  );
293
 
294
- }
295
 
296
  break;
297
 
298
- case "web_user":
299
 
300
  /*
301
  Note: server_remote_addr may not show visiting/attacking ip, if server is behind...stuff..
@@ -306,24 +308,21 @@ class SimpleLogger {
306
  */
307
 
308
  // Check if additional IP addresses are stored, from http_x_forwarded_for and so on
309
- $arr_found_additional_ip_headers = $this->get_event_ip_number_headers($row);
310
 
311
- if ( empty( $context["_server_remote_addr"] ) ) {
312
 
313
- $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided'>" . __("Anonymous web user", "simple-history") . "</strong> ";
314
 
315
  } else {
316
 
317
  $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided SimpleHistoryLogitem__anonUserWithIp'>";
318
 
319
- #if ( sizeof( $arr_found_additional_ip_headers ) ) {
320
-
321
-
322
- #$iplookup_link = sprintf('https://ipinfo.io/%1$s', esc_attr($context["_server_remote_addr"]));
323
-
324
- #$ip_numbers_joined = wp_sprintf_l('%l', array("_server_remote_addr" => $context["_server_remote_addr"]) + $arr_found_additional_ip_headers);
325
-
326
- /*$initiator_html .= sprintf(
327
  __('Anonymous user with multiple IP addresses detected: %1$s', "simple-history"),
328
  "<a target='_blank' href={$iplookup_link} class='SimpleHistoryLogitem__anonUserWithIp__theIp'>" . esc_html( $ip_numbers_joined ) . "</a>"
329
  );*/
@@ -337,31 +336,28 @@ class SimpleLogger {
337
  )
338
  */
339
 
340
- #} else {
341
-
342
  // single ip address
343
- $iplookup_link = sprintf('https://ipinfo.io/%1$s', esc_attr($context["_server_remote_addr"]));
344
 
345
  $initiator_html .= sprintf(
346
- __('Anonymous user from %1$s', "simple-history"),
347
- "<a target='_blank' href={$iplookup_link} class='SimpleHistoryLogitem__anonUserWithIp__theIp'>" . esc_html($context["_server_remote_addr"]) . "</a>"
348
  );
349
 
350
- #} // multiple ip
351
-
352
- $initiator_html .= "</strong> ";
353
 
354
  // $initiator_html .= "<strong>" . __("<br><br>Unknown user from {$context["_server_remote_addr"]}") . "</strong>";
355
  // $initiator_html .= "<strong>" . __("<br><br>{$context["_server_remote_addr"]}") . "</strong>";
356
  // $initiator_html .= "<strong>" . __("<br><br>User from IP {$context["_server_remote_addr"]}") . "</strong>";
357
  // $initiator_html .= "<strong>" . __("<br><br>Non-logged in user from IP {$context["_server_remote_addr"]}") . "</strong>";
358
-
359
- }
360
 
361
  break;
362
 
363
- case "other":
364
- $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided'>" . _x("Other", "Event header output, when initiator is unknown", "simple-history") . "</strong>";
365
  break;
366
 
367
  // no initiator
@@ -370,9 +366,9 @@ class SimpleLogger {
370
  break;
371
 
372
  default:
373
- $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided'>" . esc_html($initiator) . "</strong>";
374
 
375
- }
376
 
377
  /**
378
  * Filter generated html for the initiator row header html
@@ -382,19 +378,19 @@ class SimpleLogger {
382
  * @param string $initiator_html
383
  * @param object $row Log row
384
  */
385
- $initiator_html = apply_filters("simple_history/row_header_initiator_output", $initiator_html, $row);
386
 
387
  // HTML for date
388
  // Date (should...) always exist
389
  // http://developers.whatwg.org/text-level-semantics.html#the-time-element
390
- $date_html = "";
391
- $str_when = "";
392
 
393
  // $row->date is in GMT
394
- $date_datetime = new DateTime( $row->date, new DateTimeZone('GMT') );
395
 
396
  // Current datetime in GMT
397
- $time_current = strtotime( current_time("mysql", 1) );
398
 
399
  /**
400
  * Filter how many seconds as most that can pass since an
@@ -405,7 +401,7 @@ class SimpleLogger {
405
  * @param int $time_ago_max_time Seconds
406
  */
407
  $time_ago_max_time = DAY_IN_SECONDS * 2;
408
- $time_ago_max_time = apply_filters("simple_history/header_time_ago_max_time", $time_ago_max_time);
409
 
410
  /**
411
  * Filter how many seconds as most that can pass since an
@@ -416,37 +412,37 @@ class SimpleLogger {
416
  * @param int $time_ago_max_time Seconds
417
  */
418
  $time_ago_just_now_max_time = 30;
419
- $time_ago_just_now_max_time = apply_filters("simple_history/header_just_now_max_time", $time_ago_just_now_max_time);
420
 
421
  if ( $time_current - $date_datetime->getTimestamp() <= $time_ago_just_now_max_time ) {
422
 
423
  // show "just now" if event is very recent
424
- $str_when = __("Just now", "simple-history");
425
 
426
- } else if ( $time_current - $date_datetime->getTimestamp() > $time_ago_max_time ) {
427
 
428
  /* translators: Date format for log row header, see http://php.net/date */
429
- $datef = __('M j, Y \a\t G:i', "simple-history");
430
  $str_when = date_i18n( $datef, strtotime( get_date_from_gmt( $row->date ) ) );
431
 
432
  } else {
433
 
434
  // Show "nn minutes ago" when event is xx seconds ago or earlier
435
- $date_human_time_diff = human_time_diff($date_datetime->getTimestamp(), $time_current );
436
  /* translators: 1: last modified date and time in human time diff-format */
437
- $str_when = sprintf(__('%1$s ago', 'simple-history'), $date_human_time_diff);
438
 
439
  }
440
 
441
- $item_permalink = admin_url("index.php?page=simple_history_page");
442
  if ( ! empty( $row->id ) ) {
443
  $item_permalink .= "#item/{$row->id}";
444
  }
445
 
446
- $date_format = get_option('date_format') . ' - '. get_option('time_format');
447
  $str_datetime_title = sprintf(
448
- __('%1$s local time %3$s (%2$s GMT time)', "simple-history"),
449
- get_date_from_gmt( $date_datetime->format('Y-m-d H:i:s'), $date_format ), // 1 local time
450
  $date_datetime->format( $date_format ), // GMT time
451
  PHP_EOL // 3, new line
452
  );
@@ -459,9 +455,8 @@ class SimpleLogger {
459
  esc_html( $str_when ), // 2 date text, visible in log
460
  $date_datetime->format( DateTime::RFC3339 ) // 3
461
  );
462
- $date_html .= "</a>";
463
- $date_html .= "</span>";
464
-
465
 
466
  /**
467
  * Filter the output of the date section of the header.
@@ -471,19 +466,19 @@ class SimpleLogger {
471
  * @param String $date_html
472
  * @param array $row
473
  */
474
- $date_html = apply_filters("simple_history/row_header_date_output", $date_html, $row);
475
 
476
  // Logger "via" info in header, i.e. output some extra
477
  // info next to the time to make it more clear what plugin etc.
478
  // that "caused" this event
479
- $via_html = "";
480
- $logger_name_via = $this->getInfoValueByKey("name_via");
481
 
482
  if ( $logger_name_via ) {
483
 
484
  $via_html = "<span class='SimpleHistoryLogitem__inlineDivided SimpleHistoryLogitem__via'>";
485
  $via_html .= $logger_name_via;
486
- $via_html .= "</span>";
487
 
488
  }
489
 
@@ -502,10 +497,9 @@ class SimpleLogger {
502
  %2$s
503
  %3$s
504
  ';
505
- #if ( ! $initiator_html ) {
506
- # $template = '%2$s';
507
- #}
508
-
509
  $html = sprintf(
510
  $template,
511
  $initiator_html, // 1
@@ -521,7 +515,7 @@ class SimpleLogger {
521
  * @param string $html
522
  * @param object $row Log row
523
  */
524
- $html = apply_filters("simple_history/row_header_output", $html, $row);
525
 
526
  return $html;
527
 
@@ -543,39 +537,37 @@ class SimpleLogger {
543
  * Image that the name of the user is added in front of the text:
544
  * Jessie James: Edited post "About the company"
545
  */
546
- public function getLogRowPlainTextOutput($row) {
547
 
548
  $message = $row->message;
549
- $message_key = isset( $row->context["_message_key"] ) ? $row->context["_message_key"] : null;
550
 
551
  // Message is translated here, but translation must be added in
552
  // plain text before
553
  if ( empty( $message_key ) ) {
554
 
555
  // Message key did not exist, so check if we should translate using textdomain
556
- if ( ! empty( $row->context["_gettext_domain"] ) ) {
557
- $message = __( $message, $row->context["_gettext_domain"] );
558
  }
559
-
560
  } else {
561
 
562
  // Check that messages does exist
563
  // If we for example disable a Logger we may have references
564
  // to message keys that are unavailable. If so then fallback to message.
565
- if ( isset( $this->messages[$message_key]["translated_text"] ) ) {
566
- $message = $this->messages[$message_key]["translated_text"];
567
  } else {
568
  // Not message exists for message key. Just keep using message.
569
  }
570
-
571
  }
572
 
573
- $html = $this->interpolate($message, $row->context, $row);
574
 
575
  // All messages are escaped by default.
576
  // If you need unescaped output override this method
577
  // in your own logger
578
- $html = esc_html($html);
579
 
580
  /**
581
  * Filter generated output for plain text output
@@ -585,7 +577,7 @@ class SimpleLogger {
585
  * @param string $html
586
  * @param object $row Log row
587
  */
588
- $html = apply_filters("simple_history/row_plain_text_output", $html, $row);
589
 
590
  return $html;
591
 
@@ -596,33 +588,33 @@ class SimpleLogger {
596
  * Image can be for example gravar if sender is user,
597
  * or other images if sender i system, wordpress, and so on
598
  */
599
- public function getLogRowSenderImageOutput($row) {
600
 
601
- $sender_image_html = "";
602
  $sender_image_size = 32;
603
 
604
  $initiator = $row->initiator;
605
 
606
- switch ($initiator) {
607
 
608
  // wp_user = wordpress uses, but user may have been deleted since log entry was added
609
- case "wp_user":
610
 
611
- $user_id = isset($row->context["_user_id"]) ? $row->context["_user_id"] : null;
612
 
613
- if ($user_id > 0 && $user = get_user_by("id", $user_id)) {
614
 
615
  // Sender was user
616
- $sender_image_html = $this->simpleHistory->get_avatar($user->user_email, $sender_image_size);
617
 
618
- } else if ($user_id > 0) {
619
 
620
  // Sender was a user, but user is deleted now
621
- $sender_image_html = $this->simpleHistory->get_avatar("", $sender_image_size);
622
 
623
  } else {
624
 
625
- $sender_image_html = $this->simpleHistory->get_avatar("", $sender_image_size);
626
 
627
  }
628
 
@@ -638,7 +630,7 @@ class SimpleLogger {
638
  * @param string $sender_image_html
639
  * @param object $row Log row
640
  */
641
- $sender_image_html = apply_filters("simple_history/row_sender_image_output", $sender_image_html, $row);
642
 
643
  return $sender_image_html;
644
 
@@ -652,9 +644,9 @@ class SimpleLogger {
652
  * @param object $row
653
  * @return string HTML-formatted output
654
  */
655
- public function getLogRowDetailsOutput($row) {
656
 
657
- $html = "";
658
 
659
  /**
660
  * Filter generated output for details
@@ -664,7 +656,7 @@ class SimpleLogger {
664
  * @param string $html
665
  * @param object $row Log row
666
  */
667
- $html = apply_filters("simple_history/row_details_output", $html, $row);
668
 
669
  return $html;
670
 
@@ -674,12 +666,12 @@ class SimpleLogger {
674
  * System is unusable.
675
  *
676
  * @param string $message
677
- * @param array $context
678
  * @return null
679
  */
680
- public static function emergency($message, array $context = array()) {
681
 
682
- return $this->log(SimpleLoggerLogLevels::EMERGENCY, $message, $context);
683
 
684
  }
685
 
@@ -687,12 +679,12 @@ class SimpleLogger {
687
  * System is unusable.
688
  *
689
  * @param string $message key from getInfo messages array
690
- * @param array $context
691
  * @return null
692
  */
693
- public function emergencyMessage($message, array $context = array()) {
694
 
695
- return $this->logByMessageKey(SimpleLoggerLogLevels::EMERGENCY, $message, $context);
696
 
697
  }
698
 
@@ -704,10 +696,10 @@ class SimpleLogger {
704
  *
705
  * return $this->logByMessageKey(SimpleLoggerLogLevels::EMERGENCY, $message, $context);
706
  */
707
- private function logByMessageKey($SimpleLoggerLogLevelsLevel, $messageKey, $context) {
708
 
709
  // When logging by message then the key must exist
710
- if ( ! isset( $this->messages[ $messageKey ]["untranslated_text"] ) ) {
711
  return;
712
  }
713
 
@@ -723,14 +715,14 @@ class SimpleLogger {
723
  * @param array context
724
  * @return bool false to abort logging
725
  */
726
- $doLog = apply_filters("simple_history/simple_logger/log_message_key", true, $this->slug, $messageKey, $SimpleLoggerLogLevelsLevel, $context);
727
 
728
  if ( ! $doLog ) {
729
  return;
730
  }
731
 
732
- $context["_message_key"] = $messageKey;
733
- $message = $this->messages[ $messageKey ]["untranslated_text"];
734
 
735
  $this->log( $SimpleLoggerLogLevelsLevel, $message, $context );
736
 
@@ -741,11 +733,11 @@ class SimpleLogger {
741
  * Action must be taken immediately.
742
  *
743
  * @param string $message
744
- * @param array $context
745
  * @return null
746
  */
747
- public static function alert($message, array $context = array()) {
748
- return $this->log(SimpleLoggerLogLevels::ALERT, $message, $context);
749
 
750
  }
751
 
@@ -753,12 +745,12 @@ class SimpleLogger {
753
  * Action must be taken immediately.
754
  *
755
  * @param string $message key from getInfo messages array
756
- * @param array $context
757
  * @return null
758
  */
759
- public function alertMessage($message, array $context = array()) {
760
 
761
- return $this->logByMessageKey(SimpleLoggerLogLevels::ALERT, $message, $context);
762
 
763
  }
764
 
@@ -768,12 +760,12 @@ class SimpleLogger {
768
  * Example: Application component unavailable, unexpected exception.
769
  *
770
  * @param string $message
771
- * @param array $context
772
  * @return null
773
  */
774
- public static function critical($message, array $context = array()) {
775
 
776
- return $this->log(SimpleLoggerLogLevels::CRITICAL, $message, $context);
777
 
778
  }
779
 
@@ -781,19 +773,19 @@ class SimpleLogger {
781
  * Critical conditions.
782
  *
783
  * @param string $message key from getInfo messages array
784
- * @param array $context
785
  * @return null
786
  */
787
- public function criticalMessage($message, array $context = array()) {
788
 
789
- if (!isset($this->messages[$message]["untranslated_text"])) {
790
  return;
791
  }
792
 
793
- $context["_message_key"] = $message;
794
- $message = $this->messages[$message]["untranslated_text"];
795
 
796
- $this->log(SimpleLoggerLogLevels::CRITICAL, $message, $context);
797
 
798
  }
799
 
@@ -802,12 +794,12 @@ class SimpleLogger {
802
  * be logged and monitored.
803
  *
804
  * @param string $message
805
- * @param array $context
806
  * @return null
807
  */
808
- public function error($message, array $context = array()) {
809
 
810
- return $this->log(SimpleLoggerLogLevels::ERROR, $message, $context);
811
 
812
  }
813
 
@@ -816,12 +808,12 @@ class SimpleLogger {
816
  * be logged and monitored.
817
  *
818
  * @param string $message key from getInfo messages array
819
- * @param array $context
820
  * @return null
821
  */
822
- public function errorMessage($message, array $context = array()) {
823
 
824
- return $this->logByMessageKey(SimpleLoggerLogLevels::ERROR, $message, $context);
825
 
826
  }
827
 
@@ -832,12 +824,12 @@ class SimpleLogger {
832
  * that are not necessarily wrong.
833
  *
834
  * @param string $message
835
- * @param array $context
836
  * @return null
837
  */
838
- public function warning($message, array $context = array()) {
839
 
840
- return $this->log(SimpleLoggerLogLevels::WARNING, $message, $context);
841
 
842
  }
843
 
@@ -845,12 +837,12 @@ class SimpleLogger {
845
  * Exceptional occurrences that are not errors.
846
  *
847
  * @param string $message key from getInfo messages array
848
- * @param array $context
849
  * @return null
850
  */
851
- public function warningMessage($message, array $context = array()) {
852
 
853
- return $this->logByMessageKey(SimpleLoggerLogLevels::WARNING, $message, $context);
854
 
855
  }
856
 
@@ -858,12 +850,12 @@ class SimpleLogger {
858
  * Normal but significant events.
859
  *
860
  * @param string $message
861
- * @param array $context
862
  * @return null
863
  */
864
- public function notice($message, array $context = array()) {
865
 
866
- return $this->log(SimpleLoggerLogLevels::NOTICE, $message, $context);
867
 
868
  }
869
 
@@ -871,12 +863,12 @@ class SimpleLogger {
871
  * Normal but significant events.
872
  *
873
  * @param string $message key from getInfo messages array
874
- * @param array $context
875
  * @return null
876
  */
877
- public function noticeMessage($message, array $context = array()) {
878
 
879
- return $this->logByMessageKey(SimpleLoggerLogLevels::NOTICE, $message, $context);
880
 
881
  }
882
 
@@ -886,12 +878,12 @@ class SimpleLogger {
886
  * Example: User logs in, SQL logs.
887
  *
888
  * @param string $message
889
- * @param array $context
890
  * @return null
891
  */
892
- public function info($message, array $context = array()) {
893
 
894
- return $this->log(SimpleLoggerLogLevels::INFO, $message, $context);
895
 
896
  }
897
 
@@ -901,12 +893,12 @@ class SimpleLogger {
901
  * Example: User logs in, SQL logs.
902
  *
903
  * @param string $message key from getInfo messages array
904
- * @param array $context
905
  * @return null
906
  */
907
- public function infoMessage($message, array $context = array()) {
908
 
909
- return $this->logByMessageKey(SimpleLoggerLogLevels::INFO, $message, $context);
910
 
911
  }
912
 
@@ -914,12 +906,12 @@ class SimpleLogger {
914
  * Detailed debug information.
915
  *
916
  * @param string $message
917
- * @param array $context
918
  * @return null
919
  */
920
- public function debug($message, array $context = array()) {
921
 
922
- return $this->log(SimpleLoggerLogLevels::DEBUG, $message, $context);
923
 
924
  }
925
 
@@ -927,12 +919,12 @@ class SimpleLogger {
927
  * Detailed debug information.
928
  *
929
  * @param string $message key from getInfo messages array
930
- * @param array $context
931
  * @return null
932
  */
933
- public function debugMessage($message, array $context = array()) {
934
 
935
- return $this->logByMessageKey(SimpleLoggerLogLevels::DEBUG, $message, $context);
936
 
937
  }
938
 
@@ -983,17 +975,14 @@ class SimpleLogger {
983
  if ( isset( $sh_latest_translations[ $message ] ) ) {
984
 
985
  // Translation of this phrase was found, so use original phrase instead of translated one
986
-
987
  // Store textdomain since it's required to translate
988
- $context["_gettext_domain"] = $sh_latest_translations[$message]["domain"];
989
 
990
  // These are good to keep when debugging
991
  // $context["_gettext_org_message"] = $sh_latest_translations[$message]["text"];
992
  // $context["_gettext_translated_message"] = $sh_latest_translations[$message]["translation"];
993
-
994
- $message = $sh_latest_translations[ $message ]["text"];
995
  }
996
-
997
  }
998
 
999
  /**
@@ -1006,16 +995,17 @@ class SimpleLogger {
1006
  * @param array $context
1007
  * @param object SimpleLogger object
1008
  */
1009
- apply_filters("simple_history/log_arguments", $level, $message, $context, $this);
1010
- $context = apply_filters("simple_history/log_argument/context", $context, $level, $message, $this);
1011
- $level = apply_filters("simple_history/log_argument/level", $level, $context, $message, $this);
1012
- $message = apply_filters("simple_history/log_argument/message", $message, $level, $context, $this);
1013
 
1014
- /* Store date as GMT date, i.e. not local date/time
 
1015
  * Some info here:
1016
  * http://www.skyverge.com/blog/down-the-rabbit-hole-wordpress-and-timezones/
1017
  */
1018
- $localtime = current_time("mysql", 1);
1019
 
1020
  $db_table = $wpdb->prefix . SimpleHistory::DBTABLE;
1021
 
@@ -1026,34 +1016,34 @@ class SimpleLogger {
1026
  *
1027
  * @param string $db_table
1028
  */
1029
- $db_table = apply_filters("simple_history/db_table", $db_table);
1030
 
1031
  $data = array(
1032
- "logger" => $this->slug,
1033
- "level" => $level,
1034
- "date" => $localtime,
1035
- "message" => $message,
1036
  );
1037
 
1038
  // Allow date to be override
1039
  // Date must be in format 'Y-m-d H:i:s'
1040
- if (isset($context["_date"])) {
1041
- $data["date"] = $context["_date"];
1042
- unset($context["_date"]);
1043
  }
1044
 
1045
  // Add occasions id
1046
  $occasions_id = null;
1047
- if (isset($context["_occasionsID"])) {
1048
 
1049
  // Minimize risk of similar loggers logging same messages and such and resulting in same occasions id
1050
  // by always adding logger slug
1051
  $occasions_data = array(
1052
- "_occasionsID" => $context["_occasionsID"],
1053
- "_loggerSlug" => $this->slug,
1054
  );
1055
- $occasions_id = md5(json_encode($occasions_data));
1056
- unset($context["_occasionsID"]);
1057
 
1058
  } else {
1059
 
@@ -1061,14 +1051,14 @@ class SimpleLogger {
1061
  $occasions_data = $data + $context;
1062
  // error_log(simpleHistory::json_encode($occasions_data));
1063
  // Don't include date in context data
1064
- unset($occasions_data["date"]);
1065
 
1066
- //sf_d($occasions_data);exit;
1067
- $occasions_id = md5(json_encode($occasions_data));
1068
 
1069
  }
1070
 
1071
- $data["occasionsID"] = $occasions_id;
1072
 
1073
  // Log event type, defaults to other if not set
1074
  /*
@@ -1081,68 +1071,65 @@ class SimpleLogger {
1081
  */
1082
 
1083
  // Log initiator, defaults to current user if exists, or other if not user exist
1084
- if ( isset( $context["_initiator"] ) ) {
1085
 
1086
  // Manually set in context
1087
- $data["initiator"] = $context["_initiator"];
1088
- unset( $context["_initiator"] );
1089
 
1090
  } else {
1091
 
1092
  // No initiator set, try to determine
1093
-
1094
  // Default to other
1095
- $data["initiator"] = SimpleLoggerLogInitiators::OTHER;
1096
 
1097
  // Check if user is responsible.
1098
- if ( function_exists("wp_get_current_user") ) {
1099
 
1100
  $current_user = wp_get_current_user();
1101
 
1102
  if ( isset( $current_user->ID ) && $current_user->ID ) {
1103
 
1104
- $data["initiator"] = SimpleLoggerLogInitiators::WP_USER;
1105
- $context["_user_id"] = $current_user->ID;
1106
- $context["_user_login"] = $current_user->user_login;
1107
- $context["_user_email"] = $current_user->user_email;
1108
 
1109
  }
1110
-
1111
  }
1112
 
1113
  // If cron then set WordPress as responsible
1114
- if ( defined('DOING_CRON') && DOING_CRON ) {
1115
 
1116
  // Seems to be wp cron running and doing this
1117
- $data["initiator"] = SimpleLoggerLogInitiators::WORDPRESS;
1118
- $context["_wp_cron_running"] = true;
1119
 
1120
  }
1121
 
1122
  // If running as CLI and WP_CLI_PHP_USED is set then it is WP CLI that is doing it
1123
  // How to log this? Is this a user, is it WordPress, or what?
1124
  // I'm thinking:
1125
- // - it is a user that is manually doing this, on purpose, with intent, so not auto wordpress
1126
- // - it is a specific user, but we don't know who
1127
  // - sounds like a special case, set initiator to wp_cli
1128
  // Can be used by plugins/themes to check if WP-CLI is running or not
1129
- if ( defined( "WP_CLI" ) && WP_CLI ) {
1130
 
1131
- $data["initiator"] = SimpleLoggerLogInitiators::WP_CLI;
1132
 
1133
  }
1134
-
1135
- }
1136
 
1137
  // Detect XML-RPC calls and append to context, if not already there
1138
- if ( defined("XMLRPC_REQUEST") && XMLRPC_REQUEST && ! isset( $context["_xmlrpc_request"] ) ) {
1139
 
1140
- $context["_xmlrpc_request"] = true;
1141
 
1142
  }
1143
 
1144
  // Trim message
1145
- $data["message"] = trim( $data["message"] );
1146
 
1147
  /**
1148
  * Filter data to be saved to db
@@ -1151,17 +1138,16 @@ class SimpleLogger {
1151
  *
1152
  * @param array $data
1153
  */
1154
- $data = apply_filters("simple_history/log_insert_data", $data);
1155
 
1156
  // Insert data into db
1157
  // sf_d($db_table, '$db_table');exit;
1158
-
1159
- $result = $wpdb->insert($db_table, $data);
1160
 
1161
  $data_parent_row = null;
1162
 
1163
  // Only save context if able to store row
1164
- if (false === $result) {
1165
 
1166
  $history_inserted_id = null;
1167
 
@@ -1178,37 +1164,35 @@ class SimpleLogger {
1178
  *
1179
  * @param string $db_table_contexts
1180
  */
1181
- $db_table_contexts = apply_filters("simple_history/logger_db_table_contexts", $db_table_contexts);
1182
 
1183
- if (!is_array($context)) {
1184
  $context = array();
1185
  }
1186
 
1187
  // Append user id to context, if not already added
1188
- if (!isset($context["_user_id"])) {
1189
 
1190
  // wp_get_current_user is ont available early
1191
  // http://codex.wordpress.org/Function_Reference/wp_get_current_user
1192
  // https://core.trac.wordpress.org/ticket/14024
1193
- if (function_exists("wp_get_current_user")) {
1194
 
1195
  $current_user = wp_get_current_user();
1196
 
1197
- if (isset($current_user->ID) && $current_user->ID) {
1198
- $context["_user_id"] = $current_user->ID;
1199
- $context["_user_login"] = $current_user->user_login;
1200
- $context["_user_email"] = $current_user->user_email;
1201
  }
1202
-
1203
  }
1204
-
1205
  }
1206
 
1207
  // Add remote addr to context
1208
  // Good to always have
1209
- if ( ! isset($context["_server_remote_addr"]) ) {
1210
 
1211
- $context["_server_remote_addr"] = empty($_SERVER["REMOTE_ADDR"]) ? "" : $_SERVER["REMOTE_ADDR"];
1212
 
1213
  // If web server is behind a load balancer then the ip address will always be the same
1214
  // See bug report: https://wordpress.org/support/topic/use-x-forwarded-for-http-header-when-logging-remote_addr?replies=1#post-6422981
@@ -1216,7 +1200,6 @@ class SimpleLogger {
1216
  // Also note that the header can be faked
1217
  // Ref: http://stackoverflow.com/questions/753645/how-do-i-get-the-correct-ip-from-http-x-forwarded-for-if-it-contains-multiple-ip
1218
  // Ref: http://blackbe.lt/advanced-method-to-obtain-the-client-ip-in-php/
1219
-
1220
  // Check for IP in lots of headers
1221
  // Based on code found here:
1222
  // http://blackbe.lt/advanced-method-to-obtain-the-client-ip-in-php/
@@ -1224,41 +1207,37 @@ class SimpleLogger {
1224
 
1225
  foreach ( $ip_keys as $key ) {
1226
 
1227
- if (array_key_exists($key, $_SERVER) === true) {
1228
 
1229
  // Loop through all IPs
1230
  $ip_loop_num = 0;
1231
- foreach (explode(',', $_SERVER[$key]) as $ip) {
1232
 
1233
  // trim for safety measures
1234
- $ip = trim($ip);
1235
 
1236
  // attempt to validate IP
1237
- if ($this->validate_ip($ip)) {
1238
 
1239
  // valid, add to context, with loop index appended so we can store many IPs
1240
- $key_lower = strtolower($key);
1241
- $context["_server_{$key_lower}_{$ip_loop_num}"] = $ip;
1242
 
1243
  }
1244
 
1245
  $ip_loop_num++;
1246
 
1247
  }
1248
-
1249
  }
1250
-
1251
  }
1252
-
1253
- }
1254
 
1255
  // Append http referer
1256
  // Also good to always have!
1257
- if (!isset($context["_server_http_referer"]) && isset($_SERVER["HTTP_REFERER"])) {
1258
- $context["_server_http_referer"] = $_SERVER["HTTP_REFERER"];
1259
  }
1260
 
1261
-
1262
  /**
1263
  * Filter the context to store for this event/row
1264
  *
@@ -1268,16 +1247,16 @@ class SimpleLogger {
1268
  * @param array $data Array with data used for parent row.
1269
  * @param array $this Reference to this logger instance
1270
  */
1271
- $context = apply_filters("simple_history/log_insert_context", $context, $data, $this);
1272
  $data_parent_row = $data;
1273
 
1274
  // Insert all context values into db
1275
  foreach ( $context as $key => $value ) {
1276
 
1277
  // If value is array or object then use json_encode to store it
1278
- //if ( is_object( $value ) || is_array( $value ) ) {
1279
- // $value = simpleHistory::json_encode($value);
1280
- //}
1281
  // Any reason why the check is not the other way around?
1282
  // Everything except strings should be json_encoded
1283
  if ( ! is_string( $value ) ) {
@@ -1285,20 +1264,19 @@ class SimpleLogger {
1285
  }
1286
 
1287
  $data = array(
1288
- "history_id" => $history_inserted_id,
1289
- "key" => $key,
1290
- "value" => $value,
1291
  );
1292
 
1293
- $result = $wpdb->insert ($db_table_contexts, $data );
1294
 
1295
  }
1296
-
1297
- }
1298
 
1299
  $this->lastInsertID = $history_inserted_id;
1300
 
1301
- $this->simpleHistory->get_cache_incrementor(true);
1302
 
1303
  /**
1304
  * Action that is called after an event has been logged
@@ -1309,7 +1287,7 @@ class SimpleLogger {
1309
  * @param array $data Array with data used for parent row.
1310
  * @param array $this Reference to this logger instance
1311
  */
1312
- do_action( "simple_history/log/inserted", $context, $data_parent_row, $this );
1313
 
1314
  // Return $this so we can chain methods
1315
  return $this;
@@ -1329,7 +1307,7 @@ class SimpleLogger {
1329
  'HTTP_X_FORWARDED',
1330
  'HTTP_X_CLUSTER_CLIENT_IP',
1331
  'HTTP_FORWARDED_FOR',
1332
- 'HTTP_FORWARDED'
1333
  );
1334
 
1335
  return $arr;
@@ -1341,7 +1319,7 @@ class SimpleLogger {
1341
  *
1342
  * @since 2.0.29
1343
  */
1344
- function get_event_ip_number_headers($row) {
1345
 
1346
  $ip_keys = $this->get_ip_number_header_keys();
1347
  $arr_found_additional_ip_headers = array();
@@ -1349,20 +1327,17 @@ class SimpleLogger {
1349
 
1350
  foreach ( $ip_keys as $one_ip_header_key ) {
1351
 
1352
- $one_ip_header_key_lower = strtolower($one_ip_header_key);
1353
 
1354
  foreach ( $context as $context_key => $context_val ) {
1355
 
1356
- #$key_check_for = "_server_" . strtolower($one_ip_header_key) . "_0";
1357
-
1358
- $match = preg_match("/^_server_{$one_ip_header_key_lower}_[\d+]/", $context_key, $matches);
1359
  if ( $match ) {
1360
  $arr_found_additional_ip_headers[ $context_key ] = $context_val;
1361
  }
1362
-
1363
- } // foreach context key for this ip header key
1364
-
1365
- } // foreach ip header key
1366
 
1367
  return $arr_found_additional_ip_headers;
1368
 
@@ -1372,9 +1347,9 @@ class SimpleLogger {
1372
  * Ensures an ip address is both a valid IP and does not fall within
1373
  * a private network range.
1374
  */
1375
- function validate_ip($ip) {
1376
 
1377
- if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4|FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE) === false) {
1378
  return false;
1379
  }
1380
 
@@ -1389,14 +1364,14 @@ class SimpleLogger {
1389
  */
1390
  function adminCSS() {
1391
  /*
1392
- ?>
1393
- <style>
1394
- body {
1395
- border: 2px solid red;
1396
- }
1397
- </style>
1398
- <?php
1399
- */
1400
  }
1401
 
1402
  /**
@@ -1406,12 +1381,12 @@ class SimpleLogger {
1406
  */
1407
  function adminJS() {
1408
  /*
1409
- ?>
1410
- <script>
1411
- console.log("This is outputed in the footer");
1412
- </script>
1413
- <?php
1414
- */
1415
  }
1416
 
1417
  }
@@ -1431,10 +1406,10 @@ class SimpleLoggerLogInitiators {
1431
  const WEB_USER = 'web_user';
1432
 
1433
  // WordPress core or plugins updated automatically via wp-cron
1434
- const WORDPRESS = "wp";
1435
 
1436
  // WP CLI / terminal
1437
- const WP_CLI = "wp_cli";
1438
 
1439
  // I dunno
1440
  const OTHER = 'other';
42
 
43
  /**
44
  * Constructor. Remember to call this as parent constructor if making a childlogger
45
+ *
46
  * @param $simpleHistory history class objectinstance
47
  */
48
+ public function __construct( $simpleHistory = null ) {
49
 
50
  global $wpdb;
51
 
74
  $arr_info = array(
75
 
76
  // The logger slug. Defaulting to the class name is nice and logical I think
77
+ 'slug' => __CLASS__,
78
 
79
  // Shown on the info-tab in settings, use these fields to tell
80
  // an admin what your logger is used for
81
+ 'name' => 'SimpleLogger',
82
+ 'description' => 'The built in logger for Simple History',
83
 
84
  // Capability required to view log entries from this logger
85
+ 'capability' => 'edit_pages',
86
+ 'messages' => array(
87
  // No pre-defined variants
88
  // when adding messages __() or _x() must be used
89
  ),
118
 
119
  $arr_info = $this->getInfo();
120
 
121
+ $capability = 'manage_options';
122
 
123
+ if ( ! empty( $arr_info['capability'] ) ) {
124
+ $capability = $arr_info['capability'];
125
  }
126
 
127
  return $capability;
132
  * Interpolates context values into the message placeholders.
133
  *
134
  * @param string $message
135
+ * @param array $context
136
+ * @param array $row Currently not always passed, because loggers need to be updated to support this...
137
  */
138
  function interpolate( $message, $context = array(), $row = null ) {
139
 
146
  *
147
  * @since 2.2.4
148
  */
149
+ $context = apply_filters( 'simple_history/logger/interpolate/context', $context, $message, $row );
150
 
151
  // Build a replacement array with braces around the context keys
152
  $replace = array();
164
  continue;
165
  }
166
 
167
+ $replace[ '{' . $key . '}' ] = $val;
168
 
169
  }
170
 
190
  * Returns header output for a log row
191
  * Format should be common for all log rows and should be like:
192
  * Username (user role) · Date
193
+ *
194
  * @return string HTML
195
  */
196
+ function getLogRowHeaderOutput( $row ) {
197
 
198
  // HTML for initiator
199
+ $initiator_html = '';
200
 
201
  $initiator = $row->initiator;
202
  $context = $row->context;
203
 
204
+ switch ( $initiator ) {
205
 
206
+ case 'wp':
207
  $initiator_html .= '<strong class="SimpleHistoryLogitem__inlineDivided">WordPress</strong> ';
208
  break;
209
 
210
+ case 'wp_cli':
211
  $initiator_html .= '<strong class="SimpleHistoryLogitem__inlineDivided">WP-CLI</strong> ';
212
  break;
213
 
214
  // wp_user = wordpress uses, but user may have been deleted since log entry was added
215
+ case 'wp_user':
216
 
217
+ $user_id = isset( $row->context['_user_id'] ) ? $row->context['_user_id'] : null;
218
 
219
+ if ( $user_id > 0 && $user = get_user_by( 'id', $user_id ) ) {
220
 
221
  // Sender is user and user still exists
222
  $is_current_user = ($user_id == get_current_user_id()) ? true : false;
223
 
224
  // get user role, as done in user-edit.php
225
+ $wp_roles = $GLOBALS['wp_roles'];
226
  $all_roles = (array) $wp_roles->roles;
227
+ $user_roles = array_intersect( array_values( (array) $user->roles ), array_keys( (array) $wp_roles->roles ) );
228
  $user_role = array_shift( $user_roles );
229
 
230
  $user_display_name = $user->display_name;
236
  * @param bool If you should be used
237
  * @since 2.1
238
  */
239
+ $use_you = apply_filters( 'simple_history/header_initiator_use_you', true );
240
 
241
  if ( $use_you && $is_current_user ) {
242
 
264
  *
265
  * @param string $format.
266
  */
267
+ $tmpl_initiator_html = apply_filters( 'simple_history/header_initiator_html_existing_user', $tmpl_initiator_html );
268
 
269
  $initiator_html .= sprintf(
270
  $tmpl_initiator_html,
271
+ esc_html( $user->user_login ), // 1
272
+ esc_html( $user->user_email ), // 2
273
+ esc_html( $user_display_name ), // 3
274
  $user_role, // 4
275
+ _x( 'You', 'header output when initiator is the currently logged in user', 'simple-history' ), // 5
276
  get_edit_user_link( $user_id ) // 6
277
  );
278
 
279
+ } elseif ( $user_id > 0 ) {
280
 
281
  // Sender was a user, but user is deleted now
282
  // output all info we have
286
  // _user_email
287
  $initiator_html .= sprintf(
288
  '<strong class="SimpleHistoryLogitem__inlineDivided">' .
289
+ __( 'Deleted user (had id %1$s, email %2$s, login %3$s)', 'simple-history' ) .
290
  '</strong>',
291
+ esc_html( $context['_user_id'] ), // 1
292
+ esc_html( $context['_user_email'] ), // 2
293
+ esc_html( $context['_user_login'] ) // 3
294
  );
295
 
296
+ }// End if().
297
 
298
  break;
299
 
300
+ case 'web_user':
301
 
302
  /*
303
  Note: server_remote_addr may not show visiting/attacking ip, if server is behind...stuff..
308
  */
309
 
310
  // Check if additional IP addresses are stored, from http_x_forwarded_for and so on
311
+ $arr_found_additional_ip_headers = $this->get_event_ip_number_headers( $row );
312
 
313
+ if ( empty( $context['_server_remote_addr'] ) ) {
314
 
315
+ $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided'>" . __( 'Anonymous web user', 'simple-history' ) . '</strong> ';
316
 
317
  } else {
318
 
319
  $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided SimpleHistoryLogitem__anonUserWithIp'>";
320
 
321
+ // if ( sizeof( $arr_found_additional_ip_headers ) ) {
322
+ // $iplookup_link = sprintf('https://ipinfo.io/%1$s', esc_attr($context["_server_remote_addr"]));
323
+ // $ip_numbers_joined = wp_sprintf_l('%l', array("_server_remote_addr" => $context["_server_remote_addr"]) + $arr_found_additional_ip_headers);
324
+ /*
325
+ $initiator_html .= sprintf(
 
 
 
326
  __('Anonymous user with multiple IP addresses detected: %1$s', "simple-history"),
327
  "<a target='_blank' href={$iplookup_link} class='SimpleHistoryLogitem__anonUserWithIp__theIp'>" . esc_html( $ip_numbers_joined ) . "</a>"
328
  );*/
336
  )
337
  */
338
 
339
+ // } else {
 
340
  // single ip address
341
+ $iplookup_link = sprintf( 'https://ipinfo.io/%1$s', esc_attr( $context['_server_remote_addr'] ) );
342
 
343
  $initiator_html .= sprintf(
344
+ __( 'Anonymous user from %1$s', 'simple-history' ),
345
+ "<a target='_blank' href={$iplookup_link} class='SimpleHistoryLogitem__anonUserWithIp__theIp'>" . esc_html( $context['_server_remote_addr'] ) . '</a>'
346
  );
347
 
348
+ // } // multiple ip
349
+ $initiator_html .= '</strong> ';
 
350
 
351
  // $initiator_html .= "<strong>" . __("<br><br>Unknown user from {$context["_server_remote_addr"]}") . "</strong>";
352
  // $initiator_html .= "<strong>" . __("<br><br>{$context["_server_remote_addr"]}") . "</strong>";
353
  // $initiator_html .= "<strong>" . __("<br><br>User from IP {$context["_server_remote_addr"]}") . "</strong>";
354
  // $initiator_html .= "<strong>" . __("<br><br>Non-logged in user from IP {$context["_server_remote_addr"]}") . "</strong>";
355
+ }// End if().
 
356
 
357
  break;
358
 
359
+ case 'other':
360
+ $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided'>" . _x( 'Other', 'Event header output, when initiator is unknown', 'simple-history' ) . '</strong>';
361
  break;
362
 
363
  // no initiator
366
  break;
367
 
368
  default:
369
+ $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided'>" . esc_html( $initiator ) . '</strong>';
370
 
371
+ }// End switch().
372
 
373
  /**
374
  * Filter generated html for the initiator row header html
378
  * @param string $initiator_html
379
  * @param object $row Log row
380
  */
381
+ $initiator_html = apply_filters( 'simple_history/row_header_initiator_output', $initiator_html, $row );
382
 
383
  // HTML for date
384
  // Date (should...) always exist
385
  // http://developers.whatwg.org/text-level-semantics.html#the-time-element
386
+ $date_html = '';
387
+ $str_when = '';
388
 
389
  // $row->date is in GMT
390
+ $date_datetime = new DateTime( $row->date, new DateTimeZone( 'GMT' ) );
391
 
392
  // Current datetime in GMT
393
+ $time_current = strtotime( current_time( 'mysql', 1 ) );
394
 
395
  /**
396
  * Filter how many seconds as most that can pass since an
401
  * @param int $time_ago_max_time Seconds
402
  */
403
  $time_ago_max_time = DAY_IN_SECONDS * 2;
404
+ $time_ago_max_time = apply_filters( 'simple_history/header_time_ago_max_time', $time_ago_max_time );
405
 
406
  /**
407
  * Filter how many seconds as most that can pass since an
412
  * @param int $time_ago_max_time Seconds
413
  */
414
  $time_ago_just_now_max_time = 30;
415
+ $time_ago_just_now_max_time = apply_filters( 'simple_history/header_just_now_max_time', $time_ago_just_now_max_time );
416
 
417
  if ( $time_current - $date_datetime->getTimestamp() <= $time_ago_just_now_max_time ) {
418
 
419
  // show "just now" if event is very recent
420
+ $str_when = __( 'Just now', 'simple-history' );
421
 
422
+ } elseif ( $time_current - $date_datetime->getTimestamp() > $time_ago_max_time ) {
423
 
424
  /* translators: Date format for log row header, see http://php.net/date */
425
+ $datef = __( 'M j, Y \a\t G:i', 'simple-history' );
426
  $str_when = date_i18n( $datef, strtotime( get_date_from_gmt( $row->date ) ) );
427
 
428
  } else {
429
 
430
  // Show "nn minutes ago" when event is xx seconds ago or earlier
431
+ $date_human_time_diff = human_time_diff( $date_datetime->getTimestamp(), $time_current );
432
  /* translators: 1: last modified date and time in human time diff-format */
433
+ $str_when = sprintf( __( '%1$s ago', 'simple-history' ), $date_human_time_diff );
434
 
435
  }
436
 
437
+ $item_permalink = admin_url( 'index.php?page=simple_history_page' );
438
  if ( ! empty( $row->id ) ) {
439
  $item_permalink .= "#item/{$row->id}";
440
  }
441
 
442
+ $date_format = get_option( 'date_format' ) . ' - ' . get_option( 'time_format' );
443
  $str_datetime_title = sprintf(
444
+ __( '%1$s local time %3$s (%2$s GMT time)', 'simple-history' ),
445
+ get_date_from_gmt( $date_datetime->format( 'Y-m-d H:i:s' ), $date_format ), // 1 local time
446
  $date_datetime->format( $date_format ), // GMT time
447
  PHP_EOL // 3, new line
448
  );
455
  esc_html( $str_when ), // 2 date text, visible in log
456
  $date_datetime->format( DateTime::RFC3339 ) // 3
457
  );
458
+ $date_html .= '</a>';
459
+ $date_html .= '</span>';
 
460
 
461
  /**
462
  * Filter the output of the date section of the header.
466
  * @param String $date_html
467
  * @param array $row
468
  */
469
+ $date_html = apply_filters( 'simple_history/row_header_date_output', $date_html, $row );
470
 
471
  // Logger "via" info in header, i.e. output some extra
472
  // info next to the time to make it more clear what plugin etc.
473
  // that "caused" this event
474
+ $via_html = '';
475
+ $logger_name_via = $this->getInfoValueByKey( 'name_via' );
476
 
477
  if ( $logger_name_via ) {
478
 
479
  $via_html = "<span class='SimpleHistoryLogitem__inlineDivided SimpleHistoryLogitem__via'>";
480
  $via_html .= $logger_name_via;
481
+ $via_html .= '</span>';
482
 
483
  }
484
 
497
  %2$s
498
  %3$s
499
  ';
500
+ // if ( ! $initiator_html ) {
501
+ // $template = '%2$s';
502
+ // }
 
503
  $html = sprintf(
504
  $template,
505
  $initiator_html, // 1
515
  * @param string $html
516
  * @param object $row Log row
517
  */
518
+ $html = apply_filters( 'simple_history/row_header_output', $html, $row );
519
 
520
  return $html;
521
 
537
  * Image that the name of the user is added in front of the text:
538
  * Jessie James: Edited post "About the company"
539
  */
540
+ public function getLogRowPlainTextOutput( $row ) {
541
 
542
  $message = $row->message;
543
+ $message_key = isset( $row->context['_message_key'] ) ? $row->context['_message_key'] : null;
544
 
545
  // Message is translated here, but translation must be added in
546
  // plain text before
547
  if ( empty( $message_key ) ) {
548
 
549
  // Message key did not exist, so check if we should translate using textdomain
550
+ if ( ! empty( $row->context['_gettext_domain'] ) ) {
551
+ $message = __( $message, $row->context['_gettext_domain'] );
552
  }
 
553
  } else {
554
 
555
  // Check that messages does exist
556
  // If we for example disable a Logger we may have references
557
  // to message keys that are unavailable. If so then fallback to message.
558
+ if ( isset( $this->messages[ $message_key ]['translated_text'] ) ) {
559
+ $message = $this->messages[ $message_key ]['translated_text'];
560
  } else {
561
  // Not message exists for message key. Just keep using message.
562
  }
 
563
  }
564
 
565
+ $html = $this->interpolate( $message, $row->context, $row );
566
 
567
  // All messages are escaped by default.
568
  // If you need unescaped output override this method
569
  // in your own logger
570
+ $html = esc_html( $html );
571
 
572
  /**
573
  * Filter generated output for plain text output
577
  * @param string $html
578
  * @param object $row Log row
579
  */
580
+ $html = apply_filters( 'simple_history/row_plain_text_output', $html, $row );
581
 
582
  return $html;
583
 
588
  * Image can be for example gravar if sender is user,
589
  * or other images if sender i system, wordpress, and so on
590
  */
591
+ public function getLogRowSenderImageOutput( $row ) {
592
 
593
+ $sender_image_html = '';
594
  $sender_image_size = 32;
595
 
596
  $initiator = $row->initiator;
597
 
598
+ switch ( $initiator ) {
599
 
600
  // wp_user = wordpress uses, but user may have been deleted since log entry was added
601
+ case 'wp_user':
602
 
603
+ $user_id = isset( $row->context['_user_id'] ) ? $row->context['_user_id'] : null;
604
 
605
+ if ( $user_id > 0 && $user = get_user_by( 'id', $user_id ) ) {
606
 
607
  // Sender was user
608
+ $sender_image_html = $this->simpleHistory->get_avatar( $user->user_email, $sender_image_size );
609
 
610
+ } elseif ( $user_id > 0 ) {
611
 
612
  // Sender was a user, but user is deleted now
613
+ $sender_image_html = $this->simpleHistory->get_avatar( '', $sender_image_size );
614
 
615
  } else {
616
 
617
+ $sender_image_html = $this->simpleHistory->get_avatar( '', $sender_image_size );
618
 
619
  }
620
 
630
  * @param string $sender_image_html
631
  * @param object $row Log row
632
  */
633
+ $sender_image_html = apply_filters( 'simple_history/row_sender_image_output', $sender_image_html, $row );
634
 
635
  return $sender_image_html;
636
 
644
  * @param object $row
645
  * @return string HTML-formatted output
646
  */
647
+ public function getLogRowDetailsOutput( $row ) {
648
 
649
+ $html = '';
650
 
651
  /**
652
  * Filter generated output for details
656
  * @param string $html
657
  * @param object $row Log row
658
  */
659
+ $html = apply_filters( 'simple_history/row_details_output', $html, $row );
660
 
661
  return $html;
662
 
666
  * System is unusable.
667
  *
668
  * @param string $message
669
+ * @param array $context
670
  * @return null
671
  */
672
+ public function emergency( $message, array $context = array() ) {
673
 
674
+ return $this->log( SimpleLoggerLogLevels::EMERGENCY, $message, $context );
675
 
676
  }
677
 
679
  * System is unusable.
680
  *
681
  * @param string $message key from getInfo messages array
682
+ * @param array $context
683
  * @return null
684
  */
685
+ public function emergencyMessage( $message, array $context = array() ) {
686
 
687
+ return $this->logByMessageKey( SimpleLoggerLogLevels::EMERGENCY, $message, $context );
688
 
689
  }
690
 
696
  *
697
  * return $this->logByMessageKey(SimpleLoggerLogLevels::EMERGENCY, $message, $context);
698
  */
699
+ private function logByMessageKey( $SimpleLoggerLogLevelsLevel, $messageKey, $context ) {
700
 
701
  // When logging by message then the key must exist
702
+ if ( ! isset( $this->messages[ $messageKey ]['untranslated_text'] ) ) {
703
  return;
704
  }
705
 
715
  * @param array context
716
  * @return bool false to abort logging
717
  */
718
+ $doLog = apply_filters( 'simple_history/simple_logger/log_message_key', true, $this->slug, $messageKey, $SimpleLoggerLogLevelsLevel, $context );
719
 
720
  if ( ! $doLog ) {
721
  return;
722
  }
723
 
724
+ $context['_message_key'] = $messageKey;
725
+ $message = $this->messages[ $messageKey ]['untranslated_text'];
726
 
727
  $this->log( $SimpleLoggerLogLevelsLevel, $message, $context );
728
 
733
  * Action must be taken immediately.
734
  *
735
  * @param string $message
736
+ * @param array $context
737
  * @return null
738
  */
739
+ public function alert( $message, array $context = array() ) {
740
+ return $this->log( SimpleLoggerLogLevels::ALERT, $message, $context );
741
 
742
  }
743
 
745
  * Action must be taken immediately.
746
  *
747
  * @param string $message key from getInfo messages array
748
+ * @param array $context
749
  * @return null
750
  */
751
+ public function alertMessage( $message, array $context = array() ) {
752
 
753
+ return $this->logByMessageKey( SimpleLoggerLogLevels::ALERT, $message, $context );
754
 
755
  }
756
 
760
  * Example: Application component unavailable, unexpected exception.
761
  *
762
  * @param string $message
763
+ * @param array $context
764
  * @return null
765
  */
766
+ public function critical( $message, array $context = array() ) {
767
 
768
+ return $this->log( SimpleLoggerLogLevels::CRITICAL, $message, $context );
769
 
770
  }
771
 
773
  * Critical conditions.
774
  *
775
  * @param string $message key from getInfo messages array
776
+ * @param array $context
777
  * @return null
778
  */
779
+ public function criticalMessage( $message, array $context = array() ) {
780
 
781
+ if ( ! isset( $this->messages[ $message ]['untranslated_text'] ) ) {
782
  return;
783
  }
784
 
785
+ $context['_message_key'] = $message;
786
+ $message = $this->messages[ $message ]['untranslated_text'];
787
 
788
+ $this->log( SimpleLoggerLogLevels::CRITICAL, $message, $context );
789
 
790
  }
791
 
794
  * be logged and monitored.
795
  *
796
  * @param string $message
797
+ * @param array $context
798
  * @return null
799
  */
800
+ public function error( $message, array $context = array() ) {
801
 
802
+ return $this->log( SimpleLoggerLogLevels::ERROR, $message, $context );
803
 
804
  }
805
 
808
  * be logged and monitored.
809
  *
810
  * @param string $message key from getInfo messages array
811
+ * @param array $context
812
  * @return null
813
  */
814
+ public function errorMessage( $message, array $context = array() ) {
815
 
816
+ return $this->logByMessageKey( SimpleLoggerLogLevels::ERROR, $message, $context );
817
 
818
  }
819
 
824
  * that are not necessarily wrong.
825
  *
826
  * @param string $message
827
+ * @param array $context
828
  * @return null
829
  */
830
+ public function warning( $message, array $context = array() ) {
831
 
832
+ return $this->log( SimpleLoggerLogLevels::WARNING, $message, $context );
833
 
834
  }
835
 
837
  * Exceptional occurrences that are not errors.
838
  *
839
  * @param string $message key from getInfo messages array
840
+ * @param array $context
841
  * @return null
842
  */
843
+ public function warningMessage( $message, array $context = array() ) {
844
 
845
+ return $this->logByMessageKey( SimpleLoggerLogLevels::WARNING, $message, $context );
846
 
847
  }
848
 
850
  * Normal but significant events.
851
  *
852
  * @param string $message
853
+ * @param array $context
854
  * @return null
855
  */
856
+ public function notice( $message, array $context = array() ) {
857
 
858
+ return $this->log( SimpleLoggerLogLevels::NOTICE, $message, $context );
859
 
860
  }
861
 
863
  * Normal but significant events.
864
  *
865
  * @param string $message key from getInfo messages array
866
+ * @param array $context
867
  * @return null
868
  */
869
+ public function noticeMessage( $message, array $context = array() ) {
870
 
871
+ return $this->logByMessageKey( SimpleLoggerLogLevels::NOTICE, $message, $context );
872
 
873
  }
874
 
878
  * Example: User logs in, SQL logs.
879
  *
880
  * @param string $message
881
+ * @param array $context
882
  * @return null
883
  */
884
+ public function info( $message, array $context = array() ) {
885
 
886
+ return $this->log( SimpleLoggerLogLevels::INFO, $message, $context );
887
 
888
  }
889
 
893
  * Example: User logs in, SQL logs.
894
  *
895
  * @param string $message key from getInfo messages array
896
+ * @param array $context
897
  * @return null
898
  */
899
+ public function infoMessage( $message, array $context = array() ) {
900
 
901
+ return $this->logByMessageKey( SimpleLoggerLogLevels::INFO, $message, $context );
902
 
903
  }
904
 
906
  * Detailed debug information.
907
  *
908
  * @param string $message
909
+ * @param array $context
910
  * @return null
911
  */
912
+ public function debug( $message, array $context = array() ) {
913
 
914
+ return $this->log( SimpleLoggerLogLevels::DEBUG, $message, $context );
915
 
916
  }
917
 
919
  * Detailed debug information.
920
  *
921
  * @param string $message key from getInfo messages array
922
+ * @param array $context
923
  * @return null
924
  */
925
+ public function debugMessage( $message, array $context = array() ) {
926
 
927
+ return $this->logByMessageKey( SimpleLoggerLogLevels::DEBUG, $message, $context );
928
 
929
  }
930
 
975
  if ( isset( $sh_latest_translations[ $message ] ) ) {
976
 
977
  // Translation of this phrase was found, so use original phrase instead of translated one
 
978
  // Store textdomain since it's required to translate
979
+ $context['_gettext_domain'] = $sh_latest_translations[ $message ]['domain'];
980
 
981
  // These are good to keep when debugging
982
  // $context["_gettext_org_message"] = $sh_latest_translations[$message]["text"];
983
  // $context["_gettext_translated_message"] = $sh_latest_translations[$message]["translation"];
984
+ $message = $sh_latest_translations[ $message ]['text'];
 
985
  }
 
986
  }
987
 
988
  /**
995
  * @param array $context
996
  * @param object SimpleLogger object
997
  */
998
+ apply_filters( 'simple_history/log_arguments', $level, $message, $context, $this );
999
+ $context = apply_filters( 'simple_history/log_argument/context', $context, $level, $message, $this );
1000
+ $level = apply_filters( 'simple_history/log_argument/level', $level, $context, $message, $this );
1001
+ $message = apply_filters( 'simple_history/log_argument/message', $message, $level, $context, $this );
1002
 
1003
+ /*
1004
+ Store date as GMT date, i.e. not local date/time
1005
  * Some info here:
1006
  * http://www.skyverge.com/blog/down-the-rabbit-hole-wordpress-and-timezones/
1007
  */
1008
+ $localtime = current_time( 'mysql', 1 );
1009
 
1010
  $db_table = $wpdb->prefix . SimpleHistory::DBTABLE;
1011
 
1016
  *
1017
  * @param string $db_table
1018
  */
1019
+ $db_table = apply_filters( 'simple_history/db_table', $db_table );
1020
 
1021
  $data = array(
1022
+ 'logger' => $this->slug,
1023
+ 'level' => $level,
1024
+ 'date' => $localtime,
1025
+ 'message' => $message,
1026
  );
1027
 
1028
  // Allow date to be override
1029
  // Date must be in format 'Y-m-d H:i:s'
1030
+ if ( isset( $context['_date'] ) ) {
1031
+ $data['date'] = $context['_date'];
1032
+ unset( $context['_date'] );
1033
  }
1034
 
1035
  // Add occasions id
1036
  $occasions_id = null;
1037
+ if ( isset( $context['_occasionsID'] ) ) {
1038
 
1039
  // Minimize risk of similar loggers logging same messages and such and resulting in same occasions id
1040
  // by always adding logger slug
1041
  $occasions_data = array(
1042
+ '_occasionsID' => $context['_occasionsID'],
1043
+ '_loggerSlug' => $this->slug,
1044
  );
1045
+ $occasions_id = md5( json_encode( $occasions_data ) );
1046
+ unset( $context['_occasionsID'] );
1047
 
1048
  } else {
1049
 
1051
  $occasions_data = $data + $context;
1052
  // error_log(simpleHistory::json_encode($occasions_data));
1053
  // Don't include date in context data
1054
+ unset( $occasions_data['date'] );
1055
 
1056
+ // sf_d($occasions_data);exit;
1057
+ $occasions_id = md5( json_encode( $occasions_data ) );
1058
 
1059
  }
1060
 
1061
+ $data['occasionsID'] = $occasions_id;
1062
 
1063
  // Log event type, defaults to other if not set
1064
  /*
1071
  */
1072
 
1073
  // Log initiator, defaults to current user if exists, or other if not user exist
1074
+ if ( isset( $context['_initiator'] ) ) {
1075
 
1076
  // Manually set in context
1077
+ $data['initiator'] = $context['_initiator'];
1078
+ unset( $context['_initiator'] );
1079
 
1080
  } else {
1081
 
1082
  // No initiator set, try to determine
 
1083
  // Default to other
1084
+ $data['initiator'] = SimpleLoggerLogInitiators::OTHER;
1085
 
1086
  // Check if user is responsible.
1087
+ if ( function_exists( 'wp_get_current_user' ) ) {
1088
 
1089
  $current_user = wp_get_current_user();
1090
 
1091
  if ( isset( $current_user->ID ) && $current_user->ID ) {
1092
 
1093
+ $data['initiator'] = SimpleLoggerLogInitiators::WP_USER;
1094
+ $context['_user_id'] = $current_user->ID;
1095
+ $context['_user_login'] = $current_user->user_login;
1096
+ $context['_user_email'] = $current_user->user_email;
1097
 
1098
  }
 
1099
  }
1100
 
1101
  // If cron then set WordPress as responsible
1102
+ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
1103
 
1104
  // Seems to be wp cron running and doing this
1105
+ $data['initiator'] = SimpleLoggerLogInitiators::WORDPRESS;
1106
+ $context['_wp_cron_running'] = true;
1107
 
1108
  }
1109
 
1110
  // If running as CLI and WP_CLI_PHP_USED is set then it is WP CLI that is doing it
1111
  // How to log this? Is this a user, is it WordPress, or what?
1112
  // I'm thinking:
1113
+ // - it is a user that is manually doing this, on purpose, with intent, so not auto wordpress
1114
+ // - it is a specific user, but we don't know who
1115
  // - sounds like a special case, set initiator to wp_cli
1116
  // Can be used by plugins/themes to check if WP-CLI is running or not
1117
+ if ( defined( 'WP_CLI' ) && WP_CLI ) {
1118
 
1119
+ $data['initiator'] = SimpleLoggerLogInitiators::WP_CLI;
1120
 
1121
  }
1122
+ }// End if().
 
1123
 
1124
  // Detect XML-RPC calls and append to context, if not already there
1125
+ if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && ! isset( $context['_xmlrpc_request'] ) ) {
1126
 
1127
+ $context['_xmlrpc_request'] = true;
1128
 
1129
  }
1130
 
1131
  // Trim message
1132
+ $data['message'] = trim( $data['message'] );
1133
 
1134
  /**
1135
  * Filter data to be saved to db
1138
  *
1139
  * @param array $data
1140
  */
1141
+ $data = apply_filters( 'simple_history/log_insert_data', $data );
1142
 
1143
  // Insert data into db
1144
  // sf_d($db_table, '$db_table');exit;
1145
+ $result = $wpdb->insert( $db_table, $data );
 
1146
 
1147
  $data_parent_row = null;
1148
 
1149
  // Only save context if able to store row
1150
+ if ( false === $result ) {
1151
 
1152
  $history_inserted_id = null;
1153
 
1164
  *
1165
  * @param string $db_table_contexts
1166
  */
1167
+ $db_table_contexts = apply_filters( 'simple_history/logger_db_table_contexts', $db_table_contexts );
1168
 
1169
+ if ( ! is_array( $context ) ) {
1170
  $context = array();
1171
  }
1172
 
1173
  // Append user id to context, if not already added
1174
+ if ( ! isset( $context['_user_id'] ) ) {
1175
 
1176
  // wp_get_current_user is ont available early
1177
  // http://codex.wordpress.org/Function_Reference/wp_get_current_user
1178
  // https://core.trac.wordpress.org/ticket/14024
1179
+ if ( function_exists( 'wp_get_current_user' ) ) {
1180
 
1181
  $current_user = wp_get_current_user();
1182
 
1183
+ if ( isset( $current_user->ID ) && $current_user->ID ) {
1184
+ $context['_user_id'] = $current_user->ID;
1185
+ $context['_user_login'] = $current_user->user_login;
1186
+ $context['_user_email'] = $current_user->user_email;
1187
  }
 
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'];
1196
 
1197
  // If web server is behind a load balancer then the ip address will always be the same
1198
  // See bug report: https://wordpress.org/support/topic/use-x-forwarded-for-http-header-when-logging-remote_addr?replies=1#post-6422981
1200
  // Also note that the header can be faked
1201
  // Ref: http://stackoverflow.com/questions/753645/how-do-i-get-the-correct-ip-from-http-x-forwarded-for-if-it-contains-multiple-ip
1202
  // Ref: http://blackbe.lt/advanced-method-to-obtain-the-client-ip-in-php/
 
1203
  // Check for IP in lots of headers
1204
  // Based on code found here:
1205
  // http://blackbe.lt/advanced-method-to-obtain-the-client-ip-in-php/
1207
 
1208
  foreach ( $ip_keys as $key ) {
1209
 
1210
+ if ( array_key_exists( $key, $_SERVER ) === true ) {
1211
 
1212
  // Loop through all IPs
1213
  $ip_loop_num = 0;
1214
+ foreach ( explode( ',', $_SERVER[ $key ] ) as $ip ) {
1215
 
1216
  // trim for safety measures
1217
+ $ip = trim( $ip );
1218
 
1219
  // attempt to validate IP
1220
+ if ( $this->validate_ip( $ip ) ) {
1221
 
1222
  // valid, add to context, with loop index appended so we can store many IPs
1223
+ $key_lower = strtolower( $key );
1224
+ $context[ "_server_{$key_lower}_{$ip_loop_num}" ] = $ip;
1225
 
1226
  }
1227
 
1228
  $ip_loop_num++;
1229
 
1230
  }
 
1231
  }
 
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
  }
1240
 
 
1241
  /**
1242
  * Filter the context to store for this event/row
1243
  *
1247
  * @param array $data Array with data used for parent row.
1248
  * @param array $this Reference to this logger instance
1249
  */
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
  foreach ( $context as $key => $value ) {
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 ) ) {
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
 
1281
  /**
1282
  * Action that is called after an event has been logged
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;
1307
  'HTTP_X_FORWARDED',
1308
  'HTTP_X_CLUSTER_CLIENT_IP',
1309
  'HTTP_FORWARDED_FOR',
1310
+ 'HTTP_FORWARDED',
1311
  );
1312
 
1313
  return $arr;
1319
  *
1320
  * @since 2.0.29
1321
  */
1322
+ function get_event_ip_number_headers( $row ) {
1323
 
1324
  $ip_keys = $this->get_ip_number_header_keys();
1325
  $arr_found_additional_ip_headers = array();
1327
 
1328
  foreach ( $ip_keys as $one_ip_header_key ) {
1329
 
1330
+ $one_ip_header_key_lower = strtolower( $one_ip_header_key );
1331
 
1332
  foreach ( $context as $context_key => $context_val ) {
1333
 
1334
+ // $key_check_for = "_server_" . strtolower($one_ip_header_key) . "_0";
1335
+ $match = preg_match( "/^_server_{$one_ip_header_key_lower}_[\d+]/", $context_key, $matches );
 
1336
  if ( $match ) {
1337
  $arr_found_additional_ip_headers[ $context_key ] = $context_val;
1338
  }
1339
+ }
1340
+ } // End foreach().
 
 
1341
 
1342
  return $arr_found_additional_ip_headers;
1343
 
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
 
1352
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) === false ) {
1353
  return false;
1354
  }
1355
 
1364
  */
1365
  function adminCSS() {
1366
  /*
1367
+ ?>
1368
+ <style>
1369
+ body {
1370
+ border: 2px solid red;
1371
+ }
1372
+ </style>
1373
+ <?php
1374
+ */
1375
  }
1376
 
1377
  /**
1381
  */
1382
  function adminJS() {
1383
  /*
1384
+ ?>
1385
+ <script>
1386
+ console.log("This is outputed in the footer");
1387
+ </script>
1388
+ <?php
1389
+ */
1390
  }
1391
 
1392
  }
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';
loggers/SimpleMediaLogger.php CHANGED
@@ -5,10 +5,10 @@ defined( 'ABSPATH' ) or die();
5
  /**
6
  * Logs media uploads
7
  */
8
- class SimpleMediaLogger extends SimpleLogger
9
- {
10
 
11
- public $slug = "SimpleMediaLogger";
 
12
 
13
  /**
14
  * Get array with information about this logger
@@ -18,31 +18,31 @@ class SimpleMediaLogger extends SimpleLogger
18
  function getInfo() {
19
 
20
  $arr_info = array(
21
- "name" => "Media/Attachments Logger",
22
- "description" => "Logs media uploads and edits",
23
- "capability" => "edit_pages",
24
- "messages" => array(
25
- 'attachment_created' => __('Created {post_type} "{attachment_title}"', 'simple-history'),
26
- 'attachment_updated' => __('Edited {post_type} "{attachment_title}"', 'simple-history'),
27
- 'attachment_deleted' => __('Deleted {post_type} "{attachment_title}" ("{attachment_filename}")', 'simple-history')
28
  ),
29
- "labels" => array(
30
- "search" => array(
31
- "label" => _x("Media", "Media logger: search", "simple-history"),
32
- "label_all" => _x("All media activity", "Media logger: search", "simple-history"),
33
- "options" => array(
34
- _x("Added media", "Media logger: search", "simple-history") => array(
35
- "attachment_created"
36
  ),
37
- _x("Updated media", "Media logger: search", "simple-history") => array(
38
- "attachment_updated"
39
  ),
40
- _x("Deleted media", "Media logger: search", "simple-history") => array(
41
- "attachment_deleted"
42
  ),
43
- )
44
- ) // end search array
45
- ) // end labels
46
  );
47
 
48
  return $arr_info;
@@ -51,19 +51,19 @@ class SimpleMediaLogger extends SimpleLogger
51
 
52
  public function loaded() {
53
 
54
- add_action("admin_init", array($this, "on_admin_init"));
55
 
56
- add_action("xmlrpc_call_success_mw_newMediaObject", array($this, "on_mw_newMediaObject"), 10, 2);
57
 
58
- add_filter("simple_history/rss_item_link", array($this, "filter_rss_item_link"), 10, 2);
59
 
60
  }
61
 
62
  function on_admin_init() {
63
 
64
- add_action("add_attachment", array($this, "on_add_attachment"));
65
- add_action("edit_attachment", array($this, "on_edit_attachment"));
66
- add_action("delete_attachment", array($this, "on_delete_attachment"));
67
 
68
  }
69
 
@@ -75,7 +75,7 @@ class SimpleMediaLogger extends SimpleLogger
75
  * @param int $id ID of the new attachment.
76
  * @param array $args An array of arguments to add the attachment.
77
  */
78
- function on_mw_newMediaObject($attachment_id, $args) {
79
 
80
  $attachment_post = get_post( $attachment_id );
81
  $filename = esc_html( wp_basename( $attachment_post->guid ) );
@@ -90,12 +90,12 @@ class SimpleMediaLogger extends SimpleLogger
90
  $this->infoMessage(
91
  'attachment_created',
92
  array(
93
- "post_type" => get_post_type( $attachment_post ),
94
- "attachment_id" => $attachment_id,
95
- "attachment_title" => get_the_title( $attachment_post ),
96
- "attachment_filename" => $filename,
97
- "attachment_mime" => $mime,
98
- "attachment_filesize" => $file_size
99
  )
100
  );
101
 
@@ -104,34 +104,34 @@ class SimpleMediaLogger extends SimpleLogger
104
  /**
105
  * Modify plain output to inlcude link to post
106
  */
107
- public function getLogRowPlainTextOutput($row) {
108
 
109
  $message = $row->message;
110
  $context = $row->context;
111
- $message_key = $context["_message_key"];
112
 
113
- $attachment_id = $context["attachment_id"];
114
  $attachment_post = get_post( $attachment_id );
115
- $attachment_is_available = is_a($attachment_post, "WP_Post");
116
 
117
  // Only link to attachment if it is still available
118
  if ( $attachment_is_available ) {
119
 
120
- if ( "attachment_updated" == $message_key ) {
121
 
122
- $message = __('Edited {post_type} <a href="{edit_link}">"{attachment_title}"</a>', "simple-history");
123
 
124
- } else if ( "attachment_created" == $message_key ) {
125
 
126
- $message = __('Uploaded {post_type} <a href="{edit_link}">"{attachment_title}"</a>', "simple-history");
127
 
128
  }
129
 
130
- $context["post_type"] = esc_html( $context["post_type"] );
131
- $context["attachment_filename"] = esc_html( $context["attachment_filename"] );
132
- $context["edit_link"] = get_edit_post_link( $attachment_id );
133
 
134
- $message = $this->interpolate($message, $context, $row);
135
 
136
  } else {
137
 
@@ -159,32 +159,29 @@ class SimpleMediaLogger extends SimpleLogger
159
  $attachment_post = get_post( $attachment_id );
160
  $attachment_is_available = is_a( $attachment_post, 'WP_Post' );
161
 
162
- if ( "attachment_updated" == $message_key ) {
163
 
164
  // Attachment is changed = don't show thumbs and all
165
-
166
- } else if ( "attachment_deleted" == $message_key ) {
167
 
168
  // Attachment is deleted = don't show thumbs and all
169
-
170
- } else if ( "attachment_created" == $message_key ) {
171
 
172
  // Attachment is created/uploaded = show details with image thumbnail
173
-
174
- $attachment_id = $context["attachment_id"];
175
- $filetype = wp_check_filetype( $context["attachment_filename"] );
176
  $file_url = wp_get_attachment_url( $attachment_id );
177
  $edit_link = get_edit_post_link( $attachment_id );
178
  $attached_file = get_attached_file( $attachment_id );
179
- $message = "";
180
  $full_src = false;
181
 
182
  // Is true if attachment is an image. But for example PDFs can have thumbnail images, but they are not considered to be image.
183
  $is_image = wp_attachment_is_image( $attachment_id );
184
 
185
  // $message .= $is_image ? "is images yes" : "is image no";
186
- $is_video = strpos($filetype["type"], "video/") !== false;
187
- $is_audio = strpos($filetype["type"], "audio/") !== false;
188
 
189
  $full_image_width = null;
190
  $full_image_height = null;
@@ -201,26 +198,24 @@ class SimpleMediaLogger extends SimpleLogger
201
  // so we need to check that wp got an resized version
202
  if ( $full_image_width && $full_image_height ) {
203
 
204
- $context["full_image_width"] = $full_image_width;
205
- $context["full_image_height"] = $full_image_height;
206
 
207
  // Only output thumb if file exists
208
  // For example images deleted on file system but not in WP cause broken images (rare case, but has happened to me.)
209
  if ( file_exists( $attached_file ) && $thumb_src ) {
210
- $context["attachment_thumb"] = sprintf('<div class="SimpleHistoryLogitemThumbnail"><img src="%1$s" alt=""></div>', $thumb_src[0] );
211
  }
212
-
213
  }
 
214
 
215
- } else if ( $is_audio ) {
216
-
217
- $content = sprintf('[audio src="%1$s"]', $file_url);
218
- $context["attachment_thumb"] = do_shortcode( $content );
219
 
220
- } else if ( $is_video ) {
221
 
222
- $content = sprintf('[video src="%1$s"]', $file_url);
223
- $context["attachment_thumb"] = do_shortcode( $content );
224
 
225
  } else {
226
 
@@ -231,29 +226,27 @@ class SimpleMediaLogger extends SimpleLogger
231
  wp_get_attachment_image( $attachment_id, array( 350, 500 ), true ) // Placeholder 1.
232
  );
233
  }
 
234
 
235
- }
236
-
237
- $context["attachment_size_format"] = size_format( $row->context["attachment_filesize"] );
238
- $context["attachment_filetype_extension"] = strtoupper( $filetype["ext"] );
239
 
240
- if ( ! empty( $context["attachment_thumb"] ) ) {
241
 
242
  if ( $is_image ) {
243
- $message .= "<a class='SimpleHistoryLogitemThumbnailLink' href='".$edit_link."'>";
244
  }
245
 
246
  $message .= __( '{attachment_thumb}', 'simple-history' );
247
 
248
  if ( $is_image ) {
249
- $message .= "</a>";
250
  }
251
-
252
  }
253
 
254
  $message .= "<p class='SimpleHistoryLogitem--logger-SimpleMediaLogger--attachment-meta'>";
255
- $message .= "<span class='SimpleHistoryLogitem__inlineDivided'>" . __('{attachment_size_format}', "simple-history") . "</span> ";
256
- $message .= "<span class='SimpleHistoryLogitem__inlineDivided'>" . __('{attachment_filetype_extension}', "simple-history") . "</span>";
257
 
258
  if ( $full_image_width && $full_image_height ) {
259
 
@@ -265,7 +258,7 @@ class SimpleMediaLogger extends SimpleLogger
265
 
266
  $output .= $this->interpolate( $message, $context, $row );
267
 
268
- }
269
 
270
  return $output;
271
 
@@ -274,7 +267,7 @@ class SimpleMediaLogger extends SimpleLogger
274
  /**
275
  * Called when an attachment is added
276
  */
277
- function on_add_attachment($attachment_id) {
278
 
279
  $attachment_post = get_post( $attachment_id );
280
  $filename = esc_html( wp_basename( $attachment_post->guid ) );
@@ -289,12 +282,12 @@ class SimpleMediaLogger extends SimpleLogger
289
  $this->infoMessage(
290
  'attachment_created',
291
  array(
292
- "post_type" => get_post_type( $attachment_post ),
293
- "attachment_id" => $attachment_id,
294
- "attachment_title" => get_the_title( $attachment_post ),
295
- "attachment_filename" => $filename,
296
- "attachment_mime" => $mime,
297
- "attachment_filesize" => $file_size
298
  )
299
  );
300
 
@@ -306,7 +299,7 @@ class SimpleMediaLogger extends SimpleLogger
306
  *
307
  * @param int $attachment_id
308
  */
309
- function on_edit_attachment($attachment_id) {
310
 
311
  $attachment_post = get_post( $attachment_id );
312
  $filename = esc_html( wp_basename( $attachment_post->guid ) );
@@ -314,13 +307,13 @@ class SimpleMediaLogger extends SimpleLogger
314
  $file = get_attached_file( $attachment_id );
315
 
316
  $this->infoMessage(
317
- "attachment_updated",
318
  array(
319
- "post_type" => get_post_type( $attachment_post ),
320
- "attachment_id" => $attachment_id,
321
- "attachment_title" => get_the_title( $attachment_post ),
322
- "attachment_filename" => $filename,
323
- "attachment_mime" => $mime
324
  )
325
  );
326
 
@@ -329,7 +322,7 @@ class SimpleMediaLogger extends SimpleLogger
329
  /**
330
  * Called when an attachment is deleted
331
  */
332
- function on_delete_attachment($attachment_id) {
333
 
334
  $attachment_post = get_post( $attachment_id );
335
  $filename = esc_html( wp_basename( $attachment_post->guid ) );
@@ -337,13 +330,13 @@ class SimpleMediaLogger extends SimpleLogger
337
  $file = get_attached_file( $attachment_id );
338
 
339
  $this->infoMessage(
340
- "attachment_deleted",
341
  array(
342
- "post_type" => get_post_type( $attachment_post ),
343
- "attachment_id" => $attachment_id,
344
- "attachment_title" => get_the_title( $attachment_post ),
345
- "attachment_filename" => $filename,
346
- "attachment_mime" => $mime
347
  )
348
  );
349
 
@@ -354,15 +347,15 @@ class SimpleMediaLogger extends SimpleLogger
354
  *
355
  * @since 2.0.23
356
  * @param string $link
357
- * @param array $row
358
  */
359
- public function filter_rss_item_link($link, $row) {
360
 
361
  if ( $row->logger != $this->slug ) {
362
  return $link;
363
  }
364
 
365
- if ( isset( $row->context["attachment_id"] ) ) {
366
 
367
  $permalink = add_query_arg( array(
368
  'action' => 'edit',
@@ -372,7 +365,6 @@ class SimpleMediaLogger extends SimpleLogger
372
  if ( $permalink ) {
373
  $link = $permalink;
374
  }
375
-
376
  }
377
 
378
  return $link;
5
  /**
6
  * Logs media uploads
7
  */
8
+ class SimpleMediaLogger extends SimpleLogger {
 
9
 
10
+
11
+ public $slug = 'SimpleMediaLogger';
12
 
13
  /**
14
  * Get array with information about this logger
18
  function getInfo() {
19
 
20
  $arr_info = array(
21
+ 'name' => 'Media/Attachments Logger',
22
+ 'description' => 'Logs media uploads and edits',
23
+ 'capability' => 'edit_pages',
24
+ 'messages' => array(
25
+ 'attachment_created' => __( 'Created {post_type} "{attachment_title}"', 'simple-history' ),
26
+ 'attachment_updated' => __( 'Edited {post_type} "{attachment_title}"', 'simple-history' ),
27
+ 'attachment_deleted' => __( 'Deleted {post_type} "{attachment_title}" ("{attachment_filename}")', 'simple-history' ),
28
  ),
29
+ 'labels' => array(
30
+ 'search' => array(
31
+ 'label' => _x( 'Media', 'Media logger: search', 'simple-history' ),
32
+ 'label_all' => _x( 'All media activity', 'Media logger: search', 'simple-history' ),
33
+ 'options' => array(
34
+ _x( 'Added media', 'Media logger: search', 'simple-history' ) => array(
35
+ 'attachment_created'
36
  ),
37
+ _x( 'Updated media', 'Media logger: search', 'simple-history' ) => array(
38
+ 'attachment_updated'
39
  ),
40
+ _x( 'Deleted media', 'Media logger: search', 'simple-history' ) => array(
41
+ 'attachment_deleted'
42
  ),
43
+ ),
44
+ ),// end search array
45
+ ),// end labels
46
  );
47
 
48
  return $arr_info;
51
 
52
  public function loaded() {
53
 
54
+ add_action( 'admin_init', array( $this, 'on_admin_init' ) );
55
 
56
+ add_action( 'xmlrpc_call_success_mw_newMediaObject', array( $this, 'on_mw_newMediaObject' ), 10, 2 );
57
 
58
+ add_filter( 'simple_history/rss_item_link', array( $this, 'filter_rss_item_link' ), 10, 2 );
59
 
60
  }
61
 
62
  function on_admin_init() {
63
 
64
+ add_action( 'add_attachment', array( $this, 'on_add_attachment' ) );
65
+ add_action( 'edit_attachment', array( $this, 'on_edit_attachment' ) );
66
+ add_action( 'delete_attachment', array( $this, 'on_delete_attachment' ) );
67
 
68
  }
69
 
75
  * @param int $id ID of the new attachment.
76
  * @param array $args An array of arguments to add the attachment.
77
  */
78
+ function on_mw_newMediaObject( $attachment_id, $args ) {
79
 
80
  $attachment_post = get_post( $attachment_id );
81
  $filename = esc_html( wp_basename( $attachment_post->guid ) );
90
  $this->infoMessage(
91
  'attachment_created',
92
  array(
93
+ 'post_type' => get_post_type( $attachment_post ),
94
+ 'attachment_id' => $attachment_id,
95
+ 'attachment_title' => get_the_title( $attachment_post ),
96
+ 'attachment_filename' => $filename,
97
+ 'attachment_mime' => $mime,
98
+ 'attachment_filesize' => $file_size,
99
  )
100
  );
101
 
104
  /**
105
  * Modify plain output to inlcude link to post
106
  */
107
+ public function getLogRowPlainTextOutput( $row ) {
108
 
109
  $message = $row->message;
110
  $context = $row->context;
111
+ $message_key = $context['_message_key'];
112
 
113
+ $attachment_id = $context['attachment_id'];
114
  $attachment_post = get_post( $attachment_id );
115
+ $attachment_is_available = is_a( $attachment_post, 'WP_Post' );
116
 
117
  // Only link to attachment if it is still available
118
  if ( $attachment_is_available ) {
119
 
120
+ if ( 'attachment_updated' == $message_key ) {
121
 
122
+ $message = __( 'Edited {post_type} <a href="{edit_link}">"{attachment_title}"</a>', 'simple-history' );
123
 
124
+ } elseif ( 'attachment_created' == $message_key ) {
125
 
126
+ $message = __( 'Uploaded {post_type} <a href="{edit_link}">"{attachment_title}"</a>', 'simple-history' );
127
 
128
  }
129
 
130
+ $context['post_type'] = esc_html( $context['post_type'] );
131
+ $context['attachment_filename'] = esc_html( $context['attachment_filename'] );
132
+ $context['edit_link'] = get_edit_post_link( $attachment_id );
133
 
134
+ $message = $this->interpolate( $message, $context, $row );
135
 
136
  } else {
137
 
159
  $attachment_post = get_post( $attachment_id );
160
  $attachment_is_available = is_a( $attachment_post, 'WP_Post' );
161
 
162
+ if ( 'attachment_updated' == $message_key ) {
163
 
164
  // Attachment is changed = don't show thumbs and all
165
+ } elseif ( 'attachment_deleted' == $message_key ) {
 
166
 
167
  // Attachment is deleted = don't show thumbs and all
168
+ } elseif ( 'attachment_created' == $message_key ) {
 
169
 
170
  // Attachment is created/uploaded = show details with image thumbnail
171
+ $attachment_id = $context['attachment_id'];
172
+ $filetype = wp_check_filetype( $context['attachment_filename'] );
 
173
  $file_url = wp_get_attachment_url( $attachment_id );
174
  $edit_link = get_edit_post_link( $attachment_id );
175
  $attached_file = get_attached_file( $attachment_id );
176
+ $message = '';
177
  $full_src = false;
178
 
179
  // Is true if attachment is an image. But for example PDFs can have thumbnail images, but they are not considered to be image.
180
  $is_image = wp_attachment_is_image( $attachment_id );
181
 
182
  // $message .= $is_image ? "is images yes" : "is image no";
183
+ $is_video = strpos( $filetype['type'], 'video/' ) !== false;
184
+ $is_audio = strpos( $filetype['type'], 'audio/' ) !== false;
185
 
186
  $full_image_width = null;
187
  $full_image_height = null;
198
  // so we need to check that wp got an resized version
199
  if ( $full_image_width && $full_image_height ) {
200
 
201
+ $context['full_image_width'] = $full_image_width;
202
+ $context['full_image_height'] = $full_image_height;
203
 
204
  // Only output thumb if file exists
205
  // For example images deleted on file system but not in WP cause broken images (rare case, but has happened to me.)
206
  if ( file_exists( $attached_file ) && $thumb_src ) {
207
+ $context['attachment_thumb'] = sprintf( '<div class="SimpleHistoryLogitemThumbnail"><img src="%1$s" alt=""></div>', $thumb_src[0] );
208
  }
 
209
  }
210
+ } elseif ( $is_audio ) {
211
 
212
+ $content = sprintf( '[audio src="%1$s"]', $file_url );
213
+ $context['attachment_thumb'] = do_shortcode( $content );
 
 
214
 
215
+ } elseif ( $is_video ) {
216
 
217
+ $content = sprintf( '[video src="%1$s"]', $file_url );
218
+ $context['attachment_thumb'] = do_shortcode( $content );
219
 
220
  } else {
221
 
226
  wp_get_attachment_image( $attachment_id, array( 350, 500 ), true ) // Placeholder 1.
227
  );
228
  }
229
+ }// End if().
230
 
231
+ $context['attachment_size_format'] = size_format( $row->context['attachment_filesize'] );
232
+ $context['attachment_filetype_extension'] = strtoupper( $filetype['ext'] );
 
 
233
 
234
+ if ( ! empty( $context['attachment_thumb'] ) ) {
235
 
236
  if ( $is_image ) {
237
+ $message .= "<a class='SimpleHistoryLogitemThumbnailLink' href='" . $edit_link . "'>";
238
  }
239
 
240
  $message .= __( '{attachment_thumb}', 'simple-history' );
241
 
242
  if ( $is_image ) {
243
+ $message .= '</a>';
244
  }
 
245
  }
246
 
247
  $message .= "<p class='SimpleHistoryLogitem--logger-SimpleMediaLogger--attachment-meta'>";
248
+ $message .= "<span class='SimpleHistoryLogitem__inlineDivided'>" . __( '{attachment_size_format}', 'simple-history' ) . '</span> ';
249
+ $message .= "<span class='SimpleHistoryLogitem__inlineDivided'>" . __( '{attachment_filetype_extension}', 'simple-history' ) . '</span>';
250
 
251
  if ( $full_image_width && $full_image_height ) {
252
 
258
 
259
  $output .= $this->interpolate( $message, $context, $row );
260
 
261
+ }// End if().
262
 
263
  return $output;
264
 
267
  /**
268
  * Called when an attachment is added
269
  */
270
+ function on_add_attachment( $attachment_id ) {
271
 
272
  $attachment_post = get_post( $attachment_id );
273
  $filename = esc_html( wp_basename( $attachment_post->guid ) );
282
  $this->infoMessage(
283
  'attachment_created',
284
  array(
285
+ 'post_type' => get_post_type( $attachment_post ),
286
+ 'attachment_id' => $attachment_id,
287
+ 'attachment_title' => get_the_title( $attachment_post ),
288
+ 'attachment_filename' => $filename,
289
+ 'attachment_mime' => $mime,
290
+ 'attachment_filesize' => $file_size,
291
  )
292
  );
293
 
299
  *
300
  * @param int $attachment_id
301
  */
302
+ function on_edit_attachment( $attachment_id ) {
303
 
304
  $attachment_post = get_post( $attachment_id );
305
  $filename = esc_html( wp_basename( $attachment_post->guid ) );
307
  $file = get_attached_file( $attachment_id );
308
 
309
  $this->infoMessage(
310
+ 'attachment_updated',
311
  array(
312
+ 'post_type' => get_post_type( $attachment_post ),
313
+ 'attachment_id' => $attachment_id,
314
+ 'attachment_title' => get_the_title( $attachment_post ),
315
+ 'attachment_filename' => $filename,
316
+ 'attachment_mime' => $mime,
317
  )
318
  );
319
 
322
  /**
323
  * Called when an attachment is deleted
324
  */
325
+ function on_delete_attachment( $attachment_id ) {
326
 
327
  $attachment_post = get_post( $attachment_id );
328
  $filename = esc_html( wp_basename( $attachment_post->guid ) );
330
  $file = get_attached_file( $attachment_id );
331
 
332
  $this->infoMessage(
333
+ 'attachment_deleted',
334
  array(
335
+ 'post_type' => get_post_type( $attachment_post ),
336
+ 'attachment_id' => $attachment_id,
337
+ 'attachment_title' => get_the_title( $attachment_post ),
338
+ 'attachment_filename' => $filename,
339
+ 'attachment_mime' => $mime,
340
  )
341
  );
342
 
347
  *
348
  * @since 2.0.23
349
  * @param string $link
350
+ * @param array $row
351
  */
352
+ public function filter_rss_item_link( $link, $row ) {
353
 
354
  if ( $row->logger != $this->slug ) {
355
  return $link;
356
  }
357
 
358
+ if ( isset( $row->context['attachment_id'] ) ) {
359
 
360
  $permalink = add_query_arg( array(
361
  'action' => 'edit',
365
  if ( $permalink ) {
366
  $link = $permalink;
367
  }
 
368
  }
369
 
370
  return $link;
loggers/SimpleMenuLogger.php CHANGED
@@ -5,50 +5,50 @@ defined( 'ABSPATH' ) or die();
5
  /**
6
  * Logs WordPress menu edits
7
  */
8
- class SimpleMenuLogger extends SimpleLogger
9
- {
10
 
11
  public $slug = __CLASS__;
12
 
13
  /**
14
  * Get array with information about this logger
15
- *
16
  * @return array
17
  */
18
  function getInfo() {
19
 
20
- $arr_info = array(
21
- "name" => "Menu Logger",
22
- "description" => "Logs menu edits",
23
- "capability" => "edit_theme_options",
24
- "messages" => array(
25
- 'created_menu' => __('Created menu "{menu_name}"', "simple-history"),
26
- 'edited_menu' => __('Edited menu "{menu_name}"', "simple-history"),
27
- 'deleted_menu' => __('Deleted menu "{menu_name}"', "simple-history"),
28
- 'edited_menu_item' => __('Edited a menu item', "simple-history"),
29
- 'edited_menu_locations' => __('Updated menu locations', "simple-history"),
30
  ),
31
- "labels" => array(
32
- "search" => array(
33
- "label" => _x("Menus", "Menu logger: search", "simple-history"),
34
- "label_all" => _x("All menu activity", "Menu updates logger: search", "simple-history"),
35
- "options" => array(
36
- _x("Created menus", "Menu updates logger: search", "simple-history") => array(
37
- "created_menu"
 
 
 
 
 
38
  ),
39
- _x("Edited menus", "Menu updates logger: search", "simple-history") => array(
40
- "edited_menu",
41
- "edited_menu_item",
42
- "edited_menu_locations"
43
  ),
44
- _x("Deleted menus", "Menu updates logger: search", "simple-history") => array(
45
- "deleted_menu"
46
- )
47
- )
48
- ) // end search array
49
- ) // end labels
50
  );
51
-
52
  return $arr_info;
53
 
54
  }
@@ -63,8 +63,8 @@ class SimpleMenuLogger extends SimpleLogger
63
  * @param int $term_id ID of the deleted menu.
64
  do_action( 'wp_delete_nav_menu', $menu->term_id );
65
  */
66
- //add_action("wp_delete_nav_menu", array($this, "on_wp_delete_nav_menu"), 10, 1 );
67
- add_action("load-nav-menus.php", array($this, "on_load_nav_menus_page_detect_delete"));
68
 
69
  /*
70
  * Fires after a navigation menu is successfully created.
@@ -75,8 +75,7 @@ class SimpleMenuLogger extends SimpleLogger
75
  * @param array $menu_data An array of menu data.
76
  do_action( 'wp_create_nav_menu', $_menu['term_id'], $menu_data );
77
  */
78
- add_action("wp_create_nav_menu", array($this, "on_wp_create_nav_menu"), 10, 2 );
79
-
80
 
81
  /*
82
  * Fires after a navigation menu item has been updated.
@@ -94,10 +93,9 @@ class SimpleMenuLogger extends SimpleLogger
94
  // This is fired when adding nav items in the editor, not at save, so not
95
  // good to log because user might not end up saving the changes
96
  // add_action("wp_update_nav_menu_item", array($this, "on_wp_update_nav_menu_item"), 10, 3 );
97
-
98
  // Fired before "wp_update_nav_menu" below, to remember menu layput before it's updated
99
  // so we can't detect changes
100
- add_action("load-nav-menus.php", array($this, "on_load_nav_menus_page_detect_update"));
101
 
102
  /*
103
  * Fires after a navigation menu has been successfully updated.
@@ -108,10 +106,9 @@ class SimpleMenuLogger extends SimpleLogger
108
  * @param array $menu_data An array of menu data.
109
  do_action( 'wp_update_nav_menu', $menu_id, $menu_data );
110
  */
111
- //add_action("wp_update_nav_menu", array($this, "on_wp_update_nav_menu"), 10, 2 );
112
-
113
  // Detect meny location change in "manage locations"
114
- add_action("load-nav-menus.php", array($this, "on_load_nav_menus_page_detect_locations_update"));
115
  }
116
 
117
  /**
@@ -119,7 +116,7 @@ class SimpleMenuLogger extends SimpleLogger
119
  * it's fired after menu is deleted, so we don't have the name in this action
120
  */
121
  function on_load_nav_menus_page_detect_delete() {
122
-
123
  /*
124
  http://playground-root.ep/wp-admin/nav-menus.php?menu=22&action=delete&0=http%3A%2F%2Fplayground-root.ep%2Fwp-admin%2F&_wpnonce=f52e8a31ba
125
  $_REQUEST:
@@ -133,27 +130,26 @@ class SimpleMenuLogger extends SimpleLogger
133
  */
134
 
135
  // Check that needed vars are set
136
- if ( ! isset( $_REQUEST["menu"], $_REQUEST["action"] ) ) {
137
  return;
138
  }
139
 
140
- if ( "delete" !== $_REQUEST["action"]) {
141
  return;
142
  }
143
 
144
- $menu_id = $_REQUEST["menu"];
145
- if ( ! is_nav_menu( $menu_id) ) {
146
  return;
147
  }
148
 
149
  $menu = wp_get_nav_menu_object( $menu_id );
150
-
151
 
152
  $this->infoMessage(
153
- "deleted_menu",
154
  array(
155
- "menu_term_id" => $menu_id,
156
- "menu_name" => $menu->name,
157
  )
158
  );
159
 
@@ -178,7 +174,7 @@ class SimpleMenuLogger extends SimpleLogger
178
  }
179
  */
180
 
181
- function on_wp_create_nav_menu($term_id, $menu_data) {
182
 
183
  $menu = wp_get_nav_menu_object( $term_id );
184
 
@@ -187,10 +183,10 @@ class SimpleMenuLogger extends SimpleLogger
187
  }
188
 
189
  $this->infoMessage(
190
- "created_menu",
191
  array(
192
- "term_id" => $term_id,
193
- "menu_name" => $menu->name
194
  )
195
  );
196
 
@@ -198,7 +194,7 @@ class SimpleMenuLogger extends SimpleLogger
198
 
199
  /*
200
  function on_wp_update_nav_menu_item($menu_id, $menu_item_db_id, $args) {
201
-
202
  $this->infoMessage(
203
  "edited_menu_item",
204
  array(
@@ -241,57 +237,56 @@ class SimpleMenuLogger extends SimpleLogger
241
  */
242
 
243
  // Check that needed vars are set
244
- if ( ! isset( $_REQUEST["menu"], $_REQUEST["action"], $_REQUEST["menu-name"] ) ) {
245
  return;
246
  }
247
 
248
  // Only go on for update action
249
- if ( "update" !== $_REQUEST["action"]) {
250
  return;
251
  }
252
 
253
  // Make sure we got the id of a menu
254
- $menu_id = $_REQUEST["menu"];
255
- if ( ! is_nav_menu( $menu_id) ) {
256
  return;
257
  }
258
-
259
  // Get saved menu. May be empty if this is the first time we save the menu
260
  $arr_prev_menu_items = wp_get_nav_menu_items( $menu_id );
261
 
262
  // Compare new items to be saved with old version
263
- $old_ids = wp_list_pluck( $arr_prev_menu_items, "db_id" );
264
- $new_ids = array_values( isset( $_POST["menu-item-db-id"] ) ? $_POST["menu-item-db-id"] : array() );
265
-
266
  // Get ids of added and removed post ids
267
- $arr_removed = array_diff($old_ids, $new_ids);
268
- $arr_added = array_diff($new_ids, $old_ids);
269
 
270
  // Get old version location
271
  // $prev_menu = wp_get_nav_menu_object( $menu_id );
272
  // $locations = get_registered_nav_menus();
273
  // $menu_locations = get_nav_menu_locations();
274
-
275
  $this->infoMessage(
276
- "edited_menu",
277
  array(
278
- "menu_id" => $menu_id,
279
- "menu_name" => $_POST["menu-name"],
280
- "menu_items_added" => sizeof($arr_added),
281
- "menu_items_removed" => sizeof($arr_removed),
282
- //"request" => $this->simpleHistory->json_encode($_REQUEST)
283
  )
284
  );
285
 
286
  }
287
 
288
- /**
289
  * This seems to get called twice
290
  * one time with menu_data, a second without
291
  */
292
  /*
293
  function on_wp_update_nav_menu($menu_id, $menu_data = array()) {
294
-
295
  if (empty($menu_data)) {
296
  return;
297
  }
@@ -312,37 +307,35 @@ class SimpleMenuLogger extends SimpleLogger
312
  /**
313
  * Get detailed output
314
  */
315
- function getLogRowDetailsOutput($row) {
316
-
317
  $context = $row->context;
318
- $message_key = $context["_message_key"];
319
- $output = "";
320
 
321
- if ( "edited_menu" == $message_key ) {
322
 
323
- if ( ! empty( $context["menu_items_added"] ) || ! empty( $context["menu_items_removed"] ) ) {
324
 
325
- $output .= "<p>";
326
 
327
  $output .= '<span class="SimpleHistoryLogitem__inlineDivided">';
328
  $output .= sprintf(
329
- _nx( '%1$s menu item added', '%1$s menu items added', $context["menu_items_added"], "menu logger", "simple-history" ),
330
- esc_attr( $context["menu_items_added"] )
331
  );
332
  $output .= '</span> ';
333
 
334
  $output .= '<span class="SimpleHistoryLogitem__inlineDivided">';
335
  $output .= sprintf(
336
- _nx( '%1$s menu item removed', '%1$s menu items removed', $context["menu_items_removed"], "menu logger", "simple-history" ),
337
- esc_attr( $context["menu_items_removed"] )
338
  );
339
  $output .= '</span> ';
340
 
341
- $output .= "</p>";
342
 
343
  }
344
-
345
-
346
  }
347
 
348
  return $output;
@@ -352,14 +345,14 @@ class SimpleMenuLogger extends SimpleLogger
352
  /**
353
  * Log updates to theme menu locations
354
  */
355
- function on_load_nav_menus_page_detect_locations_update() {
356
 
357
  // Check that needed vars are set
358
- if ( ! isset( $_REQUEST["menu"], $_REQUEST["action"] ) ) {
359
  return;
360
  }
361
 
362
- if ( "locations" !== $_REQUEST["action"]) {
363
  return;
364
  }
365
 
@@ -372,12 +365,12 @@ class SimpleMenuLogger extends SimpleLogger
372
  )
373
  )
374
  */
375
- $menu_locations = $_POST["menu-locations"];
376
 
377
  $this->infoMessage(
378
- "edited_menu_locations",
379
  array(
380
- "menu_locations" => $this->simpleHistory->json_encode($menu_locations)
381
  )
382
  );
383
 
5
  /**
6
  * Logs WordPress menu edits
7
  */
8
+ class SimpleMenuLogger extends SimpleLogger {
9
+
10
 
11
  public $slug = __CLASS__;
12
 
13
  /**
14
  * Get array with information about this logger
15
+ *
16
  * @return array
17
  */
18
  function getInfo() {
19
 
20
+ $arr_info = array(
21
+ 'name' => 'Menu Logger',
22
+ 'description' => 'Logs menu edits',
23
+ 'capability' => 'edit_theme_options',
24
+ 'messages' => array(
25
+ 'created_menu' => __( 'Created menu "{menu_name}"', 'simple-history' ),
26
+ 'edited_menu' => __( 'Edited menu "{menu_name}"', 'simple-history' ),
27
+ 'deleted_menu' => __( 'Deleted menu "{menu_name}"', 'simple-history' ),
28
+ 'edited_menu_item' => __( 'Edited a menu item', 'simple-history' ),
29
+ 'edited_menu_locations' => __( 'Updated menu locations', 'simple-history' ),
30
  ),
31
+ 'labels' => array(
32
+ 'search' => array(
33
+ 'label' => _x( 'Menus', 'Menu logger: search', 'simple-history' ),
34
+ 'label_all' => _x( 'All menu activity', 'Menu updates logger: search', 'simple-history' ),
35
+ 'options' => array(
36
+ _x( 'Created menus', 'Menu updates logger: search', 'simple-history' ) => array(
37
+ 'created_menu'
38
+ ),
39
+ _x( 'Edited menus', 'Menu updates logger: search', 'simple-history' ) => array(
40
+ 'edited_menu',
41
+ 'edited_menu_item',
42
+ 'edited_menu_locations',
43
  ),
44
+ _x( 'Deleted menus', 'Menu updates logger: search', 'simple-history' ) => array(
45
+ 'deleted_menu'
 
 
46
  ),
47
+ ),
48
+ ),// end search array
49
+ ),// end labels
 
 
 
50
  );
51
+
52
  return $arr_info;
53
 
54
  }
63
  * @param int $term_id ID of the deleted menu.
64
  do_action( 'wp_delete_nav_menu', $menu->term_id );
65
  */
66
+ // add_action("wp_delete_nav_menu", array($this, "on_wp_delete_nav_menu"), 10, 1 );
67
+ add_action( 'load-nav-menus.php', array( $this, 'on_load_nav_menus_page_detect_delete' ) );
68
 
69
  /*
70
  * Fires after a navigation menu is successfully created.
75
  * @param array $menu_data An array of menu data.
76
  do_action( 'wp_create_nav_menu', $_menu['term_id'], $menu_data );
77
  */
78
+ add_action( 'wp_create_nav_menu', array( $this, 'on_wp_create_nav_menu' ), 10, 2 );
 
79
 
80
  /*
81
  * Fires after a navigation menu item has been updated.
93
  // This is fired when adding nav items in the editor, not at save, so not
94
  // good to log because user might not end up saving the changes
95
  // add_action("wp_update_nav_menu_item", array($this, "on_wp_update_nav_menu_item"), 10, 3 );
 
96
  // Fired before "wp_update_nav_menu" below, to remember menu layput before it's updated
97
  // so we can't detect changes
98
+ add_action( 'load-nav-menus.php', array( $this, 'on_load_nav_menus_page_detect_update' ) );
99
 
100
  /*
101
  * Fires after a navigation menu has been successfully updated.
106
  * @param array $menu_data An array of menu data.
107
  do_action( 'wp_update_nav_menu', $menu_id, $menu_data );
108
  */
109
+ // add_action("wp_update_nav_menu", array($this, "on_wp_update_nav_menu"), 10, 2 );
 
110
  // Detect meny location change in "manage locations"
111
+ add_action( 'load-nav-menus.php', array( $this, 'on_load_nav_menus_page_detect_locations_update' ) );
112
  }
113
 
114
  /**
116
  * it's fired after menu is deleted, so we don't have the name in this action
117
  */
118
  function on_load_nav_menus_page_detect_delete() {
119
+
120
  /*
121
  http://playground-root.ep/wp-admin/nav-menus.php?menu=22&action=delete&0=http%3A%2F%2Fplayground-root.ep%2Fwp-admin%2F&_wpnonce=f52e8a31ba
122
  $_REQUEST:
130
  */
131
 
132
  // Check that needed vars are set
133
+ if ( ! isset( $_REQUEST['menu'], $_REQUEST['action'] ) ) {
134
  return;
135
  }
136
 
137
+ if ( 'delete' !== $_REQUEST['action'] ) {
138
  return;
139
  }
140
 
141
+ $menu_id = $_REQUEST['menu'];
142
+ if ( ! is_nav_menu( $menu_id ) ) {
143
  return;
144
  }
145
 
146
  $menu = wp_get_nav_menu_object( $menu_id );
 
147
 
148
  $this->infoMessage(
149
+ 'deleted_menu',
150
  array(
151
+ 'menu_term_id' => $menu_id,
152
+ 'menu_name' => $menu->name,
153
  )
154
  );
155
 
174
  }
175
  */
176
 
177
+ function on_wp_create_nav_menu( $term_id, $menu_data ) {
178
 
179
  $menu = wp_get_nav_menu_object( $term_id );
180
 
183
  }
184
 
185
  $this->infoMessage(
186
+ 'created_menu',
187
  array(
188
+ 'term_id' => $term_id,
189
+ 'menu_name' => $menu->name,
190
  )
191
  );
192
 
194
 
195
  /*
196
  function on_wp_update_nav_menu_item($menu_id, $menu_item_db_id, $args) {
197
+
198
  $this->infoMessage(
199
  "edited_menu_item",
200
  array(
237
  */
238
 
239
  // Check that needed vars are set
240
+ if ( ! isset( $_REQUEST['menu'], $_REQUEST['action'], $_REQUEST['menu-name'] ) ) {
241
  return;
242
  }
243
 
244
  // Only go on for update action
245
+ if ( 'update' !== $_REQUEST['action'] ) {
246
  return;
247
  }
248
 
249
  // Make sure we got the id of a menu
250
+ $menu_id = $_REQUEST['menu'];
251
+ if ( ! is_nav_menu( $menu_id ) ) {
252
  return;
253
  }
254
+
255
  // Get saved menu. May be empty if this is the first time we save the menu
256
  $arr_prev_menu_items = wp_get_nav_menu_items( $menu_id );
257
 
258
  // Compare new items to be saved with old version
259
+ $old_ids = wp_list_pluck( $arr_prev_menu_items, 'db_id' );
260
+ $new_ids = array_values( isset( $_POST['menu-item-db-id'] ) ? $_POST['menu-item-db-id'] : array() );
261
+
262
  // Get ids of added and removed post ids
263
+ $arr_removed = array_diff( $old_ids, $new_ids );
264
+ $arr_added = array_diff( $new_ids, $old_ids );
265
 
266
  // Get old version location
267
  // $prev_menu = wp_get_nav_menu_object( $menu_id );
268
  // $locations = get_registered_nav_menus();
269
  // $menu_locations = get_nav_menu_locations();
 
270
  $this->infoMessage(
271
+ 'edited_menu',
272
  array(
273
+ 'menu_id' => $menu_id,
274
+ 'menu_name' => $_POST['menu-name'],
275
+ 'menu_items_added' => sizeof( $arr_added ),
276
+ 'menu_items_removed' => sizeof( $arr_removed ),
277
+ // "request" => $this->simpleHistory->json_encode($_REQUEST)
278
  )
279
  );
280
 
281
  }
282
 
283
+ /**
284
  * This seems to get called twice
285
  * one time with menu_data, a second without
286
  */
287
  /*
288
  function on_wp_update_nav_menu($menu_id, $menu_data = array()) {
289
+
290
  if (empty($menu_data)) {
291
  return;
292
  }
307
  /**
308
  * Get detailed output
309
  */
310
+ function getLogRowDetailsOutput( $row ) {
311
+
312
  $context = $row->context;
313
+ $message_key = $context['_message_key'];
314
+ $output = '';
315
 
316
+ if ( 'edited_menu' == $message_key ) {
317
 
318
+ if ( ! empty( $context['menu_items_added'] ) || ! empty( $context['menu_items_removed'] ) ) {
319
 
320
+ $output .= '<p>';
321
 
322
  $output .= '<span class="SimpleHistoryLogitem__inlineDivided">';
323
  $output .= sprintf(
324
+ _nx( '%1$s menu item added', '%1$s menu items added', $context['menu_items_added'], 'menu logger', 'simple-history' ),
325
+ esc_attr( $context['menu_items_added'] )
326
  );
327
  $output .= '</span> ';
328
 
329
  $output .= '<span class="SimpleHistoryLogitem__inlineDivided">';
330
  $output .= sprintf(
331
+ _nx( '%1$s menu item removed', '%1$s menu items removed', $context['menu_items_removed'], 'menu logger', 'simple-history' ),
332
+ esc_attr( $context['menu_items_removed'] )
333
  );
334
  $output .= '</span> ';
335
 
336
+ $output .= '</p>';
337
 
338
  }
 
 
339
  }
340
 
341
  return $output;
345
  /**
346
  * Log updates to theme menu locations
347
  */
348
+ function on_load_nav_menus_page_detect_locations_update() {
349
 
350
  // Check that needed vars are set
351
+ if ( ! isset( $_REQUEST['menu'], $_REQUEST['action'] ) ) {
352
  return;
353
  }
354
 
355
+ if ( 'locations' !== $_REQUEST['action'] ) {
356
  return;
357
  }
358
 
365
  )
366
  )
367
  */
368
+ $menu_locations = $_POST['menu-locations'];
369
 
370
  $this->infoMessage(
371
+ 'edited_menu_locations',
372
  array(
373
+ 'menu_locations' => $this->simpleHistory->json_encode( $menu_locations ),
374
  )
375
  );
376
 
loggers/SimpleOptionsLogger.php CHANGED
@@ -5,8 +5,8 @@ defined( 'ABSPATH' ) or die();
5
  /**
6
  * Logs changes to wordpress options
7
  */
8
- class SimpleOptionsLogger extends SimpleLogger
9
- {
10
 
11
  public $slug = __CLASS__;
12
 
@@ -18,14 +18,13 @@ class SimpleOptionsLogger extends SimpleLogger
18
  function getInfo() {
19
 
20
  $arr_info = array(
21
- "name" => "Options Logger",
22
- "description" => "Logs updates to WordPress settings",
23
- "capability" => "manage_options",
24
- "messages" => array(
25
- //'option_updated' => __('Updated option "{option}" on settings page "{option_page}"', "simple-history"),
26
- 'option_updated' => __('Updated option "{option}"', "simple-history"),
27
  /*
28
-
29
  Updated option "default_comment_status" on settings page "discussion"
30
  Edited option "default_comment_status" on settings page "discussion"
31
  Modified option "default_comment_status" on settings page "discussion"
@@ -34,16 +33,16 @@ class SimpleOptionsLogger extends SimpleLogger
34
 
35
  */
36
  ),
37
- "labels" => array(
38
- "search" => array(
39
- "label" => _x("Options", "Options logger: search", "simple-history"),
40
- "options" => array(
41
- _x("Changed options", "Options logger: search", "simple-history") => array(
42
- "option_updated"
43
  ),
44
- )
45
- ) // end search array
46
- ) // end labels
47
  );
48
 
49
  return $arr_info;
@@ -52,29 +51,29 @@ class SimpleOptionsLogger extends SimpleLogger
52
 
53
  function loaded() {
54
 
55
- add_action( 'updated_option', array($this, "on_updated_option"), 10, 3 );
56
 
57
  }
58
 
59
  function on_updated_option( $option, $old_value, $new_value ) {
60
 
61
- if ( empty( $_SERVER["REQUEST_URI"] ) ) {
62
  return;
63
  }
64
 
65
  $arr_option_pages = array(
66
- 0 => "options.php",
67
- 1 => "options-permalink.php"
68
  );
69
 
70
  // We only want to log options being added via pages in $arr_option_pages
71
- if ( ! in_array( basename( $_SERVER["REQUEST_URI"] ), $arr_option_pages ) || basename( dirname( $_SERVER["REQUEST_URI"] ) ) !== "wp-admin" ) {
72
  return;
73
  }
74
 
75
  // Also only if "option_page" is set to one of these "built in" ones
76
  // We don't wanna start loging things from other plugins, like EDD
77
- $option_page = isset( $_REQUEST["option_page"] ) ? $_REQUEST["option_page"] : ""; // general | discussion | ...
78
 
79
  $arr_valid_option_pages = array(
80
  'general',
@@ -87,9 +86,9 @@ class SimpleOptionsLogger extends SimpleLogger
87
  $is_valid_options_page = $option_page && in_array( $option_page, $arr_valid_option_pages );
88
 
89
  // Permalink settings page does not post any "option_page", so use http referer instead
90
- if ( strpos( $_SERVER["REQUEST_URI"], "options-permalink.php" ) !== false ) {
91
  $is_valid_options_page = true;
92
- $options_page = "permalink";
93
  }
94
 
95
  if ( ! $is_valid_options_page ) {
@@ -99,7 +98,7 @@ class SimpleOptionsLogger extends SimpleLogger
99
  // Check if option name is ok
100
  // For example if you change front page displays setting the "rewrite_rules" options gets updated too
101
  $arr_invalid_option_names = array(
102
- "rewrite_rules"
103
  );
104
 
105
  if ( in_array( $option, $arr_invalid_option_names ) ) {
@@ -111,9 +110,9 @@ class SimpleOptionsLogger extends SimpleLogger
111
  'old_value' => $old_value,
112
  'new_value' => $new_value,
113
  'option_page' => $option_page,
114
- #'referer' => wp_get_referer(),
115
- #'REQUEST_URI' => $_SERVER['REQUEST_URI'],
116
- #'$_REQUEST' => print_r($_REQUEST, true),
117
  );
118
 
119
  // Store a bit more about some options
@@ -137,12 +136,12 @@ class SimpleOptionsLogger extends SimpleLogger
137
 
138
  $message = $row->message;
139
  $context = $row->context;
140
- $message_key = $context["_message_key"];
141
 
142
- $return_message = "";
143
 
144
  // Only link to attachment if it is still available
145
- if ( "option_updated" == $message_key ) {
146
 
147
  /*
148
  $option = isset( $context["option"] ) ? $context["option"] : null;
@@ -187,16 +186,16 @@ class SimpleOptionsLogger extends SimpleLogger
187
  /**
188
  * Get detailed output
189
  */
190
- function getLogRowDetailsOutput($row) {
191
 
192
  $context = $row->context;
193
- $message_key = $context["_message_key"];
194
- $output = "";
195
 
196
- $option = isset( $context["option"] ) ? $context["option"] : null;
197
- $option_page = isset( $context["option_page"] ) ? $context["option_page"] : null;
198
- $new_value = isset( $context["new_value"] ) ? $context["new_value"] : null;
199
- $old_value = isset( $context["old_value"] ) ? $context["old_value"] : null;
200
 
201
  $tmpl_row = '
202
  <tr>
@@ -205,15 +204,15 @@ class SimpleOptionsLogger extends SimpleLogger
205
  </tr>
206
  ';
207
 
208
- if ( "option_updated" == $message_key ) {
209
 
210
- //$message = 'Old value was {old_value} and new value is {new_value}';
211
  $output .= "<table class='SimpleHistoryLogitem__keyValueTable'>";
212
 
213
  // Output old and new values
214
- if ( $context["new_value"] || $context["old_value"] ) {
215
 
216
- $option_custom_output = "";
217
  $methodname = "get_details_output_for_option_{$option}";
218
 
219
  if ( method_exists( $this, $methodname ) ) {
@@ -239,26 +238,22 @@ class SimpleOptionsLogger extends SimpleLogger
239
 
240
  $output .= sprintf(
241
  $tmpl_row,
242
- __("New value", "simple-history"),
243
  esc_html( $trimmed_new_value )
244
  );
245
 
246
  $output .= sprintf(
247
  $tmpl_row,
248
- __("Old value", "simple-history"),
249
  esc_html( $trimmed_old_value )
250
  );
251
 
252
-
253
  } else {
254
 
255
  $output .= $option_custom_output;
256
 
257
- } // if option output
258
-
259
-
260
- } // if new or old val
261
-
262
 
263
  // If key option_page this was saved from regular settings pages
264
  if ( ! empty( $option_page ) ) {
@@ -270,15 +265,15 @@ class SimpleOptionsLogger extends SimpleLogger
270
  <td><a href="%3$s">%2$s</a></td>
271
  </tr>
272
  ',
273
- __("Settings page", "simple-history"),
274
- esc_html( $context["option_page"] ),
275
- admin_url("options-{$option_page}.php")
276
  );
277
 
278
  }
279
 
280
  // If option = permalink_structure then we did it from permalink page
281
- if ( ! empty( $option ) && ( "permalink_structure" == $option || "tag_base" == $option || "category_base" == $option ) ) {
282
 
283
  $output .= sprintf(
284
  '
@@ -287,16 +282,16 @@ class SimpleOptionsLogger extends SimpleLogger
287
  <td><a href="%3$s">%2$s</a></td>
288
  </tr>
289
  ',
290
- __("Settings page", "simple-history"),
291
- "permalink",
292
- admin_url("options-permalink.php")
293
  );
294
 
295
  }
296
 
297
- $output .= "</table>";
298
 
299
- }
300
 
301
  return $output;
302
 
@@ -315,9 +310,8 @@ class SimpleOptionsLogger extends SimpleLogger
315
  $old_post = get_post( $old_value );
316
 
317
  if ( $old_post ) {
318
- $context["old_post_title"] = $old_post->post_title;
319
  }
320
-
321
  }
322
 
323
  if ( ! empty( $new_value ) && is_numeric( $new_value ) ) {
@@ -325,9 +319,8 @@ class SimpleOptionsLogger extends SimpleLogger
325
  $new_post = get_post( $new_value );
326
 
327
  if ( $new_post ) {
328
- $context["new_post_title"] = $new_post->post_title;
329
  }
330
-
331
  }
332
 
333
  return $context;
@@ -337,7 +330,7 @@ class SimpleOptionsLogger extends SimpleLogger
337
  function add_context_for_option_page_for_posts( $context, $old_value, $new_value, $option, $option_page ) {
338
 
339
  // Get same info as for page_on_front
340
- $context = call_user_func_array( array( $this, "add_context_for_option_page_on_front"), func_get_args() );
341
 
342
  return $context;
343
 
@@ -345,71 +338,71 @@ class SimpleOptionsLogger extends SimpleLogger
345
 
346
  function get_details_output_for_option_page_for_posts( $context, $old_value, $new_value, $option, $option_page ) {
347
 
348
- $output = call_user_func_array( array( $this, "get_details_output_for_option_page_on_front"), func_get_args() );
349
 
350
  return $output;
351
 
352
  }
353
 
354
  /**
355
- * Add detailed putput for page_on_front
356
  *
357
  * @return string output
358
  */
359
  function get_details_output_for_option_page_on_front( $context, $old_value, $new_value, $option, $option_page, $tmpl_row ) {
360
 
361
- $output = "";
362
 
363
- if ( $new_value && ! empty( $context["new_post_title"] ) ) {
364
 
365
- $post_title_with_link = "";
366
 
367
  if ( get_post_status( $new_value ) ) {
368
- $post_title_with_link = sprintf('<a href="%1$s">%2$s</a>', get_edit_post_link( $new_value ), esc_html( $context["new_post_title"] ) );
369
  } else {
370
- $post_title_with_link = esc_html( $context["new_post_title"] );
371
  }
372
 
373
  $output .= sprintf(
374
  $tmpl_row,
375
- __("New value", "simple-history"),
376
- sprintf( __('Page %1$s', "simple-history" ), $post_title_with_link)
377
  );
378
 
379
  }
380
- if ( intval( $new_value ) == 0 ) {
381
 
382
  $output .= sprintf(
383
  $tmpl_row,
384
- __("New value", "simple-history"),
385
- __("Your latests posts", "simple-history")
386
  );
387
 
388
  }
389
 
390
- if ( $old_value && ! empty( $context["old_post_title"] ) ) {
391
- $post_title_with_link = "";
392
 
393
  if ( get_post_status( $old_value ) ) {
394
- $post_title_with_link = sprintf('<a href="%1$s">%2$s</a>', get_edit_post_link( $old_value ), esc_html( $context["old_post_title"] ) );
395
  } else {
396
- $post_title_with_link = esc_html( $context["old_post_title"] );
397
  }
398
 
399
  $output .= sprintf(
400
  $tmpl_row,
401
- __("Old value", "simple-history"),
402
- sprintf( __('Page %1$s', "simple-history" ), $post_title_with_link)
403
  );
404
 
405
  }
406
 
407
- if ( intval( $old_value ) == 0 ) {
408
 
409
  $output .= sprintf(
410
  $tmpl_row,
411
- __("Old value", "simple-history"),
412
- __("Your latests posts", "simple-history")
413
  );
414
 
415
  }
@@ -428,24 +421,22 @@ class SimpleOptionsLogger extends SimpleLogger
428
 
429
  $old_category_name = get_the_category_by_ID( $old_value );
430
 
431
- if ( ! is_wp_error( $old_category_name) ) {
432
 
433
- $context["old_category_name"] = $old_category_name;
434
 
435
  }
436
-
437
  }
438
 
439
  if ( ! empty( $new_value ) && is_numeric( $new_value ) ) {
440
 
441
  $new_category_name = get_the_category_by_ID( $new_value );
442
 
443
- if ( ! is_wp_error( $new_category_name) ) {
444
 
445
- $context["new_category_name"] = $new_category_name;
446
 
447
  }
448
-
449
  }
450
 
451
  return $context;
@@ -454,7 +445,7 @@ class SimpleOptionsLogger extends SimpleLogger
454
 
455
  function add_context_for_option_default_email_category( $context, $old_value, $new_value, $option, $option_page ) {
456
 
457
- $context = call_user_func_array( array( $this, "add_context_for_option_default_category"), func_get_args() );
458
 
459
  return $context;
460
 
@@ -462,20 +453,21 @@ class SimpleOptionsLogger extends SimpleLogger
462
 
463
 
464
  /**
465
- * Add detailed putput for default_category
466
  *
467
  * @return string output
468
  */
469
  function get_details_output_for_option_default_category( $context, $old_value, $new_value, $option, $option_page, $tmpl_row ) {
470
 
471
- $old_category_name = isset( $context["old_category_name"] ) ? $context["old_category_name"] : null;
472
- $new_category_name = isset( $context["new_category_name"] ) ? $context["new_category_name"] : null;
 
473
 
474
  if ( $old_category_name ) {
475
 
476
  $output .= sprintf(
477
  $tmpl_row,
478
- __("Old value", "simple-history"),
479
  esc_html( $old_category_name )
480
  );
481
 
@@ -485,7 +477,7 @@ class SimpleOptionsLogger extends SimpleLogger
485
 
486
  $output .= sprintf(
487
  $tmpl_row,
488
- __("New value", "simple-history"),
489
  esc_html( $new_category_name )
490
  );
491
 
@@ -497,7 +489,7 @@ class SimpleOptionsLogger extends SimpleLogger
497
 
498
  function get_details_output_for_option_default_email_category( $context, $old_value, $new_value, $option, $option_page, $tmpl_row ) {
499
 
500
- $output = call_user_func_array( array( $this, "get_details_output_for_option_default_category"), func_get_args() );
501
 
502
  return $output;
503
 
5
  /**
6
  * Logs changes to wordpress options
7
  */
8
+ class SimpleOptionsLogger extends SimpleLogger {
9
+
10
 
11
  public $slug = __CLASS__;
12
 
18
  function getInfo() {
19
 
20
  $arr_info = array(
21
+ 'name' => 'Options Logger',
22
+ 'description' => 'Logs updates to WordPress settings',
23
+ 'capability' => 'manage_options',
24
+ 'messages' => array(
25
+ // 'option_updated' => __('Updated option "{option}" on settings page "{option_page}"', "simple-history"),
26
+ 'option_updated' => __( 'Updated option "{option}"', 'simple-history' ),
27
  /*
 
28
  Updated option "default_comment_status" on settings page "discussion"
29
  Edited option "default_comment_status" on settings page "discussion"
30
  Modified option "default_comment_status" on settings page "discussion"
33
 
34
  */
35
  ),
36
+ 'labels' => array(
37
+ 'search' => array(
38
+ 'label' => _x( 'Options', 'Options logger: search', 'simple-history' ),
39
+ 'options' => array(
40
+ _x( 'Changed options', 'Options logger: search', 'simple-history' ) => array(
41
+ 'option_updated'
42
  ),
43
+ ),
44
+ ),// end search array
45
+ ),// end labels
46
  );
47
 
48
  return $arr_info;
51
 
52
  function loaded() {
53
 
54
+ add_action( 'updated_option', array( $this, 'on_updated_option' ), 10, 3 );
55
 
56
  }
57
 
58
  function on_updated_option( $option, $old_value, $new_value ) {
59
 
60
+ if ( empty( $_SERVER['REQUEST_URI'] ) ) {
61
  return;
62
  }
63
 
64
  $arr_option_pages = array(
65
+ 0 => 'options.php',
66
+ 1 => 'options-permalink.php',
67
  );
68
 
69
  // We only want to log options being added via pages in $arr_option_pages
70
+ if ( ! in_array( basename( $_SERVER['REQUEST_URI'] ), $arr_option_pages ) || basename( dirname( $_SERVER['REQUEST_URI'] ) ) !== 'wp-admin' ) {
71
  return;
72
  }
73
 
74
  // Also only if "option_page" is set to one of these "built in" ones
75
  // We don't wanna start loging things from other plugins, like EDD
76
+ $option_page = isset( $_REQUEST['option_page'] ) ? $_REQUEST['option_page'] : ''; // general | discussion | ...
77
 
78
  $arr_valid_option_pages = array(
79
  'general',
86
  $is_valid_options_page = $option_page && in_array( $option_page, $arr_valid_option_pages );
87
 
88
  // Permalink settings page does not post any "option_page", so use http referer instead
89
+ if ( strpos( $_SERVER['REQUEST_URI'], 'options-permalink.php' ) !== false ) {
90
  $is_valid_options_page = true;
91
+ $options_page = 'permalink';
92
  }
93
 
94
  if ( ! $is_valid_options_page ) {
98
  // Check if option name is ok
99
  // For example if you change front page displays setting the "rewrite_rules" options gets updated too
100
  $arr_invalid_option_names = array(
101
+ 'rewrite_rules'
102
  );
103
 
104
  if ( in_array( $option, $arr_invalid_option_names ) ) {
110
  'old_value' => $old_value,
111
  'new_value' => $new_value,
112
  'option_page' => $option_page,
113
+ // 'referer' => wp_get_referer(),
114
+ // 'REQUEST_URI' => $_SERVER['REQUEST_URI'],
115
+ // '$_REQUEST' => print_r($_REQUEST, true),
116
  );
117
 
118
  // Store a bit more about some options
136
 
137
  $message = $row->message;
138
  $context = $row->context;
139
+ $message_key = $context['_message_key'];
140
 
141
+ $return_message = '';
142
 
143
  // Only link to attachment if it is still available
144
+ if ( 'option_updated' == $message_key ) {
145
 
146
  /*
147
  $option = isset( $context["option"] ) ? $context["option"] : null;
186
  /**
187
  * Get detailed output
188
  */
189
+ function getLogRowDetailsOutput( $row ) {
190
 
191
  $context = $row->context;
192
+ $message_key = $context['_message_key'];
193
+ $output = '';
194
 
195
+ $option = isset( $context['option'] ) ? $context['option'] : null;
196
+ $option_page = isset( $context['option_page'] ) ? $context['option_page'] : null;
197
+ $new_value = isset( $context['new_value'] ) ? $context['new_value'] : null;
198
+ $old_value = isset( $context['old_value'] ) ? $context['old_value'] : null;
199
 
200
  $tmpl_row = '
201
  <tr>
204
  </tr>
205
  ';
206
 
207
+ if ( 'option_updated' == $message_key ) {
208
 
209
+ // $message = 'Old value was {old_value} and new value is {new_value}';
210
  $output .= "<table class='SimpleHistoryLogitem__keyValueTable'>";
211
 
212
  // Output old and new values
213
+ if ( $context['new_value'] || $context['old_value'] ) {
214
 
215
+ $option_custom_output = '';
216
  $methodname = "get_details_output_for_option_{$option}";
217
 
218
  if ( method_exists( $this, $methodname ) ) {
238
 
239
  $output .= sprintf(
240
  $tmpl_row,
241
+ __( 'New value', 'simple-history' ),
242
  esc_html( $trimmed_new_value )
243
  );
244
 
245
  $output .= sprintf(
246
  $tmpl_row,
247
+ __( 'Old value', 'simple-history' ),
248
  esc_html( $trimmed_old_value )
249
  );
250
 
 
251
  } else {
252
 
253
  $output .= $option_custom_output;
254
 
255
+ }
256
+ } // End if().
 
 
 
257
 
258
  // If key option_page this was saved from regular settings pages
259
  if ( ! empty( $option_page ) ) {
265
  <td><a href="%3$s">%2$s</a></td>
266
  </tr>
267
  ',
268
+ __( 'Settings page', 'simple-history' ),
269
+ esc_html( $context['option_page'] ),
270
+ admin_url( "options-{$option_page}.php" )
271
  );
272
 
273
  }
274
 
275
  // If option = permalink_structure then we did it from permalink page
276
+ if ( ! empty( $option ) && ( 'permalink_structure' == $option || 'tag_base' == $option || 'category_base' == $option ) ) {
277
 
278
  $output .= sprintf(
279
  '
282
  <td><a href="%3$s">%2$s</a></td>
283
  </tr>
284
  ',
285
+ __( 'Settings page', 'simple-history' ),
286
+ 'permalink',
287
+ admin_url( 'options-permalink.php' )
288
  );
289
 
290
  }
291
 
292
+ $output .= '</table>';
293
 
294
+ }// End if().
295
 
296
  return $output;
297
 
310
  $old_post = get_post( $old_value );
311
 
312
  if ( $old_post ) {
313
+ $context['old_post_title'] = $old_post->post_title;
314
  }
 
315
  }
316
 
317
  if ( ! empty( $new_value ) && is_numeric( $new_value ) ) {
319
  $new_post = get_post( $new_value );
320
 
321
  if ( $new_post ) {
322
+ $context['new_post_title'] = $new_post->post_title;
323
  }
 
324
  }
325
 
326
  return $context;
330
  function add_context_for_option_page_for_posts( $context, $old_value, $new_value, $option, $option_page ) {
331
 
332
  // Get same info as for page_on_front
333
+ $context = call_user_func_array( array( $this, 'add_context_for_option_page_on_front' ), func_get_args() );
334
 
335
  return $context;
336
 
338
 
339
  function get_details_output_for_option_page_for_posts( $context, $old_value, $new_value, $option, $option_page ) {
340
 
341
+ $output = call_user_func_array( array( $this, 'get_details_output_for_option_page_on_front' ), func_get_args() );
342
 
343
  return $output;
344
 
345
  }
346
 
347
  /**
348
+ * Add detailed output for page_on_front
349
  *
350
  * @return string output
351
  */
352
  function get_details_output_for_option_page_on_front( $context, $old_value, $new_value, $option, $option_page, $tmpl_row ) {
353
 
354
+ $output = '';
355
 
356
+ if ( $new_value && ! empty( $context['new_post_title'] ) ) {
357
 
358
+ $post_title_with_link = '';
359
 
360
  if ( get_post_status( $new_value ) ) {
361
+ $post_title_with_link = sprintf( '<a href="%1$s">%2$s</a>', get_edit_post_link( $new_value ), esc_html( $context['new_post_title'] ) );
362
  } else {
363
+ $post_title_with_link = esc_html( $context['new_post_title'] );
364
  }
365
 
366
  $output .= sprintf(
367
  $tmpl_row,
368
+ __( 'New value', 'simple-history' ),
369
+ sprintf( __( 'Page %1$s', 'simple-history' ), $post_title_with_link )
370
  );
371
 
372
  }
373
+ if ( intval( $new_value ) == 0 ) {
374
 
375
  $output .= sprintf(
376
  $tmpl_row,
377
+ __( 'New value', 'simple-history' ),
378
+ __( 'Your latests posts', 'simple-history' )
379
  );
380
 
381
  }
382
 
383
+ if ( $old_value && ! empty( $context['old_post_title'] ) ) {
384
+ $post_title_with_link = '';
385
 
386
  if ( get_post_status( $old_value ) ) {
387
+ $post_title_with_link = sprintf( '<a href="%1$s">%2$s</a>', get_edit_post_link( $old_value ), esc_html( $context['old_post_title'] ) );
388
  } else {
389
+ $post_title_with_link = esc_html( $context['old_post_title'] );
390
  }
391
 
392
  $output .= sprintf(
393
  $tmpl_row,
394
+ __( 'Old value', 'simple-history' ),
395
+ sprintf( __( 'Page %1$s', 'simple-history' ), $post_title_with_link )
396
  );
397
 
398
  }
399
 
400
+ if ( intval( $old_value ) == 0 ) {
401
 
402
  $output .= sprintf(
403
  $tmpl_row,
404
+ __( 'Old value', 'simple-history' ),
405
+ __( 'Your latests posts', 'simple-history' )
406
  );
407
 
408
  }
421
 
422
  $old_category_name = get_the_category_by_ID( $old_value );
423
 
424
+ if ( ! is_wp_error( $old_category_name ) ) {
425
 
426
+ $context['old_category_name'] = $old_category_name;
427
 
428
  }
 
429
  }
430
 
431
  if ( ! empty( $new_value ) && is_numeric( $new_value ) ) {
432
 
433
  $new_category_name = get_the_category_by_ID( $new_value );
434
 
435
+ if ( ! is_wp_error( $new_category_name ) ) {
436
 
437
+ $context['new_category_name'] = $new_category_name;
438
 
439
  }
 
440
  }
441
 
442
  return $context;
445
 
446
  function add_context_for_option_default_email_category( $context, $old_value, $new_value, $option, $option_page ) {
447
 
448
+ $context = call_user_func_array( array( $this, 'add_context_for_option_default_category' ), func_get_args() );
449
 
450
  return $context;
451
 
453
 
454
 
455
  /**
456
+ * Add detailed output for default_category
457
  *
458
  * @return string output
459
  */
460
  function get_details_output_for_option_default_category( $context, $old_value, $new_value, $option, $option_page, $tmpl_row ) {
461
 
462
+ $old_category_name = isset( $context['old_category_name'] ) ? $context['old_category_name'] : null;
463
+ $new_category_name = isset( $context['new_category_name'] ) ? $context['new_category_name'] : null;
464
+ $output = '';
465
 
466
  if ( $old_category_name ) {
467
 
468
  $output .= sprintf(
469
  $tmpl_row,
470
+ __( 'Old value', 'simple-history' ),
471
  esc_html( $old_category_name )
472
  );
473
 
477
 
478
  $output .= sprintf(
479
  $tmpl_row,
480
+ __( 'New value', 'simple-history' ),
481
  esc_html( $new_category_name )
482
  );
483
 
489
 
490
  function get_details_output_for_option_default_email_category( $context, $old_value, $new_value, $option, $option_page, $tmpl_row ) {
491
 
492
+ $output = call_user_func_array( array( $this, 'get_details_output_for_option_default_category' ), func_get_args() );
493
 
494
  return $output;
495
 
loggers/SimplePluginLogger.php CHANGED
@@ -139,38 +139,37 @@ class SimplePluginLogger extends SimpleLogger {
139
  * At least the plugin bulk upgrades fires this action before upgrade
140
  * We use it to fetch the current version of all plugins, before they are upgraded
141
  */
142
- add_filter( 'upgrader_pre_install', array( $this, "save_versions_before_update" ), 10, 2 );
143
 
144
  // Clear our transient after an update is done
145
  // Removed because something probably changed in core and this was fired earlier than it used to be
146
  // add_action( 'delete_site_transient_update_plugins', array( $this, "remove_saved_versions" ) );
147
-
148
  // Fires after a plugin has been activated.
149
  // If a plugin is silently activated (such as during an update),
150
  // this hook does not fire.
151
- add_action( 'activated_plugin', array( $this, "on_activated_plugin" ), 10, 2 );
152
 
153
  // Fires after a plugin is deactivated.
154
  // If a plugin is silently deactivated (such as during an update),
155
  // this hook does not fire.
156
- add_action( 'deactivated_plugin', array( $this, "on_deactivated_plugin" ), 10, 2 );
157
 
158
  // Fires after the upgrades has done it's thing
159
  // Check hook extra for upgrader initiator
160
- add_action( 'upgrader_process_complete', array( $this, "on_upgrader_process_complete" ), 10, 2 );
161
 
162
  // Detect files removed
163
  add_action( 'setted_transient', array( $this, 'on_setted_transient_for_remove_files' ), 10, 2 );
164
 
165
- add_action("admin_action_delete-selected", array($this, "on_action_delete_selected" ), 10, 1);
166
 
167
  // Ajax function to get info from GitHub repo. Used by "View plugin info"-link for plugin installs
168
- add_action("wp_ajax_SimplePluginLogger_GetGitHubPluginInfo", array($this, "ajax_GetGitHubPluginInfo"));
169
 
170
  // If the Github Update plugin is not installed we need to get extra fields used by it.
171
  // So need to hook filter "extra_plugin_headers" ourself.
172
- add_filter( "extra_plugin_headers", function( $arr_headers ) {
173
- $arr_headers[] = "GitHub Plugin URI";
174
  return $arr_headers;
175
  } );
176
 
@@ -247,7 +246,7 @@ class SimplePluginLogger extends SimpleLogger {
247
  global $pagenow;
248
 
249
  // We only act on page plugins.php.
250
- if ( ! isset( $pagenow ) || $pagenow !== "plugins.php" ) {
251
  return $translation;
252
  }
253
 
@@ -300,19 +299,19 @@ class SimplePluginLogger extends SimpleLogger {
300
  */
301
  function ajax_GetGitHubPluginInfo() {
302
 
303
- if ( ! current_user_can("install_plugins") ) {
304
- wp_die( __("You don't have access to this page.", "simple-history" ));
305
  }
306
 
307
- $repo = isset( $_GET["repo"] ) ? (string) $_GET["repo"] : "";
308
 
309
  if ( ! $repo ) {
310
- wp_die( __("Could not find GitHub repository.", "simple-history" ));
311
  }
312
 
313
- $repo_parts = explode("/", rtrim($repo, "/"));
314
- if ( count($repo_parts) !== 5 ) {
315
- wp_die( __("Could not find GitHub repository.", "simple-history" ));
316
  }
317
 
318
  $repo_username = $repo_parts[3];
@@ -320,24 +319,24 @@ class SimplePluginLogger extends SimpleLogger {
320
 
321
  // https://developer.github.com/v3/repos/contents/
322
  // https://api.github.com/repos/<username>/<repo>/readme
323
- $api_url = sprintf('https://api.github.com/repos/%1$s/%2$s/readme', urlencode( $repo_username ), urlencode( $repo_repo ));
324
 
325
  // Get file. Use accept-header to get file as HTML instead of JSON
326
  $response = wp_remote_get( $api_url, array(
327
- "headers" => array(
328
- "accept" => "application/vnd.github.VERSION.html"
329
- )
330
  ) );
331
 
332
  $response_body = wp_remote_retrieve_body( $response );
333
 
334
  $repo_info = sprintf(
335
- __('<p>Viewing <code>readme</code> from repository <code><a target="_blank" href="%1$s">%2$s</a></code>.</p>', "simple-history"),
336
- esc_url( $repo ),
337
- esc_html( $repo )
338
- );
339
 
340
- $github_markdown_css_path = SIMPLE_HISTORY_PATH . "/css/github-markdown.css";
341
 
342
  printf(
343
  '
@@ -382,8 +381,7 @@ class SimplePluginLogger extends SimpleLogger {
382
  esc_url( $repo ) // 4
383
  );
384
 
385
- #echo($response_body);
386
-
387
  exit;
388
 
389
  }
@@ -396,38 +394,36 @@ class SimplePluginLogger extends SimpleLogger {
396
  function on_action_delete_selected() {
397
 
398
  // Same as in plugins.php
399
- if ( ! current_user_can('delete_plugins') ) {
400
- wp_die(__('You do not have sufficient permissions to delete plugins for this site.'));
401
  }
402
 
403
  // Verify delete must be set
404
- if ( ! isset( $_POST["verify-delete"] ) || ! $_POST["verify-delete"] ) {
405
  return;
406
  }
407
 
408
  // An arr of plugins must be set
409
- if ( ! isset( $_POST["checked"] ) || ! is_array( $_POST["checked"] ) ) {
410
  return;
411
  }
412
 
413
  // If we get this far it looks like a plugin is begin deleted
414
  // Get and save info about it
415
-
416
  $this->save_versions_before_update();
417
 
418
-
419
  }
420
 
421
  /**
422
  * Saves info about all installed plugins to an option.
423
  * When we are done logging then we remove the option.
424
  */
425
- function save_versions_before_update($bool = null, $hook_extra = null) {
426
 
427
  $plugins = get_plugins();
428
 
429
  // does not work
430
- $option_name = $this->slug . "_plugin_info_before_update";
431
 
432
  $r = update_option( $option_name, SimpleHistory::json_encode( $plugins ) );
433
 
@@ -441,9 +437,8 @@ class SimplePluginLogger extends SimpleLogger {
441
  * set_transient('plugins_delete_result_' . $user_ID, $delete_result);
442
  *
443
  * We detect when that transient is set and then we have all info needed to log the plugin delete
444
- *
445
  */
446
- public function on_setted_transient_for_remove_files( $transient = "", $value = "" ) {
447
 
448
  if ( ! $user_id = get_current_user_id() ) {
449
  return;
@@ -456,10 +451,10 @@ class SimplePluginLogger extends SimpleLogger {
456
 
457
  // We found the transient we were looking for
458
  if (
459
- isset( $_POST["action"] )
460
- && "delete-selected" == $_POST["action"]
461
- && isset( $_POST["checked"] )
462
- && is_array( $_POST["checked"] )
463
  ) {
464
 
465
  /*
@@ -469,31 +464,30 @@ class SimplePluginLogger extends SimpleLogger {
469
  )
470
  */
471
 
472
- $plugins_deleted = $_POST["checked"];
473
- $plugins_before_update = json_decode( get_option( $this->slug . "_plugin_info_before_update", false ), true );
474
 
475
  foreach ( $plugins_deleted as $plugin ) {
476
 
477
  $context = array(
478
- "plugin" => $plugin // plugin-name-folder/plugin-main-file.php
479
  );
480
 
481
  if ( is_array( $plugins_before_update ) && isset( $plugins_before_update[ $plugin ] ) ) {
482
- $context["plugin_name"] = $plugins_before_update[ $plugin ]["Name"];
483
- $context["plugin_title"] = $plugins_before_update[ $plugin ]["Title"];
484
- $context["plugin_description"] = $plugins_before_update[ $plugin ]["Description"];
485
- $context["plugin_author"] = $plugins_before_update[ $plugin ]["Author"];
486
- $context["plugin_version"] = $plugins_before_update[ $plugin ]["Version"];
487
- $context["plugin_url"] = $plugins_before_update[ $plugin ]["PluginURI"];
488
  }
489
 
490
  $this->infoMessage(
491
- "plugin_deleted",
492
  $context
493
  );
494
 
495
  }
496
-
497
  }
498
 
499
  $this->remove_saved_versions();
@@ -504,7 +498,8 @@ class SimplePluginLogger extends SimpleLogger {
504
  * Save all plugin information before a plugin is updated or removed.
505
  * This way we can know both the old (pre updated/removed) and the current version of the plugin
506
  */
507
- /*public function save_versions_before_update() {
 
508
 
509
  $current_screen = get_current_screen();
510
  $request_uri = $_SERVER["SCRIPT_NAME"];
@@ -541,15 +536,15 @@ class SimplePluginLogger extends SimpleLogger {
541
  */
542
 
543
  /**
544
- * when plugin updates are done wp_clean_plugins_cache() is called,
545
- * which in its turn run:
546
- * delete_site_transient( 'update_plugins' );
547
- * do_action( 'delete_site_transient_' . $transient, $transient );
548
- * delete_site_transient_update_plugins
549
- */
550
  public function remove_saved_versions() {
551
 
552
- delete_option( $this->slug . "_plugin_info_before_update" );
553
 
554
  }
555
 
@@ -561,13 +556,11 @@ class SimplePluginLogger extends SimpleLogger {
561
  * be a Theme_Upgrader or Core_Upgrade instance.
562
  * @param array $data {
563
  * Array of bulk item update data.
564
- *
565
  */
566
  function on_upgrader_process_complete( $plugin_upgrader_instance, $arr_data ) {
567
 
568
  // Can't use get_plugins() here to get version of plugins updated from
569
  // Tested that, and it will get the new version (and that's the correct answer I guess. but too bad for us..)
570
-
571
  /*
572
  If an update fails then $plugin_upgrader_instance->skin->result->errors contains something like:
573
  Array
@@ -581,7 +574,6 @@ class SimplePluginLogger extends SimpleLogger {
581
  */
582
 
583
  /*
584
-
585
  # Contents of $arr_data in different scenarios
586
 
587
  ## WordPress core update
@@ -628,36 +620,35 @@ class SimplePluginLogger extends SimpleLogger {
628
  // only if we did not log anything
629
  $did_log = false;
630
 
631
- if ( isset( $arr_data["type"] ) && "plugin" == $arr_data["type"] ) {
632
 
633
  // Single plugin install
634
- if ( isset( $arr_data["action"] ) && "install" == $arr_data["action"] && ! $plugin_upgrader_instance->bulk ) {
635
 
636
  $upgrader_skin_options = isset( $plugin_upgrader_instance->skin->options ) && is_array( $plugin_upgrader_instance->skin->options ) ? $plugin_upgrader_instance->skin->options : array();
637
  $upgrader_skin_result = isset( $plugin_upgrader_instance->skin->result ) && is_array( $plugin_upgrader_instance->skin->result ) ? $plugin_upgrader_instance->skin->result : array();
638
  $upgrader_skin_api = isset( $plugin_upgrader_instance->skin->api ) ? $plugin_upgrader_instance->skin->api : (object) array();
639
 
640
- $plugin_slug = isset( $upgrader_skin_result["destination_name"] ) ? $upgrader_skin_result["destination_name"] : "";
641
 
642
  // Upgrader contains current info
643
  $context = array(
644
- "plugin_slug" => $plugin_slug,
645
- "plugin_name" => isset( $upgrader_skin_api->name ) ? $upgrader_skin_api->name : "",
646
- "plugin_version" => isset( $upgrader_skin_api->version ) ? $upgrader_skin_api->version : "",
647
- "plugin_author" => isset( $upgrader_skin_api->author ) ? $upgrader_skin_api->author : "",
648
- "plugin_last_updated" => isset( $upgrader_skin_api->last_updated ) ? $upgrader_skin_api->last_updated : "",
649
- "plugin_requires" => isset( $upgrader_skin_api->requires ) ? $upgrader_skin_api->requires : "",
650
- "plugin_tested" => isset( $upgrader_skin_api->tested ) ? $upgrader_skin_api->tested : "",
651
- "plugin_rating" => isset( $upgrader_skin_api->rating ) ? $upgrader_skin_api->rating : "",
652
- "plugin_num_ratings" => isset( $upgrader_skin_api->num_ratings ) ? $upgrader_skin_api->num_ratings : "",
653
- "plugin_downloaded" => isset( $upgrader_skin_api->downloaded ) ? $upgrader_skin_api->downloaded : "",
654
- "plugin_added" => isset( $upgrader_skin_api->added ) ? $upgrader_skin_api->added : "",
655
- "plugin_source_files" => $this->simpleHistory->json_encode( $plugin_upgrader_instance->result["source_files"] ),
656
 
657
  // To debug comment out these:
658
  // "debug_skin_options" => $this->simpleHistory->json_encode( $upgrader_skin_options ),
659
  // "debug_skin_result" => $this->simpleHistory->json_encode( $upgrader_skin_result ),
660
-
661
  );
662
 
663
  /*
@@ -670,17 +661,18 @@ class SimplePluginLogger extends SimpleLogger {
670
 
671
  Also: plugins hosted at GitHub have a de-facto standard field of "GitHub Plugin URI"
672
  */
673
- $install_source = "unknown";
674
- if ( isset( $upgrader_skin_options["type"] ) ) {
675
- $install_source = (string) $upgrader_skin_options["type"];
676
  }
677
 
678
- $context["plugin_install_source"] = $install_source;
679
 
680
  // If uploaded plugin store name of ZIP
681
- if ( "upload" == $install_source ) {
682
 
683
- /*_debug_files
 
684
  {
685
  "pluginzip": {
686
  "name": "WPThumb-master.zip",
@@ -692,20 +684,18 @@ class SimplePluginLogger extends SimpleLogger {
692
  }
693
  */
694
 
695
- if ( isset( $_FILES["pluginzip"]["name"] ) ) {
696
- $plugin_upload_name = $_FILES["pluginzip"]["name"];
697
- $context["plugin_upload_name"] = $plugin_upload_name;
698
  }
699
-
700
  }
701
 
702
-
703
- if ( is_a( $plugin_upgrader_instance->skin->result, "WP_Error" ) ) {
704
 
705
  // Add errors
706
  // Errors is in original wp admin language
707
- $context["error_messages"] = $this->simpleHistory->json_encode( $plugin_upgrader_instance->skin->result->errors );
708
- $context["error_data"] = $this->simpleHistory->json_encode( $plugin_upgrader_instance->skin->result->error_data );
709
 
710
  $this->infoMessage(
711
  'plugin_installed_failed',
@@ -719,7 +709,7 @@ class SimplePluginLogger extends SimpleLogger {
719
  // Plugin was successfully installed
720
  // Try to grab more info from the readme
721
  // Would be nice to grab a screenshot, but that is difficult since they often are stored remotely
722
- $plugin_destination = isset( $plugin_upgrader_instance->result["destination"] ) ? $plugin_upgrader_instance->result["destination"] : null;
723
 
724
  if ( $plugin_destination ) {
725
 
@@ -730,20 +720,18 @@ class SimplePluginLogger extends SimpleLogger {
730
  $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_info, true, false );
731
  }
732
 
733
- $context["plugin_name"] = isset( $plugin_data["Name"] ) ? $plugin_data["Name"] : "";
734
- $context["plugin_description"] = isset( $plugin_data["Description"] ) ? $plugin_data["Description"] : "";
735
- $context["plugin_url"] = isset( $plugin_data["PluginURI"] ) ? $plugin_data["PluginURI"] : "";
736
- $context["plugin_version"] = isset( $plugin_data["Version"] ) ? $plugin_data["Version"] : "";
737
- $context["plugin_author"] = isset( $plugin_data["AuthorName"] ) ? $plugin_data["AuthorName"] : "";
738
 
739
  // Comment out these to debug plugin installs
740
- #$context["debug_plugin_data"] = $this->simpleHistory->json_encode( $plugin_data );
741
- #$context["debug_plugin_info"] = $this->simpleHistory->json_encode( $plugin_info );
742
-
743
- if ( ! empty( $plugin_data["GitHub Plugin URI"] ) ) {
744
- $context["plugin_github_url"] = $plugin_data["GitHub Plugin URI"];
745
  }
746
-
747
  }
748
 
749
  $this->infoMessage(
@@ -753,39 +741,38 @@ class SimplePluginLogger extends SimpleLogger {
753
 
754
  $did_log = true;
755
 
756
- } // if error or not
757
-
758
- } // install single
759
 
760
  // Single plugin update
761
- if ( isset( $arr_data["action"] ) && "update" == $arr_data["action"] && ! $plugin_upgrader_instance->bulk ) {
762
 
763
  // No plugin info in instance, so get it ourself
764
  $plugin_data = array();
765
- if ( file_exists( WP_PLUGIN_DIR . '/' . $arr_data["plugin"] ) ) {
766
- $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $arr_data["plugin"], true, false );
767
  }
768
 
769
  // autoptimize/autoptimize.php
770
- $plugin_slug = dirname( $arr_data["plugin"] );
771
 
772
  $context = array(
773
- "plugin_slug" => $plugin_slug,
774
- "request" => $this->simpleHistory->json_encode( $_REQUEST ),
775
- "plugin_name" => $plugin_data["Name"],
776
- "plugin_title" => $plugin_data["Title"],
777
- "plugin_description" => $plugin_data["Description"],
778
- "plugin_author" => $plugin_data["Author"],
779
- "plugin_version" => $plugin_data["Version"],
780
- "plugin_url" => $plugin_data["PluginURI"],
781
- "plugin_source_files" => $this->simpleHistory->json_encode( $plugin_upgrader_instance->result["source_files"] )
782
  );
783
 
784
  // update status for plugins are in response
785
  // plugin folder + index file = key
786
  // use transient to get url and package
787
  $update_plugins = get_site_transient( 'update_plugins' );
788
- if ( $update_plugins && isset( $update_plugins->response[ $arr_data["plugin"] ] ) ) {
789
 
790
  /*
791
  $update_plugins[plugin_path/slug]:
@@ -800,35 +787,33 @@ class SimplePluginLogger extends SimpleLogger {
800
  */
801
  // for debug purposes the update_plugins key can be added
802
  // $context["update_plugins"] = $this->simpleHistory->json_encode( $update_plugins );
803
-
804
- $plugin_update_info = $update_plugins->response[ $arr_data["plugin"] ];
805
 
806
  // autoptimize/autoptimize.php
807
  if ( isset( $plugin_update_info->plugin ) ) {
808
- $context["plugin_update_info_plugin"] = $plugin_update_info->plugin;
809
  }
810
 
811
  // https://downloads.wordpress.org/plugin/autoptimize.1.9.1.zip
812
  if ( isset( $plugin_update_info->package ) ) {
813
- $context["plugin_update_info_package"] = $plugin_update_info->package;
814
  }
815
-
816
  }
817
 
818
  // To get old version we use our option
819
- $plugins_before_update = json_decode( get_option( $this->slug . "_plugin_info_before_update", false ), true );
820
- if ( is_array( $plugins_before_update ) && isset( $plugins_before_update[ $arr_data["plugin"] ] ) ) {
821
 
822
- $context["plugin_prev_version"] = $plugins_before_update[ $arr_data["plugin"] ]["Version"];
823
 
824
  }
825
 
826
- if ( is_a( $plugin_upgrader_instance->skin->result, "WP_Error" ) ) {
827
 
828
  // Add errors
829
  // Errors is in original wp admin language
830
- $context["error_messages"] = json_encode( $plugin_upgrader_instance->skin->result->errors );
831
- $context["error_data"] = json_encode( $plugin_upgrader_instance->skin->result->error_data );
832
 
833
  $this->infoMessage(
834
  'plugin_update_failed',
@@ -844,16 +829,13 @@ class SimplePluginLogger extends SimpleLogger {
844
  $context
845
  );
846
 
847
- #echo "on_upgrader_process_complete";
848
- #sf_d( $plugin_upgrader_instance, '$plugin_upgrader_instance' );
849
- #sf_d( $arr_data, '$arr_data' );
850
-
851
  $did_log = true;
852
 
853
  }
854
-
855
- } // update single
856
-
857
 
858
  /**
859
  * For bulk updates $arr_data looks like:
@@ -869,24 +851,24 @@ class SimplePluginLogger extends SimpleLogger {
869
  * )
870
  * )
871
  */
872
- if ( isset( $arr_data["bulk"] ) && $arr_data["bulk"] && isset( $arr_data["action"] ) && "update" == $arr_data["action"] ) {
873
 
874
- $plugins_updated = isset( $arr_data["plugins"] ) ? (array) $arr_data["plugins"] : array();
875
 
876
- foreach ($plugins_updated as $plugin_name) {
877
 
878
  $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name, true, false );
879
 
880
  $plugin_slug = dirname( $plugin_name );
881
 
882
  $context = array(
883
- "plugin_slug" => $plugin_slug,
884
- "plugin_name" => $plugin_data["Name"],
885
- "plugin_title" => $plugin_data["Title"],
886
- "plugin_description" => $plugin_data["Description"],
887
- "plugin_author" => $plugin_data["Author"],
888
- "plugin_version" => $plugin_data["Version"],
889
- "plugin_url" => $plugin_data["PluginURI"]
890
  );
891
 
892
  // get url and package
@@ -909,22 +891,21 @@ class SimplePluginLogger extends SimpleLogger {
909
 
910
  // autoptimize/autoptimize.php
911
  if ( isset( $plugin_update_info->plugin ) ) {
912
- $context["plugin_update_info_plugin"] = $plugin_update_info->plugin;
913
  }
914
 
915
  // https://downloads.wordpress.org/plugin/autoptimize.1.9.1.zip
916
  if ( isset( $plugin_update_info->package ) ) {
917
- $context["plugin_update_info_package"] = $plugin_update_info->package;
918
  }
919
-
920
  }
921
 
922
  // To get old version we use our option
923
  // @TODO: this does not always work, why?
924
- $plugins_before_update = json_decode( get_option( $this->slug . "_plugin_info_before_update", false ), true );
925
  if ( is_array( $plugins_before_update ) && isset( $plugins_before_update[ $plugin_name ] ) ) {
926
 
927
- $context["plugin_prev_version"] = $plugins_before_update[ $plugin_name ]["Version"];
928
 
929
  }
930
 
@@ -933,18 +914,15 @@ class SimplePluginLogger extends SimpleLogger {
933
  $context
934
  );
935
 
936
- }
937
-
938
- } // bulk update
939
-
940
-
941
- } // if plugin
942
 
943
  if ( ! $did_log ) {
944
- #echo "on_upgrader_process_complete";
945
- #sf_d( $plugin_upgrader_instance, '$plugin_upgrader_instance' );
946
- #sf_d( $arr_data, '$arr_data' );
947
- #exit;
948
  }
949
 
950
  $this->remove_saved_versions();
@@ -956,7 +934,7 @@ class SimplePluginLogger extends SimpleLogger {
956
  * Plugin is activated
957
  * plugin_name is like admin-menu-tree-page-view/index.php
958
  */
959
- function on_activated_plugin($plugin_name, $network_wide) {
960
 
961
  /*
962
  Plugin data returned array contains the following:
@@ -976,17 +954,17 @@ class SimplePluginLogger extends SimpleLogger {
976
  $plugin_slug = dirname( $plugin_name );
977
 
978
  $context = array(
979
- "plugin_name" => $plugin_data["Name"],
980
- "plugin_slug" => $plugin_slug,
981
- "plugin_title" => $plugin_data["Title"],
982
- "plugin_description" => $plugin_data["Description"],
983
- "plugin_author" => $plugin_data["Author"],
984
- "plugin_version" => $plugin_data["Version"],
985
- "plugin_url" => $plugin_data["PluginURI"],
986
  );
987
 
988
- if ( ! empty( $plugin_data["GitHub Plugin URI"] ) ) {
989
- $context["plugin_github_url"] = $plugin_data["GitHub Plugin URI"];
990
  }
991
 
992
  $this->infoMessage( 'plugin_activated', $context );
@@ -997,23 +975,23 @@ class SimplePluginLogger extends SimpleLogger {
997
  * Plugin is deactivated
998
  * plugin_name is like admin-menu-tree-page-view/index.php
999
  */
1000
- function on_deactivated_plugin($plugin_name) {
1001
 
1002
  $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name, true, false );
1003
  $plugin_slug = dirname( $plugin_name );
1004
 
1005
  $context = array(
1006
- "plugin_name" => $plugin_data["Name"],
1007
- "plugin_slug" => $plugin_slug,
1008
- "plugin_title" => $plugin_data["Title"],
1009
- "plugin_description" => $plugin_data["Description"],
1010
- "plugin_author" => $plugin_data["Author"],
1011
- "plugin_version" => $plugin_data["Version"],
1012
- "plugin_url" => $plugin_data["PluginURI"],
1013
  );
1014
 
1015
- if ( ! empty( $plugin_data["GitHub Plugin URI"] ) ) {
1016
- $context["plugin_github_url"] = $plugin_data["GitHub Plugin URI"];
1017
  }
1018
 
1019
  $this->infoMessage( 'plugin_deactivated', $context );
@@ -1024,97 +1002,97 @@ class SimplePluginLogger extends SimpleLogger {
1024
  /**
1025
  * Get output for detailed log section
1026
  */
1027
- function getLogRowDetailsOutput($row) {
1028
 
1029
  $context = $row->context;
1030
- $message_key = $context["_message_key"];
1031
- $output = "";
1032
 
1033
  // When a plugin is installed we show a bit more information
1034
  // We do it only on install because we don't want to clutter to log,
1035
  // and when something is installed the description is most useul for other
1036
  // admins on the site
1037
- if ( "plugin_installed" === $message_key ) {
1038
 
1039
- if ( isset( $context["plugin_description"] ) ) {
1040
 
1041
  // Description includes a link to author, remove that, i.e. all text after and including <cite>
1042
- $plugin_description = $context["plugin_description"];
1043
- $cite_pos = strpos( $plugin_description, "<cite>" );
1044
- if ($cite_pos) {
1045
  $plugin_description = substr( $plugin_description, 0, $cite_pos );
1046
  }
1047
 
1048
  // Keys to show
1049
  $arr_plugin_keys = array(
1050
- "plugin_description" => _x("Description", "plugin logger - detailed output", "simple-history"),
1051
- "plugin_install_source" => _x("Source", "plugin logger - detailed output install source", "simple-history"),
1052
- "plugin_install_source_file" => _x("Source file name", "plugin logger - detailed output install source", "simple-history"),
1053
- "plugin_version" => _x("Version", "plugin logger - detailed output version", "simple-history"),
1054
- "plugin_author" => _x("Author", "plugin logger - detailed output author", "simple-history"),
1055
- "plugin_url" => _x("URL", "plugin logger - detailed output url", "simple-history"),
1056
- #"plugin_downloaded" => _x("Downloads", "plugin logger - detailed output downloaded", "simple-history"),
1057
- #"plugin_requires" => _x("Requires", "plugin logger - detailed output author", "simple-history"),
1058
- #"plugin_tested" => _x("Compatible up to", "plugin logger - detailed output compatible", "simple-history"),
1059
  // also available: plugin_rating, plugin_num_ratings
1060
  );
1061
 
1062
- $arr_plugin_keys = apply_filters("simple_history/plugin_logger/row_details_plugin_info_keys", $arr_plugin_keys);
1063
 
1064
  // Start output of plugin meta data table
1065
  $output .= "<table class='SimpleHistoryLogitem__keyValueTable'>";
1066
 
1067
  foreach ( $arr_plugin_keys as $key => $desc ) {
1068
 
1069
- $desc_output = "";
1070
 
1071
  switch ( $key ) {
1072
 
1073
- case "plugin_downloaded":
1074
  $desc_output = esc_html( number_format_i18n( (int) $context[ $key ] ) );
1075
  break;
1076
 
1077
  // author is already formatted
1078
- case "plugin_author":
1079
  $desc_output = $context[ $key ];
1080
  break;
1081
 
1082
  // URL needs a link
1083
- case "plugin_url":
1084
- $desc_output = sprintf('<a href="%1$s">%2$s</a>', esc_attr( $context["plugin_url"] ), esc_html( $context["plugin_url"] ));
1085
  break;
1086
 
1087
- case "plugin_description":
1088
  $desc_output = $plugin_description;
1089
  break;
1090
 
1091
- case "plugin_install_source":
1092
 
1093
  if ( ! isset( $context[ $key ] ) ) {
1094
  continue;
1095
  }
1096
 
1097
- if ( "web" == $context[ $key ] ) {
1098
- $desc_output = esc_html( __("WordPress Plugin Repository", "simple-history") );
1099
- } else if ( "upload" == $context[ $key ] ) {
1100
- #$plugin_upload_name = isset( $context["plugin_upload_name"] ) ? $context["plugin_upload_name"] : __("Unknown archive name", "simple-history");
1101
- $desc_output = esc_html( __('Uploaded ZIP archive', "simple-history") );
1102
- #$desc_output = esc_html( sprintf( __('Uploaded ZIP archive (%1$s)', "simple-history"), $plugin_upload_name ) );
1103
- #$desc_output = esc_html( sprintf( __('%1$s (uploaded ZIP archive)', "simple-history"), $plugin_upload_name ) );
1104
  } else {
1105
  $desc_output = esc_html( $context[ $key ] );
1106
  }
1107
 
1108
  break;
1109
 
1110
- case "plugin_install_source_file":
1111
 
1112
- if ( ! isset( $context["plugin_upload_name"] ) || ! isset( $context["plugin_install_source"] ) ) {
1113
  continue;
1114
  }
1115
 
1116
- if ( "upload" == $context["plugin_install_source"] ) {
1117
- $plugin_upload_name = $context["plugin_upload_name"];
1118
  $desc_output = esc_html( $plugin_upload_name );
1119
  }
1120
 
@@ -1123,7 +1101,7 @@ class SimplePluginLogger extends SimpleLogger {
1123
  default;
1124
  $desc_output = esc_html( $context[ $key ] );
1125
  break;
1126
- }
1127
 
1128
  if ( ! trim( $desc_output ) ) {
1129
  continue;
@@ -1136,21 +1114,20 @@ class SimplePluginLogger extends SimpleLogger {
1136
  <td>%2$s</td>
1137
  </tr>
1138
  ',
1139
- esc_html($desc),
1140
  $desc_output
1141
  );
1142
 
1143
- }
1144
 
1145
  // Add link with more info about the plugin
1146
  // If plugin_install_source = web then it should be a wordpress.org-plugin
1147
  // If plugin_github_url is set then it's a zip from a github thingie
1148
  // so use link to that.
1149
-
1150
- $plugin_slug = ! empty( $context["plugin_slug"] ) ? $context["plugin_slug"] : "";
1151
 
1152
  // Slug + web as install source = show link to wordpress.org
1153
- if ( $plugin_slug && isset( $context["plugin_install_source"] ) && $context["plugin_install_source"] == "web" ) {
1154
 
1155
  $output .= sprintf(
1156
  '
@@ -1160,17 +1137,15 @@ class SimplePluginLogger extends SimpleLogger {
1160
  </tr>
1161
  ',
1162
  admin_url( "plugin-install.php?tab=plugin-information&amp;plugin={$plugin_slug}&amp;section=&amp;TB_iframe=true&amp;width=640&amp;height=550" ),
1163
- esc_html_x("View plugin info", "plugin logger: plugin info thickbox title view all info", "simple-history")
1164
  );
1165
 
1166
- }
1167
- // GitHub plugin url set = show link to github repo
1168
- else if ( isset( $context["plugin_install_source"] ) && $context["plugin_install_source"] == "upload" && ! empty( $context["plugin_github_url"] ) ) {
1169
 
1170
  // Can't embed iframe
1171
  // Must use API instead
1172
  // https://api.github.com/repos/<username>/<repo>/readme?callback=<callbackname>
1173
-
1174
  $output .= sprintf(
1175
  '
1176
  <tr>
@@ -1178,35 +1153,33 @@ class SimplePluginLogger extends SimpleLogger {
1178
  <td><a title="%2$s" class="thickbox" href="%1$s">%2$s</a></td>
1179
  </tr>
1180
  ',
1181
- admin_url(sprintf('admin-ajax.php?action=SimplePluginLogger_GetGitHubPluginInfo&getrepo&amp;repo=%1$s&amp;TB_iframe=true&amp;width=640&amp;height=550', esc_url_raw( $context["plugin_github_url"] ) ) ),
1182
- esc_html_x("View plugin info", "plugin logger: plugin info thickbox title view all info", "simple-history")
1183
  );
1184
 
1185
  }
1186
 
1187
- $output .= "</table>";
1188
-
1189
- }
1190
 
1191
- } elseif ( "plugin_bulk_updated" === $message_key || "plugin_updated" === $message_key || "plugin_activated" === $message_key || "plugin_deactivated" === $message_key ) {
 
1192
 
1193
- $plugin_slug = ! empty( $context["plugin_slug"] ) ? $context["plugin_slug"] : "";
1194
 
1195
- if ( $plugin_slug && empty( $context["plugin_github_url"] ) ) {
1196
 
1197
- $link_title = esc_html_x("View plugin info", "plugin logger: plugin info thickbox title", "simple-history");
1198
  $url = admin_url( "plugin-install.php?tab=plugin-information&amp;plugin={$plugin_slug}&amp;section=&amp;TB_iframe=true&amp;width=640&amp;height=550" );
1199
 
1200
- if ( "plugin_updated" == $message_key || "plugin_bulk_updated" == $message_key ) {
1201
 
1202
- $link_title = esc_html_x("View changelog", "plugin logger: plugin info thickbox title", "simple-history");
1203
 
1204
  if ( is_multisite() ) {
1205
  $url = network_admin_url( "plugin-install.php?tab=plugin-information&amp;plugin={$plugin_slug}&amp;section=changelog&amp;TB_iframe=true&amp;width=772&amp;height=550" );
1206
  } else {
1207
  $url = admin_url( "plugin-install.php?tab=plugin-information&amp;plugin={$plugin_slug}&amp;section=changelog&amp;TB_iframe=true&amp;width=772&amp;height=550" );
1208
  }
1209
-
1210
  }
1211
 
1212
  $output .= sprintf(
@@ -1215,7 +1188,7 @@ class SimplePluginLogger extends SimpleLogger {
1215
  $link_title
1216
  );
1217
 
1218
- } else if ( ! empty( $context["plugin_github_url"] ) ) {
1219
 
1220
  $output .= sprintf(
1221
  '
@@ -1224,14 +1197,12 @@ class SimplePluginLogger extends SimpleLogger {
1224
  <td><a title="%2$s" class="thickbox" href="%1$s">%2$s</a></td>
1225
  </tr>
1226
  ',
1227
- admin_url(sprintf('admin-ajax.php?action=SimplePluginLogger_GetGitHubPluginInfo&getrepo&amp;repo=%1$s&amp;TB_iframe=true&amp;width=640&amp;height=550', esc_url_raw( $context["plugin_github_url"] ) ) ),
1228
- esc_html_x("View plugin info", "plugin logger: plugin info thickbox title view all info", "simple-history")
1229
  );
1230
 
1231
- }
1232
-
1233
-
1234
- } // if plugin_updated
1235
 
1236
  return $output;
1237
 
139
  * At least the plugin bulk upgrades fires this action before upgrade
140
  * We use it to fetch the current version of all plugins, before they are upgraded
141
  */
142
+ add_filter( 'upgrader_pre_install', array( $this, 'save_versions_before_update' ), 10, 2 );
143
 
144
  // Clear our transient after an update is done
145
  // Removed because something probably changed in core and this was fired earlier than it used to be
146
  // add_action( 'delete_site_transient_update_plugins', array( $this, "remove_saved_versions" ) );
 
147
  // Fires after a plugin has been activated.
148
  // If a plugin is silently activated (such as during an update),
149
  // this hook does not fire.
150
+ add_action( 'activated_plugin', array( $this, 'on_activated_plugin' ), 10, 2 );
151
 
152
  // Fires after a plugin is deactivated.
153
  // If a plugin is silently deactivated (such as during an update),
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( 'extra_plugin_headers', function( $arr_headers ) {
172
+ $arr_headers[] = 'GitHub Plugin URI';
173
  return $arr_headers;
174
  } );
175
 
246
  global $pagenow;
247
 
248
  // We only act on page plugins.php.
249
+ if ( ! isset( $pagenow ) || $pagenow !== 'plugins.php' ) {
250
  return $translation;
251
  }
252
 
299
  */
300
  function ajax_GetGitHubPluginInfo() {
301
 
302
+ if ( ! current_user_can( 'install_plugins' ) ) {
303
+ wp_die( __( "You don't have access to this page.", 'simple-history' ) );
304
  }
305
 
306
+ $repo = isset( $_GET['repo'] ) ? (string) $_GET['repo'] : '';
307
 
308
  if ( ! $repo ) {
309
+ wp_die( __( 'Could not find GitHub repository.', 'simple-history' ) );
310
  }
311
 
312
+ $repo_parts = explode( '/', rtrim( $repo, '/' ) );
313
+ if ( count( $repo_parts ) !== 5 ) {
314
+ wp_die( __( 'Could not find GitHub repository.', 'simple-history' ) );
315
  }
316
 
317
  $repo_username = $repo_parts[3];
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( $api_url, array(
326
+ 'headers' => array(
327
+ 'accept' => 'application/vnd.github.VERSION.html',
328
+ ),
329
  ) );
330
 
331
  $response_body = wp_remote_retrieve_body( $response );
332
 
333
  $repo_info = sprintf(
334
+ __( '<p>Viewing <code>readme</code> from repository <code><a target="_blank" href="%1$s">%2$s</a></code>.</p>', 'simple-history' ),
335
+ esc_url( $repo ),
336
+ esc_html( $repo )
337
+ );
338
 
339
+ $github_markdown_css_path = SIMPLE_HISTORY_PATH . '/css/github-markdown.css';
340
 
341
  printf(
342
  '
381
  esc_url( $repo ) // 4
382
  );
383
 
384
+ // echo($response_body);
 
385
  exit;
386
 
387
  }
394
  function on_action_delete_selected() {
395
 
396
  // Same as in plugins.php
397
+ if ( ! current_user_can( 'delete_plugins' ) ) {
398
+ wp_die( __( 'You do not have sufficient permissions to delete plugins for this site.' ) );
399
  }
400
 
401
  // Verify delete must be set
402
+ if ( ! isset( $_POST['verify-delete'] ) || ! $_POST['verify-delete'] ) {
403
  return;
404
  }
405
 
406
  // An arr of plugins must be set
407
+ if ( ! isset( $_POST['checked'] ) || ! is_array( $_POST['checked'] ) ) {
408
  return;
409
  }
410
 
411
  // If we get this far it looks like a plugin is begin deleted
412
  // Get and save info about it
 
413
  $this->save_versions_before_update();
414
 
 
415
  }
416
 
417
  /**
418
  * Saves info about all installed plugins to an option.
419
  * When we are done logging then we remove the option.
420
  */
421
+ function save_versions_before_update( $bool = null, $hook_extra = null ) {
422
 
423
  $plugins = get_plugins();
424
 
425
  // does not work
426
+ $option_name = $this->slug . '_plugin_info_before_update';
427
 
428
  $r = update_option( $option_name, SimpleHistory::json_encode( $plugins ) );
429
 
437
  * set_transient('plugins_delete_result_' . $user_ID, $delete_result);
438
  *
439
  * We detect when that transient is set and then we have all info needed to log the plugin delete
 
440
  */
441
+ public function on_setted_transient_for_remove_files( $transient = '', $value = '' ) {
442
 
443
  if ( ! $user_id = get_current_user_id() ) {
444
  return;
451
 
452
  // We found the transient we were looking for
453
  if (
454
+ isset( $_POST['action'] )
455
+ && 'delete-selected' == $_POST['action']
456
+ && isset( $_POST['checked'] )
457
+ && is_array( $_POST['checked'] )
458
  ) {
459
 
460
  /*
464
  )
465
  */
466
 
467
+ $plugins_deleted = $_POST['checked'];
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,// plugin-name-folder/plugin-main-file.php
474
  );
475
 
476
  if ( is_array( $plugins_before_update ) && isset( $plugins_before_update[ $plugin ] ) ) {
477
+ $context['plugin_name'] = $plugins_before_update[ $plugin ]['Name'];
478
+ $context['plugin_title'] = $plugins_before_update[ $plugin ]['Title'];
479
+ $context['plugin_description'] = $plugins_before_update[ $plugin ]['Description'];
480
+ $context['plugin_author'] = $plugins_before_update[ $plugin ]['Author'];
481
+ $context['plugin_version'] = $plugins_before_update[ $plugin ]['Version'];
482
+ $context['plugin_url'] = $plugins_before_update[ $plugin ]['PluginURI'];
483
  }
484
 
485
  $this->infoMessage(
486
+ 'plugin_deleted',
487
  $context
488
  );
489
 
490
  }
 
491
  }
492
 
493
  $this->remove_saved_versions();
498
  * Save all plugin information before a plugin is updated or removed.
499
  * This way we can know both the old (pre updated/removed) and the current version of the plugin
500
  */
501
+ /*
502
+ public function save_versions_before_update() {
503
 
504
  $current_screen = get_current_screen();
505
  $request_uri = $_SERVER["SCRIPT_NAME"];
536
  */
537
 
538
  /**
539
+ * when plugin updates are done wp_clean_plugins_cache() is called,
540
+ * which in its turn run:
541
+ * delete_site_transient( 'update_plugins' );
542
+ * do_action( 'delete_site_transient_' . $transient, $transient );
543
+ * delete_site_transient_update_plugins
544
+ */
545
  public function remove_saved_versions() {
546
 
547
+ delete_option( $this->slug . '_plugin_info_before_update' );
548
 
549
  }
550
 
556
  * be a Theme_Upgrader or Core_Upgrade instance.
557
  * @param array $data {
558
  * Array of bulk item update data.
 
559
  */
560
  function on_upgrader_process_complete( $plugin_upgrader_instance, $arr_data ) {
561
 
562
  // Can't use get_plugins() here to get version of plugins updated from
563
  // Tested that, and it will get the new version (and that's the correct answer I guess. but too bad for us..)
 
564
  /*
565
  If an update fails then $plugin_upgrader_instance->skin->result->errors contains something like:
566
  Array
574
  */
575
 
576
  /*
 
577
  # Contents of $arr_data in different scenarios
578
 
579
  ## WordPress core update
620
  // only if we did not log anything
621
  $did_log = false;
622
 
623
+ if ( isset( $arr_data['type'] ) && 'plugin' == $arr_data['type'] ) {
624
 
625
  // Single plugin install
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 = isset( $plugin_upgrader_instance->skin->result ) && is_array( $plugin_upgrader_instance->skin->result ) ? $plugin_upgrader_instance->skin->result : array();
630
  $upgrader_skin_api = isset( $plugin_upgrader_instance->skin->api ) ? $plugin_upgrader_instance->skin->api : (object) array();
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' => $plugin_slug,
637
+ 'plugin_name' => isset( $upgrader_skin_api->name ) ? $upgrader_skin_api->name : '',
638
+ 'plugin_version' => isset( $upgrader_skin_api->version ) ? $upgrader_skin_api->version : '',
639
+ 'plugin_author' => isset( $upgrader_skin_api->author ) ? $upgrader_skin_api->author : '',
640
+ 'plugin_last_updated' => isset( $upgrader_skin_api->last_updated ) ? $upgrader_skin_api->last_updated : '',
641
+ 'plugin_requires' => isset( $upgrader_skin_api->requires ) ? $upgrader_skin_api->requires : '',
642
+ 'plugin_tested' => isset( $upgrader_skin_api->tested ) ? $upgrader_skin_api->tested : '',
643
+ 'plugin_rating' => isset( $upgrader_skin_api->rating ) ? $upgrader_skin_api->rating : '',
644
+ 'plugin_num_ratings' => isset( $upgrader_skin_api->num_ratings ) ? $upgrader_skin_api->num_ratings : '',
645
+ 'plugin_downloaded' => isset( $upgrader_skin_api->downloaded ) ? $upgrader_skin_api->downloaded : '',
646
+ 'plugin_added' => isset( $upgrader_skin_api->added ) ? $upgrader_skin_api->added : '',
647
+ 'plugin_source_files' => $this->simpleHistory->json_encode( $plugin_upgrader_instance->result['source_files'] ),
648
 
649
  // To debug comment out these:
650
  // "debug_skin_options" => $this->simpleHistory->json_encode( $upgrader_skin_options ),
651
  // "debug_skin_result" => $this->simpleHistory->json_encode( $upgrader_skin_result ),
 
652
  );
653
 
654
  /*
661
 
662
  Also: plugins hosted at GitHub have a de-facto standard field of "GitHub Plugin URI"
663
  */
664
+ $install_source = 'unknown';
665
+ if ( isset( $upgrader_skin_options['type'] ) ) {
666
+ $install_source = (string) $upgrader_skin_options['type'];
667
  }
668
 
669
+ $context['plugin_install_source'] = $install_source;
670
 
671
  // If uploaded plugin store name of ZIP
672
+ if ( 'upload' == $install_source ) {
673
 
674
+ /*
675
+ _debug_files
676
  {
677
  "pluginzip": {
678
  "name": "WPThumb-master.zip",
684
  }
685
  */
686
 
687
+ if ( isset( $_FILES['pluginzip']['name'] ) ) {
688
+ $plugin_upload_name = $_FILES['pluginzip']['name'];
689
+ $context['plugin_upload_name'] = $plugin_upload_name;
690
  }
 
691
  }
692
 
693
+ if ( is_a( $plugin_upgrader_instance->skin->result, 'WP_Error' ) ) {
 
694
 
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'] = $this->simpleHistory->json_encode( $plugin_upgrader_instance->skin->result->error_data );
699
 
700
  $this->infoMessage(
701
  'plugin_installed_failed',
709
  // Plugin was successfully installed
710
  // Try to grab more info from the readme
711
  // Would be nice to grab a screenshot, but that is difficult since they often are stored remotely
712
+ $plugin_destination = isset( $plugin_upgrader_instance->result['destination'] ) ? $plugin_upgrader_instance->result['destination'] : null;
713
 
714
  if ( $plugin_destination ) {
715
 
720
  $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_info, true, false );
721
  }
722
 
723
+ $context['plugin_name'] = isset( $plugin_data['Name'] ) ? $plugin_data['Name'] : '';
724
+ $context['plugin_description'] = isset( $plugin_data['Description'] ) ? $plugin_data['Description'] : '';
725
+ $context['plugin_url'] = isset( $plugin_data['PluginURI'] ) ? $plugin_data['PluginURI'] : '';
726
+ $context['plugin_version'] = isset( $plugin_data['Version'] ) ? $plugin_data['Version'] : '';
727
+ $context['plugin_author'] = isset( $plugin_data['AuthorName'] ) ? $plugin_data['AuthorName'] : '';
728
 
729
  // Comment out these to debug plugin installs
730
+ // $context["debug_plugin_data"] = $this->simpleHistory->json_encode( $plugin_data );
731
+ // $context["debug_plugin_info"] = $this->simpleHistory->json_encode( $plugin_info );
732
+ if ( ! empty( $plugin_data['GitHub Plugin URI'] ) ) {
733
+ $context['plugin_github_url'] = $plugin_data['GitHub Plugin URI'];
 
734
  }
 
735
  }
736
 
737
  $this->infoMessage(
741
 
742
  $did_log = true;
743
 
744
+ }// End if().
745
+ } // End if().
 
746
 
747
  // Single plugin update
748
+ if ( isset( $arr_data['action'] ) && 'update' == $arr_data['action'] && ! $plugin_upgrader_instance->bulk ) {
749
 
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
757
+ $plugin_slug = dirname( $arr_data['plugin'] );
758
 
759
  $context = array(
760
+ 'plugin_slug' => $plugin_slug,
761
+ 'request' => $this->simpleHistory->json_encode( $_REQUEST ),
762
+ 'plugin_name' => $plugin_data['Name'],
763
+ 'plugin_title' => $plugin_data['Title'],
764
+ 'plugin_description' => $plugin_data['Description'],
765
+ 'plugin_author' => $plugin_data['Author'],
766
+ 'plugin_version' => $plugin_data['Version'],
767
+ 'plugin_url' => $plugin_data['PluginURI'],
768
+ 'plugin_source_files' => $this->simpleHistory->json_encode( $plugin_upgrader_instance->result['source_files'] ),
769
  );
770
 
771
  // update status for plugins are in response
772
  // plugin folder + index file = key
773
  // use transient to get url and package
774
  $update_plugins = get_site_transient( 'update_plugins' );
775
+ if ( $update_plugins && isset( $update_plugins->response[ $arr_data['plugin'] ] ) ) {
776
 
777
  /*
778
  $update_plugins[plugin_path/slug]:
787
  */
788
  // for debug purposes the update_plugins key can be added
789
  // $context["update_plugins"] = $this->simpleHistory->json_encode( $update_plugins );
790
+ $plugin_update_info = $update_plugins->response[ $arr_data['plugin'] ];
 
791
 
792
  // autoptimize/autoptimize.php
793
  if ( isset( $plugin_update_info->plugin ) ) {
794
+ $context['plugin_update_info_plugin'] = $plugin_update_info->plugin;
795
  }
796
 
797
  // https://downloads.wordpress.org/plugin/autoptimize.1.9.1.zip
798
  if ( isset( $plugin_update_info->package ) ) {
799
+ $context['plugin_update_info_package'] = $plugin_update_info->package;
800
  }
 
801
  }
802
 
803
  // To get old version we use our option
804
+ $plugins_before_update = json_decode( get_option( $this->slug . '_plugin_info_before_update', false ), true );
805
+ if ( is_array( $plugins_before_update ) && isset( $plugins_before_update[ $arr_data['plugin'] ] ) ) {
806
 
807
+ $context['plugin_prev_version'] = $plugins_before_update[ $arr_data['plugin'] ]['Version'];
808
 
809
  }
810
 
811
+ if ( is_a( $plugin_upgrader_instance->skin->result, 'WP_Error' ) ) {
812
 
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'] = json_encode( $plugin_upgrader_instance->skin->result->error_data );
817
 
818
  $this->infoMessage(
819
  'plugin_update_failed',
829
  $context
830
  );
831
 
832
+ // echo "on_upgrader_process_complete";
833
+ // sf_d( $plugin_upgrader_instance, '$plugin_upgrader_instance' );
834
+ // sf_d( $arr_data, '$arr_data' );
 
835
  $did_log = true;
836
 
837
  }
838
+ } // End if().
 
 
839
 
840
  /**
841
  * For bulk updates $arr_data looks like:
851
  * )
852
  * )
853
  */
854
+ if ( isset( $arr_data['bulk'] ) && $arr_data['bulk'] && isset( $arr_data['action'] ) && 'update' == $arr_data['action'] ) {
855
 
856
+ $plugins_updated = isset( $arr_data['plugins'] ) ? (array) $arr_data['plugins'] : array();
857
 
858
+ foreach ( $plugins_updated as $plugin_name ) {
859
 
860
  $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name, true, false );
861
 
862
  $plugin_slug = dirname( $plugin_name );
863
 
864
  $context = array(
865
+ 'plugin_slug' => $plugin_slug,
866
+ 'plugin_name' => $plugin_data['Name'],
867
+ 'plugin_title' => $plugin_data['Title'],
868
+ 'plugin_description' => $plugin_data['Description'],
869
+ 'plugin_author' => $plugin_data['Author'],
870
+ 'plugin_version' => $plugin_data['Version'],
871
+ 'plugin_url' => $plugin_data['PluginURI'],
872
  );
873
 
874
  // get url and package
891
 
892
  // autoptimize/autoptimize.php
893
  if ( isset( $plugin_update_info->plugin ) ) {
894
+ $context['plugin_update_info_plugin'] = $plugin_update_info->plugin;
895
  }
896
 
897
  // https://downloads.wordpress.org/plugin/autoptimize.1.9.1.zip
898
  if ( isset( $plugin_update_info->package ) ) {
899
+ $context['plugin_update_info_package'] = $plugin_update_info->package;
900
  }
 
901
  }
902
 
903
  // To get old version we use our option
904
  // @TODO: this does not always work, why?
905
+ $plugins_before_update = json_decode( get_option( $this->slug . '_plugin_info_before_update', false ), true );
906
  if ( is_array( $plugins_before_update ) && isset( $plugins_before_update[ $plugin_name ] ) ) {
907
 
908
+ $context['plugin_prev_version'] = $plugins_before_update[ $plugin_name ]['Version'];
909
 
910
  }
911
 
914
  $context
915
  );
916
 
917
+ }// End foreach().
918
+ }// End if().
919
+ } // End if().
 
 
 
920
 
921
  if ( ! $did_log ) {
922
+ // echo "on_upgrader_process_complete";
923
+ // sf_d( $plugin_upgrader_instance, '$plugin_upgrader_instance' );
924
+ // sf_d( $arr_data, '$arr_data' );
925
+ // exit;
926
  }
927
 
928
  $this->remove_saved_versions();
934
  * Plugin is activated
935
  * plugin_name is like admin-menu-tree-page-view/index.php
936
  */
937
+ function on_activated_plugin( $plugin_name, $network_wide ) {
938
 
939
  /*
940
  Plugin data returned array contains the following:
954
  $plugin_slug = dirname( $plugin_name );
955
 
956
  $context = array(
957
+ 'plugin_name' => $plugin_data['Name'],
958
+ 'plugin_slug' => $plugin_slug,
959
+ 'plugin_title' => $plugin_data['Title'],
960
+ 'plugin_description' => $plugin_data['Description'],
961
+ 'plugin_author' => $plugin_data['Author'],
962
+ 'plugin_version' => $plugin_data['Version'],
963
+ 'plugin_url' => $plugin_data['PluginURI'],
964
  );
965
 
966
+ if ( ! empty( $plugin_data['GitHub Plugin URI'] ) ) {
967
+ $context['plugin_github_url'] = $plugin_data['GitHub Plugin URI'];
968
  }
969
 
970
  $this->infoMessage( 'plugin_activated', $context );
975
  * Plugin is deactivated
976
  * plugin_name is like admin-menu-tree-page-view/index.php
977
  */
978
+ function on_deactivated_plugin( $plugin_name ) {
979
 
980
  $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_name, true, false );
981
  $plugin_slug = dirname( $plugin_name );
982
 
983
  $context = array(
984
+ 'plugin_name' => $plugin_data['Name'],
985
+ 'plugin_slug' => $plugin_slug,
986
+ 'plugin_title' => $plugin_data['Title'],
987
+ 'plugin_description' => $plugin_data['Description'],
988
+ 'plugin_author' => $plugin_data['Author'],
989
+ 'plugin_version' => $plugin_data['Version'],
990
+ 'plugin_url' => $plugin_data['PluginURI'],
991
  );
992
 
993
+ if ( ! empty( $plugin_data['GitHub Plugin URI'] ) ) {
994
+ $context['plugin_github_url'] = $plugin_data['GitHub Plugin URI'];
995
  }
996
 
997
  $this->infoMessage( 'plugin_deactivated', $context );
1002
  /**
1003
  * Get output for detailed log section
1004
  */
1005
+ function getLogRowDetailsOutput( $row ) {
1006
 
1007
  $context = $row->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,
1013
  // and when something is installed the description is most useul for other
1014
  // admins on the site
1015
+ if ( 'plugin_installed' === $message_key ) {
1016
 
1017
+ if ( isset( $context['plugin_description'] ) ) {
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 = strpos( $plugin_description, '<cite>' );
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' => _x( 'Description', 'plugin logger - detailed output', 'simple-history' ),
1029
+ 'plugin_install_source' => _x( 'Source', 'plugin logger - detailed output install source', 'simple-history' ),
1030
+ 'plugin_install_source_file' => _x( 'Source file name', 'plugin logger - detailed output install source', 'simple-history' ),
1031
+ 'plugin_version' => _x( 'Version', 'plugin logger - detailed output version', 'simple-history' ),
1032
+ 'plugin_author' => _x( 'Author', 'plugin logger - detailed output author', 'simple-history' ),
1033
+ 'plugin_url' => _x( 'URL', 'plugin logger - detailed output url', 'simple-history' ),
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"),
1037
  // also available: plugin_rating, plugin_num_ratings
1038
  );
1039
 
1040
+ $arr_plugin_keys = apply_filters( 'simple_history/plugin_logger/row_details_plugin_info_keys', $arr_plugin_keys );
1041
 
1042
  // Start output of plugin meta data table
1043
  $output .= "<table class='SimpleHistoryLogitem__keyValueTable'>";
1044
 
1045
  foreach ( $arr_plugin_keys as $key => $desc ) {
1046
 
1047
+ $desc_output = '';
1048
 
1049
  switch ( $key ) {
1050
 
1051
+ case 'plugin_downloaded':
1052
  $desc_output = esc_html( number_format_i18n( (int) $context[ $key ] ) );
1053
  break;
1054
 
1055
  // author is already formatted
1056
+ case 'plugin_author':
1057
  $desc_output = $context[ $key ];
1058
  break;
1059
 
1060
  // URL needs a link
1061
+ case 'plugin_url':
1062
+ $desc_output = sprintf( '<a href="%1$s">%2$s</a>', esc_attr( $context['plugin_url'] ), esc_html( $context['plugin_url'] ) );
1063
  break;
1064
 
1065
+ case 'plugin_description':
1066
  $desc_output = $plugin_description;
1067
  break;
1068
 
1069
+ case 'plugin_install_source':
1070
 
1071
  if ( ! isset( $context[ $key ] ) ) {
1072
  continue;
1073
  }
1074
 
1075
+ if ( 'web' == $context[ $key ] ) {
1076
+ $desc_output = esc_html( __( 'WordPress Plugin Repository', 'simple-history' ) );
1077
+ } elseif ( 'upload' == $context[ $key ] ) {
1078
+ // $plugin_upload_name = isset( $context["plugin_upload_name"] ) ? $context["plugin_upload_name"] : __("Unknown archive name", "simple-history");
1079
+ $desc_output = esc_html( __( 'Uploaded ZIP archive', 'simple-history' ) );
1080
+ // $desc_output = esc_html( sprintf( __('Uploaded ZIP archive (%1$s)', "simple-history"), $plugin_upload_name ) );
1081
+ // $desc_output = esc_html( sprintf( __('%1$s (uploaded ZIP archive)', "simple-history"), $plugin_upload_name ) );
1082
  } else {
1083
  $desc_output = esc_html( $context[ $key ] );
1084
  }
1085
 
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 = esc_html( $plugin_upload_name );
1097
  }
1098
 
1101
  default;
1102
  $desc_output = esc_html( $context[ $key ] );
1103
  break;
1104
+ }// End switch().
1105
 
1106
  if ( ! trim( $desc_output ) ) {
1107
  continue;
1114
  <td>%2$s</td>
1115
  </tr>
1116
  ',
1117
+ esc_html( $desc ),
1118
  $desc_output
1119
  );
1120
 
1121
+ }// End foreach().
1122
 
1123
  // Add link with more info about the plugin
1124
  // If plugin_install_source = web then it should be a wordpress.org-plugin
1125
  // If plugin_github_url is set then it's a zip from a github thingie
1126
  // so use link to that.
1127
+ $plugin_slug = ! empty( $context['plugin_slug'] ) ? $context['plugin_slug'] : '';
 
1128
 
1129
  // Slug + web as install source = show link to wordpress.org
1130
+ if ( $plugin_slug && isset( $context['plugin_install_source'] ) && $context['plugin_install_source'] == 'web' ) {
1131
 
1132
  $output .= sprintf(
1133
  '
1137
  </tr>
1138
  ',
1139
  admin_url( "plugin-install.php?tab=plugin-information&amp;plugin={$plugin_slug}&amp;section=&amp;TB_iframe=true&amp;width=640&amp;height=550" ),
1140
+ esc_html_x( 'View plugin info', 'plugin logger: plugin info thickbox title view all info', 'simple-history' )
1141
  );
1142
 
1143
+ } // End if().
1144
+ elseif ( isset( $context['plugin_install_source'] ) && $context['plugin_install_source'] == 'upload' && ! empty( $context['plugin_github_url'] ) ) {
 
1145
 
1146
  // Can't embed iframe
1147
  // Must use API instead
1148
  // https://api.github.com/repos/<username>/<repo>/readme?callback=<callbackname>
 
1149
  $output .= sprintf(
1150
  '
1151
  <tr>
1153
  <td><a title="%2$s" class="thickbox" href="%1$s">%2$s</a></td>
1154
  </tr>
1155
  ',
1156
+ admin_url( sprintf( 'admin-ajax.php?action=SimplePluginLogger_GetGitHubPluginInfo&getrepo&amp;repo=%1$s&amp;TB_iframe=true&amp;width=640&amp;height=550', esc_url_raw( $context['plugin_github_url'] ) ) ),
1157
+ esc_html_x( 'View plugin info', 'plugin logger: plugin info thickbox title view all info', 'simple-history' )
1158
  );
1159
 
1160
  }
1161
 
1162
+ $output .= '</table>';
 
 
1163
 
1164
+ }// End if().
1165
+ } elseif ( 'plugin_bulk_updated' === $message_key || 'plugin_updated' === $message_key || 'plugin_activated' === $message_key || 'plugin_deactivated' === $message_key ) {
1166
 
1167
+ $plugin_slug = ! empty( $context['plugin_slug'] ) ? $context['plugin_slug'] : '';
1168
 
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 = admin_url( "plugin-install.php?tab=plugin-information&amp;plugin={$plugin_slug}&amp;section=&amp;TB_iframe=true&amp;width=640&amp;height=550" );
1173
 
1174
+ if ( 'plugin_updated' == $message_key || 'plugin_bulk_updated' == $message_key ) {
1175
 
1176
+ $link_title = esc_html_x( 'View changelog', 'plugin logger: plugin info thickbox title', 'simple-history' );
1177
 
1178
  if ( is_multisite() ) {
1179
  $url = network_admin_url( "plugin-install.php?tab=plugin-information&amp;plugin={$plugin_slug}&amp;section=changelog&amp;TB_iframe=true&amp;width=772&amp;height=550" );
1180
  } else {
1181
  $url = admin_url( "plugin-install.php?tab=plugin-information&amp;plugin={$plugin_slug}&amp;section=changelog&amp;TB_iframe=true&amp;width=772&amp;height=550" );
1182
  }
 
1183
  }
1184
 
1185
  $output .= sprintf(
1188
  $link_title
1189
  );
1190
 
1191
+ } elseif ( ! empty( $context['plugin_github_url'] ) ) {
1192
 
1193
  $output .= sprintf(
1194
  '
1197
  <td><a title="%2$s" class="thickbox" href="%1$s">%2$s</a></td>
1198
  </tr>
1199
  ',
1200
+ admin_url( sprintf( 'admin-ajax.php?action=SimplePluginLogger_GetGitHubPluginInfo&getrepo&amp;repo=%1$s&amp;TB_iframe=true&amp;width=640&amp;height=550', esc_url_raw( $context['plugin_github_url'] ) ) ),
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;
1208
 
loggers/SimplePostLogger.php CHANGED
@@ -6,8 +6,8 @@ defined( 'ABSPATH' ) or die();
6
  /**
7
  * Logs changes to posts and pages, including custom post types
8
  */
9
- class SimplePostLogger extends SimpleLogger
10
- {
11
 
12
  // The logger slug. Defaulting to the class name is nice and logical I think
13
  public $slug = __CLASS__;
@@ -17,14 +17,14 @@ class SimplePostLogger extends SimpleLogger
17
 
18
  public function loaded() {
19
 
20
- add_action("admin_action_editpost", array($this, "on_admin_action_editpost"));
21
- add_action("transition_post_status", array($this, "on_transition_post_status"), 10, 3);
22
- add_action("delete_post", array($this, "on_delete_post"));
23
- add_action("untrash_post", array($this, "on_untrash_post"));
24
 
25
  $this->add_xml_rpc_hooks();
26
 
27
- add_filter("simple_history/rss_item_link", array($this, "filter_rss_item_link"), 10, 2);
28
 
29
  }
30
 
@@ -40,23 +40,23 @@ class SimplePostLogger extends SimpleLogger
40
  }, 10, 1);
41
  */
42
 
43
- add_action('xmlrpc_call_success_blogger_newPost', array($this, "on_xmlrpc_newPost"), 10, 2);
44
- add_action('xmlrpc_call_success_mw_newPost', array($this, "on_xmlrpc_newPost"), 10,2 );
45
 
46
- add_action('xmlrpc_call_success_blogger_editPost', array($this, "on_xmlrpc_editPost"), 10, 2);
47
- add_action('xmlrpc_call_success_mw_editPost', array($this, "on_xmlrpc_editPost"), 10, 2);
48
 
49
- add_action('xmlrpc_call_success_blogger_deletePost', array($this, "on_xmlrpc_deletePost"), 10, 2);
50
- add_action('xmlrpc_call_success_wp_deletePage', array($this, "on_xmlrpc_deletePost"), 10, 2);
51
 
52
- add_action("xmlrpc_call", array($this, "on_xmlrpc_call"), 10, 1);
53
 
54
  }
55
 
56
- function on_xmlrpc_call($method) {
57
 
58
  $arr_methods_to_act_on = array(
59
- "wp.deletePost"
60
  );
61
 
62
  $raw_post_data = null;
@@ -66,21 +66,21 @@ class SimplePostLogger extends SimpleLogger
66
  if ( in_array( $method, $arr_methods_to_act_on ) ) {
67
 
68
  // Setup common stuff
69
- $raw_post_data = file_get_contents("php://input");
70
- $context["wp.deletePost.xmldata"] = $this->simpleHistory->json_encode( $raw_post_data );
71
  $message = new IXR_Message( $raw_post_data );
72
 
73
  if ( ! $message->parse() ) {
74
  return;
75
  }
76
 
77
- $context["wp.deletePost.xmlrpc_message"] = $this->simpleHistory->json_encode( $message );
78
- $context["wp.deletePost.xmlrpc_message.messageType"] = $this->simpleHistory->json_encode( $message->messageType );
79
- $context["wp.deletePost.xmlrpc_message.methodName"] = $this->simpleHistory->json_encode( $message->methodName );
80
- $context["wp.deletePost.xmlrpc_message.messageParams"] = $this->simpleHistory->json_encode( $message->params );
81
 
82
  // Actions for delete post
83
- if ( "wp.deletePost" == $method ) {
84
 
85
  // 4 params, where the last is the post id
86
  if ( ! isset( $message->params[3] ) ) {
@@ -92,17 +92,15 @@ class SimplePostLogger extends SimpleLogger
92
  $post = get_post( $post_ID );
93
 
94
  $context = array(
95
- "post_id" => $post->ID,
96
- "post_type" => get_post_type( $post ),
97
- "post_title" => get_the_title( $post )
98
  );
99
 
100
- $this->infoMessage( "post_trashed", $context );
101
-
102
 
103
- } // if delete post
104
-
105
- }
106
 
107
  }
108
 
@@ -115,39 +113,39 @@ class SimplePostLogger extends SimpleLogger
115
  function getInfo() {
116
 
117
  $arr_info = array(
118
- "name" => "Post Logger",
119
- "description" => "Logs the creation and modification of posts and pages",
120
- "capability" => "edit_pages",
121
- "messages" => array(
122
- 'post_created' => __('Created {post_type} "{post_title}"', 'simple-history'),
123
- 'post_updated' => __('Updated {post_type} "{post_title}"', 'simple-history'),
124
- 'post_restored' => __('Restored {post_type} "{post_title}" from trash', 'simple-history'),
125
- 'post_deleted' => __('Deleted {post_type} "{post_title}"', 'simple-history'),
126
- 'post_trashed' => __('Moved {post_type} "{post_title}" to the trash', 'simple-history')
127
  ),
128
- "labels" => array(
129
- "search" => array(
130
- "label" => _x("Posts & Pages", "Post logger: search", "simple-history"),
131
- "label_all" => _x("All posts & pages activity", "Post logger: search", "simple-history"),
132
- "options" => array(
133
- _x("Posts created", "Post logger: search", "simple-history") => array(
134
- "post_created"
135
  ),
136
- _x("Posts updated", "Post logger: search", "simple-history") => array(
137
- "post_updated"
138
  ),
139
- _x("Posts trashed", "Post logger: search", "simple-history") => array(
140
- "post_trashed"
141
  ),
142
- _x("Posts deleted", "Post logger: search", "simple-history") => array(
143
- "post_deleted"
144
  ),
145
- _x("Posts restored", "Post logger: search", "simple-history") => array(
146
- "post_restored"
147
  ),
148
- )
149
- ) // end search array
150
- ) // end labels
151
 
152
  );
153
 
@@ -166,7 +164,7 @@ class SimplePostLogger extends SimpleLogger
166
  */
167
  function on_admin_action_editpost() {
168
 
169
- $post_ID = isset( $_POST["post_ID"] ) ? (int) $_POST["post_ID"] : 0;
170
 
171
  if ( ! $post_ID ) {
172
  return;
@@ -178,9 +176,9 @@ class SimplePostLogger extends SimpleLogger
178
 
179
  $prev_post_data = get_post( $post_ID );
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
  }
@@ -193,17 +191,17 @@ class SimplePostLogger extends SimpleLogger
193
  * @param int $post_ID ID of the deleted post.
194
  * @param array $args An array of arguments to delete the post.
195
  */
196
- function on_xmlrpc_deletePost($post_ID, $args) {
197
 
198
  $post = get_post( $post_ID );
199
 
200
  $context = array(
201
- "post_id" => $post->ID,
202
- "post_type" => get_post_type( $post ),
203
- "post_title" => get_the_title( $post )
204
  );
205
 
206
- $this->infoMessage( "post_deleted", $context );
207
 
208
  }
209
 
@@ -215,17 +213,17 @@ class SimplePostLogger extends SimpleLogger
215
  * @param int $post_ID ID of the updated post.
216
  * @param array $args An array of arguments for the post to edit.
217
  */
218
- function on_xmlrpc_editPost($post_ID, $args) {
219
 
220
  $post = get_post( $post_ID );
221
 
222
  $context = array(
223
- "post_id" => $post->ID,
224
- "post_type" => get_post_type( $post ),
225
- "post_title" => get_the_title( $post )
226
  );
227
 
228
- $this->infoMessage( "post_updated", $context );
229
 
230
  }
231
 
@@ -237,33 +235,33 @@ class SimplePostLogger extends SimpleLogger
237
  * @param int $post_ID ID of the new post.
238
  * @param array $args An array of new post arguments.
239
  */
240
- function on_xmlrpc_newPost($post_ID, $args) {
241
 
242
  $post = get_post( $post_ID );
243
 
244
  $context = array(
245
- "post_id" => $post->ID,
246
- "post_type" => get_post_type( $post ),
247
- "post_title" => get_the_title( $post )
248
  );
249
 
250
- $this->infoMessage( "post_created", $context );
251
 
252
  }
253
 
254
  /**
255
  * Called when a post is restored from the trash
256
  */
257
- function on_untrash_post($post_id) {
258
 
259
  $post = get_post( $post_id );
260
 
261
  $this->infoMessage(
262
- "post_restored",
263
  array(
264
- "post_id" => $post_id,
265
- "post_type" => get_post_type( $post ),
266
- "post_title" => get_the_title( $post )
267
  )
268
  );
269
 
@@ -272,19 +270,19 @@ class SimplePostLogger extends SimpleLogger
272
  /**
273
  * Called when a post is deleted from the trash
274
  */
275
- function on_delete_post($post_id) {
276
 
277
- $post = get_post($post_id);
278
 
279
- if ( wp_is_post_revision($post_id) ) {
280
  return;
281
  }
282
 
283
- if ( $post->post_status === "auto-draft" || $post->post_status === "inherit" ) {
284
  return;
285
  }
286
 
287
- if ( "nav_menu_item" == get_post_type( $post ) ) {
288
  return;
289
  }
290
 
@@ -320,11 +318,11 @@ class SimplePostLogger extends SimpleLogger
320
 
321
 
322
  /**
323
- * Fired when a post has changed status
324
- * Only run in certain cases,
325
- * because when always enabled it catches a lots of edits made by plugins during cron jobs etc,
326
- * which by definition is not wrong, but perhaps not wanted/annoying
327
- */
328
  function on_transition_post_status( $new_status, $old_status, $post ) {
329
 
330
  $ok_to_log = true;
@@ -338,7 +336,7 @@ class SimplePostLogger extends SimpleLogger
338
 
339
  // except when calls are from/for jetpack/wordpress apps
340
  // seems to be jetpack/app request when $_GET["for"] == "jetpack
341
- if ( defined("XMLRPC_REQUEST") && XMLRPC_REQUEST && isset( $_GET["for"] ) && $_GET["for"] === "jetpack" ) {
342
  $ok_to_log = true;
343
  }
344
 
@@ -383,50 +381,50 @@ class SimplePostLogger extends SimpleLogger
383
  if not from & to = same, then user has changed something
384
  */
385
  $context = array(
386
- "post_id" => $post->ID,
387
- "post_type" => get_post_type($post),
388
- "post_title" => get_the_title($post)
389
  );
390
 
391
- if ( $old_status == "auto-draft" && ($new_status != "auto-draft" && $new_status != "inherit") ) {
392
 
393
  // Post created
394
- $this->infoMessage( "post_created", $context );
395
 
396
- } elseif ( $new_status == "auto-draft" || ($old_status == "new" && $new_status == "inherit") ) {
397
 
398
  // Post was automagically saved by WordPress
399
  return;
400
 
401
- } elseif ( $new_status == "trash" ) {
402
 
403
  // Post trashed
404
- $this->infoMessage( "post_trashed", $context );
405
 
406
  } else {
407
 
408
  // Post updated
409
  // Also add diff between previod saved data and new data
410
- if ( isset( $this->old_post_data[$post->ID] ) ) {
411
 
412
- $old_post_data = $this->old_post_data[$post->ID];
413
 
414
  $new_post_data = array(
415
- "post_data" => $post,
416
- "post_meta" => get_post_custom($post->ID)
417
  );
418
 
419
  // Now we have both old and new post data, including custom fields, in the same format
420
  // So let's compare!
421
- $context = $this->add_post_data_diff_to_context($context, $old_post_data, $new_post_data);
422
 
423
  }
424
 
425
- $context["_occasionsID"] = __CLASS__ . '/' . __FUNCTION__ . "/post_updated/{$post->ID}";
426
 
427
- $this->infoMessage( "post_updated", $context );
428
 
429
- }
430
 
431
  }
432
 
@@ -441,35 +439,34 @@ class SimplePostLogger extends SimpleLogger
441
  * - tags
442
  * @return array $context with diff data added
443
  */
444
- function add_post_data_diff_to_context($context, $old_post_data, $new_post_data) {
445
 
446
- $old_data = $old_post_data["post_data"];
447
- $new_data = $new_post_data["post_data"];
448
 
449
  // Will contain the differences
450
  $post_data_diff = array();
451
 
452
  $arr_keys_to_diff = array(
453
- "post_title",
454
- "post_name",
455
- "post_content",
456
- "post_status",
457
- "menu_order",
458
- "post_date",
459
- "post_date_gmt",
460
- "post_excerpt",
461
- "comment_status",
462
- "ping_status",
463
- "post_parent", // only id, need to get context for that, like name of parent at least?
464
- "post_author" // only id, need to get context for that, like name, login, email at least?
465
  );
466
 
467
  foreach ( $arr_keys_to_diff as $key ) {
468
 
469
  if ( isset( $old_data->$key ) && isset( $new_data->$key ) ) {
470
- $post_data_diff = $this->add_diff($post_data_diff, $key, $old_data->$key, $new_data->$key);
471
  }
472
-
473
  }
474
 
475
  // If changes where detected
@@ -479,84 +476,64 @@ class SimplePostLogger extends SimpleLogger
479
  // Save at least 2 values for each detected value change, i.e. the old value and the new value
480
  foreach ( $post_data_diff as $diff_key => $diff_values ) {
481
 
482
- $context["post_prev_{$diff_key}"] = $diff_values["old"];
483
- $context["post_new_{$diff_key}"] = $diff_values["new"];
484
 
485
  // If post_author then get more author info
486
  // Because just a user ID does not get us far
487
- if ( "post_author" == $diff_key ) {
488
 
489
- $old_author_user = get_userdata( (int) $diff_values["old"] );
490
- $new_author_user = get_userdata( (int) $diff_values["new"] );
491
 
492
- if ( is_a( $old_author_user, "WP_User" ) && is_a( $new_author_user, "WP_User" ) ) {
493
 
494
- $context["post_prev_{$diff_key}/user_login"] = $old_author_user->user_login;
495
- $context["post_prev_{$diff_key}/user_email"] = $old_author_user->user_email;
496
- $context["post_prev_{$diff_key}/display_name"] = $old_author_user->display_name;
497
 
498
- $context["post_new_{$diff_key}/user_login"] = $new_author_user->user_login;
499
- $context["post_new_{$diff_key}/user_email"] = $new_author_user->user_email;
500
- $context["post_new_{$diff_key}/display_name"] = $new_author_user->display_name;
501
 
502
  }
503
-
504
  }
505
-
506
- // If post parent changed then
507
- // store info about old and new parent
508
- /*
509
- sf_d($post_data_diff);exit;
510
- post_parent] => Array
511
- (
512
- [old] => 0
513
- [new] => 25556
514
- )
515
- */
516
-
517
-
518
-
519
  }
520
-
521
- } // post_data_diff
522
-
523
 
524
  // Compare custom fields
525
-
526
  // Array with custom field keys to ignore because changed everytime or very internal
527
  $arr_meta_keys_to_ignore = array(
528
- "_edit_lock",
529
- "_edit_last",
530
- "_post_restored_from",
531
- "_wp_page_template"
532
  );
533
 
534
  $meta_changes = array(
535
- "added" => array(),
536
- "removed" => array(),
537
- "changed" => array()
538
  );
539
 
540
- $old_meta = $old_post_data["post_meta"];
541
- $new_meta = $new_post_data["post_meta"];
542
 
543
  // @todo: post thumb is stored in _thumbnail_id
544
-
545
  // page template is stored in _wp_page_template
546
- if ( isset( $old_meta["_wp_page_template"][0] ) && isset( $new_meta["_wp_page_template"][0] ) ) {
547
 
548
  /*
549
  Var is string with length 7: default
550
  Var is string with length 20: template-builder.php
551
  */
552
 
553
- if ( $old_meta["_wp_page_template"][0] != $new_meta["_wp_page_template"][0] ) {
554
 
555
  // prev page template is different from new page template
556
-
557
  // store template php file name
558
- $context["post_prev_page_template"] = $old_meta["_wp_page_template"][0];
559
- $context["post_new_page_template"] = $new_meta["_wp_page_template"][0];
560
 
561
  $theme_templates = (array) $this->get_theme_templates();
562
  /*
@@ -568,20 +545,18 @@ class SimplePostLogger extends SimpleLogger
568
  [sidebar-page.php] => Sidebar Template
569
  )
570
  */
571
- if ( isset( $theme_templates[ $context["post_prev_page_template"] ] ) ) {
572
- $context["post_prev_page_template_name"] = $theme_templates[$context["post_prev_page_template"]];
573
  }
574
 
575
- if ( isset( $theme_templates[ $context["post_new_page_template"] ] ) ) {
576
- $context["post_new_page_template_name"] = $theme_templates[$context["post_new_page_template"]];
577
  }
578
-
579
  }
580
-
581
  }
582
 
583
  // Remove fields that we have checked already and other that should be ignored
584
- foreach ($arr_meta_keys_to_ignore as $key_to_ignore) {
585
  unset( $old_meta[ $key_to_ignore ] );
586
  unset( $new_meta[ $key_to_ignore ] );
587
  }
@@ -590,9 +565,8 @@ class SimplePostLogger extends SimpleLogger
590
  foreach ( $new_meta as $meta_key => $meta_value ) {
591
 
592
  if ( ! isset( $old_meta[ $meta_key ] ) ) {
593
- $meta_changes["added"][ $meta_key ] = true;
594
  }
595
-
596
  }
597
 
598
  // Look for removed meta
@@ -613,22 +587,21 @@ class SimplePostLogger extends SimpleLogger
613
  if ( isset( $new_meta[ $meta_key ] ) ) {
614
 
615
  if ( json_encode( $old_meta[ $meta_key ] ) != json_encode( $new_meta[ $meta_key ] ) ) {
616
- $meta_changes["changed"][ $meta_key ] = true;
617
  }
618
  }
619
-
620
  }
621
 
622
- if ( $meta_changes["added"] ) {
623
- $context["post_meta_added"] = sizeof($meta_changes["added"]);
624
  }
625
 
626
- if ( $meta_changes["removed"] ) {
627
- $context["post_meta_removed"] = sizeof($meta_changes["removed"]);
628
  }
629
 
630
- if ( $meta_changes["changed"] ) {
631
- $context["post_meta_changed"] = sizeof($meta_changes["changed"]);
632
  }
633
 
634
  return $context;
@@ -650,8 +623,9 @@ class SimplePostLogger extends SimpleLogger
650
  $files = (array) $theme->get_files( 'php', 1 );
651
 
652
  foreach ( $files as $file => $full_path ) {
653
- if ( ! preg_match( '|Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) )
654
  continue;
 
655
  $page_templates[ $file ] = _cleanup_header_comment( $header[1] );
656
  }
657
 
@@ -664,13 +638,13 @@ class SimplePostLogger extends SimpleLogger
664
  *
665
  * Since 2.0.29
666
  */
667
- function add_diff($post_data_diff, $key, $old_value, $new_value) {
668
 
669
  if ( $old_value != $new_value ) {
670
 
671
- $post_data_diff[$key] = array(
672
- "old" => $old_value,
673
- "new" => $new_value
674
  );
675
 
676
  }
@@ -682,10 +656,10 @@ class SimplePostLogger extends SimpleLogger
682
  /**
683
  * Modify plain output to include link to post
684
  */
685
- public function getLogRowPlainTextOutput($row) {
686
 
687
  $context = $row->context;
688
- $post_id = isset($context["post_id"]) ? $context["post_id"] : 0;
689
 
690
  // Default to original log message
691
  $message = $row->message;
@@ -694,116 +668,111 @@ class SimplePostLogger extends SimpleLogger
694
  // It will return a WP_Post Object if post still is in system
695
  // If post is deleted from trash (not just moved there), then null is returned
696
  $post = get_post( $post_id );
697
- $post_is_available = is_a($post, "WP_Post");
698
-
699
- #sf_d($post_is_available, '$post_is_available');
700
- #sf_d($message_key, '$message_key');
701
 
702
- $message_key = isset($context["_message_key"]) ? $context["_message_key"] : null;
 
 
703
 
704
  // Try to get singular name
705
- $post_type = isset($context["post_type"]) ? $context["post_type"] : "";
706
  $post_type_obj = get_post_type_object( $post_type );
707
  if ( ! is_null( $post_type_obj ) ) {
708
 
709
- if ( ! empty ($post_type_obj->labels->singular_name) ) {
710
- $context["post_type"] = strtolower( $post_type_obj->labels->singular_name );
711
  }
712
-
713
  }
714
 
715
- $context["edit_link"] = get_edit_post_link( $post_id );
716
 
717
  // If post is not available any longer then we can't link to it, so keep plain message then
718
  // Also keep plain format if user is not allowed to edit post (edit link is empty)
719
- if ( $post_is_available && $context["edit_link"] ) {
720
 
721
- if ( "post_updated" == $message_key ) {
722
 
723
- $message = __('Updated {post_type} <a href="{edit_link}">"{post_title}"</a>', "simple-history");
724
 
725
- } else if ( "post_deleted" == $message_key ) {
726
 
727
- $message = __('Deleted {post_type} "{post_title}"', 'simple-history');
728
 
729
- } else if ( "post_created" == $message_key ) {
730
 
731
- $message = __('Created {post_type} <a href="{edit_link}">"{post_title}"</a>', "simple-history");
732
 
733
- } else if ( "post_trashed" == $message_key ) {
734
 
735
  // while in trash we can still get actions to delete or restore if we follow the edit link
736
- $message = __('Moved {post_type} <a href="{edit_link}">"{post_title}"</a> to the trash', "simple-history");
737
 
738
  }
 
739
 
740
- } // post still available
741
-
742
- $context["post_type"] = isset( $context["post_type"] ) ? esc_html( $context["post_type"] ) : "";
743
- $context["post_title"] = isset( $context["post_title"] ) ? esc_html( $context["post_title"] ) : "";
744
 
745
- return $this->interpolate($message, $context, $row);
746
 
747
  }
748
 
749
- public function getLogRowDetailsOutput($row) {
750
 
751
  $context = $row->context;
752
- $message_key = $context["_message_key"];
753
- $post_id = isset($context["post_id"]) ? $context["post_id"] : 0;
754
 
755
- $out = "";
756
 
757
- if ( "post_updated" == $message_key) {
758
 
759
  // Check for keys like "post_prev_post_title" and "post_new_post_title"
760
- $diff_table_output = "";
761
  $has_diff_values = false;
762
 
763
  // @TODO: this is silly. why loop if we know what we're looking for?
764
  foreach ( $context as $key => $val ) {
765
 
766
- if ( strpos($key, "post_prev_") !== false ) {
767
 
768
  // Old value exists, new value must also exist for diff to be calculates
769
- $key_to_diff = substr($key, strlen("post_prev_"));
770
 
771
  $key_for_new_val = "post_new_{$key_to_diff}";
772
 
773
  if ( isset( $context[ $key_for_new_val ] ) ) {
774
 
775
- $post_old_value = $context[$key];
776
- $post_new_value = $context[$key_for_new_val];
777
 
778
  if ( $post_old_value != $post_new_value ) {
779
 
780
  // Different diffs for different keys
781
- if ( "post_title" == $key_to_diff ) {
782
 
783
  $has_diff_values = true;
784
 
785
  $diff_table_output .= sprintf(
786
  '<tr><td>%1$s</td><td>%2$s</td></tr>',
787
- __("Title", "simple-history"),
788
- simple_history_text_diff($post_old_value, $post_new_value)
789
  );
790
 
791
- } else if ( "post_content" == $key_to_diff ) {
792
 
793
  // Problem: to much text/content
794
  // Risks to fill the visual output
795
  // Maybe solution: use own diff function, that uses none or few context lines
796
-
797
  $has_diff_values = true;
798
 
799
  $diff_table_output .= sprintf(
800
  '<tr><td>%1$s</td><td>%2$s</td></tr>',
801
- __("Content", "simple-history"),
802
- simple_history_text_diff($post_old_value, $post_new_value)
803
  );
804
 
805
-
806
- } else if ( "post_status" == $key_to_diff ) {
807
 
808
  $has_diff_values = true;
809
 
@@ -812,156 +781,149 @@ class SimplePostLogger extends SimpleLogger
812
  <td>%1$s</td>
813
  <td>Changed from %2$s to %3$s</td>
814
  </tr>',
815
- __("Status", "simple-history"),
816
- esc_html($post_old_value),
817
- esc_html($post_new_value)
818
  );
819
 
820
- } else if ( "post_date" == $key_to_diff ) {
821
 
822
  $has_diff_values = true;
823
 
824
- #$diff = new FineDiff($post_old_value, $post_new_value, FineDiff::$wordGranularity);
825
  $diff_table_output .= sprintf(
826
  '<tr>
827
  <td>%1$s</td>
828
  <td>Changed from %2$s to %3$s</td>
829
  </tr>',
830
- __("Publish date", "simple-history"),
831
- esc_html($post_old_value),
832
- esc_html($post_new_value)
833
  );
834
 
835
- } else if ( "post_name" == $key_to_diff ) {
836
 
837
  $has_diff_values = true;
838
 
839
- #$diff = new FineDiff($post_old_value, $post_new_value, FineDiff::$wordGranularity);
840
  $diff_table_output .= sprintf(
841
  '<tr>
842
  <td>%1$s</td>
843
  <td>%2$s</td>
844
  </tr>',
845
- __("Permalink", "simple-history"),
846
- simple_history_text_diff($post_old_value, $post_new_value)
847
  );
848
 
849
- } else if ( "comment_status" == $key_to_diff ) {
850
 
851
  $has_diff_values = true;
852
 
853
- #$diff = new FineDiff($post_old_value, $post_new_value, FineDiff::$wordGranularity);
854
  $diff_table_output .= sprintf(
855
  '<tr>
856
  <td>%1$s</td>
857
  <td>Changed from %2$s to %3$s</td>
858
  </tr>',
859
- __("Comment status", "simple-history"),
860
- esc_html($post_old_value),
861
- esc_html($post_new_value)
862
  );
863
 
864
- } else if ( "post_author" == $key_to_diff ) {
865
 
866
  $has_diff_values = true;
867
 
868
  // wp post edit screen uses display_name so we should use it too
869
- if ( isset( $context["post_prev_post_author/display_name"] ) && isset( $context["post_new_post_author/display_name"] ) ) {
870
 
871
- $prev_user_display_name = $context["post_prev_post_author/display_name"];
872
- $new_user_display_name = $context["post_new_post_author/display_name"];
873
 
874
- $prev_user_user_email = $context["post_prev_post_author/user_email"];
875
- $new_user_user_email = $context["post_new_post_author/user_email"];
876
 
877
  $diff_table_output .= sprintf(
878
  '<tr>
879
  <td>%1$s</td>
880
  <td>%2$s</td>
881
  </tr>',
882
- __("Author", "simple-history"),
883
  $this->interpolate(
884
- __('Changed from {prev_user_display_name} ({prev_user_email}) to {new_user_display_name} ({new_user_email})', "simple-history"),
885
  array(
886
- "prev_user_display_name" => esc_html( $prev_user_display_name ),
887
- "prev_user_email" => esc_html( $prev_user_user_email ),
888
- "new_user_display_name" => esc_html( $new_user_display_name ),
889
- "new_user_email" => esc_html( $new_user_user_email )
890
  )
891
  )
892
  );
893
 
894
-
895
  }
896
-
897
- } else if ( "page_template" == $key_to_diff ) {
898
 
899
  // page template filename
900
- $prev_page_template = $context["post_prev_page_template"];
901
- $new_page_template = $context["post_new_page_template"];
902
 
903
  // page template name, should exist, but I guess someone could have deleted a template
904
  // and after that change the template for a post
905
- $prev_page_template_name = isset( $context["post_prev_page_template_name"] ) ? $context["post_prev_page_template_name"] : "";
906
- $new_page_template_name = isset( $context["post_new_page_template_name"] ) ? $context["post_new_page_template_name"] : "";
907
 
908
  // If prev och new template is "default" then use that as name
909
- if ( "default" == $prev_page_template && ! $prev_page_template_name ) {
910
  $prev_page_template_name = $prev_page_template;
911
- } else if ( "default" == $new_page_template && ! $new_page_template_name ) {
912
  $new_page_template_name = $new_page_template;
913
  }
914
 
915
- // @TODO: translate template names
916
- // $value = translate( $value, $this->get('TextDomain') );
917
-
918
- $message = __('Changed from {prev_page_template} to {new_page_template}', "simple-history");
919
  if ( $prev_page_template_name && $new_page_template_name ) {
920
- $message = __('Changed from "{prev_page_template_name}" to "{new_page_template_name}"', "simple-history");
921
  }
922
 
923
- $diff_table_output .= sprintf(
924
- '<tr>
925
  <td>%1$s</td>
926
  <td>%2$s</td>
927
  </tr>',
928
- __("Template", "simple-history"),
929
- $this->interpolate(
930
- $message,
931
- array(
932
- "prev_page_template" => "<code>" . esc_html( $prev_page_template ) . "</code>",
933
- "new_page_template" => "<code>" . esc_html( $new_page_template ) . "</code>",
934
- "prev_page_template_name" => esc_html( $prev_page_template_name ),
935
- "new_page_template_name" => esc_html( $new_page_template_name )
936
- )
937
- )
938
- );
939
-
940
- }
941
-
942
- }
943
-
944
- }
945
-
946
- }
947
-
948
- } // for each context key
949
-
950
- if ( isset( $context["post_meta_added"] ) || isset( $context["post_meta_removed"] ) || isset( $context["post_meta_changed"] ) ) {
951
-
952
- $meta_changed_out = "";
953
  $has_diff_values = true;
954
 
955
- if ( isset( $context["post_meta_added"] ) ) {
956
- $meta_changed_out .= "<span class='SimpleHistoryLogitem__inlineDivided'>". (int) $context["post_meta_added"] ." added</span> ";
957
  }
958
 
959
- if ( isset( $context["post_meta_removed"] ) ) {
960
- $meta_changed_out .= "<span class='SimpleHistoryLogitem__inlineDivided'>". (int) $context["post_meta_removed"] ." removed</span> ";
961
  }
962
 
963
- if ( isset( $context["post_meta_changed"] ) ) {
964
- $meta_changed_out .= "<span class='SimpleHistoryLogitem__inlineDivided'>". (int) $context["post_meta_changed"] ." changed</span> ";
965
  }
966
 
967
  $diff_table_output .= sprintf(
@@ -969,7 +931,7 @@ class SimplePostLogger extends SimpleLogger
969
  <td>%1$s</td>
970
  <td>%2$s</td>
971
  </tr>',
972
- esc_html( __("Custom fields", "simple-history") ),
973
  $meta_changed_out
974
  );
975
 
@@ -996,7 +958,7 @@ class SimplePostLogger extends SimpleLogger
996
 
997
  $out .= $diff_table_output;
998
 
999
- }
1000
 
1001
  return $out;
1002
 
@@ -1007,22 +969,24 @@ class SimplePostLogger extends SimpleLogger
1007
  *
1008
  * @since 2.0.23
1009
  * @param string $link
1010
- * @param array $row
1011
  */
1012
- public function filter_rss_item_link($link, $row) {
1013
 
1014
  if ( $row->logger != $this->slug ) {
1015
  return $link;
1016
  }
1017
 
1018
- if ( isset( $row->context["post_id"] ) ) {
1019
 
1020
- $permalink = add_query_arg(array("action" => "edit", "post" => $row->context["post_id"]), admin_url( "post.php" ) );
 
 
 
1021
 
1022
  if ( $permalink ) {
1023
  $link = $permalink;
1024
  }
1025
-
1026
  }
1027
 
1028
  return $link;
6
  /**
7
  * Logs changes to posts and pages, including custom post types
8
  */
9
+ class SimplePostLogger extends SimpleLogger {
10
+
11
 
12
  // The logger slug. Defaulting to the class name is nice and logical I think
13
  public $slug = __CLASS__;
17
 
18
  public function loaded() {
19
 
20
+ add_action( 'admin_action_editpost', array( $this, 'on_admin_action_editpost' ) );
21
+ add_action( 'transition_post_status', array( $this, 'on_transition_post_status' ), 10, 3 );
22
+ add_action( 'delete_post', array( $this, 'on_delete_post' ) );
23
+ add_action( 'untrash_post', array( $this, 'on_untrash_post' ) );
24
 
25
  $this->add_xml_rpc_hooks();
26
 
27
+ add_filter( 'simple_history/rss_item_link', array( $this, 'filter_rss_item_link' ), 10, 2 );
28
 
29
  }
30
 
40
  }, 10, 1);
41
  */
42
 
43
+ add_action( 'xmlrpc_call_success_blogger_newPost', array( $this, 'on_xmlrpc_newPost' ), 10, 2 );
44
+ add_action( 'xmlrpc_call_success_mw_newPost', array( $this, 'on_xmlrpc_newPost' ), 10,2 );
45
 
46
+ add_action( 'xmlrpc_call_success_blogger_editPost', array( $this, 'on_xmlrpc_editPost' ), 10, 2 );
47
+ add_action( 'xmlrpc_call_success_mw_editPost', array( $this, 'on_xmlrpc_editPost' ), 10, 2 );
48
 
49
+ add_action( 'xmlrpc_call_success_blogger_deletePost', array( $this, 'on_xmlrpc_deletePost' ), 10, 2 );
50
+ add_action( 'xmlrpc_call_success_wp_deletePage', array( $this, 'on_xmlrpc_deletePost' ), 10, 2 );
51
 
52
+ add_action( 'xmlrpc_call', array( $this, 'on_xmlrpc_call' ), 10, 1 );
53
 
54
  }
55
 
56
+ function on_xmlrpc_call( $method ) {
57
 
58
  $arr_methods_to_act_on = array(
59
+ 'wp.deletePost'
60
  );
61
 
62
  $raw_post_data = null;
66
  if ( in_array( $method, $arr_methods_to_act_on ) ) {
67
 
68
  // Setup common stuff
69
+ $raw_post_data = file_get_contents( 'php://input' );
70
+ $context['wp.deletePost.xmldata'] = $this->simpleHistory->json_encode( $raw_post_data );
71
  $message = new IXR_Message( $raw_post_data );
72
 
73
  if ( ! $message->parse() ) {
74
  return;
75
  }
76
 
77
+ $context['wp.deletePost.xmlrpc_message'] = $this->simpleHistory->json_encode( $message );
78
+ $context['wp.deletePost.xmlrpc_message.messageType'] = $this->simpleHistory->json_encode( $message->messageType );
79
+ $context['wp.deletePost.xmlrpc_message.methodName'] = $this->simpleHistory->json_encode( $message->methodName );
80
+ $context['wp.deletePost.xmlrpc_message.messageParams'] = $this->simpleHistory->json_encode( $message->params );
81
 
82
  // Actions for delete post
83
+ if ( 'wp.deletePost' == $method ) {
84
 
85
  // 4 params, where the last is the post id
86
  if ( ! isset( $message->params[3] ) ) {
92
  $post = get_post( $post_ID );
93
 
94
  $context = array(
95
+ 'post_id' => $post->ID,
96
+ 'post_type' => get_post_type( $post ),
97
+ 'post_title' => get_the_title( $post ),
98
  );
99
 
100
+ $this->infoMessage( 'post_trashed', $context );
 
101
 
102
+ }
103
+ }// End if().
 
104
 
105
  }
106
 
113
  function getInfo() {
114
 
115
  $arr_info = array(
116
+ 'name' => 'Post Logger',
117
+ 'description' => 'Logs the creation and modification of posts and pages',
118
+ 'capability' => 'edit_pages',
119
+ 'messages' => array(
120
+ 'post_created' => __( 'Created {post_type} "{post_title}"', 'simple-history' ),
121
+ 'post_updated' => __( 'Updated {post_type} "{post_title}"', 'simple-history' ),
122
+ 'post_restored' => __( 'Restored {post_type} "{post_title}" from trash', 'simple-history' ),
123
+ 'post_deleted' => __( 'Deleted {post_type} "{post_title}"', 'simple-history' ),
124
+ 'post_trashed' => __( 'Moved {post_type} "{post_title}" to the trash', 'simple-history' ),
125
  ),
126
+ 'labels' => array(
127
+ 'search' => array(
128
+ 'label' => _x( 'Posts & Pages', 'Post logger: search', 'simple-history' ),
129
+ 'label_all' => _x( 'All posts & pages activity', 'Post logger: search', 'simple-history' ),
130
+ 'options' => array(
131
+ _x( 'Posts created', 'Post logger: search', 'simple-history' ) => array(
132
+ 'post_created'
133
  ),
134
+ _x( 'Posts updated', 'Post logger: search', 'simple-history' ) => array(
135
+ 'post_updated'
136
  ),
137
+ _x( 'Posts trashed', 'Post logger: search', 'simple-history' ) => array(
138
+ 'post_trashed'
139
  ),
140
+ _x( 'Posts deleted', 'Post logger: search', 'simple-history' ) => array(
141
+ 'post_deleted'
142
  ),
143
+ _x( 'Posts restored', 'Post logger: search', 'simple-history' ) => array(
144
+ 'post_restored'
145
  ),
146
+ ),
147
+ ),// end search array
148
+ ),// end labels
149
 
150
  );
151
 
164
  */
165
  function on_admin_action_editpost() {
166
 
167
+ $post_ID = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
168
 
169
  if ( ! $post_ID ) {
170
  return;
176
 
177
  $prev_post_data = get_post( $post_ID );
178
 
179
+ $this->old_post_data[ $post_ID ] = array(
180
+ 'post_data' => $prev_post_data,
181
+ 'post_meta' => get_post_custom( $post_ID ),
182
  );
183
 
184
  }
191
  * @param int $post_ID ID of the deleted post.
192
  * @param array $args An array of arguments to delete the post.
193
  */
194
+ function on_xmlrpc_deletePost( $post_ID, $args ) {
195
 
196
  $post = get_post( $post_ID );
197
 
198
  $context = array(
199
+ 'post_id' => $post->ID,
200
+ 'post_type' => get_post_type( $post ),
201
+ 'post_title' => get_the_title( $post ),
202
  );
203
 
204
+ $this->infoMessage( 'post_deleted', $context );
205
 
206
  }
207
 
213
  * @param int $post_ID ID of the updated post.
214
  * @param array $args An array of arguments for the post to edit.
215
  */
216
+ function on_xmlrpc_editPost( $post_ID, $args ) {
217
 
218
  $post = get_post( $post_ID );
219
 
220
  $context = array(
221
+ 'post_id' => $post->ID,
222
+ 'post_type' => get_post_type( $post ),
223
+ 'post_title' => get_the_title( $post ),
224
  );
225
 
226
+ $this->infoMessage( 'post_updated', $context );
227
 
228
  }
229
 
235
  * @param int $post_ID ID of the new post.
236
  * @param array $args An array of new post arguments.
237
  */
238
+ function on_xmlrpc_newPost( $post_ID, $args ) {
239
 
240
  $post = get_post( $post_ID );
241
 
242
  $context = array(
243
+ 'post_id' => $post->ID,
244
+ 'post_type' => get_post_type( $post ),
245
+ 'post_title' => get_the_title( $post ),
246
  );
247
 
248
+ $this->infoMessage( 'post_created', $context );
249
 
250
  }
251
 
252
  /**
253
  * Called when a post is restored from the trash
254
  */
255
+ function on_untrash_post( $post_id ) {
256
 
257
  $post = get_post( $post_id );
258
 
259
  $this->infoMessage(
260
+ 'post_restored',
261
  array(
262
+ 'post_id' => $post_id,
263
+ 'post_type' => get_post_type( $post ),
264
+ 'post_title' => get_the_title( $post ),
265
  )
266
  );
267
 
270
  /**
271
  * Called when a post is deleted from the trash
272
  */
273
+ function on_delete_post( $post_id ) {
274
 
275
+ $post = get_post( $post_id );
276
 
277
+ if ( wp_is_post_revision( $post_id ) ) {
278
  return;
279
  }
280
 
281
+ if ( $post->post_status === 'auto-draft' || $post->post_status === 'inherit' ) {
282
  return;
283
  }
284
 
285
+ if ( 'nav_menu_item' == get_post_type( $post ) ) {
286
  return;
287
  }
288
 
318
 
319
 
320
  /**
321
+ * Fired when a post has changed status
322
+ * Only run in certain cases,
323
+ * because when always enabled it catches a lots of edits made by plugins during cron jobs etc,
324
+ * which by definition is not wrong, but perhaps not wanted/annoying
325
+ */
326
  function on_transition_post_status( $new_status, $old_status, $post ) {
327
 
328
  $ok_to_log = true;
336
 
337
  // except when calls are from/for jetpack/wordpress apps
338
  // seems to be jetpack/app request when $_GET["for"] == "jetpack
339
+ if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && isset( $_GET['for'] ) && $_GET['for'] === 'jetpack' ) {
340
  $ok_to_log = true;
341
  }
342
 
381
  if not from & to = same, then user has changed something
382
  */
383
  $context = array(
384
+ 'post_id' => $post->ID,
385
+ 'post_type' => get_post_type( $post ),
386
+ 'post_title' => get_the_title( $post ),
387
  );
388
 
389
+ if ( $old_status == 'auto-draft' && ($new_status != 'auto-draft' && $new_status != 'inherit') ) {
390
 
391
  // Post created
392
+ $this->infoMessage( 'post_created', $context );
393
 
394
+ } elseif ( $new_status == 'auto-draft' || ($old_status == 'new' && $new_status == 'inherit') ) {
395
 
396
  // Post was automagically saved by WordPress
397
  return;
398
 
399
+ } elseif ( $new_status == 'trash' ) {
400
 
401
  // Post trashed
402
+ $this->infoMessage( 'post_trashed', $context );
403
 
404
  } else {
405
 
406
  // Post updated
407
  // Also add diff between previod saved data and new data
408
+ if ( isset( $this->old_post_data[ $post->ID ] ) ) {
409
 
410
+ $old_post_data = $this->old_post_data[ $post->ID ];
411
 
412
  $new_post_data = array(
413
+ 'post_data' => $post,
414
+ 'post_meta' => get_post_custom( $post->ID ),
415
  );
416
 
417
  // Now we have both old and new post data, including custom fields, in the same format
418
  // So let's compare!
419
+ $context = $this->add_post_data_diff_to_context( $context, $old_post_data, $new_post_data );
420
 
421
  }
422
 
423
+ $context['_occasionsID'] = __CLASS__ . '/' . __FUNCTION__ . "/post_updated/{$post->ID}";
424
 
425
+ $this->infoMessage( 'post_updated', $context );
426
 
427
+ }// End if().
428
 
429
  }
430
 
439
  * - tags
440
  * @return array $context with diff data added
441
  */
442
+ function add_post_data_diff_to_context( $context, $old_post_data, $new_post_data ) {
443
 
444
+ $old_data = $old_post_data['post_data'];
445
+ $new_data = $new_post_data['post_data'];
446
 
447
  // Will contain the differences
448
  $post_data_diff = array();
449
 
450
  $arr_keys_to_diff = array(
451
+ 'post_title',
452
+ 'post_name',
453
+ 'post_content',
454
+ 'post_status',
455
+ 'menu_order',
456
+ 'post_date',
457
+ 'post_date_gmt',
458
+ 'post_excerpt',
459
+ 'comment_status',
460
+ 'ping_status',
461
+ 'post_parent', // only id, need to get context for that, like name of parent at least?
462
+ 'post_author', // only id, need to get context for that, like name, login, email at least?
463
  );
464
 
465
  foreach ( $arr_keys_to_diff as $key ) {
466
 
467
  if ( isset( $old_data->$key ) && isset( $new_data->$key ) ) {
468
+ $post_data_diff = $this->add_diff( $post_data_diff, $key, $old_data->$key, $new_data->$key );
469
  }
 
470
  }
471
 
472
  // If changes where detected
476
  // Save at least 2 values for each detected value change, i.e. the old value and the new value
477
  foreach ( $post_data_diff as $diff_key => $diff_values ) {
478
 
479
+ $context[ "post_prev_{$diff_key}" ] = $diff_values['old'];
480
+ $context[ "post_new_{$diff_key}" ] = $diff_values['new'];
481
 
482
  // If post_author then get more author info
483
  // Because just a user ID does not get us far
484
+ if ( 'post_author' == $diff_key ) {
485
 
486
+ $old_author_user = get_userdata( (int) $diff_values['old'] );
487
+ $new_author_user = get_userdata( (int) $diff_values['new'] );
488
 
489
+ if ( is_a( $old_author_user, 'WP_User' ) && is_a( $new_author_user, 'WP_User' ) ) {
490
 
491
+ $context[ "post_prev_{$diff_key}/user_login" ] = $old_author_user->user_login;
492
+ $context[ "post_prev_{$diff_key}/user_email" ] = $old_author_user->user_email;
493
+ $context[ "post_prev_{$diff_key}/display_name" ] = $old_author_user->display_name;
494
 
495
+ $context[ "post_new_{$diff_key}/user_login" ] = $new_author_user->user_login;
496
+ $context[ "post_new_{$diff_key}/user_email" ] = $new_author_user->user_email;
497
+ $context[ "post_new_{$diff_key}/display_name" ] = $new_author_user->display_name;
498
 
499
  }
 
500
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
  }
502
+ } // End if().
 
 
503
 
504
  // Compare custom fields
 
505
  // Array with custom field keys to ignore because changed everytime or very internal
506
  $arr_meta_keys_to_ignore = array(
507
+ '_edit_lock',
508
+ '_edit_last',
509
+ '_post_restored_from',
510
+ '_wp_page_template',
511
  );
512
 
513
  $meta_changes = array(
514
+ 'added' => array(),
515
+ 'removed' => array(),
516
+ 'changed' => array(),
517
  );
518
 
519
+ $old_meta = $old_post_data['post_meta'];
520
+ $new_meta = $new_post_data['post_meta'];
521
 
522
  // @todo: post thumb is stored in _thumbnail_id
 
523
  // page template is stored in _wp_page_template
524
+ if ( isset( $old_meta['_wp_page_template'][0] ) && isset( $new_meta['_wp_page_template'][0] ) ) {
525
 
526
  /*
527
  Var is string with length 7: default
528
  Var is string with length 20: template-builder.php
529
  */
530
 
531
+ if ( $old_meta['_wp_page_template'][0] != $new_meta['_wp_page_template'][0] ) {
532
 
533
  // prev page template is different from new page template
 
534
  // store template php file name
535
+ $context['post_prev_page_template'] = $old_meta['_wp_page_template'][0];
536
+ $context['post_new_page_template'] = $new_meta['_wp_page_template'][0];
537
 
538
  $theme_templates = (array) $this->get_theme_templates();
539
  /*
545
  [sidebar-page.php] => Sidebar Template
546
  )
547
  */
548
+ if ( isset( $theme_templates[ $context['post_prev_page_template'] ] ) ) {
549
+ $context['post_prev_page_template_name'] = $theme_templates[ $context['post_prev_page_template'] ];
550
  }
551
 
552
+ if ( isset( $theme_templates[ $context['post_new_page_template'] ] ) ) {
553
+ $context['post_new_page_template_name'] = $theme_templates[ $context['post_new_page_template'] ];
554
  }
 
555
  }
 
556
  }
557
 
558
  // Remove fields that we have checked already and other that should be ignored
559
+ foreach ( $arr_meta_keys_to_ignore as $key_to_ignore ) {
560
  unset( $old_meta[ $key_to_ignore ] );
561
  unset( $new_meta[ $key_to_ignore ] );
562
  }
565
  foreach ( $new_meta as $meta_key => $meta_value ) {
566
 
567
  if ( ! isset( $old_meta[ $meta_key ] ) ) {
568
+ $meta_changes['added'][ $meta_key ] = true;
569
  }
 
570
  }
571
 
572
  // Look for removed meta
587
  if ( isset( $new_meta[ $meta_key ] ) ) {
588
 
589
  if ( json_encode( $old_meta[ $meta_key ] ) != json_encode( $new_meta[ $meta_key ] ) ) {
590
+ $meta_changes['changed'][ $meta_key ] = true;
591
  }
592
  }
 
593
  }
594
 
595
+ if ( $meta_changes['added'] ) {
596
+ $context['post_meta_added'] = sizeof( $meta_changes['added'] );
597
  }
598
 
599
+ if ( $meta_changes['removed'] ) {
600
+ $context['post_meta_removed'] = sizeof( $meta_changes['removed'] );
601
  }
602
 
603
+ if ( $meta_changes['changed'] ) {
604
+ $context['post_meta_changed'] = sizeof( $meta_changes['changed'] );
605
  }
606
 
607
  return $context;
623
  $files = (array) $theme->get_files( 'php', 1 );
624
 
625
  foreach ( $files as $file => $full_path ) {
626
+ if ( ! preg_match( '|Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) ) {
627
  continue;
628
+ }
629
  $page_templates[ $file ] = _cleanup_header_comment( $header[1] );
630
  }
631
 
638
  *
639
  * Since 2.0.29
640
  */
641
+ function add_diff( $post_data_diff, $key, $old_value, $new_value ) {
642
 
643
  if ( $old_value != $new_value ) {
644
 
645
+ $post_data_diff[ $key ] = array(
646
+ 'old' => $old_value,
647
+ 'new' => $new_value,
648
  );
649
 
650
  }
656
  /**
657
  * Modify plain output to include link to post
658
  */
659
+ public function getLogRowPlainTextOutput( $row ) {
660
 
661
  $context = $row->context;
662
+ $post_id = isset( $context['post_id'] ) ? $context['post_id'] : 0;
663
 
664
  // Default to original log message
665
  $message = $row->message;
668
  // It will return a WP_Post Object if post still is in system
669
  // If post is deleted from trash (not just moved there), then null is returned
670
  $post = get_post( $post_id );
671
+ $post_is_available = is_a( $post, 'WP_Post' );
 
 
 
672
 
673
+ // sf_d($post_is_available, '$post_is_available');
674
+ // sf_d($message_key, '$message_key');
675
+ $message_key = isset( $context['_message_key'] ) ? $context['_message_key'] : null;
676
 
677
  // Try to get singular name
678
+ $post_type = isset( $context['post_type'] ) ? $context['post_type'] : '';
679
  $post_type_obj = get_post_type_object( $post_type );
680
  if ( ! is_null( $post_type_obj ) ) {
681
 
682
+ if ( ! empty( $post_type_obj->labels->singular_name ) ) {
683
+ $context['post_type'] = strtolower( $post_type_obj->labels->singular_name );
684
  }
 
685
  }
686
 
687
+ $context['edit_link'] = get_edit_post_link( $post_id );
688
 
689
  // If post is not available any longer then we can't link to it, so keep plain message then
690
  // Also keep plain format if user is not allowed to edit post (edit link is empty)
691
+ if ( $post_is_available && $context['edit_link'] ) {
692
 
693
+ if ( 'post_updated' == $message_key ) {
694
 
695
+ $message = __( 'Updated {post_type} <a href="{edit_link}">"{post_title}"</a>', 'simple-history' );
696
 
697
+ } elseif ( 'post_deleted' == $message_key ) {
698
 
699
+ $message = __( 'Deleted {post_type} "{post_title}"', 'simple-history' );
700
 
701
+ } elseif ( 'post_created' == $message_key ) {
702
 
703
+ $message = __( 'Created {post_type} <a href="{edit_link}">"{post_title}"</a>', 'simple-history' );
704
 
705
+ } elseif ( 'post_trashed' == $message_key ) {
706
 
707
  // while in trash we can still get actions to delete or restore if we follow the edit link
708
+ $message = __( 'Moved {post_type} <a href="{edit_link}">"{post_title}"</a> to the trash', 'simple-history' );
709
 
710
  }
711
+ } // End if().
712
 
713
+ $context['post_type'] = isset( $context['post_type'] ) ? esc_html( $context['post_type'] ) : '';
714
+ $context['post_title'] = isset( $context['post_title'] ) ? esc_html( $context['post_title'] ) : '';
 
 
715
 
716
+ return $this->interpolate( $message, $context, $row );
717
 
718
  }
719
 
720
+ public function getLogRowDetailsOutput( $row ) {
721
 
722
  $context = $row->context;
723
+ $message_key = $context['_message_key'];
724
+ $post_id = isset( $context['post_id'] ) ? $context['post_id'] : 0;
725
 
726
+ $out = '';
727
 
728
+ if ( 'post_updated' == $message_key ) {
729
 
730
  // Check for keys like "post_prev_post_title" and "post_new_post_title"
731
+ $diff_table_output = '';
732
  $has_diff_values = false;
733
 
734
  // @TODO: this is silly. why loop if we know what we're looking for?
735
  foreach ( $context as $key => $val ) {
736
 
737
+ if ( strpos( $key, 'post_prev_' ) !== false ) {
738
 
739
  // Old value exists, new value must also exist for diff to be calculates
740
+ $key_to_diff = substr( $key, strlen( 'post_prev_' ) );
741
 
742
  $key_for_new_val = "post_new_{$key_to_diff}";
743
 
744
  if ( isset( $context[ $key_for_new_val ] ) ) {
745
 
746
+ $post_old_value = $context[ $key ];
747
+ $post_new_value = $context[ $key_for_new_val ];
748
 
749
  if ( $post_old_value != $post_new_value ) {
750
 
751
  // Different diffs for different keys
752
+ if ( 'post_title' == $key_to_diff ) {
753
 
754
  $has_diff_values = true;
755
 
756
  $diff_table_output .= sprintf(
757
  '<tr><td>%1$s</td><td>%2$s</td></tr>',
758
+ __( 'Title', 'simple-history' ),
759
+ simple_history_text_diff( $post_old_value, $post_new_value )
760
  );
761
 
762
+ } elseif ( 'post_content' == $key_to_diff ) {
763
 
764
  // Problem: to much text/content
765
  // Risks to fill the visual output
766
  // Maybe solution: use own diff function, that uses none or few context lines
 
767
  $has_diff_values = true;
768
 
769
  $diff_table_output .= sprintf(
770
  '<tr><td>%1$s</td><td>%2$s</td></tr>',
771
+ __( 'Content', 'simple-history' ),
772
+ simple_history_text_diff( $post_old_value, $post_new_value )
773
  );
774
 
775
+ } elseif ( 'post_status' == $key_to_diff ) {
 
776
 
777
  $has_diff_values = true;
778
 
781
  <td>%1$s</td>
782
  <td>Changed from %2$s to %3$s</td>
783
  </tr>',
784
+ __( 'Status', 'simple-history' ),
785
+ esc_html( $post_old_value ),
786
+ esc_html( $post_new_value )
787
  );
788
 
789
+ } elseif ( 'post_date' == $key_to_diff ) {
790
 
791
  $has_diff_values = true;
792
 
793
+ // $diff = new FineDiff($post_old_value, $post_new_value, FineDiff::$wordGranularity);
794
  $diff_table_output .= sprintf(
795
  '<tr>
796
  <td>%1$s</td>
797
  <td>Changed from %2$s to %3$s</td>
798
  </tr>',
799
+ __( 'Publish date', 'simple-history' ),
800
+ esc_html( $post_old_value ),
801
+ esc_html( $post_new_value )
802
  );
803
 
804
+ } elseif ( 'post_name' == $key_to_diff ) {
805
 
806
  $has_diff_values = true;
807
 
808
+ // $diff = new FineDiff($post_old_value, $post_new_value, FineDiff::$wordGranularity);
809
  $diff_table_output .= sprintf(
810
  '<tr>
811
  <td>%1$s</td>
812
  <td>%2$s</td>
813
  </tr>',
814
+ __( 'Permalink', 'simple-history' ),
815
+ simple_history_text_diff( $post_old_value, $post_new_value )
816
  );
817
 
818
+ } elseif ( 'comment_status' == $key_to_diff ) {
819
 
820
  $has_diff_values = true;
821
 
822
+ // $diff = new FineDiff($post_old_value, $post_new_value, FineDiff::$wordGranularity);
823
  $diff_table_output .= sprintf(
824
  '<tr>
825
  <td>%1$s</td>
826
  <td>Changed from %2$s to %3$s</td>
827
  </tr>',
828
+ __( 'Comment status', 'simple-history' ),
829
+ esc_html( $post_old_value ),
830
+ esc_html( $post_new_value )
831
  );
832
 
833
+ } elseif ( 'post_author' == $key_to_diff ) {
834
 
835
  $has_diff_values = true;
836
 
837
  // wp post edit screen uses display_name so we should use it too
838
+ if ( isset( $context['post_prev_post_author/display_name'] ) && isset( $context['post_new_post_author/display_name'] ) ) {
839
 
840
+ $prev_user_display_name = $context['post_prev_post_author/display_name'];
841
+ $new_user_display_name = $context['post_new_post_author/display_name'];
842
 
843
+ $prev_user_user_email = $context['post_prev_post_author/user_email'];
844
+ $new_user_user_email = $context['post_new_post_author/user_email'];
845
 
846
  $diff_table_output .= sprintf(
847
  '<tr>
848
  <td>%1$s</td>
849
  <td>%2$s</td>
850
  </tr>',
851
+ __( 'Author', 'simple-history' ),
852
  $this->interpolate(
853
+ __( 'Changed from {prev_user_display_name} ({prev_user_email}) to {new_user_display_name} ({new_user_email})', 'simple-history' ),
854
  array(
855
+ 'prev_user_display_name' => esc_html( $prev_user_display_name ),
856
+ 'prev_user_email' => esc_html( $prev_user_user_email ),
857
+ 'new_user_display_name' => esc_html( $new_user_display_name ),
858
+ 'new_user_email' => esc_html( $new_user_user_email ),
859
  )
860
  )
861
  );
862
 
 
863
  }
864
+ } elseif ( 'page_template' == $key_to_diff ) {
 
865
 
866
  // page template filename
867
+ $prev_page_template = $context['post_prev_page_template'];
868
+ $new_page_template = $context['post_new_page_template'];
869
 
870
  // page template name, should exist, but I guess someone could have deleted a template
871
  // and after that change the template for a post
872
+ $prev_page_template_name = isset( $context['post_prev_page_template_name'] ) ? $context['post_prev_page_template_name'] : '';
873
+ $new_page_template_name = isset( $context['post_new_page_template_name'] ) ? $context['post_new_page_template_name'] : '';
874
 
875
  // If prev och new template is "default" then use that as name
876
+ if ( 'default' == $prev_page_template && ! $prev_page_template_name ) {
877
  $prev_page_template_name = $prev_page_template;
878
+ } elseif ( 'default' == $new_page_template && ! $new_page_template_name ) {
879
  $new_page_template_name = $new_page_template;
880
  }
881
 
882
+ // @TODO: translate template names
883
+ // $value = translate( $value, $this->get('TextDomain') );
884
+ $message = __( 'Changed from {prev_page_template} to {new_page_template}', 'simple-history' );
 
885
  if ( $prev_page_template_name && $new_page_template_name ) {
886
+ $message = __( 'Changed from "{prev_page_template_name}" to "{new_page_template_name}"', 'simple-history' );
887
  }
888
 
889
+ $diff_table_output .= sprintf(
890
+ '<tr>
891
  <td>%1$s</td>
892
  <td>%2$s</td>
893
  </tr>',
894
+ __( 'Template', 'simple-history' ),
895
+ $this->interpolate(
896
+ $message,
897
+ array(
898
+ 'prev_page_template' => '<code>' . esc_html( $prev_page_template ) . '</code>',
899
+ 'new_page_template' => '<code>' . esc_html( $new_page_template ) . '</code>',
900
+ 'prev_page_template_name' => esc_html( $prev_page_template_name ),
901
+ 'new_page_template_name' => esc_html( $new_page_template_name ),
902
+ )
903
+ )
904
+ );
905
+
906
+ }// End if().
907
+ }// End if().
908
+ }// End if().
909
+ }// End if().
910
+ } // End foreach().
911
+
912
+ if ( isset( $context['post_meta_added'] ) || isset( $context['post_meta_removed'] ) || isset( $context['post_meta_changed'] ) ) {
913
+
914
+ $meta_changed_out = '';
 
 
 
 
915
  $has_diff_values = true;
916
 
917
+ if ( isset( $context['post_meta_added'] ) ) {
918
+ $meta_changed_out .= "<span class='SimpleHistoryLogitem__inlineDivided'>" . (int) $context['post_meta_added'] . ' added</span> ';
919
  }
920
 
921
+ if ( isset( $context['post_meta_removed'] ) ) {
922
+ $meta_changed_out .= "<span class='SimpleHistoryLogitem__inlineDivided'>" . (int) $context['post_meta_removed'] . ' removed</span> ';
923
  }
924
 
925
+ if ( isset( $context['post_meta_changed'] ) ) {
926
+ $meta_changed_out .= "<span class='SimpleHistoryLogitem__inlineDivided'>" . (int) $context['post_meta_changed'] . ' changed</span> ';
927
  }
928
 
929
  $diff_table_output .= sprintf(
931
  <td>%1$s</td>
932
  <td>%2$s</td>
933
  </tr>',
934
+ esc_html( __( 'Custom fields', 'simple-history' ) ),
935
  $meta_changed_out
936
  );
937
 
958
 
959
  $out .= $diff_table_output;
960
 
961
+ }// End if().
962
 
963
  return $out;
964
 
969
  *
970
  * @since 2.0.23
971
  * @param string $link
972
+ * @param array $row
973
  */
974
+ public function filter_rss_item_link( $link, $row ) {
975
 
976
  if ( $row->logger != $this->slug ) {
977
  return $link;
978
  }
979
 
980
+ if ( isset( $row->context['post_id'] ) ) {
981
 
982
+ $permalink = add_query_arg( array(
983
+ 'action' => 'edit',
984
+ 'post' => $row->context['post_id'],
985
+ ), admin_url( 'post.php' ) );
986
 
987
  if ( $permalink ) {
988
  $link = $permalink;
989
  }
 
990
  }
991
 
992
  return $link;
loggers/SimpleThemeLogger.php CHANGED
@@ -20,59 +20,59 @@ class SimpleThemeLogger extends SimpleLogger {
20
  function getInfo() {
21
 
22
  $arr_info = array(
23
- "name" => "Theme Logger",
24
- "description" => "Logs theme edits",
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"),
34
- 'widget_order_changed' => __('Changed widget order "{widget_id_base}" in sidebar "{sidebar_id}"', "simple-history"),
35
- 'widget_edited' => __('Changed widget "{widget_id_base}" in sidebar "{sidebar_id}"', "simple-history"),
36
- "custom_background_changed" => __("Changed settings for the theme custom background", "simple-history")
37
  ),
38
- "labels" => array(
39
- "search" => array(
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
  ),
55
- _x("Changed appearance of themes", "Theme logger: search", "simple-history") => array(
56
- "appearance_customized"
57
  ),
58
- _x("Added widgets", "Theme logger: search", "simple-history") => array(
59
- "widget_added"
60
  ),
61
- _x("Removed widgets", "Theme logger: search", "simple-history") => array(
62
- "widget_removed"
63
  ),
64
- _x("Changed widgets order", "Theme logger: search", "simple-history") => array(
65
- "widget_order_changed"
66
  ),
67
- _x("Edited widgets", "Theme logger: search", "simple-history") => array(
68
- "widget_edited"
69
  ),
70
- _x("Background of themes changed", "Theme logger: search", "simple-history") => array(
71
- "custom_background_changed"
72
  ),
73
- )
74
- ) // end search array
75
- ) // end labels
76
 
77
  );
78
 
@@ -84,29 +84,29 @@ class SimpleThemeLogger extends SimpleLogger {
84
 
85
  /**
86
  * Fires after the theme is switched.
 
87
  * @param string $new_name Name of the new theme.
88
  * @param WP_Theme $new_theme WP_Theme instance of the new theme.
89
  */
90
- add_action( 'switch_theme', array( $this, "on_switch_theme" ), 10, 2 );
91
- add_action( 'load-themes.php', array( $this, "on_page_load_themes" ) );
92
 
93
- add_action("customize_save", array( $this, "on_action_customize_save" ));
94
 
95
- add_action("sidebar_admin_setup", array( $this, "on_action_sidebar_admin_setup__detect_widget_delete") );
96
- add_action("sidebar_admin_setup", array( $this, "on_action_sidebar_admin_setup__detect_widget_add") );
97
- //add_action("wp_ajax_widgets-order", array( $this, "on_action_sidebar_admin_setup__detect_widget_order_change"), 1 );
98
- //add_action("sidebar_admin_setup", array( $this, "on_action_sidebar_admin_setup__detect_widget_edit") );
 
99
 
100
- add_filter( 'widget_update_callback', array( $this, "on_widget_update_callback" ), 10, 4 );
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
 
@@ -120,7 +120,7 @@ class SimpleThemeLogger extends SimpleLogger {
120
  */
121
  function on_deleted_site_transient_theme_deleted( $transient = null ) {
122
 
123
- if ( "update_themes" !== $transient ) {
124
  return;
125
  }
126
 
@@ -137,20 +137,20 @@ class SimpleThemeLogger extends SimpleLogger {
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
 
@@ -190,7 +190,7 @@ class SimpleThemeLogger extends SimpleLogger {
190
  }
191
 
192
  // Must be type theme and action install
193
- if ( $arr_data["type"] !== "theme" || $arr_data["action"] !== "update" ) {
194
  return;
195
  }
196
 
@@ -204,11 +204,11 @@ class SimpleThemeLogger extends SimpleLogger {
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
 
@@ -226,22 +226,22 @@ class SimpleThemeLogger extends SimpleLogger {
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
 
@@ -252,7 +252,6 @@ class SimpleThemeLogger extends SimpleLogger {
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
@@ -269,7 +268,7 @@ class SimpleThemeLogger extends SimpleLogger {
269
  }
270
 
271
  // Must be type theme and action install
272
- if ( $arr_data["type"] !== "theme" || $arr_data["action"] !== "install" ) {
273
  return;
274
  }
275
 
@@ -315,16 +314,15 @@ class SimpleThemeLogger extends SimpleLogger {
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
  );
@@ -338,23 +336,22 @@ class SimpleThemeLogger extends SimpleLogger {
338
  }
339
 
340
  $arr_valid_post_keys = array(
341
- "reset-background" => 1,
342
- "remove-background" => 1,
343
- "background-repeat" => 1,
344
- "background-position-x" => 1,
345
- "background-attachment" => 1,
346
- "background-color" => 1
347
  );
348
 
349
- $valid_post_key_exists = array_intersect_key($arr_valid_post_keys, $_POST);
350
 
351
- if ( ! empty( $valid_post_key_exists) ) {
352
 
353
  $context = array();
354
  // $context["POST"] = $this->simpleHistory->json_encode( $_POST );
355
-
356
  $this->infoMessage(
357
- "custom_background_changed",
358
  $context
359
  );
360
 
@@ -365,7 +362,7 @@ class SimpleThemeLogger extends SimpleLogger {
365
  /*
366
  WP_Customize_Manager $this WP_Customize_Manager instance.
367
  */
368
- function on_action_customize_save($customize_manager) {
369
 
370
  /*
371
  - Loop through all sections
@@ -387,98 +384,86 @@ class SimpleThemeLogger extends SimpleLogger {
387
  nav - Navigation
388
  static_front_page - Static Front Page
389
  */
390
- /*
391
- Array
392
- (
393
- [wp_customize] => on
394
- [theme] => make
395
- [customized] => {\"widget_pages[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_calendar[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_calendar[6]\":{\"encoded_serialized_instance\":\"YToxOntzOjU6InRpdGxlIjtzOjE3OiJTZWUgd2hhdCBoYXBwZW5zISI7fQ==\",\"title\":\"See what happens!\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"ca37c1913982fa69bce33f77cef871cd\"},\"widget_calendar[7]\":{\"encoded_serialized_instance\":\"YToxOntzOjU6InRpdGxlIjtzOjg6IkthbGVuZGVyIjt9\",\"title\":\"Kalender\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"c602d6d891e3f7addb11ca21ac142b49\"},\"widget_archives[4]\":{\"encoded_serialized_instance\":\"YTozOntzOjU6InRpdGxlIjtzOjA6IiI7czo1OiJjb3VudCI7aTowO3M6ODoiZHJvcGRvd24iO2k6MDt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"3480afa3934342872c740122c4988ab5\"},\"widget_archives[6]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_meta[2]\":{\"encoded_serialized_instance\":\"YToxOntzOjU6InRpdGxlIjtzOjA6IiI7fQ==\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"b518e607928dcfc07867f25e07a3a875\"},\"widget_search[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_text[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_categories[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_recent-posts[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_recent-comments[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_rss[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_tag_cloud[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_nav_menu[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_caldera_forms_widget[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_edd_cart_widget[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_edd_categories_tags_widget[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_edd_categories_tags_widget[2]\":{\"encoded_serialized_instance\":\"YTo0OntzOjU6InRpdGxlIjtzOjA6IiI7czo4OiJ0YXhvbm9teSI7czoxNzoiZG93bmxvYWRfY2F0ZWdvcnkiO3M6NToiY291bnQiO3M6MDoiIjtzOjEwOiJoaWRlX2VtcHR5IjtzOjA6IiI7fQ==\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"afb767ddd896180593a758ba3228a6a4\"},\"widget_edd_product_details[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_icl_lang_sel_widget[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"sidebars_widgets[wp_inactive_widgets]\":[\"calendar-6\",\"calendar-7\",\"archives-4\",\"archives-6\",\"edd_categories_tags_widget-2\"],\"sidebars_widgets[sidebar-left]\":[\"meta-2\"],\"sidebars_widgets[sidebar-right]\":[],\"sidebars_widgets[footer-1]\":[],\"sidebars_widgets[footer-2]\":[],\"sidebars_widgets[footer-3]\":[],\"sidebars_widgets[footer-4]\":[],\"blogname\":\"My test sitexxxxx\",\"blogdescription\":\"hej\",\"header_textcolor\":false,\"background_color\":\"#30d132\",\"header_image\":false,\"header_image_data\":\"\",\"background_image\":\"http://playground-root.ep/assets/uploads/2014/09/small-image.gif\",\"background_image_thumb\":\"\",\"background_repeat\":\"repeat-y\",\"background_position_x\":\"right\",\"background_attachment\":\"scroll\",\"nav_menu_locations[primary]\":\"31\",\"nav_menu_locations[social]\":0,\"nav_menu_locations[header-bar]\":\"32\",\"show_on_front\":\"page\",\"page_on_front\":\"24851\",\"page_for_posts\":\"25253\",\"logo-regular\":\"\",\"logo-retina\":\"\",\"logo-favicon\":\"\",\"logo-apple-touch\":\"\",\"social-facebook\":\"\",\"social-twitter\":\"\",\"social-google-plus-square\":\"\",\"social-linkedin\":\"\",\"social-instagram\":\"\",\"social-flickr\":\"\",\"social-youtube\":\"\",\"social-vimeo-square\":\"\",\"social-pinterest\":\"\",\"social-email\":\"\",\"social-hide-rss\":0,\"social-custom-rss\":\"\",\"font-subset\":\"latin\",\"font-family-site-title\":\"Dawning of a New Day\",\"font-size-site-title\":32,\"font-family-site-tagline\":\"Open Sans\",\"font-size-site-tagline\":12,\"font-family-nav\":\"Open Sans\",\"font-size-nav\":14,\"font-family-subnav\":\"Open Sans\",\"font-size-subnav\":13,\"font-subnav-mobile\":1,\"font-family-widget\":\"Open Sans\",\"font-size-widget\":13,\"font-family-h1\":\"monospace\",\"font-size-h1\":50,\"font-family-h2\":\"monospace\",\"font-size-h2\":37,\"font-family-h3\":\"monospace\",\"font-size-h3\":26,\"font-family-h4\":\"monospace\",\"font-size-h4\":26,\"font-family-h5\":\"monospace\",\"font-size-h5\":18,\"font-family-h6\":\"monospace\",\"font-size-h6\":15,\"font-family-body\":\"Open Sans\",\"font-size-body\":17,\"color-primary\":\"#2fce6f\",\"color-secondary\":\"#35c904\",\"color-text\":\"#969696\",\"color-detail\":\"#b9bcbf\",\"main-background-color\":\"#ffffff\",\"header-bar-background-color\":\"#171717\",\"header-bar-text-color\":\"#16dd66\",\"header-bar-border-color\":\"#171717\",\"header-background-color\":\"#ffffff\",\"header-text-color\":\"#171717\",\"color-site-title\":\"#1a6aba\",\"footer-background-color\":\"#eaecee\",\"footer-text-color\":\"#464849\",\"footer-border-color\":\"#b9bcbf\",\"header-background-image\":\"\",\"header-background-repeat\":\"no-repeat\",\"header-background-position\":\"center\",\"header-background-size\":\"cover\",\"header-layout\":1,\"header-branding-position\":\"left\",\"header-bar-content-layout\":\"flipped\",\"header-text\":\"text\",\"header-show-social\":0,\"header-show-search\":1,\"general-layout\":\"boxed\",\"general-sticky-label\":\"sticky name\",\"main-content-link-underline\":0,\"layout-blog-hide-header\":0,\"layout-blog-hide-footer\":0,\"layout-blog-sidebar-left\":0,\"layout-blog-sidebar-right\":1,\"layout-blog-featured-images\":\"post-header\",\"layout-blog-featured-images-alignment\":\"center\",\"layout-blog-post-date\":\"absolute\",\"layout-blog-post-date-location\":\"top\",\"layout-blog-post-author\":\"avatar\",\"layout-blog-post-author-location\":\"post-footer\",\"layout-blog-auto-excerpt\":0,\"layout-blog-show-categories\":1,\"layout-blog-show-tags\":1,\"layout-blog-comment-count\":\"none\",\"layout-blog-comment-count-location\":\"before-content\",\"layout-archive-hide-header\":0,\"layout-archive-hide-footer\":0,\"layout-archive-sidebar-left\":0,\"layout-archive-sidebar-right\":1,\"layout-archive-featured-images\":\"post-header\",\"layout-archive-featured-images-alignment\":\"center\",\"layout-archive-post-date\":\"absolute\",\"layout-archive-post-date-location\":\"top\",\"layout-archive-post-author\":\"avatar\",\"layout-archive-post-author-location\":\"post-footer\",\"layout-archive-auto-excerpt\":0,\"layout-archive-show-categories\":1,\"layout-archive-show-tags\":1,\"layout-archive-comment-count\":\"none\",\"layout-archive-comment-count-location\":\"before-content\",\"layout-search-hide-header\":0,\"layout-search-hide-footer\":0,\"layout-search-sidebar-left\":true,\"layout-search-sidebar-right\":1,\"layout-search-featured-images\":\"thumbnail\",\"layout-search-featured-images-alignment\":\"center\",\"layout-search-post-date\":\"absolute\",\"layout-search-post-date-location\":\"top\",\"layout-search-post-author\":\"name\",\"layout-search-post-author-location\":\"post-footer\",\"layout-search-auto-excerpt\":1,\"layout-search-show-categories\":1,\"layout-search-show-tags\":1,\"layout-search-comment-count\":\"none\",\"layout-search-comment-count-location\":\"before-content\",\"layout-post-hide-header\":0,\"layout-post-hide-footer\":0,\"layout-post-sidebar-left\":0,\"layout-post-sidebar-right\":0,\"layout-post-featured-images\":\"post-header\",\"layout-post-featured-images-alignment\":\"center\",\"layout-post-post-date\":\"absolute\",\"layout-post-post-date-location\":\"top\",\"layout-post-post-author\":\"name\",\"layout-post-post-author-location\":\"post-footer\",\"layout-post-show-categories\":0,\"layout-post-show-tags\":0,\"layout-post-comment-count\":\"none\",\"layout-post-comment-count-location\":\"before-content\",\"layout-page-hide-header\":0,\"layout-page-hide-footer\":0,\"layout-page-sidebar-left\":0,\"layout-page-sidebar-right\":0,\"layout-page-hide-title\":1,\"layout-page-featured-images\":\"none\",\"layout-page-featured-images-alignment\":\"center\",\"layout-page-post-date\":\"none\",\"layout-page-post-date-location\":\"top\",\"layout-page-post-author\":\"none\",\"layout-page-post-author-location\":\"post-footer\",\"layout-page-comment-count\":\"none\",\"layout-page-comment-count-location\":\"before-content\",\"footer-background-image\":\"\",\"footer-background-repeat\":\"no-repeat\",\"footer-background-position\":\"center\",\"footer-background-size\":\"cover\",\"footer-widget-areas\":3,\"footer-layout\":1,\"footer-text\":\"\",\"footer-show-social\":1,\"background_size\":\"auto\",\"main-background-image\":\"\",\"main-background-repeat\":\"repeat\",\"main-background-position\":\"left\",\"main-background-size\":\"auto\",\"navigation-mobile-label\":\"Menuxx\",\"hide-site-title\":0,\"hide-tagline\":0}
396
- [nonce] => e983bc7d41
397
- [action] => customize_save
398
- )
399
- */
400
-
401
- /*
402
- keys in customized = settings id
403
- */
404
- #print_r($_REQUEST);
405
-
406
- // Needed to get sections and controls in sorted order
407
- $customize_manager->prepare_controls();
408
-
409
- $settings = $customize_manager->settings();
410
- $sections = $customize_manager->sections();
411
- $controls = $customize_manager->controls();
412
-
413
- $customized = json_decode( wp_unslash( $_REQUEST["customized"] ) );
414
-
415
- foreach ($customized as $setting_id => $posted_values) {
416
-
417
- foreach ($settings as $one_setting) {
418
-
419
- if ($one_setting->id == $setting_id) {
420
-
421
- // sf_d("MATCH");
422
- $old_value = $one_setting->value();
423
- $new_value = $one_setting->post_value();
424
-
425
- if ($old_value != $new_value) {
426
-
427
- $context = array(
428
- "setting_id" => $one_setting->id,
429
- "setting_old_value" => $old_value,
430
- "setting_new_value" => $new_value,
431
- #"control_id" => $section_control->id,
432
- #"control_label" => $section_control->label,
433
- #"control_type" => $section_control->type,
434
- #"section_id" => $section->id,
435
- #"section_title" => $section->title,
436
- );
437
-
438
- // value is changed
439
- // find which control it belongs to
440
- #foreach ($sections as $section) {
441
- foreach ($controls as $one_control) {
442
-
443
- foreach ($one_control->settings as $section_control_setting) {
444
-
445
- if ( $section_control_setting->id == $setting_id) {
446
 
447
- #echo "\n" . $one_control->id;
448
- #echo "\n" . $one_control->label;
449
- #echo "\n" . $one_control->type;
450
- $context["control_id"] = $one_control->id;
451
- $context["control_label"] = $one_control->label;
452
- $context["control_type"] = $one_control->type;
453
 
454
- }
 
 
455
 
456
- }
457
 
458
- }
459
- #}
460
 
461
- $this->infoMessage(
462
- "appearance_customized",
463
- $context
464
- );
465
 
466
- }
467
 
468
- }
 
 
469
 
470
- }
 
 
 
 
 
 
 
 
 
 
 
471
 
472
- }
 
 
 
473
 
474
- return;
475
- #print_r( json_decode( $customized ) );
476
- #exit;
477
 
 
478
 
 
 
 
 
 
 
479
 
 
 
 
 
 
 
 
 
480
 
 
 
 
 
481
 
 
 
 
482
  // Set to true to echo some info about stuff
483
  // that can be views in console when saving
484
  $debug = 0;
@@ -486,44 +471,40 @@ return;
486
  $arr_changed_settings = array();
487
  $arr_changed_settings_ids = array();
488
 
 
 
489
 
 
 
 
 
490
 
491
- /*
492
-
493
-
494
- foreach ($settings as $setting) {
495
-
496
- #echo "\n\nsetting";
497
- #sf_d( $setting->id );
498
- #sf_d( $setting->value() );
499
- #sf_d( $setting->post_value() );
500
-
501
- // Get control for this settings
502
- foreach ($sections as $section) {
503
  foreach ($section->controls as $control) {
504
  foreach ($control->settings as $one_setting) {
505
  sf_d( $one_setting->id );
506
  }
507
  }
508
- }
509
 
510
 
511
- }
512
- return;
513
- */
514
- foreach ($sections as $section ) {
515
- #echo "Section: " . $section->id . " (".$section->title.")";
516
  // Id is unique slug
517
  // Can't use title because that's translated
518
- if ($debug) {
519
 
520
  echo "\n-------\n";
521
- echo "Section: " . $section->id . " (".$section->title.")";
522
 
523
  }
524
 
525
  $section_controls = $section->controls;
526
- foreach ($section_controls as $section_control) {
527
 
528
  /*
529
  if ( ! $section_control->check_capabilities() ) {
@@ -536,10 +517,10 @@ return;
536
  // Settings is always array, but mostly with just one setting in it it seems like
537
  $section_control_settings = $section_control->settings;
538
 
539
- if ($debug) {
540
  echo "\n\nControl ";
541
- echo $section_control->id . " (". $section_control->label . ")";
542
- //echo "\ncontrol setting: " . $section_control->setting;
543
  // echo "\nSettings:";
544
  }
545
 
@@ -548,7 +529,8 @@ return;
548
  har underlig setting
549
  setting = blogname = uppdateras som en tok!
550
  */
551
- /*if ( $section_control->id == "ttfmake_stylekit-info" ) {
 
552
  print_r( sizeof($section_control_settings) );
553
  echo "\nid: " . $section_control_settings[0]->id;
554
  echo "\ntitle: " . $section_control_settings[0]->title;
@@ -557,7 +539,7 @@ return;
557
 
558
  foreach ( $section_control_settings as $one_setting ) {
559
 
560
- if ($debug) {
561
  // setting id is supposed to be unique, but some themes
562
  // seems to register "blogname" for example
563
  // which messes things up...
@@ -572,37 +554,33 @@ return;
572
  $new_value = $one_setting->post_value();
573
 
574
  // If old and new value is different then we log
575
- if ($old_value != $new_value && ! in_array($one_setting_id, $arr_changed_settings_ids) ) {
576
- #if ( $old_value != $new_value ) {
577
-
578
- if ($debug) {
579
  echo "\nSetting with id ";
580
  echo $one_setting->id;
581
- echo " changed";
582
  echo "\nold value $old_value";
583
  echo "\nnew value $new_value";
584
  }
585
 
586
  $arr_changed_settings[] = array(
587
- "setting_id" => $one_setting->id,
588
- "setting_old_value" => $old_value,
589
- "setting_new_value" => $new_value,
590
- "control_id" => $section_control->id,
591
- "control_label" => $section_control->label,
592
- "control_type" => $section_control->type,
593
- "section_id" => $section->id,
594
- "section_title" => $section->title,
595
  );
596
 
597
  $arr_changed_settings_ids[] = $one_setting->id;
598
 
599
- } // if settings changed
600
-
601
- } // foreach setting
602
-
603
- } // foreach control
604
-
605
- } // foreach section
606
 
607
  /*
608
  arr_changed_settingsArray
@@ -633,9 +611,9 @@ return;
633
 
634
  )
635
  */
636
- if ($arr_changed_settings) {
637
 
638
- if ($debug) {
639
  echo "\narr_changed_settings";
640
  print_r( $arr_changed_settings );
641
  }
@@ -647,12 +625,11 @@ return;
647
  foreach ( $arr_changed_settings as $one_changed_setting ) {
648
 
649
  $this->infoMessage(
650
- "appearance_customized",
651
  $one_changed_setting
652
  );
653
 
654
  }
655
-
656
  }
657
 
658
  }
@@ -663,7 +640,7 @@ return;
663
  */
664
  function on_page_load_themes() {
665
 
666
- //sf_d($_REQUEST, "request");exit;
667
  /*
668
  request:
669
  Array
@@ -674,7 +651,7 @@ return;
674
  )
675
  */
676
 
677
- if ( ! isset($_GET["action"]) || $_GET["action"] != "activate") {
678
  return;
679
  }
680
 
@@ -712,55 +689,53 @@ return;
712
  )
713
 
714
  */
715
- if ( ! is_a($current_theme, "WP_Theme") ) {
716
  return;
717
  }
718
- #sf_d($current_theme);
719
-
720
  $this->prev_theme_data = array(
721
- "name" => $current_theme->name,
722
- "version" => $current_theme->version
723
  );
724
 
725
  }
726
 
727
- function on_switch_theme($new_name, $new_theme) {
728
 
729
  $prev_theme_data = $this->prev_theme_data;
730
 
731
  $this->infoMessage(
732
- "theme_switched",
733
  array(
734
- "theme_name" => $new_name,
735
- "theme_version" => $new_theme->version,
736
- "prev_theme_name" => $prev_theme_data["name"],
737
- "prev_theme_version" => $prev_theme_data["version"]
738
  )
739
  );
740
 
741
  }
742
 
743
- function getLogRowDetailsOutput($row) {
744
 
745
  $context = $row->context;
746
- $message_key = $context["_message_key"];
747
- $output = "";
748
 
749
  // Theme customizer
750
- if ( "appearance_customized" == $message_key ) {
751
-
752
- #if ( ! class_exists("WP_Customize_Manager") ) {
753
- # require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
754
- # $wp_customize = new WP_Customize_Manager;
755
- #}
756
 
757
- //$output .= "<pre>" . print_r($context, true);
758
- if ( isset( $context["setting_old_value"] ) && isset( $context["setting_new_value"] ) ) {
 
 
 
 
759
 
760
  $output .= "<table class='SimpleHistoryLogitem__keyValueTable'>";
761
 
762
  // Output section, if saved
763
- if ( ! empty( $context["section_id"] ) ) {
764
  $output .= sprintf(
765
  '
766
  <tr>
@@ -768,33 +743,32 @@ return;
768
  <td>%2$s</td>
769
  </tr>
770
  ',
771
- __("Section", "simple-history"),
772
- esc_html( $context["section_id"] )
773
  );
774
  }
775
 
776
  // Don't output prev and new value if none exist
777
- if ( empty( $context["setting_old_value"] ) && empty( $context["setting_new_value"] ) ) {
778
 
779
  // empty, so skip
780
-
781
  } else {
782
 
783
  // if control is color let's be fancy and output as color
784
- $control_type = isset( $context["control_type"] ) ? $context["control_type"] : "";
785
- $str_old_value_prepend = "";
786
- $str_new_value_prepend = "";
787
 
788
- if ("color" == $control_type) {
789
 
790
  $str_old_value_prepend .= sprintf(
791
  '<span style="background-color: #%1$s; width: 1em; display: inline-block;">&nbsp;</span> ',
792
- esc_attr( ltrim( $context["setting_old_value"], " #" ) )
793
  );
794
 
795
  $str_new_value_prepend .= sprintf(
796
  '<span style="background-color: #%1$s; width: 1em; display: inline-block;">&nbsp;</span> ',
797
- esc_attr( ltrim( $context["setting_new_value"], "#" ) )
798
  );
799
 
800
  }
@@ -806,8 +780,8 @@ return;
806
  <td>%3$s%2$s</td>
807
  </tr>
808
  ',
809
- __("New value", "simple-history"),
810
- esc_html( $context["setting_new_value"] ),
811
  $str_new_value_prepend
812
  );
813
 
@@ -818,20 +792,17 @@ return;
818
  <td>%3$s%2$s</td>
819
  </tr>
820
  ',
821
- __("Old value", "simple-history"),
822
- esc_html( $context["setting_old_value"] ),
823
  $str_old_value_prepend
824
  );
825
 
 
826
 
827
- }
828
-
829
- $output .= "</table>";
830
-
831
- }
832
 
833
-
834
- }
835
 
836
  return $output;
837
 
@@ -840,41 +811,39 @@ return;
840
  /**
841
  * Add widget name and sidebar name to output
842
  */
843
- function getLogRowPlainTextOutput($row) {
844
 
845
  $context = $row->context;
846
- $message_key = $context["_message_key"];
847
  $message = $row->message;
848
- $output = "";
849
 
850
  // Widget changed or added or removed
851
  // Simple replace widget_id_base and sidebar_id with widget name and sidebar name
852
- if ( in_array($message_key, array("widget_added", "widget_edited", "widget_removed") ) ) {
853
 
854
- $widget = $this->getWidgetByIdBase( $context["widget_id_base"] );
855
- $sidebar = $this->getSidebarById( $context["sidebar_id"] );
856
 
857
  if ( $widget && $sidebar ) {
858
 
859
  // Translate message first
860
- $message = $this->messages[ $message_key ]["translated_text"];
861
 
862
  $message = $this->interpolate( $message, array(
863
- "widget_id_base" => $widget->name,
864
- "sidebar_id" => $sidebar["name"],
865
  ), $row );
866
 
867
  $output .= $message;
868
 
869
  }
870
-
871
-
872
  }
873
 
874
  // Fallback to default/parent output if nothing was added to output
875
  if ( ! $output ) {
876
 
877
- $output .= parent::getLogRowPlainTextOutput($row);
878
 
879
  }
880
 
@@ -926,11 +895,12 @@ return;
926
 
927
  /**
928
  * A widget is changed, i.e. new values are saved
 
929
  * @TODO: first time a widget is added it seems to call this and we get double edit logs that are confusing
930
  */
931
- function on_widget_update_callback($instance, $new_instance, $old_instance, $widget_instance) {
932
 
933
- #sf_d($instance);
934
  /*
935
  Array
936
  (
@@ -940,7 +910,7 @@ return;
940
 
941
  */
942
 
943
- #sf_d($new_instance);
944
  /*
945
  Custom Menu
946
  Array
@@ -950,7 +920,7 @@ return;
950
  )
951
  */
952
 
953
- #sf_d($old_instance);
954
  /*
955
  Array
956
  (
@@ -959,7 +929,7 @@ return;
959
  )
960
  */
961
 
962
- #sf_d($widget_instance);
963
  /*
964
  WP_Nav_Menu_Widget Object
965
  (
@@ -994,30 +964,29 @@ return;
994
  $context = array();
995
 
996
  // Add widget info
997
- $context["widget_id_base"] = $widget_id_base;
998
  $widget = $this->getWidgetByIdBase( $widget_id_base );
999
- if ($widget) {
1000
- $context["widget_name_translated"] = $widget->name;
1001
  }
1002
 
1003
  // Add sidebar info
1004
- $sidebar_id = $_POST["sidebar"];
1005
- $context["sidebar_id"] = $sidebar_id;
1006
  $sidebar = $this->getSidebarById( $sidebar_id );
1007
- if ($sidebar) {
1008
- $context["sidebar_name_translated"] = $sidebar["name"];
1009
  }
1010
 
1011
  // Calculate changes
1012
- $context["old_instance"] = $this->simpleHistory->json_encode( $old_instance );
1013
- $context["new_instance"] = $this->simpleHistory->json_encode( $new_instance );
1014
 
1015
  $this->infoMessage(
1016
- "widget_edited",
1017
  $context
1018
  );
1019
 
1020
-
1021
  return $instance;
1022
 
1023
  }
@@ -1066,26 +1035,26 @@ return;
1066
  */
1067
  function on_action_sidebar_admin_setup__detect_widget_add() {
1068
 
1069
- if ( isset( $_POST["add_new"] ) && ! empty( $_POST["add_new"] ) && isset( $_POST["sidebar"] ) && isset( $_POST["id_base"] ) ) {
1070
 
1071
  // Add widget info
1072
- $widget_id_base = $_POST["id_base"];
1073
- $context["widget_id_base"] = $widget_id_base;
1074
  $widget = $this->getWidgetByIdBase( $widget_id_base );
1075
- if ($widget) {
1076
- $context["widget_name_translated"] = $widget->name;
1077
  }
1078
 
1079
  // Add sidebar info
1080
- $sidebar_id = $_POST["sidebar"];
1081
- $context["sidebar_id"] = $sidebar_id;
1082
  $sidebar = $this->getSidebarById( $sidebar_id );
1083
- if ($sidebar) {
1084
- $context["sidebar_name_translated"] = $sidebar["name"];
1085
  }
1086
 
1087
  $this->infoMessage(
1088
- "widget_added",
1089
  $context
1090
  );
1091
 
@@ -1098,28 +1067,28 @@ return;
1098
  function on_action_sidebar_admin_setup__detect_widget_delete() {
1099
 
1100
  // Widget was deleted
1101
- if ( isset( $_POST["delete_widget"] ) ) {
1102
 
1103
  $context = array();
1104
 
1105
  // Add widget info
1106
- $widget_id_base = $_POST["id_base"];
1107
- $context["widget_id_base"] = $widget_id_base;
1108
  $widget = $this->getWidgetByIdBase( $widget_id_base );
1109
- if ($widget) {
1110
- $context["widget_name_translated"] = $widget->name;
1111
  }
1112
 
1113
  // Add sidebar info
1114
- $sidebar_id = $_POST["sidebar"];
1115
- $context["sidebar_id"] = $sidebar_id;
1116
  $sidebar = $this->getSidebarById( $sidebar_id );
1117
- if ($sidebar) {
1118
- $context["sidebar_name_translated"] = $sidebar["name"];
1119
  }
1120
 
1121
  $this->infoMessage(
1122
- "widget_removed",
1123
  $context
1124
  );
1125
 
@@ -1133,7 +1102,7 @@ return;
1133
  * @param string $sidebar_id
1134
  * @return sidebar info or false on failure
1135
  */
1136
- function getSidebarById($sidebar_id) {
1137
 
1138
  $sidebars = isset( $GLOBALS['wp_registered_sidebars'] ) ? $GLOBALS['wp_registered_sidebars'] : false;
1139
 
@@ -1158,22 +1127,21 @@ return;
1158
  * @param string $id_base
1159
  * @return wp_widget object or false on failure
1160
  */
1161
- function getWidgetByIdBase($widget_id_base) {
1162
 
1163
- $widget_factory = isset( $GLOBALS["wp_widget_factory"] ) ? $GLOBALS["wp_widget_factory"] : false;
1164
 
1165
  if ( ! $widget_factory ) {
1166
  return false;
1167
  }
1168
 
1169
- foreach ($widget_factory->widgets as $one_widget) {
1170
 
1171
  if ( $one_widget->id_base == $widget_id_base ) {
1172
 
1173
  return $one_widget;
1174
 
1175
  }
1176
-
1177
  }
1178
 
1179
  return false;
20
  function getInfo() {
21
 
22
  $arr_info = array(
23
+ 'name' => 'Theme Logger',
24
+ 'description' => 'Logs theme edits',
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' ),
34
+ 'widget_order_changed' => __( 'Changed widget order "{widget_id_base}" in sidebar "{sidebar_id}"', 'simple-history' ),
35
+ 'widget_edited' => __( 'Changed widget "{widget_id_base}" in sidebar "{sidebar_id}"', 'simple-history' ),
36
+ 'custom_background_changed' => __( 'Changed settings for the theme custom background', 'simple-history' ),
37
  ),
38
+ 'labels' => array(
39
+ 'search' => array(
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
  ),
55
+ _x( 'Changed appearance of themes', 'Theme logger: search', 'simple-history' ) => array(
56
+ 'appearance_customized'
57
  ),
58
+ _x( 'Added widgets', 'Theme logger: search', 'simple-history' ) => array(
59
+ 'widget_added'
60
  ),
61
+ _x( 'Removed widgets', 'Theme logger: search', 'simple-history' ) => array(
62
+ 'widget_removed'
63
  ),
64
+ _x( 'Changed widgets order', 'Theme logger: search', 'simple-history' ) => array(
65
+ 'widget_order_changed'
66
  ),
67
+ _x( 'Edited widgets', 'Theme logger: search', 'simple-history' ) => array(
68
+ 'widget_edited'
69
  ),
70
+ _x( 'Background of themes changed', 'Theme logger: search', 'simple-history' ) => array(
71
+ 'custom_background_changed'
72
  ),
73
+ ),
74
+ ),// end search array
75
+ ),// end labels
76
 
77
  );
78
 
84
 
85
  /**
86
  * Fires after the theme is switched.
87
+ *
88
  * @param string $new_name Name of the new theme.
89
  * @param WP_Theme $new_theme WP_Theme instance of the new theme.
90
  */
91
+ add_action( 'switch_theme', array( $this, 'on_switch_theme' ), 10, 2 );
92
+ add_action( 'load-themes.php', array( $this, 'on_page_load_themes' ) );
93
 
94
+ add_action( 'customize_save', array( $this, 'on_action_customize_save' ) );
95
 
96
+ add_action( 'sidebar_admin_setup', array( $this, 'on_action_sidebar_admin_setup__detect_widget_delete' ) );
97
+ add_action( 'sidebar_admin_setup', array( $this, 'on_action_sidebar_admin_setup__detect_widget_add' ) );
98
+ // add_action("wp_ajax_widgets-order", array( $this, "on_action_sidebar_admin_setup__detect_widget_order_change"), 1 );
99
+ // add_action("sidebar_admin_setup", array( $this, "on_action_sidebar_admin_setup__detect_widget_edit") );
100
+ add_filter( 'widget_update_callback', array( $this, 'on_widget_update_callback' ), 10, 4 );
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
 
120
  */
121
  function on_deleted_site_transient_theme_deleted( $transient = null ) {
122
 
123
+ if ( 'update_themes' !== $transient ) {
124
  return;
125
  }
126
 
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
 
190
  }
191
 
192
  // Must be type theme and action install
193
+ if ( $arr_data['type'] !== 'theme' || $arr_data['action'] !== 'update' ) {
194
  return;
195
  }
196
 
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
 
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
 
252
  function on_upgrader_process_complete_theme_install( $upgrader_instance = null, $arr_data = null ) {
253
 
254
  /*
 
255
  For theme installs $arr_data looks like:
256
 
257
  Array
268
  }
269
 
270
  // Must be type theme and action install
271
+ if ( $arr_data['type'] !== 'theme' || $arr_data['action'] !== 'install' ) {
272
  return;
273
  }
274
 
314
  $theme_name = empty( $skin->api->name ) ? null : $skin->api->name;
315
  $theme_slug = empty( $skin->api->slug ) ? null : $skin->api->slug;
316
  $theme_version = empty( $skin->api->version ) ? null : $skin->api->version;
317
+ // $theme_screenshot_url = $skin->api->screenshot_url;
318
+ // $theme_last_updated = $skin->api->last_updated;
319
+ // $theme_last_homepage = $skin->api->last_homepage;
320
+ // $theme_download_link = $skin->api->last_download_link;
 
321
  $this->infoMessage(
322
+ 'theme_installed',
323
  array(
324
+ 'theme_name' => $theme_name,
325
+ 'theme_version' => $theme_version,
326
  // "debug_skin" => $skin_str
327
  )
328
  );
336
  }
337
 
338
  $arr_valid_post_keys = array(
339
+ 'reset-background' => 1,
340
+ 'remove-background' => 1,
341
+ 'background-repeat' => 1,
342
+ 'background-position-x' => 1,
343
+ 'background-attachment' => 1,
344
+ 'background-color' => 1,
345
  );
346
 
347
+ $valid_post_key_exists = array_intersect_key( $arr_valid_post_keys, $_POST );
348
 
349
+ if ( ! empty( $valid_post_key_exists ) ) {
350
 
351
  $context = array();
352
  // $context["POST"] = $this->simpleHistory->json_encode( $_POST );
 
353
  $this->infoMessage(
354
+ 'custom_background_changed',
355
  $context
356
  );
357
 
362
  /*
363
  WP_Customize_Manager $this WP_Customize_Manager instance.
364
  */
365
+ function on_action_customize_save( $customize_manager ) {
366
 
367
  /*
368
  - Loop through all sections
384
  nav - Navigation
385
  static_front_page - Static Front Page
386
  */
387
+ /*
388
+ Array
389
+ (
390
+ [wp_customize] => on
391
+ [theme] => make
392
+ [customized] => {\"widget_pages[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_calendar[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_calendar[6]\":{\"encoded_serialized_instance\":\"YToxOntzOjU6InRpdGxlIjtzOjE3OiJTZWUgd2hhdCBoYXBwZW5zISI7fQ==\",\"title\":\"See what happens!\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"ca37c1913982fa69bce33f77cef871cd\"},\"widget_calendar[7]\":{\"encoded_serialized_instance\":\"YToxOntzOjU6InRpdGxlIjtzOjg6IkthbGVuZGVyIjt9\",\"title\":\"Kalender\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"c602d6d891e3f7addb11ca21ac142b49\"},\"widget_archives[4]\":{\"encoded_serialized_instance\":\"YTozOntzOjU6InRpdGxlIjtzOjA6IiI7czo1OiJjb3VudCI7aTowO3M6ODoiZHJvcGRvd24iO2k6MDt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"3480afa3934342872c740122c4988ab5\"},\"widget_archives[6]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_meta[2]\":{\"encoded_serialized_instance\":\"YToxOntzOjU6InRpdGxlIjtzOjA6IiI7fQ==\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"b518e607928dcfc07867f25e07a3a875\"},\"widget_search[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_text[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_categories[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_recent-posts[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_recent-comments[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_rss[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_tag_cloud[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_nav_menu[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_caldera_forms_widget[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_edd_cart_widget[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_edd_categories_tags_widget[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_edd_categories_tags_widget[2]\":{\"encoded_serialized_instance\":\"YTo0OntzOjU6InRpdGxlIjtzOjA6IiI7czo4OiJ0YXhvbm9teSI7czoxNzoiZG93bmxvYWRfY2F0ZWdvcnkiO3M6NToiY291bnQiO3M6MDoiIjtzOjEwOiJoaWRlX2VtcHR5IjtzOjA6IiI7fQ==\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"afb767ddd896180593a758ba3228a6a4\"},\"widget_edd_product_details[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"widget_icl_lang_sel_widget[1]\":{\"encoded_serialized_instance\":\"YTowOnt9\",\"title\":\"\",\"is_widget_customizer_js_value\":true,\"instance_hash_key\":\"1eb11012ea65a32e655e37f998225608\"},\"sidebars_widgets[wp_inactive_widgets]\":[\"calendar-6\",\"calendar-7\",\"archives-4\",\"archives-6\",\"edd_categories_tags_widget-2\"],\"sidebars_widgets[sidebar-left]\":[\"meta-2\"],\"sidebars_widgets[sidebar-right]\":[],\"sidebars_widgets[footer-1]\":[],\"sidebars_widgets[footer-2]\":[],\"sidebars_widgets[footer-3]\":[],\"sidebars_widgets[footer-4]\":[],\"blogname\":\"My test sitexxxxx\",\"blogdescription\":\"hej\",\"header_textcolor\":false,\"background_color\":\"#30d132\",\"header_image\":false,\"header_image_data\":\"\",\"background_image\":\"http://playground-root.ep/assets/uploads/2014/09/small-image.gif\",\"background_image_thumb\":\"\",\"background_repeat\":\"repeat-y\",\"background_position_x\":\"right\",\"background_attachment\":\"scroll\",\"nav_menu_locations[primary]\":\"31\",\"nav_menu_locations[social]\":0,\"nav_menu_locations[header-bar]\":\"32\",\"show_on_front\":\"page\",\"page_on_front\":\"24851\",\"page_for_posts\":\"25253\",\"logo-regular\":\"\",\"logo-retina\":\"\",\"logo-favicon\":\"\",\"logo-apple-touch\":\"\",\"social-facebook\":\"\",\"social-twitter\":\"\",\"social-google-plus-square\":\"\",\"social-linkedin\":\"\",\"social-instagram\":\"\",\"social-flickr\":\"\",\"social-youtube\":\"\",\"social-vimeo-square\":\"\",\"social-pinterest\":\"\",\"social-email\":\"\",\"social-hide-rss\":0,\"social-custom-rss\":\"\",\"font-subset\":\"latin\",\"font-family-site-title\":\"Dawning of a New Day\",\"font-size-site-title\":32,\"font-family-site-tagline\":\"Open Sans\",\"font-size-site-tagline\":12,\"font-family-nav\":\"Open Sans\",\"font-size-nav\":14,\"font-family-subnav\":\"Open Sans\",\"font-size-subnav\":13,\"font-subnav-mobile\":1,\"font-family-widget\":\"Open Sans\",\"font-size-widget\":13,\"font-family-h1\":\"monospace\",\"font-size-h1\":50,\"font-family-h2\":\"monospace\",\"font-size-h2\":37,\"font-family-h3\":\"monospace\",\"font-size-h3\":26,\"font-family-h4\":\"monospace\",\"font-size-h4\":26,\"font-family-h5\":\"monospace\",\"font-size-h5\":18,\"font-family-h6\":\"monospace\",\"font-size-h6\":15,\"font-family-body\":\"Open Sans\",\"font-size-body\":17,\"color-primary\":\"#2fce6f\",\"color-secondary\":\"#35c904\",\"color-text\":\"#969696\",\"color-detail\":\"#b9bcbf\",\"main-background-color\":\"#ffffff\",\"header-bar-background-color\":\"#171717\",\"header-bar-text-color\":\"#16dd66\",\"header-bar-border-color\":\"#171717\",\"header-background-color\":\"#ffffff\",\"header-text-color\":\"#171717\",\"color-site-title\":\"#1a6aba\",\"footer-background-color\":\"#eaecee\",\"footer-text-color\":\"#464849\",\"footer-border-color\":\"#b9bcbf\",\"header-background-image\":\"\",\"header-background-repeat\":\"no-repeat\",\"header-background-position\":\"center\",\"header-background-size\":\"cover\",\"header-layout\":1,\"header-branding-position\":\"left\",\"header-bar-content-layout\":\"flipped\",\"header-text\":\"text\",\"header-show-social\":0,\"header-show-search\":1,\"general-layout\":\"boxed\",\"general-sticky-label\":\"sticky name\",\"main-content-link-underline\":0,\"layout-blog-hide-header\":0,\"layout-blog-hide-footer\":0,\"layout-blog-sidebar-left\":0,\"layout-blog-sidebar-right\":1,\"layout-blog-featured-images\":\"post-header\",\"layout-blog-featured-images-alignment\":\"center\",\"layout-blog-post-date\":\"absolute\",\"layout-blog-post-date-location\":\"top\",\"layout-blog-post-author\":\"avatar\",\"layout-blog-post-author-location\":\"post-footer\",\"layout-blog-auto-excerpt\":0,\"layout-blog-show-categories\":1,\"layout-blog-show-tags\":1,\"layout-blog-comment-count\":\"none\",\"layout-blog-comment-count-location\":\"before-content\",\"layout-archive-hide-header\":0,\"layout-archive-hide-footer\":0,\"layout-archive-sidebar-left\":0,\"layout-archive-sidebar-right\":1,\"layout-archive-featured-images\":\"post-header\",\"layout-archive-featured-images-alignment\":\"center\",\"layout-archive-post-date\":\"absolute\",\"layout-archive-post-date-location\":\"top\",\"layout-archive-post-author\":\"avatar\",\"layout-archive-post-author-location\":\"post-footer\",\"layout-archive-auto-excerpt\":0,\"layout-archive-show-categories\":1,\"layout-archive-show-tags\":1,\"layout-archive-comment-count\":\"none\",\"layout-archive-comment-count-location\":\"before-content\",\"layout-search-hide-header\":0,\"layout-search-hide-footer\":0,\"layout-search-sidebar-left\":true,\"layout-search-sidebar-right\":1,\"layout-search-featured-images\":\"thumbnail\",\"layout-search-featured-images-alignment\":\"center\",\"layout-search-post-date\":\"absolute\",\"layout-search-post-date-location\":\"top\",\"layout-search-post-author\":\"name\",\"layout-search-post-author-location\":\"post-footer\",\"layout-search-auto-excerpt\":1,\"layout-search-show-categories\":1,\"layout-search-show-tags\":1,\"layout-search-comment-count\":\"none\",\"layout-search-comment-count-location\":\"before-content\",\"layout-post-hide-header\":0,\"layout-post-hide-footer\":0,\"layout-post-sidebar-left\":0,\"layout-post-sidebar-right\":0,\"layout-post-featured-images\":\"post-header\",\"layout-post-featured-images-alignment\":\"center\",\"layout-post-post-date\":\"absolute\",\"layout-post-post-date-location\":\"top\",\"layout-post-post-author\":\"name\",\"layout-post-post-author-location\":\"post-footer\",\"layout-post-show-categories\":0,\"layout-post-show-tags\":0,\"layout-post-comment-count\":\"none\",\"layout-post-comment-count-location\":\"before-content\",\"layout-page-hide-header\":0,\"layout-page-hide-footer\":0,\"layout-page-sidebar-left\":0,\"layout-page-sidebar-right\":0,\"layout-page-hide-title\":1,\"layout-page-featured-images\":\"none\",\"layout-page-featured-images-alignment\":\"center\",\"layout-page-post-date\":\"none\",\"layout-page-post-date-location\":\"top\",\"layout-page-post-author\":\"none\",\"layout-page-post-author-location\":\"post-footer\",\"layout-page-comment-count\":\"none\",\"layout-page-comment-count-location\":\"before-content\",\"footer-background-image\":\"\",\"footer-background-repeat\":\"no-repeat\",\"footer-background-position\":\"center\",\"footer-background-size\":\"cover\",\"footer-widget-areas\":3,\"footer-layout\":1,\"footer-text\":\"\",\"footer-show-social\":1,\"background_size\":\"auto\",\"main-background-image\":\"\",\"main-background-repeat\":\"repeat\",\"main-background-position\":\"left\",\"main-background-size\":\"auto\",\"navigation-mobile-label\":\"Menuxx\",\"hide-site-title\":0,\"hide-tagline\":0}
393
+ [nonce] => e983bc7d41
394
+ [action] => customize_save
395
+ )
396
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
 
398
+ /*
399
+ keys in customized = settings id
400
+ */
401
+ // print_r($_REQUEST);
402
+ // Needed to get sections and controls in sorted order
403
+ $customize_manager->prepare_controls();
404
 
405
+ $settings = $customize_manager->settings();
406
+ $sections = $customize_manager->sections();
407
+ $controls = $customize_manager->controls();
408
 
409
+ $customized = json_decode( wp_unslash( $_REQUEST['customized'] ) );
410
 
411
+ foreach ( $customized as $setting_id => $posted_values ) {
 
412
 
413
+ foreach ( $settings as $one_setting ) {
 
 
 
414
 
415
+ if ( $one_setting->id == $setting_id ) {
416
 
417
+ // sf_d("MATCH");
418
+ $old_value = $one_setting->value();
419
+ $new_value = $one_setting->post_value();
420
 
421
+ if ( $old_value != $new_value ) {
422
+
423
+ $context = array(
424
+ 'setting_id' => $one_setting->id,
425
+ 'setting_old_value' => $old_value,
426
+ 'setting_new_value' => $new_value,
427
+ // "control_id" => $section_control->id,
428
+ // "control_label" => $section_control->label,
429
+ // "control_type" => $section_control->type,
430
+ // "section_id" => $section->id,
431
+ // "section_title" => $section->title,
432
+ );
433
 
434
+ // value is changed
435
+ // find which control it belongs to
436
+ // foreach ($sections as $section) {
437
+ foreach ( $controls as $one_control ) {
438
 
439
+ foreach ( $one_control->settings as $section_control_setting ) {
 
 
440
 
441
+ if ( $section_control_setting->id == $setting_id ) {
442
 
443
+ // echo "\n" . $one_control->id;
444
+ // echo "\n" . $one_control->label;
445
+ // echo "\n" . $one_control->type;
446
+ $context['control_id'] = $one_control->id;
447
+ $context['control_label'] = $one_control->label;
448
+ $context['control_type'] = $one_control->type;
449
 
450
+ }
451
+ }
452
+ }
453
+ // }
454
+ $this->infoMessage(
455
+ 'appearance_customized',
456
+ $context
457
+ );
458
 
459
+ }// End if().
460
+ }// End if().
461
+ }// End foreach().
462
+ }// End foreach().
463
 
464
+ return;
465
+ // print_r( json_decode( $customized ) );
466
+ // exit;
467
  // Set to true to echo some info about stuff
468
  // that can be views in console when saving
469
  $debug = 0;
471
  $arr_changed_settings = array();
472
  $arr_changed_settings_ids = array();
473
 
474
+ /*
475
+ foreach ($settings as $setting) {
476
 
477
+ #echo "\n\nsetting";
478
+ #sf_d( $setting->id );
479
+ #sf_d( $setting->value() );
480
+ #sf_d( $setting->post_value() );
481
 
482
+ // Get control for this settings
483
+ foreach ($sections as $section) {
 
 
 
 
 
 
 
 
 
 
484
  foreach ($section->controls as $control) {
485
  foreach ($control->settings as $one_setting) {
486
  sf_d( $one_setting->id );
487
  }
488
  }
489
+ }
490
 
491
 
492
+ }
493
+ return;
494
+ */
495
+ foreach ( $sections as $section ) {
496
+ // echo "Section: " . $section->id . " (".$section->title.")";
497
  // Id is unique slug
498
  // Can't use title because that's translated
499
+ if ( $debug ) {
500
 
501
  echo "\n-------\n";
502
+ echo 'Section: ' . $section->id . ' (' . $section->title . ')';
503
 
504
  }
505
 
506
  $section_controls = $section->controls;
507
+ foreach ( $section_controls as $section_control ) {
508
 
509
  /*
510
  if ( ! $section_control->check_capabilities() ) {
517
  // Settings is always array, but mostly with just one setting in it it seems like
518
  $section_control_settings = $section_control->settings;
519
 
520
+ if ( $debug ) {
521
  echo "\n\nControl ";
522
+ echo $section_control->id . ' (' . $section_control->label . ')';
523
+ // echo "\ncontrol setting: " . $section_control->setting;
524
  // echo "\nSettings:";
525
  }
526
 
529
  har underlig setting
530
  setting = blogname = uppdateras som en tok!
531
  */
532
+ /*
533
+ if ( $section_control->id == "ttfmake_stylekit-info" ) {
534
  print_r( sizeof($section_control_settings) );
535
  echo "\nid: " . $section_control_settings[0]->id;
536
  echo "\ntitle: " . $section_control_settings[0]->title;
539
 
540
  foreach ( $section_control_settings as $one_setting ) {
541
 
542
+ if ( $debug ) {
543
  // setting id is supposed to be unique, but some themes
544
  // seems to register "blogname" for example
545
  // which messes things up...
554
  $new_value = $one_setting->post_value();
555
 
556
  // If old and new value is different then we log
557
+ if ( $old_value != $new_value && ! in_array( $one_setting_id, $arr_changed_settings_ids ) ) {
558
+ // if ( $old_value != $new_value ) {
559
+ if ( $debug ) {
 
560
  echo "\nSetting with id ";
561
  echo $one_setting->id;
562
+ echo ' changed';
563
  echo "\nold value $old_value";
564
  echo "\nnew value $new_value";
565
  }
566
 
567
  $arr_changed_settings[] = array(
568
+ 'setting_id' => $one_setting->id,
569
+ 'setting_old_value' => $old_value,
570
+ 'setting_new_value' => $new_value,
571
+ 'control_id' => $section_control->id,
572
+ 'control_label' => $section_control->label,
573
+ 'control_type' => $section_control->type,
574
+ 'section_id' => $section->id,
575
+ 'section_title' => $section->title,
576
  );
577
 
578
  $arr_changed_settings_ids[] = $one_setting->id;
579
 
580
+ }
581
+ }// End foreach().
582
+ }// End foreach().
583
+ } // End foreach().
 
 
 
584
 
585
  /*
586
  arr_changed_settingsArray
611
 
612
  )
613
  */
614
+ if ( $arr_changed_settings ) {
615
 
616
+ if ( $debug ) {
617
  echo "\narr_changed_settings";
618
  print_r( $arr_changed_settings );
619
  }
625
  foreach ( $arr_changed_settings as $one_changed_setting ) {
626
 
627
  $this->infoMessage(
628
+ 'appearance_customized',
629
  $one_changed_setting
630
  );
631
 
632
  }
 
633
  }
634
 
635
  }
640
  */
641
  function on_page_load_themes() {
642
 
643
+ // sf_d($_REQUEST, "request");exit;
644
  /*
645
  request:
646
  Array
651
  )
652
  */
653
 
654
+ if ( ! isset( $_GET['action'] ) || $_GET['action'] != 'activate' ) {
655
  return;
656
  }
657
 
689
  )
690
 
691
  */
692
+ if ( ! is_a( $current_theme, 'WP_Theme' ) ) {
693
  return;
694
  }
695
+ // sf_d($current_theme);
 
696
  $this->prev_theme_data = array(
697
+ 'name' => $current_theme->name,
698
+ 'version' => $current_theme->version,
699
  );
700
 
701
  }
702
 
703
+ function on_switch_theme( $new_name, $new_theme ) {
704
 
705
  $prev_theme_data = $this->prev_theme_data;
706
 
707
  $this->infoMessage(
708
+ 'theme_switched',
709
  array(
710
+ 'theme_name' => $new_name,
711
+ 'theme_version' => $new_theme->version,
712
+ 'prev_theme_name' => $prev_theme_data['name'],
713
+ 'prev_theme_version' => $prev_theme_data['version'],
714
  )
715
  );
716
 
717
  }
718
 
719
+ function getLogRowDetailsOutput( $row ) {
720
 
721
  $context = $row->context;
722
+ $message_key = $context['_message_key'];
723
+ $output = '';
724
 
725
  // Theme customizer
726
+ if ( 'appearance_customized' == $message_key ) {
 
 
 
 
 
727
 
728
+ // if ( ! class_exists("WP_Customize_Manager") ) {
729
+ // require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
730
+ // $wp_customize = new WP_Customize_Manager;
731
+ // }
732
+ // $output .= "<pre>" . print_r($context, true);
733
+ if ( isset( $context['setting_old_value'] ) && isset( $context['setting_new_value'] ) ) {
734
 
735
  $output .= "<table class='SimpleHistoryLogitem__keyValueTable'>";
736
 
737
  // Output section, if saved
738
+ if ( ! empty( $context['section_id'] ) ) {
739
  $output .= sprintf(
740
  '
741
  <tr>
743
  <td>%2$s</td>
744
  </tr>
745
  ',
746
+ __( 'Section', 'simple-history' ),
747
+ esc_html( $context['section_id'] )
748
  );
749
  }
750
 
751
  // Don't output prev and new value if none exist
752
+ if ( empty( $context['setting_old_value'] ) && empty( $context['setting_new_value'] ) ) {
753
 
754
  // empty, so skip
 
755
  } else {
756
 
757
  // if control is color let's be fancy and output as color
758
+ $control_type = isset( $context['control_type'] ) ? $context['control_type'] : '';
759
+ $str_old_value_prepend = '';
760
+ $str_new_value_prepend = '';
761
 
762
+ if ( 'color' == $control_type ) {
763
 
764
  $str_old_value_prepend .= sprintf(
765
  '<span style="background-color: #%1$s; width: 1em; display: inline-block;">&nbsp;</span> ',
766
+ esc_attr( ltrim( $context['setting_old_value'], ' #' ) )
767
  );
768
 
769
  $str_new_value_prepend .= sprintf(
770
  '<span style="background-color: #%1$s; width: 1em; display: inline-block;">&nbsp;</span> ',
771
+ esc_attr( ltrim( $context['setting_new_value'], '#' ) )
772
  );
773
 
774
  }
780
  <td>%3$s%2$s</td>
781
  </tr>
782
  ',
783
+ __( 'New value', 'simple-history' ),
784
+ esc_html( $context['setting_new_value'] ),
785
  $str_new_value_prepend
786
  );
787
 
792
  <td>%3$s%2$s</td>
793
  </tr>
794
  ',
795
+ __( 'Old value', 'simple-history' ),
796
+ esc_html( $context['setting_old_value'] ),
797
  $str_old_value_prepend
798
  );
799
 
800
+ }// End if().
801
 
802
+ $output .= '</table>';
 
 
 
 
803
 
804
+ }// End if().
805
+ }// End if().
806
 
807
  return $output;
808
 
811
  /**
812
  * Add widget name and sidebar name to output
813
  */
814
+ function getLogRowPlainTextOutput( $row ) {
815
 
816
  $context = $row->context;
817
+ $message_key = $context['_message_key'];
818
  $message = $row->message;
819
+ $output = '';
820
 
821
  // Widget changed or added or removed
822
  // Simple replace widget_id_base and sidebar_id with widget name and sidebar name
823
+ if ( in_array( $message_key, array( 'widget_added', 'widget_edited', 'widget_removed' ) ) ) {
824
 
825
+ $widget = $this->getWidgetByIdBase( $context['widget_id_base'] );
826
+ $sidebar = $this->getSidebarById( $context['sidebar_id'] );
827
 
828
  if ( $widget && $sidebar ) {
829
 
830
  // Translate message first
831
+ $message = $this->messages[ $message_key ]['translated_text'];
832
 
833
  $message = $this->interpolate( $message, array(
834
+ 'widget_id_base' => $widget->name,
835
+ 'sidebar_id' => $sidebar['name'],
836
  ), $row );
837
 
838
  $output .= $message;
839
 
840
  }
 
 
841
  }
842
 
843
  // Fallback to default/parent output if nothing was added to output
844
  if ( ! $output ) {
845
 
846
+ $output .= parent::getLogRowPlainTextOutput( $row );
847
 
848
  }
849
 
895
 
896
  /**
897
  * A widget is changed, i.e. new values are saved
898
+ *
899
  * @TODO: first time a widget is added it seems to call this and we get double edit logs that are confusing
900
  */
901
+ function on_widget_update_callback( $instance, $new_instance, $old_instance, $widget_instance ) {
902
 
903
+ // sf_d($instance);
904
  /*
905
  Array
906
  (
910
 
911
  */
912
 
913
+ // sf_d($new_instance);
914
  /*
915
  Custom Menu
916
  Array
920
  )
921
  */
922
 
923
+ // sf_d($old_instance);
924
  /*
925
  Array
926
  (
929
  )
930
  */
931
 
932
+ // sf_d($widget_instance);
933
  /*
934
  WP_Nav_Menu_Widget Object
935
  (
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
 
985
  $this->infoMessage(
986
+ 'widget_edited',
987
  $context
988
  );
989
 
 
990
  return $instance;
991
 
992
  }
1035
  */
1036
  function on_action_sidebar_admin_setup__detect_widget_add() {
1037
 
1038
+ if ( isset( $_POST['add_new'] ) && ! empty( $_POST['add_new'] ) && isset( $_POST['sidebar'] ) && isset( $_POST['id_base'] ) ) {
1039
 
1040
  // Add widget info
1041
+ $widget_id_base = $_POST['id_base'];
1042
+ $context['widget_id_base'] = $widget_id_base;
1043
  $widget = $this->getWidgetByIdBase( $widget_id_base );
1044
+ if ( $widget ) {
1045
+ $context['widget_name_translated'] = $widget->name;
1046
  }
1047
 
1048
  // Add sidebar info
1049
+ $sidebar_id = $_POST['sidebar'];
1050
+ $context['sidebar_id'] = $sidebar_id;
1051
  $sidebar = $this->getSidebarById( $sidebar_id );
1052
+ if ( $sidebar ) {
1053
+ $context['sidebar_name_translated'] = $sidebar['name'];
1054
  }
1055
 
1056
  $this->infoMessage(
1057
+ 'widget_added',
1058
  $context
1059
  );
1060
 
1067
  function on_action_sidebar_admin_setup__detect_widget_delete() {
1068
 
1069
  // Widget was deleted
1070
+ if ( isset( $_POST['delete_widget'] ) ) {
1071
 
1072
  $context = array();
1073
 
1074
  // Add widget info
1075
+ $widget_id_base = $_POST['id_base'];
1076
+ $context['widget_id_base'] = $widget_id_base;
1077
  $widget = $this->getWidgetByIdBase( $widget_id_base );
1078
+ if ( $widget ) {
1079
+ $context['widget_name_translated'] = $widget->name;
1080
  }
1081
 
1082
  // Add sidebar info
1083
+ $sidebar_id = $_POST['sidebar'];
1084
+ $context['sidebar_id'] = $sidebar_id;
1085
  $sidebar = $this->getSidebarById( $sidebar_id );
1086
+ if ( $sidebar ) {
1087
+ $context['sidebar_name_translated'] = $sidebar['name'];
1088
  }
1089
 
1090
  $this->infoMessage(
1091
+ 'widget_removed',
1092
  $context
1093
  );
1094
 
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
 
1127
  * @param string $id_base
1128
  * @return wp_widget object or false on failure
1129
  */
1130
+ function getWidgetByIdBase( $widget_id_base ) {
1131
 
1132
+ $widget_factory = isset( $GLOBALS['wp_widget_factory'] ) ? $GLOBALS['wp_widget_factory'] : false;
1133
 
1134
  if ( ! $widget_factory ) {
1135
  return false;
1136
  }
1137
 
1138
+ foreach ( $widget_factory->widgets as $one_widget ) {
1139
 
1140
  if ( $one_widget->id_base == $widget_id_base ) {
1141
 
1142
  return $one_widget;
1143
 
1144
  }
 
1145
  }
1146
 
1147
  return false;
loggers/SimpleUserLogger.php CHANGED
@@ -3,147 +3,144 @@
3
  /**
4
  * Logs changes to user logins (and logouts)
5
  */
6
- class SimpleUserLogger extends SimpleLogger
7
- {
8
-
9
- public $slug = __CLASS__;
10
-
11
- /**
12
- * Get array with information about this logger
13
- *
14
- * @return array
15
- */
16
- public function getInfo()
17
- {
18
-
19
- $arr_info = array(
20
- "name" => __("User Logger", "simple-history"),
21
- "description" => __("Logs user logins, logouts, and failed logins", "simple-history"),
22
- "capability" => "edit_users",
23
- "messages" => array(
24
- 'user_login_failed' => __(
25
- 'Failed to login with username "{login}" (incorrect password entered)',
26
- "simple-history"
27
- ),
28
- 'user_unknown_login_failed' => __(
29
- 'Failed to login with username "{failed_username}" (username does not exist)',
30
- "simple-history"
31
- ),
32
- 'user_logged_in' => __('Logged in', "simple-history"),
33
- 'user_unknown_logged_in' => __("Unknown user logged in", "simple-history"),
34
- 'user_logged_out' => __("Logged out", "simple-history"),
35
- 'user_updated_profile' => __(
36
- "Edited the profile for user {edited_user_login} ({edited_user_email})",
37
- "simple-history"
38
- ),
39
- 'user_created' => __(
40
- "Created user {created_user_login} ({created_user_email}) with role {created_user_role}",
41
- "simple-history"
42
- ),
43
- 'user_deleted' => __("Deleted user {deleted_user_login} ({deleted_user_email})", "simple-history"),
44
- "user_password_reseted" => __("Reset their password", "simple-history"),
45
- "user_requested_password_reset_link" => __(
46
- "Requested a password reset link for user with login '{user_login}' and email '{user_email}'",
47
- "simple-history"
48
- ),
49
-
50
- /*
51
  Text used in admin:
52
  Log Out of All Other Sessions
53
  Left your account logged in at a public computer?
54
  Lost your phone? This will log you out everywhere except your current browser
55
  */
56
- 'user_session_destroy_others' => _x(
57
- 'Logged out from all other sessions',
58
- 'User destroys other login sessions for themself',
59
- 'simple-history'
60
- ),
61
- /*
62
  Text used in admin:
63
  'Log %s out of all sessions' ), $profileuser->display_name );
64
  */
65
- 'user_session_destroy_everywhere' => _x(
66
- 'Logged out "{user_display_name}" from all sessions',
67
- 'User destroys all login sessions for a user',
68
- 'simple-history'
69
- ),
70
- ),
71
-
72
- "labels" => array(
73
- "search" => array(
74
- "label" => _x("Users", "User logger: search", "simple-history"),
75
- "label_all" => _x("All user activity", "User logger: search", "simple-history"),
76
- "options" => array(
77
- _x("Successful user logins", "User logger: search", "simple-history") => array(
78
- "user_logged_in",
79
- "user_unknown_logged_in",
80
- ),
81
- _x("Failed user logins", "User logger: search", "simple-history") => array(
82
- 'user_login_failed',
83
- 'user_unknown_login_failed',
84
- ),
85
- _x('User logouts', 'User logger: search', 'simple-history') => array(
86
- "user_logged_out",
87
- ),
88
- _x('Created users', 'User logger: search', 'simple-history') => array(
89
- "user_created",
90
- ),
91
- _x("User profile updates", "User logger: search", "simple-history") => array(
92
- "user_updated_profile",
93
- ),
94
- _x('User deletions', 'User logger: search', 'simple-history') => array(
95
- "user_deleted",
96
- ),
97
-
98
- ),
99
- ), // end search
100
-
101
- ), // end labels
102
-
103
- );
104
-
105
- return $arr_info;
106
- }
107
-
108
- /**
109
- * Add actions and filters when logger is loaded by Simple History
110
- */
111
- public function loaded()
112
- {
113
-
114
- // Plain logins and logouts
115
- add_action("wp_login", array($this, "onWpLogin"), 10, 3);
116
- add_action("wp_logout", array($this, "onWpLogout"));
117
-
118
- // Failed login attempt to username that exists
119
- add_action("wp_authenticate_user", array($this, "onWpAuthenticateUser"), 10, 2);
120
-
121
- // Failed to login to user that did not exist (perhaps brute force)
122
- // run this later than 10 because wordpress own email login check is done with prio 20
123
- // so if we run at 10 we just get null
124
- add_filter('authenticate', array($this, "onAuthenticate"), 30, 3);
125
-
126
- // User is changed
127
- #add_action("profile_update", array($this, "on_profile_update"), 10, 2);
128
-
129
- // User is created
130
- add_action("user_register", array($this, "onUserRegister"), 10, 2);
131
-
132
- // User is deleted
133
- add_action('delete_user', array($this, "onDeleteUser"), 10, 2);
134
-
135
- // User sessions is destroyed. AJAX call that we hook onto early.
136
- add_action("wp_ajax_destroy-sessions", array($this, "onDestroyUserSession"), 0);
137
-
138
- // User reaches reset password (from link or only from user created link)
139
- add_action('validate_password_reset', array($this, "onValidatePasswordReset" ), 10, 2);
140
-
141
- add_action('retrieve_password_message', array($this, "onRetrievePasswordMessage" ), 10, 4);
142
-
143
- add_filter('insert_user_meta', array($this, "onInsertUserMeta" ), 10, 3);
144
- }
145
-
146
- /*
147
  * Called before the user is updated
148
  *
149
  * Filter a user's meta values and keys before the user is created or updated.
@@ -168,183 +165,174 @@ class SimpleUserLogger extends SimpleLogger
168
  * @param WP_User $user User object.
169
  * @param bool $update Whether the user is being updated rather than created.
170
  */
171
- public function onInsertUserMeta($meta, $user, $update)
172
- {
173
-
174
- // We only log updates here
175
- if (! $update) {
176
- return $meta;
177
- }
178
-
179
- // $user should be set, but check just in case
180
- if (empty($user) || ! is_object($user)) {
181
- return $meta;
182
- }
183
-
184
- // Make of copy of the posted data, because we change the keys
185
- $posted_data = $_POST;
186
- $posted_data = stripslashes_deep($posted_data);
187
-
188
- // Paranoid mode, just in case some other plugin fires the "insert_user_meta"
189
- // filter and the user.php file is not loaded for some super wierd reason
190
- if (! function_exists("_get_additional_user_keys")) {
191
- return $meta;
192
- }
193
-
194
- // Get the default fields to include.
195
- // This includes contact methods (including filter, so more could have been added)
196
- $arr_keys_to_check = _get_additional_user_keys($user);
197
-
198
- // Somehow some fields are not include above, so add them manually
199
- $arr_keys_to_check = array_merge(
200
- $arr_keys_to_check,
201
- array( 'user_email', 'user_url', 'display_name')
202
- );
203
-
204
- // Skip some keys, because to much info or I don't know what they are
205
- $arr_keys_to_check = array_diff($arr_keys_to_check, array("use_ssl"));
206
-
207
- // Some keys have different ways of getting data from user
208
- // so change posted object to match those
209
- $posted_data["user_url"] = isset($posted_data["url"]) ? $posted_data["url"] : null;
210
- $posted_data["show_admin_bar_front"] = isset($posted_data["admin_bar_front"]) ? true : null;
211
- $posted_data["user_email"] = isset($posted_data["email"]) ? $posted_data["email"] : null;
212
-
213
- // Display name publicly as = POST "display_name"
214
- #var_dump($user->display_name);
215
-
216
- // Set vals for Enable keyboard shortcuts for comment moderation
217
- $posted_data['comment_shortcuts'] = isset($posted_data['comment_shortcuts']) ? "true" : "false";
218
-
219
- // Set vals for Disable the visual editor when writing
220
- // posted val = string "false" = yes, disable
221
- $posted_data['rich_editing'] = isset($posted_data['rich_editing']) ? "false" : "true";
222
-
223
- // Set vals for Show Toolbar when viewing site
224
- $posted_data['show_admin_bar_front'] = isset($posted_data['admin_bar_front']) ? "true" : "false";
225
-
226
- // if checkbox is checked in admin then this is the saved value on the user object
227
- // @todo:
228
-
229
- // Check if password was updated
230
- $password_changed = false;
231
- if (! empty($posted_data['pass1']) && ! empty($posted_data['pass2']) && $posted_data['pass1'] == $posted_data['pass2']) {
232
- $password_changed = 1;
233
- }
234
-
235
- // Check if role was changed
236
- //[role] => bbp_moderator
237
- $role_changed = false;
238
-
239
- // if user is network admin then role dropdown does not exist and role is not posted here
240
- $new_role = isset($posted_data["role"]) ? $posted_data["role"] : null;
241
-
242
- if ($new_role) {
243
- // as done in user-edit.php
244
- // Compare user role against currently editable roles
245
- $user_roles = array_intersect(array_values($user->roles), array_keys(get_editable_roles()));
246
- $old_role = reset($user_roles);
247
-
248
- $role_changed = $new_role != $old_role;
249
- }
250
-
251
- // Will contain the differences
252
- $user_data_diff = array();
253
-
254
- // locale: sv_SE, empty = english, site-default = site....default!
255
-
256
- // Check all keys for diff values
257
- foreach ($arr_keys_to_check as $one_key_to_check) {
258
- $old_val = $user->$one_key_to_check;
259
- $new_val = isset($posted_data[$one_key_to_check]) ? $posted_data[$one_key_to_check] : null;
260
-
261
- #echo "<hr>key: $one_key_to_check";
262
- #echo "<br>old val: $old_val";
263
- #echo "<br>new val: $new_val";
264
-
265
- // new val must be set, because otherwise we are not setting anything
266
- if (! isset($new_val)) {
267
- continue;
268
- }
269
-
270
- $user_data_diff = $this->addDiff($user_data_diff, $one_key_to_check, $old_val, $new_val);
271
- }
272
-
273
- // Setup basic context
274
- $context = array(
275
- "edited_user_id" => $user->ID,
276
- "edited_user_email" => $user->user_email,
277
- "edited_user_login" => $user->user_login,
278
- "server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null,
279
- );
280
-
281
- if ($password_changed) {
282
- $context["edited_user_password_changed"] = "1";
283
- }
284
-
285
- if ($role_changed) {
286
- $context["user_prev_role"] = $old_role;
287
- $context["user_new_role"] = $new_role;
288
- }
289
-
290
- // Add diff to context
291
- if ($user_data_diff) {
292
- foreach ($user_data_diff as $one_diff_key => $one_diff_vals) {
293
- /*
294
  One diff looks like:
295
  "nickname": {
296
  "old": "MyOldNick",
297
  "new": "MyNewNick"
298
  }
299
  */
300
- $context["user_prev_{$one_diff_key}"] = $one_diff_vals["old"];
301
- $context["user_new_{$one_diff_key}"] = $one_diff_vals["new"];
302
- }
303
- }
304
-
305
- // print_r($context);exit;
306
-
307
- $this->infoMessage("user_updated_profile", $context);
308
-
309
- return $meta;
310
- }
311
-
312
- /**
313
- *
314
- * user requests a reset password link
315
- *
316
- */
317
- public function onRetrievePasswordMessage($message, $key, $user_login, $user_data)
318
- {
319
-
320
- if (isset($_GET["action"]) && ("lostpassword" == $_GET["action"])) {
321
- $context = array(
322
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER,
323
- "message" => $message,
324
- "key" => $key,
325
- "user_login" => $user_login,
326
- );
327
-
328
- if (is_a($user_data, "WP_User")) {
329
- $context["user_email"] = $user_data->user_email;
330
- }
331
-
332
- $this->noticeMessage("user_requested_password_reset_link", $context);
333
- }
334
-
335
- return $message;
336
- }
337
-
338
- /**
339
- * Fired before the password reset procedure is validated.
340
- *
341
- * @param object $errors WP Error object.
342
- * @param WP_User|WP_Error $user WP_User object if the login and reset key match. WP_Error object otherwise.
343
- */
344
- public function onValidatePasswordReset($errors, $user)
345
- {
346
-
347
- /*
348
  User visits the forgot password screen
349
  $errors object are empty
350
  $user contains a user
@@ -357,247 +345,239 @@ class SimpleUserLogger extends SimpleLogger
357
 
358
  */
359
 
360
- $context = array();
361
-
362
- if (is_a($user, "WP_User")) {
363
- $context["_initiator"] = SimpleLoggerLogInitiators::WP_USER;
364
- $context["_user_id"] = $user->ID;
365
- $context["_user_login"] = $user->user_login;
366
- $context["_user_email"] = $user->user_email;
367
- }
368
-
369
- if (isset($_POST['pass1']) && $_POST['pass1'] != $_POST['pass2']) {
370
- // $errors->add( 'password_reset_mismatch', __( 'The passwords do not match.' ) );
371
- // user failed to reset password
372
- }
373
-
374
-
375
- if ((! $errors->get_error_code()) && isset($_POST['pass1']) && !empty($_POST['pass1'])) {
376
- // login_header( __( 'Password Reset' ), '<p class="message reset-pass">'
377
- // . __( 'Your password has been reset.' ) . ' <a href="' . esc_url(
378
- $this->infoMessage("user_password_reseted", $context);
379
- }
380
- }
381
-
382
- /**
383
- * Called when user dessions are destroyed from admin
384
- * Can be called for current logged in user = destroy all other sessions
385
- * or for another user = destroy alla sessions for that user
386
- * Fires from AJAX call
387
- *
388
- * @since 2.0.6
389
- */
390
- public function onDestroyUserSession()
391
- {
392
-
393
- /*
394
  Post params:
395
  nonce: a14df12195
396
  user_id: 1
397
  action: destroy-sessions
398
  */
399
 
400
- $user = get_userdata((int) $_POST['user_id']);
401
-
402
- if ($user) {
403
- if (!current_user_can('edit_user', $user->ID)) {
404
- $user = false;
405
- } elseif (!wp_verify_nonce($_POST['nonce'], 'update-user_' . $user->ID)) {
406
- $user = false;
407
- }
408
- }
409
-
410
- if (!$user) {
411
- // Could not log out user sessions. Please try again.
412
- return;
413
- }
414
-
415
- $sessions = WP_Session_Tokens::get_instance($user->ID);
416
-
417
- $context = array();
418
-
419
- if ($user->ID === get_current_user_id()) {
420
- $this->infoMessage("user_session_destroy_others");
421
- } else {
422
- $context["user_id"] = $user->ID;
423
- $context["user_login"] = $user->user_login;
424
- $context["user_display_name"] = $user->display_name;
425
-
426
- $this->infoMessage("user_session_destroy_everywhere", $context);
427
- }
428
- }
429
-
430
- /**
431
- * Fires before a user is deleted from the database.
432
- *
433
- * @param int $user_id ID of the deleted user.
434
- * @param int|null $reassign ID of the user to reassign posts and links to.
435
- * Default null, for no reassignment.
436
- */
437
- public function onDeleteUser($user_id, $reassign)
438
- {
439
-
440
- $wp_user_to_delete = get_userdata($user_id);
441
-
442
- // wp_user->roles (array) - the roles the user is part of.
443
- $role = null;
444
- if (is_array($wp_user_to_delete->roles) && !empty($wp_user_to_delete->roles[0])) {
445
- $role = $wp_user_to_delete->roles[0];
446
- }
447
-
448
- $context = array(
449
- "deleted_user_id" => $wp_user_to_delete->ID,
450
- "deleted_user_email" => $wp_user_to_delete->user_email,
451
- "deleted_user_login" => $wp_user_to_delete->user_login,
452
- "deleted_user_role" => $role,
453
- "reassign_user_id" => $reassign,
454
- "server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null
455
- );
456
-
457
- // Let's log this as a little bit more significant that just "message"
458
- $this->noticeMessage("user_deleted", $context);
459
- }
460
-
461
- /**
462
- * Modify plain text row output
463
- * - adds link to user profil
464
- * - change to "your profile" if you're looking at your own edit
465
- */
466
- public function getLogRowPlainTextOutput($row)
467
- {
468
-
469
- $context = $row->context;
470
-
471
- $output = parent::getLogRowPlainTextOutput($row);
472
- $current_user_id = get_current_user_id();
473
-
474
- if ("user_updated_profile" == $context["_message_key"]) {
475
- $wp_user = get_user_by("id", $context["edited_user_id"]);
476
-
477
- // If edited_user_id and _user_id is the same then a user edited their own profile
478
- // Note: it's not the same thing as the currently logged in user (but.. it can be!)
479
- if (! empty($context["_user_id"]) && $context["edited_user_id"] === $context["_user_id"]) {
480
- if ($wp_user) {
481
- $context["edit_profile_link"] = get_edit_user_link($wp_user->ID);
482
-
483
- $use_you = apply_filters("simple_history/user_logger/plain_text_output_use_you", true);
484
-
485
- //error_log( serialize($current_user_id) ); // int 1
486
- //error_log( serialize($context["_user_id"]) ); // string 1
487
-
488
- // User still exist, so link to their profile
489
- if ((int) $current_user_id === (int) $context["_user_id"] && $use_you) {
490
- // User that is viewing the log is the same as the edited user
491
- $msg = __('Edited <a href="{edit_profile_link}">your profile</a>', "simple-history");
492
- } else {
493
- $msg = __('Edited <a href="{edit_profile_link}">their profile</a>', "simple-history");
494
- }
495
-
496
- $output = $this->interpolate($msg, $context, $row);
497
- } else {
498
- // User does not exist any longer
499
- $output = __("Edited your profile", "simple-history");
500
- }
501
- } else {
502
- // User edited another users profile
503
- if ($wp_user) {
504
- // Edited user still exist, so link to their profile
505
- $context["edit_profile_link"] = get_edit_user_link($wp_user->ID);
506
- $msg = __('Edited the profile for user <a href="{edit_profile_link}">{edited_user_login} ({edited_user_email})</a>', "simple-history");
507
- $output = $this->interpolate($msg, $context, $row);
508
- } else {
509
- // Edited user does not exist any longer
510
- }
511
- }
512
- // if user_updated_profile
513
- } elseif ("user_created" == $context["_message_key"]) {
514
- // A user was created. Create link of username that goes to user profile.
515
- $wp_user = get_user_by("id", $context["created_user_id"]);
516
-
517
- // If edited_user_id and _user_id is the same then a user edited their own profile
518
- // Note: it's not the same thing as the currently logged in user (but.. it can be!)
519
-
520
- if ($wp_user) {
521
- $context["edit_profile_link"] = get_edit_user_link($wp_user->ID);
522
-
523
- // User that is viewing the log is the same as the edited user
524
- $msg = __(
525
- 'Created user <a href="{edit_profile_link}">{created_user_login} ({created_user_email})</a> with role {created_user_role}',
526
- "simple-history"
527
- );
528
-
529
- $output = $this->interpolate(
530
- $msg,
531
- $context,
532
- $row
533
- );
534
- } else {
535
- // User does not exist any longer, keep original message
536
- }
537
- }
538
-
539
- return $output;
540
- }
541
-
542
- /**
543
- * User logs in
544
- *
545
- * @param string $user_login
546
- * @param object $user
547
- */
548
- public function onWpLogin($user_login = null, $user = null)
549
- {
550
-
551
- $context = array(
552
- "user_login" => $user_login
553
- );
554
-
555
- if (isset($user_login)) {
556
- $user_obj = get_user_by("login", $user_login);
557
- } elseif (isset($user) && isset($user->ID)) {
558
- $user_obj = get_user_by("id", $user->ID);
559
- }
560
-
561
- if (is_a($user_obj, "WP_User")) {
562
- $context = array(
563
- "user_id" => $user_obj->ID,
564
- "user_email" => $user_obj->user_email,
565
- "user_login" => $user_obj->user_login,
566
- );
567
-
568
- // Override some data that is usually set automagically by Simple History
569
- // Because wp_get_current_user() does not return any data yet at this point
570
- $context["_initiator"] = SimpleLoggerLogInitiators::WP_USER;
571
- $context["_user_id"] = $user_obj->ID;
572
- $context["_user_login"] = $user_obj->user_login;
573
- $context["_user_email"] = $user_obj->user_email;
574
- $context["server_http_user_agent"] = isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null;
575
-
576
- $this->infoMessage("user_logged_in", $context);
577
- } else {
578
- // Could not get any info about the user logging in
579
- $this->warningMessage("user_unknown_logged_in", $context);
580
- }
581
- }
582
-
583
- /**
584
- * User logs out
585
- * http://codex.wordpress.org/Plugin_API/Action_Reference/wp_logout
586
- */
587
- public function onWpLogout()
588
- {
589
- $this->infoMessage("user_logged_out");
590
- }
591
-
592
- /**
593
- * User is edited
594
- *
595
- * Called immediately after an existing user is updated.
596
- * @param int $user_id User ID.
597
- * @param object $old_user_data Object containing user's data prior to update.
598
- */
599
- // public function on_profile_update($user_id, $old_user_data) {
600
- /*
601
  if (!$user_id || !is_numeric($user_id)) {
602
  return;
603
  }
@@ -615,360 +595,354 @@ class SimpleUserLogger extends SimpleLogger
615
 
616
  $this->infoMessage("user_updated_profile", $context);
617
  */
618
- // }
619
-
620
- /**
621
- * User is created
622
- *
623
- * "This action hook allows you to access data for a new user immediately after they are added to the database.
624
- * The user id is passed to hook as an argument."
625
- *
626
- */
627
- public function onUserRegister($user_id)
628
- {
629
-
630
- if (! $user_id || ! is_numeric($user_id)) {
631
- return;
632
- }
633
-
634
- $wp_user_added = get_userdata($user_id);
635
-
636
- // wp_user->roles (array) - the roles the user is part of.
637
- $role = null;
638
- if (is_array($wp_user_added->roles) && ! empty($wp_user_added->roles[0])) {
639
- $role = $wp_user_added->roles[0];
640
- }
641
-
642
- $send_user_notification = (int) (isset($_POST["send_user_notification"]) && $_POST["send_user_notification"] );
643
-
644
- $context = array(
645
- "created_user_id" => $wp_user_added->ID,
646
- "created_user_email" => $wp_user_added->user_email,
647
- "created_user_login" => $wp_user_added->user_login, // username
648
- "created_user_role" => $role,
649
- "created_user_first_name" => $wp_user_added->first_name,
650
- "created_user_last_name" => $wp_user_added->last_name,
651
- "created_user_url" => $wp_user_added->user_url,
652
- "send_user_notification" => $send_user_notification,
653
- "server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null
654
- );
655
-
656
- $this->infoMessage("user_created", $context);
657
- }
658
-
659
- /**
660
- * Log failed login attempt to username that exists
661
- *
662
- * @param WP_User or WP_Error
663
- * $user The WP_User() object of the user being edited,
664
- * or a WP_Error() object if validation has already failed.
665
- * @param string password used
666
- */
667
- public function onWpAuthenticateUser($userOrError, $password)
668
- {
669
-
670
- // Only continue if $userOrError is a WP_user object
671
- if (! is_a($userOrError, "WP_User")) {
672
- return $userOrError;
673
- }
674
-
675
- // Only log failed attempts
676
- if (! wp_check_password($password, $userOrError->user_pass, $userOrError->ID)) {
677
- // Overwrite some vars that Simple History set automagically
678
- $context = array(
679
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER,
680
- "login_id" => $userOrError->ID,
681
- "login_email" => $userOrError->user_email,
682
- "login" => $userOrError->user_login,
683
- "server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null,
684
- "_occasionsID" => __CLASS__ . '/failed_user_login',
685
- );
686
-
687
- /**
688
- * Maybe store password too
689
- * Default is to not do this because of privacy and security
690
- *
691
- * @since 2.0
692
- *
693
- * @param bool $log_password
694
- */
695
- $log_password = false;
696
- $log_password = apply_filters("simple_history/comments_logger/log_failed_password", $log_password);
697
-
698
- if ($log_password) {
699
- $context["login_user_password"] = $password;
700
- }
701
-
702
- $this->warningMessage("user_login_failed", $context);
703
- }
704
-
705
- return $userOrError;
706
- }
707
-
708
- /**
709
- * Attempt to login to user that does not exist
710
- *
711
- * @param $user (null or WP_User or WP_Error) (required)
712
- * null indicates no process has authenticated the user yet.
713
- * A WP_Error object indicates another process has failed the authentication.
714
- * A WP_User object indicates another process has authenticated the user.
715
- * @param $username The user's username. since 4.5.0 `$username` now accepts an email address.
716
- * @param $password The user's password (encrypted)
717
- */
718
- public function onAuthenticate($user, $username, $password)
719
- {
720
-
721
- // Don't log empty usernames
722
- if (! trim($username)) {
723
- return $user;
724
- }
725
-
726
- // If null then no auth done yet. Wierd. But what can we do.
727
- if (is_null($user)) {
728
- return $user;
729
- }
730
-
731
- // If auth ok then $user is a wp_user object
732
- if (is_a($user, 'WP_User')) {
733
- return $user;
734
- }
735
-
736
- // If user is a WP_Error object then auth failed
737
- // Error codes can be:
738
- // "incorrect_password" | "empty_password" | "invalid_email" | "invalid_username"
739
- // We only act on invalid emails and invalid usernames
740
- if (is_a($user, 'WP_Error') && ($user->get_error_code() == "invalid_username" || $user->get_error_code() == "invalid_email")) {
741
- $context = array(
742
- "_initiator" => SimpleLoggerLogInitiators::WEB_USER,
743
- "failed_username" => $username,
744
- "server_http_user_agent" => isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : null,
745
- // count all failed logins to unknown users as the same occasions,
746
- // to prevent log being flooded with login/hack attempts
747
- // "_occasionsID" => __CLASS__ . '/' . __FUNCTION__
748
- // Use same occasionsID as for failed login attempts to existing users,
749
- // because log can flood otherwise if hacker is rotating existing and non-existing usernames
750
- //"_occasionsID" => __CLASS__ . '/' . __FUNCTION__ . "/failed_user_login/userid:{$user->ID}"
751
- "_occasionsID" => __CLASS__ . '/failed_user_login',
752
- );
753
-
754
- /**
755
- * Maybe store password too
756
- * Default is to not do this because of privacy and security
757
- *
758
- * @since 2.0
759
- *
760
- * @param bool $log_password
761
- */
762
- $log_password = false;
763
- $log_password = apply_filters(
764
- "simple_history/comments_logger/log_not_existing_user_password",
765
- $log_password
766
- );
767
- if ($log_password) {
768
- $context["failed_login_password"] = $password;
769
- }
770
-
771
- $this->warningMessage("user_unknown_login_failed", $context);
772
- }
773
-
774
- return $user;
775
- }
776
-
777
- /**
778
- * Add diff to array if old and new values are different
779
- *
780
- * Since 2.0.29
781
- */
782
- public function addDiff($post_data_diff, $key, $old_value, $new_value)
783
- {
784
- if ($old_value != $new_value) {
785
- $post_data_diff[$key] = array(
786
- "old" => $old_value,
787
- "new" => $new_value
788
- );
789
- }
790
-
791
- return $post_data_diff;
792
- }
793
-
794
- /**
795
- * Return more info about an logged event
796
- * Supports so far:
797
- */
798
- public function getLogRowDetailsOutput($row)
799
- {
800
- $context = $row->context;
801
- $message_key = $context["_message_key"];
802
-
803
- $out = "";
804
- $diff_table_output = "";
805
-
806
- if ("user_updated_profile" == $message_key) {
807
- // Find all user_prev_ and user_new_ values and show them
808
- $arr_user_keys_to_show_diff_for = array(
809
- "first_name" => array(
810
- "title" => _x("First name", "User logger", "simple-history")
811
- ),
812
- "last_name" => array(
813
- "title" => _x("Last name", "User logger", "simple-history")
814
- ),
815
- "nickname" => array(
816
- "title" => _x("Nickname", "User logger", "simple-history")
817
- ),
818
- "description" => array(
819
- "title" => _x("Description", "User logger", "simple-history"),
820
- ),
821
- "rich_editing" => array(
822
- // Disable visual editor
823
- "title" => _x("Visual editor", "User logger", "simple-history")
824
- ),
825
- "comment_shortcuts" => array(
826
- // Enable keyboard shortcuts for comment moderation
827
- "title" => _x("Keyboard shortcuts", "User logger", "simple-history")
828
- ),
829
- "show_admin_bar_front" => array(
830
- // Show Toolbar when viewing site
831
- "title" => _x("Show Toolbar", "User logger", "simple-history")
832
- ),
833
- "admin_color" => array(
834
- // Admin Colour Scheme
835
- "title" => _x("Colour Scheme", "User logger", "simple-history")
836
- ),
837
- "aim" => array(
838
- "title" => _x("AIM", "User logger", "simple-history")
839
- ),
840
- "yim" => array(
841
- "title" => _x("Yahoo IM", "User logger", "simple-history")
842
- ),
843
- "jabber" => array(
844
- "title" => _x("Jabber / Google Talk ", "User logger", "simple-history")
845
- ),
846
- /*"user_nicename" => array(
847
  "title" => _x("Nicename", "User logger", "simple-history")
848
  ),*/
849
- "user_email" => array(
850
- "title" => _x("Email", "User logger", "simple-history")
851
- ),
852
- "display_name" => array(
853
- //"title" => _x("Display name publicly as", "User logger", "simple-history")
854
- "title" => _x("Display name", "User logger", "simple-history")
855
- ),
856
- "user_url" => array(
857
- "title" => _x("Website", "User logger", "simple-history")
858
- ),
859
- "role" => array(
860
- "title" => _x("Role", "User logger", "simple-history")
861
- ),
862
- "locale" => array(
863
- "title" => _x("Locale", "User logger", "simple-history")
864
- ),
865
- );
866
-
867
- foreach ($arr_user_keys_to_show_diff_for as $key => $val) {
868
- if (isset($context["user_prev_{$key}"]) && isset($context["user_new_{$key}"])) {
869
- $user_old_value = $context["user_prev_{$key}"];
870
- $user_new_value = $context["user_new_{$key}"];
871
-
872
- $diff_table_output .= sprintf(
873
- '<tr>
874
  <td>%1$s</td>
875
  <td>%2$s</td>
876
  </tr>',
877
- $val["title"],
878
- sprintf(
879
- '<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins> <del class="SimpleHistoryLogitem__keyValueTable__removedThing">%2$s</del>',
880
- esc_html($user_new_value), // 1
881
- esc_html($user_old_value) // 2
882
- )
883
- );
884
- }
885
- }
886
-
887
- // check if password was changed
888
- if (isset($context["edited_user_password_changed"])) {
889
- $diff_table_output .= sprintf(
890
- '<tr>
891
  <td>%1$s</td>
892
  <td>%2$s</td>
893
  </tr>',
894
- _x("Password", "User logger", "simple-history"),
895
- _x("Changed", "User logger", "simple-history")
896
- );
897
- }
898
-
899
- if ($diff_table_output) {
900
- $diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
901
- }
902
-
903
- $out .= $diff_table_output;
904
- } elseif ("user_created" == $message_key) {
905
- // Show fields for created users
906
- $arr_user_keys_to_show_diff_for = array(
907
- "created_user_first_name" => array(
908
- "title" => _x("First name", "User logger", "simple-history")
909
- ),
910
- "created_user_last_name" => array(
911
- "title" => _x("Last name", "User logger", "simple-history")
912
- ),
913
- "created_user_url" => array(
914
- "title" => _x("Website", "User logger", "simple-history")
915
- ),
916
- "send_user_notification" => array(
917
- "title" => _x("User notification email sent", "User logger", "simple-history")
918
- )
919
- );
920
-
921
- foreach ($arr_user_keys_to_show_diff_for as $key => $val) {
922
- if (isset($context[$key]) && trim($context[$key])) {
923
- if ("send_user_notification" == $key) {
924
- if (intval($context[$key]) == 1) {
925
- $sent_status = _x(
926
- "Yes, email with account details was sent",
927
- "User logger",
928
- "simple-history"
929
- );
930
- } else {
931
- // $sent_status =
932
- // _x("No, no email with account details was sent", "User logger", "simple-history");
933
- $sent_status = "";
934
- }
935
-
936
- if ($sent_status) {
937
- $diff_table_output .= sprintf(
938
- '<tr>
939
  <td>%1$s</td>
940
  <td>%2$s</td>
941
  </tr>',
942
- _x("Notification", "User logger", "simple-history"),
943
- sprintf(
944
- '<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>',
945
- esc_html($sent_status) // 1
946
- )
947
- );
948
- }
949
- } else {
950
- $diff_table_output .= sprintf(
951
- '<tr>
952
  <td>%1$s</td>
953
  <td>%2$s</td>
954
  </tr>',
955
- $val["title"],
956
- sprintf(
957
- '<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>',
958
- esc_html($context[$key]) // 1
959
- )
960
- );
961
- }
962
- }
963
- }
964
-
965
- if ($diff_table_output) {
966
- $diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
967
- }
968
-
969
- $out .= $diff_table_output;
970
- } // message key
971
-
972
- return $out;
973
- }
974
  }
3
  /**
4
  * Logs changes to user logins (and logouts)
5
  */
6
+ class SimpleUserLogger extends SimpleLogger {
7
+
8
+
9
+ public $slug = __CLASS__;
10
+
11
+ /**
12
+ * Get array with information about this logger
13
+ *
14
+ * @return array
15
+ */
16
+ public function getInfo() {
17
+
18
+ $arr_info = array(
19
+ 'name' => __( 'User Logger', 'simple-history' ),
20
+ 'description' => __( 'Logs user logins, logouts, and failed logins', 'simple-history' ),
21
+ 'capability' => 'edit_users',
22
+ 'messages' => array(
23
+ 'user_login_failed' => __(
24
+ 'Failed to login with username "{login}" (incorrect password entered)',
25
+ 'simple-history'
26
+ ),
27
+ 'user_unknown_login_failed' => __(
28
+ 'Failed to login with username "{failed_username}" (username does not exist)',
29
+ 'simple-history'
30
+ ),
31
+ 'user_logged_in' => __( 'Logged in', 'simple-history' ),
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' => __(
39
+ 'Created user {created_user_login} ({created_user_email}) with role {created_user_role}',
40
+ 'simple-history'
41
+ ),
42
+ 'user_deleted' => __( 'Deleted user {deleted_user_login} ({deleted_user_email})', 'simple-history' ),
43
+ 'user_password_reseted' => __( 'Reset their password', 'simple-history' ),
44
+ 'user_requested_password_reset_link' => __(
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
+
71
+ 'labels' => array(
72
+ 'search' => array(
73
+ 'label' => _x( 'Users', 'User logger: search', 'simple-history' ),
74
+ 'label_all' => _x( 'All user activity', 'User logger: search', 'simple-history' ),
75
+ 'options' => array(
76
+ _x( 'Successful user logins', 'User logger: search', 'simple-history' ) => array(
77
+ 'user_logged_in',
78
+ 'user_unknown_logged_in',
79
+ ),
80
+ _x( 'Failed user logins', 'User logger: search', 'simple-history' ) => array(
81
+ 'user_login_failed',
82
+ 'user_unknown_login_failed',
83
+ ),
84
+ _x( 'User logouts', 'User logger: search', 'simple-history' ) => array(
85
+ 'user_logged_out',
86
+ ),
87
+ _x( 'Created users', 'User logger: search', 'simple-history' ) => array(
88
+ 'user_created',
89
+ ),
90
+ _x( 'User profile updates', 'User logger: search', 'simple-history' ) => array(
91
+ 'user_updated_profile',
92
+ ),
93
+ _x( 'User deletions', 'User logger: search', 'simple-history' ) => array(
94
+ 'user_deleted',
95
+ ),
96
+
97
+ ),
98
+ ), // end search
99
+
100
+ ), // end labels
101
+
102
+ );
103
+
104
+ return $arr_info;
105
+ }
106
+
107
+ /**
108
+ * Add actions and filters when logger is loaded by Simple History
109
+ */
110
+ public function loaded() {
111
+
112
+ // Plain logins and logouts
113
+ add_action( 'wp_login', array( $this, 'onWpLogin' ), 10, 3 );
114
+ add_action( 'wp_logout', array( $this, 'onWpLogout' ) );
115
+
116
+ // Failed login attempt to username that exists
117
+ add_action( 'wp_authenticate_user', array( $this, 'onWpAuthenticateUser' ), 10, 2 );
118
+
119
+ // Failed to login to user that did not exist (perhaps brute force)
120
+ // run this later than 10 because wordpress own email login check is done with prio 20
121
+ // so if we run at 10 we just get null
122
+ add_filter( 'authenticate', array( $this, 'onAuthenticate' ), 30, 3 );
123
+
124
+ // User is changed
125
+ // add_action("profile_update", array($this, "on_profile_update"), 10, 2);
126
+ // User is created
127
+ add_action( 'user_register', array( $this, 'onUserRegister' ), 10, 2 );
128
+
129
+ // User is deleted
130
+ add_action( 'delete_user', array( $this, 'onDeleteUser' ), 10, 2 );
131
+
132
+ // User sessions is destroyed. AJAX call that we hook onto early.
133
+ add_action( 'wp_ajax_destroy-sessions', array( $this, 'onDestroyUserSession' ), 0 );
134
+
135
+ // User reaches reset password (from link or only from user created link)
136
+ add_action( 'validate_password_reset', array( $this, 'onValidatePasswordReset' ), 10, 2 );
137
+
138
+ add_action( 'retrieve_password_message', array( $this, 'onRetrievePasswordMessage' ), 10, 4 );
139
+
140
+ add_filter( 'insert_user_meta', array( $this, 'onInsertUserMeta' ), 10, 3 );
141
+ }
142
+
143
+ /*
 
 
144
  * Called before the user is updated
145
  *
146
  * Filter a user's meta values and keys before the user is created or updated.
165
  * @param WP_User $user User object.
166
  * @param bool $update Whether the user is being updated rather than created.
167
  */
168
+ public function onInsertUserMeta( $meta, $user, $update ) {
169
+
170
+ // We only log updates here
171
+ if ( ! $update ) {
172
+ return $meta;
173
+ }
174
+
175
+ // $user should be set, but check just in case
176
+ if ( empty( $user ) || ! is_object( $user ) ) {
177
+ return $meta;
178
+ }
179
+
180
+ // Make of copy of the posted data, because we change the keys
181
+ $posted_data = $_POST;
182
+ $posted_data = stripslashes_deep( $posted_data );
183
+
184
+ // Paranoid mode, just in case some other plugin fires the "insert_user_meta"
185
+ // filter and the user.php file is not loaded for some super wierd reason
186
+ if ( ! function_exists( '_get_additional_user_keys' ) ) {
187
+ return $meta;
188
+ }
189
+
190
+ // Get the default fields to include.
191
+ // This includes contact methods (including filter, so more could have been added)
192
+ $arr_keys_to_check = _get_additional_user_keys( $user );
193
+
194
+ // Somehow some fields are not include above, so add them manually
195
+ $arr_keys_to_check = array_merge(
196
+ $arr_keys_to_check,
197
+ array( 'user_email', 'user_url', 'display_name' )
198
+ );
199
+
200
+ // Skip some keys, because to much info or I don't know what they are
201
+ $arr_keys_to_check = array_diff( $arr_keys_to_check, array( 'use_ssl' ) );
202
+
203
+ // Some keys have different ways of getting data from user
204
+ // so change posted object to match those
205
+ $posted_data['user_url'] = isset( $posted_data['url'] ) ? $posted_data['url'] : null;
206
+ $posted_data['show_admin_bar_front'] = isset( $posted_data['admin_bar_front'] ) ? true : null;
207
+ $posted_data['user_email'] = isset( $posted_data['email'] ) ? $posted_data['email'] : null;
208
+
209
+ // Display name publicly as = POST "display_name"
210
+ // var_dump($user->display_name);
211
+ // Set vals for Enable keyboard shortcuts for comment moderation
212
+ $posted_data['comment_shortcuts'] = isset( $posted_data['comment_shortcuts'] ) ? 'true' : 'false';
213
+
214
+ // Set vals for Disable the visual editor when writing
215
+ // posted val = string "false" = yes, disable
216
+ $posted_data['rich_editing'] = isset( $posted_data['rich_editing'] ) ? 'false' : 'true';
217
+
218
+ // Set vals for Show Toolbar when viewing site
219
+ $posted_data['show_admin_bar_front'] = isset( $posted_data['admin_bar_front'] ) ? 'true' : 'false';
220
+
221
+ // if checkbox is checked in admin then this is the saved value on the user object
222
+ // @todo:
223
+ // Check if password was updated
224
+ $password_changed = false;
225
+ if ( ! empty( $posted_data['pass1'] ) && ! empty( $posted_data['pass2'] ) && $posted_data['pass1'] == $posted_data['pass2'] ) {
226
+ $password_changed = 1;
227
+ }
228
+
229
+ // Check if role was changed
230
+ // [role] => bbp_moderator
231
+ $role_changed = false;
232
+
233
+ // if user is network admin then role dropdown does not exist and role is not posted here
234
+ $new_role = isset( $posted_data['role'] ) ? $posted_data['role'] : null;
235
+
236
+ if ( $new_role ) {
237
+ // as done in user-edit.php
238
+ // Compare user role against currently editable roles
239
+ $user_roles = array_intersect( array_values( $user->roles ), array_keys( get_editable_roles() ) );
240
+ $old_role = reset( $user_roles );
241
+
242
+ $role_changed = $new_role != $old_role;
243
+ }
244
+
245
+ // Will contain the differences
246
+ $user_data_diff = array();
247
+
248
+ // locale: sv_SE, empty = english, site-default = site....default!
249
+ // Check all keys for diff values
250
+ foreach ( $arr_keys_to_check as $one_key_to_check ) {
251
+ $old_val = $user->$one_key_to_check;
252
+ $new_val = isset( $posted_data[ $one_key_to_check ] ) ? $posted_data[ $one_key_to_check ] : null;
253
+
254
+ // echo "<hr>key: $one_key_to_check";
255
+ // echo "<br>old val: $old_val";
256
+ // echo "<br>new val: $new_val";
257
+ // new val must be set, because otherwise we are not setting anything
258
+ if ( ! isset( $new_val ) ) {
259
+ continue;
260
+ }
261
+
262
+ $user_data_diff = $this->addDiff( $user_data_diff, $one_key_to_check, $old_val, $new_val );
263
+ }
264
+
265
+ // Setup basic context
266
+ $context = array(
267
+ 'edited_user_id' => $user->ID,
268
+ 'edited_user_email' => $user->user_email,
269
+ 'edited_user_login' => $user->user_login,
270
+ 'server_http_user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
271
+ );
272
+
273
+ if ( $password_changed ) {
274
+ $context['edited_user_password_changed'] = '1';
275
+ }
276
+
277
+ if ( $role_changed ) {
278
+ $context['user_prev_role'] = $old_role;
279
+ $context['user_new_role'] = $new_role;
280
+ }
281
+
282
+ // Add diff to context
283
+ if ( $user_data_diff ) {
284
+ foreach ( $user_data_diff as $one_diff_key => $one_diff_vals ) {
285
+ /*
 
 
 
 
 
286
  One diff looks like:
287
  "nickname": {
288
  "old": "MyOldNick",
289
  "new": "MyNewNick"
290
  }
291
  */
292
+ $context[ "user_prev_{$one_diff_key}" ] = $one_diff_vals['old'];
293
+ $context[ "user_new_{$one_diff_key}" ] = $one_diff_vals['new'];
294
+ }
295
+ }
296
+
297
+ // print_r($context);exit;
298
+ $this->infoMessage( 'user_updated_profile', $context );
299
+
300
+ return $meta;
301
+ }
302
+
303
+ /**
304
+ *
305
+ * user requests a reset password link
306
+ */
307
+ public function onRetrievePasswordMessage( $message, $key, $user_login, $user_data = "" ) {
308
+
309
+ if ( isset( $_GET['action'] ) && ('lostpassword' == $_GET['action']) ) {
310
+ $context = array(
311
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
312
+ 'message' => $message,
313
+ 'key' => $key,
314
+ 'user_login' => $user_login,
315
+ );
316
+
317
+ if ( is_a( $user_data, 'WP_User' ) ) {
318
+ $context['user_email'] = $user_data->user_email;
319
+ }
320
+
321
+ $this->noticeMessage( 'user_requested_password_reset_link', $context );
322
+ }
323
+
324
+ return $message;
325
+ }
326
+
327
+ /**
328
+ * Fired before the password reset procedure is validated.
329
+ *
330
+ * @param object $errors WP Error object.
331
+ * @param WP_User|WP_Error $user WP_User object if the login and reset key match. WP_Error object otherwise.
332
+ */
333
+ public function onValidatePasswordReset( $errors, $user ) {
334
+
335
+ /*
 
 
 
 
336
  User visits the forgot password screen
337
  $errors object are empty
338
  $user contains a user
345
 
346
  */
347
 
348
+ $context = array();
349
+
350
+ if ( is_a( $user, 'WP_User' ) ) {
351
+ $context['_initiator'] = SimpleLoggerLogInitiators::WP_USER;
352
+ $context['_user_id'] = $user->ID;
353
+ $context['_user_login'] = $user->user_login;
354
+ $context['_user_email'] = $user->user_email;
355
+ }
356
+
357
+ if ( isset( $_POST['pass1'] ) && $_POST['pass1'] != $_POST['pass2'] ) {
358
+ // $errors->add( 'password_reset_mismatch', __( 'The passwords do not match.' ) );
359
+ // user failed to reset password
360
+ }
361
+
362
+ if ( ( ! $errors->get_error_code()) && isset( $_POST['pass1'] ) && ! empty( $_POST['pass1'] ) ) {
363
+ // login_header( __( 'Password Reset' ), '<p class="message reset-pass">'
364
+ // . __( 'Your password has been reset.' ) . ' <a href="' . esc_url(
365
+ $this->infoMessage( 'user_password_reseted', $context );
366
+ }
367
+ }
368
+
369
+ /**
370
+ * Called when user dessions are destroyed from admin
371
+ * Can be called for current logged in user = destroy all other sessions
372
+ * or for another user = destroy alla sessions for that user
373
+ * Fires from AJAX call
374
+ *
375
+ * @since 2.0.6
376
+ */
377
+ public function onDestroyUserSession() {
378
+
379
+ /*
 
 
380
  Post params:
381
  nonce: a14df12195
382
  user_id: 1
383
  action: destroy-sessions
384
  */
385
 
386
+ $user = get_userdata( (int) $_POST['user_id'] );
387
+
388
+ if ( $user ) {
389
+ if ( ! current_user_can( 'edit_user', $user->ID ) ) {
390
+ $user = false;
391
+ } elseif ( ! wp_verify_nonce( $_POST['nonce'], 'update-user_' . $user->ID ) ) {
392
+ $user = false;
393
+ }
394
+ }
395
+
396
+ if ( ! $user ) {
397
+ // Could not log out user sessions. Please try again.
398
+ return;
399
+ }
400
+
401
+ $sessions = WP_Session_Tokens::get_instance( $user->ID );
402
+
403
+ $context = array();
404
+
405
+ if ( $user->ID === get_current_user_id() ) {
406
+ $this->infoMessage( 'user_session_destroy_others' );
407
+ } else {
408
+ $context['user_id'] = $user->ID;
409
+ $context['user_login'] = $user->user_login;
410
+ $context['user_display_name'] = $user->display_name;
411
+
412
+ $this->infoMessage( 'user_session_destroy_everywhere', $context );
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Fires before a user is deleted from the database.
418
+ *
419
+ * @param int $user_id ID of the deleted user.
420
+ * @param int|null $reassign ID of the user to reassign posts and links to.
421
+ * Default null, for no reassignment.
422
+ */
423
+ public function onDeleteUser( $user_id, $reassign ) {
424
+
425
+ $wp_user_to_delete = get_userdata( $user_id );
426
+
427
+ // wp_user->roles (array) - the roles the user is part of.
428
+ $role = null;
429
+ if ( is_array( $wp_user_to_delete->roles ) && ! empty( $wp_user_to_delete->roles[0] ) ) {
430
+ $role = $wp_user_to_delete->roles[0];
431
+ }
432
+
433
+ $context = array(
434
+ 'deleted_user_id' => $wp_user_to_delete->ID,
435
+ 'deleted_user_email' => $wp_user_to_delete->user_email,
436
+ 'deleted_user_login' => $wp_user_to_delete->user_login,
437
+ 'deleted_user_role' => $role,
438
+ 'reassign_user_id' => $reassign,
439
+ 'server_http_user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
440
+ );
441
+
442
+ // Let's log this as a little bit more significant that just "message"
443
+ $this->noticeMessage( 'user_deleted', $context );
444
+ }
445
+
446
+ /**
447
+ * Modify plain text row output
448
+ * - adds link to user profil
449
+ * - change to "your profile" if you're looking at your own edit
450
+ */
451
+ public function getLogRowPlainTextOutput( $row ) {
452
+
453
+ $context = $row->context;
454
+
455
+ $output = parent::getLogRowPlainTextOutput( $row );
456
+ $current_user_id = get_current_user_id();
457
+
458
+ if ( 'user_updated_profile' == $context['_message_key'] ) {
459
+ $wp_user = get_user_by( 'id', $context['edited_user_id'] );
460
+
461
+ // If edited_user_id and _user_id is the same then a user edited their own profile
462
+ // Note: it's not the same thing as the currently logged in user (but.. it can be!)
463
+ if ( ! empty( $context['_user_id'] ) && $context['edited_user_id'] === $context['_user_id'] ) {
464
+ if ( $wp_user ) {
465
+ $context['edit_profile_link'] = get_edit_user_link( $wp_user->ID );
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
474
+ $msg = __( 'Edited <a href="{edit_profile_link}">your profile</a>', 'simple-history' );
475
+ } else {
476
+ $msg = __( 'Edited <a href="{edit_profile_link}">their profile</a>', 'simple-history' );
477
+ }
478
+
479
+ $output = $this->interpolate( $msg, $context, $row );
480
+ } else {
481
+ // User does not exist any longer
482
+ $output = __( 'Edited your profile', 'simple-history' );
483
+ }
484
+ } else {
485
+ // User edited another users profile
486
+ if ( $wp_user ) {
487
+ // Edited user still exist, so link to their profile
488
+ $context['edit_profile_link'] = get_edit_user_link( $wp_user->ID );
489
+ $msg = __( 'Edited the profile for user <a href="{edit_profile_link}">{edited_user_login} ({edited_user_email})</a>', 'simple-history' );
490
+ $output = $this->interpolate( $msg, $context, $row );
491
+ } else {
492
+ // Edited user does not exist any longer
493
+ }
494
+ }
495
+ } elseif ( 'user_created' == $context['_message_key'] ) {
496
+ // A user was created. Create link of username that goes to user profile.
497
+ $wp_user = get_user_by( 'id', $context['created_user_id'] );
498
+
499
+ // If edited_user_id and _user_id is the same then a user edited their own profile
500
+ // Note: it's not the same thing as the currently logged in user (but.. it can be!)
501
+ if ( $wp_user ) {
502
+ $context['edit_profile_link'] = get_edit_user_link( $wp_user->ID );
503
+
504
+ // User that is viewing the log is the same as the edited user
505
+ $msg = __(
506
+ 'Created user <a href="{edit_profile_link}">{created_user_login} ({created_user_email})</a> with role {created_user_role}',
507
+ 'simple-history'
508
+ );
509
+
510
+ $output = $this->interpolate(
511
+ $msg,
512
+ $context,
513
+ $row
514
+ );
515
+ } else {
516
+ // User does not exist any longer, keep original message
517
+ }
518
+ }// End if().
519
+
520
+ return $output;
521
+ }
522
+
523
+ /**
524
+ * User logs in
525
+ *
526
+ * @param string $user_login
527
+ * @param object $user
528
+ */
529
+ public function onWpLogin( $user_login = null, $user = null ) {
530
+
531
+ $context = array(
532
+ 'user_login' => $user_login,
533
+ );
534
+
535
+ if ( isset( $user_login ) ) {
536
+ $user_obj = get_user_by( 'login', $user_login );
537
+ } elseif ( isset( $user ) && isset( $user->ID ) ) {
538
+ $user_obj = get_user_by( 'id', $user->ID );
539
+ }
540
+
541
+ if ( is_a( $user_obj, 'WP_User' ) ) {
542
+ $context = array(
543
+ 'user_id' => $user_obj->ID,
544
+ 'user_email' => $user_obj->user_email,
545
+ 'user_login' => $user_obj->user_login,
546
+ );
547
+
548
+ // Override some data that is usually set automagically by Simple History
549
+ // Because wp_get_current_user() does not return any data yet at this point
550
+ $context['_initiator'] = SimpleLoggerLogInitiators::WP_USER;
551
+ $context['_user_id'] = $user_obj->ID;
552
+ $context['_user_login'] = $user_obj->user_login;
553
+ $context['_user_email'] = $user_obj->user_email;
554
+ $context['server_http_user_agent'] = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
555
+
556
+ $this->infoMessage( 'user_logged_in', $context );
557
+ } else {
558
+ // Could not get any info about the user logging in
559
+ $this->warningMessage( 'user_unknown_logged_in', $context );
560
+ }
561
+ }
562
+
563
+ /**
564
+ * User logs out
565
+ * http://codex.wordpress.org/Plugin_API/Action_Reference/wp_logout
566
+ */
567
+ public function onWpLogout() {
568
+ $this->infoMessage( 'user_logged_out' );
569
+ }
570
+
571
+ /**
572
+ * User is edited
573
+ *
574
+ * Called immediately after an existing user is updated.
575
+ *
576
+ * @param int $user_id User ID.
577
+ * @param object $old_user_data Object containing user's data prior to update.
578
+ */
579
+ // public function on_profile_update($user_id, $old_user_data) {
580
+ /*
 
 
 
 
 
 
581
  if (!$user_id || !is_numeric($user_id)) {
582
  return;
583
  }
595
 
596
  $this->infoMessage("user_updated_profile", $context);
597
  */
598
+ // }
599
+ /**
600
+ * User is created
601
+ *
602
+ * "This action hook allows you to access data for a new user immediately after they are added to the database.
603
+ * The user id is passed to hook as an argument."
604
+ */
605
+ public function onUserRegister( $user_id ) {
606
+
607
+ if ( ! $user_id || ! is_numeric( $user_id ) ) {
608
+ return;
609
+ }
610
+
611
+ $wp_user_added = get_userdata( $user_id );
612
+
613
+ // wp_user->roles (array) - the roles the user is part of.
614
+ $role = null;
615
+ if ( is_array( $wp_user_added->roles ) && ! empty( $wp_user_added->roles[0] ) ) {
616
+ $role = $wp_user_added->roles[0];
617
+ }
618
+
619
+ $send_user_notification = (int) (isset( $_POST['send_user_notification'] ) && $_POST['send_user_notification'] );
620
+
621
+ $context = array(
622
+ 'created_user_id' => $wp_user_added->ID,
623
+ 'created_user_email' => $wp_user_added->user_email,
624
+ 'created_user_login' => $wp_user_added->user_login, // username
625
+ 'created_user_role' => $role,
626
+ 'created_user_first_name' => $wp_user_added->first_name,
627
+ 'created_user_last_name' => $wp_user_added->last_name,
628
+ 'created_user_url' => $wp_user_added->user_url,
629
+ 'send_user_notification' => $send_user_notification,
630
+ 'server_http_user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
631
+ );
632
+
633
+ $this->infoMessage( 'user_created', $context );
634
+ }
635
+
636
+ /**
637
+ * Log failed login attempt to username that exists
638
+ *
639
+ * @param WP_User or WP_Error
640
+ * $user The WP_User() object of the user being edited,
641
+ * or a WP_Error() object if validation has already failed.
642
+ * @param string password used
643
+ */
644
+ public function onWpAuthenticateUser( $userOrError, $password ) {
645
+
646
+ // Only continue if $userOrError is a WP_user object
647
+ if ( ! is_a( $userOrError, 'WP_User' ) ) {
648
+ return $userOrError;
649
+ }
650
+
651
+ // Only log failed attempts
652
+ if ( ! wp_check_password( $password, $userOrError->user_pass, $userOrError->ID ) ) {
653
+ // Overwrite some vars that Simple History set automagically
654
+ $context = array(
655
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
656
+ 'login_id' => $userOrError->ID,
657
+ 'login_email' => $userOrError->user_email,
658
+ 'login' => $userOrError->user_login,
659
+ 'server_http_user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
660
+ '_occasionsID' => __CLASS__ . '/failed_user_login',
661
+ );
662
+
663
+ /**
664
+ * Maybe store password too
665
+ * Default is to not do this because of privacy and security
666
+ *
667
+ * @since 2.0
668
+ *
669
+ * @param bool $log_password
670
+ */
671
+ $log_password = false;
672
+ $log_password = apply_filters( 'simple_history/comments_logger/log_failed_password', $log_password );
673
+
674
+ if ( $log_password ) {
675
+ $context['login_user_password'] = $password;
676
+ }
677
+
678
+ $this->warningMessage( 'user_login_failed', $context );
679
+ }
680
+
681
+ return $userOrError;
682
+ }
683
+
684
+ /**
685
+ * Attempt to login to user that does not exist
686
+ *
687
+ * @param $user (null or WP_User or WP_Error) (required)
688
+ * null indicates no process has authenticated the user yet.
689
+ * A WP_Error object indicates another process has failed the authentication.
690
+ * A WP_User object indicates another process has authenticated the user.
691
+ * @param $username The user's username. since 4.5.0 `$username` now accepts an email address.
692
+ * @param $password The user's password (encrypted)
693
+ */
694
+ public function onAuthenticate( $user, $username, $password ) {
695
+
696
+ // Don't log empty usernames
697
+ if ( ! trim( $username ) ) {
698
+ return $user;
699
+ }
700
+
701
+ // If null then no auth done yet. Wierd. But what can we do.
702
+ if ( is_null( $user ) ) {
703
+ return $user;
704
+ }
705
+
706
+ // If auth ok then $user is a wp_user object
707
+ if ( is_a( $user, 'WP_User' ) ) {
708
+ return $user;
709
+ }
710
+
711
+ // If user is a WP_Error object then auth failed
712
+ // Error codes can be:
713
+ // "incorrect_password" | "empty_password" | "invalid_email" | "invalid_username"
714
+ // We only act on invalid emails and invalid usernames
715
+ if ( is_a( $user, 'WP_Error' ) && ($user->get_error_code() == 'invalid_username' || $user->get_error_code() == 'invalid_email') ) {
716
+ $context = array(
717
+ '_initiator' => SimpleLoggerLogInitiators::WEB_USER,
718
+ 'failed_username' => $username,
719
+ 'server_http_user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
720
+ // count all failed logins to unknown users as the same occasions,
721
+ // to prevent log being flooded with login/hack attempts
722
+ // "_occasionsID" => __CLASS__ . '/' . __FUNCTION__
723
+ // Use same occasionsID as for failed login attempts to existing users,
724
+ // because log can flood otherwise if hacker is rotating existing and non-existing usernames
725
+ // "_occasionsID" => __CLASS__ . '/' . __FUNCTION__ . "/failed_user_login/userid:{$user->ID}"
726
+ '_occasionsID' => __CLASS__ . '/failed_user_login',
727
+ );
728
+
729
+ /**
730
+ * Maybe store password too
731
+ * Default is to not do this because of privacy and security
732
+ *
733
+ * @since 2.0
734
+ *
735
+ * @param bool $log_password
736
+ */
737
+ $log_password = false;
738
+ $log_password = apply_filters(
739
+ 'simple_history/comments_logger/log_not_existing_user_password',
740
+ $log_password
741
+ );
742
+ if ( $log_password ) {
743
+ $context['failed_login_password'] = $password;
744
+ }
745
+
746
+ $this->warningMessage( 'user_unknown_login_failed', $context );
747
+ }
748
+
749
+ return $user;
750
+ }
751
+
752
+ /**
753
+ * Add diff to array if old and new values are different
754
+ *
755
+ * Since 2.0.29
756
+ */
757
+ public function addDiff( $post_data_diff, $key, $old_value, $new_value ) {
758
+ if ( $old_value != $new_value ) {
759
+ $post_data_diff[ $key ] = array(
760
+ 'old' => $old_value,
761
+ 'new' => $new_value,
762
+ );
763
+ }
764
+
765
+ return $post_data_diff;
766
+ }
767
+
768
+ /**
769
+ * Return more info about an logged event
770
+ * Supports so far:
771
+ */
772
+ public function getLogRowDetailsOutput( $row ) {
773
+ $context = $row->context;
774
+ $message_key = $context['_message_key'];
775
+
776
+ $out = '';
777
+ $diff_table_output = '';
778
+
779
+ if ( 'user_updated_profile' == $message_key ) {
780
+ // Find all user_prev_ and user_new_ values and show them
781
+ $arr_user_keys_to_show_diff_for = array(
782
+ 'first_name' => array(
783
+ 'title' => _x( 'First name', 'User logger', 'simple-history' ),
784
+ ),
785
+ 'last_name' => array(
786
+ 'title' => _x( 'Last name', 'User logger', 'simple-history' ),
787
+ ),
788
+ 'nickname' => array(
789
+ 'title' => _x( 'Nickname', 'User logger', 'simple-history' ),
790
+ ),
791
+ 'description' => array(
792
+ 'title' => _x( 'Description', 'User logger', 'simple-history' ),
793
+ ),
794
+ 'rich_editing' => array(
795
+ // Disable visual editor
796
+ 'title' => _x( 'Visual editor', 'User logger', 'simple-history' ),
797
+ ),
798
+ 'comment_shortcuts' => array(
799
+ // Enable keyboard shortcuts for comment moderation
800
+ 'title' => _x( 'Keyboard shortcuts', 'User logger', 'simple-history' ),
801
+ ),
802
+ 'show_admin_bar_front' => array(
803
+ // Show Toolbar when viewing site
804
+ 'title' => _x( 'Show Toolbar', 'User logger', 'simple-history' ),
805
+ ),
806
+ 'admin_color' => array(
807
+ // Admin Colour Scheme
808
+ 'title' => _x( 'Colour Scheme', 'User logger', 'simple-history' ),
809
+ ),
810
+ 'aim' => array(
811
+ 'title' => _x( 'AIM', 'User logger', 'simple-history' ),
812
+ ),
813
+ 'yim' => array(
814
+ 'title' => _x( 'Yahoo IM', 'User logger', 'simple-history' ),
815
+ ),
816
+ 'jabber' => array(
817
+ 'title' => _x( 'Jabber / Google Talk ', 'User logger', 'simple-history' ),
818
+ ),
819
+ /*
820
+ "user_nicename" => array(
 
 
 
 
 
 
821
  "title" => _x("Nicename", "User logger", "simple-history")
822
  ),*/
823
+ 'user_email' => array(
824
+ 'title' => _x( 'Email', 'User logger', 'simple-history' ),
825
+ ),
826
+ 'display_name' => array(
827
+ // "title" => _x("Display name publicly as", "User logger", "simple-history")
828
+ 'title' => _x( 'Display name', 'User logger', 'simple-history' ),
829
+ ),
830
+ 'user_url' => array(
831
+ 'title' => _x( 'Website', 'User logger', 'simple-history' ),
832
+ ),
833
+ 'role' => array(
834
+ 'title' => _x( 'Role', 'User logger', 'simple-history' ),
835
+ ),
836
+ 'locale' => array(
837
+ 'title' => _x( 'Locale', 'User logger', 'simple-history' ),
838
+ ),
839
+ );
840
+
841
+ foreach ( $arr_user_keys_to_show_diff_for as $key => $val ) {
842
+ if ( isset( $context[ "user_prev_{$key}" ] ) && isset( $context[ "user_new_{$key}" ] ) ) {
843
+ $user_old_value = $context[ "user_prev_{$key}" ];
844
+ $user_new_value = $context[ "user_new_{$key}" ];
845
+
846
+ $diff_table_output .= sprintf(
847
+ '<tr>
848
  <td>%1$s</td>
849
  <td>%2$s</td>
850
  </tr>',
851
+ $val['title'],
852
+ sprintf(
853
+ '<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins> <del class="SimpleHistoryLogitem__keyValueTable__removedThing">%2$s</del>',
854
+ esc_html( $user_new_value ), // 1
855
+ esc_html( $user_old_value ) // 2
856
+ )
857
+ );
858
+ }
859
+ }
860
+
861
+ // check if password was changed
862
+ if ( isset( $context['edited_user_password_changed'] ) ) {
863
+ $diff_table_output .= sprintf(
864
+ '<tr>
865
  <td>%1$s</td>
866
  <td>%2$s</td>
867
  </tr>',
868
+ _x( 'Password', 'User logger', 'simple-history' ),
869
+ _x( 'Changed', 'User logger', 'simple-history' )
870
+ );
871
+ }
872
+
873
+ if ( $diff_table_output ) {
874
+ $diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
875
+ }
876
+
877
+ $out .= $diff_table_output;
878
+ } elseif ( 'user_created' == $message_key ) {
879
+ // Show fields for created users
880
+ $arr_user_keys_to_show_diff_for = array(
881
+ 'created_user_first_name' => array(
882
+ 'title' => _x( 'First name', 'User logger', 'simple-history' ),
883
+ ),
884
+ 'created_user_last_name' => array(
885
+ 'title' => _x( 'Last name', 'User logger', 'simple-history' ),
886
+ ),
887
+ 'created_user_url' => array(
888
+ 'title' => _x( 'Website', 'User logger', 'simple-history' ),
889
+ ),
890
+ 'send_user_notification' => array(
891
+ 'title' => _x( 'User notification email sent', 'User logger', 'simple-history' ),
892
+ ),
893
+ );
894
+
895
+ foreach ( $arr_user_keys_to_show_diff_for as $key => $val ) {
896
+ if ( isset( $context[ $key ] ) && trim( $context[ $key ] ) ) {
897
+ if ( 'send_user_notification' == $key ) {
898
+ if ( intval( $context[ $key ] ) == 1 ) {
899
+ $sent_status = _x(
900
+ 'Yes, email with account details was sent',
901
+ 'User logger',
902
+ 'simple-history'
903
+ );
904
+ } else {
905
+ // $sent_status =
906
+ // _x("No, no email with account details was sent", "User logger", "simple-history");
907
+ $sent_status = '';
908
+ }
909
+
910
+ if ( $sent_status ) {
911
+ $diff_table_output .= sprintf(
912
+ '<tr>
913
  <td>%1$s</td>
914
  <td>%2$s</td>
915
  </tr>',
916
+ _x( 'Notification', 'User logger', 'simple-history' ),
917
+ sprintf(
918
+ '<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>',
919
+ esc_html( $sent_status ) // 1
920
+ )
921
+ );
922
+ }
923
+ } else {
924
+ $diff_table_output .= sprintf(
925
+ '<tr>
926
  <td>%1$s</td>
927
  <td>%2$s</td>
928
  </tr>',
929
+ $val['title'],
930
+ sprintf(
931
+ '<ins class="SimpleHistoryLogitem__keyValueTable__addedThing">%1$s</ins>',
932
+ esc_html( $context[ $key ] ) // 1
933
+ )
934
+ );
935
+ }// End if().
936
+ }// End if().
937
+ }// End foreach().
938
+
939
+ if ( $diff_table_output ) {
940
+ $diff_table_output = '<table class="SimpleHistoryLogitem__keyValueTable">' . $diff_table_output . '</table>';
941
+ }
942
+
943
+ $out .= $diff_table_output;
944
+ } // End if().
945
+
946
+ return $out;
947
+ }
948
  }
phpcs.xml.dist ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <ruleset name="Simple-History">
3
+ <description>WordPress Coding Standards for Simple History</description>
4
+
5
+ <!-- Show sniff codes in all reports, and progress while running -->
6
+ <arg value="sp"/>
7
+ <!-- Check all PHP files in directory tree by default. -->
8
+ <arg name="extensions" value="php"/>
9
+ <!-- Run different reports -->
10
+ <arg name="report" value="full"/>
11
+ <arg name="report" value="summary"/>
12
+ <arg name="report" value="source"/>
13
+
14
+ <file>.</file>
15
+ <exclude-pattern>*/vendor/*</exclude-pattern>
16
+ <exclude-pattern>*/node_modules/*</exclude-pattern>
17
+
18
+ <rule ref="PHPCompatibility">
19
+ <!-- Polyfill package is used so array_column() is available for PHP 5.4- -->
20
+ <exclude name="PHPCompatibility.PHP.NewFunctions.array_columnFound"/>
21
+ <!-- Both magic quotes directives set in wp-settings-cli.php to provide consistent starting point. -->
22
+ <exclude name="PHPCompatibility.PHP.DeprecatedIniDirectives.magic_quotes_runtimeDeprecatedRemoved"/>
23
+ <exclude name="PHPCompatibility.PHP.DeprecatedIniDirectives.magic_quotes_sybaseDeprecatedRemoved"/>
24
+ </rule>
25
+ <config name="testVersion" value="5.3-"/>
26
+
27
+ <rule ref="WordPress-Core">
28
+ <exclude name="Squiz.PHP.DisallowMultipleAssignments.Found" />
29
+ <exclude name="WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar" />
30
+ <exclude name="WordPress.NamingConventions.ValidVariableName.MemberNotSnakeCase" />
31
+ <exclude name="WordPress.NamingConventions.ValidVariableName.NotSnakeCase" />
32
+ </rule>
33
+ <rule ref="WordPress.Files.FileName">
34
+ <properties>
35
+ <property name="strict_class_file_names" value="false"/>
36
+ </properties>
37
+ <exclude name="WordPress.Files.FileName.NotHyphenatedLowercase" />
38
+ </rule>
39
+ </ruleset>
readme.txt CHANGED
@@ -3,8 +3,9 @@ Contributors: eskapism
3
  Donate link: http://eskapism.se/sida/donate/
4
  Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, dashboard, admin, syslog, feed, activity, stream, audit trail, brute-force
5
  Requires at least: 4.5.1
6
- Tested up to: 4.8
7
- Stable tag: 2.18
 
8
 
9
  View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
10
 
@@ -98,13 +99,13 @@ If you are a theme or plugin developer and would like to add your own things/eve
98
 
99
  if ( function_exists("SimpleLogger") ) {
100
 
101
- // Most basic example: just add some information to the log
102
- SimpleLogger()->info("This is a message sent to the log");
103
 
104
- // A bit more advanced: log events with different severities
105
- SimpleLogger()->info("User admin edited page 'About our company'");
106
- SimpleLogger()->warning("User 'Jessie' deleted user 'Kim'");
107
- SimpleLogger()->debug("Ok, cron job is running!");
108
 
109
  }
110
  ?>
@@ -158,10 +159,20 @@ initiated by a specific user.
158
  7. A chart with some quick statistics is available, so you can see the number of events that has been logged each day.
159
  A simple way to see any uncommon activity, for example an increased number of logins or similar.
160
 
161
- == Changelog ==
 
162
 
163
  ## Changelog
164
 
 
 
 
 
 
 
 
 
 
165
  = 2.18 (August 2017) =
166
 
167
  - Set from_term_description correctly, fixes https://github.com/bonny/WordPress-Simple-History/issues/127.
@@ -192,7 +203,7 @@ so you can see what CSS styles a client changed or what PHP changes they made in
192
 
193
  - Use thumbnail version of PDF preview instead of full size image.
194
  - Remove Google Maps image when clicking IP address of failed login and similar, because Google Maps must be used with API key.
195
- Hostname, Network, City, Region and Country is still shown.
196
  - Fix notice in available updates logger.
197
  - Fix notice in redirection logger.
198
 
@@ -203,7 +214,7 @@ so you can see what CSS styles a client changed or what PHP changes they made in
203
  = 2.14 (April 2017) =
204
 
205
  - Added support for plugin [Duplicate Post](https://wordpress.org/plugins/duplicate-post/).
206
- Now when a user clones a post or page you will se this in the history log, with links to both the original post and the new copy.
207
  - Removed log level info from title in RSS feed
208
  - Make date dropdown less "jumpy" when loading page (due to select element switching to Select2)
209
  - Only add filters for plugin Limit Login Attempts if plugin is active. This fixes problem with Limit Login Attempts Reloaded and possibly other forks of the plugin.
@@ -225,20 +236,20 @@ so you can see what CSS styles a client changed or what PHP changes they made in
225
  = 2.11 (September 2016) =
226
 
227
  - Added support for plugin [Redirection](https://wordpress.org/plugins/redirection/).
228
- Redirects and groups that are created, changed, enabled and disabled will be logged. Also when the plugin global settings are changed that will be logged.
229
  - Fix possible notice error from User logger.
230
  - "View changelog" link now works on multisite.
231
 
232
  = 2.10 (September 2016) =
233
 
234
  - Available updates to plugins, themes, and WordPress itself is now logged.
235
- Pretty great if you subscribe to the RSS feed to get the changes on a site. No need to manually check the updates-page to see if there are any updates.
236
  - Changed to logic used to determine if a post edit should be logged or not. Version 2.9 used a version that started to log a bit to much for some plugins. This should fix the problems with the Nextgen Gallery, All-In-One Events Calendar, and Membership 2 plugins. If you still have problems with a plugin that is causing to many events to be logged, please let me know!
237
 
238
  = 2.9.1 (August 2016) =
239
 
240
  - Fixed an issue where the logged time was off by some hours, due to timezone being manually set elsewhere.
241
- Should fix https://wordpress.org/support/topic/logged-time-off-by-2-hours and https://wordpress.org/support/topic/different-time-between-dashboard-and-logger.
242
  - Fixed Nextgen Gallery and Nextgen Gallery Plus logging lots and lots of event when viewing posts with galleries. The posts was actually updated, so this plugin did nothing wrong. But it was indeed a bit annoying and most likely something you didn't want in your log. Fixes https://wordpress.org/support/topic/non-stop-logging-nextgen-gallery-items.
243
 
244
  = 2.9 (August 2016) =
@@ -255,7 +266,7 @@ so you can see what CSS styles a client changed or what PHP changes they made in
255
  - ...and so are theme updates
256
  - ...and theme deletions. Awesome!
257
  - Support for plugin [Limit Login Attempts](https://wordpress.org/plugins/limit-login-attempts/).
258
- Failed login attempts, lockouts and configuration changes will be logged.
259
  - Correct message is now used when a plugin update fails, i.e. the message for key `plugin_update_failed`.
260
  - The original untranslated strings for plugin name and so on are stored when storing info for plugin installs and updates and similar.
261
  - Default number of events to show is now 10 instead of 5.
@@ -264,7 +275,7 @@ so you can see what CSS styles a client changed or what PHP changes they made in
264
 
265
  - User logins using e-mail are now logged correctly. Previously the user would be logged in successfully but the log said that they failed.
266
  - Security fix: only users with [`list_users`](https://codex.wordpress.org/Roles_and_Capabilities#list_users) capability can view the users filter and use the autocomplete api for users.
267
- Previously the autocomplete function could be used by all logged in users.
268
  - Add labels to search filters. (I do really hate label-less forms so it's kinda very strange that this was not in place before.)
269
  - Misc other internal fixes
270
 
3
  Donate link: http://eskapism.se/sida/donate/
4
  Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, dashboard, admin, syslog, feed, activity, stream, audit trail, brute-force
5
  Requires at least: 4.5.1
6
+ Tested up to: 4.9
7
+ Requires PHP: 5.3
8
+ Stable tag: 2.19
9
 
10
  View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
11
 
99
 
100
  if ( function_exists("SimpleLogger") ) {
101
 
102
+ // Most basic example: just add some information to the log
103
+ SimpleLogger()->info("This is a message sent to the log");
104
 
105
+ // A bit more advanced: log events with different severities
106
+ SimpleLogger()->info("User admin edited page 'About our company'");
107
+ SimpleLogger()->warning("User 'Jessie' deleted user 'Kim'");
108
+ SimpleLogger()->debug("Ok, cron job is running!");
109
 
110
  }
111
  ?>
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.19 (November 2017) =
168
+
169
+ - Add filter `simple_history/user_can_clear_log`. Return `false` from this filter to disable the "Clear blog" button.
170
+ - Remove static keyword from some methods in SimpleLogger, so now calls like `SimpleLogger()->critical('Doh!');` works.
171
+ - Don't show link to WordPress updates if user is not allowed to view the updates page.
172
+ - Fix notice error in SimpleOptionsLogger.
173
+ - Fix for fatal errors when using the lost password form in [Membership 2](https://wordpress.org/plugins/membership/). Fixes https://wordpress.org/support/topic/conflict-with-simple-history-plugin-and-php-7/.
174
+ - Code (a little bit) better formatted according to [WordPress coding standard](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards).
175
+
176
  = 2.18 (August 2017) =
177
 
178
  - Set from_term_description correctly, fixes https://github.com/bonny/WordPress-Simple-History/issues/127.
203
 
204
  - Use thumbnail version of PDF preview instead of full size image.
205
  - Remove Google Maps image when clicking IP address of failed login and similar, because Google Maps must be used with API key.
206
+ Hostname, Network, City, Region and Country is still shown.
207
  - Fix notice in available updates logger.
208
  - Fix notice in redirection logger.
209
 
214
  = 2.14 (April 2017) =
215
 
216
  - Added support for plugin [Duplicate Post](https://wordpress.org/plugins/duplicate-post/).
217
+ Now when a user clones a post or page you will se this in the history log, with links to both the original post and the new copy.
218
  - Removed log level info from title in RSS feed
219
  - Make date dropdown less "jumpy" when loading page (due to select element switching to Select2)
220
  - Only add filters for plugin Limit Login Attempts if plugin is active. This fixes problem with Limit Login Attempts Reloaded and possibly other forks of the plugin.
236
  = 2.11 (September 2016) =
237
 
238
  - Added support for plugin [Redirection](https://wordpress.org/plugins/redirection/).
239
+ Redirects and groups that are created, changed, enabled and disabled will be logged. Also when the plugin global settings are changed that will be logged.
240
  - Fix possible notice error from User logger.
241
  - "View changelog" link now works on multisite.
242
 
243
  = 2.10 (September 2016) =
244
 
245
  - Available updates to plugins, themes, and WordPress itself is now logged.
246
+ Pretty great if you subscribe to the RSS feed to get the changes on a site. No need to manually check the updates-page to see if there are any updates.
247
  - Changed to logic used to determine if a post edit should be logged or not. Version 2.9 used a version that started to log a bit to much for some plugins. This should fix the problems with the Nextgen Gallery, All-In-One Events Calendar, and Membership 2 plugins. If you still have problems with a plugin that is causing to many events to be logged, please let me know!
248
 
249
  = 2.9.1 (August 2016) =
250
 
251
  - Fixed an issue where the logged time was off by some hours, due to timezone being manually set elsewhere.
252
+ Should fix https://wordpress.org/support/topic/logged-time-off-by-2-hours and https://wordpress.org/support/topic/different-time-between-dashboard-and-logger.
253
  - Fixed Nextgen Gallery and Nextgen Gallery Plus logging lots and lots of event when viewing posts with galleries. The posts was actually updated, so this plugin did nothing wrong. But it was indeed a bit annoying and most likely something you didn't want in your log. Fixes https://wordpress.org/support/topic/non-stop-logging-nextgen-gallery-items.
254
 
255
  = 2.9 (August 2016) =
266
  - ...and so are theme updates
267
  - ...and theme deletions. Awesome!
268
  - Support for plugin [Limit Login Attempts](https://wordpress.org/plugins/limit-login-attempts/).
269
+ Failed login attempts, lockouts and configuration changes will be logged.
270
  - Correct message is now used when a plugin update fails, i.e. the message for key `plugin_update_failed`.
271
  - The original untranslated strings for plugin name and so on are stored when storing info for plugin installs and updates and similar.
272
  - Default number of events to show is now 10 instead of 5.
275
 
276
  - User logins using e-mail are now logged correctly. Previously the user would be logged in successfully but the log said that they failed.
277
  - Security fix: only users with [`list_users`](https://codex.wordpress.org/Roles_and_Capabilities#list_users) capability can view the users filter and use the autocomplete api for users.
278
+ Previously the autocomplete function could be used by all logged in users.
279
  - Add labels to search filters. (I do really hate label-less forms so it's kinda very strange that this was not in place before.)
280
  - Misc other internal fixes
281
 
templates/settings-general.php CHANGED
@@ -4,14 +4,14 @@ defined( 'ABSPATH' ) or die();
4
 
5
  <form method="post" action="options.php">
6
 
7
- <?php
8
  // Prints out all settings sections added to a particular settings page
9
- do_settings_sections(SimpleHistory::SETTINGS_MENU_SLUG);
10
  ?>
11
 
12
- <?php
13
  // Output nonce, action, and option_page fields
14
- settings_fields("simple_history_settings_group");
15
  ?>
16
 
17
  <?php submit_button(); ?>
4
 
5
  <form method="post" action="options.php">
6
 
7
+ <?php
8
  // Prints out all settings sections added to a particular settings page
9
+ do_settings_sections( SimpleHistory::SETTINGS_MENU_SLUG );
10
  ?>
11
 
12
+ <?php
13
  // Output nonce, action, and option_page fields
14
+ settings_fields( 'simple_history_settings_group' );
15
  ?>
16
 
17
  <?php submit_button(); ?>
templates/settings-log.php CHANGED
@@ -11,7 +11,7 @@ $pager_size = $this->get_pager_size();
11
  *
12
  * @param int $pager_size
13
  */
14
- $pager_size = apply_filters("simple_history/settings_page_pager_size", $pager_size);
15
 
16
  ?>
17
  <div class="SimpleHistoryGui"
11
  *
12
  * @param int $pager_size
13
  */
14
+ $pager_size = apply_filters( 'simple_history/settings_page_pager_size', $pager_size );
15
 
16
  ?>
17
  <div class="SimpleHistoryGui"
templates/settings-statsForGeeks.php CHANGED
@@ -19,9 +19,9 @@ defined( 'ABSPATH' ) or die();
19
  </script>
20
  <?php
21
 
22
- defined('ABSPATH') OR exit;
23
 
24
- echo "<hr>";
25
  echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsForGeeks'>Show stats for geeks</button></p>";
26
 
27
  ?>
@@ -29,26 +29,26 @@ echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsF
29
  <div class="SimpleHistory__statsForGeeksInner hide-if-js">
30
  <?php
31
 
32
- echo "<h4>Rows count</h4>";
33
  $logQuery = new SimpleHistoryLogQuery();
34
  $rows = $logQuery->query(array(
35
- "posts_per_page" => 1,
36
- //"date_from" => strtotime("-$period_days days")
37
  ));
38
 
39
  // This is the number of rows with occasions taken into consideration
40
- $total_accassions_rows_count = $rows["total_row_count"];
41
 
42
  // Total number of log rows
43
  // Not caring about occasions, this number = all occasions
44
- $total_num_rows = $wpdb->get_var("select count(*) FROM {$table_name}");
45
- echo "<ul>";
46
  echo "<li>Total $total_num_rows log rows in db.</li>";
47
  echo "<li>Total $total_accassions_rows_count rows, when grouped by occasion id.</li>";
48
- echo "</ul>";
49
 
50
- echo "<h4>Clear history interval</h4>";
51
- echo "<p>" . $this->sh->get_clear_history_interval() . "</p>";
52
 
53
  $sql_table_size = sprintf('
54
  SELECT table_name AS "table_name",
@@ -56,29 +56,29 @@ echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsF
56
  FROM information_schema.TABLES
57
  WHERE table_schema = "%1$s"
58
  AND table_name IN ("%2$s", "%3$s");
59
- ',
60
  DB_NAME, // 1
61
  $table_name, // 2
62
  $table_name_contexts
63
  );
64
 
65
- $table_size_result = $wpdb->get_results($sql_table_size);
66
 
67
 
68
- echo "<h4>Database size</h4>";
69
 
70
  echo "<table class='widefat'>";
71
- echo "
72
- <thead>
73
- <tr>
74
- <th>Table name</th>
75
- <th>Table size (MB)</th>
76
- </tr>
77
- </thead>
78
- ";
79
 
80
  $loopnum = 0;
81
- foreach ($table_size_result as $one_table) {
82
 
83
  printf('<tr class="%3$s">
84
  <td>%1$s</td>
@@ -86,36 +86,36 @@ echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsF
86
  </tr>',
87
  $one_table->table_name,
88
  $one_table->size_in_mb,
89
- $loopnum % 2 ? " alt " : ""
90
  );
91
 
92
  $loopnum++;
93
  }
94
 
95
- echo "</table>";
96
 
97
- // @TODO: this does actually only show all loggers that have logged rows,
98
  // not all loggers!
99
- echo "<h4>Loggers</h4>";
100
 
101
- echo "<p>All instantiated loggers.</p>";
102
 
103
  echo "<table class='widefat' cellpadding=2>";
104
- echo "
105
- <thead>
106
- <tr>
107
- <th>Name + Slug</th>
108
- <th>Description</th>
109
- <th>Messages</th>
110
- <th>Capability</th>
111
- <th>Rows count</th>
112
- </tr>
113
- </thead>
114
- ";
115
 
116
  $arr_logger_slugs = array();
117
  foreach ( $this->sh->getInstantiatedLoggers() as $oneLogger ) {
118
- $arr_logger_slugs[] = $oneLogger["instance"]->slug;
119
  }
120
 
121
  $sql_logger_counts = sprintf('
@@ -124,7 +124,7 @@ echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsF
124
  WHERE logger IN ("%2$s")
125
  GROUP BY logger
126
  ORDER BY count DESC
127
- ', $table_name, join($arr_logger_slugs, '","'));
128
 
129
  $logger_rows_count = $wpdb->get_results( $sql_logger_counts, OBJECT_K );
130
 
@@ -133,7 +133,7 @@ echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsF
133
  foreach ( $arr_logger_slugs as $one_logger_slug ) {
134
 
135
  $logger = $this->sh->getInstantiatedLoggerBySlug( $one_logger_slug );
136
-
137
  if ( ! $logger ) {
138
  continue;
139
  }
@@ -145,15 +145,15 @@ echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsF
145
  $one_logger_count = new stdclass;
146
  $one_logger_count->count = 0;
147
  }
148
-
149
  $logger_info = $logger->getInfo();
150
- $logger_messages = $logger_info["messages"];
151
-
152
- $html_logger_messages = "";
153
- foreach ($logger_messages as $message_key => $message) {
154
- $html_logger_messages .= sprintf('<li>%1$s</li>', esc_html($message));
155
  }
156
- if ($html_logger_messages) {
157
  $html_logger_messages = "<ul>{$html_logger_messages}</ul>";
158
  }
159
 
@@ -172,17 +172,17 @@ echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsF
172
  ',
173
  $one_logger_count->count,
174
  $one_logger_slug,
175
- esc_html( $logger_info["name"]),
176
- esc_html( $logger_info["description"]), // 4
177
  esc_html( $logger->getCapability() ),
178
- $loopnum % 2 ? " alt " : "", // 6
179
  $html_logger_messages // 7
180
  );
181
 
182
  $loopnum++;
183
 
184
- }
185
- echo "</table>";
186
 
187
  ?>
188
  </div><!-- // stats for geeks inner -->
19
  </script>
20
  <?php
21
 
22
+ defined( 'ABSPATH' ) or exit;
23
 
24
+ echo '<hr>';
25
  echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsForGeeks'>Show stats for geeks</button></p>";
26
 
27
  ?>
29
  <div class="SimpleHistory__statsForGeeksInner hide-if-js">
30
  <?php
31
 
32
+ echo '<h4>Rows count</h4>';
33
  $logQuery = new SimpleHistoryLogQuery();
34
  $rows = $logQuery->query(array(
35
+ 'posts_per_page' => 1,
36
+ // "date_from" => strtotime("-$period_days days")
37
  ));
38
 
39
  // This is the number of rows with occasions taken into consideration
40
+ $total_accassions_rows_count = $rows['total_row_count'];
41
 
42
  // Total number of log rows
43
  // Not caring about occasions, this number = all occasions
44
+ $total_num_rows = $wpdb->get_var( "select count(*) FROM {$table_name}" );
45
+ echo '<ul>';
46
  echo "<li>Total $total_num_rows log rows in db.</li>";
47
  echo "<li>Total $total_accassions_rows_count rows, when grouped by occasion id.</li>";
48
+ echo '</ul>';
49
 
50
+ echo '<h4>Clear history interval</h4>';
51
+ echo '<p>' . $this->sh->get_clear_history_interval() . '</p>';
52
 
53
  $sql_table_size = sprintf('
54
  SELECT table_name AS "table_name",
56
  FROM information_schema.TABLES
57
  WHERE table_schema = "%1$s"
58
  AND table_name IN ("%2$s", "%3$s");
59
+ ',
60
  DB_NAME, // 1
61
  $table_name, // 2
62
  $table_name_contexts
63
  );
64
 
65
+ $table_size_result = $wpdb->get_results( $sql_table_size );
66
 
67
 
68
+ echo '<h4>Database size</h4>';
69
 
70
  echo "<table class='widefat'>";
71
+ echo '
72
+ <thead>
73
+ <tr>
74
+ <th>Table name</th>
75
+ <th>Table size (MB)</th>
76
+ </tr>
77
+ </thead>
78
+ ';
79
 
80
  $loopnum = 0;
81
+ foreach ( $table_size_result as $one_table ) {
82
 
83
  printf('<tr class="%3$s">
84
  <td>%1$s</td>
86
  </tr>',
87
  $one_table->table_name,
88
  $one_table->size_in_mb,
89
+ $loopnum % 2 ? ' alt ' : ''
90
  );
91
 
92
  $loopnum++;
93
  }
94
 
95
+ echo '</table>';
96
 
97
+ // @TODO: this does actually only show all loggers that have logged rows,
98
  // not all loggers!
99
+ echo '<h4>Loggers</h4>';
100
 
101
+ echo '<p>All instantiated loggers.</p>';
102
 
103
  echo "<table class='widefat' cellpadding=2>";
104
+ echo '
105
+ <thead>
106
+ <tr>
107
+ <th>Name + Slug</th>
108
+ <th>Description</th>
109
+ <th>Messages</th>
110
+ <th>Capability</th>
111
+ <th>Rows count</th>
112
+ </tr>
113
+ </thead>
114
+ ';
115
 
116
  $arr_logger_slugs = array();
117
  foreach ( $this->sh->getInstantiatedLoggers() as $oneLogger ) {
118
+ $arr_logger_slugs[] = $oneLogger['instance']->slug;
119
  }
120
 
121
  $sql_logger_counts = sprintf('
124
  WHERE logger IN ("%2$s")
125
  GROUP BY logger
126
  ORDER BY count DESC
127
+ ', $table_name, join( $arr_logger_slugs, '","' ));
128
 
129
  $logger_rows_count = $wpdb->get_results( $sql_logger_counts, OBJECT_K );
130
 
133
  foreach ( $arr_logger_slugs as $one_logger_slug ) {
134
 
135
  $logger = $this->sh->getInstantiatedLoggerBySlug( $one_logger_slug );
136
+
137
  if ( ! $logger ) {
138
  continue;
139
  }
145
  $one_logger_count = new stdclass;
146
  $one_logger_count->count = 0;
147
  }
148
+
149
  $logger_info = $logger->getInfo();
150
+ $logger_messages = $logger_info['messages'];
151
+
152
+ $html_logger_messages = '';
153
+ foreach ( $logger_messages as $message_key => $message ) {
154
+ $html_logger_messages .= sprintf( '<li>%1$s</li>', esc_html( $message ) );
155
  }
156
+ if ( $html_logger_messages ) {
157
  $html_logger_messages = "<ul>{$html_logger_messages}</ul>";
158
  }
159
 
172
  ',
173
  $one_logger_count->count,
174
  $one_logger_slug,
175
+ esc_html( $logger_info['name'] ),
176
+ esc_html( $logger_info['description'] ), // 4
177
  esc_html( $logger->getCapability() ),
178
+ $loopnum % 2 ? ' alt ' : '', // 6
179
  $html_logger_messages // 7
180
  );
181
 
182
  $loopnum++;
183
 
184
+ }// End foreach().
185
+ echo '</table>';
186
 
187
  ?>
188
  </div><!-- // stats for geeks inner -->
templates/settings-statsInitiators.php CHANGED
@@ -5,7 +5,6 @@ defined( 'ABSPATH' ) or die();
5
 
6
  <?php
7
  // Stats based by initiator
8
-
9
  // Stats på level (notice, warning, debug, etc.)
10
  $sql = sprintf('
11
  SELECT
@@ -17,31 +16,31 @@ $sql = sprintf('
17
  ', $table_name
18
  );
19
 
20
- $level_counts = $wpdb->get_results($sql);
21
 
22
- echo "<h3>Initiators</h3>";
23
- echo "<table>";
24
- echo "<tr>
25
- <th>Initiator</th>
26
- <th>Count</th>
27
- </tr>";
28
 
29
  foreach ( $level_counts as $row ) {
30
 
31
- if ( empty($row->initiator) ) {
32
  continue;
33
  }
34
-
35
  printf('
36
  <tr>
37
  <td>%1$s</td>
38
  <td>%2$s</td>
39
  </tr>
40
- ',
41
- $row->initiator,
42
- $row->count
43
  );
44
 
45
  }
46
 
47
- echo "</table>";
5
 
6
  <?php
7
  // Stats based by initiator
 
8
  // Stats på level (notice, warning, debug, etc.)
9
  $sql = sprintf('
10
  SELECT
16
  ', $table_name
17
  );
18
 
19
+ $level_counts = $wpdb->get_results( $sql );
20
 
21
+ echo '<h3>Initiators</h3>';
22
+ echo '<table>';
23
+ echo '<tr>
24
+ <th>Initiator</th>
25
+ <th>Count</th>
26
+ </tr>';
27
 
28
  foreach ( $level_counts as $row ) {
29
 
30
+ if ( empty( $row->initiator ) ) {
31
  continue;
32
  }
33
+
34
  printf('
35
  <tr>
36
  <td>%1$s</td>
37
  <td>%2$s</td>
38
  </tr>
39
+ ',
40
+ $row->initiator,
41
+ $row->count
42
  );
43
 
44
  }
45
 
46
+ echo '</table>';
templates/settings-statsIntro.php CHANGED
@@ -3,23 +3,23 @@
3
  defined( 'ABSPATH' ) or die();
4
 
5
  // Number of rows the last n days
6
- function get_num_rows_last_n_days($period_days) {
7
 
8
  global $wpdb;
9
 
10
  $sql = sprintf(
11
  'select count(*) FROM %1$s WHERE UNIX_TIMESTAMP(date) >= %2$d',
12
  $wpdb->prefix . SimpleHistory::DBTABLE,
13
- strtotime("-$period_days days")
14
  );
15
-
16
- return $wpdb->get_var($sql);
17
 
18
  }
19
 
20
  printf(
21
- __('<b>%1$s rows</b> have been logged the last <b>%2$s days</b>', "simple-history"),
22
- get_num_rows_last_n_days($period_days),
23
  $period_days
24
  );
25
 
3
  defined( 'ABSPATH' ) or die();
4
 
5
  // Number of rows the last n days
6
+ function get_num_rows_last_n_days( $period_days ) {
7
 
8
  global $wpdb;
9
 
10
  $sql = sprintf(
11
  'select count(*) FROM %1$s WHERE UNIX_TIMESTAMP(date) >= %2$d',
12
  $wpdb->prefix . SimpleHistory::DBTABLE,
13
+ strtotime( "-$period_days days" )
14
  );
15
+
16
+ return $wpdb->get_var( $sql );
17
 
18
  }
19
 
20
  printf(
21
+ __( '<b>%1$s rows</b> have been logged the last <b>%2$s days</b>', 'simple-history' ),
22
+ get_num_rows_last_n_days( $period_days ),
23
  $period_days
24
  );
25
 
templates/settings-statsLogLevels.php CHANGED
@@ -3,9 +3,9 @@
3
  defined( 'ABSPATH' ) or die();
4
 
5
  // Stats på level (notice, warning, debug, etc.)
6
- echo "<h3>" . __("Log levels", "simple-history") . "</h3>";
7
 
8
- echo "<p>" . __("Number of rows logged for each log level.", "simple-history") . "</p>";
9
 
10
  /*
11
  echo "<table>";
@@ -22,13 +22,13 @@ $sql = sprintf('
22
  WHERE UNIX_TIMESTAMP(date) >= %2$d
23
  GROUP BY level
24
  ORDER BY count DESC
25
- ',
26
  $table_name, // 1
27
- strtotime("-$period_days days") // 2
28
  );
29
 
30
 
31
- $level_counts = $wpdb->get_results($sql);
32
 
33
  $arr_chart_data = array();
34
  $arr_chart_labels = array();
@@ -36,19 +36,19 @@ $str_js_google_chart_data = '["Log level", "Count"], ';
36
 
37
  foreach ( $level_counts as $row ) {
38
 
39
- if ( empty($row->level) ) {
40
  continue;
41
  }
42
-
43
  /*
44
  printf('
45
  <tr>
46
  <td>%1$s</td>
47
  <td>%2$s</td>
48
  </tr>
49
- ',
50
- $row->level,
51
- $row->count
52
  );
53
  */
54
 
@@ -63,9 +63,9 @@ foreach ( $level_counts as $row ) {
63
 
64
  }
65
 
66
- $str_js_google_chart_data = rtrim($str_js_google_chart_data, ", ");
67
 
68
- echo "</table>";
69
 
70
  echo "<div class='SimpleHistoryChart__logLevelsPie'></div>";
71
 
@@ -79,9 +79,9 @@ echo "<div class='SimpleHistoryChart__logLevelsPie'></div>";
79
  jQuery(function($) {
80
 
81
  var data = {
82
- labels: ["<?php echo implode('", "', $arr_chart_labels) ?>"],
83
  series: [
84
- [<?php echo implode(",", $arr_chart_data) ?>]
85
  ]
86
  };
87
 
@@ -102,10 +102,10 @@ echo "<div class='SimpleHistoryChart__logLevelsPie'></div>";
102
  xtitle: 'My Daily Activities',
103
  backgroundColor: "transparent",
104
  is3D: true,
105
- legend: {
106
- xposition: 'top',
107
- alignment: 'center'
108
- }
109
  };
110
 
111
  var chart = new google.visualization.PieChart( $(".SimpleHistoryChart__logLevelsPie").get(0) );
3
  defined( 'ABSPATH' ) or die();
4
 
5
  // Stats på level (notice, warning, debug, etc.)
6
+ echo '<h3>' . __( 'Log levels', 'simple-history' ) . '</h3>';
7
 
8
+ echo '<p>' . __( 'Number of rows logged for each log level.', 'simple-history' ) . '</p>';
9
 
10
  /*
11
  echo "<table>";
22
  WHERE UNIX_TIMESTAMP(date) >= %2$d
23
  GROUP BY level
24
  ORDER BY count DESC
25
+ ',
26
  $table_name, // 1
27
+ strtotime( "-$period_days days" ) // 2
28
  );
29
 
30
 
31
+ $level_counts = $wpdb->get_results( $sql );
32
 
33
  $arr_chart_data = array();
34
  $arr_chart_labels = array();
36
 
37
  foreach ( $level_counts as $row ) {
38
 
39
+ if ( empty( $row->level ) ) {
40
  continue;
41
  }
42
+
43
  /*
44
  printf('
45
  <tr>
46
  <td>%1$s</td>
47
  <td>%2$s</td>
48
  </tr>
49
+ ',
50
+ $row->level,
51
+ $row->count
52
  );
53
  */
54
 
63
 
64
  }
65
 
66
+ $str_js_google_chart_data = rtrim( $str_js_google_chart_data, ', ' );
67
 
68
+ echo '</table>';
69
 
70
  echo "<div class='SimpleHistoryChart__logLevelsPie'></div>";
71
 
79
  jQuery(function($) {
80
 
81
  var data = {
82
+ labels: ["<?php echo implode( '", "', $arr_chart_labels ) ?>"],
83
  series: [
84
+ [<?php echo implode( ',', $arr_chart_data ) ?>]
85
  ]
86
  };
87
 
102
  xtitle: 'My Daily Activities',
103
  backgroundColor: "transparent",
104
  is3D: true,
105
+ legend: {
106
+ xposition: 'top',
107
+ alignment: 'center'
108
+ }
109
  };
110
 
111
  var chart = new google.visualization.PieChart( $(".SimpleHistoryChart__logLevelsPie").get(0) );
templates/settings-statsLoggers.php CHANGED
@@ -2,16 +2,15 @@
2
  defined( 'ABSPATH' ) or die();
3
 
4
  echo "<h4 class=''>";
5
- echo __("Loggers", "simple-history");
6
- echo "</h4>";
7
 
8
- #echo '<div class="SimpleHistoryChart__loggersPie"></div>';
9
  echo '<div class="SimpleHistoryChart__loggersPieGoogleChart"></div>';
10
- #echo '<div class="SimpleHistoryChart__loggersGoogleBarChart"></div>';
11
-
12
  $arr_logger_slugs = array();
13
  foreach ( $this->sh->getInstantiatedLoggers() as $oneLogger ) {
14
- $arr_logger_slugs[] = $oneLogger["instance"]->slug;
15
  }
16
 
17
  $sql_logger_counts = sprintf('
@@ -22,32 +21,32 @@ $sql_logger_counts = sprintf('
22
  AND UNIX_TIMESTAMP(date) >= %3$d
23
  GROUP BY logger
24
  ORDER BY count DESC
25
- ',
26
  $table_name, // 1
27
- join($arr_logger_slugs, '","'), // 2
28
- strtotime("-$period_days days")
29
  );
30
 
31
  $logger_rows_count = $wpdb->get_results( $sql_logger_counts );
32
- #sf_d($logger_rows_count);
33
- $str_js_chart_labels = "";
34
- $str_js_chart_data = "";
35
- $str_js_chart_data_chartist = "";
36
  $str_js_google_chart_data = "['Logger name', 'Logged rows'],";
37
  $i = 0;
38
 
39
- //shuffle($arr_colors);
40
  $max_loggers_in_chart = sizeof( $arr_colors );
41
 
42
  foreach ( $logger_rows_count as $one_logger_count ) {
43
 
44
  $logger = $this->sh->getInstantiatedLoggerBySlug( $one_logger_count->logger );
45
 
46
- if ( ! $logger) {
47
  continue;
48
  }
49
 
50
- if ($i > $max_loggers_in_chart) {
51
  break;
52
  }
53
 
@@ -61,8 +60,8 @@ foreach ( $logger_rows_count as $one_logger_count ) {
61
  label: "%2$s"
62
  },',
63
  $one_logger_count->count, // 1
64
- $logger_info["name"], // 2
65
- $arr_colors[$i] // 3
66
  );
67
 
68
  $str_js_chart_data_chartist .= sprintf(
@@ -72,22 +71,22 @@ foreach ( $logger_rows_count as $one_logger_count ) {
72
 
73
  $str_js_chart_labels .= sprintf(
74
  '"%1$s",',
75
- $logger_info["name"]
76
  );
77
 
78
  $str_js_google_chart_data .= sprintf(
79
  '["%1$s", %2$d], ',
80
- $logger_info["name"], // 1
81
  $one_logger_count->count // 2
82
  );
83
 
84
  $i++;
85
 
86
- }
87
- $str_js_chart_data = rtrim($str_js_chart_data, ",");
88
- $str_js_chart_data_chartist = rtrim($str_js_chart_data_chartist, ",");
89
- $str_js_chart_labels = rtrim($str_js_chart_labels, ",");
90
- $str_js_google_chart_data = rtrim($str_js_google_chart_data, ",");
91
 
92
  ?>
93
  <script>
@@ -116,10 +115,10 @@ $str_js_google_chart_data = rtrim($str_js_google_chart_data, ",");
116
  xtitle: 'My Daily Activities',
117
  backgroundColor: "transparent",
118
  is3D: true,
119
- legend: {
120
- xposition: 'top',
121
- alignment: 'center'
122
- }
123
 
124
  };
125
 
@@ -131,4 +130,4 @@ $str_js_google_chart_data = rtrim($str_js_google_chart_data, ",");
131
 
132
  });
133
 
134
- </script>
2
  defined( 'ABSPATH' ) or die();
3
 
4
  echo "<h4 class=''>";
5
+ echo __( 'Loggers', 'simple-history' );
6
+ echo '</h4>';
7
 
8
+ // echo '<div class="SimpleHistoryChart__loggersPie"></div>';
9
  echo '<div class="SimpleHistoryChart__loggersPieGoogleChart"></div>';
10
+ // echo '<div class="SimpleHistoryChart__loggersGoogleBarChart"></div>';
 
11
  $arr_logger_slugs = array();
12
  foreach ( $this->sh->getInstantiatedLoggers() as $oneLogger ) {
13
+ $arr_logger_slugs[] = $oneLogger['instance']->slug;
14
  }
15
 
16
  $sql_logger_counts = sprintf('
21
  AND UNIX_TIMESTAMP(date) >= %3$d
22
  GROUP BY logger
23
  ORDER BY count DESC
24
+ ',
25
  $table_name, // 1
26
+ join( $arr_logger_slugs, '","' ), // 2
27
+ strtotime( "-$period_days days" )
28
  );
29
 
30
  $logger_rows_count = $wpdb->get_results( $sql_logger_counts );
31
+ // sf_d($logger_rows_count);
32
+ $str_js_chart_labels = '';
33
+ $str_js_chart_data = '';
34
+ $str_js_chart_data_chartist = '';
35
  $str_js_google_chart_data = "['Logger name', 'Logged rows'],";
36
  $i = 0;
37
 
38
+ // shuffle($arr_colors);
39
  $max_loggers_in_chart = sizeof( $arr_colors );
40
 
41
  foreach ( $logger_rows_count as $one_logger_count ) {
42
 
43
  $logger = $this->sh->getInstantiatedLoggerBySlug( $one_logger_count->logger );
44
 
45
+ if ( ! $logger ) {
46
  continue;
47
  }
48
 
49
+ if ( $i > $max_loggers_in_chart ) {
50
  break;
51
  }
52
 
60
  label: "%2$s"
61
  },',
62
  $one_logger_count->count, // 1
63
+ $logger_info['name'], // 2
64
+ $arr_colors[ $i ] // 3
65
  );
66
 
67
  $str_js_chart_data_chartist .= sprintf(
71
 
72
  $str_js_chart_labels .= sprintf(
73
  '"%1$s",',
74
+ $logger_info['name']
75
  );
76
 
77
  $str_js_google_chart_data .= sprintf(
78
  '["%1$s", %2$d], ',
79
+ $logger_info['name'], // 1
80
  $one_logger_count->count // 2
81
  );
82
 
83
  $i++;
84
 
85
+ }// End foreach().
86
+ $str_js_chart_data = rtrim( $str_js_chart_data, ',' );
87
+ $str_js_chart_data_chartist = rtrim( $str_js_chart_data_chartist, ',' );
88
+ $str_js_chart_labels = rtrim( $str_js_chart_labels, ',' );
89
+ $str_js_google_chart_data = rtrim( $str_js_google_chart_data, ',' );
90
 
91
  ?>
92
  <script>
115
  xtitle: 'My Daily Activities',
116
  backgroundColor: "transparent",
117
  is3D: true,
118
+ legend: {
119
+ xposition: 'top',
120
+ alignment: 'center'
121
+ }
122
 
123
  };
124
 
130
 
131
  });
132
 
133
+ </script>
templates/settings-statsRowsPerDay.php CHANGED
@@ -3,8 +3,8 @@
3
  defined( 'ABSPATH' ) or die();
4
 
5
  echo "<h4 class=''>";
6
- echo __("Rows per day", "simple-history");
7
- echo "</h4>";
8
 
9
  $sql = sprintf(
10
  '
@@ -18,37 +18,39 @@ $sql = sprintf(
18
  ORDER BY yearDate ASC
19
  ',
20
  $wpdb->prefix . SimpleHistory::DBTABLE,
21
- strtotime("-$period_days days")
22
  );
23
 
24
  $dates = $wpdb->get_results( $sql );
25
 
26
- #echo '<div class="SimpleHistoryChart__rowsPerDay"></div>';
27
  echo '<div class="SimpleHistoryChart__rowsPerDayGoogleChart"></div>';
28
 
29
  // Loop from $period_start_date to $period_end_date
30
- $interval = DateInterval::createFromDateString('1 day');
31
- $period = new DatePeriod($period_start_date, $interval, $period_end_date->add( date_interval_create_from_date_string('1 days') ) );
32
- $str_js_chart_labels = "";
33
- $str_js_chart_data = "";
34
- $str_js_google_chart_data = "";
35
 
36
  foreach ( $period as $dt ) {
37
-
38
- $datef = _x( 'M j', "stats: date in rows per day chart", "simple-history" );
39
  $str_date = date_i18n( $datef, $dt->getTimestamp() );
40
 
41
  $str_js_chart_labels .= sprintf(
42
- '"%1$s",',
43
  $str_date
44
  );
45
 
46
  // Get data for this day, if exist
47
  // Day in object is in format '2014-09-07'
48
- $day_data = wp_filter_object_list( $dates, array("yearDate" => $dt->format( "Y-m-d" )) );
 
 
49
  $day_data_value = 0;
50
  if ( $day_data ) {
51
- $day_data_value = (int) current($day_data)->count;
52
  }
53
 
54
  $str_js_chart_data .= sprintf(
@@ -64,9 +66,9 @@ foreach ( $period as $dt ) {
64
 
65
  }
66
 
67
- $str_js_chart_labels = rtrim($str_js_chart_labels, ",");
68
- $str_js_chart_data = rtrim($str_js_chart_data, ",");
69
- $str_js_google_chart_data = rtrim($str_js_google_chart_data, ",");
70
 
71
  ?>
72
 
@@ -133,10 +135,10 @@ $str_js_google_chart_data = rtrim($str_js_google_chart_data, ",");
133
  xchartArea: { left: 0, width: "80%" },
134
  xchartArea2: {'width': '100%', 'xheight': '80%'},
135
  xxlegend: {'position': 'bottom'},
136
- legend: {
137
- xposition: 'top',
138
- alignment: 'center'
139
- }
140
 
141
 
142
  };
@@ -147,4 +149,4 @@ $str_js_google_chart_data = rtrim($str_js_google_chart_data, ",");
147
 
148
  });
149
 
150
- </script>
3
  defined( 'ABSPATH' ) or die();
4
 
5
  echo "<h4 class=''>";
6
+ echo __( 'Rows per day', 'simple-history' );
7
+ echo '</h4>';
8
 
9
  $sql = sprintf(
10
  '
18
  ORDER BY yearDate ASC
19
  ',
20
  $wpdb->prefix . SimpleHistory::DBTABLE,
21
+ strtotime( "-$period_days days" )
22
  );
23
 
24
  $dates = $wpdb->get_results( $sql );
25
 
26
+ // echo '<div class="SimpleHistoryChart__rowsPerDay"></div>';
27
  echo '<div class="SimpleHistoryChart__rowsPerDayGoogleChart"></div>';
28
 
29
  // Loop from $period_start_date to $period_end_date
30
+ $interval = DateInterval::createFromDateString( '1 day' );
31
+ $period = new DatePeriod( $period_start_date, $interval, $period_end_date->add( date_interval_create_from_date_string( '1 days' ) ) );
32
+ $str_js_chart_labels = '';
33
+ $str_js_chart_data = '';
34
+ $str_js_google_chart_data = '';
35
 
36
  foreach ( $period as $dt ) {
37
+
38
+ $datef = _x( 'M j', 'stats: date in rows per day chart', 'simple-history' );
39
  $str_date = date_i18n( $datef, $dt->getTimestamp() );
40
 
41
  $str_js_chart_labels .= sprintf(
42
+ '"%1$s",',
43
  $str_date
44
  );
45
 
46
  // Get data for this day, if exist
47
  // Day in object is in format '2014-09-07'
48
+ $day_data = wp_filter_object_list( $dates, array(
49
+ 'yearDate' => $dt->format( 'Y-m-d' ),
50
+ ) );
51
  $day_data_value = 0;
52
  if ( $day_data ) {
53
+ $day_data_value = (int) current( $day_data )->count;
54
  }
55
 
56
  $str_js_chart_data .= sprintf(
66
 
67
  }
68
 
69
+ $str_js_chart_labels = rtrim( $str_js_chart_labels, ',' );
70
+ $str_js_chart_data = rtrim( $str_js_chart_data, ',' );
71
+ $str_js_google_chart_data = rtrim( $str_js_google_chart_data, ',' );
72
 
73
  ?>
74
 
135
  xchartArea: { left: 0, width: "80%" },
136
  xchartArea2: {'width': '100%', 'xheight': '80%'},
137
  xxlegend: {'position': 'bottom'},
138
+ legend: {
139
+ xposition: 'top',
140
+ alignment: 'center'
141
+ }
142
 
143
 
144
  };
149
 
150
  });
151
 
152
+ </script>
templates/settings-statsUsers.php CHANGED
@@ -4,10 +4,10 @@ defined( 'ABSPATH' ) or die();
4
 
5
 
6
  // Output users
7
- echo "<h3>" . __("Users", "simple-history") . "</h3>";
8
 
9
- echo "<p>" . __("Number of logged items for the 5 users with most logged rows.", "simple-history") . "</p>";
10
- echo "<p>" . __("Deleted users are also included.", "simple-history") . "</p>";
11
 
12
  $sql_users = sprintf('
13
  SELECT
@@ -18,35 +18,34 @@ $sql_users = sprintf('
18
  WHERE c.key = "_user_id"
19
  GROUP BY c.value
20
  ',
21
- $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS // 1
22
- );
23
-
24
- $user_results = $wpdb->get_results($sql_users);
25
- #sf_d($user_results);
26
- #printf('<p>Total %1$s users found.</p>', sizeof( $user_results ));
27
 
 
 
 
28
  echo "<table class='widefat' cellpadding=2>";
29
- echo "<thead><tr>
30
- <th></th>
31
- <th>User ID</th>
32
- <th>login</th>
33
- <th>email</th>
34
- <th>logged items</th>
35
- <th>deleted</th>
36
- </tr></thead>";
37
 
38
  $arr_users = array();
39
- foreach ($user_results as $one_user_result) {
40
-
41
  $user_id = $one_user_result->user_id;
42
  if ( empty( $user_id ) ) {
43
  continue;
44
  }
45
 
46
- $str_deleted = empty($one_user_result->user_login) ? "yes" : "";
47
 
48
  // get number of rows this user is responsible for
49
- if ($user_id) {
50
 
51
  $sql_user_count = sprintf('
52
  SELECT count(VALUE) AS count
@@ -59,7 +58,7 @@ foreach ($user_results as $one_user_result) {
59
  $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS, // 1
60
  $wpdb->prefix . SimpleHistory::DBTABLE, // 2
61
  $user_id, // 3
62
- strtotime("-$period_days days") // 4
63
  );
64
 
65
  $user_rows_count = $wpdb->get_var( $sql_user_count );
@@ -67,25 +66,25 @@ foreach ($user_results as $one_user_result) {
67
  }
68
 
69
  $arr_users[] = array(
70
- "user_id" => $user_id,
71
- "user_login" => $one_user_result->user_login,
72
- "user_email" => $one_user_result->user_email, // 3
73
- "str_deleted" => $str_deleted,
74
- "user_rows_count" => $user_rows_count
75
  );
76
 
77
- }
78
 
79
  // order users by count
80
- usort($arr_users, function($a, $b) {
81
- return $a["user_rows_count"] < $b["user_rows_count"];
82
  });
83
 
84
  // only keep the top 10
85
- $arr_users = array_slice($arr_users, 0, 5);
86
 
87
  $loopnum = 0;
88
- foreach ($arr_users as $one_user) {
89
 
90
  printf('
91
  <tr class="%6$s">
@@ -96,19 +95,19 @@ foreach ($arr_users as $one_user) {
96
  <td>%5$s</td>
97
  <td>%4$s</td>
98
  </tr>
99
- ',
100
- $one_user["user_id"],
101
- $one_user["user_login"],
102
- $one_user["user_email"], // 3
103
- $one_user["str_deleted"],
104
- $one_user["user_rows_count"],
105
- $loopnum % 2 ? " alternate " : "", // 6
106
- $this->sh->get_avatar( $one_user["user_email"], 38 ) // 7
107
  );
108
 
109
  $loopnum++;
110
 
111
  }
112
 
113
- echo "</table>";
114
 
4
 
5
 
6
  // Output users
7
+ echo '<h3>' . __( 'Users', 'simple-history' ) . '</h3>';
8
 
9
+ echo '<p>' . __( 'Number of logged items for the 5 users with most logged rows.', 'simple-history' ) . '</p>';
10
+ echo '<p>' . __( 'Deleted users are also included.', 'simple-history' ) . '</p>';
11
 
12
  $sql_users = sprintf('
13
  SELECT
18
  WHERE c.key = "_user_id"
19
  GROUP BY c.value
20
  ',
21
+ $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS // 1
22
+ );
 
 
 
 
23
 
24
+ $user_results = $wpdb->get_results( $sql_users );
25
+ // sf_d($user_results);
26
+ // printf('<p>Total %1$s users found.</p>', sizeof( $user_results ));
27
  echo "<table class='widefat' cellpadding=2>";
28
+ echo '<thead><tr>
29
+ <th></th>
30
+ <th>User ID</th>
31
+ <th>login</th>
32
+ <th>email</th>
33
+ <th>logged items</th>
34
+ <th>deleted</th>
35
+ </tr></thead>';
36
 
37
  $arr_users = array();
38
+ foreach ( $user_results as $one_user_result ) {
39
+
40
  $user_id = $one_user_result->user_id;
41
  if ( empty( $user_id ) ) {
42
  continue;
43
  }
44
 
45
+ $str_deleted = empty( $one_user_result->user_login ) ? 'yes' : '';
46
 
47
  // get number of rows this user is responsible for
48
+ if ( $user_id ) {
49
 
50
  $sql_user_count = sprintf('
51
  SELECT count(VALUE) AS count
58
  $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS, // 1
59
  $wpdb->prefix . SimpleHistory::DBTABLE, // 2
60
  $user_id, // 3
61
+ strtotime( "-$period_days days" ) // 4
62
  );
63
 
64
  $user_rows_count = $wpdb->get_var( $sql_user_count );
66
  }
67
 
68
  $arr_users[] = array(
69
+ 'user_id' => $user_id,
70
+ 'user_login' => $one_user_result->user_login,
71
+ 'user_email' => $one_user_result->user_email, // 3
72
+ 'str_deleted' => $str_deleted,
73
+ 'user_rows_count' => $user_rows_count,
74
  );
75
 
76
+ }// End foreach().
77
 
78
  // order users by count
79
+ usort($arr_users, function( $a, $b ) {
80
+ return $a['user_rows_count'] < $b['user_rows_count'];
81
  });
82
 
83
  // only keep the top 10
84
+ $arr_users = array_slice( $arr_users, 0, 5 );
85
 
86
  $loopnum = 0;
87
+ foreach ( $arr_users as $one_user ) {
88
 
89
  printf('
90
  <tr class="%6$s">
95
  <td>%5$s</td>
96
  <td>%4$s</td>
97
  </tr>
98
+ ',
99
+ $one_user['user_id'],
100
+ $one_user['user_login'],
101
+ $one_user['user_email'], // 3
102
+ $one_user['str_deleted'],
103
+ $one_user['user_rows_count'],
104
+ $loopnum % 2 ? ' alternate ' : '', // 6
105
+ $this->sh->get_avatar( $one_user['user_email'], 38 ) // 7
106
  );
107
 
108
  $loopnum++;
109
 
110
  }
111
 
112
+ echo '</table>';
113
 
templates/settings-style-example.php CHANGED
@@ -4,92 +4,92 @@ defined( 'ABSPATH' ) or die();
4
 
5
  <div class="SimpleHistoryGuiExample">
6
 
7
- <ul class="SimpleHistoryLogitems">
8
 
9
- <li data-row-id="665" data-occasions-count="0" data-occasions-id="8cdab45b0f40a0c9ffea63683e6edd8a" class="SimpleHistoryLogitem SimpleHistoryLogitem--loglevel-info SimpleHistoryLogitem--logger-SimpleMediaLogger SimpleHistoryLogitem--initiator-wp_user">
10
 
11
- <div class="SimpleHistoryLogitem__firstcol">
12
- <div class="SimpleHistoryLogitem__senderImage">
13
- <img src="http://0.gravatar.com/avatar/eabcdc5ce4112ee4bceff4d7567d43a5?s=38&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D38&amp;r=G" class="avatar avatar-38 photo" height="38" width="38">
14
- </div>
15
- </div>
16
 
17
- <div class="SimpleHistoryLogitem__secondcol">
18
 
19
- <div class="SimpleHistoryLogitem__header">
20
- <strong class="SimpleHistoryLogitem__inlineDivided">Jessie</strong>
21
- <span class="SimpleHistoryLogitem__inlineDivided SimpleHistoryLogitem__headerEmail">admin@example.com</span>
22
- <span class="SimpleHistoryLogitem__permalink SimpleHistoryLogitem__when SimpleHistoryLogitem__inlineDivided"><a class="" href="http://playground-root.ep/wp-admin/index.php?page=simple_history_page#item/665"><time datetime="2014-08-11T21:08:44+00:00" title="2014-08-11T21:08:44+00:00" class="">1 min ago</time></a></span>
23
- </div>
24
 
25
- <div class="SimpleHistoryLogitem__text">
26
- Short message descriping the thing that happened.
27
- </div>
28
 
29
- <div class="SimpleHistoryLogitem__details">
30
 
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&amp;action=edit&amp;lang=en">
37
- <div class="SimpleHistoryLogitemThumbnail">
38
- <img src="http://placehold.it/250x250&text=Image">
39
- </div>
40
- </a>
41
- </p>
42
-
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
-
59
- <table class="SimpleHistoryLogitem__keyValueTable">
60
- <tbody>
61
- <tr>
62
- <td>Author</td>
63
- <td><a href="http://bbpress.org">The bbPress Community</a>
64
- </td>
65
- </tr>
66
- <tr>
67
- <td>URL</td>
68
- <td><a href="http://bbpress.org">http://bbpress.org</a>
69
- </td>
70
- </tr>
71
- <tr>
72
- <td>Version</td>
73
- <td>2.5.4</td>
74
- </tr>
75
- <tr>
76
- <td>Updated</td>
77
- <td>2014-07-15</td>
78
- </tr>
79
- <tr>
80
- <td>Requires</td>
81
- <td>3.6</td>
82
- </tr>
83
- <tr>
84
- <td>Compatible up to</td>
85
- <td>3.9.2</td>
86
- </tr>
87
- <tr>
88
- <td>Downloads</td>
89
- <td>1,392,515</td>
90
- </tr>
91
- </tbody>
92
- </table>
93
 
94
  <p>
95
  <span class="SimpleHistoryLogitem__inlineDivided">
@@ -125,14 +125,14 @@ defined( 'ABSPATH' ) or die();
125
  </span>
126
  </p>
127
 
128
- </div>
129
 
130
- </div>
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
 
138
  <div class="SimpleHistoryLogitem__firstcol">
@@ -165,26 +165,26 @@ defined( 'ABSPATH' ) or die();
165
  </li>
166
  ';
167
 
168
- $arr_messages = array(
169
- "emergency" => "Harddrive on VPS 1 has errors",
170
- "alert" => "The WordPress installation on VPS 2 is running out of memory",
171
- "critical" => "There is 21 security updates available for your site",
172
- "error" => "A JavaScript error was detected on page <code>example.com/about-us/contact/</code>",
173
- "warning" => "A user attempted to login to your site with username \"admin\"",
174
- "notice" => "User Jessie logged in",
175
- "info" => "Page \"about us\" was updated",
176
- "debug" => "The variable <code>\$heyhey</code> had value <code>'abc123'</code> and the hash of the user values is <code>'1f3870be274f6c49b3e31a0c6728957f'</code>",
177
- );
178
 
179
- $refl = new ReflectionClass('SimpleLoggerLogLevels');
180
- foreach ( $refl->getConstants() as $key => $val ) {
181
 
182
- $msg = isset($arr_messages[$val]) ? $arr_messages[$val] : "This is a message with loglevel";
183
- echo sprintf($template, $val, $msg);
184
 
185
- }
186
 
187
- ?>
188
 
189
- </ul>
190
  </div>
4
 
5
  <div class="SimpleHistoryGuiExample">
6
 
7
+ <ul class="SimpleHistoryLogitems">
8
 
9
+ <li data-row-id="665" data-occasions-count="0" data-occasions-id="8cdab45b0f40a0c9ffea63683e6edd8a" class="SimpleHistoryLogitem SimpleHistoryLogitem--loglevel-info SimpleHistoryLogitem--logger-SimpleMediaLogger SimpleHistoryLogitem--initiator-wp_user">
10
 
11
+ <div class="SimpleHistoryLogitem__firstcol">
12
+ <div class="SimpleHistoryLogitem__senderImage">
13
+ <img src="http://0.gravatar.com/avatar/eabcdc5ce4112ee4bceff4d7567d43a5?s=38&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D38&amp;r=G" class="avatar avatar-38 photo" height="38" width="38">
14
+ </div>
15
+ </div>
16
 
17
+ <div class="SimpleHistoryLogitem__secondcol">
18
 
19
+ <div class="SimpleHistoryLogitem__header">
20
+ <strong class="SimpleHistoryLogitem__inlineDivided">Jessie</strong>
21
+ <span class="SimpleHistoryLogitem__inlineDivided SimpleHistoryLogitem__headerEmail">admin@example.com</span>
22
+ <span class="SimpleHistoryLogitem__permalink SimpleHistoryLogitem__when SimpleHistoryLogitem__inlineDivided"><a class="" href="http://playground-root.ep/wp-admin/index.php?page=simple_history_page#item/665"><time datetime="2014-08-11T21:08:44+00:00" title="2014-08-11T21:08:44+00:00" class="">1 min ago</time></a></span>
23
+ </div>
24
 
25
+ <div class="SimpleHistoryLogitem__text">
26
+ Short message descriping the thing that happened.
27
+ </div>
28
 
29
+ <div class="SimpleHistoryLogitem__details">
30
 
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&amp;action=edit&amp;lang=en">
37
+ <div class="SimpleHistoryLogitemThumbnail">
38
+ <img src="http://placehold.it/250x250&text=Image">
39
+ </div>
40
+ </a>
41
+ </p>
42
+
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
+
59
+ <table class="SimpleHistoryLogitem__keyValueTable">
60
+ <tbody>
61
+ <tr>
62
+ <td>Author</td>
63
+ <td><a href="http://bbpress.org">The bbPress Community</a>
64
+ </td>
65
+ </tr>
66
+ <tr>
67
+ <td>URL</td>
68
+ <td><a href="http://bbpress.org">http://bbpress.org</a>
69
+ </td>
70
+ </tr>
71
+ <tr>
72
+ <td>Version</td>
73
+ <td>2.5.4</td>
74
+ </tr>
75
+ <tr>
76
+ <td>Updated</td>
77
+ <td>2014-07-15</td>
78
+ </tr>
79
+ <tr>
80
+ <td>Requires</td>
81
+ <td>3.6</td>
82
+ </tr>
83
+ <tr>
84
+ <td>Compatible up to</td>
85
+ <td>3.9.2</td>
86
+ </tr>
87
+ <tr>
88
+ <td>Downloads</td>
89
+ <td>1,392,515</td>
90
+ </tr>
91
+ </tbody>
92
+ </table>
93
 
94
  <p>
95
  <span class="SimpleHistoryLogitem__inlineDivided">
125
  </span>
126
  </p>
127
 
128
+ </div>
129
 
130
+ </div>
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
 
138
  <div class="SimpleHistoryLogitem__firstcol">
165
  </li>
166
  ';
167
 
168
+ $arr_messages = array(
169
+ 'emergency' => 'Harddrive on VPS 1 has errors',
170
+ 'alert' => 'The WordPress installation on VPS 2 is running out of memory',
171
+ 'critical' => 'There is 21 security updates available for your site',
172
+ 'error' => 'A JavaScript error was detected on page <code>example.com/about-us/contact/</code>',
173
+ 'warning' => 'A user attempted to login to your site with username "admin"',
174
+ 'notice' => 'User Jessie logged in',
175
+ 'info' => 'Page "about us" was updated',
176
+ 'debug' => "The variable <code>\$heyhey</code> had value <code>'abc123'</code> and the hash of the user values is <code>'1f3870be274f6c49b3e31a0c6728957f'</code>",
177
+ );
178
 
179
+ $refl = new ReflectionClass( 'SimpleLoggerLogLevels' );
180
+ foreach ( $refl->getConstants() as $key => $val ) {
181
 
182
+ $msg = isset( $arr_messages[ $val ] ) ? $arr_messages[ $val ] : 'This is a message with loglevel';
183
+ echo sprintf( $template, $val, $msg );
184
 
185
+ }
186
 
187
+ ?>
188
 
189
+ </ul>
190
  </div>
templates/template-settings-tab-debug.php CHANGED
@@ -54,21 +54,21 @@ printf(
54
  </tr>
55
  </thead>
56
  ',
57
- _x("Table name", "debug dropin", "simple-history"),
58
- _x("Size", "debug dropin", "simple-history"),
59
- _x("Rows", "debug dropin", "simple-history")
60
  );
61
 
62
  $loopnum = 0;
63
  foreach ( $table_size_result as $one_table ) {
64
 
65
  $size = sprintf(
66
- _x('%s MB', "debug dropin", "simple-history"),
67
  $one_table->size_in_mb
68
  );
69
 
70
  $rows = sprintf(
71
- _x('%s rows', "debug dropin", "simple-history"),
72
  number_format_i18n( $one_table->num_rows, 0 )
73
  );
74
 
@@ -80,34 +80,32 @@ foreach ( $table_size_result as $one_table ) {
80
  $one_table->table_name,
81
  $size,
82
  $rows,
83
- $loopnum % 2 ? " alt " : ""
84
  );
85
 
86
  $loopnum++;
87
  }
88
 
89
- echo "</table>";
90
 
91
  $logQuery = new SimpleHistoryLogQuery();
92
  $rows = $logQuery->query( array(
93
- "posts_per_page" => 1,
94
  ) );
95
 
96
  // This is the number of rows with occasions taken into consideration
97
- $total_accassions_rows_count = $rows["total_row_count"];
98
 
99
- echo "<p>";
100
  printf(
101
- _x('Total %s rows, when grouped by occasion id.', "debug dropin", "simple-history" ),
102
  $total_accassions_rows_count
103
  );
104
- echo "</p>";
105
 
106
 
107
  // echo "<h4>Clear history interval</h4>";
108
  // echo "<p>" . $this->sh->get_clear_history_interval() . "</p>";
109
-
110
-
111
  /**
112
  * Output a list of all active loggers, including name, slug, comment, message, capability and number of rows
113
  * Retrieve them in order by the number of rows they have in the db
@@ -118,7 +116,7 @@ echo "</p>";
118
  $arr_logger_slugs = array();
119
 
120
  foreach ( $this->sh->getInstantiatedLoggers() as $oneLogger ) {
121
- $arr_logger_slugs[] = $oneLogger["instance"]->slug;
122
  }
123
 
124
  $sql_logger_counts = sprintf( '
@@ -136,23 +134,23 @@ $missing_logger_slugs = array_diff( $arr_logger_slugs, array_keys( $logger_rows_
136
 
137
  foreach ( $missing_logger_slugs as $one_missing_logger_slug ) {
138
 
139
- $logger_rows_count[$one_missing_logger_slug] = (object) array(
140
- "logger" => $one_missing_logger_slug,
141
- "count" => 0
142
- );
143
 
144
  }
145
 
146
- echo "<h3>";
147
- _ex("Loggers", "debug dropin", "simple-history");
148
- echo "</h3>";
149
 
150
- echo "<p>";
151
  printf(
152
- _x('Listing %1$d loggers, ordered by rows count in database.', "debug dropin", "simple-history"),
153
- sizeof( $arr_logger_slugs ) // 1
154
- );
155
- echo "</p>";
156
 
157
  echo "<table class='widefat fixed' cellpadding=2>";
158
  printf(
@@ -168,12 +166,12 @@ printf(
168
  </tr>
169
  </thead>
170
  ',
171
- _x("Logger name", "debug dropin", "simple-history"),
172
- _x("Slug", "debug dropin", "simple-history"),
173
- _x("Description", "debug dropin", "simple-history"),
174
- _x("Messages", "debug dropin", "simple-history"),
175
- _x("Capability", "debug dropin", "simple-history"),
176
- _x("Rows count", "debug dropin", "simple-history")
177
  );
178
 
179
  $loopnum = 0;
@@ -195,18 +193,18 @@ foreach ( $logger_rows_count as $one_logger_slug => $one_logger_val ) {
195
  }
196
 
197
  $logger_info = $logger->getInfo();
198
- $logger_messages = isset( $logger_info["messages"] ) ? (array) $logger_info["messages"] : array();
199
 
200
- $html_logger_messages = "";
201
 
202
  foreach ( $logger_messages as $message_key => $message ) {
203
  $html_logger_messages .= sprintf( '<li>%1$s</li>', esc_html( $message ) );
204
  }
205
 
206
- if ( $html_logger_messages ) {
207
 
208
  $str_num_message_strings = sprintf(
209
- _x('%1$s message strings', "debug dropin", "simple-history"),
210
  sizeof( $logger_messages )
211
  );
212
 
@@ -217,12 +215,12 @@ foreach ( $logger_rows_count as $one_logger_slug => $one_logger_val ) {
217
  </ul>
218
  ',
219
  $str_num_message_strings, // 1
220
- $html_logger_messages // 2
221
- );
222
 
223
  } else {
224
- $html_logger_messages = "<p>No message strings</p>";
225
- }
226
 
227
  printf(
228
  '
@@ -249,18 +247,18 @@ foreach ( $logger_rows_count as $one_logger_slug => $one_logger_val ) {
249
  ',
250
  number_format_i18n( $one_logger_count->count ),
251
  esc_html( $one_logger_slug ), // 2
252
- esc_html( $logger_info["name"] ),
253
- esc_html( $logger_info["description"] ), // 4
254
  esc_html( $logger->getCapability() ), // 5
255
- $loopnum % 2 ? " alt " : "", // 6
256
  $html_logger_messages // 7
257
  );
258
 
259
  $loopnum++;
260
 
261
- }
262
 
263
- echo "</table>";
264
 
265
  // List installed plugins
266
  echo '<h2>Plugins</h2>';
@@ -270,7 +268,7 @@ $plugins = get_plugins();
270
 
271
  echo "<table class='widefat'>";
272
  printf(
273
- '<thead>
274
  <tr>
275
  <th>%1$s</th>
276
  <th>%2$s</th>
@@ -278,25 +276,25 @@ printf(
278
  </tr>
279
  </thead>
280
  ',
281
- _x("Plugin name", "debug dropin", "simple-history"),
282
- _x("Plugin file path", "debug dropin", "simple-history"),
283
- _x("Active", "debug dropin", "simple-history")
284
  );
285
 
286
- foreach ($plugins as $pluginFilePath => $onePlugin) {
287
- $isPluginActive = is_plugin_active($pluginFilePath);
288
- printf(
289
- '
290
  <tr>
291
  <td><strong>%1$s</strong></td>
292
  <td>%2$s</td>
293
  <td>%3$s</td>
294
  </tr>
295
  ',
296
- esc_html($onePlugin["Name"]),
297
- esc_html($pluginFilePath),
298
- $isPluginActive ? "Yes" : "No" // 3
299
- );
300
  }
301
 
302
- echo "</table>";
54
  </tr>
55
  </thead>
56
  ',
57
+ _x( 'Table name', 'debug dropin', 'simple-history' ),
58
+ _x( 'Size', 'debug dropin', 'simple-history' ),
59
+ _x( 'Rows', 'debug dropin', 'simple-history' )
60
  );
61
 
62
  $loopnum = 0;
63
  foreach ( $table_size_result as $one_table ) {
64
 
65
  $size = sprintf(
66
+ _x( '%s MB', 'debug dropin', 'simple-history' ),
67
  $one_table->size_in_mb
68
  );
69
 
70
  $rows = sprintf(
71
+ _x( '%s rows', 'debug dropin', 'simple-history' ),
72
  number_format_i18n( $one_table->num_rows, 0 )
73
  );
74
 
80
  $one_table->table_name,
81
  $size,
82
  $rows,
83
+ $loopnum % 2 ? ' alt ' : ''
84
  );
85
 
86
  $loopnum++;
87
  }
88
 
89
+ echo '</table>';
90
 
91
  $logQuery = new SimpleHistoryLogQuery();
92
  $rows = $logQuery->query( array(
93
+ 'posts_per_page' => 1,
94
  ) );
95
 
96
  // This is the number of rows with occasions taken into consideration
97
+ $total_accassions_rows_count = $rows['total_row_count'];
98
 
99
+ echo '<p>';
100
  printf(
101
+ _x( 'Total %s rows, when grouped by occasion id.', 'debug dropin', 'simple-history' ),
102
  $total_accassions_rows_count
103
  );
104
+ echo '</p>';
105
 
106
 
107
  // echo "<h4>Clear history interval</h4>";
108
  // echo "<p>" . $this->sh->get_clear_history_interval() . "</p>";
 
 
109
  /**
110
  * Output a list of all active loggers, including name, slug, comment, message, capability and number of rows
111
  * Retrieve them in order by the number of rows they have in the db
116
  $arr_logger_slugs = array();
117
 
118
  foreach ( $this->sh->getInstantiatedLoggers() as $oneLogger ) {
119
+ $arr_logger_slugs[] = $oneLogger['instance']->slug;
120
  }
121
 
122
  $sql_logger_counts = sprintf( '
134
 
135
  foreach ( $missing_logger_slugs as $one_missing_logger_slug ) {
136
 
137
+ $logger_rows_count[ $one_missing_logger_slug ] = (object) array(
138
+ 'logger' => $one_missing_logger_slug,
139
+ 'count' => 0,
140
+ );
141
 
142
  }
143
 
144
+ echo '<h3>';
145
+ _ex( 'Loggers', 'debug dropin', 'simple-history' );
146
+ echo '</h3>';
147
 
148
+ echo '<p>';
149
  printf(
150
+ _x( 'Listing %1$d loggers, ordered by rows count in database.', 'debug dropin', 'simple-history' ),
151
+ sizeof( $arr_logger_slugs ) // 1
152
+ );
153
+ echo '</p>';
154
 
155
  echo "<table class='widefat fixed' cellpadding=2>";
156
  printf(
166
  </tr>
167
  </thead>
168
  ',
169
+ _x( 'Logger name', 'debug dropin', 'simple-history' ),
170
+ _x( 'Slug', 'debug dropin', 'simple-history' ),
171
+ _x( 'Description', 'debug dropin', 'simple-history' ),
172
+ _x( 'Messages', 'debug dropin', 'simple-history' ),
173
+ _x( 'Capability', 'debug dropin', 'simple-history' ),
174
+ _x( 'Rows count', 'debug dropin', 'simple-history' )
175
  );
176
 
177
  $loopnum = 0;
193
  }
194
 
195
  $logger_info = $logger->getInfo();
196
+ $logger_messages = isset( $logger_info['messages'] ) ? (array) $logger_info['messages'] : array();
197
 
198
+ $html_logger_messages = '';
199
 
200
  foreach ( $logger_messages as $message_key => $message ) {
201
  $html_logger_messages .= sprintf( '<li>%1$s</li>', esc_html( $message ) );
202
  }
203
 
204
+ if ( $html_logger_messages ) {
205
 
206
  $str_num_message_strings = sprintf(
207
+ _x( '%1$s message strings', 'debug dropin', 'simple-history' ),
208
  sizeof( $logger_messages )
209
  );
210
 
215
  </ul>
216
  ',
217
  $str_num_message_strings, // 1
218
+ $html_logger_messages // 2
219
+ );
220
 
221
  } else {
222
+ $html_logger_messages = '<p>No message strings</p>';
223
+ }
224
 
225
  printf(
226
  '
247
  ',
248
  number_format_i18n( $one_logger_count->count ),
249
  esc_html( $one_logger_slug ), // 2
250
+ esc_html( $logger_info['name'] ),
251
+ esc_html( $logger_info['description'] ), // 4
252
  esc_html( $logger->getCapability() ), // 5
253
+ $loopnum % 2 ? ' alt ' : '', // 6
254
  $html_logger_messages // 7
255
  );
256
 
257
  $loopnum++;
258
 
259
+ }// End foreach().
260
 
261
+ echo '</table>';
262
 
263
  // List installed plugins
264
  echo '<h2>Plugins</h2>';
268
 
269
  echo "<table class='widefat'>";
270
  printf(
271
+ '<thead>
272
  <tr>
273
  <th>%1$s</th>
274
  <th>%2$s</th>
276
  </tr>
277
  </thead>
278
  ',
279
+ _x( 'Plugin name', 'debug dropin', 'simple-history' ),
280
+ _x( 'Plugin file path', 'debug dropin', 'simple-history' ),
281
+ _x( 'Active', 'debug dropin', 'simple-history' )
282
  );
283
 
284
+ foreach ( $plugins as $pluginFilePath => $onePlugin ) {
285
+ $isPluginActive = is_plugin_active( $pluginFilePath );
286
+ printf(
287
+ '
288
  <tr>
289
  <td><strong>%1$s</strong></td>
290
  <td>%2$s</td>
291
  <td>%3$s</td>
292
  </tr>
293
  ',
294
+ esc_html( $onePlugin['Name'] ),
295
+ esc_html( $pluginFilePath ),
296
+ $isPluginActive ? 'Yes' : 'No' // 3
297
+ );
298
  }
299
 
300
+ echo '</table>';
tests/test-simplehistory.php CHANGED
@@ -3,9 +3,9 @@
3
  class SimpleHistoryTest extends WP_UnitTestCase {
4
 
5
  // https://phpunit.de/manual/current/en/fixtures.html
6
- public static function setUpBeforeClass() {
7
 
8
- }
9
 
10
 
11
  function test_sample() {
@@ -16,25 +16,25 @@ class SimpleHistoryTest extends WP_UnitTestCase {
16
 
17
  function test_history_setup() {
18
 
19
- $this->assertTrue( defined("SIMPLE_HISTORY_VERSION") );
20
- $this->assertTrue( defined("SIMPLE_HISTORY_PATH") );
21
- $this->assertTrue( defined("SIMPLE_HISTORY_BASENAME") );
22
- $this->assertTrue( defined("SIMPLE_HISTORY_DIR_URL") );
23
- $this->assertTrue( defined("SIMPLE_HISTORY_FILE") );
24
 
25
- $this->assertFalse( defined("SIMPLE_HISTORY_DEV") );
26
- $this->assertFalse( defined("SIMPLE_HISTORY_LOG_DEBUG") );
27
 
28
  }
29
 
30
  function test_history_classes() {
31
 
32
- $this->assertTrue( class_exists("SimpleHistory") );
33
- $this->assertTrue( class_exists("SimpleHistoryLogQuery") );
34
 
35
  $sh = SimpleHistory::get_instance();
36
- $this->assertTrue( is_object($sh) );
37
- $this->assertTrue( is_a($sh, "SimpleHistory") );
38
 
39
  }
40
 
@@ -44,21 +44,21 @@ class SimpleHistoryTest extends WP_UnitTestCase {
44
  $loggers = $sh->getInstantiatedLoggers();
45
 
46
  $arr_default_loggers = array(
47
- "SimpleCommentsLogger",
48
- "SimpleCoreUpdatesLogger",
49
- "SimpleExportLogger",
50
- "SimpleLegacyLogger",
51
- "SimpleLogger",
52
- "SimpleMediaLogger",
53
- "SimpleMenuLogger",
54
- "SimpleOptionsLogger",
55
- "SimplePluginLogger",
56
- "SimplePostLogger",
57
- "SimpleThemeLogger",
58
- "SimpleUserLogger",
59
  );
60
 
61
- foreach ($arr_default_loggers as $slug) {
62
 
63
  $this->assertArrayHasKey( $slug, $loggers );
64
 
@@ -72,18 +72,18 @@ class SimpleHistoryTest extends WP_UnitTestCase {
72
  $dropins = $sh->getInstantiatedDropins();
73
 
74
  $arr_default_dropins = array(
75
- "SimpleHistoryDonateDropin",
76
- "SimpleHistoryExportDropin",
77
- "SimpleHistoryFilterDropin",
78
- "SimpleHistoryIpInfoDropin",
79
- "SimpleHistoryNewRowsNotifier",
80
- "SimpleHistoryRSSDropin",
81
- "SimpleHistorySettingsLogtestDropin",
82
- "SimpleHistorySettingsStatsDropin",
83
- "SimpleHistorySidebarDropin",
84
  );
85
 
86
- foreach ($arr_default_dropins as $slug) {
87
 
88
  $this->assertArrayHasKey( $slug, $dropins );
89
 
@@ -96,13 +96,13 @@ class SimpleHistoryTest extends WP_UnitTestCase {
96
  $sh = SimpleHistory::get_instance();
97
  $settings_tabs = $sh->getSettingsTabs();
98
  $arr_default_settings = array(
99
- "settings",
100
- "export",
101
- "debug"
102
  );
103
 
104
- $loaded_settings_slugs = wp_list_pluck( $settings_tabs, "slug" );
105
- $this->assertEquals($arr_default_settings, $loaded_settings_slugs);
106
 
107
  }
108
 
@@ -115,69 +115,66 @@ class SimpleHistoryTest extends WP_UnitTestCase {
115
  $table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name_simple_history ) );
116
  $this->assertEquals( $table_name_simple_history, $table_exists );
117
 
118
- $table_cols = $wpdb->get_col("DESCRIBE $table_name_simple_history");
119
  $expected_table_cols = array(
120
- "id",
121
- "date",
122
- "logger",
123
- "level",
124
- "message",
125
- "occasionsID",
126
- "initiator"
127
  );
128
 
129
- $this->assertEquals($expected_table_cols, $table_cols, "cols in history table should be the same");
130
-
131
 
132
  // Test table simple history contexts
133
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
134
  $table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name_contexts ) );
135
  $this->assertEquals( $table_name_contexts, $table_exists );
136
 
137
- $table_cols_context = $wpdb->get_col("DESCRIBE $table_name_contexts");
138
  $expected_table_cols_context = array(
139
- "context_id",
140
- "history_id",
141
- "key",
142
- "value"
143
  );
144
 
145
- $this->assertEquals($expected_table_cols_context, $table_cols_context, "cols in context table should be the same");
146
-
147
 
148
  }
149
 
150
  function test_loglevels_and_initiators() {
151
 
152
- $refl = new ReflectionClass('SimpleLoggerLogLevels');
153
  $log_levels = (array) $refl->getConstants();
154
 
155
  $expected_log_levels = array(
156
- 'EMERGENCY' => "emergency",
157
- 'ALERT' => "alert",
158
- 'CRITICAL' => "critical",
159
- 'ERROR' => "error",
160
- 'WARNING' => "warning",
161
- 'NOTICE' => "notice",
162
- 'INFO' => "info",
163
- 'DEBUG' => "debug"
164
  );
165
 
166
- $this->assertEquals( $expected_log_levels, $log_levels, "log levels" );
167
 
168
- $refl = new ReflectionClass('SimpleLoggerLogInitiators');
169
  $log_initiators = (array) $refl->getConstants();
170
 
171
  $expected_log_initiators = array(
172
- "WP_USER" => 'wp_user',
173
- "WEB_USER" => 'web_user',
174
- "WORDPRESS" => "wp",
175
- "WP_CLI" => "wp_cli",
176
- "OTHER" => 'other'
177
  );
178
 
179
- $this->assertEquals( $expected_log_initiators, $log_initiators, "log initiators" );
180
-
181
 
182
  }
183
 
@@ -188,10 +185,10 @@ class SimpleHistoryTest extends WP_UnitTestCase {
188
 
189
  $table_name_simple_history = $wpdb->prefix . SimpleHistory::DBTABLE;
190
 
191
- $refl_log_levels = new ReflectionClass('SimpleLoggerLogLevels');
192
  $log_levels = (array) $refl_log_levels->getConstants();
193
 
194
- $refl_log_initiators = new ReflectionClass('SimpleLoggerLogInitiators');
195
  $log_initiators = (array) $refl_log_initiators->getConstants();
196
 
197
  foreach ( $log_levels as $level_const => $level_str ) {
@@ -201,67 +198,67 @@ class SimpleHistoryTest extends WP_UnitTestCase {
201
  $message = "This is a message with log level $level_str";
202
 
203
  SimpleLogger()->log( $level_str, $message, array(
204
- "_initiator" => $initiator_str
205
  ) );
206
 
207
  // Last logged message in db should be the above
208
  $db_row = $wpdb->get_row( "SELECT logger, level, message, initiator FROM $table_name_simple_history ORDER BY id DESC LIMIT 1", ARRAY_A );
209
 
210
  $expected_row = array(
211
- 'logger' => "SimpleLogger",
212
  'level' => $level_str,
213
  'message' => $message,
214
- 'initiator' => $initiator_str
215
  );
216
 
217
- $this->assertEquals( $expected_row, $db_row, "logged event in db" );
218
 
219
  }
220
-
221
  }
222
 
223
  // TODO: test logging with context
224
-
225
  }
226
 
227
  function test_log_query() {
228
 
229
  // Add admin user
230
- $user_id = $this->factory->user->create( array( 'role' => 'administrator' ) );
 
 
231
  wp_set_current_user( $user_id );
232
 
233
  $args = array(
234
- "posts_per_page" => 1
235
  );
236
 
237
  $logQuery = new SimpleHistoryLogQuery();
238
  $queryResults = $logQuery->query( $args );
239
 
240
  // The latest row should be the user we create above
241
- $this->assertArrayHasKey( "total_row_count", $queryResults );
242
- $this->assertArrayHasKey( "pages_count", $queryResults );
243
- $this->assertArrayHasKey( "page_current", $queryResults );
244
- $this->assertArrayHasKey( "page_rows_from", $queryResults );
245
- $this->assertArrayHasKey( "page_rows_to", $queryResults );
246
- $this->assertArrayHasKey( "max_id", $queryResults );
247
- $this->assertArrayHasKey( "min_id", $queryResults );
248
- $this->assertArrayHasKey( "log_rows_count", $queryResults );
249
- $this->assertArrayHasKey( "log_rows", $queryResults );
250
-
251
- $this->assertCount( 1, $queryResults["log_rows"] );
252
-
253
- $this->assertObjectHasAttribute( "id", $queryResults["log_rows"][0] );
254
- $this->assertObjectHasAttribute( "logger", $queryResults["log_rows"][0] );
255
- $this->assertObjectHasAttribute( "level", $queryResults["log_rows"][0] );
256
- $this->assertObjectHasAttribute( "date", $queryResults["log_rows"][0] );
257
- $this->assertObjectHasAttribute( "message", $queryResults["log_rows"][0] );
258
- $this->assertObjectHasAttribute( "initiator", $queryResults["log_rows"][0] );
259
- $this->assertObjectHasAttribute( "occasionsID", $queryResults["log_rows"][0] );
260
- $this->assertObjectHasAttribute( "subsequentOccasions", $queryResults["log_rows"][0] );
261
- $this->assertObjectHasAttribute( "rep", $queryResults["log_rows"][0] );
262
- $this->assertObjectHasAttribute( "repeated", $queryResults["log_rows"][0] );
263
- $this->assertObjectHasAttribute( "occasionsIDType", $queryResults["log_rows"][0] );
264
- $this->assertObjectHasAttribute( "context", $queryResults["log_rows"][0] );
265
 
266
  }
267
 
@@ -269,18 +266,18 @@ class SimpleHistoryTest extends WP_UnitTestCase {
269
 
270
  $sh = SimpleHistory::get_instance();
271
 
272
- $postlogger = $sh->getInstantiatedLoggerBySlug( "SimplePostLogger" );
273
  $info = $postlogger->getInfo();
274
 
275
- $this->assertArrayHasKey( "name", $info );
276
- $this->assertArrayHasKey( "description", $info );
277
- $this->assertArrayHasKey( "capability", $info );
278
- $this->assertArrayHasKey( "messages", $info );
279
 
280
- $this->assertTrue( is_array( $info["messages"] ) );
281
- $this->assertTrue( is_array( $info["labels"] ) );
282
- $this->assertTrue( is_array( $info["labels"]["search"] ) );
283
- $this->assertTrue( is_array( $info["labels"]["search"]["options"] ) );
284
 
285
  }
286
 
3
  class SimpleHistoryTest extends WP_UnitTestCase {
4
 
5
  // https://phpunit.de/manual/current/en/fixtures.html
6
+ public static function setUpBeforeClass() {
7
 
8
+ }
9
 
10
 
11
  function test_sample() {
16
 
17
  function test_history_setup() {
18
 
19
+ $this->assertTrue( defined( 'SIMPLE_HISTORY_VERSION' ) );
20
+ $this->assertTrue( defined( 'SIMPLE_HISTORY_PATH' ) );
21
+ $this->assertTrue( defined( 'SIMPLE_HISTORY_BASENAME' ) );
22
+ $this->assertTrue( defined( 'SIMPLE_HISTORY_DIR_URL' ) );
23
+ $this->assertTrue( defined( 'SIMPLE_HISTORY_FILE' ) );
24
 
25
+ $this->assertFalse( defined( 'SIMPLE_HISTORY_DEV' ) );
26
+ $this->assertFalse( defined( 'SIMPLE_HISTORY_LOG_DEBUG' ) );
27
 
28
  }
29
 
30
  function test_history_classes() {
31
 
32
+ $this->assertTrue( class_exists( 'SimpleHistory' ) );
33
+ $this->assertTrue( class_exists( 'SimpleHistoryLogQuery' ) );
34
 
35
  $sh = SimpleHistory::get_instance();
36
+ $this->assertTrue( is_object( $sh ) );
37
+ $this->assertTrue( is_a( $sh, 'SimpleHistory' ) );
38
 
39
  }
40
 
44
  $loggers = $sh->getInstantiatedLoggers();
45
 
46
  $arr_default_loggers = array(
47
+ 'SimpleCommentsLogger',
48
+ 'SimpleCoreUpdatesLogger',
49
+ 'SimpleExportLogger',
50
+ 'SimpleLegacyLogger',
51
+ 'SimpleLogger',
52
+ 'SimpleMediaLogger',
53
+ 'SimpleMenuLogger',
54
+ 'SimpleOptionsLogger',
55
+ 'SimplePluginLogger',
56
+ 'SimplePostLogger',
57
+ 'SimpleThemeLogger',
58
+ 'SimpleUserLogger',
59
  );
60
 
61
+ foreach ( $arr_default_loggers as $slug ) {
62
 
63
  $this->assertArrayHasKey( $slug, $loggers );
64
 
72
  $dropins = $sh->getInstantiatedDropins();
73
 
74
  $arr_default_dropins = array(
75
+ 'SimpleHistoryDonateDropin',
76
+ 'SimpleHistoryExportDropin',
77
+ 'SimpleHistoryFilterDropin',
78
+ 'SimpleHistoryIpInfoDropin',
79
+ 'SimpleHistoryNewRowsNotifier',
80
+ 'SimpleHistoryRSSDropin',
81
+ 'SimpleHistorySettingsLogtestDropin',
82
+ 'SimpleHistorySettingsStatsDropin',
83
+ 'SimpleHistorySidebarDropin',
84
  );
85
 
86
+ foreach ( $arr_default_dropins as $slug ) {
87
 
88
  $this->assertArrayHasKey( $slug, $dropins );
89
 
96
  $sh = SimpleHistory::get_instance();
97
  $settings_tabs = $sh->getSettingsTabs();
98
  $arr_default_settings = array(
99
+ 'settings',
100
+ 'export',
101
+ 'debug',
102
  );
103
 
104
+ $loaded_settings_slugs = wp_list_pluck( $settings_tabs, 'slug' );
105
+ $this->assertEquals( $arr_default_settings, $loaded_settings_slugs );
106
 
107
  }
108
 
115
  $table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name_simple_history ) );
116
  $this->assertEquals( $table_name_simple_history, $table_exists );
117
 
118
+ $table_cols = $wpdb->get_col( "DESCRIBE $table_name_simple_history" );
119
  $expected_table_cols = array(
120
+ 'id',
121
+ 'date',
122
+ 'logger',
123
+ 'level',
124
+ 'message',
125
+ 'occasionsID',
126
+ 'initiator',
127
  );
128
 
129
+ $this->assertEquals( $expected_table_cols, $table_cols, 'cols in history table should be the same' );
 
130
 
131
  // Test table simple history contexts
132
  $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
133
  $table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name_contexts ) );
134
  $this->assertEquals( $table_name_contexts, $table_exists );
135
 
136
+ $table_cols_context = $wpdb->get_col( "DESCRIBE $table_name_contexts" );
137
  $expected_table_cols_context = array(
138
+ 'context_id',
139
+ 'history_id',
140
+ 'key',
141
+ 'value',
142
  );
143
 
144
+ $this->assertEquals( $expected_table_cols_context, $table_cols_context, 'cols in context table should be the same' );
 
145
 
146
  }
147
 
148
  function test_loglevels_and_initiators() {
149
 
150
+ $refl = new ReflectionClass( 'SimpleLoggerLogLevels' );
151
  $log_levels = (array) $refl->getConstants();
152
 
153
  $expected_log_levels = array(
154
+ 'EMERGENCY' => 'emergency',
155
+ 'ALERT' => 'alert',
156
+ 'CRITICAL' => 'critical',
157
+ 'ERROR' => 'error',
158
+ 'WARNING' => 'warning',
159
+ 'NOTICE' => 'notice',
160
+ 'INFO' => 'info',
161
+ 'DEBUG' => 'debug',
162
  );
163
 
164
+ $this->assertEquals( $expected_log_levels, $log_levels, 'log levels' );
165
 
166
+ $refl = new ReflectionClass( 'SimpleLoggerLogInitiators' );
167
  $log_initiators = (array) $refl->getConstants();
168
 
169
  $expected_log_initiators = array(
170
+ 'WP_USER' => 'wp_user',
171
+ 'WEB_USER' => 'web_user',
172
+ 'WORDPRESS' => 'wp',
173
+ 'WP_CLI' => 'wp_cli',
174
+ 'OTHER' => 'other',
175
  );
176
 
177
+ $this->assertEquals( $expected_log_initiators, $log_initiators, 'log initiators' );
 
178
 
179
  }
180
 
185
 
186
  $table_name_simple_history = $wpdb->prefix . SimpleHistory::DBTABLE;
187
 
188
+ $refl_log_levels = new ReflectionClass( 'SimpleLoggerLogLevels' );
189
  $log_levels = (array) $refl_log_levels->getConstants();
190
 
191
+ $refl_log_initiators = new ReflectionClass( 'SimpleLoggerLogInitiators' );
192
  $log_initiators = (array) $refl_log_initiators->getConstants();
193
 
194
  foreach ( $log_levels as $level_const => $level_str ) {
198
  $message = "This is a message with log level $level_str";
199
 
200
  SimpleLogger()->log( $level_str, $message, array(
201
+ '_initiator' => $initiator_str,
202
  ) );
203
 
204
  // Last logged message in db should be the above
205
  $db_row = $wpdb->get_row( "SELECT logger, level, message, initiator FROM $table_name_simple_history ORDER BY id DESC LIMIT 1", ARRAY_A );
206
 
207
  $expected_row = array(
208
+ 'logger' => 'SimpleLogger',
209
  'level' => $level_str,
210
  'message' => $message,
211
+ 'initiator' => $initiator_str,
212
  );
213
 
214
+ $this->assertEquals( $expected_row, $db_row, 'logged event in db' );
215
 
216
  }
 
217
  }
218
 
219
  // TODO: test logging with context
 
220
  }
221
 
222
  function test_log_query() {
223
 
224
  // Add admin user
225
+ $user_id = $this->factory->user->create( array(
226
+ 'role' => 'administrator',
227
+ ) );
228
  wp_set_current_user( $user_id );
229
 
230
  $args = array(
231
+ 'posts_per_page' => 1,
232
  );
233
 
234
  $logQuery = new SimpleHistoryLogQuery();
235
  $queryResults = $logQuery->query( $args );
236
 
237
  // The latest row should be the user we create above
238
+ $this->assertArrayHasKey( 'total_row_count', $queryResults );
239
+ $this->assertArrayHasKey( 'pages_count', $queryResults );
240
+ $this->assertArrayHasKey( 'page_current', $queryResults );
241
+ $this->assertArrayHasKey( 'page_rows_from', $queryResults );
242
+ $this->assertArrayHasKey( 'page_rows_to', $queryResults );
243
+ $this->assertArrayHasKey( 'max_id', $queryResults );
244
+ $this->assertArrayHasKey( 'min_id', $queryResults );
245
+ $this->assertArrayHasKey( 'log_rows_count', $queryResults );
246
+ $this->assertArrayHasKey( 'log_rows', $queryResults );
247
+
248
+ $this->assertCount( 1, $queryResults['log_rows'] );
249
+
250
+ $this->assertObjectHasAttribute( 'id', $queryResults['log_rows'][0] );
251
+ $this->assertObjectHasAttribute( 'logger', $queryResults['log_rows'][0] );
252
+ $this->assertObjectHasAttribute( 'level', $queryResults['log_rows'][0] );
253
+ $this->assertObjectHasAttribute( 'date', $queryResults['log_rows'][0] );
254
+ $this->assertObjectHasAttribute( 'message', $queryResults['log_rows'][0] );
255
+ $this->assertObjectHasAttribute( 'initiator', $queryResults['log_rows'][0] );
256
+ $this->assertObjectHasAttribute( 'occasionsID', $queryResults['log_rows'][0] );
257
+ $this->assertObjectHasAttribute( 'subsequentOccasions', $queryResults['log_rows'][0] );
258
+ $this->assertObjectHasAttribute( 'rep', $queryResults['log_rows'][0] );
259
+ $this->assertObjectHasAttribute( 'repeated', $queryResults['log_rows'][0] );
260
+ $this->assertObjectHasAttribute( 'occasionsIDType', $queryResults['log_rows'][0] );
261
+ $this->assertObjectHasAttribute( 'context', $queryResults['log_rows'][0] );
262
 
263
  }
264
 
266
 
267
  $sh = SimpleHistory::get_instance();
268
 
269
+ $postlogger = $sh->getInstantiatedLoggerBySlug( 'SimplePostLogger' );
270
  $info = $postlogger->getInfo();
271
 
272
+ $this->assertArrayHasKey( 'name', $info );
273
+ $this->assertArrayHasKey( 'description', $info );
274
+ $this->assertArrayHasKey( 'capability', $info );
275
+ $this->assertArrayHasKey( 'messages', $info );
276
 
277
+ $this->assertTrue( is_array( $info['messages'] ) );
278
+ $this->assertTrue( is_array( $info['labels'] ) );
279
+ $this->assertTrue( is_array( $info['labels']['search'] ) );
280
+ $this->assertTrue( is_array( $info['labels']['search']['options'] ) );
281
 
282
  }
283
 
uninstall.php CHANGED
@@ -1,12 +1,14 @@
1
  <?php
2
  /**
3
  * File that is run during plugin uninstall (not just de-activate)
 
4
  * @TODO: delete all tables in network if on multisite
5
  */
6
 
7
  // If uninstall not called from WordPress exit
8
- if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) )
9
- exit ();
 
10
 
11
  /*
12
  Go on with uninstall actions:
@@ -16,24 +18,24 @@ Go on with uninstall actions:
16
 
17
  // Remove options
18
  $arr_options = array(
19
- "simple_history_pager_size",
20
- "simple_history_db_version",
21
- "simple_history_rss_secret",
22
- "simple_history_show_on_dashboard",
23
- "simple_history_show_as_page"
24
  );
25
 
26
- foreach ($arr_options as $one_option) {
27
  delete_option( $one_option );
28
  }
29
 
30
  global $wpdb;
31
 
32
  // Remove database tables
33
- $table_name = $wpdb->prefix . "simple_history";
34
- $wpdb->query("DROP TABLE IF EXISTS $table_name");
35
 
36
- $table_name = $wpdb->prefix . "simple_history_contexts";
37
- $wpdb->query("DROP TABLE IF EXISTS $table_name");
38
 
39
  // And we are done. Simple History is ... history.
1
  <?php
2
  /**
3
  * File that is run during plugin uninstall (not just de-activate)
4
+ *
5
  * @TODO: delete all tables in network if on multisite
6
  */
7
 
8
  // If uninstall not called from WordPress exit
9
+ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
10
+ exit();
11
+ }
12
 
13
  /*
14
  Go on with uninstall actions:
18
 
19
  // Remove options
20
  $arr_options = array(
21
+ 'simple_history_pager_size',
22
+ 'simple_history_db_version',
23
+ 'simple_history_rss_secret',
24
+ 'simple_history_show_on_dashboard',
25
+ 'simple_history_show_as_page',
26
  );
27
 
28
+ foreach ( $arr_options as $one_option ) {
29
  delete_option( $one_option );
30
  }
31
 
32
  global $wpdb;
33
 
34
  // Remove database tables
35
+ $table_name = $wpdb->prefix . 'simple_history';
36
+ $wpdb->query( "DROP TABLE IF EXISTS $table_name" );
37
 
38
+ $table_name = $wpdb->prefix . 'simple_history_contexts';
39
+ $wpdb->query( "DROP TABLE IF EXISTS $table_name" );
40
 
41
  // And we are done. Simple History is ... history.