Event List - Version 0.2.0

Version Description

(2012-09-29) =

  • adapted menu names to wordpress standard (similar to posts and pages)
  • adapted event list table admin page to wordpress standard layout
  • used wordpress included table view for admin event table
  • added sort functionality in admin event table
  • added bulk action delete in admin event table
  • added status messages for added, modified and deleted events on admin page
Download this release

Release Info

Developer mibuthu
Plugin Icon 128x128 Event List
Version 0.2.0
Comparing to
See all releases

Code changes from version 0.1.1 to 0.2.0

Files changed (5) hide show
  1. event-list.php +5 -3
  2. php/admin.php +101 -169
  3. php/admin_event_table.php +330 -0
  4. php/db.php +55 -29
  5. readme.txt +10 -1
event-list.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Event List
4
  Plugin URI: http://wordpress.org/extend/plugins/event-list/
5
  Description: Manage your events and show them in a list view on your site.
6
- Version: 0.1.1
7
  Author: Michael Burtscher
8
  Author URI: http://wordpress.org/extend/plugins/event-list/
9
  License: GPLv2
@@ -60,9 +60,11 @@ function on_el_plugin_loaded() {
60
 
61
  function on_el_admin() {
62
  require_once( 'php/admin.php' );
63
- $page = add_menu_page('Event List', 'Event List', 'edit_posts', 'el_admin_main', array( 'el_admin', 'show_main' ) );
 
64
  add_action( 'admin_head-'.$page, array( 'el_admin', 'embed_admin_js' ) );
65
- $page = add_submenu_page('el_admin_main', 'New Event', 'New Event', 'edit_posts', 'el_admin_new', array( 'el_admin', 'show_new' ) );
 
66
  add_action( 'admin_head-'.$page, array( 'el_admin', 'embed_admin_js' ) );
67
  add_submenu_page( 'el_admin_main', 'Event List Settings', 'Settings', 'manage_options', 'el_admin_settings', array( 'el_admin', 'show_settings' ) );
68
  add_submenu_page( 'el_admin_main', 'About Event List', 'About', 'manage_options', 'el_admin_about', array( 'el_admin', 'show_about' ) );
3
  Plugin Name: Event List
4
  Plugin URI: http://wordpress.org/extend/plugins/event-list/
5
  Description: Manage your events and show them in a list view on your site.
6
+ Version: 0.2.0
7
  Author: Michael Burtscher
8
  Author URI: http://wordpress.org/extend/plugins/event-list/
9
  License: GPLv2
60
 
61
  function on_el_admin() {
62
  require_once( 'php/admin.php' );
63
+ add_menu_page( 'Event List', 'Event List', 'edit_posts', 'el_admin_main', array( 'el_admin', 'show_main' ) );
64
+ $page = add_submenu_page( 'el_admin_main', 'Events', 'All Events', 'edit_posts', 'el_admin_main', array( 'el_admin', 'show_main' ) );
65
  add_action( 'admin_head-'.$page, array( 'el_admin', 'embed_admin_js' ) );
66
+ add_action( 'admin_head-'.$page, array( 'el_admin', 'embed_table_style' ) );
67
+ $page = add_submenu_page( 'el_admin_main', 'Add New Event', 'Add New', 'edit_posts', 'el_admin_new', array( 'el_admin', 'show_new' ) );
68
  add_action( 'admin_head-'.$page, array( 'el_admin', 'embed_admin_js' ) );
69
  add_submenu_page( 'el_admin_main', 'Event List Settings', 'Settings', 'manage_options', 'el_admin_settings', array( 'el_admin', 'show_settings' ) );
70
  add_submenu_page( 'el_admin_main', 'About Event List', 'About', 'manage_options', 'el_admin_about', array( 'el_admin', 'show_about' ) );
php/admin.php CHANGED
@@ -1,45 +1,52 @@
1
  <?php
2
  //require_once( EL_PATH.'php/options.php' );
3
  require_once( EL_PATH.'php/db.php' );
 
4
 
5
  // This class handles all available admin pages
6
  class el_admin {
7
-
 
 
8
  // show the main admin page as a submenu of "Comments"
9
  public static function show_main() {
10
  if ( !current_user_can( 'edit_posts' ) ) {
11
  wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
12
  }
13
-
14
- $out ='
15
- <div class="wrap nosubsub" style="padding-bottom:15px">
16
- <div id="icon-edit-pages" class="icon32"><br /></div><h2>Event List</h2>
17
- </div>';
18
-
19
- // is there POST data to deal with?
20
  if( !empty( $_POST ) ) {
21
- el_db::update_event( $_POST );
 
22
  }
23
-
24
- $out .= '<div class="wrap">';
25
-
26
- if( !isset( $_GET['action'] ) ) {
27
- $_GET['action'] = '';
28
  }
29
- switch ( $_GET['action'] ) {
30
- case "edit" :
31
- $out .= self::show_edit();
32
- break;
33
- case "delete" :
34
- el_db::delete_event( $_GET['id'] );
35
- $out .= self::list_events();
36
- break;
37
- case "copy" :
38
- $out .= self::edit_event();
39
- break;
40
- default :
41
- $out .= self::list_events();
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  $out .= '</div>';
44
  echo $out;
45
  }
@@ -47,7 +54,7 @@ class el_admin {
47
  public static function show_new() {
48
  $out = '<div class="wrap">
49
  <div class="wrap nosubsub" style="padding-bottom:15px">
50
- <div id="icon-edit-pages" class="icon32"><br /></div><h2>New Event</h2>
51
  </div>';
52
  $out .= self::edit_event();
53
  $out .= '</div>';
@@ -149,82 +156,67 @@ class el_admin {
149
  echo '<script type="text/javascript" src="'.EL_URL.'/js/admin.js"></script>';
150
  }
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  private static function list_events() {
153
- if ( isset( $_GET['ytd'] ) ) {
154
- $events = el_db::get_events( $_GET['ytd'] );
155
- }
156
- else {
157
- $events = el_db::get_events( 'upcoming' );
158
- }
159
  $out = el_db::html_calendar_nav();
160
- $out .= '<style type="text/css">
161
- <!--
162
- .widefat .event_date { text-align: right; width: 150px; }
163
- .widefat .event_location { text-align: left; width: 27%; min-width: 200px; }
164
- .widefat .event_details { min-width: 70px; }
165
- .widefat .event_buttons { text-align: right; padding: 8px; }
166
- .widefat .event_title { font-weight: bold; }
167
- }
168
- -->
169
- </style>';
170
- $out .= '<a href="?page=el_admin_new" class="button-primary" style="float:right;">New Event</a>
171
- <table class="widefat" style="margin-top:10px;">
172
- <thead>
173
- <tr><th class="event_date">Date</th><th class="event_location">Event</th><th class="event_details">Details</th><th class="event_buttons">Actions</tr>
174
- </thead>';
175
-
176
- if ( !empty( $events ) ) {
177
- foreach ( $events as $event ) {
178
- $out .= '<tr><td class="event_date">';
179
- $out .= self::format_date( $event->start_date, $event->end_date).'<br />';
180
- $out .= $event->time;
181
- $out .= '</td>
182
- <td class="event_location"><div class="event_title">'.$event->title.'</div>'.self::truncate( 80, $event->location ).'</td>
183
- <td class="event_details">'.self::truncate( 100, $event->details ).'</td>
184
- <td class="event_buttons" style="white-space:nowrap;">
185
- <a href="?page=el_admin_main&id='.$event->id.'&action=edit" class="button-secondary" title="Edit this event">Edit</a>
186
- <a href="?page=el_admin_main&id='.$event->id.'&action=copy" class="button-secondary" title="Create a new event based on this event">Duplicate</a>
187
- <a href="#" onClick="eventlist_deleteEvent('.$event->id.');return false;" class="button-secondary" title="Delete this event">Delete</a>
188
- </td></tr>';
189
- }
190
- }
191
- else {
192
- $out .= '<tr>
193
- <td colspan="10" style="text-align:center;">No events found in this range.</td>
194
- </tr>';
195
  }
196
-
197
- $out .= "</table>";
 
 
 
 
 
 
 
 
 
 
198
  return $out;
199
  }
200
 
201
  private static function edit_event() {
202
- $copy = false;
203
- $new = false;
204
- if( isset( $_GET['id'] ) ) {
205
  // existing event
206
  $event = el_db::get_event( $_GET['id'] );
207
- if( isset( $_GET['action'] ) && $_GET['action'] == 'copy' ) {
208
  // copy of existing event
209
  $start_date = date('Y-m-d');
210
  $end_date = date('Y-m-d');
211
- $copy = true;
212
  }
213
  else {
214
  // edit existing event
215
  $start_date = $event->start_date;
216
  $end_date = $event->end_date;
 
217
  }
218
  }
219
  else {
220
  //new event
221
  $start_date = date('Y-m-d');
222
  $end_date = date('Y-m-d');
223
- $new = true;
224
  }
225
 
226
  $out = '<form method="POST" action="?page=el_admin_main">';
227
- if ( !$new && !$copy ) {
228
  $out .= '<input type="hidden" name="id" value="'.$_GET['id'].'" />';
229
  }
230
  $out .= '<table class="form-table">
@@ -268,38 +260,45 @@ class el_admin {
268
  $out .= '<p class="submit"><input type="submit" class="button-primary" name="save" value="Save Event" id="submitbutton"> <a href="?page=el_admin_main" class="button-secondary">Cancel</a></p></form>';
269
  return $out;
270
  }
271
-
272
- private static function format_date( $start_date, $end_date ) {
273
- $start_array = explode("-", $start_date);
274
- $start_date = mktime(0,0,0,$start_array[1],$start_array[2],$start_array[0]);
275
- $end_array = explode("-", $end_date);
276
- $end_date = mktime(0,0,0,$end_array[1],$end_array[2],$end_array[0]);
277
  $out = '';
278
-
279
- if ($start_date == $end_date) {
280
- if ($start_array[2] == "00") {
281
- $start_date = mktime(0,0,0,$start_array[1],15,$start_array[0]);
282
- $out .= '<span style="white-space:nowrap;">' . date("F, Y", $start_date) . "</span>";
283
- return $out;
 
284
  }
285
- $out .= '<span style="white-space:nowrap;">' . date("M j, Y", $start_date) . "</span>";
286
- return $out;
287
  }
288
-
289
- if ($start_array[0] == $end_array[0]) {
290
- if ($start_array[1] == $end_array[1]) {
291
- $out .= '<span style="white-space:nowrap;">' . date("M j", $start_date) . "-" . date("j, Y", $end_date) . "</span>";
292
- return $out;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  }
294
- $out .= '<span style="white-space:nowrap;">' . date("M j", $start_date) . "-" . date("M j, Y", $end_date) . "</span>";
295
- return $out;
296
-
297
  }
298
-
299
- $out .= '<span style="white-space:nowrap;">' . date("M j, Y", $start_date) . "-" . date("M j, Y", $end_date) . "</span>";
300
  return $out;
301
  }
302
 
 
303
  private static function create_tabs( $current = 'general' ) {
304
  $tabs = array( 'general' => 'General settings', 'comment_list' => 'Comment-list settings', 'comment_form' => 'Comment-form settings',
305
  'comment_form_html' => 'Comment-form html code', 'comment_html' => 'Comment html code' );
@@ -382,72 +381,5 @@ class el_admin {
382
  <textarea name="'.$name.'" id="'.$name.'" rows="20" class="large-text code">'.$value.'</textarea>';
383
  return $out;
384
  }
385
-
386
- // function to truncate and shorten html text
387
- private static function truncate( $maxLength, $html ) {
388
- $printedLength = 0;
389
- $position = 0;
390
- $tags = array();
391
-
392
- $out = '';
393
-
394
- while ($printedLength < $maxLength && preg_match('{</?([a-z]+)[^>]*>|&#?[a-zA-Z0-9]+;}', $html, $match, PREG_OFFSET_CAPTURE, $position)) {
395
- list($tag, $tagPosition) = $match[0];
396
-
397
- // Print text leading up to the tag.
398
- $str = substr($html, $position, $tagPosition - $position);
399
- if ($printedLength + strlen($str) > $maxLength) {
400
- $out .= substr($str, 0, $maxLength - $printedLength);
401
- $printedLength = $maxLength;
402
- break;
403
- }
404
-
405
- $out .= $str;
406
- $printedLength += strlen($str);
407
-
408
- if ($tag[0] == '&') {
409
- // Handle the entity.
410
- $out .= $tag;
411
- $printedLength++;
412
- }
413
- else {
414
- // Handle the tag.
415
- $tagName = $match[1][0];
416
- if ($tag[1] == '/')
417
- {
418
- // This is a closing tag.
419
- $openingTag = array_pop($tags);
420
- assert($openingTag == $tagName); // check that tags are properly nested.
421
- $out .= $tag;
422
- }
423
- else if ($tag[strlen($tag) - 2] == '/') {
424
- // Self-closing tag.
425
- $out .= $tag;
426
- }
427
- else {
428
- // Opening tag.
429
- $out .= $tag;
430
- $tags[] = $tagName;
431
- }
432
- }
433
-
434
- // Continue after the tag.
435
- $position = $tagPosition + strlen($tag);
436
- }
437
-
438
- // Print any remaining text.
439
- if ($printedLength < $maxLength && $position < strlen($html)) {
440
- $out .= substr($html, $position, $maxLength - $printedLength);
441
- }
442
- if ($maxLength < strlen($html)) {
443
- $out .= "...";
444
- }
445
-
446
- // Close any open tags.
447
- while (!empty($tags)) {
448
- $out .= "</" . array_pop($tags) . ">";
449
- }
450
- return $out;
451
- }
452
  }
453
  ?>
1
  <?php
2
  //require_once( EL_PATH.'php/options.php' );
3
  require_once( EL_PATH.'php/db.php' );
4
+ require_once( EL_PATH.'php/admin_event_table.php' );
5
 
6
  // This class handles all available admin pages
7
  class el_admin {
8
+ private static $event_action = false;
9
+ private static $event_action_error = false;
10
+
11
  // show the main admin page as a submenu of "Comments"
12
  public static function show_main() {
13
  if ( !current_user_can( 'edit_posts' ) ) {
14
  wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
15
  }
16
+ $action = '';
17
+ // is there POST data an event was edited must be updated
 
 
 
 
 
18
  if( !empty( $_POST ) ) {
19
+ self::$event_action_error = !el_db::update_event( $_POST );
20
+ self::$event_action = isset( $_POST['id'] ) ? 'modified' : 'added';
21
  }
22
+ // get action
23
+ if( isset( $_GET['action'] ) ) {
24
+ $action = $_GET['action'];
 
 
25
  }
26
+ // if an event should be edited a different page must be displayed
27
+ if( $action === 'edit' ) {
28
+ self::show_edit();
29
+ return;
30
+ }
31
+ // delete events if required
32
+ if( $action === 'delete' && isset( $_GET['id'] ) ) {
33
+ self::$event_action_error = !el_db::delete_events( $_GET['id'] );
34
+ self::$event_action = 'deleted';
 
 
 
 
35
  }
36
+ // automatically set order of table to date, if no manual sorting is set
37
+ if( !isset( $_GET['orderby'] ) ) {
38
+ $_GET['orderby'] = 'date';
39
+ $_GET['order'] = 'asc';
40
+ }
41
+
42
+ // headline for the normal page
43
+ $out ='
44
+ <div class="wrap">
45
+ <div id="icon-edit-pages" class="icon32"><br /></div><h2>Events <a href="?page=el_admin_new" class="add-new-h2">Add New</a></h2>';
46
+ // added messages if required
47
+ $out .= self::show_messages();
48
+ // list event table
49
+ $out .= self::list_events();
50
  $out .= '</div>';
51
  echo $out;
52
  }
54
  public static function show_new() {
55
  $out = '<div class="wrap">
56
  <div class="wrap nosubsub" style="padding-bottom:15px">
57
+ <div id="icon-edit-pages" class="icon32"><br /></div><h2>Add New Event</h2>
58
  </div>';
59
  $out .= self::edit_event();
60
  $out .= '</div>';
156
  echo '<script type="text/javascript" src="'.EL_URL.'/js/admin.js"></script>';
157
  }
158
 
159
+ public static function embed_table_style() {
160
+ // add styles for event table
161
+ $out = '<style type="text/css">
162
+ .wp-list-table .column-date { width: 140px; }
163
+ .wp-list-table .column-title { width: 35%; }
164
+ .wp-list-table .column-location { width: 25% }
165
+ .wp-list-table .column-details { width: 40%; }
166
+ .wp-list-table .column-pub_user { width: 90px; }
167
+ .wp-list-table .column-pub_date { width: 150px; }
168
+ </style>';
169
+ echo $out;
170
+ }
171
+
172
  private static function list_events() {
173
+ // show calendar navigation
 
 
 
 
 
174
  $out = el_db::html_calendar_nav();
175
+ // set date range of events being displayed
176
+ $date_range = 'upcoming';
177
+ if( isset( $_GET['ytd'] ) && is_numeric( $_GET['ytd'] ) ) {
178
+ $date_range = $_GET['ytd'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  }
180
+ // show event table
181
+ // the form is required for bulk actions, the page field is required for plugins to ensure that the form posts back to the current page
182
+ $out .= '<form id="event-filter" method="get">
183
+ <input type="hidden" name="page" value="'.$_REQUEST['page'].'" />';
184
+ // show table
185
+ $table = new Admin_Event_Table();
186
+ $table->prepare_items( $date_range );
187
+ ob_start();
188
+ $table->display();
189
+ $out .= ob_get_contents();
190
+ ob_end_clean();
191
+ $out .= '</form>';
192
  return $out;
193
  }
194
 
195
  private static function edit_event() {
196
+ $edit = false;
197
+ if( isset( $_GET['id'] ) && is_numeric( $_GET['id'] ) ) {
 
198
  // existing event
199
  $event = el_db::get_event( $_GET['id'] );
200
+ if( isset( $_GET['action'] ) && $_GET['action'] === 'copy' ) {
201
  // copy of existing event
202
  $start_date = date('Y-m-d');
203
  $end_date = date('Y-m-d');
 
204
  }
205
  else {
206
  // edit existing event
207
  $start_date = $event->start_date;
208
  $end_date = $event->end_date;
209
+ $edit = true;
210
  }
211
  }
212
  else {
213
  //new event
214
  $start_date = date('Y-m-d');
215
  $end_date = date('Y-m-d');
 
216
  }
217
 
218
  $out = '<form method="POST" action="?page=el_admin_main">';
219
+ if ( true === $edit ) {
220
  $out .= '<input type="hidden" name="id" value="'.$_GET['id'].'" />';
221
  }
222
  $out .= '<table class="form-table">
260
  $out .= '<p class="submit"><input type="submit" class="button-primary" name="save" value="Save Event" id="submitbutton"> <a href="?page=el_admin_main" class="button-secondary">Cancel</a></p></form>';
261
  return $out;
262
  }
263
+
264
+ private static function show_messages() {
 
 
 
 
265
  $out = '';
266
+ // event added
267
+ if( 'added' === self::$event_action ) {
268
+ if( false === self::$event_action_error ) {
269
+ $out .= '<div id="message" class=updated below-h2"><p>New Event "'.$_POST['title'].'" was added.</p></div>';
270
+ }
271
+ else {
272
+ $out .= '<div id="message" class=error below-h2"><p>Error: New Event "'.$_POST['title'].'" could not be added.</p></div>';
273
  }
 
 
274
  }
275
+ // event modified
276
+ elseif( 'modified' === self::$event_action ) {
277
+ if( false === self::$event_action_error ) {
278
+ $out .= '<div id="message" class=updated below-h2"><p>Event "'.$_POST['title'].'" (id: '.$_POST['id'].') was modified.</p></div>';
279
+ }
280
+ else {
281
+ $out .= '<div id="message" class=error below-h2"><p>Error: Event "'.$_POST['title'].'" (id: '.$_POST['id'].') could not be modified.</p></div>';
282
+ }
283
+ }
284
+ // event deleted
285
+ elseif( 'deleted' === self::$event_action ) {
286
+ $num_deleted = count( explode( ',', $_GET['id'] ) );
287
+ $plural = '';
288
+ if( $num_deleted > 1 ) {
289
+ $plural = 's';
290
+ }
291
+ if( false === self::$event_action_error ) {
292
+ $out .= '<div id="message" class=updated below-h2"><p>'.$num_deleted.' Event'.$plural.' deleted (id'.$plural.': '.$_GET['id'].').</p></div>';
293
+ }
294
+ else {
295
+ $out .= '<div id="message" class=error below-h2"><p>Error while deleting '.$num_deleted.' Event'.$plural.'.</p></div>';
296
  }
 
 
 
297
  }
 
 
298
  return $out;
299
  }
300
 
301
+ // TODO: Function "create_tabs" not required yet, can be removed probably
302
  private static function create_tabs( $current = 'general' ) {
303
  $tabs = array( 'general' => 'General settings', 'comment_list' => 'Comment-list settings', 'comment_form' => 'Comment-form settings',
304
  'comment_form_html' => 'Comment-form html code', 'comment_html' => 'Comment html code' );
381
  <textarea name="'.$name.'" id="'.$name.'" rows="20" class="large-text code">'.$value.'</textarea>';
382
  return $out;
383
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
  }
385
  ?>
php/admin_event_table.php ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // load the base class (WP_List_Table class isn't automatically available)
3
+ if(!class_exists('WP_List_Table')){
4
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
5
+ }
6
+ require_once( EL_PATH.'php/db.php' );
7
+
8
+ class Admin_Event_Table extends WP_List_Table {
9
+ public function __construct() {
10
+ global $status, $page;
11
+ //Set parent defaults
12
+ parent::__construct( array(
13
+ 'singular' => 'event', //singular name of the listed records
14
+ 'plural' => 'events', //plural name of the listed records
15
+ 'ajax' => false //does this table support ajax?
16
+ ) );
17
+ }
18
+
19
+ /** ************************************************************************
20
+ * This method is called when the parent class can't find a method
21
+ * specifically build for a given column.
22
+ *
23
+ * @param array $item A singular item (one full row's worth of data)
24
+ * @param array $column_name The name/slug of the column to be processed
25
+ * @return string Text or HTML to be placed inside the column <td>
26
+ ***************************************************************************/
27
+ protected function column_default($item, $column_name) {
28
+ switch($column_name){
29
+ case 'date' :
30
+ return $this->format_date( $item->start_date, $item->end_date, $item->time );
31
+ case 'details' :
32
+ return $this->truncate( 80, $item->details );
33
+ case 'pub_user' :
34
+ return get_userdata( $item->$column_name )->user_login;
35
+ default :
36
+ return $item->$column_name;
37
+ }
38
+ }
39
+
40
+ /** ************************************************************************
41
+ * This is a custom column method and is responsible for what is
42
+ * rendered in any column with a name/slug of 'title'.
43
+ *
44
+ * @see WP_List_Table::::single_row_columns()
45
+ * @param array $item A singular item (one full row's worth of data)
46
+ * @return string Text to be placed inside the column <td> (movie title only)
47
+ ***************************************************************************/
48
+ protected function column_title($item) {
49
+ //Prepare Columns
50
+ $actions = array(
51
+ 'edit' => '<a href="?page='.$_REQUEST['page'].'&id='.$item->id.'&action=edit">Edit</a>',
52
+ 'duplicate' => '<a href="?page=el_admin_new&id='.$item->id.'&action=copy">Duplicate</a>',
53
+ 'delete' => '<a href="#" onClick="eventlist_deleteEvent('.$item->id.');return false;">Delete</a>'
54
+ );
55
+
56
+ //Return the title contents
57
+ return sprintf( '<b>%1$s</b> <span style="color:silver">(id:%2$s)</span>%3$s',
58
+ $item->title,
59
+ $item->id,
60
+ $this->row_actions( $actions )
61
+ );
62
+ }
63
+
64
+ /** ************************************************************************
65
+ * Required if displaying checkboxes or using bulk actions! The 'cb' column
66
+ * is given special treatment when columns are processed.
67
+ *
68
+ * @see WP_List_Table::::single_row_columns()
69
+ * @param array $item A singular item (one full row's worth of data)
70
+ * @return string Text to be placed inside the column <td> (movie title only)
71
+ ***************************************************************************/
72
+ protected function column_cb($item) {
73
+ //Let's simply repurpose the table's singular label ("event")
74
+ //The value of the checkbox should be the record's id
75
+ return '<input type="checkbox" name="id[]" value="'.$item->id.'" />';
76
+ }
77
+
78
+ /** ************************************************************************
79
+ * This method dictates the table's columns and titles. This should returns
80
+ * an array where the key is the column slug (and class) and the value is
81
+ * the column's title text.
82
+ *
83
+ * @see WP_List_Table::::single_row_columns()
84
+ * @return array An associative array containing column information: 'slugs'=>'Visible Titles'
85
+ ***************************************************************************/
86
+ public function get_columns() {
87
+ return array(
88
+ 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
89
+ 'date' => 'Date',
90
+ 'title' => 'Event',
91
+ 'location' => 'Location',
92
+ 'details' => 'Details',
93
+ 'pub_user' => 'Author',
94
+ 'pub_date' => 'Published'
95
+ );
96
+ }
97
+
98
+ /** ************************************************************************
99
+ * If you want one or more columns to be sortable (ASC/DESC toggle), you
100
+ * will need to register it here. This should return an array where the key
101
+ * is the column that needs to be sortable, and the value is db column to
102
+ * sort by.
103
+ *
104
+ * @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
105
+ ***************************************************************************/
106
+ public function get_sortable_columns() {
107
+ $sortable_columns = array(
108
+ 'date' => array( 'date', true ), //true means its already sorted
109
+ 'title' => array( 'title', false ),
110
+ 'location' => array( 'location', false ),
111
+ 'pub_user' => array( 'pub_user', false ),
112
+ 'pub_date' => array( 'pub_date', false )
113
+ );
114
+ return $sortable_columns;
115
+
116
+ return array();
117
+ }
118
+
119
+ /** ************************************************************************
120
+ * Optional. If you need to include bulk actions in your list table, this is
121
+ * the place to define them. Bulk actions are an associative array in the format
122
+ * 'slug'=>'Visible Title'
123
+ * If this method returns an empty value, no bulk action will be rendered.
124
+ *
125
+ * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
126
+ ****************************************************************************/
127
+ public function get_bulk_actions() {
128
+ $actions = array(
129
+ 'delete_bulk' => 'Delete'
130
+ );
131
+ return $actions;
132
+ }
133
+
134
+ /** ************************************************************************
135
+ * Function to handle the process of the bulk actions.
136
+ *
137
+ * @see $this->prepare_items()
138
+ ***************************************************************************/
139
+ private function process_bulk_action() {
140
+ // TODO: bulk action must be integrated
141
+ //Detect when a bulk action is being triggered...
142
+ if( 'delete_bulk'===$this->current_action() ) {
143
+ // Show confirmation window before deleting
144
+ echo '<script language="JavaScript">eventlist_deleteEvent ("'.implode( ', ', $_GET['id'] ).'");</script>';
145
+ }
146
+ }
147
+
148
+ /** ************************************************************************
149
+ * In this function the data for the display is prepared.
150
+ *
151
+ * @param string $date_range Date range for displaying the events
152
+ * @uses $this->_column_headers
153
+ * @uses $this->items
154
+ * @uses $this->get_columns()
155
+ * @uses $this->get_sortable_columns()
156
+ * @uses $this->get_pagenum()
157
+ * @uses $this->set_pagination_args()
158
+ ***************************************************************************/
159
+ public function prepare_items( $date_range='upcoming' ) {
160
+ $per_page = 20;
161
+ // define column headers
162
+ $columns = $this->get_columns();
163
+ $hidden = array();
164
+ $sortable = $this->get_sortable_columns();
165
+ $this->_column_headers = array( $columns, $hidden, $sortable );
166
+ // handle the bulk actions
167
+ $this->process_bulk_action();
168
+ // get the required event data
169
+ $data = $this->get_events( $date_range );
170
+ // setup pagination
171
+ $current_page = $this->get_pagenum();
172
+ $total_items = count( $data );
173
+ $data = array_slice( $data, ( ( $current_page-1 )*$per_page ), $per_page );
174
+ $this->set_pagination_args( array(
175
+ 'total_items' => $total_items,
176
+ 'per_page' => $per_page,
177
+ 'total_pages' => ceil($total_items/$per_page)
178
+ ) );
179
+ // setup items which are used by the rest of the class
180
+ $this->items = $data;
181
+ }
182
+
183
+ private function get_events( $date_range ) {
184
+ // define sort_array
185
+ $order = 'ASC';
186
+ if( isset( $_GET['order'] ) && $_GET['order'] === 'desc' ) {
187
+ $order = 'DESC';
188
+ }
189
+ $orderby = '';
190
+ if( isset( $_GET['orderby'] ) ){
191
+ $orderby = $_GET['orderby'];
192
+ }
193
+ // set standard sort according date ASC, only when date should be sorted desc, DESC should be used
194
+ if( $orderby == 'date' && $order == 'DESC' ) {
195
+ $sort_array = array( 'start_date DESC', 'time DESC', 'end_date DESC');
196
+ }
197
+ else {
198
+ $sort_array = array( 'start_date ASC', 'time ASC', 'end_date ASC');
199
+ }
200
+ // add primary order column to the front of the standard sort array
201
+ switch( $orderby )
202
+ {
203
+ case 'title' :
204
+ array_unshift( $sort_array, 'title '.$order );
205
+ break;
206
+ case 'location' :
207
+ array_unshift( $sort_array, 'location '.$order );
208
+ break;
209
+ case 'pub_user' :
210
+ array_unshift( $sort_array, 'pub_user '.$order );
211
+ break;
212
+ case 'pub_date' :
213
+ array_unshift( $sort_array, 'pub_date '.$order );
214
+ break;
215
+ }
216
+ // get and return events in the correct order
217
+ return el_db::get_events( $date_range, $sort_array );
218
+ }
219
+
220
+ /** ************************************************************************
221
+ * In this function the start date, the end date and time is formated for
222
+ * the output.
223
+ *
224
+ * @param string $start_date The start date of the event
225
+ * @param string $end_date The end date of the event
226
+ * @param string $time The start time of the event
227
+ ***************************************************************************/
228
+ private function format_date( $start_date, $end_date, $start_time ) {
229
+ $start_array = explode("-", $start_date);
230
+ $start_date = mktime(0,0,0,$start_array[1],$start_array[2],$start_array[0]);
231
+ $end_array = explode("-", $end_date);
232
+ $end_date = mktime(0,0,0,$end_array[1],$end_array[2],$end_array[0]);
233
+ $out = '<span style="white-space:nowrap;">';
234
+ // one day event
235
+ if( $start_date == $end_date ) {
236
+ if ($start_array[2] == "00") {
237
+ $start_date = mktime(0,0,0,$start_array[1],15,$start_array[0]);
238
+ $out .= date("F, Y", $start_date);
239
+ }
240
+ else {
241
+ $out .= date("M j, Y", $start_date);
242
+ }
243
+ }
244
+ // multiday event with start and end date in the same year
245
+ elseif( $start_array[0] == $end_array[0] ) {
246
+ $out .= date("M j", $start_date).'-';
247
+ // same start and end month
248
+ if( $start_array[1] == $end_array[1] ) {
249
+ $out .= date("j, Y", $end_date);
250
+ }
251
+ // different start and end month
252
+ else {
253
+ $out .= date("M j, Y", $end_date);
254
+ }
255
+ }
256
+ // multiday event with different start and end year
257
+ else {
258
+ $out .= date("M j, Y", $start_date).'-<br />'.date("M j, Y", $end_date).'&nbsp;';
259
+ }
260
+ $out .= '<br />
261
+ '.$start_time.'</span>';
262
+ return $out;
263
+ }
264
+
265
+ // function to truncate and shorten html text
266
+ /** ************************************************************************
267
+ * Function to truncate and shorten text
268
+ *
269
+ * @param int $max_length The length to which the text should be shortened
270
+ * @param string $text The text which should be shortened
271
+ ***************************************************************************/
272
+ private static function truncate( $max_length, $text ) {
273
+ $printedLength = 0;
274
+ $position = 0;
275
+ $tags = array();
276
+ $out = '';
277
+ while ($printedLength < $max_length && preg_match('{</?([a-z]+)[^>]*>|&#?[a-zA-Z0-9]+;}', $text, $match, PREG_OFFSET_CAPTURE, $position)) {
278
+ list($tag, $tagPosition) = $match[0];
279
+ // Print text leading up to the tag.
280
+ $str = substr($text, $position, $tagPosition - $position);
281
+ if ($printedLength + strlen($str) > $max_length) {
282
+ $out .= substr($str, 0, $max_length - $printedLength);
283
+ $printedLength = $max_length;
284
+ break;
285
+ }
286
+ $out .= $str;
287
+ $printedLength += strlen($str);
288
+ if ($tag[0] == '&') {
289
+ // Handle the entity.
290
+ $out .= $tag;
291
+ $printedLength++;
292
+ }
293
+ else {
294
+ // Handle the tag.
295
+ $tagName = $match[1][0];
296
+ if ($tag[1] == '/')
297
+ {
298
+ // This is a closing tag.
299
+ $openingTag = array_pop($tags);
300
+ assert($openingTag == $tagName); // check that tags are properly nested.
301
+ $out .= $tag;
302
+ }
303
+ else if ($tag[strlen($tag) - 2] == '/') {
304
+ // Self-closing tag.
305
+ $out .= $tag;
306
+ }
307
+ else {
308
+ // Opening tag.
309
+ $out .= $tag;
310
+ $tags[] = $tagName;
311
+ }
312
+ }
313
+ // Continue after the tag.
314
+ $position = $tagPosition + strlen($tag);
315
+ }
316
+ // Print any remaining text.
317
+ if ($printedLength < $max_length && $position < strlen($text)) {
318
+ $out .= substr($text, $position, $max_length - $printedLength);
319
+ }
320
+ if ($max_length < strlen($text)) {
321
+ $out .= "...";
322
+ }
323
+ // Close any open tags.
324
+ while (!empty($tags)) {
325
+ $out .= "</" . array_pop($tags) . ">";
326
+ }
327
+ return $out;
328
+ }
329
+ }
330
+
php/db.php CHANGED
@@ -36,7 +36,7 @@ class el_db {
36
  return $wpdb->prefix.self::TABLE_NAME;
37
  }
38
 
39
- public static function get_events( $date_range='all' ) {
40
  global $wpdb;
41
 
42
  // set date for data base query
@@ -54,7 +54,7 @@ class el_db {
54
  $range_start = $date_range.'-01-01';
55
  $range_end = $date_range.'-12-31';
56
  }
57
- $sql = 'SELECT * FROM '.self::table_name().' WHERE (end_date >= "'.$range_start.'" AND start_date <= "'.$range_end.'") ORDER BY start_date ASC, time ASC, end_date ASC';
58
  return $wpdb->get_results( $sql );
59
  }
60
 
@@ -131,11 +131,19 @@ class el_db {
131
  else { // new event
132
  $wpdb->insert( self::table_name(), $sqldata, $sqltypes );
133
  }
 
134
  }
135
 
136
- public static function delete_event( $event_id ) {
137
  global $wpdb;
138
- $wpdb->query( $wpdb->prepare( 'DELETE FROM '.self::table_name().' WHERE id = "'.$event_id.'"' ) );
 
 
 
 
 
 
 
139
  }
140
 
141
  public static function extract_date( $datestring, $ret_format, &$ret_timestamp=NULL, &$ret_datearray=NULL ) {
@@ -160,38 +168,56 @@ class el_db {
160
  $first_year = self::get_event_date( 'first' );
161
  $last_year = self::get_event_date( 'last' );
162
 
163
- if( is_admin() ) {
164
- $url = "?page=el_admin_main&";
165
- }
166
- else if( get_option( 'permalink_structure' ) ) {
167
- $url = "?";
168
- }
169
- else {
170
- $existing = "?";
171
- foreach( $_GET as $k => $v ) {
172
- if( $k != "ytd" && $k != "event_id" ) $existing .= $k . "=" . $v . "&";
173
- }
174
- $url = $existing;
175
- }
176
-
177
  // Calendar Navigation
178
- $out = '<div id="eventlist_nav">';
179
- if( isset( $_GET['ytd'] ) || isset( $_GET['event_id'] ) ) {
180
- $out .= '<a href="'.$url.'">Upcoming</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  }
182
  else {
183
- $out .= '<strong>Upcoming</strong>';
184
- }
185
- for( $year=$last_year; $year>=$first_year; $year-- ) {
186
- $out .= ' | ';
187
- if( isset( $_GET['ytd'] ) && $year == $_GET['ytd'] ) {
188
- $out .= '<strong>'.$year.'</strong>';
189
  }
190
  else {
191
- $out .= '<a href="'.$url.'ytd='.$year.'">'.$year.'</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  }
 
193
  }
194
- $out .= '</div><br />';
195
 
196
  // Title (only if event details are viewed)
197
  if( isset( $_GET['event_id'] ) ) {
36
  return $wpdb->prefix.self::TABLE_NAME;
37
  }
38
 
39
+ public static function get_events( $date_range='all', $sort_array=array( 'start_date ASC', 'time ASC', 'end_date ASC') ) {
40
  global $wpdb;
41
 
42
  // set date for data base query
54
  $range_start = $date_range.'-01-01';
55
  $range_end = $date_range.'-12-31';
56
  }
57
+ $sql = 'SELECT * FROM '.self::table_name().' WHERE (end_date >= "'.$range_start.'" AND start_date <= "'.$range_end.'") ORDER BY '.implode( ', ', $sort_array );
58
  return $wpdb->get_results( $sql );
59
  }
60
 
131
  else { // new event
132
  $wpdb->insert( self::table_name(), $sqldata, $sqltypes );
133
  }
134
+ return true;
135
  }
136
 
137
+ public static function delete_events( $event_ids ) {
138
  global $wpdb;
139
+ // sql query
140
+ $num_deleted = (int) $wpdb->query( $wpdb->prepare( 'DELETE FROM '.self::table_name().' WHERE id IN ('.$event_ids.')' ) );
141
+ if( $num_deleted == count( explode( ',', $event_ids ) ) ) {
142
+ return true;
143
+ }
144
+ else {
145
+ return false;
146
+ }
147
  }
148
 
149
  public static function extract_date( $datestring, $ret_format, &$ret_timestamp=NULL, &$ret_datearray=NULL ) {
168
  $first_year = self::get_event_date( 'first' );
169
  $last_year = self::get_event_date( 'last' );
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  // Calendar Navigation
172
+ if( true === is_admin() ) {
173
+ $url = "?page=el_admin_main";
174
+ $out = '<ul class="subsubsub">';
175
+ if( isset( $_GET['ytd'] ) || isset( $_GET['event_id'] ) ) {
176
+ $out .= '<li class="upcoming"><a href="'.$url.'">Upcoming</a></li>';
177
+ }
178
+ else {
179
+ $out .= '<li class="upcoming"><a class="current" href="'.$url.'">Upcoming</a></li>';
180
+ }
181
+ for( $year=$last_year; $year>=$first_year; $year-- ) {
182
+ $out .= ' | ';
183
+ if( isset( $_GET['ytd'] ) && $year == $_GET['ytd'] ) {
184
+ $out .= '<li class="year"><a class="current" href="'.$url.'&ytd='.$year.'">'.$year.'</a></li>';
185
+ }
186
+ else {
187
+ $out .= '<li class="year"><a href="'.$url.'&ytd='.$year.'">'.$year.'</a></li>';
188
+ }
189
+ }
190
+ $out .= '</ul><br />';
191
  }
192
  else {
193
+ if( get_option( 'permalink_structure' ) ) {
194
+ $url = "?";
 
 
 
 
195
  }
196
  else {
197
+ $existing = "?";
198
+ foreach( $_GET as $k => $v ) {
199
+ if( $k != "ytd" && $k != "event_id" ) $existing .= $k . "=" . $v . "&";
200
+ }
201
+ $url = $existing;
202
+ }
203
+ $out = '<div class="subsubsub">';
204
+ if( isset( $_GET['ytd'] ) || isset( $_GET['event_id'] ) ) {
205
+ $out .= '<a href="'.$url.'">Upcoming</a>';
206
+ }
207
+ else {
208
+ $out .= '<strong>Upcoming</strong>';
209
+ }
210
+ for( $year=$last_year; $year>=$first_year; $year-- ) {
211
+ $out .= ' | ';
212
+ if( isset( $_GET['ytd'] ) && $year == $_GET['ytd'] ) {
213
+ $out .= '<strong>'.$year.'</strong>';
214
+ }
215
+ else {
216
+ $out .= '<a href="'.$url.'ytd='.$year.'">'.$year.'</a>';
217
+ }
218
  }
219
+ $out .= '</div><br />';
220
  }
 
221
 
222
  // Title (only if event details are viewed)
223
  if( isset( $_GET['event_id'] ) ) {
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: event, events, list, listview, calendar, schedule, shortcode, page, category, categories, admin, attribute, widget, sidebar
5
  Requires at least: 3.3
6
  Tested up to: 3.4.2
7
- Stable tag: 0.1.1
8
  Plugin URI: http://wordpress.org/extend/plugins/event-list
9
  Licence: GPLv2
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -53,6 +53,15 @@ not available yet
53
 
54
  == Changelog ==
55
 
 
 
 
 
 
 
 
 
 
56
  = 0.1.1 (2012-09-24) =
57
 
58
  * fixed an issue with additional quotes after adding or editing an event
4
  Tags: event, events, list, listview, calendar, schedule, shortcode, page, category, categories, admin, attribute, widget, sidebar
5
  Requires at least: 3.3
6
  Tested up to: 3.4.2
7
+ Stable tag: 0.2.0
8
  Plugin URI: http://wordpress.org/extend/plugins/event-list
9
  Licence: GPLv2
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
53
 
54
  == Changelog ==
55
 
56
+ = 0.2.0 (2012-09-29) =
57
+
58
+ * adapted menu names to wordpress standard (similar to posts and pages)
59
+ * adapted event list table admin page to wordpress standard layout
60
+ * used wordpress included table view for admin event table
61
+ * added sort functionality in admin event table
62
+ * added bulk action delete in admin event table
63
+ * added status messages for added, modified and deleted events on admin page
64
+
65
  = 0.1.1 (2012-09-24) =
66
 
67
  * fixed an issue with additional quotes after adding or editing an event