Event List - Version 0.4.5

Version Description

(2013-08-05) =

  • added capability to sync the event categories with the post categories (manually or automatically)
  • fixed problem with empty category list
  • fixed link to category page in new event page
  • fixed indention in in category parent combo box
Download this release

Release Info

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

Code changes from version 0.4.4 to 0.4.5

admin/admin.php CHANGED
@@ -3,9 +3,16 @@ if(!defined('ABSPATH')) {
3
  exit;
4
  }
5
 
 
 
6
  // This class handles all available admin pages
7
  class EL_Admin {
8
  private static $instance;
 
 
 
 
 
9
 
10
  public static function &get_instance() {
11
  // Create class instance if required
@@ -20,6 +27,13 @@ class EL_Admin {
20
  // Register actions
21
  add_action('admin_menu', array(&$this, 'register_pages'));
22
  add_action('plugins_loaded', array(&$this, 'db_upgrade_check'));
 
 
 
 
 
 
 
23
  }
24
 
25
  /**
@@ -104,5 +118,20 @@ class EL_Admin {
104
  require_once(EL_PATH.'admin/includes/admin-about.php');
105
  EL_Admin_About::get_instance()->embed_about_scripts();
106
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
108
  ?>
3
  exit;
4
  }
5
 
6
+ require_once( EL_PATH.'includes/options.php' );
7
+
8
  // This class handles all available admin pages
9
  class EL_Admin {
10
  private static $instance;
11
+ private $options;
12
+
13
+ private function __construct() {
14
+ $this->options = &EL_Options::get_instance();
15
+ }
16
 
17
  public static function &get_instance() {
18
  // Create class instance if required
27
  // Register actions
28
  add_action('admin_menu', array(&$this, 'register_pages'));
29
  add_action('plugins_loaded', array(&$this, 'db_upgrade_check'));
30
+
31
+ // Register syncing if required
32
+ if(1 == $this->options->get('el_sync_cats')) {
33
+ add_action('create_category', array(&$this, 'action_add_category'));
34
+ add_action('edit_category', array(&$this, 'action_edit_category'));
35
+ add_action('delete_category', array(&$this, 'action_delete_category'));
36
+ }
37
  }
38
 
39
  /**
118
  require_once(EL_PATH.'admin/includes/admin-about.php');
119
  EL_Admin_About::get_instance()->embed_about_scripts();
120
  }
121
+
122
+ public function action_add_category($cat_id) {
123
+ require_once(EL_PATH.'includes/categories.php');
124
+ EL_Categories::get_instance()->add_post_category($cat_id);
125
+ }
126
+
127
+ public function action_edit_category($cat_id) {
128
+ require_once(EL_PATH.'includes/categories.php');
129
+ EL_Categories::get_instance()->edit_post_category($cat_id);
130
+ }
131
+
132
+ public function action_delete_category($cat_id) {
133
+ require_once(EL_PATH.'includes/categories.php');
134
+ EL_Categories::get_instance()->delete_post_category($cat_id);
135
+ }
136
  }
137
  ?>
admin/includes/admin-categories.php CHANGED
@@ -5,6 +5,7 @@ if(!defined('ABSPATH')) {
5
 
6
  require_once(EL_PATH.'includes/db.php');
7
  require_once(EL_PATH.'includes/categories.php');
 
8
  require_once(EL_PATH.'admin/includes/admin-functions.php');
9
 
10
  // This class handles all data for the admin categories page
@@ -12,6 +13,7 @@ class EL_Admin_Categories {
12
  private static $instance;
13
  private $db;
14
  private $categories;
 
15
  private $functions;
16
 
17
  public static function &get_instance() {
@@ -26,6 +28,7 @@ class EL_Admin_Categories {
26
  private function __construct() {
27
  $this->db = &EL_Db::get_instance();
28
  $this->categories = &EL_Categories::get_instance();
 
29
  $this->functions = &EL_Admin_Functions::get_instance();
30
  }
31
 
@@ -54,6 +57,8 @@ class EL_Admin_Categories {
54
  $out .= $this->show_category_table();
55
  // show add category form
56
  $out .= $this->show_edit_category_form(__('Add New Category'), __('Add New Category'));
 
 
57
  }
58
  $out .= '
59
  </div>
@@ -62,54 +67,83 @@ class EL_Admin_Categories {
62
  }
63
 
64
  public function embed_categories_scripts() {
 
65
  wp_enqueue_script('eventlist_admin_categories_js', EL_URL.'admin/js/admin_categories.js');
66
  }
67
 
68
  private function check_actions_and_show_messages($action) {
 
69
  $out = '';
70
  if('delete' === $action && isset($_GET['slug'])) {
71
- // delete categories
72
- $slug_array = explode(', ', $_GET['slug']);
73
- $num_affected_events = $this->db->remove_category_in_events($slug_array);
74
- require_once(EL_PATH.'admin/includes/category_table.php');
75
- if($this->categories->remove_categories($slug_array)) {
76
- $out .= '<div id="message" class="updated">
77
- <p><strong>'.sprintf(__('Category "%s" deleted.'), $_GET['slug']);
78
- if($num_affected_events > 0) {
79
- $out .= '<br />'.sprintf(__('This Category was also removed from %d events.'), $num_affected_events);
 
 
 
80
  }
81
- $out .= '</strong></p>
82
- </div>';
 
 
 
 
 
 
 
 
 
 
83
  }
84
  else {
85
- $out .= '<div id="message" class="error below-h2"><p><strong>Error while deleting category "'.$_GET['slug'].'".</strong></p></div>';
86
  }
87
  }
88
- else if(!empty($_POST)) {
89
- if(!isset($_POST['id'])) {
90
- // add new category
91
- if($this->categories->add_category($_POST)) {
92
- $out .= '<div id="message" class="updated below-h2"><p><strong>New Category "'.$_POST['name'].'" was added.</strong></p></div>';
93
- }
94
- else {
95
- $out .= '<div id="message" class="error below-h2"><p><strong>Error: New Category "'.$_POST['name'].'" could not be added.</strong></p></div>';
96
- }
97
  }
98
- else {
99
- // edit category
100
- if($this->categories->edit_category($_POST, $_POST['id'])) {
101
- $this->db->change_category_slug_in_events($_POST['id'], $_POST['slug']);
102
- $out .= '<div id="message" class="updated below-h2"><p><strong>Category "'.$_POST['id'].'" was modified.</strong></p></div>';
 
 
 
 
 
 
103
  }
104
  else {
105
- $out .= '<div id="message" class="error below-h2"><p><strong>Error: Category "'.$_POST['id'].'" could not be modified.</strong></p></div>';
 
 
 
 
 
 
106
  }
107
  }
108
  }
 
 
 
 
 
 
109
  return $out;
110
  }
111
 
112
  private function show_edit_category_form($title, $button_text, $cat_data=null) {
 
113
  $is_new_event = (null == $cat_data);
114
  if($is_new_event) {
115
  $cat_data['name'] = '';
@@ -121,7 +155,7 @@ class EL_Admin_Categories {
121
  <div class="col-wrap">
122
  <div class="form-wrap">
123
  <h3>'.$title.'</h3>
124
- <form id="addtag" method="POST" action="?page=el_admin_categories&amp;tab=category">';
125
  if(!$is_new_event) {
126
  $out .= '
127
  <input type="hidden" name="id" value="'.$cat_data['slug'].'">';
@@ -129,12 +163,12 @@ class EL_Admin_Categories {
129
  // Category Name
130
  $out .= '
131
  <div class="form-field form-required"><label for="name">Name: </label>';
132
- $out .= $this->functions->show_text('name', $cat_data['name']);
133
  $out .= '<p>'.__('The name is how it appears on your site.').'</p></div>';
134
  // Category Slug
135
  $out .= '
136
  <div class="form-field"><label for="name">Slug: </label>';
137
- $out .= $this->functions->show_text('slug', $cat_data['slug']);
138
  $out .= '<p>'.__('The “slug” is the URL-friendly version of the name. It is usually all lowercase and contains only letters, numbers, and hyphens.').'</p></div>';
139
  // Category Parent
140
  $out .= '
@@ -144,22 +178,21 @@ class EL_Admin_Categories {
144
  $class_array = array();
145
  foreach($cat_array as $cat) {
146
  if($cat['slug'] != $cat_data['slug']) {
147
- $option_array[$cat['slug']] = str_pad($cat['name'], 18*$cat['level'], '&nbsp;', STR_PAD_LEFT);
148
  $class_array[$cat['slug']] = 'level-'.$cat['level'];
149
  }
150
  }
151
  $selected = isset($cat_data['parent']) ? $cat_data['parent'] : null;
152
- $out .= $this->functions->show_combobox('parent', $option_array, $selected, $class_array);
153
  $out .= '<p>'.__('Categories can have a hierarchy. You might have a Jazz category, and under that have children categories for Bebop and Big Band. Totally optional.').'</p></div>';
154
  // Category Description
155
  $out .= '
156
  <div class="form-field"><label for="name">Description: </label>';
157
- $out .= $this->functions->show_textarea('desc', $cat_data['desc']);
158
  $out .= '</div>
159
- <p class="submit"><input type="submit" class="button-primary" name="add_cat" value="'.$button_text.'" id="submitbutton"></p>';
160
  $out .= '
161
  </form>
162
- </div>
163
  </div>
164
  </div>
165
  </div>';
@@ -173,8 +206,9 @@ class EL_Admin_Categories {
173
  <div class="col-wrap">
174
  <form id="category-filter" method="get">
175
  <input type="hidden" name="page" value="'.$_REQUEST['page'].'" />';
 
176
  require_once(EL_PATH.'admin/includes/category_table.php');
177
- $category_table = new EL_Category_Table();
178
  $category_table->prepare_items();
179
  ob_start();
180
  $category_table->display();
@@ -186,5 +220,33 @@ class EL_Admin_Categories {
186
  </div>';
187
  return $out;
188
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  }
190
  ?>
5
 
6
  require_once(EL_PATH.'includes/db.php');
7
  require_once(EL_PATH.'includes/categories.php');
8
+ require_once(EL_PATH.'includes/options.php');
9
  require_once(EL_PATH.'admin/includes/admin-functions.php');
10
 
11
  // This class handles all data for the admin categories page
13
  private static $instance;
14
  private $db;
15
  private $categories;
16
+ private $options;
17
  private $functions;
18
 
19
  public static function &get_instance() {
28
  private function __construct() {
29
  $this->db = &EL_Db::get_instance();
30
  $this->categories = &EL_Categories::get_instance();
31
+ $this->options = &EL_Options::get_instance();
32
  $this->functions = &EL_Admin_Functions::get_instance();
33
  }
34
 
57
  $out .= $this->show_category_table();
58
  // show add category form
59
  $out .= $this->show_edit_category_form(__('Add New Category'), __('Add New Category'));
60
+ // show cat sync option form
61
+ $out .= $this->show_cat_sync_form();
62
  }
63
  $out .= '
64
  </div>
67
  }
68
 
69
  public function embed_categories_scripts() {
70
+ wp_enqueue_script('jquery');
71
  wp_enqueue_script('eventlist_admin_categories_js', EL_URL.'admin/js/admin_categories.js');
72
  }
73
 
74
  private function check_actions_and_show_messages($action) {
75
+ $is_disabled = '1' == $this->options->get('el_sync_cats');
76
  $out = '';
77
  if('delete' === $action && isset($_GET['slug'])) {
78
+ if(!$is_disabled) {
79
+ // delete categories
80
+ $slug_array = explode(', ', $_GET['slug']);
81
+ $num_affected_events = $this->db->remove_category_in_events($slug_array);
82
+ if($this->categories->remove_categories($slug_array, false)) {
83
+ $out .= '<div id="message" class="updated">
84
+ <p><strong>'.sprintf(__('Category "%s" deleted.'), $_GET['slug']);
85
+ if($num_affected_events > 0) {
86
+ $out .= '<br />'.sprintf(__('This Category was also removed from %d events.'), $num_affected_events);
87
+ }
88
+ $out .= '</strong></p>
89
+ </div>';
90
  }
91
+ else {
92
+ $out .= '<div id="message" class="error below-h2"><p><strong>Error while deleting category "'.$_GET['slug'].'".</strong></p></div>';
93
+ }
94
+ }
95
+ }
96
+ else if('setcatsync' === $action) {
97
+ $el_sync_cats = isset($_POST['el_sync_cats']) ? '1' : '';
98
+ $this->options->set('el_sync_cats', $el_sync_cats);
99
+ $is_disabled = '1' == $this->options->get('el_sync_cats');
100
+ if($is_disabled) {
101
+ $this->categories->sync_with_post_cats();
102
+ $out .= '<div id="message" class="updated"><p><strong>'.__('Sync with post categories enabled.').'</strong></p></div>';
103
  }
104
  else {
105
+ $out .= '<div id="message" class="updated"><p><strong>'.__('Sync with post categories disabled.').'</strong></p></div>';
106
  }
107
  }
108
+ else if('manualcatsync' === $action) {
109
+ if(!$is_disabled) {
110
+ $this->categories->sync_with_post_cats();
111
+ $out .= '<div id="message" class="updated"><p><strong>'.__('Manual sync with post categories sucessfully finished.').'</strong></p></div>';
 
 
 
 
 
112
  }
113
+ }
114
+ else if('editcat' === $action && !empty($_POST)) {
115
+ if(!$is_disabled) {
116
+ if(!isset($_POST['id'])) {
117
+ // add new category
118
+ if($this->categories->add_category($_POST)) {
119
+ $out .= '<div id="message" class="updated below-h2"><p><strong>New Category "'.$_POST['name'].'" was added.</strong></p></div>';
120
+ }
121
+ else {
122
+ $out .= '<div id="message" class="error below-h2"><p><strong>Error: New Category "'.$_POST['name'].'" could not be added.</strong></p></div>';
123
+ }
124
  }
125
  else {
126
+ // edit category
127
+ if($this->categories->edit_category($_POST, $_POST['id'])) {
128
+ $out .= '<div id="message" class="updated below-h2"><p><strong>Category "'.$_POST['id'].'" was modified.</strong></p></div>';
129
+ }
130
+ else {
131
+ $out .= '<div id="message" class="error below-h2"><p><strong>Error: Category "'.$_POST['id'].'" could not be modified.</strong></p></div>';
132
+ }
133
  }
134
  }
135
  }
136
+ // add message if forms are disabled
137
+ if($is_disabled) {
138
+ $out .= '<div id="message" class="updated"><p>'.__('Categories are automatically synced with the post categories.<br />
139
+ Because of this all options to add new categories or editing existing categories are disabled.<br />
140
+ If you want to manually edit the categories you have to disable this option.').'</p></div>';
141
+ }
142
  return $out;
143
  }
144
 
145
  private function show_edit_category_form($title, $button_text, $cat_data=null) {
146
+ $is_disabled = '1' == $this->options->get('el_sync_cats');
147
  $is_new_event = (null == $cat_data);
148
  if($is_new_event) {
149
  $cat_data['name'] = '';
155
  <div class="col-wrap">
156
  <div class="form-wrap">
157
  <h3>'.$title.'</h3>
158
+ <form id="addtag" method="POST" action="?page=el_admin_categories&amp;action=editcat">';
159
  if(!$is_new_event) {
160
  $out .= '
161
  <input type="hidden" name="id" value="'.$cat_data['slug'].'">';
163
  // Category Name
164
  $out .= '
165
  <div class="form-field form-required"><label for="name">Name: </label>';
166
+ $out .= $this->functions->show_text('name', $cat_data['name'], $is_disabled);
167
  $out .= '<p>'.__('The name is how it appears on your site.').'</p></div>';
168
  // Category Slug
169
  $out .= '
170
  <div class="form-field"><label for="name">Slug: </label>';
171
+ $out .= $this->functions->show_text('slug', $cat_data['slug'], $is_disabled);
172
  $out .= '<p>'.__('The “slug” is the URL-friendly version of the name. It is usually all lowercase and contains only letters, numbers, and hyphens.').'</p></div>';
173
  // Category Parent
174
  $out .= '
178
  $class_array = array();
179
  foreach($cat_array as $cat) {
180
  if($cat['slug'] != $cat_data['slug']) {
181
+ $option_array[$cat['slug']] = str_pad('', 12*$cat['level'], '&nbsp;', STR_PAD_LEFT).$cat['name'];
182
  $class_array[$cat['slug']] = 'level-'.$cat['level'];
183
  }
184
  }
185
  $selected = isset($cat_data['parent']) ? $cat_data['parent'] : null;
186
+ $out .= $this->functions->show_combobox('parent', $option_array, $selected, $class_array, $is_disabled);
187
  $out .= '<p>'.__('Categories can have a hierarchy. You might have a Jazz category, and under that have children categories for Bebop and Big Band. Totally optional.').'</p></div>';
188
  // Category Description
189
  $out .= '
190
  <div class="form-field"><label for="name">Description: </label>';
191
+ $out .= $this->functions->show_textarea('desc', $cat_data['desc'], $is_disabled);
192
  $out .= '</div>
193
+ <p class="submit"><input type="submit" class="button-primary" value="'.$button_text.'" id="submitbutton"'.$this->functions->get_disabled_text($is_disabled).'></p>';
194
  $out .= '
195
  </form>
 
196
  </div>
197
  </div>
198
  </div>';
206
  <div class="col-wrap">
207
  <form id="category-filter" method="get">
208
  <input type="hidden" name="page" value="'.$_REQUEST['page'].'" />';
209
+ $is_disabled = '1' == $this->options->get('el_sync_cats');
210
  require_once(EL_PATH.'admin/includes/category_table.php');
211
+ $category_table = new EL_Category_Table($is_disabled);
212
  $category_table->prepare_items();
213
  ob_start();
214
  $category_table->display();
220
  </div>';
221
  return $out;
222
  }
223
+
224
+ private function show_cat_sync_form() {
225
+ $sync_option = &$this->options->options['el_sync_cats'];
226
+ $sync_option_value = $this->options->get('el_sync_cats');
227
+ $out = '
228
+ <div id="col-left">
229
+ <div class="col-wrap">
230
+ <div class="form-wrap">
231
+ <h3>'.$sync_option['label'].'</h3>
232
+ <form id="catsync" method="POST" action="?page=el_admin_categories&amp;action=setcatsync">';
233
+ // Checkbox
234
+ $out .= $this->functions->show_checkbox('el_sync_cats', $sync_option_value, $sync_option['caption'].' <input type="submit" class="button-primary" value="'.__('Apply').'" id="catsyncsubmitbutton">');
235
+ $out .= '<br />'.$sync_option['desc'];
236
+ $out .= '
237
+ </form>
238
+ </div>';
239
+ // Manual sync button
240
+ $disabled_text = $this->functions->get_disabled_text('1' == $sync_option_value);
241
+ $out .= '<br />
242
+ <div>
243
+ <form id="manualcatsync" method="POST" action="?page=el_admin_categories&amp;action=manualcatsync">
244
+ <input type="submit" class="button-secondary" value="'.__('Do a manual sync with post categories').'" id="manualcatsyncbutton"'.$disabled_text.'>
245
+ </form>
246
+ </div>';
247
+ $out .= '
248
+ </div>';
249
+ return $out;
250
+ }
251
  }
252
  ?>
admin/includes/admin-functions.php CHANGED
@@ -22,22 +22,22 @@ class EL_Admin_Functions {
22
 
23
  }
24
 
25
- public function show_checkbox($name, $value, $caption) {
26
  $out = '
27
  <label for="'.$name.'">
28
  <input name="'.$name.'" type="checkbox" id="'.$name.'" value="1"';
29
  if($value == 1) {
30
  $out .= ' checked="checked"';
31
  }
32
- $out .= ' />
33
  '.$caption.'
34
  </label>';
35
  return $out;
36
  }
37
 
38
- public function show_combobox($name, $option_array, $selected=null, $class_array=null) {
39
  $out = '
40
- <select id="'.$name.'" name="'.$name.'">';
41
  foreach($option_array as $key => $value) {
42
  $class_text = isset($class_array[$key]) ? 'class="'.$class_array[$key].'" ' : '';
43
  $selected_text = $selected===$key ? 'selected ' : '';
@@ -49,7 +49,7 @@ class EL_Admin_Functions {
49
  return $out;
50
  }
51
 
52
- public function show_radio($name, $value, $caption) {
53
  $out = '
54
  <fieldset>';
55
  foreach($caption as $okey => $ocaption) {
@@ -66,16 +66,20 @@ class EL_Admin_Functions {
66
  return $out;
67
  }
68
 
69
- public function show_text($name, $value) {
70
  $out = '
71
- <input name="'.$name.'" type="text" id="'.$name.'" value="'.$value.'" />';
72
  return $out;
73
  }
74
 
75
- public function show_textarea($name, $value) {
76
  $out = '
77
- <textarea name="'.$name.'" id="'.$name.'" rows="5" class="large-text code">'.$value.'</textarea>';
78
  return $out;
79
  }
 
 
 
 
80
  }
81
  ?>
22
 
23
  }
24
 
25
+ public function show_checkbox($name, $value, $caption, $disabled=false) {
26
  $out = '
27
  <label for="'.$name.'">
28
  <input name="'.$name.'" type="checkbox" id="'.$name.'" value="1"';
29
  if($value == 1) {
30
  $out .= ' checked="checked"';
31
  }
32
+ $out .= $this->get_disabled_text($disabled).' />
33
  '.$caption.'
34
  </label>';
35
  return $out;
36
  }
37
 
38
+ public function show_combobox($name, $option_array, $selected=null, $class_array=null, $disabled=false) {
39
  $out = '
40
+ <select id="'.$name.'" name="'.$name.'"'.$this->get_disabled_text($disabled).'>';
41
  foreach($option_array as $key => $value) {
42
  $class_text = isset($class_array[$key]) ? 'class="'.$class_array[$key].'" ' : '';
43
  $selected_text = $selected===$key ? 'selected ' : '';
49
  return $out;
50
  }
51
 
52
+ public function show_radio($name, $value, $caption, $disabled=false) {
53
  $out = '
54
  <fieldset>';
55
  foreach($caption as $okey => $ocaption) {
66
  return $out;
67
  }
68
 
69
+ public function show_text($name, $value, $disabled=false) {
70
  $out = '
71
+ <input name="'.$name.'" type="text" id="'.$name.'" value="'.$value.'"'.$this->get_disabled_text($disabled).' />';
72
  return $out;
73
  }
74
 
75
+ public function show_textarea($name, $value, $disabled=false) {
76
  $out = '
77
+ <textarea name="'.$name.'" id="'.$name.'" rows="5" class="large-text code"'.$this->get_disabled_text($disabled).'>'.$value.'</textarea>';
78
  return $out;
79
  }
80
+
81
+ public function get_disabled_text($disabled=false) {
82
+ return $disabled ? ' disabled="disabled"' : '';
83
+ }
84
  }
85
  ?>
admin/includes/admin-new.php CHANGED
@@ -193,7 +193,7 @@ class EL_Admin_New {
193
  </div>*/
194
  $out .= '
195
  <div id="category-manager">
196
- <a id="category-manage-link" href="?page=el_admin_settings&amp;tab=category">'.__('Goto Category Settings').'</a>
197
  </div>
198
  </div>';
199
  echo $out;
193
  </div>*/
194
  $out .= '
195
  <div id="category-manager">
196
+ <a id="category-manage-link" href="?page=el_admin_categories">'.__('Goto Category Settings').'</a>
197
  </div>
198
  </div>';
199
  echo $out;
admin/includes/category_table.php CHANGED
@@ -15,12 +15,13 @@ class EL_Category_Table extends WP_List_Table {
15
  private $options;
16
  private $db;
17
  private $categories;
 
18
 
19
- public function __construct() {
20
  $this->options = &EL_Options::get_instance();
21
  $this->db = &EL_Db::get_instance();
22
  $this->categories = &EL_Categories::get_instance();
23
- //global $status, $page;
24
  //Set parent defaults
25
  parent::__construct( array(
26
  'singular' => 'event', //singular name of the listed records
@@ -60,15 +61,19 @@ class EL_Category_Table extends WP_List_Table {
60
  * @return string Text to be placed inside the column <td> (movie title only)
61
  ***************************************************************************/
62
  protected function column_name($item) {
63
- // prepare Actions
64
- $actions = array(
65
- 'edit' => '<a href="?page='.$_REQUEST['page'].'&amp;id='.$item['slug'].'&amp;action=edit">Edit</a>',
66
- 'delete' => '<a href="#" onClick="eventlist_deleteCategory(\''.$item['slug'].'\');return false;">Delete</a>'
67
- );
68
  // create prefix with indenting according cat level
69
  $prefix = str_pad('', 7*$item['level'], '&#8212;', STR_PAD_LEFT).' ';
70
- //Return the title contents
71
- return '<b>'.$prefix.$item['name'].'</b>'.$this->row_actions($actions);
 
 
 
 
 
 
 
 
 
72
  }
73
 
74
  /** ************************************************************************
@@ -80,9 +85,12 @@ class EL_Category_Table extends WP_List_Table {
80
  * @return string Text to be placed inside the column <td> (movie title only)
81
  ***************************************************************************/
82
  protected function column_cb($item) {
83
- //Let's simply repurpose the table's singular label ("event")
84
- //The value of the checkbox should be the record's id
85
- return '<input type="checkbox" name="slug[]" value="'.$item['slug'].'" />';
 
 
 
86
  }
87
 
88
  /** ************************************************************************
@@ -95,7 +103,7 @@ class EL_Category_Table extends WP_List_Table {
95
  ***************************************************************************/
96
  public function get_columns() {
97
  return array(
98
- 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
99
  'name' => 'Name',
100
  'desc' => 'Description',
101
  'slug' => 'Slug',
@@ -132,10 +140,15 @@ class EL_Category_Table extends WP_List_Table {
132
  * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
133
  ****************************************************************************/
134
  public function get_bulk_actions() {
135
- $actions = array(
136
- 'delete_bulk' => 'Delete'
137
- );
138
- return $actions;
 
 
 
 
 
139
  }
140
 
141
  /** ************************************************************************
@@ -144,10 +157,12 @@ class EL_Category_Table extends WP_List_Table {
144
  * @see $this->prepare_items()
145
  ***************************************************************************/
146
  private function process_bulk_action() {
147
- //Detect when a bulk action is being triggered...
148
- if( 'delete_bulk' === $this->current_action() ) {
149
- // Show confirmation window before deleting
150
- echo '<script language="JavaScript">eventlist_deleteCategory ("'.implode( ', ', $_GET['slug'] ).'");</script>';
 
 
151
  }
152
  }
153
 
15
  private $options;
16
  private $db;
17
  private $categories;
18
+ private $is_disabled;
19
 
20
+ public function __construct($is_disabled) {
21
  $this->options = &EL_Options::get_instance();
22
  $this->db = &EL_Db::get_instance();
23
  $this->categories = &EL_Categories::get_instance();
24
+ $this->is_disabled = $is_disabled;
25
  //Set parent defaults
26
  parent::__construct( array(
27
  'singular' => 'event', //singular name of the listed records
61
  * @return string Text to be placed inside the column <td> (movie title only)
62
  ***************************************************************************/
63
  protected function column_name($item) {
 
 
 
 
 
64
  // create prefix with indenting according cat level
65
  $prefix = str_pad('', 7*$item['level'], '&#8212;', STR_PAD_LEFT).' ';
66
+ $out = '<b>'.$prefix.$item['name'].'</b>';
67
+ if(!$this->is_disabled) {
68
+ // prepare Actions
69
+ $actions = array(
70
+ 'edit' => '<a href="?page='.$_REQUEST['page'].'&amp;id='.$item['slug'].'&amp;action=edit">Edit</a>',
71
+ 'delete' => '<a href="#" onClick="eventlist_deleteCategory(\''.$item['slug'].'\');return false;">Delete</a>'
72
+ );
73
+ //Return the title contents
74
+ $out .= $this->row_actions($actions);
75
+ }
76
+ return $out;
77
  }
78
 
79
  /** ************************************************************************
85
  * @return string Text to be placed inside the column <td> (movie title only)
86
  ***************************************************************************/
87
  protected function column_cb($item) {
88
+ if(!$this->is_disabled) {
89
+ return '<input type="checkbox" name="slug[]" value="'.$item['slug'].'" />';
90
+ }
91
+ else {
92
+ return '';
93
+ }
94
  }
95
 
96
  /** ************************************************************************
103
  ***************************************************************************/
104
  public function get_columns() {
105
  return array(
106
+ 'cb' => $this->is_disabled ? '' : '<input type="checkbox" />', //Render a checkbox instead of text
107
  'name' => 'Name',
108
  'desc' => 'Description',
109
  'slug' => 'Slug',
140
  * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
141
  ****************************************************************************/
142
  public function get_bulk_actions() {
143
+ if(!$this->is_disabled) {
144
+ $actions = array(
145
+ 'delete_bulk' => 'Delete'
146
+ );
147
+ return $actions;
148
+ }
149
+ else {
150
+ return array();
151
+ }
152
  }
153
 
154
  /** ************************************************************************
157
  * @see $this->prepare_items()
158
  ***************************************************************************/
159
  private function process_bulk_action() {
160
+ if(!$this->is_disabled) {
161
+ //Detect when a bulk action is being triggered...
162
+ if( 'delete_bulk' === $this->current_action() ) {
163
+ // Show confirmation window before deleting
164
+ echo '<script language="JavaScript">eventlist_deleteCategory ("'.implode( ', ', $_GET['slug'] ).'");</script>';
165
+ }
166
  }
167
  }
168
 
admin/js/admin_categories.js CHANGED
@@ -1,8 +1,27 @@
1
  // Javascript functions for event-list admin_settings page
2
 
3
  // Confirmation for event deletion
4
- function eventlist_deleteCategory (id) {
5
- if (confirm("Are you sure you want to delete this event category? This is a permanent action.")) {
6
  document.location.href = "?page=el_admin_categories&slug=" + id + "&action=delete";
7
  }
8
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  // Javascript functions for event-list admin_settings page
2
 
3
  // Confirmation for event deletion
4
+ function eventlist_deleteCategory(id) {
5
+ if(confirm("Are you sure you want to delete this event category? This is a permanent action.")) {
6
  document.location.href = "?page=el_admin_categories&slug=" + id + "&action=delete";
7
  }
8
+ }
9
+
10
+ jQuery(document).ready(function($) {
11
+ // Confirmation for manual syncing with post categories
12
+ $("#manualcatsync").submit(function() {
13
+ if(!confirm("Are you sure you want to manually sync the event categories with the post categories?\n\nWarning: Please not that this will delete all categories which are not available in post categories!")) {
14
+ return false;
15
+ }
16
+ return true;
17
+ });
18
+ // Confirmation for automatic syncing with post categories
19
+ $("#catsync").submit(function() {
20
+ if($("#el_sync_cats").prop('checked')) {
21
+ if(!confirm("Are you sure you want to automatically sync the event categories with the post categories?\n\nWarning: Please not that this will delete all categories which are not available in post categories!")) {
22
+ return false;
23
+ }
24
+ }
25
+ return true;
26
+ });
27
+ });
admin/js/admin_new.js CHANGED
@@ -1,7 +1,7 @@
1
  // Javascript functions for event-list admin_new page
2
 
3
  // Date helpers
4
- jQuery(document).ready(function( $ ) {
5
  // Read required config data from hidden field json_for_js
6
  var json = $("#json_for_js").val();
7
  var conf = eval('(' + json + ')');
1
  // Javascript functions for event-list admin_new page
2
 
3
  // Date helpers
4
+ jQuery(document).ready(function($) {
5
  // Read required config data from hidden field json_for_js
6
  var json = $("#json_for_js").val();
7
  var conf = eval('(' + json + ')');
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.4.4
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.4.5
7
  Author: Michael Burtscher
8
  Author URI: http://wordpress.org/extend/plugins/event-list/
9
  License: GPLv2
includes/categories.php CHANGED
@@ -28,32 +28,37 @@ class EL_Categories {
28
  }
29
 
30
  private function initalize_cat_array() {
31
- $cat_array = (array) $this->options->get( 'el_categories' );
32
  $this->cat_array = array();
33
- foreach( $cat_array as $cat ) {
34
- // check if "parent" field is available (required due to old version without parent field)
35
- // this can be removed in a later version
36
- if(!isset($cat['parent']) || !isset($cat['level'])) {
37
- $cat['parent'] = '';
38
- $cat['level'] = 0;
 
 
 
39
  }
40
- $this->cat_array[$cat['slug']] = $cat;
41
  }
42
  }
43
 
44
- public function add_category( $cat_data ) {
45
  // check if name was set
46
  if( !isset( $cat_data['name'] ) || '' == $cat_data['name'] ) {
47
  return false;
48
  }
49
  // check if name already exists
50
- foreach( $this->cat_array as $cat ) {
51
- if( $cat['name'] == $cat_data['name'] ) {
52
- return false;
 
 
 
53
  }
54
  }
55
  // set cat name
56
- $cat['name'] = trim( $cat_data['name'] );
57
  // set slug
58
  // generate slug if no slug was given
59
  if( !isset( $cat_data['slug'] ) || '' == $cat_data['slug'] ) {
@@ -84,16 +89,25 @@ class EL_Categories {
84
  return $this->safe_categories();
85
  }
86
 
87
- public function edit_category( $cat_data, $old_slug ) {
88
  // check if slug already exists
89
  if(!isset($this->cat_array[$old_slug])) {
90
  return false;
91
  }
 
 
 
 
 
92
  unset($this->cat_array[$old_slug]);
93
- return $this->add_category($cat_data);
 
94
  }
95
 
96
- public function remove_categories( $slugs ) {
 
 
 
97
  foreach( $slugs as $slug ) {
98
  unset( $this->cat_array[$slug] );
99
  }
@@ -101,9 +115,14 @@ class EL_Categories {
101
  }
102
 
103
  private function safe_categories() {
104
- $cat_array = $this->get_cat_array('slug', true);
105
- if(!is_array($cat_array) || empty($cat_array)) {
106
- return false;
 
 
 
 
 
107
  }
108
  if(!$this->options->set('el_categories', $cat_array)) {
109
  return false;
@@ -111,8 +130,102 @@ class EL_Categories {
111
  return true;
112
  }
113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  public function get_cat_array($sort_key='name', $sort_order='asc') {
115
- return $this->get_cat_child_array('', $sort_key, $sort_order);
 
 
 
 
 
116
  }
117
 
118
  private function get_cat_child_array($slug, $sort_key, $sort_order) {
28
  }
29
 
30
  private function initalize_cat_array() {
31
+ $cat_array = $this->options->get('el_categories');
32
  $this->cat_array = array();
33
+ if(!empty($cat_array)) {
34
+ foreach($cat_array as $cat) {
35
+ // check if "parent" field is available (required due to old version without parent field)
36
+ // this can be removed in a later version
37
+ if(!isset($cat['parent']) || !isset($cat['level'])) {
38
+ $cat['parent'] = '';
39
+ $cat['level'] = 0;
40
+ }
41
+ $this->cat_array[$cat['slug']] = $cat;
42
  }
 
43
  }
44
  }
45
 
46
+ public function add_category($cat_data, $allow_identical_names=false) {
47
  // check if name was set
48
  if( !isset( $cat_data['name'] ) || '' == $cat_data['name'] ) {
49
  return false;
50
  }
51
  // check if name already exists
52
+ $cat_data['name'] = trim($cat_data['name']);
53
+ if(!$allow_identical_names) {
54
+ foreach( $this->cat_array as $category ) {
55
+ if( $category['name'] === $cat_data['name'] ) {
56
+ return false;
57
+ }
58
  }
59
  }
60
  // set cat name
61
+ $cat['name'] = $cat_data['name'];
62
  // set slug
63
  // generate slug if no slug was given
64
  if( !isset( $cat_data['slug'] ) || '' == $cat_data['slug'] ) {
89
  return $this->safe_categories();
90
  }
91
 
92
+ public function edit_category($cat_data, $old_slug, $allow_identical_names=false) {
93
  // check if slug already exists
94
  if(!isset($this->cat_array[$old_slug])) {
95
  return false;
96
  }
97
+ // update events if slug has changed
98
+ if($old_slug != $cat_data['slug']) {
99
+ $this->db->change_category_slug_in_events($old_slug, $cat_data['slug']);
100
+ }
101
+ // delete old category
102
  unset($this->cat_array[$old_slug]);
103
+ // add new category
104
+ return $this->add_category($cat_data, $allow_identical_names);
105
  }
106
 
107
+ public function remove_categories($slugs, $remove_cats_in_events=true) {
108
+ if($remove_cats_in_events) {
109
+ $this->db->remove_category_in_events($slugs);
110
+ }
111
  foreach( $slugs as $slug ) {
112
  unset( $this->cat_array[$slug] );
113
  }
115
  }
116
 
117
  private function safe_categories() {
118
+ if(empty($this->cat_array)) {
119
+ $cat_array = '';
120
+ }
121
+ else {
122
+ $cat_array = $this->get_cat_array('slug', true);
123
+ if(!is_array($cat_array) || empty($cat_array)) {
124
+ return false;
125
+ }
126
  }
127
  if(!$this->options->set('el_categories', $cat_array)) {
128
  return false;
130
  return true;
131
  }
132
 
133
+ public function sync_with_post_cats() {
134
+ $post_cats = get_categories(array('type'=>'post', 'orderby'=>'slug', 'hide_empty'=>0));
135
+ // delete not available categories(compare categories by slug)
136
+ $cats_to_delete = array();
137
+ foreach($this->cat_array as $event_cat) {
138
+ $in_array = false;
139
+ foreach($post_cats as $post_cat) {
140
+ if($post_cat->slug === $event_cat['slug']) {
141
+ $in_array = true;
142
+ break;
143
+ }
144
+ }
145
+ if(!$in_array) {
146
+ $cats_to_delete[] = $event_cat['slug'];
147
+ }
148
+ }
149
+ $this->remove_categories($cats_to_delete);
150
+ // update existing and add not existing categories
151
+ $this->update_post_cats_children(0);
152
+ }
153
+
154
+ private function update_post_cats_children($parent_id) {
155
+ $post_cats = get_categories(array('type'=>'post', 'parent'=>$parent_id, 'orderby'=>'slug', 'hide_empty'=>0));
156
+ // add not existing categories, update existing categories
157
+ if(!empty($post_cats)) {
158
+ foreach($post_cats as $post_cat) {
159
+ $in_array = false;
160
+ foreach($this->cat_array as $event_cat) {
161
+ if($event_cat['slug'] === $post_cat->slug) {
162
+ $in_array = true;
163
+ // update an already existing category
164
+ $cat_data = $this->get_cat_data_from_post_cat($post_cat);
165
+ $this->edit_category($cat_data, $event_cat['slug'], true);
166
+ break;
167
+ }
168
+ }
169
+ // add a new category
170
+ if(!$in_array) {
171
+ $cat_data = $this->get_cat_data_from_post_cat($post_cat);
172
+ $this->add_category($cat_data, true);
173
+ }
174
+ // update the children of the actual category
175
+ $this->update_post_cats_children($post_cat->cat_ID);
176
+ }
177
+ }
178
+ }
179
+
180
+ private function get_cat_data_from_post_cat($post_cat) {
181
+ $cat['name'] = $post_cat->name;
182
+ $cat['slug'] = $post_cat->slug;
183
+ $cat['desc'] = $post_cat->description;
184
+ if(0 != $post_cat->parent) {
185
+ $cat['parent'] = get_category($post_cat->parent)->slug;
186
+ }
187
+ return $cat;
188
+ }
189
+
190
+ public function add_post_category($cat_id) {
191
+ $cat_data = $this->get_cat_data_from_post_cat(get_category($cat_id));
192
+ $this->add_category($cat_data, true);
193
+ }
194
+
195
+ public function edit_post_category($cat_id) {
196
+ // the get_category still holds the old cat_data
197
+ // the new data is available in $_POST
198
+ if(isset($_POST['name'])) {
199
+ $old_slug = get_category($cat_id)->slug;
200
+ // set new cat_data from $_POST
201
+ $cat_data['name'] = $_POST['name'];
202
+ $cat_data['slug'] = isset($_POST['slug']) ? $_POST['slug'] : '';
203
+ $cat_data['desc'] = isset($_POST['description']) ? $_POST['description'] : '';
204
+ if(isset($_POST['parent']) && 0 != $_POST['parent']) {
205
+ $cat_data['parent'] = get_category($_POST['parent'])->slug;
206
+ }
207
+ // edit event category
208
+ $this->edit_category($cat_data, $old_slug, true);
209
+ }
210
+ }
211
+
212
+ public function delete_post_category($cat_id) {
213
+ // search for deleted categories
214
+ foreach($this->cat_array as $event_cat) {
215
+ if(false == get_category_by_slug($event_cat['slug'])) {
216
+ $this->remove_categories(array($event_cat['slug']));
217
+ break;
218
+ }
219
+ }
220
+ }
221
+
222
  public function get_cat_array($sort_key='name', $sort_order='asc') {
223
+ if(empty($this->cat_array)) {
224
+ return array();
225
+ }
226
+ else {
227
+ return $this->get_cat_child_array('', $sort_key, $sort_order);
228
+ }
229
  }
230
 
231
  private function get_cat_child_array($slug, $sort_key, $sort_order) {
includes/db.php CHANGED
@@ -179,24 +179,24 @@ class EL_Db {
179
  }
180
  }
181
 
182
- public function remove_category_in_events( $category_slugs ) {
183
  global $wpdb;
184
- $sql = 'SELECT * FROM '.$this->table.' WHERE categories LIKE "%|'.implode( '|%" OR categories LIKE "%|', $category_slugs ).'|%"';
185
  $affected_events = $wpdb->get_results($sql, ARRAY_A);
186
- foreach( $affected_events as $event ) {
187
  // remove category from categorystring
188
- foreach( $category_slugs as $slug ) {
189
- $event['categories'] = str_replace('|'.$slug, '', $event['categories']);
190
  }
191
- if( 3 > strlen( $event['categories'] ) ) {
192
  $event['categories'] = '';
193
  }
194
  else {
195
- $event['categories'] = explode( '|', substr($event['categories'], 1, -1 ) );
196
  }
197
- $this->update_event( $event );
198
  }
199
- return count( $affected_events );
200
  }
201
 
202
  public function change_category_slug_in_events($old_slug, $new_slug) {
179
  }
180
  }
181
 
182
+ public function remove_category_in_events($category_slugs) {
183
  global $wpdb;
184
+ $sql = 'SELECT * FROM '.$this->table.' WHERE categories LIKE "%|'.implode('|%" OR categories LIKE "%|', $category_slugs).'|%"';
185
  $affected_events = $wpdb->get_results($sql, ARRAY_A);
186
+ foreach($affected_events as $event) {
187
  // remove category from categorystring
188
+ foreach($category_slugs as $slug) {
189
+ $event['categories'] = str_replace('|'.$slug.'|', '|', $event['categories']);
190
  }
191
+ if(3 > strlen( $event['categories'])) {
192
  $event['categories'] = '';
193
  }
194
  else {
195
+ $event['categories'] = explode( '|', substr($event['categories'], 1, -1));
196
  }
197
+ $this->update_event($event);
198
  }
199
+ return count($affected_events);
200
  }
201
 
202
  public function change_category_slug_in_events($old_slug, $new_slug) {
includes/options.php CHANGED
@@ -29,29 +29,37 @@ class EL_Options {
29
  'std_val' => '',
30
  'label' => '',
31
  'caption' => '',
32
- 'desc' => 'Database version' ),
33
 
34
  'el_categories' => array( 'section' => 'categories',
35
  'type' => 'category',
36
  'std_val' => null,
37
- 'label' => 'Event Categories',
38
  'caption' => '',
39
- 'desc' => 'This option specifies all event category data.' ),
 
 
 
 
 
 
 
 
40
 
41
  'el_no_event_text' => array( 'section' => 'general',
42
  'type' => 'text',
43
  'std_val' => 'no event',
44
- 'label' => 'Text for no events',
45
  'caption' => '',
46
- 'desc' => 'This option defines the text which is displayed if no events are available for the selected view.' ),
47
 
48
  'el_date_once_per_day' => array( 'section' => 'general',
49
  'type' => 'checkbox',
50
  'std_val' => '',
51
- 'label' => 'Date display',
52
- 'caption' => 'Show date only once per day',
53
- 'desc' => 'With this option you can display the date only once per day if multiple events are available on the same day.<br />
54
- If this option is enabled the events are ordered in a different way (end date before start time) to allow using the same date for as much events as possible.' ),
55
  );
56
  }
57
 
29
  'std_val' => '',
30
  'label' => '',
31
  'caption' => '',
32
+ 'desc' => __('Database version')),
33
 
34
  'el_categories' => array( 'section' => 'categories',
35
  'type' => 'category',
36
  'std_val' => null,
37
+ 'label' => __('Event Categories'),
38
  'caption' => '',
39
+ 'desc' => __('This option specifies all event category data.')),
40
+
41
+ 'el_sync_cats' => array( 'section' => 'categories',
42
+ 'type' => 'checkbox',
43
+ 'std_val' => '',
44
+ 'label' => __('Sync Categories'),
45
+ 'caption' => __('Keep event categories in sync with post categories automatically'),
46
+ 'desc' => '<table><tr style="vertical-align:top"><td><strong>'.__('Attention').':</strong></td>
47
+ <td>'.__('Please note that this option will delete all categories which are not available in the post categories! Existing Categories with the same slug will be updated.').'</td></tr></table>'),
48
 
49
  'el_no_event_text' => array( 'section' => 'general',
50
  'type' => 'text',
51
  'std_val' => 'no event',
52
+ 'label' => __('Text for no events'),
53
  'caption' => '',
54
+ 'desc' => __('This option defines the text which is displayed if no events are available for the selected view.')),
55
 
56
  'el_date_once_per_day' => array( 'section' => 'general',
57
  'type' => 'checkbox',
58
  'std_val' => '',
59
+ 'label' => __('Date display'),
60
+ 'caption' => __('Show date only once per day'),
61
+ 'desc' => __('With this option you can display the date only once per day if multiple events are available on the same day.<br />
62
+ If this option is enabled the events are ordered in a different way (end date before start time) to allow using the same date for as much events as possible.')),
63
  );
64
  }
65
 
readme.txt CHANGED
@@ -3,8 +3,8 @@ 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
5
  Requires at least: 3.3
6
- Tested up to: 3.5.2
7
- Stable tag: 0.4.4
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
@@ -24,6 +24,7 @@ The purpose of this plugin is to to show a list of events with date, time, descr
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
 
28
  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:
29
 
@@ -66,6 +67,13 @@ Yes, you can create an instance of the "SC_Event_List" class which located in "i
66
 
67
  == Changelog ==
68
 
 
 
 
 
 
 
 
69
  = 0.4.4 (2013-07-20) =
70
 
71
  * added support for sub-categories
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
5
  Requires at least: 3.3
6
+ Tested up to: 3.6
7
+ Stable tag: 0.4.5
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
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
 
29
  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:
30
 
67
 
68
  == Changelog ==
69
 
70
+ = 0.4.5 (2013-08-05) =
71
+
72
+ * added capability to sync the event categories with the post categories (manually or automatically)
73
+ * fixed problem with empty category list
74
+ * fixed link to category page in new event page
75
+ * fixed indention in in category parent combo box
76
+
77
  = 0.4.4 (2013-07-20) =
78
 
79
  * added support for sub-categories