Event List - Version 0.6.0

Version Description

(2013-12-31) = * added adjustment options for the filterbar (shortcode attribute "filterbar_items") * added "All" and "Past" options to years filter in filterbar * added category filter option in filterbar * change "cat_filter" behavior with additional features * added option to display categorys/years filter in a dropdown * added reset option to filterbar * added category filter selection in admin event table * added shortcode attribute "initial_date" * renamed shortcode attribute "show_nav" into "show_filterbar" * renamed url parameter "ytd" to "years" * removed underline before event-list id in url * some css fixes * some help text updates

Attention: In this version some of the shortcode attributes and the behavior of some existing attributes have changed and are not compatible with the old version! Please check all your shortcodes after the update. Additionally the url parameter has changed. So if you are using existing links to an eventlist with parameters you have to update them. Also existing widgets must be updated after plugin upgrade. Please visit the widget admin page and press save for all evenlist wigets.

Download this release

Release Info

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

Code changes from version 0.5.2 to 0.6.0

admin/css/admin_about.css CHANGED
@@ -9,7 +9,7 @@
9
  .el-atts-table {
10
  border: 1px solid #aaa;
11
  border-collapse: collapse;
12
- width: 95%;
13
  }
14
  .el-atts-table th {
15
  border: 1px solid #aaa;
@@ -21,15 +21,35 @@
21
  padding: 2px 5px !important;
22
  vertical-align: top;
23
  }
24
-
25
- .el-atts-table-name {
26
  width: 110px;
27
  }
28
 
29
- .el-atts-table-options {
30
- width: 110px;
 
 
 
31
  }
