Simple History - Version 0.3.1

Version Description

  • forgot to escape html for posts
  • reduced memory usage... I think/hope...
  • changes internal verbs for actions. some old history items may look a bit weird.
  • added RSS feed for recent changes - keep track of changes via your favorite RSS-reader
Download this release

Release Info

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

Version 0.3.1

Files changed (5) hide show
  1. index.php +1233 -0
  2. readme.txt +88 -0
  3. screenshot-1.png +0 -0
  4. screenshot-2.png +0 -0
  5. styles.css +103 -0
index.php ADDED
@@ -0,0 +1,1233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Simple History
4
+ Plugin URI: http://eskapism.se/code-playground/simple-history/
5
+ Description: Get a log of the changes made by users in WordPress.
6
+ Version: 0.3.1
7
+ Author: Pär Thernström
8
+ Author URI: http://eskapism.se/
9
+ License: GPL2
10
+ */
11
+
12
+ /* Copyright 2010 Pär Thernström (email: par.thernstrom@gmail.com)
13
+
14
+ This program is free software; you can redistribute it and/or modify
15
+ it under the terms of the GNU General Public License, version 2, as
16
+ published by the Free Software Foundation.
17
+
18
+ This program is distributed in the hope that it will be useful,
19
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
+ GNU General Public License for more details.
22
+
23
+ You should have received a copy of the GNU General Public License
24
+ along with this program; if not, write to the Free Software
25
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
+ */
27
+
28
+ define( "SIMPLE_HISTORY_VERSION", "0.3.1");
29
+ define( "SIMPLE_HISTORY_NAME", "Simple History");
30
+ define( "SIMPLE_HISTORY_URL", WP_PLUGIN_URL . '/simple-history/');
31
+
32
+ add_action( 'admin_head', "simple_history_admin_head" );
33
+ add_action( 'admin_init', 'simple_history_admin_init' ); // start listening to changes
34
+ add_action( 'init', 'simple_history_init' ); // start listening to changes
35
+ add_action( 'admin_menu', 'simple_history_admin_menu' );
36
+ add_action( 'wp_dashboard_setup', 'simple_history_wp_dashboard_setup' );
37
+ add_action( 'wp_ajax_simple_history_ajax', 'simple_history_ajax' );
38
+
39
+ function simple_history_ajax() {
40
+
41
+ $type = $_POST["type"];
42
+ if ($type == "All types") { $type = ""; }
43
+
44
+ $user = $_POST["user"];
45
+ if ($user == "By all users") { $user = ""; }
46
+
47
+ $page = (int) $_POST["page"];
48
+
49
+ $args = array(
50
+ "is_ajax" => true,
51
+ "filter_type" => $type,
52
+ "filter_user" => $user,
53
+ "page" => $page
54
+ );
55
+ simple_history_print_history($args);
56
+ exit;
57
+
58
+ }
59
+
60
+ function simple_history_admin_menu() {
61
+
62
+ #define( "SIMPLE_HISTORY_PAGE_FILE", menu_page_url("simple_history_page", false)); // no need yet
63
+
64
+ // show as page?
65
+ if (simple_history_setting_show_as_page()) {
66
+ add_dashboard_page(SIMPLE_HISTORY_NAME, SIMPLE_HISTORY_NAME, "edit_pages", "simple_history_page", "simple_history_management_page");
67
+ }
68
+
69
+ }
70
+
71
+
72
+ function simple_history_wp_dashboard_setup() {
73
+ if (simple_history_setting_show_on_dashboard()) {
74
+ if (current_user_can("edit_pages")) {
75
+ wp_add_dashboard_widget("simple_history_dashboard_widget", SIMPLE_HISTORY_NAME, "simple_history_dashboard");
76
+ }
77
+ }
78
+ }
79
+
80
+ function simple_history_dashboard() {
81
+ simple_history_purge_db();
82
+ simple_history_print_nav();
83
+ simple_history_print_history();
84
+ }
85
+
86
+ function simple_history_admin_head() {
87
+ ?>
88
+ <script type="text/javascript">
89
+ /* <![CDATA[ */
90
+ /**
91
+ * load history items via ajax
92
+ */
93
+ var simple_history_current_page = 0;
94
+ jQuery(".simple-history-filter a").live("click", function() {
95
+ $t = jQuery(this);
96
+ $t.closest("ul").find("li").removeClass("selected");
97
+ $t.closest("li").addClass("selected");
98
+ $ol = jQuery("ol.simple-history");
99
+
100
+ jQuery(".simple-history-added-by-ajax").remove();
101
+
102
+ var $wrapper = jQuery("#simple-history-ol-wrapper");
103
+ $wrapper.height($wrapper.height()); // so dashboard widget does not collapse when loading new items
104
+
105
+ jQuery("#simple-history-load-more").hide("fast");
106
+ $ol.fadeOut("fast");
107
+ jQuery("#simple-history-no-more-items").hide();
108
+
109
+ simple_history_current_page = 0;
110
+ var data = {
111
+ "action": "simple_history_ajax",
112
+ "type": jQuery(".simple-history-filter-type li.selected a").text(),
113
+ "user": jQuery(".simple-history-filter-user li.selected a").text()
114
+ };
115
+ jQuery.post(ajaxurl, data, function(data, textStatus, XMLHttpRequest){
116
+ $ol.html(data);
117
+ $ol.fadeIn("fast");
118
+ $wrapper.height("auto");
119
+ jQuery("#simple-history-load-more").fadeIn("fast");
120
+ });
121
+
122
+ return false;
123
+ });
124
+
125
+ jQuery("#simple-history-load-more a").live("click", function() {
126
+ simple_history_current_page++;
127
+
128
+ jQuery("#simple-history-load-more,#simple-history-load-more-loading").toggle();
129
+
130
+ $ol = jQuery("ol.simple-history:last");
131
+ var data = {
132
+ "action": "simple_history_ajax",
133
+ "type": jQuery(".simple-history-filter-type li.selected a").text(),
134
+ "user": jQuery(".simple-history-filter-user li.selected a").text(),
135
+ "page": simple_history_current_page
136
+ };
137
+ jQuery.post(ajaxurl, data, function(data, textStatus, XMLHttpRequest){
138
+
139
+ // if data = simpleHistoryNoMoreItems then no more items found, so hide load-more-link
140
+ if (data == "simpleHistoryNoMoreItems") {
141
+ jQuery("#simple-history-load-more,#simple-history-load-more-loading").hide();
142
+ jQuery("#simple-history-no-more-items").show();
143
+ } else {
144
+ var $new_elm = jQuery("<ol class='simple-history simple-history-added-by-ajax'>" + data + "</ol>");
145
+ $new_elm.hide();
146
+ $ol.after($new_elm);
147
+ $new_elm.show("slow");
148
+ jQuery("#simple-history-load-more,#simple-history-load-more-loading").toggle();
149
+ }
150
+ });
151
+ return false;
152
+ });
153
+
154
+ jQuery("ol.simple-history .when").live("mouseover", function() {
155
+ jQuery(this).closest("li").find(".when_detail").fadeIn("fast");
156
+ });
157
+ jQuery("ol.simple-history .when").live("mouseout", function() {
158
+ jQuery(this).closest("li").find(".when_detail").fadeOut("fast");
159
+ });
160
+
161
+ // show occasions
162
+ jQuery("a.simple-history-occasion-show").live("click", function() {
163
+ jQuery(this).closest("li").find("ul.simple-history-occasions").toggle("fast");
164
+ return false;
165
+ });
166
+ /* ]]> */
167
+ </script>
168
+ <?php
169
+ }
170
+
171
+
172
+ /*
173
+ http://codex.wordpress.org/Plugin_API/Action_Reference
174
+
175
+ create_category
176
+ Runs when a new category is created. Action function arguments: category ID.
177
+
178
+ delete_category
179
+ Runs just after a category is deleted from the database and its corresponding links/posts are updated to remove the category. Action function arguments: category ID.
180
+
181
+ edit_category
182
+ Runs when a category is updated/edited, including when a post or blogroll link is added/deleted or its categories are updated (which causes the count for the category to update). Action function arguments: category ID.
183
+
184
+ edit_comment
185
+ Runs after a comment is updated/edited in the database. Action function arguments: comment ID
186
+
187
+ delete_comment
188
+ Runs just before a comment is deleted. Action function arguments: comment ID.
189
+
190
+ comment_closed
191
+ Runs when the post is marked as not allowing comments while trying to display comment entry form. Action function argument: post ID.
192
+
193
+ edit_comment
194
+ Runs after a comment is updated/edited in the database. Action function arguments: comment ID.
195
+
196
+ delete_comment
197
+ Runs just before a comment is deleted. Action function arguments: comment ID.
198
+
199
+ add_link
200
+ Runs when a new blogroll link is first added to the database. Action function arguments: link ID.
201
+
202
+ delete_link
203
+ Runs when a blogroll link is deleted. Action function arguments: link ID.
204
+
205
+ edit_link
206
+ Runs when a blogroll link is edited. Action function arguments: link ID.
207
+
208
+ switch_theme
209
+ Runs when the blog's theme is changed. Action function argument: name of the new theme.
210
+
211
+
212
+ */
213
+
214
+ function simple_history_init() {
215
+ // users
216
+ add_action("wp_login", "simple_history_wp_login");
217
+ add_action("wp_logout", "simple_history_wp_logout");
218
+ add_action("delete_user", "simple_history_delete_user");
219
+ add_action("user_register", "simple_history_user_register");
220
+ add_action("profile_update", "simple_history_profile_update");
221
+
222
+ // options
223
+ #add_action("updated_option", "simple_history_updated_option", 10, 3);
224
+ #add_action("updated_option", "simple_history_updated_option2", 10, 2);
225
+ #add_action("updated_option", "simple_history_updated_option3", 10, 1);
226
+ #add_action("update_option", "simple_history_update_option", 10, 3);
227
+
228
+ // plugin
229
+ add_action("activated_plugin", "simple_history_activated_plugin");
230
+ add_action("deactivated_plugin", "simple_history_deactivated_plugin");
231
+
232
+ // check for RSS
233
+ // don't know if this is the right way to do this, but it seems to work!
234
+ if ($_GET["simple_history_get_rss"]) {
235
+
236
+ $rss_secret_option = get_option("simple_history_rss_secret");
237
+ $rss_secret_get = $_GET["rss_secret"];
238
+ if ($rss_secret_option == $rss_secret_get) {
239
+ echo '<?xml version="1.0"?>';
240
+ ?>
241
+ <rss version="2.0">
242
+ <channel>
243
+ <title>Simple History for <?php echo get_bloginfo("name") ?></title>
244
+ <link><?php get_bloginfo("link") ?></link>
245
+ <?php
246
+ $arr_items = simple_history_get_items_array("items=10");
247
+ foreach ($arr_items as $one_item) {
248
+ $object_type = ucwords($one_item->object_type);
249
+ $object_name = esc_html($one_item->object_name);
250
+ $user = get_user_by("id", $one_item->user_id);
251
+ $user_nicename = esc_html($user->user_nicename);
252
+ $description = "";
253
+ if ($user_nicename) {
254
+ $description .= "By $user_nicename<br />";
255
+ }
256
+ if ($one_item->occasions) {
257
+ $description .= sizeof($one_item->occasions) . " occasions<br />";
258
+ }
259
+
260
+ ?>
261
+ <item>
262
+ <title><?php echo "$object_type \"{$object_name}\" {$one_item->action}" ?></title>
263
+ <description><![CDATA[<?php echo $description ?>]]></description>
264
+ <pubDate><?php echo date("D, d M Y H:i:s", $one_item->date_unix) ?> GMT</pubDate>
265
+ </item>
266
+ <?php
267
+ }
268
+ ?>
269
+ </channel>
270
+ </rss>
271
+ <?php
272
+ } else {
273
+ // not ok rss secret
274
+ echo '<?xml version="1.0"?>';
275
+ ?>
276
+ <rss version="2.0">
277
+ <channel>
278
+ <title>Simple History for <?php echo get_bloginfo("name") ?></title>
279
+ <link><?php get_bloginfo("link") ?></link>
280
+ <item>
281
+ <title>Wrong RSS secret</title>
282
+ <description>Your RSS secret for Simple History RSS feed is wrong. Please see WordPress settings for current link to the RSS feed.</description>
283
+ <pubDate><?php echo date("D, d M Y H:i:s", time()) ?> GMT</pubDate>
284
+ </item>
285
+ </channel>
286
+ </rss>
287
+ <?php
288
+
289
+ }
290
+ exit;
291
+ }
292
+
293
+ }
294
+
295
+
296
+ function simple_history_admin_init() {
297
+
298
+ // posts
299
+ add_action("save_post", "simple_history_save_post");
300
+ add_action("transition_post_status", "simple_history_transition_post_status", 10, 3);
301
+ add_action("delete_post", "simple_history_delete_post");
302
+
303
+ // attachments/media
304
+ add_action("add_attachment", "simple_history_add_attachment");
305
+ add_action("edit_attachment", "simple_history_edit_attachment");
306
+ add_action("delete_attachment", "simple_history_delete_attachment");
307
+
308
+ add_settings_section("simple_history_settings_general", SIMPLE_HISTORY_NAME, "simple_history_settings_page", "general");
309
+ add_settings_field("simple_history_settings_field_1", "Show Simple History", "simple_history_settings_field", "general", "simple_history_settings_general");
310
+ add_settings_field("simple_history_settings_field_2", "RSS feed", "simple_history_settings_field_rss", "general", "simple_history_settings_general");
311
+ register_setting("general", "simple_history_show_on_dashboard");
312
+ register_setting("general", "simple_history_show_as_page");
313
+
314
+ wp_enqueue_style( "simple_history_styles", SIMPLE_HISTORY_URL . "styles.css", false, SIMPLE_HISTORY_VERSION );
315
+
316
+ }
317
+ function simple_history_settings_page() {
318
+ // leave empty. must exist.
319
+ }
320
+
321
+ function simple_history_setting_show_on_dashboard() {
322
+ return (bool) get_option("simple_history_show_on_dashboard", 1);
323
+ }
324
+ function simple_history_setting_show_as_page() {
325
+ return (bool) get_option("simple_history_show_as_page", 1);
326
+ }
327
+
328
+
329
+ function simple_history_settings_field() {
330
+ $show_on_dashboard = simple_history_setting_show_on_dashboard();
331
+ $show_as_page = simple_history_setting_show_as_page();
332
+ ?>
333
+
334
+ <input <?php echo $show_on_dashboard ? "checked='checked'" : "" ?> type="checkbox" value="1" name="simple_history_show_on_dashboard" id="simple_history_show_on_dashboard" />
335
+ <label for="simple_history_show_on_dashboard">on the dashboard</label>
336
+
337
+ <br />
338
+
339
+ <input <?php echo $show_as_page ? "checked='checked'" : "" ?> type="checkbox" value="1" name="simple_history_show_as_page" id="simple_history_show_as_page" />
340
+ <label for="simple_history_show_as_page">as a page under the tools menu</label>
341
+
342
+ <?php
343
+ }
344
+
345
+ function simple_history_get_rss_address() {
346
+ $rss_secret = get_option("simple_history_rss_secret");
347
+ $rss_address = add_query_arg(array("simple_history_get_rss" => "1", "rss_secret" => $rss_secret), get_bloginfo("url") . "/");
348
+ return $rss_address;
349
+ }
350
+
351
+ function simple_history_update_rss_secret() {
352
+ $rss_secret = "";
353
+ for ($i=0; $i<20; $i++) {
354
+ $rss_secret .= chr(rand(97,122));
355
+ }
356
+ update_option("simple_history_rss_secret", $rss_secret);
357
+ return $rss_secret;
358
+ }
359
+
360
+ function simple_history_settings_field_rss() {
361
+ ?>
362
+ <?php
363
+ $create_new_secret = false;
364
+ if ($rss_secret == false) {
365
+ $create_new_secret = true;
366
+ }
367
+ if ($_GET["simple_history_rss_update_secret"]) {
368
+ $create_new_secret = true;
369
+ echo "<p class='updated'>Created new secret RSS adress</p>";
370
+ }
371
+
372
+ if ($create_new_secret) {
373
+ simple_history_update_rss_secret();
374
+ }
375
+
376
+ $rss_address = simple_history_get_rss_address();
377
+ echo "<code><a href='$rss_address'>$rss_address</a></code>";
378
+ echo "<br />This is a secret RSS feed for Simple History. Only share the link with people you trust.";
379
+ echo "<br />";
380
+ $update_link = add_query_arg("simple_history_rss_update_secret", "1");
381
+ echo "You can <a href='$update_link'>generate a new address</a> for the RSS feed. This is useful if you think that the address has fallen into the wrong hands.";
382
+ }
383
+
384
+ // @todo: move all add-related stuff to own file? there are so many of them.. kinda confusing, ey.
385
+
386
+ function simple_history_activated_plugin($plugin_name) {
387
+ $plugin_name = urlencode($plugin_name);
388
+ simple_history_add("action=activated&object_type=plugin&object_name=$plugin_name");
389
+ }
390
+ function simple_history_deactivated_plugin($plugin_name) {
391
+ $plugin_name = urlencode($plugin_name);
392
+ simple_history_add("action=deactivated&object_type=plugin&object_name=$plugin_name");
393
+ }
394
+
395
+
396
+ function simple_history_update_option($option, $oldval, $newval) {
397
+ /*
398
+ echo "<br><br>simple_history_update_option()";
399
+ echo "<br>Updated option $option";
400
+ echo "<br>oldval: ";
401
+ bonny_d($oldval);
402
+ echo "<br>newval:";
403
+ bonny_d($newval);
404
+ */
405
+
406
+ if ($option == "active_plugins") {
407
+
408
+ $debug = "\n";
409
+ $debug .= "\nsimple_history_update_option()";
410
+ $debug .= "\noption: $option";
411
+ $debug .= "\noldval: " . print_r($oldval, true);
412
+ $debug .= "\nnewval: " . print_r($newval, true);
413
+
414
+ // Returns an array containing all the entries from array1 that are not present in any of the other arrays.
415
+ // alltså:
416
+ // om newval är array1 och innehåller en rad så är den tillagd
417
+ // om oldval är array1 och innhåller en rad så är den bortagen
418
+ $diff_added = array_diff((array) $newval, (array) $oldval);
419
+ $diff_removed = array_diff((array) $oldval, (array) $newval);
420
+ $debug .= "\ndiff_added: " . print_r($diff_added, true);
421
+ $debug .= "\ndiff_removed: " . print_r($diff_removed, true);
422
+ b_fd($debug);
423
+ }
424
+ }
425
+
426
+ function simple_history_updated_option($option, $oldval, $newval) {
427
+ /*
428
+ echo "<br><br>simple_history_updated_option()";
429
+ echo "<br>Updated option $option";
430
+ echo "<br>oldval: ";
431
+ bonny_d($oldval);
432
+ echo "<br>newval:";
433
+ bonny_d($newval);
434
+ */
435
+
436
+ }
437
+
438
+ // debug to file
439
+ // short for "bonny_file_debug" :)
440
+ function b_fd($str) {
441
+ $file = "/Users/bonny/Dropbox/localhost/wordpress3/wp-content/plugins/simple-history/debug.txt";
442
+ #$f = fopen($file, "+a");
443
+ file_put_contents($file, $str, FILE_APPEND);
444
+ }
445
+
446
+ /*
447
+ function simple_history_updated_option2($option, $oldval) {
448
+ echo "<br><br>xxx_simple_history_updated_option2";
449
+ bonny_d($option);
450
+ bonny_d($oldval);
451
+ }
452
+ function simple_history_updated_option3($option) {
453
+ echo "<br><br>xxx_simple_history_updated_option3";
454
+ echo "<br>option: $option";
455
+ }
456
+ */
457
+
458
+
459
+ function simple_history_add_attachment($attachment_id) {
460
+ $post = get_post($attachment_id);
461
+ $post_title = urlencode($post->post_title);
462
+ simple_history_add("action=added&object_type=attachment&object_id=$attachment_id&object_name=$post_title");
463
+ }
464
+ function simple_history_edit_attachment($attachment_id) {
465
+ // is this only being called if the title of the attachment is changed?!
466
+ $post = get_post($attachment_id);
467
+ $post_title = urlencode($post->post_title);
468
+ simple_history_add("action=updated&object_type=attachment&object_id=$attachment_id&object_name=$post_title");
469
+ }
470
+ function simple_history_delete_attachment($attachment_id) {
471
+ $post = get_post($attachment_id);
472
+ $post_title = urlencode($post->post_title);
473
+ simple_history_add("action=deleted&object_type=attachment&object_id=$attachment_id&object_name=$post_title");
474
+ }
475
+
476
+ // user is updated
477
+ function simple_history_profile_update($user_id) {
478
+ $user = get_user_by("id", $user_id);
479
+ $user_nicename = urlencode($user->user_nicename);
480
+ simple_history_add("action=updated&object_type=user&object_id=$user_id&object_name=$user_nicename");
481
+ }
482
+
483
+ // user is created
484
+ function simple_history_user_register($user_id) {
485
+ $user = get_user_by("id", $user_id);
486
+ $user_nicename = urlencode($user->user_nicename);
487
+ simple_history_add("action=created&object_type=user&object_id=$user_id&object_name=$user_nicename");
488
+ }
489
+
490
+ // user is deleted
491
+ function simple_history_delete_user($user_id) {
492
+ $user = get_user_by("id", $user_id);
493
+ $user_nicename = urlencode($user->user_nicename);
494
+ simple_history_add("action=deleted&object_type=user&object_id=$user_id&object_name=$user_nicename");
495
+ }
496
+
497
+ // user logs in
498
+ function simple_history_wp_login($user) {
499
+ $current_user = wp_get_current_user();
500
+ $user = get_user_by("login", $user);
501
+ $user_nicename = urlencode($user->user_nicename);
502
+ // if user id = null then it's because we are logged out and then no one is acutally loggin in.. like a.. ghost-user!
503
+ if ($current_user->ID == 0) {
504
+ $user_id = $user->ID;
505
+ } else {
506
+ $user_id = $current_user->ID;
507
+ }
508
+ simple_history_add("action=logged_in&object_type=user&object_id=".$user->ID."&user_id=$user_id&object_name=$user_nicename");
509
+ }
510
+ // user logs out
511
+ function simple_history_wp_logout() {
512
+ $current_user = wp_get_current_user();
513
+ $current_user_id = $current_user->ID;
514
+ $user_nicename = urlencode($current_user->user_nicename);
515
+ simple_history_add("action=logged_out&object_type=user&object_id=$current_user_id&object_name=$user_nicename");
516
+ }
517
+
518
+ function simple_history_delete_post($post_id) {
519
+ if (wp_is_post_revision($post_id) == false) {
520
+ $post = get_post($post_id);
521
+ if ($post->post_status != "auto-draft" && $post->post_status != "inherit") {
522
+ $post_title = urlencode($post->post_title);
523
+ simple_history_add("action=deleted&object_type=post&object_subtype=" . $post->post_type . "&object_id=$post_id&object_name=$post_title");
524
+ }
525
+ }
526
+ }
527
+
528
+ function simple_history_save_post($post_id) {
529
+
530
+ if (wp_is_post_revision($post_id) == false) {
531
+ // not a revision
532
+ // it should also not be of type auto draft
533
+ $post = get_post($post_id);
534
+ if ($post->post_status != "auto-draft") {
535
+ // bonny_d($post);
536
+ #echo "save";
537
+ // [post_title] => neu
538
+ // [post_type] => page
539
+ }
540
+
541
+ }
542
+ }
543
+
544
+ // post has changed status
545
+ function simple_history_transition_post_status($new_status, $old_status, $post) {
546
+
547
+ #echo "<br>From $old_status to $new_status";
548
+
549
+ // From new to auto-draft <- ignore
550
+ // From new to inherit <- ignore
551
+ // From auto-draft to draft <- page/post created
552
+ // From draft to draft
553
+ // From draft to pending
554
+ // From pending to publish
555
+ # From pending to trash
556
+ // if not from & to = same, then user has changed something
557
+ //bonny_d($post); // regular post object
558
+ if ($old_status == "auto-draft" && ($new_status != "auto-draft" && $new_status != "inherit")) {
559
+ // page created
560
+ $action = "created";
561
+ } elseif ($new_status == "auto-draft" || ($old_status == "new" && $new_status == "inherit")) {
562
+ // page...eh.. just leave it.
563
+ return;
564
+ } elseif ($new_status == "trash") {
565
+ $action = "deleted";
566
+ } else {
567
+ // page updated. i guess.
568
+ $action = "updated";
569
+ }
570
+ $object_type = "post";
571
+ $object_subtype = $post->post_type;
572
+ if ($object_subtype == "revision") {
573
+ // don't log revisions
574
+ return;
575
+ }
576
+
577
+ if (wp_is_post_revision($post->ID) === false) {
578
+ // ok, no revision
579
+ $object_id = $post->ID;
580
+ } else {
581
+ return;
582
+ }
583
+
584
+ $post_title = urlencode($post->post_title);
585
+
586
+ simple_history_add("action=$action&object_type=$object_type&object_subtype=$object_subtype&object_id=$object_id&object_name=$post_title");
587
+ }
588
+
589
+
590
+ /**
591
+ * add event to history table
592
+ */
593
+ function simple_history_add($args) {
594
+
595
+ $defaults = array(
596
+ "action" => null,
597
+ "object_type" => null,
598
+ "object_subtype" => null,
599
+ "object_id" => null,
600
+ "object_name" => null,
601
+ "user_id" => null,
602
+ );
603
+
604
+ $args = wp_parse_args( $args, $defaults );
605
+
606
+ $action = $args["action"];
607
+ $object_type = $args["object_type"];
608
+ $object_subtype = $args["object_subtype"];
609
+ $object_id = $args["object_id"];
610
+ $object_name = mysql_real_escape_string($args["object_name"]);
611
+ $user_id = $args["user_id"];
612
+
613
+ global $wpdb;
614
+ $tableprefix = $wpdb->prefix;
615
+ if ($user_id) {
616
+ $current_user_id = $user_id;
617
+ } else {
618
+ $current_user = wp_get_current_user();
619
+ $current_user_id = (int) $current_user->ID;
620
+ }
621
+ $sql = "INSERT INTO {$tableprefix}simple_history SET date = now(), action = '$action', object_type = '$object_type', object_subtype = '$object_subtype', user_id = '$current_user_id', object_id = '$object_id', object_name = '$object_name'";
622
+ $wpdb->query($sql);
623
+ }
624
+
625
+
626
+ // Returns an English representation of a past date within the last month
627
+ // Graciously stolen from http://ejohn.org/files/pretty.js
628
+ // ..and simple_history stole it even more graciously from simple-php-framework http://github.com/tylerhall/simple-php-framework/
629
+ function simple_history_time2str($ts) {
630
+ #if(!ctype_digit($ts))
631
+ # $ts = strtotime($ts);
632
+
633
+ $diff = time() - $ts;
634
+ if($diff == 0)
635
+ return 'now';
636
+ elseif($diff > 0)
637
+ {
638
+ $day_diff = floor($diff / 86400);
639
+ if($day_diff == 0)
640
+ {
641
+ if($diff < 60) return 'just now';
642
+ if($diff < 120) return '1 minute ago';
643
+ if($diff < 3600) return floor($diff / 60) . ' minutes ago';
644
+ if($diff < 7200) return '1 hour ago';
645
+ if($diff < 86400) return floor($diff / 3600) . ' hours ago';
646
+ }
647
+ if($day_diff == 1) return 'Yesterday';
648
+ if($day_diff < 7) return $day_diff . ' days ago';
649
+ if($day_diff < 31) return ceil($day_diff / 7) . ' weeks ago';
650
+ if($day_diff < 60) return 'last month';
651
+ return date('F Y', $ts);
652
+ }
653
+ else
654
+ {
655
+ $diff = abs($diff);
656
+ $day_diff = floor($diff / 86400);
657
+ if($day_diff == 0)
658
+ {
659
+ if($diff < 120) return 'in a minute';
660
+ if($diff < 3600) return 'in ' . floor($diff / 60) . ' minutes';
661
+ if($diff < 7200) return 'in an hour';
662
+ if($diff < 86400) return 'in ' . floor($diff / 3600) . ' hours';
663
+ }
664
+ if($day_diff == 1) return 'Tomorrow';
665
+ if($day_diff < 4) return date('l', $ts);
666
+ if($day_diff < 7 + (7 - date('w'))) return 'next week';
667
+ if(ceil($day_diff / 7) < 4) return 'in ' . ceil($day_diff / 7) . ' weeks';
668
+ if(date('n', $ts) == date('n') + 1) return 'next month';
669
+ #return date('F Y', $ts);
670
+ return $ts; // return back and let us do something else with it
671
+ }
672
+ }
673
+
674
+ function simple_history_purge_db() {
675
+ global $wpdb;
676
+ $tableprefix = $wpdb->prefix;
677
+ $sql = "DELETE FROM {$tableprefix}simple_history WHERE DATE_ADD(date, INTERVAL 60 DAY) < now()";
678
+ $wpdb->query($sql);
679
+ }
680
+
681
+ function simple_history_management_page() {
682
+
683
+ simple_history_purge_db();
684
+
685
+ ?>
686
+
687
+ <div class="wrap">
688
+ <h2><?php echo SIMPLE_HISTORY_NAME ?></h2>
689
+ <?php
690
+ simple_history_print_nav();
691
+ simple_history_print_history();
692
+ ?>
693
+ </div>
694
+
695
+ <?php
696
+
697
+ }
698
+
699
+ if (!function_exists("bonny_d")) {
700
+ function bonny_d($var) {
701
+ echo "<pre>";
702
+ print_r($var);
703
+ echo "</pre>";
704
+ }
705
+ }
706
+
707
+ // when activating plugin: create tables
708
+ #register_activation_hook( __FILE__, 'simple_history_install' );
709
+ #echo "<br>" . WP_PLUGIN_DIR . "/simple-history/index.php";
710
+ #echo plugin_basename(__FILE__);
711
+ // __FILE__ doesnt work for me because of soft linkes directories
712
+ register_activation_hook( WP_PLUGIN_DIR . "/simple-history/index.php" , 'simple_history_install' );
713
+
714
+ function simple_history_install() {
715
+
716
+ global $wpdb;
717
+
718
+ $table_name = $wpdb->prefix . "simple_history";
719
+ #if($wpdb->get_var("show tables like '$table_name'") != $table_name) {
720
+
721
+ $sql = "CREATE TABLE " . $table_name . " (
722
+ id int(10) NOT NULL AUTO_INCREMENT,
723
+ date datetime NOT NULL,
724
+ action varchar(255) NOT NULL,
725
+ object_type varchar(255) NOT NULL,
726
+ object_subtype VARCHAR(255) NOT NULL,
727
+ user_id int(10) NOT NULL,
728
+ object_id int(10) NOT NULL,
729
+ object_name varchar(255) NOT NULL,
730
+ PRIMARY KEY (id)
731
+ );";
732
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
733
+ dbDelta($sql);
734
+
735
+ // add ourself as a history item.
736
+ $plugin_name = urlencode(SIMPLE_HISTORY_NAME);
737
+
738
+ #}
739
+
740
+ simple_history_add("action=activated&object_type=plugin&object_name=$plugin_name");
741
+
742
+ }
743
+
744
+ function simple_history_print_nav() {
745
+
746
+ global $wpdb;
747
+ $tableprefix = $wpdb->prefix;
748
+
749
+ // fetch all types that are in the log
750
+ $simple_history_type_to_show = $_GET["simple_history_type_to_show"];
751
+ $sql = "SELECT DISTINCT object_type, object_subtype FROM {$tableprefix}simple_history ORDER BY object_type, object_subtype";
752
+ $arr_types = $wpdb->get_results($sql);
753
+ #echo "<p>View:</p>";
754
+ $str_types = "";
755
+ $str_types .= "<ul class='simple-history-filter simple-history-filter-type'>";
756
+ $css = "";
757
+ if (empty($simple_history_type_to_show)) {
758
+ $css = "class='selected'";
759
+ }
760
+
761
+ // add_query_arg(
762
+ $link = esc_html(add_query_arg("simple_history_type_to_show", ""));
763
+ #echo "<li>Filter by type: </li>";
764
+ $str_types .= "<li $css><a href='$link'>All types</a> | </li>";
765
+ foreach ($arr_types as $one_type) {
766
+ $css = "";
767
+ if ($one_type->object_subtype && $simple_history_type_to_show == ($one_type->object_type."/".$one_type->object_subtype)) {
768
+ $css = "class='selected'";
769
+ } elseif (!$one_type->object_subtype && $simple_history_type_to_show == $one_type->object_type) {
770
+ $css = "class='selected'";
771
+ }
772
+ $str_types .= "<li $css>";
773
+ $arg = "";
774
+ if ($one_type->object_subtype) {
775
+ $arg = $one_type->object_type."/".$one_type->object_subtype;
776
+ } else {
777
+ $arg = $one_type->object_type;
778
+ }
779
+ $link = esc_html(add_query_arg("simple_history_type_to_show", $arg));
780
+ $str_types .= "<a href='$link'>";
781
+ $str_types .= $one_type->object_type;
782
+ if ($one_type->object_subtype) {
783
+ $str_types .= "/".$one_type->object_subtype;
784
+ }
785
+ $str_types .= "</a> | ";
786
+ $str_types .= "</li>";
787
+ }
788
+ $str_types .= "</ul>";
789
+ $str_types = str_replace("| </li></ul>", "</li></ul>", $str_types);
790
+ if (!empty($arr_types)) {
791
+ echo $str_types;
792
+ }
793
+
794
+ // fetch all users that are in the log
795
+ $sql = "SELECT DISTINCT user_id FROM {$tableprefix}simple_history WHERE user_id <> 0";
796
+ $arr_users_regular = $wpdb->get_results($sql);
797
+ foreach ($arr_users_regular as $one_user) {
798
+ $arr_users[$one_user->user_id] = array("user_id" => $one_user->user_id);
799
+ }
800
+ if (!empty($arr_users)) {
801
+ foreach ($arr_users as $user_id => $one_user) {
802
+ $user = get_user_by("id", $user_id);
803
+ $arr_users[$user_id]["user_login"] = $user->user_login;
804
+ $arr_users[$user_id]["user_nicename"] = $user->user_nicename;
805
+ $arr_users[$user_id]["first_name"] = $user->first_name;
806
+ $arr_users[$user_id]["last_name"] = $user->last_name;
807
+ }
808
+ }
809
+
810
+ if ($arr_users) {
811
+ $simple_history_user_to_show = $_GET["simple_history_user_to_show"];
812
+ $str_users = "";
813
+ $str_users .= "<ul class='simple-history-filter simple-history-filter-user'>";
814
+ $css = "";
815
+ if (empty($simple_history_user_to_show)) {
816
+ $css = " class='selected' ";
817
+ }
818
+ $link = esc_html(add_query_arg("simple_history_user_to_show", ""));
819
+ #echo "<li>Filter by user: </li>";
820
+ $str_users .= "<li $css><a href='$link'>By all users</a> | </li>";
821
+ foreach ($arr_users as $user_id => $user_info) {
822
+ $link = esc_html(add_query_arg("simple_history_user_to_show", $user_id));
823
+ $css = "";
824
+ if ($user_id == $simple_history_user_to_show) {
825
+ $css = " class='selected' ";
826
+ }
827
+ $str_users .= "<li $css>";
828
+ $str_users .= "<a href='$link'>";
829
+ $str_users .= $user_info["user_nicename"];
830
+ $str_users .= "</a> | ";
831
+ $str_users .= "</li>";
832
+ }
833
+ $str_users .= "</ul>";
834
+ $str_users = str_replace("| </li></ul>", "</li></ul>", $str_users);
835
+ echo $str_users;
836
+ }
837
+
838
+
839
+ }
840
+
841
+
842
+ // return an array with all events and occasions
843
+ function simple_history_get_items_array($args) {
844
+
845
+ global $wpdb;
846
+
847
+ $defaults = array(
848
+ "page" => 0,
849
+ "items" => 5,
850
+ "filter_type" => "",
851
+ "filter_user" => "",
852
+ "is_ajax" => false
853
+ );
854
+ $args = wp_parse_args( $args, $defaults );
855
+
856
+ $simple_history_type_to_show = $args["filter_type"];
857
+ $simple_history_user_to_show = $args["filter_user"];
858
+
859
+ $where = " WHERE 1=1 ";
860
+ if ($simple_history_type_to_show) {
861
+ $filter_type = "";
862
+ $filter_subtype = "";
863
+ if (strpos($simple_history_type_to_show, "/") !== false) {
864
+ // split it up
865
+ $arr_args = explode("/", $simple_history_type_to_show);
866
+ $filter_type = $arr_args[0];
867
+ $filter_subtype = $arr_args[1];
868
+ } else {
869
+ $filter_type = $simple_history_type_to_show;
870
+ }
871
+ $where .= " AND object_type = '$filter_type' ";
872
+ $where .= " AND object_subtype = '$filter_subtype' ";
873
+ }
874
+ if ($simple_history_user_to_show) {
875
+ $userinfo = get_user_by("slug", $simple_history_user_to_show);
876
+ $where .= " AND user_id = '" . $userinfo->ID . "'";
877
+ }
878
+
879
+ $tableprefix = $wpdb->prefix;
880
+ $limit_page = $args["page"] * $args["items"];
881
+ $limit_items = $args["items"];
882
+ $sql_limit = " LIMIT $limit_page, $args[items]";
883
+
884
+ $sql = "SELECT *, UNIX_TIMESTAMP(date) as date_unix FROM {$tableprefix}simple_history $where ORDER BY date DESC ";
885
+ $rows = $wpdb->get_results($sql);
886
+
887
+ $loopNum = 0;
888
+ $real_loop_num = -1;
889
+
890
+ $arr_events = array();
891
+ if ($rows) {
892
+ $prev_row = null;
893
+ foreach ($rows as $one_row) {
894
+ if (
895
+ $one_row->action == $prev_row->action
896
+ && $one_row->object_type == $prev_row->object_type
897
+ && $one_row->object_type == $prev_row->object_type
898
+ && $one_row->object_subtype == $prev_row->object_subtype
899
+ && $one_row->user_id == $prev_row->user_id
900
+ && $one_row->object_id == $prev_row->object_id
901
+ && $one_row->object_name == $prev_row->object_name
902
+ ) {
903
+ // this event is like the previous event, but only with a different date
904
+ // so add it to the last element in arr_events
905
+ $arr_events[$prev_row->id]->occasions[] = $one_row;
906
+ } else {
907
+
908
+ $real_loop_num++;
909
+
910
+ #echo "<br>real_loop_num: $real_loop_num";
911
+ #echo "<br>loop_num: $loopNum";
912
+
913
+ if ($args["page"] > 0 && ($args["page"] * $args["items"] > $real_loop_num)) {
914
+ #echo "<br>CONTINUE";
915
+ continue;
916
+ }
917
+
918
+ if ($loopNum >= $args["items"]) {
919
+ #echo "<br>BREAK";
920
+ break;
921
+ }
922
+
923
+ // new event, not as previous one
924
+ #echo "<br><br>adding one";
925
+ $arr_events[$one_row->id] = $one_row;
926
+ $arr_events[$one_row->id]->occasions = array();
927
+
928
+ $prev_row = $one_row;
929
+
930
+ $loopNum++;
931
+ }
932
+ }
933
+ }
934
+ return $arr_events;
935
+ }
936
+
937
+ // output the log
938
+ // take filtrering into consideration
939
+ function simple_history_print_history($args = null) {
940
+
941
+ $arr_events = simple_history_get_items_array($args);
942
+
943
+ $defaults = array(
944
+ "page" => 0,
945
+ "items" => 5,
946
+ "filter_type" => "",
947
+ "filter_user" => "",
948
+ "is_ajax" => false
949
+ );
950
+
951
+ $args = wp_parse_args( $args, $defaults );
952
+
953
+ if ($arr_events) {
954
+ if (!$args["is_ajax"]) { echo "<div id='simple-history-ol-wrapper'><ol class='simple-history'>"; }
955
+
956
+ $loopNum = 0;
957
+ $real_loop_num = -1;
958
+ foreach ($arr_events as $one_row) {
959
+
960
+ $real_loop_num++;
961
+
962
+ #if ($args["page"] > 0 && ($args["page"] * $args["items"] > $real_loop_num)) {
963
+ # continue;
964
+ #}
965
+
966
+ #if ($loopNum >= $args["items"]) {
967
+ # break;
968
+ #}
969
+ /*
970
+ stdClass Object
971
+ (
972
+ [id] => 94
973
+ [date] => 2010-07-03 21:08:43
974
+ [action] => update
975
+ [object_type] => post
976
+ [object_subtype] => page
977
+ [user_id] => 1
978
+ [object_id] => 732
979
+ [date_unix] => 1278184123
980
+ [occasions] => array
981
+ )
982
+ */
983
+ #bonny_d($one_row);
984
+
985
+ $object_type = $one_row->object_type;
986
+ $object_subtype = $one_row->object_subtype;
987
+ $object_id = $one_row->object_id;
988
+ $object_name = $one_row->object_name;
989
+ $user_id = $one_row->user_id;
990
+ $action = $one_row->action;
991
+ $occasions = $one_row->occasions;
992
+ $num_occasions = sizeof($occasions);
993
+
994
+ $css = "";
995
+ if ("attachment" == $object_type) {
996
+ if (wp_get_attachment_image_src($object_id, array(50,50), true)) {
997
+ // yep, it's an attachment and it has an icon/thumbnail
998
+ $css .= ' simple-history-has-attachment-thumnbail ';
999
+ }
1000
+ }
1001
+ if ("user" == $object_type) {
1002
+ $css .= ' simple-history-has-attachment-thumnbail ';
1003
+ }
1004
+
1005
+ if ($num_occasions > 0) {
1006
+ $css .= ' simple-history-has-occasions ';
1007
+ }
1008
+
1009
+ echo "<li class='$css'>";
1010
+
1011
+ echo "<div class='first'>";
1012
+
1013
+ // who performed the action
1014
+ $who = "";
1015
+ $user = get_user_by("id", $user_id);
1016
+
1017
+ $who .= "<span class='who'>";
1018
+ if ($user) {
1019
+ // http://localhost/wordpress3/wp-admin/user-edit.php?user_id=6
1020
+ $user_link = "user-edit.php?user_id={$user->ID}";
1021
+ $who .= "<a href='$user_link'>";
1022
+ $who .= $user->user_nicename;
1023
+ $who .= "</a>";
1024
+ if ($user->first_name || $user->last_name) {
1025
+ $who .= " (";
1026
+ if ($user->first_name && $user->last_name) {
1027
+ $who .= $user->first_name . " " . $user->last_name;
1028
+ } else {
1029
+ $who .= $user->first_name . $user->last_name; // just one of them, no space necessary
1030
+ }
1031
+ $who .= ")";
1032
+ }
1033
+ } else {
1034
+ $who .= "&lt;Unknown or deleted user&gt;";
1035
+ }
1036
+ $who .= "</span>";
1037
+
1038
+ // what and object
1039
+ if ("post" == $object_type) {
1040
+
1041
+ $post_out = "";
1042
+ $post_out .= $object_subtype;
1043
+ $post = get_post($object_id);
1044
+ if (null == $post) {
1045
+ // post does not exist, probably deleted
1046
+ // check if object_name exists
1047
+ if ($object_name) {
1048
+ $post_out .= " <span class='simple-history-title'>\"" . esc_html($object_name) . "\"</span>";
1049
+ } else {
1050
+ $post_out .= " <span class='simple-history-title'>&lt;unknown name&gt;</span>";
1051
+ }
1052
+ } else {
1053
+ $title = esc_html($post->post_title);
1054
+ $edit_link = get_edit_post_link($object_id, 'display');
1055
+ $post_out .= " <a href='$edit_link'>";
1056
+ $post_out .= "<span class='simple-history-title'>{$title}</span>";
1057
+ $post_out .= "</a>";
1058
+ }
1059
+ if ("created" == $action) {
1060
+ $post_out .= " created ";
1061
+ } elseif ("updated" == $action) {
1062
+ $post_out .= " updated ";
1063
+ } elseif ("deleted" == $action) {
1064
+ $post_out .= " deleted";
1065
+ } else {
1066
+ $post_out .= " $action";
1067
+ }
1068
+
1069
+ $post_out = ucfirst($post_out);
1070
+ echo $post_out;
1071
+
1072
+
1073
+ } elseif ("attachment" == $object_type) {
1074
+
1075
+ $attachment_out = "";
1076
+ $attachment_out .= "attachment ";
1077
+ $post = get_post($object_id);
1078
+
1079
+ if ($post) {
1080
+ $title = $post->post_title;
1081
+ $edit_link = get_edit_post_link($object_id, 'display');
1082
+ $attachment_image_src = wp_get_attachment_image_src($object_id, array(50,50), true);
1083
+ $attachment_image = "";
1084
+ if ($attachment_image_src) {
1085
+ $attachment_image = "<a class='simple-history-attachment-thumbnail' href='$edit_link'><img src='{$attachment_image_src[0]}' alt='Attachment icon' width='{$attachment_image_src[1]}' height='{$attachment_image_src[2]}' /></a>";
1086
+ }
1087
+ $attachment_out .= $attachment_image;
1088
+ $attachment_out .= " <a href='$edit_link'>";
1089
+ $attachment_out .= "<span class='simple-history-title'>{$title}</span>";
1090
+ $attachment_out .= "</a>";
1091
+
1092
+ #echo " (".get_post_mime_type($object_id).")";
1093
+ } else {
1094
+ if ($object_name) {
1095
+ $attachment_out .= "<span class='simple-history-title'>\"" . esc_html($object_name) . "\"</span>";
1096
+ } else {
1097
+ $attachment_out .= " <span class='simple-history-title'>&lt;deleted&gt;</span>";
1098
+ }
1099
+ }
1100
+
1101
+ if ("added" == $action) {
1102
+ $attachment_out .= " added ";
1103
+ } elseif ("updated" == $action) {
1104
+ $attachment_out .= " updated ";
1105
+ } elseif ("deleted" == $action) {
1106
+ $attachment_out .= " deleted ";
1107
+ } else {
1108
+ $attachment_out .= " $action ";
1109
+ }
1110
+
1111
+ $attachment_out = ucfirst($attachment_out);
1112
+ echo $attachment_out;
1113
+ #echo " <span class='simple-history-discrete'>(".get_post_mime_type($object_id).")</span>";
1114
+
1115
+
1116
+ } elseif ("user" == $object_type) {
1117
+ $user_out = "";
1118
+ $user_out .= "user";
1119
+ $user = get_user_by("id", $object_id);
1120
+ if ($user) {
1121
+ $user_link = "user-edit.php?user_id={$user->ID}";
1122
+ $user_out .= "<span class='simple-history-title'>";
1123
+ $user_out .= " <a href='$user_link'>";
1124
+ $user_out .= $user->user_nicename;
1125
+ $user_out .= "</a>";
1126
+ if ($user->first_name || $user->last_name) {
1127
+ $user_out .= " (";
1128
+ if ($user->first_name && $user->last_name) {
1129
+ $user_out .= $user->first_name . " " . $user->last_name;
1130
+ } else {
1131
+ $user_out .= $user->first_name . $user->last_name; // just one of them, no space necessary
1132
+ }
1133
+ $user_out .= ")";
1134
+ }
1135
+ $user_out .= "</span>";
1136
+ } else {
1137
+ // most likely deleted user
1138
+ $user_link = "";
1139
+ $user_out .= " \"$object_name\"";
1140
+ }
1141
+
1142
+ $user_avatar = get_avatar($user->user_email, "50");
1143
+ if ($user_link) {
1144
+ $user_out .= "<a class='simple-history-attachment-thumbnail' href='$user_link'>$user_avatar</a>";
1145
+ } else {
1146
+ $user_out .= "<span class='simple-history-attachment-thumbnail' href='$user_link'>$user_avatar</span>";
1147
+ }
1148
+
1149
+ if ("created" == $action) {
1150
+ $user_out .= " added ";
1151
+ } elseif ("updated" == $action) {
1152
+ $user_out .= " updated ";
1153
+ } elseif ("deleted" == $action) {
1154
+ $user_out .= " deleted ";
1155
+ } elseif ("logged_in" == $action) {
1156
+ $user_out .= " logged in";
1157
+ } elseif ("logged_out" == $action) {
1158
+ $user_out .= " logged out";
1159
+ } else {
1160
+ $user_out .= " $action";
1161
+ }
1162
+
1163
+ $user_out = ucfirst($user_out);
1164
+ echo $user_out;
1165
+ } else {
1166
+
1167
+ // unknown type
1168
+ echo ucwords($object_type) . " $object_subtype <span class='simple-history-title'>\"$object_name\"</span> $action";
1169
+
1170
+ }
1171
+ echo "</div>";
1172
+
1173
+ echo "<div class='second'>";
1174
+ // when
1175
+ $date_i18n_date = date_i18n(get_option('date_format'), strtotime($one_row->date), $gmt=false);
1176
+ $date_i18n_time = date_i18n(get_option('time_format'), strtotime($one_row->date), $gmt=false);
1177
+ echo "By $who, ";
1178
+ echo "<span class='when'>".simple_history_time2str($one_row->date_unix)."</span>";
1179
+ echo "<span class='when_detail'>$date_i18n_date at $date_i18n_time</span>";
1180
+ echo "</div>";
1181
+
1182
+ // occasions
1183
+ if ($num_occasions > 0) {
1184
+ echo "<div class='third'>";
1185
+ if ($num_occasions == 1) {
1186
+ echo "<a class='simple-history-occasion-show' href='#'>+ 1 occasion</a>";
1187
+ } else {
1188
+ echo "<a class='simple-history-occasion-show' href='#'>+ $num_occasions occasions</a>";
1189
+ }
1190
+ echo "<ul class='simple-history-occasions hidden'>";
1191
+ foreach ($occasions as $one_occasion) {
1192
+ echo "<li>";
1193
+ $date_i18n_date = date_i18n(get_option('date_format'), strtotime($one_occasion->date), $gmt=false);
1194
+ $date_i18n_time = date_i18n(get_option('time_format'), strtotime($one_occasion->date), $gmt=false);
1195
+ echo simple_history_time2str($one_occasion->date_unix) . " ($date_i18n_date at $date_i18n_time)";
1196
+
1197
+ echo "</li>";
1198
+ }
1199
+ echo "</ul>";
1200
+ echo "</div>";
1201
+ }
1202
+
1203
+
1204
+ echo "</li>";
1205
+
1206
+ $loopNum++;
1207
+ }
1208
+
1209
+ // if $loopNum == 0 no items where found for this page
1210
+ if ($loopNum == 0) {
1211
+ echo "simpleHistoryNoMoreItems";
1212
+ }
1213
+
1214
+ if (!$args["is_ajax"]) {
1215
+ echo "</ol>
1216
+ </div>
1217
+ <p id='simple-history-load-more'><a href='#'>Show $args[items] more</a></p>
1218
+ <p class='hidden' id='simple-history-load-more-loading'>Loading...</p>
1219
+ <p class='hidden' id='simple-history-no-more-items'>No more history items found.</p>
1220
+ ";
1221
+ }
1222
+ } else {
1223
+ if ($args["is_ajax"]) {
1224
+ echo "simpleHistoryNoMoreItems";
1225
+ } else {
1226
+ echo "<p>No history items found.</p>";
1227
+ echo "<p>Please note that Simple History only records things that happen after this plugin have been installed.</p>";
1228
+ }
1229
+
1230
+ }
1231
+ }
1232
+
1233
+ ?>
readme.txt ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Plugin Name ===
2
+ Contributors: eskapism
3
+ Donate link: http://eskapism.se/sida/donate/
4
+ Tags: history, log, changes, changelog, audit, trail, pages, attachments, users, cms, dashboard, admin
5
+ Requires at least: 2.9.2
6
+ Tested up to: 3.0
7
+ Stable tag: trunk
8
+
9
+ View changes made by users within WordPress. It’s a history/change log/audit/recent changes-plugin.
10
+
11
+ == Description ==
12
+
13
+ Simple History is a plugin that shows recent changes made within WordPress.
14
+
15
+ Users of the system can see what articles have been created, modified or deleted,
16
+ what attachments have been uploaded, modified or deleted, and what plugins that have been
17
+ activated or deactivated.
18
+
19
+ All changes are also avaialable as a RSS feed som you can keep track of the changes made
20
+ via your favorite RSS reader on your phone, on your iPad, or on your computer. Or any where you like.
21
+
22
+ It’s a pretty good plugin to have on websites where several people are
23
+ involved.
24
+
25
+ #### Example scenarios
26
+
27
+ Keep track of what other people are doing:
28
+ _"Has someone done anything today? Ah, Sarah uploaded
29
+ the new press release and created an article for it. Great! Now I don't have to do that."_
30
+
31
+ Or for debug purposes:
32
+ _"The site feels very slow since yesterday. Has anyone done anything special? ... Ah, Steven activated 'naughy-plugin-x',
33
+ that must be it."
34
+
35
+
36
+ #### See it in action
37
+ See the plugin in action with this short screencast:
38
+ [youtube http://www.youtube.com/watch?v=4cu4kooJBzs]
39
+
40
+ ![Screenshot of Simple History](http://eskapism.se/wordpress/wp-content/uploads/2010/07/simple-history-dashboard-screenshot.png "Screenshot of Simple History")
41
+
42
+ == Installation ==
43
+
44
+ 1. Upload the folder "simple-history" to "/wp-content/plugins/"
45
+ 1. Activate the plugin through the "Plugins" menu in WordPress
46
+ 1. Done!
47
+
48
+ Now Simple History will be visible both on the dashboard and in the menu under pages.
49
+
50
+ == Feedback ==
51
+ Like the plugin? Dislike it? Got bugs or feature request?
52
+ Great! Contact me at par.thernstrom@gmail.com or at twitter.com/eskapism and hopefully
53
+ I can do something about it.
54
+
55
+ == Screenshots ==
56
+
57
+ 1. Simple History as it looks on your (well, mine anyway..) dashboard.
58
+
59
+ 2. Simple History settings. Choose to show the plugin on your dashboard, or as a separately page. Or both. Or none, since you can choose
60
+ to only use the secret RSS feed to keep track of the changes on you web site/WordPress installation.
61
+
62
+ == Changelog ==
63
+
64
+ = 0.3.1 =
65
+ - forgot to escape html for posts
66
+ - reduced memory usage... I think/hope...
67
+ - changes internal verbs for actions. some old history items may look a bit weird.
68
+ - added RSS feed for recent changes - keep track of changes via your favorite RSS-reader
69
+
70
+ = 0.3 =
71
+ - page is now added under dashboard (was previously under tools). just feel better.
72
+ - mouse over on date now display detailed date a bit faster
73
+ - layout fixes to make it cooler, better, faster, stronger
74
+ - multiple events of same type, performed on the same object, by the same user, are now grouped together. This way 30 edits on the same page does not end up with 30 rows in Simple History. Much better overview!
75
+ - the name of deleted items now show up, instead of "Unknown name" or similar
76
+ - added support for plugins (who activated/deactivated what plugin)
77
+ - support for third party history items. Use like this:
78
+ simple_history_add("action=repaired&object_type=starship&object_name=USS Enterprise");
79
+ this would result in somehting like this:
80
+ Starship "USS Enterprise" repaired
81
+ by admin (John Doe), just now
82
+ - capability edit_pages needed to show history. Is this an appropriate capability do you think?
83
+
84
+ = 0.2 =
85
+ * Compatible with 2.9.2
86
+
87
+ = 0.1 =
88
+ * First public version. It works!
screenshot-1.png ADDED
Binary file
screenshot-2.png ADDED
Binary file
styles.css ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .simple-history-filter {
3
+ margin-bottom: .5em;
4
+ margin-top: .5em;
5
+ }
6
+ .simple-history-filter li {
7
+ display: inline;
8
+ }
9
+ .simple-history-filter li.selected a {
10
+ font-weight: bold;
11
+ text-decoration: none;
12
+ color: black;
13
+ }
14
+
15
+ ol.simple-history {
16
+ list-style-type: none;
17
+ margin: 0;
18
+ padding: 0;
19
+ }
20
+ ol.simple-history li {
21
+ margin-bottom: 1.5em;
22
+ margin-top: 1.5em;
23
+ /*
24
+ xpadding-bottom: 1em;
25
+ xborder-bottom: 1px solid #eee;
26
+ */
27
+ position: relative;
28
+ line-height: 1.5;
29
+ }
30
+ ol.simple-history .first {
31
+ font-size: 13px;
32
+ font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
33
+ margin: 0 0 0.2em;
34
+ /* margin-left: 60px; */
35
+ }
36
+
37
+ ol.simple-history .second {
38
+ color: #999;
39
+ /* margin-left: 60px; */
40
+ }
41
+
42
+ ol.simple-history .when {
43
+ color: #999;
44
+ cursor: help;
45
+ border-bottom: 1px dotted #bbb;
46
+ }
47
+ ol.simple-history .when_detail {
48
+ /* margin-left: .5em; */
49
+ display: none;
50
+ position: relative;
51
+ top: 1.75em;
52
+ left: -2em;
53
+ padding: .5ex;
54
+ background-color: #fffdb5;
55
+ border: 1px solid #eee;
56
+ color: black;
57
+ }
58
+
59
+ .simple-history-attachment-thumbnail {
60
+ position: absolute;
61
+ left: 0;
62
+ top: 0;
63
+ }
64
+ .simple-history-title {
65
+ font-weight: bold;
66
+ }
67
+
68
+ li.simple-history-has-attachment-thumnbail {
69
+ min-height: 50px;
70
+ }
71
+ ol.simple-history .simple-history-has-attachment-thumnbail .first,
72
+ ol.simple-history .simple-history-has-attachment-thumnbail .second,
73
+ ol.simple-history .simple-history-has-attachment-thumnbail .third
74
+ {
75
+ margin-left: 60px;
76
+ }
77
+
78
+ .simple-history-discrete {
79
+ font-size: 11px;
80
+ color: #999;
81
+ }
82
+
83
+ .simple-history-added-by-ajax {
84
+ border-top: 1px solid #ddd;
85
+ }
86
+
87
+ ul.simple-history-occasions {
88
+ margin: 0;
89
+ padding: 0;
90
+ list-style-type: none;
91
+ color: #999999;
92
+ }
93
+ ul.simple-history-occasions li {
94
+ margin: 0;
95
+ padding: 0;
96
+ }
97
+
98
+ #simple-history-no-more-items {
99
+ padding: .5em;
100
+ background-color: #FFFFE0;
101
+ border: 1px solid #E6DB55;
102
+ font-weight: bold;
103
+ }