Simple History - Version 2.1

Version Description

(May 2015) =

  • Added: Export! Now it's possible to export the events log to a JSON or CSV formatted file. It's your data so you should be able to export it any time you want or need. And now you can do that. You will find the export function in the Simple History settings page (Settings -> Simple History).
  • Added: Filter simple_history/add_custom_logger and function register_logger that together are used to load external custom loggers. See example-logger.php for usage example.
  • Added: Filter simple_history/header_initiator_use_you.
  • Fixed: Fixed an undefined variable in get_avatar(). Fixes https://github.com/bonny/WordPress-Simple-History/issues/74.
  • Fixed: When using HyperDB only one event was returned. Fixed by using adding NO_SELECT_FOUND_ROWS to the query. Should fix problems for users using HyperDB and also users using for example wpengine.com (that probably also is using HyperDB or a similar approach).
  • Changed: Loggers now get default capability "manage_options" if they have no capability set.
  • Changed: Misc internal cleanup.
  • Removed: filter simple_history/loggers_dir removed, because loggers are loaded from array instead of file listing generated from glob(). Should be (however to the eye non-noticable) faster.
Download this release

Release Info

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

Code changes from version 2.0.30 to 2.1

dropins/SimpleHistoryExportDropin.php ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ Dropin Name: Export
5
+ Dropin Description: Adds a tab with export options
6
+ Dropin URI: http://simple-history.com/
7
+ Author: Pär Thernström
8
+ */
9
+
10
+ class SimpleHistoryExportDropin {
11
+
12
+ // Simple History instance
13
+ private $sh;
14
+
15
+ public function __construct($sh) {
16
+
17
+ // Since it's not quite done yet, it's for da devs only for now
18
+ if ( ! defined("SIMPLE_HISTORY_DEV") || ! SIMPLE_HISTORY_DEV ) {
19
+ return;
20
+ }
21
+
22
+ // Set simple history variable
23
+ $this->sh = $sh;
24
+
25
+ // Add tab to settings page
26
+ $sh->registerSettingsTab(array(
27
+ "slug" => "export",
28
+ "name" => _x("Export", "Export dropin: Tab name on settings page", "simple-history"),
29
+ "function" => array($this, "output")
30
+ ));
31
+
32
+ add_action("init", array($this, "downloadExport"));
33
+
34
+ }
35
+
36
+ public function downloadExport() {
37
+
38
+ global $wpdb;
39
+
40
+ $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
41
+ $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
42
+
43
+ if ( isset($_POST["simple-history-action"]) && $_POST["simple-history-action"] === "export-history" ) {
44
+
45
+ // Will die if nonce not valid
46
+ check_admin_referer( __CLASS__ . "-action-export" );
47
+
48
+ $export_format = isset( $_POST["format"] ) ? $_POST["format"] : "json";
49
+
50
+ // Disable relative time output in header
51
+ add_filter("simple_history/header_time_ago_max_time", "__return_zero");
52
+ add_filter("simple_history/header_just_now_max_time", "__return_zero");
53
+
54
+ // Don't use "You" if event is initiated by the same user that does the export
55
+ add_filter("simple_history/header_initiator_use_you", "__return_false");
56
+
57
+ $query = new SimpleHistoryLogQuery();
58
+
59
+ $query_args = array(
60
+ "paged" => 1,
61
+ "posts_per_page" => 3000
62
+ );
63
+
64
+ $events = $query->query($query_args);
65
+
66
+ // $events->total_row_count;
67
+ $pages_count = $events["pages_count"];
68
+ $page_current = $events["page_current"];
69
+
70
+ $fp = fopen('php://output', 'w');
71
+
72
+ #header("Content-Type: application/octet-stream");
73
+ if ( "csv" == $export_format ) {
74
+
75
+ $filename = "simple-history-export-" . time() . ".csv";
76
+ header("Content-Type: text/plain");
77
+ header("Content-Disposition: attachment; filename='{$filename}'");
78
+
79
+ } else if ( "json" == $export_format ) {
80
+
81
+ $filename = "simple-history-export-" . time() . ".json";
82
+ header("Content-Type: application/json");
83
+ header("Content-Disposition: attachment; filename='{$filename}'");
84
+
85
+ } else if ( "html" == $export_format ) {
86
+
87
+ $filename = "simple-history-export-" . time() . ".html";
88
+ header("Content-Type: text/html");
89
+ #header("Content-Disposition: attachment; filename='{$filename}'");
90
+
91
+ }
92
+
93
+ // Some formats need to output some stuff before the actual loops
94
+ if ( "json" == $export_format ) {
95
+
96
+ $json_row = "[";
97
+ fwrite($fp, $json_row);
98
+
99
+ } else if ( "html" == $export_format ) {
100
+
101
+ $html = sprintf(
102
+ '
103
+ <!doctype html>
104
+ <meta charset="utf-8">
105
+ <title>Simple History export</title>
106
+ <ul>
107
+ ');
108
+ fwrite($fp, $html);
109
+
110
+ }
111
+
112
+ // Paginate through all pages and all their rows
113
+ $row_loop = 0;
114
+ while ( $page_current <= $pages_count + 1 ) {
115
+
116
+ // if ($page_current > 1) { break; } # To debug/test
117
+
118
+ foreach ( $events["log_rows"] as $one_row ) {
119
+
120
+ // if ( $row_loop > 10) { break; } # To debug/test
121
+
122
+ set_time_limit(30);
123
+
124
+ if ( "csv" == $export_format ) {
125
+
126
+ $header_output = strip_tags( html_entity_decode( $this->sh->getLogRowHeaderOutput( $one_row ), ENT_QUOTES, 'UTF-8') );
127
+ $header_output = trim(preg_replace('/\s\s+/', ' ', $header_output));
128
+
129
+ $message_output = strip_tags( html_entity_decode( $this->sh->getLogRowPlainTextOutput( $one_row ), ENT_QUOTES, 'UTF-8') );
130
+
131
+ fputcsv($fp, array(
132
+ $one_row->date,
133
+ $one_row->logger,
134
+ $one_row->level,
135
+ $one_row->initiator,
136
+ $one_row->context_message_key,
137
+ $header_output,
138
+ $message_output,
139
+ $one_row->subsequentOccasions
140
+ ));
141
+
142
+ } else if ( "json" == $export_format ) {
143
+
144
+ // If not first loop then add a comma between all json objects
145
+ if ( $row_loop == 0 ) {
146
+ $comma = "\n";
147
+ } else {
148
+ $comma = ",\n";
149
+ }
150
+
151
+ $json_row = $comma . $this->sh->json_encode($one_row);
152
+ fwrite($fp, $json_row);
153
+
154
+ } else if ( "html" == $export_format ) {
155
+
156
+ $html = sprintf(
157
+ '
158
+ <li>
159
+ <div>%1$s</div>
160
+ <div>%2$s</div>
161
+ <div>%3$s</div>
162
+ </li>
163
+ ',
164
+ $this->sh->getLogRowHeaderOutput( $one_row ),
165
+ $this->sh->getLogRowPlainTextOutput( $one_row ),
166
+ $this->sh->getLogRowDetailsOutput( $one_row )
167
+ );
168
+
169
+ fwrite($fp, $html);
170
+
171
+ }
172
+
173
+ $row_loop++;
174
+
175
+ }
176
+
177
+ #echo "<br>memory_get_usage:<br>"; print_r(memory_get_usage());
178
+ #echo "<br>memory_get_peak_usage:<br>"; print_r(memory_get_peak_usage());
179
+ #echo "<br>fetch next page";
180
+
181
+ flush();
182
+
183
+ // Fetch next page
184
+ // @TODO: must take into consideration that new items can be added while we do the fetch
185
+ $page_current++;
186
+ $query_args["paged"] = $page_current;
187
+ $events = $query->query($query_args);
188
+
189
+ #echo "<br>did fetch next page";
190
+ #echo "<br>memory_get_usage:<br>"; print_r(memory_get_usage());
191
+ #echo "<br>memory_get_peak_usage:<br>"; print_r(memory_get_peak_usage());
192
+
193
+
194
+ }
195
+
196
+ if ("json" == $export_format) {
197
+
198
+ $json_row = "]";
199
+ fwrite($fp, $json_row);
200
+
201
+ } else if ("html" == $export_format) {
202
+
203
+ $html = sprintf('</ul>');
204
+ fwrite($fp, $html);
205
+
206
+ }
207
+
208
+ fclose($fp);
209
+ flush();
210
+
211
+ exit;
212
+
213
+ #echo "<br>done";
214
+
215
+ }
216
+
217
+ }
218
+
219
+
220
+ public function output() {
221
+
222
+
223
+ ?>
224
+ <!-- <h2>Export</h2> -->
225
+
226
+ <p><?php _ex("The export function will export the full history.", "Export dropin: introtext", "simple-history" ) ?></p>
227
+
228
+ <form method="post">
229
+
230
+ <h3><?php _ex("Choose format to export to", "Export dropin: format", "simple-history" ) ?></h3>
231
+
232
+ <p>
233
+ <label>
234
+ <input type="radio" name="format" value="json" checked>
235
+ <?php _ex("JSON", "Export dropin: export format", "simple-history" ) ?>
236
+ </label>
237
+ </p>
238
+
239
+ <p>
240
+ <label>
241
+ <input type="radio" name="format" value="csv">
242
+ <?php _ex("CSV", "Export dropin: export format", "simple-history" ) ?>
243
+ </label>
244
+ </p>
245
+
246
+ <!-- <br> -->
247
+
248
+ <!--<label>
249
+ <input type="radio" name="format" value="html">
250
+ HTML
251
+ </label>
252
+ <br> -->
253
+
254
+ <!-- <label>
255
+ <input type="radio" name="format" value="xml">
256
+ XML
257
+ </label> -->
258
+
259
+ <p>
260
+ <button type="submit" class="button button-primary"><?php _ex("Download Export File", "Export dropin: submit button", "simple-history" ) ?></button>
261
+ <input type="hidden" name="simple-history-action" value="export-history">
262
+ </p>
263
+
264
+ <?php
265
+ wp_nonce_field( __CLASS__ . "-action-export" );
266
+ ?>
267
+
268
+ </form>
269
+
270
+ <?php
271
+
272
+ }
273
+
274
+ }
examples/example-logger.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // No external calls allowed to test file
4
+ exit;
5
+
6
+
7
+ /**
8
+ * This example shows how to create a simple logger that will
9
+ * log 404-errors on your website.
10
+ */
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
+ }
inc/SimpleHistory.php CHANGED
@@ -10,7 +10,7 @@ class SimpleHistory {
10
  const NAME = "Simple History";
11
 
12
  // Dont use this any more! Will be removed in future versions. Use global SIMPLE_HISTORY_VERSION instead.
13
- const VERSION = "2.0.30";
14
 
15
  /**
16
  * For singleton
@@ -27,6 +27,11 @@ class SimpleHistory {
27
  */
28
  private $view_settings_capability;
29
 
 
 
 
 
 
30
  /**
31
  * Array with all instantiated loggers
32
  */
@@ -37,8 +42,6 @@ class SimpleHistory {
37
  */
38
  private $instantiatedDropins;
39
 
40
- public $pluginBasename;
41
-
42
  /**
43
  * Bool if gettext filter function should be active
44
  * Should only be active during the load of a logger
@@ -82,13 +85,13 @@ class SimpleHistory {
82
  */
83
  do_action("simple_history/before_init", $this);
84
 
85
- $this->setupVariables();
86
 
87
  // Actions and filters, ordered by order specified in codex: http://codex.wordpress.org/Plugin_API/Action_Reference
88
  add_action('after_setup_theme', array($this, 'load_plugin_textdomain'));
89
  add_action('after_setup_theme', array($this, 'add_default_settings_tabs'));
90
- add_action('after_setup_theme', array($this, 'loadLoggers'));
91
- add_action('after_setup_theme', array($this, 'loadDropins'));
92
 
93
  // Run before loading of loggers and before menu items are added
94
  add_action('after_setup_theme', array($this, 'check_for_upgrade'), 5);
@@ -532,7 +535,11 @@ class SimpleHistory {
532
  /**
533
  * Setup variables and things
534
  */
535
- public function setupVariables() {
 
 
 
 
536
 
537
  // Capability required to view history = for who will the History page be added
538
  $this->view_history_capability = "edit_pages";
@@ -586,30 +593,50 @@ class SimpleHistory {
586
 
587
  }
588
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
  /**
590
  * Load built in loggers from all files in /loggers
591
  * and instantiates them
592
  */
593
- public function loadLoggers() {
594
 
595
  $loggersDir = SIMPLE_HISTORY_PATH . "loggers/";
596
 
597
- /**
598
- * Filter the directory to load loggers from
599
- *
600
- * @since 2.0
601
- *
602
- * @param string $loggersDir Full directory path
603
- */
604
- $loggersDir = apply_filters("simple_history/loggers_dir", $loggersDir);
605
-
606
- $loggersFiles = glob($loggersDir . "*.php");
607
-
608
- // SimpleLogger.php must be loaded first since the other loggers extend it
 
 
 
 
 
609
  include_once $loggersDir . "SimpleLogger.php";
610
 
611
  /**
612
- * Filter the array with absolute paths to files as returned by glob function.
 
613
  * Each file will be loaded and will be assumed to be a logger with a classname
614
  * the same as the filename.
615
  *
@@ -619,8 +646,10 @@ class SimpleHistory {
619
  */
620
  $loggersFiles = apply_filters("simple_history/loggers_files", $loggersFiles);
621
 
 
 
622
  $arrLoggersToInstantiate = array();
623
-
624
  foreach ( $loggersFiles as $oneLoggerFile ) {
625
 
626
  $load_logger = true;
@@ -633,7 +662,7 @@ class SimpleHistory {
633
  * @since 2.0.22
634
  *
635
  * @param bool if to load the logger. return false to not load it.
636
- * @param srting slug of logger
637
  */
638
  $load_logger = apply_filters("simple_history/logger/load_logger", $load_logger, $basename_no_suffix );
639
 
@@ -647,9 +676,29 @@ class SimpleHistory {
647
 
648
  }
649
 
 
 
 
 
 
 
 
 
 
 
 
 
 
650
  /**
651
  * Filter the array with names of loggers to instantiate.
652
  *
 
 
 
 
 
 
 
653
  * @since 2.0
654
  *
655
  * @param array $arrLoggersToInstantiate Array with class names
@@ -716,7 +765,7 @@ class SimpleHistory {
716
  * Load built in dropins from all files in /dropins
717
  * and instantiates them
718
  */
719
- public function loadDropins() {
720
 
721
  $dropinsDir = SIMPLE_HISTORY_PATH . "dropins/";
722
 
@@ -2462,7 +2511,7 @@ class SimpleHistory {
2462
  * @param string $alt Alternative text to use in the avatar image tag.
2463
  * Default empty.
2464
  */
2465
- $avatar = apply_filters( 'get_avatar', $avatar, $id_or_email, $size, $default, $alt );
2466
 
2467
  return $avatar;
2468
 
10
  const NAME = "Simple History";
11
 
12
  // Dont use this any more! Will be removed in future versions. Use global SIMPLE_HISTORY_VERSION instead.
13
+ const VERSION = "2.1";
14
 
15
  /**
16
  * For singleton
27
  */
28
  private $view_settings_capability;
29
 
30
+ /**
31
+ * Array with external loggers to load
32
+ */
33
+ private $externalLoggers;
34
+
35
  /**
36
  * Array with all instantiated loggers
37
  */
42
  */
43
  private $instantiatedDropins;
44
 
 
 
45
  /**
46
  * Bool if gettext filter function should be active
47
  * Should only be active during the load of a logger
85
  */
86
  do_action("simple_history/before_init", $this);
87
 
88
+ $this->setup_variables();
89
 
90
  // Actions and filters, ordered by order specified in codex: http://codex.wordpress.org/Plugin_API/Action_Reference
91
  add_action('after_setup_theme', array($this, 'load_plugin_textdomain'));
92
  add_action('after_setup_theme', array($this, 'add_default_settings_tabs'));
93
+ add_action('after_setup_theme', array($this, 'load_loggers'));
94
+ add_action('after_setup_theme', array($this, 'load_dropins'));
95
 
96
  // Run before loading of loggers and before menu items are added
97
  add_action('after_setup_theme', array($this, 'check_for_upgrade'), 5);
535
  /**
536
  * Setup variables and things
537
  */
538
+ public function setup_variables() {
539
+
540
+ $this->externalLoggers = array();
541
+ $this->instantiatedLoggers = array();
542
+ $this->instantiatedDropins = array();
543
 
544
  // Capability required to view history = for who will the History page be added
545
  $this->view_history_capability = "edit_pages";
593
 
594
  }
595
 
596
+ /**
597
+ * Register an external logger so Simple History knows about it.
598
+ * Does not load the logger, so file with logger must be loaded already.
599
+ *
600
+ * See example-logger.php for an example on how to use this.
601
+ *
602
+ * @since 2.1
603
+ */
604
+ function register_logger($loggerClassName) {
605
+
606
+ $this->externalLoggers[] = $loggerClassName;
607
+
608
+ }
609
+
610
  /**
611
  * Load built in loggers from all files in /loggers
612
  * and instantiates them
613
  */
614
+ public function load_loggers() {
615
 
616
  $loggersDir = SIMPLE_HISTORY_PATH . "loggers/";
617
 
618
+ $loggersFiles = array(
619
+ $loggersDir . "SimpleCommentsLogger.php",
620
+ $loggersDir . "SimpleCoreUpdatesLogger.php",
621
+ $loggersDir . "SimpleExportLogger.php",
622
+ $loggersDir . "SimpleLegacyLogger.php",
623
+ $loggersDir . "SimpleLogger.php",
624
+ $loggersDir . "SimpleMediaLogger.php",
625
+ $loggersDir . "SimpleMenuLogger.php",
626
+ $loggersDir . "SimpleOptionsLogger.php",
627
+ $loggersDir . "SimplePluginLogger.php",
628
+ $loggersDir . "SimplePostLogger.php",
629
+ $loggersDir . "SimpleThemeLogger.php",
630
+ $loggersDir . "SimpleUserLogger.php",
631
+ );
632
+
633
+ // SimpleLogger.php must be loaded first and always since the other loggers extend it
634
+ // Include it manually so risk of anyone using filters or similar disables it
635
  include_once $loggersDir . "SimpleLogger.php";
636
 
637
  /**
638
+ * Filter the array with absolute paths to logger files to be loaded.
639
+ *
640
  * Each file will be loaded and will be assumed to be a logger with a classname
641
  * the same as the filename.
642
  *
646
  */
647
  $loggersFiles = apply_filters("simple_history/loggers_files", $loggersFiles);
648
 
649
+ // Array with slug of loggers to instantiate
650
+ // Slug of logger must also be the name of the logger class
651
  $arrLoggersToInstantiate = array();
652
+
653
  foreach ( $loggersFiles as $oneLoggerFile ) {
654
 
655
  $load_logger = true;
662
  * @since 2.0.22
663
  *
664
  * @param bool if to load the logger. return false to not load it.
665
+ * @param string slug of logger
666
  */
667
  $load_logger = apply_filters("simple_history/logger/load_logger", $load_logger, $basename_no_suffix );
668
 
676
 
677
  }
678
 
679
+ /**
680
+ * Action that plugins should use to add their custom loggers.
681
+ * See register_logger() for more info.
682
+ *
683
+ * @since 2.1
684
+ *
685
+ * @param array $arrLoggersToInstantiate Array with class names
686
+ */
687
+
688
+ do_action("simple_history/add_custom_logger", $this);
689
+
690
+ $arrLoggersToInstantiate = array_merge($arrLoggersToInstantiate, $this->externalLoggers);
691
+
692
  /**
693
  * Filter the array with names of loggers to instantiate.
694
  *
695
+ * Array
696
+ * (
697
+ * [0] => SimpleCommentsLogger
698
+ * [1] => SimpleCoreUpdatesLogger
699
+ * ...
700
+ * )
701
+ *
702
  * @since 2.0
703
  *
704
  * @param array $arrLoggersToInstantiate Array with class names
765
  * Load built in dropins from all files in /dropins
766
  * and instantiates them
767
  */
768
+ public function load_dropins() {
769
 
770
  $dropinsDir = SIMPLE_HISTORY_PATH . "dropins/";
771
 
2511
  * @param string $alt Alternative text to use in the avatar image tag.
2512
  * Default empty.
2513
  */
2514
+ $avatar = apply_filters( 'get_avatar', $avatar, $email, $size, $default, $alt );
2515
 
2516
  return $avatar;
2517
 
inc/SimpleHistoryLogQuery.php CHANGED
@@ -4,9 +4,9 @@ defined( 'ABSPATH' ) or die();
4
 
5
  /**
6
  * Queries the Simple History Log
7
- */
8
  class SimpleHistoryLogQuery {
9
-
10
  public function __construct() {
11
 
12
  /*
@@ -20,7 +20,7 @@ class SimpleHistoryLogQuery {
20
  }
21
 
22
  public function query($args) {
23
-
24
  $defaults = array(
25
 
26
  // overview | occasions
@@ -44,7 +44,7 @@ class SimpleHistoryLogQuery {
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,
@@ -56,10 +56,10 @@ class SimpleHistoryLogQuery {
56
 
57
  // search
58
  "search" => null,
59
-
60
  // log levels to include. comma separated or as array. defaults to all.
61
  "loglevels" => null,
62
-
63
  // loggers to include. comma separated. defaults to all the user can read
64
  "loggers" => null,
65
 
@@ -73,6 +73,9 @@ class SimpleHistoryLogQuery {
73
  // occasionsCountMaxReturn
74
  // occasionsID
75
 
 
 
 
76
  );
77
 
78
  $args = wp_parse_args( $args, $defaults );
@@ -81,7 +84,7 @@ class SimpleHistoryLogQuery {
81
  $cache_key = "SimpleHistoryLogQuery_" . md5(serialize( $args )) . "_get_" . md5(serialize( $_GET )) . "_userid_" . get_current_user_id();
82
  $cache_group = "simple-history-" . SimpleHistory::get_cache_incrementor();
83
  $arr_return = wp_cache_get($cache_key, $cache_group);
84
-
85
  if ( false !== $arr_return ) {
86
  return $arr_return;
87
  }
@@ -120,7 +123,8 @@ class SimpleHistoryLogQuery {
120
  // 4 = where for inner calc sql query thingie
121
  // 5 = db name contexts
122
  $sql_tmpl = '
123
- SELECT
 
124
  SQL_CALC_FOUND_ROWS
125
  t.id,
126
  t.logger,
@@ -135,29 +139,29 @@ class SimpleHistoryLogQuery {
135
  t.repeated,
136
  t.occasionsIDType,
137
  c1.value AS context_message_key
138
- FROM
139
  (
140
- SELECT
141
- id,
142
- logger,
143
- level,
144
- message,
145
  type,
146
  initiator,
147
- occasionsID,
148
- date,
149
  IF(@a=occasionsID,@counter:=@counter+1,@counter:=1) AS rep,
150
  IF(@counter=1,@groupby:=@groupby+1,@groupby) AS repeated,
151
- @a:=occasionsID occasionsIDType
152
  FROM %3$s
153
 
154
  # Add where here
155
- WHERE 1 = 1
156
  %4$s
157
 
158
  ORDER BY id DESC
159
  ) AS t
160
-
161
  LEFT OUTER JOIN %5$s AS c1 ON c1.history_id = t.id AND c1.key = "_message_key"
162
 
163
  WHERE %1$s
@@ -168,7 +172,7 @@ class SimpleHistoryLogQuery {
168
 
169
  $sh = SimpleHistory::get_instance();
170
 
171
- // Only include loggers that the current user can view
172
  $sql_loggers_user_can_view = $sh->getLoggersThatUserCanRead(get_current_user_id(), "sql");
173
  $inner_where = " AND logger IN {$sql_loggers_user_can_view}";
174
 
@@ -209,7 +213,7 @@ class SimpleHistoryLogQuery {
209
  // [occasionsCount] =&gt; 18
210
 
211
  }
212
-
213
  // Determine limit
214
  // Both posts_per_page and paged must be set
215
  $is_limit_query = ( is_numeric( $args["posts_per_page"] ) && $args["posts_per_page"] > 0 );
@@ -229,7 +233,7 @@ class SimpleHistoryLogQuery {
229
  // If max_id_first_page is then then only include rows
230
  // with id equal to or earlier
231
  if ( isset($args["max_id_first_page"]) && is_numeric($args["max_id_first_page"]) ) {
232
-
233
  $max_id_first_page = (int) $args["max_id_first_page"];
234
  $where .= sprintf(
235
  ' AND t.id <= %1$d',
@@ -239,7 +243,7 @@ class SimpleHistoryLogQuery {
239
  }
240
 
241
  if ( isset($args["since_id"]) && is_numeric($args["since_id"]) ) {
242
-
243
  $since_id = (int) $args["since_id"];
244
  /*
245
  $where .= sprintf(
@@ -255,9 +259,9 @@ class SimpleHistoryLogQuery {
255
 
256
  }
257
 
258
- // Append date where
259
  if ( ! empty( $args["date_from"] ) ) {
260
-
261
  // date_to=2014-08-01
262
  // if date is not numeric assume Y-m-d H:i-format
263
  $date_from = $args["date_from"];
@@ -293,11 +297,11 @@ class SimpleHistoryLogQuery {
293
 
294
  $sql_months = '
295
  # sql_months
296
- AND (
297
  ';
298
 
299
  foreach ( $arr_months as $one_month ) {
300
-
301
  // beginning of month
302
  // $ php -r ' echo date("Y-m-d H:i", strtotime("2014-08") ) . "\n";
303
  // >> 2014-08-01 00:00
@@ -307,7 +311,7 @@ class SimpleHistoryLogQuery {
307
  // $ php -r ' echo date("Y-m-d H:i", strtotime("2014-08 + 1 month") ) . "\n";'
308
  // >> 2014-09-01 00:00
309
  $date_month_end = strtotime( "{$one_month} + 1 month" );
310
-
311
  $sql_months .= sprintf(
312
  '
313
  (
@@ -315,8 +319,8 @@ class SimpleHistoryLogQuery {
315
  AND UNIX_TIMESTAMP(date) <= %2$d
316
  )
317
 
318
- OR
319
- ',
320
  $date_month_beginning, // 1
321
  $date_month_end // 2
322
 
@@ -339,22 +343,22 @@ class SimpleHistoryLogQuery {
339
 
340
  // search
341
  if ( ! empty( $args["search"] ) ) {
342
-
343
  $search_words = $args["search"];
344
  $str_search_conditions = "";
345
  $arr_search_words = preg_split("/[\s,]+/", $search_words);
346
-
347
  // create array of all searched words
348
  // split both spaces and commas and such
349
  $arr_sql_like_cols = array("message", "logger", "level");
350
 
351
  foreach ($arr_sql_like_cols as $one_col) {
352
-
353
  $str_sql_search_words = "";
354
 
355
 
356
  foreach ($arr_search_words as $one_search_word) {
357
-
358
  if ( method_exists($wpdb, "esc_like") ) {
359
  $str_like = esc_sql( $wpdb->esc_like( $one_search_word ) );
360
  } else {
@@ -370,7 +374,7 @@ class SimpleHistoryLogQuery {
370
  }
371
 
372
  $str_sql_search_words = ltrim($str_sql_search_words, ' AND ');
373
-
374
  $str_search_conditions .= "\n" . sprintf(
375
  ' OR ( %1$s ) ',
376
  $str_sql_search_words
@@ -411,7 +415,7 @@ class SimpleHistoryLogQuery {
411
  // comma separated
412
  // 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
413
  if ( ! empty( $args["loglevels"] ) ) {
414
-
415
  $sql_loglevels = "";
416
 
417
  if ( is_array( $args["loglevels"] ) ) {
@@ -419,7 +423,7 @@ class SimpleHistoryLogQuery {
419
  } else {
420
  $arr_loglevels = explode(",", $args["loglevels"]);
421
  }
422
-
423
  foreach ( $arr_loglevels as $one_loglevel ) {
424
  $sql_loglevels .= sprintf(' "%s", ', esc_sql( $one_loglevel ));
425
  }
@@ -430,12 +434,12 @@ class SimpleHistoryLogQuery {
430
  }
431
 
432
  $inner_where .= $sql_loglevels;
433
-
434
  }
435
 
436
  // messages
437
  if ( ! empty( $args["messages"] ) ) {
438
-
439
  #print_r($args["messages"]);exit;
440
  /*
441
  Array
@@ -444,7 +448,7 @@ class SimpleHistoryLogQuery {
444
  [1] => SimpleCommentsLogger:SimpleCommentsLogger:comment_status_spam,SimpleCommentsLogger:trackback_status_spam,SimpleCommentsLogger:pingback_status_spam
445
  )
446
  */
447
-
448
  // Array with loggers and messages
449
  $arr_loggers_and_messages = array();
450
 
@@ -492,7 +496,7 @@ class SimpleHistoryLogQuery {
492
  }
493
  // remove last or
494
  $sql_messages_where = preg_replace('/OR $/', "", $sql_messages_where);
495
-
496
  $sql_messages_where .= "\n )";
497
  #echo $sql_messages_where;exit;
498
  $where .= $sql_messages_where;
@@ -548,7 +552,7 @@ class SimpleHistoryLogQuery {
548
  // comma separated
549
  // 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
550
  if ( ! empty( $args["loggers"] ) ) {
551
-
552
  $sql_loggers = "";
553
  if ( is_array( $args["loggers"] ) ) {
554
  $arr_loggers = $args["loggers"];
@@ -566,7 +570,7 @@ class SimpleHistoryLogQuery {
566
  [1] => SimpleUserLogger:user_deleted
567
  )
568
  */
569
-
570
  foreach ( $arr_loggers as $one_logger ) {
571
  $sql_loggers .= sprintf(' "%s", ', esc_sql( $one_logger ));
572
  }
@@ -577,12 +581,12 @@ class SimpleHistoryLogQuery {
577
  }
578
 
579
  $inner_where .= $sql_loggers;
580
-
581
  }
582
 
583
  // user, a single userID
584
  if ( ! empty( $args["user"] ) && is_numeric( $args["user"] ) ) {
585
-
586
  $userID = (int) $args["user"];
587
  $sql_user = sprintf(
588
  '
@@ -635,13 +639,13 @@ class SimpleHistoryLogQuery {
635
 
636
  $sql = sprintf(
637
  $sql_tmpl, // sprintf template
638
- $where, // 1
639
  $limit, // 2
640
  $table_name, // 3
641
  $inner_where,// 4
642
  $table_name_contexts // 5
643
  );
644
-
645
 
646
  /**
647
  * Filter the final sql query
@@ -663,6 +667,11 @@ class SimpleHistoryLogQuery {
663
 
664
  }
665
 
 
 
 
 
 
666
  $log_rows = $wpdb->get_results($sql, OBJECT_K);
667
  $num_rows = sizeof($log_rows);
668
 
@@ -670,7 +679,7 @@ class SimpleHistoryLogQuery {
670
  // This is the number of rows with occasions taken into consideration
671
  $sql_found_rows = 'SELECT FOUND_ROWS()';
672
  $total_found_rows = (int) $wpdb->get_var( $sql_found_rows );
673
-
674
  // Add context
675
  $post_ids = wp_list_pluck( $log_rows, "id" );
676
 
@@ -710,13 +719,13 @@ class SimpleHistoryLogQuery {
710
  $min_id = $last_row->id;
711
 
712
  } else {
713
-
714
  // Last row did have occaions, so fetch all occasions, and find id of last one
715
  $db_table = $wpdb->prefix . SimpleHistory::DBTABLE;
716
  $sql = sprintf(
717
  '
718
  SELECT id, date, occasionsID
719
- FROM %1$s
720
  WHERE id <= %2$s
721
  ORDER BY id DESC
722
  LIMIT %3$s
@@ -725,14 +734,14 @@ class SimpleHistoryLogQuery {
725
  $last_row->id,
726
  $last_row_occasions_count + 1
727
  );
728
-
729
  $results = $wpdb->get_results( $sql );
730
 
731
  // the last occasion has the id we consider last in this paged result
732
  $min_id = end($results)->id;
733
 
734
  }
735
-
736
  }
737
 
738
  // Calc pages
@@ -764,8 +773,7 @@ class SimpleHistoryLogQuery {
764
  wp_cache_set($cache_key, $arr_return, $cache_group);
765
 
766
  return $arr_return;
767
-
768
  } // query
769
 
770
  } // class
771
-
4
 
5
  /**
6
  * Queries the Simple History Log
7
+ */
8
  class SimpleHistoryLogQuery {
9
+
10
  public function __construct() {
11
 
12
  /*
20
  }
21
 
22
  public function query($args) {
23
+
24
  $defaults = array(
25
 
26
  // overview | occasions
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,
56
 
57
  // search
58
  "search" => null,
59
+
60
  // log levels to include. comma separated or as array. defaults to all.
61
  "loglevels" => null,
62
+
63
  // loggers to include. comma separated. defaults to all the user can read
64
  "loggers" => null,
65
 
73
  // occasionsCountMaxReturn
74
  // occasionsID
75
 
76
+ // If rows should be returned, or the actualy sql query used
77
+ "returnQuery" => false
78
+
79
  );
80
 
81
  $args = wp_parse_args( $args, $defaults );
84
  $cache_key = "SimpleHistoryLogQuery_" . md5(serialize( $args )) . "_get_" . md5(serialize( $_GET )) . "_userid_" . get_current_user_id();
85
  $cache_group = "simple-history-" . SimpleHistory::get_cache_incrementor();
86
  $arr_return = wp_cache_get($cache_key, $cache_group);
87
+
88
  if ( false !== $arr_return ) {
89
  return $arr_return;
90
  }
123
  // 4 = where for inner calc sql query thingie
124
  // 5 = db name contexts
125
  $sql_tmpl = '
126
+ /*NO_SELECT_FOUND_ROWS*/
127
+ SELECT
128
  SQL_CALC_FOUND_ROWS
129
  t.id,
130
  t.logger,
139
  t.repeated,
140
  t.occasionsIDType,
141
  c1.value AS context_message_key
142
+ FROM
143
  (
144
+ SELECT
145
+ id,
146
+ logger,
147
+ level,
148
+ message,
149
  type,
150
  initiator,
151
+ occasionsID,
152
+ date,
153
  IF(@a=occasionsID,@counter:=@counter+1,@counter:=1) AS rep,
154
  IF(@counter=1,@groupby:=@groupby+1,@groupby) AS repeated,
155
+ @a:=occasionsID occasionsIDType
156
  FROM %3$s
157
 
158
  # Add where here
159
+ WHERE 1 = 1
160
  %4$s
161
 
162
  ORDER BY id DESC
163
  ) AS t
164
+
165
  LEFT OUTER JOIN %5$s AS c1 ON c1.history_id = t.id AND c1.key = "_message_key"
166
 
167
  WHERE %1$s
172
 
173
  $sh = SimpleHistory::get_instance();
174
 
175
+ // Only include loggers that the current user can view
176
  $sql_loggers_user_can_view = $sh->getLoggersThatUserCanRead(get_current_user_id(), "sql");
177
  $inner_where = " AND logger IN {$sql_loggers_user_can_view}";
178
 
213
  // [occasionsCount] =&gt; 18
214
 
215
  }
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 );
233
  // If max_id_first_page is then then only include rows
234
  // with id equal to or earlier
235
  if ( isset($args["max_id_first_page"]) && is_numeric($args["max_id_first_page"]) ) {
236
+
237
  $max_id_first_page = (int) $args["max_id_first_page"];
238
  $where .= sprintf(
239
  ' AND t.id <= %1$d',
243
  }
244
 
245
  if ( isset($args["since_id"]) && is_numeric($args["since_id"]) ) {
246
+
247
  $since_id = (int) $args["since_id"];
248
  /*
249
  $where .= sprintf(
259
 
260
  }
261
 
262
+ // Append date where
263
  if ( ! empty( $args["date_from"] ) ) {
264
+
265
  // date_to=2014-08-01
266
  // if date is not numeric assume Y-m-d H:i-format
267
  $date_from = $args["date_from"];
297
 
298
  $sql_months = '
299
  # sql_months
300
+ AND (
301
  ';
302
 
303
  foreach ( $arr_months as $one_month ) {
304
+
305
  // beginning of month
306
  // $ php -r ' echo date("Y-m-d H:i", strtotime("2014-08") ) . "\n";
307
  // >> 2014-08-01 00:00
311
  // $ php -r ' echo date("Y-m-d H:i", strtotime("2014-08 + 1 month") ) . "\n";'
312
  // >> 2014-09-01 00:00
313
  $date_month_end = strtotime( "{$one_month} + 1 month" );
314
+
315
  $sql_months .= sprintf(
316
  '
317
  (
319
  AND UNIX_TIMESTAMP(date) <= %2$d
320
  )
321
 
322
+ OR
323
+ ',
324
  $date_month_beginning, // 1
325
  $date_month_end // 2
326
 
343
 
344
  // search
345
  if ( ! empty( $args["search"] ) ) {
346
+
347
  $search_words = $args["search"];
348
  $str_search_conditions = "";
349
  $arr_search_words = preg_split("/[\s,]+/", $search_words);
350
+
351
  // create array of all searched words
352
  // split both spaces and commas and such
353
  $arr_sql_like_cols = array("message", "logger", "level");
354
 
355
  foreach ($arr_sql_like_cols as $one_col) {
356
+
357
  $str_sql_search_words = "";
358
 
359
 
360
  foreach ($arr_search_words as $one_search_word) {
361
+
362
  if ( method_exists($wpdb, "esc_like") ) {
363
  $str_like = esc_sql( $wpdb->esc_like( $one_search_word ) );
364
  } else {
374
  }
375
 
376
  $str_sql_search_words = ltrim($str_sql_search_words, ' AND ');
377
+
378
  $str_search_conditions .= "\n" . sprintf(
379
  ' OR ( %1$s ) ',
380
  $str_sql_search_words
415
  // comma separated
416
  // 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
417
  if ( ! empty( $args["loglevels"] ) ) {
418
+
419
  $sql_loglevels = "";
420
 
421
  if ( is_array( $args["loglevels"] ) ) {
423
  } else {
424
  $arr_loglevels = explode(",", $args["loglevels"]);
425
  }
426
+
427
  foreach ( $arr_loglevels as $one_loglevel ) {
428
  $sql_loglevels .= sprintf(' "%s", ', esc_sql( $one_loglevel ));
429
  }
434
  }
435
 
436
  $inner_where .= $sql_loglevels;
437
+
438
  }
439
 
440
  // messages
441
  if ( ! empty( $args["messages"] ) ) {
442
+
443
  #print_r($args["messages"]);exit;
444
  /*
445
  Array
448
  [1] => SimpleCommentsLogger:SimpleCommentsLogger:comment_status_spam,SimpleCommentsLogger:trackback_status_spam,SimpleCommentsLogger:pingback_status_spam
449
  )
450
  */
451
+
452
  // Array with loggers and messages
453
  $arr_loggers_and_messages = array();
454
 
496
  }
497
  // remove last or
498
  $sql_messages_where = preg_replace('/OR $/', "", $sql_messages_where);
499
+
500
  $sql_messages_where .= "\n )";
501
  #echo $sql_messages_where;exit;
502
  $where .= $sql_messages_where;
552
  // comma separated
553
  // 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
554
  if ( ! empty( $args["loggers"] ) ) {
555
+
556
  $sql_loggers = "";
557
  if ( is_array( $args["loggers"] ) ) {
558
  $arr_loggers = $args["loggers"];
570
  [1] => SimpleUserLogger:user_deleted
571
  )
572
  */
573
+
574
  foreach ( $arr_loggers as $one_logger ) {
575
  $sql_loggers .= sprintf(' "%s", ', esc_sql( $one_logger ));
576
  }
581
  }
582
 
583
  $inner_where .= $sql_loggers;
584
+
585
  }
586
 
587
  // user, a single userID
588
  if ( ! empty( $args["user"] ) && is_numeric( $args["user"] ) ) {
589
+
590
  $userID = (int) $args["user"];
591
  $sql_user = sprintf(
592
  '
639
 
640
  $sql = sprintf(
641
  $sql_tmpl, // sprintf template
642
+ $where, // 1
643
  $limit, // 2
644
  $table_name, // 3
645
  $inner_where,// 4
646
  $table_name_contexts // 5
647
  );
648
+
649
 
650
  /**
651
  * Filter the final sql query
667
 
668
  }
669
 
670
+ // Only return sql query
671
+ if ( $args["returnQuery"] ) {
672
+ return $sql;
673
+ }
674
+
675
  $log_rows = $wpdb->get_results($sql, OBJECT_K);
676
  $num_rows = sizeof($log_rows);
677
 
679
  // This is the number of rows with occasions taken into consideration
680
  $sql_found_rows = 'SELECT FOUND_ROWS()';
681
  $total_found_rows = (int) $wpdb->get_var( $sql_found_rows );
682
+
683
  // Add context
684
  $post_ids = wp_list_pluck( $log_rows, "id" );
685
 
719
  $min_id = $last_row->id;
720
 
721
  } else {
722
+
723
  // Last row did have occaions, so fetch all occasions, and find id of last one
724
  $db_table = $wpdb->prefix . SimpleHistory::DBTABLE;
725
  $sql = sprintf(
726
  '
727
  SELECT id, date, occasionsID
728
+ FROM %1$s
729
  WHERE id <= %2$s
730
  ORDER BY id DESC
731
  LIMIT %3$s
734
  $last_row->id,
735
  $last_row_occasions_count + 1
736
  );
737
+
738
  $results = $wpdb->get_results( $sql );
739
 
740
  // the last occasion has the id we consider last in this paged result
741
  $min_id = end($results)->id;
742
 
743
  }
744
+
745
  }
746
 
747
  // Calc pages
773
  wp_cache_set($cache_key, $arr_return, $cache_group);
774
 
775
  return $arr_return;
776
+
777
  } // query
778
 
779
  } // class
 
index.php CHANGED
@@ -2,8 +2,10 @@
2
  /*
3
  Plugin Name: Simple History
4
  Plugin URI: http://simple-history.com
 
 
5
  Description: Plugin that logs various things that occur in WordPress and then presents those events in a very nice GUI.
6
- Version: 2.0.30
7
  Author: Pär Thernström
8
  Author URI: http://simple-history.com/
9
  License: GPL2
@@ -42,7 +44,7 @@ if ( version_compare( phpversion(), "5.3", ">=") ) {
42
  */
43
  // register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
44
 
45
- define( 'SIMPLE_HISTORY_VERSION', '2.0.30' );
46
 
47
  define( 'SIMPLE_HISTORY_FILE', __FILE__ );
48
  define( 'SIMPLE_HISTORY_PATH', plugin_dir_path( SIMPLE_HISTORY_FILE ) );
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.1
9
  Author: Pär Thernström
10
  Author URI: http://simple-history.com/
11
  License: GPL2
44
  */
45
  // register_activation_hook( trailingslashit(WP_PLUGIN_DIR) . trailingslashit( plugin_basename(__DIR__) ) . "index.php" , array("SimpleHistory", "on_plugin_activate" ) );
46
 
47
+ define( 'SIMPLE_HISTORY_VERSION', '2.1' );
48
 
49
  define( 'SIMPLE_HISTORY_FILE', __FILE__ );
50
  define( 'SIMPLE_HISTORY_PATH', plugin_dir_path( SIMPLE_HISTORY_FILE ) );
loggers/SimpleLogger.php CHANGED
@@ -102,7 +102,13 @@ class SimpleLogger {
102
 
103
  $arr_info = $this->getInfo();
104
 
105
- return $arr_info["capability"];
 
 
 
 
 
 
106
 
107
  }
108
 
@@ -168,15 +174,23 @@ class SimpleLogger {
168
 
169
  $user_display_name = $user->display_name;
170
 
171
- // If user who logged this is the currently logged in user
172
- // skip name and email and use just "You"
173
- if ( $is_current_user ) {
 
 
 
 
 
 
 
174
 
175
  $tmpl_initiator_html = '
176
  <a href="%6$s" class="SimpleHistoryLogitem__headerUserProfileLink">
177
  <strong class="SimpleHistoryLogitem__inlineDivided">%5$s</strong>
178
  </a>
179
- ' ;
 
180
  } else {
181
 
182
  $tmpl_initiator_html = '
@@ -274,14 +288,14 @@ class SimpleLogger {
274
 
275
  // single ip address
276
  $iplookup_link = sprintf('https://ipinfo.io/%1$s', esc_attr($context["_server_remote_addr"]));
277
-
278
  $initiator_html .= sprintf(
279
  __('Anonymous user from %1$s', "simple-history"),
280
  "<a target='_blank' href={$iplookup_link} class='SimpleHistoryLogitem__anonUserWithIp__theIp'>" . esc_html($context["_server_remote_addr"]) . "</a>"
281
  );
282
 
283
  #} // multiple ip
284
-
285
  $initiator_html .= "</strong> ";
286
 
287
  // $initiator_html .= "<strong>" . __("<br><br>Unknown user from {$context["_server_remote_addr"]}") . "</strong>";
@@ -294,7 +308,7 @@ class SimpleLogger {
294
  break;
295
 
296
  case "other":
297
- $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided'>Other</strong>";
298
  break;
299
 
300
  // no initiator
@@ -594,8 +608,8 @@ class SimpleLogger {
594
  * return $this->logByMessageKey(SimpleLoggerLogLevels::EMERGENCY, $message, $context);
595
  */
596
  private function logByMessageKey($SimpleLoggerLogLevelsLevel, $messageKey, $context) {
597
-
598
- // When logging by message then the key must exist
599
  if ( ! isset( $this->messages[ $messageKey ]["untranslated_text"] ) ) {
600
  return;
601
  }
@@ -613,7 +627,7 @@ class SimpleLogger {
613
  * @return bool false to abort logging
614
  */
615
  $doLog = apply_filters("simple_history/simple_logger/log_message_key", true, $this->slug, $messageKey, $SimpleLoggerLogLevelsLevel, $context);
616
-
617
  if ( ! $doLog ) {
618
  return;
619
  }
@@ -839,16 +853,16 @@ class SimpleLogger {
839
 
840
  // Check if $message is a translated message, and if so then fetch original
841
  $sh_latest_translations = $this->simpleHistory->gettextLatestTranslations;
842
-
843
  if ( ! empty( $sh_latest_translations ) ) {
844
 
845
  if ( isset( $sh_latest_translations[ $message ] ) ) {
846
-
847
  // Translation of this phrase was found, so use original phrase instead of translated one
848
 
849
  // Store textdomain since it's required to translate
850
  $context["_gettext_domain"] = $sh_latest_translations[$message]["domain"];
851
-
852
  // These are good to keep when debugging
853
  // $context["_gettext_org_message"] = $sh_latest_translations[$message]["text"];
854
  // $context["_gettext_translated_message"] = $sh_latest_translations[$message]["translation"];
@@ -988,12 +1002,12 @@ class SimpleLogger {
988
 
989
  // If running as CLI and WP_CLI_PHP_USED is set then it is WP CLI that is doing it
990
  // How to log this? Is this a user, is it WordPress, or what?
991
- // I'm thinking:
992
  // - it is a user that is manually doing this, on purpose, with intent, so not auto wordpress
993
  // - it is a specific user, but we don't know who
994
  // - sounds like a special case, set initiator to wp_cli
995
  if ( isset( $_SERVER["WP_CLI_PHP_USED"] ) && "cli" == php_sapi_name() ) {
996
-
997
  $data["initiator"] = SimpleLoggerLogInitiators::WP_CLI;
998
 
999
  }
@@ -1128,7 +1142,7 @@ class SimpleLogger {
1128
  * @param array $data Array with data used for parent row.
1129
  */
1130
  $context = apply_filters("simple_history/log_insert_context", $context, $data);
1131
-
1132
  // Insert all context values into db
1133
  foreach ($context as $key => $value) {
1134
 
@@ -1161,7 +1175,7 @@ class SimpleLogger {
1161
  public function get_ip_number_header_keys() {
1162
 
1163
  $arr = array(
1164
- 'HTTP_CLIENT_IP',
1165
  'HTTP_X_FORWARDED_FOR',
1166
  'HTTP_X_FORWARDED',
1167
  'HTTP_X_CLUSTER_CLIENT_IP',
@@ -1185,7 +1199,7 @@ class SimpleLogger {
1185
  $context = $row->context;
1186
 
1187
  foreach ( $ip_keys as $one_ip_header_key ) {
1188
-
1189
  $one_ip_header_key_lower = strtolower($one_ip_header_key);
1190
 
1191
  foreach ( $context as $context_key => $context_val ) {
@@ -1200,7 +1214,7 @@ class SimpleLogger {
1200
  } // foreach context key for this ip header key
1201
 
1202
  } // foreach ip header key
1203
-
1204
  return $arr_found_additional_ip_headers;
1205
 
1206
  }
102
 
103
  $arr_info = $this->getInfo();
104
 
105
+ $capability = "manage_options";
106
+
107
+ if ( ! empty( $arr_info["capability"] ) ) {
108
+ $capability = $arr_info["capability"];
109
+ }
110
+
111
+ return $capability;
112
 
113
  }
114
 
174
 
175
  $user_display_name = $user->display_name;
176
 
177
+ /*
178
+ * If user who logged this is the currently logged in user
179
+ * skip name and email and use just "You"
180
+ *
181
+ * @param bool If you should be used
182
+ * @since 2.1
183
+ */
184
+ $use_you = apply_filters("simple_history/header_initiator_use_you", true);
185
+
186
+ if ( $use_you && $is_current_user ) {
187
 
188
  $tmpl_initiator_html = '
189
  <a href="%6$s" class="SimpleHistoryLogitem__headerUserProfileLink">
190
  <strong class="SimpleHistoryLogitem__inlineDivided">%5$s</strong>
191
  </a>
192
+ ';
193
+
194
  } else {
195
 
196
  $tmpl_initiator_html = '
288
 
289
  // single ip address
290
  $iplookup_link = sprintf('https://ipinfo.io/%1$s', esc_attr($context["_server_remote_addr"]));
291
+
292
  $initiator_html .= sprintf(
293
  __('Anonymous user from %1$s', "simple-history"),
294
  "<a target='_blank' href={$iplookup_link} class='SimpleHistoryLogitem__anonUserWithIp__theIp'>" . esc_html($context["_server_remote_addr"]) . "</a>"
295
  );
296
 
297
  #} // multiple ip
298
+
299
  $initiator_html .= "</strong> ";
300
 
301
  // $initiator_html .= "<strong>" . __("<br><br>Unknown user from {$context["_server_remote_addr"]}") . "</strong>";
308
  break;
309
 
310
  case "other":
311
+ $initiator_html .= "<strong class='SimpleHistoryLogitem__inlineDivided'>" . _x("Other", "Event header output, when initiator is unknown", "simple-history") . "</strong>";
312
  break;
313
 
314
  // no initiator
608
  * return $this->logByMessageKey(SimpleLoggerLogLevels::EMERGENCY, $message, $context);
609
  */
610
  private function logByMessageKey($SimpleLoggerLogLevelsLevel, $messageKey, $context) {
611
+
612
+ // When logging by message then the key must exist
613
  if ( ! isset( $this->messages[ $messageKey ]["untranslated_text"] ) ) {
614
  return;
615
  }
627
  * @return bool false to abort logging
628
  */
629
  $doLog = apply_filters("simple_history/simple_logger/log_message_key", true, $this->slug, $messageKey, $SimpleLoggerLogLevelsLevel, $context);
630
+
631
  if ( ! $doLog ) {
632
  return;
633
  }
853
 
854
  // Check if $message is a translated message, and if so then fetch original
855
  $sh_latest_translations = $this->simpleHistory->gettextLatestTranslations;
856
+
857
  if ( ! empty( $sh_latest_translations ) ) {
858
 
859
  if ( isset( $sh_latest_translations[ $message ] ) ) {
860
+
861
  // Translation of this phrase was found, so use original phrase instead of translated one
862
 
863
  // Store textdomain since it's required to translate
864
  $context["_gettext_domain"] = $sh_latest_translations[$message]["domain"];
865
+
866
  // These are good to keep when debugging
867
  // $context["_gettext_org_message"] = $sh_latest_translations[$message]["text"];
868
  // $context["_gettext_translated_message"] = $sh_latest_translations[$message]["translation"];
1002
 
1003
  // If running as CLI and WP_CLI_PHP_USED is set then it is WP CLI that is doing it
1004
  // How to log this? Is this a user, is it WordPress, or what?
1005
+ // I'm thinking:
1006
  // - it is a user that is manually doing this, on purpose, with intent, so not auto wordpress
1007
  // - it is a specific user, but we don't know who
1008
  // - sounds like a special case, set initiator to wp_cli
1009
  if ( isset( $_SERVER["WP_CLI_PHP_USED"] ) && "cli" == php_sapi_name() ) {
1010
+
1011
  $data["initiator"] = SimpleLoggerLogInitiators::WP_CLI;
1012
 
1013
  }
1142
  * @param array $data Array with data used for parent row.
1143
  */
1144
  $context = apply_filters("simple_history/log_insert_context", $context, $data);
1145
+
1146
  // Insert all context values into db
1147
  foreach ($context as $key => $value) {
1148
 
1175
  public function get_ip_number_header_keys() {
1176
 
1177
  $arr = array(
1178
+ 'HTTP_CLIENT_IP',
1179
  'HTTP_X_FORWARDED_FOR',
1180
  'HTTP_X_FORWARDED',
1181
  'HTTP_X_CLUSTER_CLIENT_IP',
1199
  $context = $row->context;
1200
 
1201
  foreach ( $ip_keys as $one_ip_header_key ) {
1202
+
1203
  $one_ip_header_key_lower = strtolower($one_ip_header_key);
1204
 
1205
  foreach ( $context as $context_key => $context_val ) {
1214
  } // foreach context key for this ip header key
1215
 
1216
  } // foreach ip header key
1217
+
1218
  return $arr_found_additional_ip_headers;
1219
 
1220
  }
loggers/SimpleMediaLogger.php CHANGED
@@ -199,7 +199,7 @@ class SimpleMediaLogger extends SimpleLogger
199
 
200
  $context["full_image_width"] = $full_image_width;
201
  $context["full_image_height"] = $full_image_height;
202
- $context["attachment_thumb"] = sprintf('<div class="SimpleHistoryLogitemThumbnail"><img src="%1$s"></div>', $thumb_src[0] );
203
 
204
  }
205
 
@@ -340,7 +340,7 @@ class SimpleMediaLogger extends SimpleLogger
340
 
341
  /**
342
  * Modify RSS links so they go directly to the correct media in wp admin
343
- *
344
  * @since 2.0.23
345
  * @param string $link
346
  * @param array $row
@@ -354,7 +354,7 @@ class SimpleMediaLogger extends SimpleLogger
354
  if ( isset( $row->context["attachment_id"] ) ) {
355
 
356
  $permalink = add_query_arg(array("action" => "edit", "post" => $row->context["attachment_id"]), admin_url( "post.php" ) );
357
-
358
  if ( $permalink ) {
359
  $link = $permalink;
360
  }
199
 
200
  $context["full_image_width"] = $full_image_width;
201
  $context["full_image_height"] = $full_image_height;
202
+ $context["attachment_thumb"] = sprintf('<div class="SimpleHistoryLogitemThumbnail"><img src="%1$s" alt=""></div>', $thumb_src[0] );
203
 
204
  }
205
 
340
 
341
  /**
342
  * Modify RSS links so they go directly to the correct media in wp admin
343
+ *
344
  * @since 2.0.23
345
  * @param string $link
346
  * @param array $row
354
  if ( isset( $row->context["attachment_id"] ) ) {
355
 
356
  $permalink = add_query_arg(array("action" => "edit", "post" => $row->context["attachment_id"]), admin_url( "post.php" ) );
357
+
358
  if ( $permalink ) {
359
  $link = $permalink;
360
  }
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: eskapism
3
  Donate link: http://eskapism.se/sida/donate/
4
  Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, cms, dashboard, admin, syslog, feed, activity, stream
5
  Requires at least: 3.6.0
6
- Tested up to: 4.2.1
7
- Stable tag: 2.0.30
8
 
9
  View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
10
 
@@ -116,11 +116,22 @@ initiated by a specific user.
116
 
117
  ## Changelog
118
 
 
 
 
 
 
 
 
 
 
 
 
119
  = 2.0.30 (May 2015) =
120
 
121
  - Added: Username of logged events now link to that user's profile.
122
  - Fixed: When expanding ocassions the first loaded occasion was the same event as the one you expanded from, and the last ocassion was missing. Looked extra stupid when only 1 occasion existed, and you clicked "show ocassions" only to just find the same event again. So stupid. But fixed now!
123
- - Fixed: If an event had many similar events the list of similar events could freeze the browser. ([17948 failed login attempts overnight](https://twitter.com/eskapism/status/595478847598002176) is not that uncommon it turns out!
124
  - Fixed: Some loggers were missing the "All"-message in the search.
125
  - Changed: Hide some more keys and values by default in the context data popup.
126
  - Changed: Use `truncate` instead of `delete` when clearing the database. Works much faster on large logs.
3
  Donate link: http://eskapism.se/sida/donate/
4
  Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, cms, dashboard, admin, syslog, feed, activity, stream
5
  Requires at least: 3.6.0
6
+ Tested up to: 4.2.2
7
+ Stable tag: 2.1
8
 
9
  View changes made by users within WordPress. See who created a page, uploaded an attachment or approved an comment, and more.
10
 
116
 
117
  ## Changelog
118
 
119
+ = 2.1 (May 2015) =
120
+
121
+ - Added: Export! Now it's possible to export the events log to a JSON or CSV formatted file. It's your data so you should be able to export it any time you want or need. And now you can do that. You will find the export function in the Simple History settings page (Settings -> Simple History).
122
+ - Added: Filter `simple_history/add_custom_logger` and function `register_logger` that together are used to load external custom loggers. See [example-logger.php](https://github.com/bonny/WordPress-Simple-History/blob/master/examples/example-logger.php) for usage example.
123
+ - Added: Filter `simple_history/header_initiator_use_you`.
124
+ - Fixed: Fixed an undefined variable in get_avatar(). Fixes https://github.com/bonny/WordPress-Simple-History/issues/74.
125
+ - Fixed: When using [HyperDB](https://wordpress.org/support/plugin/hyperdb) only one event was returned. Fixed by using [adding `NO_SELECT_FOUND_ROWS` to the query](https://plugins.trac.wordpress.org/browser/hyperdb/trunk/db.php?#L49). Should fix problems for users using HyperDB and also users using for example [wpengine.com](http://wpengine.com) (that probably also is using HyperDB or a similar approach).
126
+ - Changed: Loggers now get default capability "manage_options" if they have no capability set.
127
+ - Changed: Misc internal cleanup.
128
+ - Removed: filter `simple_history/loggers_dir` removed, because loggers are loaded from array instead of file listing generated from `glob()`. Should be (however to the eye non-noticable) faster.
129
+
130
  = 2.0.30 (May 2015) =
131
 
132
  - Added: Username of logged events now link to that user's profile.
133
  - Fixed: When expanding ocassions the first loaded occasion was the same event as the one you expanded from, and the last ocassion was missing. Looked extra stupid when only 1 occasion existed, and you clicked "show ocassions" only to just find the same event again. So stupid. But fixed now!
134
+ - Fixed: If an event had many similar events the list of similar events could freeze the browser. ([17948 failed login attempts overnight](https://twitter.com/eskapism/status/595478847598002176) is not that uncommon it turns out!)
135
  - Fixed: Some loggers were missing the "All"-message in the search.
136
  - Changed: Hide some more keys and values by default in the context data popup.
137
  - Changed: Use `truncate` instead of `delete` when clearing the database. Works much faster on large logs.
templates/settings-statsForGeeks.php CHANGED
@@ -174,7 +174,7 @@ echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsF
174
  $one_logger_slug,
175
  esc_html( $logger_info["name"]),
176
  esc_html( $logger_info["description"]), // 4
177
- esc_html( $logger_info["capability"]),
178
  $loopnum % 2 ? " alt " : "", // 6
179
  $html_logger_messages // 7
180
  );
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
  );