32
-
33
- .el-atts-table-default {
34
- width: 110px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
9
  .el-atts-table {
10
  border: 1px solid #aaa;
11
  border-collapse: collapse;
12
+ width: 98%;
13
  }
14
  .el-atts-table th {
15
  border: 1px solid #aaa;
21
  padding: 2px 5px !important;
22
  vertical-align: top;
23
  }
24
+ .el-atts-table-name, .el-atts-table-options, .el-atts-table-default {
 
25
  width: 110px;
26
  }
27
 
28
+ .el-filterbar-table {
29
+ border: 1px solid #aaa;
30
+ border-collapse: collapse;
31
+ width: 100%;
32
+ margin: 0.2em 0 1.2em 0;
33
  }
34
+ .el-filterbar-table th {
35
+ border: 1px solid #aaa;
36
+ padding: 1px 3px !important;
37
+ background: #eeeeee;
38
+ }
39
+ .el-filterbar-table td {
40
+ border: 1px solid #aaa;
41
+ padding: 1px 4px !important;
42
+ vertical-align: top;
43
+ }
44
+ .el-filterbar-item, .el-filterbar-doption {
45
+ width: 85px;
46
+ }
47
+ .el-filterbar-options, .el-filterbar-values {
48
+ width: 90px;
49
+ }
50
+ .el-filterbar-default {
51
+ width: 70px;
52
+ }
53
+ .el-filterbar-desc2, .el-filterbar-for {
54
+ width: 270px;
55
  }
admin/includes/admin-about.php CHANGED
@@ -33,12 +33,12 @@ class EL_Admin_About {
33
  <li>you can add the <strong>widget</strong> "Event List" in your sidebars</li></ul>
34
  The displayed events and their style can be modified with the available widget settings and the available attributes for the shortcode.<br />
35
  A list of all available shortcode attributes with their description is available below.<br />
36
- The most available options of the widget should be clear by there description.<br />
37
- It is important to know that you have to insert an URL to the linked event-list page if you enable one of the links options ("Add links to the single events" or "Add a link to an event page").
38
- This is required because the widget didn´t know in which page or post you have insert the shortcode.<br />
39
  Additonally you have to insert the correct Shortcode ID on the linked page. This ID describes which shortcode should be used on the given page or post if you have more than one.
40
- So the standard value "1" is normally o.k., but you can check the ID if you have a look into the URL of an event link on your linked page or post.
41
- The ID is given behind the "_" (e.g. <i>http://www.your-homepage.com/?page_id=99&event_id_<strong>1</strong>=11</i>).
42
  </p>
43
  <p>Be sure to also check the <a href="admin.php?page=el_admin_settings">Settings page</a> to get Event List behaving just the way you want.</p>
44
  </div>';
@@ -52,11 +52,11 @@ class EL_Admin_About {
52
 
53
  private function show_atts() {
54
  $out = '
55
- <h3 class="el-headline">AShortcode Attributes</h3>
56
  <div>
57
  You have the possibility to modify the output if you add some of the following attributes to the shortcode.<br />
58
- You can combine as much attributes as you want. E.g.the shortcode including the attributes "num_events" and "show_nav" would looks like this:
59
- <p><code>[event-list num_events=10 show_nav=false]</code></p>
60
  <p>Below you can find a list of all supported attributes with their descriptions and available options:</p>';
61
  $out .= $this->show_atts_table();
62
  $out .= '
33
  <li>you can add the <strong>widget</strong> "Event List" in your sidebars</li></ul>
34
  The displayed events and their style can be modified with the available widget settings and the available attributes for the shortcode.<br />
35
  A list of all available shortcode attributes with their description is available below.<br />
36
+ The available widget options are described in their tooltip text.<br />
37
+ For the widget it is important to know that you have to insert an URL to the linked event-list page if you enable one of the links options ("Add links to the single events" or "Add a link to an event page").
38
+ This is required because the widget didn´t know in which page or post the shortcode was included.<br />
39
  Additonally you have to insert the correct Shortcode ID on the linked page. This ID describes which shortcode should be used on the given page or post if you have more than one.
40
+ So the standard value "1" is normally o.k., but if required you can check the ID by looking into the URL of an event link on your linked page or post.
41
+ The ID will be added at the end of the query parameter name (e.g. <i>http://www.your-homepage.com/?page_id=99&event_id<strong>1</strong>=11</i>).
42
  </p>
43
  <p>Be sure to also check the <a href="admin.php?page=el_admin_settings">Settings page</a> to get Event List behaving just the way you want.</p>
44
  </div>';
52
 
53
  private function show_atts() {
54
  $out = '
55
+ <h3 class="el-headline">Shortcode Attributes</h3>
56
  <div>
57
  You have the possibility to modify the output if you add some of the following attributes to the shortcode.<br />
58
+ You can combine as much attributes as you want. E.g.the shortcode including the attributes "num_events" and "show_filterbar" would looks like this:
59
+ <p><code>[event-list num_events=10 show_filterbar=false]</code></p>
60
  <p>Below you can find a list of all supported attributes with their descriptions and available options:</p>';
61
  $out .= $this->show_atts_table();
62
  $out .= '
admin/includes/admin-main.php CHANGED
@@ -5,13 +5,15 @@ if(!defined('ABSPATH')) {
5
 
6
  require_once(EL_PATH.'includes/db.php');
7
  require_once(EL_PATH.'admin/includes/event_table.php');
 
8
 
9
  // This class handles all data for the admin main page
10
  class EL_Admin_Main {
11
  private static $instance;
12
  private $db;
13
- private $event_action = false;
14
- private $event_action_error = false;
 
15
 
16
  public static function &get_instance() {
17
  // Create class instance if required
@@ -24,161 +26,176 @@ class EL_Admin_Main {
24
 
25
  private function __construct() {
26
  $this->db = &EL_Db::get_instance();
27
- $this->event_action = null;
28
- $this->event_action_error = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
30
 
31
  // show the main admin page
32
  public function show_main() {
 
33
  if(!current_user_can('edit_posts')) {
34
  wp_die(__('You do not have sufficient permissions to access this page.'));
35
  }
36
- $action = '';
37
  // is there POST data an event was edited must be updated
38
- if(!empty($_POST)) {
39
- $this->event_action_error = !$this->db->update_event($_POST, __('Y/m/d'));
40
- $this->event_action = isset($_POST['id']) ? 'modified' : 'added';
41
- }
42
- // get action
43
- if(isset($_GET['action'])) {
44
- $action = $_GET['action'];
45
- }
46
- // if an event should be edited a different page must be displayed
47
- if($action === 'edit') {
48
- $this->show_edit();
49
- return;
50
- }
51
- // delete events if required
52
- if($action === 'delete' && isset($_GET['id'])) {
53
- $this->event_action_error = !$this->db->delete_events(explode(',', $_GET['id']));
54
- $this->event_action = 'deleted';
55
  }
56
- // automatically set order of table to date, if no manual sorting is set
 
57
  if(!isset($_GET['orderby'])) {
 
58
  $_GET['orderby'] = 'date';
59
  $_GET['order'] = 'asc';
60
  }
 
 
 
 
61
 
62
- // headline for the normal page
63
- $out ='
 
 
 
 
 
 
64
  <div class="wrap">
65
- <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>';
66
- // added messages if required
67
- $out .= $this->show_messages();
68
- // list event table
69
- $out .= $this->list_events();
70
- $out .= '</div>';
71
- echo $out;
72
  }
73
 
74
- private function show_edit() {
75
- $out = '<div class="wrap">
76
- <div id="icon-edit-pages" class="icon32"><br /></div><h2>Edit Event</h2>';
77
  require_once(EL_PATH.'admin/includes/admin-new.php');
78
- $out .= EL_Admin_New::get_instance()->edit_event();
79
- $out .= '</div>';
80
- echo $out;
81
  }
82
 
83
  public function embed_main_scripts() {
84
  // If edit event is selected switch to embed admin_new
85
- if(isset($_GET['action']) && 'edit' === $_GET['action']) {
86
- require_once(EL_PATH.'admin/includes/admin-new.php');
87
- EL_Admin_New::get_instance()->embed_new_scripts();
88
- }
89
- else {
90
- // Proceed with embedding for admin_main
91
- wp_enqueue_script('eventlist_admin_main_js', EL_URL.'admin/js/admin_main.js');
92
- wp_enqueue_style('eventlist_admin_main', EL_URL.'admin/css/admin_main.css');
 
 
 
93
  }
94
  }
95
 
96
- private function list_events() {
97
- // show calendar navigation
98
- $out = $this->show_calendar_nav();
99
- // set date range of events being displayed
100
- $date_range = 'upcoming';
101
- if(isset($_GET['ytd']) && is_numeric($_GET['ytd'])) {
102
- $date_range = $_GET['ytd'];
103
- }
104
  // show event table
105
  // 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
106
  $out .= '<form id="event-filter" method="get">
107
  <input type="hidden" name="page" value="'.$_REQUEST['page'].'" />';
108
  // show table
109
- $table = new EL_Event_Table();
110
- $table->prepare_items($date_range);
111
  ob_start();
112
- $table->display();
113
  $out .= ob_get_contents();
114
  ob_end_clean();
115
  $out .= '</form>';
116
  return $out;
117
  }
118
 
119
- private function show_calendar_nav() {
120
- $first_year = $this->db->get_event_date('first');
121
- $last_year = $this->db->get_event_date('last');
122
-
123
- // Calendar Navigation
124
- if(true === is_admin()) {
125
- $url = "?page=el_admin_main";
126
- $out = '<ul class="subsubsub">';
127
- if(isset($_GET['ytd']) || isset($_GET['event_id'])) {
128
- $out .= '<li class="upcoming"><a href="'.$url.'">Upcoming</a></li>';
129
- }
130
- else {
131
- $out .= '<li class="upcoming"><a class="current" href="'.$url.'">Upcoming</a></li>';
132
- }
133
- for($year=$last_year; $year>=$first_year; $year--) {
134
- $out .= ' | ';
135
- if(isset($_GET['ytd']) && $year == $_GET['ytd']) {
136
- $out .= '<li class="year"><a class="current" href="'.$url.'ytd='.$year.'">'.$year.'</a></li>';
137
- }
138
- else {
139
- $out .= '<li class="year"><a href="'.$url.'&amp;ytd='.$year.'">'.$year.'</a></li>';
140
- }
141
- }
142
- $out .= '</ul><br />';
143
  }
144
- return $out;
145
  }
146
 
147
- private function show_messages() {
148
- $out = '';
149
- // event added
150
- if('added' === $this->event_action) {
151
- if(false === $this->event_action_error) {
152
- $out .= '<div id="message" class="updated below-h2"><p><strong>New Event "'.stripslashes($_POST['title']).'" was added.</strong></p></div>';
153
- }
154
- else {
155
- $out .= '<div id="message" class="error below-h2"><p><strong>Error: New Event "'.stripslashes($_POST['title']).'" could not be added.</strong></p></div>';
156
- }
157
- }
158
- // event modified
159
- elseif('modified' === $this->event_action) {
160
- if(false === $this->event_action_error) {
161
- $out .= '<div id="message" class="updated below-h2"><p><strong>Event "'.stripslashes($_POST['title']).'" (id: '.$_POST['id'].') was modified.</strong></p></div>';
162
- }
163
- else {
164
- $out .= '<div id="message" class="error below-h2"><p><strong>Error: Event "'.stripslashes($_POST['title']).'" (id: '.$_POST['id'].') could not be modified.</strong></p></div>';
165
- }
166
  }
167
- // event deleted
168
- elseif('deleted' === $this->event_action) {
169
- $num_deleted = count(explode(',', $_GET['id']));
170
- $plural = '';
171
- if($num_deleted > 1) {
172
- $plural = 's';
173
- }
174
- if(false === $this->event_action_error) {
175
- $out .= '<div id="message" class="updated below-h2"><p><strong>'.$num_deleted.' Event'.$plural.' deleted (id'.$plural.': '.$_GET['id'].').</strong></p></div>';
176
- }
177
- else {
178
- $out .= '<div id="message" class="error below-h2"><p><strong>Error while deleting '.$num_deleted.' Event'.$plural.'.</strong></p></div>';
179
- }
180
  }
181
- return $out;
 
 
182
  }
183
  }
184
- ?>
5
 
6
  require_once(EL_PATH.'includes/db.php');
7
  require_once(EL_PATH.'admin/includes/event_table.php');
8
+ require_once(EL_PATH.'includes/filterbar.php');
9
 
10
  // This class handles all data for the admin main page
11
  class EL_Admin_Main {
12
  private static $instance;
13
  private $db;
14
+ private $filterbar;
15
+ private $event_table;
16
+ private $action;
17
 
18
  public static function &get_instance() {
19
  // Create class instance if required
26
 
27
  private function __construct() {
28
  $this->db = &EL_Db::get_instance();
29
+ $this->filterbar = &EL_Filterbar::get_instance();
30
+ $this->event_table = new EL_Event_Table();
31
+ $this->action = $this->event_table->current_action();
32
+ // check for real actions
33
+ if($this->action) {
34
+ switch($this->action) {
35
+ // real actions (redirect when finished)
36
+ case 'new':
37
+ if(!empty($_POST)) {
38
+ $id = $this->db->update_event($_POST, __('Y/m/d'));
39
+ $error = !$id;
40
+ $this->redirect('added', $error, array('title' => $_POST['title'], 'id' => $id));
41
+ }
42
+ case 'edited':
43
+ if(!empty($_POST)) {
44
+ $error = !$this->db->update_event($_POST, __('Y/m/d'));
45
+ $this->redirect('modified', $error, array('title' => $_POST['title'], 'id' => $_POST['id']));
46
+ }
47
+ break;
48
+ case 'delete':
49
+ if(isset($_GET['id'])) {
50
+ $error = !$this->db->delete_events(explode(',', $_GET['id']));
51
+ $this->redirect('deleted', $error, array('id' => $_GET['id']));
52
+ }
53
+ break;
54
+ }
55
+ }
56
+ // cleanup query args when filter button was pressed
57
+ if(isset($_GET['filter'])) {
58
+ $this->redirect();
59
+ }
60
  }
61
 
62
  // show the main admin page
63
  public function show_main() {
64
+ // check permissions
65
  if(!current_user_can('edit_posts')) {
66
  wp_die(__('You do not have sufficient permissions to access this page.'));
67
  }
68
+ // TODO: add check_admin_referer to improve security (see /wp-admin/edit.php)
69
  // is there POST data an event was edited must be updated
70
+
71
+ // check for actions
72
+ if($this->action) {
73
+ switch($this->action) {
74
+ // actions showing edit view
75
+ case 'edit':
76
+ case 'added':
77
+ case 'modified':
78
+ $this->show_edit_view($this->action);
79
+ return;
80
+
81
+ // actions showing event list
82
+ case 'deleted':
83
+ // nothing to do
84
+ break;
85
+ }
 
86
  }
87
+
88
+ // proceed with normal event list page
89
  if(!isset($_GET['orderby'])) {
90
+ // set initial sorting
91
  $_GET['orderby'] = 'date';
92
  $_GET['order'] = 'asc';
93
  }
94
+ $this->show_page_header($this->action);
95
+ echo $this->show_event_table();
96
+ echo '</div>';
97
+ }
98
 
99
+ private function show_page_header($action, $editview=false) {
100
+ if($editview) {
101
+ $header = 'Edit Event';
102
+ }
103
+ else {
104
+ $header = 'Events <a href="?page=el_admin_new" class="add-new-h2">Add New</a>';
105
+ }
106
+ echo '
107
  <div class="wrap">
108
+ <div id="icon-edit-pages" class="icon32"><br /></div><h2>'.$header.'</h2>';
109
+ $this->show_message($action);
 
 
 
 
 
110
  }
111
 
112
+ private function show_edit_view($action) {
113
+ $this->show_page_header($action, true);
 
114
  require_once(EL_PATH.'admin/includes/admin-new.php');
115
+ echo EL_Admin_New::get_instance()->edit_event();
116
+ echo '</div>';
 
117
  }
118
 
119
  public function embed_main_scripts() {
120
  // If edit event is selected switch to embed admin_new
121
+ switch($this->action) {
122
+ case 'edit':
123
+ case 'added':
124
+ case 'modified':
125
+ // embed admin new script
126
+ require_once(EL_PATH.'admin/includes/admin-new.php');
127
+ EL_Admin_New::get_instance()->embed_new_scripts();
128
+ default:
129
+ // embed admin_main script
130
+ wp_enqueue_script('eventlist_admin_main_js', EL_URL.'admin/js/admin_main.js');
131
+ wp_enqueue_style('eventlist_admin_main', EL_URL.'admin/css/admin_main.css');
132
  }
133
  }
134
 
135
+ private function show_event_table() {
136
+ // show filterbar
137
+ $out = '';
 
 
 
 
 
138
  // show event table
139
  // 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
140
  $out .= '<form id="event-filter" method="get">
141
  <input type="hidden" name="page" value="'.$_REQUEST['page'].'" />';
142
  // show table
143
+ $this->event_table->prepare_items();
 
144
  ob_start();
145
+ $this->event_table->display();
146
  $out .= ob_get_contents();
147
  ob_end_clean();
148
  $out .= '</form>';
149
  return $out;
150
  }
151
 
152
+ private function show_message($action) {
153
+ $error = isset($_GET['error']);
154
+ switch($action) {
155
+ case 'added':
156
+ if(!$error)
157
+ $this->show_update_message('New Event "'.stripslashes($_GET['title']).'" was added.');
158
+ else
159
+ $this->show_error_message('Error: New Event "'.stripslashes($_GET['title']).'" could not be added.');
160
+ break;
161
+ case 'modified':
162
+ if(!$error)
163
+ $this->show_update_message('Event "'.stripslashes($_GET['title']).'" (id: '.$_GET['id'].') was modified.');
164
+ else
165
+ $this->show_error_message('Error: Event "'.stripslashes($_GET['title']).'" (id: '.$_GET['id'].') could not be modified.');
166
+ break;
167
+ case 'deleted':
168
+ $num_deleted = count(explode(',', $_GET['id']));
169
+ $plural = ($num_deleted > 1) ? 's' : '';
170
+ if(!$error)
171
+ $this->show_update_message($num_deleted.' Event'.$plural.' deleted (id'.$plural.': '.$_GET['id'].').');
172
+ else
173
+ $this->show_error_message('Error while deleting '.$num_deleted.' Event'.$plural.'.');
174
+ break;
 
175
  }
 
176
  }
177
 
178
+ private function show_update_message($text) {
179
+ echo '
180
+ <div id="message" class="updated below-h2"><p><strong>'.$text.'</strong></p></div>';
181
+ }
182
+
183
+ private function show_error_message($text) {
184
+ echo '
185
+ <div id="message" class="error below-h2"><p><strong>'.$text.'</strong></p></div>';
186
+ }
187
+
188
+ private function redirect($action=false, $error=false, $query_args=array()) {
189
+ $url = remove_query_arg(array('action', 'action2', 'filter', '_wpnonce', '_wp_http_referer'), $_SERVER['REQUEST_URI']);
190
+ if($action) {
191
+ $url = add_query_arg('action', $action, $url);
 
 
 
 
 
192
  }
193
+ if($error) {
194
+ $url = add_query_arg('error', '1', $url);
 
 
 
 
 
 
 
 
 
 
 
195
  }
196
+ $url = add_query_arg($query_args, $url);
197
+ wp_redirect($url);
198
+ exit;
199
  }
200
  }
201
+ ?>
admin/includes/admin-new.php CHANGED
@@ -58,13 +58,13 @@ class EL_Admin_New {
58
  }
59
  else {
60
  //new event
61
- $start_date = time()+1*24*60*60;
62
  $end_date = $start_date;
63
  }
64
 
65
  // Add required data for javascript in a hidden field
66
  $json = json_encode(array('el_url' => EL_URL,
67
- 'el_date_format' => $this->datepicker_format(__('Y/m/d'))));
68
  $out = '
69
  <form method="POST" action="?page=el_admin_main">';
70
  $out .= "
@@ -78,8 +78,12 @@ class EL_Admin_New {
78
  <div id="post-body" class="metabox-holder columns-2">
79
  <div id="post-body-content">';
80
  if(true === $edit) {
 
81
  $out .= '<input type="hidden" name="id" value="'.$_GET['id'].'" />';
82
  }
 
 
 
83
  $out .= '<table class="form-table">
84
  <tr>
85
  <th><label>Event Title (required)</label></th>
58
  }
59
  else {
60
  //new event
61
+ $start_date = current_time('timestamp')+86400; // next day (86400 seconds = 1*24*60*60 = 1 day);
62
  $end_date = $start_date;
63
  }
64
 
65
  // Add required data for javascript in a hidden field
66
  $json = json_encode(array('el_url' => EL_URL,
67
+ 'el_date_format' => $this->datepicker_format(__('Y/m/d'))));
68
  $out = '
69
  <form method="POST" action="?page=el_admin_main">';
70
  $out .= "
78
  <div id="post-body" class="metabox-holder columns-2">
79
  <div id="post-body-content">';
80
  if(true === $edit) {
81
+ $out .= '<input type="hidden" name="action" value="edited" />';
82
  $out .= '<input type="hidden" name="id" value="'.$_GET['id'].'" />';
83
  }
84
+ else {
85
+ $out .= '<input type="hidden" name="action" value="new" />';
86
+ }
87
  $out .= '<table class="form-table">
88
  <tr>
89
  <th><label>Event Title (required)</label></th>
admin/includes/event_table.php CHANGED
@@ -1,22 +1,27 @@
1
  <?php
2
- if( !defined( 'ABSPATH' ) ) {
3
  exit;
4
  }
5
 
6
  // load the base class (WP_List_Table class isn't automatically available)
7
  if(!class_exists('WP_List_Table')){
8
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
9
  }
10
- require_once( EL_PATH.'includes/db.php' );
11
- require_once( EL_PATH.'includes/categories.php' );
 
12
 
13
  class EL_Event_Table extends WP_List_Table {
14
  private $db;
15
  private $categories;
 
 
16
 
17
  public function __construct() {
18
  $this->db = &EL_Db::get_instance();
19
  $this->categories = &EL_Categories::get_instance();
 
 
20
 
21
  global $status, $page;
22
  //Set parent defaults
@@ -36,19 +41,19 @@ class EL_Event_Table extends WP_List_Table {
36
  * @return string Text or HTML to be placed inside the column <td>
37
  ***************************************************************************/
38
  protected function column_default($item, $column_name) {
39
- switch($column_name){
40
  case 'date' :
41
- return $this->format_event_date( $item->start_date, $item->end_date, $item->time );
42
  case 'details' :
43
- return '<div>'.$this->db->truncate( 80, $item->details ).'</div>';
44
  case 'pub_user' :
45
- return get_userdata( $item->pub_user )->user_login;
46
  case 'pub_date' :
47
- return $this->format_pub_date( $item->pub_date );
48
  case 'categories' :
49
- return $this->categories->get_category_string( $item->$column_name );
50
  default :
51
- return $item->$column_name;
52
  }
53
  }
54
 
@@ -65,15 +70,13 @@ class EL_Event_Table extends WP_List_Table {
65
  $actions = array(
66
  'edit' => '<a href="?page='.$_REQUEST['page'].'&amp;id='.$item->id.'&amp;action=edit">Edit</a>',
67
  'duplicate' => '<a href="?page=el_admin_new&amp;id='.$item->id.'&amp;action=copy">Duplicate</a>',
68
- 'delete' => '<a href="#" onClick="eventlist_deleteEvent('.$item->id.');return false;">Delete</a>'
69
- );
70
 
71
  //Return the title contents
72
- return sprintf( '<b>%1$s</b> <span style="color:silver">(id:%2$s)</span>%3$s',
73
- $item->title,
74
  $item->id,
75
- $this->row_actions( $actions )
76
- );
77
  }
78
 
79
  /** ************************************************************************
@@ -158,6 +161,21 @@ class EL_Event_Table extends WP_List_Table {
158
  }
159
  }
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  /** ************************************************************************
162
  * In this function the data for the display is prepared.
163
  *
@@ -169,7 +187,7 @@ class EL_Event_Table extends WP_List_Table {
169
  * @uses $this->get_pagenum()
170
  * @uses $this->set_pagination_args()
171
  ***************************************************************************/
172
- public function prepare_items( $date_range='upcoming' ) {
173
  $per_page = 20;
174
  // define column headers
175
  $columns = $this->get_columns();
@@ -179,7 +197,7 @@ class EL_Event_Table extends WP_List_Table {
179
  // handle the bulk actions
180
  $this->process_bulk_action();
181
  // get the required event data
182
- $data = $this->get_events( $date_range );
183
  // setup pagination
184
  $current_page = $this->get_pagenum();
185
  $total_items = count( $data );
@@ -193,7 +211,23 @@ class EL_Event_Table extends WP_List_Table {
193
  $this->items = $data;
194
  }
195
 
196
- private function get_events( $date_range ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  // define sort_array
198
  $order = 'ASC';
199
  if( isset( $_GET['order'] ) && $_GET['order'] === 'desc' ) {
@@ -227,7 +261,7 @@ class EL_Event_Table extends WP_List_Table {
227
  break;
228
  }
229
  // get and return events in the correct order
230
- return $this->db->get_events( $date_range, 0, null, $sort_array );
231
  }
232
 
233
  /** ************************************************************************
@@ -254,8 +288,9 @@ class EL_Event_Table extends WP_List_Table {
254
  $start_time = mysql2date( get_option( 'time_format' ), $start_time );
255
  }
256
  $out .= '<br />
257
- <span class="time">'.$start_time.'</span></span>';
258
  }
 
259
  return $out;
260
  }
261
 
1
  <?php
2
+ if(!defined('ABSPATH')) {
3
  exit;
4
  }
5
 
6
  // load the base class (WP_List_Table class isn't automatically available)
7
  if(!class_exists('WP_List_Table')){
8
+ require_once(ABSPATH.'wp-admin/includes/class-wp-list-table.php');
9
  }
10
+ require_once(EL_PATH.'includes/db.php');
11
+ require_once(EL_PATH.'includes/categories.php');
12
+ require_once(EL_PATH.'includes/filterbar.php');
13
 
14
  class EL_Event_Table extends WP_List_Table {
15
  private $db;
16
  private $categories;
17
+ private $filterbar;
18
+ private $args;
19
 
20
  public function __construct() {
21
  $this->db = &EL_Db::get_instance();
22
  $this->categories = &EL_Categories::get_instance();
23
+ $this->filterbar = &EL_Filterbar::get_instance();
24
+ $this->set_args();
25
 
26
  global $status, $page;
27
  //Set parent defaults
41
  * @return string Text or HTML to be placed inside the column <td>
42
  ***************************************************************************/
43
  protected function column_default($item, $column_name) {
44
+ switch($column_name) {
45
  case 'date' :
46
+ return $this->format_event_date($item->start_date, $item->end_date, $item->time);
47
  case 'details' :
48
+ return '<div>'.esc_html($this->db->truncate(80, $item->details)).'</div>';
49
  case 'pub_user' :
50
+ return get_userdata($item->pub_user)->user_login;
51
  case 'pub_date' :
52
+ return $this->format_pub_date($item->pub_date);
53
  case 'categories' :
54
+ return esc_html($this->categories->get_category_string($item->$column_name));
55
  default :
56
+ return esc_html($item->$column_name);
57
  }
58
  }
59
 
70
  $actions = array(
71
  'edit' => '<a href="?page='.$_REQUEST['page'].'&amp;id='.$item->id.'&amp;action=edit">Edit</a>',
72
  'duplicate' => '<a href="?page=el_admin_new&amp;id='.$item->id.'&amp;action=copy">Duplicate</a>',
73
+ 'delete' => '<a href="#" onClick="eventlist_deleteEvent('.$item->id.');return false;">Delete</a>');
 
74
 
75
  //Return the title contents
76
+ return sprintf('<b>%1$s</b> <span style="color:silver">(id:%2$s)</span>%3$s',
77
+ esc_html($item->title),
78
  $item->id,
79
+ $this->row_actions($actions));
 
80
  }
81
 
82
  /** ************************************************************************
161
  }
162
  }
163
 
164
+ public function extra_tablenav($which) {
165
+ $out = '';
166
+ // add filter elements
167
+ if('top' === $which) {
168
+ $out = '
169
+ <div class="alignleft actions">';
170
+ $out .= $this->filterbar->show_years('?page=el_admin_main', $this->args, 'dropdown', 'admin');
171
+ $out .= $this->filterbar->show_cats('?page=el_admin_main', $this->args, 'dropdown', 'admin');
172
+ $out .= '
173
+ <input id="event-query-submit" class="button" type="submit" name ="filter" value="'.__('Filter').'" />
174
+ </div>';
175
+ }
176
+ echo $out;
177
+ }
178
+
179
  /** ************************************************************************
180
  * In this function the data for the display is prepared.
181
  *
187
  * @uses $this->get_pagenum()
188
  * @uses $this->set_pagination_args()
189
  ***************************************************************************/
190
+ public function prepare_items() {
191
  $per_page = 20;
192
  // define column headers
193
  $columns = $this->get_columns();
197
  // handle the bulk actions
198
  $this->process_bulk_action();
199
  // get the required event data
200
+ $data = $this->get_events();
201
  // setup pagination
202
  $current_page = $this->get_pagenum();
203
  $total_items = count( $data );
211
  $this->items = $data;
212
  }
213
 
214
+ private function set_args() {
215
+ // filters
216
+ $this->args['date_filter'] = 'all';
217
+ $this->args['cat_filter'] = 'all';
218
+ // actual_date
219
+ $this->args['actual_date'] = 'upcoming';
220
+ if(isset($_GET['date']) && (is_numeric($_GET['date']) || 'all' == $_GET['date'] || 'upcoming' == $_GET['date'])) {
221
+ $this->args['actual_date'] = $_GET['date'];
222
+ }
223
+ // actual_cat
224
+ $this->args['actual_cat'] = 'all';
225
+ if(isset($_GET['cat'])) {
226
+ $this->args['actual_cat'] = $_GET['cat'];
227
+ }
228
+ }
229
+
230
+ private function get_events() {
231
  // define sort_array
232
  $order = 'ASC';
233
  if( isset( $_GET['order'] ) && $_GET['order'] === 'desc' ) {
261
  break;
262
  }
263
  // get and return events in the correct order
264
+ return $this->db->get_events($this->args['actual_date'], $this->args['actual_cat'], 0, $sort_array);
265
  }
266
 
267
  /** ************************************************************************
288
  $start_time = mysql2date( get_option( 'time_format' ), $start_time );
289
  }
290
  $out .= '<br />
291
+ <span class="time">'.$start_time.'</span>';
292
  }
293
+ $out .= '</span>';
294
  return $out;
295
  }
296
 
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.5.2
7
  Author: Michael Burtscher
8
  Author URI: http://wordpress.org/extend/plugins/event-list/
9
  License: GPLv2
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.6.0
7
  Author: Michael Burtscher
8
  Author URI: http://wordpress.org/extend/plugins/event-list/
9
  License: GPLv2
includes/css/event-list.css CHANGED
@@ -1,6 +1,10 @@
 
 
 
 
1
  ul.event-list-view, ul.single-event-view {
2
  list-style: none !important;
3
- margin: 1em 0 1.5em 0;
4
  padding: 0;
5
  }
6
 
@@ -50,7 +54,7 @@ li.event {
50
  text-transform: uppercase;
51
  font-size: 1.0em;
52
  line-height: 1em;
53
- padding: 0.4em 0 0.4em 0;
54
  }
55
 
56
  .event-year {
@@ -70,7 +74,7 @@ li.event {
70
 
71
  .event-title h3 {
72
  clear: none;
73
- margin: 0;
74
  padding: 0;
75
  }
76
 
@@ -98,3 +102,25 @@ div.feed a * {
98
  div.feed img {
99
  margin: 0 5px 0 2px;
100
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .event-list {
2
+ clear: both;
3
+ }
4
+
5
  ul.event-list-view, ul.single-event-view {
6
  list-style: none !important;
7
+ margin: 1.5em 0 2em 0;
8
  padding: 0;
9
  }
10
 
54
  text-transform: uppercase;
55
  font-size: 1.0em;
56
  line-height: 1em;
57
+ padding: 0.4em 0;
58
  }
59
 
60
  .event-year {
74
 
75
  .event-title h3 {
76
  clear: none;
77
+ margin: 0 !important;
78
  padding: 0;
79
  }
80
 
102
  div.feed img {
103
  margin: 0 5px 0 2px;
104
  }
105
+
106
+ div.filterbar, div.filterbar div {
107
+ clear both;
108
+ margin: 1em 0;
109
+ vertical-align: middle;
110
+ }
111
+
112
+ div.filterbar select.dropdown, div.filterbar ul.hlist, div.filterbar a.link {
113
+ margin: 0 3px;
114
+ vertical-align: middle;
115
+ }
116
+
117
+ div.filterbar ul.hlist li {
118
+ float: left;
119
+ list-style-type: none;
120
+ margin: 0;
121
+ }
122
+
123
+ div.filterbar ul.hlist li + li:before {
124
+ content: "|";
125
+ padding: 0 1px;
126
+ }
includes/db.php CHANGED
@@ -51,32 +51,14 @@ class EL_Db {
51
  }
52
  }
53
 
54
- public function get_events( $date_range='all', $num_events=0, $cat_filter=null, $sort_array=array( 'start_date ASC', 'time ASC', 'end_date ASC') ) {
55
  global $wpdb;
56
-
57
- // set date for data base query
58
- if( is_numeric( $date_range ) ) {
59
- // get events of a specific year
60
- $range_start = $date_range.'-01-01';
61
- $range_end = $date_range.'-12-31';
62
- }
63
- elseif( 'all' === $date_range ) {
64
- // get all events
65
- $range_start = '0000-01-01';
66
- $range_end = '9999-12-31';
67
- }
68
- else { // upcoming
69
- // get only events in the future
70
- $range_start = date( 'Y-m-d' );
71
- $range_end = '9999-12-31';
72
- }
73
- // set category filter
74
- $sql_cat_filter = empty( $cat_filter ) ? '' : ' AND ( categories LIKE "%|'.implode( '|%" OR categories LIKE "%|', $cat_filter ).'|%" )';
75
- $sql = 'SELECT * FROM '.$this->table.' WHERE end_date >= "'.$range_start.'" AND start_date <= "'.$range_end.'"'.$sql_cat_filter.' ORDER BY '.implode( ', ', $sort_array );
76
- if( 'upcoming' === $date_range && is_numeric($num_events) && 0 < $num_events ) {
77
  $sql .= ' LIMIT '.$num_events;
78
  }
79
- return $wpdb->get_results( $sql );
80
  }
81
 
82
  public function get_event( $id ) {
@@ -102,7 +84,7 @@ class EL_Db {
102
  $date = $this->extract_date( $date[0][$search_date],'Y');
103
  }
104
  else {
105
- $date = date("Y");
106
  }
107
  return $date;
108
  }
@@ -122,7 +104,7 @@ class EL_Db {
122
  //pub_user
123
  $sqldata['pub_user'] = isset($event_data['id']) ? $event_data['pub_user'] : wp_get_current_user()->ID;
124
  //pub_date
125
- $sqldata['pub_date'] = isset($event_data['pub_date']) ? $event_data['pub_date'] : date("Y-m-d H:i:s");
126
  }
127
  //start_date
128
  if( !isset( $event_data['start_date']) ) { return false; }
@@ -157,13 +139,13 @@ class EL_Db {
157
  else { $sqldata['categories'] = '|'.implode( '|', $event_data['categories'] ).'|'; }
158
  //types for sql data
159
  $sqltypes = array( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' );
160
- if( isset( $event_data['id'] ) ) { // update event
161
- $wpdb->update( $this->table, $sqldata, array( 'id' => $event_data['id'] ), $sqltypes );
162
  }
163
  else { // new event
164
- $wpdb->insert( $this->table, $sqldata, $sqltypes );
 
165
  }
166
- return true;
167
  }
168
 
169
  public function delete_events( $event_ids ) {
@@ -247,6 +229,70 @@ class EL_Db {
247
  return date( $ret_format, $timestamp );
248
  }
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  /** ************************************************************************
251
  * Function to truncate and shorten text
252
  *
51
  }
52
  }
53
 
54
+ public function get_events($date_filter=null, $cat_filter=null, $num_events=0, $sort_array=array('start_date ASC', 'time ASC', 'end_date ASC')) {
55
  global $wpdb;
56
+ $where_string = $this->get_sql_filter_string($date_filter, $cat_filter);
57
+ $sql = 'SELECT * FROM '.$this->table.' WHERE '.$where_string.' ORDER BY '.implode(', ', $sort_array);
58
+ if('upcoming' === $date_filter && is_numeric($num_events) && 0 < $num_events) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  $sql .= ' LIMIT '.$num_events;
60
  }
61
+ return $wpdb->get_results($sql);
62
  }
63
 
64
  public function get_event( $id ) {
84
  $date = $this->extract_date( $date[0][$search_date],'Y');
85
  }
86
  else {
87
+ $date = date('Y', current_time('timestamp'));
88
  }
89
  return $date;
90
  }
104
  //pub_user
105
  $sqldata['pub_user'] = isset($event_data['id']) ? $event_data['pub_user'] : wp_get_current_user()->ID;
106
  //pub_date
107
+ $sqldata['pub_date'] = isset($event_data['pub_date']) ? $event_data['pub_date'] : date("Y-m-d H:i:s", current_time('timestamp'));
108
  }
109
  //start_date
110
  if( !isset( $event_data['start_date']) ) { return false; }
139
  else { $sqldata['categories'] = '|'.implode( '|', $event_data['categories'] ).'|'; }
140
  //types for sql data
141
  $sqltypes = array( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' );
142
+ if(isset( $event_data['id'] ) ) { // update event
143
+ return $wpdb->update($this->table, $sqldata, array('id' => $event_data['id']), $sqltypes);
144
  }
145
  else { // new event
146
+ $wpdb->insert($this->table, $sqldata, $sqltypes);
147
+ return $wpdb->insert_id;
148
  }
 
149
  }
150
 
151
  public function delete_events( $event_ids ) {
229
  return date( $ret_format, $timestamp );
230
  }
231
 
232
+ private function get_sql_filter_string($date_filter=null, $cat_filter=null) {
233
+ $sql_filter_string = '';
234
+ // date filter
235
+ $date_filter=str_replace(' ','',$date_filter);
236
+ if(null != $date_filter && 'all' != $date_filter && '' != $date_filter) {
237
+ if(is_numeric($date_filter)) {
238
+ // get events of a specific year
239
+ $range_start = $date_filter.'-01-01';
240
+ $range_end = $date_filter.'-12-31';
241
+ }
242
+ elseif('past' === $date_filter) {
243
+ // get only events in the past
244
+ $range_start = '0000-01-01';
245
+ $range_end = date('Y-m-d', current_time('timestamp')-86400); // previous day (86400 seconds = 1*24*60*60 = 1 day))
246
+ }
247
+ else { // upcoming
248
+ // get only events from today and in the future
249
+ $range_start = date('Y-m-d', current_time('timestamp'));
250
+ $range_end = '9999-12-31';
251
+ }
252
+ $sql_filter_string .= '(end_date >= "'.$range_start.'" AND start_date <= "'.$range_end.'")';
253
+ }
254
+
255
+ // cat_filter
256
+ $cat_filter=str_replace(' ', '', $cat_filter);
257
+ if(null != $cat_filter && 'all' != $cat_filter && '' != $cat_filter) {
258
+ if('' != $sql_filter_string) {
259
+ $sql_filter_string .= ' AND ';
260
+ }
261
+ $sql_filter_string .= '(';
262
+ $delimiters = array('&' => ' AND ',
263
+ '|' => ' OR ',
264
+ ',' => ' OR ',
265
+ '(' => '(',
266
+ ')' => ')');
267
+ $delimiter_keys = array_keys($delimiters);
268
+ $tmp_element = '';
269
+ $len_cat_filter = strlen($cat_filter);
270
+ for($i=0; $i<$len_cat_filter; $i++) {
271
+ if(in_array($cat_filter[$i], $delimiter_keys)) {
272
+ if('' !== $tmp_element) {
273
+ $sql_filter_string .= 'categories LIKE "%|'.$tmp_element.'|%"';
274
+ $tmp_element = '';
275
+ }
276
+ $sql_filter_string .= $delimiters[$cat_filter[$i]];
277
+ }
278
+ else {
279
+ $tmp_element .= $cat_filter[$i];
280
+ }
281
+ }
282
+ if('' !== $tmp_element) {
283
+ $sql_filter_string .= 'categories LIKE "%|'.$tmp_element.'|%"';
284
+ }
285
+ $sql_filter_string .= ')';
286
+ }
287
+
288
+ // no filter
289
+ if('' == $sql_filter_string) {
290
+ $sql_filter_string = '1'; // in SQL "WHERE 1" is used to show all events
291
+ }
292
+
293
+ return $sql_filter_string;
294
+ }
295
+
296
  /** ************************************************************************
297
  * Function to truncate and shorten text
298
  *
includes/filterbar.php ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if(!defined('ABSPATH')) {
3
+ exit;
4
+ }
5
+
6
+ require_once( EL_PATH.'includes/db.php' );
7
+ //require_once( EL_PATH.'includes/options.php' );
8
+ require_once( EL_PATH.'includes/categories.php' );
9
+
10
+ // This class handles the navigation and filter bar
11
+ class EL_Filterbar {
12
+ private static $instance;
13
+ private $db;
14
+ // private $options;
15
+ private $categories;
16
+
17
+ public static function &get_instance() {
18
+ // Create class instance if required
19
+ if( !isset( self::$instance ) ) {
20
+ self::$instance = new EL_Filterbar();
21
+ }
22
+ // Return class instance
23
+ return self::$instance;
24
+ }
25
+
26
+ private function __construct() {
27
+ $this->db = &EL_Db::get_instance();
28
+ // $this->options = &EL_Options::get_instance();
29
+ $this->categories = &EL_Categories::get_instance();
30
+ }
31
+
32
+ // main function to show the rendered HTML output
33
+ public function show($url, $args) {
34
+ $out = '
35
+ <style type="text/css">
36
+ .filterbar { display:table; width:100% }
37
+ .filterbar > div { display:table-cell }
38
+ </style>
39
+ <!--[if lte IE 7]>
40
+ <style>.filterbar > div { float:left }</style>
41
+ <![endif]-->
42
+ <div class="filterbar subsubsub">';
43
+ // prepare filterbar-items
44
+ //split 3 section (left, center, right) seperated by semicolon
45
+ $sections = explode(";", $args['filterbar_items']);
46
+ $section_align = array('left', 'center', 'right');
47
+ for($i=0; $i<sizeof($sections) && $i<3; $i++) {
48
+ if(strlen($sections[$i]) > 0) {
49
+ $out .= '
50
+ <div style="text-align:'.$section_align[$i].'">';
51
+ //split items in section seperated by comma
52
+ $items = explode(",", $sections[$i]);
53
+ foreach($items as $item) {
54
+ //search for item options
55
+ $options = array();
56
+ $item_array = explode("(", $item);
57
+ if(sizeof($item_array) > 1) {
58
+ // options available
59
+ $option_array = explode("|", substr($item_array[1],0,-1));
60
+ foreach($option_array as $option_text) {
61
+ $o = explode("=", $option_text);
62
+ $options[$o[0]] = $o[1];
63
+ }
64
+ }
65
+ $item_array = explode("_", $item_array[0]);
66
+ switch($item_array[0]) {
67
+ case 'years':
68
+ $out .= $this->show_years($url, $args, $item_array[1], 'std', $options);
69
+ break;
70
+ case 'cats':
71
+ $out .= $this->show_cats($url, $args, $item_array[1], 'std', $options);
72
+ break;
73
+ case 'reset':
74
+ $out .= $this->show_reset($url, $args);
75
+ }
76
+ }
77
+ $out .= '
78
+ </div>';
79
+ }
80
+ }
81
+ $out .= '</div>';
82
+ return $out;
83
+ }
84
+ /* TODO: implementation of show_all and show_upcoming
85
+ private function show_all() {
86
+ $elements[] = $this->all_element();
87
+ return $this->show_hlist($elements);
88
+ }
89
+
90
+ private function show_upcoming() {
91
+ $elements[] = $this->upcoming_element();
92
+ return $this->show_hlist($elements);
93
+ }
94
+ */
95
+ public function show_years($url, $args, $type='hlist', $subtype='std', $options=array()) {
96
+ $args = $this->parse_args($args);
97
+ $argname = 'date'.$args['sc_id_for_url'];
98
+ // prepare displayed elements
99
+ $elements = array();
100
+ if(!isset($options['show_all']) || 'true' == $options['show_all']) { // default is true
101
+ $elements[] = $this->all_element('hlist'==$type ? null : __('Show all dates'));
102
+ }
103
+ if(!isset($options['show_upcoming']) || 'true' == $options['show_upcoming']) { // default is true
104
+ $elements[] = $this->upcoming_element();
105
+ }
106
+ if(isset($options['show_past']) && 'true' == $options['show_past']) { // default is false
107
+ $elements[] = $this->past_element();
108
+ }
109
+ $first_year = $this->db->get_event_date('first');
110
+ $last_year = $this->db->get_event_date('last');
111
+ for($year=$last_year; $year>=$first_year; $year--) {
112
+ $elements[] = array('slug'=>$year, 'name'=>$year);
113
+ }
114
+ // filter elements acc. date_filter
115
+ /* TODO: implement date_filter
116
+ if('all' !== $args['date_filter']) {
117
+ $filter_array = explode(',', $args['date_filter']);
118
+ foreach($elements as $id => $element) {
119
+ if(!in_array($element['slug'], $filter_array) && 'all' !== $element['slug'] && 'upcoming' !== $element['slug'] && 'past' !== $element['slug']) {
120
+ unset($elements[$id]);
121
+ }
122
+ }
123
+ }*/
124
+ // set selection
125
+ if(is_numeric($args['event_id'])) {
126
+ $actual = null;
127
+ }
128
+ elseif('all' === $args['actual_date'] || 'upcoming' === $args['actual_date'] || 'past' === $args['actual_date'] || is_numeric($args['actual_date'])) {
129
+ $actual = $args['actual_date'];
130
+ }
131
+ else {
132
+ $actual = null;
133
+ }
134
+ if('dropdown' === $type) {
135
+ return $this->show_dropdown($elements, $argname, $subtype, $actual, $args['sc_id_for_url']);
136
+ }
137
+ else {
138
+ return $this->show_hlist($elements, $url, $argname, $actual);
139
+ }
140
+ }
141
+
142
+ public function show_cats($url, $args, $type='dropdown', $subtype='std', $options=array()) {
143
+ $args = $this->parse_args($args);
144
+ $argname = 'cat'.$args['sc_id_for_url'];
145
+ // prepare displayed elements
146
+ $cat_array = $this->categories->get_cat_array();
147
+ $elements = array();
148
+ if(!isset($options['show_all']) || 'true' == $options['show_all']) {
149
+ $elements[] = $this->all_element('hlist'==$type ? null : __('View all categories'));
150
+ }
151
+ foreach($cat_array as $cat) {
152
+ $elements[] = array('slug' => $cat['slug'], 'name' => str_pad('', 12*$cat['level'], '&nbsp;', STR_PAD_LEFT).$cat['name']);
153
+ }
154
+ // filter elements acc. cat_filter (if only OR connections are used)
155
+ if('all' !== $args['cat_filter'] && !strpos($args['cat_filter'], '&')) {
156
+ $tmp_filter = str_replace(array(' ', '(', ')'), '', $args['cat_filter']);
157
+ $tmp_filter = str_replace(',', '|', $tmp_filter);
158
+ $filter_array = explode('|', $tmp_filter);
159
+ foreach($elements as $id => $element) {
160
+ if(!in_array($element['slug'], $filter_array) && 'all' !== $element['slug']) {
161
+ unset($elements[$id]);
162
+ }
163
+ }
164
+ }
165
+ // set selection
166
+ $actual = isset($args['actual_cat']) ? $args['actual_cat'] : null;
167
+ if('hlist' === $type) {
168
+ return $this->show_hlist($elements, $url, $argname, $actual);
169
+ }
170
+ else {
171
+ return $this->show_dropdown($elements, $argname, $subtype, $actual, $args['sc_id_for_url']);
172
+ }
173
+ }
174
+
175
+ public function show_reset($url, $args) {
176
+ $args_to_remove = array('event_id'.$args['sc_id_for_url'],
177
+ 'date'.$args['sc_id_for_url'],
178
+ 'cat'.$args['sc_id_for_url']);
179
+ return $this->show_link(remove_query_arg($args_to_remove, $url), __('Reset'), 'link');
180
+ }
181
+
182
+ private function show_hlist($elements, $url, $name, $actual=null) {
183
+ $out = '<ul class="hlist">';
184
+ foreach($elements as $element) {
185
+ $out .= '<li>';
186
+ if($actual == $element['slug']) {
187
+ $out .= '<strong>'.$element['name'].'</strong>';
188
+ }
189
+ else {
190
+ $out .= $this->show_link(add_query_arg($name, $element['slug'], $url), $element['name']);
191
+ }
192
+ $out .= '</li>';
193
+ }
194
+ $out .= '</ul>';
195
+ return $out;
196
+ }
197
+
198
+ private function show_dropdown($elements, $name, $subtype='std', $actual=null, $sc_id='') {
199
+ $onchange = '';
200
+ if('admin' != $subtype) {
201
+ wp_register_script('el_filterbar', EL_URL.'includes/js/filterbar.js', null, true);
202
+ add_action('wp_footer', array(&$this, 'footer_script'));
203
+ $onchange = ' onchange="eventlist_redirect(this.name,this.value,'.$sc_id.')"';
204
+ }
205
+ $out = '<select class="dropdown" name="'.$name.'"'.$onchange.'>';
206
+ foreach($elements as $element) {
207
+ $out .= '
208
+ <option';
209
+ if($element['slug'] == $actual) {
210
+ $out .= ' selected="selected"';
211
+ }
212
+ $out .= ' value="'.$element['slug'].'">'.esc_html($element['name']).'</option>';
213
+ }
214
+ $out .= '
215
+ </select>';
216
+ return $out;
217
+ }
218
+
219
+ private function show_link($url, $caption, $class=null) {
220
+ $class = (null === $class) ? '' : ' class="'.$class.'"';
221
+ return '<a href="'.esc_url($url).'"'.$class.'>'.esc_html($caption).'</a>';
222
+ }
223
+
224
+ private function all_element($name=null) {
225
+ if(null == $name) {
226
+ $name = __('All');
227
+ }
228
+ return array('slug' => 'all', 'name' => $name);
229
+ }
230
+
231
+ private function upcoming_element() {
232
+ return array('slug' => 'upcoming', 'name' => __('Upcoming'));
233
+ }
234
+
235
+ private function past_element() {
236
+ return array('slug' => 'past', 'name' => __('Past'));
237
+ }
238
+
239
+ private function parse_args($args) {
240
+ $defaults = array('date' => null, 'event_id' => null, 'sc_id_for_url' => null);
241
+ $args = wp_parse_args($args, $defaults);
242
+ return $args;
243
+ }
244
+
245
+ public function footer_script() {
246
+ wp_print_scripts('el_filterbar');
247
+ }
248
+ }
249
+ ?>
includes/js/filterbar.js ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Javascript functions for event-list admin_main page
2
+
3
+ // Confirmation for event deletion
4
+ function eventlist_redirect(name, value, sc_id) {
5
+ window.location.assign(updateUrlParameter(window.location.href, name, value, sc_id));
6
+ }
7
+
8
+ function updateUrlParameter(url, paramName, paramVal, sc_id) {
9
+ // extrude anchor
10
+ var urlArray = url.split("#");
11
+ var anchor = urlArray[1] ? "#" + urlArray[1] : "";
12
+ // split base url and parameters
13
+ urlArray = urlArray[0].split("?");
14
+ var baseUrl = urlArray[0];
15
+ var oldParams = urlArray[1] ? urlArray[1] : null;
16
+ // create new parameter list
17
+ var newParams = "";
18
+ var seperator = "?";
19
+ var paramNameAdded = false;
20
+ if(null != oldParams.length) {
21
+ urlArray = oldParams.split("&");
22
+ for(i=0; i<urlArray.length; i++) {
23
+ if(urlArray[i].split("=")[0] == "event_id"+sc_id) {
24
+ // do nothing
25
+ }
26
+ else if(urlArray[i].split("=")[0] == paramName) {
27
+ newParams += seperator + paramName + "=" + paramVal;
28
+ paramNameAdded = true;
29
+ }
30
+ else {
31
+ newParams += seperator + urlArray[i];
32
+ }
33
+ seperator = "&";
34
+ }
35
+ }
36
+ // add paramName if not already done
37
+ if(!paramNameAdded) {
38
+ newParams += seperator + paramName + "=" + paramVal;
39
+ }
40
+ return baseUrl + newParams + anchor;
41
+ }
includes/sc_event-list.php CHANGED
@@ -34,30 +34,75 @@ class SC_Event_List {
34
  // All available attributes
35
  $this->atts = array(
36
 
37
- 'initial_date' => array( 'val' => 'upcoming<br />year e.g. "2013"',
38
  'std_val' => 'upcoming',
39
  'visible' => true,
40
  'desc' => 'This attribute specifies which events are initially shown. The standard is to show the upcoming events.<br />
41
- Specify a year e.g. "2013" to change this behavior.' ),
42
 
43
- 'cat_filter' => array( 'val' => 'none<br />category slug',
44
- 'std_val' => 'none',
45
  'visible' => true,
46
- 'desc' => 'This attribute specifies the categories of which events are shown. The standard is "none" to show all events.<br />
47
- Specify a category slug or a list of category slugs separated by a comma "," e.g. "tennis,hockey" to only show events of the specified categories.' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  'num_events' => array( 'val' => 'number',
50
  'std_val' => '0',
51
  'visible' => true,
52
  'desc' => 'This attribute specifies how many events should be displayed if upcoming events is selected.<br />
53
- 0 is the standard value which means that all events will be displayed.' ),
 
54
 
55
- 'show_nav' => array( 'val' => 'false<br />true<br />event_list_only<br />single_event_only',
56
  'std_val' => 'true',
57
  'visible' => true,
58
- 'desc' => 'This attribute specifies if the calendar navigation should be displayed.<br />
59
  Choose "false" to always hide and "true" to always show the navigation.<br />
60
- With "event_list_only" the navigation is only visible in the event list and with "single_event_only" only for a single event'),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  'show_starttime' => array( 'val' => 'false<br />true<br />event_list_only<br />single_event_only',
63
  'std_val' => 'true',
@@ -90,7 +135,7 @@ class SC_Event_List {
90
  'details_length' => array( 'val' => 'number',
91
  'std_val' => '0',
92
  'visible' => true,
93
- 'desc' => 'This attribute specifies if the details should be truncate to the given number of character in the event list.<br />
94
  With the standard value 0 the full details are displayed.<br />
95
  This attribute has no influence if only a single event is shown.'),
96
 
@@ -105,22 +150,22 @@ class SC_Event_List {
105
  'std_val' => 'false',
106
  'visible' => true,
107
  'desc' => 'This attribute specifies if a rss feed link should be added.<br />
108
- You have to enable the feed in the eventlist options to make this attribute workable.<br />
109
- In the options you can also find some settings to modify the output.<br />
110
  Choose "false" to never add and "true" to always add the link.<br />
111
  With "event_list_only" the link is only added in the event list and with "single_event_only" only for a single event'),
112
  // Invisible attributes ('visibe' = false): This attributes are required for the widget but will not be listed in the attributes table on the admin info page
113
  'title_length' => array( 'val' => 'number',
114
  'std_val' => '0',
115
  'visible' => false,
116
- 'desc' => 'This attribute specifies if the title should be truncate to the given number of character in the event list.<br />
117
  With the standard value 0 the full details are displayed.<br />
118
  This attribute has no influence if only a single event is shown.'),
119
 
120
  'location_length' => array( 'val' => 'number',
121
  'std_val' => '0',
122
  'visible' => false,
123
- 'desc' => 'This attribute specifies if the title should be truncate to the given number of character in the event list.<br />
124
  With the standard value 0 the full details are displayed.<br />
125
  This attribute has no influence if only a single event is shown.'),
126
 
@@ -138,7 +183,8 @@ class SC_Event_List {
138
  The empty standard value is o.k. for the normal use. This attribute is normally only required for the event-list widget.' ),
139
  // Internal attributes: This parameters will be added by the script and are not available in the shortcode
140
  // 'sc_id'
141
- // 'ytd'
 
142
  );
143
 
144
  $this->num_sc_loaded = 0;
@@ -172,12 +218,13 @@ class SC_Event_List {
172
  $a = shortcode_atts( $std_values, $atts );
173
  // add internal attributes
174
  $a['sc_id'] = $this->num_sc_loaded;
175
- $a['event_id'] = isset( $_GET['event_id_'.$a['sc_id']] ) ? (integer)$_GET['event_id_'.$a['sc_id']] : null;
176
- $a['ytd'] = $this->get_ytd( $a );
177
  // fix sc_id_for_url if required
178
  if( !is_numeric( $a['sc_id_for_url'] ) ) {
179
  $a['sc_id_for_url'] = $a['sc_id'];
180
  }
 
 
181
 
182
  $out = '
183
  <div class="event-list">';
@@ -198,7 +245,7 @@ class SC_Event_List {
198
 
199
  private function html_event_details( &$a ) {
200
  $event = $this->db->get_event( $a['event_id'] );
201
- $out = $this->html_calendar_nav( $a );
202
  $out .= '
203
  <h2>Event Information:</h2>
204
  <ul class="single-event-view">';
@@ -209,10 +256,11 @@ class SC_Event_List {
209
 
210
  private function html_events( &$a ) {
211
  // specify to show all events if not upcoming is selected
212
- if( is_numeric( $a['ytd'] ) ) {
213
  $a['num_events'] = 0;
214
  }
215
- $cat_filter = 'none' === $a['cat_filter'] ? null : explode( ',', $a['cat_filter'] );
 
216
  if( '1' !== $this->options->get( 'el_date_once_per_day' ) ) {
217
  // normal sort
218
  $sort_array = array( 'start_date ASC', 'time ASC', 'end_date ASC' );
@@ -221,12 +269,12 @@ class SC_Event_List {
221
  // sort according end_date before start time (required for option el_date_once_per_day)
222
  $sort_array = array( 'start_date ASC', 'end_date ASC', 'time ASC' );
223
  }
224
- $events = $this->db->get_events( $a['ytd'], $a['num_events'], $cat_filter, $sort_array );
225
 
226
  // generate output
227
  $out = '';
228
  $out .= $this->html_feed_link($a, 'top');
229
- $out .= $this->html_calendar_nav( $a );
230
  $out .= $this->html_feed_link($a, 'below_nav');
231
  if( empty( $events ) ) {
232
  // no events found
@@ -247,7 +295,7 @@ class SC_Event_List {
247
  }
248
 
249
  private function html_event( &$event, &$a, $single_day_only=false ) {
250
- static $last_event_startdate, $last_event_enddate;
251
  $max_length = is_numeric( $a['event_id'] ) ? 0 : 999999;
252
  $out = '
253
  <li class="event">';
@@ -264,16 +312,16 @@ class SC_Event_List {
264
  }
265
  $out .= '">';
266
 
267
- $out .= '<span class="event-title"><h3>';
268
 
269
  $title = esc_attr($this->db->truncate(min($max_length, $a['title_length']), $event->title));
270
  if( $this->is_visible( $a['link_to_event'] ) ) {
271
- $out .= '<a href="'.esc_html(add_query_arg('event_id_'.$a['sc_id_for_url'], $event->id, $this->get_url($a))).'">'.$title.'</a>';
272
  }
273
  else {
274
  $out .= $title;
275
  }
276
- $out .= '</h3></span>';
277
  if( $event->time != '' && $this->is_visible( $a['show_starttime'] ) ) {
278
  // set time format if a known format is available, else only show the text
279
  $date_array = date_parse( $event->time );
@@ -335,34 +383,13 @@ class SC_Event_List {
335
  return $out;
336
  }
337
 
338
- private function html_calendar_nav( &$a ) {
339
- $out = '';
340
- if( ! $this->is_visible( $a['show_nav'] ) ) {
341
- // no calendar navigation required
342
- return $out;
343
- }
344
- $first_year = $this->db->get_event_date( 'first' );
345
- $last_year = $this->db->get_event_date( 'last' );
346
-
347
- $url = $this->get_url( $a );
348
- $out .= '<div class="subsubsub">';
349
- if( is_numeric( $a['ytd'] ) || is_numeric( $a['event_id'] ) ) {
350
- $out .= '<a href="'.add_query_arg( 'ytd_'.$a['sc_id_for_url'], 'upcoming', $url ).'">Upcoming</a>';
351
- }
352
- else {
353
- $out .= '<strong>Upcoming</strong>';
354
- }
355
- for( $year=$last_year; $year>=$first_year; $year-- ) {
356
- $out .= ' | ';
357
- if( $year == $a['ytd'] ) {
358
- $out .= '<strong>'.$year.'</strong>';
359
- }
360
- else {
361
- $out .= '<a href="'.add_query_arg( 'ytd_'.$a['sc_id_for_url'], $year, $url ).'">'.$year.'</a>';
362
- }
363
  }
364
- $out .= '</div><br />';
365
- return $out;
 
366
  }
367
 
368
  private function html_feed_link(&$a, $pos) {
@@ -391,23 +418,55 @@ class SC_Event_List {
391
  return $out;
392
  }
393
 
394
- private function get_ytd( &$a ) {
395
- if( isset( $_GET['ytd_'.$a['sc_id']] ) && 'upcoming' === $_GET['ytd_'.$a['sc_id']] ){
396
- // ytd is 'upcoming'
397
- $ytd = 'upcoming';
398
  }
399
- elseif( isset( $_GET['ytd_'.$a['sc_id']] ) && is_numeric( $_GET['ytd_'.$a['sc_id']] ) ) {
400
- // ytd is a year
401
- $ytd = (int)$_GET['ytd_'.$a['sc_id']];
402
  }
403
- elseif( isset( $a['initial_date'] ) && is_numeric( $a['initial_date'] ) && !is_numeric( $a['event_id'] ) && !isset( $_GET['link_'.$a['sc_id']] ) ) {
404
- // initial_date attribute is set
405
- $ytd = (int)$a['initial_date'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  }
407
  else {
408
- $ytd = 'upcoming';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409
  }
410
- return $ytd;
411
  }
412
 
413
  private function get_url( &$a ) {
@@ -419,7 +478,7 @@ class SC_Event_List {
419
  // use actual page
420
  $url = get_permalink();
421
  foreach( $_GET as $k => $v ) {
422
- if( 'ytd_'.$a['sc_id'] !== $k && 'event_id_'.$a['sc_id'] !== $k && 'link_'.$a['sc_id'] !== $k ) {
423
  $url = add_query_arg( $k, $v, $url );
424
  }
425
  }
34
  // All available attributes
35
  $this->atts = array(
36
 
37
+ 'initial_date' => array( 'val' => 'all<br />upcoming<br />year e.g. "2014"',
38
  'std_val' => 'upcoming',
39
  'visible' => true,
40
  'desc' => 'This attribute specifies which events are initially shown. The standard is to show the upcoming events.<br />
41
+ Specify a year e.g. "2014" to change this behavior.'),
42
 
43
+ 'initial_cat' => array( 'val' => 'all<br />category slug',
44
+ 'std_val' => 'all',
45
  'visible' => true,
46
+ 'desc' => 'This attribute specifies the category of which events are initially shown. The standard is to show events of all categories.<br />
47
+ Specify a category slug to change this behavior. You can include a category selection in the filterbar to give users the possibility to change the displayed categories.'),
48
+ /*
49
+ 'date_filter' => array( 'val' => 'all<br />upcoming<br />year e.g. "2014"',
50
+ 'std_val' => 'all',
51
+ 'visible' => true,
52
+ 'desc' => 'This attribute specifies the date range of which events are displayed. The standard is "all" to show all events.<br />
53
+ Events defined in date ranges not listed here are also not available in the date selection in the filterbar. It is also not possible to show them with a manual added url parameter<br />
54
+ Specify a year or a list of years separated by a comma "," e.g. "2014,2015,2016".'),
55
+ */
56
+ 'cat_filter' => array( 'val' => 'all<br />category slugs',
57
+ 'std_val' => 'all',
58
+ 'visible' => true,
59
+ 'desc' => 'This attribute specifies the categories of which events are shown. The standard is "all" or an empty string to show all events.<br />
60
+ Events defined in categories which doesn´t match cat_filter are not shown in the event list. They are also not available if a manual url parameter is added.<br />
61
+ The filter is specified via the given category slug. You can use AND ("&") and OR ("|" or ",") connections to define complex filters. Additionally you can set brackets for nested queries.<br />
62
+ Examples:<br />
63
+ <code>tennis</code> ... Show all events with category "tennis".<br />
64
+ <code>tennis,hockey</code> ... Show all events with category "tennis" or "hockey".<br />
65
+ <code>tennis|(hockey&winter)</code> ... Show all events with category "tennis" and all events where category "hockey" as well as "winter" is selected.<br />
66
+ If you only use OR connections (no AND connection) the category selection in the filterbar will also be filtered according to the given filter.<br />'),
67
 
68
  'num_events' => array( 'val' => 'number',
69
  'std_val' => '0',
70
  'visible' => true,
71
  'desc' => 'This attribute specifies how many events should be displayed if upcoming events is selected.<br />
72
+ 0 is the standard value which means that all events will be displayed.<br />
73
+ Please not that in the actual version there is no pagination of the events available.'),
74
 
75
+ 'show_filterbar' => array( 'val' => 'false<br />true<br />event_list_only<br />single_event_only',
76
  'std_val' => 'true',
77
  'visible' => true,
78
+ 'desc' => 'This attribute specifies if the filterbar should be displayed. The filterbar allows the users to select filters to limit the listed events.<br />
79
  Choose "false" to always hide and "true" to always show the navigation.<br />
80
+ With "event_list_only" the filterbar is only visible in the event list and with "single_event_only" only for a single event'),
81
+
82
+ 'filterbar_items' => array( 'val' => 'years_hlist<br />years_dropdown<br />cats_hlist<br />cats_dropdown<br />reset_link',
83
+ 'std_val' => 'years_hlist',
84
+ 'visible' => true,
85
+ 'desc' => 'This attribute specifies the available items in the filterbar. This options are only valid if the filterbar is displayed (see show_filterbar attribute).<br /><br />
86
+ Find below an overview of the available filterbar items and their options:<br />
87
+ <small><table class="el-filterbar-table">
88
+ <th class="el-filterbar-item">filterbar item</th><th class="el-filterbar-desc">description</th><th class="el-filterbar-options">item options</th><th class="el-filterbar-values">option values</th><th class="el-filterbar-default">default value</th><th class="el-filterbar-desc2">description</th></thead>
89
+ <tr><td>years</td><td>Show a list of all available years. Additional there are some special entries available (see item options).</td><td>show_all<br />show_upcoming<br />show_past</td><td>true | false<br />true | false<br />true | false</td><td>true<br />true<br />false</td><td>Add an entry to show all events.<br />Add an entry to show all upcoming events.<br />Add an entry to show events in the past.</tr>
90
+ <tr><td>cats</td><td>Show a list of all available categories.</td><td>show_all</td><td>true<br />false</td><td>true</td><td>Add an entry to show events from all categories.</td></tr>
91
+ <tr><td>reset</td><td>Only a link to reset the eventlist filter to standard.</td><td>none</td><td></td><td></td><td></td></tr>
92
+ </table></small>
93
+ Find below an overview of the available filterbar display options:<br />
94
+ <small><table class="el-filterbar-table">
95
+ <th class="el-filterbar-doption">display option</th><th class="el-filterbar-desc3">description</th><th class="el-filterbar-for">available for</th></thead>
96
+ <tr><td>hlist</td><td>"hlist" shows a horizonal list seperated by "|" with a link to each item</td><td>years, cat</td></tr>
97
+ <tr><td>dropdown</td><td>"dropdown" shows a select box where an item can be choosen. After the selection of an item the page is reloaded via javascript to show the filtered events.</td><td>years, cat</td></tr>
98
+ <tr><td>link</td><td>"link" shows a simple link which can be clicked.</td><td>reset</td></tr>
99
+ </table></small>
100
+ <p>Find below some declaration examples with descriptions:</p>
101
+ <code>years_hlist,cats_dropdown</code><br />
102
+ In this example you can see that the filterbar item and the used display option is seperated by "_". You can define several filterbar items seperated by comma (","). The items will be aligned on the left side.
103
+ <p><code>years_dropdown(show-all=false|show-past=true),cats_dropdown;;reset_link</code><br />
104
+ In this example you can see that filterbar options can be added in brackets in format "option_name=value". You can also add multiple options seperated by a pipe ("|").<br />
105
+ The 2 semicolon (";") devides the bar in 3 section. The first section will be displayed left-justified, the second section will be centered and the third section will be right-aligned. So in this example the 2 dropdown will be left-aligned and the reset link will be on the right side.</p>'),
106
 
107
  'show_starttime' => array( 'val' => 'false<br />true<br />event_list_only<br />single_event_only',
108
  'std_val' => 'true',
135
  'details_length' => array( 'val' => 'number',
136
  'std_val' => '0',
137
  'visible' => true,
138
+ 'desc' => 'This attribute specifies if the details should be truncate to the given number of characters in the event list.<br />
139
  With the standard value 0 the full details are displayed.<br />
140
  This attribute has no influence if only a single event is shown.'),
141
 
150
  'std_val' => 'false',
151
  'visible' => true,
152
  'desc' => 'This attribute specifies if a rss feed link should be added.<br />
153
+ You have to enable the feed in the eventlist settings to make this attribute workable.<br />
154
+ On that page you can also find some settings to modify the output.<br />
155
  Choose "false" to never add and "true" to always add the link.<br />
156
  With "event_list_only" the link is only added in the event list and with "single_event_only" only for a single event'),
157
  // Invisible attributes ('visibe' = false): This attributes are required for the widget but will not be listed in the attributes table on the admin info page
158
  'title_length' => array( 'val' => 'number',
159
  'std_val' => '0',
160
  'visible' => false,
161
+ 'desc' => 'This attribute specifies if the title should be truncate to the given number of characters in the event list.<br />
162
  With the standard value 0 the full details are displayed.<br />
163
  This attribute has no influence if only a single event is shown.'),
164
 
165
  'location_length' => array( 'val' => 'number',
166
  'std_val' => '0',
167
  'visible' => false,
168
+ 'desc' => 'This attribute specifies if the title should be truncate to the given number of characters in the event list.<br />
169
  With the standard value 0 the full details are displayed.<br />
170
  This attribute has no influence if only a single event is shown.'),
171
 
183
  The empty standard value is o.k. for the normal use. This attribute is normally only required for the event-list widget.' ),
184
  // Internal attributes: This parameters will be added by the script and are not available in the shortcode
185
  // 'sc_id'
186
+ // 'actual_date'
187
+ // 'actual_cat'
188
  );
189
 
190
  $this->num_sc_loaded = 0;
218
  $a = shortcode_atts( $std_values, $atts );
219
  // add internal attributes
220
  $a['sc_id'] = $this->num_sc_loaded;
221
+ $a['event_id'] = isset($_GET['event_id'.$a['sc_id']]) ? (int)$_GET['event_id'.$a['sc_id']] : null;
 
222
  // fix sc_id_for_url if required
223
  if( !is_numeric( $a['sc_id_for_url'] ) ) {
224
  $a['sc_id_for_url'] = $a['sc_id'];
225
  }
226
+ $a['actual_date'] = $this->get_actual_date($a);
227
+ $a['actual_cat'] = $this->get_actual_cat($a);
228
 
229
  $out = '
230
  <div class="event-list">';
245
 
246
  private function html_event_details( &$a ) {
247
  $event = $this->db->get_event( $a['event_id'] );
248
+ $out = $this->html_filterbar($a);
249
  $out .= '
250
  <h2>Event Information:</h2>
251
  <ul class="single-event-view">';
256
 
257
  private function html_events( &$a ) {
258
  // specify to show all events if not upcoming is selected
259
+ if('upcoming' != $a['actual_date']) {
260
  $a['num_events'] = 0;
261
  }
262
+ $date_filter = $this->get_date_filter('all', $a['actual_date']);
263
+ $cat_filter = $this->get_cat_filter($a['cat_filter'], $a['actual_cat']);
264
  if( '1' !== $this->options->get( 'el_date_once_per_day' ) ) {
265
  // normal sort
266
  $sort_array = array( 'start_date ASC', 'time ASC', 'end_date ASC' );
269
  // sort according end_date before start time (required for option el_date_once_per_day)
270
  $sort_array = array( 'start_date ASC', 'end_date ASC', 'time ASC' );
271
  }
272
+ $events = $this->db->get_events($date_filter, $cat_filter, $a['num_events'], $sort_array);
273
 
274
  // generate output
275
  $out = '';
276
  $out .= $this->html_feed_link($a, 'top');
277
+ $out .= $this->html_filterbar($a);
278
  $out .= $this->html_feed_link($a, 'below_nav');
279
  if( empty( $events ) ) {
280
  // no events found
295
  }
296
 
297
  private function html_event( &$event, &$a, $single_day_only=false ) {
298
+ static $last_event_startdate=null, $last_event_enddate=null;
299
  $max_length = is_numeric( $a['event_id'] ) ? 0 : 999999;
300
  $out = '
301
  <li class="event">';
312
  }
313
  $out .= '">';
314
 
315
+ $out .= '<div class="event-title"><h3>';
316
 
317
  $title = esc_attr($this->db->truncate(min($max_length, $a['title_length']), $event->title));
318
  if( $this->is_visible( $a['link_to_event'] ) ) {
319
+ $out .= '<a href="'.esc_html(add_query_arg('event_id'.$a['sc_id_for_url'], $event->id, $this->get_url($a))).'">'.$title.'</a>';
320
  }
321
  else {
322
  $out .= $title;
323
  }
324
+ $out .= '</h3></div>';
325
  if( $event->time != '' && $this->is_visible( $a['show_starttime'] ) ) {
326
  // set time format if a known format is available, else only show the text
327
  $date_array = date_parse( $event->time );
383
  return $out;
384
  }
385
 
386
+ private function html_filterbar(&$a) {
387
+ if(!$this->is_visible($a['show_filterbar'])) {
388
+ return '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  }
390
+ require_once( EL_PATH.'includes/filterbar.php');
391
+ $filterbar = EL_Filterbar::get_instance();
392
+ return $filterbar->show($this->get_url($a), $a);
393
  }
394
 
395
  private function html_feed_link(&$a, $pos) {
418
  return $out;
419
  }
420
 
421
+ private function get_actual_date(&$a) {
422
+ $actual_date = $a['initial_date'];
423
+ if(isset($_GET['event_id'.$a['sc_id']])) {
424
+ $actual_date = null;
425
  }
426
+ elseif(isset($_GET['date'.$a['sc_id']])) {
427
+ $actual_date = $_GET['date'.$a['sc_id']];
 
428
  }
429
+ return $actual_date;
430
+ }
431
+
432
+ private function get_actual_cat(&$a) {
433
+ $actual_cat = $a['initial_cat'];
434
+ if(isset($_GET['event_id'.$a['sc_id']])) {
435
+ $actual_cat = null;
436
+ }
437
+ elseif(isset($_GET['cat'.$a['sc_id']])) {
438
+ $actual_cat = $_GET['cat'.$a['sc_id']];
439
+ }
440
+ return $actual_cat;
441
+ }
442
+
443
+ private function get_date_filter($date_filter, $actual_date) {
444
+ // TODO: date_filter not implemented yet
445
+ if('all' == $actual_date) {
446
+ return null;
447
  }
448
  else {
449
+ return $actual_date;
450
+ }
451
+ }
452
+
453
+ private function get_cat_filter($cat_filter, $actual_cat) {
454
+ if('all' == $cat_filter || '' == $cat_filter) {
455
+ if('all' == $actual_cat || '' == $actual_cat) {
456
+ return null;
457
+ }
458
+ else {
459
+ return $actual_cat;
460
+ }
461
+ }
462
+ else {
463
+ if('all' == $actual_cat || '' == $actual_cat) {
464
+ return $cat_filter;
465
+ }
466
+ else {
467
+ return '('.$cat_filter.')&('.$actual_cat.')';
468
+ }
469
  }
 
470
  }
471
 
472
  private function get_url( &$a ) {
478
  // use actual page
479
  $url = get_permalink();
480
  foreach( $_GET as $k => $v ) {
481
+ if('date'.$a['sc_id'] !== $k && 'event_id'.$a['sc_id'] !== $k) {
482
  $url = add_query_arg( $k, $v, $url );
483
  }
484
  }
includes/widget.php CHANGED
@@ -31,10 +31,10 @@ class EL_Widget extends WP_Widget {
31
  'form_width' => null ),
32
 
33
  'cat_filter' => array( 'type' => 'text',
34
- 'std_value' => 'none',
35
  'caption' => __('Category Filter:'),
36
  'caption_after' => null,
37
- 'tooltip' => __('This attribute specifies the categories of which events are shown. The standard is \'none\' to show all events. Specify a category slug or a list of category slugs separated by a comma to only show events of the specified categories.'),
38
  'form_style' => 'margin:0 0 0.8em 0',
39
  'form_width' => null ),
40
 
@@ -152,9 +152,10 @@ class EL_Widget extends WP_Widget {
152
  {
153
  echo $args['before_title'].$title.$args['after_title'];
154
  }
 
155
  $linked_page_is_set = 0 < strlen( $instance['url_to_page'] );
156
  $linked_page_id_is_set = 0 < (int)$instance['sc_id_for_url'];
157
- $shortcode = '[event-list show_nav=false';
158
  $shortcode .= ' cat_filter='.$instance['cat_filter'];
159
  $shortcode .= ' num_events="'.$instance['num_events'].'"';
160
  $shortcode .= ' title_length='.$instance['title_length'];
@@ -210,6 +211,7 @@ class EL_Widget extends WP_Widget {
210
  * @param array $instance Previously saved values from database.
211
  */
212
  public function form( $instance ) {
 
213
  $out = '';
214
  foreach( $this->items as $itemname => $item ) {
215
  if( ! isset( $instance[$itemname] ) ) {
@@ -250,5 +252,19 @@ class EL_Widget extends WP_Widget {
250
  }
251
  }
252
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  }
254
  ?>
31
  'form_width' => null ),
32
 
33
  'cat_filter' => array( 'type' => 'text',
34
+ 'std_value' => 'all',
35
  'caption' => __('Category Filter:'),
36
  'caption_after' => null,
37
+ 'tooltip' => __('This attribute specifies the categories of which events are shown. The standard is \'all\' or an empty string to show all events. Specify a category slug or a list of category slugs to only show events of the specified categories. See description of the shortcode attribute "cat_filter" for detailed info about all possibilities.'),
38
  'form_style' => 'margin:0 0 0.8em 0',
39
  'form_width' => null ),
40
 
152
  {
153
  echo $args['before_title'].$title.$args['after_title'];
154
  }
155
+ $this->upgrade_widget($instance, true);
156
  $linked_page_is_set = 0 < strlen( $instance['url_to_page'] );
157
  $linked_page_id_is_set = 0 < (int)$instance['sc_id_for_url'];
158
+ $shortcode = '[event-list show_filterbar=false';
159
  $shortcode .= ' cat_filter='.$instance['cat_filter'];
160
  $shortcode .= ' num_events="'.$instance['num_events'].'"';
161
  $shortcode .= ' title_length='.$instance['title_length'];
211
  * @param array $instance Previously saved values from database.
212
  */
213
  public function form( $instance ) {
214
+ $this->upgrade_widget($instance);
215
  $out = '';
216
  foreach( $this->items as $itemname => $item ) {
217
  if( ! isset( $instance[$itemname] ) ) {
252
  }
253
  }
254
  }
255
+
256
+ private function upgrade_widget(&$instance, $on_frontpage=false) {
257
+ // required change of cat_filter in version 0.6.0 (can be removed in 0.7.0)
258
+ if(isset($instance['cat_filter']) && 'none' === $instance['cat_filter']) {
259
+ if($on_frontpage) {
260
+ echo '<p style="color:red"><strong>Please visit widget admin page and press "Save" to perform the required widget updates (required due to changes in new plugin version) !</strong></p>';
261
+ }
262
+ else {
263
+ echo '<p style="color:red"><strong>Press "Save" to perform the required widget updates (required due to changes in new plugin version) !</strong></p>';
264
+ $instance['cat_filter'] = 'all';
265
+ $this->update($instance, null);
266
+ }
267
+ }
268
+ }
269
  }
270
  ?>
readme.txt CHANGED
@@ -1,15 +1,15 @@
1
  === Event List ===
2
  Contributors: mibuthu
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W54LNZMWF9KW2
4
- Tags: event, events, list, listview, calendar, schedule, shortcode, page, category, categories, admin, attribute, widget, sidebar, feed, rss
5
  Requires at least: 3.3
6
- Tested up to: 3.7.1
7
- Stable tag: 0.5.2
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
11
 
12
- Manage your events and show them in a list view on your site.
13
 
14
 
15
  == Description ==
@@ -18,21 +18,21 @@ The purpose of this plugin is to to show a list of events with date, time, descr
18
 
19
  = Current Features =
20
  * Admin pages to view/create/manage/modify events
21
- * Available event data fields: event title, event start time, event location, event details
22
- * Beginning and end dates for multiple-day events
23
- * Wordpress's WYSIWYG editor for the event details. So you can include styled text, links, images and other media in your event list.
24
- * A duplicate function for events
25
- * Event navigation to view only upcoming events or past/future events filtered by year
26
  * Event categories
27
  * Sync event categories with post categories
28
- * Event feed
 
29
 
30
- The event list can be placed in any page or post on your Wordpress site. Just include the following short code where you want the calendar to appear:
31
 
32
  ‘[event-list]’
33
 
34
  You can modify the listed events and their style with attributes. All available attributes can be found on the Event List -> About page.
35
- There is also a widget available to view the upcoming events in a sidebar.
36
 
37
  If you want to follow the development status have a look at the [git-repository on github](https://github.com/mibuthu/wp-event-list "wp-event-list git-repository").
38
 
@@ -46,14 +46,15 @@ If you want to install the plugin manually download the zip-file and extract the
46
 
47
  == Frequently Asked Questions ==
48
 
49
- = How do I get a calendar to show up in a Page or Post on my site? =
50
- Insert the shortcode [event-list] in your page.
51
 
52
  = How do I use styled text and images in the event descriptions? =
53
- Event List uses the built-in Wordpress WYSIWYG editor. It's exactly the same process you use when creating Posts or Pages.
54
 
55
  = Can I call the shortcode directly via php e.g. for my own template, theme or plugin? =
56
- Yes, you can create an instance of the "SC_Event_List" class which located in "includes/sc_event-list.php" in the plugin folder and call the function show_html($atts).With $atts you can specify all the shortcode attributes you require. Another possibility would be to call the wordpress function "do_shortcode()".
 
57
 
58
 
59
  == Screenshots ==
@@ -70,6 +71,26 @@ Yes, you can create an instance of the "SC_Event_List" class which located in "i
70
 
71
  == Changelog ==
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  = 0.5.2 (2013-11-09) =
74
 
75
  * added number of events in Right Now dashboard widget
1
  === Event List ===
2
  Contributors: mibuthu
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W54LNZMWF9KW2
4
+ Tags: event, events, list, listview, calendar, schedule, shortcode, page, category, categories, filter, admin, attribute, widget, sidebar, feed, rss
5
  Requires at least: 3.3
6
+ Tested up to: 3.8
7
+ Stable tag: 0.6.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
11
 
12
+ Manage your events and show them on your site.
13
 
14
 
15
  == Description ==
18
 
19
  = Current Features =
20
  * Admin pages to view/create/manage/modify events
21
+ * Available event data fields: event title, event date, event start time, event location, event details
22
+ * Beginning and end dates for multi-day events
23
+ * Wordpress's WYSIWYG editor for the event details. So you can include styled text, links, images and other media in your events.
24
+ * A duplicate function for events to easier create similar event copies
 
25
  * Event categories
26
  * Sync event categories with post categories
27
+ * Filter events according to dates or categories
28
+ * Include an event feed in your site
29
 
30
+ The event list can be placed in any page or post on your Wordpress site. Just include the following short code where you want the events to appear:
31
 
32
  ‘[event-list]’
33
 
34
  You can modify the listed events and their style with attributes. All available attributes can be found on the Event List -> About page.
35
+ There is also a widget available to view the upcoming events in a sidebar with many options.
36
 
37
  If you want to follow the development status have a look at the [git-repository on github](https://github.com/mibuthu/wp-event-list "wp-event-list git-repository").
38
 
46
 
47
  == Frequently Asked Questions ==
48
 
49
+ = How do I get an event list to show up in a Page or Post on my site? =
50
+ Insert the shortcode [event-list] in your page or post. You can modify the output by many available shortcode attributes (see Event List -> About page for more infos).
51
 
52
  = How do I use styled text and images in the event descriptions? =
53
+ Event List uses the built-in Wordpress WYSIWYG editor. It's exactly the same process like in creating Posts or Pages.
54
 
55
  = Can I call the shortcode directly via php e.g. for my own template, theme or plugin? =
56
+ Yes, you can create an instance of the "SC_Event_List" class which is located in the plugin folder under "includes/sc_event-list.php" and call the function show_html($atts).With $atts you can specify all the shortcode attributes you require.
57
+ Another possibility would be to call the wordpress function "do_shortcode()".
58
 
59
 
60
  == Screenshots ==
71
 
72
  == Changelog ==
73
 
74
+ = 0.6.0 (2013-12-31) =
75
+ * added adjustment options for the filterbar (shortcode attribute "filterbar_items")
76
+ * added "All" and "Past" options to years filter in filterbar
77
+ * added category filter option in filterbar
78
+ * change "cat_filter" behavior with additional features
79
+ * added option to display categorys/years filter in a dropdown
80
+ * added reset option to filterbar
81
+ * added category filter selection in admin event table
82
+ * added shortcode attribute "initial_date"
83
+ * renamed shortcode attribute "show_nav" into "show_filterbar"
84
+ * renamed url parameter "ytd" to "years"
85
+ * removed underline before event-list id in url
86
+ * some css fixes
87
+ * some help text updates
88
+
89
+ Attention:
90
+ In this version some of the shortcode attributes and the behavior of some existing attributes have changed and are not compatible with the old version! Please check all your shortcodes after the update.
91
+ Additionally the url parameter has changed. So if you are using existing links to an eventlist with parameters you have to update them.
92
+ Also existing widgets must be updated after plugin upgrade. Please visit the widget admin page and press save for all evenlist wigets.
93
+
94
  = 0.5.2 (2013-11-09) =
95
 
96
  * added number of events in Right Now dashboard widget