Changeset 714127
- Timestamp:
- 05/17/2013 12:00:24 AM (13 years ago)
- Location:
- the-events-calendar-housekeeper
- Files:
-
- 8 added
- 3 edited
-
tags/1.2.0 (added)
-
tags/1.2.0/config (added)
-
tags/1.2.0/config/settingstab.php (added)
-
tags/1.2.0/housekeeper.php (added)
-
tags/1.2.0/lang (added)
-
tags/1.2.0/license.txt (added)
-
tags/1.2.0/readme.txt (added)
-
trunk/config/settingstab.php (modified) (1 diff)
-
trunk/housekeeper.php (modified) (20 diffs)
-
trunk/lang (added)
-
trunk/readme.txt (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
the-events-calendar-housekeeper/trunk/config/settingstab.php
r621079 r714127 13 13 'info-box-description' => array( 14 14 'type' => 'html', 15 'html' => '<p>'.__('Keep your calendar clean and efficient by scheduling regular garbage collection of expired events.', 'events-housekeeper').' '.ECHousekeeper::instance()->expiredItemsAlert().' '.__('Garbage collection takes place once a day – so changes may not be instant.', 'events-housekeeper').'</p>' 15 'html' => '<p>'.__('Keep your calendar clean and efficient by scheduling regular garbage collection of expired events. ', 'events-housekeeper') 16 .ECHousekeeper::instance()->expiredItemsAlert().' ' 17 .__('Garbage collection takes place once a day when enabled and, by default, a maximum of 100 events will be collected in a single sweep. ', 'events-housekeeper').'</p>' 18 .'<ul><li>'.__('Events are considered to be expired after they have started, <em>not when once they have ended,</em> so you should set the expiry criteria accordingly.', 'events-housekeeper').'</li>' 19 .'<li>'.__('The collection will not take place immediately after saving/updating – there is normally a short delay first of all.', 'events-housekeeper').'</li></ul>' 16 20 ), 17 21 'info-end' => array( -
the-events-calendar-housekeeper/trunk/housekeeper.php
r621079 r714127 2 2 /* 3 3 Plugin Name: The Events Calendar Housekeeper 4 Description: Adds tools to keep your events under control. 5 Version: 1. 0.34 Description: Adds tools to keep your events under control. This version targets Events Calendar PRO 3.x. 5 Version: 1.2.0 6 6 Author: Barry Hughes 7 7 Author URI: http://freshlybakedwebsites.net … … 53 53 54 54 /** 55 * The maximum number of events to tackle in a single clean up operation. 56 * This can be adjusted directly (obtain the current object via the 57 * instance() method) by using an appropriate action and priority, such 58 * as init/1. 55 * The maximum number of events to tackle in a single clean up operation. This can be adjusted directly (obtain the 56 * current object via the instance() method) by using an appropriate action and priority (ie, early during init). 59 57 * 60 58 * @var int … … 84 82 85 83 /** 86 * Creates a new instance of ECHousekeeper, which can then be accessed via 87 * the instance() method. 84 * Creates a new instance of ECHousekeeper, which can then be accessed via the instance() method. 88 85 * 89 86 * @static … … 98 95 99 96 /** 100 * Initializes and sets up actions to conduct prerequisite checks, integrate 101 * with The Events Calendar settings pages and run scheduled tasks. 97 * Initializes and sets up actions to conduct prerequisite checks, integrate with The Events Calendar settings pages and run scheduled tasks. 102 98 * 103 99 * @return ECHousekeeper … … 121 117 122 118 /** 123 * We require WP 3.4.2 and any requirements inherited by virtue of that, 124 * plus The Events Calendar 2.0.9 or later. 119 * We require WP 3.4.2 and any requirements inherited by virtue of that, plus The Events Calendar 2.0.9 or later. 125 120 * 126 121 * Sets the $preflightCheck property to true if we are all good here. … … 130 125 $missingRequirements = false; 131 126 132 if (version_compare($wp_version, '3.4.2') < 0) 133 $missingRequirements = true; 134 135 if (class_exists('TribeEvents') === false) 136 $missingRequirements = true; 137 138 if (version_compare(TribeEvents::VERSION, '2.0.9') < 0) 139 $missingRequirements = true; 140 141 if ($missingRequirements === false) 142 $this->preflightCheck = true; 143 } 144 145 146 /** 147 * Checks that the prerequisites were met then hooks into The Events 148 * Calendar to display and save settings. 127 if (version_compare($wp_version, '3.4.2') < 0) $missingRequirements = true; 128 if (class_exists('TribeEvents') === false) $missingRequirements = true; 129 if (version_compare(TribeEvents::VERSION, '2.0.9') < 0) $missingRequirements = true; 130 if ($missingRequirements === false) $this->preflightCheck = true; 131 } 132 133 134 /** 135 * Checks that the prerequisites were met then hooks into The Events Calendar to display and save settings. 149 136 */ 150 137 public function start() { … … 166 153 167 154 /** 168 * Builds an alert message to indicate if expired events are sitting in the 169 * database. 155 * Builds an alert message to indicate if expired events are sitting in the database. 170 156 * 171 157 * @return string 172 158 */ 173 159 public function expiredItemsAlert() { 174 $count = $this->expiredItemsCount(); 175 $message = sprintf(__('There are currently %d expired events (this includes remnants of deleted events).', 176 'events-housekeeper'), $count); 177 178 if ($count > 0) $message = "<strong> $message </strong>"; 160 $criteriaCount = (int) $this->expiredItemsCount(true, true); 161 $totalCount = (int) $this->expiredItemsCount(false, true); 162 163 $message = sprintf(_n('1 event currently meets the expiry criteria.', 164 '%d events currently meet the expiry criteria.', $criteriaCount, 'events-housekeeper'), $criteriaCount); 165 166 $message = "<strong> $message </strong>"; 179 167 return $message; 180 168 } … … 182 170 183 171 /** 184 * Counts the number of expired events in the database. 185 * 172 * Counts the number of expired events in the database. Setting $meetingCriteria to true means only events falling 173 * fowl of the current expiry criteria will be counted; setting $allInstances to true means individual recurring 174 * instances will be counted - not just 'primary' events. 175 * 176 * @param bool $meetingCriteria 177 * @param bool $allInstances 186 178 * @return int 187 179 */ 188 protected function expiredItemsCount() { 189 global $wpdb; 180 protected function expiredItemsCount($meetingCriteria, $allInstances) { 181 global $wpdb; 182 $cutoff = $meetingCriteria ? $this->criteriaCutOffDate() : date('Y-m-d'); 183 $include = $allInstances ? '' : 'DISTINCT'; 190 184 191 185 $expiredEvents = $wpdb->get_var($wpdb->prepare(" 192 SELECT COUNT( DISTINCTpost_id)193 FROM {$wpdb->p refix}postmeta194 WHERE meta_key = '_Event EndDate'186 SELECT COUNT($include post_id) 187 FROM {$wpdb->postmeta} 188 WHERE meta_key = '_EventStartDate' 195 189 AND meta_value < '%s'; 196 ", date('Y-m-d')));190 ", $cutoff)); 197 191 198 192 return (int) $expiredEvents; … … 205 199 public function updateSettings() { 206 200 $settings = (array) get_option(self::SETTINGS); 207 $settings = array_merge(array('enableGarbageCollection' => false), $settings); 208 209 if ($settings['enableGarbageCollection'] === false) $this->clearCollection(); 210 else $this->enableCollection($settings['expiryCollection']); 211 } 212 213 214 /** 215 * Remove our scheduled task. 216 */ 217 protected function clearCollection() { 218 wp_clear_scheduled_hook(self::SCHEDULE); 219 } 220 221 222 /** 223 * (Re-)establish our scheduled task - it will normally run almost 224 * immediately after this, except in the case of busy/slow systems. 225 * 226 * @param $frequency 227 */ 228 protected function enableCollection($frequency) { 201 202 if (isset($settings['enableGarbageCollection']) and $settings['enableGarbageCollection'] === false) 203 wp_clear_scheduled_hook(self::SCHEDULE); 204 else $this->enableCollection(); 205 } 206 207 208 /** 209 * (Re-)establish our scheduled task - it will normally run almost immediately after this, except in the case of 210 * busy/slow systems. 211 */ 212 protected function enableCollection() { 229 213 // Clear then reschedule to ensure a collection happens quickly after a change of settings 230 214 if (wp_next_scheduled(self::SCHEDULE) !== false) 231 215 wp_clear_scheduled_hook(self::SCHEDULE); 232 216 233 wp_schedule_event(time(), 'daily', self::SCHEDULE); 234 } 235 236 237 /** 238 * Carry out the actual collection, interpret the criteria specified in the 239 * settings tab and do the clean up. 217 // Next cleanup 10secs from now then daily. The 10sec buffer prevents confusion - otherwise the Housekeeper 218 // settings tab typically reloads part way through a clean-up and looks as if it has only done half a job 219 wp_schedule_event(time() + 10, 'daily', self::SCHEDULE); 220 } 221 222 223 /** 224 * Carry out the actual collection, interpret the criteria specified in the settings tab and do the clean up. 240 225 */ 241 226 public function doCollection() { 227 $this->expiryDate = $this->criteriaCutOffDate(); 228 $this->cleanUpAllBefore(); 229 } 230 231 232 protected function criteriaCutOffDate() { 242 233 $settings = (array) get_option(self::SETTINGS); 243 234 $settings = array_merge(array('expiryCriteria' => 'allExpired'), $settings); … … 251 242 } 252 243 253 $this->expiryDate = date('Y-m-d', $criteria); 254 $this->cleanUpAllBefore(); 255 } 256 257 258 /** 259 * Cleans up expired events/event instances, with special handling for 260 * recurring events. 261 * 262 * Note: recurring instance handling is likely to require significant 263 * revision in time for The Events Calendar 3.0 release. 244 return date('Y-m-d', $criteria); 245 } 246 247 248 /** 249 * Cleans up expired events/event instances, with special handling for recurring events. 264 250 */ 265 251 protected function cleanUpAllBefore() { 266 foreach ($this->listExpiredPostIDs() as $id) { 267 if ($this->isRecurringEvent($id)) { 268 $this->killRecurringInstances($id); 269 } 270 else { 271 $this->killPost($id); 272 $this->killPostMeta($id); 273 } 274 } 252 foreach ($this->listExpiredPostIDs() as $id) 253 if ($this->isRecurringEvent($id)) $this->killRecurringInstances($id); 254 else wp_delete_post($id, true); 275 255 } 276 256 … … 279 259 * Tries to determine if the event has recurring instances. 280 260 * 281 * This can be seen in the database where there is A) an _EventRecurrence 282 * meta entry and B) multiple _EventStartDate entries. For expediency, we 283 * test only for A. 261 * This can be seen in the database where there is A) an _EventRecurrence meta entry and B) multiple _EventStartDate 262 * entries. For expediency, we test only for A. 284 263 * 285 264 * @param $id … … 289 268 global $wpdb; 290 269 291 $recurrence = $wpdb->get_var( "270 $recurrence = $wpdb->get_var($wpdb->prepare(" 292 271 SELECT meta_value 293 FROM {$wpdb->p refix}postmeta272 FROM {$wpdb->postmeta} 294 273 WHERE meta_key = '_EventRecurrence' 295 274 AND LENGTH(meta_value) > 0 275 AND post_id = '%d' 296 276 LIMIT 1; 297 " );277 ", $id)); 298 278 299 279 if ($recurrence === null) return false; … … 314 294 SELECT DISTINCT post_id 315 295 FROM {$wpdb->prefix}postmeta 316 WHERE meta_key = '_Event EndDate'296 WHERE meta_key = '_EventStartDate' 317 297 AND meta_value < '%s' 318 298 LIMIT %d; … … 324 304 325 305 /** 326 * Deletes the specified post. 327 * 328 * @param $id 329 */ 330 protected function killPost($id) { 331 global $wpdb; 306 * Intelligently removes recurring instances of an event, where those instances have expired. The initial 307 * _EventEndDate is also adjusted to compensate for this. 308 * 309 * @param $id 310 */ 311 protected function killRecurringInstances($id) { 312 global $wpdb; 313 314 $eventInterval = $this->determineEventInterval($id); 332 315 333 316 $wpdb->query($wpdb->prepare(" 334 DELETE FROM {$wpdb->prefix}posts 335 WHERE ID = '%d' 336 ", $id)); 337 } 338 339 340 /** 341 * Deletes meta data associated with the specified post. 342 * 343 * @param $id 344 */ 345 protected function killPostMeta($id) { 346 global $wpdb; 347 348 $wpdb->query($wpdb->prepare(" 349 DELETE FROM {$wpdb->prefix}postmeta 350 WHERE post_id = '%d' 351 ", $id)); 352 } 353 354 355 /** 356 * Intelligently removes recurring instances of an event, where those 357 * instances have expired. The initial _EventEndDate is also adjusted to 358 * compensate for this. 359 * 360 * @param $id 361 */ 362 protected function killRecurringInstances($id) { 363 global $wpdb; 364 365 $eventInterval = $this->determineEventInterval($id); 366 367 $wpdb->query($wpdb->prepare(" 368 DELETE FROM {$wpdb->prefix}postmeta 317 DELETE FROM {$wpdb->postmeta} 369 318 WHERE post_id = '%d' 370 319 AND meta_key = '_EventStartDate' … … 377 326 378 327 /** 379 * Calculates the length of time for the event (could be hours, all day or 380 * days). 328 * Calculates the length of time for the event (could be hours, all day or days). 381 329 * 382 330 * @param $id … … 391 339 392 340 /** 393 * Adjusts the _EventEndDate so that it is the correct interval ahead of the 394 * oldest surviving _EventStartDate. 341 * Adjusts the _EventEndDate so that it is the correct interval ahead of the oldest surviving _EventStartDate. 395 342 * 396 343 * @param $id … … 403 350 $newEndTime = date('Y-m-d H:i:s', $currentStart + $interval); 404 351 405 $wpdb->query($wpdb->prepare(" 406 UPDATE wp_postmeta 352 // End time in the past? Kill the entire post 353 if ($newEndTime < date('Y-m-d H:i:s')) 354 wp_delete_post($id, true); 355 356 // Otherwise adjust the end date 357 else $wpdb->query($wpdb->prepare(" 358 UPDATE {$wpdb->postmeta} 407 359 SET meta_value = '%s' 408 360 WHERE meta_key = '_EventEndDate' … … 423 375 return $wpdb->get_var($wpdb->prepare(" 424 376 SELECT MIN(meta_value) 425 FROM {$wpdb->p refix}postmeta377 FROM {$wpdb->postmeta} 426 378 WHERE meta_key = '_EventStartDate' 427 379 AND post_id = '%d'; … … 441 393 return $wpdb->get_var($wpdb->prepare(" 442 394 SELECT MIN(meta_value) 443 FROM {$wpdb->p refix}postmeta395 FROM {$wpdb->postmeta} 444 396 WHERE meta_key = '_EventEndDate' 445 397 AND post_id = '%d'; … … 449 401 450 402 /** 451 * Loads the specified config array, allowing it to be pulled directly into 452 * the scope of the calling method. 403 * Loads the specified config array, allowing it to be pulled directly into the scope of the calling method. 453 404 * 454 405 * @param $config -
the-events-calendar-housekeeper/trunk/readme.txt
r621079 r714127 3 3 Donate link: http://freshlybakedwebsites.net/say-thanks-with-a-beer/ 4 4 Tags: events, calendar, housekeeping, clean up, database, tidy 5 Requires at least: 3. 4.26 Tested up to: 3. 4.27 Stable tag: 1. 0.35 Requires at least: 3.5.1 6 Tested up to: 3.5.1 7 Stable tag: 1.2.0 8 8 License: GPL3 or later 9 9 License URI: http://www.gnu.org/licenses/gpl.html … … 13 13 == Description == 14 14 15 Developed to work with The Events Calendar 2.0.9, this plugin allows for expired events to be automatically vacuumed up rather than leaving them to clutter up your database. 15 Developed to work with The Events Calendar 3.0, this plugin allows for expired events to be automatically vacuumed up rather than leaving them to clutter up your database. 16 _If you are still using The Events Calendar 2.x then you should use [this older version of Housekeeper](http://downloads.wordpress.org/plugin/the-events-calendar-housekeeper.1.0.3.zip)_, 17 noting that it still has some minor bugs and of course remembering that awesome people use the latest and greatest. 16 18 17 19 * Configurable: clean up events almost as soon as they have expired or enforce a buffer period of 1 week upto 6 months … … 21 23 22 24 = Author = 23 This plugin was written by [Barry Hughes](http://freshlybakedwebsites.net). Go on, [buy him a beer!](http://freshlybakedwebsites.net/say-thanks-with-a-beer/) More than anything, it will make you feel good about yourself. 25 This plugin was written by [Barry Hughes](http://codingkills.me "WordPress and PHP Developer based in BC, Canada") (it _is not_ an official plugin by Modern Tribe, so don't go pestering them for support). If this helps you out then 26 [buy the plugin author a beer!](http://freshlybakedwebsites.net/say-thanks-with-a-beer/) More than anything, it will make you feel good about yourself. 24 27 25 28 == Installation == … … 27 30 Like any other plugin you simply upload the plugin directory to the wp-content/plugins directory. You can also upload and install it through the WordPress plugins admin page. 28 31 29 *Remember that a prerequisite is the existence of The Events Calendar 2.0.9* ( and possibly later versions).32 *Remember that a prerequisite is the existence of The Events Calendar 2.0.9* (though the latest version targets The Events Calendar 3.0). 30 33 31 34 Once installed and activated a new "Housekeeping" tab will appear on the Events > Settings page. You must enable garbage collection via this tab or it will not do anything. … … 34 37 35 38 = How are recurring events handled? = 36 First of all, recurring events may be overhauled as of The Events Calendar 3.0 and hopefully this will be revised in time to accommodate any such changes. 37 38 For the time being however, any instances of recurring events meeting the _Expiry Criteria_ are deleted - those instances not meeting the criteria are preserved. This seemed like the most logical way to approach recurring events but any other ideas are welcome. 39 Any instances of recurring events meeting the _Expiry Criteria_ are deleted - those instances not meeting the criteria are preserved. This seemed like the most logical way to approach recurring events but any other ideas are welcome. 39 40 40 41 = What if the wrong events are deleted? = 41 That's completely possible for a variety of reasons. First of all, ensure your server and WordPress date/time settings are correct. Second, but more importantly, back-up before you use it and then keep on backing-up, frequently and often. You _should_ be doing this anyway - and remember! - a back-up is useless unless you know how to restore it. 42 That's completely possible for a variety of reasons. First of all, ensure your server and WordPress date/time settings are correct. Second, but more importantly, back-up before you use it and then keep on backing-up, frequently and often. 43 You _should_ be doing this anyway - and remember! - a back-up is useless unless you know how to restore it. 42 44 43 45 = Are they trashed or deleted out-right? = 44 They are not trashed in the same way that you might trash an event from the admin interface (which allows you to recover them after the fact). When this plugin runs any events it scoops up are effectively wiped out forever. 46 They are deleted out right. So don't confuse this with the "Trash" function WordPress provides for pages, posts and many custom post types. With this plugin, any events deemed to have expired will effectively be wiped out forever. 47 48 = Does an event expire after it has started or after it has ended? = 49 In the eyes of this plugin an event has expired after it has started and this is flagged up in the settings tab. That may not always be ideal - and for those cases you 50 can adjust the expiry criteria appropriately or just deactivate this plugin. 51 52 = I found a bug = 53 Please post details on the forum. Better yet, post a fix and add appropriate details. This is free and open source software and comes with no guarantees, so bear that 54 in mind first of all. 45 55 46 56 = I need help! =
Note: See TracChangeset
for help on using the changeset viewer.