Events Manager - Version 5.9

Version Description

  • fixes applied to 5.8.1.2 merged into dev version
  • added timezone support
  • added new admin notice interface objects
  • added new EM_Options option storage class
  • fixed some PHP strict warnings regarding parent/child class method signatures
  • fixed taxonomy pagination issues in AJAX (affecting tags specifically)
  • fixed shortcode not getting parsed properly due to fix in 5.8.1.1 attempting to parse shortcode with supplied formats
  • fixed non-standard YYYY-M-D date formats not being accepted in scope arguments
  • improved multisite blog update interface
  • added modular update logic to admin pages for future features
  • further hardening against XSS strings
  • fixed non-standard YYYY-M-D date formats not being accepted in scope arguments
  • fixed duplicate slug issues when duplicating events
  • removed all references of create_function for php 7.2 compatibility
  • fixed documented 'postcode' search attribute not filtering results by that value
  • fixed event duplication not copying other plugin meta data, such as ACF
  • fixed EM_Bookings::get() producing SQL error if passing an array of booking IDs
  • added em_event_post_scope_meta_query filter for admin-side custom scopes
  • fixed bug where blank start/end times of tickets and booking cut-offs default to 12AM istead of event start time
  • fixed preview mode not reflecting new event description
  • fixed broken ical permalinks for individual subcategories
  • changed recurrence warning strips from green to orange/blue at top of admin pages
  • added 'ticket total' column to bookings export and split 'ticket price' from 'total' booking price when exporting split by ticket type
  • fixed issues with caching not getting updated other plugins data such as ACF and possibly others
  • fixed issue where logged out user didn't see login feedback message on booking form under certain setting combinations
  • added EM_ML::restore_current_lang and EM_ML::switch_to_lang functions
  • fixed language detection of bookings not being done early enough
Download this release

Release Info

Developer netweblogic
Plugin Icon 128x128 Events Manager
Version 5.9
Comparing to
See all releases

Code changes from version 5.8.1.3 to 5.9

Files changed (289) hide show
  1. admin/bookings/em-cancelled.php +0 -0
  2. admin/bookings/em-confirmed.php +0 -0
  3. admin/bookings/em-events.php +7 -18
  4. admin/bookings/em-pending.php +0 -0
  5. admin/bookings/em-person.php +0 -0
  6. admin/bookings/em-rejected.php +0 -0
  7. admin/em-admin.php +0 -0
  8. admin/em-bookings.php +6 -16
  9. admin/em-docs.php +1 -1
  10. admin/em-help.php +0 -0
  11. admin/em-locations-search.php +0 -0
  12. admin/em-ms-options.php +17 -8
  13. admin/em-options.php +104 -1
  14. admin/settings/tabs/bookings.php +1 -1
  15. admin/settings/tabs/emails.php +0 -0
  16. admin/settings/tabs/formats.php +0 -0
  17. admin/settings/tabs/general.php +14 -0
  18. admin/settings/tabs/pages.php +2 -2
  19. admin/settings/updates/timezone-backcompat.php +112 -0
  20. admin/settings/wpfc-admin.php +0 -0
  21. buddypress/bp-em-activity.php +0 -0
  22. buddypress/bp-em-core.php +2 -2
  23. buddypress/bp-em-groups.php +0 -0
  24. buddypress/bp-em-notifications.php +0 -0
  25. buddypress/bp-em-templatetags.php +0 -0
  26. buddypress/screens/attending.php +0 -0
  27. buddypress/screens/group-events.php +0 -0
  28. buddypress/screens/my-bookings.php +0 -0
  29. buddypress/screens/my-events.php +0 -0
  30. buddypress/screens/my-group-events.php +0 -0
  31. buddypress/screens/my-locations.php +0 -0
  32. buddypress/screens/profile.php +0 -0
  33. classes/em-admin-notice.php +176 -0
  34. classes/em-admin-notices.php +195 -0
  35. classes/em-booking.php +73 -11
  36. classes/em-bookings-table.php +23 -20
  37. classes/em-bookings.php +22 -14
  38. classes/em-calendar.php +18 -17
  39. classes/em-categories-admin.php +0 -0
  40. classes/em-categories-frontend.php +0 -0
  41. classes/em-categories.php +1 -0
  42. classes/em-category.php +2 -2
  43. classes/em-datetime.php +480 -0
  44. classes/em-event-post-admin.php +26 -5
  45. classes/em-event-post.php +50 -69
  46. classes/em-event-posts-admin.php +6 -5
  47. classes/em-event.php +476 -213
  48. classes/em-events.php +39 -34
  49. classes/em-location-post-admin.php +21 -0
  50. classes/em-location.php +11 -7
  51. classes/em-locations.php +1 -0
  52. classes/em-mailer.php +8 -4
  53. classes/em-notices.php +0 -0
  54. classes/em-object.php +82 -97
  55. classes/em-options.php +105 -0
  56. classes/em-people.php +0 -0
  57. classes/em-permalinks.php +1 -1
  58. classes/em-person.php +0 -0
  59. classes/em-tag.php +3 -3
  60. classes/em-tags-admin.php +0 -0
  61. classes/em-tags-frontend.php +0 -0
  62. classes/em-tags.php +2 -1
  63. classes/em-taxonomy-admin.php +0 -0
  64. classes/em-taxonomy-frontend.php +8 -5
  65. classes/em-taxonomy-term.php +2 -2
  66. classes/em-taxonomy-terms.php +10 -4
  67. classes/em-ticket-booking.php +1 -0
  68. classes/em-ticket.php +130 -37
  69. classes/em-tickets-bookings.php +0 -0
  70. classes/em-tickets.php +0 -0
  71. em-debug.php +10 -2
  72. em-events.php +2 -1
  73. em-functions.php +0 -0
  74. em-ical.php +0 -0
  75. em-install.php +236 -7
  76. em-rss.php +41 -0
  77. em-shortcode.php +0 -0
  78. em-template-tags.php +0 -0
  79. em-wpfc.php +14 -12
  80. events-manager.php +8 -4
  81. includes/css/events_manager.css +0 -0
  82. includes/css/events_manager_admin.css +4 -0
  83. includes/css/images/loading.gif +0 -0
  84. includes/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  85. includes/css/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  86. includes/css/images/ui-bg_flat_10_000000_40x100.png +0 -0
  87. includes/css/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  88. includes/css/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  89. includes/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  90. includes/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  91. includes/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  92. includes/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  93. includes/css/images/ui-icons_222222_256x240.png +0 -0
  94. includes/css/images/ui-icons_228ef1_256x240.png +0 -0
  95. includes/css/images/ui-icons_ef8c08_256x240.png +0 -0
  96. includes/css/images/ui-icons_ffd27a_256x240.png +0 -0
  97. includes/css/images/ui-icons_ffffff_256x240.png +0 -0
  98. includes/css/jquery-ui.css +0 -0
  99. includes/css/jquery-ui.min.css +0 -0
  100. includes/images/baloon.png +0 -0
  101. includes/images/calendar-16.png +0 -0
  102. includes/images/calendar-32.png +0 -0
  103. includes/images/close.png +0 -0
  104. includes/images/event-caps-source.png +0 -0
  105. includes/images/event-caps.jpg +0 -0
  106. includes/images/event-perms-source.png +0 -0
  107. includes/images/loading.gif +0 -0
  108. includes/js/events-manager.js +21 -19
  109. includes/js/events-manager.min.js +3 -0
  110. includes/js/i18n/jquery-ui-i18n.js +1199 -0
  111. includes/js/i18n/jquery.ui.datepicker-af.js +23 -0
  112. includes/js/i18n/jquery.ui.datepicker-ar.js +24 -0
  113. includes/js/i18n/jquery.ui.datepicker-az.js +23 -0
  114. includes/js/i18n/jquery.ui.datepicker-bg.js +24 -0
  115. includes/js/i18n/jquery.ui.datepicker-bs.js +23 -0
  116. includes/js/i18n/jquery.ui.datepicker-ca.js +23 -0
  117. includes/js/i18n/jquery.ui.datepicker-cs.js +23 -0
  118. includes/js/i18n/jquery.ui.datepicker-da.js +23 -0
  119. includes/js/i18n/jquery.ui.datepicker-de.js +23 -0
  120. includes/js/i18n/jquery.ui.datepicker-el.js +23 -0
  121. includes/js/i18n/jquery.ui.datepicker-en-GB.js +23 -0
  122. includes/js/i18n/jquery.ui.datepicker-eo.js +23 -0
  123. includes/js/i18n/jquery.ui.datepicker-es.js +23 -0
  124. includes/js/i18n/jquery.ui.datepicker-et.js +23 -0
  125. includes/js/i18n/jquery.ui.datepicker-eu.js +23 -0
  126. includes/js/i18n/jquery.ui.datepicker-fa.js +23 -0
  127. includes/js/i18n/jquery.ui.datepicker-fi.js +23 -0
  128. includes/js/i18n/jquery.ui.datepicker-fo.js +23 -0
  129. includes/js/i18n/jquery.ui.datepicker-fr-CH.js +23 -0
  130. includes/js/i18n/jquery.ui.datepicker-fr.js +23 -0
  131. includes/js/i18n/jquery.ui.datepicker-he.js +23 -0
  132. includes/js/i18n/jquery.ui.datepicker-hr.js +23 -0
  133. includes/js/i18n/jquery.ui.datepicker-hu.js +23 -0
  134. includes/js/i18n/jquery.ui.datepicker-hy.js +23 -0
  135. includes/js/i18n/jquery.ui.datepicker-id.js +23 -0
  136. includes/js/i18n/jquery.ui.datepicker-is.js +23 -0
  137. includes/js/i18n/jquery.ui.datepicker-it.js +23 -0
  138. includes/js/i18n/jquery.ui.datepicker-ja.js +23 -0
  139. includes/js/i18n/jquery.ui.datepicker-ko.js +23 -0
  140. includes/js/i18n/jquery.ui.datepicker-kz.js +23 -0
  141. includes/js/i18n/jquery.ui.datepicker-lt.js +23 -0
  142. includes/js/i18n/jquery.ui.datepicker-lv.js +23 -0
  143. includes/js/i18n/jquery.ui.datepicker-ms.js +23 -0
  144. includes/js/i18n/jquery.ui.datepicker-nl.js +24 -0
  145. includes/js/i18n/jquery.ui.datepicker-no.js +23 -0
  146. includes/js/i18n/jquery.ui.datepicker-pl.js +23 -0
  147. includes/js/i18n/jquery.ui.datepicker-pt-BR.js +23 -0
  148. includes/js/i18n/jquery.ui.datepicker-ro.js +26 -0
  149. includes/js/i18n/jquery.ui.datepicker-ru.js +23 -0
  150. includes/js/i18n/jquery.ui.datepicker-sk.js +23 -0
  151. includes/js/i18n/jquery.ui.datepicker-sl.js +24 -0
  152. includes/js/i18n/jquery.ui.datepicker-sq.js +23 -0
  153. includes/js/i18n/jquery.ui.datepicker-sr-SR.js +23 -0
  154. includes/js/i18n/jquery.ui.datepicker-sr.js +23 -0
  155. includes/js/i18n/jquery.ui.datepicker-sv.js +23 -0
  156. includes/js/i18n/jquery.ui.datepicker-ta.js +23 -0
  157. includes/js/i18n/jquery.ui.datepicker-th.js +23 -0
  158. includes/js/i18n/jquery.ui.datepicker-tr.js +23 -0
  159. includes/js/i18n/jquery.ui.datepicker-uk.js +23 -0
  160. includes/js/i18n/jquery.ui.datepicker-vi.js +23 -0
  161. includes/js/i18n/jquery.ui.datepicker-zh-CN.js +23 -0
  162. includes/js/i18n/jquery.ui.datepicker-zh-HK.js +23 -0
  163. includes/js/i18n/jquery.ui.datepicker-zh-TW.js +23 -0
  164. includes/js/taxonomies-admin.js +0 -0
  165. includes/langs/events-manager-ar.mo +0 -0
  166. includes/langs/events-manager-ar.po +0 -0
  167. includes/langs/events-manager-ca.mo +0 -0
  168. includes/langs/events-manager-ca.po +0 -0
  169. includes/langs/events-manager-cs_CZ.mo +0 -0
  170. includes/langs/events-manager-cs_CZ.po +0 -0
  171. includes/langs/events-manager-da_DK.mo +0 -0
  172. includes/langs/events-manager-da_DK.po +0 -0
  173. includes/langs/events-manager-de_DE.mo +0 -0
  174. includes/langs/events-manager-de_DE.po +0 -0
  175. includes/langs/events-manager-el.mo +0 -0
  176. includes/langs/events-manager-el.po +0 -0
  177. includes/langs/events-manager-en_AU.mo +0 -0
  178. includes/langs/events-manager-en_AU.po +0 -0
  179. includes/langs/events-manager-en_CA.mo +0 -0
  180. includes/langs/events-manager-en_CA.po +0 -0
  181. includes/langs/events-manager-en_GB.mo +0 -0
  182. includes/langs/events-manager-en_GB.po +0 -0
  183. includes/langs/events-manager-es_ES.mo +0 -0
  184. includes/langs/events-manager-es_ES.po +0 -0
  185. includes/langs/events-manager-et.mo +0 -0
  186. includes/langs/events-manager-et.po +0 -0
  187. includes/langs/events-manager-fa_IR.mo +0 -0
  188. includes/langs/events-manager-fa_IR.po +0 -0
  189. includes/langs/events-manager-fi.mo +0 -0
  190. includes/langs/events-manager-fi.po +0 -0
  191. includes/langs/events-manager-fr_FR.mo +0 -0
  192. includes/langs/events-manager-fr_FR.po +0 -0
  193. includes/langs/events-manager-he_IL.mo +0 -0
  194. includes/langs/events-manager-he_IL.po +0 -0
  195. includes/langs/events-manager-hu_HU.mo +0 -0
  196. includes/langs/events-manager-hu_HU.po +0 -0
  197. includes/langs/events-manager-it_IT.mo +0 -0
  198. includes/langs/events-manager-it_IT.po +0 -0
  199. includes/langs/events-manager-ja.mo +0 -0
  200. includes/langs/events-manager-ja.po +0 -0
  201. includes/langs/events-manager-nb_NO.mo +0 -0
  202. includes/langs/events-manager-nb_NO.po +0 -0
  203. includes/langs/events-manager-nl_NL.mo +0 -0
  204. includes/langs/events-manager-nl_NL.po +0 -0
  205. includes/langs/events-manager-no_NO.mo +0 -0
  206. includes/langs/events-manager-no_NO.po +0 -0
  207. includes/langs/events-manager-pl_PL.mo +0 -0
  208. includes/langs/events-manager-pl_PL.po +0 -0
  209. includes/langs/events-manager-pt_BR.mo +0 -0
  210. includes/langs/events-manager-pt_BR.po +0 -0
  211. includes/langs/events-manager-pt_PT.mo +0 -0
  212. includes/langs/events-manager-pt_PT.po +0 -0
  213. includes/langs/events-manager-ru_RU.mo +0 -0
  214. includes/langs/events-manager-ru_RU.po +0 -0
  215. includes/langs/events-manager-sk_SK.mo +0 -0
  216. includes/langs/events-manager-sk_SK.po +0 -0
  217. includes/langs/events-manager-sl_SI.mo +0 -0
  218. includes/langs/events-manager-sl_SI.po +0 -0
  219. includes/langs/events-manager-sv_SE.mo +0 -0
  220. includes/langs/events-manager-sv_SE.po +0 -0
  221. includes/langs/events-manager-tr_TR.mo +0 -0
  222. includes/langs/events-manager-tr_TR.po +0 -0
  223. includes/langs/events-manager-zh_CN.mo +0 -0
  224. includes/langs/events-manager-zh_CN.po +0 -0
  225. includes/langs/events-manager-zh_TW.mo +0 -0
  226. includes/langs/events-manager-zh_TW.po +0 -0
  227. includes/langs/events-manager.pot +0 -0
  228. includes/sample-placeholders/booking-email.html +0 -0
  229. includes/sample-placeholders/event-list-default.html +0 -0
  230. includes/sample-placeholders/event-single-default.html +0 -0
  231. includes/sample-placeholders/event-single.html +0 -0
  232. includes/sample-placeholders/location-single-default.html +0 -0
  233. multilingual/em-ml-admin.php +8 -0
  234. multilingual/em-ml-bookings.php +4 -3
  235. multilingual/em-ml-io.php +1 -3
  236. multilingual/em-ml-options.php +5 -7
  237. multilingual/em-ml-placeholders.php +0 -0
  238. multilingual/em-ml-search.php +0 -0
  239. multilingual/em-ml.php +28 -0
  240. plugins/wp-seo.php +12 -0
  241. readme.txt +32 -2
  242. screenshot-1.png +0 -0
  243. screenshot-2.png +0 -0
  244. screenshot-3.png +0 -0
  245. screenshot-4.png +0 -0
  246. screenshot-5.png +0 -0
  247. screenshot-6.png +0 -0
  248. templates/buddypress/group-events.php +5 -14
  249. templates/buddypress/my-bookings.php +0 -0
  250. templates/buddypress/my-events.php +0 -0
  251. templates/buddypress/my-group-events.php +4 -16
  252. templates/buddypress/my-locations.php +0 -0
  253. templates/formats/readme.txt +0 -0
  254. templates/forms/event-editor.php +0 -0
  255. templates/forms/event/bookings-ticket-form.php +7 -7
  256. templates/forms/event/bookings.php +5 -5
  257. templates/forms/event/recurring-when.php +12 -4
  258. templates/forms/event/when-with-recurring.php +12 -4
  259. templates/forms/event/when.php +13 -5
  260. templates/forms/location-editor.php +0 -0
  261. templates/forms/readme.txt +0 -0
  262. templates/forms/ticket-form.php +0 -0
  263. templates/forms/tickets-form.php +0 -0
  264. templates/placeholders/attendees.php +0 -0
  265. templates/placeholders/bookingbutton.php +0 -0
  266. templates/placeholders/bookingform.php +1 -1
  267. templates/placeholders/categories.php +0 -0
  268. templates/placeholders/locationmap.php +0 -0
  269. templates/placeholders/readme.txt +0 -0
  270. templates/tables/events.php +4 -17
  271. templates/templates/calendar-day.php +0 -0
  272. templates/templates/calendar-full.php +0 -0
  273. templates/templates/calendar-small.php +0 -0
  274. templates/templates/categories-list.php +0 -0
  275. templates/templates/category-single.php +0 -0
  276. templates/templates/event-single.php +0 -0
  277. templates/templates/events-calendar.php +0 -0
  278. templates/templates/events-list.php +0 -0
  279. templates/templates/events-search.php +0 -0
  280. templates/templates/ical.php +108 -19
  281. templates/templates/location-single.php +0 -0
  282. templates/templates/locations-list.php +0 -0
  283. templates/templates/map-global.php +0 -0
  284. templates/templates/my-bookings.php +1 -1
  285. templates/templates/readme.txt +0 -0
  286. templates/templates/rss.php +2 -2
  287. widgets/em-calendar.php +6 -1
  288. widgets/em-events.php +5 -1
  289. widgets/em-locations.php +5 -1
admin/bookings/em-cancelled.php CHANGED
File without changes
admin/bookings/em-confirmed.php CHANGED
File without changes
admin/bookings/em-events.php CHANGED
@@ -7,7 +7,6 @@
7
  function em_bookings_events_table() {
8
  //TODO Simplify panel for events, use form flags to detect certain actions (e.g. submitted, etc)
9
  global $wpdb;
10
- global $EM_Event;
11
 
12
  $scope_names = array (
13
  'past' => __ ( 'Past events', 'events-manager'),
@@ -36,7 +35,7 @@ function em_bookings_events_table() {
36
  $scope = "future";
37
  }
38
  $owner = !current_user_can('manage_others_bookings') ? get_current_user_id() : false;
39
- $events = EM_Events::get( array('scope'=>$scope, 'limit'=>$limit, 'offset' => $offset, 'order'=>$order, 'bookings'=>true, 'owner' => $owner, 'pagination' => 1 ) );
40
  $events_count = EM_Events::$num_rows_found;
41
 
42
  $use_events_end = get_option ( 'dbem_use_event_end' );
@@ -98,40 +97,30 @@ function em_bookings_events_table() {
98
  <tbody>
99
  <?php
100
  $rowno = 0;
101
- foreach ( $events as $event ) {
102
  /* @var $event EM_Event */
103
  $rowno++;
104
  $class = ($rowno % 2) ? ' class="alternate"' : '';
105
- // FIXME set to american
106
- $localised_start_date = date_i18n(get_option('date_format'), $event->start);
107
- $localised_end_date = date_i18n(get_option('date_format'), $event->end);
108
  $style = "";
109
- $today = date ( "Y-m-d" );
110
 
111
- if ($event->start_date < $today && $event->end_date < $today){
112
  $style = "style ='background-color: #FADDB7;'";
113
  }
114
  ?>
115
  <tr <?php echo "$class $style"; ?>>
116
  <td>
117
  <strong>
118
- <?php echo $event->output('#_BOOKINGSLINK'); ?>
119
  </strong>
120
  &ndash;
121
- <?php esc_html_e("Booked Spaces",'events-manager') ?>: <?php echo $event->get_bookings()->get_booked_spaces()."/".$event->get_spaces() ?>
122
  <?php if( get_option('dbem_bookings_approval') == 1 ) : ?>
123
- | <?php esc_html_e("Pending",'events-manager') ?>: <?php echo $event->get_bookings()->get_pending_spaces(); ?>
124
  <?php endif; ?>
125
  </td>
126
 
127
  <td>
128
- <?php echo $localised_start_date; ?>
129
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
130
- &ndash;
131
- <?php
132
- //TODO Should 00:00 - 00:00 be treated as an all day event?
133
- echo substr ( $event->start_time, 0, 5 ) . " - " . substr ( $event->end_time, 0, 5 );
134
- ?>
135
  </td>
136
  </tr>
137
  <?php
7
  function em_bookings_events_table() {
8
  //TODO Simplify panel for events, use form flags to detect certain actions (e.g. submitted, etc)
9
  global $wpdb;
 
10
 
11
  $scope_names = array (
12
  'past' => __ ( 'Past events', 'events-manager'),
35
  $scope = "future";
36
  }
37
  $owner = !current_user_can('manage_others_bookings') ? get_current_user_id() : false;
38
+ $events = EM_Events::get( array('scope'=>$scope, 'limit'=>$limit, 'offset' => $offset, 'order'=>$order, 'orderby'=>'event_start', 'bookings'=>true, 'owner' => $owner, 'pagination' => 1 ) );
39
  $events_count = EM_Events::$num_rows_found;
40
 
41
  $use_events_end = get_option ( 'dbem_use_event_end' );
97
  <tbody>
98
  <?php
99
  $rowno = 0;
100
+ foreach ( $events as $EM_Event ) {
101
  /* @var $event EM_Event */
102
  $rowno++;
103
  $class = ($rowno % 2) ? ' class="alternate"' : '';
 
 
 
104
  $style = "";
 
105
 
106
+ if ($EM_Event->start()->getTimestamp() < time() && $EM_Event->end()->getTimestamp() < time()){
107
  $style = "style ='background-color: #FADDB7;'";
108
  }
109
  ?>
110
  <tr <?php echo "$class $style"; ?>>
111
  <td>
112
  <strong>
113
+ <?php echo $EM_Event->output('#_BOOKINGSLINK'); ?>
114
  </strong>
115
  &ndash;
116
+ <?php esc_html_e("Booked Spaces",'events-manager') ?>: <?php echo $EM_Event->get_bookings()->get_booked_spaces()."/".$EM_Event->get_spaces() ?>
117
  <?php if( get_option('dbem_bookings_approval') == 1 ) : ?>
118
+ | <?php esc_html_e("Pending",'events-manager') ?>: <?php echo $EM_Event->get_bookings()->get_pending_spaces(); ?>
119
  <?php endif; ?>
120
  </td>
121
 
122
  <td>
123
+ <?php echo $EM_Event->output_dates(false, " - "). ' @ ' . $EM_Event->output_times('H:i', ' - '); ?>
 
 
 
 
 
 
124
  </td>
125
  </tr>
126
  <?php
admin/bookings/em-pending.php CHANGED
File without changes
admin/bookings/em-person.php CHANGED
File without changes
admin/bookings/em-rejected.php CHANGED
File without changes
admin/em-admin.php CHANGED
File without changes
admin/em-bookings.php CHANGED
@@ -79,8 +79,6 @@ function em_bookings_event(){
79
  <?php
80
  return false;
81
  }
82
- $localised_start_date = date_i18n('D d M Y', $EM_Event->start);
83
- $localised_end_date = date_i18n('D d M Y', $EM_Event->end);
84
  $header_button_classes = is_admin() ? 'page-title-action':'button add-new-h2';
85
  ?>
86
  <div class='wrap'>
@@ -106,9 +104,7 @@ function em_bookings_event(){
106
  </p>
107
  <p>
108
  <strong><?php esc_html_e('Date','events-manager'); ?></strong> :
109
- <?php echo $localised_start_date; ?>
110
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
111
- <?php echo substr ( $EM_Event->event_start_time, 0, 5 ) . " - " . substr ( $EM_Event->event_end_time, 0, 5 ); ?>
112
  </p>
113
  <p>
114
  <strong><?php esc_html_e('Location','events-manager'); ?></strong> :
@@ -158,8 +154,8 @@ function em_bookings_ticket(){
158
  <tr><td><?php echo __('Spaces','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_spaces) ? $EM_Ticket->ticket_spaces : '-'; ?></td></tr>
159
  <tr><td><?php echo __('Min','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_min) ? $EM_Ticket->ticket_min : '-'; ?></td></tr>
160
  <tr><td><?php echo __('Max','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_max) ? $EM_Ticket->ticket_max : '-'; ?></td></tr>
161
- <tr><td><?php echo __('Start','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_start) ? $EM_Ticket->ticket_start : '-'; ?></td></tr>
162
- <tr><td><?php echo __('End','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_end) ? $EM_Ticket->ticket_end : '-'; ?></td></tr>
163
  <?php do_action('em_booking_admin_ticket_row', $EM_Ticket); ?>
164
  </table>
165
  </div>
@@ -202,17 +198,13 @@ function em_bookings_single(){
202
  <div class="inside">
203
  <?php
204
  $EM_Event = $EM_Booking->get_event();
205
- $localised_start_date = date_i18n(get_option('dbem_date_format'), $EM_Event->start);
206
- $localised_end_date = date_i18n(get_option('dbem_date_format'), $EM_Event->end);
207
  ?>
208
  <table>
209
  <tr><td><strong><?php esc_html_e('Name','events-manager'); ?></strong></td><td><a class="row-title" href="<?php echo $EM_Event->get_bookings_url(); ?>"><?php echo ($EM_Event->event_name); ?></a></td></tr>
210
  <tr>
211
  <td><strong><?php esc_html_e('Date/Time','events-manager'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td>
212
  <td>
213
- <?php echo $localised_start_date; ?>
214
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
215
- <?php echo substr ( $EM_Event->event_start_time, 0, 5 ) . " - " . substr ( $EM_Event->event_end_time, 0, 5 ); ?>
216
  </td>
217
  </tr>
218
  </table>
@@ -265,8 +257,6 @@ function em_bookings_single(){
265
  <div class="inside">
266
  <?php
267
  $EM_Event = $EM_Booking->get_event();
268
- $localised_start_date = date_i18n(get_option('date_format'), $EM_Event->start);
269
- $localised_end_date = date_i18n(get_option('date_format'), $EM_Event->end);
270
  $shown_tickets = array();
271
  ?>
272
  <div>
@@ -395,12 +385,12 @@ function em_bookings_single(){
395
  </tr>
396
  <?php endforeach; ?>
397
  <?php endif; ?>
398
- <tr>
399
  <th><?php esc_html_e('Total Price','events-manager'); ?></th>
400
  <th>&nbsp;</th>
401
  <th><?php echo $price_summary['total']; ?></th>
402
  </tr>
403
- <?php do_action('em_bookings_admin_ticket_totals_footer'); ?>
404
  </tfoot>
405
  </table>
406
  <table class="em-form-fields" cellspacing="0" cellpadding="0">
79
  <?php
80
  return false;
81
  }
 
 
82
  $header_button_classes = is_admin() ? 'page-title-action':'button add-new-h2';
83
  ?>
84
  <div class='wrap'>
104
  </p>
105
  <p>
106
  <strong><?php esc_html_e('Date','events-manager'); ?></strong> :
107
+ <?php echo $EM_Event->output_dates(false, " - "). ' @ ' . $EM_Event->output_times(false, ' - '); ?>
 
 
108
  </p>
109
  <p>
110
  <strong><?php esc_html_e('Location','events-manager'); ?></strong> :
154
  <tr><td><?php echo __('Spaces','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_spaces) ? $EM_Ticket->ticket_spaces : '-'; ?></td></tr>
155
  <tr><td><?php echo __('Min','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_min) ? $EM_Ticket->ticket_min : '-'; ?></td></tr>
156
  <tr><td><?php echo __('Max','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_max) ? $EM_Ticket->ticket_max : '-'; ?></td></tr>
157
+ <tr><td><?php echo __('Start','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_start) ? $EM_Ticket->start()->formatDefault() : '-'; ?></td></tr>
158
+ <tr><td><?php echo __('End','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_end) ? $EM_Ticket->end()->formatDefault() : '-'; ?></td></tr>
159
  <?php do_action('em_booking_admin_ticket_row', $EM_Ticket); ?>
160
  </table>
161
  </div>
198
  <div class="inside">
199
  <?php
200
  $EM_Event = $EM_Booking->get_event();
 
 
201
  ?>
202
  <table>
203
  <tr><td><strong><?php esc_html_e('Name','events-manager'); ?></strong></td><td><a class="row-title" href="<?php echo $EM_Event->get_bookings_url(); ?>"><?php echo ($EM_Event->event_name); ?></a></td></tr>
204
  <tr>
205
  <td><strong><?php esc_html_e('Date/Time','events-manager'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td>
206
  <td>
207
+ <?php echo $EM_Event->output('#_EVENTDATES @ #_EVENTTIMES'); ?>
 
 
208
  </td>
209
  </tr>
210
  </table>
257
  <div class="inside">
258
  <?php
259
  $EM_Event = $EM_Booking->get_event();
 
 
260
  $shown_tickets = array();
261
  ?>
262
  <div>
385
  </tr>
386
  <?php endforeach; ?>
387
  <?php endif; ?>
388
+ <tr class="em-hr">
389
  <th><?php esc_html_e('Total Price','events-manager'); ?></th>
390
  <th>&nbsp;</th>
391
  <th><?php echo $price_summary['total']; ?></th>
392
  </tr>
393
+ <?php do_action('em_bookings_admin_ticket_totals_footer', $EM_Booking); ?>
394
  </tfoot>
395
  </table>
396
  <table class="em-form-fields" cellspacing="0" cellpadding="0">
admin/em-docs.php CHANGED
@@ -78,7 +78,7 @@ function em_docs_init($force_init = false){
78
  'format' => array( 'desc'=> 'If you are displaying some information with the shortcode or function (e.g. listing events), you can supply the html and placeholders here. When providing a custom format value, format_header and format_footer will be blank if not also provided.', 'default'=> 'The relevant default format will be taken from the settings page.'),
79
  'format_footer' => array( 'desc'=> sprintf('If you are displaying lists (e.g. listing events), you can supply the %s html and placeholders here.','footer'), 'default'=> 'If the <em>format</em> attribute is not provided, the relevant default format will be taken from the settings page.'),
80
  'limit' => array( 'desc'=> 'Limits the amount of values returned to this number.', 'default'=>'0 (no limit)'),
81
- 'offset' => array( 'desc'=> 'For example, if you have ten results, if you set this to 5, only the last 5 results will be returned. Useful for pagination.', 'default'=>0),
82
  'order' => array( 'desc'=> 'Indicates the alphabeitcal/numerical order of the lists. Choose between ASC (ascending) and DESC (descending).', 'default'=>'ASC'),
83
  'orderby' => array( 'desc'=> 'Choose what fields to order your results by. You can supply a single field or multiple comma-separated fields (e.g. "event_start_date,event_name").', 'default'=>0, 'args'=>'Database table fields, e.g. <code>event_name</code> or <code>location_name</code>'),
84
  'pagination' => array('desc'=> 'When using a function or shortcode that outputs items (e.g. [events_list] for events, [locations_list] for locations), if the number of items supercede the limit of items to show, setting this to 1 will show page links under the list.', 'default'=>0),
78
  'format' => array( 'desc'=> 'If you are displaying some information with the shortcode or function (e.g. listing events), you can supply the html and placeholders here. When providing a custom format value, format_header and format_footer will be blank if not also provided.', 'default'=> 'The relevant default format will be taken from the settings page.'),
79
  'format_footer' => array( 'desc'=> sprintf('If you are displaying lists (e.g. listing events), you can supply the %s html and placeholders here.','footer'), 'default'=> 'If the <em>format</em> attribute is not provided, the relevant default format will be taken from the settings page.'),
80
  'limit' => array( 'desc'=> 'Limits the amount of values returned to this number.', 'default'=>'0 (no limit)'),
81
+ 'offset' => array( 'desc'=> 'For example, if you have ten results, if you set this to 5, only the last 5 results will be returned. A limit higher than 0 is required for offsets to work.', 'default'=>0),
82
  'order' => array( 'desc'=> 'Indicates the alphabeitcal/numerical order of the lists. Choose between ASC (ascending) and DESC (descending).', 'default'=>'ASC'),
83
  'orderby' => array( 'desc'=> 'Choose what fields to order your results by. You can supply a single field or multiple comma-separated fields (e.g. "event_start_date,event_name").', 'default'=>0, 'args'=>'Database table fields, e.g. <code>event_name</code> or <code>location_name</code>'),
84
  'pagination' => array('desc'=> 'When using a function or shortcode that outputs items (e.g. [events_list] for events, [locations_list] for locations), if the number of items supercede the limit of items to show, setting this to 1 will show page links under the list.', 'default'=>0),
admin/em-help.php CHANGED
File without changes
admin/em-locations-search.php CHANGED
File without changes
admin/em-ms-options.php CHANGED
@@ -5,9 +5,11 @@ function em_ms_upgrade( $blog_id ){
5
  <div id='icon-options-general' class='icon32'><br /></div>
6
  <h2><?php esc_html_e('Update Network','events-manager'); ?></h2>
7
  <?php
8
- if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'upgrade' && check_admin_referer('em_ms_ugrade_'.get_current_user_id()) ){
 
9
  global $current_site,$wpdb;
10
  $blog_ids = $wpdb->get_col('SELECT blog_id FROM '.$wpdb->blogs.' WHERE site_id='.$current_site->id);
 
11
  foreach($blog_ids as $blog_id){
12
  $plugin_basename = plugin_basename(dirname(dirname(__FILE__)).'/events-manager.php');
13
  if( in_array( $plugin_basename, (array) get_blog_option($blog_id, 'active_plugins', array() ) ) || is_plugin_active_for_network($plugin_basename) ){
@@ -15,25 +17,32 @@ function em_ms_upgrade( $blog_id ){
15
  switch_to_blog($blog_id);
16
  require_once( dirname(__FILE__).'/../em-install.php');
17
  em_install();
18
- echo "<p>Upgraded - ".get_bloginfo('blogname')."</p>";
19
  restore_current_blog();
20
  }else{
21
- echo "<p>&quot;".get_blog_option($blog_id, 'blogname')."&quot; is up to date.</p>";
22
  }
23
  }else{
24
- echo "<p>&quot;".get_blog_option($blog_id, 'blogname')."&quot; does not have Events Manager activated.</p>";
25
  }
26
  }
27
- echo "<p>Done Upgrading</p>";
 
 
 
28
  }else{
29
  ?>
30
  <form action="" method="post">
31
  <p><?php esc_html_e('To update your network blogs with the latest Events Manager automatically, click the update button below.','events-manager'); ?></p>
32
- <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('em_ms_ugrade_'.get_current_user_id()); ?>" />
33
- <input type="hidden" name="action" value="upgrade" />
34
- <input type="submit" value="<?php esc_attr_e('Update','events-manager'); ?>" />
35
  </form>
36
  <?php
 
 
 
 
37
  }
38
  ?>
39
  </div>
5
  <div id='icon-options-general' class='icon32'><br /></div>
6
  <h2><?php esc_html_e('Update Network','events-manager'); ?></h2>
7
  <?php
8
+ $site_updates = EM_Options::site_get('updates');
9
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'upgrade_network' && check_admin_referer('em_ms_upgrade') ){
10
  global $current_site,$wpdb;
11
  $blog_ids = $wpdb->get_col('SELECT blog_id FROM '.$wpdb->blogs.' WHERE site_id='.$current_site->id);
12
+ echo '<ul>';
13
  foreach($blog_ids as $blog_id){
14
  $plugin_basename = plugin_basename(dirname(dirname(__FILE__)).'/events-manager.php');
15
  if( in_array( $plugin_basename, (array) get_blog_option($blog_id, 'active_plugins', array() ) ) || is_plugin_active_for_network($plugin_basename) ){
17
  switch_to_blog($blog_id);
18
  require_once( dirname(__FILE__).'/../em-install.php');
19
  em_install();
20
+ echo "<li>".sprintf(_x('Updated %s.', 'Multisite Blog Update','events-manager'), get_bloginfo('blogname'))."</li>";
21
  restore_current_blog();
22
  }else{
23
+ echo "<li>".sprintf(_x('%s is up to date.', 'Multisite Blog Update','events-manager'), get_blog_option($blog_id, 'blogname'))."</li>";
24
  }
25
  }else{
26
+ echo "<li>".sprintf(_x('%s does not have Events Manager activated.', 'Multisite Blog Update','events-manager'), get_blog_option($blog_id, 'blogname'))."</li>";
27
  }
28
  }
29
+ echo '</ul>';
30
+ echo "<p>".esc_html__('Update process has finished.', 'events-manager')."</p>";
31
+ }elseif( !empty($_REQUEST['action']) && !empty($site_updates[$_REQUEST['action']]) ){
32
+ do_action('em_admin_update_ms_'.$_REQUEST['action']);
33
  }else{
34
  ?>
35
  <form action="" method="post">
36
  <p><?php esc_html_e('To update your network blogs with the latest Events Manager automatically, click the update button below.','events-manager'); ?></p>
37
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('em_ms_upgrade'); ?>" />
38
+ <input type="hidden" name="action" value="upgrade_network" />
39
+ <input type="submit" value="<?php esc_attr_e('Update Network','events-manager'); ?>" class="button-primary" />
40
  </form>
41
  <?php
42
+ //extra upgrade stuff
43
+ foreach( $site_updates as $update => $update_data ){
44
+ do_action('em_admin_update_ms_settings_'.$update, $update_data);
45
+ }
46
  }
47
  ?>
48
  </div>
admin/em-options.php CHANGED
@@ -243,6 +243,45 @@ function em_options_save(){
243
  exit();
244
  }
245
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
  add_action('admin_init', 'em_options_save');
248
 
@@ -333,6 +372,10 @@ function em_admin_options_page() {
333
  em_admin_options_reset_page();
334
  return;
335
  }
 
 
 
 
336
  //substitute dropdowns with input boxes for some situations to improve speed, e.g. if there 1000s of locations or users
337
  $total_users = $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->users};");
338
  if( $total_users > 100 && !defined('EM_OPTIMIZE_SETTINGS_PAGE_USERS') ){ define('EM_OPTIMIZE_SETTINGS_PAGE_USERS',true); }
@@ -472,7 +515,7 @@ function em_admin_option_box_email(){
472
  <p class="em-email-settings-check em-boxheader">
473
  <em><?php _e('Before you save your changes, you can quickly send yourself a test email by clicking this button.','events-manager'); ?>
474
  <?php echo sprintf(__('A test email will be sent to your account email - %s','events-manager'), $current_user->user_email . ' <a href="'.admin_url( 'profile.php' ).'">'.__('edit','events-manager').'</a>'); ?></em><br />
475
- <input type="button" id="em-admin-check-email" class="secondary-button" value="<?php esc_attr_e('Test Email Settings','events-manager'); ?>" />
476
  <input type="hidden" name="_check_email_nonce" value="<?php echo wp_create_nonce('check_email'); ?>" />
477
  <span id="em-email-settings-check-status"></span>
478
  </p>
@@ -659,11 +702,21 @@ function em_admin_option_box_uninstall(){
659
  $export_settings_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=export_em_settings&amp;_wpnonce='.wp_create_nonce('export_em_settings');
660
  $import_nonce = wp_create_nonce('import_em_settings');
661
  }
 
 
662
  ?>
663
  <div class="postbox" id="em-opt-admin-tools" >
664
  <div class="handlediv" title="<?php __('Click to toggle', 'events-manager'); ?>"><br /></div><h3><span><?php _e ( 'Admin Tools', 'events-manager'); ?> (<?php _e ( 'Advanced', 'events-manager'); ?>)</span></h3>
665
  <div class="inside">
666
 
 
 
 
 
 
 
 
 
667
  <table class="form-table">
668
  <tr class="em-header"><td colspan="2">
669
  <h4><?php _e ( 'Development Versions &amp; Updates', 'events-manager'); ?></h4>
@@ -743,6 +796,56 @@ function em_admin_option_box_uninstall(){
743
  if( typeof EM == 'object' ){ EM.admin_db_cleanup_warning = '<?php echo esc_js(__('Are you sure you want to proceed? We recommend you back up your database first, just in case!', 'events-manager')); ?>'; }
744
  </script>
745
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
746
  <table class="form-table">
747
  <tr class="em-header"><td colspan="2">
748
  <h4><?php _e ( 'Uninstall/Reset', 'events-manager'); ?></h4>
243
  exit();
244
  }
245
 
246
+ //reset timezones
247
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'reset_timezones' && check_admin_referer('reset_timezones') && em_wp_is_super_admin() ){
248
+ include(EM_DIR.'/em-install.php');
249
+ if( empty($_REQUEST['timezone_reset_value']) ) return;
250
+ $timezone = str_replace('UTC ', '', $_REQUEST['timezone_reset_value']);
251
+ if( is_multisite() ){
252
+ if( !empty($_REQUEST['timezone_reset_blog']) && is_numeric($_REQUEST['timezone_reset_blog']) ){
253
+ $blog_id = $_REQUEST['timezone_reset_blog'];
254
+ switch_to_blog($blog_id);
255
+ $blog_name = get_bloginfo('name');
256
+ $result = em_migrate_datetime_timezones(true, true, $timezone);
257
+ restore_current_blog();
258
+ }else{
259
+ $result = __('A valid blog ID must be provided, you can only reset one blog at a time.','events-manager');
260
+ }
261
+ }else{
262
+ $result = em_migrate_datetime_timezones(true, true, $timezone);
263
+ }
264
+ if( $result !== true ){
265
+ $EM_Notices->add_error($result, true);
266
+ }else{
267
+ if( is_multisite() ){
268
+ $EM_Notices->add_confirm(sprintf(__('Event timezones for blog %s have been reset to %s.','events-manager'), '<code>'.$blog_name.'</code>', '<code>'.$timezone.'</code>'), true);
269
+ }else{
270
+ $EM_Notices->add_confirm(sprintf(__('Event timezones have been reset to %s.','events-manager'), '<code>'.$timezone.'</code>'), true);
271
+ }
272
+ }
273
+ wp_redirect(em_wp_get_referer());
274
+ exit();
275
+ }
276
+
277
+ //update scripts that may need to run
278
+ $blog_updates = is_multisite() ? array_merge(EM_Options::get('updates'), EM_Options::site_get('updates')) : EM_Options::get('updates');
279
+ foreach( $blog_updates as $update => $update_data ){
280
+ $filename = EM_DIR.'/admin/settings/updates/'.$update.'.php';
281
+ if( file_exists($filename) ) include_once($filename);
282
+ do_action('em_admin_update_'.$update, $update_data);
283
+ }
284
+
285
  }
286
  add_action('admin_init', 'em_options_save');
287
 
372
  em_admin_options_reset_page();
373
  return;
374
  }
375
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'update' && !empty($_REQUEST['update_action']) ){
376
+ do_action('em_admin_update_settings_confirm_'.$_REQUEST['update_action']);
377
+ return;
378
+ }
379
  //substitute dropdowns with input boxes for some situations to improve speed, e.g. if there 1000s of locations or users
380
  $total_users = $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->users};");
381
  if( $total_users > 100 && !defined('EM_OPTIMIZE_SETTINGS_PAGE_USERS') ){ define('EM_OPTIMIZE_SETTINGS_PAGE_USERS',true); }
515
  <p class="em-email-settings-check em-boxheader">
516
  <em><?php _e('Before you save your changes, you can quickly send yourself a test email by clicking this button.','events-manager'); ?>
517
  <?php echo sprintf(__('A test email will be sent to your account email - %s','events-manager'), $current_user->user_email . ' <a href="'.admin_url( 'profile.php' ).'">'.__('edit','events-manager').'</a>'); ?></em><br />
518
+ <input type="button" id="em-admin-check-email" class="button-secondary" value="<?php esc_attr_e('Test Email Settings','events-manager'); ?>" />
519
  <input type="hidden" name="_check_email_nonce" value="<?php echo wp_create_nonce('check_email'); ?>" />
520
  <span id="em-email-settings-check-status"></span>
521
  </p>
702
  $export_settings_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=export_em_settings&amp;_wpnonce='.wp_create_nonce('export_em_settings');
703
  $import_nonce = wp_create_nonce('import_em_settings');
704
  }
705
+ $reset_timezone_nonce = wp_create_nonce('reset_timezones');
706
+ $options_data = get_option('dbem_data');
707
  ?>
708
  <div class="postbox" id="em-opt-admin-tools" >
709
  <div class="handlediv" title="<?php __('Click to toggle', 'events-manager'); ?>"><br /></div><h3><span><?php _e ( 'Admin Tools', 'events-manager'); ?> (<?php _e ( 'Advanced', 'events-manager'); ?>)</span></h3>
710
  <div class="inside">
711
 
712
+ <?php
713
+ //update scripts that may need to run
714
+ $blog_updates = is_multisite() ? array_merge(EM_Options::get('updates'), EM_Options::site_get('updates')) : EM_Options::get('updates');
715
+ foreach( $blog_updates as $update => $update_data ){
716
+ do_action('em_admin_update_settings_'.$update, $update_data);
717
+ }
718
+ ?>
719
+
720
  <table class="form-table">
721
  <tr class="em-header"><td colspan="2">
722
  <h4><?php _e ( 'Development Versions &amp; Updates', 'events-manager'); ?></h4>
796
  if( typeof EM == 'object' ){ EM.admin_db_cleanup_warning = '<?php echo esc_js(__('Are you sure you want to proceed? We recommend you back up your database first, just in case!', 'events-manager')); ?>'; }
797
  </script>
798
 
799
+ <table class="form-table">
800
+ <tr class="em-header"><td colspan="2">
801
+ <h4><?php _e ( 'Reset Timezones', 'events-manager'); ?></h4>
802
+ </td></tr>
803
+ <tr>
804
+ <th style="text-align:right;">
805
+ <a href="#" class="button-secondary" id="em-reset-event-timezones"><?php esc_html_e('Reset Event Timezones','events-manager'); ?></a>
806
+ </th>
807
+ <td>
808
+ <select name="timezone_reset_value" class="em-reset-event-timezones">
809
+ <?php echo wp_timezone_choice(''); ?>
810
+ </select>
811
+ <?php if( is_multisite() ): ?>
812
+ <select name="timezone_reset_blog" class="em-reset-event-timezones">
813
+ <option value="0"><?php esc_html_e('Select a blog...', 'events-manager'); ?></option>
814
+ <?php
815
+ foreach( get_sites() as $WP_Site){ /* @var WP_Site $WP_Site */
816
+ echo '<option value="'.esc_attr($WP_Site->blog_id).'">'. esc_html($WP_Site->blogname) .'</option>';
817
+ }
818
+ ?>
819
+ </select>
820
+ <?php endif; ?>
821
+ <p>
822
+ <em><?php esc_html_e('Select a Timezone to reset all your blog events to.','events-manager'); ?></em><br />
823
+ <em><strong><?php esc_html_e('WARNING! This cannot be undone and will overwrite all event timezones, you may want to back up your database first!','events-manager'); ?></strong></em>
824
+ </p>
825
+ </td>
826
+ <script type="text/javascript" charset="utf-8">
827
+ jQuery(document).ready(function($){
828
+ $('select[name="timezone_reset_value"]').change( function( e ){
829
+ if( $(this).val() == '' ){
830
+ $('a#em-reset-event-timezones').css({opacity:0.5, cursor:'default'});
831
+ }else{
832
+ $('a#em-reset-event-timezones').css({opacity:1, cursor:'pointer'});
833
+ }
834
+ }).trigger('change');
835
+ $('a#em-reset-event-timezones').click(function(e,el){
836
+ if( $('select[name="timezone_reset_value"]').val() == '' ) return false;
837
+ var thisform = $(this).closest('form');
838
+ thisform.find('input, textarea, select').prop('disabled', true);
839
+ thisform.find('select.em-reset-event-timezones').prop('disabled', false);
840
+ thisform.find('input[name=_wpnonce]').val('<?php echo esc_attr($reset_timezone_nonce); ?>').prop('disabled', false);
841
+ thisform.append($('<input type="hidden" name="action" value="<?php echo is_multisite() ? 'reset_timezones':'reset_timezones'; ?>" />'));
842
+ thisform.submit();
843
+ });
844
+ });
845
+ </script>
846
+ </td></tr>
847
+ </table>
848
+
849
  <table class="form-table">
850
  <tr class="em-header"><td colspan="2">
851
  <h4><?php _e ( 'Uninstall/Reset', 'events-manager'); ?></h4>
admin/settings/tabs/bookings.php CHANGED
@@ -70,7 +70,7 @@
70
  em_options_input_text ( __( 'Maximum spaces per booking', 'events-manager'), 'dbem_booking_feedback_spaces_limit', __( 'If the user tries to make a booking with spaces that exceeds the maximum number of spaces per booking.', 'events-manager').' '. __('%d will be replaced by a number.','events-manager') );
71
  ?>
72
  <tr class="em-header"><td colspan='2'><h4><?php _e('Booking button feedback messages','events-manager') ?></h4></td></tr>
73
- <tr><td colspan='2'><?php echo sprintf(__('When the %s placeholder, the below texts will be used.','events-manager'),'<code>#_BOOKINGBUTTON</code>'); ?></td></tr>
74
  <?php
75
  em_options_input_text ( __( 'User can book', 'events-manager'), 'dbem_booking_button_msg_book', '');
76
  em_options_input_text ( __( 'Booking in progress', 'events-manager'), 'dbem_booking_button_msg_booking', '');
70
  em_options_input_text ( __( 'Maximum spaces per booking', 'events-manager'), 'dbem_booking_feedback_spaces_limit', __( 'If the user tries to make a booking with spaces that exceeds the maximum number of spaces per booking.', 'events-manager').' '. __('%d will be replaced by a number.','events-manager') );
71
  ?>
72
  <tr class="em-header"><td colspan='2'><h4><?php _e('Booking button feedback messages','events-manager') ?></h4></td></tr>
73
+ <tr><td colspan='2'><?php echo sprintf(__('With the %s placeholder, the below texts will be used.','events-manager'),'<code>#_BOOKINGBUTTON</code>'); ?></td></tr>
74
  <?php
75
  em_options_input_text ( __( 'User can book', 'events-manager'), 'dbem_booking_button_msg_book', '');
76
  em_options_input_text ( __( 'Booking in progress', 'events-manager'), 'dbem_booking_button_msg_booking', '');
admin/settings/tabs/emails.php CHANGED
File without changes
admin/settings/tabs/formats.php CHANGED
File without changes
admin/settings/tabs/general.php CHANGED
@@ -12,6 +12,20 @@
12
  </td>
13
  </tr>
14
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  em_options_radio_binary ( __( 'Enable recurrence?', 'events-manager'), 'dbem_recurrence_enabled', __( 'Select yes to enable the recurrence features feature','events-manager') );
16
  em_options_radio_binary ( __( 'Enable bookings?', 'events-manager'), 'dbem_rsvp_enabled', __( 'Select yes to allow bookings and tickets for events.','events-manager') );
17
  em_options_radio_binary ( __( 'Enable tags?', 'events-manager'), 'dbem_tags_enabled', __( 'Select yes to enable the tag features','events-manager') );
12
  </td>
13
  </tr>
14
  <?php
15
+ em_options_radio_binary ( __( 'Enable Timezone Support?', 'events-manager'), 'dbem_timezone_enabled', sprintf(__( 'Each event can have its own timezone if enabled. If set to no, then all newly created events will have the blog timezone, which currently is set to %s','events-manager'), '<code>'.EM_DateTimeZone::create()->getName().'</code>'), '', '.event-timezone-option' );
16
+ ?>
17
+ <tr class="event-timezone-option">
18
+ <th>
19
+ <label for="event-timezone"><?php esc_html_e('Default Timezone', 'events-manager'); ?></label>
20
+ </th>
21
+ <td>
22
+ <select id="event-timezone" name="dbem_timezone_default">
23
+ <?php echo wp_timezone_choice( get_option('dbem_timezone_default') ); ?>
24
+ </select><br />
25
+ <i><?php esc_html_e('When creating a new event, this timezone will be applied by default.','events-manager'); ?></i>
26
+ </td>
27
+ </tr>
28
+ <?php
29
  em_options_radio_binary ( __( 'Enable recurrence?', 'events-manager'), 'dbem_recurrence_enabled', __( 'Select yes to enable the recurrence features feature','events-manager') );
30
  em_options_radio_binary ( __( 'Enable bookings?', 'events-manager'), 'dbem_rsvp_enabled', __( 'Select yes to allow bookings and tickets for events.','events-manager') );
31
  em_options_radio_binary ( __( 'Enable tags?', 'events-manager'), 'dbem_tags_enabled', __( 'Select yes to enable the tag features','events-manager') );
admin/settings/tabs/pages.php CHANGED
@@ -88,9 +88,9 @@
88
  <select name="dbem_events_default_archive_orderby" >
89
  <?php
90
  $event_archive_orderby_options = apply_filters('em_settings_events_default_archive_orderby_ddm', array(
91
- '_start_ts' => __('Order by start date, start time','events-manager'),
92
  'title' => __('Order by name','events-manager')
93
- ));
94
  ?>
95
  <?php foreach($event_archive_orderby_options as $key => $value) : ?>
96
  <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_events_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
88
  <select name="dbem_events_default_archive_orderby" >
89
  <?php
90
  $event_archive_orderby_options = apply_filters('em_settings_events_default_archive_orderby_ddm', array(
91
+ '_event_start' => __('Order by start date, start time','events-manager'),
92
  'title' => __('Order by name','events-manager')
93
+ ));
94
  ?>
95
  <?php foreach($event_archive_orderby_options as $key => $value) : ?>
96
  <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_events_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
admin/settings/updates/timezone-backcompat.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //This file will handle upgradeing from EM < 5.9 for timezones, removing the unecessary postmeta fields.
3
+ function em_admin_update_timezone_backcompat_site( $site_id = false ){
4
+ global $wpdb;
5
+ if( is_multisite() && $site_id != false ){ switch_to_blog($site_id); }
6
+ $sql = $wpdb->prepare('DELETE FROM '.$wpdb->postmeta.' WHERE meta_key=%s OR meta_key=%s', array('_start_ts', '_end_ts'));
7
+ $result = $wpdb->query($sql);
8
+ if( $result !== false && !is_multisite() ){
9
+ EM_Options::remove('updates', 'timezone-backcompat');
10
+ EM_Admin_Notices::remove('date_time_migration');
11
+ }
12
+ if( is_multisite() && $site_id != false ){ restore_current_blog(); }
13
+ return $result !== false;
14
+ }
15
+
16
+ function em_admin_update_timezone_backcompat(){
17
+ if( !empty($_REQUEST['confirmed']) && check_admin_referer('em_timezone_backcompat_confirmed') && em_wp_is_super_admin() ){
18
+ global $wpdb, $EM_Notices;
19
+ if( em_admin_update_timezone_backcompat_site() ){
20
+ $EM_Notices->add_confirm(__('You have successfully finalized upgrading your site.', 'events-manager'), true);
21
+ $redirect = esc_url_raw( remove_query_arg(array('action','update','confirmed','_wpnonce')) );
22
+ wp_redirect($redirect);
23
+ exit();
24
+ }else{
25
+ $EM_Notices->add_error(__('There was an error upgrading your site, please try again or contact support.', 'events-manager'), true);
26
+ $redirect = esc_url_raw( remove_query_arg(array('confirmed','_wpnonce')) );
27
+ wp_redirect($redirect);
28
+ exit();
29
+ }
30
+ }
31
+ }
32
+ add_action('em_admin_update_timezone-backcompat', 'em_admin_update_timezone_backcompat');
33
+
34
+ function em_admin_update_settings_timezone_backcompat(){
35
+ if( is_multisite() ) return;
36
+ ?>
37
+ <div>
38
+ <h4 style="color:#ca4a1f;"><?php esc_html_e ( 'Finalize Timezones Upgrade', 'events-manager'); ?></h4>
39
+ <p><?php esc_html_e('Events Manager 5.9 introduced timezone functionality, which does not require certain fields in your database. To maintain backwards compatibility with earlier versions, these fields will still be created.','events-manager'); ?></p>
40
+ <p><?php esc_html_e('This is not a required step to enable any extra functionality, and therefore is not urgent. Only until you are happy with the upgrade and are confident you don\'t need to downgrade, finalize your upgrade by deleting and discontinuing these fields.','events-manager'); ?></p>
41
+ <p><a href="<?php echo esc_url(EM_ADMIN_URL.'&page=events-manager-options&amp;action=update&update_action=timezone-backcompat'); ?>" class="button-secondary"><?php esc_html_e ( 'Finalize Timezones Upgrade', 'events-manager'); ?></a>
42
+ </div>
43
+ <?php
44
+ }
45
+ add_action('em_admin_update_settings_timezone-backcompat', 'em_admin_update_settings_timezone_backcompat');
46
+
47
+ function em_admin_update_settings_confirm_timezone_backcompat(){
48
+ ?>
49
+ <div class="wrap">
50
+ <h1><?php esc_html_e ( 'Finalize Timezones Upgrade', 'events-manager'); ?></h1>
51
+ <p><?php esc_html_e('Events Manager 5.9 introduced timezone functionality, which does not require certain fields in your database. To maintain backwards compatibility with earlier versions, these fields will still be created.','events-manager'); ?></p>
52
+ <p><?php esc_html_e('This is not a required step to enable any extra functionality, and therefore is not urgent. Only until you are happy with the upgrade and are confident you don\'t need to downgrade, finalize your upgrade by deleting and discontinuing these fields.','events-manager'); ?></p>
53
+ <p style="font-weight:bold;"><?php esc_html_e('We recommend you back up your database! Once the upgrade is finalized, you cannot downgrade to an earlier version of the plugin. This cannot be undone.','events-manager')?></p>
54
+ <p>
55
+ <a href="<?php echo esc_url(add_query_arg(array('_wpnonce' => wp_create_nonce('em_timezone_backcompat_confirmed'), 'confirmed'=>1))); ?>" class="button-primary"><?php _e('Finalize Timezones Upgrade','events-manager'); ?></a>
56
+ <a href="<?php echo esc_url(em_wp_get_referer()); ?>" class="button-secondary"><?php _e('Cancel','events-manager'); ?></a>
57
+ </p>
58
+ </div>
59
+ <?php
60
+ }
61
+ add_action('em_admin_update_settings_confirm_timezone-backcompat', 'em_admin_update_settings_confirm_timezone_backcompat');
62
+
63
+ function em_admin_update_ms_settings_timezone_backcompat(){
64
+ ?>
65
+ <div>
66
+ <br><hr>
67
+ <h2 style="color:#ca4a1f;"><?php esc_html_e( 'Finalize Timezones Upgrade', 'events-manager'); ?></h2>
68
+ <p><?php esc_html_e('Events Manager 5.9 introduced timezone functionality, which does not require certain fields in your database. To maintain backwards compatibility with earlier versions, these fields will still be created.','events-manager'); ?></p>
69
+ <p><?php esc_html_e('This is not a required step to enable any extra functionality, and therefore is not urgent. Only until you are happy with the upgrade and are confident you don\'t need to downgrade, finalize your upgrade by deleting and discontinuing these fields.','events-manager'); ?></p>
70
+ <p style="font-weight:bold;"><?php esc_html_e('We recommend you back up your database! Once the upgrade is finalized, you cannot downgrade to an earlier version of the plugin. This cannot be undone.','events-manager')?></p>
71
+ <p>
72
+ <a href="<?php echo esc_url(add_query_arg(array('action'=>'timezone-backcompat', '_wpnonce' => wp_create_nonce('em_ms_finalize_timezone_upgrade')))); ?>" class="button-primary">
73
+ <?php esc_html_e ( 'Finalize Timezones Upgrade', 'events-manager'); ?>
74
+ </a>
75
+ </p>
76
+ </div>
77
+ <?php
78
+ }
79
+ add_action('em_admin_update_ms_settings_timezone-backcompat', 'em_admin_update_ms_settings_timezone_backcompat');
80
+
81
+ function em_admin_update_ms_timezone_backcompat(){
82
+ if( check_admin_referer('em_ms_finalize_timezone_upgrade') && em_wp_is_super_admin() ){
83
+ global $current_site,$wpdb;
84
+ $blog_ids = $wpdb->get_col('SELECT blog_id FROM '.$wpdb->blogs.' WHERE site_id='.$current_site->id);
85
+ $result = true;
86
+ echo '<h2 style="color:#ca4a1f;">'. esc_html__( 'Finalize Timezones Upgrade', 'events-manager') .'</h2>';
87
+ echo '<ul>';
88
+ $plugin_basename = plugin_basename(EM_DIR.'/events-manager.php');
89
+ $network_active = is_plugin_active_for_network($plugin_basename);
90
+ foreach($blog_ids as $blog_id){
91
+ if( $network_active || is_plugin_active($plugin_basename.'/events-manager.php') ){
92
+ if( em_admin_update_timezone_backcompat_site($blog_id) ){
93
+ echo "<li>".sprintf(_x('Updated %s.', 'Multisite Blog Update','events-manager'), get_blog_option($blog_id, 'blogname'))."</li>";
94
+ }else{
95
+ echo "<li>".sprintf(_x('Failed to update %s.', 'Multisite Blog Update','events-manager'), get_blog_option($blog_id, 'blogname'))."</li>";
96
+ $result = false;
97
+ }
98
+ }else{
99
+ echo "<li>".sprintf(_x('%s does not have Events Manager activated.', 'Multisite Blog Update','events-manager'), get_blog_option($blog_id, 'blogname'))."</li>";
100
+ }
101
+ }
102
+ echo '</ul>';
103
+ if( $result ){
104
+ EM_Admin_Notices::remove('date_time_migration', true);
105
+ EM_Options::site_remove('updates', 'timezone-backcompat');
106
+ echo "<p>".esc_html__('Update process has finished.', 'events-manager')."</p>";
107
+ }else{
108
+ echo "<p>".esc_html__('An error has occurred, not all sites were upgraded successfully.', 'events-manager')."</p>";
109
+ }
110
+ }
111
+ }
112
+ add_action('em_admin_update_ms_timezone-backcompat', 'em_admin_update_ms_timezone_backcompat');
admin/settings/wpfc-admin.php CHANGED
File without changes
buddypress/bp-em-activity.php CHANGED
File without changes
buddypress/bp-em-core.php CHANGED
@@ -317,8 +317,8 @@ if( !is_admin() || ( defined('DOING_AJAX') && !empty($_REQUEST['is_public'])) ){
317
  //CSS and JS Loading
318
  function bp_em_enqueue_scripts( ){
319
  if( bp_is_current_component('events') || (bp_is_current_component('groups') && bp_is_current_action('group-events')) ){
320
- add_filter('option_dbem_js_limit', create_function('$args','return false;'));
321
- add_filter('option_dbem_css_limit', create_function('$args','return false;'));
322
  }
323
 
324
  }
317
  //CSS and JS Loading
318
  function bp_em_enqueue_scripts( ){
319
  if( bp_is_current_component('events') || (bp_is_current_component('groups') && bp_is_current_action('group-events')) ){
320
+ add_filter('option_dbem_js_limit', '__return_false');
321
+ add_filter('option_dbem_css_limit', '__return_false');
322
  }
323
 
324
  }
buddypress/bp-em-groups.php CHANGED
File without changes
buddypress/bp-em-notifications.php CHANGED
File without changes
buddypress/bp-em-templatetags.php CHANGED
File without changes
buddypress/screens/attending.php CHANGED
File without changes
buddypress/screens/group-events.php CHANGED
File without changes
buddypress/screens/my-bookings.php CHANGED
File without changes
buddypress/screens/my-events.php CHANGED
File without changes
buddypress/screens/my-group-events.php CHANGED
File without changes
buddypress/screens/my-locations.php CHANGED
File without changes
buddypress/screens/profile.php CHANGED
File without changes
classes/em-admin-notice.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A single admin notice which contains information about who to display it to, what to dispaly, when and where to display it.
4
+ * @since 5.8.2.0
5
+ */
6
+ class EM_Admin_Notice {
7
+
8
+ /**
9
+ * Notice key
10
+ * @var string
11
+ */
12
+ public $name = '';
13
+ /**
14
+ * Which user should see this message. Can be 'admin', 'all' (or false), or a specific capability.
15
+ * Note that 'admin' in MultiSite context is considered a super admin, use the 'manage_options' cap instead.
16
+ * @var string
17
+ */
18
+ public $who = 'admin';
19
+ /**
20
+ * Represents the date of when
21
+ * @var string
22
+ */
23
+ public $what = 'info';
24
+ /**
25
+ * Timestamp indicating when a notice should be shown. If empty, message will show immediately.
26
+ * @var int
27
+ */
28
+ public $when;
29
+ /**
30
+ * Where a message should be shown. Values accepted are 'all' (all pages), 'network_admin', 'plugin' (plugin-specific pages), 'settings'
31
+ * or any value representing an admin page in the events admin menu, e.g. 'events-manager-bookings' would be the bookings admin page.
32
+ *
33
+ * @var string
34
+ */
35
+ public $where = 'settings';
36
+ /**
37
+ * The actual message that will be displayed. If left blank, a filter will be applied upon output with format
38
+ * em_admin_notice_output_{$this->name}
39
+ * @var string
40
+ */
41
+ public $message = false; //the message
42
+ /**
43
+ * Whether a message is dismissable
44
+ * @var boolean
45
+ */
46
+ public $dismissible = true;
47
+ /**
48
+ * If a message is dismissable and this is set to true, it will be shown to every user matching the who property until dismissed.
49
+ * This is also set to true by default if the user type is not 'admin' and not previously set to true or false by the em_admin_notice_ hook.
50
+ * @var boolean
51
+ */
52
+ protected $user_notice = null;
53
+ /**
54
+ * If set to true, this is treated as a network-level notice, meaning it can apply to all sites on the network or the network admin in MultiSite mode.
55
+ * @var bool
56
+ */
57
+ public $network = false;
58
+
59
+ public function __construct( $key, $type = false, $message = false ){
60
+ //process the supplied data
61
+ if( empty($message) ){
62
+ if( empty($type) && is_array($key) ){
63
+ $notice = $key;
64
+ }elseif( is_array($type) ){
65
+ $this->name = $key;
66
+ $notice = $type;
67
+ }elseif( is_array($key) ){
68
+ $notice = $key;
69
+ }else{
70
+ //we may even have simply a key/name for this notice, for hooking later on
71
+ if( is_string($key) ) $this->name = $key;
72
+ $notice = array();
73
+ }
74
+ }else{
75
+ //here we expect a string for eveything
76
+ $notice = array('name'=> (string) $key, 'what' => (string) $type, 'message' => (string) $message) ;
77
+ }
78
+ //we should have an array to process at this point
79
+ foreach( $notice as $key => $value ){
80
+ $this->$key = $value;
81
+ }
82
+ //call a hook
83
+ do_action('em_admin_notice_'.$this->name, $this);
84
+ if( !is_multisite() && $this->where == 'network_admin' ) $this->where = 'settings';
85
+ }
86
+
87
+ public function __set( $prop, $val ){
88
+ $this->$prop = $val;
89
+ }
90
+
91
+ public function __get( $prop ){
92
+ if( $prop == 'user_notice' ){
93
+ return $this->is_user_notice();
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Returns whether or not this object should be dismissed on a per-user basis.
99
+ * @return boolean
100
+ */
101
+ public function is_user_notice(){
102
+ if( $this->who != 'admin' && $this->user_notice === null ){
103
+ //user_notice was not specifically set, so if notice is dismissible and not targetted at admins we assume it's dismissed at per-user basis
104
+ return $this->dismissible;
105
+ }
106
+ return $this->user_notice;
107
+ }
108
+
109
+ /**
110
+ * Returns notice as an array with non-default values.
111
+ * @return array
112
+ */
113
+ public function to_array(){
114
+ $default = new EM_Admin_Notice('default');
115
+ $notice = array();
116
+ foreach( get_class_vars('EM_Admin_Notice') as $var => $val ){
117
+ if( $this->$var != $default->$var ) $notice[$var] = $this->$var;
118
+ }
119
+ return $notice;
120
+ }
121
+
122
+ public function can_show(){
123
+ //check that we have at least a notice to show
124
+ if( empty($this->name) ) return false;
125
+ //can we display due to time?
126
+ $return = ( empty($this->when) || $this->when <= time() );
127
+ //who to display it to
128
+ if( $return && !empty($this->who) && $this->who != 'all' ){
129
+ $return = false; //unless this test passes, don't show it
130
+ if( $this->who == 'all' ) $return = true;
131
+ elseif ( $this->who == 'admin' ){
132
+ if( $this->network && em_wp_is_super_admin() ) $return = true;
133
+ elseif( current_user_can('manage_options') ) $return = true;
134
+ }
135
+ elseif( $this->who == 'blog_admin' && current_user_can('manage_options') ) $return = true;
136
+ elseif( !$return && current_user_can($this->who) ) $return = true;
137
+ }
138
+ //can we display due to location?
139
+ if( $return ){
140
+ $return = false; //unless this test passes, don't show it
141
+ if( empty($this->where) || $this->where == 'all' ){
142
+ $return = true;
143
+ }elseif( !empty($_REQUEST['post_type']) && in_array($_REQUEST['post_type'], array(EM_POST_TYPE_EVENT, EM_POST_TYPE_LOCATION, 'event-recurring')) ){
144
+ if( $this->where == 'plugin' ) $return = true;
145
+ elseif( empty($_REQUEST['page']) && in_array($this->where, array(EM_POST_TYPE_EVENT, EM_POST_TYPE_LOCATION, 'event-recurring')) ) $return = true;
146
+ elseif( $this->where == 'settings' && !empty($_REQUEST['page']) && $_REQUEST['page'] == 'events-manager-options' ) $return = true;
147
+ elseif( !empty($_REQUEST['page']) && $this->where == $_REQUEST['page'] ) $return = true;
148
+ }elseif( is_network_admin() && !empty($_REQUEST['page']) && preg_match('/^events\-manager\-/', $_REQUEST['page']) ){
149
+ $return = $this->where == 'plugin' || $this->where == 'settings' || $this->where == 'network_admin';
150
+ }
151
+ }
152
+ //does this even have a message we can display?
153
+ if( $return && empty($this->message)){
154
+ $this->message = apply_filters('em_admin_notice_'.$this->name .'_message', false, $this);
155
+ $return = !empty($this->message);
156
+ }
157
+ //is this user-dismissable, and if so, did this user dismiss it?
158
+ if( $return && $this->is_user_notice() ){
159
+ $user_id = get_current_user_id();
160
+ $dismissed_notices = get_user_meta( $user_id, '_em_dismissed_notices', true);
161
+ $return = empty($dismissed_notices) || !in_array($this->name, $dismissed_notices);
162
+ }
163
+ return $return;
164
+ }
165
+
166
+ public function output(){
167
+ if( empty($this->message) ) return false;
168
+ $action = $this->network ? 'em_dismiss_network_admin_notice':'em_dismiss_admin_notice';
169
+ ?>
170
+ <div class="em-admin-notice notice notice-<?php echo esc_attr($this->what); ?> <?php if($this->dismissible) echo 'is-dismissible'?>" data-dismiss-action="<?php echo $action; ?>" data-dismiss-key="<?php echo esc_attr($this->name); ?>">
171
+ <p><?php echo $this->message; ?></p>
172
+ </div>
173
+ <?php
174
+ return true;
175
+ }
176
+ }
classes/em-admin-notices.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles the registration and display of admin notices, including storage and retrieval of individual EM_Admin_Notice notice objects.
4
+ * @since 5.8.2.0
5
+ */
6
+ class EM_Admin_Notices {
7
+
8
+ /**
9
+ * Flag for whether or not to add dismissable notice JS to admin page footer.
10
+ * @var boolean
11
+ */
12
+ public static $js_footer = false;
13
+
14
+ /**
15
+ * Initialize EM Admin Notices by adding the relevant hooks.
16
+ */
17
+ public static function init(){
18
+ add_action('admin_notices', 'EM_Admin_Notices::admin_notices');
19
+ add_action('wp_ajax_em_dismiss_admin_notice', 'EM_Admin_Notices::dismiss_admin_notice');
20
+ if( is_multisite() ){
21
+ add_action('admin_notices', 'EM_Admin_Notices::network_admin_notices');
22
+ add_action('network_admin_notices', 'EM_Admin_Notices::network_admin_notices');
23
+ add_action('wp_ajax_em_dismiss_network_admin_notice', 'EM_Admin_Notices::dismiss_admin_notice');
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Adds an admin notice to the site. If $network is set to true, notice will be saved at network level.
29
+ * If a string is provided as $EM_Admin_Notice, it will be considered as a notice requiring a hook to ouptut anything.
30
+ * If a notice with an identical key is provided, it will overwrite the previously stored notice.
31
+ * When adding a notice that all users will see and can dismiss, it's recommended you use a hook to build the EM_Admin_Notice object, to avoid storing unecessary data in the DB
32
+ * @param EM_Admin_Notice|string $EM_Admin_Notice
33
+ * @param boolean $network
34
+ * @return boolean Returns true if added successfully, false if not or if the exact same record exists.
35
+ */
36
+ public static function add( $EM_Admin_Notice, $network = false ){
37
+ $network = $network && is_multisite(); //make sure we are actually in multisite!
38
+ if( is_string($EM_Admin_Notice) ) $EM_Admin_Notice = new EM_Admin_Notice( $EM_Admin_Notice );
39
+ if( !$EM_Admin_Notice->name ) return false;
40
+ $data = $network ? get_site_option('dbem_data') : get_option('dbem_data');
41
+ $notices = !empty($data['admin_notices']) ? $data['admin_notices'] : array();
42
+ $notices_data = $network ? get_site_option('dbem_admin_notices') : get_option('dbem_admin_notices');
43
+ $notices[$EM_Admin_Notice->name] = !empty($EM_Admin_Notice->when) ? $EM_Admin_Notice->when : 0;
44
+ //if no message supplied, we assume it's a hook, possibly with a time-to-show assigned above
45
+ if( !empty($EM_Admin_Notice->message) ){
46
+ $notices_data[$EM_Admin_Notice->name] = $EM_Admin_Notice->to_array();
47
+ }
48
+ if( !empty($notices) ){
49
+ $data['admin_notices'] = $notices;
50
+ $update_notices = $network ? update_site_option('dbem_data', $data) : update_option('dbem_data', $data);
51
+ $update_notices_data = true;
52
+ if( !empty($notices_data) ){
53
+ $update_notices_data = $network ? update_site_option('dbem_admin_notices', $notices_data) : update_option('dbem_admin_notices', $notices_data, false);
54
+ }
55
+ return $update_notices && $update_notices_data;
56
+ }
57
+ return false;
58
+ }
59
+
60
+ /**
61
+ * Remove an admin notice. If $network is true, then a network-level admin notice will be removed.
62
+ * @param string $notice_key
63
+ * @param string $network
64
+ * @return boolean Returns true if successfully deleted, false if there's an error or if there's nothing to delete.
65
+ */
66
+ public static function remove( $notice_key, $network = false ){
67
+ $network = $network && is_multisite(); //make sure we are actually in multisite!
68
+ $data = $network ? get_site_option('dbem_data') : get_option('dbem_data');
69
+ if( !empty($data['admin_notices']) && isset($data['admin_notices'][$notice_key])){
70
+ unset($data['admin_notices'][$notice_key]);
71
+ if( empty($data['admin_notices']) ) unset($data['admin_notices']);
72
+ $result = $update_notices_data = $network ? update_site_option('dbem_data', $data) : update_option('dbem_data', $data);
73
+ $notices_data = $network ? get_site_option('dbem_admin_notices') : get_option('dbem_admin_notices');
74
+ if( !empty($notices_data[$notice_key]) ){
75
+ unset($notices_data[$notice_key]);
76
+ if( empty($notices_data) ){
77
+ $update_notices_data = $network ? delete_site_option('dbem_admin_notices') : delete_option('dbem_admin_notices');
78
+ }else{
79
+ $update_notices_data = $network ? update_site_option('dbem_admin_notices', $notices_data) : update_option('dbem_admin_notices', $notices_data, false);
80
+ }
81
+ }
82
+ return $result && $update_notices_data;
83
+ }
84
+ return false;
85
+ }
86
+
87
+ /**
88
+ * Adds admin notice to network rather than specific blog. Equivalent to self::add( $EM_Admin_Notice, true );
89
+ * @see EM_Admin_Notices::add()
90
+ */
91
+ public static function network_add( $EM_Admin_Notice ){ return self::add( $EM_Admin_Notice, true ); }
92
+
93
+ /**
94
+ * Removes admin notice from network rather than specific blog. Equivalent to self::remove( $EM_Admin_Notice, true );
95
+ * @see EM_Admin_Notices::remove()
96
+ */
97
+ public static function network_remove( $notice_key ){ return self::remove( $notice_key, true ); }
98
+
99
+ /**
100
+ * Output the admin notices we need to output now. If $network is true, MultiSite network messages will be output.
101
+ * @param string $network
102
+ */
103
+ public static function admin_notices( $network = false ){
104
+ $notices = array();
105
+ $data = $network ? get_site_option('dbem_data') : get_option('dbem_data');
106
+ $possible_notices = !empty($data['admin_notices']) ? $data['admin_notices'] : array();
107
+ //we may have something to show, so we make sure that there's something to show right now
108
+ foreach( $possible_notices as $key => $val ){
109
+ //to avoid extra loading etc. we weed out time-based notices that aren't triggered right now
110
+ if( empty($val) || ($val > 0 && $val < time()) ){
111
+ //we have a match, so we add this to $notices
112
+ $notices[$key] = self::get_notice($key, $network);
113
+ }
114
+ }
115
+ self::output( $notices, $network );
116
+ }
117
+
118
+ public static function get_notice( $key, $network = false ){
119
+ //build notice object
120
+ $notice_data = $network ? get_site_option('dbem_admin_notices') : get_option('dbem_admin_notices');
121
+ if( empty($notice_data[$key]) || !is_array($notice_data[$key]) ){
122
+ $notice = array('name'=>$key, 'network'=>$network);
123
+ }else{
124
+ $notice = $notice_data[$key];
125
+ $notice['network'] = $network;
126
+ }
127
+ return new EM_Admin_Notice($notice);
128
+ }
129
+
130
+ /**
131
+ * Outputs admin notices at network level, same as EM_Admin_Notices::admin_notices(true)
132
+ * @see EM_Admin_Notices::admin_notices()
133
+ */
134
+ public static function network_admin_notices(){ self::admin_notices(true); }
135
+
136
+ /**
137
+ * Outputs admin notices and calls the dismissable JS to be output at footer of admin page.
138
+ * If $network is true, only MultiSite network-level notices will be shown.
139
+ * @param array $notices
140
+ * @param boolean $network
141
+ */
142
+ public static function output( $notices, $network = false ){
143
+ foreach( $notices as $EM_Admin_Notice ){
144
+ //output the notice if meant to
145
+ if( $EM_Admin_Notice->can_show() ){
146
+ if( $EM_Admin_Notice->output() ) self::$js_footer = true;
147
+ }
148
+ }
149
+ if( self::$js_footer ){
150
+ add_action('admin_footer', 'EM_Admin_Notices::admin_footer');
151
+ }
152
+ }
153
+
154
+ /**
155
+ * If called via AJAX, the notice will be removed.
156
+ */
157
+ public static function dismiss_admin_notice(){
158
+ if( empty($_REQUEST['notice']) ) return;
159
+ $key = $_REQUEST['notice'];
160
+ $network = $_REQUEST['action'] == 'em_dismiss_network_admin_notice';
161
+ //get the notice
162
+ $EM_Admin_Notice = self::get_notice($key, $network);
163
+ if( $EM_Admin_Notice->is_user_notice() ){
164
+ //user-specific notices are flagged on the user-level
165
+ $user_id = get_current_user_id();
166
+ $dismissed_notices = get_user_meta( $user_id, '_em_dismissed_notices', true);
167
+ $dismissed_notices = is_array($dismissed_notices) ? $dismissed_notices : array();
168
+ if( !in_array($EM_Admin_Notice->name, $dismissed_notices) ){
169
+ $dismissed_notices[] = $EM_Admin_Notice->name;
170
+ $result = update_user_meta( $user_id, '_em_dismissed_notices', $dismissed_notices);
171
+ }
172
+ }else{
173
+ $result = self::remove($_REQUEST['notice'], $network);
174
+ }
175
+ echo !empty($result) ? 'Thou art dismissed!' : 'Thou shall not pass!';
176
+ exit();
177
+ }
178
+
179
+ /**
180
+ * Outputs JS for dismissing notices.
181
+ */
182
+ public static function admin_footer(){
183
+ ?>
184
+ <script type="text/javascript">
185
+ jQuery(document).ready( function($){
186
+ $('.em-admin-notice').on('click', 'button.notice-dismiss', function(e){
187
+ var the_notice = $(this).closest('.em-admin-notice');
188
+ $.get('<?php echo admin_url('admin-ajax.php'); ?>', {'action' : the_notice.data('dismiss-action'), 'notice' : the_notice.data('dismiss-key') });
189
+ });
190
+ });
191
+ </script>
192
+ <?php
193
+ }
194
+ }
195
+ EM_Admin_Notices::init();
classes/em-booking.php CHANGED
@@ -58,7 +58,21 @@ class EM_Booking extends EM_Object{
58
  * @var array
59
  */
60
  var $notes;
61
- var $timestamp;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  var $person;
63
  var $required_fields = array('booking_id', 'event_id', 'person_id', 'booking_spaces');
64
  var $feedback_message = "";
@@ -125,7 +139,7 @@ class EM_Booking extends EM_Object{
125
  $this->to_object($booking);
126
  $this->previous_status = $this->booking_status;
127
  $this->get_person();
128
- $this->timestamp = !empty($booking['booking_date']) ? strtotime($booking['booking_date'], current_time('timestamp')):false;
129
  }
130
  //Do it here so things appear in the po file.
131
  $this->status_array = array(
@@ -145,6 +159,27 @@ class EM_Booking extends EM_Object{
145
  }
146
  do_action('em_booking', $this, $booking_data);
147
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
  function get_notes(){
150
  global $wpdb;
@@ -187,7 +222,7 @@ class EM_Booking extends EM_Object{
187
  }else{
188
  $update = false;
189
  $data_types = $this->get_types($data);
190
- $data['booking_date'] = current_time('mysql');
191
  $data_types[] = '%s';
192
  $result = $wpdb->insert($table, $data, $data_types);
193
  $this->booking_id = $wpdb->insert_id;
@@ -391,8 +426,9 @@ class EM_Booking extends EM_Object{
391
  }
392
 
393
  /**
394
- * Gets price AFTER taxes and post-tax discounts have also been added
395
  * @param boolean $format
 
396
  * @return double|string
397
  */
398
  function get_price_post_taxes( $format = false, $include_adjustments = true ){
@@ -636,12 +672,12 @@ class EM_Booking extends EM_Object{
636
  global $EM_Event;
637
  if( is_object($this->event) && get_class($this->event)=='EM_Event' && $this->event->event_id == $this->event_id ){
638
  return $this->event;
639
- }elseif( is_object($EM_Event) && ( (is_object($this->event) && $this->event->event_id == $this->event_id) || empty($this->booking_id)) ){
640
  $this->event = $EM_Event;
641
  }else{
642
- $this->event = new EM_Event($this->event_id, 'event_id');
643
  }
644
- return apply_filters('em_booking_get_event',$this->event, $this);
645
  }
646
 
647
  /**
@@ -955,7 +991,7 @@ class EM_Booking extends EM_Object{
955
  global $wpdb;
956
  if( $this->can_manage() ){
957
  $this->get_notes();
958
- $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>current_time('timestamp'));
959
  $this->notes[] = wp_kses_data($note);
960
  $this->feedback_message = __('Booking note successfully added.','events-manager');
961
  return $wpdb->insert(EM_META_TABLE, array('object_id'=>$this->booking_id, 'meta_key'=>'booking-note', 'meta_value'=> serialize($note)),array('%d','%s','%s'));
@@ -1005,13 +1041,13 @@ class EM_Booking extends EM_Object{
1005
  $replace = $this->get_spaces();
1006
  break;
1007
  case '#_BOOKINGDATE':
1008
- $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_date_format'), $this->timestamp):'n/a';
1009
  break;
1010
  case '#_BOOKINGTIME':
1011
- $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_time_format'), $this->timestamp):'n/a';
1012
  break;
1013
  case '#_BOOKINGDATETIME':
1014
- $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_date_format').' '.get_option('dbem_time_format'), $this->timestamp):'n/a';
1015
  break;
1016
  case '#_BOOKINGLISTURL':
1017
  $replace = em_get_my_bookings_url();
@@ -1175,6 +1211,32 @@ class EM_Booking extends EM_Object{
1175
  return apply_filters('em_booking_email_messages', $msg, $this);
1176
  }
1177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1178
  /**
1179
  * Can the user manage this event?
1180
  */
58
  * @var array
59
  */
60
  var $notes;
61
+ /**
62
+ * Deprecated as of 5.8.2, previously used to store timestamp of booking date. Use EM_Booking->date()->getTimestamp() instead.
63
+ * @var int
64
+ */
65
+ private $timestamp;
66
+ /**
67
+ * The date of the booking, in UTC time, represented as a DATETIME mysql value.
68
+ * @var string
69
+ */
70
+ protected $booking_date;
71
+ /**
72
+ * Contains the booking date in EM_DateTime object form.
73
+ * @var EM_DateTime
74
+ */
75
+ protected $date;
76
  var $person;
77
  var $required_fields = array('booking_id', 'event_id', 'person_id', 'booking_spaces');
78
  var $feedback_message = "";
139
  $this->to_object($booking);
140
  $this->previous_status = $this->booking_status;
141
  $this->get_person();
142
+ $this->booking_date = !empty($booking['booking_date']) ? $booking['booking_date']:false;
143
  }
144
  //Do it here so things appear in the po file.
145
  $this->status_array = array(
159
  }
160
  do_action('em_booking', $this, $booking_data);
161
  }
162
+
163
+
164
+ function __get( $var ){
165
+ //get the modified or created date from the DB only if requested, and save to object
166
+ if( $var == 'timestamp' ){
167
+ if( $this->date() === false ) return 0;
168
+ return $this->date()->getTimestampWithOffset();
169
+ }
170
+ return null;
171
+ }
172
+
173
+ public function __set( $prop, $val ){
174
+ if( $prop == 'timestamp' ){
175
+ if( $this->date() !== false );
176
+ $this->date()->setTimestamp($val);
177
+ }
178
+ }
179
+
180
+ public function __isset( $prop ){
181
+ if( $prop == 'timestamp' ) $this->date()->getTimestamp() > 0;
182
+ }
183
 
184
  function get_notes(){
185
  global $wpdb;
222
  }else{
223
  $update = false;
224
  $data_types = $this->get_types($data);
225
+ $data['booking_date'] = gmdate('Y-m-d H:i:s');
226
  $data_types[] = '%s';
227
  $result = $wpdb->insert($table, $data, $data_types);
228
  $this->booking_id = $wpdb->insert_id;
426
  }
427
 
428
  /**
429
+ * Gets price AFTER taxes and (optionally) post-tax discounts and surcharges have also been added.
430
  * @param boolean $format
431
+ * @param boolean $include_adjustments If set to true discounts and surcharges won't be applied to the overall price.
432
  * @return double|string
433
  */
434
  function get_price_post_taxes( $format = false, $include_adjustments = true ){
672
  global $EM_Event;
673
  if( is_object($this->event) && get_class($this->event)=='EM_Event' && $this->event->event_id == $this->event_id ){
674
  return $this->event;
675
+ }elseif( is_object($EM_Event) && $EM_Event->event_id == $this->event_id ){
676
  $this->event = $EM_Event;
677
  }else{
678
+ $this->event = em_get_event($this->event_id, 'event_id');
679
  }
680
+ return apply_filters('em_booking_get_event', $this->event, $this);
681
  }
682
 
683
  /**
991
  global $wpdb;
992
  if( $this->can_manage() ){
993
  $this->get_notes();
994
+ $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>time());
995
  $this->notes[] = wp_kses_data($note);
996
  $this->feedback_message = __('Booking note successfully added.','events-manager');
997
  return $wpdb->insert(EM_META_TABLE, array('object_id'=>$this->booking_id, 'meta_key'=>'booking-note', 'meta_value'=> serialize($note)),array('%d','%s','%s'));
1041
  $replace = $this->get_spaces();
1042
  break;
1043
  case '#_BOOKINGDATE':
1044
+ $replace = ( $this->date() !== false ) ? $this->date()->i18n( em_get_date_format() ):'n/a';
1045
  break;
1046
  case '#_BOOKINGTIME':
1047
+ $replace = ( $this->date() !== false ) ? $this->date()->i18n( em_get_hour_format() ):'n/a';
1048
  break;
1049
  case '#_BOOKINGDATETIME':
1050
+ $replace = ( $this->date() !== false ) ? $this->date()->i18n( em_get_date_format().' '.em_get_hour_format()):'n/a';
1051
  break;
1052
  case '#_BOOKINGLISTURL':
1053
  $replace = em_get_my_bookings_url();
1211
  return apply_filters('em_booking_email_messages', $msg, $this);
1212
  }
1213
 
1214
+ /**
1215
+ * Returns an EM_DateTime representation of when booking was made in UTC timezone. If no valid date defined, false will be returned
1216
+ * @return EM_DateTime
1217
+ */
1218
+ public function date( $utc_timezone = false ){
1219
+ if( empty($this->date) || !$this->date->valid ){
1220
+ if( !empty($this->booking_date ) ){
1221
+ $this->date = new EM_DateTime($this->booking_date, 'UTC');
1222
+ }else{
1223
+ //we retrn a date regardless but it's not based on a 'valid' booking date
1224
+ $this->date = new EM_DateTime();
1225
+ $this->date->valid = false;
1226
+ }
1227
+ }
1228
+ //Set to UTC timezone if requested, local blog time by default
1229
+ if( $utc_timezone ){
1230
+ $timezone = 'UTC';
1231
+ }else{
1232
+ //we could set this to false but this way we might avoid creating a new timezone if it's already in this one
1233
+ $timezone = get_option( 'timezone_string' );
1234
+ if( !$timezone ) $timezone = get_option('gmt_offset');
1235
+ }
1236
+ $this->date->setTimezone($timezone);
1237
+ return $this->date;
1238
+ }
1239
+
1240
  /**
1241
  * Can the user manage this event?
1242
  */
classes/em-bookings-table.php CHANGED
@@ -92,6 +92,7 @@ class EM_Bookings_Table{
92
  'ticket_name'=>__('Ticket Name','events-manager'),
93
  'ticket_description'=>__('Ticket Description','events-manager'),
94
  'ticket_price'=>__('Ticket Price','events-manager'),
 
95
  'ticket_id'=>__('Ticket ID','events-manager')
96
  ), $this);
97
  //add tickets to template if we're showing rows by booking-ticket
@@ -514,10 +515,11 @@ class EM_Bookings_Table{
514
  * @param Object $object
515
  * @return array()
516
  */
517
- function get_row( $object, $csv = false ){
518
  /* @var $EM_Ticket EM_Ticket */
519
  /* @var $EM_Ticket_Booking EM_Ticket_Booking */
520
  /* @var $EM_Booking EM_Booking */
 
521
  if( get_class($object) == 'EM_Ticket_Booking' ){
522
  $EM_Ticket_Booking = $object;
523
  $EM_Ticket = $EM_Ticket_Booking->get_ticket();
@@ -533,19 +535,21 @@ class EM_Bookings_Table{
533
  if( $col == 'user_email' ){
534
  $val = $EM_Booking->get_person()->user_email;
535
  }elseif($col == 'dbem_phone'){
536
- $val = esc_html($EM_Booking->get_person()->phone);
537
  }elseif($col == 'user_name'){
538
- if( $csv || $EM_Booking->is_no_user() ){
539
  $val = $EM_Booking->get_person()->get_name();
 
 
540
  }else{
541
  $val = '<a href="'.esc_url(add_query_arg(array('person_id'=>$EM_Booking->person_id, 'event_id'=>null), $EM_Booking->get_event()->get_bookings_url())).'">'. esc_html($EM_Booking->person->get_name()) .'</a>';
542
  }
543
  }elseif($col == 'first_name'){
544
- $val = esc_html($EM_Booking->get_person()->first_name);
545
  }elseif($col == 'last_name'){
546
- $val = esc_html($EM_Booking->get_person()->last_name);
547
  }elseif($col == 'event_name'){
548
- if( $csv ){
549
  $val = $EM_Booking->get_event()->event_name;
550
  }else{
551
  $val = '<a href="'.$EM_Booking->get_event()->get_bookings_url().'">'. esc_html($EM_Booking->get_event()->event_name) .'</a>';
@@ -555,46 +559,45 @@ class EM_Bookings_Table{
555
  }elseif($col == 'event_time'){
556
  $val = $EM_Booking->get_event()->output('#_EVENTTIMES');
557
  }elseif($col == 'booking_price'){
558
- if($this->show_tickets && !empty($EM_Ticket)){
559
- $val = em_get_currency_formatted(apply_filters('em_bookings_table_row_booking_price_ticket', $EM_Ticket_Booking->get_price(false,false, true), $EM_Booking, true));
560
- }else{
561
- $val = $EM_Booking->get_price(true);
562
- }
563
  }elseif($col == 'booking_status'){
564
  $val = $EM_Booking->get_status(true);
565
  }elseif($col == 'booking_date'){
566
- $val = date_i18n(get_option('dbem_date_format').' '. get_option('dbem_time_format'), $EM_Booking->timestamp);
567
  }elseif($col == 'actions' ){
568
- if( $csv ) continue;
569
  $val = implode(' | ', $this->get_booking_actions($EM_Booking));
570
  }elseif( $col == 'booking_spaces' ){
571
  $val = ($this->show_tickets && !empty($EM_Ticket)) ? $EM_Ticket_Booking->get_spaces() : $EM_Booking->get_spaces();
572
  }elseif( $col == 'booking_id' ){
573
  $val = $EM_Booking->booking_id;
574
  }elseif( $col == 'ticket_name' && $this->show_tickets && !empty($EM_Ticket) ){
575
- $val = $csv ? $EM_Ticket->$col : esc_html($EM_Ticket->$col);
576
  }elseif( $col == 'ticket_description' && $this->show_tickets && !empty($EM_Ticket) ){
577
- $val = $csv ? $EM_Ticket->$col : esc_html($EM_Ticket->$col);
578
  }elseif( $col == 'ticket_price' && $this->show_tickets && !empty($EM_Ticket) ){
579
  $val = $EM_Ticket->get_price(true);
 
 
 
580
  }elseif( $col == 'ticket_id' && $this->show_tickets && !empty($EM_Ticket) ){
581
  $val = $EM_Ticket->ticket_id;
582
  }elseif( $col == 'booking_comment' ){
583
- $val = $csv ? $EM_Booking->booking_comment : esc_html($EM_Booking->booking_comment);
584
  }
585
  //escape all HTML if destination is HTML or not defined
586
- if( $csv == 'html' || empty($csv) ){
587
  if( !in_array($col, array('user_name', 'event_name', 'actions')) ) $val = esc_html($val);
588
  }
589
  //use this
590
- $val = apply_filters('em_bookings_table_rows_col_'.$col, $val, $EM_Booking, $this, $csv, $object);
591
- $cols[] = apply_filters('em_bookings_table_rows_col', $val, $col, $EM_Booking, $this, $csv, $object); //deprecated, use the above filter instead for better performance
592
  }
593
  return $cols;
594
  }
595
 
596
  function get_row_csv($EM_Booking){
597
- $row = $this->get_row($EM_Booking, true);
598
  foreach($row as $k=>$v) $row[$k] = html_entity_decode($v); //remove things like &amp; which may have been saved to the DB directly
599
  return $row;
600
  }
92
  'ticket_name'=>__('Ticket Name','events-manager'),
93
  'ticket_description'=>__('Ticket Description','events-manager'),
94
  'ticket_price'=>__('Ticket Price','events-manager'),
95
+ 'ticket_total'=>__('Ticket Total','events-manager'),
96
  'ticket_id'=>__('Ticket ID','events-manager')
97
  ), $this);
98
  //add tickets to template if we're showing rows by booking-ticket
515
  * @param Object $object
516
  * @return array()
517
  */
518
+ function get_row( $object, $format = 'html' ){
519
  /* @var $EM_Ticket EM_Ticket */
520
  /* @var $EM_Ticket_Booking EM_Ticket_Booking */
521
  /* @var $EM_Booking EM_Booking */
522
+ if( $format === true ) $format = 'csv'; //backwards compatibility, previously $format was $csv which was a boolean
523
  if( get_class($object) == 'EM_Ticket_Booking' ){
524
  $EM_Ticket_Booking = $object;
525
  $EM_Ticket = $EM_Ticket_Booking->get_ticket();
535
  if( $col == 'user_email' ){
536
  $val = $EM_Booking->get_person()->user_email;
537
  }elseif($col == 'dbem_phone'){
538
+ $val = $EM_Booking->get_person()->phone;
539
  }elseif($col == 'user_name'){
540
+ if( $format == 'csv' ){
541
  $val = $EM_Booking->get_person()->get_name();
542
+ }elseif( $EM_Booking->is_no_user() ){
543
+ $val = esc_html($EM_Booking->get_person()->get_name());
544
  }else{
545
  $val = '<a href="'.esc_url(add_query_arg(array('person_id'=>$EM_Booking->person_id, 'event_id'=>null), $EM_Booking->get_event()->get_bookings_url())).'">'. esc_html($EM_Booking->person->get_name()) .'</a>';
546
  }
547
  }elseif($col == 'first_name'){
548
+ $val = $EM_Booking->get_person()->first_name;
549
  }elseif($col == 'last_name'){
550
+ $val = $EM_Booking->get_person()->last_name;
551
  }elseif($col == 'event_name'){
552
+ if( $format == 'csv' ){
553
  $val = $EM_Booking->get_event()->event_name;
554
  }else{
555
  $val = '<a href="'.$EM_Booking->get_event()->get_bookings_url().'">'. esc_html($EM_Booking->get_event()->event_name) .'</a>';
559
  }elseif($col == 'event_time'){
560
  $val = $EM_Booking->get_event()->output('#_EVENTTIMES');
561
  }elseif($col == 'booking_price'){
562
+ $val = $EM_Booking->get_price(true);
 
 
 
 
563
  }elseif($col == 'booking_status'){
564
  $val = $EM_Booking->get_status(true);
565
  }elseif($col == 'booking_date'){
566
+ $val = $EM_Booking->date()->i18n( get_option('dbem_date_format').' '. get_option('dbem_time_format') );
567
  }elseif($col == 'actions' ){
568
+ if( $format == 'csv' ) continue;
569
  $val = implode(' | ', $this->get_booking_actions($EM_Booking));
570
  }elseif( $col == 'booking_spaces' ){
571
  $val = ($this->show_tickets && !empty($EM_Ticket)) ? $EM_Ticket_Booking->get_spaces() : $EM_Booking->get_spaces();
572
  }elseif( $col == 'booking_id' ){
573
  $val = $EM_Booking->booking_id;
574
  }elseif( $col == 'ticket_name' && $this->show_tickets && !empty($EM_Ticket) ){
575
+ $val = $EM_Ticket->$col;
576
  }elseif( $col == 'ticket_description' && $this->show_tickets && !empty($EM_Ticket) ){
577
+ $val = $EM_Ticket->$col;
578
  }elseif( $col == 'ticket_price' && $this->show_tickets && !empty($EM_Ticket) ){
579
  $val = $EM_Ticket->get_price(true);
580
+ }elseif( $col == 'ticket_total' && $this->show_tickets && !empty($EM_Ticket_Booking) ){
581
+ $val = apply_filters('em_bookings_table_row_booking_price_ticket', $EM_Ticket_Booking->get_price(false), $EM_Booking, true);
582
+ $val = $EM_Booking->format_price($val * (1 + $EM_Booking->get_tax_rate(true)));
583
  }elseif( $col == 'ticket_id' && $this->show_tickets && !empty($EM_Ticket) ){
584
  $val = $EM_Ticket->ticket_id;
585
  }elseif( $col == 'booking_comment' ){
586
+ $val = $EM_Booking->booking_comment;
587
  }
588
  //escape all HTML if destination is HTML or not defined
589
+ if( $format == 'html' || empty($format) ){
590
  if( !in_array($col, array('user_name', 'event_name', 'actions')) ) $val = esc_html($val);
591
  }
592
  //use this
593
+ $val = apply_filters('em_bookings_table_rows_col_'.$col, $val, $EM_Booking, $this, $format, $object);
594
+ $cols[] = apply_filters('em_bookings_table_rows_col', $val, $col, $EM_Booking, $this, $format, $object); //use the above filter instead for better performance
595
  }
596
  return $cols;
597
  }
598
 
599
  function get_row_csv($EM_Booking){
600
+ $row = $this->get_row($EM_Booking, 'csv');
601
  foreach($row as $k=>$v) $row[$k] = html_entity_decode($v); //remove things like &amp; which may have been saved to the DB directly
602
  return $row;
603
  }
classes/em-bookings.php CHANGED
@@ -198,23 +198,32 @@ class EM_Bookings extends EM_Object implements Iterator{
198
  function get_tickets( $force_reload = false ){
199
  if( !is_object($this->tickets) || $force_reload ){
200
  $this->tickets = new EM_Tickets($this->event_id);
201
- if( get_option('dbem_bookings_tickets_single') && count($this->tickets->tickets) == 1 && !empty($this->get_event()->rsvp_end) ){
202
  //if in single ticket mode, then the event booking cut-off is the ticket end date
203
  $EM_Ticket = $this->tickets->get_first();
204
  $EM_Event = $this->get_event();
205
  //if ticket has cut-off date, that should take precedence as we save the ticket cut-off date/time to the event in single ticket mode
206
  if( !empty($EM_Ticket->ticket_end) ){
207
  //if ticket end dates are set, move to event
208
- $EM_Event->event_rsvp_date = date('Y-m-d', $EM_Ticket->end_timestamp);
209
- $EM_Event->event_rsvp_time = date('H:i:00', $EM_Ticket->end_timestamp);
210
- $EM_Event->rsvp_end = $EM_Ticket->end_timestamp;
211
  if( $EM_Event->is_recurring() && !empty($EM_Ticket->ticket_meta['recurrences']) ){
212
  $EM_Event->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days'];
213
  }
214
  }else{
215
- //if no end date is set, use event end date (which will have defaulted to the event start date
216
- $EM_Ticket->ticket_end = $EM_Event->event_rsvp_date." ".$EM_Event->event_rsvp_time;
217
- $EM_Ticket->end_timestamp = $EM_Event->rsvp_end;
 
 
 
 
 
 
 
 
 
 
218
  }
219
  }
220
  }else{
@@ -272,9 +281,7 @@ class EM_Bookings extends EM_Object implements Iterator{
272
  function has_open_time(){
273
  $return = false;
274
  $EM_Event = $this->get_event();
275
- if(!empty($EM_Event->event_rsvp_date) && $EM_Event->rsvp_end > current_time('timestamp')){
276
- $return = true;
277
- }elseif( empty($EM_Event->event_rsvp_date) && $EM_Event->start > current_time('timestamp') ){
278
  $return = true;
279
  }
280
  return $return;
@@ -445,7 +452,8 @@ class EM_Bookings extends EM_Object implements Iterator{
445
  }
446
 
447
  /**
448
- * Gets number of bookings (not spaces). If booking approval is enabled, only the number of approved bookings will be shown.
 
449
  * @return EM_Bookings
450
  */
451
  function get_bookings( $all_bookings = false ){
@@ -562,7 +570,7 @@ class EM_Bookings extends EM_Object implements Iterator{
562
  $sql = "
563
  SELECT * FROM $bookings_table b
564
  LEFT JOIN $events_table e ON e.event_id=b.event_id
565
- WHERE booking_id".implode(" OR booking_id=", $args);
566
  $results = $wpdb->get_results(apply_filters('em_bookings_get_sql',$sql),ARRAY_A);
567
  $bookings = array();
568
  foreach($results as $result){
@@ -613,7 +621,7 @@ class EM_Bookings extends EM_Object implements Iterator{
613
  $results = $wpdb->get_results($sql, ARRAY_A);
614
 
615
  //If we want results directly in an array, why not have a shortcut here?
616
- if( $args['array'] == true ){
617
  return $results;
618
  }
619
 
@@ -741,7 +749,7 @@ class EM_Bookings extends EM_Object implements Iterator{
741
  'person' => true, //to add later, search by person's bookings...
742
  'blog' => get_current_blog_id(),
743
  'ticket_id' => false,
744
- 'array' => false //returns an array of results if true, if an array or text it's assumed an array or single row requested
745
  );
746
  //sort out whether defaults were supplied or just the array of search values
747
  if( empty($array) ){
198
  function get_tickets( $force_reload = false ){
199
  if( !is_object($this->tickets) || $force_reload ){
200
  $this->tickets = new EM_Tickets($this->event_id);
201
+ if( get_option('dbem_bookings_tickets_single') && count($this->tickets->tickets) == 1 ){
202
  //if in single ticket mode, then the event booking cut-off is the ticket end date
203
  $EM_Ticket = $this->tickets->get_first();
204
  $EM_Event = $this->get_event();
205
  //if ticket has cut-off date, that should take precedence as we save the ticket cut-off date/time to the event in single ticket mode
206
  if( !empty($EM_Ticket->ticket_end) ){
207
  //if ticket end dates are set, move to event
208
+ $EM_Event->event_rsvp_date = $EM_Ticket->end()->format('Y-m-d');
209
+ $EM_Event->event_rsvp_time = $EM_Ticket->end()->format('H:i:00');
 
210
  if( $EM_Event->is_recurring() && !empty($EM_Ticket->ticket_meta['recurrences']) ){
211
  $EM_Event->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days'];
212
  }
213
  }else{
214
+ //if no end date is set, use event end date (which will have defaulted to the event start date
215
+ if( !$EM_Event->is_recurring() ){
216
+ $EM_Ticket->ticket_end = $EM_Event->rsvp_end()->getDateTime();
217
+ }else{
218
+ if( !isset($EM_Ticket->ticket_meta['recurrences']['end_days']) ){
219
+ //for recurrences, we take the recurrence_rsvp_days and feed it into the ticket meta that'll handle recurrences
220
+ $EM_Ticket->ticket_meta['recurrences']['end_days'] = $EM_Event->recurrence_rsvp_days;
221
+ if( !isset($EM_Ticket->ticket_meta['recurrences']['time']) ){
222
+ $EM_Ticket->ticket_meta['recurrences']['end_time'] = $EM_Event->event_rsvp_time;
223
+ }
224
+ $EM_Ticket->ticket_end = date('Y-m-d ') . $EM_Ticket->ticket_meta['recurrences']['end_time'];
225
+ }
226
+ }
227
  }
228
  }
229
  }else{
281
  function has_open_time(){
282
  $return = false;
283
  $EM_Event = $this->get_event();
284
+ if( $EM_Event->rsvp_end()->getTimestamp() > time()){
 
 
285
  $return = true;
286
  }
287
  return $return;
452
  }
453
 
454
  /**
455
+ * Gets booking objects (not spaces). If booking approval is enabled, only the number of approved bookings will be shown.
456
+ * @param boolean $all_bookings If set to true, then all bookings with any status is returned
457
  * @return EM_Bookings
458
  */
459
  function get_bookings( $all_bookings = false ){
570
  $sql = "
571
  SELECT * FROM $bookings_table b
572
  LEFT JOIN $events_table e ON e.event_id=b.event_id
573
+ WHERE booking_id=".implode(" OR booking_id=", $args);
574
  $results = $wpdb->get_results(apply_filters('em_bookings_get_sql',$sql),ARRAY_A);
575
  $bookings = array();
576
  foreach($results as $result){
621
  $results = $wpdb->get_results($sql, ARRAY_A);
622
 
623
  //If we want results directly in an array, why not have a shortcut here?
624
+ if( !empty($args['array']) ){
625
  return $results;
626
  }
627
 
749
  'person' => true, //to add later, search by person's bookings...
750
  'blog' => get_current_blog_id(),
751
  'ticket_id' => false,
752
+ 'array' => false //returns an array of results if true, if an array or text it's assumed an array of specific table fields or single field name requested
753
  );
754
  //sort out whether defaults were supplied or just the array of search values
755
  if( empty($array) ){
classes/em-calendar.php CHANGED
@@ -19,11 +19,12 @@ class EM_Calendar extends EM_Object {
19
  //figure out what month to look for, if we need to
20
  if( empty($args['month']) && is_array($args['scope']) ){
21
  //if a scope is supplied, figure out the month/year we're after, which will be between these two dates.
22
- $scope_start = strtotime($args['scope'][0]);
23
- $scope_end = strtotime($args['scope'][1]);
24
- $scope_middle = $scope_start + ($scope_end - $scope_start)/2;
25
- $month = $args['month'] = date('n', $scope_middle);
26
- $year = $args['year'] = date('Y', $scope_middle);
 
27
  }else{
28
  //if month/year supplied, we use those or later on default to current month/year
29
  $month = $args['month'];
@@ -200,10 +201,10 @@ class EM_Calendar extends EM_Object {
200
  }
201
 
202
  //query the database for events in this time span with $offset days before and $outset days after this month to account for these cells in the calendar
203
- $scope_datetime_start = new DateTime("{$year}-{$month}-1");
204
- $scope_datetime_end = new DateTime($scope_datetime_start->format('Y-m-t'));
205
- $scope_datetime_start->modify("-$offset days");
206
- $scope_datetime_end->modify("+$outset days");
207
  //we have two methods here, one for high-volume event sites i.e. many thousands of events per month, and another for thousands or less per month.
208
  $args['array'] = true; //we're getting an array first to avoid extra queries during object creation
209
  unset($args['month']);
@@ -244,18 +245,18 @@ class EM_Calendar extends EM_Object {
244
  $event = apply_filters('em_calendar_output_loop_start', $event);
245
  if( $long_events ){
246
  //If $long_events is set then show a date as eventful if there is an multi-day event which runs during that day
247
- $event_start_ts = strtotime($event['event_start_date']);
248
- $event_end_ts = strtotime($event['event_end_date']);
249
- $event_end_ts = $event_end_ts > $scope_datetime_end->format('U') ? $scope_datetime_end->format('U') : $event_end_ts;
250
- while( $event_start_ts <= $event_end_ts ){ //we loop until the last day of our time-range, not the end date of the event, which could be in a year
251
  //Ensure date is within event dates and also within the limits of events to show per day, if so add to eventful days array
252
- $event_eventful_date = date('Y-m-d', $event_start_ts);
253
  if( empty($eventful_days_count[$event_eventful_date]) || !$limit || $eventful_days_count[$event_eventful_date] < $limit ){
254
  //now we know this is an event that'll be used, convert it to an object
255
  $EM_Event = EM_MS_GLOBAL ? em_get_event($event['post_id'], $event['blog_id']) : $EM_Event = em_get_event($event['post_id'], 'post_id');
256
  if( empty($eventful_days[$event_eventful_date]) || !is_array($eventful_days[$event_eventful_date]) ) $eventful_days[$event_eventful_date] = array();
257
  //add event to array with a corresponding timestamp for sorting of times including long and all-day events
258
- $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) strtotime($event_eventful_date.' '.$EM_Event->event_start_time);
259
  while( !empty($eventful_days[$event_eventful_date][$event_ts_marker]) ){
260
  $event_ts_marker++; //add a second
261
  }
@@ -263,7 +264,7 @@ class EM_Calendar extends EM_Object {
263
  }
264
  //count events for that day
265
  $eventful_days_count[$event_eventful_date] = empty($eventful_days_count[$event_eventful_date]) ? 1 : $eventful_days_count[$event_eventful_date]+1;
266
- $event_start_ts += (86400); //add a day
267
  }
268
  }else{
269
  //Only show events on the day that they start
@@ -272,7 +273,7 @@ class EM_Calendar extends EM_Object {
272
  $EM_Event = EM_MS_GLOBAL ? em_get_event($event['post_id'], $event['blog_id']) : em_get_event($event['post_id'], 'post_id');
273
  if( empty($eventful_days[$event_eventful_date]) || !is_array($eventful_days[$event_eventful_date]) ) $eventful_days[$event_eventful_date] = array();
274
  //add event to array with a corresponding timestamp for sorting of times including long and all-day events
275
- $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) $EM_Event->start;
276
  while( !empty($eventful_days[$event_eventful_date][$event_ts_marker]) ){
277
  $event_ts_marker++; //add a second
278
  }
19
  //figure out what month to look for, if we need to
20
  if( empty($args['month']) && is_array($args['scope']) ){
21
  //if a scope is supplied, figure out the month/year we're after, which will be between these two dates.
22
+ $EM_DateTime = new EM_DateTime($args['scope'][0]);
23
+ $scope_start = $EM_DateTime->getTimestamp();
24
+ $scope_end = $EM_DateTime->modify($args['scope'][1])->getTimestamp();
25
+ $EM_DateTime->setTimestamp( $scope_start + ($scope_end - $scope_start)/2 );
26
+ $month = $args['month'] = $EM_DateTime->format('n');
27
+ $year = $args['year'] = $EM_DateTime->format('Y');
28
  }else{
29
  //if month/year supplied, we use those or later on default to current month/year
30
  $month = $args['month'];
201
  }
202
 
203
  //query the database for events in this time span with $offset days before and $outset days after this month to account for these cells in the calendar
204
+ $scope_datetime_start = new EM_DateTime("{$year}-{$month}-1");
205
+ $scope_datetime_end = new EM_DateTime($scope_datetime_start->format('Y-m-t'));
206
+ $scope_datetime_start->sub('P'.$offset.'D');
207
+ $scope_datetime_end->add('P'.$outset.'D');
208
  //we have two methods here, one for high-volume event sites i.e. many thousands of events per month, and another for thousands or less per month.
209
  $args['array'] = true; //we're getting an array first to avoid extra queries during object creation
210
  unset($args['month']);
245
  $event = apply_filters('em_calendar_output_loop_start', $event);
246
  if( $long_events ){
247
  //If $long_events is set then show a date as eventful if there is an multi-day event which runs during that day
248
+ $event_start = new EM_DateTime($event['event_start_date'], $event['event_timezone']);
249
+ $event_end = new EM_DateTime($event['event_end_date'], $event['event_timezone']);
250
+ if( $event_end->getTimestamp() > $scope_datetime_end->getTimestamp() ) $event_end = $scope_datetime_end;
251
+ while( $event_start->getTimestamp() <= $event_end->getTimestamp() ){ //we loop until the last day of our time-range, not the end date of the event, which could be in a year
252
  //Ensure date is within event dates and also within the limits of events to show per day, if so add to eventful days array
253
+ $event_eventful_date = $event_start->getDate();
254
  if( empty($eventful_days_count[$event_eventful_date]) || !$limit || $eventful_days_count[$event_eventful_date] < $limit ){
255
  //now we know this is an event that'll be used, convert it to an object
256
  $EM_Event = EM_MS_GLOBAL ? em_get_event($event['post_id'], $event['blog_id']) : $EM_Event = em_get_event($event['post_id'], 'post_id');
257
  if( empty($eventful_days[$event_eventful_date]) || !is_array($eventful_days[$event_eventful_date]) ) $eventful_days[$event_eventful_date] = array();
258
  //add event to array with a corresponding timestamp for sorting of times including long and all-day events
259
+ $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) $event_start->getTimestamp();
260
  while( !empty($eventful_days[$event_eventful_date][$event_ts_marker]) ){
261
  $event_ts_marker++; //add a second
262
  }
264
  }
265
  //count events for that day
266
  $eventful_days_count[$event_eventful_date] = empty($eventful_days_count[$event_eventful_date]) ? 1 : $eventful_days_count[$event_eventful_date]+1;
267
+ $event_start->add('P1D');
268
  }
269
  }else{
270
  //Only show events on the day that they start
273
  $EM_Event = EM_MS_GLOBAL ? em_get_event($event['post_id'], $event['blog_id']) : em_get_event($event['post_id'], 'post_id');
274
  if( empty($eventful_days[$event_eventful_date]) || !is_array($eventful_days[$event_eventful_date]) ) $eventful_days[$event_eventful_date] = array();
275
  //add event to array with a corresponding timestamp for sorting of times including long and all-day events
276
+ $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) $EM_Event->start()->getTimestamp();
277
  while( !empty($eventful_days[$event_eventful_date][$event_ts_marker]) ){
278
  $event_ts_marker++; //add a second
279
  }
classes/em-categories-admin.php CHANGED
File without changes
classes/em-categories-frontend.php CHANGED
File without changes
classes/em-categories.php CHANGED
@@ -7,6 +7,7 @@ class EM_Categories extends EM_Taxonomy_Terms {
7
  protected $meta_key = 'event-category';
8
  protected $terms_name = 'categories';
9
  protected $term_class = 'EM_Category';
 
10
 
11
  /**
12
  * Creates an EM_Categories instance, currently accepts an EM_Event object (gets all Categories for that event) or array of any EM_Category objects, which can be manipulated in bulk with helper functions.
7
  protected $meta_key = 'event-category';
8
  protected $terms_name = 'categories';
9
  protected $term_class = 'EM_Category';
10
+ protected $ajax_search_action = 'search_cats';
11
 
12
  /**
13
  * Creates an EM_Categories instance, currently accepts an EM_Event object (gets all Categories for that event) or array of any EM_Category objects, which can be manipulated in bulk with helper functions.
classes/em-category.php CHANGED
@@ -12,7 +12,7 @@ class EM_Category extends EM_Taxonomy_Term {
12
  * @param string $class_name
13
  * @return EM_Taxonomy
14
  */
15
- public static function get( $id = false, $class_name = 'EM_Category' ){
16
  return parent::get($id, $class_name);
17
  }
18
 
@@ -27,6 +27,6 @@ class EM_Category extends EM_Taxonomy_Term {
27
  * @return EM_Category
28
  * @uses EM_Category::get()
29
  */
30
- function em_get_category( $id = false ) {
31
  return EM_Category::get($id);
32
  }
12
  * @param string $class_name
13
  * @return EM_Taxonomy
14
  */
15
+ public static function get( $id, $class_name = 'EM_Category' ){
16
  return parent::get($id, $class_name);
17
  }
18
 
27
  * @return EM_Category
28
  * @uses EM_Category::get()
29
  */
30
+ function em_get_category( $id ) {
31
  return EM_Category::get($id);
32
  }
classes/em-datetime.php ADDED
@@ -0,0 +1,480 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Extends DateTime allowing supplied timezone to be a string, which can also be a UTC offset.
4
+ * Also prevents an exception being thrown. Some additional shortcuts added so less coding is required for regular tasks.
5
+ * By doing this, we support WP's option to manually offset time without DST, which is not supported by DateTimeZone in PHP <5.5.10
6
+ *
7
+ * @since 5.8.2
8
+ */
9
+ class EM_DateTime extends DateTime {
10
+
11
+ /**
12
+ * The name of this timezone. For example, America/New_York or UTC+3.5
13
+ * @var string
14
+ */
15
+ protected $timezone_name = false;
16
+ /**
17
+ * Shortcut representing the offset of time in the timezone, if it's a UTC manual offset, false if not.
18
+ * @var int
19
+ */
20
+ protected $timezone_manual_offset = false;
21
+ /**
22
+ * Flag for validation purposes, so we can still have a real EM_DateTime and extract dates but know if the intended datetime failed validation.
23
+ * A completely invalid date and time will become 1970-01-01 00:00:00 in local timezone, however a valid time can still exist with the 1970-01-01 date.
24
+ * If the date is invalid, only local timezones should be used since the time will not accurately convert timezone switches.
25
+ * @var string
26
+ */
27
+ public $valid = true;
28
+
29
+ /**
30
+ * @see DateTime::__construct()
31
+ * @param string $time
32
+ * @param string|EM_DateTimeZone $timezone Unlike DateTime this also accepts string representation of a valid timezone, as well as UTC offsets in form of 'UTC -3' or just '-3'
33
+ */
34
+ public function __construct( $time = null, $timezone = null ){
35
+ //get our EM_DateTimeZone
36
+ $timezone = EM_DateTimeZone::create($timezone);
37
+ //fix DateTime error if a regular timestamp is supplied without prepended @ symbol
38
+ if( is_numeric($time) ) $time = '@'.$time;
39
+ //finally, run parent function with our custom timezone
40
+ try{
41
+ @parent::__construct($time, $timezone);
42
+ $this->valid = true; //if we get this far, supplied time is valid
43
+ }catch( Exception $e ){
44
+ //get current date/time in relevant timezone and set valid flag to false
45
+ parent::__construct('@0');
46
+ $this->setTimezone($timezone);
47
+ $this->setDate(1970,1,1);
48
+ $this->setTime(0,0,0);
49
+ $this->valid = false;
50
+ }
51
+ //save timezone name for use in getTimezone()
52
+ $this->timezone_name = $timezone->getName();
53
+ $this->timezone_manual_offset = $timezone->manual_offset;
54
+ //deal with manual UTC offsets, but only if we haven't defaulted to the current timestamp since that would already be a correct relative value
55
+ if( $time !== null && $time != 'now' ) $this->handleOffsets($timezone);
56
+ }
57
+
58
+ /**
59
+ * If a UTC offset timezone is active, upon object creation or modification of the time, we need to store the actual UTC time relative to
60
+ * the offset timezone, whereas initially the saved time will be UTC time relative to the time modified/created.
61
+ *
62
+ * Example:
63
+ * We create an object with local UTC-5 time 12pm which is actually 5pm UTC. However, by default we'll have a 12PM UTC time stored as our internal timestamp.
64
+ * What we'll want to do is make sure we're internally storing 5pm UTC time, which is the same value we'd have if we had a PHP native timezone like New York.
65
+ * The only exception we don't want to do this is if we're setting the time to NOW, as in the current time which will always be the same value in UTC no matter what timezone.
66
+ */
67
+ protected function handleOffsets(){
68
+ //handle manual UTC offsets
69
+ if( $this->timezone_manual_offset !== false ){
70
+ //the actual time here needs to be in actual UTC time because offsets are applied to UTC on any output functions
71
+ $this->setTimestamp( $this->getTimestamp() - $this->timezone_manual_offset );
72
+ }
73
+ }
74
+
75
+ /**
76
+ * {@inheritDoc}
77
+ * @see DateTime::format()
78
+ */
79
+ public function format( $format = 'Y-m-d H:i:s'){
80
+ if( !$this->valid && ($format == 'Y-m-d' || $format == em_get_date_format())) return '';
81
+ //if we deal with offsets, then we offset UTC time by that much
82
+ if( $this->timezone_manual_offset !== false ){
83
+ return date($format, $this->getTimestamp() + $this->timezone_manual_offset );
84
+ }
85
+ return parent::format($format);
86
+ }
87
+
88
+ /**
89
+ * Returns a date and time representation in the format stored in Events Manager settings.
90
+ * @param string $include_hour
91
+ * @return string
92
+ */
93
+ public function formatDefault( $include_hour = true ){
94
+ $format = $include_hour ? em_get_date_format() . ' ' . em_get_hour_format() : em_get_date_format();
95
+ $format = apply_filters( 'em_datetime_format_default', $format, $include_hour );
96
+ return $this->i18n( $format );
97
+ }
98
+
99
+ /**
100
+ * Provides a translated date and time according to the current blog language.
101
+ * Useful if using formats that provide date-related names such as 'Monday' or 'January', which should be translated if displayed in another language.
102
+ * @param string $format
103
+ * @return string
104
+ */
105
+ public function i18n( $format = 'Y-m-d H:i:s' ){
106
+ if( !$this->valid && $format == em_get_date_format()) return '';
107
+ //if we deal with offsets, then we offset UTC time by that much
108
+ $ts = $this->getTimestamp();
109
+ $tswo = $this->getTimestampWithOffset();
110
+ return date_i18n( $format, $this->getTimestampWithOffset() );
111
+ }
112
+
113
+ /**
114
+ * Outputs a default mysql datetime formatted string.
115
+ * @return string
116
+ */
117
+ public function __toString(){
118
+ return $this->format('Y-m-d H:i:s');
119
+ }
120
+
121
+ /**
122
+ * Modifies the time of this object, if a mysql TIME valid format is provided (e.g. 14:30:00)
123
+ * @param string $hour
124
+ * @return EM_DateTime Returns object for chaining.
125
+ */
126
+ public function setTimeString( $hour ){
127
+ if( preg_match('/^\d{2}:\d{2}:\d{2}$/', $hour) ){
128
+ $time = explode(':', $hour);
129
+ $this->setTime($time[0], $time[1], $time[2]);
130
+ }
131
+ return $this;
132
+ }
133
+
134
+ public function setTimestamp( $timestamp ){
135
+ if( function_exists('date_timestamp_set') ){
136
+ return parent::setTimestamp( $timestamp );
137
+ }else{
138
+ //PHP < 5.3 fallback :/ setting modify() with a timestamp produces unpredictable results, so we play more tricks...
139
+ $date = explode(',', date('Y,n,j,G,i,s', $timestamp));
140
+ parent::setDate( (int) $date[0], (int) $date[1], (int) $date[2]);
141
+ parent::setTime( (int) $date[3], (int) $date[4], (int) $date[5]);
142
+ return $this;
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Extends DateTime functionality by accepting a false or string value for a timezone.
148
+ * @see DateTime::setTimezone()
149
+ * @return EM_DateTime Returns object for chaining.
150
+ */
151
+ public function setTimezone( $timezone ){
152
+ if( $timezone == $this->getTimezone()->getName() ) return $this;
153
+ $timezone = EM_DateTimeZone::create($timezone);
154
+ parent::setTimezone($timezone);
155
+ $this->timezone_name = $timezone->getName();
156
+ $this->timezone_manual_offset = $timezone->manual_offset;
157
+ return $this;
158
+ }
159
+
160
+ public function setTime( $hour, $minute, $second = NULL, $microseconds = NULL ){
161
+ parent::setTime( $hour, $minute, $second );
162
+ $this->handleOffsets();
163
+ return $this;
164
+ }
165
+
166
+ public function setDate( $year, $month, $day ){
167
+ if( $this->timezone_manual_offset !== false ){
168
+ //we run into issues if we're dealing with timezones on the fringe of date changes e.g. 2018-01-01 01:00:00 UTC+2
169
+ $DateTime = new DateTime( $this->getDateTime(), new DateTimeZone('UTC'));
170
+ $DateTime->setDate( $year, $month, $day );
171
+ //create a new timestamp based on UTC DateTime and offset it to current timezone
172
+ if( function_exists('date_timestamp_get') ){
173
+ $timestamp = $DateTime->getTimestamp();
174
+ }else{
175
+ //PHP < 5.3 fallback :/
176
+ $timestamp = $DateTime->format('U');
177
+ }
178
+ $timestamp -= $this->timezone_manual_offset;
179
+ $this->setTimestamp( $timestamp );
180
+ }else{
181
+ parent::setDate( $year, $month, $day );
182
+ }
183
+ return $this;
184
+ }
185
+
186
+ public function setISODate( $year, $week, $day = NULL ){
187
+ parent::setISODate( $year, $week, $day );
188
+ return $this;
189
+ }
190
+
191
+ public function modify( $modify ){
192
+ if( function_exists('date_add') ){
193
+ parent::modify($modify);
194
+ }else{
195
+ //PHP < 5.3 fallback :/ wierd stuff happens when using the DateTime modify function
196
+ $this->setTimestamp( strtotime($modify, $this->getTimestamp()) );
197
+ }
198
+ $this->handleOffsets();
199
+ return $this;
200
+ }
201
+
202
+ /**
203
+ * Extends DateTime function to allow string representation of argument passed to create a new DateInterval object.
204
+ * @see DateTime::add()
205
+ * @param string|DateInterval
206
+ * @return EM_DateTime Returns object for chaining.
207
+ */
208
+ public function add( $DateInterval ){
209
+ if( function_exists('date_add') ){
210
+ if( is_object($DateInterval) ){
211
+ return parent::add($DateInterval);
212
+ }else{
213
+ return parent::add( new DateInterval($DateInterval) );
214
+ }
215
+ }else{
216
+ //PHP < 5.3 fallback :/
217
+ $strtotime = $this->dateinterval_fallback($DateInterval, 'add');
218
+ $this->setTimestamp( strtotime($strtotime, $this->getTimestamp()) );
219
+ return $this;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Extends DateTime function to allow string representation of argument passed to create a new DateInterval object.
225
+ * @see DateTime::sub()
226
+ * @param string|DateInterval
227
+ * @return EM_DateTime
228
+ */
229
+ public function sub( $DateInterval ){
230
+ if( function_exists('date_sub') ){
231
+ if( is_object($DateInterval) ){
232
+ return parent::sub($DateInterval);
233
+ }else{
234
+ return parent::sub( new DateInterval($DateInterval) );
235
+ }
236
+ }else{
237
+ //PHP < 5.3 fallback :/
238
+ $strtotime = $this->dateinterval_fallback($DateInterval, 'subtract');
239
+ $this->setTimestamp( strtotime($strtotime, $this->getTimestamp()) );
240
+ return $this;
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Fallback function for PHP versions prior to 5.3, as sub() and add() methods aren't available and therefore we need to generate a valid string we can pass onto modify()
246
+ * @param unknown $dateinteval_string
247
+ * @param unknown $add_or_subtract
248
+ * @return string
249
+ */
250
+ private function dateinterval_fallback( $dateinteval_string, $add_or_subtract ){
251
+ $date_time_split = explode('T', $dateinteval_string);
252
+ $matches = $modify_string_array = array();
253
+ //first parse date then time if available
254
+ preg_match_all('/([0-9]+)([YMDW])/', preg_replace('/^P/', '', $date_time_split[0]), $matches['date']);
255
+ if( !empty($date_time_split[1]) ){
256
+ preg_match_all('/([0-9]+)([HMS])/', $date_time_split[1], $matches['time']);
257
+ }
258
+ //convert DateInterval into a strtotime() valid string for use in $this->modify();
259
+ $modify_conversion = array('Y'=>'years', 'M'=>'months', 'D'=>'days', 'W'=>'weeks', 'H'=>'hours', 'S'=>'seconds');
260
+ foreach( $matches as $match_type => $match ){
261
+ foreach( $match[1] as $k => $v ){
262
+ if( $match[2][$k] == 'M' ){
263
+ $modify_string_array[] = $match_type == 'time' ? $v . ' minutes': $v . ' months';
264
+ }else{
265
+ $modify_string_array[] = $v . ' '. $modify_conversion[$match[2][$k]];
266
+ }
267
+ }
268
+ }
269
+ $modifier = $add_or_subtract == 'subtract' ? '-':'+';
270
+ return $modifier . implode(' '.$modifier, $modify_string_array);
271
+ }
272
+
273
+ /**
274
+ * Easy chainable cloning function, useful for situations where you may want to manipulate the current date,
275
+ * such as adding a month and getting the DATETIME string without changing the original value of this object.
276
+ * @return EM_DateTime
277
+ */
278
+ public function copy(){
279
+ return clone $this;
280
+ }
281
+
282
+ public function getTimestamp(){
283
+ if( function_exists('date_timestamp_get') ){
284
+ return parent::getTimestamp();
285
+ }else{
286
+ //PHP < 5.3 fallback :/
287
+ $strtotime = parent::format('Y-m-d H:i:s');
288
+ $timestamp = strtotime($strtotime);
289
+ return $timestamp;
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Gets a timestamp with an offset, which will represent the local time equivalent in UTC time (so a local time would be produced if supplied to date())
295
+ */
296
+ public function getTimestampWithOffset(){
297
+ return $this->getOffset() + $this->getTimestamp();
298
+ }
299
+
300
+ /**
301
+ * Extends DateTime::getOffset() by checking for timezones with manual offsets, such as UTC+3.5
302
+ * @see DateTime::getOffset()
303
+ * @return int
304
+ */
305
+ public function getOffset(){
306
+ if( $this->timezone_manual_offset !== false ){
307
+ return $this->timezone_manual_offset;
308
+ }
309
+ return parent::getOffset();
310
+ }
311
+
312
+ /**
313
+ * Returns an EM_DateTimeZone object instead of the default DateTimeZone object.
314
+ * @see DateTime::getTimezone()
315
+ * @return EM_DateTimeZone
316
+ */
317
+ public function getTimezone(){
318
+ return new EM_DateTimeZone($this->timezone_name);
319
+ }
320
+
321
+ /**
322
+ * Returns a MySQL TIME formatted string, with the option of providing the UTC equivalent.
323
+ * @param bool $utc If set to true a UTC relative time will be provided.
324
+ * @return string
325
+ */
326
+ public function getTime( $utc = false ){
327
+ if( $utc ){
328
+ $current_timezone = $this->getTimezone()->getName();
329
+ $this->setTimezone('UTC');
330
+ }
331
+ $return = $this->format('H:i:s');
332
+ if( $utc ) $this->setTimezone($current_timezone);
333
+ return $return;
334
+ }
335
+
336
+ /**
337
+ * Returns a MySQL DATE formatted string.
338
+ * @return string
339
+ */
340
+ public function getDate( $utc = false ){
341
+ return $this->format('Y-m-d');
342
+ }
343
+
344
+ /**
345
+ * Returns a MySQL DATETIME formatted string, with the option of providing the UTC equivalent.
346
+ * @param bool $utc If set to true a UTC relative time will be provided.
347
+ * @return string
348
+ */
349
+ public function getDateTime( $utc = false ){
350
+ if( $utc ){
351
+ $current_timezone = $this->getTimezone()->getName();
352
+ $this->setTimezone('UTC');
353
+ }
354
+ $return = $this->format('Y-m-d H:i:s');
355
+ if( $utc ) $this->setTimezone($current_timezone);
356
+ return $return;
357
+ }
358
+
359
+ /* PHP 5.3+ functions that are not used and should not be used until 5.3 is a minimum requirement
360
+
361
+ /**
362
+ * NOT TO BE USED until PHP 5.3 is a minimum requirement in WordPress
363
+ * Extends the DateTime::createFromFormat() function by setting the timezone to the default blog timezone if none is provided.
364
+ * @param string $format
365
+ * @param string $time
366
+ * @param string|EM_DateTimeZone $timezone
367
+ * @return boolean|EM_DateTime
368
+ */
369
+ public static function createFromFormat( $format, $time, $timezone = null ){
370
+ $timezone = EM_DateTimeZone::create($timezone);
371
+ $DateTime = parent::createFromFormat($format, $time, $timezone);
372
+ if( $DateTime === false ) return false;
373
+ return new EM_DateTime($DateTime->format('Y-m-d H:i:s'), $timezone);
374
+ }
375
+
376
+ public function diff( $DateTime, $absolute = null ){
377
+ if( function_exists('date_diff') ){
378
+ return parent::diff( $DateTime, $absolute );
379
+ }else{
380
+ //PHP < 5.3 fallback :/ there is no fallback, really
381
+ return new stdClass();
382
+ }
383
+ }
384
+ }
385
+
386
+ /**
387
+ * Extends the native DateTimeZone object by allowing for UTC manual offsets as supported by WordPress, along with eash creation of a DateTimeZone object with the blog's timezone.
388
+ * @since 5.8.2
389
+ */
390
+ class EM_DateTimeZone extends DateTimeZone {
391
+
392
+ public $manual_offset = false;
393
+
394
+ public function __construct( $timezone ){
395
+ //if we're not suppiled a DateTimeZone object, create one from string or implement manual offset
396
+ if( $timezone != 'UTC' ){
397
+ $timezone = preg_replace('/^UTC ?/', '', $timezone);
398
+ if( is_numeric($timezone) ){
399
+ if( absint($timezone) == 0 ){
400
+ $timezone = 'UTC';
401
+ }else{
402
+ $this->manual_offset = $timezone * 3600;
403
+ $timezone = 'UTC';
404
+ }
405
+ }
406
+ }
407
+ parent::__construct($timezone);
408
+ }
409
+
410
+ /**
411
+ * Special function which converts a timezone string, UTC offset or DateTimeZone object into a valid EM_DateTimeZone object.
412
+ * If no value supplied, a EM_DateTimezone with the default WP environment timezone is created.
413
+ * @param mixed $timezone
414
+ * @return EM_DateTimeZone
415
+ */
416
+ public static function create( $timezone = false ){
417
+ //if we're not suppiled a DateTimeZone object, create one from string or implement manual offset
418
+ if( !empty($timezone) && !is_object($timezone) ){
419
+ //create EM_DateTimeZone object if valid, otherwise allow defaults to override later
420
+ try {
421
+ $timezone = new EM_DateTimeZone($timezone);
422
+ }catch( Exception $e ){
423
+ $timezone = null;
424
+ }
425
+ }elseif( is_object($timezone) && get_class($timezone) == 'DateTimeZone'){
426
+ //if supplied a regular DateTimeZone, convert it to EM_DateTimeZone
427
+ $timezone = new EM_DateTimeZone($timezone->getName());
428
+ }
429
+ if( !is_object($timezone) ){
430
+ //if no valid timezone supplied, get the default timezone in EM environment, otherwise the WP timezone or offset
431
+ $timezone = get_option( 'timezone_string' );
432
+ if( !$timezone ) $timezone = get_option('gmt_offset');
433
+ $timezone = new EM_DateTimeZone($timezone);
434
+ }
435
+ return $timezone;
436
+ }
437
+
438
+ /**
439
+ * {@inheritDoc}
440
+ * @see DateTimeZone::getOffset()
441
+ */
442
+ public function getOffset( $datetime ){
443
+ if( $this->manual_offset !== false ){
444
+ return $this->manual_offset;
445
+ }
446
+ return parent::getOffset( $datetime );
447
+ }
448
+
449
+ /**
450
+ * {@inheritDoc}
451
+ * @see DateTimeZone::getName()
452
+ */
453
+ public function getName(){
454
+ if( $this->manual_offset !== false ){
455
+ if( $this->manual_offset > 0 ){
456
+ $return = 'UTC+'.$this->manual_offset/3600;
457
+ }else{
458
+ $return = 'UTC'.$this->manual_offset/3600;
459
+ }
460
+ return $return;
461
+ }
462
+ return parent::getName();
463
+ }
464
+
465
+ /**
466
+ * If the timezone has a manual UTC offset, then an empty array of transitions is returned.
467
+ * {@inheritDoc}
468
+ * @see DateTimeZone::getTransitions()
469
+ */
470
+ public function getTransitions( $timestamp_begin = null, $timestamp_end = null ){
471
+ if( $this->manual_offset !== false ){
472
+ return array();
473
+ }
474
+ if( version_compare(phpversion(), '5.3') < 0 ){
475
+ return parent::getTransitions();
476
+ }else{
477
+ return parent::getTransitions($timestamp_begin, $timestamp_end);
478
+ }
479
+ }
480
+ }
classes/em-event-post-admin.php CHANGED
@@ -39,17 +39,17 @@ class EM_Event_Post_Admin{
39
  $warning .= "<p>". __( 'Modifications to recurring events will be applied to all recurrences and will overwrite any changes made to those individual event recurrences.', 'events-manager') . '</p>';
40
  $warning .= "<p>". __( 'Bookings to individual event recurrences will be preserved if event times and ticket settings are not modified.', 'events-manager') . '</p>';
41
  $warning .= '<p><a href="'. esc_url( add_query_arg(array('scope'=>'all', 'recurrence_id'=>$EM_Event->event_id), em_get_events_admin_url()) ).'">'. esc_html__('You can edit individual recurrences and disassociate them with this recurring event.','events-manager') . '</a></p>';
42
- ?><div class="updated"><?php echo $warning; ?></div><?php
43
  } elseif ( $EM_Event->is_recurrence() ) {
44
  $warning = "<p><strong>".__('WARNING: This is a recurrence in a set of recurring events.', 'events-manager')."</strong></p>";
45
  $warning .= "<p>". sprintf(__('If you update this event data and save, it could get overwritten if you edit the recurring event template. To make it an independent, <a href="%s">detach it</a>.', 'events-manager'), $EM_Event->get_detach_url())."</p>";
46
  $warning .= "<p>".sprintf(__('To manage the whole set, <a href="%s">edit the recurring event template</a>.', 'events-manager'),admin_url('post.php?action=edit&amp;post='.$EM_Event->get_event_recurrence()->post_id))."</p>";
47
- ?><div class="updated"><?php echo $warning; ?></div><?php
48
  }
49
  if( !empty($EM_Event->group_id) && function_exists('groups_get_group') ){
50
  $group = groups_get_group(array('group_id'=>$EM_Event->group_id));
51
  $warning = sprintf(__('WARNING: This is a event belonging to the group "%s". Other group admins can also modify this event.', 'events-manager'), $group->name);
52
- ?><div class="updated"><p><?php echo $warning; ?></p></div><?php
53
  }
54
  }
55
  }
@@ -142,6 +142,9 @@ class EM_Event_Post_Admin{
142
  if( $EM_Event->is_published() ){ $EM_Event->set_status(0, true); } //no publishing and editing... security threat
143
  }
144
  apply_filters('em_event_save', true, $EM_Event);
 
 
 
145
  }
146
  }else{
147
  //we're updating only the quick-edit style information, which is only post info saved into the index
@@ -171,6 +174,9 @@ class EM_Event_Post_Admin{
171
  $EM_Event->save_events();
172
  }
173
  apply_filters('em_event_save', true, $EM_Event);
 
 
 
174
  }else{
175
  do_action('em_event_save_pre', $EM_Event); //technically, the event is saved... but the meta isn't. wp doesn't give an pre-intervention action for this (or does it?)
176
  //Event doesn't validate, so set status to null
@@ -182,6 +188,21 @@ class EM_Event_Post_Admin{
182
  }
183
  }
184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  /**
186
  * Publish the location if the event has just been approved and the location is pending. We assume an editor published the event and approves the location too.
187
  * @param EM_Event $EM_Event
@@ -243,7 +264,7 @@ class EM_Event_Post_Admin{
243
  if(get_option('dbem_locations_enabled', true)){
244
  add_meta_box('em-event-where', __('Where','events-manager'), array('EM_Event_Post_Admin','meta_box_location'),EM_POST_TYPE_EVENT, 'normal','high');
245
  }
246
- if( defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_DISPLAY') && WP_DEBUG_DISPLAY ){
247
  add_meta_box('em-event-meta', 'Event Meta (debugging only)', array('EM_Event_Post_Admin','meta_box_metadump'),EM_POST_TYPE_EVENT, 'normal','high');
248
  }
249
  if( get_option('dbem_rsvp_enabled', true) && $EM_Event->can_manage('manage_bookings','manage_others_bookings') ){
@@ -272,7 +293,7 @@ class EM_Event_Post_Admin{
272
 
273
  public static function meta_box_metadump(){
274
  global $post,$EM_Event;
275
- echo "<pre>"; print_r($EM_Event); echo "</pre>";
276
  }
277
 
278
  public static function meta_box_anonymous(){
39
  $warning .= "<p>". __( 'Modifications to recurring events will be applied to all recurrences and will overwrite any changes made to those individual event recurrences.', 'events-manager') . '</p>';
40
  $warning .= "<p>". __( 'Bookings to individual event recurrences will be preserved if event times and ticket settings are not modified.', 'events-manager') . '</p>';
41
  $warning .= '<p><a href="'. esc_url( add_query_arg(array('scope'=>'all', 'recurrence_id'=>$EM_Event->event_id), em_get_events_admin_url()) ).'">'. esc_html__('You can edit individual recurrences and disassociate them with this recurring event.','events-manager') . '</a></p>';
42
+ ?><div class="notice notice-warning is-dismissible"><?php echo $warning; ?></div><?php
43
  } elseif ( $EM_Event->is_recurrence() ) {
44
  $warning = "<p><strong>".__('WARNING: This is a recurrence in a set of recurring events.', 'events-manager')."</strong></p>";
45
  $warning .= "<p>". sprintf(__('If you update this event data and save, it could get overwritten if you edit the recurring event template. To make it an independent, <a href="%s">detach it</a>.', 'events-manager'), $EM_Event->get_detach_url())."</p>";
46
  $warning .= "<p>".sprintf(__('To manage the whole set, <a href="%s">edit the recurring event template</a>.', 'events-manager'),admin_url('post.php?action=edit&amp;post='.$EM_Event->get_event_recurrence()->post_id))."</p>";
47
+ ?><div class="notice notice-warning is-dismissible"><?php echo $warning; ?></div><?php
48
  }
49
  if( !empty($EM_Event->group_id) && function_exists('groups_get_group') ){
50
  $group = groups_get_group(array('group_id'=>$EM_Event->group_id));
51
  $warning = sprintf(__('WARNING: This is a event belonging to the group "%s". Other group admins can also modify this event.', 'events-manager'), $group->name);
52
+ ?><div class="notice notice-info is-dismissible"><p><?php echo $warning; ?></p></div><?php
53
  }
54
  }
55
  }
142
  if( $EM_Event->is_published() ){ $EM_Event->set_status(0, true); } //no publishing and editing... security threat
143
  }
144
  apply_filters('em_event_save', true, $EM_Event);
145
+ //flag a cache refresh if we get here
146
+ $EM_Event->refresh_cache = true;
147
+ add_filter('save_post', 'EM_Event_Post_Admin::refresh_cache', 100000000);
148
  }
149
  }else{
150
  //we're updating only the quick-edit style information, which is only post info saved into the index
174
  $EM_Event->save_events();
175
  }
176
  apply_filters('em_event_save', true, $EM_Event);
177
+ //flag a cache refresh if we get here
178
+ $EM_Event->refresh_cache = true;
179
+ add_filter('save_post', 'EM_Event_Post_Admin::refresh_cache', 100000000);
180
  }else{
181
  do_action('em_event_save_pre', $EM_Event); //technically, the event is saved... but the meta isn't. wp doesn't give an pre-intervention action for this (or does it?)
182
  //Event doesn't validate, so set status to null
188
  }
189
  }
190
 
191
+ /**
192
+ * Refreshes the cache of the current global $EM_Event, provided the refresh_cache flag is set to true within the object and the object has a published state
193
+ */
194
+ public static function refresh_cache(){
195
+ global $EM_Event;
196
+ //if this is a published event, and the refresh_cache flag was added to this event during save_post, refresh the meta and update the cache
197
+ if( !empty($EM_Event->refresh_cache) && !empty($EM_Event->post_id) && $EM_Event->is_published() ){
198
+ $post = get_post($EM_Event->post_id);
199
+ $EM_Event->load_postdata($post);
200
+ unset($EM_Event->refresh_cache);
201
+ wp_cache_set($EM_Event->event_id, $EM_Event, 'em_events');
202
+ wp_cache_set($EM_Event->post_id, $EM_Event->event_id, 'em_events_ids');
203
+ }
204
+ }
205
+
206
  /**
207
  * Publish the location if the event has just been approved and the location is pending. We assume an editor published the event and approves the location too.
208
  * @param EM_Event $EM_Event
264
  if(get_option('dbem_locations_enabled', true)){
265
  add_meta_box('em-event-where', __('Where','events-manager'), array('EM_Event_Post_Admin','meta_box_location'),EM_POST_TYPE_EVENT, 'normal','high');
266
  }
267
+ if( defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_DISPLAY') && WP_DEBUG_DISPLAY && (!defined('EM_DEBUG_DISPLAY') || EM_DEBUG_DISPLAY) ){
268
  add_meta_box('em-event-meta', 'Event Meta (debugging only)', array('EM_Event_Post_Admin','meta_box_metadump'),EM_POST_TYPE_EVENT, 'normal','high');
269
  }
270
  if( get_option('dbem_rsvp_enabled', true) && $EM_Event->can_manage('manage_bookings','manage_others_bookings') ){
293
 
294
  public static function meta_box_metadump(){
295
  global $post,$EM_Event;
296
+ echo "<pre>"; print_r($EM_Event); echo "</pre>";
297
  }
298
 
299
  public static function meta_box_anonymous(){
classes/em-event-post.php CHANGED
@@ -138,6 +138,12 @@ class EM_Event_Post {
138
  }else{
139
  if( get_option('dbem_cp_events_formats') && !post_password_required() ){
140
  $EM_Event = em_get_event($post);
 
 
 
 
 
 
141
  ob_start();
142
  em_locate_template('templates/event-single.php',true);
143
  $content = ob_get_clean();
@@ -158,9 +164,9 @@ class EM_Event_Post {
158
  if( $post->post_type == EM_POST_TYPE_EVENT ){
159
  $EM_Event = em_get_event($post);
160
  if ( '' == $d ){
161
- $the_date = date_i18n(get_option('date_format'), $EM_Event->start);
162
  }else{
163
- $the_date = date_i18n($d, $EM_Event->start);
164
  }
165
  }
166
  return $the_date;
@@ -171,9 +177,9 @@ class EM_Event_Post {
171
  if( $post->post_type == EM_POST_TYPE_EVENT ){
172
  $EM_Event = em_get_event($post);
173
  if ( '' == $f ){
174
- $the_time = date_i18n(get_option('time_format'), $EM_Event->start);
175
  }else{
176
- $the_time = date_i18n($f, $EM_Event->start);
177
  }
178
  }
179
  return $the_time;
@@ -265,104 +271,79 @@ class EM_Event_Post {
265
  $scope = $wp_query->query_vars['scope'];
266
  }
267
  }
268
- $time = current_time('timestamp');
269
- if ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
270
- $today = strtotime($scope);
271
- $tomorrow = $today + 60*60*24-1;
272
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
273
- $query[] = array( 'key' => '_start_ts', 'value' => array($today,$tomorrow), 'compare' => 'BETWEEN' );
274
  }else{
275
- $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' );
276
- $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
277
  }
278
- }elseif ($scope == "future"){
279
- $today = strtotime(date('Y-m-d', $time));
280
- if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
281
- $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' );
282
- }else{
283
- $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
284
- }
285
- }elseif ($scope == "past"){
286
- $today = strtotime(date('Y-m-d', $time));
287
- if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
288
- $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<' );
289
- }else{
290
- $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '<' );
291
- }
292
- }elseif ($scope == "today"){
293
- $today = strtotime(date('Y-m-d', $time));
294
- $tomorrow = strtotime(date('Y-m-d',$time+60*60*24));
295
- if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
296
- //date must be only today
297
- $query[] = array( 'key' => '_start_ts', 'value' => array($today, $tomorrow), 'compare' => 'BETWEEN');
298
- }else{
299
- $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<' );
300
- $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
301
- }
302
- }elseif ($scope == "tomorrow"){
303
- $tomorrow = strtotime(date('Y-m-d',$time+60*60*24));
304
- $after_tomorrow = $tomorrow + 60*60*24;
305
- if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
306
- //date must be only tomorrow
307
- $query[] = array( 'key' => '_start_ts', 'value' => array($tomorrow, $after_tomorrow), 'compare' => 'BETWEEN');
308
- }else{
309
- $query[] = array( 'key' => '_start_ts', 'value' => $after_tomorrow, 'compare' => '<' );
310
- $query[] = array( 'key' => '_end_ts', 'value' => $tomorrow, 'compare' => '>=' );
311
- }
312
- }elseif ($scope == "month"){
313
- $start_month = strtotime(date('Y-m-d',$time));
314
- $end_month = strtotime(date('Y-m-t',$time)) + 86399;
315
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
316
- $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
317
  }else{
318
- $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
319
- $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
320
  }
321
- }elseif ($scope == "next-month"){
322
- $start_month_timestamp = strtotime('+1 month', $time); //get the end of this month + 1 day
323
- $start_month = strtotime(date('Y-m-1',$start_month_timestamp));
324
- $end_month = strtotime(date('Y-m-t',$start_month_timestamp)) + 86399;
 
325
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
326
- $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
327
  }else{
328
- $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
329
- $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
330
  }
331
  }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
 
332
  $months_to_add = $matches[1];
333
- $start_month = strtotime(date('Y-m-d',$time));
334
- $end_month = strtotime(date('Y-m-t',strtotime("+$months_to_add month", $time))) + 86399;
335
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
336
- $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
337
  }else{
338
- $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
339
- $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
340
  }
 
 
341
  }
342
  if( !empty($query) && is_array($query) ){
343
  $wp_query->query_vars['meta_query'] = $query;
344
  }
345
  if( is_admin() ){
346
  //admin areas don't need special ordering, so make it simple
347
- $wp_query->query_vars['orderby'] = (!empty($_REQUEST['orderby']) && $_REQUEST['orderby'] != 'date-time') ? $_REQUEST['orderby']:'meta_value_num';
348
- $wp_query->query_vars['meta_key'] = '_start_ts';
 
 
 
 
 
349
  $wp_query->query_vars['order'] = (!empty($_REQUEST['order'])) ? $_REQUEST['order']:'ASC';
350
  }else{
351
  if( get_option('dbem_events_default_archive_orderby') == 'title'){
352
  $wp_query->query_vars['orderby'] = 'title';
353
  $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_order','ASC');
354
  }else{
355
- $wp_query->query_vars['orderby'] = 'meta_value_num';
356
- $wp_query->query_vars['meta_key'] = '_start_ts';
 
357
  }
358
  $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_order','ASC');
359
  }
360
  }elseif( !empty($wp_query->query_vars['post_type']) && $wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT ){
361
  $wp_query->query_vars['scope'] = 'all';
362
  if( $wp_query->query_vars['post_status'] == 'pending' ){
363
- $wp_query->query_vars['orderby'] = 'meta_value_num';
364
  $wp_query->query_vars['order'] = 'ASC';
365
- $wp_query->query_vars['meta_key'] = '_start_ts';
 
366
  }
367
  }
368
  }
138
  }else{
139
  if( get_option('dbem_cp_events_formats') && !post_password_required() ){
140
  $EM_Event = em_get_event($post);
141
+ //do a little check for preview mode and re-insert content from $post
142
+ if( !empty($_REQUEST['preview']) ){
143
+ //we don't do extra checks here because WP will have already done the work for us here...
144
+ $EM_Event->post_content = $post->post_content;
145
+ $EM_Event->post_content_filtered = $post->post_content_filtered;
146
+ }
147
  ob_start();
148
  em_locate_template('templates/event-single.php',true);
149
  $content = ob_get_clean();
164
  if( $post->post_type == EM_POST_TYPE_EVENT ){
165
  $EM_Event = em_get_event($post);
166
  if ( '' == $d ){
167
+ $the_date = $EM_Event->start()->i18n(get_option('date_format'));
168
  }else{
169
+ $the_date = $EM_Event->start()->i18n($d);
170
  }
171
  }
172
  return $the_date;
177
  if( $post->post_type == EM_POST_TYPE_EVENT ){
178
  $EM_Event = em_get_event($post);
179
  if ( '' == $f ){
180
+ $the_time = $EM_Event->start()->i18n(get_option('time_format'));
181
  }else{
182
+ $the_time = $EM_Event->start()->i18n($f);
183
  }
184
  }
185
  return $the_time;
271
  $scope = $wp_query->query_vars['scope'];
272
  }
273
  }
274
+ if ( $scope == 'today' || $scope == 'tomorrow' || preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
275
+ $EM_DateTime = new EM_DateTime($scope); //create default time in blog timezone
 
 
276
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
277
+ $query[] = array( 'key' => '_event_start_date', 'value' => $EM_DateTime->getDate() );
278
  }else{
279
+ $query[] = array( 'key' => '_event_start_date', 'value' => $EM_DateTime->getDate(), 'compare' => '<=', 'type' => 'DATE' );
280
+ $query[] = array( 'key' => '_event_end_date', 'value' => $EM_DateTime->getDate(), 'compare' => '>=', 'type' => 'DATE' );
281
  }
282
+ }elseif ($scope == "future" || $scope == 'past' ){
283
+ $EM_DateTime = new EM_DateTime(); //create default time in blog timezone
284
+ $EM_DateTime->setTimezone('UTC');
285
+ $compare = $scope == 'future' ? '>=' : '<';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
287
+ $query[] = array( 'key' => '_event_start', 'value' => $EM_DateTime->getDateTime(), 'compare' => $compare, 'type' => 'DATETIME' );
288
  }else{
289
+ $query[] = array( 'key' => '_event_end', 'value' => $EM_DateTime->getDateTime(), 'compare' => $compare, 'type' => 'DATETIME' );
 
290
  }
291
+ }elseif ($scope == "month" || $scope == "next-month" ){
292
+ $EM_DateTime = new EM_DateTime(); //create default time in blog timezone
293
+ if( $scope == 'next-month' ) $EM_DateTime->add('P1M');
294
+ $start_month = $EM_DateTime->modify('first day of this month')->getDate();
295
+ $end_month = $EM_DateTime->modify('last day of this month')->getDate();
296
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
297
+ $query[] = array( 'key' => '_event_start_date', 'value' => array($start_month,$end_month), 'type' => 'DATE', 'compare' => 'BETWEEN');
298
  }else{
299
+ $query[] = array( 'key' => '_event_start_date', 'value' => $end_month, 'compare' => '<=', 'type' => 'DATE' );
300
+ $query[] = array( 'key' => '_event_end_date', 'value' => $start_month, 'compare' => '>=', 'type' => 'DATE' );
301
  }
302
  }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
303
+ $EM_DateTime = new EM_DateTime(); //create default time in blog timezone
304
  $months_to_add = $matches[1];
305
+ $start_month = $EM_DateTime->getDate();
306
+ $end_month = $EM_DateTime->add('P'.$months_to_add.'M')->format('Y-m-t');
307
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
308
+ $query[] = array( 'key' => '_event_start_date', 'value' => array($start_month,$end_month), 'type' => 'DATE', 'compare' => 'BETWEEN');
309
  }else{
310
+ $query[] = array( 'key' => '_event_start_date', 'value' => $end_month, 'compare' => '<=', 'type' => 'DATE' );
311
+ $query[] = array( 'key' => '_event_end_date', 'value' => $start_month, 'compare' => '>=', 'type' => 'DATE' );
312
  }
313
+ }elseif( !empty($scope) ){
314
+ $query = apply_filters('em_event_post_scope_meta_query', $query, $scope);
315
  }
316
  if( !empty($query) && is_array($query) ){
317
  $wp_query->query_vars['meta_query'] = $query;
318
  }
319
  if( is_admin() ){
320
  //admin areas don't need special ordering, so make it simple
321
+ if( !empty($_REQUEST['orderby']) && $_REQUEST['orderby'] != 'date-time' ){
322
+ $wp_query->query_vars['orderby'] = $_REQUEST['orderby'];
323
+ }else{
324
+ $wp_query->query_vars['orderby'] = 'meta_value';
325
+ $wp_query->query_vars['meta_key'] = '_event_start_local';
326
+ $wp_query->query_vars['meta_type'] = 'DATETIME';
327
+ }
328
  $wp_query->query_vars['order'] = (!empty($_REQUEST['order'])) ? $_REQUEST['order']:'ASC';
329
  }else{
330
  if( get_option('dbem_events_default_archive_orderby') == 'title'){
331
  $wp_query->query_vars['orderby'] = 'title';
332
  $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_order','ASC');
333
  }else{
334
+ $wp_query->query_vars['orderby'] = 'meta_value';
335
+ $wp_query->query_vars['meta_key'] = '_event_start_local';
336
+ $wp_query->query_vars['meta_type'] = 'DATETIME';
337
  }
338
  $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_order','ASC');
339
  }
340
  }elseif( !empty($wp_query->query_vars['post_type']) && $wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT ){
341
  $wp_query->query_vars['scope'] = 'all';
342
  if( $wp_query->query_vars['post_status'] == 'pending' ){
343
+ $wp_query->query_vars['orderby'] = 'meta_value';
344
  $wp_query->query_vars['order'] = 'ASC';
345
+ $wp_query->query_vars['meta_key'] = '_event_start_local';
346
+ $wp_query->query_vars['meta_type'] = 'DATETIME';
347
  }
348
  }
349
  }
classes/em-event-posts-admin.php CHANGED
@@ -68,7 +68,7 @@ class EM_Event_Posts_Admin{
68
  if( !empty($_REQUEST['recurrence_id']) && is_numeric($_REQUEST['recurrence_id']) ){
69
  $EM_Event = em_get_event($_REQUEST['recurrence_id']);
70
  ?>
71
- <div class="updated">
72
  <p><?php echo sprintf(esc_html__('You are viewing individual recurrences of recurring event %s.', 'events-manager'), '<a href="'.$EM_Event->get_edit_url().'">'.$EM_Event->event_name.'</a>'); ?></p>
73
  <p><?php esc_html_e('You can edit individual recurrences and disassociate them with this recurring event.', 'events-manager'); ?></p>
74
  </div>
@@ -224,16 +224,17 @@ class EM_Event_Posts_Admin{
224
  break;
225
  case 'date-time':
226
  //get meta value to see if post has location, otherwise
227
- $localised_start_date = date_i18n(get_option('date_format'), $EM_Event->start);
228
- $localised_end_date = date_i18n(get_option('date_format'), $EM_Event->end);
229
  echo $localised_start_date;
230
  echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'';
231
  echo "<br />";
232
  if(!$EM_Event->event_all_day){
233
- echo date_i18n(get_option('time_format'), $EM_Event->start) . " - " . date_i18n(get_option('time_format'), $EM_Event->end);
234
  }else{
235
  echo get_option('dbem_event_all_day_message');
236
  }
 
237
  break;
238
  case 'extra':
239
  if( get_option('dbem_rsvp_enabled') == 1 && !empty($EM_Event->event_rsvp) && $EM_Event->can_manage('manage_bookings','manage_others_bookings')){
@@ -308,7 +309,7 @@ class EM_Event_Recurring_Posts_Admin{
308
 
309
  public static function admin_notices(){
310
  ?>
311
- <div class="updated">
312
  <p><?php esc_html_e( 'Modifications to recurring events will be applied to all recurrences and will overwrite any changes made to those individual event recurrences.', 'events-manager'); ?></p>
313
  <p><?php esc_html_e( 'Bookings to individual event recurrences will be preserved if event times and ticket settings are not modified.', 'events-manager'); ?></p>
314
  <p>
68
  if( !empty($_REQUEST['recurrence_id']) && is_numeric($_REQUEST['recurrence_id']) ){
69
  $EM_Event = em_get_event($_REQUEST['recurrence_id']);
70
  ?>
71
+ <div class="notice notice-info">
72
  <p><?php echo sprintf(esc_html__('You are viewing individual recurrences of recurring event %s.', 'events-manager'), '<a href="'.$EM_Event->get_edit_url().'">'.$EM_Event->event_name.'</a>'); ?></p>
73
  <p><?php esc_html_e('You can edit individual recurrences and disassociate them with this recurring event.', 'events-manager'); ?></p>
74
  </div>
224
  break;
225
  case 'date-time':
226
  //get meta value to see if post has location, otherwise
227
+ $localised_start_date = $EM_Event->start()->i18n(get_option('date_format'));
228
+ $localised_end_date = $EM_Event->end()->i18n(get_option('date_format'));
229
  echo $localised_start_date;
230
  echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'';
231
  echo "<br />";
232
  if(!$EM_Event->event_all_day){
233
+ echo $EM_Event->start()->i18n(get_option('time_format')) . " - " . $EM_Event->end()->i18n(get_option('time_format'));
234
  }else{
235
  echo get_option('dbem_event_all_day_message');
236
  }
237
+ if( $EM_Event->get_timezone()->getName() != EM_DateTimeZone::create()->getName() ) echo '<span class="dashicons dashicons-info" style="font-size:16px; color:#ccc; padding-top:2px;" title="'.esc_attr(str_replace('_', ' ', $EM_Event->event_timezone)).'"></span>';
238
  break;
239
  case 'extra':
240
  if( get_option('dbem_rsvp_enabled') == 1 && !empty($EM_Event->event_rsvp) && $EM_Event->can_manage('manage_bookings','manage_others_bookings')){
309
 
310
  public static function admin_notices(){
311
  ?>
312
+ <div class="notice notice-info">
313
  <p><?php esc_html_e( 'Modifications to recurring events will be applied to all recurrences and will overwrite any changes made to those individual event recurrences.', 'events-manager'); ?></p>
314
  <p><?php esc_html_e( 'Bookings to individual event recurrences will be preserved if event times and ticket settings are not modified.', 'events-manager'); ?></p>
315
  <p>
classes/em-event.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
  /**
3
  * Get an event in a db friendly way, by checking globals, cache and passed variables to avoid extra class instantiations.
4
- * @param mixed $id
5
- * @param mixed $search_by
6
  * @return EM_Event
7
  */
8
  function em_get_event($id = false, $search_by = 'event_id') {
@@ -61,15 +61,56 @@ class EM_Event extends EM_Object{
61
  var $event_slug;
62
  var $event_owner;
63
  var $event_name;
64
- var $event_start_time = '00:00:00';
65
- var $event_end_time = '00:00:00';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  var $event_all_day;
67
- var $event_start_date;
68
- var $event_end_date;
 
 
 
69
  var $post_content;
70
  var $event_rsvp = 0;
71
- var $event_rsvp_date;
72
- var $event_rsvp_time = "00:00:00";
73
  var $event_rsvp_spaces;
74
  var $event_spaces;
75
  var $event_private;
@@ -105,8 +146,11 @@ class EM_Event extends EM_Object{
105
  'event_slug' => array( 'name'=>'slug', 'type'=>'%s', 'null'=>true ),
106
  'event_owner' => array( 'name'=>'owner', 'type'=>'%d', 'null'=>true ),
107
  'event_name' => array( 'name'=>'name', 'type'=>'%s', 'null'=>true ),
 
108
  'event_start_time' => array( 'name'=>'start_time', 'type'=>'%s', 'null'=>true ),
109
  'event_end_time' => array( 'name'=>'end_time', 'type'=>'%s', 'null'=>true ),
 
 
110
  'event_all_day' => array( 'name'=>'all_day', 'type'=>'%d', 'null'=>true ),
111
  'event_start_date' => array( 'name'=>'start_date', 'type'=>'%s', 'null'=>true ),
112
  'event_end_date' => array( 'name'=>'end_date', 'type'=>'%s', 'null'=>true ),
@@ -135,30 +179,24 @@ class EM_Event extends EM_Object{
135
 
136
  var $image_url = '';
137
  /**
138
- * Timestamp of start date/time
139
- * @var int
 
 
140
  */
141
- var $start;
142
  /**
143
- * Timestamp of end date/time
144
- * @var int
 
 
145
  */
146
- var $end;
147
  /**
148
  * Timestamp for booking cut-off date/time
149
- * @var int
150
- */
151
- var $rsvp_end;
152
- /**
153
- * Created on timestamp, taken from DB, converted to TS
154
- * @var int
155
  */
156
- var $created;
157
- /**
158
- * Created on timestamp, taken from DB, converted to TS
159
- * @var int
160
- */
161
- var $modified;
162
 
163
  /**
164
  * @var EM_Location
@@ -174,10 +212,15 @@ class EM_Event extends EM_Object{
174
  */
175
  var $contact;
176
  /**
177
- * The category object
178
- * @var EM_Category
 
 
 
 
 
179
  */
180
- var $category;
181
  /**
182
  * If there are any errors, they will be added here.
183
  * @var array
@@ -256,7 +299,7 @@ class EM_Event extends EM_Object{
256
  /**
257
  * Initialize an event. You can provide event data in an associative array (using database table field names), an id number, or false (default) to create empty event.
258
  * @param mixed $event_data
259
- * @param mixed $search_by default is post_id, otherwise it can be by event_id as well.
260
  * @return null
261
  */
262
  function __construct($id = false, $search_by = 'event_id') {
@@ -304,6 +347,17 @@ class EM_Event extends EM_Object{
304
  }
305
  $this->load_postdata($event_post, $search_by);
306
  }
 
 
 
 
 
 
 
 
 
 
 
307
  $this->recurrence = $this->is_recurring() ? 1:0;
308
  //Do it here so things appear in the po file.
309
  $this->status_array = array(
@@ -318,6 +372,70 @@ class EM_Event extends EM_Object{
318
  do_action('em_event', $this, $id, $search_by);
319
  }
320
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  /**
322
  * When cloning this event, we get rid of the bookings and location objects, since they can be retrieved again from the cache instead.
323
  */
@@ -356,12 +474,6 @@ class EM_Event extends EM_Object{
356
  }
357
  }
358
  }
359
- //Start/End times should be available as timestamp
360
- $this->start = strtotime($this->event_start_date." ".$this->event_start_time, current_time('timestamp'));
361
- $this->end = strtotime($this->event_end_date." ".$this->event_end_time, current_time('timestamp'));
362
- if( !empty($this->event_rsvp_date ) ){
363
- $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp'));
364
- }
365
  //quick compatability fix in case _event_id isn't loaded or somehow got erased in post meta
366
  if( empty($this->event_id) && !$this->is_recurring() ){
367
  global $wpdb;
@@ -403,9 +515,6 @@ class EM_Event extends EM_Object{
403
  $this->post_id = $this->ID = $event_array['post_id'] = null; //reset post_id because it doesn't really exist
404
  $this->to_object($event_array);
405
  }
406
- //Start/End times should be available as timestamp
407
- $this->start = strtotime($this->event_start_date." ".$this->event_start_time, current_time('timestamp'));
408
- $this->end = strtotime($this->event_end_date." ".$this->event_end_time, current_time('timestamp'));
409
  }
410
  if( empty($this->location_id) && !empty($this->event_id) ) $this->location_id = 0; //just set location_id to 0 and avoid any doubt
411
  if( EM_MS_GLOBAL && empty($this->blog_id) ) $this->blog_id = get_current_site()->blog_id; //events created before going multisite may have null values, so we set it to main site id
@@ -440,7 +549,7 @@ class EM_Event extends EM_Object{
440
  //we need to get the post/event name and content.... that's it.
441
  $this->post_content = isset($_POST['content']) ? wp_kses( wp_unslash($_POST['content']), $allowedposttags):'';
442
  $this->post_excerpt = !empty($this->post_excerpt) ? $this->post_excerpt:''; //fix null error
443
- $this->event_name = !empty($_POST['event_name']) ? htmlspecialchars_decode(wp_kses_data(htmlspecialchars_decode(wp_unslash($_POST['event_name'])))):'';
444
  $this->post_type = ($this->is_recurring() || !empty($_POST['recurring'])) ? 'event-recurring':EM_POST_TYPE_EVENT;
445
  //don't forget categories!
446
  if( get_option('dbem_categories_enabled') ) $this->get_categories()->get_post();
@@ -468,11 +577,17 @@ class EM_Event extends EM_Object{
468
  $this->recurrence = 1;
469
  $this->post_type = 'event-recurring';
470
  }
471
-
 
 
 
 
 
472
  //Dates and Times - dates ignored if event is recurring being updated (not new) and not specifically chosen to reschedule event
 
473
  if( !$this->is_recurring() || (empty($this->event_id) || !empty($_REQUEST['event_reschedule'])) ){
474
  //Event Dates
475
- $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? wp_kses_data($_POST['event_start_date']) : '';
476
  $this->event_end_date = ( !empty($_POST['event_end_date']) ) ? wp_kses_data($_POST['event_end_date']) : $this->event_start_date;
477
  }
478
  //Sort out time
@@ -499,9 +614,8 @@ class EM_Event extends EM_Object{
499
  $this->$timeName = ($timeName == 'event_start_time') ? "00:00:00":$this->event_start_time;
500
  }
501
  }
502
- //Start/End times should be available as timestamp
503
- $this->start = strtotime($this->event_start_date." ".$this->event_start_time);
504
- $this->end = strtotime($this->event_end_date." ".$this->event_end_time);
505
 
506
  //Get Location info
507
  if( !get_option('dbem_locations_enabled') || (!empty($_POST['no_location']) && !get_option('dbem_require_location',true)) || (empty($_POST['location_id']) && !get_option('dbem_require_location',true) && get_option('dbem_use_select_for_locations')) ){
@@ -524,15 +638,15 @@ class EM_Event extends EM_Object{
524
  $this->get_bookings()->get_tickets()->get_post();
525
  }
526
  $this->event_rsvp = 1;
527
- //RSVP cuttoff TIME is set up above where start/end times are as well
528
- if( !$this->is_recurring() ){
529
  if( get_option('dbem_bookings_tickets_single') && count($this->get_tickets()->tickets) == 1 ){
530
  //single ticket mode will use the ticket end date/time as cut-off date/time
531
  $EM_Ticket = $this->get_tickets()->get_first();
532
- $this->event_rsvp_date = '';
533
- if( !empty($EM_Ticket->end_timestamp) ){
534
- $this->event_rsvp_date = date('Y-m-d', $EM_Ticket->end_timestamp);
535
- $this->event_rsvp_time = date('H:i:00', $EM_Ticket->end_timestamp);
536
  }else{
537
  //no default ticket end time, so make it default to event start date/time
538
  $this->event_rsvp_date = $this->event_start_date;
@@ -542,53 +656,17 @@ class EM_Event extends EM_Object{
542
  }else{
543
  //if no rsvp cut-off date supplied, make it the event start date
544
  $this->event_rsvp_date = ( !empty($_POST['event_rsvp_date']) ) ? wp_kses_data($_POST['event_rsvp_date']) : $this->event_start_date;
545
- if ( empty($_POST['event_rsvp_date']) ) $this->event_rsvp_time = $this->event_start_time;
546
  if( $this->event_all_day && empty($_POST['event_rsvp_date']) ){ $this->event_rsvp_time = '00:00:00'; } //all-day events start at 0 hour
547
  }
548
- //create timestamp
549
- if( empty($this->event_rsvp_date) ){
550
- //falback in case nothing gets set for rsvp cut-off
551
- $this->event_rsvp_time = '00:00:00';
552
- $this->rsvp_end = 0; //empty value but timestamp compatible
553
- }else{
554
- $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp'));
555
- }
556
- }else{
557
- //recurring events may have a cut-off date x days before or after the recurrence start dates
558
- $this->recurrence_rsvp_days = null;
559
- if( get_option('dbem_bookings_tickets_single') && count($this->get_tickets()->tickets) == 1 ){
560
- //if in single ticket mode then ticket cut-off date determines event cut-off date
561
- $EM_Ticket = $this->get_tickets()->get_first();
562
- if( !empty($EM_Ticket->ticket_meta['recurrences']) ){
563
- $this->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days'];
564
- $this->event_rsvp_time = $EM_Ticket->ticket_meta['recurrences']['end_time'];
565
- }
566
- }else{
567
- if( array_key_exists('recurrence_rsvp_days', $_POST) ){
568
- if( !empty($_POST['recurrence_rsvp_days_when']) && $_POST['recurrence_rsvp_days_when'] == 'after' ){
569
- $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']);
570
- }else{ //by default the start date is the point of reference
571
- $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']) * -1;
572
- }
573
- }
574
- }
575
- //create timestamps and set rsvp date/time for a normal event
576
- if( !is_numeric($this->recurrence_rsvp_days) ){
577
- //falback in case nothing gets set for rsvp cut-off
578
- $this->event_rsvp_date = '';
579
- $this->event_rsvp_time = '00:00:00';
580
- $this->rsvp_end = 0; //empty value but timestamp compatible
581
- }else{
582
- $this->event_rsvp_date = date('Y-m-d', strtotime($this->recurrence_rsvp_days.' days', $this->start));
583
- $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp'));
584
- }
585
- }
586
  $this->event_spaces = ( isset($_POST['event_spaces']) ) ? absint($_POST['event_spaces']):0;
587
  $this->event_rsvp_spaces = ( isset($_POST['event_rsvp_spaces']) ) ? absint($_POST['event_rsvp_spaces']):0;
588
  }elseif( !$preview_autosave && ($can_manage_bookings || !$this->event_rsvp) ){
589
  if( empty($_POST['event_rsvp']) && $this->event_rsvp ) $deleting_bookings = true;
590
  $this->event_rsvp = 0;
591
- $this->event_rsvp_time = null;
592
  }
593
 
594
  //Sort out event attributes - note that custom post meta now also gets inserted here automatically (and is overwritten by these attributes)
@@ -692,6 +770,31 @@ class EM_Event extends EM_Object{
692
  //new event so we create everything from scratch
693
  $this->recurring_reschedule = $this->recurring_recreate_bookings = true;
694
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
695
  }else{
696
  foreach( $this->recurrence_fields as $recurrence_field ){
697
  $this->$recurrence_field = null;
@@ -737,9 +840,9 @@ class EM_Event extends EM_Object{
737
  }
738
  }
739
  if( preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_start_date) && preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_end_date) ){
740
- if( strtotime($this->event_start_date . $this->event_start_time) > strtotime($this->event_end_date . $this->event_end_time) ){
741
  $this->add_error(__('Events cannot start after they end.','events-manager'));
742
- }elseif( $this->is_recurring() && $this->recurrence_days == 0 && strtotime($this->event_start_date . $this->event_start_time) > strtotime($this->event_start_date . $this->event_end_time) ){
743
  $this->add_error(__('Events cannot start after they end.','events-manager').' '.__('For recurring events that end the following day, ensure you make your event last 1 or more days.'));
744
  }
745
  }else{
@@ -804,7 +907,7 @@ class EM_Event extends EM_Object{
804
  //Overwrite new post info
805
  $post_array['post_type'] = ($this->recurrence && get_option('dbem_recurrence_enabled')) ? 'event-recurring':EM_POST_TYPE_EVENT;
806
  $post_array['post_title'] = $this->event_name;
807
- $post_array['post_content'] = $this->post_content;
808
  $post_array['post_excerpt'] = $this->post_excerpt;
809
  //decide on post status
810
  if( empty($this->force_status) ){
@@ -863,6 +966,14 @@ class EM_Event extends EM_Object{
863
  }
864
  $return = apply_filters('em_event_save', $result, $this);
865
  $EM_SAVING_EVENT = false;
 
 
 
 
 
 
 
 
866
  return $return;
867
  }
868
 
@@ -895,8 +1006,7 @@ class EM_Event extends EM_Object{
895
  if( !in_array($key, $this->post_fields) && $key != 'event_attributes' ){
896
  //ignore certain fields and delete if not new
897
  $save_meta_key = true;
898
- $recurrence_array = array('recurrence', 'recurrence_interval', 'recurrence_freq', 'recurrence_days', 'recurrence_byday', 'recurrence_byweekno', 'recurrence_rsvp_days');
899
- if( !$this->is_recurring() && in_array($key, $recurrence_array) ) $save_meta_key = false;
900
  if( !$this->is_recurrence() && $key == 'recurrence_id' ) $save_meta_key = false;
901
  $ignore_zero_keys = array('location_id', 'group_id', 'event_all_day' );
902
  if( in_array($key, $ignore_zero_keys) && empty($this->$key) ) $save_meta_key = false;
@@ -926,9 +1036,15 @@ class EM_Event extends EM_Object{
926
  }
927
  }
928
  }
929
- //update timestampes
930
- update_post_meta($this->post_id, '_start_ts', str_pad($this->start, 10, 0, STR_PAD_LEFT));
931
- update_post_meta($this->post_id, '_end_ts', str_pad($this->end, 10, 0, STR_PAD_LEFT));
 
 
 
 
 
 
932
  //sort out event status
933
  $result = count($this->errors) == 0;
934
  $this->get_status();
@@ -969,6 +1085,7 @@ class EM_Event extends EM_Object{
969
  update_post_meta($this->post_id, '_event_id', $this->event_id);
970
  $this->feedback_message = sprintf(__('Successfully saved %s','events-manager'),__('Event','events-manager'));
971
  $this->just_added_event = true; //make an easy hook
 
972
  do_action('em_event_save_new', $this);
973
  }
974
  }else{
@@ -993,8 +1110,10 @@ class EM_Event extends EM_Object{
993
  }
994
  //Add/Delete Tickets
995
  if($this->event_rsvp == 0){
996
- $this->get_bookings()->delete();
997
- $this->get_tickets()->delete();
 
 
998
  }elseif( $this->can_manage('manage_bookings','manage_others_bookings') ){
999
  if( !$this->get_bookings()->get_tickets()->save() ){
1000
  $this->add_error( $this->get_bookings()->get_tickets()->get_errors() );
@@ -1025,13 +1144,7 @@ class EM_Event extends EM_Object{
1025
  do_action('em_event_added', $this);
1026
  }
1027
  }
1028
- $result = count($this->errors) == 0;
1029
- //add this event to the cache
1030
- if( $result ){
1031
- wp_cache_set($this->event_id, $this, 'em_events');
1032
- wp_cache_set($this->post_id, $this->event_id, 'em_events_ids');
1033
- }
1034
- return apply_filters('em_event_save_meta', $result, $this);
1035
  }
1036
 
1037
  /**
@@ -1076,9 +1189,8 @@ class EM_Event extends EM_Object{
1076
  //Get custom fields and post meta - adapted from $this->load_post_meta()
1077
  foreach($event_meta as $event_meta_key => $event_meta_vals){
1078
  if( $event_meta_key == '_wpas_' ) continue; //allow JetPack Publicize to detect this as a new post when published
1079
- if($event_meta_key[0] == '_' && is_array($event_meta_vals)){
1080
- $field_name = substr($event_meta_key, 1);
1081
- if($field_name != 'event_attributes' && !array_key_exists($event_meta_key, $new_event_meta) && !in_array($field_name, array('edit_last', 'edit_lock', 'event_owner_name','event_owner_anonymous','event_owner_email')) ){
1082
  foreach($event_meta_vals as $event_meta_val){
1083
  $event_meta_inserts[] = "({$EM_Event->post_id}, '{$event_meta_key}', '{$event_meta_val}')";
1084
  }
@@ -1222,7 +1334,8 @@ class EM_Event extends EM_Object{
1222
  $post_status = $set_status ? 'publish':'pending';
1223
  if( empty($this->post_name) ){
1224
  //published or pending posts should have a valid post slug
1225
- $this->post_name = sanitize_title($this->post_title);
 
1226
  $set_post_name = true;
1227
  }
1228
  if($set_post_status){
@@ -1240,10 +1353,111 @@ class EM_Event extends EM_Object{
1240
  return apply_filters('em_event_set_status', $result !== false, $status, $this);
1241
  }
1242
 
 
 
 
 
 
 
 
 
 
 
 
 
1243
  function is_published(){
1244
  return apply_filters('em_event_is_published', ($this->post_status == 'publish' || $this->post_status == 'private'), $this);
1245
  }
1246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1247
  function get_status($db = false){
1248
  switch( $this->post_status ){
1249
  case 'private':
@@ -1497,23 +1711,24 @@ class EM_Event extends EM_Object{
1497
  */
1498
  function output($format, $target="html") {
1499
  global $wpdb;
1500
- $format = do_shortcode($format); //parse shortcode first, so that formats within shortcodes are parsed properly
1501
  $event_string = $format;
1502
  //Time place holder that doesn't show if empty.
1503
  //TODO add filter here too
1504
  preg_match_all('/#@?_\{[^}]+\}/', $format, $results);
1505
  foreach($results[0] as $result) {
1506
  if(substr($result, 0, 3 ) == "#@_"){
1507
- $date = 'end_date';
1508
  $offset = 4;
1509
  }else{
1510
- $date = 'start_date';
1511
  $offset = 3;
1512
  }
1513
- if( $date == 'end_date' && $this->event_end_date == $this->event_start_date ){
1514
  $replace = __( apply_filters('em_event_output_placeholder', '', $this, $result, $target) );
1515
  }else{
1516
- $replace = __( apply_filters('em_event_output_placeholder', mysql2date(substr($result, $offset, (strlen($result)-($offset+1)) ), $this->$date), $this, $result, $target) );
 
1517
  }
1518
  $event_string = str_replace($result,$replace,$event_string );
1519
  }
@@ -1571,6 +1786,12 @@ class EM_Event extends EM_Object{
1571
  }elseif ($condition == 'no_time'){
1572
  //are the booking times exactly the same and it's not an all-day event.
1573
  $show_condition = ( $this->event_start_time == $this->event_end_time && !$this->event_all_day );
 
 
 
 
 
 
1574
  }elseif ($condition == 'all_day'){
1575
  //is it an all day event
1576
  $show_condition = !empty($this->event_all_day);
@@ -1607,17 +1828,16 @@ class EM_Event extends EM_Object{
1607
  }elseif ($condition == 'is_past'){
1608
  //if event is past
1609
  if( get_option('dbem_events_current_are_past') ){
1610
- $show_condition = $this->start <= current_time('timestamp');
1611
  }else{
1612
- $show_condition = $this->end <= current_time('timestamp');
1613
  }
1614
  }elseif ($condition == 'is_future'){
1615
  //if event is upcoming
1616
- $show_condition = $this->start > current_time('timestamp');
1617
  }elseif ($condition == 'is_current'){
1618
  //if event is currently happening
1619
- $ts = current_time('timestamp');
1620
- $show_condition = $this->start <= $ts && $this->end >= $ts;
1621
  }elseif ($condition == 'is_recurrence'){
1622
  //if event is a recurrence
1623
  $show_condition = $this->is_recurrence();
@@ -1765,13 +1985,11 @@ class EM_Event extends EM_Object{
1765
  //Times & Dates
1766
  case '#_24HSTARTTIME':
1767
  case '#_24HENDTIME':
1768
- $time = ($result == '#_24HSTARTTIME') ? $this->event_start_time:$this->event_end_time;
1769
- $replace = substr($time, 0,5);
1770
  break;
1771
  case '#_12HSTARTTIME':
1772
  case '#_12HENDTIME':
1773
- $time = ($result == '#_12HSTARTTIME') ? $this->event_start_time:$this->event_end_time;
1774
- $replace = date('g:i A', strtotime($time));
1775
  break;
1776
  case '#_EVENTTIMES':
1777
  //get format of time to show
@@ -1781,6 +1999,12 @@ class EM_Event extends EM_Object{
1781
  //get format of time to show
1782
  $replace = $this->output_dates();
1783
  break;
 
 
 
 
 
 
1784
  //Links
1785
  case '#_EVENTPAGEURL': //deprecated
1786
  case '#_LINKEDNAME': //deprecated
@@ -1928,11 +2152,11 @@ class EM_Event extends EM_Object{
1928
  case '#_BOOKINGSCUTOFFDATE':
1929
  case '#_BOOKINGSCUTOFFTIME':
1930
  $replace = '';
1931
- if ($this->event_rsvp && get_option('dbem_rsvp_enabled') && !empty($this->rsvp_end)) {
1932
- $replace_format = get_option('dbem_date_format').' '. get_option('dbem_time_format');
1933
- if( $result == '#_BOOKINGSCUTOFFDATE' ) $replace_format = get_option('dbem_date_format');
1934
- if( $result == '#_BOOKINGSCUTOFFTIME' ) $replace_format = get_option('dbem_time_format');
1935
- $replace = date($replace_format, $this->rsvp_end);
1936
  }
1937
  break;
1938
  //Contact Person
@@ -2034,20 +2258,21 @@ class EM_Event extends EM_Object{
2034
  case '#_EVENTGCALLINK':
2035
  //get dates in UTC/GMT time
2036
  if($this->event_all_day && $this->event_start_date == $this->event_end_date){
2037
- $dateStart = get_gmt_from_date(date('Y-m-d H:i:s', $this->start), 'Ymd');
2038
- $dateEnd = get_gmt_from_date(date('Y-m-d H:i:s', $this->start + 60*60*24), 'Ymd');
2039
  }else{
2040
- $dateStart = get_gmt_from_date(date('Y-m-d H:i:s', $this->start), 'Ymd\THis\Z');
2041
- $dateEnd = get_gmt_from_date(date('Y-m-d H:i:s', $this->end), 'Ymd\THis\Z');
2042
  }
2043
  //build url
2044
- $gcal_url = 'http://www.google.com/calendar/event?action=TEMPLATE&text=event_name&dates=start_date/end_date&details=post_content&location=location_name&trp=false&sprop=event_url&sprop=name:blog_name';
2045
  $gcal_url = str_replace('event_name', urlencode($this->event_name), $gcal_url);
2046
  $gcal_url = str_replace('start_date', urlencode($dateStart), $gcal_url);
2047
  $gcal_url = str_replace('end_date', urlencode($dateEnd), $gcal_url);
2048
  $gcal_url = str_replace('location_name', urlencode($this->output('#_LOCATION, #_LOCATIONADDRESS, #_LOCATIONCOUNTRY')), $gcal_url);
2049
  $gcal_url = str_replace('blog_name', urlencode(get_bloginfo()), $gcal_url);
2050
  $gcal_url = str_replace('event_url', urlencode($this->get_permalink()), $gcal_url);
 
2051
  //calculate URL length so we know how much we can work with to make a description.
2052
  if( !empty($this->post_excerpt) ){
2053
  $gcal_url_description = $this->post_excerpt;
@@ -2089,13 +2314,13 @@ class EM_Event extends EM_Object{
2089
  foreach($placeholders[1] as $result) {
2090
  // matches all PHP START date and time placeholders
2091
  if (preg_match('/^#[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) {
2092
- $replace = date_i18n(ltrim($result, "#"), $this->start);
2093
  $replace = apply_filters('em_event_output_placeholder', $replace, $this, $result, $target);
2094
  $event_string = str_replace($result, $replace, $event_string );
2095
  }
2096
  // matches all PHP END time placeholders for endtime
2097
  if (preg_match('/^#@[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) {
2098
- $replace = date_i18n(ltrim($result, "#@"), $this->end);
2099
  $replace = apply_filters('em_event_output_placeholder', $replace, $this, $result, $target);
2100
  $event_string = str_replace($result, $replace, $event_string );
2101
  }
@@ -2140,13 +2365,14 @@ class EM_Event extends EM_Object{
2140
  return apply_filters('em_event_output', $event_string, $this, $format, $target);
2141
  }
2142
 
2143
- function output_times(){
2144
  if( !$this->event_all_day ){
2145
- $time_format = ( get_option('dbem_time_format') ) ? get_option('dbem_time_format'):get_option('time_format');
2146
- if($this->event_start_time != $this->event_end_time ){
2147
- $replace = date_i18n($time_format, $this->start). get_option('dbem_times_separator') . date_i18n($time_format, $this->end);
 
2148
  }else{
2149
- $replace = date_i18n($time_format, $this->start);
2150
  }
2151
  }else{
2152
  $replace = get_option('dbem_event_all_day_message');
@@ -2154,12 +2380,13 @@ class EM_Event extends EM_Object{
2154
  return $replace;
2155
  }
2156
 
2157
- function output_dates(){
2158
- $date_format = ( get_option('dbem_date_format') ) ? get_option('dbem_date_format'):get_option('date_format');
 
2159
  if( $this->event_start_date != $this->event_end_date){
2160
- $replace = date_i18n($date_format, $this->start). get_option('dbem_dates_separator') . date_i18n($date_format, $this->end);
2161
  }else{
2162
- $replace = date_i18n($date_format, $this->start);
2163
  }
2164
  return $replace;
2165
  }
@@ -2282,7 +2509,7 @@ class EM_Event extends EM_Object{
2282
  //remove recurrence meta info we won't need in events
2283
  foreach( $this->recurrence_fields as $recurrence_field){
2284
  $event[$recurrence_field] = null;
2285
- unset($meta_fields['_'.$recurrence_field]);
2286
  }
2287
  //Set the recurrence ID
2288
  $event['recurrence_id'] = $meta_fields['_recurrence_id'] = $this->event_id;
@@ -2299,26 +2526,49 @@ class EM_Event extends EM_Object{
2299
  unset($event['event_date_modified']);
2300
  if( count($matching_days) > 0 ){
2301
  //first save event post data
 
2302
  foreach( $matching_days as $day ) {
 
 
 
2303
  //rewrite post fields if needed
2304
- $post_fields['post_name'] = $event['event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.date($recurring_date_format, $day), $post_fields, $day, $matching_days, $this);
2305
- //adjust certain meta information
2306
- $event['event_start_date'] = $meta_fields['_event_start_date'] = date("Y-m-d", $day);
2307
- $meta_fields['_start_ts'] = strtotime($event['event_start_date'].' '.$event['event_start_time']);
 
2308
  if( !empty($this->recurrence_rsvp_days) && is_numeric($this->recurrence_rsvp_days) ){
2309
- $event_rsvp_days = $this->recurrence_rsvp_days >= 0 ? '+'. $this->recurrence_rsvp_days: $this->recurrence_rsvp_days;
2310
- $event_rsvp_date = date('Y-m-d', strtotime($event_rsvp_days.' days', $meta_fields['_start_ts']));
 
 
 
 
 
2311
  $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date;
2312
  }else{
2313
  $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event['event_start_date'];
2314
  }
2315
  $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
 
 
2316
  if($this->recurrence_days > 0){
2317
- $event['event_end_date'] = $meta_fields['_event_end_date'] = date("Y-m-d", $meta_fields['_start_ts'] + ($this->recurrence_days * 60*60*24));
 
2318
  }else{
2319
  $event['event_end_date'] = $meta_fields['_event_end_date'] = $event['event_start_date'];
2320
- }
2321
- $meta_fields['_end_ts'] = strtotime($event['event_end_date'].' '.$event['event_end_time']);
 
 
 
 
 
 
 
 
 
 
2322
  //create the event
2323
  if( $wpdb->insert($wpdb->posts, $post_fields ) ){
2324
  $event['post_id'] = $post_id = $post_ids[] = $wpdb->insert_id; //post id saved into event and also as a var for later user
@@ -2327,7 +2577,7 @@ class EM_Event extends EM_Object{
2327
  //insert into events index table
2328
  $event_saves[] = $wpdb->insert(EM_EVENTS_TABLE, $event);
2329
  $event_ids[$post_id] = $event_id = $wpdb->insert_id;
2330
- $event_dates[$event_id] = $meta_fields['_start_ts'];
2331
  //create the meta inserts for each event
2332
  $meta_fields['_event_id'] = $event_id;
2333
  foreach($meta_fields as $meta_key => $meta_val){
@@ -2357,34 +2607,45 @@ class EM_Event extends EM_Object{
2357
  $event['event_date_modified'] = current_time('mysql'); //since the recurrences are modified but not recreated
2358
  unset( $post_fields['comment_count'], $post_fields['guid'], $post_fields['menu_order']);
2359
  //now we go through the recurrences and check whether things relative to dates need to be changed
2360
- //@todo do a direct DB lookup once we have timezones implemented to save processing and memory
2361
- $EM_Events = EM_Events::get( array('recurrence'=>$this->event_id, 'scope'=>'all', 'status'=>'everything' ) );
2362
- foreach($EM_Events as $EM_Event){ /* @var $EM_Event EM_Event */
2363
- $event_ids[$EM_Event->post_id] = $EM_Event->event_id;
2364
- $event_dates[$EM_Event->event_id] = $EM_Event->start;
2365
- $post_ids[] = $EM_Event->post_id;
 
 
 
 
 
 
2366
  //do we need to change the slugs?
2367
- $post_fields['post_name'] = $event['event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.date($recurring_date_format, $EM_Event->start), $post_fields, $EM_Event->start, array(), $this);
2368
- //adjust certain meta information relativv
2369
  if( !empty($this->recurrence_rsvp_days) && is_numeric($this->recurrence_rsvp_days) ){
2370
  $event_rsvp_days = $this->recurrence_rsvp_days >= 0 ? '+'. $this->recurrence_rsvp_days: $this->recurrence_rsvp_days;
2371
- $event_rsvp_date = date('Y-m-d', strtotime($event_rsvp_days.' days', $EM_Event->start));
2372
  $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date;
2373
  }else{
2374
- $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $EM_Event->event_start_date;
2375
  }
2376
  $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
2377
  //add meta fields we deleted and are specific to this event
2378
- $meta_fields['_event_start_date'] = $EM_Event->event_start_date;
2379
- $meta_fields['_event_end_date'] = $EM_Event->event_end_date;
2380
- $meta_fields['_start_ts'] = strtotime($EM_Event->event_start_date." ".$this->event_start_time);
2381
- $meta_fields['_end_ts'] = strtotime($EM_Event->event_end_date." ".$this->event_end_time);
 
 
 
 
 
2382
  //overwrite event and post tables
2383
- $wpdb->update(EM_EVENTS_TABLE, $event, array('event_id' => $EM_Event->event_id));
2384
- $wpdb->update($wpdb->posts, $post_fields, array('ID' => $EM_Event->post_id));
2385
  //save meta field data for insertion in one go
2386
  foreach($meta_fields as $meta_key => $meta_val){
2387
- $meta_inserts[] = $wpdb->prepare("(%d, %s, %s)", array($EM_Event->post_id, $meta_key, $meta_val));
2388
  }
2389
  }
2390
  //delete all meta
@@ -2403,11 +2664,15 @@ class EM_Event extends EM_Object{
2403
  if( $this->recurring_reschedule || $this->recurring_recreate_bookings ){
2404
  //first, delete all bookings & tickets if we haven't done so during the reschedule above - something we'll want to change later if possible so bookings can be modified without losing all data
2405
  if( !$this->recurring_reschedule ){
2406
- foreach($EM_Events as $EM_Event){ //$EM_Events was defined in the else statement above so we reuse it
2407
- /* @var $EM_Event EM_Event */
2408
- if($EM_Event->recurrence_id == $this->event_id){
2409
- $EM_Event->get_bookings()->delete();
2410
- $EM_Event->get_tickets()->delete();
 
 
 
 
2411
  }
2412
  }
2413
  }
@@ -2436,19 +2701,23 @@ class EM_Event extends EM_Object{
2436
  $ticket[$k] = $wpdb->prepare($data_type,$v);
2437
  }
2438
  }
 
 
2439
  foreach($event_ids as $event_id){
2440
  $ticket['event_id'] = $event_id;
2441
  $ticket['ticket_start'] = $ticket['ticket_end'] = 'NULL';
2442
  //sort out cut-of dates
2443
  if( !empty($ticket_meta_recurrences) ){
 
2444
  if( array_key_exists('start_days', $ticket_meta_recurrences) && $ticket_meta_recurrences['start_days'] !== false ){
2445
  $ticket_start_days = $ticket_meta_recurrences['start_days'] >= 0 ? '+'. $ticket_meta_recurrences['start_days']: $ticket_meta_recurrences['start_days'];
2446
- $ticket_start_date = date('Y-m-d', strtotime($ticket_start_days.' days', $event_dates[$event_id]));
2447
  $ticket['ticket_start'] = "'". $ticket_start_date . ' '. $ticket_meta_recurrences['start_time'] ."'";
2448
  }
2449
  if( array_key_exists('end_days', $ticket_meta_recurrences) && $ticket_meta_recurrences['end_days'] !== false ){
2450
  $ticket_end_days = $ticket_meta_recurrences['end_days'] >= 0 ? '+'. $ticket_meta_recurrences['end_days']: $ticket_meta_recurrences['end_days'];
2451
- $ticket_end_date = date('Y-m-d', strtotime($ticket_end_days.' days', $event_dates[$event_id]));
 
2452
  $ticket['ticket_end'] = "'". $ticket_end_date . ' '. $ticket_meta_recurrences['end_time'] . "'";
2453
  }
2454
  }
@@ -2462,11 +2731,15 @@ class EM_Event extends EM_Object{
2462
  $result = $wpdb->query($sql);
2463
  }
2464
  }elseif( $this->recurring_delete_bookings ){
2465
- foreach($EM_Events as $EM_Event){ //$EM_Events was defined in the else statement above so we reuse it
2466
- /* @var $EM_Event EM_Event */
2467
- if($EM_Event->recurrence_id == $this->event_id){
2468
- $EM_Event->get_bookings()->delete();
2469
- $EM_Event->get_tickets()->delete();
 
 
 
 
2470
  }
2471
  }
2472
  }
@@ -2541,9 +2814,10 @@ class EM_Event extends EM_Object{
2541
  * @param array $recurrence
2542
  * @return array
2543
  */
2544
- function get_recurrence_days(){
2545
- $start_date = strtotime($this->event_start_date);
2546
- $end_date = strtotime($this->event_end_date);
 
2547
 
2548
  $weekdays = explode(",", $this->recurrence_byday); //what days of the week (or if monthly, one value at index 0)
2549
 
@@ -2631,15 +2905,11 @@ class EM_Event extends EM_Object{
2631
  }
2632
  break;
2633
  case 'yearly':
2634
- //If yearly, it's simple. Get start date, add interval timestamps to that and create matching day for each interval until end date.
2635
- $month = date('m', $this->start);
2636
- $day = date('d',$this->start);
2637
- $year = date('Y',$this->start);
2638
- $end_year = date('Y',$this->end);
2639
- if( @mktime(0,0,0,$day,$month,$end_year) < $this->end ) $end_year--;
2640
- while( $year <= $end_year ){
2641
- $matching_days[] = mktime(0,0,0,$month,$day,$year);
2642
- $year++;
2643
  }
2644
  break;
2645
  }
@@ -2721,7 +2991,7 @@ class EM_Event extends EM_Object{
2721
  $freq_desc .= ", ".sprintf (__("every %s months",'events-manager'), $EM_Event_Recurring->recurrence_interval);
2722
  }
2723
  }elseif ($EM_Event_Recurring->recurrence_freq == 'yearly') {
2724
- $freq_desc .= __("every year", 'events-manager');
2725
  if ($EM_Event_Recurring->recurrence_interval > 1 ) {
2726
  $freq_desc .= sprintf (__("every %s years",'events-manager'), $EM_Event_Recurring->recurrence_interval);
2727
  }
@@ -2735,19 +3005,12 @@ class EM_Event extends EM_Object{
2735
  /**********************************************************
2736
  * UTILITIES
2737
  ***********************************************************/
2738
-
2739
- function __get( $var ){
2740
- //get the modified or created date from the DB only if requested, and save to object
2741
- if( $var == 'event_date_modified' || $var == 'event_date_created'){
2742
- global $wpdb;
2743
- $row = $wpdb->get_row($wpdb->prepare("SELECT event_date_created, event_date_modified FROM ".EM_EVENTS_TABLE.' WHERE event_id=%s', $this->event_id));
2744
- if( $row ){
2745
- $this->event_date_modified = $row->event_date_modified;
2746
- $this->event_date_created = $row->event_date_created;
2747
- return $this->$var;
2748
- }
2749
- }
2750
- return null;
2751
  }
2752
 
2753
  /**
1
  <?php
2
  /**
3
  * Get an event in a db friendly way, by checking globals, cache and passed variables to avoid extra class instantiations.
4
+ * @param mixed $id can be either a post object, event object, event id or post id
5
+ * @param mixed $search_by default is post_id, otherwise it can be by event_id as well. In multisite global mode, a blog id can be supplied to load events from another blog.
6
  * @return EM_Event
7
  */
8
  function em_get_event($id = false, $search_by = 'event_id') {
61
  var $event_slug;
62
  var $event_owner;
63
  var $event_name;
64
+ /**
65
+ * The event start time in local time, represented by a mysql TIME format or 00:00:00 default.
66
+ * Protected so when set in PHP it will reset the EM_Event->start property (EM_DateTime object) so it will have the correct UTC time according to timezone.
67
+ * @var string
68
+ */
69
+ protected $event_start_time = '00:00:00';
70
+ /**
71
+ * The event end time in local time, represented by a mysql TIME format or 00:00:00 default.
72
+ * Protected so when set in PHP it will reset the EM_Event->end property (EM_DateTime object) so it will have the correct UTC time according to timezone.
73
+ * @var string
74
+ */
75
+ protected $event_end_time = '00:00:00';
76
+ /**
77
+ * The event start date in local time. represented by a mysql DATE format.
78
+ * Protected so when set in PHP it will reset the EM_Event->start property (EM_DateTime object) so it will have the correct UTC time according to timezone.
79
+ * @var string
80
+ */
81
+ protected $event_start_date;
82
+ /**
83
+ * The event end date in local time. represented by a mysql DATE format.
84
+ * Protected so when set in PHP it will reset the EM_Event->start property (EM_DateTime object) so it will have the correct UTC time according to timezone.
85
+ * @var string
86
+ */
87
+ protected $event_end_date;
88
+ /**
89
+ * The event start date/time in UTC timezone, represented as a mysql DATETIME value. Protected non-accessible property.
90
+ * Use $EM_Event->start() to obtain the date/time via the returned EM_DateTime object.
91
+ * @var string
92
+ */
93
+ protected $event_start;
94
+ /**
95
+ * The event end date/time in UTC timezone, represented as a mysql DATETIME value. Protected non-accessible property.
96
+ * Use $EM_Event->end() to obtain the date/time via the returned EM_DateTime object.
97
+ * @var string
98
+ */
99
+ protected $event_end;
100
+ /**
101
+ * Whether an event is all day or at specific start/end times. When set to true, event start/end times are assumed to be 00:00:00 and 11:59:59 respectively.
102
+ * @var boolean
103
+ */
104
  var $event_all_day;
105
+ /**
106
+ * Timezone representation in PHP string or WP-style UTC offset.
107
+ * @var string
108
+ */
109
+ protected $event_timezone;
110
  var $post_content;
111
  var $event_rsvp = 0;
112
+ protected $event_rsvp_date;
113
+ protected $event_rsvp_time = "00:00:00";
114
  var $event_rsvp_spaces;
115
  var $event_spaces;
116
  var $event_private;
146
  'event_slug' => array( 'name'=>'slug', 'type'=>'%s', 'null'=>true ),
147
  'event_owner' => array( 'name'=>'owner', 'type'=>'%d', 'null'=>true ),
148
  'event_name' => array( 'name'=>'name', 'type'=>'%s', 'null'=>true ),
149
+ 'event_timezone' => array('type'=>'%s', 'null'=>true ),
150
  'event_start_time' => array( 'name'=>'start_time', 'type'=>'%s', 'null'=>true ),
151
  'event_end_time' => array( 'name'=>'end_time', 'type'=>'%s', 'null'=>true ),
152
+ 'event_start' => array('type'=>'%s', 'null'=>true ),
153
+ 'event_end' => array('type'=>'%s', 'null'=>true ),
154
  'event_all_day' => array( 'name'=>'all_day', 'type'=>'%d', 'null'=>true ),
155
  'event_start_date' => array( 'name'=>'start_date', 'type'=>'%s', 'null'=>true ),
156
  'event_end_date' => array( 'name'=>'end_date', 'type'=>'%s', 'null'=>true ),
179
 
180
  var $image_url = '';
181
  /**
182
+ * EM_DateTime of start date/time in local timezone.
183
+ * As of EM 5.8 this property is protected and accessible via __get(). For backwards compatibility accessing this property directly returns the timestamp as before with an offset to timezone.
184
+ * To access the object use EM_Event::start(), do not try to access it directly for better accuracy use EM_Event::start()->getTimestamp();
185
+ * @var EM_DateTime
186
  */
187
+ protected $start;
188
  /**
189
+ * EM_DateTime of end date/time in local timezone.
190
+ * As of EM 5.8 this property is protected and accessible via __get(). For backwards compatibility accessing this property directly returns the timestamp as before, with an offset to timezone.
191
+ * To access the object use EM_Event::end(), do not try to access it directly for better accuracy use EM_Event::start()->getTimestamp();
192
+ * @var EM_DateTime
193
  */
194
+ protected $end;
195
  /**
196
  * Timestamp for booking cut-off date/time
197
+ * @var EM_DateTime
 
 
 
 
 
198
  */
199
+ protected $rsvp_end;
 
 
 
 
 
200
 
201
  /**
202
  * @var EM_Location
212
  */
213
  var $contact;
214
  /**
215
+ * The categories object containing the event categories
216
+ * @var EM_Categories
217
+ */
218
+ var $categories;
219
+ /**
220
+ * The tags object containing the event tags
221
+ * @var EM_Tags
222
  */
223
+ var $tags;
224
  /**
225
  * If there are any errors, they will be added here.
226
  * @var array
299
  /**
300
  * Initialize an event. You can provide event data in an associative array (using database table field names), an id number, or false (default) to create empty event.
301
  * @param mixed $event_data
302
+ * @param mixed $search_by default is post_id, otherwise it can be by event_id as well. In multisite global mode, a blog id can be supplied to load events from another blog.
303
  * @return null
304
  */
305
  function __construct($id = false, $search_by = 'event_id') {
347
  }
348
  $this->load_postdata($event_post, $search_by);
349
  }
350
+ //set default timezone
351
+ if( empty($this->event_timezone) ){
352
+ if( get_option('dbem_timezone_enabled') ){
353
+ //get default timezone for event, and sanitize UTC variations
354
+ $this->event_timezone = get_option('dbem_timezone_default');
355
+ if( $this->event_timezone == 'UTC+0' || $this->event_timezone == 'UTC +0' ){ $this->event_timezone = 'UTC'; }
356
+ }else{
357
+ $this->event_timezone = EM_DateTimeZone::create()->getName(); //set a default timezone if none exists
358
+ }
359
+ }
360
+ //set recurrence value already
361
  $this->recurrence = $this->is_recurring() ? 1:0;
362
  //Do it here so things appear in the po file.
363
  $this->status_array = array(
372
  do_action('em_event', $this, $id, $search_by);
373
  }
374
 
375
+ function __get( $var ){
376
+ //get the modified or created date from the DB only if requested, and save to object
377
+ if( $var == 'event_date_modified' || $var == 'event_date_created'){
378
+ global $wpdb;
379
+ $row = $wpdb->get_row($wpdb->prepare("SELECT event_date_created, event_date_modified FROM ".EM_EVENTS_TABLE.' WHERE event_id=%s', $this->event_id));
380
+ if( $row ){
381
+ $this->event_date_modified = $row->event_date_modified;
382
+ $this->event_date_created = $row->event_date_created;
383
+ return $this->$var;
384
+ }
385
+ }elseif( in_array($var, array('event_start_date', 'event_start_time', 'event_end_date', 'event_end_time', 'event_rsvp_date', 'event_rsvp_time')) ){
386
+ return $this->$var;
387
+ }elseif( $var == 'event_timezone' ){
388
+ return $this->get_timezone()->getName();
389
+ }
390
+ //deprecated properties for external access, use the start(), end() and rsvp_end() functions to access any of this data.
391
+ if( $var == 'start' ) return $this->start()->getTimestampWithOffset();
392
+ if( $var == 'end' ) return $this->end()->getTimestampWithOffset();
393
+ if( $var == 'rsvp_end' ) return $this->rsvp_end()->getTimestampWithOffset();
394
+ return null;
395
+ }
396
+
397
+ public function __set( $prop, $val ){
398
+ if( $prop == 'event_start_date' || $prop == 'event_end_date' || $prop == 'event_rsvp_date' ){
399
+ //if date is valid, set it, if not set it to null
400
+ $this->$prop = preg_match('/^\d{4}-\d{2}-\d{2}$/', $val) ? $val : null;
401
+ if( $prop == 'event_start_date') $this->start = $this->event_start = null;
402
+ elseif( $prop == 'event_end_date') $this->end = $this->event_end = null;
403
+ elseif( $prop == 'event_rsvp_date') $this->rsvp_end = null;
404
+ }elseif( $prop == 'event_start_time' || $prop == 'event_end_time' || $prop == 'event_rsvp_time' ){
405
+ //if time is valid, set it, otherwise set it to midnight
406
+ $this->$prop = preg_match('/^\d{2}:\d{2}:\d{2}$/', $val) ? $val : '00:00:00';
407
+ if( $prop == 'event_start_date') $this->start = null;
408
+ elseif( $prop == 'event_end_date') $this->end = null;
409
+ elseif( $prop == 'event_rsvp_date') $this->rsvp_end = null;
410
+ }
411
+ //deprecated properties, use start()->setTimestamp() instead
412
+ elseif( $prop == 'start' || $prop == 'end' ){
413
+ if( is_numeric($val) ){
414
+ if( $prop == 'start' ){
415
+ $this->start()->setTimestamp($val);
416
+ }else{
417
+ $this->end()->setTimestamp($val);
418
+ }
419
+ }elseif( is_string($val) ){
420
+ $this->$val = new EM_DateTime($val, $this->event_timezone);
421
+ }
422
+ }
423
+ //anything else
424
+ else{
425
+ $this->$prop = $val;
426
+ }
427
+ }
428
+
429
+ public function __isset( $prop ){
430
+ if( in_array($prop, array('event_start_date', 'event_end_date', 'event_start_time', 'event_end_time', 'event_rsvp_date', 'event_rsvp_time', 'event_start', 'event_end')) ){
431
+ return !empty($this->$prop);
432
+ }elseif( $prop == 'event_timezone' ){
433
+ return true;
434
+ }elseif( $prop == 'start' || $prop == 'end' || $prop == 'rsvp_end' ){
435
+ return $this->$prop()->valid;
436
+ }
437
+ }
438
+
439
  /**
440
  * When cloning this event, we get rid of the bookings and location objects, since they can be retrieved again from the cache instead.
441
  */
474
  }
475
  }
476
  }
 
 
 
 
 
 
477
  //quick compatability fix in case _event_id isn't loaded or somehow got erased in post meta
478
  if( empty($this->event_id) && !$this->is_recurring() ){
479
  global $wpdb;
515
  $this->post_id = $this->ID = $event_array['post_id'] = null; //reset post_id because it doesn't really exist
516
  $this->to_object($event_array);
517
  }
 
 
 
518
  }
519
  if( empty($this->location_id) && !empty($this->event_id) ) $this->location_id = 0; //just set location_id to 0 and avoid any doubt
520
  if( EM_MS_GLOBAL && empty($this->blog_id) ) $this->blog_id = get_current_site()->blog_id; //events created before going multisite may have null values, so we set it to main site id
549
  //we need to get the post/event name and content.... that's it.
550
  $this->post_content = isset($_POST['content']) ? wp_kses( wp_unslash($_POST['content']), $allowedposttags):'';
551
  $this->post_excerpt = !empty($this->post_excerpt) ? $this->post_excerpt:''; //fix null error
552
+ $this->event_name = ( !empty($_POST['event_name']) ) ? sanitize_post_field('post_title', $_POST['event_name'], $this->post_id, 'db'):'';
553
  $this->post_type = ($this->is_recurring() || !empty($_POST['recurring'])) ? 'event-recurring':EM_POST_TYPE_EVENT;
554
  //don't forget categories!
555
  if( get_option('dbem_categories_enabled') ) $this->get_categories()->get_post();
577
  $this->recurrence = 1;
578
  $this->post_type = 'event-recurring';
579
  }
580
+ //Set Event Timezone to supplied value or alternatively use blog timezone value by default.
581
+ if( !empty($_REQUEST['event_timezone']) ){
582
+ $this->event_timezone = EM_DateTimeZone::create($_REQUEST['event_timezone'])->getName();
583
+ }elseif( empty($this->event_timezone ) ){ //if timezone was already set but not supplied, we don't change it
584
+ $this->event_timezone = EM_DateTimeZone::create()->getName();
585
+ }
586
  //Dates and Times - dates ignored if event is recurring being updated (not new) and not specifically chosen to reschedule event
587
+ $this->event_start = $this->event_end = null;
588
  if( !$this->is_recurring() || (empty($this->event_id) || !empty($_REQUEST['event_reschedule'])) ){
589
  //Event Dates
590
+ $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? wp_kses_data($_POST['event_start_date']) : null;
591
  $this->event_end_date = ( !empty($_POST['event_end_date']) ) ? wp_kses_data($_POST['event_end_date']) : $this->event_start_date;
592
  }
593
  //Sort out time
614
  $this->$timeName = ($timeName == 'event_start_time') ? "00:00:00":$this->event_start_time;
615
  }
616
  }
617
+ //reset start and end objects so they are recreated with the new dates/times if and when needed
618
+ $this->start = $this->end = null;
 
619
 
620
  //Get Location info
621
  if( !get_option('dbem_locations_enabled') || (!empty($_POST['no_location']) && !get_option('dbem_require_location',true)) || (empty($_POST['location_id']) && !get_option('dbem_require_location',true) && get_option('dbem_use_select_for_locations')) ){
638
  $this->get_bookings()->get_tickets()->get_post();
639
  }
640
  $this->event_rsvp = 1;
641
+ $this->rsvp_end = null;
642
+ //RSVP cuttoff TIME is set up above where start/end times are as well
643
  if( get_option('dbem_bookings_tickets_single') && count($this->get_tickets()->tickets) == 1 ){
644
  //single ticket mode will use the ticket end date/time as cut-off date/time
645
  $EM_Ticket = $this->get_tickets()->get_first();
646
+ $this->event_rsvp_date = null;
647
+ if( !empty($EM_Ticket->ticket_end) ){
648
+ $this->event_rsvp_date = $EM_Ticket->end()->getDate();
649
+ $this->event_rsvp_time = $EM_Ticket->end()->getTime();
650
  }else{
651
  //no default ticket end time, so make it default to event start date/time
652
  $this->event_rsvp_date = $this->event_start_date;
656
  }else{
657
  //if no rsvp cut-off date supplied, make it the event start date
658
  $this->event_rsvp_date = ( !empty($_POST['event_rsvp_date']) ) ? wp_kses_data($_POST['event_rsvp_date']) : $this->event_start_date;
659
+ if ( empty($_POST['event_rsvp_date']) || empty($_POST['event_rsvp_time']) ) $this->event_rsvp_time = $this->event_start_time;
660
  if( $this->event_all_day && empty($_POST['event_rsvp_date']) ){ $this->event_rsvp_time = '00:00:00'; } //all-day events start at 0 hour
661
  }
662
+ //reset EM_DateTime object
663
+ $this->rsvp_end = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  $this->event_spaces = ( isset($_POST['event_spaces']) ) ? absint($_POST['event_spaces']):0;
665
  $this->event_rsvp_spaces = ( isset($_POST['event_rsvp_spaces']) ) ? absint($_POST['event_rsvp_spaces']):0;
666
  }elseif( !$preview_autosave && ($can_manage_bookings || !$this->event_rsvp) ){
667
  if( empty($_POST['event_rsvp']) && $this->event_rsvp ) $deleting_bookings = true;
668
  $this->event_rsvp = 0;
669
+ $this->event_rsvp_date = $this->event_rsvp_time = $this->rsvp_end = null;
670
  }
671
 
672
  //Sort out event attributes - note that custom post meta now also gets inserted here automatically (and is overwritten by these attributes)
770
  //new event so we create everything from scratch
771
  $this->recurring_reschedule = $this->recurring_recreate_bookings = true;
772
  }
773
+ //recurring events may have a cut-off date x days before or after the recurrence start dates
774
+ $this->recurrence_rsvp_days = null;
775
+ if( get_option('dbem_bookings_tickets_single') && count($this->get_tickets()->tickets) == 1 ){
776
+ //if in single ticket mode then ticket cut-off date determines event cut-off date
777
+ $EM_Ticket = $this->get_tickets()->get_first();
778
+ if( !empty($EM_Ticket->ticket_meta['recurrences']) ){
779
+ $this->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days'];
780
+ $this->event_rsvp_time = $EM_Ticket->ticket_meta['recurrences']['end_time'];
781
+ }
782
+ }else{
783
+ if( array_key_exists('recurrence_rsvp_days', $_POST) ){
784
+ if( !empty($_POST['recurrence_rsvp_days_when']) && $_POST['recurrence_rsvp_days_when'] == 'after' ){
785
+ $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']);
786
+ }else{ //by default the start date is the point of reference
787
+ $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']) * -1;
788
+ }
789
+ }
790
+ }
791
+ //create timestamps and set rsvp date/time for a normal event
792
+ if( !is_numeric($this->recurrence_rsvp_days) ){
793
+ //falback in case nothing gets set for rsvp cut-off
794
+ $this->event_rsvp_date = $this->event_rsvp_time = $this->rsvp_end = null;
795
+ }else{
796
+ $this->event_rsvp_date = $this->start()->copy()->modify($this->recurrence_rsvp_days.' days')->getDate();
797
+ }
798
  }else{
799
  foreach( $this->recurrence_fields as $recurrence_field ){
800
  $this->$recurrence_field = null;
840
  }
841
  }
842
  if( preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_start_date) && preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_end_date) ){
843
+ if( $this->start()->getTimestamp() > $this->end()->getTimestamp() ){
844
  $this->add_error(__('Events cannot start after they end.','events-manager'));
845
+ }elseif( $this->is_recurring() && $this->recurrence_days == 0 && $this->start()->getTimestamp() > $this->end()->getTimestamp() ){
846
  $this->add_error(__('Events cannot start after they end.','events-manager').' '.__('For recurring events that end the following day, ensure you make your event last 1 or more days.'));
847
  }
848
  }else{
907
  //Overwrite new post info
908
  $post_array['post_type'] = ($this->recurrence && get_option('dbem_recurrence_enabled')) ? 'event-recurring':EM_POST_TYPE_EVENT;
909
  $post_array['post_title'] = $this->event_name;
910
+ $post_array['post_content'] = !empty($this->post_content) ? $this->post_content : '';
911
  $post_array['post_excerpt'] = $this->post_excerpt;
912
  //decide on post status
913
  if( empty($this->force_status) ){
966
  }
967
  $return = apply_filters('em_event_save', $result, $this);
968
  $EM_SAVING_EVENT = false;
969
+ //reload post data and add this event to the cache, after any other hooks have done their thing
970
+ //cache refresh when saving via admin area is handled in EM_Event_Post_Admin::save_post/refresh_cache
971
+ if( $result && $this->is_published() ){
972
+ //we won't depend on hooks, if we saved the event and it's still published in its saved state, refresh the cache regardless
973
+ $this->load_postdata($this);
974
+ wp_cache_set($this->event_id, $this, 'em_events');
975
+ wp_cache_set($this->post_id, $this->event_id, 'em_events_ids');
976
+ }
977
  return $return;
978
  }
979
 
1006
  if( !in_array($key, $this->post_fields) && $key != 'event_attributes' ){
1007
  //ignore certain fields and delete if not new
1008
  $save_meta_key = true;
1009
+ if( !$this->is_recurring() && in_array($key, $this->recurrence_fields) ) $save_meta_key = false;
 
1010
  if( !$this->is_recurrence() && $key == 'recurrence_id' ) $save_meta_key = false;
1011
  $ignore_zero_keys = array('location_id', 'group_id', 'event_all_day' );
1012
  if( in_array($key, $ignore_zero_keys) && empty($this->$key) ) $save_meta_key = false;
1036
  }
1037
  }
1038
  }
1039
+ //update timestamps, dates and times
1040
+ update_post_meta($this->post_id, '_event_start_local', $this->start()->getDateTime());
1041
+ update_post_meta($this->post_id, '_event_end_local', $this->end()->getDateTime());
1042
+ //Deprecated, only for backwards compatibility, these meta fields will eventually be deleted!
1043
+ $site_data = get_site_option('dbem_data');
1044
+ if( !empty($site_data['updates']['timezone-backcompat']) ){
1045
+ update_post_meta($this->post_id, '_start_ts', str_pad($this->start()->getTimestamp(), 10, 0, STR_PAD_LEFT));
1046
+ update_post_meta($this->post_id, '_end_ts', str_pad($this->end()->getTimestamp(), 10, 0, STR_PAD_LEFT));
1047
+ }
1048
  //sort out event status
1049
  $result = count($this->errors) == 0;
1050
  $this->get_status();
1085
  update_post_meta($this->post_id, '_event_id', $this->event_id);
1086
  $this->feedback_message = sprintf(__('Successfully saved %s','events-manager'),__('Event','events-manager'));
1087
  $this->just_added_event = true; //make an easy hook
1088
+ $this->get_bookings()->bookings = array(); //set bookings array to 0 to avoid an extra DB query
1089
  do_action('em_event_save_new', $this);
1090
  }
1091
  }else{
1110
  }
1111
  //Add/Delete Tickets
1112
  if($this->event_rsvp == 0){
1113
+ if( !$this->just_added_event ){
1114
+ $this->get_bookings()->delete();
1115
+ $this->get_tickets()->delete();
1116
+ }
1117
  }elseif( $this->can_manage('manage_bookings','manage_others_bookings') ){
1118
  if( !$this->get_bookings()->get_tickets()->save() ){
1119
  $this->add_error( $this->get_bookings()->get_tickets()->get_errors() );
1144
  do_action('em_event_added', $this);
1145
  }
1146
  }
1147
+ return apply_filters('em_event_save_meta', count($this->errors) == 0, $this);
 
 
 
 
 
 
1148
  }
1149
 
1150
  /**
1189
  //Get custom fields and post meta - adapted from $this->load_post_meta()
1190
  foreach($event_meta as $event_meta_key => $event_meta_vals){
1191
  if( $event_meta_key == '_wpas_' ) continue; //allow JetPack Publicize to detect this as a new post when published
1192
+ if( is_array($event_meta_vals) ){
1193
+ if( !array_key_exists($event_meta_key, $new_event_meta) && !in_array($event_meta_key, array('_event_attributes', '_edit_last', '_edit_lock', '_event_owner_name','_event_owner_anonymous','_event_owner_email')) ){
 
1194
  foreach($event_meta_vals as $event_meta_val){
1195
  $event_meta_inserts[] = "({$EM_Event->post_id}, '{$event_meta_key}', '{$event_meta_val}')";
1196
  }
1334
  $post_status = $set_status ? 'publish':'pending';
1335
  if( empty($this->post_name) ){
1336
  //published or pending posts should have a valid post slug
1337
+ $slug = sanitize_title($this->post_title);
1338
+ $this->post_name = wp_unique_post_slug( $slug, $this->post_id, $post_status, EM_POST_TYPE_EVENT, 0);
1339
  $set_post_name = true;
1340
  }
1341
  if($set_post_status){
1353
  return apply_filters('em_event_set_status', $result !== false, $status, $this);
1354
  }
1355
 
1356
+ public function set_timezone( $timezone = false ){
1357
+ //reset UTC times and objects so they're recreated with local time and new timezone
1358
+ $this->event_start = $this->event_end = $this->start = $this->end = $this->rsvp_end = null;
1359
+ $EM_DateTimeZone = EM_DateTimeZone::create($timezone);
1360
+ //modify the timezone string name itself
1361
+ $this->event_timezone = $EM_DateTimeZone->getName();
1362
+ }
1363
+
1364
+ public function get_timezone(){
1365
+ return $this->start()->getTimezone();
1366
+ }
1367
+
1368
  function is_published(){
1369
  return apply_filters('em_event_is_published', ($this->post_status == 'publish' || $this->post_status == 'private'), $this);
1370
  }
1371
 
1372
+ /**
1373
+ * Returns an EM_DateTime object of the event start date/time in local timezone of event.
1374
+ * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default.
1375
+ * @return EM_DateTime
1376
+ * @see EM_Event::get_datetime()
1377
+ */
1378
+ public function start( $utc_timezone = false ){
1379
+ return apply_filters('em_event_start', $this->get_datetime('start', $utc_timezone), $this);
1380
+ }
1381
+
1382
+ /**
1383
+ * Returns an EM_DateTime object of the event end date/time in local timezone of event
1384
+ * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default.
1385
+ * @return EM_DateTime
1386
+ * @see EM_Event::get_datetime()
1387
+ */
1388
+ public function end( $utc_timezone = false ){
1389
+ return apply_filters('em_event_end', $this->get_datetime('end', $utc_timezone), $this);
1390
+ }
1391
+
1392
+ /**
1393
+ * Returns an EM_DateTime representation of when bookings close in local event timezone. If no valid date defined, event start date/time will be used.
1394
+ * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default.
1395
+ * @return EM_DateTime
1396
+ */
1397
+ public function rsvp_end( $utc_timezone = false ){
1398
+ if( empty($this->rsvp_end) || !$this->rsvp_end->valid ){
1399
+ if( !empty($this->event_rsvp_date ) ){
1400
+ $this->rsvp_end = new EM_DateTime($this->event_rsvp_date." ".$this->event_rsvp_time, $this->event_timezone);
1401
+ if( !$this->rsvp_end->valid ){
1402
+ //invalid date will revert to start time
1403
+ $this->rsvp_end = $this->start()->copy();
1404
+ }
1405
+ }else{
1406
+ //no date defined means event start date/time is used
1407
+ $this->rsvp_end = $this->start()->copy();
1408
+ }
1409
+ }
1410
+ //Set to UTC timezone if requested, local by default
1411
+ $tz = $utc_timezone ? 'UTC' : $this->event_timezone;
1412
+ $this->rsvp_end->setTimezone($tz);
1413
+ return $this->rsvp_end;
1414
+ }
1415
+
1416
+ /**
1417
+ * Generates an EM_DateTime for the the start/end date/times of the event in local timezone, as well as setting a valid flag if dates and times are valid.
1418
+ * The generated object will be derived from the local date and time values. If no date exists, then 1970-01-01 will be used, and 00:00:00 if no valid time exists.
1419
+ * If date is invalid but time is, only use local timezones since a UTC conversion will provide inaccurate timezone differences due to unknown DST status. *
1420
+ * @param string $when 'start' or 'end' date/time
1421
+ * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. Do not use if EM_DateTime->valid is false.
1422
+ * @return EM_DateTime
1423
+ */
1424
+ public function get_datetime( $when = 'start', $utc_timezone = false ){
1425
+ if( $when != 'start' && $when != 'end') return new EM_DateTime(); //currently only start/end dates are relevant
1426
+ //Initialize EM_DateTime if not already initialized, or if previously initialized object is invalid (e.g. draft event with invalid dates being resubmitted)
1427
+ $when_date = 'event_'.$when.'_date';
1428
+ $when_time = 'event_'.$when.'_time';
1429
+ //we take a pass at creating a new datetime object if it's empty, invalid or a different time to the current start date
1430
+ if( empty($this->$when) || !$this->$when->valid ){
1431
+ $when_utc = 'event_'.$when;
1432
+ $date_regex = '/^\d{4}-\d{2}-\d{2}$/';
1433
+ $valid_time = !empty($this->$when_time) && preg_match('/^\d{2}:\d{2}:\d{2}$/', $this->$when_time);
1434
+ //If there now is a valid date string for local or UTC timezones, create a new object which will set the valid flag to true by default
1435
+ if( !empty($this->$when_date) && preg_match($date_regex, $this->$when_date) && $valid_time ){
1436
+ $EM_DateTime = new EM_DateTime(trim($this->$when_date.' '.$this->$when_time), $this->event_timezone);
1437
+ if( $EM_DateTime->valid && empty($this->$when_utc) ){
1438
+ $EM_DateTime->setTimezone('UTC');
1439
+ $this->$when_utc = $EM_DateTime->format();
1440
+ }
1441
+ }
1442
+ //If we didn't attempt to create a date above, or it didn't work out, create an invalid date based on time.
1443
+ if( empty($EM_DateTime) || !$EM_DateTime->valid ){
1444
+ //create a new datetime just with the time (if set), fake date and set the valid flag to false
1445
+ $time = $valid_time ? $this->$when_time : '00:00:00';
1446
+ $EM_DateTime = new EM_DateTime('1970-01-01 '.$time, $this->event_timezone);
1447
+ $EM_DateTime->valid = false;
1448
+ }
1449
+ //set new datetime
1450
+ $this->$when = $EM_DateTime;
1451
+ }else{
1452
+ /* @var EM_DateTime $EM_DateTime */
1453
+ $EM_DateTime = $this->$when;
1454
+ }
1455
+ //Set to UTC timezone if requested, local by default
1456
+ $tz = $utc_timezone ? 'UTC' : $this->event_timezone;
1457
+ $EM_DateTime->setTimezone($tz);
1458
+ return $EM_DateTime;
1459
+ }
1460
+
1461
  function get_status($db = false){
1462
  switch( $this->post_status ){
1463
  case 'private':
1711
  */
1712
  function output($format, $target="html") {
1713
  global $wpdb;
1714
+ //$format = do_shortcode($format); //parse shortcode first, so that formats within shortcodes are parsed properly, however uncommenting this will break shortcode containing placeholders for arguments
1715
  $event_string = $format;
1716
  //Time place holder that doesn't show if empty.
1717
  //TODO add filter here too
1718
  preg_match_all('/#@?_\{[^}]+\}/', $format, $results);
1719
  foreach($results[0] as $result) {
1720
  if(substr($result, 0, 3 ) == "#@_"){
1721
+ $date = 'end';
1722
  $offset = 4;
1723
  }else{
1724
+ $date = 'start';
1725
  $offset = 3;
1726
  }
1727
+ if( $date == 'end' && $this->event_end_date == $this->event_start_date ){
1728
  $replace = __( apply_filters('em_event_output_placeholder', '', $this, $result, $target) );
1729
  }else{
1730
+ $date_format = substr( $result, $offset, (strlen($result)-($offset+1)) );
1731
+ $replace = apply_filters('em_event_output_placeholder', $this->$date()->i18n($date_format), $this, $result, $target);
1732
  }
1733
  $event_string = str_replace($result,$replace,$event_string );
1734
  }
1786
  }elseif ($condition == 'no_time'){
1787
  //are the booking times exactly the same and it's not an all-day event.
1788
  $show_condition = ( $this->event_start_time == $this->event_end_time && !$this->event_all_day );
1789
+ }elseif ($condition == 'different_timezone'){
1790
+ //current event timezone is different to blog timezone
1791
+ $show_condition = $this->event_timezone != EM_DateTimeZone::create()->getName();
1792
+ }elseif ($condition == 'same_timezone'){
1793
+ //current event timezone is different to blog timezone
1794
+ $show_condition = $this->event_timezone == EM_DateTimeZone::create()->getName();
1795
  }elseif ($condition == 'all_day'){
1796
  //is it an all day event
1797
  $show_condition = !empty($this->event_all_day);
1828
  }elseif ($condition == 'is_past'){
1829
  //if event is past
1830
  if( get_option('dbem_events_current_are_past') ){
1831
+ $show_condition = $this->start()->getTimestamp() <= time();
1832
  }else{
1833
+ $show_condition = $this->end()->getTimestamp() <= time();
1834
  }
1835
  }elseif ($condition == 'is_future'){
1836
  //if event is upcoming
1837
+ $show_condition = $this->start()->getTimestamp() > time();
1838
  }elseif ($condition == 'is_current'){
1839
  //if event is currently happening
1840
+ $show_condition = $this->start()->getTimestamp() <= time() && $this->end()->getTimestamp() >= time();
 
1841
  }elseif ($condition == 'is_recurrence'){
1842
  //if event is a recurrence
1843
  $show_condition = $this->is_recurrence();
1985
  //Times & Dates
1986
  case '#_24HSTARTTIME':
1987
  case '#_24HENDTIME':
1988
+ $replace = ($result == '#_24HSTARTTIME') ? $this->start()->format('H:i'):$this->end()->format('H:i');
 
1989
  break;
1990
  case '#_12HSTARTTIME':
1991
  case '#_12HENDTIME':
1992
+ $replace = ($result == '#_12HSTARTTIME') ? $this->start()->format('g:i A'):$this->end()->format('g:i A');
 
1993
  break;
1994
  case '#_EVENTTIMES':
1995
  //get format of time to show
1999
  //get format of time to show
2000
  $replace = $this->output_dates();
2001
  break;
2002
+ case '#_EVENTTIMEZONE':
2003
+ $replace = str_replace('_', ' ', $this->event_timezone);
2004
+ break;
2005
+ case '#_EVENTTIMEZONERAW':
2006
+ $replace = $this->event_timezone;
2007
+ break;
2008
  //Links
2009
  case '#_EVENTPAGEURL': //deprecated
2010
  case '#_LINKEDNAME': //deprecated
2152
  case '#_BOOKINGSCUTOFFDATE':
2153
  case '#_BOOKINGSCUTOFFTIME':
2154
  $replace = '';
2155
+ if ($this->event_rsvp && get_option('dbem_rsvp_enabled') ) {
2156
+ $replace_format = em_get_date_format() .' '. em_get_hour_format();
2157
+ if( $result == '#_BOOKINGSCUTOFFDATE' ) $replace_format = em_get_date_format();
2158
+ if( $result == '#_BOOKINGSCUTOFFTIME' ) $replace_format = em_get_hour_format();
2159
+ $replace = $this->rsvp_end()->format($replace_format);
2160
  }
2161
  break;
2162
  //Contact Person
2258
  case '#_EVENTGCALLINK':
2259
  //get dates in UTC/GMT time
2260
  if($this->event_all_day && $this->event_start_date == $this->event_end_date){
2261
+ $dateStart = $this->start()->format('Ymd');
2262
+ $dateEnd = $this->end()->copy()->add('P1D')->format('Ymd');
2263
  }else{
2264
+ $dateStart = $this->start()->format('Ymd\THis');
2265
+ $dateEnd = $this->end()->format('Ymd\THis');
2266
  }
2267
  //build url
2268
+ $gcal_url = 'http://www.google.com/calendar/event?action=TEMPLATE&text=event_name&dates=start_date/end_date&details=post_content&location=location_name&trp=false&sprop=event_url&sprop=name:blog_name&ctz=event_timezone';
2269
  $gcal_url = str_replace('event_name', urlencode($this->event_name), $gcal_url);
2270
  $gcal_url = str_replace('start_date', urlencode($dateStart), $gcal_url);
2271
  $gcal_url = str_replace('end_date', urlencode($dateEnd), $gcal_url);
2272
  $gcal_url = str_replace('location_name', urlencode($this->output('#_LOCATION, #_LOCATIONADDRESS, #_LOCATIONCOUNTRY')), $gcal_url);
2273
  $gcal_url = str_replace('blog_name', urlencode(get_bloginfo()), $gcal_url);
2274
  $gcal_url = str_replace('event_url', urlencode($this->get_permalink()), $gcal_url);
2275
+ $gcal_url = str_replace('event_timezone', urlencode($this->event_timezone), $gcal_url);
2276
  //calculate URL length so we know how much we can work with to make a description.
2277
  if( !empty($this->post_excerpt) ){
2278
  $gcal_url_description = $this->post_excerpt;
2314
  foreach($placeholders[1] as $result) {
2315
  // matches all PHP START date and time placeholders
2316
  if (preg_match('/^#[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) {
2317
+ $replace = $this->start()->i18n(ltrim($result, "#"));
2318
  $replace = apply_filters('em_event_output_placeholder', $replace, $this, $result, $target);
2319
  $event_string = str_replace($result, $replace, $event_string );
2320
  }
2321
  // matches all PHP END time placeholders for endtime
2322
  if (preg_match('/^#@[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) {
2323
+ $replace = $this->end()->i18n(ltrim($result, "#@"));
2324
  $replace = apply_filters('em_event_output_placeholder', $replace, $this, $result, $target);
2325
  $event_string = str_replace($result, $replace, $event_string );
2326
  }
2365
  return apply_filters('em_event_output', $event_string, $this, $format, $target);
2366
  }
2367
 
2368
+ function output_times( $time_format = false, $time_separator = false , $all_day_message = false ){
2369
  if( !$this->event_all_day ){
2370
+ if( empty($time_format) ) $time_format = ( get_option('dbem_time_format') ) ? get_option('dbem_time_format'):get_option('time_format');
2371
+ if( empty($time_separator) ) $time_separator = get_option('dbem_times_separator');
2372
+ if( $this->event_start_time != $this->event_end_time ){
2373
+ $replace = $this->start()->i18n($time_format). $time_separator . $this->end()->i18n($time_format);
2374
  }else{
2375
+ $replace = $this->start()->i18n($time_format);
2376
  }
2377
  }else{
2378
  $replace = get_option('dbem_event_all_day_message');
2380
  return $replace;
2381
  }
2382
 
2383
+ function output_dates( $date_format = false, $date_separator = false ){
2384
+ if( empty($date_format) ) $date_format = ( get_option('dbem_date_format') ) ? get_option('dbem_date_format'):get_option('date_format');
2385
+ if( empty($date_separator) ) $date_separator = get_option('dbem_dates_separator');
2386
  if( $this->event_start_date != $this->event_end_date){
2387
+ $replace = $this->start()->i18n($date_format). $date_separator . $this->end()->i18n($date_format);
2388
  }else{
2389
+ $replace = $this->start()->i18n($date_format);
2390
  }
2391
  return $replace;
2392
  }
2509
  //remove recurrence meta info we won't need in events
2510
  foreach( $this->recurrence_fields as $recurrence_field){
2511
  $event[$recurrence_field] = null;
2512
+ if( isset($meta_fields['_'.$recurrence_field]) ) unset($meta_fields['_'.$recurrence_field]);
2513
  }
2514
  //Set the recurrence ID
2515
  $event['recurrence_id'] = $meta_fields['_recurrence_id'] = $this->event_id;
2526
  unset($event['event_date_modified']);
2527
  if( count($matching_days) > 0 ){
2528
  //first save event post data
2529
+ $EM_DateTime = $this->start()->copy();
2530
  foreach( $matching_days as $day ) {
2531
+ //set start date/time to $EM_DateTime for relative use further on
2532
+ $EM_DateTime->setTimestamp($day)->setTimeString($event['event_start_time']);
2533
+ $start_timestamp = $EM_DateTime->getTimestamp(); //for quick access later
2534
  //rewrite post fields if needed
2535
+ $post_fields['post_name'] = $event['event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.$EM_DateTime->format($recurring_date_format), $post_fields, $day, $matching_days, $this);
2536
+ //set start date
2537
+ $event['event_start_date'] = $meta_fields['_event_start_date'] = $EM_DateTime->getDate();
2538
+ $event['event_start'] = $meta_fields['_event_start'] = $EM_DateTime->getDateTime(true);
2539
+ //add rsvp date/time restrictions
2540
  if( !empty($this->recurrence_rsvp_days) && is_numeric($this->recurrence_rsvp_days) ){
2541
+ if( $this->recurrence_rsvp_days > 0 ){
2542
+ $event_rsvp_date = $EM_DateTime->copy()->add('P'.absint($this->recurrence_rsvp_days).'D')->getDate(); //cloned so original object isn't modified
2543
+ }elseif($this->recurrence_rsvp_days < 0 ){
2544
+ $event_rsvp_date = $EM_DateTime->copy()->sub('P'.absint($this->recurrence_rsvp_days).'D')->getDate(); //cloned so original object isn't modified
2545
+ }else{
2546
+ $event_rsvp_date = $EM_DateTime->getDate();
2547
+ }
2548
  $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date;
2549
  }else{
2550
  $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event['event_start_date'];
2551
  }
2552
  $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
2553
+ //set end date
2554
+ $EM_DateTime->setTimeString($event['event_end_time']);
2555
  if($this->recurrence_days > 0){
2556
+ //$EM_DateTime modified here, and used further down for UTC end date
2557
+ $event['event_end_date'] = $meta_fields['_event_end_date'] = $EM_DateTime->add('P'.$this->recurrence_days.'D')->getDate();
2558
  }else{
2559
  $event['event_end_date'] = $meta_fields['_event_end_date'] = $event['event_start_date'];
2560
+ }
2561
+ $end_timestamp = $EM_DateTime->getTimestamp(); //for quick access later
2562
+ $event['event_end'] = $meta_fields['_event_end'] = $EM_DateTime->getDateTime(true);
2563
+ //add extra date/time post meta
2564
+ $meta_fields['_event_start_local'] = $event['event_start_date'].' '.$event['event_start_time'];
2565
+ $meta_fields['_event_end_local'] = $event['event_end_date'].' '.$event['event_end_time'];
2566
+ //Deprecated meta fields
2567
+ $site_data = get_site_option('dbem_data');
2568
+ if( !empty($site_data['updates']['timezone-backcompat']) ){
2569
+ $meta_fields['_start_ts'] = $start_timestamp;
2570
+ $meta_fields['_end_ts'] = $end_timestamp;
2571
+ }
2572
  //create the event
2573
  if( $wpdb->insert($wpdb->posts, $post_fields ) ){
2574
  $event['post_id'] = $post_id = $post_ids[] = $wpdb->insert_id; //post id saved into event and also as a var for later user
2577
  //insert into events index table
2578
  $event_saves[] = $wpdb->insert(EM_EVENTS_TABLE, $event);
2579
  $event_ids[$post_id] = $event_id = $wpdb->insert_id;
2580
+ $event_dates[$event_id] = $start_timestamp;
2581
  //create the meta inserts for each event
2582
  $meta_fields['_event_id'] = $event_id;
2583
  foreach($meta_fields as $meta_key => $meta_val){
2607
  $event['event_date_modified'] = current_time('mysql'); //since the recurrences are modified but not recreated
2608
  unset( $post_fields['comment_count'], $post_fields['guid'], $post_fields['menu_order']);
2609
  //now we go through the recurrences and check whether things relative to dates need to be changed
2610
+ $events = EM_Events::get( array('recurrence'=>$this->event_id, 'scope'=>'all', 'status'=>'everything', 'array' => true ) );
2611
+ foreach($events as $event_array){ /* @var $EM_Event EM_Event */
2612
+ //set new start/end times to obtain accurate timestamp according to timezone and DST
2613
+ $EM_DateTime = $this->start()->copy()->modify($event_array['event_start_date']. ' ' . $event_array['event_start_time']);
2614
+ $start_timestamp = $EM_DateTime->getTimestamp();
2615
+ $event['event_start'] = $meta_fields['_event_start'] = $EM_DateTime->getDateTime(true);
2616
+ $end_timestamp = $EM_DateTime->modify($event_array['event_end_date']. ' ' . $event_array['event_end_time'])->getTimestamp();
2617
+ $event['event_end'] = $meta_fields['_event_end'] = $EM_DateTime->getDateTime(true);
2618
+ //set indexes for reference further down
2619
+ $event_ids[$event_array['post_id']] = $event_array['event_id'];
2620
+ $event_dates[$event_array['event_id']] = $start_timestamp;
2621
+ $post_ids[] = $event_array['post_id'];
2622
  //do we need to change the slugs?
2623
+ $post_fields['post_name'] = $event['event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.$EM_DateTime->setTimestamp($start_timestamp)->format($recurring_date_format), $post_fields, $start_timestamp, array(), $this);
2624
+ //adjust certain meta information relative to dates and times
2625
  if( !empty($this->recurrence_rsvp_days) && is_numeric($this->recurrence_rsvp_days) ){
2626
  $event_rsvp_days = $this->recurrence_rsvp_days >= 0 ? '+'. $this->recurrence_rsvp_days: $this->recurrence_rsvp_days;
2627
+ $event_rsvp_date = $EM_DateTime->setTimestamp($start_timestamp)->modify($event_rsvp_days.' days')->getDate();
2628
  $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date;
2629
  }else{
2630
+ $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_array['event_start_date'];
2631
  }
2632
  $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
2633
  //add meta fields we deleted and are specific to this event
2634
+ $meta_fields['_event_start_date'] = $event_array['event_start_date'];
2635
+ $meta_fields['_event_start_local'] = $event_array['event_start_date']. ' ' . $event_array['event_start_time'];
2636
+ $meta_fields['_event_end_date'] = $event_array['event_end_date'];
2637
+ $meta_fields['_event_end_local'] = $event_array['event_end_date']. ' ' . $event_array['event_end_time'];
2638
+ $site_data = get_site_option('dbem_data');
2639
+ if( $site_data['updates']['timezone-backcompat'] ){
2640
+ $meta_fields['_start_ts'] = $start_timestamp;
2641
+ $meta_fields['_end_ts'] = $end_timestamp;
2642
+ }
2643
  //overwrite event and post tables
2644
+ $wpdb->update(EM_EVENTS_TABLE, $event, array('event_id' => $event_array['event_id']));
2645
+ $wpdb->update($wpdb->posts, $post_fields, array('ID' => $event_array['post_id']));
2646
  //save meta field data for insertion in one go
2647
  foreach($meta_fields as $meta_key => $meta_val){
2648
+ $meta_inserts[] = $wpdb->prepare("(%d, %s, %s)", array($event_array['post_id'], $meta_key, $meta_val));
2649
  }
2650
  }
2651
  //delete all meta
2664
  if( $this->recurring_reschedule || $this->recurring_recreate_bookings ){
2665
  //first, delete all bookings & tickets if we haven't done so during the reschedule above - something we'll want to change later if possible so bookings can be modified without losing all data
2666
  if( !$this->recurring_reschedule ){
2667
+ //create empty EM_Bookings and EM_Tickets objects to circumvent extra loading of data and SQL queries
2668
+ $EM_Bookings = new EM_Bookings();
2669
+ $EM_Tickets = new EM_Tickets();
2670
+ foreach($events as $event){ //$events was defined in the else statement above so we reuse it
2671
+ if($event['recurrence_id'] == $this->event_id){
2672
+ //trick EM_Bookings and EM_Tickets to think it was loaded, and make use of optimized delete functions since 5.7.3.4
2673
+ $EM_Bookings->event_id = $EM_Tickets->event_id = $event['event_id'];
2674
+ $EM_Bookings->delete();
2675
+ $EM_Tickets->delete();
2676
  }
2677
  }
2678
  }
2701
  $ticket[$k] = $wpdb->prepare($data_type,$v);
2702
  }
2703
  }
2704
+ //prep ticket meta for insertion with relative info for each event date
2705
+ $EM_DateTime = $this->start()->copy();
2706
  foreach($event_ids as $event_id){
2707
  $ticket['event_id'] = $event_id;
2708
  $ticket['ticket_start'] = $ticket['ticket_end'] = 'NULL';
2709
  //sort out cut-of dates
2710
  if( !empty($ticket_meta_recurrences) ){
2711
+ $EM_DateTime->setTimestamp($event_dates[$event_id]); //by using EM_DateTime we'll generate timezone aware dates
2712
  if( array_key_exists('start_days', $ticket_meta_recurrences) && $ticket_meta_recurrences['start_days'] !== false ){
2713
  $ticket_start_days = $ticket_meta_recurrences['start_days'] >= 0 ? '+'. $ticket_meta_recurrences['start_days']: $ticket_meta_recurrences['start_days'];
2714
+ $ticket_start_date = $EM_DateTime->modify($ticket_start_days.' days')->getDate();
2715
  $ticket['ticket_start'] = "'". $ticket_start_date . ' '. $ticket_meta_recurrences['start_time'] ."'";
2716
  }
2717
  if( array_key_exists('end_days', $ticket_meta_recurrences) && $ticket_meta_recurrences['end_days'] !== false ){
2718
  $ticket_end_days = $ticket_meta_recurrences['end_days'] >= 0 ? '+'. $ticket_meta_recurrences['end_days']: $ticket_meta_recurrences['end_days'];
2719
+ $EM_DateTime->setTimestamp($event_dates[$event_id]);
2720
+ $ticket_end_date = $EM_DateTime->modify($ticket_end_days.' days')->getDate();
2721
  $ticket['ticket_end'] = "'". $ticket_end_date . ' '. $ticket_meta_recurrences['end_time'] . "'";
2722
  }
2723
  }
2731
  $result = $wpdb->query($sql);
2732
  }
2733
  }elseif( $this->recurring_delete_bookings ){
2734
+ //create empty EM_Bookings and EM_Tickets objects to circumvent extra loading of data and SQL queries
2735
+ $EM_Bookings = new EM_Bookings();
2736
+ $EM_Tickets = new EM_Tickets();
2737
+ foreach($events as $event){ //$events was defined in the else statement above so we reuse it
2738
+ if($event['recurrence_id'] == $this->event_id){
2739
+ //trick EM_Bookings and EM_Tickets to think it was loaded, and make use of optimized delete functions since 5.7.3.4
2740
+ $EM_Bookings->event_id = $EM_Tickets->event_id = $event['event_id'];
2741
+ $EM_Bookings->delete();
2742
+ $EM_Tickets->delete();
2743
  }
2744
  }
2745
  }
2814
  * @param array $recurrence
2815
  * @return array
2816
  */
2817
+ function get_recurrence_days(){
2818
+ $EM_DateTime = new EM_DateTime();
2819
+ $start_date = $EM_DateTime->modify($this->start()->getDate())->getTimestamp();
2820
+ $end_date = $EM_DateTime->modify($this->end()->getDate())->getTimestamp();
2821
 
2822
  $weekdays = explode(",", $this->recurrence_byday); //what days of the week (or if monthly, one value at index 0)
2823
 
2905
  }
2906
  break;
2907
  case 'yearly':
2908
+ //Yearly is easy, we get the start date as a cloned EM_DateTime and keep adding a year until it surpasses the end EM_DateTime value.
2909
+ $EM_DateTime = $this->start()->copy();
2910
+ while( $EM_DateTime <= $this->end() ){
2911
+ $matching_days[] = $EM_DateTime->getTimestamp();
2912
+ $EM_DateTime->add('P1Y');
 
 
 
 
2913
  }
2914
  break;
2915
  }
2991
  $freq_desc .= ", ".sprintf (__("every %s months",'events-manager'), $EM_Event_Recurring->recurrence_interval);
2992
  }
2993
  }elseif ($EM_Event_Recurring->recurrence_freq == 'yearly') {
2994
+ $freq_desc = __("every year", 'events-manager');
2995
  if ($EM_Event_Recurring->recurrence_interval > 1 ) {
2996
  $freq_desc .= sprintf (__("every %s years",'events-manager'), $EM_Event_Recurring->recurrence_interval);
2997
  }
3005
  /**********************************************************
3006
  * UTILITIES
3007
  ***********************************************************/
3008
+ function to_array( $db = false ){
3009
+ $event_array = parent::to_array($db);
3010
+ //we reset start/end datetimes here, based on the EM_DateTime objects if they are valid
3011
+ $event_array['event_start'] = $this->start()->valid ? $this->start(true)->format('Y-m-d H:i:s') : null;
3012
+ $event_array['event_end'] = $this->end()->valid ? $this->end(true)->format('Y-m-d H:i:s') : null;
3013
+ return apply_filters('em_event_to_array', $event_array, $this);
 
 
 
 
 
 
 
3014
  }
3015
 
3016
  /**
classes/em-events.php CHANGED
@@ -360,6 +360,7 @@ $limit $offset";
360
  $args['page'] = (!empty($args['pagination']) && !empty($_REQUEST['pno']) && is_numeric($_REQUEST['pno']) )? $_REQUEST['pno'] : $args['page'];
361
  $args['offset'] = ($args['page']-1) * $args['limit'];
362
  $args['orderby'] = 'event_start_date,event_start_time,event_name'; // must override this to display events in right cronology.
 
363
 
364
  $args['mode'] = !empty($args['mode']) ? $args['mode'] : get_option('dbem_event_list_groupby');
365
  $args['header_format'] = !empty($args['header_format']) ? $args['header_format'] : get_option('dbem_event_list_groupby_header_format', '<h2>#s</h2>');
@@ -379,12 +380,12 @@ $limit $offset";
379
  $format = (!empty($args['date_format'])) ? $args['date_format']:'Y';
380
  $events_dates = array();
381
  foreach($EM_Events as $EM_Event){ /* @var $EM_Event EM_Event */
382
- $year = date('Y',$EM_Event->start);
383
  $events_dates[$year][] = $EM_Event;
384
  //if long events requested, add event to other dates too
385
- if( empty($args['limit']) && !empty($args['long_events']) && $EM_Event->event_end_date != $EM_Event->event_start_date ) {
386
  $next_year = $year + 1;
387
- $year_end = date('Y', $EM_Event->end);
388
  while( $next_year <= $year_end ){
389
  $events_dates[$next_year][] = $EM_Event;
390
  $next_year = $next_year + 1;
@@ -392,7 +393,8 @@ $limit $offset";
392
  }
393
  }
394
  foreach ($events_dates as $year => $events){
395
- echo str_replace('#s', date_i18n($format,strtotime($year.'-01-01', current_time('timestamp'))), $args['header_format']);
 
396
  echo self::output($events, $atts);
397
  }
398
  break;
@@ -401,18 +403,20 @@ $limit $offset";
401
  $format = (!empty($args['date_format'])) ? $args['date_format']:'M Y';
402
  $events_dates = array();
403
  foreach($EM_Events as $EM_Event){
404
- $events_dates[date('Y-m-'.'01', $EM_Event->start)][] = $EM_Event;
405
  //if long events requested, add event to other dates too
406
- if( empty($args['limit']) && !empty($args['long_events']) && $EM_Event->event_end_date != $EM_Event->event_start_date ) {
407
- $next_month = strtotime("+1 Month", $EM_Event->start);
408
- while( $next_month <= $EM_Event->end ){
409
- $events_dates[date('Y-m-'.'01',$next_month)][] = $EM_Event;
410
- $next_month = strtotime("+1 Month", $next_month);
 
411
  }
412
  }
413
  }
414
  foreach ($events_dates as $month => $events){
415
- echo str_replace('#s', date_i18n($format, strtotime($month, current_time('timestamp'))), $args['header_format']);
 
416
  echo self::output($events, $atts);
417
  }
418
  break;
@@ -420,25 +424,25 @@ $limit $offset";
420
  $format = (!empty($args['date_format'])) ? $args['date_format']:get_option('date_format');
421
  $events_dates = array();
422
  foreach($EM_Events as $EM_Event){
 
423
  $start_of_week = get_option('start_of_week');
424
- $day_of_week = date('w',$EM_Event->start);
425
- $day_of_week = date('w',$EM_Event->start);
426
  $offset = $day_of_week - $start_of_week;
427
  if($offset<0){ $offset += 7; }
428
- $offset = $offset * 60*60*24; //days in seconds
429
- $start_day = strtotime($EM_Event->start_date);
430
- $events_dates[$start_day - $offset][] = $EM_Event;
431
  //if long events requested, add event to other dates too
432
- if( empty($args['limit']) && !empty($args['long_events']) && $EM_Event->event_end_date != $EM_Event->event_start_date ) {
433
- $next_week = $start_day - $offset + (86400 * 7);
434
- while( $next_week <= $EM_Event->end ){
435
- $events_dates[$next_week][] = $EM_Event;
436
- $next_week = $next_week + (86400 * 7);
437
- }
438
  }
439
  }
440
- foreach ($events_dates as $event_day_ts => $events){
441
- echo str_replace('#s', date_i18n($format,$event_day_ts). get_option('dbem_dates_separator') .date_i18n($format,$event_day_ts+(60*60*24*6)), $args['header_format']);
 
442
  echo self::output($events, $atts);
443
  }
444
  break;
@@ -447,19 +451,19 @@ $limit $offset";
447
  $format = (!empty($args['date_format'])) ? $args['date_format']:get_option('date_format');
448
  $events_dates = array();
449
  foreach($EM_Events as $EM_Event){
450
- $event_start_date = strtotime($EM_Event->start_date);
451
- $events_dates[$event_start_date][] = $EM_Event;
452
  //if long events requested, add event to other dates too
453
- if( empty($args['limit']) && !empty($args['long_events']) && $EM_Event->event_end_date != $EM_Event->event_start_date ) {
454
- $tomorrow = $event_start_date + 86400;
455
- while( $tomorrow <= $EM_Event->end ){
456
- $events_dates[$tomorrow][] = $EM_Event;
457
- $tomorrow = $tomorrow + 86400;
458
- }
459
  }
460
  }
461
- foreach ($events_dates as $event_day_ts => $events){
462
- echo str_replace('#s', date_i18n($format,$event_day_ts), $args['header_format']);
463
  echo self::output($events, $atts);
464
  }
465
  break;
@@ -645,6 +649,7 @@ $limit $offset";
645
  'state' => false,
646
  'country' => false,
647
  'region' => false,
 
648
  'blog' => get_current_blog_id(),
649
  'private' => current_user_can('read_private_events'),
650
  'private_only' => false,
360
  $args['page'] = (!empty($args['pagination']) && !empty($_REQUEST['pno']) && is_numeric($_REQUEST['pno']) )? $_REQUEST['pno'] : $args['page'];
361
  $args['offset'] = ($args['page']-1) * $args['limit'];
362
  $args['orderby'] = 'event_start_date,event_start_time,event_name'; // must override this to display events in right cronology.
363
+ $long_events = !empty($args['long_events']);
364
 
365
  $args['mode'] = !empty($args['mode']) ? $args['mode'] : get_option('dbem_event_list_groupby');
366
  $args['header_format'] = !empty($args['header_format']) ? $args['header_format'] : get_option('dbem_event_list_groupby_header_format', '<h2>#s</h2>');
380
  $format = (!empty($args['date_format'])) ? $args['date_format']:'Y';
381
  $events_dates = array();
382
  foreach($EM_Events as $EM_Event){ /* @var $EM_Event EM_Event */
383
+ $year = $EM_Event->start()->format('Y');
384
  $events_dates[$year][] = $EM_Event;
385
  //if long events requested, add event to other dates too
386
+ if( empty($args['limit']) && $long_events && $EM_Event->end()->getDate() != $EM_Event->start()->getDate() ) {
387
  $next_year = $year + 1;
388
+ $year_end = $EM_Event->end()->format('Y');
389
  while( $next_year <= $year_end ){
390
  $events_dates[$next_year][] = $EM_Event;
391
  $next_year = $next_year + 1;
393
  }
394
  }
395
  foreach ($events_dates as $year => $events){
396
+ $EM_DateTime = new EM_DateTime($year.'-01-01');
397
+ echo str_replace('#s', $EM_DateTime->i18n($format), $args['header_format']);
398
  echo self::output($events, $atts);
399
  }
400
  break;
403
  $format = (!empty($args['date_format'])) ? $args['date_format']:'M Y';
404
  $events_dates = array();
405
  foreach($EM_Events as $EM_Event){
406
+ $events_dates[$EM_Event->start()->format('Y-m-01')][] = $EM_Event;
407
  //if long events requested, add event to other dates too
408
+ if( empty($args['limit']) && $long_events && $EM_Event->end()->getDate() != $EM_Event->start()->getDate() ) {
409
+ ///$EM_DateTime is synoymous with the next month here
410
+ $EM_DateTime = $EM_Event->start()->copy()->add('P1M');
411
+ while( $EM_DateTime <= $EM_Event->end() ){
412
+ $events_dates[$EM_DateTime->format('Y-m-01')][] = $EM_Event;
413
+ $EM_DateTime = $EM_DateTime->add('P1M');
414
  }
415
  }
416
  }
417
  foreach ($events_dates as $month => $events){
418
+ $EM_DateTime = new EM_DateTime($month);
419
+ echo str_replace('#s', $EM_DateTime->i18n($format), $args['header_format']);
420
  echo self::output($events, $atts);
421
  }
422
  break;
424
  $format = (!empty($args['date_format'])) ? $args['date_format']:get_option('date_format');
425
  $events_dates = array();
426
  foreach($EM_Events as $EM_Event){
427
+ //obtain start of the week as per WordPress general settings
428
  $start_of_week = get_option('start_of_week');
429
+ $day_of_week = $EM_Event->start()->format('w');
 
430
  $offset = $day_of_week - $start_of_week;
431
  if($offset<0){ $offset += 7; }
432
+ $EM_DateTime = $EM_Event->start()->copy()->sub('P'.$offset.'D');
433
+ //save event to date representing start of week for this WP install based on general settings
434
+ $events_dates[$EM_DateTime->getDate()][] = $EM_Event;
435
  //if long events requested, add event to other dates too
436
+ if( empty($args['limit']) && $long_events && $EM_Event->end()->getDate() != $EM_Event->start()->getDate() ) {
437
+ do{
438
+ $EM_DateTime->add('P1W');
439
+ $events_dates[$EM_DateTime->getDate()][] = $EM_Event;
440
+ }while( $EM_DateTime <= $EM_Event->end() );
 
441
  }
442
  }
443
+ foreach ($events_dates as $date => $events){
444
+ $dates_formatted = $EM_DateTime->modify($date)->i18n($format). get_option('dbem_dates_separator') . $EM_DateTime->add('P6D')->i18n($format);
445
+ echo str_replace('#s', $dates_formatted, $args['header_format']);
446
  echo self::output($events, $atts);
447
  }
448
  break;
451
  $format = (!empty($args['date_format'])) ? $args['date_format']:get_option('date_format');
452
  $events_dates = array();
453
  foreach($EM_Events as $EM_Event){
454
+ $EM_DateTime = $EM_Event->start()->copy()->setTime(0,0,0); /* @var EM_DateTime $EM_DateTime */
455
+ $events_dates[$EM_DateTime->getDate()][] = $EM_Event;
456
  //if long events requested, add event to other dates too
457
+ if( empty($args['limit']) && $long_events && $EM_Event->end()->getDate() != $EM_Event->start()->getDate() ) {
458
+ do{
459
+ $EM_DateTime->add('P1D');
460
+ //store indexes as Y-m-d format so we become timezone independent
461
+ $events_dates[$EM_DateTime->getDate()][] = $EM_Event;
462
+ }while( $EM_DateTime <= $EM_Event->end() );
463
  }
464
  }
465
+ foreach ($events_dates as $date => $events){
466
+ echo str_replace('#s', $EM_DateTime->modify($date)->i18n($format), $args['header_format']);
467
  echo self::output($events, $atts);
468
  }
469
  break;
649
  'state' => false,
650
  'country' => false,
651
  'region' => false,
652
+ 'postcode' => false,
653
  'blog' => get_current_blog_id(),
654
  'private' => current_user_can('read_private_events'),
655
  'private_only' => false,
classes/em-location-post-admin.php CHANGED
@@ -97,6 +97,9 @@ class EM_Location_Post_Admin{
97
  apply_filters('em_location_save', false , $EM_Location);
98
  }else{
99
  apply_filters('em_location_save', true , $EM_Location);
 
 
 
100
  }
101
  }else{
102
  //do a quick and dirty update
@@ -112,9 +115,27 @@ class EM_Location_Post_Admin{
112
  $sql = $wpdb->prepare("UPDATE ".EM_LOCATIONS_TABLE." SET location_name=%s, location_owner=%s, location_slug=%s, location_private=%d, location_status={$location_status} WHERE location_id=%d", $where_array);
113
  $wpdb->query($sql);
114
  apply_filters('em_location_save', true , $EM_Location);
 
 
 
115
  }
116
  }
117
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  public static function before_delete_post($post_id){
120
  if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
97
  apply_filters('em_location_save', false , $EM_Location);
98
  }else{
99
  apply_filters('em_location_save', true , $EM_Location);
100
+ //flag a cache refresh if we get here
101
+ $EM_Location->refresh_cache = true;
102
+ add_filter('save_post', 'EM_Location_Post_Admin::refresh_cache', 100000000);
103
  }
104
  }else{
105
  //do a quick and dirty update
115
  $sql = $wpdb->prepare("UPDATE ".EM_LOCATIONS_TABLE." SET location_name=%s, location_owner=%s, location_slug=%s, location_private=%d, location_status={$location_status} WHERE location_id=%d", $where_array);
116
  $wpdb->query($sql);
117
  apply_filters('em_location_save', true , $EM_Location);
118
+ //flag a cache refresh if we get here
119
+ $EM_Location->refresh_cache = true;
120
+ add_filter('save_post', 'EM_Location_Post_Admin::refresh_cache', 100000000);
121
  }
122
  }
123
  }
124
+
125
+ /**
126
+ * Refreshes the cache of the current global $EM_Location, provided the refresh_cache flag is set to true within the object and the object has a published state
127
+ */
128
+ public static function refresh_cache(){
129
+ global $EM_Location;
130
+ //if this is a published event, and the refresh_cache flag was added to this event during save_post, refresh the meta and update the cache
131
+ if( !empty($EM_Location->refresh_cache) && !empty($EM_Location->post_id) && $EM_Location->is_published() ){
132
+ $post = get_post($EM_Location->post_id);
133
+ $EM_Location->load_postdata($post);
134
+ unset($EM_Location->refresh_cache);
135
+ wp_cache_set($EM_Location->location_id, $EM_Location, 'em_locations');
136
+ wp_cache_set($EM_Location->post_id, $EM_Location->location_id, 'em_locations_ids');
137
+ }
138
+ }
139
 
140
  public static function before_delete_post($post_id){
141
  if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
classes/em-location.php CHANGED
@@ -241,7 +241,7 @@ class EM_Location extends EM_Object {
241
  function get_post($validate = true){
242
  global $allowedtags;
243
  do_action('em_location_get_post_pre', $this);
244
- $this->location_name = ( !empty($_POST['location_name']) ) ? htmlspecialchars_decode(wp_kses_data(htmlspecialchars_decode(wp_unslash($_POST['location_name'])))):'';
245
  $this->post_content = ( !empty($_POST['content']) ) ? wp_kses( wp_unslash($_POST['content']), $allowedtags):'';
246
  $this->get_post_meta(false);
247
  $result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
@@ -388,6 +388,14 @@ class EM_Location extends EM_Object {
388
  if( get_site_option('dbem_ms_mainblog_locations') ){ self::ms_global_switch_back(); }
389
  $return = apply_filters('em_location_save', $post_save && $meta_save, $this );
390
  $EM_SAVING_LOCATION = false;
 
 
 
 
 
 
 
 
391
  return $return;
392
  }
393
 
@@ -468,11 +476,6 @@ class EM_Location extends EM_Object {
468
  }
469
  $this->compat_keys();
470
  $result = count($this->errors) == 0;
471
- //add this location to the cache
472
- if( $result ){
473
- wp_cache_set($this->location_id, $this, 'em_locations');
474
- wp_cache_set($this->post_id, $this->location_id, 'em_locations_ids');
475
- }
476
  return apply_filters('em_location_save_meta', count($this->errors) == 0, $this);
477
  }
478
 
@@ -547,7 +550,8 @@ class EM_Location extends EM_Object {
547
  $post_status = $set_status ? 'publish':'pending';
548
  if( empty($this->post_name) ){
549
  //published or pending posts should have a valid post slug
550
- $this->post_name = sanitize_title($this->post_title);
 
551
  $set_post_name = true;
552
  }
553
  if($set_post_status){
241
  function get_post($validate = true){
242
  global $allowedtags;
243
  do_action('em_location_get_post_pre', $this);
244
+ $this->location_name = ( !empty($_POST['location_name']) ) ? sanitize_post_field('post_title', $_POST['location_name'], $this->post_id, 'db'):'';
245
  $this->post_content = ( !empty($_POST['content']) ) ? wp_kses( wp_unslash($_POST['content']), $allowedtags):'';
246
  $this->get_post_meta(false);
247
  $result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
388
  if( get_site_option('dbem_ms_mainblog_locations') ){ self::ms_global_switch_back(); }
389
  $return = apply_filters('em_location_save', $post_save && $meta_save, $this );
390
  $EM_SAVING_LOCATION = false;
391
+ //reload post data and add this location to the cache, after any other hooks have done their thing
392
+ //cache refresh when saving via admin area is handled in EM_Event_Post_Admin::save_post/refresh_cache
393
+ if( $post_save && $meta_save && $this->is_published() ){
394
+ //we won't depend on hooks, if we saved the event and it's still published in its saved state, refresh the cache regardless
395
+ $this->load_postdata($this);
396
+ wp_cache_set($this->location_id, $this, 'em_locations');
397
+ wp_cache_set($this->post_id, $this->location_id, 'em_locations_ids');
398
+ }
399
  return $return;
400
  }
401
 
476
  }
477
  $this->compat_keys();
478
  $result = count($this->errors) == 0;
 
 
 
 
 
479
  return apply_filters('em_location_save_meta', count($this->errors) == 0, $this);
480
  }
481
 
550
  $post_status = $set_status ? 'publish':'pending';
551
  if( empty($this->post_name) ){
552
  //published or pending posts should have a valid post slug
553
+ $slug = sanitize_title($this->post_title);
554
+ $this->post_name = wp_unique_post_slug( $slug, $this->post_id, $post_status, EM_POST_TYPE_LOCATION, 0);
555
  $set_post_name = true;
556
  }
557
  if($set_post_status){
classes/em-locations.php CHANGED
@@ -444,6 +444,7 @@ $limit $offset
444
  'state' => false,
445
  'country' => false,
446
  'region' => false,
 
447
  'status' => 1, //approved locations only
448
  'scope' => 'all', //we probably want to search all locations by default, not like events
449
  'blog' => get_current_blog_id(),
444
  'state' => false,
445
  'country' => false,
446
  'region' => false,
447
+ 'postcode' => false,
448
  'status' => 1, //approved locations only
449
  'scope' => 'all', //we probably want to search all locations by default, not like events
450
  'blog' => get_current_blog_id(),
classes/em-mailer.php CHANGED
@@ -9,14 +9,14 @@ class EM_Mailer {
9
  * if any errors crop up, here they are
10
  * @var array
11
  */
12
- var $errors = array();
13
 
14
  /**
15
  * @param $subject
16
  * @param $body
17
  * @param $receiver
18
  */
19
- function send($subject="no title",$body="No message specified", $receiver='', $attachments = array() ) {
20
  //TODO add an EM_Error global object, for this sort of error reporting. (@marcus like StatusNotice)
21
  global $smtpsettings, $phpmailer, $cformsSettings;
22
  $subject = html_entity_decode(wp_kses_data($subject)); //decode entities, but run kses first just in case users use placeholders containing html
@@ -36,7 +36,7 @@ class EM_Mailer {
36
  $from = get_option('dbem_mail_sender_address');
37
  $headers = get_option('dbem_mail_sender_name') ? 'From: '.get_option('dbem_mail_sender_name').' <'.$from.'>':'From: '.$from;
38
  if( get_option('dbem_smtp_html') ){ //create filter to change content type to html in wp_mail
39
- add_filter('wp_mail_content_type',create_function('', 'return "text/html";'));
40
  }
41
  $send = wp_mail($receiver, $subject, $body, $headers);
42
  if(!$send){
@@ -112,9 +112,13 @@ class EM_Mailer {
112
  /**
113
  * load phpmailer classes
114
  */
115
- function load_phpmailer(){
116
  require_once ABSPATH . WPINC . '/class-phpmailer.php';
117
  require_once ABSPATH . WPINC . '/class-smtp.php';
118
  }
 
 
 
 
119
  }
120
  ?>
9
  * if any errors crop up, here they are
10
  * @var array
11
  */
12
+ public $errors = array();
13
 
14
  /**
15
  * @param $subject
16
  * @param $body
17
  * @param $receiver
18
  */
19
+ public function send($subject="no title",$body="No message specified", $receiver='', $attachments = array() ) {
20
  //TODO add an EM_Error global object, for this sort of error reporting. (@marcus like StatusNotice)
21
  global $smtpsettings, $phpmailer, $cformsSettings;
22
  $subject = html_entity_decode(wp_kses_data($subject)); //decode entities, but run kses first just in case users use placeholders containing html
36
  $from = get_option('dbem_mail_sender_address');
37
  $headers = get_option('dbem_mail_sender_name') ? 'From: '.get_option('dbem_mail_sender_name').' <'.$from.'>':'From: '.$from;
38
  if( get_option('dbem_smtp_html') ){ //create filter to change content type to html in wp_mail
39
+ add_filter('wp_mail_content_type','EM_Mailer::return_texthtml');
40
  }
41
  $send = wp_mail($receiver, $subject, $body, $headers);
42
  if(!$send){
112
  /**
113
  * load phpmailer classes
114
  */
115
+ public function load_phpmailer(){
116
  require_once ABSPATH . WPINC . '/class-phpmailer.php';
117
  require_once ABSPATH . WPINC . '/class-smtp.php';
118
  }
119
+
120
+ public static function return_texthtml(){
121
+ return "text/html";
122
+ }
123
  }
124
  ?>
classes/em-notices.php CHANGED
File without changes
classes/em-object.php CHANGED
@@ -26,6 +26,7 @@ class EM_Object {
26
  $super_defaults = array(
27
  'limit' => false,
28
  'scope' => 'future',
 
29
  'order' => 'ASC', //hard-coded at end of this function
30
  'orderby' => false,
31
  'groupby' => false,
@@ -113,6 +114,13 @@ class EM_Object {
113
  foreach( array_keys($array) as $key){
114
  if( !array_key_exists($key, $defaults) && !array_key_exists($key, $taxonomies) ) unset($array[$key]);
115
  }
 
 
 
 
 
 
 
116
  //return clean array
117
  $defaults = array_merge ( $defaults, $array ); //No point using WP's cleaning function, we're doing it already.
118
  }
@@ -132,16 +140,16 @@ class EM_Object {
132
  $defaults['year'] = preg_match($year_regex, $defaults['year']) ? $defaults['year']:'';
133
  }
134
  //Deal with scope and date searches
135
- if ( !is_array($defaults['scope']) && preg_match ( "/^([0-9]{4}-[0-9]{2}-[0-9]{2})?,([0-9]{4}-[0-9]{2}-[0-9]{2})?$/", $defaults['scope'] ) ) {
136
  //This is to become an array, so let's split it up
137
  $defaults['scope'] = explode(',', $defaults['scope']);
138
  }
139
  if( is_array($defaults['scope']) ){
140
  //looking for a date range here, so we'll verify the dates validate, if not get the default.
141
- if ( !preg_match("/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $defaults['scope'][0]) ){
142
  $defaults['scope'][0] = '';
143
  }
144
- if( !preg_match("/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $defaults['scope'][1]) ) {
145
  $defaults['scope'][1] = '';
146
  }
147
  if( empty($defaults['scope'][0]) && empty($defaults['scope'][1]) ){
@@ -212,7 +220,6 @@ class EM_Object {
212
  $event = $args['event'];
213
  $month = $args['month'];
214
  $year = $args['year'];
215
- $today = date('Y-m-d', current_time('timestamp'));
216
  //Create the WHERE statement
217
  $conditions = array();
218
 
@@ -270,6 +277,16 @@ class EM_Object {
270
  $conditions['recurring'] = "(`recurrence`!=1 OR `recurrence` IS NULL)";
271
  }
272
  }
 
 
 
 
 
 
 
 
 
 
273
  //Dates - first check 'month', and 'year', and adjust scope if needed
274
  if( !($month=='' && $year=='') ){
275
  //Sort out month range, if supplied an array of array(month,month), it'll check between these two months
@@ -295,7 +312,7 @@ class EM_Object {
295
  $date_end = date('Y-m-t', mktime(0,0,0,$date_month_end,1,$date_year_end));
296
  $scope = array($date_start,$date_end); //just modify the scope here
297
  }
298
- //No date requested, so let's look at scope
299
  if ( is_array($scope) ) {
300
  //This is an array, let's split it up
301
  $date_start = $scope[0];
@@ -319,7 +336,7 @@ class EM_Object {
319
  }
320
  //$conditions['scope'] = " ( ( event_start_date <= CAST('$date_end' AS DATE) AND event_end_date >= CAST('$date_start' AS DATE) ) OR (event_start_date BETWEEN CAST('$date_start' AS DATE) AND CAST('$date_end' AS DATE)) OR (event_end_date BETWEEN CAST('$date_start' AS DATE) AND CAST('$date_end' AS DATE)) )";
321
  }
322
- } elseif ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
323
  //Scope can also be a specific date. However, if 'day', 'month', or 'year' are set, that will take precedence
324
  if( get_option('dbem_events_current_are_past') ){
325
  $conditions['scope'] = "event_start_date = CAST('$scope' AS DATE)";
@@ -327,50 +344,44 @@ class EM_Object {
327
  $conditions['scope'] = " ( event_start_date = CAST('$scope' AS DATE) OR ( event_start_date <= CAST('$scope' AS DATE) AND event_end_date >= CAST('$scope' AS DATE) ) )";
328
  }
329
  } else {
 
330
  if ($scope == "past"){
331
  if( get_option('dbem_events_current_are_past') ){
332
- $conditions['scope'] = " event_start_date < '$today'";
333
  }else{
334
- $conditions['scope'] = " event_end_date < '$today'";
335
  }
336
  }elseif ($scope == "today"){
337
- $conditions['scope'] = " (event_start_date = CAST('$today' AS DATE))";
338
  if( !get_option('dbem_events_current_are_past') ){
339
- $conditions['scope'] .= " OR (event_start_date <= CAST('$today' AS DATE) AND event_end_date >= CAST('$today' AS DATE))";
340
  }
341
  }elseif ($scope == "tomorrow"){
342
- $tomorrow = date('Y-m-d',current_time('timestamp')+60*60*24);
343
- $conditions['scope'] = "(event_start_date = CAST('$tomorrow' AS DATE))";
344
  if( !get_option('dbem_events_current_are_past') ){
345
- $conditions['scope'] .= " OR (event_start_date <= CAST('$tomorrow' AS DATE) AND event_end_date >= CAST('$tomorrow' AS DATE))";
346
  }
347
- }elseif ($scope == "month"){
348
- $start_month = date('Y-m-d',current_time('timestamp'));
349
- $end_month = date('Y-m-t',current_time('timestamp'));
350
- $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))";
351
- if( !get_option('dbem_events_current_are_past') ){
352
- $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))";
353
- }
354
- }elseif ($scope == "next-month"){
355
- $start_month_timestamp = strtotime('+1 month', current_time('timestamp')); //get the end of this month + 1 day
356
- $start_month = date('Y-m-1',$start_month_timestamp);
357
- $end_month = date('Y-m-t',$start_month_timestamp);
358
  $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))";
359
  if( !get_option('dbem_events_current_are_past') ){
360
  $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))";
361
  }
362
  }elseif( preg_match('/([0-9]+)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
363
  $months_to_add = $matches[1];
364
- $start_month = date('Y-m-d',current_time('timestamp'));
365
- $end_month = date('Y-m-t',strtotime("+$months_to_add month", current_time('timestamp')));
366
  $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))";
367
  if( !get_option('dbem_events_current_are_past') ){
368
  $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))";
369
  }
370
  }elseif ($scope == "future"){
371
- $conditions['scope'] = " event_start_date >= CAST('$today' AS DATE)";
372
  if( !get_option('dbem_events_current_are_past') ){
373
- $conditions['scope'] .= " OR (event_end_date >= CAST('$today' AS DATE) AND event_end_date != '0000-00-00' AND event_end_date IS NOT NULL)";
374
  }
375
  }
376
  if( !empty($conditions['scope']) ){
@@ -451,6 +462,10 @@ class EM_Object {
451
  if( !empty($args['region']) ){
452
  $conditions['region'] = $wpdb->prepare('location_region=%s', $args['region']);
453
  }
 
 
 
 
454
  }
455
 
456
  //START TAXONOMY FILTERS - can be id, slug, name or comma separated ids/slugs/names, if negative or prepended with a - then considered a negative filter
@@ -613,7 +628,7 @@ class EM_Object {
613
  }
614
 
615
  /**
616
- * WORK IN PROGRESS
617
  * Builds an array of SQL query conditions based on regularly used arguments
618
  * @param array $args
619
  * @return array
@@ -636,7 +651,6 @@ class EM_Object {
636
  $event = $args['event'];
637
  $month = $args['month'];
638
  $year = $args['year'];
639
- $today = date('Y-m-d', current_time('timestamp'));
640
  //Create the WHERE statement
641
 
642
  //Recurrences
@@ -670,88 +684,57 @@ class EM_Object {
670
  $scope = array($date_start,$date_end); //just modify the scope here
671
  }
672
  //No date requested, so let's look at scope
673
- $time = current_time('timestamp');
674
- if ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
675
- $today = strtotime($scope);
676
- $tomorrow = $today + 60*60*24-1;
677
- if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
678
- $query[] = array( 'key' => '_start_ts', 'value' => array($today,$tomorrow), 'compare' => 'BETWEEN' );
679
- }else{
680
- $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' );
681
- $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
682
- }
683
- }elseif ( is_array($scope) || preg_match( "/^[0-9]{4}-[0-9]{2}-[0-9]{2},[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
684
  if( !is_array($scope) ) $scope = explode(',',$scope);
685
  if( !empty($scope[0]) ){
686
- $start = strtotime(date('Y-m-d',$scope[0]));
687
- $end = !empty($scope[1]) ? strtotime(date('Y-m-t',$scope[1])):$start;
 
688
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
689
- $query[] = array( 'key' => '_start_ts', 'value' => array($start,$end), 'type' => 'numeric', 'compare' => 'BETWEEN');
690
  }else{
691
- $query[] = array( 'key' => '_start_ts', 'value' => $end, 'compare' => '<=' );
692
- $query[] = array( 'key' => '_end_ts', 'value' => $start, 'compare' => '>=' );
693
  }
694
  }
695
- }elseif ($scope == "future"){
696
- $today = strtotime(date('Y-m-d', $time));
697
- if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
698
- $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' );
699
- }else{
700
- $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
701
- }
702
- }elseif ($scope == "past"){
703
- $today = strtotime(date('Y-m-d', $time));
704
- if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
705
- $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<' );
706
- }else{
707
- $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '<' );
708
- }
709
- }elseif ($scope == "today"){
710
- $today = strtotime(date('Y-m-d', $time));
711
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
712
- //date must be only today
713
- $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '=');
714
  }else{
715
- $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<=' );
716
- $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
717
- }
718
- }elseif ($scope == "tomorrow"){
719
- $tomorrow = strtotime(date('Y-m-d',$time+60*60*24));
720
- if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
721
- //date must be only tomorrow
722
- $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '=');
723
- }else{
724
- $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' );
725
- $query[] = array( 'key' => '_end_ts', 'value' => $tomorrow, 'compare' => '>=' );
726
- }
727
- }elseif ($scope == "month"){
728
- $start_month = strtotime(date('Y-m-d',$time));
729
- $end_month = strtotime(date('Y-m-t',$time));
730
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
731
- $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
732
  }else{
733
- $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
734
- $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
735
  }
736
- }elseif ($scope == "next-month"){
737
- $start_month_timestamp = strtotime('+1 month', $time); //get the end of this month + 1 day
738
- $start_month = strtotime(date('Y-m-1',$start_month_timestamp));
739
- $end_month = strtotime(date('Y-m-t',$start_month_timestamp));
 
740
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
741
- $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
742
  }else{
743
- $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
744
- $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
745
  }
746
  }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
 
747
  $months_to_add = $matches[1];
748
- $start_month = strtotime(date('Y-m-d',$time));
749
- $end_month = strtotime(date('Y-m-t',strtotime("+$months_to_add month", $time)));
750
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
751
- $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
752
  }else{
753
- $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
754
- $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
755
  }
756
  }
757
 
@@ -1061,7 +1044,7 @@ class EM_Object {
1061
  * @return string
1062
  * @uses em_paginate()
1063
  */
1064
- public static function get_pagination_links($args, $count, $search_action, $default_args = array()){
1065
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
1066
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
1067
  $pno = !empty($args['page_queryvar']) ? $args['page_queryvar'] : 'pno';
@@ -1233,8 +1216,10 @@ class EM_Object {
1233
  */
1234
  function compat_keys(){
1235
  foreach($this->fields as $key => $fieldinfo){
1236
- $field_name = $fieldinfo['name'];
1237
- if(!empty($this->$key)) $this->$field_name = $this->$key;
 
 
1238
  }
1239
  }
1240
 
26
  $super_defaults = array(
27
  'limit' => false,
28
  'scope' => 'future',
29
+ 'timezone' => false, //default blog timezone
30
  'order' => 'ASC', //hard-coded at end of this function
31
  'orderby' => false,
32
  'groupby' => false,
114
  foreach( array_keys($array) as $key){
115
  if( !array_key_exists($key, $defaults) && !array_key_exists($key, $taxonomies) ) unset($array[$key]);
116
  }
117
+ //Timezone
118
+ if( !empty($array['timezone']) ){
119
+ if( !is_array($array['timezone']) ) {
120
+ $array['timezone'] = str_replace(' ', '', $array['timezone']);
121
+ $array['timezone'] = explode(',', $array['timezone']);
122
+ }
123
+ }
124
  //return clean array
125
  $defaults = array_merge ( $defaults, $array ); //No point using WP's cleaning function, we're doing it already.
126
  }
140
  $defaults['year'] = preg_match($year_regex, $defaults['year']) ? $defaults['year']:'';
141
  }
142
  //Deal with scope and date searches
143
+ if ( !is_array($defaults['scope']) && preg_match ( "/^([0-9]{4}-[0-9]{1,2}-[0-9]{1,2})?,([0-9]{4}-[0-9]{1,2}-[0-9]{1,2})?$/", $defaults['scope'] ) ) {
144
  //This is to become an array, so let's split it up
145
  $defaults['scope'] = explode(',', $defaults['scope']);
146
  }
147
  if( is_array($defaults['scope']) ){
148
  //looking for a date range here, so we'll verify the dates validate, if not get the default.
149
+ if ( !preg_match("/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/", $defaults['scope'][0]) ){
150
  $defaults['scope'][0] = '';
151
  }
152
+ if( !preg_match("/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/", $defaults['scope'][1]) ) {
153
  $defaults['scope'][1] = '';
154
  }
155
  if( empty($defaults['scope'][0]) && empty($defaults['scope'][1]) ){
220
  $event = $args['event'];
221
  $month = $args['month'];
222
  $year = $args['year'];
 
223
  //Create the WHERE statement
224
  $conditions = array();
225
 
277
  $conditions['recurring'] = "(`recurrence`!=1 OR `recurrence` IS NULL)";
278
  }
279
  }
280
+
281
+ //Timezone - search for events in a specific timezone
282
+ if( !empty($args['timezone']) ){
283
+ if( !is_array($args['timezone']) ){
284
+ $args['timezone'] = explode(',', $args['timezone']);
285
+ }
286
+ foreach( $args['timezone'] as $tz ) $timezones[] = $wpdb->prepare('%s', $tz);
287
+ $conditions['timezone'] = '`event_timezone` IN ('.implode(',', $timezones).')';
288
+ }
289
+
290
  //Dates - first check 'month', and 'year', and adjust scope if needed
291
  if( !($month=='' && $year=='') ){
292
  //Sort out month range, if supplied an array of array(month,month), it'll check between these two months
312
  $date_end = date('Y-m-t', mktime(0,0,0,$date_month_end,1,$date_year_end));
313
  $scope = array($date_start,$date_end); //just modify the scope here
314
  }
315
+ //Build scope query
316
  if ( is_array($scope) ) {
317
  //This is an array, let's split it up
318
  $date_start = $scope[0];
336
  }
337
  //$conditions['scope'] = " ( ( event_start_date <= CAST('$date_end' AS DATE) AND event_end_date >= CAST('$date_start' AS DATE) ) OR (event_start_date BETWEEN CAST('$date_start' AS DATE) AND CAST('$date_end' AS DATE)) OR (event_end_date BETWEEN CAST('$date_start' AS DATE) AND CAST('$date_end' AS DATE)) )";
338
  }
339
+ } elseif ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{1,2}$/", $scope ) ) {
340
  //Scope can also be a specific date. However, if 'day', 'month', or 'year' are set, that will take precedence
341
  if( get_option('dbem_events_current_are_past') ){
342
  $conditions['scope'] = "event_start_date = CAST('$scope' AS DATE)";
344
  $conditions['scope'] = " ( event_start_date = CAST('$scope' AS DATE) OR ( event_start_date <= CAST('$scope' AS DATE) AND event_end_date >= CAST('$scope' AS DATE) ) )";
345
  }
346
  } else {
347
+ $EM_DateTime = new EM_DateTime(); //the time, now, in blog/site timezone
348
  if ($scope == "past"){
349
  if( get_option('dbem_events_current_are_past') ){
350
+ $conditions['scope'] = " event_start < '".$EM_DateTime->getDateTime(true)."'";
351
  }else{
352
+ $conditions['scope'] = " event_end < '".$EM_DateTime->getDateTime(true)."'";
353
  }
354
  }elseif ($scope == "today"){
355
+ $conditions['scope'] = " (event_start_date = CAST('".$EM_DateTime->getDate()."' AS DATE))";
356
  if( !get_option('dbem_events_current_are_past') ){
357
+ $conditions['scope'] .= " OR (event_start_date <= CAST('".$EM_DateTime->getDate()."' AS DATE) AND event_end_date >= CAST('$EM_DateTime' AS DATE))";
358
  }
359
  }elseif ($scope == "tomorrow"){
360
+ $EM_DateTime->modify('+1 day');
361
+ $conditions['scope'] = "(event_start_date = CAST('".$EM_DateTime->getDate()."' AS DATE))";
362
  if( !get_option('dbem_events_current_are_past') ){
363
+ $conditions['scope'] .= " OR (event_start_date <= CAST('".$EM_DateTime->getDate()."' AS DATE) AND event_end_date >= CAST('".$EM_DateTime->getDate()."' AS DATE))";
364
  }
365
+ }elseif ($scope == "month" || $scope == "next-month"){
366
+ if( $scope == 'next-month' ) $EM_DateTime->add('P1M');
367
+ $start_month = $EM_DateTime->modify('first day of this month')->getDate();
368
+ $end_month = $EM_DateTime->modify('last day of this month')->getDate();
 
 
 
 
 
 
 
369
  $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))";
370
  if( !get_option('dbem_events_current_are_past') ){
371
  $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))";
372
  }
373
  }elseif( preg_match('/([0-9]+)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
374
  $months_to_add = $matches[1];
375
+ $start_month = $EM_DateTime->getDate();
376
+ $end_month = $EM_DateTime->add('P'.$months_to_add.'M')->format('Y-m-t');
377
  $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))";
378
  if( !get_option('dbem_events_current_are_past') ){
379
  $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))";
380
  }
381
  }elseif ($scope == "future"){
382
+ $conditions['scope'] = " event_start >= '".$EM_DateTime->getDateTime(true)."'";
383
  if( !get_option('dbem_events_current_are_past') ){
384
+ $conditions['scope'] .= " OR (event_end >= '".$EM_DateTime->getDateTime(true)."')";
385
  }
386
  }
387
  if( !empty($conditions['scope']) ){
462
  if( !empty($args['region']) ){
463
  $conditions['region'] = $wpdb->prepare('location_region=%s', $args['region']);
464
  }
465
+ //postcode lookup
466
+ if( !empty($args['postcode']) ){
467
+ $conditions['postcode'] = $wpdb->prepare('location_postcode=%s', $args['postcode']);
468
+ }
469
  }
470
 
471
  //START TAXONOMY FILTERS - can be id, slug, name or comma separated ids/slugs/names, if negative or prepended with a - then considered a negative filter
628
  }
629
 
630
  /**
631
+ * WORK IN PROGRESS - not recommended for production use due to lack of syncing with regular condition builder and timezones feature
632
  * Builds an array of SQL query conditions based on regularly used arguments
633
  * @param array $args
634
  * @return array
651
  $event = $args['event'];
652
  $month = $args['month'];
653
  $year = $args['year'];
 
654
  //Create the WHERE statement
655
 
656
  //Recurrences
684
  $scope = array($date_start,$date_end); //just modify the scope here
685
  }
686
  //No date requested, so let's look at scope
687
+ if ( is_array($scope) || preg_match( "/^[0-9]{4}-[0-9]{2}-[0-9]{2},[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
 
 
 
 
 
 
 
 
 
 
688
  if( !is_array($scope) ) $scope = explode(',',$scope);
689
  if( !empty($scope[0]) ){
690
+ $EM_DateTime = new EM_DateTime($scope[0]); //create default time in blog timezone
691
+ $start_date = $EM_DateTime->getDate();
692
+ $end_date = $EM_DateTime->modify($scope[1])->getDate();
693
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
694
+ $query[] = array( 'key' => '_event_start_date', 'value' => array($start_date,$end_date), 'type' => 'DATE', 'compare' => 'BETWEEN');
695
  }else{
696
+ $query[] = array( 'key' => '_event_start_date', 'value' => $end_date, 'compare' => '<=', 'type' => 'DATE' );
697
+ $query[] = array( 'key' => '_event_end_date', 'value' => $start_date, 'compare' => '>=', 'type' => 'DATE' );
698
  }
699
  }
700
+ }elseif ( $scope == 'today' || $scope == 'tomorrow' || preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
701
+ $EM_DateTime = new EM_DateTime($scope); //create default time in blog timezone
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
703
+ $query[] = array( 'key' => '_event_start_date', 'value' => $EM_DateTime->getDate() );
 
704
  }else{
705
+ $query[] = array( 'key' => '_event_start_date', 'value' => $EM_DateTime->getDate(), 'compare' => '<=', 'type' => 'DATE' );
706
+ $query[] = array( 'key' => '_event_end_date', 'value' => $EM_DateTime->getDate(), 'compare' => '>=', 'type' => 'DATE' );
707
+ }
708
+ }elseif ($scope == "future" || $scope == 'past' ){
709
+ $EM_DateTime = new EM_DateTime(); //create default time in blog timezone
710
+ $EM_DateTime->setTimezone('UTC');
711
+ $compare = $scope == 'future' ? '>=' : '<';
 
 
 
 
 
 
 
 
712
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
713
+ $query[] = array( 'key' => '_event_start', 'value' => $EM_DateTime->getDateTime(), 'compare' => $compare, 'type' => 'DATETIME' );
714
  }else{
715
+ $query[] = array( 'key' => '_event_end', 'value' => $EM_DateTime->getDateTime(), 'compare' => $compare, 'type' => 'DATETIME' );
 
716
  }
717
+ }elseif ($scope == "month" || $scope == "next-month" ){
718
+ $EM_DateTime = new EM_DateTime(); //create default time in blog timezone
719
+ if( $scope == 'next-month' ) $EM_DateTime->add('P1M');
720
+ $start_month = $EM_DateTime->modify('first day of this month')->getDate();
721
+ $end_month = $EM_DateTime->modify('last day of this month')->getDate();
722
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
723
+ $query[] = array( 'key' => '_event_start_date', 'value' => array($start_month,$end_month), 'type' => 'DATE', 'compare' => 'BETWEEN');
724
  }else{
725
+ $query[] = array( 'key' => '_event_start_date', 'value' => $end_month, 'compare' => '<=', 'type' => 'DATE' );
726
+ $query[] = array( 'key' => '_event_end_date', 'value' => $start_month, 'compare' => '>=', 'type' => 'DATE' );
727
  }
728
  }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
729
+ $EM_DateTime = new EM_DateTime(); //create default time in blog timezone
730
  $months_to_add = $matches[1];
731
+ $start_month = $EM_DateTime->getDate();
732
+ $end_month = $EM_DateTime->add('P'.$months_to_add.'M')->format('Y-m-t');
733
  if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
734
+ $query[] = array( 'key' => '_event_start_date', 'value' => array($start_month,$end_month), 'type' => 'DATE', 'compare' => 'BETWEEN');
735
  }else{
736
+ $query[] = array( 'key' => '_event_start_date', 'value' => $end_month, 'compare' => '<=', 'type' => 'DATE' );
737
+ $query[] = array( 'key' => '_event_end_date', 'value' => $start_month, 'compare' => '>=', 'type' => 'DATE' );
738
  }
739
  }
740
 
1044
  * @return string
1045
  * @uses em_paginate()
1046
  */
1047
+ public static function get_pagination_links($args, $count, $search_action = 'search_events', $default_args = array()){
1048
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
1049
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
1050
  $pno = !empty($args['page_queryvar']) ? $args['page_queryvar'] : 'pno';
1216
  */
1217
  function compat_keys(){
1218
  foreach($this->fields as $key => $fieldinfo){
1219
+ if( !empty($fieldinfo['name']) ){
1220
+ $field_name = $fieldinfo['name'];
1221
+ if(!empty($this->$key)) $this->$field_name = $this->$key;
1222
+ }
1223
  }
1224
  }
1225
 
classes/em-options.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An interface for the dbem_data option stored in wp_options as a serialized array.
4
+ * This option can hold various information which can be stored in one record rather than individual records in wp_options.
5
+ * The functions in this class deal directly with that dbem_data option as if it was the wp_options table itself, and therefore
6
+ * have similarities to the get_option and update_option functions.
7
+ * @since 5.8.2.0
8
+ *
9
+ */
10
+ class EM_Options {
11
+
12
+ /**
13
+ * Get a specific setting form the EM options array. If no value is set, an empty array is provided by default.
14
+ * @param string $option_name
15
+ * @param mixed $default the default value to return
16
+ * @param boolean $site if set to true it'll retrieve a site option in MultiSite instead
17
+ * @return mixed
18
+ */
19
+ public static function get( $option_name, $default = array(), $site = false ){
20
+ $data = $site ? get_site_option('dbem_data') : get_option('dbem_data');
21
+ if( !empty($data[$option_name]) ){
22
+ return $data[$option_name];
23
+ }else{
24
+ return $default;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Set a value in the EM options array. Returns result of storage, which may be false if no changes are made.
30
+ * @param string $option_name
31
+ * @param mixed $option_value
32
+ * @param boolean $site if set to true it'll retrieve a site option in MultiSite instead
33
+ * @return boolean
34
+ */
35
+ public static function set( $option_name, $option_value, $site = false ){
36
+ $data = $site ? get_site_option('dbem_data') : get_option('dbem_data');
37
+ $data[$option_name] = $option_value;
38
+ return $site ? update_site_option('dbem_data', $data) : update_option('dbem_data', $data);
39
+ }
40
+
41
+ /**
42
+ * Adds a value to an specific key in the EM options array, and assumes the option name is an array.
43
+ * Returns true on success or false saving failed or if no changes made.
44
+ * @param string $option_name
45
+ * @param string $option_key
46
+ * @param mixed $option_value
47
+ * @param boolean $site
48
+ * @return boolean
49
+ */
50
+ public static function add( $option_name, $option_key, $option_value, $site = false ){
51
+ $data = $site ? get_site_option('dbem_data') : get_option('dbem_data');
52
+ if( empty($data[$option_name]) ){
53
+ $data[$option_name] = array( $option_key => $option_value );
54
+ }else{
55
+ $data[$option_name][$option_key] = $option_value;
56
+ }
57
+ return $site ? update_site_option('dbem_data', $data) : update_option('dbem_data', $data);
58
+ }
59
+
60
+ /**
61
+ * Removes an item from an array in the EM options array, it assumes the supplied option name is an array.
62
+ *
63
+ * @param string $option_name
64
+ * @param string $option_key
65
+ * @param string $site
66
+ * @return boolean
67
+ */
68
+ public static function remove( $option_name, $option_key, $site = false ){
69
+ $data = $site ? get_site_option('dbem_data') : get_option('dbem_data');
70
+ if( !empty($data[$option_name][$option_key]) ){
71
+ unset($data[$option_name][$option_key]);
72
+ if( empty($data[$option_name]) ) unset($data[$option_name]);
73
+ return $site ? update_site_option('dbem_data', $data) : update_option('dbem_data', $data);
74
+ }
75
+ return false;
76
+ }
77
+
78
+ /**
79
+ * @see EM_Options::get()
80
+ */
81
+ public static function site_get( $option_name, $default = array() ){
82
+ return self::get( $option_name, $default, true );
83
+ }
84
+
85
+ /**
86
+ * @see EM_Options::set()
87
+ */
88
+ public static function site_set( $option_name, $option_value ){
89
+ return self::set( $option_name, $option_value, true );
90
+ }
91
+
92
+ /**
93
+ * @see EM_Options::add()
94
+ */
95
+ public static function site_add( $option_name, $option_key, $option_value ){
96
+ return self::add( $option_name, $option_key, $option_value, true );
97
+ }
98
+
99
+ /**
100
+ * @see EM_Options::remove()
101
+ */
102
+ public static function site_remove( $option_name, $option_key ){
103
+ return self::remove( $option_name, $option_key, true );
104
+ }
105
+ }
classes/em-people.php CHANGED
File without changes
classes/em-permalinks.php CHANGED
@@ -208,7 +208,7 @@ if( !class_exists('EM_Permalinks') ){
208
  $taxonomies = EM_Object::get_taxonomies();
209
  foreach($taxonomies as $tax_arg => $taxonomy_info){
210
  //set the dynamic rule for this taxonomy
211
- $em_rules[$taxonomy_info['slug']."/([^/]+)/ical/?$"] = 'index.php?'.$taxonomy_info['query_var'].'=$matches[1]&ical=1';
212
  }
213
  //add RSS location CPT endpoint
214
  if( get_option('dbem_locations_enabled') ){
208
  $taxonomies = EM_Object::get_taxonomies();
209
  foreach($taxonomies as $tax_arg => $taxonomy_info){
210
  //set the dynamic rule for this taxonomy
211
+ $em_rules[$taxonomy_info['slug']."/(.+)/ical/?$"] = 'index.php?'.$taxonomy_info['query_var'].'=$matches[1]&ical=1';
212
  }
213
  //add RSS location CPT endpoint
214
  if( get_option('dbem_locations_enabled') ){
classes/em-person.php CHANGED
File without changes
classes/em-tag.php CHANGED
@@ -14,7 +14,7 @@ class EM_Tag extends EM_Taxonomy_Term {
14
  * @param string $class_name
15
  * @return EM_Taxonomy
16
  */
17
- public static function get( $id = false, $class_name = 'EM_Tag' ){
18
  return parent::get($id, $class_name);
19
  }
20
 
@@ -27,8 +27,8 @@ class EM_Tag extends EM_Taxonomy_Term {
27
  * Get an category in a db friendly way, by checking globals and passed variables to avoid extra class instantiations
28
  * @param mixed $id
29
  * @return EM_Category
30
- * @uses EM_Category::get()
31
  */
32
- function em_get_tag( $id = false ) {
33
  return EM_Tag::get($id);
34
  }
14
  * @param string $class_name
15
  * @return EM_Taxonomy
16
  */
17
+ public static function get( $id, $class_name = 'EM_Tag' ){
18
  return parent::get($id, $class_name);
19
  }
20
 
27
  * Get an category in a db friendly way, by checking globals and passed variables to avoid extra class instantiations
28
  * @param mixed $id
29
  * @return EM_Category
30
+ * @uses EM_Tag::get()
31
  */
32
+ function em_get_tag( $id ) {
33
  return EM_Tag::get($id);
34
  }
classes/em-tags-admin.php CHANGED
File without changes
classes/em-tags-frontend.php CHANGED
File without changes
classes/em-tags.php CHANGED
@@ -5,6 +5,7 @@ class EM_Tags extends EM_Taxonomy_Terms {
5
  protected $meta_key = 'event-tags';
6
  protected $terms_name = 'tags';
7
  protected $term_class = 'EM_Tag';
 
8
 
9
  /**
10
  * Creates an EM_Tags instance, currently accepts an EM_Event object (gets all Categories for that event) or array of any EM_Category objects, which can be manipulated in bulk with helper functions.
@@ -52,7 +53,7 @@ class EM_Tags extends EM_Taxonomy_Terms {
52
  return parent::output($args);
53
  }
54
 
55
- public static function get_pagination_links($args, $count, $search_action = 'search_cats', $default_args = array()){
56
  self::$instance = new EM_Tags();
57
  return parent::get_pagination_links($args, $count, $search_action, $default_args);
58
  }
5
  protected $meta_key = 'event-tags';
6
  protected $terms_name = 'tags';
7
  protected $term_class = 'EM_Tag';
8
+ protected $ajax_search_action = 'search_tags';
9
 
10
  /**
11
  * Creates an EM_Tags instance, currently accepts an EM_Event object (gets all Categories for that event) or array of any EM_Category objects, which can be manipulated in bulk with helper functions.
53
  return parent::output($args);
54
  }
55
 
56
+ public static function get_pagination_links($args, $count, $search_action = 'search_tags', $default_args = array()){
57
  self::$instance = new EM_Tags();
58
  return parent::get_pagination_links($args, $count, $search_action, $default_args);
59
  }
classes/em-taxonomy-admin.php CHANGED
File without changes
classes/em-taxonomy-frontend.php CHANGED
@@ -124,17 +124,20 @@ class EM_Taxonomy_Frontend {
124
  if( !$wp_query->is_main_query() ) return;
125
  if( $wp_query->is_tax(self::$taxonomy_name) ){
126
  //Scope is future
127
- $today = strtotime(date('Y-m-d', current_time('timestamp')));
128
  if( get_option('dbem_events_current_are_past') ){
129
- $wp_query->query_vars['meta_query'][] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' );
130
  }else{
131
- $wp_query->query_vars['meta_query'][] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
132
  }
133
  if( get_option('dbem_'. self::$option_name_plural .'_default_archive_orderby') == 'title'){
134
  $wp_query->query_vars['orderby'] = 'title';
135
  }else{
136
- $wp_query->query_vars['orderby'] = 'meta_value_num';
137
- $wp_query->query_vars['meta_key'] = get_option('dbem_'. self::$option_name_plural .'_default_archive_orderby','_start_ts');
 
 
 
138
  }
139
  $wp_query->query_vars['order'] = get_option('dbem_'. self::$option_name_plural .'_default_archive_order','ASC');
140
  $post_types = $wp_query->get( 'post_type');
124
  if( !$wp_query->is_main_query() ) return;
125
  if( $wp_query->is_tax(self::$taxonomy_name) ){
126
  //Scope is future
127
+ $today = current_time('mysql');
128
  if( get_option('dbem_events_current_are_past') ){
129
+ $wp_query->query_vars['meta_query'][] = array( 'key' => '_event_start', 'value' => $today, 'compare' => '>=', 'type' => 'DATETIME' );
130
  }else{
131
+ $wp_query->query_vars['meta_query'][] = array( 'key' => '_event_end', 'value' => $today, 'compare' => '>=', 'type' => 'DATETIME' );
132
  }
133
  if( get_option('dbem_'. self::$option_name_plural .'_default_archive_orderby') == 'title'){
134
  $wp_query->query_vars['orderby'] = 'title';
135
  }else{
136
+ $wp_query->query_vars['orderby'] = 'meta_value';
137
+ $wp_query->query_vars['meta_key'] = get_option('dbem_'. self::$option_name_plural .'_default_archive_orderby');
138
+ if( in_array($wp_query->query_vars['meta_key'], array('_event_start', '_event_end', '_event_start_local', '_event_end_local')) ){
139
+ $wp_query->query_vars['meta_type'] = 'DATETIME';
140
+ }
141
  }
142
  $wp_query->query_vars['order'] = get_option('dbem_'. self::$option_name_plural .'_default_archive_order','ASC');
143
  $post_types = $wp_query->get( 'post_type');
classes/em-taxonomy-term.php CHANGED
@@ -65,7 +65,7 @@ class EM_Taxonomy_Term extends EM_Object {
65
  * @param string $taxonomy_class The name of the EM class used for this taxonomy.
66
  * @return EM_Taxonomy
67
  */
68
- public static function get( $id, $taxonomy_class ){
69
  //check if it's not already global so we don't instantiate again
70
  $EM_Taxonomy = !empty( $GLOBALS[$taxonomy_class] ) ? $GLOBALS[$taxonomy_class] : '';
71
  if( is_object($EM_Taxonomy) && get_class($EM_Taxonomy) == $taxonomy_class ){
@@ -75,7 +75,7 @@ class EM_Taxonomy_Term extends EM_Object {
75
  return $EM_Taxonomy;
76
  }
77
  }
78
- if( is_object($id) && get_class($id) == '$taxonomy_class' ){
79
  return $id;
80
  }else{
81
  return new $taxonomy_class($id);
65
  * @param string $taxonomy_class The name of the EM class used for this taxonomy.
66
  * @return EM_Taxonomy
67
  */
68
+ public static function get( $id, $taxonomy_class = 'EM_Taxonomy_Term' ){
69
  //check if it's not already global so we don't instantiate again
70
  $EM_Taxonomy = !empty( $GLOBALS[$taxonomy_class] ) ? $GLOBALS[$taxonomy_class] : '';
71
  if( is_object($EM_Taxonomy) && get_class($EM_Taxonomy) == $taxonomy_class ){
75
  return $EM_Taxonomy;
76
  }
77
  }
78
+ if( is_object($id) && get_class($id) == $taxonomy_class ){
79
  return $id;
80
  }else{
81
  return new $taxonomy_class($id);
classes/em-taxonomy-terms.php CHANGED
@@ -6,6 +6,11 @@ class EM_Taxonomy_Terms extends EM_Object implements Iterator{
6
  protected $taxonomy = 'event-taxonomy';
7
  protected $terms_name = 'taxonomies';
8
  protected $term_class = 'EM_Taxonomy';
 
 
 
 
 
9
 
10
  /**
11
  * Blank instance of this class used in the static functions until PHP 5.3 brings us LSB
@@ -17,17 +22,17 @@ class EM_Taxonomy_Terms extends EM_Object implements Iterator{
17
  * Array of EM_Taxonomy_Term child objects for a specific event
18
  * @var array
19
  */
20
- var $terms = array();
21
  /**
22
  * Event ID of this set of taxonomy terms
23
  * @var int
24
  */
25
- var $event_id;
26
  /**
27
  * Post ID of this set of taxonomy terms
28
  * @var int
29
  */
30
- var $post_id;
31
 
32
  /**
33
  * Creates an EM_Taxonomy_Terms instance, currently accepts an EM_Event object (gets all Taxonomy Terms for that event) or array of any EM_Taxonomy_Term objects, which can be manipulated in bulk with helper functions.
@@ -256,8 +261,9 @@ class EM_Taxonomy_Terms extends EM_Object implements Iterator{
256
  return apply_filters('em_'. self::$instance->terms_name .'_output', $output, $terms, $args);
257
  }
258
 
259
- public static function get_pagination_links($args, $count, $search_action = 'search_cats', $default_args = array()){
260
  //get default args if we're in a search, supply to parent since we can't depend on late static binding until WP requires PHP 5.3 or later
 
261
  if( empty($default_args) && (!empty($args['ajax']) || !empty($_REQUEST['action']) && $_REQUEST['action'] == $search_action) ){
262
  $default_args = self::get_default_search();
263
  $default_args['limit'] = get_option('dbem_'. self::$instance->terms_name .'_default_limit');
6
  protected $taxonomy = 'event-taxonomy';
7
  protected $terms_name = 'taxonomies';
8
  protected $term_class = 'EM_Taxonomy';
9
+ /**
10
+ * String representing the search action used in AJAX searches which will be available in child function when PHP 5.3 brings us LSB
11
+ * @var string
12
+ */
13
+ protected $ajax_search_action = 'search_taxonomy';
14
 
15
  /**
16
  * Blank instance of this class used in the static functions until PHP 5.3 brings us LSB
22
  * Array of EM_Taxonomy_Term child objects for a specific event
23
  * @var array
24
  */
25
+ public $terms = array();
26
  /**
27
  * Event ID of this set of taxonomy terms
28
  * @var int
29
  */
30
+ public $event_id;
31
  /**
32
  * Post ID of this set of taxonomy terms
33
  * @var int
34
  */
35
+ public $post_id;
36
 
37
  /**
38
  * Creates an EM_Taxonomy_Terms instance, currently accepts an EM_Event object (gets all Taxonomy Terms for that event) or array of any EM_Taxonomy_Term objects, which can be manipulated in bulk with helper functions.
261
  return apply_filters('em_'. self::$instance->terms_name .'_output', $output, $terms, $args);
262
  }
263
 
264
+ public static function get_pagination_links($args, $count, $search_action = false, $default_args = array()){
265
  //get default args if we're in a search, supply to parent since we can't depend on late static binding until WP requires PHP 5.3 or later
266
+ if( $search_action === false ) $search_action = self::$instance->ajax_search_action;
267
  if( empty($default_args) && (!empty($args['ajax']) || !empty($_REQUEST['action']) && $_REQUEST['action'] == $search_action) ){
268
  $default_args = self::get_default_search();
269
  $default_args['limit'] = get_option('dbem_'. self::$instance->terms_name .'_default_limit');
classes/em-ticket-booking.php CHANGED
@@ -62,6 +62,7 @@ class EM_Ticket_Booking extends EM_Object{
62
  //Now we save the ticket
63
  $this->booking_id = $this->get_booking()->booking_id; //event wouldn't exist before save, so refresh id
64
  $data = $this->to_array(true); //add the true to remove the nulls
 
65
  if($this->ticket_booking_id != ''){
66
  if($this->get_spaces() > 0){
67
  $where = array( 'ticket_booking_id' => $this->ticket_booking_id );
62
  //Now we save the ticket
63
  $this->booking_id = $this->get_booking()->booking_id; //event wouldn't exist before save, so refresh id
64
  $data = $this->to_array(true); //add the true to remove the nulls
65
+ $result = null;
66
  if($this->ticket_booking_id != ''){
67
  if($this->get_spaces() > 0){
68
  $where = array( 'ticket_booking_id' => $this->ticket_booking_id );
classes/em-ticket.php CHANGED
@@ -6,8 +6,8 @@ class EM_Ticket extends EM_Object{
6
  var $ticket_name;
7
  var $ticket_description;
8
  var $ticket_price;
9
- var $ticket_start;
10
- var $ticket_end;
11
  var $ticket_min;
12
  var $ticket_max;
13
  var $ticket_spaces = 10;
@@ -22,8 +22,8 @@ class EM_Ticket extends EM_Object{
22
  'ticket_name' => array('name'=>'name','type'=>'%s'),
23
  'ticket_description' => array('name'=>'description','type'=>'%s','null'=>1),
24
  'ticket_price' => array('name'=>'price','type'=>'%f','null'=>1),
25
- 'ticket_start' => array('name'=>'start','type'=>'%s','null'=>1),
26
- 'ticket_end' => array('name'=>'end','type'=>'%s','null'=>1),
27
  'ticket_min' => array('name'=>'min','type'=>'%s','null'=>1),
28
  'ticket_max' => array('name'=>'max','type'=>'%s','null'=>1),
29
  'ticket_spaces' => array('name'=>'spaces','type'=>'%s','null'=>1),
@@ -40,8 +40,8 @@ class EM_Ticket extends EM_Object{
40
  */
41
  var $bookings = array();
42
  var $required_fields = array('ticket_name');
43
- var $start_timestamp;
44
- var $end_timestamp;
45
  /**
46
  * is this ticket limited by spaces allotted to this ticket? false if no limit (i.e. the events general limit of seats)
47
  * @var unknown_type
@@ -81,20 +81,72 @@ class EM_Ticket extends EM_Object{
81
  $this->ticket_meta = (!empty($ticket['ticket_meta'])) ? maybe_unserialize($ticket['ticket_meta']):array();
82
  $this->ticket_members_roles = maybe_unserialize($this->ticket_members_roles);
83
  if( !is_array($this->ticket_members_roles) ) $this->ticket_members_roles = array();
84
- //timestamps
85
- $this->start_timestamp = (!empty($ticket['ticket_start'])) ? strtotime($ticket['ticket_start'], current_time('timestamp')):false;
86
- $this->end_timestamp = (!empty($ticket['ticket_end'])) ? strtotime($ticket['ticket_end'], current_time('timestamp')):false;
87
  //sort out recurrence meta to save extra empty() checks, the 'true' cut-off info is here for the ticket if part of a recurring event
88
  if( !empty($this->ticket_meta['recurrences']) ){
89
  if( !array_key_exists('start_days', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['start_days'] = false;
90
- if( !array_key_exists('start_time', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['start_time'] = false;
91
  if( !array_key_exists('end_days', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['end_days'] = false;
 
92
  if( !array_key_exists('end_time', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['end_time'] = false;
 
 
 
 
 
 
 
93
  }
94
  }
95
  $this->compat_keys();
96
  do_action('em_ticket',$this, $ticket_data, $ticket);
97
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
  function get_notes(){
100
  global $wpdb;
@@ -123,6 +175,9 @@ class EM_Ticket extends EM_Object{
123
  $data = $this->to_array(true); //add the true to remove the nulls
124
  if( !empty($data['ticket_meta']) ) $data['ticket_meta'] = serialize($data['ticket_meta']);
125
  if( !empty($data['ticket_members_roles']) ) $data['ticket_members_roles'] = serialize($data['ticket_members_roles']);
 
 
 
126
  if($this->ticket_id != ''){
127
  //since currently wpdb calls don't accept null, let's build the sql ourselves.
128
  $set_array = array();
@@ -179,10 +234,10 @@ class EM_Ticket extends EM_Object{
179
  $this->ticket_price = ( !empty($post['ticket_price']) ) ? wp_kses_data($post['ticket_price']):'';
180
  $this->ticket_start = ( !empty($post['ticket_start']) ) ? wp_kses_data($post['ticket_start']):'';
181
  $this->ticket_end = ( !empty($post['ticket_end']) ) ? wp_kses_data($post['ticket_end']):'';
182
- if( !empty($post['ticket_start_time']) && !empty($this->ticket_start) ) $this->ticket_start .= ' '. $this->sanitize_time($post['ticket_start_time']);
183
- if( !empty($post['ticket_end_time']) && !empty($this->ticket_end) ) $this->ticket_end .= ' '. $this->sanitize_time($post['ticket_end_time']);
184
- $this->start_timestamp = ( !empty($post['ticket_start']) ) ? strtotime($this->ticket_start):'';
185
- $this->end_timestamp = ( !empty($post['ticket_end']) ) ? strtotime($this->ticket_end):'';
186
  //sort out user availability restrictions
187
  $this->ticket_members = ( !empty($post['ticket_type']) && $post['ticket_type'] == 'members' ) ? 1:0;
188
  $this->ticket_guests = ( !empty($post['ticket_type']) && $post['ticket_type'] == 'guests' ) ? 1:0;
@@ -198,42 +253,34 @@ class EM_Ticket extends EM_Object{
198
  $this->ticket_required = ( !empty($post['ticket_required']) ) ? 1:0;
199
  //if event is recurring, store start/end restrictions of this ticket, which are determined by number of days before (negative number) or after (positive number) the event start date
200
  if($this->get_event()->is_recurring()){
 
 
 
201
  //start of ticket cut-off
202
  if( array_key_exists('ticket_start_recurring_days', $post) && is_numeric($post['ticket_start_recurring_days']) ){
203
  if( !empty($post['ticket_start_recurring_when']) && $post['ticket_start_recurring_when'] == 'after' ){
204
  $this->ticket_meta['recurrences']['start_days'] = absint($post['ticket_start_recurring_days']);
205
- $this->ticket_start = date('Y-m-d', strtotime('+' . $this->ticket_meta['recurrences']['start_days'] . ' days', $this->get_event()->start));
206
  }else{ //by default the start date is the point of reference
207
  $this->ticket_meta['recurrences']['start_days'] = absint($post['ticket_start_recurring_days']) * -1;
208
- $this->ticket_start = date('Y-m-d', strtotime($this->ticket_meta['recurrences']['start_days'] . ' days', $this->get_event()->start));
209
  }
210
- $this->ticket_meta['recurrences']['start_time'] = ( !empty($post['ticket_start_time']) ) ? $this->sanitize_time($post['ticket_start_time']) : '00:00:00';
211
- $this->ticket_start .= ' '. $this->ticket_meta['recurrences']['start_time'];
212
- //timestamp - calculated only for purposes of not screwing up interfaces that use timestamps for outputting cut-off times such as booking settings for event
213
- $this->start_timestamp = strtotime($this->ticket_start, current_time('timestamp'));
214
  }else{
215
  unset($this->ticket_meta['recurrences']['start_days']);
216
  unset($this->ticket_meta['recurrences']['start_time']);
217
- $this->ticket_start = $this->start_timestamp = '';
218
  }
219
  //end of ticket cut-off
220
  if( array_key_exists('ticket_end_recurring_days', $post) && is_numeric($post['ticket_end_recurring_days']) ){
221
  if( !empty($post['ticket_end_recurring_when']) && $post['ticket_end_recurring_when'] == 'after' ){
222
  $this->ticket_meta['recurrences']['end_days'] = absint($post['ticket_end_recurring_days']);
223
- $this->ticket_end = date('Y-m-d', strtotime('+' . $this->ticket_meta['recurrences']['end_days'] . ' days', $this->get_event()->end));
224
  }else{ //by default the end date is the point of reference
225
  $this->ticket_meta['recurrences']['end_days'] = absint($post['ticket_end_recurring_days']) * -1;
226
- $this->ticket_end = date('Y-m-d', strtotime($this->ticket_meta['recurrences']['end_days'] . ' days', $this->get_event()->end));
227
  }
228
- $this->ticket_meta['recurrences']['end_time'] = ( !empty($post['ticket_end_time']) ) ? $this->sanitize_time($post['ticket_end_time']) : '00:00:00';
229
- $this->ticket_end .= ' '. $this->ticket_meta['recurrences']['end_time'];
230
- //timestamp - calculated only for purposes of not screwing up interfaces that use timestamps for outputting cut-off times such as booking settings for event
231
- $this->end_timestamp = strtotime($this->ticket_end, current_time('timestamp')); //we save these timestamps for quicker loading on construct
232
  }else{
233
  unset($this->ticket_meta['recurrences']['end_days']);
234
  unset($this->ticket_meta['recurrences']['end_time']);
235
- $this->ticket_end = $this->end_timestamp = '';
236
  }
 
237
  }
238
  $this->compat_keys();
239
  do_action('em_ticket_get_post', $this, $post);
@@ -263,17 +310,16 @@ class EM_Ticket extends EM_Object{
263
  }
264
 
265
  function is_available( $ignore_member_restrictions = false, $ignore_guest_restrictions = false ){
266
- $timestamp = current_time('timestamp');
267
  if( isset($this->is_available) && !$ignore_member_restrictions && !$ignore_guest_restrictions ) return apply_filters('em_ticket_is_available', $this->is_available, $this); //save extra queries if doing a standard check
268
  $is_available = false;
269
  $EM_Event = $this->get_event();
270
  $available_spaces = $this->get_available_spaces();
271
- $condition_1 = (empty($this->ticket_start) || $this->start_timestamp <= $timestamp);
272
- $condition_2 = $this->end_timestamp >= $timestamp || empty($this->ticket_end);
273
- $condition_3 = (empty($EM_Event->event_rsvp_date) && $EM_Event->start > $timestamp) || $EM_Event->rsvp_end > $timestamp;
274
  $condition_4 = !$this->ticket_members || ($this->ticket_members && is_user_logged_in()) || $ignore_member_restrictions;
275
  $condition_5 = true;
276
- if( !EM_Bookings::$disable_restrictions && $this->ticket_members && !empty($this->ticket_members_roles) ){
277
  //check if user has the right role to use this ticket
278
  $condition_5 = false;
279
  if( is_user_logged_in() ){
@@ -549,6 +595,54 @@ class EM_Ticket extends EM_Object{
549
  }
550
  }
551
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
552
  /**
553
  * Can the user manage this event?
554
  */
@@ -560,18 +654,17 @@ class EM_Ticket extends EM_Object{
560
  }
561
 
562
  /**
563
- * Outputs properties with formatting
564
  * @param string $property
565
  * @return string
566
  */
567
  function output_property($property){
568
  switch($property){
569
  case 'start':
570
- $value = date_i18n( get_option('date_format'), $this->start_timestamp );
571
  break;
572
  case 'end':
573
- $value = date_i18n( get_option('date_format'), $this->end_timestamp );
574
- break;
575
  break;
576
  default:
577
  $value = $this->$property;
6
  var $ticket_name;
7
  var $ticket_description;
8
  var $ticket_price;
9
+ protected $ticket_start;
10
+ protected $ticket_end;
11
  var $ticket_min;
12
  var $ticket_max;
13
  var $ticket_spaces = 10;
22
  'ticket_name' => array('name'=>'name','type'=>'%s'),
23
  'ticket_description' => array('name'=>'description','type'=>'%s','null'=>1),
24
  'ticket_price' => array('name'=>'price','type'=>'%f','null'=>1),
25
+ 'ticket_start' => array('type'=>'%s','null'=>1),
26
+ 'ticket_end' => array('type'=>'%s','null'=>1),
27
  'ticket_min' => array('name'=>'min','type'=>'%s','null'=>1),
28
  'ticket_max' => array('name'=>'max','type'=>'%s','null'=>1),
29
  'ticket_spaces' => array('name'=>'spaces','type'=>'%s','null'=>1),
40
  */
41
  var $bookings = array();
42
  var $required_fields = array('ticket_name');
43
+ protected $start;
44
+ protected $end;
45
  /**
46
  * is this ticket limited by spaces allotted to this ticket? false if no limit (i.e. the events general limit of seats)
47
  * @var unknown_type
81
  $this->ticket_meta = (!empty($ticket['ticket_meta'])) ? maybe_unserialize($ticket['ticket_meta']):array();
82
  $this->ticket_members_roles = maybe_unserialize($this->ticket_members_roles);
83
  if( !is_array($this->ticket_members_roles) ) $this->ticket_members_roles = array();
 
 
 
84
  //sort out recurrence meta to save extra empty() checks, the 'true' cut-off info is here for the ticket if part of a recurring event
85
  if( !empty($this->ticket_meta['recurrences']) ){
86
  if( !array_key_exists('start_days', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['start_days'] = false;
 
87
  if( !array_key_exists('end_days', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['end_days'] = false;
88
+ if( !array_key_exists('start_time', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['start_time'] = false;
89
  if( !array_key_exists('end_time', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['end_time'] = false;
90
+ //if we have start and end times, we'll set the ticket start/end properties
91
+ if( !empty($this->ticket_meta['recurrences']['start_time']) ){
92
+ $this->ticket_start = date('Y-m-d ') . $this->ticket_meta['recurrences']['start_time'];
93
+ }
94
+ if( !empty($this->ticket_meta['recurrences']['end_time']) ){
95
+ $this->ticket_end = date('Y-m-d ') . $this->ticket_meta['recurrences']['end_time'];
96
+ }
97
  }
98
  }
99
  $this->compat_keys();
100
  do_action('em_ticket',$this, $ticket_data, $ticket);
101
  }
102
+
103
+
104
+ function __get( $var ){
105
+ if( $var == 'ticket_start' || $var == 'ticket_end' ){
106
+ return $this->$var;
107
+ }
108
+ //these are deprecated properties, use the start() and end() functions directly instead
109
+ elseif( $var == 'start_timestamp' || $var == 'start' ){
110
+ if( !$this->start()->valid ) return 0;
111
+ return $this->start()->getTimestampWithOffset();
112
+ }elseif( $var == 'end_timestamp' || $var == 'end' ){
113
+ if( !$this->end()->valid ) return 0;
114
+ return $this->end()->getTimestampWithOffset();
115
+ }
116
+ return null;
117
+ }
118
+
119
+ public function __set( $prop, $val ){
120
+ if( $prop == 'ticket_start' ){
121
+ $this->$prop = $val;
122
+ $this->start = false;
123
+ }elseif( $prop == 'ticket_end' ){
124
+ $this->$prop = $val;
125
+ $this->end = false;
126
+ }
127
+ //These are deprecated and should not be used. Either use the class start() or end() equivalent methods
128
+ elseif( $prop == 'start_timestamp' ){
129
+ if( $this->start() !== false ) $this->start()->setTimestamp($val);
130
+ }elseif( $prop == 'end_timestamp' ){
131
+ if( $this->end() !== false ) $this->end()->setTimestamp($val);
132
+ }elseif( $prop == 'start' || $prop == 'end' ){
133
+ //start and end properties are inefficient to set, and deprecated. Set ticket_start and ticket_end with a valid MySQL DATETIME value instead.
134
+ $EM_DateTime = new EM_DateTime( $val, $this->get_event()->get_timezone() );
135
+ if( !$EM_DateTime->valid ) return false;
136
+ $when_prop = 'ticket_'.$prop;
137
+ $this->$when_prop = $EM_DateTime->getDateTime();
138
+ }
139
+ $this->$prop = $val;
140
+ }
141
+
142
+ public function __isset( $prop ){
143
+ //start_timestamp and end_timestamp are deprecated, don't use them anymore
144
+ if( $prop == 'ticket_start' || $prop == 'start_timestamp' ){
145
+ return !empty($this->ticket_start);
146
+ }elseif( $prop == 'ticket_end' || $prop == 'end_timestamp' ){
147
+ return !empty($this->ticket_end);
148
+ }
149
+ }
150
 
151
  function get_notes(){
152
  global $wpdb;
175
  $data = $this->to_array(true); //add the true to remove the nulls
176
  if( !empty($data['ticket_meta']) ) $data['ticket_meta'] = serialize($data['ticket_meta']);
177
  if( !empty($data['ticket_members_roles']) ) $data['ticket_members_roles'] = serialize($data['ticket_members_roles']);
178
+ if( !empty($this->ticket_meta['recurrences']) ){
179
+ $data['ticket_start'] = $data['ticket_end'] = null;
180
+ }
181
  if($this->ticket_id != ''){
182
  //since currently wpdb calls don't accept null, let's build the sql ourselves.
183
  $set_array = array();
234
  $this->ticket_price = ( !empty($post['ticket_price']) ) ? wp_kses_data($post['ticket_price']):'';
235
  $this->ticket_start = ( !empty($post['ticket_start']) ) ? wp_kses_data($post['ticket_start']):'';
236
  $this->ticket_end = ( !empty($post['ticket_end']) ) ? wp_kses_data($post['ticket_end']):'';
237
+ $start_time = !empty($post['ticket_start_time']) ? $post['ticket_start_time'] : $this->get_event()->start()->format('H:i');
238
+ if( !empty($this->ticket_start) ) $this->ticket_start .= ' '. $this->sanitize_time($start_time);
239
+ $end_time = !empty($post['ticket_end_time']) ? $post['ticket_end_time'] : $this->get_event()->start()->format('H:i');
240
+ if( !empty($this->ticket_end) ) $this->ticket_end .= ' '. $this->sanitize_time($end_time);
241
  //sort out user availability restrictions
242
  $this->ticket_members = ( !empty($post['ticket_type']) && $post['ticket_type'] == 'members' ) ? 1:0;
243
  $this->ticket_guests = ( !empty($post['ticket_type']) && $post['ticket_type'] == 'guests' ) ? 1:0;
253
  $this->ticket_required = ( !empty($post['ticket_required']) ) ? 1:0;
254
  //if event is recurring, store start/end restrictions of this ticket, which are determined by number of days before (negative number) or after (positive number) the event start date
255
  if($this->get_event()->is_recurring()){
256
+ if( empty($this->ticket_meta['recurrences']) ){
257
+ $this->ticket_meta['recurrences'] = array('start_days'=>false, 'start_time'=>false, 'end_days'=>false, 'end_time'=>false);
258
+ }
259
  //start of ticket cut-off
260
  if( array_key_exists('ticket_start_recurring_days', $post) && is_numeric($post['ticket_start_recurring_days']) ){
261
  if( !empty($post['ticket_start_recurring_when']) && $post['ticket_start_recurring_when'] == 'after' ){
262
  $this->ticket_meta['recurrences']['start_days'] = absint($post['ticket_start_recurring_days']);
 
263
  }else{ //by default the start date is the point of reference
264
  $this->ticket_meta['recurrences']['start_days'] = absint($post['ticket_start_recurring_days']) * -1;
 
265
  }
266
+ $this->ticket_meta['recurrences']['start_time'] = ( !empty($post['ticket_start_time']) ) ? $this->sanitize_time($post['ticket_start_time']) : $this->get_event()->start()->format('H:i');
 
 
 
267
  }else{
268
  unset($this->ticket_meta['recurrences']['start_days']);
269
  unset($this->ticket_meta['recurrences']['start_time']);
 
270
  }
271
  //end of ticket cut-off
272
  if( array_key_exists('ticket_end_recurring_days', $post) && is_numeric($post['ticket_end_recurring_days']) ){
273
  if( !empty($post['ticket_end_recurring_when']) && $post['ticket_end_recurring_when'] == 'after' ){
274
  $this->ticket_meta['recurrences']['end_days'] = absint($post['ticket_end_recurring_days']);
 
275
  }else{ //by default the end date is the point of reference
276
  $this->ticket_meta['recurrences']['end_days'] = absint($post['ticket_end_recurring_days']) * -1;
 
277
  }
278
+ $this->ticket_meta['recurrences']['end_time'] = ( !empty($post['ticket_end_time']) ) ? $this->sanitize_time($post['ticket_end_time']) : $this->get_event()->start()->format('H:i');
 
 
 
279
  }else{
280
  unset($this->ticket_meta['recurrences']['end_days']);
281
  unset($this->ticket_meta['recurrences']['end_time']);
 
282
  }
283
+ $this->ticket_start = $this->ticket_end = null;
284
  }
285
  $this->compat_keys();
286
  do_action('em_ticket_get_post', $this, $post);
310
  }
311
 
312
  function is_available( $ignore_member_restrictions = false, $ignore_guest_restrictions = false ){
 
313
  if( isset($this->is_available) && !$ignore_member_restrictions && !$ignore_guest_restrictions ) return apply_filters('em_ticket_is_available', $this->is_available, $this); //save extra queries if doing a standard check
314
  $is_available = false;
315
  $EM_Event = $this->get_event();
316
  $available_spaces = $this->get_available_spaces();
317
+ $condition_1 = empty($this->ticket_start) || $this->start()->getTimestamp() <= time();
318
+ $condition_2 = empty($this->ticket_end) || $this->end()->getTimestamp() >= time();
319
+ $condition_3 = $EM_Event->rsvp_end()->getTimestamp() > time(); //either defined ending rsvp time, or start datetime is used here
320
  $condition_4 = !$this->ticket_members || ($this->ticket_members && is_user_logged_in()) || $ignore_member_restrictions;
321
  $condition_5 = true;
322
+ if( !$ignore_member_restrictions && !EM_Bookings::$disable_restrictions && $this->ticket_members && !empty($this->ticket_members_roles) ){
323
  //check if user has the right role to use this ticket
324
  $condition_5 = false;
325
  if( is_user_logged_in() ){
595
  }
596
  }
597
 
598
+ /**
599
+ * Returns an EM_DateTime object of the ticket start date/time in local timezone of event.
600
+ * If no start date defined or if date is invalid, false is returned.
601
+ * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default.
602
+ * @return EM_DateTime|false
603
+ * @see EM_Event::get_datetime()
604
+ */
605
+ public function start( $utc_timezone = false ){
606
+ return apply_filters('em_ticket_start', $this->get_datetime('start', $utc_timezone), $this);
607
+ }
608
+
609
+ /**
610
+ * Returns an EM_DateTime object of the ticket end date/time in local timezone of event.
611
+ * If no start date defined or if date is invalid, false is returned.
612
+ * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default.
613
+ * @return EM_DateTime|false
614
+ * @see EM_Event::get_datetime()
615
+ */
616
+ public function end( $utc_timezone = false ){
617
+ return apply_filters('em_ticket_end', $this->get_datetime('end', $utc_timezone), $this);
618
+ }
619
+
620
+ /**
621
+ * Generates an EM_DateTime for the the start/end date/times of the ticket in local timezone.
622
+ * If ticket has no start/end date, or an invalid format, false is returned.
623
+ * @param string $when 'start' or 'end' date/time
624
+ * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. Do not use if EM_DateTime->valid is false.
625
+ * @return EM_DateTime|false
626
+ */
627
+ public function get_datetime( $when = 'start', $utc_timezone = false ){
628
+ if( $when != 'start' && $when != 'end') return new EM_DateTime(); //currently only start/end dates are relevant
629
+ //Initialize EM_DateTime if not already initialized, or if previously initialized object is invalid (e.g. draft event with invalid dates being resubmitted)
630
+ $when_date = 'ticket_'.$when;
631
+ //we take a pass at creating a new datetime object if it's empty, invalid or a different time to the current start date
632
+ if( !empty($this->$when_date) ){
633
+ if( empty($this->$when) || !$this->$when->valid ){
634
+ $this->$when = new EM_DateTime( $this->$when_date, $this->get_event()->get_timezone() );
635
+ }
636
+ }else{
637
+ $this->$when = new EM_DateTime();
638
+ $this->$when->valid = false;
639
+ }
640
+ //Set to UTC timezone if requested, local by default
641
+ $tz = $utc_timezone ? 'UTC' : $this->get_event()->get_timezone();
642
+ $this->$when->setTimezone($tz);
643
+ return $this->$when;
644
+ }
645
+
646
  /**
647
  * Can the user manage this event?
648
  */
654
  }
655
 
656
  /**
657
+ * Deprecated since 5.8.2, just access properties directly or use relevant functions such as $this->start() for ticket_start time - Outputs properties with formatting
658
  * @param string $property
659
  * @return string
660
  */
661
  function output_property($property){
662
  switch($property){
663
  case 'start':
664
+ $value = ( $this->start()->valid ) ? $this->start()->i18n( em_get_date_format() ) : '';
665
  break;
666
  case 'end':
667
+ $value = ( $this->end()->valid ) ? $this->end()->i18n( em_get_date_format() ) : '';
 
668
  break;
669
  default:
670
  $value = $this->$property;
classes/em-tickets-bookings.php CHANGED
File without changes
classes/em-tickets.php CHANGED
File without changes
em-debug.php CHANGED
@@ -33,10 +33,18 @@ $dbem_debug_options = array(
33
  'dbem_bookings_email_cancelled_body' => $dbem_email_template
34
  );
35
 
36
- if( get_option('dbem_debug') && !empty($_REQUEST['page']) && $_REQUEST['page'] != 'events-manager-options' ){
 
 
 
 
 
 
 
 
37
  foreach($dbem_debug_options as $debug_option => $value){
38
  if( !empty($dbem_debug_options[$debug_option]) ){
39
- add_filter('pre_option_'.$debug_option, create_function('','return "'.$dbem_debug_options[$debug_option].'";'));
40
  }
41
  }
42
  }
33
  'dbem_bookings_email_cancelled_body' => $dbem_email_template
34
  );
35
 
36
+ class EM_DEBUG {
37
+ public function __call( $name, $arguments ){
38
+ global $dbem_debug_options;
39
+ return $dbem_debug_options[$name];
40
+ }
41
+ }
42
+
43
+ if( get_option('dbem_debug') && (empty($_REQUEST['page']) || $_REQUEST['page'] != 'events-manager-options') ){
44
+ $EM_DEBUG = new EM_DEBUG();
45
  foreach($dbem_debug_options as $debug_option => $value){
46
  if( !empty($dbem_debug_options[$debug_option]) ){
47
+ add_filter('pre_option_'.$debug_option, array($EM_DEBUG,$debug_option));
48
  }
49
  }
50
  }
em-events.php CHANGED
@@ -130,6 +130,7 @@ function em_content($page_content) {
130
  function em_add_content_filter_after_head(){
131
  add_filter('the_content', 'em_content');
132
  }
 
133
  add_action('wp_head', 'em_add_content_filter_after_head', 1000);
134
 
135
  /**
@@ -202,8 +203,8 @@ function em_content_page_title($original_content, $id = null) {
202
  $content = $EM_Event->name .' - '. $original_content;
203
  }
204
  }
205
- return apply_filters('em_content_page_title', $content);
206
  }
 
207
  }
208
  return $original_content;
209
  }
130
  function em_add_content_filter_after_head(){
131
  add_filter('the_content', 'em_content');
132
  }
133
+ //remember that this gets removed by taxonomy pages showing a single taxonomy page, so careful if changing the priority
134
  add_action('wp_head', 'em_add_content_filter_after_head', 1000);
135
 
136
  /**
203
  $content = $EM_Event->name .' - '. $original_content;
204
  }
205
  }
 
206
  }
207
+ return apply_filters('em_content_page_title', $content);
208
  }
209
  return $original_content;
210
  }
em-functions.php CHANGED
File without changes
em-ical.php CHANGED
File without changes
em-install.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  function em_install() {
4
  global $wp_rewrite;
 
5
  $wp_rewrite->flush_rules();
6
  $old_version = get_option('dbem_version');
7
  //Won't upgrade <4.300 anymore
@@ -59,6 +60,7 @@ function em_install() {
59
  return;
60
  }
61
  }
 
62
  }
63
 
64
  /**
@@ -135,11 +137,14 @@ function em_create_events_table() {
135
  event_owner bigint(20) unsigned DEFAULT NULL,
136
  event_status int(1) NULL DEFAULT NULL,
137
  event_name text NULL DEFAULT NULL,
138
- event_start_time time NULL DEFAULT NULL,
139
- event_end_time time NULL DEFAULT NULL,
140
- event_all_day int(1) NULL DEFAULT NULL,
141
  event_start_date date NULL DEFAULT NULL,
142
  event_end_date date NULL DEFAULT NULL,
 
 
 
 
 
 
143
  post_content longtext NULL DEFAULT NULL,
144
  event_rsvp bool NOT NULL DEFAULT 0,
145
  event_rsvp_date date NULL DEFAULT NULL,
@@ -189,7 +194,7 @@ function em_create_events_table() {
189
  }
190
  dbDelta($sql);
191
  }
192
- em_sort_out_table_nu_keys($table_name, array('event_status','post_id','blog_id','group_id','location_id'));
193
  if( em_check_utf8mb4_tables() ) maybe_convert_table_to_utf8mb4( $table_name );
194
  }
195
 
@@ -371,7 +376,7 @@ function em_add_options() {
371
  $contact_person_email_body_template = '#_EVENTNAME - #_EVENTDATES @ #_EVENTTIMES'.'<br/>'
372
  .__('Now there are #_BOOKEDSPACES spaces reserved, #_AVAILABLESPACES are still available.','events-manager').'<br/>'.
373
  strtoupper(__('Booking Details','events-manager')).'<br/>'.
374
- __('Name','events-manager').' : #_BOOKINGNAME'."\n".
375
  __('Email','events-manager').' : #_BOOKINGEMAIL'.'<br/>'.
376
  '#_BOOKINGSUMMARY'.'<br/>'.
377
  '<br/>Powered by Events Manager - http://wp-events-plugin.com';
@@ -389,6 +394,7 @@ function em_add_options() {
389
  '<br/>'.sprintf(__('To view your bookings, please visit %s after logging in.', 'events-manager'), em_get_my_bookings_url());
390
  //all the options
391
  $dbem_options = array(
 
392
  //time formats
393
  'dbem_time_format' => get_option('time_format'),
394
  'dbem_date_format' => 'd/m/Y',
@@ -655,6 +661,8 @@ function em_add_options() {
655
  'dbem_display_calendar_events_limit_msg' => __('more...','events-manager'),
656
  'dbem_calendar_direct_links' => 1,
657
  //General Settings
 
 
658
  'dbem_require_location' => 0,
659
  'dbem_locations_enabled' => 1,
660
  'dbem_use_select_for_locations' => 0,
@@ -780,7 +788,7 @@ function em_add_options() {
780
  'dbem_cp_events_post_class' => '',
781
  'dbem_cp_events_formats' => 1,
782
  'dbem_cp_events_has_archive' => 1,
783
- 'dbem_events_default_archive_orderby' => '_start_ts',
784
  'dbem_events_default_archive_order' => 'ASC',
785
  'dbem_events_archive_scope' => 'past',
786
  'dbem_cp_events_archive_formats' => 1,
@@ -844,7 +852,7 @@ function em_add_options() {
844
  }
845
 
846
  function em_upgrade_current_installation(){
847
- global $wpdb, $wp_locale;
848
  if( !get_option('dbem_version') ){ add_option('dbem_credits',1); }
849
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5 ){
850
  //make events, cats and locs pages
@@ -997,6 +1005,53 @@ function em_upgrade_current_installation(){
997
  delete_option('dbem_bookings_registration_user');
998
  }
999
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1000
  }
1001
 
1002
  function em_set_mass_caps( $roles, $caps ){
@@ -1390,4 +1445,178 @@ function em_migrate_uploads(){
1390
  delete_option('dbem_migrate_images');
1391
  return $result;
1392
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1393
  ?>
2
 
3
  function em_install() {
4
  global $wp_rewrite;
5
+ EM_ML::switch_to_lang(EM_ML::$wplang); //switch to blog language (if applicable)
6
  $wp_rewrite->flush_rules();
7
  $old_version = get_option('dbem_version');
8
  //Won't upgrade <4.300 anymore
60
  return;
61
  }
62
  }
63
+ EM_ML::restore_current_lang(); //now that we're done, switch back to current language (if applicable)
64
  }
65
 
66
  /**
137
  event_owner bigint(20) unsigned DEFAULT NULL,
138
  event_status int(1) NULL DEFAULT NULL,
139
  event_name text NULL DEFAULT NULL,
 
 
 
140
  event_start_date date NULL DEFAULT NULL,
141
  event_end_date date NULL DEFAULT NULL,
142
+ event_start_time time NULL DEFAULT NULL,
143
+ event_end_time time NULL DEFAULT NULL,
144
+ event_all_day int(1) NULL DEFAULT NULL,
145
+ event_start datetime NULL DEFAULT NULL,
146
+ event_end datetime NULL DEFAULT NULL,
147
+ event_timezone tinytext NULL DEFAULT NULL,
148
  post_content longtext NULL DEFAULT NULL,
149
  event_rsvp bool NOT NULL DEFAULT 0,
150
  event_rsvp_date date NULL DEFAULT NULL,
194
  }
195
  dbDelta($sql);
196
  }
197
+ em_sort_out_table_nu_keys($table_name, array('event_status','post_id','blog_id','group_id','location_id','event_start', 'event_end', 'event_start_date', 'event_end_date'));
198
  if( em_check_utf8mb4_tables() ) maybe_convert_table_to_utf8mb4( $table_name );
199
  }
200
 
376
  $contact_person_email_body_template = '#_EVENTNAME - #_EVENTDATES @ #_EVENTTIMES'.'<br/>'
377
  .__('Now there are #_BOOKEDSPACES spaces reserved, #_AVAILABLESPACES are still available.','events-manager').'<br/>'.
378
  strtoupper(__('Booking Details','events-manager')).'<br/>'.
379
+ __('Name','events-manager').' : #_BOOKINGNAME'.'<br/>'.
380
  __('Email','events-manager').' : #_BOOKINGEMAIL'.'<br/>'.
381
  '#_BOOKINGSUMMARY'.'<br/>'.
382
  '<br/>Powered by Events Manager - http://wp-events-plugin.com';
394
  '<br/>'.sprintf(__('To view your bookings, please visit %s after logging in.', 'events-manager'), em_get_my_bookings_url());
395
  //all the options
396
  $dbem_options = array(
397
+ 'dbem_data' => array(), //used to store admin-related data such as notice flags and other row keys that may not always exist in the wp_options table
398
  //time formats
399
  'dbem_time_format' => get_option('time_format'),
400
  'dbem_date_format' => 'd/m/Y',
661
  'dbem_display_calendar_events_limit_msg' => __('more...','events-manager'),
662
  'dbem_calendar_direct_links' => 1,
663
  //General Settings
664
+ 'dbem_timezone_enabled' => 1,
665
+ 'dbem_timezone_default' => EM_DateTimeZone::create()->getName(),
666
  'dbem_require_location' => 0,
667
  'dbem_locations_enabled' => 1,
668
  'dbem_use_select_for_locations' => 0,
788
  'dbem_cp_events_post_class' => '',
789
  'dbem_cp_events_formats' => 1,
790
  'dbem_cp_events_has_archive' => 1,
791
+ 'dbem_events_default_archive_orderby' => '_event_start',
792
  'dbem_events_default_archive_order' => 'ASC',
793
  'dbem_events_archive_scope' => 'past',
794
  'dbem_cp_events_archive_formats' => 1,
852
  }
853
 
854
  function em_upgrade_current_installation(){
855
+ global $wpdb, $wp_locale, $EM_Notices;
856
  if( !get_option('dbem_version') ){ add_option('dbem_credits',1); }
857
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5 ){
858
  //make events, cats and locs pages
1005
  delete_option('dbem_bookings_registration_user');
1006
  }
1007
  }
1008
+ if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.821 ){
1009
+ $admin_data = get_option('dbem_data');
1010
+ //upgrade tables only if we didn't do it before during earlier dev versions
1011
+ if( empty($admin_data['datetime_backcompat']) ){
1012
+ $migration_result = em_migrate_datetime_timezones( false );
1013
+ if( $migration_result !== true ){
1014
+ $EM_Notices->add_error($migration_result);
1015
+ }
1016
+ //migrate certain options
1017
+ $opt = get_option('dbem_tags_default_archive_orderby');
1018
+ if( $opt == '_start_ts' ) update_option('dbem_tags_default_archive_orderby', '_event_start');
1019
+ $opt = get_option('dbem_categories_default_archive_orderby');
1020
+ if( $opt == '_start_ts' ) update_option('dbem_categories_default_archive_orderby', '_event_start');
1021
+ $opt = get_option('dbem_events_default_archive_orderby');
1022
+ if( $opt == '_start_ts' ) update_option('dbem_events_default_archive_orderby', '_event_start');
1023
+ }else{
1024
+ //we're doing this at multisite level instead within dev versions, so fix this for dev versions
1025
+ unset( $admin_data['datetime_backcompat'] );
1026
+ update_option('dbem_data', $admin_data);
1027
+ }
1028
+ //add backwards compatability settings and warnings
1029
+ $admin_data = get_site_option('dbem_data');
1030
+ if( empty($admin_data['updates']) ) $admin_data['updates'] = array();
1031
+ $admin_data['updates']['timezone-backcompat'] = true;
1032
+ update_site_option('dbem_data', $admin_data);
1033
+ if( !is_multisite() || em_wp_is_super_admin() ){
1034
+ $message = __('Events Manager now supports multiple timezones for your events! Your events will initially match your blog timezone.','events-manager');
1035
+ if( is_multisite() ){
1036
+ $url = network_admin_url('admin.php?page=events-manager-options#general+admin-tools');
1037
+ $admin_tools_link = '<a href="'.$url.'">'.__('Network Admin').' &gt; '.__('Events Manager','events-manager').' &gt; '.__('Admin Tools','events-manager').'</a>';
1038
+ $options_link = '<a href="'.network_admin_url('admin.php?page=events-manager-update').'">'.__('Update Network','events-manager').'</a>';
1039
+ $message .= '</p><p>' . sprintf(__("Please update your network and when you're happy with the changes you can also finalize the migration by deleting unecessary data in the %s page.", 'events-manager'), $options_link);
1040
+ $message .= '</p><p>' . sprintf(__('You can also reset all events of a blog to a new timezone in %s', 'events-manager'), $admin_tools_link);
1041
+ }else{
1042
+ $options_link = get_admin_url(null, 'edit.php?post_type=event&page=events-manager-options#general+admin-tools');
1043
+ $options_link = '<a href="'.$options_link.'">'.__('Settings','events-manager').' &gt; '.__('General','events-manager').' &gt; '.__('Admin Tools','events-manager').'</a>';
1044
+ $message .= '</p><p>' . sprintf(__('You can reset your events to a new timezone and also complete the final migration step by deleting unecessary data in %s', 'events-manager'), $options_link);
1045
+ }
1046
+ $EM_Admin_Notice = new EM_Admin_Notice(array(
1047
+ 'name' => 'date_time_migration',
1048
+ 'who' => 'admin',
1049
+ 'where' => 'all',
1050
+ 'message' => $message
1051
+ ));
1052
+ EM_Admin_Notices::add($EM_Admin_Notice, is_multisite());
1053
+ }
1054
+ }
1055
  }
1056
 
1057
  function em_set_mass_caps( $roles, $caps ){
1445
  delete_option('dbem_migrate_images');
1446
  return $result;
1447
  }
1448
+
1449
+ function em_migrate_datetime_timezones( $reset_new_fields = true, $migrate_date_fields = true, $timezone = false ){
1450
+ global $wpdb;
1451
+ //create AND and WHERE conditions for blog IDs if we're in Multisite Glboal Mode
1452
+ $blog_id_where = $blog_id_and = '';
1453
+ if( EM_MS_GLOBAL ){
1454
+ if( is_main_site() ){
1455
+ $blog_id_cond = $wpdb->prepare('(blog_id = %d OR blog_id IS NULL OR blog_id = 0)', get_current_blog_id());
1456
+ }else{
1457
+ $blog_id_cond = $wpdb->prepare('blog_id = %d', get_current_blog_id());
1458
+ }
1459
+ $blog_id_where = ' WHERE '.$blog_id_cond;
1460
+ $blog_id_and = ' AND '.$blog_id_cond;
1461
+ }
1462
+ //reset all the data for these purposes
1463
+ if( $reset_new_fields || $migrate_date_fields ) $wpdb->query('UPDATE '. EM_EVENTS_TABLE .' SET event_start = NULL, event_end = NULL, event_timezone = NULL'.$blog_id_where);
1464
+ if( !$migrate_date_fields ) return true;
1465
+
1466
+ //start migration of old date formats to new datetime formats in local and UTC mode along with a declared timezone
1467
+ $migration_results = $migration_meta_results = $migration_errors = array();
1468
+ //firstly, we do a query for all-day events and reset the times, so that UTC times are correct relative to the local time
1469
+ $migration_result = $wpdb->query('UPDATE '.EM_EVENTS_TABLE." SET event_start_time = '00:00:00', event_end_time = '23:59:59' WHERE event_all_day = 1".$blog_id_and);
1470
+ if( $migration_result === false ) $migration_errors[] = array('Local datetime allday event times modification errors', $wpdb->last_error);
1471
+
1472
+ //migration procedure depends on whether we have an actual timezone or just a manual offset of hours in the WP settings page
1473
+ if( empty($timezone) ){
1474
+ $timezone = get_option('timezone_string');
1475
+ if( empty($timezone) ){
1476
+ $timezone = get_option('gmt_offset');
1477
+ $timezone = preg_match('/[+\-]/', $timezone) ? 'UTC'.$timezone : 'UTC+'.$timezone;
1478
+ }
1479
+ }
1480
+ if( !preg_match('/^UTC/', $timezone) ){
1481
+ //we'll get the minimum start/end dates in our events, and get the transitions for this range
1482
+ $transitions = em_migrate_get_tz_transitions($timezone, $blog_id_where);
1483
+ //now, build the SQL statements with the transitions
1484
+ $query_data = array();
1485
+ $where_start = $where_end = array();
1486
+ //go through each transition and add it to the right offset array key
1487
+ foreach( $transitions as $t ){
1488
+ //format start/end transitions for mysql DATETIME format IN CORRECT TIMEZONE
1489
+ $start = $t['start'] ? date('Y-m-d H:i:s', $t['start'] + $t['offset']) : false;
1490
+ $end = $t['end'] ? date('Y-m-d H:i:s', $t['end'] + $t['offset']) : false;
1491
+ //set up SQL statement for offset if it doesn't exist, but without the WHERE clause, which we'll add later
1492
+ if( empty($query_data[$t['offset']]) ){
1493
+ $query_data[$t['offset']] = array(
1494
+ 'start' => array(
1495
+ 'sql' => $wpdb->prepare('UPDATE '. EM_EVENTS_TABLE. ' SET event_start = DATE_SUB(TIMESTAMP(event_start_date,event_start_time), INTERVAL %d SECOND)', $t['offset']),
1496
+ 'where' => array()
1497
+ ),
1498
+ 'end' => array(
1499
+ 'sql' => $wpdb->prepare('UPDATE '. EM_EVENTS_TABLE. ' SET event_end = DATE_SUB(TIMESTAMP(event_end_date, event_end_time), INTERVAL %d SECOND)', $t['offset']),
1500
+ 'where' => array()
1501
+ )
1502
+ );
1503
+ }
1504
+ //create array of conditions, which we'll join into single statements for each unique offset amount
1505
+ if( $start && $end ){
1506
+ $query_data[$t['offset']]['start']['where'][] = $wpdb->prepare("(TIMESTAMP(event_start_date,event_start_time) BETWEEN %s AND %s)", $start, $end);
1507
+ $query_data[$t['offset']]['end']['where'][] = $wpdb->prepare("(TIMESTAMP(event_end_date, event_end_time) BETWEEN %s AND %s)", $start, $end);
1508
+ }elseif( $start ){
1509
+ $query_data[$t['offset']]['start']['where'][] = $wpdb->prepare("(TIMESTAMP(event_start_date,event_start_time) > %s)", $start);
1510
+ $query_data[$t['offset']]['end']['where'][] = $wpdb->prepare("(TIMESTAMP(event_end_date, event_end_time) > %s)", $start);
1511
+ }elseif( $end ){
1512
+ $query_data[$t['offset']]['start']['where'][] = $wpdb->prepare("(TIMESTAMP(event_start_date,event_start_time) < %s)", $end);
1513
+ $query_data[$t['offset']]['end']['where'][] = $wpdb->prepare("(TIMESTAMP(event_end_date, event_end_time) < %s)", $end);
1514
+ }
1515
+ }
1516
+ //glue the where clauses together with SQLs and create the minimum required statements to run this update
1517
+ $sql_array = array();
1518
+ foreach( $query_data as $offset => $statements ){
1519
+ $migration_result = $wpdb->query($statements['start']['sql'] .' WHERE event_start IS NULL AND ('. implode(' OR ', $statements['start']['where']).')'.$blog_id_and);
1520
+ if( $migration_result === false ) $migration_errors[] = array('Event start UTC transition',$wpdb->last_error);
1521
+ $migration_result = $wpdb->query($statements['end']['sql'] ." WHERE event_end IS NULL AND (". implode(' OR ', $statements['end']['where']).')'.$blog_id_and);
1522
+ if( $migration_result === false ) $migration_errors[] = array('Event end UTC transation', $wpdb->last_error);
1523
+ }
1524
+ }else{
1525
+ //This gets very easy... just do a single query that copies over all the times to right columns with relevant offset
1526
+ $EM_DateTimeZone = EM_DateTimeZone::create($timezone);
1527
+ $offset = $timezone == 'UTC' ? 0 : $EM_DateTimeZone->manual_offset / MINUTE_IN_SECONDS;
1528
+ $timezone = $EM_DateTimeZone->getName();
1529
+ $migration_result = $wpdb->query($wpdb->prepare('UPDATE '. EM_EVENTS_TABLE. ' SET event_start = DATE_SUB(TIMESTAMP(event_start_date,event_start_time), INTERVAL %d MINUTE), event_end = DATE_SUB(TIMESTAMP(event_end_date, event_end_time), INTERVAL %d MINUTE) WHERE event_end IS NULL '.$blog_id_and, $offset, $offset));
1530
+ if( $migration_result === false ) $migration_errors[] = array('Event start/end UTC offset', $wpdb->last_error);
1531
+ }
1532
+
1533
+ //set the timezone (on initial migration all events have same timezone of blog)
1534
+ $migration_result = $wpdb->query($wpdb->prepare('UPDATE '.EM_EVENTS_TABLE.' SET event_timezone = %s WHERE event_timezone IS NULL'.$blog_id_and, $timezone));
1535
+ if( $migration_result === false ) $migration_errors[] = array('Event timezone setting', $wpdb->last_error);
1536
+
1537
+ //reave meta data - at this point once we've copied over all of the dates, so we do 5 queries to postmeta, one for each field we've created above start/end times in local/utc and timezone
1538
+ if( empty($migration_errors) ){
1539
+ //delete all previously added fields, in case they were added before
1540
+ $sql = 'DELETE FROM '.$wpdb->postmeta." WHERE meta_key IN ('_event_start','_event_end','_event_timezone', '_event_start_local', '_event_end_local') AND post_id IN (SELECT ID FROM ".$wpdb->posts." WHERE post_type='".EM_POST_TYPE_EVENT."' OR post_type='event-recurring')";
1541
+ $migration_result = $wpdb->query($sql);
1542
+ if( $migration_result === false ) $migration_errors[] = array('Previous meta deletion', $wpdb->last_error);
1543
+ foreach( array('event_start', 'event_end', 'event_timezone', 'start', 'end') as $field ){
1544
+ if( $field == 'start' || $field == 'end' ){
1545
+ //create a timestamp combining two given fields, which we'll now use
1546
+ $sql = 'INSERT INTO '.$wpdb->postmeta." (post_id, meta_key, meta_value) SELECT post_id, '_event_{$field}_local', TIMESTAMP(event_{$field}_date, event_{$field}_time) FROM ".EM_EVENTS_TABLE. $blog_id_where;
1547
+ $field = "event_".$field."_local";
1548
+ }else{
1549
+ $sql = 'INSERT INTO '.$wpdb->postmeta." (post_id, meta_key, meta_value) SELECT post_id, '_{$field}', {$field} FROM ".EM_EVENTS_TABLE. $blog_id_where;
1550
+ }
1551
+ $migration_result = $wpdb->query($sql);
1552
+ if( $migration_result === false ) $migration_errors[] = array('Adding new meta data key <em>_'.$field.'</em>', $wpdb->last_error);
1553
+ }
1554
+ }
1555
+
1556
+ //return the result of this migration, either true for no errors, or a string of errors.
1557
+ if( !empty($migration_errors) ){
1558
+ $string = __('There was an error whilst migrating your times to our new timezone-aware formats. Below is a list of errors:', 'events-manager');
1559
+ $string .= '<ul>';
1560
+ foreach( $migration_errors as $err ){
1561
+ $string .= '<li><strong>'. $err[0] .': </strong>'. $err[1] .'</li>';
1562
+ }
1563
+ $string .= '</ul>';
1564
+ return $string;
1565
+ }
1566
+ return true;
1567
+ }
1568
+
1569
+ function em_migrate_get_tz_transitions( $timezone, $blog_id_where = '' ){
1570
+ global $wpdb;
1571
+ $minmax_dates = $wpdb->get_row('SELECT MIN(event_start_date) AS mindate, MAX(event_end_date) AS maxdate FROM '.EM_EVENTS_TABLE.$blog_id_where);
1572
+ $DTZ = new EM_DateTimeZone( $timezone );
1573
+ $start = strtotime($minmax_dates->mindate, current_time('timestamp')) - 60*60*24;
1574
+ $end = strtotime($minmax_dates->maxdate, current_time('timestamp')) + 60*60*24; //we add a day just to get the most comprehensive range possible
1575
+ $DTZ_Transitions = $DTZ->getTransitions($start, $end);
1576
+ //get first and next transitions to create a range, if there's only one transition we create a fake transition
1577
+ $transitions = array();
1578
+ if( count($DTZ_Transitions) == 1 ){
1579
+ $current_transition = current($DTZ_Transitions);
1580
+ $dst_offset = $current_transition['isdst'] ? 60*60 : 0;
1581
+ $transitions[] = array(
1582
+ 'start' => $start,
1583
+ 'end' => false,
1584
+ 'offset' => $current_transition['offset']
1585
+ );
1586
+ }else{
1587
+ do{
1588
+ $current_transition = current($DTZ_Transitions);
1589
+ $transition_key = key($DTZ_Transitions);
1590
+ $next_transition = next($DTZ_Transitions);
1591
+ if( $current_transition['ts'] < $start ) continue;
1592
+ $dst_offset = $current_transition['isdst'] ? 60*60 : 0;
1593
+ if( $transition_key == 0 ){
1594
+ //add the final transition and break this loop
1595
+ $transitions[] = array(
1596
+ 'start' => false,
1597
+ 'end' => $next_transition['ts'] - 1 - $dst_offset,
1598
+ 'offset' => $current_transition['offset']
1599
+ );
1600
+ }else{
1601
+ if( empty($next_transition) ){
1602
+ //add the final transition and break this loop
1603
+ $transitions[] = array(
1604
+ 'start' => $current_transition['ts'] - $dst_offset,
1605
+ 'end' => false,
1606
+ 'offset' => $current_transition['offset']
1607
+ );
1608
+ break;
1609
+ }else{
1610
+ $transitions[] = array(
1611
+ 'start' => $current_transition['ts'] - $dst_offset,
1612
+ 'end' => $next_transition['ts'] - 1 - $dst_offset,
1613
+ 'offset' => $current_transition['offset']
1614
+ );
1615
+ }
1616
+ }
1617
+ if( $current_transition['ts'] > $end ) break;
1618
+ } while( $next_transition !== false );
1619
+ }
1620
+ return $transitions;
1621
+ }
1622
  ?>
em-rss.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ function em_rss() {
3
+ global $post, $wp_query;
4
+ if ( !empty($_REQUEST['dbem_rss']) || (is_object($post) && $post->ID == get_option('dbem_events_page') && $wp_query->get('rss')) ) {
5
+ header ( "Content-type: text/xml" );
6
+ ob_start();
7
+ echo "<?xml version='1.0'?>\n";
8
+ ?>
9
+ <rss version="2.0">
10
+ <channel>
11
+ <title><?php echo get_option ( 'dbem_rss_main_title' ); ?></title>
12
+ <link><?php echo get_permalink ( get_option('dbem_events_page') ); ?></link>
13
+ <description><?php echo get_option ( 'dbem_rss_main_description' ); ?></description>
14
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
15
+ <generator>Weblog Editor 2.0</generator>
16
+
17
+ <?php
18
+ $description_format = str_replace ( ">", "&gt;", str_replace ( "<", "&lt;", get_option ( 'dbem_rss_description_format' ) ) );
19
+ $events = EM_Events::get( array('limit'=>5, 'owner'=>false) );
20
+ foreach ( $events as $event ) {
21
+ $description = $event->output( get_option ( 'dbem_rss_description_format' ), "rss");
22
+ $description = ent2ncr(convert_chars(strip_tags($description))); //Some RSS filtering
23
+ ?>
24
+ <item>
25
+ <title><?php echo $event->output( get_option('dbem_rss_title_format'), "rss" ); ?></title>
26
+ <link><?php echo $event->output('#_EVENTURL'); ?></link>
27
+ <description><?php echo $description; ?></description>
28
+ </item>
29
+ <?php
30
+ }
31
+ ?>
32
+
33
+ </channel>
34
+ </rss>
35
+ <?php
36
+ echo apply_filters('em_rss', ob_get_clean());
37
+ die ();
38
+ }
39
+ }
40
+ add_action ( 'template_redirect', 'em_rss' );
41
+ ?>
em-shortcode.php CHANGED
File without changes
em-template-tags.php CHANGED
File without changes
em-wpfc.php CHANGED
@@ -135,11 +135,12 @@ function wpfc_em_ajax() {
135
  $_REQUEST['year'] = false;
136
 
137
  //get the month/year between the start/end dates and feed these to EM
138
- $scope_start = strtotime(substr($_REQUEST['start'],0,10));
139
- $scope_end = strtotime(substr($_REQUEST['end'],0,10));
 
140
  $scope_middle = $scope_start + ($scope_end - $scope_start)/2;
141
- $month = date('n', $scope_middle);
142
- $year = date('Y', $scope_middle);
143
 
144
  $args = array ('month'=>$month, 'year'=>$year, 'owner'=>false, 'status'=>1, 'orderby'=>'event_start_time, event_name'); //since wpfc handles date sorting we only care about time and name ordering here
145
  $args['number_of_weeks'] = 6; //WPFC always has 6 weeks
@@ -195,10 +196,11 @@ function wpfc_em_ajax() {
195
  }
196
  if( !in_array($EM_Event->event_id, $event_ids) ){
197
  //count events for all days this event may span
198
- if( $EM_Event->event_start_date != $EM_Event->event_end_date ){
199
- for( $i = $EM_Event->start; $i <= $EM_Event->end; $i = $i + 86400 ){
200
- $idate = date('Y-m-d',$i);
201
- empty($event_day_counts[$idate]) ? $event_day_counts[$idate] = 1 : $event_day_counts[$idate]++;
 
202
  }
203
  }else{
204
  $event_day_counts[$date]++;
@@ -207,11 +209,11 @@ function wpfc_em_ajax() {
207
  $title = $EM_Event->output(get_option('dbem_emfc_full_calendar_event_format', '#_EVENTNAME'), 'raw');
208
  $allDay = $EM_Event->event_all_day == true;
209
  if( $allDay ){
210
- $start_date = date('Y-m-d\TH:i:s', $EM_Event->start);
211
- $end_date = date('Y-m-d\T00:00:00', $EM_Event->end + (60*60*24)); //on all day events the end date/time is next day of end date at 00:00:00 - see end attribute on http://fullcalendar.io/docs/event_data/Event_Object/
212
  }else{
213
- $start_date = date('Y-m-d\TH:i:s', $EM_Event->start);
214
- $end_date = date('Y-m-d\TH:i:s', $EM_Event->end);
215
  }
216
  $event_array = array ("title" => $title, "color" => $color, 'textColor'=>$textColor, 'borderColor'=>$borderColor, "start" => $start_date, "end" => $end_date, "url" => $EM_Event->get_permalink(), 'post_id' => $EM_Event->post_id, 'event_id' => $EM_Event->event_id, 'allDay' => $allDay );
217
  if( $args['long_events'] == 0 ) $event_array['end'] = $event_array['start']; //if long events aren't wanted, make the end date same as start so it shows this way on the calendar
135
  $_REQUEST['year'] = false;
136
 
137
  //get the month/year between the start/end dates and feed these to EM
138
+ $EM_DateTime = new EM_DateTime(substr($_REQUEST['start'],0,10));
139
+ $scope_start = $EM_DateTime->getTimestamp();
140
+ $scope_end = $EM_DateTime->modify(substr($_REQUEST['end'],0,10))->getTimestamp();
141
  $scope_middle = $scope_start + ($scope_end - $scope_start)/2;
142
+ $month = $EM_DateTime->setTimestamp($scope_middle)->format('n');
143
+ $year = $EM_DateTime->format('Y');
144
 
145
  $args = array ('month'=>$month, 'year'=>$year, 'owner'=>false, 'status'=>1, 'orderby'=>'event_start_time, event_name'); //since wpfc handles date sorting we only care about time and name ordering here
146
  $args['number_of_weeks'] = 6; //WPFC always has 6 weeks
196
  }
197
  if( !in_array($EM_Event->event_id, $event_ids) ){
198
  //count events for all days this event may span
199
+ if( $EM_Event->start()->getDate() != $EM_Event->end()->getDate() ){
200
+ $EM_DateTime = $EM_Event->start()->copy();
201
+ while( $EM_DateTime <= $EM_Event->end() ){
202
+ $EM_DateTime->add('P1D');
203
+ empty($event_day_counts[$EM_DateTime->getDate()]) ? $event_day_counts[$EM_DateTime->getDate()] = 1 : $event_day_counts[$EM_DateTime->getDate()]++;
204
  }
205
  }else{
206
  $event_day_counts[$date]++;
209
  $title = $EM_Event->output(get_option('dbem_emfc_full_calendar_event_format', '#_EVENTNAME'), 'raw');
210
  $allDay = $EM_Event->event_all_day == true;
211
  if( $allDay ){
212
+ $start_date = $EM_Event->start()->format('Y-m-d\T00:00:00');
213
+ $end_date = $EM_Event->end()->copy()->add('P1D')->format('Y-m-d\T00:00:00'); //on all day events the end date/time is next day of end date at 00:00:00 - see end attribute on http://fullcalendar.io/docs/event_data/Event_Object/
214
  }else{
215
+ $start_date = $EM_Event->start()->format('Y-m-d\TH:i:s');
216
+ $end_date = $EM_Event->end()->format('Y-m-d\TH:i:s');
217
  }
218
  $event_array = array ("title" => $title, "color" => $color, 'textColor'=>$textColor, 'borderColor'=>$borderColor, "start" => $start_date, "end" => $end_date, "url" => $EM_Event->get_permalink(), 'post_id' => $EM_Event->post_id, 'event_id' => $EM_Event->event_id, 'allDay' => $allDay );
219
  if( $args['long_events'] == 0 ) $event_array['end'] = $event_array['start']; //if long events aren't wanted, make the end date same as start so it shows this way on the calendar
events-manager.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Plugin Name: Events Manager
4
- Version: 5.8.1.3
5
  Plugin URI: http://wp-events-plugin.com
6
  Description: Event registration and booking management for WordPress. Recurring events, locations, google maps, rss, ical, booking registration and more!
7
  Author: Marcus Sykes
@@ -10,7 +10,7 @@ Text Domain: events-manager
10
  */
11
 
12
  /*
13
- Copyright (c) 2017, Marcus Sykes
14
 
15
  This program is free software; you can redistribute it and/or
16
  modify it under the terms of the GNU General Public License
@@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28
  */
29
 
30
  // Setting constants
31
- define('EM_VERSION', 5.8); //self expanatory
32
  define('EM_PRO_MIN_VERSION', 2.392); //self expanatory
33
  define('EM_PRO_MIN_VERSION_CRITICAL', 2.377); //self expanatory
34
  define('EM_DIR', dirname( __FILE__ )); //an absolute path to this directory
@@ -66,7 +66,9 @@ function dbem_debug_mode(){
66
 
67
  // INCLUDES
68
  //Base classes
 
69
  include('classes/em-object.php');
 
70
  include('classes/em-taxonomy-term.php');
71
  include('classes/em-taxonomy-terms.php');
72
  include('classes/em-taxonomy-frontend.php');
@@ -115,6 +117,8 @@ include('classes/em-tickets-bookings.php');
115
  include('classes/em-tickets.php');
116
  //Admin Files
117
  if( is_admin() ){
 
 
118
  include('admin/em-admin.php');
119
  include('admin/em-bookings.php');
120
  include('admin/em-docs.php');
@@ -710,7 +714,7 @@ add_action ( 'template_redirect', 'em_rss' );
710
  */
711
  function em_modified_monitor($result){
712
  if($result){
713
- update_option('em_last_modified', current_time('timestamp', true));
714
  }
715
  return $result;
716
  }
1
  <?php
2
  /*
3
  Plugin Name: Events Manager
4
+ Version: 5.9
5
  Plugin URI: http://wp-events-plugin.com
6
  Description: Event registration and booking management for WordPress. Recurring events, locations, google maps, rss, ical, booking registration and more!
7
  Author: Marcus Sykes
10
  */
11
 
12
  /*
13
+ Copyright (c) 2018, Marcus Sykes
14
 
15
  This program is free software; you can redistribute it and/or
16
  modify it under the terms of the GNU General Public License
28
  */
29
 
30
  // Setting constants
31
+ define('EM_VERSION', 5.9); //self expanatory
32
  define('EM_PRO_MIN_VERSION', 2.392); //self expanatory
33
  define('EM_PRO_MIN_VERSION_CRITICAL', 2.377); //self expanatory
34
  define('EM_DIR', dirname( __FILE__ )); //an absolute path to this directory
66
 
67
  // INCLUDES
68
  //Base classes
69
+ include('classes/em-options.php');
70
  include('classes/em-object.php');
71
+ include('classes/em-datetime.php');
72
  include('classes/em-taxonomy-term.php');
73
  include('classes/em-taxonomy-terms.php');
74
  include('classes/em-taxonomy-frontend.php');
117
  include('classes/em-tickets.php');
118
  //Admin Files
119
  if( is_admin() ){
120
+ include('classes/em-admin-notice.php');
121
+ include('classes/em-admin-notices.php');
122
  include('admin/em-admin.php');
123
  include('admin/em-bookings.php');
124
  include('admin/em-docs.php');
714
  */
715
  function em_modified_monitor($result){
716
  if($result){
717
+ update_option('em_last_modified', time());
718
  }
719
  return $result;
720
  }
includes/css/events_manager.css CHANGED
File without changes
includes/css/events_manager_admin.css CHANGED
@@ -92,6 +92,10 @@ table.events-table .category { color:#888; }
92
  .em-tablenav-pagination.tablenav-pages .current { font-size:16px; }
93
  /* Ticket table info */
94
  table.em-tickets-bookings-table { width:100%; border:1px #efefef solid; margin:10px 0px; }
 
 
 
 
95
  table.em-tickets-bookings-table th, table.em-tickets-bookings-table td { padding:5px 5px; margin:0px; }
96
  table.em-tickets-bookings-table thead th, table.em-tickets-bookings-table tfoot th { background:#cdcdcd; text-align:center }
97
  table.em-tickets-bookings-table tbody td.ticket-type { text-align:left; padding-left:10px; }
92
  .em-tablenav-pagination.tablenav-pages .current { font-size:16px; }
93
  /* Ticket table info */
94
  table.em-tickets-bookings-table { width:100%; border:1px #efefef solid; margin:10px 0px; }
95
+ table.em-tickets-bookings-table tr.em-hr th { border-top: 1px solid #bbb; }
96
+ table.em-tickets-bookings-table tfoot th:first-child { text-align:right; }
97
+ table.em-tickets-bookings-table tfoot th:last-child { text-align:right; padding-right:20px; vertical-align:top; }
98
+ table.em-tickets-bookings-table tfoot th em { font-size:12px; font-weight:normal; }
99
  table.em-tickets-bookings-table th, table.em-tickets-bookings-table td { padding:5px 5px; margin:0px; }
100
  table.em-tickets-bookings-table thead th, table.em-tickets-bookings-table tfoot th { background:#cdcdcd; text-align:center }
101
  table.em-tickets-bookings-table tbody td.ticket-type { text-align:left; padding-left:10px; }
includes/css/images/loading.gif CHANGED
File without changes
includes/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png CHANGED
File without changes
includes/css/images/ui-bg_diagonals-thick_20_666666_40x40.png CHANGED
File without changes
includes/css/images/ui-bg_flat_10_000000_40x100.png CHANGED
File without changes
includes/css/images/ui-bg_glass_100_f6f6f6_1x400.png CHANGED
File without changes
includes/css/images/ui-bg_glass_100_fdf5ce_1x400.png CHANGED
File without changes
includes/css/images/ui-bg_glass_65_ffffff_1x400.png CHANGED
File without changes
includes/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png CHANGED
File without changes
includes/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png CHANGED
File without changes
includes/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png CHANGED
File without changes
includes/css/images/ui-icons_222222_256x240.png CHANGED
File without changes
includes/css/images/ui-icons_228ef1_256x240.png CHANGED
File without changes
includes/css/images/ui-icons_ef8c08_256x240.png CHANGED
File without changes
includes/css/images/ui-icons_ffd27a_256x240.png CHANGED
File without changes
includes/css/images/ui-icons_ffffff_256x240.png CHANGED
File without changes
includes/css/jquery-ui.css CHANGED
File without changes
includes/css/jquery-ui.min.css CHANGED
File without changes
includes/images/baloon.png CHANGED
File without changes
includes/images/calendar-16.png CHANGED
File without changes
includes/images/calendar-32.png CHANGED
File without changes
includes/images/close.png CHANGED
File without changes
includes/images/event-caps-source.png CHANGED
File without changes
includes/images/event-caps.jpg CHANGED
File without changes
includes/images/event-perms-source.png CHANGED
File without changes
includes/images/loading.gif CHANGED
File without changes
includes/js/events-manager.js CHANGED
@@ -683,7 +683,7 @@ jQuery(document).ready( function($){
683
  return false;
684
  }
685
  }).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
686
- html_val = "<a>" + item.label + '<br><span style="font-size:11px"><em>'+ item.address + ', ' + item.town+"</em></span></a>";
687
  return jQuery( "<li></li>" ).data( "item.autocomplete", item ).append(html_val).appendTo( ul );
688
  };
689
  jQuery('#em-location-reset a').click( function(){
@@ -845,7 +845,7 @@ var em_ajaxify = function(url){
845
  var em_maps_loaded = false;
846
  var maps = {};
847
  var maps_markers = {};
848
- var infowindow;
849
  //loads maps script if not already loaded and executes EM maps script
850
  function em_maps_load(){
851
  if( !em_maps_loaded ){
@@ -942,13 +942,13 @@ function em_maps_load_location(el){
942
  };
943
  jQuery(document).triggerHandler('em_maps_location_marker_options', marker_options);
944
  maps_markers[map_id] = new google.maps.Marker(marker_options);
945
- infowindow = new google.maps.InfoWindow({ content: jQuery('#em-location-map-info-'+map_id+' .em-map-balloon').get(0) });
946
- infowindow.open(maps[map_id],maps_markers[map_id]);
947
  maps[map_id].panBy(40,-70);
948
 
949
  //JS Hook for handling map after instantiation
950
  //Example hook, which you can add elsewhere in your theme's JS - jQuery(document).bind('em_maps_location_hook', function(){ alert('hi');} );
951
- jQuery(document).triggerHandler('em_maps_location_hook', [maps[map_id], infowindow, maps_markers[map_id], map_id]);
952
  //map resize listener
953
  jQuery(window).on('resize', function(e) {
954
  google.maps.event.trigger(maps[map_id], "resize");
@@ -978,25 +978,22 @@ function em_maps() {
978
  if( !(location_latitude == 0 && location_longitude == 0) ){
979
  var position = new google.maps.LatLng(location_latitude, location_longitude); //the location coords
980
  marker.setPosition(position);
981
- var mapTitle = (jQuery('input#location-name').length > 0) ? jQuery(jQuery.parseHTML(jQuery('input#location-name').val())).text():jQuery('input#title').val();
982
- var mapAddress = jQuery('#location-address').val();
983
- var mapTown = jQuery('#location-town').val();
984
- marker.setTitle( jQuery('input#location-name input#title, #location-select-id').first().val() );
985
  jQuery('#em-map').show();
986
  jQuery('#em-map-404').hide();
987
  google.maps.event.trigger(map, 'resize');
988
  map.setCenter(position);
989
  map.panBy(40,-55);
990
  infoWindow.setContent(
991
- '<div id="location-balloon-content"><strong>' +
992
- mapTitle +
993
- '</strong><br>' +
994
- jQuery(jQuery.parseHTML(mapAddress)).text() +
995
- '<br>' + jQuery(jQuery.parseHTML(mapTown)).text() +
996
  '</div>'
997
  );
998
  infoWindow.open(map, marker);
999
- jQuery(document).triggerHandler('em_maps_location_hook', [map, infowindow, marker, 0]);
1000
  } else {
1001
  jQuery('#em-map').hide();
1002
  jQuery('#em-map-404').show();
@@ -1019,7 +1016,7 @@ function em_maps() {
1019
  infoWindow.setContent( '<div id="location-balloon-content">'+ data.location_balloon +'</div>');
1020
  infoWindow.open(map, marker);
1021
  google.maps.event.trigger(map, 'resize');
1022
- jQuery(document).triggerHandler('em_maps_location_hook', [map, infowindow, marker, 0]);
1023
  }else{
1024
  jQuery('#em-map').hide();
1025
  jQuery('#em-map-404').show();
@@ -1094,7 +1091,7 @@ function em_maps() {
1094
  }else{
1095
  refresh_map_location();
1096
  }
1097
- jQuery(document).triggerHandler('em_map_loaded', [map, infowindow, marker]);
1098
  }
1099
  //map resize listener
1100
  jQuery(window).on('resize', function(e) {
@@ -1110,11 +1107,16 @@ function em_maps() {
1110
  function em_map_infobox(marker, message, map) {
1111
  var iw = new google.maps.InfoWindow({ content: message });
1112
  google.maps.event.addListener(marker, 'click', function() {
1113
- if( infowindow ) infowindow.close();
1114
- infowindow = iw;
1115
  iw.open(map,marker);
1116
  });
1117
  }
1118
 
 
 
 
 
 
1119
  /* jQuery timePicker - http://labs.perifer.se/timedatepicker/ @ http://github.com/perifer/timePicker commit 100644 */
1120
  (function(e){function t(t,n,r,i){t.value=e(n).text();e(t).change();if(!navigator.userAgent.match(/msie/i)){t.focus()}r.hide()}function n(e,t){var n=e.getHours();var i=t.show24Hours?n:(n+11)%12+1;var s=e.getMinutes();return r(i)+t.separator+r(s)+(t.show24Hours?"":n<12?" AM":" PM")}function r(e){return(e<10?"0":"")+e}function i(e,t){return typeof e=="object"?o(e):s(e,t)}function s(e,t){if(e){var n=e.split(t.separator);var r=parseFloat(n[0]);var i=parseFloat(n[1]);if(!t.show24Hours){if(r===12&&e.indexOf("AM")!==-1){r=0}else if(r!==12&&e.indexOf("PM")!==-1){r+=12}}var s=new Date(0,0,0,r,i,0);return o(s)}return null}function o(e){e.setFullYear(2001);e.setMonth(0);e.setDate(0);return e}e.fn.timePicker=function(t){var n=e.extend({},e.fn.timePicker.defaults,t);return this.each(function(){e.timePicker(this,n)})};e.timePicker=function(t,n){var r=e(t)[0];return r.timePicker||(r.timePicker=new jQuery._timePicker(r,n))};e.timePicker.version="0.3";e._timePicker=function(r,u){var a=false;var f=false;var l=i(u.startTime,u);var c=i(u.endTime,u);var h="selected";var p="li."+h;e(r).attr("autocomplete","OFF");var d=[];var v=new Date(l);while(v<=c){d[d.length]=n(v,u);v=new Date(v.setMinutes(v.getMinutes()+u.step))}var m=e('<div class="time-picker'+(u.show24Hours?"":" time-picker-12hours")+'"></div>');var g=e("<ul></ul>");for(var y=0;y<d.length;y++){g.append("<li>"+d[y]+"</li>")}m.append(g);m.appendTo("body").hide();m.mouseover(function(){a=true}).mouseout(function(){a=false});e("li",g).mouseover(function(){if(!f){e(p,m).removeClass(h);e(this).addClass(h)}}).mousedown(function(){a=true}).click(function(){t(r,this,m,u);a=false});var b=function(){if(m.is(":visible")){return false}e("li",m).removeClass(h);var t=e(r).offset();m.css({top:t.top+r.offsetHeight,left:t.left});m.show();var i=r.value?s(r.value,u):l;var a=l.getHours()*60+l.getMinutes();var f=i.getHours()*60+i.getMinutes()-a;var p=Math.round(f/u.step);var d=o(new Date(0,0,0,0,p*u.step+a,0));d=l<d&&d<=c?d:l;var v=e("li:contains("+n(d,u)+")",m);if(v.length){v.addClass(h);m[0].scrollTop=v[0].offsetTop}return true};e(r).focus(b).click(b);e(r).blur(function(){if(!a){m.hide()}});e(r)["keydown"](function(n){var i;f=true;var s=m[0].scrollTop;switch(n.keyCode){case 38:if(b()){return false}i=e(p,g);var o=i.prev().addClass(h)[0];if(o){i.removeClass(h);if(o.offsetTop<s){m[0].scrollTop=s-o.offsetHeight}}else{i.removeClass(h);o=e("li:last",g).addClass(h)[0];m[0].scrollTop=o.offsetTop-o.offsetHeight}return false;break;case 40:if(b()){return false}i=e(p,g);var a=i.next().addClass(h)[0];if(a){i.removeClass(h);if(a.offsetTop+a.offsetHeight>s+m[0].offsetHeight){m[0].scrollTop=s+a.offsetHeight}}else{i.removeClass(h);a=e("li:first",g).addClass(h)[0];m[0].scrollTop=0}return false;break;case 13:if(m.is(":visible")){var l=e(p,g)[0];t(r,l,m,u)}return false;break;case 27:m.hide();return false;break}return true});e(r).keyup(function(e){f=false});this.getTime=function(){return s(r.value,u)};this.setTime=function(t){r.value=n(i(t,u),u);e(r).change()}};e.fn.timePicker.defaults={step:30,startTime:new Date(0,0,0,0,0,0),endTime:new Date(0,0,0,23,30,0),separator:":",show24Hours:true}})(jQuery)
683
  return false;
684
  }
685
  }).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
686
+ html_val = "<a>" + em_esc_attr(item.label) + '<br><span style="font-size:11px"><em>'+ em_esc_attr(item.address) + ', ' + em_esc_attr(item.town)+"</em></span></a>";
687
  return jQuery( "<li></li>" ).data( "item.autocomplete", item ).append(html_val).appendTo( ul );
688
  };
689
  jQuery('#em-location-reset a').click( function(){
845
  var em_maps_loaded = false;
846
  var maps = {};
847
  var maps_markers = {};
848
+ var infoWindow;
849
  //loads maps script if not already loaded and executes EM maps script
850
  function em_maps_load(){
851
  if( !em_maps_loaded ){
942
  };
943
  jQuery(document).triggerHandler('em_maps_location_marker_options', marker_options);
944
  maps_markers[map_id] = new google.maps.Marker(marker_options);
945
+ infoWindow = new google.maps.InfoWindow({ content: jQuery('#em-location-map-info-'+map_id+' .em-map-balloon').get(0) });
946
+ infoWindow.open(maps[map_id],maps_markers[map_id]);
947
  maps[map_id].panBy(40,-70);
948
 
949
  //JS Hook for handling map after instantiation
950
  //Example hook, which you can add elsewhere in your theme's JS - jQuery(document).bind('em_maps_location_hook', function(){ alert('hi');} );
951
+ jQuery(document).triggerHandler('em_maps_location_hook', [maps[map_id], infoWindow, maps_markers[map_id], map_id]);
952
  //map resize listener
953
  jQuery(window).on('resize', function(e) {
954
  google.maps.event.trigger(maps[map_id], "resize");
978
  if( !(location_latitude == 0 && location_longitude == 0) ){
979
  var position = new google.maps.LatLng(location_latitude, location_longitude); //the location coords
980
  marker.setPosition(position);
981
+ var mapTitle = (jQuery('input#location-name').length > 0) ? jQuery('input#location-name').val():jQuery('input#title').val();
982
+ mapTitle = em_esc_attr(mapTitle);
983
+ marker.setTitle( mapTitle );
 
984
  jQuery('#em-map').show();
985
  jQuery('#em-map-404').hide();
986
  google.maps.event.trigger(map, 'resize');
987
  map.setCenter(position);
988
  map.panBy(40,-55);
989
  infoWindow.setContent(
990
+ '<div id="location-balloon-content"><strong>' + mapTitle + '</strong><br>' +
991
+ em_esc_attr(jQuery('#location-address').val()) +
992
+ '<br>' + em_esc_attr(jQuery('#location-town').val()) +
 
 
993
  '</div>'
994
  );
995
  infoWindow.open(map, marker);
996
+ jQuery(document).triggerHandler('em_maps_location_hook', [map, infoWindow, marker, 0]);
997
  } else {
998
  jQuery('#em-map').hide();
999
  jQuery('#em-map-404').show();
1016
  infoWindow.setContent( '<div id="location-balloon-content">'+ data.location_balloon +'</div>');
1017
  infoWindow.open(map, marker);
1018
  google.maps.event.trigger(map, 'resize');
1019
+ jQuery(document).triggerHandler('em_maps_location_hook', [map, infoWindow, marker, 0]);
1020
  }else{
1021
  jQuery('#em-map').hide();
1022
  jQuery('#em-map-404').show();
1091
  }else{
1092
  refresh_map_location();
1093
  }
1094
+ jQuery(document).triggerHandler('em_map_loaded', [map, infoWindow, marker]);
1095
  }
1096
  //map resize listener
1097
  jQuery(window).on('resize', function(e) {
1107
  function em_map_infobox(marker, message, map) {
1108
  var iw = new google.maps.InfoWindow({ content: message });
1109
  google.maps.event.addListener(marker, 'click', function() {
1110
+ if( infoWindow ) infoWindow.close();
1111
+ infoWindow = iw;
1112
  iw.open(map,marker);
1113
  });
1114
  }
1115
 
1116
+ function em_esc_attr( str ){
1117
+ if( typeof str !== 'string' ) return '';
1118
+ return str.replace(/</gi,'&lt;').replace(/>/gi,'&gt;');
1119
+ }
1120
+
1121
  /* jQuery timePicker - http://labs.perifer.se/timedatepicker/ @ http://github.com/perifer/timePicker commit 100644 */
1122
  (function(e){function t(t,n,r,i){t.value=e(n).text();e(t).change();if(!navigator.userAgent.match(/msie/i)){t.focus()}r.hide()}function n(e,t){var n=e.getHours();var i=t.show24Hours?n:(n+11)%12+1;var s=e.getMinutes();return r(i)+t.separator+r(s)+(t.show24Hours?"":n<12?" AM":" PM")}function r(e){return(e<10?"0":"")+e}function i(e,t){return typeof e=="object"?o(e):s(e,t)}function s(e,t){if(e){var n=e.split(t.separator);var r=parseFloat(n[0]);var i=parseFloat(n[1]);if(!t.show24Hours){if(r===12&&e.indexOf("AM")!==-1){r=0}else if(r!==12&&e.indexOf("PM")!==-1){r+=12}}var s=new Date(0,0,0,r,i,0);return o(s)}return null}function o(e){e.setFullYear(2001);e.setMonth(0);e.setDate(0);return e}e.fn.timePicker=function(t){var n=e.extend({},e.fn.timePicker.defaults,t);return this.each(function(){e.timePicker(this,n)})};e.timePicker=function(t,n){var r=e(t)[0];return r.timePicker||(r.timePicker=new jQuery._timePicker(r,n))};e.timePicker.version="0.3";e._timePicker=function(r,u){var a=false;var f=false;var l=i(u.startTime,u);var c=i(u.endTime,u);var h="selected";var p="li."+h;e(r).attr("autocomplete","OFF");var d=[];var v=new Date(l);while(v<=c){d[d.length]=n(v,u);v=new Date(v.setMinutes(v.getMinutes()+u.step))}var m=e('<div class="time-picker'+(u.show24Hours?"":" time-picker-12hours")+'"></div>');var g=e("<ul></ul>");for(var y=0;y<d.length;y++){g.append("<li>"+d[y]+"</li>")}m.append(g);m.appendTo("body").hide();m.mouseover(function(){a=true}).mouseout(function(){a=false});e("li",g).mouseover(function(){if(!f){e(p,m).removeClass(h);e(this).addClass(h)}}).mousedown(function(){a=true}).click(function(){t(r,this,m,u);a=false});var b=function(){if(m.is(":visible")){return false}e("li",m).removeClass(h);var t=e(r).offset();m.css({top:t.top+r.offsetHeight,left:t.left});m.show();var i=r.value?s(r.value,u):l;var a=l.getHours()*60+l.getMinutes();var f=i.getHours()*60+i.getMinutes()-a;var p=Math.round(f/u.step);var d=o(new Date(0,0,0,0,p*u.step+a,0));d=l<d&&d<=c?d:l;var v=e("li:contains("+n(d,u)+")",m);if(v.length){v.addClass(h);m[0].scrollTop=v[0].offsetTop}return true};e(r).focus(b).click(b);e(r).blur(function(){if(!a){m.hide()}});e(r)["keydown"](function(n){var i;f=true;var s=m[0].scrollTop;switch(n.keyCode){case 38:if(b()){return false}i=e(p,g);var o=i.prev().addClass(h)[0];if(o){i.removeClass(h);if(o.offsetTop<s){m[0].scrollTop=s-o.offsetHeight}}else{i.removeClass(h);o=e("li:last",g).addClass(h)[0];m[0].scrollTop=o.offsetTop-o.offsetHeight}return false;break;case 40:if(b()){return false}i=e(p,g);var a=i.next().addClass(h)[0];if(a){i.removeClass(h);if(a.offsetTop+a.offsetHeight>s+m[0].offsetHeight){m[0].scrollTop=s+a.offsetHeight}}else{i.removeClass(h);a=e("li:first",g).addClass(h)[0];m[0].scrollTop=0}return false;break;case 13:if(m.is(":visible")){var l=e(p,g)[0];t(r,l,m,u)}return false;break;case 27:m.hide();return false;break}return true});e(r).keyup(function(e){f=false});this.getTime=function(){return s(r.value,u)};this.setTime=function(t){r.value=n(i(t,u),u);e(r).change()}};e.fn.timePicker.defaults={step:30,startTime:new Date(0,0,0,0,0,0),endTime:new Date(0,0,0,23,30,0),separator:":",show24Hours:true}})(jQuery)
includes/js/events-manager.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ function em_load_jquery_css(){if(EM.ui_css&&0==jQuery("script#jquery-ui-css").length){var e=document.createElement("link");e.id="jquery-ui-css",e.rel="stylesheet",e.href=EM.ui_css,document.body.appendChild(e)}}function em_setup_datepicker(e){e=jQuery(e);var t={altFormat:"yy-mm-dd",changeMonth:!0,changeYear:!0,firstDay:EM.firstDay,yearRange:"-100:+10"};EM.dateFormat&&(t.dateFormat=EM.dateFormat),EM.yearRange&&(t.yearRange=EM.yearRange),jQuery(document).triggerHandler("em_datepicker",t),dateDivs=e.find(".em-date-single, .em-date-range"),dateDivs.length>0&&(dateDivs.find("input.em-date-input-loc").each(function(e,a){var a=jQuery(a),n=a.nextAll("input.em-date-input").first(),o=n.val();if(a.datepicker(t),a.datepicker("option","altField",n),o){var i=jQuery.datepicker.formatDate(EM.dateFormat,jQuery.datepicker.parseDate("yy-mm-dd",o));a.val(i),n.val(o)}a.change(function(){""==jQuery(this).val()&&jQuery(this).nextAll(".em-date-input").first().val("")})}),dateDivs.filter(".em-date-range").find("input.em-date-input-loc").each(function(e,t){if(t=jQuery(t),t.hasClass("em-date-start"))t.datepicker("option","onSelect",function(e){var t=jQuery(this),a=t.parents(".em-date-range").find(".em-date-end").first();t.val()>a.val()&&""!=a.val()&&(a.datepicker("setDate",e),a.trigger("change")),a.datepicker("option","minDate",e)});else if(t.hasClass("em-date-end")){var a=t.parents(".em-date-range").find(".em-date-start").first();""!=a.val()&&t.datepicker("option","minDate",a.val())}}))}function em_setup_timepicker(e){e=jQuery(e),e.find(".em-time-input").timePicker({show24Hours:1==EM.show24hours,step:15}),e.find(".em-time-range input.em-time-start").each(function(e,t){jQuery(t).data("oldTime",jQuery.timePicker(t).getTime())}).change(function(){var e=jQuery(this),t=e.nextAll(".em-time-end");if(t.val()){var a=e.data("oldTime"),n=jQuery.timePicker(t).getTime()-a,o=jQuery.timePicker(e).getTime();jQuery.timePicker(t).getTime()>=a&&jQuery.timePicker(t).setTime(new Date(new Date(o.getTime()+n))),e.data("oldTime",o)}}),e.find(".em-time-range input.em-time-end").change(function(){var e=jQuery(this),t=e.prevAll(".em-time-start");t.val()&&(jQuery.timePicker(t).getTime()>jQuery.timePicker(this).getTime()&&(0==jQuery(".em-date-end").val().length||jQuery(".em-date-start").val()==jQuery(".em-date-end").val())?e.addClass("error"):e.removeClass("error"))}),e.find(".em-time-range input.em-time-all-day").change(function(){var e=jQuery(this);e.is(":checked")?e.siblings(".em-time-input").css("background-color","#ccc"):e.siblings(".em-time-input").css("background-color","#fff")}).trigger("change")}function em_maps_load(){if(!em_maps_loaded)if(0!=jQuery("script#google-maps").length||"object"==typeof google&&"object"==typeof google.maps)"object"!=typeof google||"object"!=typeof google.maps||em_maps_loaded?jQuery("script#google-maps").length>0&&jQuery(window).load(function(){em_maps_loaded||em_maps()}):em_maps();else{var e=document.createElement("script");e.type="text/javascript",e.id="google-maps";var t=EM.is_ssl?"https:":"http:";e.src=t+"//maps.google.com/maps/api/js?v=3.12&sensor=false&libraries=places&callback=em_maps",document.body.appendChild(e)}}function em_maps_load_locations(e){var e=jQuery(e),t=e.attr("id").replace("em-locations-map-",""),a=jQuery.parseJSON(e.nextAll(".em-locations-map-coords").first().text());if(null==a)var a=jQuery.parseJSON(jQuery("#em-locations-map-coords-"+t).text());jQuery.getJSON(document.URL,a,function(a){if(a.length>0){var n={mapTypeId:google.maps.MapTypeId.ROADMAP};jQuery(document).triggerHandler("em_maps_locations_map_options",n);var o={};jQuery(document).triggerHandler("em_maps_location_marker_options",o),maps[t]=new google.maps.Map(e[0],n),maps_markers[t]=[];for(var i=[0,0],r=[0,0],c=0;c<a.length;c++)if(0!=a[c].location_latitude||0!=a[c].location_longitude){var s=parseFloat(a[c].location_latitude),l=parseFloat(a[c].location_longitude),m=new google.maps.LatLng(s,l);jQuery.extend(o,{position:m,map:maps[t]});var d=new google.maps.Marker(o);maps_markers[t].push(d),d.setTitle(a[c].location_name);var u='<div class="em-map-balloon"><div id="em-map-balloon-'+t+'" class="em-map-balloon-content">'+a[c].location_balloon+"</div></div>";em_map_infobox(d,u,maps[t]),i[0]=s<i[0]||0==c?s:i[0],i[1]=l<i[1]||0==c?l:i[1],r[0]=s>r[0]||0==c?s:r[0],r[1]=l>r[1]||0==c?l:r[1]}var p=new google.maps.LatLng(i[0],i[1]),g=new google.maps.LatLng(r[0],r[1]),f=new google.maps.LatLngBounds(p,g);maps[t].fitBounds(f),jQuery(document).triggerHandler("em_maps_locations_hook",[maps[t],a,t])}else e.children().first().html("No locations found"),jQuery(document).triggerHandler("em_maps_locations_hook_not_found",[e])})}function em_maps_load_location(e){e=jQuery(e);var t=e.attr("id").replace("em-location-map-","");em_LatLng=new google.maps.LatLng(jQuery("#em-location-map-coords-"+t+" .lat").text(),jQuery("#em-location-map-coords-"+t+" .lng").text());var a={zoom:14,center:em_LatLng,mapTypeId:google.maps.MapTypeId.ROADMAP,mapTypeControl:!1};jQuery(document).triggerHandler("em_maps_location_map_options",a),maps[t]=new google.maps.Map(document.getElementById("em-location-map-"+t),a);var n={position:em_LatLng,map:maps[t]};jQuery(document).triggerHandler("em_maps_location_marker_options",n),maps_markers[t]=new google.maps.Marker(n),infowindow=new google.maps.InfoWindow({content:jQuery("#em-location-map-info-"+t+" .em-map-balloon").get(0)}),infowindow.open(maps[t],maps_markers[t]),maps[t].panBy(40,-70),jQuery(document).triggerHandler("em_maps_location_hook",[maps[t],infowindow,maps_markers[t],t]),jQuery(window).on("resize",function(){google.maps.event.trigger(maps[t],"resize"),maps[t].setCenter(maps_markers[t].getPosition()),maps[t].panBy(40,-70)})}function em_maps(){if(jQuery(".em-location-map").each(function(e,t){em_maps_load_location(t)}),jQuery(".em-locations-map").each(function(e,t){em_maps_load_locations(t)}),jQuery("select#location-select-id, input#location-address").length>0){var e,t,a=function(){var a=jQuery("#location-latitude").val(),n=jQuery("#location-longitude").val();if(0!=a||0!=n){var o=new google.maps.LatLng(a,n);t.setPosition(o);var i=jQuery("input#location-name").length>0?jQuery("input#location-name").val():jQuery("input#title").val();t.setTitle(jQuery("input#location-name input#title, #location-select-id").first().val()),jQuery("#em-map").show(),jQuery("#em-map-404").hide(),google.maps.event.trigger(e,"resize"),e.setCenter(o),e.panBy(40,-55),infoWindow.setContent('<div id="location-balloon-content"><strong>'+i+"</strong><br/>"+jQuery("#location-address").val()+"<br/>"+jQuery("#location-town").val()+"</div>"),infoWindow.open(e,t),jQuery(document).triggerHandler("em_maps_location_hook",[e,infowindow,t,0])}else jQuery("#em-map").hide(),jQuery("#em-map-404").show()},n=function(a){jQuery("#em-map").length>0&&jQuery.getJSON(document.URL,{em_ajax_action:"get_location",id:a},function(a){0!=a.location_latitude&&0!=a.location_longitude?(loc_latlng=new google.maps.LatLng(a.location_latitude,a.location_longitude),t.setPosition(loc_latlng),t.setTitle(a.location_name),t.setDraggable(!1),jQuery("#em-map").show(),jQuery("#em-map-404").hide(),e.setCenter(loc_latlng),e.panBy(40,-55),infoWindow.setContent('<div id="location-balloon-content">'+a.location_balloon+"</div>"),infoWindow.open(e,t),google.maps.event.trigger(e,"resize"),jQuery(document).triggerHandler("em_maps_location_hook",[e,infowindow,t,0])):(jQuery("#em-map").hide(),jQuery("#em-map-404").show())})};if(jQuery("#location-select-id, input#location-id").change(function(){n(jQuery(this).val())}),jQuery("#location-name, #location-town, #location-address, #location-state, #location-postcode, #location-country").change(function(){var e=[jQuery("#location-address").val(),jQuery("#location-town").val(),jQuery("#location-state").val(),jQuery("#location-postcode").val()],t="";return jQuery.each(e,function(e,a){""!=a&&(t=""==t?t+a:t+", "+a)}),""==t?(jQuery("#em-map").hide(),jQuery("#em-map-404").show(),!1):(0!=jQuery("#location-country option:selected").val()&&(t=""==t?t+jQuery("#location-country option:selected").text():t+", "+jQuery("#location-country option:selected").text()),void(""!=t&&jQuery("#em-map").length>0&&i.geocode({address:t},function(e,t){t==google.maps.GeocoderStatus.OK&&(jQuery("#location-latitude").val(e[0].geometry.location.lat()),jQuery("#location-longitude").val(e[0].geometry.location.lng())),a()})))}),jQuery("#em-map").length>0){var o=new google.maps.LatLng(0,0);e=new google.maps.Map(document.getElementById("em-map"),{zoom:14,center:o,mapTypeId:google.maps.MapTypeId.ROADMAP,mapTypeControl:!1});var t=new google.maps.Marker({position:o,map:e,draggable:!0});infoWindow=new google.maps.InfoWindow({content:""});var i=new google.maps.Geocoder;google.maps.event.addListener(infoWindow,"domready",function(){document.getElementById("location-balloon-content").parentNode.style.overflow="",document.getElementById("location-balloon-content").parentNode.parentNode.style.overflow=""}),google.maps.event.addListener(t,"dragend",function(){var a=t.getPosition();jQuery("#location-latitude").val(a.lat()),jQuery("#location-longitude").val(a.lng()),e.setCenter(a),e.panBy(40,-55)}),jQuery("#location-select-id").length>0?jQuery("#location-select-id").trigger("change"):a(),jQuery(document).triggerHandler("em_map_loaded",[e,infowindow,t])}jQuery(window).on("resize",function(){google.maps.event.trigger(e,"resize"),e.setCenter(t.getPosition()),e.panBy(40,-55)})}em_maps_loaded=!0,jQuery(document).triggerHandler("em_maps_loaded")}function em_map_infobox(e,t,a){var n=new google.maps.InfoWindow({content:t});google.maps.event.addListener(e,"click",function(){infowindow&&infowindow.close(),infowindow=n,n.open(a,e)})}jQuery(document).ready(function(e){function t(){e(".interval-desc").hide();var t="-plural";(1==e("input#recurrence-interval").val()||""==e("input#recurrence-interval").val())&&(t="-singular");var a="span#interval-"+e("select#recurrence-frequency").val()+t;e(a).show()}function a(){e("p.alternate-selector").hide(),e("p#"+e("select#recurrence-frequency").val()+"-selector").show()}function n(){e("input#event-recurrence").is(":checked")?(e("#event_recurrence_pattern").fadeIn(),e("#event-date-explanation").hide(),e("#recurrence-dates-explanation").show(),e("h3#recurrence-dates-title").show(),e("h3#event-date-title").hide()):(e("#event_recurrence_pattern").hide(),e("#recurrence-dates-explanation").hide(),e("#event-date-explanation").show(),e("h3#recurrence-dates-title").hide(),e("h3#event-date-title").show())}var o=!1;if(e("#start-time").each(function(t,a){e(a).addClass("em-time-input em-time-start").next("#end-time").addClass("em-time-input em-time-end").parent().addClass("em-time-range")}),e(".em-time-input").length>0&&em_setup_timepicker("body"),e(".em-calendar-wrapper a").unbind("click"),e(".em-calendar-wrapper a").undelegate("click"),e(".em-calendar-wrapper").delegate("a.em-calnav, a.em-calnav","click",function(t){t.preventDefault(),e(this).closest(".em-calendar-wrapper").prepend('<div class="loading" id="em-loading"></div>');var a=em_ajaxify(e(this).attr("href"));e(this).closest(".em-calendar-wrapper").load(a,function(){e(this).trigger("em_calendar_load")})}),e(document).delegate(".em-toggle","click change",function(t){t.preventDefault();var a=e(this),n=a.attr("rel").split(":");a.hasClass("show-search")?(n.length>1?a.closest(n[1]).find(n[0]).slideUp():e(n[0]).slideUp(),a.find(".show, .show-advanced").show(),a.find(".hide, .hide-advanced").hide(),a.removeClass("show-search")):(n.length>1?a.closest(n[1]).find(n[0]).slideDown():e(n[0]).slideDown(),a.find(".show, .show-advanced").hide(),a.find(".hide, .hide-advanced").show(),a.addClass("show-search"))}),EM.search_term_placeholder&&("placeholder"in document.createElement("input")?e("input.em-events-search-text, input.em-search-text").attr("placeholder",EM.search_term_placeholder):e("input.em-events-search-text, input.em-search-text").blur(function(){""==this.value&&(this.value=EM.search_term_placeholder)}).focus(function(){this.value==EM.search_term_placeholder&&(this.value="")}).trigger("blur")),e(".em-search-form select[name=country]").change(function(){var t=e(this);if(e(".em-search select[name=state]").html('<option value="">'+EM.txt_loading+"</option>"),e(".em-search select[name=region]").html('<option value="">'+EM.txt_loading+"</option>"),e(".em-search select[name=town]").html('<option value="">'+EM.txt_loading+"</option>"),""!=t.val()){t.closest(".em-search-location").find(".em-search-location-meta").slideDown();var a={action:"search_states",country:t.val(),return_html:!0};e(".em-search select[name=state]").load(EM.ajaxurl,a),a.action="search_regions",e(".em-search select[name=region]").load(EM.ajaxurl,a),a.action="search_towns",e(".em-search select[name=town]").load(EM.ajaxurl,a)}else t.closest(".em-search-location").find(".em-search-location-meta").slideUp()}),e(".em-search-form select[name=region]").change(function(){e(".em-search select[name=state]").html('<option value="">'+EM.txt_loading+"</option>"),e(".em-search select[name=town]").html('<option value="">'+EM.txt_loading+"</option>");var t={action:"search_states",region:e(this).val(),country:e(".em-search-form select[name=country]").val(),return_html:!0};e(".em-search select[name=state]").load(EM.ajaxurl,t),t.action="search_towns",e(".em-search select[name=town]").load(EM.ajaxurl,t)}),e(".em-search-form select[name=state]").change(function(){e(".em-search select[name=town]").html('<option value="">'+EM.txt_loading+"</option>");var t={action:"search_towns",state:e(this).val(),region:e(".em-search-form select[name=region]").val(),country:e(".em-search-form select[name=country]").val(),return_html:!0};e(".em-search select[name=town]").load(EM.ajaxurl,t)}),e(document).delegate(".em-search-form, .em-events-search-form","submit",function(t){var a=e(this);this.em_search&&this.em_search.value==EM.txt_search&&(this.em_search.value="");var n=a.closest(".em-search-wrapper").find(".em-search-ajax");if(0==n.length&&(n=e(".em-search-ajax")),n.length>0){n.append('<div class="loading" id="em-loading"></div>');var o=a.find(".em-search-submit");o.data("buttonText",o.val()).val(EM.txt_searching);var i=o.children("img");i.length>0&&i.attr("src",i.attr("src").replace("search-mag.png","search-loading.gif"));var r=a.serialize();return e.ajax(EM.ajaxurl,{type:"POST",dataType:"html",data:r,success:function(c){o.val(o.data("buttonText")),i.length>0&&i.attr("src",i.attr("src").replace("search-loading.gif","search-mag.png")),n.replaceWith(c),""==a.find("input[name=em_search]").val()&&a.find("input[name=em_search]").val(EM.txt_search),n=a.closest(".em-search-wrapper").find(".em-search-ajax"),0==n.length&&(n=e(".em-search-ajax")),jQuery(document).triggerHandler("em_search_ajax",[r,n,t])}}),t.preventDefault(),!1}}),e(".em-search-ajax").length>0&&e(document).delegate(".em-search-ajax a.page-numbers","click",function(t){var a=e(this),n=a.closest(".em-pagination").attr("data-em-ajax"),o=a.closest(".em-search-ajax"),i=o.parent(),r=a.attr("href").split("?"),c=r[1];return""!=n&&(c=""!=c?c+"&"+n:n),o.append('<div class="loading" id="em-loading"></div>'),e.ajax(EM.ajaxurl,{type:"POST",dataType:"html",data:c,success:function(e){o.replaceWith(e),o=i.find(".em-search-ajax"),jQuery(document).triggerHandler("em_search_ajax",[c,o,t])}}),t.preventDefault(),!1}),e(".events-table").on("click",".em-event-delete",function(){return confirm("Are you sure you want to delete?")?void(window.location.href=this.href):!1}),e("#event-form #event-image-delete, #location-form #location-image-delete").on("click",function(){var t=e(this);t.is(":checked")?t.closest(".event-form-image, .location-form-image").find("#event-image-img, #location-image-img").hide():t.closest(".event-form-image, .location-form-image").find("#event-image-img, #location-image-img").show()}),e("#em-tickets-form").length>0){e("#event-rsvp").click(function(t){this.checked?e("#event-rsvp-options").fadeIn():(confirmation=confirm(EM.disable_bookings_warning),0==confirmation?t.preventDefault():e("#event-rsvp-options").hide())}),e("input#event-rsvp").is(":checked")?e("div#rsvp-data").fadeIn():e("div#rsvp-data").hide();var i=function(){e("#em-tickets-form table tbody tr.em-tickets-row").show(),e("#em-tickets-form table tbody tr.em-tickets-row-form").hide()};e("#em-recurrence-checkbox").length>0?e("#em-recurrence-checkbox").change(function(){e("#em-recurrence-checkbox").is(":checked")?(e("#em-tickets-form .ticket-dates-from-recurring, #em-tickets-form .ticket-dates-to-recurring, #event-rsvp-options .em-booking-date-recurring").show(),e("#em-tickets-form .ticket-dates-from-normal, #em-tickets-form .ticket-dates-to-normal, #event-rsvp-options .em-booking-date-normal, #em-tickets-form .hidden").hide()):(e("#em-tickets-form .ticket-dates-from-normal, #em-tickets-form .ticket-dates-to-normal, #event-rsvp-options .em-booking-date-normal").show(),e("#em-tickets-form .ticket-dates-from-recurring, #em-tickets-form .ticket-dates-to-recurring, #event-rsvp-options .em-booking-date-recurring, #em-tickets-form .hidden").hide())}).trigger("change"):e("#em-form-recurrence").length>0?(e("#em-tickets-form .ticket-dates-from-recurring, #em-tickets-form .ticket-dates-to-recurring, #event-rsvp-options .em-booking-date-recurring").show(),e("#em-tickets-form .ticket-dates-from-normal, #em-tickets-form .ticket-dates-to-normal, #event-rsvp-options .em-booking-date-normal, #em-tickets-form .hidden").hide()):e("#em-tickets-form .ticket-dates-from-recurring, #em-tickets-form .ticket-dates-to-recurring, #event-rsvp-options .em-booking-date-recurring, #em-tickets-form .hidden").hide(),e("#em-tickets-add").click(function(t){t.preventDefault(),i();var a=e("#em-tickets-form table tbody"),n=a.length+1,o=a.first().clone(!0).attr("id","em-ticket-"+n).appendTo(e("#em-tickets-form table"));o.find("*[name]").each(function(t,a){a=e(a),a.attr("name",a.attr("name").replace("em_tickets[0]","em_tickets["+n+"]"))}),o.show().find(".ticket-actions-edit").trigger("click"),o.find(".em-date-input-loc").datepicker("destroy").removeAttr("id"),o.find(".em-time-input").unbind().each(function(){this.timePicker=!1}),em_setup_datepicker(o),em_setup_timepicker(o),e("html, body").animate({scrollTop:o.offset().top-30})}),e(document).delegate(".ticket-actions-edit","click",function(t){t.preventDefault(),i();var a=e(this).closest("tbody");return a.find("tr.em-tickets-row").hide(),a.find("tr.em-tickets-row-form").fadeIn(),!1}),e(document).delegate(".ticket-actions-edited","click",function(t){t.preventDefault();var a=e(this).closest("tbody"),n=a.attr("id").replace("em-ticket-","");return a.find(".em-tickets-row").fadeIn(),a.find(".em-tickets-row-form").hide(),a.find("*[name]").each(function(t,o){if(o=e(o),"ticket_start_pub"==o.attr("name"))a.find("span.ticket_start").text(o.attr("value"));else if("ticket_end_pub"==o.attr("name"))a.find("span.ticket_end").text(o.attr("value"));else if(o.attr("name")=="em_tickets["+n+"][ticket_type]")"members"==o.find(":selected").val()&&a.find("span.ticket_name").prepend("* ");else if(o.attr("name")=="em_tickets["+n+"][ticket_start_recurring_days]"){var i="before"==a.find("select.ticket-dates-from-recurring-when").val()?"-"+o.attr("value"):o.attr("value");""!=o.attr("value")?(a.find("span.ticket_start_recurring_days").text(i),a.find("span.ticket_start_recurring_days_text, span.ticket_start_time").removeClass("hidden").show()):(a.find("span.ticket_start_recurring_days").text(" - "),a.find("span.ticket_start_recurring_days_text, span.ticket_start_time").removeClass("hidden").hide())}else if(o.attr("name")=="em_tickets["+n+"][ticket_end_recurring_days]"){var i="before"==a.find("select.ticket-dates-to-recurring-when").val()?"-"+o.attr("value"):o.attr("value");""!=o.attr("value")?(a.find("span.ticket_end_recurring_days").text(i),a.find("span.ticket_end_recurring_days_text, span.ticket_end_time").removeClass("hidden").show()):(a.find("span.ticket_end_recurring_days").text(" - "),a.find("span.ticket_end_recurring_days_text, span.ticket_end_time").removeClass("hidden").hide())}else a.find("."+o.attr("name").replace("em_tickets["+n+"][","").replace("]","").replace("[]","")).text(o.attr("value"))}),e(document).triggerHandler("em_maps_tickets_edit",[a,n,!0]),e("html, body").animate({scrollTop:a.parent().offset().top-30}),!1}),e(document).delegate(".em-ticket-form select.ticket_type","change",function(){var t=e(this);"members"==t.find("option:selected").val()?t.closest(".em-ticket-form").find(".ticket-roles").fadeIn():t.closest(".em-ticket-form").find(".ticket-roles").hide()}),e(document).delegate(".em-ticket-form .ticket-options-advanced","click",function(t){t.preventDefault();var a=e(this);a.hasClass("show")?(a.closest(".em-ticket-form").find(".em-ticket-form-advanced").fadeIn(),a.find(".show").hide(),a.find(".hide").show()):(a.closest(".em-ticket-form").find(".em-ticket-form-advanced").hide(),a.find(".show").show(),a.find(".hide").hide()),a.toggleClass("show").toggleClass("hide")}),e(".em-ticket-form").each(function(){var t=!1,a=e(this);a.find('.em-ticket-form-advanced input[type="text"]').each(function(){""!=this.value&&(t=!0)}),a.find('.em-ticket-form-advanced input[type="checkbox"]:checked').length>0&&(t=!0),a.find(".em-ticket-form-advanced option:selected").each(function(){""!=this.value&&(t=!0)}),t&&a.find(".ticket-options-advanced").trigger("click")}),e(document).delegate(".ticket-actions-delete","click",function(t){t.preventDefault();var a=e(this),n=a.closest("tbody");return n.find("input.ticket_id").val()>0?(a.text("Deleting..."),e.getJSON(e(this).attr("href"),{em_ajax_action:"delete_ticket",id:n.find("input.ticket_id").val()},function(e){e.result?n.remove():(a.text("Delete"),alert(e.error))})):n.remove(),!1})}if(e("#em-bookings-table").length>0){e(document).delegate("#em-bookings-table .tablenav-pages a","click",function(){var t=e(this),a=t.parents("#em-bookings-table form.bookings-filter"),n=t.attr("href").match(/#[0-9]+/);if(null!=n&&n.length>0){var o=n[0].replace("#","");a.find("input[name=pno]").val(o)}else a.find("input[name=pno]").val(1);return a.trigger("submit"),!1});var r={modal:!0,autoOpen:!1,minWidth:500,height:"auto",buttons:[{text:EM.bookings_settings_save,click:function(t){t.preventDefault();var a=e("#em-bookings-table form.bookings-filter [name=cols]").val(""),n=e("form#em-bookings-table-settings-form input.em-bookings-col-item");e.each(n,function(e,t){1==t.value&&a.val(""!=a.val()?a.val()+","+t.name:t.name)}),e("#em-bookings-table-settings").trigger("submitted"),e("#em-bookings-table form.bookings-filter").trigger("submit"),e(this).dialog("close")}}]},c={modal:!0,autoOpen:!1,minWidth:500,height:"auto",buttons:[{text:EM.bookings_export_save,click:function(){e(this).children("form").submit(),e(this).dialog("close")}}]};if(e("#em-bookings-table-settings").length>0){e("#em-bookings-table-settings").dialog(r),e(document).delegate("#em-bookings-table-settings-trigger","click",function(t){t.preventDefault(),e("#em-bookings-table-settings").dialog("open")}),e("#em-bookings-table-export").dialog(c),e(document).delegate("#em-bookings-table-export-trigger","click",function(t){t.preventDefault(),e("#em-bookings-table-export").dialog("open")});var s=function(){e("#em-bookings-table-export-form input[name=show_tickets]").is(":checked")?(e("#em-bookings-table-export-form .em-bookings-col-item-ticket").show(),e("#em-bookings-table-export-form #em-bookings-export-cols-active .em-bookings-col-item-ticket input").val(1)):e("#em-bookings-table-export-form .em-bookings-col-item-ticket").hide().find("input").val(0)};e("#em-bookings-table form select").each(function(t,a){e(a).change(function(){var t=e(this),a=e("#em-bookings-table-export-form input[name="+t.attr("name")+"]"),n=t.find("option:selected");a.val(n.val())})}),s(),e("#em-bookings-table-export-form input[name=show_tickets]").click(s),e(".em-bookings-cols-sortable").sortable({connectWith:".em-bookings-cols-sortable",update:function(e,t){t.item.parents("ul#em-bookings-cols-active, ul#em-bookings-export-cols-active").length>0?t.item.addClass("ui-state-highlight").removeClass("ui-state-default").children("input").val(1):t.item.addClass("ui-state-default").removeClass("ui-state-highlight").children("input").val(0)}}).disableSelection(),o=!0}e(document).delegate("#em-bookings-table form.bookings-filter","submit",function(){var t=e(this);return t.parents("#em-bookings-table").find(".table-wrap").first().append('<div id="em-loading" />'),e.post(EM.ajaxurl,t.serializeArray(),function(a){var n=t.parents("#em-bookings-table").first();n.replaceWith(a),e("#em-bookings-table-export input[name=scope]").val(n.find("select[name=scope]").val()),e("#em-bookings-table-export input[name=status]").val(n.find("select[name=status]").val()),jQuery(document).triggerHandler("em_bookings_filtered",[a,n,t])}),!1}),e(document).delegate(".em-bookings-approve,.em-bookings-reject,.em-bookings-unapprove,.em-bookings-delete","click",function(){var t=e(this);if(t.hasClass("em-bookings-delete")&&!confirm(EM.booking_delete))return!1;var a=em_ajaxify(t.attr("href")),n=t.parents("td").first();return n.html(EM.txt_loading),n.load(a),!1})}e(".em_bookings_events_table").length>0&&(e(document).delegate(".em_bookings_events_table form","submit",function(){var t=e(this),a=em_ajaxify(t.attr("action"));return t.parents(".em_bookings_events_table").find(".table-wrap").first().append('<div id="em-loading" />'),e.get(a,t.serializeArray(),function(e){t.parents(".em_bookings_events_table").first().replaceWith(e)}),!1}),e(document).delegate(".em_bookings_events_table .tablenav-pages a","click",function(){var t=e(this),a=em_ajaxify(t.attr("href"));return t.parents(".em_bookings_events_table").find(".table-wrap").first().append('<div id="em-loading" />'),e.get(a,function(e){t.parents(".em_bookings_events_table").first().replaceWith(e)}),!1})),e("a.em-booking-button").click(function(t){t.preventDefault();var a=e(this);if(a.text()!=EM.bb_booked&&e(this).text()!=EM.bb_booking){a.text(EM.bb_booking);var n=a.attr("id").split("_");e.ajax({url:EM.ajaxurl,dataType:"jsonp",data:{event_id:n[1],_wpnonce:n[2],action:"booking_add_one"},success:function(e){a.text(e.result?EM.bb_booked:EM.bb_error),""!=e.message&&alert(e.message)},error:function(){a.text(EM.bb_error)}})}return!1}),e("a.em-cancel-button").click(function(t){t.preventDefault();var a=e(this);if(a.text()!=EM.bb_cancelled&&a.text()!=EM.bb_canceling){a.text(EM.bb_canceling);var n=a.attr("id").split("_");e.ajax({url:EM.ajaxurl,dataType:"jsonp",data:{booking_id:n[1],_wpnonce:n[2],action:"booking_cancel"},success:function(e){a.text(e.result?EM.bb_cancelled:EM.bb_cancel_error)},error:function(){a.text(EM.bb_cancel_error)}})}return!1}),e(".em-date-single, .em-date-range, #em-date-start").length>0&&("en"!=EM.locale&&EM.locale_data&&e.datepicker.setDefaults(EM.locale_data),o=!0,em_setup_datepicker("body")),o&&em_load_jquery_css(),e("#recurrence-dates-explanation").hide(),e("#date-to-submit").hide(),e("#end-date-to-submit").hide(),e("#localised-date").show(),e("#localised-end-date").show(),e("#em-wrapper input.select-all").change(function(){e(this).is(":checked")?(e("input.row-selector").prop("checked",!0),e("input.select-all").prop("checked",!0)):(e("input.row-selector").prop("checked",!1),e("input.select-all").prop("checked",!1))}),t(),a(),n(),e("input#event-recurrence").change(n),e("input#recurrence-interval").keyup(t),e("select#recurrence-frequency").change(t),e("select#recurrence-frequency").change(a),(e(".em-location-map").length>0||e(".em-locations-map").length>0||e("#em-map").length>0||e(".em-search-geo").length>0)&&em_maps_load(),jQuery("div.em-location-data input#location-name").length>0&&(jQuery("div.em-location-data input#location-name").autocomplete({source:EM.locationajaxurl,minLength:2,focus:function(e,t){return jQuery("input#location-id").val(t.item.value),!1},select:function(e,t){return jQuery("input#location-id").val(t.item.id).trigger("change"),jQuery("input#location-name").val(t.item.value),jQuery("input#location-address").val(t.item.address),jQuery("input#location-town").val(t.item.town),jQuery("input#location-state").val(t.item.state),jQuery("input#location-region").val(t.item.region),jQuery("input#location-postcode").val(t.item.postcode),""==t.item.country?jQuery("select#location-country option:selected").removeAttr("selected"):jQuery('select#location-country option[value="'+t.item.country+'"]').attr("selected","selected"),jQuery("div.em-location-data input, div.em-location-data select").css("background-color","#ccc").attr("readonly","readonly"),jQuery("#em-location-reset").show(),jQuery("#em-location-search-tip").hide(),jQuery(document).triggerHandler("em_locations_autocomplete_selected",[e,t]),!1}}).data("ui-autocomplete")._renderItem=function(e,t){return html_val="<a>"+t.label+'<br><span style="font-size:11px"><em>'+t.address+", "+t.town+"</em></span></a>",jQuery("<li></li>").data("item.autocomplete",t).append(html_val).appendTo(e)},jQuery("#em-location-reset a").click(function(){return jQuery("div.em-location-data input").css("background-color","#fff").val("").removeAttr("readonly"),jQuery("div.em-location-data select").css("background-color","#fff"),jQuery("div.em-location-data option:selected").removeAttr("selected"),jQuery("input#location-id").val(""),jQuery("#em-location-reset").hide(),jQuery("#em-location-search-tip").show(),jQuery("#em-map").hide(),jQuery("#em-map-404").show(),"undefined"!=typeof marker&&(marker.setPosition(new google.maps.LatLng(0,0)),infoWindow.close(),marker.setDraggable(!0)),!1}),"0"!=jQuery("input#location-id").val()&&""!=jQuery("input#location-id").val()&&(jQuery("div.em-location-data input, div.em-location-data select").css("background-color","#ccc").attr("readonly","readonly"),jQuery("#em-location-reset").show(),jQuery("#em-location-search-tip").hide()))});var em_ajaxify=function(e){return-1!=e.search("em_ajax=0")?e=e.replace("em_ajax=0","em_ajax=1"):e+=-1!=e.search(/\?/)?"&em_ajax=1":"?em_ajax=1",e},em_maps_loaded=!1,maps={},maps_markers={},infowindow;jQuery(document).bind("em_search_ajax",function(e,t,a){em_maps_loaded&&(a.find(".em-location-map").each(function(e,t){em_maps_load_location(t)}),a.find(".em-locations-map").each(function(e,t){em_maps_load_locations(t)}))});
2
+ /* jQuery timePicker - http://labs.perifer.se/timedatepicker/ @ http://github.com/perifer/timePicker commit 100644 */
3
+ (function(e){function t(t,n,r,i){t.value=e(n).text();e(t).change();if(!navigator.userAgent.match(/msie/i)){t.focus()}r.hide()}function n(e,t){var n=e.getHours();var i=t.show24Hours?n:(n+11)%12+1;var s=e.getMinutes();return r(i)+t.separator+r(s)+(t.show24Hours?"":n<12?" AM":" PM")}function r(e){return(e<10?"0":"")+e}function i(e,t){return typeof e=="object"?o(e):s(e,t)}function s(e,t){if(e){var n=e.split(t.separator);var r=parseFloat(n[0]);var i=parseFloat(n[1]);if(!t.show24Hours){if(r===12&&e.indexOf("AM")!==-1){r=0}else if(r!==12&&e.indexOf("PM")!==-1){r+=12}}var s=new Date(0,0,0,r,i,0);return o(s)}return null}function o(e){e.setFullYear(2001);e.setMonth(0);e.setDate(0);return e}e.fn.timePicker=function(t){var n=e.extend({},e.fn.timePicker.defaults,t);return this.each(function(){e.timePicker(this,n)})};e.timePicker=function(t,n){var r=e(t)[0];return r.timePicker||(r.timePicker=new jQuery._timePicker(r,n))};e.timePicker.version="0.3";e._timePicker=function(r,u){var a=false;var f=false;var l=i(u.startTime,u);var c=i(u.endTime,u);var h="selected";var p="li."+h;e(r).attr("autocomplete","OFF");var d=[];var v=new Date(l);while(v<=c){d[d.length]=n(v,u);v=new Date(v.setMinutes(v.getMinutes()+u.step))}var m=e('<div class="time-picker'+(u.show24Hours?"":" time-picker-12hours")+'"></div>');var g=e("<ul></ul>");for(var y=0;y<d.length;y++){g.append("<li>"+d[y]+"</li>")}m.append(g);m.appendTo("body").hide();m.mouseover(function(){a=true}).mouseout(function(){a=false});e("li",g).mouseover(function(){if(!f){e(p,m).removeClass(h);e(this).addClass(h)}}).mousedown(function(){a=true}).click(function(){t(r,this,m,u);a=false});var b=function(){if(m.is(":visible")){return false}e("li",m).removeClass(h);var t=e(r).offset();m.css({top:t.top+r.offsetHeight,left:t.left});m.show();var i=r.value?s(r.value,u):l;var a=l.getHours()*60+l.getMinutes();var f=i.getHours()*60+i.getMinutes()-a;var p=Math.round(f/u.step);var d=o(new Date(0,0,0,0,p*u.step+a,0));d=l<d&&d<=c?d:l;var v=e("li:contains("+n(d,u)+")",m);if(v.length){v.addClass(h);m[0].scrollTop=v[0].offsetTop}return true};e(r).focus(b).click(b);e(r).blur(function(){if(!a){m.hide()}});e(r)["keydown"](function(n){var i;f=true;var s=m[0].scrollTop;switch(n.keyCode){case 38:if(b()){return false}i=e(p,g);var o=i.prev().addClass(h)[0];if(o){i.removeClass(h);if(o.offsetTop<s){m[0].scrollTop=s-o.offsetHeight}}else{i.removeClass(h);o=e("li:last",g).addClass(h)[0];m[0].scrollTop=o.offsetTop-o.offsetHeight}return false;break;case 40:if(b()){return false}i=e(p,g);var a=i.next().addClass(h)[0];if(a){i.removeClass(h);if(a.offsetTop+a.offsetHeight>s+m[0].offsetHeight){m[0].scrollTop=s+a.offsetHeight}}else{i.removeClass(h);a=e("li:first",g).addClass(h)[0];m[0].scrollTop=0}return false;break;case 13:if(m.is(":visible")){var l=e(p,g)[0];t(r,l,m,u)}return false;break;case 27:m.hide();return false;break}return true});e(r).keyup(function(e){f=false});this.getTime=function(){return s(r.value,u)};this.setTime=function(t){r.value=n(i(t,u),u);e(r).change()}};e.fn.timePicker.defaults={step:30,startTime:new Date(0,0,0,0,0,0),endTime:new Date(0,0,0,23,30,0),separator:":",show24Hours:true}})(jQuery)
includes/js/i18n/jquery-ui-i18n.js ADDED
@@ -0,0 +1,1199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Afrikaans initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Renier Pretorius. */
3
+ jQuery(function($){
4
+ $.datepicker.regional['af'] = {
5
+ closeText: 'Selekteer',
6
+ prevText: 'Vorige',
7
+ nextText: 'Volgende',
8
+ currentText: 'Vandag',
9
+ monthNames: ['Januarie','Februarie','Maart','April','Mei','Junie',
10
+ 'Julie','Augustus','September','Oktober','November','Desember'],
11
+ monthNamesShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun',
12
+ 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
13
+ dayNames: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
14
+ dayNamesShort: ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],
15
+ dayNamesMin: ['So','Ma','Di','Wo','Do','Vr','Sa'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['af']);
23
+ });
24
+ /* Arabic Translation for jQuery UI date picker plugin. */
25
+ /* Khaled Al Horani -- koko.dw@gmail.com */
26
+ /* خالد الحوراني -- koko.dw@gmail.com */
27
+ /* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */
28
+ jQuery(function($){
29
+ $.datepicker.regional['ar'] = {
30
+ closeText: 'إغلاق',
31
+ prevText: '&#x3c;السابق',
32
+ nextText: 'التالي&#x3e;',
33
+ currentText: 'اليوم',
34
+ monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'حزيران',
35
+ 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
36
+ monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
37
+ dayNames: ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'],
38
+ dayNamesShort: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],
39
+ dayNamesMin: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],
40
+ weekHeader: 'أسبوع',
41
+ dateFormat: 'dd/mm/yy',
42
+ firstDay: 0,
43
+ isRTL: true,
44
+ showMonthAfterYear: false,
45
+ yearSuffix: ''};
46
+ $.datepicker.setDefaults($.datepicker.regional['ar']);
47
+ });/* Azerbaijani (UTF-8) initialisation for the jQuery UI date picker plugin. */
48
+ /* Written by Jamil Najafov (necefov33@gmail.com). */
49
+ jQuery(function($) {
50
+ $.datepicker.regional['az'] = {
51
+ closeText: 'Bağla',
52
+ prevText: '&#x3c;Geri',
53
+ nextText: 'İrəli&#x3e;',
54
+ currentText: 'Bugün',
55
+ monthNames: ['Yanvar','Fevral','Mart','Aprel','May','İyun',
56
+ 'İyul','Avqust','Sentyabr','Oktyabr','Noyabr','Dekabr'],
57
+ monthNamesShort: ['Yan','Fev','Mar','Apr','May','İyun',
58
+ 'İyul','Avq','Sen','Okt','Noy','Dek'],
59
+ dayNames: ['Bazar','Bazar ertəsi','Çərşənbə axşamı','Çərşənbə','Cümə axşamı','Cümə','Şənbə'],
60
+ dayNamesShort: ['B','Be','Ça','Ç','Ca','C','Ş'],
61
+ dayNamesMin: ['B','B','Ç','С','Ç','C','Ş'],
62
+ weekHeader: 'Hf',
63
+ dateFormat: 'dd.mm.yy',
64
+ firstDay: 1,
65
+ isRTL: false,
66
+ showMonthAfterYear: false,
67
+ yearSuffix: ''};
68
+ $.datepicker.setDefaults($.datepicker.regional['az']);
69
+ });/* Bulgarian initialisation for the jQuery UI date picker plugin. */
70
+ /* Written by Stoyan Kyosev (http://svest.org). */
71
+ jQuery(function($){
72
+ $.datepicker.regional['bg'] = {
73
+ closeText: 'затвори',
74
+ prevText: '&#x3c;назад',
75
+ nextText: 'напред&#x3e;',
76
+ nextBigText: '&#x3e;&#x3e;',
77
+ currentText: 'днес',
78
+ monthNames: ['Януари','Февруари','Март','Април','Май','Юни',
79
+ 'Юли','Август','Септември','Октомври','Ноември','Декември'],
80
+ monthNamesShort: ['Яну','Фев','Мар','Апр','Май','Юни',
81
+ 'Юли','Авг','Сеп','Окт','Нов','Дек'],
82
+ dayNames: ['Неделя','Понеделник','Вторник','Сряда','Четвъртък','Петък','Събота'],
83
+ dayNamesShort: ['Нед','Пон','Вто','Сря','Чет','Пет','Съб'],
84
+ dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Съ'],
85
+ weekHeader: 'Wk',
86
+ dateFormat: 'dd.mm.yy',
87
+ firstDay: 1,
88
+ isRTL: false,
89
+ showMonthAfterYear: false,
90
+ yearSuffix: ''};
91
+ $.datepicker.setDefaults($.datepicker.regional['bg']);
92
+ });
93
+ /* Bosnian i18n for the jQuery UI date picker plugin. */
94
+ /* Written by Kenan Konjo. */
95
+ jQuery(function($){
96
+ $.datepicker.regional['bs'] = {
97
+ closeText: 'Zatvori',
98
+ prevText: '&#x3c;',
99
+ nextText: '&#x3e;',
100
+ currentText: 'Danas',
101
+ monthNames: ['Januar','Februar','Mart','April','Maj','Juni',
102
+ 'Juli','August','Septembar','Oktobar','Novembar','Decembar'],
103
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
104
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
105
+ dayNames: ['Nedelja','Ponedeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
106
+ dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
107
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
108
+ weekHeader: 'Wk',
109
+ dateFormat: 'dd.mm.yy',
110
+ firstDay: 1,
111
+ isRTL: false,
112
+ showMonthAfterYear: false,
113
+ yearSuffix: ''};
114
+ $.datepicker.setDefaults($.datepicker.regional['bs']);
115
+ });/* Inicialització en català per a l'extenció 'calendar' per jQuery. */
116
+ /* Writers: (joan.leon@gmail.com). */
117
+ jQuery(function($){
118
+ $.datepicker.regional['ca'] = {
119
+ closeText: 'Tancar',
120
+ prevText: '&#x3c;Ant',
121
+ nextText: 'Seg&#x3e;',
122
+ currentText: 'Avui',
123
+ monthNames: ['Gener','Febrer','Mar&ccedil;','Abril','Maig','Juny',
124
+ 'Juliol','Agost','Setembre','Octubre','Novembre','Desembre'],
125
+ monthNamesShort: ['Gen','Feb','Mar','Abr','Mai','Jun',
126
+ 'Jul','Ago','Set','Oct','Nov','Des'],
127
+ dayNames: ['Diumenge','Dilluns','Dimarts','Dimecres','Dijous','Divendres','Dissabte'],
128
+ dayNamesShort: ['Dug','Dln','Dmt','Dmc','Djs','Dvn','Dsb'],
129
+ dayNamesMin: ['Dg','Dl','Dt','Dc','Dj','Dv','Ds'],
130
+ weekHeader: 'Sm',
131
+ dateFormat: 'dd/mm/yy',
132
+ firstDay: 1,
133
+ isRTL: false,
134
+ showMonthAfterYear: false,
135
+ yearSuffix: ''};
136
+ $.datepicker.setDefaults($.datepicker.regional['ca']);
137
+ });/* Czech initialisation for the jQuery UI date picker plugin. */
138
+ /* Written by Tomas Muller (tomas@tomas-muller.net). */
139
+ jQuery(function($){
140
+ $.datepicker.regional['cs'] = {
141
+ closeText: 'Zavřít',
142
+ prevText: '&#x3c;Dříve',
143
+ nextText: 'Později&#x3e;',
144
+ currentText: 'Nyní',
145
+ monthNames: ['leden','únor','březen','duben','květen','červen',
146
+ 'červenec','srpen','září','říjen','listopad','prosinec'],
147
+ monthNamesShort: ['led','úno','bře','dub','kvě','čer',
148
+ 'čvc','srp','zář','říj','lis','pro'],
149
+ dayNames: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],
150
+ dayNamesShort: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
151
+ dayNamesMin: ['ne','po','út','st','čt','pá','so'],
152
+ weekHeader: 'Týd',
153
+ dateFormat: 'dd.mm.yy',
154
+ firstDay: 1,
155
+ isRTL: false,
156
+ showMonthAfterYear: false,
157
+ yearSuffix: ''};
158
+ $.datepicker.setDefaults($.datepicker.regional['cs']);
159
+ });
160
+ /* Danish initialisation for the jQuery UI date picker plugin. */
161
+ /* Written by Jan Christensen ( deletestuff@gmail.com). */
162
+ jQuery(function($){
163
+ $.datepicker.regional['da'] = {
164
+ closeText: 'Luk',
165
+ prevText: '&#x3c;Forrige',
166
+ nextText: 'Næste&#x3e;',
167
+ currentText: 'Idag',
168
+ monthNames: ['Januar','Februar','Marts','April','Maj','Juni',
169
+ 'Juli','August','September','Oktober','November','December'],
170
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
171
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
172
+ dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
173
+ dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],
174
+ dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],
175
+ weekHeader: 'Uge',
176
+ dateFormat: 'dd-mm-yy',
177
+ firstDay: 1,
178
+ isRTL: false,
179
+ showMonthAfterYear: false,
180
+ yearSuffix: ''};
181
+ $.datepicker.setDefaults($.datepicker.regional['da']);
182
+ });
183
+ /* German initialisation for the jQuery UI date picker plugin. */
184
+ /* Written by Milian Wolff (mail@milianw.de). */
185
+ jQuery(function($){
186
+ $.datepicker.regional['de'] = {
187
+ closeText: 'schließen',
188
+ prevText: '&#x3c;zurück',
189
+ nextText: 'Vor&#x3e;',
190
+ currentText: 'heute',
191
+ monthNames: ['Januar','Februar','März','April','Mai','Juni',
192
+ 'Juli','August','September','Oktober','November','Dezember'],
193
+ monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',
194
+ 'Jul','Aug','Sep','Okt','Nov','Dez'],
195
+ dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
196
+ dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
197
+ dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
198
+ weekHeader: 'Wo',
199
+ dateFormat: 'dd.mm.yy',
200
+ firstDay: 1,
201
+ isRTL: false,
202
+ showMonthAfterYear: false,
203
+ yearSuffix: ''};
204
+ $.datepicker.setDefaults($.datepicker.regional['de']);
205
+ });
206
+ /* Greek (el) initialisation for the jQuery UI date picker plugin. */
207
+ /* Written by Alex Cicovic (http://www.alexcicovic.com) */
208
+ jQuery(function($){
209
+ $.datepicker.regional['el'] = {
210
+ closeText: 'Κλείσιμο',
211
+ prevText: 'Προηγούμενος',
212
+ nextText: 'Επόμενος',
213
+ currentText: 'Τρέχων Μήνας',
214
+ monthNames: ['Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος',
215
+ 'Ιούλιος','Αύγουστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος'],
216
+ monthNamesShort: ['Ιαν','Φεβ','Μαρ','Απρ','Μαι','Ιουν',
217
+ 'Ιουλ','Αυγ','Σεπ','Οκτ','Νοε','Δεκ'],
218
+ dayNames: ['Κυριακή','Δευτέρα','Τρίτη','Τετάρτη','Πέμπτη','Παρασκευή','Σάββατο'],
219
+ dayNamesShort: ['Κυρ','Δευ','Τρι','Τετ','Πεμ','Παρ','Σαβ'],
220
+ dayNamesMin: ['Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'],
221
+ weekHeader: 'Εβδ',
222
+ dateFormat: 'dd/mm/yy',
223
+ firstDay: 1,
224
+ isRTL: false,
225
+ showMonthAfterYear: false,
226
+ yearSuffix: ''};
227
+ $.datepicker.setDefaults($.datepicker.regional['el']);
228
+ });/* English/UK initialisation for the jQuery UI date picker plugin. */
229
+ /* Written by Stuart. */
230
+ jQuery(function($){
231
+ $.datepicker.regional['en-GB'] = {
232
+ closeText: 'Done',
233
+ prevText: 'Prev',
234
+ nextText: 'Next',
235
+ currentText: 'Today',
236
+ monthNames: ['January','February','March','April','May','June',
237
+ 'July','August','September','October','November','December'],
238
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
239
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
240
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
241
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
242
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],
243
+ weekHeader: 'Wk',
244
+ dateFormat: 'dd/mm/yy',
245
+ firstDay: 1,
246
+ isRTL: false,
247
+ showMonthAfterYear: false,
248
+ yearSuffix: ''};
249
+ $.datepicker.setDefaults($.datepicker.regional['en-GB']);
250
+ });
251
+ /* Esperanto initialisation for the jQuery UI date picker plugin. */
252
+ /* Written by Olivier M. (olivierweb@ifrance.com). */
253
+ jQuery(function($){
254
+ $.datepicker.regional['eo'] = {
255
+ closeText: 'Fermi',
256
+ prevText: '&lt;Anta',
257
+ nextText: 'Sekv&gt;',
258
+ currentText: 'Nuna',
259
+ monthNames: ['Januaro','Februaro','Marto','Aprilo','Majo','Junio',
260
+ 'Julio','Aŭgusto','Septembro','Oktobro','Novembro','Decembro'],
261
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
262
+ 'Jul','Aŭg','Sep','Okt','Nov','Dec'],
263
+ dayNames: ['Dimanĉo','Lundo','Mardo','Merkredo','Ĵaŭdo','Vendredo','Sabato'],
264
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Ĵaŭ','Ven','Sab'],
265
+ dayNamesMin: ['Di','Lu','Ma','Me','Ĵa','Ve','Sa'],
266
+ weekHeader: 'Sb',
267
+ dateFormat: 'dd/mm/yy',
268
+ firstDay: 0,
269
+ isRTL: false,
270
+ showMonthAfterYear: false,
271
+ yearSuffix: ''};
272
+ $.datepicker.setDefaults($.datepicker.regional['eo']);
273
+ });
274
+ /* Inicialización en español para la extensión 'UI date picker' para jQuery. */
275
+ /* Traducido por Vester (xvester@gmail.com). */
276
+ jQuery(function($){
277
+ $.datepicker.regional['es'] = {
278
+ closeText: 'Cerrar',
279
+ prevText: '&#x3c;Ant',
280
+ nextText: 'Sig&#x3e;',
281
+ currentText: 'Hoy',
282
+ monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio',
283
+ 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
284
+ monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun',
285
+ 'Jul','Ago','Sep','Oct','Nov','Dic'],
286
+ dayNames: ['Domingo','Lunes','Martes','Mi&eacute;rcoles','Jueves','Viernes','S&aacute;bado'],
287
+ dayNamesShort: ['Dom','Lun','Mar','Mi&eacute;','Juv','Vie','S&aacute;b'],
288
+ dayNamesMin: ['Do','Lu','Ma','Mi','Ju','Vi','S&aacute;'],
289
+ weekHeader: 'Sm',
290
+ dateFormat: 'dd/mm/yy',
291
+ firstDay: 1,
292
+ isRTL: false,
293
+ showMonthAfterYear: false,
294
+ yearSuffix: ''};
295
+ $.datepicker.setDefaults($.datepicker.regional['es']);
296
+ });/* Estonian initialisation for the jQuery UI date picker plugin. */
297
+ /* Written by Mart Sõmermaa (mrts.pydev at gmail com). */
298
+ jQuery(function($){
299
+ $.datepicker.regional['et'] = {
300
+ closeText: 'Sulge',
301
+ prevText: 'Eelnev',
302
+ nextText: 'Järgnev',
303
+ currentText: 'Täna',
304
+ monthNames: ['Jaanuar','Veebruar','Märts','Aprill','Mai','Juuni',
305
+ 'Juuli','August','September','Oktoober','November','Detsember'],
306
+ monthNamesShort: ['Jaan', 'Veebr', 'Märts', 'Apr', 'Mai', 'Juuni',
307
+ 'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'],
308
+ dayNames: ['Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'],
309
+ dayNamesShort: ['Pühap', 'Esmasp', 'Teisip', 'Kolmap', 'Neljap', 'Reede', 'Laup'],
310
+ dayNamesMin: ['P','E','T','K','N','R','L'],
311
+ weekHeader: 'Sm',
312
+ dateFormat: 'dd.mm.yy',
313
+ firstDay: 1,
314
+ isRTL: false,
315
+ showMonthAfterYear: false,
316
+ yearSuffix: ''};
317
+ $.datepicker.setDefaults($.datepicker.regional['et']);
318
+ }); /* Euskarako oinarria 'UI date picker' jquery-ko extentsioarentzat */
319
+ /* Karrikas-ek itzulia (karrikas@karrikas.com) */
320
+ jQuery(function($){
321
+ $.datepicker.regional['eu'] = {
322
+ closeText: 'Egina',
323
+ prevText: '&#x3c;Aur',
324
+ nextText: 'Hur&#x3e;',
325
+ currentText: 'Gaur',
326
+ monthNames: ['Urtarrila','Otsaila','Martxoa','Apirila','Maiatza','Ekaina',
327
+ 'Uztaila','Abuztua','Iraila','Urria','Azaroa','Abendua'],
328
+ monthNamesShort: ['Urt','Ots','Mar','Api','Mai','Eka',
329
+ 'Uzt','Abu','Ira','Urr','Aza','Abe'],
330
+ dayNames: ['Igandea','Astelehena','Asteartea','Asteazkena','Osteguna','Ostirala','Larunbata'],
331
+ dayNamesShort: ['Iga','Ast','Ast','Ast','Ost','Ost','Lar'],
332
+ dayNamesMin: ['Ig','As','As','As','Os','Os','La'],
333
+ weekHeader: 'Wk',
334
+ dateFormat: 'yy/mm/dd',
335
+ firstDay: 1,
336
+ isRTL: false,
337
+ showMonthAfterYear: false,
338
+ yearSuffix: ''};
339
+ $.datepicker.setDefaults($.datepicker.regional['eu']);
340
+ });/* Persian (Farsi) Translation for the jQuery UI date picker plugin. */
341
+ /* Javad Mowlanezhad -- jmowla@gmail.com */
342
+ /* Jalali calendar should supported soon! (Its implemented but I have to test it) */
343
+ jQuery(function($) {
344
+ $.datepicker.regional['fa'] = {
345
+ closeText: 'بستن',
346
+ prevText: '&#x3c;قبلي',
347
+ nextText: 'بعدي&#x3e;',
348
+ currentText: 'امروز',
349
+ monthNames: ['فروردين','ارديبهشت','خرداد','تير','مرداد','شهريور',
350
+ 'مهر','آبان','آذر','دي','بهمن','اسفند'],
351
+ monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
352
+ dayNames: ['يکشنبه','دوشنبه','سه‌شنبه','چهارشنبه','پنجشنبه','جمعه','شنبه'],
353
+ dayNamesShort: ['ي','د','س','چ','پ','ج', 'ش'],
354
+ dayNamesMin: ['ي','د','س','چ','پ','ج', 'ش'],
355
+ weekHeader: 'هف',
356
+ dateFormat: 'yy/mm/dd',
357
+ firstDay: 6,
358
+ isRTL: true,
359
+ showMonthAfterYear: false,
360
+ yearSuffix: ''};
361
+ $.datepicker.setDefaults($.datepicker.regional['fa']);
362
+ });/* Finnish initialisation for the jQuery UI date picker plugin. */
363
+ /* Written by Harri Kilpi� (harrikilpio@gmail.com). */
364
+ jQuery(function($){
365
+ $.datepicker.regional['fi'] = {
366
+ closeText: 'Sulje',
367
+ prevText: '&laquo;Edellinen',
368
+ nextText: 'Seuraava&raquo;',
369
+ currentText: 'T&auml;n&auml;&auml;n',
370
+ monthNames: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kes&auml;kuu',
371
+ 'Hein&auml;kuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],
372
+ monthNamesShort: ['Tammi','Helmi','Maalis','Huhti','Touko','Kes&auml;',
373
+ 'Hein&auml;','Elo','Syys','Loka','Marras','Joulu'],
374
+ dayNamesShort: ['Su','Ma','Ti','Ke','To','Pe','Su'],
375
+ dayNames: ['Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'],
376
+ dayNamesMin: ['Su','Ma','Ti','Ke','To','Pe','La'],
377
+ weekHeader: 'Vk',
378
+ dateFormat: 'dd.mm.yy',
379
+ firstDay: 1,
380
+ isRTL: false,
381
+ showMonthAfterYear: false,
382
+ yearSuffix: ''};
383
+ $.datepicker.setDefaults($.datepicker.regional['fi']);
384
+ });
385
+ /* Faroese initialisation for the jQuery UI date picker plugin */
386
+ /* Written by Sverri Mohr Olsen, sverrimo@gmail.com */
387
+ jQuery(function($){
388
+ $.datepicker.regional['fo'] = {
389
+ closeText: 'Lat aftur',
390
+ prevText: '&#x3c;Fyrra',
391
+ nextText: 'Næsta&#x3e;',
392
+ currentText: 'Í dag',
393
+ monthNames: ['Januar','Februar','Mars','Apríl','Mei','Juni',
394
+ 'Juli','August','September','Oktober','November','Desember'],
395
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
396
+ 'Jul','Aug','Sep','Okt','Nov','Des'],
397
+ dayNames: ['Sunnudagur','Mánadagur','Týsdagur','Mikudagur','Hósdagur','Fríggjadagur','Leyardagur'],
398
+ dayNamesShort: ['Sun','Mán','Týs','Mik','Hós','Frí','Ley'],
399
+ dayNamesMin: ['Su','Má','Tý','Mi','Hó','Fr','Le'],
400
+ weekHeader: 'Vk',
401
+ dateFormat: 'dd-mm-yy',
402
+ firstDay: 0,
403
+ isRTL: false,
404
+ showMonthAfterYear: false,
405
+ yearSuffix: ''};
406
+ $.datepicker.setDefaults($.datepicker.regional['fo']);
407
+ });
408
+ /* Swiss-French initialisation for the jQuery UI date picker plugin. */
409
+ /* Written Martin Voelkle (martin.voelkle@e-tc.ch). */
410
+ jQuery(function($){
411
+ $.datepicker.regional['fr-CH'] = {
412
+ closeText: 'Fermer',
413
+ prevText: '&#x3c;Préc',
414
+ nextText: 'Suiv&#x3e;',
415
+ currentText: 'Courant',
416
+ monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
417
+ 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
418
+ monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',
419
+ 'Jul','Aoû','Sep','Oct','Nov','Déc'],
420
+ dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
421
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
422
+ dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
423
+ weekHeader: 'Sm',
424
+ dateFormat: 'dd.mm.yy',
425
+ firstDay: 1,
426
+ isRTL: false,
427
+ showMonthAfterYear: false,
428
+ yearSuffix: ''};
429
+ $.datepicker.setDefaults($.datepicker.regional['fr-CH']);
430
+ });/* French initialisation for the jQuery UI date picker plugin. */
431
+ /* Written by Keith Wood (kbwood{at}iinet.com.au) and Stéphane Nahmani (sholby@sholby.net). */
432
+ jQuery(function($){
433
+ $.datepicker.regional['fr'] = {
434
+ closeText: 'Fermer',
435
+ prevText: '&#x3c;Préc',
436
+ nextText: 'Suiv&#x3e;',
437
+ currentText: 'Courant',
438
+ monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
439
+ 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
440
+ monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',
441
+ 'Jul','Aoû','Sep','Oct','Nov','Déc'],
442
+ dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
443
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
444
+ dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
445
+ weekHeader: 'Sm',
446
+ dateFormat: 'dd/mm/yy',
447
+ firstDay: 1,
448
+ isRTL: false,
449
+ showMonthAfterYear: false,
450
+ yearSuffix: ''};
451
+ $.datepicker.setDefaults($.datepicker.regional['fr']);
452
+ });/* Hebrew initialisation for the UI Datepicker extension. */
453
+ /* Written by Amir Hardon (ahardon at gmail dot com). */
454
+ jQuery(function($){
455
+ $.datepicker.regional['he'] = {
456
+ closeText: 'סגור',
457
+ prevText: '&#x3c;הקודם',
458
+ nextText: 'הבא&#x3e;',
459
+ currentText: 'היום',
460
+ monthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני',
461
+ 'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'],
462
+ monthNamesShort: ['1','2','3','4','5','6',
463
+ '7','8','9','10','11','12'],
464
+ dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],
465
+ dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
466
+ dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
467
+ weekHeader: 'Wk',
468
+ dateFormat: 'dd/mm/yy',
469
+ firstDay: 0,
470
+ isRTL: true,
471
+ showMonthAfterYear: false,
472
+ yearSuffix: ''};
473
+ $.datepicker.setDefaults($.datepicker.regional['he']);
474
+ });
475
+ /* Croatian i18n for the jQuery UI date picker plugin. */
476
+ /* Written by Vjekoslav Nesek. */
477
+ jQuery(function($){
478
+ $.datepicker.regional['hr'] = {
479
+ closeText: 'Zatvori',
480
+ prevText: '&#x3c;',
481
+ nextText: '&#x3e;',
482
+ currentText: 'Danas',
483
+ monthNames: ['Siječanj','Veljača','Ožujak','Travanj','Svibanj','Lipanj',
484
+ 'Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'],
485
+ monthNamesShort: ['Sij','Velj','Ožu','Tra','Svi','Lip',
486
+ 'Srp','Kol','Ruj','Lis','Stu','Pro'],
487
+ dayNames: ['Nedjelja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
488
+ dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
489
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
490
+ weekHeader: 'Tje',
491
+ dateFormat: 'dd.mm.yy.',
492
+ firstDay: 1,
493
+ isRTL: false,
494
+ showMonthAfterYear: false,
495
+ yearSuffix: ''};
496
+ $.datepicker.setDefaults($.datepicker.regional['hr']);
497
+ });/* Hungarian initialisation for the jQuery UI date picker plugin. */
498
+ /* Written by Istvan Karaszi (jquery@spam.raszi.hu). */
499
+ jQuery(function($){
500
+ $.datepicker.regional['hu'] = {
501
+ closeText: 'bezárás',
502
+ prevText: '&laquo;&nbsp;vissza',
503
+ nextText: 'előre&nbsp;&raquo;',
504
+ currentText: 'ma',
505
+ monthNames: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június',
506
+ 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],
507
+ monthNamesShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún',
508
+ 'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],
509
+ dayNames: ['Vasárnap', 'Hétfö', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],
510
+ dayNamesShort: ['Vas', 'Hét', 'Ked', 'Sze', 'Csü', 'Pén', 'Szo'],
511
+ dayNamesMin: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
512
+ weekHeader: 'Hé',
513
+ dateFormat: 'yy-mm-dd',
514
+ firstDay: 1,
515
+ isRTL: false,
516
+ showMonthAfterYear: false,
517
+ yearSuffix: ''};
518
+ $.datepicker.setDefaults($.datepicker.regional['hu']);
519
+ });
520
+ /* Armenian(UTF-8) initialisation for the jQuery UI date picker plugin. */
521
+ /* Written by Levon Zakaryan (levon.zakaryan@gmail.com)*/
522
+ jQuery(function($){
523
+ $.datepicker.regional['hy'] = {
524
+ closeText: 'Փակել',
525
+ prevText: '&#x3c;Նախ.',
526
+ nextText: 'Հաջ.&#x3e;',
527
+ currentText: 'Այսօր',
528
+ monthNames: ['Հունվար','Փետրվար','Մարտ','Ապրիլ','Մայիս','Հունիս',
529
+ 'Հուլիս','Օգոստոս','Սեպտեմբեր','Հոկտեմբեր','Նոյեմբեր','Դեկտեմբեր'],
530
+ monthNamesShort: ['Հունվ','Փետր','Մարտ','Ապր','Մայիս','Հունիս',
531
+ 'Հուլ','Օգս','Սեպ','Հոկ','Նոյ','Դեկ'],
532
+ dayNames: ['կիրակի','եկուշաբթի','երեքշաբթի','չորեքշաբթի','հինգշաբթի','ուրբաթ','շաբաթ'],
533
+ dayNamesShort: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
534
+ dayNamesMin: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
535
+ weekHeader: 'ՇԲՏ',
536
+ dateFormat: 'dd.mm.yy',
537
+ firstDay: 1,
538
+ isRTL: false,
539
+ showMonthAfterYear: false,
540
+ yearSuffix: ''};
541
+ $.datepicker.setDefaults($.datepicker.regional['hy']);
542
+ });/* Indonesian initialisation for the jQuery UI date picker plugin. */
543
+ /* Written by Deden Fathurahman (dedenf@gmail.com). */
544
+ jQuery(function($){
545
+ $.datepicker.regional['id'] = {
546
+ closeText: 'Tutup',
547
+ prevText: '&#x3c;mundur',
548
+ nextText: 'maju&#x3e;',
549
+ currentText: 'hari ini',
550
+ monthNames: ['Januari','Februari','Maret','April','Mei','Juni',
551
+ 'Juli','Agustus','September','Oktober','Nopember','Desember'],
552
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
553
+ 'Jul','Agus','Sep','Okt','Nop','Des'],
554
+ dayNames: ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'],
555
+ dayNamesShort: ['Min','Sen','Sel','Rab','kam','Jum','Sab'],
556
+ dayNamesMin: ['Mg','Sn','Sl','Rb','Km','jm','Sb'],
557
+ weekHeader: 'Mg',
558
+ dateFormat: 'dd/mm/yy',
559
+ firstDay: 0,
560
+ isRTL: false,
561
+ showMonthAfterYear: false,
562
+ yearSuffix: ''};
563
+ $.datepicker.setDefaults($.datepicker.regional['id']);
564
+ });/* Icelandic initialisation for the jQuery UI date picker plugin. */
565
+ /* Written by Haukur H. Thorsson (haukur@eskill.is). */
566
+ jQuery(function($){
567
+ $.datepicker.regional['is'] = {
568
+ closeText: 'Loka',
569
+ prevText: '&#x3c; Fyrri',
570
+ nextText: 'N&aelig;sti &#x3e;',
571
+ currentText: '&Iacute; dag',
572
+ monthNames: ['Jan&uacute;ar','Febr&uacute;ar','Mars','Apr&iacute;l','Ma&iacute','J&uacute;n&iacute;',
573
+ 'J&uacute;l&iacute;','&Aacute;g&uacute;st','September','Okt&oacute;ber','N&oacute;vember','Desember'],
574
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Ma&iacute;','J&uacute;n',
575
+ 'J&uacute;l','&Aacute;g&uacute;','Sep','Okt','N&oacute;v','Des'],
576
+ dayNames: ['Sunnudagur','M&aacute;nudagur','&THORN;ri&eth;judagur','Mi&eth;vikudagur','Fimmtudagur','F&ouml;studagur','Laugardagur'],
577
+ dayNamesShort: ['Sun','M&aacute;n','&THORN;ri','Mi&eth;','Fim','F&ouml;s','Lau'],
578
+ dayNamesMin: ['Su','M&aacute;','&THORN;r','Mi','Fi','F&ouml;','La'],
579
+ weekHeader: 'Vika',
580
+ dateFormat: 'dd/mm/yy',
581
+ firstDay: 0,
582
+ isRTL: false,
583
+ showMonthAfterYear: false,
584
+ yearSuffix: ''};
585
+ $.datepicker.setDefaults($.datepicker.regional['is']);
586
+ });/* Italian initialisation for the jQuery UI date picker plugin. */
587
+ /* Written by Antonello Pasella (antonello.pasella@gmail.com). */
588
+ jQuery(function($){
589
+ $.datepicker.regional['it'] = {
590
+ closeText: 'Chiudi',
591
+ prevText: '&#x3c;Prec',
592
+ nextText: 'Succ&#x3e;',
593
+ currentText: 'Oggi',
594
+ monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',
595
+ 'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
596
+ monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu',
597
+ 'Lug','Ago','Set','Ott','Nov','Dic'],
598
+ dayNames: ['Domenica','Luned&#236','Marted&#236','Mercoled&#236','Gioved&#236','Venerd&#236','Sabato'],
599
+ dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],
600
+ dayNamesMin: ['Do','Lu','Ma','Me','Gi','Ve','Sa'],
601
+ weekHeader: 'Sm',
602
+ dateFormat: 'dd/mm/yy',
603
+ firstDay: 1,
604
+ isRTL: false,
605
+ showMonthAfterYear: false,
606
+ yearSuffix: ''};
607
+ $.datepicker.setDefaults($.datepicker.regional['it']);
608
+ });
609
+ /* Japanese initialisation for the jQuery UI date picker plugin. */
610
+ /* Written by Kentaro SATO (kentaro@ranvis.com). */
611
+ jQuery(function($){
612
+ $.datepicker.regional['ja'] = {
613
+ closeText: '閉じる',
614
+ prevText: '&#x3c;前',
615
+ nextText: '次&#x3e;',
616
+ currentText: '今日',
617
+ monthNames: ['1月','2月','3月','4月','5月','6月',
618
+ '7月','8月','9月','10月','11月','12月'],
619
+ monthNamesShort: ['1月','2月','3月','4月','5月','6月',
620
+ '7月','8月','9月','10月','11月','12月'],
621
+ dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
622
+ dayNamesShort: ['日','月','火','水','木','金','土'],
623
+ dayNamesMin: ['日','月','火','水','木','金','土'],
624
+ weekHeader: '週',
625
+ dateFormat: 'yy/mm/dd',
626
+ firstDay: 0,
627
+ isRTL: false,
628
+ showMonthAfterYear: true,
629
+ yearSuffix: '年'};
630
+ $.datepicker.setDefaults($.datepicker.regional['ja']);
631
+ });/* Korean initialisation for the jQuery calendar extension. */
632
+ /* Written by DaeKwon Kang (ncrash.dk@gmail.com). */
633
+ jQuery(function($){
634
+ $.datepicker.regional['ko'] = {
635
+ closeText: '닫기',
636
+ prevText: '이전달',
637
+ nextText: '다음달',
638
+ currentText: '오늘',
639
+ monthNames: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)',
640
+ '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'],
641
+ monthNamesShort: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)',
642
+ '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'],
643
+ dayNames: ['일','월','화','수','목','금','토'],
644
+ dayNamesShort: ['일','월','화','수','목','금','토'],
645
+ dayNamesMin: ['일','월','화','수','목','금','토'],
646
+ weekHeader: 'Wk',
647
+ dateFormat: 'yy-mm-dd',
648
+ firstDay: 0,
649
+ isRTL: false,
650
+ showMonthAfterYear: false,
651
+ yearSuffix: '년'};
652
+ $.datepicker.setDefaults($.datepicker.regional['ko']);
653
+ });/* Kazakh (UTF-8) initialisation for the jQuery UI date picker plugin. */
654
+ /* Written by Dmitriy Karasyov (dmitriy.karasyov@gmail.com). */
655
+ jQuery(function($){
656
+ $.datepicker.regional['kz'] = {
657
+ closeText: 'Жабу',
658
+ prevText: '&#x3c;Алдыңғы',
659
+ nextText: 'Келесі&#x3e;',
660
+ currentText: 'Бүгін',
661
+ monthNames: ['Қаңтар','Ақпан','Наурыз','Сәуір','Мамыр','Маусым',
662
+ 'Шілде','Тамыз','Қыркүйек','Қазан','Қараша','Желтоқсан'],
663
+ monthNamesShort: ['Қаң','Ақп','Нау','Сәу','Мам','Мау',
664
+ 'Шіл','Там','Қыр','Қаз','Қар','Жел'],
665
+ dayNames: ['Жексенбі','Дүйсенбі','Сейсенбі','Сәрсенбі','Бейсенбі','Жұма','Сенбі'],
666
+ dayNamesShort: ['жкс','дсн','ссн','срс','бсн','жма','снб'],
667
+ dayNamesMin: ['Жк','Дс','Сс','Ср','Бс','Жм','Сн'],
668
+ weekHeader: 'Не',
669
+ dateFormat: 'dd.mm.yy',
670
+ firstDay: 1,
671
+ isRTL: false,
672
+ showMonthAfterYear: false,
673
+ yearSuffix: ''};
674
+ $.datepicker.setDefaults($.datepicker.regional['kz']);
675
+ });
676
+ /* Lithuanian (UTF-8) initialisation for the jQuery UI date picker plugin. */
677
+ /* @author Arturas Paleicikas <arturas@avalon.lt> */
678
+ jQuery(function($){
679
+ $.datepicker.regional['lt'] = {
680
+ closeText: 'Uždaryti',
681
+ prevText: '&#x3c;Atgal',
682
+ nextText: 'Pirmyn&#x3e;',
683
+ currentText: 'Šiandien',
684
+ monthNames: ['Sausis','Vasaris','Kovas','Balandis','Gegužė','Birželis',
685
+ 'Liepa','Rugpjūtis','Rugsėjis','Spalis','Lapkritis','Gruodis'],
686
+ monthNamesShort: ['Sau','Vas','Kov','Bal','Geg','Bir',
687
+ 'Lie','Rugp','Rugs','Spa','Lap','Gru'],
688
+ dayNames: ['sekmadienis','pirmadienis','antradienis','trečiadienis','ketvirtadienis','penktadienis','šeštadienis'],
689
+ dayNamesShort: ['sek','pir','ant','tre','ket','pen','šeš'],
690
+ dayNamesMin: ['Se','Pr','An','Tr','Ke','Pe','Še'],
691
+ weekHeader: 'Wk',
692
+ dateFormat: 'yy-mm-dd',
693
+ firstDay: 1,
694
+ isRTL: false,
695
+ showMonthAfterYear: false,
696
+ yearSuffix: ''};
697
+ $.datepicker.setDefaults($.datepicker.regional['lt']);
698
+ });/* Latvian (UTF-8) initialisation for the jQuery UI date picker plugin. */
699
+ /* @author Arturas Paleicikas <arturas.paleicikas@metasite.net> */
700
+ jQuery(function($){
701
+ $.datepicker.regional['lv'] = {
702
+ closeText: 'Aizvērt',
703
+ prevText: 'Iepr',
704
+ nextText: 'Nāka',
705
+ currentText: 'Šodien',
706
+ monthNames: ['Janvāris','Februāris','Marts','Aprīlis','Maijs','Jūnijs',
707
+ 'Jūlijs','Augusts','Septembris','Oktobris','Novembris','Decembris'],
708
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jūn',
709
+ 'Jūl','Aug','Sep','Okt','Nov','Dec'],
710
+ dayNames: ['svētdiena','pirmdiena','otrdiena','trešdiena','ceturtdiena','piektdiena','sestdiena'],
711
+ dayNamesShort: ['svt','prm','otr','tre','ctr','pkt','sst'],
712
+ dayNamesMin: ['Sv','Pr','Ot','Tr','Ct','Pk','Ss'],
713
+ weekHeader: 'Nav',
714
+ dateFormat: 'dd-mm-yy',
715
+ firstDay: 1,
716
+ isRTL: false,
717
+ showMonthAfterYear: false,
718
+ yearSuffix: ''};
719
+ $.datepicker.setDefaults($.datepicker.regional['lv']);
720
+ });/* Malaysian initialisation for the jQuery UI date picker plugin. */
721
+ /* Written by Mohd Nawawi Mohamad Jamili (nawawi@ronggeng.net). */
722
+ jQuery(function($){
723
+ $.datepicker.regional['ms'] = {
724
+ closeText: 'Tutup',
725
+ prevText: '&#x3c;Sebelum',
726
+ nextText: 'Selepas&#x3e;',
727
+ currentText: 'hari ini',
728
+ monthNames: ['Januari','Februari','Mac','April','Mei','Jun',
729
+ 'Julai','Ogos','September','Oktober','November','Disember'],
730
+ monthNamesShort: ['Jan','Feb','Mac','Apr','Mei','Jun',
731
+ 'Jul','Ogo','Sep','Okt','Nov','Dis'],
732
+ dayNames: ['Ahad','Isnin','Selasa','Rabu','Khamis','Jumaat','Sabtu'],
733
+ dayNamesShort: ['Aha','Isn','Sel','Rab','kha','Jum','Sab'],
734
+ dayNamesMin: ['Ah','Is','Se','Ra','Kh','Ju','Sa'],
735
+ weekHeader: 'Mg',
736
+ dateFormat: 'dd/mm/yy',
737
+ firstDay: 0,
738
+ isRTL: false,
739
+ showMonthAfterYear: false,
740
+ yearSuffix: ''};
741
+ $.datepicker.setDefaults($.datepicker.regional['ms']);
742
+ });/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */
743
+ /* Written by Mathias Bynens <http://mathiasbynens.be/> */
744
+ jQuery(function($){
745
+ $.datepicker.regional.nl = {
746
+ closeText: 'Sluiten',
747
+ prevText: '←',
748
+ nextText: '→',
749
+ currentText: 'Vandaag',
750
+ monthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',
751
+ 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
752
+ monthNamesShort: ['jan', 'feb', 'maa', 'apr', 'mei', 'jun',
753
+ 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
754
+ dayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
755
+ dayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],
756
+ dayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
757
+ weekHeader: 'Wk',
758
+ dateFormat: 'dd/mm/yy',
759
+ firstDay: 1,
760
+ isRTL: false,
761
+ showMonthAfterYear: false,
762
+ yearSuffix: ''};
763
+ $.datepicker.setDefaults($.datepicker.regional.nl);
764
+ });/* Norwegian initialisation for the jQuery UI date picker plugin. */
765
+ /* Written by Naimdjon Takhirov (naimdjon@gmail.com). */
766
+ jQuery(function($){
767
+ $.datepicker.regional['no'] = {
768
+ closeText: 'Lukk',
769
+ prevText: '&laquo;Forrige',
770
+ nextText: 'Neste&raquo;',
771
+ currentText: 'I dag',
772
+ monthNames: ['Januar','Februar','Mars','April','Mai','Juni',
773
+ 'Juli','August','September','Oktober','November','Desember'],
774
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jun',
775
+ 'Jul','Aug','Sep','Okt','Nov','Des'],
776
+ dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],
777
+ dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
778
+ dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],
779
+ weekHeader: 'Uke',
780
+ dateFormat: 'yy-mm-dd',
781
+ firstDay: 0,
782
+ isRTL: false,
783
+ showMonthAfterYear: false,
784
+ yearSuffix: ''};
785
+ $.datepicker.setDefaults($.datepicker.regional['no']);
786
+ });
787
+ /* Polish initialisation for the jQuery UI date picker plugin. */
788
+ /* Written by Jacek Wysocki (jacek.wysocki@gmail.com). */
789
+ jQuery(function($){
790
+ $.datepicker.regional['pl'] = {
791
+ closeText: 'Zamknij',
792
+ prevText: '&#x3c;Poprzedni',
793
+ nextText: 'Następny&#x3e;',
794
+ currentText: 'Dziś',
795
+ monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec',
796
+ 'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
797
+ monthNamesShort: ['Sty','Lu','Mar','Kw','Maj','Cze',
798
+ 'Lip','Sie','Wrz','Pa','Lis','Gru'],
799
+ dayNames: ['Niedziela','Poniedziałek','Wtorek','Środa','Czwartek','Piątek','Sobota'],
800
+ dayNamesShort: ['Nie','Pn','Wt','Śr','Czw','Pt','So'],
801
+ dayNamesMin: ['N','Pn','Wt','Śr','Cz','Pt','So'],
802
+ weekHeader: 'Tydz',
803
+ dateFormat: 'dd.mm.yy',
804
+ firstDay: 1,
805
+ isRTL: false,
806
+ showMonthAfterYear: false,
807
+ yearSuffix: ''};
808
+ $.datepicker.setDefaults($.datepicker.regional['pl']);
809
+ });
810
+ /* Brazilian initialisation for the jQuery UI date picker plugin. */
811
+ /* Written by Leonildo Costa Silva (leocsilva@gmail.com). */
812
+ jQuery(function($){
813
+ $.datepicker.regional['pt-BR'] = {
814
+ closeText: 'Fechar',
815
+ prevText: '&#x3c;Anterior',
816
+ nextText: 'Pr&oacute;ximo&#x3e;',
817
+ currentText: 'Hoje',
818
+ monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho',
819
+ 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
820
+ monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
821
+ 'Jul','Ago','Set','Out','Nov','Dez'],
822
+ dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&aacute;bado'],
823
+ dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
824
+ dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
825
+ weekHeader: 'Sm',
826
+ dateFormat: 'dd/mm/yy',
827
+ firstDay: 0,
828
+ isRTL: false,
829
+ showMonthAfterYear: false,
830
+ yearSuffix: ''};
831
+ $.datepicker.setDefaults($.datepicker.regional['pt-BR']);
832
+ });/* Romanian initialisation for the jQuery UI date picker plugin.
833
+ *
834
+ * Written by Edmond L. (ll_edmond@walla.com)
835
+ * and Ionut G. Stan (ionut.g.stan@gmail.com)
836
+ */
837
+ jQuery(function($){
838
+ $.datepicker.regional['ro'] = {
839
+ closeText: 'Închide',
840
+ prevText: '&laquo; Luna precedentă',
841
+ nextText: 'Luna următoare &raquo;',
842
+ currentText: 'Azi',
843
+ monthNames: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie',
844
+ 'Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],
845
+ monthNamesShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',
846
+ 'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
847
+ dayNames: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
848
+ dayNamesShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
849
+ dayNamesMin: ['Du','Lu','Ma','Mi','Jo','Vi','Sâ'],
850
+ weekHeader: 'Săpt',
851
+ dateFormat: 'dd.mm.yy',
852
+ firstDay: 1,
853
+ isRTL: false,
854
+ showMonthAfterYear: false,
855
+ yearSuffix: ''};
856
+ $.datepicker.setDefaults($.datepicker.regional['ro']);
857
+ });
858
+ /* Russian (UTF-8) initialisation for the jQuery UI date picker plugin. */
859
+ /* Written by Andrew Stromnov (stromnov@gmail.com). */
860
+ jQuery(function($){
861
+ $.datepicker.regional['ru'] = {
862
+ closeText: 'Закрыть',
863
+ prevText: '&#x3c;Пред',
864
+ nextText: 'След&#x3e;',
865
+ currentText: 'Сегодня',
866
+ monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь',
867
+ 'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
868
+ monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',
869
+ 'Июл','Авг','Сен','Окт','Ноя','Дек'],
870
+ dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],
871
+ dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],
872
+ dayNamesMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],
873
+ weekHeader: 'Не',
874
+ dateFormat: 'dd.mm.yy',
875
+ firstDay: 1,
876
+ isRTL: false,
877
+ showMonthAfterYear: false,
878
+ yearSuffix: ''};
879
+ $.datepicker.setDefaults($.datepicker.regional['ru']);
880
+ });/* Slovak initialisation for the jQuery UI date picker plugin. */
881
+ /* Written by Vojtech Rinik (vojto@hmm.sk). */
882
+ jQuery(function($){
883
+ $.datepicker.regional['sk'] = {
884
+ closeText: 'Zavrieť',
885
+ prevText: '&#x3c;Predchádzajúci',
886
+ nextText: 'Nasledujúci&#x3e;',
887
+ currentText: 'Dnes',
888
+ monthNames: ['Január','Február','Marec','Apríl','Máj','Jún',
889
+ 'Júl','August','September','Október','November','December'],
890
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',
891
+ 'Júl','Aug','Sep','Okt','Nov','Dec'],
892
+ dayNames: ['Nedel\'a','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],
893
+ dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],
894
+ dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],
895
+ weekHeader: 'Ty',
896
+ dateFormat: 'dd.mm.yy',
897
+ firstDay: 1,
898
+ isRTL: false,
899
+ showMonthAfterYear: false,
900
+ yearSuffix: ''};
901
+ $.datepicker.setDefaults($.datepicker.regional['sk']);
902
+ });
903
+ /* Slovenian initialisation for the jQuery UI date picker plugin. */
904
+ /* Written by Jaka Jancar (jaka@kubje.org). */
905
+ /* c = &#x10D;, s = &#x161; z = &#x17E; C = &#x10C; S = &#x160; Z = &#x17D; */
906
+ jQuery(function($){
907
+ $.datepicker.regional['sl'] = {
908
+ closeText: 'Zapri',
909
+ prevText: '&lt;Prej&#x161;nji',
910
+ nextText: 'Naslednji&gt;',
911
+ currentText: 'Trenutni',
912
+ monthNames: ['Januar','Februar','Marec','April','Maj','Junij',
913
+ 'Julij','Avgust','September','Oktober','November','December'],
914
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
915
+ 'Jul','Avg','Sep','Okt','Nov','Dec'],
916
+ dayNames: ['Nedelja','Ponedeljek','Torek','Sreda','&#x10C;etrtek','Petek','Sobota'],
917
+ dayNamesShort: ['Ned','Pon','Tor','Sre','&#x10C;et','Pet','Sob'],
918
+ dayNamesMin: ['Ne','Po','To','Sr','&#x10C;e','Pe','So'],
919
+ weekHeader: 'Teden',
920
+ dateFormat: 'dd.mm.yy',
921
+ firstDay: 1,
922
+ isRTL: false,
923
+ showMonthAfterYear: false,
924
+ yearSuffix: ''};
925
+ $.datepicker.setDefaults($.datepicker.regional['sl']);
926
+ });
927
+ /* Albanian initialisation for the jQuery UI date picker plugin. */
928
+ /* Written by Flakron Bytyqi (flakron@gmail.com). */
929
+ jQuery(function($){
930
+ $.datepicker.regional['sq'] = {
931
+ closeText: 'mbylle',
932
+ prevText: '&#x3c;mbrapa',
933
+ nextText: 'Përpara&#x3e;',
934
+ currentText: 'sot',
935
+ monthNames: ['Janar','Shkurt','Mars','Prill','Maj','Qershor',
936
+ 'Korrik','Gusht','Shtator','Tetor','Nëntor','Dhjetor'],
937
+ monthNamesShort: ['Jan','Shk','Mar','Pri','Maj','Qer',
938
+ 'Kor','Gus','Sht','Tet','Nën','Dhj'],
939
+ dayNames: ['E Diel','E Hënë','E Martë','E Mërkurë','E Enjte','E Premte','E Shtune'],
940
+ dayNamesShort: ['Di','Hë','Ma','Më','En','Pr','Sh'],
941
+ dayNamesMin: ['Di','Hë','Ma','Më','En','Pr','Sh'],
942
+ weekHeader: 'Ja',
943
+ dateFormat: 'dd.mm.yy',
944
+ firstDay: 1,
945
+ isRTL: false,
946
+ showMonthAfterYear: false,
947
+ yearSuffix: ''};
948
+ $.datepicker.setDefaults($.datepicker.regional['sq']);
949
+ });
950
+ /* Serbian i18n for the jQuery UI date picker plugin. */
951
+ /* Written by Dejan Dimić. */
952
+ jQuery(function($){
953
+ $.datepicker.regional['sr-SR'] = {
954
+ closeText: 'Zatvori',
955
+ prevText: '&#x3c;',
956
+ nextText: '&#x3e;',
957
+ currentText: 'Danas',
958
+ monthNames: ['Januar','Februar','Mart','April','Maj','Jun',
959
+ 'Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'],
960
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
961
+ 'Jul','Avg','Sep','Okt','Nov','Dec'],
962
+ dayNames: ['Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'],
963
+ dayNamesShort: ['Ned','Pon','Uto','Sre','Čet','Pet','Sub'],
964
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
965
+ weekHeader: 'Sed',
966
+ dateFormat: 'dd/mm/yy',
967
+ firstDay: 1,
968
+ isRTL: false,
969
+ showMonthAfterYear: false,
970
+ yearSuffix: ''};
971
+ $.datepicker.setDefaults($.datepicker.regional['sr-SR']);
972
+ });
973
+ /* Serbian i18n for the jQuery UI date picker plugin. */
974
+ /* Written by Dejan Dimić. */
975
+ jQuery(function($){
976
+ $.datepicker.regional['sr'] = {
977
+ closeText: 'Затвори',
978
+ prevText: '&#x3c;',
979
+ nextText: '&#x3e;',
980
+ currentText: 'Данас',
981
+ monthNames: ['Јануар','Фебруар','Март','Април','Мај','Јун',
982
+ 'Јул','Август','Септембар','Октобар','Новембар','Децембар'],
983
+ monthNamesShort: ['Јан','Феб','Мар','Апр','Мај','Јун',
984
+ 'Јул','Авг','Сеп','Окт','Нов','Дец'],
985
+ dayNames: ['Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'],
986
+ dayNamesShort: ['Нед','Пон','Уто','Сре','Чет','Пет','Суб'],
987
+ dayNamesMin: ['Не','По','Ут','Ср','Че','Пе','Су'],
988
+ weekHeader: 'Сед',
989
+ dateFormat: 'dd/mm/yy',
990
+ firstDay: 1,
991
+ isRTL: false,
992
+ showMonthAfterYear: false,
993
+ yearSuffix: ''};
994
+ $.datepicker.setDefaults($.datepicker.regional['sr']);
995
+ });
996
+ /* Swedish initialisation for the jQuery UI date picker plugin. */
997
+ /* Written by Anders Ekdahl ( anders@nomadiz.se). */
998
+ jQuery(function($){
999
+ $.datepicker.regional['sv'] = {
1000
+ closeText: 'Stäng',
1001
+ prevText: '&laquo;Förra',
1002
+ nextText: 'Nästa&raquo;',
1003
+ currentText: 'Idag',
1004
+ monthNames: ['Januari','Februari','Mars','April','Maj','Juni',
1005
+ 'Juli','Augusti','September','Oktober','November','December'],
1006
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
1007
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
1008
+ dayNamesShort: ['Sön','Mån','Tis','Ons','Tor','Fre','Lör'],
1009
+ dayNames: ['Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'],
1010
+ dayNamesMin: ['Sö','Må','Ti','On','To','Fr','Lö'],
1011
+ weekHeader: 'Ve',
1012
+ dateFormat: 'yy-mm-dd',
1013
+ firstDay: 1,
1014
+ isRTL: false,
1015
+ showMonthAfterYear: false,
1016
+ yearSuffix: ''};
1017
+ $.datepicker.setDefaults($.datepicker.regional['sv']);
1018
+ });
1019
+ /* Tamil (UTF-8) initialisation for the jQuery UI date picker plugin. */
1020
+ /* Written by S A Sureshkumar (saskumar@live.com). */
1021
+ jQuery(function($){
1022
+ $.datepicker.regional['ta'] = {
1023
+ closeText: 'மூடு',
1024
+ prevText: 'முன்னையது',
1025
+ nextText: 'அடுத்தது',
1026
+ currentText: 'இன்று',
1027
+ monthNames: ['தை','மாசி','பங்குனி','சித்திரை','வைகாசி','ஆனி',
1028
+ 'ஆடி','ஆவணி','புரட்டாசி','ஐப்பசி','கார்த்திகை','மார்கழி'],
1029
+ monthNamesShort: ['தை','மாசி','பங்','சித்','வைகா','ஆனி',
1030
+ 'ஆடி','ஆவ','புர','ஐப்','கார்','மார்'],
1031
+ dayNames: ['ஞாயிற்றுக்கிழமை','திங்கட்கிழமை','செவ்வாய்க்கிழமை','புதன்கிழமை','வியாழக்கிழமை','வெள்ளிக்கிழமை','சனிக்கிழமை'],
1032
+ dayNamesShort: ['ஞாயிறு','திங்கள்','செவ்வாய்','புதன்','வியாழன்','வெள்ளி','சனி'],
1033
+ dayNamesMin: ['ஞா','தி','செ','பு','வி','வெ','ச'],
1034
+ weekHeader: 'Не',
1035
+ dateFormat: 'dd/mm/yy',
1036
+ firstDay: 1,
1037
+ isRTL: false,
1038
+ showMonthAfterYear: false,
1039
+ yearSuffix: ''};
1040
+ $.datepicker.setDefaults($.datepicker.regional['ta']);
1041
+ });
1042
+ /* Thai initialisation for the jQuery UI date picker plugin. */
1043
+ /* Written by pipo (pipo@sixhead.com). */
1044
+ jQuery(function($){
1045
+ $.datepicker.regional['th'] = {
1046
+ closeText: 'ปิด',
1047
+ prevText: '&laquo;&nbsp;ย้อน',
1048
+ nextText: 'ถัดไป&nbsp;&raquo;',
1049
+ currentText: 'วันนี้',
1050
+ monthNames: ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน',
1051
+ 'กรกฏาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'],
1052
+ monthNamesShort: ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.',
1053
+ 'ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'],
1054
+ dayNames: ['อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'],
1055
+ dayNamesShort: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
1056
+ dayNamesMin: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
1057
+ weekHeader: 'Wk',
1058
+ dateFormat: 'dd/mm/yy',
1059
+ firstDay: 0,
1060
+ isRTL: false,
1061
+ showMonthAfterYear: false,
1062
+ yearSuffix: ''};
1063
+ $.datepicker.setDefaults($.datepicker.regional['th']);
1064
+ });/* Turkish initialisation for the jQuery UI date picker plugin. */
1065
+ /* Written by Izzet Emre Erkan (kara@karalamalar.net). */
1066
+ jQuery(function($){
1067
+ $.datepicker.regional['tr'] = {
1068
+ closeText: 'kapat',
1069
+ prevText: '&#x3c;geri',
1070
+ nextText: 'ileri&#x3e',
1071
+ currentText: 'bugün',
1072
+ monthNames: ['Ocak','Şubat','Mart','Nisan','Mayıs','Haziran',
1073
+ 'Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'],
1074
+ monthNamesShort: ['Oca','Şub','Mar','Nis','May','Haz',
1075
+ 'Tem','Ağu','Eyl','Eki','Kas','Ara'],
1076
+ dayNames: ['Pazar','Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi'],
1077
+ dayNamesShort: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
1078
+ dayNamesMin: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
1079
+ weekHeader: 'Hf',
1080
+ dateFormat: 'dd.mm.yy',
1081
+ firstDay: 1,
1082
+ isRTL: false,
1083
+ showMonthAfterYear: false,
1084
+ yearSuffix: ''};
1085
+ $.datepicker.setDefaults($.datepicker.regional['tr']);
1086
+ });/* Ukrainian (UTF-8) initialisation for the jQuery UI date picker plugin. */
1087
+ /* Written by Maxim Drogobitskiy (maxdao@gmail.com). */
1088
+ jQuery(function($){
1089
+ $.datepicker.regional['uk'] = {
1090
+ closeText: 'Закрити',
1091
+ prevText: '&#x3c;',
1092
+ nextText: '&#x3e;',
1093
+ currentText: 'Сьогодні',
1094
+ monthNames: ['Січень','Лютий','Березень','Квітень','Травень','Червень',
1095
+ 'Липень','Серпень','Вересень','Жовтень','Листопад','Грудень'],
1096
+ monthNamesShort: ['Січ','Лют','Бер','Кві','Тра','Чер',
1097
+ 'Лип','Сер','Вер','Жов','Лис','Гру'],
1098
+ dayNames: ['неділя','понеділок','вівторок','середа','четвер','п’ятниця','субота'],
1099
+ dayNamesShort: ['нед','пнд','вів','срд','чтв','птн','сбт'],
1100
+ dayNamesMin: ['Нд','Пн','Вт','Ср','Чт','Пт','Сб'],
1101
+ weekHeader: 'Не',
1102
+ dateFormat: 'dd/mm/yy',
1103
+ firstDay: 1,
1104
+ isRTL: false,
1105
+ showMonthAfterYear: false,
1106
+ yearSuffix: ''};
1107
+ $.datepicker.setDefaults($.datepicker.regional['uk']);
1108
+ });/* Vietnamese initialisation for the jQuery UI date picker plugin. */
1109
+ /* Translated by Le Thanh Huy (lthanhhuy@cit.ctu.edu.vn). */
1110
+ jQuery(function($){
1111
+ $.datepicker.regional['vi'] = {
1112
+ closeText: 'Đóng',
1113
+ prevText: '&#x3c;Trước',
1114
+ nextText: 'Tiếp&#x3e;',
1115
+ currentText: 'Hôm nay',
1116
+ monthNames: ['Tháng Một', 'Tháng Hai', 'Tháng Ba', 'Tháng Tư', 'Tháng Năm', 'Tháng Sáu',
1117
+ 'Tháng Bảy', 'Tháng Tám', 'Tháng Chín', 'Tháng Mười', 'Tháng Mười Một', 'Tháng Mười Hai'],
1118
+ monthNamesShort: ['Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6',
1119
+ 'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12'],
1120
+ dayNames: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy'],
1121
+ dayNamesShort: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
1122
+ dayNamesMin: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
1123
+ weekHeader: 'Tu',
1124
+ dateFormat: 'dd/mm/yy',
1125
+ firstDay: 0,
1126
+ isRTL: false,
1127
+ showMonthAfterYear: false,
1128
+ yearSuffix: ''};
1129
+ $.datepicker.setDefaults($.datepicker.regional['vi']);
1130
+ });
1131
+ /* Chinese initialisation for the jQuery UI date picker plugin. */
1132
+ /* Written by Cloudream (cloudream@gmail.com). */
1133
+ jQuery(function($){
1134
+ $.datepicker.regional['zh-CN'] = {
1135
+ closeText: '关闭',
1136
+ prevText: '&#x3c;上月',
1137
+ nextText: '下月&#x3e;',
1138
+ currentText: '今天',
1139
+ monthNames: ['一月','二月','三月','四月','五月','六月',
1140
+ '七月','八月','九月','十月','十一月','十二月'],
1141
+ monthNamesShort: ['一','二','三','四','五','六',
1142
+ '七','八','九','十','十一','十二'],
1143
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
1144
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
1145
+ dayNamesMin: ['日','一','二','三','四','五','六'],
1146
+ weekHeader: '周',
1147
+ dateFormat: 'yy-mm-dd',
1148
+ firstDay: 1,
1149
+ isRTL: false,
1150
+ showMonthAfterYear: true,
1151
+ yearSuffix: '年'};
1152
+ $.datepicker.setDefaults($.datepicker.regional['zh-CN']);
1153
+ });
1154
+ /* Chinese initialisation for the jQuery UI date picker plugin. */
1155
+ /* Written by SCCY (samuelcychan@gmail.com). */
1156
+ jQuery(function($){
1157
+ $.datepicker.regional['zh-HK'] = {
1158
+ closeText: '關閉',
1159
+ prevText: '&#x3c;上月',
1160
+ nextText: '下月&#x3e;',
1161
+ currentText: '今天',
1162
+ monthNames: ['一月','二月','三月','四月','五月','六月',
1163
+ '七月','八月','九月','十月','十一月','十二月'],
1164
+ monthNamesShort: ['一','二','三','四','五','六',
1165
+ '七','八','九','十','十一','十二'],
1166
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
1167
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
1168
+ dayNamesMin: ['日','一','二','三','四','五','六'],
1169
+ weekHeader: '周',
1170
+ dateFormat: 'dd-mm-yy',
1171
+ firstDay: 0,
1172
+ isRTL: false,
1173
+ showMonthAfterYear: true,
1174
+ yearSuffix: '年'};
1175
+ $.datepicker.setDefaults($.datepicker.regional['zh-HK']);
1176
+ });
1177
+ /* Chinese initialisation for the jQuery UI date picker plugin. */
1178
+ /* Written by Ressol (ressol@gmail.com). */
1179
+ jQuery(function($){
1180
+ $.datepicker.regional['zh-TW'] = {
1181
+ closeText: '關閉',
1182
+ prevText: '&#x3c;上月',
1183
+ nextText: '下月&#x3e;',
1184
+ currentText: '今天',
1185
+ monthNames: ['一月','二月','三月','四月','五月','六月',
1186
+ '七月','八月','九月','十月','十一月','十二月'],
1187
+ monthNamesShort: ['一','二','三','四','五','六',
1188
+ '七','八','九','十','十一','十二'],
1189
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
1190
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
1191
+ dayNamesMin: ['日','一','二','三','四','五','六'],
1192
+ weekHeader: '周',
1193
+ dateFormat: 'yy/mm/dd',
1194
+ firstDay: 1,
1195
+ isRTL: false,
1196
+ showMonthAfterYear: true,
1197
+ yearSuffix: '年'};
1198
+ $.datepicker.setDefaults($.datepicker.regional['zh-TW']);
1199
+ });
includes/js/i18n/jquery.ui.datepicker-af.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Afrikaans initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Renier Pretorius. */
3
+ jQuery(function($){
4
+ $.datepicker.regional['af'] = {
5
+ closeText: 'Selekteer',
6
+ prevText: 'Vorige',
7
+ nextText: 'Volgende',
8
+ currentText: 'Vandag',
9
+ monthNames: ['Januarie','Februarie','Maart','April','Mei','Junie',
10
+ 'Julie','Augustus','September','Oktober','November','Desember'],
11
+ monthNamesShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun',
12
+ 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
13
+ dayNames: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
14
+ dayNamesShort: ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],
15
+ dayNamesMin: ['So','Ma','Di','Wo','Do','Vr','Sa'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['af']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-ar.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Arabic Translation for jQuery UI date picker plugin. */
2
+ /* Khaled Al Horani -- koko.dw@gmail.com */
3
+ /* خالد الحوراني -- koko.dw@gmail.com */
4
+ /* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */
5
+ jQuery(function($){
6
+ $.datepicker.regional['ar'] = {
7
+ closeText: 'إغلاق',
8
+ prevText: '&#x3c;السابق',
9
+ nextText: 'التالي&#x3e;',
10
+ currentText: 'اليوم',
11
+ monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'حزيران',
12
+ 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
13
+ monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
14
+ dayNames: ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'],
15
+ dayNamesShort: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],
16
+ dayNamesMin: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],
17
+ weekHeader: 'أسبوع',
18
+ dateFormat: 'dd/mm/yy',
19
+ firstDay: 0,
20
+ isRTL: true,
21
+ showMonthAfterYear: false,
22
+ yearSuffix: ''};
23
+ $.datepicker.setDefaults($.datepicker.regional['ar']);
24
+ });
includes/js/i18n/jquery.ui.datepicker-az.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Azerbaijani (UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Jamil Najafov (necefov33@gmail.com). */
3
+ jQuery(function($) {
4
+ $.datepicker.regional['az'] = {
5
+ closeText: 'Bağla',
6
+ prevText: '&#x3c;Geri',
7
+ nextText: 'İrəli&#x3e;',
8
+ currentText: 'Bugün',
9
+ monthNames: ['Yanvar','Fevral','Mart','Aprel','May','İyun',
10
+ 'İyul','Avqust','Sentyabr','Oktyabr','Noyabr','Dekabr'],
11
+ monthNamesShort: ['Yan','Fev','Mar','Apr','May','İyun',
12
+ 'İyul','Avq','Sen','Okt','Noy','Dek'],
13
+ dayNames: ['Bazar','Bazar ertəsi','Çərşənbə axşamı','Çərşənbə','Cümə axşamı','Cümə','Şənbə'],
14
+ dayNamesShort: ['B','Be','Ça','Ç','Ca','C','Ş'],
15
+ dayNamesMin: ['B','B','Ç','С','Ç','C','Ş'],
16
+ weekHeader: 'Hf',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['az']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-bg.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Bulgarian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Stoyan Kyosev (http://svest.org). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['bg'] = {
5
+ closeText: 'затвори',
6
+ prevText: '&#x3c;назад',
7
+ nextText: 'напред&#x3e;',
8
+ nextBigText: '&#x3e;&#x3e;',
9
+ currentText: 'днес',
10
+ monthNames: ['Януари','Февруари','Март','Април','Май','Юни',
11
+ 'Юли','Август','Септември','Октомври','Ноември','Декември'],
12
+ monthNamesShort: ['Яну','Фев','Мар','Апр','Май','Юни',
13
+ 'Юли','Авг','Сеп','Окт','Нов','Дек'],
14
+ dayNames: ['Неделя','Понеделник','Вторник','Сряда','Четвъртък','Петък','Събота'],
15
+ dayNamesShort: ['Нед','Пон','Вто','Сря','Чет','Пет','Съб'],
16
+ dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Съ'],
17
+ weekHeader: 'Wk',
18
+ dateFormat: 'dd.mm.yy',
19
+ firstDay: 1,
20
+ isRTL: false,
21
+ showMonthAfterYear: false,
22
+ yearSuffix: ''};
23
+ $.datepicker.setDefaults($.datepicker.regional['bg']);
24
+ });
includes/js/i18n/jquery.ui.datepicker-bs.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Bosnian i18n for the jQuery UI date picker plugin. */
2
+ /* Written by Kenan Konjo. */
3
+ jQuery(function($){
4
+ $.datepicker.regional['bs'] = {
5
+ closeText: 'Zatvori',
6
+ prevText: '&#x3c;',
7
+ nextText: '&#x3e;',
8
+ currentText: 'Danas',
9
+ monthNames: ['Januar','Februar','Mart','April','Maj','Juni',
10
+ 'Juli','August','Septembar','Oktobar','Novembar','Decembar'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
12
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
13
+ dayNames: ['Nedelja','Ponedeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
14
+ dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
15
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['bs']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-ca.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Inicialització en català per a l'extenció 'calendar' per jQuery. */
2
+ /* Writers: (joan.leon@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['ca'] = {
5
+ closeText: 'Tancar',
6
+ prevText: '&#x3c;Ant',
7
+ nextText: 'Seg&#x3e;',
8
+ currentText: 'Avui',
9
+ monthNames: ['Gener','Febrer','Mar&ccedil;','Abril','Maig','Juny',
10
+ 'Juliol','Agost','Setembre','Octubre','Novembre','Desembre'],
11
+ monthNamesShort: ['Gen','Feb','Mar','Abr','Mai','Jun',
12
+ 'Jul','Ago','Set','Oct','Nov','Des'],
13
+ dayNames: ['Diumenge','Dilluns','Dimarts','Dimecres','Dijous','Divendres','Dissabte'],
14
+ dayNamesShort: ['Dug','Dln','Dmt','Dmc','Djs','Dvn','Dsb'],
15
+ dayNamesMin: ['Dg','Dl','Dt','Dc','Dj','Dv','Ds'],
16
+ weekHeader: 'Sm',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['ca']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-cs.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Czech initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Tomas Muller (tomas@tomas-muller.net). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['cs'] = {
5
+ closeText: 'Zavřít',
6
+ prevText: '&#x3c;Dříve',
7
+ nextText: 'Později&#x3e;',
8
+ currentText: 'Nyní',
9
+ monthNames: ['leden','únor','březen','duben','květen','červen',
10
+ 'červenec','srpen','září','říjen','listopad','prosinec'],
11
+ monthNamesShort: ['led','úno','bře','dub','kvě','čer',
12
+ 'čvc','srp','zář','říj','lis','pro'],
13
+ dayNames: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],
14
+ dayNamesShort: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
15
+ dayNamesMin: ['ne','po','út','st','čt','pá','so'],
16
+ weekHeader: 'Týd',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['cs']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-da.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Danish initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Jan Christensen ( deletestuff@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['da'] = {
5
+ closeText: 'Luk',
6
+ prevText: '&#x3c;Forrige',
7
+ nextText: 'Næste&#x3e;',
8
+ currentText: 'Idag',
9
+ monthNames: ['Januar','Februar','Marts','April','Maj','Juni',
10
+ 'Juli','August','September','Oktober','November','December'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
12
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
13
+ dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
14
+ dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],
15
+ dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],
16
+ weekHeader: 'Uge',
17
+ dateFormat: 'dd-mm-yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['da']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-de.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* German initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Milian Wolff (mail@milianw.de). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['de'] = {
5
+ closeText: 'schließen',
6
+ prevText: '&#x3c;zurück',
7
+ nextText: 'Vor&#x3e;',
8
+ currentText: 'heute',
9
+ monthNames: ['Januar','Februar','März','April','Mai','Juni',
10
+ 'Juli','August','September','Oktober','November','Dezember'],
11
+ monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',
12
+ 'Jul','Aug','Sep','Okt','Nov','Dez'],
13
+ dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
14
+ dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
15
+ dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
16
+ weekHeader: 'Wo',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['de']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-el.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Greek (el) initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Alex Cicovic (http://www.alexcicovic.com) */
3
+ jQuery(function($){
4
+ $.datepicker.regional['el'] = {
5
+ closeText: 'Κλείσιμο',
6
+ prevText: 'Προηγούμενος',
7
+ nextText: 'Επόμενος',
8
+ currentText: 'Τρέχων Μήνας',
9
+ monthNames: ['Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος',
10
+ 'Ιούλιος','Αύγουστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος'],
11
+ monthNamesShort: ['Ιαν','Φεβ','Μαρ','Απρ','Μαι','Ιουν',
12
+ 'Ιουλ','Αυγ','Σεπ','Οκτ','Νοε','Δεκ'],
13
+ dayNames: ['Κυριακή','Δευτέρα','Τρίτη','Τετάρτη','Πέμπτη','Παρασκευή','Σάββατο'],
14
+ dayNamesShort: ['Κυρ','Δευ','Τρι','Τετ','Πεμ','Παρ','Σαβ'],
15
+ dayNamesMin: ['Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'],
16
+ weekHeader: 'Εβδ',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['el']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-en-GB.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* English/UK initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Stuart. */
3
+ jQuery(function($){
4
+ $.datepicker.regional['en-GB'] = {
5
+ closeText: 'Done',
6
+ prevText: 'Prev',
7
+ nextText: 'Next',
8
+ currentText: 'Today',
9
+ monthNames: ['January','February','March','April','May','June',
10
+ 'July','August','September','October','November','December'],
11
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
12
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
13
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
14
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
15
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['en-GB']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-eo.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Esperanto initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Olivier M. (olivierweb@ifrance.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['eo'] = {
5
+ closeText: 'Fermi',
6
+ prevText: '&lt;Anta',
7
+ nextText: 'Sekv&gt;',
8
+ currentText: 'Nuna',
9
+ monthNames: ['Januaro','Februaro','Marto','Aprilo','Majo','Junio',
10
+ 'Julio','Aŭgusto','Septembro','Oktobro','Novembro','Decembro'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
12
+ 'Jul','Aŭg','Sep','Okt','Nov','Dec'],
13
+ dayNames: ['Dimanĉo','Lundo','Mardo','Merkredo','Ĵaŭdo','Vendredo','Sabato'],
14
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Ĵaŭ','Ven','Sab'],
15
+ dayNamesMin: ['Di','Lu','Ma','Me','Ĵa','Ve','Sa'],
16
+ weekHeader: 'Sb',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['eo']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-es.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Inicialización en español para la extensión 'UI date picker' para jQuery. */
2
+ /* Traducido por Vester (xvester@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['es'] = {
5
+ closeText: 'Cerrar',
6
+ prevText: '&#x3c;Ant',
7
+ nextText: 'Sig&#x3e;',
8
+ currentText: 'Hoy',
9
+ monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio',
10
+ 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
11
+ monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun',
12
+ 'Jul','Ago','Sep','Oct','Nov','Dic'],
13
+ dayNames: ['Domingo','Lunes','Martes','Mi&eacute;rcoles','Jueves','Viernes','S&aacute;bado'],
14
+ dayNamesShort: ['Dom','Lun','Mar','Mi&eacute;','Juv','Vie','S&aacute;b'],
15
+ dayNamesMin: ['Do','Lu','Ma','Mi','Ju','Vi','S&aacute;'],
16
+ weekHeader: 'Sm',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['es']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-et.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Estonian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Mart Sõmermaa (mrts.pydev at gmail com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['et'] = {
5
+ closeText: 'Sulge',
6
+ prevText: 'Eelnev',
7
+ nextText: 'Järgnev',
8
+ currentText: 'Täna',
9
+ monthNames: ['Jaanuar','Veebruar','Märts','Aprill','Mai','Juuni',
10
+ 'Juuli','August','September','Oktoober','November','Detsember'],
11
+ monthNamesShort: ['Jaan', 'Veebr', 'Märts', 'Apr', 'Mai', 'Juuni',
12
+ 'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'],
13
+ dayNames: ['Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'],
14
+ dayNamesShort: ['Pühap', 'Esmasp', 'Teisip', 'Kolmap', 'Neljap', 'Reede', 'Laup'],
15
+ dayNamesMin: ['P','E','T','K','N','R','L'],
16
+ weekHeader: 'Sm',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['et']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-eu.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Euskarako oinarria 'UI date picker' jquery-ko extentsioarentzat */
2
+ /* Karrikas-ek itzulia (karrikas@karrikas.com) */
3
+ jQuery(function($){
4
+ $.datepicker.regional['eu'] = {
5
+ closeText: 'Egina',
6
+ prevText: '&#x3c;Aur',
7
+ nextText: 'Hur&#x3e;',
8
+ currentText: 'Gaur',
9
+ monthNames: ['Urtarrila','Otsaila','Martxoa','Apirila','Maiatza','Ekaina',
10
+ 'Uztaila','Abuztua','Iraila','Urria','Azaroa','Abendua'],
11
+ monthNamesShort: ['Urt','Ots','Mar','Api','Mai','Eka',
12
+ 'Uzt','Abu','Ira','Urr','Aza','Abe'],
13
+ dayNames: ['Igandea','Astelehena','Asteartea','Asteazkena','Osteguna','Ostirala','Larunbata'],
14
+ dayNamesShort: ['Iga','Ast','Ast','Ast','Ost','Ost','Lar'],
15
+ dayNamesMin: ['Ig','As','As','As','Os','Os','La'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'yy/mm/dd',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['eu']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-fa.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Persian (Farsi) Translation for the jQuery UI date picker plugin. */
2
+ /* Javad Mowlanezhad -- jmowla@gmail.com */
3
+ /* Jalali calendar should supported soon! (Its implemented but I have to test it) */
4
+ jQuery(function($) {
5
+ $.datepicker.regional['fa'] = {
6
+ closeText: 'بستن',
7
+ prevText: '&#x3c;قبلي',
8
+ nextText: 'بعدي&#x3e;',
9
+ currentText: 'امروز',
10
+ monthNames: ['فروردين','ارديبهشت','خرداد','تير','مرداد','شهريور',
11
+ 'مهر','آبان','آذر','دي','بهمن','اسفند'],
12
+ monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
13
+ dayNames: ['يکشنبه','دوشنبه','سه‌شنبه','چهارشنبه','پنجشنبه','جمعه','شنبه'],
14
+ dayNamesShort: ['ي','د','س','چ','پ','ج', 'ش'],
15
+ dayNamesMin: ['ي','د','س','چ','پ','ج', 'ش'],
16
+ weekHeader: 'هف',
17
+ dateFormat: 'yy/mm/dd',
18
+ firstDay: 6,
19
+ isRTL: true,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['fa']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-fi.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Finnish initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Harri Kilpi� (harrikilpio@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['fi'] = {
5
+ closeText: 'Sulje',
6
+ prevText: '&laquo;Edellinen',
7
+ nextText: 'Seuraava&raquo;',
8
+ currentText: 'T&auml;n&auml;&auml;n',
9
+ monthNames: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kes&auml;kuu',
10
+ 'Hein&auml;kuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],
11
+ monthNamesShort: ['Tammi','Helmi','Maalis','Huhti','Touko','Kes&auml;',
12
+ 'Hein&auml;','Elo','Syys','Loka','Marras','Joulu'],
13
+ dayNamesShort: ['Su','Ma','Ti','Ke','To','Pe','Su'],
14
+ dayNames: ['Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'],
15
+ dayNamesMin: ['Su','Ma','Ti','Ke','To','Pe','La'],
16
+ weekHeader: 'Vk',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['fi']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-fo.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Faroese initialisation for the jQuery UI date picker plugin */
2
+ /* Written by Sverri Mohr Olsen, sverrimo@gmail.com */
3
+ jQuery(function($){
4
+ $.datepicker.regional['fo'] = {
5
+ closeText: 'Lat aftur',
6
+ prevText: '&#x3c;Fyrra',
7
+ nextText: 'Næsta&#x3e;',
8
+ currentText: 'Í dag',
9
+ monthNames: ['Januar','Februar','Mars','Apríl','Mei','Juni',
10
+ 'Juli','August','September','Oktober','November','Desember'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
12
+ 'Jul','Aug','Sep','Okt','Nov','Des'],
13
+ dayNames: ['Sunnudagur','Mánadagur','Týsdagur','Mikudagur','Hósdagur','Fríggjadagur','Leyardagur'],
14
+ dayNamesShort: ['Sun','Mán','Týs','Mik','Hós','Frí','Ley'],
15
+ dayNamesMin: ['Su','Má','Tý','Mi','Hó','Fr','Le'],
16
+ weekHeader: 'Vk',
17
+ dateFormat: 'dd-mm-yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['fo']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-fr-CH.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Swiss-French initialisation for the jQuery UI date picker plugin. */
2
+ /* Written Martin Voelkle (martin.voelkle@e-tc.ch). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['fr-CH'] = {
5
+ closeText: 'Fermer',
6
+ prevText: '&#x3c;Préc',
7
+ nextText: 'Suiv&#x3e;',
8
+ currentText: 'Courant',
9
+ monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
10
+ 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
11
+ monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',
12
+ 'Jul','Aoû','Sep','Oct','Nov','Déc'],
13
+ dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
14
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
15
+ dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
16
+ weekHeader: 'Sm',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['fr-CH']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-fr.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* French initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Keith Wood (kbwood{at}iinet.com.au) and Stéphane Nahmani (sholby@sholby.net). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['fr'] = {
5
+ closeText: 'Fermer',
6
+ prevText: '&#x3c;Préc',
7
+ nextText: 'Suiv&#x3e;',
8
+ currentText: 'Courant',
9
+ monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
10
+ 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
11
+ monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',
12
+ 'Jul','Aoû','Sep','Oct','Nov','Déc'],
13
+ dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
14
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
15
+ dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
16
+ weekHeader: 'Sm',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['fr']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-he.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Hebrew initialisation for the UI Datepicker extension. */
2
+ /* Written by Amir Hardon (ahardon at gmail dot com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['he'] = {
5
+ closeText: 'סגור',
6
+ prevText: '&#x3c;הקודם',
7
+ nextText: 'הבא&#x3e;',
8
+ currentText: 'היום',
9
+ monthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני',
10
+ 'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'],
11
+ monthNamesShort: ['1','2','3','4','5','6',
12
+ '7','8','9','10','11','12'],
13
+ dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],
14
+ dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
15
+ dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 0,
19
+ isRTL: true,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['he']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-hr.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Croatian i18n for the jQuery UI date picker plugin. */
2
+ /* Written by Vjekoslav Nesek. */
3
+ jQuery(function($){
4
+ $.datepicker.regional['hr'] = {
5
+ closeText: 'Zatvori',
6
+ prevText: '&#x3c;',
7
+ nextText: '&#x3e;',
8
+ currentText: 'Danas',
9
+ monthNames: ['Siječanj','Veljača','Ožujak','Travanj','Svibanj','Lipanj',
10
+ 'Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'],
11
+ monthNamesShort: ['Sij','Velj','Ožu','Tra','Svi','Lip',
12
+ 'Srp','Kol','Ruj','Lis','Stu','Pro'],
13
+ dayNames: ['Nedjelja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
14
+ dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
15
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
16
+ weekHeader: 'Tje',
17
+ dateFormat: 'dd.mm.yy.',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['hr']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-hu.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Hungarian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Istvan Karaszi (jquery@spam.raszi.hu). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['hu'] = {
5
+ closeText: 'bezárás',
6
+ prevText: '&laquo;&nbsp;vissza',
7
+ nextText: 'előre&nbsp;&raquo;',
8
+ currentText: 'ma',
9
+ monthNames: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június',
10
+ 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],
11
+ monthNamesShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún',
12
+ 'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],
13
+ dayNames: ['Vasárnap', 'Hétfö', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],
14
+ dayNamesShort: ['Vas', 'Hét', 'Ked', 'Sze', 'Csü', 'Pén', 'Szo'],
15
+ dayNamesMin: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
16
+ weekHeader: 'Hé',
17
+ dateFormat: 'yy-mm-dd',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['hu']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-hy.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Armenian(UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Levon Zakaryan (levon.zakaryan@gmail.com)*/
3
+ jQuery(function($){
4
+ $.datepicker.regional['hy'] = {
5
+ closeText: 'Փակել',
6
+ prevText: '&#x3c;Նախ.',
7
+ nextText: 'Հաջ.&#x3e;',
8
+ currentText: 'Այսօր',
9
+ monthNames: ['Հունվար','Փետրվար','Մարտ','Ապրիլ','Մայիս','Հունիս',
10
+ 'Հուլիս','Օգոստոս','Սեպտեմբեր','Հոկտեմբեր','Նոյեմբեր','Դեկտեմբեր'],
11
+ monthNamesShort: ['Հունվ','Փետր','Մարտ','Ապր','Մայիս','Հունիս',
12
+ 'Հուլ','Օգս','Սեպ','Հոկ','Նոյ','Դեկ'],
13
+ dayNames: ['կիրակի','եկուշաբթի','երեքշաբթի','չորեքշաբթի','հինգշաբթի','ուրբաթ','շաբաթ'],
14
+ dayNamesShort: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
15
+ dayNamesMin: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
16
+ weekHeader: 'ՇԲՏ',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['hy']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-id.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Indonesian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Deden Fathurahman (dedenf@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['id'] = {
5
+ closeText: 'Tutup',
6
+ prevText: '&#x3c;mundur',
7
+ nextText: 'maju&#x3e;',
8
+ currentText: 'hari ini',
9
+ monthNames: ['Januari','Februari','Maret','April','Mei','Juni',
10
+ 'Juli','Agustus','September','Oktober','Nopember','Desember'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
12
+ 'Jul','Agus','Sep','Okt','Nop','Des'],
13
+ dayNames: ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'],
14
+ dayNamesShort: ['Min','Sen','Sel','Rab','kam','Jum','Sab'],
15
+ dayNamesMin: ['Mg','Sn','Sl','Rb','Km','jm','Sb'],
16
+ weekHeader: 'Mg',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['id']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-is.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Icelandic initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Haukur H. Thorsson (haukur@eskill.is). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['is'] = {
5
+ closeText: 'Loka',
6
+ prevText: '&#x3c; Fyrri',
7
+ nextText: 'N&aelig;sti &#x3e;',
8
+ currentText: '&Iacute; dag',
9
+ monthNames: ['Jan&uacute;ar','Febr&uacute;ar','Mars','Apr&iacute;l','Ma&iacute','J&uacute;n&iacute;',
10
+ 'J&uacute;l&iacute;','&Aacute;g&uacute;st','September','Okt&oacute;ber','N&oacute;vember','Desember'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Ma&iacute;','J&uacute;n',
12
+ 'J&uacute;l','&Aacute;g&uacute;','Sep','Okt','N&oacute;v','Des'],
13
+ dayNames: ['Sunnudagur','M&aacute;nudagur','&THORN;ri&eth;judagur','Mi&eth;vikudagur','Fimmtudagur','F&ouml;studagur','Laugardagur'],
14
+ dayNamesShort: ['Sun','M&aacute;n','&THORN;ri','Mi&eth;','Fim','F&ouml;s','Lau'],
15
+ dayNamesMin: ['Su','M&aacute;','&THORN;r','Mi','Fi','F&ouml;','La'],
16
+ weekHeader: 'Vika',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['is']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-it.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Italian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Antonello Pasella (antonello.pasella@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['it'] = {
5
+ closeText: 'Chiudi',
6
+ prevText: '&#x3c;Prec',
7
+ nextText: 'Succ&#x3e;',
8
+ currentText: 'Oggi',
9
+ monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',
10
+ 'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
11
+ monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu',
12
+ 'Lug','Ago','Set','Ott','Nov','Dic'],
13
+ dayNames: ['Domenica','Luned&#236','Marted&#236','Mercoled&#236','Gioved&#236','Venerd&#236','Sabato'],
14
+ dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],
15
+ dayNamesMin: ['Do','Lu','Ma','Me','Gi','Ve','Sa'],
16
+ weekHeader: 'Sm',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['it']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-ja.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Japanese initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Kentaro SATO (kentaro@ranvis.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['ja'] = {
5
+ closeText: '閉じる',
6
+ prevText: '&#x3c;前',
7
+ nextText: '次&#x3e;',
8
+ currentText: '今日',
9
+ monthNames: ['1月','2月','3月','4月','5月','6月',
10
+ '7月','8月','9月','10月','11月','12月'],
11
+ monthNamesShort: ['1月','2月','3月','4月','5月','6月',
12
+ '7月','8月','9月','10月','11月','12月'],
13
+ dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
14
+ dayNamesShort: ['日','月','火','水','木','金','土'],
15
+ dayNamesMin: ['日','月','火','水','木','金','土'],
16
+ weekHeader: '週',
17
+ dateFormat: 'yy/mm/dd',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: true,
21
+ yearSuffix: '年'};
22
+ $.datepicker.setDefaults($.datepicker.regional['ja']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-ko.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Korean initialisation for the jQuery calendar extension. */
2
+ /* Written by DaeKwon Kang (ncrash.dk@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['ko'] = {
5
+ closeText: '닫기',
6
+ prevText: '이전달',
7
+ nextText: '다음달',
8
+ currentText: '오늘',
9
+ monthNames: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)',
10
+ '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'],
11
+ monthNamesShort: ['1월(JAN)','2월(FEB)','3월(MAR)','4월(APR)','5월(MAY)','6월(JUN)',
12
+ '7월(JUL)','8월(AUG)','9월(SEP)','10월(OCT)','11월(NOV)','12월(DEC)'],
13
+ dayNames: ['일','월','화','수','목','금','토'],
14
+ dayNamesShort: ['일','월','화','수','목','금','토'],
15
+ dayNamesMin: ['일','월','화','수','목','금','토'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'yy-mm-dd',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: '년'};
22
+ $.datepicker.setDefaults($.datepicker.regional['ko']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-kz.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Kazakh (UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Dmitriy Karasyov (dmitriy.karasyov@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['kz'] = {
5
+ closeText: 'Жабу',
6
+ prevText: '&#x3c;Алдыңғы',
7
+ nextText: 'Келесі&#x3e;',
8
+ currentText: 'Бүгін',
9
+ monthNames: ['Қаңтар','Ақпан','Наурыз','Сәуір','Мамыр','Маусым',
10
+ 'Шілде','Тамыз','Қыркүйек','Қазан','Қараша','Желтоқсан'],
11
+ monthNamesShort: ['Қаң','Ақп','Нау','Сәу','Мам','Мау',
12
+ 'Шіл','Там','Қыр','Қаз','Қар','Жел'],
13
+ dayNames: ['Жексенбі','Дүйсенбі','Сейсенбі','Сәрсенбі','Бейсенбі','Жұма','Сенбі'],
14
+ dayNamesShort: ['жкс','дсн','ссн','срс','бсн','жма','снб'],
15
+ dayNamesMin: ['Жк','Дс','Сс','Ср','Бс','Жм','Сн'],
16
+ weekHeader: 'Не',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['kz']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-lt.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Lithuanian (UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* @author Arturas Paleicikas <arturas@avalon.lt> */
3
+ jQuery(function($){
4
+ $.datepicker.regional['lt'] = {
5
+ closeText: 'Uždaryti',
6
+ prevText: '&#x3c;Atgal',
7
+ nextText: 'Pirmyn&#x3e;',
8
+ currentText: 'Šiandien',
9
+ monthNames: ['Sausis','Vasaris','Kovas','Balandis','Gegužė','Birželis',
10
+ 'Liepa','Rugpjūtis','Rugsėjis','Spalis','Lapkritis','Gruodis'],
11
+ monthNamesShort: ['Sau','Vas','Kov','Bal','Geg','Bir',
12
+ 'Lie','Rugp','Rugs','Spa','Lap','Gru'],
13
+ dayNames: ['sekmadienis','pirmadienis','antradienis','trečiadienis','ketvirtadienis','penktadienis','šeštadienis'],
14
+ dayNamesShort: ['sek','pir','ant','tre','ket','pen','šeš'],
15
+ dayNamesMin: ['Se','Pr','An','Tr','Ke','Pe','Še'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'yy-mm-dd',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['lt']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-lv.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Latvian (UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* @author Arturas Paleicikas <arturas.paleicikas@metasite.net> */
3
+ jQuery(function($){
4
+ $.datepicker.regional['lv'] = {
5
+ closeText: 'Aizvērt',
6
+ prevText: 'Iepr',
7
+ nextText: 'Nāka',
8
+ currentText: 'Šodien',
9
+ monthNames: ['Janvāris','Februāris','Marts','Aprīlis','Maijs','Jūnijs',
10
+ 'Jūlijs','Augusts','Septembris','Oktobris','Novembris','Decembris'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jūn',
12
+ 'Jūl','Aug','Sep','Okt','Nov','Dec'],
13
+ dayNames: ['svētdiena','pirmdiena','otrdiena','trešdiena','ceturtdiena','piektdiena','sestdiena'],
14
+ dayNamesShort: ['svt','prm','otr','tre','ctr','pkt','sst'],
15
+ dayNamesMin: ['Sv','Pr','Ot','Tr','Ct','Pk','Ss'],
16
+ weekHeader: 'Nav',
17
+ dateFormat: 'dd-mm-yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['lv']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-ms.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Malaysian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Mohd Nawawi Mohamad Jamili (nawawi@ronggeng.net). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['ms'] = {
5
+ closeText: 'Tutup',
6
+ prevText: '&#x3c;Sebelum',
7
+ nextText: 'Selepas&#x3e;',
8
+ currentText: 'hari ini',
9
+ monthNames: ['Januari','Februari','Mac','April','Mei','Jun',
10
+ 'Julai','Ogos','September','Oktober','November','Disember'],
11
+ monthNamesShort: ['Jan','Feb','Mac','Apr','Mei','Jun',
12
+ 'Jul','Ogo','Sep','Okt','Nov','Dis'],
13
+ dayNames: ['Ahad','Isnin','Selasa','Rabu','Khamis','Jumaat','Sabtu'],
14
+ dayNamesShort: ['Aha','Isn','Sel','Rab','kha','Jum','Sab'],
15
+ dayNamesMin: ['Ah','Is','Se','Ra','Kh','Ju','Sa'],
16
+ weekHeader: 'Mg',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['ms']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-nl.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Mathias Bynens <http://mathiasbynens.be/> */
3
+ jQuery(function($){
4
+ $.datepicker.regional['nl'] = {
5
+ closeText: 'Sluiten',
6
+ prevText: '←',
7
+ nextText: '→',
8
+ currentText: 'Vandaag',
9
+ monthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',
10
+ 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
11
+ monthNamesShort: ['jan', 'feb', 'maa', 'apr', 'mei', 'jun',
12
+ 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
13
+ dayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
14
+ dayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],
15
+ dayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''
22
+ };
23
+ $.datepicker.setDefaults($.datepicker.regional.nl);
24
+ });
includes/js/i18n/jquery.ui.datepicker-no.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Norwegian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Naimdjon Takhirov (naimdjon@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['no'] = {
5
+ closeText: 'Lukk',
6
+ prevText: '&laquo;Forrige',
7
+ nextText: 'Neste&raquo;',
8
+ currentText: 'I dag',
9
+ monthNames: ['Januar','Februar','Mars','April','Mai','Juni',
10
+ 'Juli','August','September','Oktober','November','Desember'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jun',
12
+ 'Jul','Aug','Sep','Okt','Nov','Des'],
13
+ dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],
14
+ dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
15
+ dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],
16
+ weekHeader: 'Uke',
17
+ dateFormat: 'yy-mm-dd',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['no']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-pl.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Polish initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Jacek Wysocki (jacek.wysocki@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['pl'] = {
5
+ closeText: 'Zamknij',
6
+ prevText: '&#x3c;Poprzedni',
7
+ nextText: 'Następny&#x3e;',
8
+ currentText: 'Dziś',
9
+ monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec',
10
+ 'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
11
+ monthNamesShort: ['Sty','Lu','Mar','Kw','Maj','Cze',
12
+ 'Lip','Sie','Wrz','Pa','Lis','Gru'],
13
+ dayNames: ['Niedziela','Poniedziałek','Wtorek','Środa','Czwartek','Piątek','Sobota'],
14
+ dayNamesShort: ['Nie','Pn','Wt','Śr','Czw','Pt','So'],
15
+ dayNamesMin: ['N','Pn','Wt','Śr','Cz','Pt','So'],
16
+ weekHeader: 'Tydz',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['pl']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-pt-BR.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Brazilian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Leonildo Costa Silva (leocsilva@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['pt-BR'] = {
5
+ closeText: 'Fechar',
6
+ prevText: '&#x3c;Anterior',
7
+ nextText: 'Pr&oacute;ximo&#x3e;',
8
+ currentText: 'Hoje',
9
+ monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho',
10
+ 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
11
+ monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
12
+ 'Jul','Ago','Set','Out','Nov','Dez'],
13
+ dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&aacute;bado'],
14
+ dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
15
+ dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
16
+ weekHeader: 'Sm',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['pt-BR']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-ro.js ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Romanian initialisation for the jQuery UI date picker plugin.
2
+ *
3
+ * Written by Edmond L. (ll_edmond@walla.com)
4
+ * and Ionut G. Stan (ionut.g.stan@gmail.com)
5
+ */
6
+ jQuery(function($){
7
+ $.datepicker.regional['ro'] = {
8
+ closeText: 'Închide',
9
+ prevText: '&laquo; Luna precedentă',
10
+ nextText: 'Luna următoare &raquo;',
11
+ currentText: 'Azi',
12
+ monthNames: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie',
13
+ 'Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],
14
+ monthNamesShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',
15
+ 'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
16
+ dayNames: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
17
+ dayNamesShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
18
+ dayNamesMin: ['Du','Lu','Ma','Mi','Jo','Vi','Sâ'],
19
+ weekHeader: 'Săpt',
20
+ dateFormat: 'dd.mm.yy',
21
+ firstDay: 1,
22
+ isRTL: false,
23
+ showMonthAfterYear: false,
24
+ yearSuffix: ''};
25
+ $.datepicker.setDefaults($.datepicker.regional['ro']);
26
+ });
includes/js/i18n/jquery.ui.datepicker-ru.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Russian (UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Andrew Stromnov (stromnov@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['ru'] = {
5
+ closeText: 'Закрыть',
6
+ prevText: '&#x3c;Пред',
7
+ nextText: 'След&#x3e;',
8
+ currentText: 'Сегодня',
9
+ monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь',
10
+ 'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
11
+ monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',
12
+ 'Июл','Авг','Сен','Окт','Ноя','Дек'],
13
+ dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],
14
+ dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],
15
+ dayNamesMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],
16
+ weekHeader: 'Не',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['ru']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-sk.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Slovak initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Vojtech Rinik (vojto@hmm.sk). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['sk'] = {
5
+ closeText: 'Zavrieť',
6
+ prevText: '&#x3c;Predchádzajúci',
7
+ nextText: 'Nasledujúci&#x3e;',
8
+ currentText: 'Dnes',
9
+ monthNames: ['Január','Február','Marec','Apríl','Máj','Jún',
10
+ 'Júl','August','September','Október','November','December'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',
12
+ 'Júl','Aug','Sep','Okt','Nov','Dec'],
13
+ dayNames: ['Nedel\'a','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],
14
+ dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],
15
+ dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],
16
+ weekHeader: 'Ty',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['sk']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-sl.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Slovenian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Jaka Jancar (jaka@kubje.org). */
3
+ /* c = &#x10D;, s = &#x161; z = &#x17E; C = &#x10C; S = &#x160; Z = &#x17D; */
4
+ jQuery(function($){
5
+ $.datepicker.regional['sl'] = {
6
+ closeText: 'Zapri',
7
+ prevText: '&lt;Prej&#x161;nji',
8
+ nextText: 'Naslednji&gt;',
9
+ currentText: 'Trenutni',
10
+ monthNames: ['Januar','Februar','Marec','April','Maj','Junij',
11
+ 'Julij','Avgust','September','Oktober','November','December'],
12
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
13
+ 'Jul','Avg','Sep','Okt','Nov','Dec'],
14
+ dayNames: ['Nedelja','Ponedeljek','Torek','Sreda','&#x10C;etrtek','Petek','Sobota'],
15
+ dayNamesShort: ['Ned','Pon','Tor','Sre','&#x10C;et','Pet','Sob'],
16
+ dayNamesMin: ['Ne','Po','To','Sr','&#x10C;e','Pe','So'],
17
+ weekHeader: 'Teden',
18
+ dateFormat: 'dd.mm.yy',
19
+ firstDay: 1,
20
+ isRTL: false,
21
+ showMonthAfterYear: false,
22
+ yearSuffix: ''};
23
+ $.datepicker.setDefaults($.datepicker.regional['sl']);
24
+ });
includes/js/i18n/jquery.ui.datepicker-sq.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Albanian initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Flakron Bytyqi (flakron@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['sq'] = {
5
+ closeText: 'mbylle',
6
+ prevText: '&#x3c;mbrapa',
7
+ nextText: 'Përpara&#x3e;',
8
+ currentText: 'sot',
9
+ monthNames: ['Janar','Shkurt','Mars','Prill','Maj','Qershor',
10
+ 'Korrik','Gusht','Shtator','Tetor','Nëntor','Dhjetor'],
11
+ monthNamesShort: ['Jan','Shk','Mar','Pri','Maj','Qer',
12
+ 'Kor','Gus','Sht','Tet','Nën','Dhj'],
13
+ dayNames: ['E Diel','E Hënë','E Martë','E Mërkurë','E Enjte','E Premte','E Shtune'],
14
+ dayNamesShort: ['Di','Hë','Ma','Më','En','Pr','Sh'],
15
+ dayNamesMin: ['Di','Hë','Ma','Më','En','Pr','Sh'],
16
+ weekHeader: 'Ja',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['sq']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-sr-SR.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Serbian i18n for the jQuery UI date picker plugin. */
2
+ /* Written by Dejan Dimić. */
3
+ jQuery(function($){
4
+ $.datepicker.regional['sr-SR'] = {
5
+ closeText: 'Zatvori',
6
+ prevText: '&#x3c;',
7
+ nextText: '&#x3e;',
8
+ currentText: 'Danas',
9
+ monthNames: ['Januar','Februar','Mart','April','Maj','Jun',
10
+ 'Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
12
+ 'Jul','Avg','Sep','Okt','Nov','Dec'],
13
+ dayNames: ['Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'],
14
+ dayNamesShort: ['Ned','Pon','Uto','Sre','Čet','Pet','Sub'],
15
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
16
+ weekHeader: 'Sed',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['sr-SR']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-sr.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Serbian i18n for the jQuery UI date picker plugin. */
2
+ /* Written by Dejan Dimić. */
3
+ jQuery(function($){
4
+ $.datepicker.regional['sr'] = {
5
+ closeText: 'Затвори',
6
+ prevText: '&#x3c;',
7
+ nextText: '&#x3e;',
8
+ currentText: 'Данас',
9
+ monthNames: ['Јануар','Фебруар','Март','Април','Мај','Јун',
10
+ 'Јул','Август','Септембар','Октобар','Новембар','Децембар'],
11
+ monthNamesShort: ['Јан','Феб','Мар','Апр','Мај','Јун',
12
+ 'Јул','Авг','Сеп','Окт','Нов','Дец'],
13
+ dayNames: ['Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'],
14
+ dayNamesShort: ['Нед','Пон','Уто','Сре','Чет','Пет','Суб'],
15
+ dayNamesMin: ['Не','По','Ут','Ср','Че','Пе','Су'],
16
+ weekHeader: 'Сед',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['sr']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-sv.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Swedish initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Anders Ekdahl ( anders@nomadiz.se). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['sv'] = {
5
+ closeText: 'Stäng',
6
+ prevText: '&laquo;Förra',
7
+ nextText: 'Nästa&raquo;',
8
+ currentText: 'Idag',
9
+ monthNames: ['Januari','Februari','Mars','April','Maj','Juni',
10
+ 'Juli','Augusti','September','Oktober','November','December'],
11
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
12
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
13
+ dayNamesShort: ['Sön','Mån','Tis','Ons','Tor','Fre','Lör'],
14
+ dayNames: ['Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'],
15
+ dayNamesMin: ['Sö','Må','Ti','On','To','Fr','Lö'],
16
+ weekHeader: 'Ve',
17
+ dateFormat: 'yy-mm-dd',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['sv']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-ta.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Tamil (UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by S A Sureshkumar (saskumar@live.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['ta'] = {
5
+ closeText: 'மூடு',
6
+ prevText: 'முன்னையது',
7
+ nextText: 'அடுத்தது',
8
+ currentText: 'இன்று',
9
+ monthNames: ['தை','மாசி','பங்குனி','சித்திரை','வைகாசி','ஆனி',
10
+ 'ஆடி','ஆவணி','புரட்டாசி','ஐப்பசி','கார்த்திகை','மார்கழி'],
11
+ monthNamesShort: ['தை','மாசி','பங்','சித்','வைகா','ஆனி',
12
+ 'ஆடி','ஆவ','புர','ஐப்','கார்','மார்'],
13
+ dayNames: ['ஞாயிற்றுக்கிழமை','திங்கட்கிழமை','செவ்வாய்க்கிழமை','புதன்கிழமை','வியாழக்கிழமை','வெள்ளிக்கிழமை','சனிக்கிழமை'],
14
+ dayNamesShort: ['ஞாயிறு','திங்கள்','செவ்வாய்','புதன்','வியாழன்','வெள்ளி','சனி'],
15
+ dayNamesMin: ['ஞா','தி','செ','பு','வி','வெ','ச'],
16
+ weekHeader: 'Не',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['ta']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-th.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Thai initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by pipo (pipo@sixhead.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['th'] = {
5
+ closeText: 'ปิด',
6
+ prevText: '&laquo;&nbsp;ย้อน',
7
+ nextText: 'ถัดไป&nbsp;&raquo;',
8
+ currentText: 'วันนี้',
9
+ monthNames: ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน',
10
+ 'กรกฏาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'],
11
+ monthNamesShort: ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.',
12
+ 'ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'],
13
+ dayNames: ['อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'],
14
+ dayNamesShort: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
15
+ dayNamesMin: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
16
+ weekHeader: 'Wk',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['th']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-tr.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Turkish initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Izzet Emre Erkan (kara@karalamalar.net). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['tr'] = {
5
+ closeText: 'kapat',
6
+ prevText: '&#x3c;geri',
7
+ nextText: 'ileri&#x3e',
8
+ currentText: 'bugün',
9
+ monthNames: ['Ocak','Şubat','Mart','Nisan','Mayıs','Haziran',
10
+ 'Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'],
11
+ monthNamesShort: ['Oca','Şub','Mar','Nis','May','Haz',
12
+ 'Tem','Ağu','Eyl','Eki','Kas','Ara'],
13
+ dayNames: ['Pazar','Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi'],
14
+ dayNamesShort: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
15
+ dayNamesMin: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
16
+ weekHeader: 'Hf',
17
+ dateFormat: 'dd.mm.yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['tr']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-uk.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Ukrainian (UTF-8) initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Maxim Drogobitskiy (maxdao@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['uk'] = {
5
+ closeText: 'Закрити',
6
+ prevText: '&#x3c;',
7
+ nextText: '&#x3e;',
8
+ currentText: 'Сьогодні',
9
+ monthNames: ['Січень','Лютий','Березень','Квітень','Травень','Червень',
10
+ 'Липень','Серпень','Вересень','Жовтень','Листопад','Грудень'],
11
+ monthNamesShort: ['Січ','Лют','Бер','Кві','Тра','Чер',
12
+ 'Лип','Сер','Вер','Жов','Лис','Гру'],
13
+ dayNames: ['неділя','понеділок','вівторок','середа','четвер','п’ятниця','субота'],
14
+ dayNamesShort: ['нед','пнд','вів','срд','чтв','птн','сбт'],
15
+ dayNamesMin: ['Нд','Пн','Вт','Ср','Чт','Пт','Сб'],
16
+ weekHeader: 'Не',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['uk']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-vi.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Vietnamese initialisation for the jQuery UI date picker plugin. */
2
+ /* Translated by Le Thanh Huy (lthanhhuy@cit.ctu.edu.vn). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['vi'] = {
5
+ closeText: 'Đóng',
6
+ prevText: '&#x3c;Trước',
7
+ nextText: 'Tiếp&#x3e;',
8
+ currentText: 'Hôm nay',
9
+ monthNames: ['Tháng Một', 'Tháng Hai', 'Tháng Ba', 'Tháng Tư', 'Tháng Năm', 'Tháng Sáu',
10
+ 'Tháng Bảy', 'Tháng Tám', 'Tháng Chín', 'Tháng Mười', 'Tháng Mười Một', 'Tháng Mười Hai'],
11
+ monthNamesShort: ['Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6',
12
+ 'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12'],
13
+ dayNames: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy'],
14
+ dayNamesShort: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
15
+ dayNamesMin: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
16
+ weekHeader: 'Tu',
17
+ dateFormat: 'dd/mm/yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: false,
21
+ yearSuffix: ''};
22
+ $.datepicker.setDefaults($.datepicker.regional['vi']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-zh-CN.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Chinese initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Cloudream (cloudream@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['zh-CN'] = {
5
+ closeText: '关闭',
6
+ prevText: '&#x3c;上月',
7
+ nextText: '下月&#x3e;',
8
+ currentText: '今天',
9
+ monthNames: ['一月','二月','三月','四月','五月','六月',
10
+ '七月','八月','九月','十月','十一月','十二月'],
11
+ monthNamesShort: ['一','二','三','四','五','六',
12
+ '七','八','九','十','十一','十二'],
13
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
14
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
15
+ dayNamesMin: ['日','一','二','三','四','五','六'],
16
+ weekHeader: '周',
17
+ dateFormat: 'yy-mm-dd',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: true,
21
+ yearSuffix: '年'};
22
+ $.datepicker.setDefaults($.datepicker.regional['zh-CN']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-zh-HK.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Chinese initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by SCCY (samuelcychan@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['zh-HK'] = {
5
+ closeText: '關閉',
6
+ prevText: '&#x3c;上月',
7
+ nextText: '下月&#x3e;',
8
+ currentText: '今天',
9
+ monthNames: ['一月','二月','三月','四月','五月','六月',
10
+ '七月','八月','九月','十月','十一月','十二月'],
11
+ monthNamesShort: ['一','二','三','四','五','六',
12
+ '七','八','九','十','十一','十二'],
13
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
14
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
15
+ dayNamesMin: ['日','一','二','三','四','五','六'],
16
+ weekHeader: '周',
17
+ dateFormat: 'dd-mm-yy',
18
+ firstDay: 0,
19
+ isRTL: false,
20
+ showMonthAfterYear: true,
21
+ yearSuffix: '年'};
22
+ $.datepicker.setDefaults($.datepicker.regional['zh-HK']);
23
+ });
includes/js/i18n/jquery.ui.datepicker-zh-TW.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Chinese initialisation for the jQuery UI date picker plugin. */
2
+ /* Written by Ressol (ressol@gmail.com). */
3
+ jQuery(function($){
4
+ $.datepicker.regional['zh-TW'] = {
5
+ closeText: '關閉',
6
+ prevText: '&#x3c;上月',
7
+ nextText: '下月&#x3e;',
8
+ currentText: '今天',
9
+ monthNames: ['一月','二月','三月','四月','五月','六月',
10
+ '七月','八月','九月','十月','十一月','十二月'],
11
+ monthNamesShort: ['一','二','三','四','五','六',
12
+ '七','八','九','十','十一','十二'],
13
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
14
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
15
+ dayNamesMin: ['日','一','二','三','四','五','六'],
16
+ weekHeader: '周',
17
+ dateFormat: 'yy/mm/dd',
18
+ firstDay: 1,
19
+ isRTL: false,
20
+ showMonthAfterYear: true,
21
+ yearSuffix: '年'};
22
+ $.datepicker.setDefaults($.datepicker.regional['zh-TW']);
23
+ });
includes/js/taxonomies-admin.js CHANGED
File without changes
includes/langs/events-manager-ar.mo CHANGED
File without changes
includes/langs/events-manager-ar.po CHANGED
File without changes
includes/langs/events-manager-ca.mo CHANGED
File without changes
includes/langs/events-manager-ca.po CHANGED
File without changes
includes/langs/events-manager-cs_CZ.mo CHANGED
File without changes
includes/langs/events-manager-cs_CZ.po CHANGED
File without changes
includes/langs/events-manager-da_DK.mo CHANGED
File without changes
includes/langs/events-manager-da_DK.po CHANGED
File without changes
includes/langs/events-manager-de_DE.mo CHANGED
File without changes
includes/langs/events-manager-de_DE.po CHANGED
File without changes
includes/langs/events-manager-el.mo CHANGED
File without changes
includes/langs/events-manager-el.po CHANGED
File without changes
includes/langs/events-manager-en_AU.mo CHANGED
File without changes
includes/langs/events-manager-en_AU.po CHANGED
File without changes
includes/langs/events-manager-en_CA.mo CHANGED
File without changes
includes/langs/events-manager-en_CA.po CHANGED
File without changes
includes/langs/events-manager-en_GB.mo CHANGED
File without changes
includes/langs/events-manager-en_GB.po CHANGED
File without changes
includes/langs/events-manager-es_ES.mo CHANGED
File without changes
includes/langs/events-manager-es_ES.po CHANGED
File without changes
includes/langs/events-manager-et.mo CHANGED
File without changes
includes/langs/events-manager-et.po CHANGED
File without changes
includes/langs/events-manager-fa_IR.mo CHANGED
File without changes
includes/langs/events-manager-fa_IR.po CHANGED
File without changes
includes/langs/events-manager-fi.mo CHANGED
File without changes
includes/langs/events-manager-fi.po CHANGED
File without changes
includes/langs/events-manager-fr_FR.mo CHANGED
File without changes
includes/langs/events-manager-fr_FR.po CHANGED
File without changes
includes/langs/events-manager-he_IL.mo CHANGED
File without changes
includes/langs/events-manager-he_IL.po CHANGED
File without changes
includes/langs/events-manager-hu_HU.mo CHANGED
File without changes
includes/langs/events-manager-hu_HU.po CHANGED
File without changes
includes/langs/events-manager-it_IT.mo CHANGED
File without changes
includes/langs/events-manager-it_IT.po CHANGED
File without changes
includes/langs/events-manager-ja.mo CHANGED
File without changes
includes/langs/events-manager-ja.po CHANGED
File without changes
includes/langs/events-manager-nb_NO.mo CHANGED
File without changes
includes/langs/events-manager-nb_NO.po CHANGED
File without changes
includes/langs/events-manager-nl_NL.mo CHANGED
File without changes
includes/langs/events-manager-nl_NL.po CHANGED
File without changes
includes/langs/events-manager-no_NO.mo CHANGED
File without changes
includes/langs/events-manager-no_NO.po CHANGED
File without changes
includes/langs/events-manager-pl_PL.mo CHANGED
File without changes
includes/langs/events-manager-pl_PL.po CHANGED
File without changes
includes/langs/events-manager-pt_BR.mo CHANGED
File without changes
includes/langs/events-manager-pt_BR.po CHANGED
File without changes
includes/langs/events-manager-pt_PT.mo CHANGED
File without changes
includes/langs/events-manager-pt_PT.po CHANGED
File without changes
includes/langs/events-manager-ru_RU.mo CHANGED
File without changes
includes/langs/events-manager-ru_RU.po CHANGED
File without changes
includes/langs/events-manager-sk_SK.mo CHANGED
File without changes
includes/langs/events-manager-sk_SK.po CHANGED
File without changes
includes/langs/events-manager-sl_SI.mo CHANGED
File without changes
includes/langs/events-manager-sl_SI.po CHANGED
File without changes
includes/langs/events-manager-sv_SE.mo CHANGED
File without changes
includes/langs/events-manager-sv_SE.po CHANGED
File without changes
includes/langs/events-manager-tr_TR.mo CHANGED
File without changes
includes/langs/events-manager-tr_TR.po CHANGED
File without changes
includes/langs/events-manager-zh_CN.mo CHANGED
File without changes
includes/langs/events-manager-zh_CN.po CHANGED
File without changes
includes/langs/events-manager-zh_TW.mo CHANGED
File without changes
includes/langs/events-manager-zh_TW.po CHANGED
File without changes
includes/langs/events-manager.pot CHANGED
File without changes
includes/sample-placeholders/booking-email.html CHANGED
File without changes
includes/sample-placeholders/event-list-default.html CHANGED
File without changes
includes/sample-placeholders/event-single-default.html CHANGED
File without changes
includes/sample-placeholders/event-single.html CHANGED
File without changes
includes/sample-placeholders/location-single-default.html CHANGED
File without changes
multilingual/em-ml-admin.php CHANGED
@@ -8,6 +8,14 @@ class EM_ML_Admin{
8
  if( !defined('EM_SETTINGS_TABS') && count(EM_ML::$langs) > 3 ) define('EM_SETTINGS_TABS',true);
9
  }
10
 
 
 
 
 
 
 
 
 
11
  public static function meta_boxes(){
12
  global $EM_Event, $EM_Location;
13
  //decide if it's a master event, if not then hide the meta boxes
8
  if( !defined('EM_SETTINGS_TABS') && count(EM_ML::$langs) > 3 ) define('EM_SETTINGS_TABS',true);
9
  }
10
 
11
+ /**
12
+ * Returns array of settings page names used in $_REQUEST['page'] that must always be served in the original language of the blog
13
+ * @return array
14
+ */
15
+ public static function settings_pages(){
16
+ return apply_filters('em_ml_admin_settings_pages', array('events-manager-options'));
17
+ }
18
+
19
  public static function meta_boxes(){
20
  global $EM_Event, $EM_Location;
21
  //decide if it's a master event, if not then hide the meta boxes
multilingual/em-ml-bookings.php CHANGED
@@ -2,7 +2,7 @@
2
  class EM_ML_Bookings {
3
 
4
  public static function init(){
5
- add_action('em_booking_add','EM_ML_Bookings::em_booking_add', 1, 3);
6
  add_filter('em_event_get_bookings', 'EM_ML_Bookings::override_bookings',100,2);
7
  add_action('em_booking_form_footer','EM_ML_Bookings::em_booking_form_footer',10,1);
8
  add_action('em_booking_output_event', 'EM_ML_Bookings::em_booking_output_event',10,2);
@@ -12,11 +12,12 @@ class EM_ML_Bookings {
12
  /**
13
  * @param EM_Booking $EM_Booking
14
  */
15
- public static function em_booking_add( $EM_Event, $EM_Booking ){
16
- if( empty($EM_Booking->booking_id) && EM_ML::$current_language != EM_ML::$wplang ){
17
  $EM_Booking->booking_meta['lang'] = EM_ML::$current_language;
18
  }
19
  }
 
20
 
21
  public static function override_bookings($EM_Bookings, $EM_Event){
22
  if( !EM_ML::is_original($EM_Event) ){
2
  class EM_ML_Bookings {
3
 
4
  public static function init(){
5
+ add_action('em_booking_save_pre','EM_ML_Bookings::em_booking_save_pre', 1, 1);
6
  add_filter('em_event_get_bookings', 'EM_ML_Bookings::override_bookings',100,2);
7
  add_action('em_booking_form_footer','EM_ML_Bookings::em_booking_form_footer',10,1);
8
  add_action('em_booking_output_event', 'EM_ML_Bookings::em_booking_output_event',10,2);
12
  /**
13
  * @param EM_Booking $EM_Booking
14
  */
15
+ public static function em_booking_save_pre( $EM_Booking ){
16
+ if( empty($EM_Booking->booking_id) ){
17
  $EM_Booking->booking_meta['lang'] = EM_ML::$current_language;
18
  }
19
  }
20
+ public static function em_booking_add( $EM_Event, $EM_Booking ){ em_booking_save_pre($EM_Booking); }
21
 
22
  public static function override_bookings($EM_Bookings, $EM_Event){
23
  if( !EM_ML::is_original($EM_Event) ){
multilingual/em-ml-io.php CHANGED
@@ -78,11 +78,9 @@ class EM_ML_IO {
78
  $EM_Event->event_all_day = $event->event_all_day ;
79
  $EM_Event->event_start_time = $event->event_start_time ;
80
  $EM_Event->event_end_time = $event->event_end_time ;
81
- $EM_Event->start = $event->start ;
82
- $EM_Event->end = $event->end ;
83
- $EM_Event->event_rsvp_date = $event->event_rsvp_date ;
84
 
85
  $EM_Event->event_rsvp = $event->event_rsvp ;
 
86
  $EM_Event->event_rsvp_time = $event->event_rsvp_time ;
87
 
88
  $EM_Event->blog_id = $event->blog_id ;
78
  $EM_Event->event_all_day = $event->event_all_day ;
79
  $EM_Event->event_start_time = $event->event_start_time ;
80
  $EM_Event->event_end_time = $event->event_end_time ;
 
 
 
81
 
82
  $EM_Event->event_rsvp = $event->event_rsvp ;
83
+ $EM_Event->event_rsvp_date = $event->event_rsvp_date ;
84
  $EM_Event->event_rsvp_time = $event->event_rsvp_time ;
85
 
86
  $EM_Event->blog_id = $event->blog_id ;
multilingual/em-ml-options.php CHANGED
@@ -179,11 +179,9 @@ class EM_ML_Options {
179
  //When in the EM settings page translatable values should be shown in the currently active language
180
  if( is_admin() && !empty($_REQUEST['page']) && $_REQUEST['page'] == 'events-manager-options' ) return;
181
  //add a hook for all trnalsateable values
182
- if( EM_ML::$current_language != EM_ML::$wplang ){
183
- foreach( self::$translatable_options as $option ){
184
- add_filter('pre_option_'.$option, array(&$this, 'pre_option_'.$option), 1,1);
185
- }
186
- }
187
  //Switch EM page IDs to translated versions if they exist, so e.g. the events page in another language grabs the right translated page format if available
188
  add_filter('option_dbem_events_page','EM_ML_Options::get_translated_page');
189
  add_filter('option_dbem_locations_page','EM_ML_Options::get_translated_page');
@@ -203,8 +201,8 @@ class EM_ML_Options {
203
  * @param mixed $value Supplied filter value.
204
  * @return mixed Returns either translated data or the supplied value.
205
  */
206
- public function __call($filter_name, $value){
207
- if( strstr($filter_name, 'pre_option_') !== false ){
208
  //we're calling an option to be overridden by the default language
209
  $option_name = str_replace('pre_option_','',$filter_name);
210
  //don't use EM_ML::get_option as it creates an endless loop for options without a translation
179
  //When in the EM settings page translatable values should be shown in the currently active language
180
  if( is_admin() && !empty($_REQUEST['page']) && $_REQUEST['page'] == 'events-manager-options' ) return;
181
  //add a hook for all trnalsateable values
182
+ foreach( self::$translatable_options as $option ){
183
+ add_filter('pre_option_'.$option, array(&$this, 'pre_option_'.$option), 1,1);
184
+ }
 
 
185
  //Switch EM page IDs to translated versions if they exist, so e.g. the events page in another language grabs the right translated page format if available
186
  add_filter('option_dbem_events_page','EM_ML_Options::get_translated_page');
187
  add_filter('option_dbem_locations_page','EM_ML_Options::get_translated_page');
201
  * @param mixed $value Supplied filter value.
202
  * @return mixed Returns either translated data or the supplied value.
203
  */
204
+ public function __call($filter_name, $value){
205
+ if( EM_ML::$current_language != EM_ML::$wplang && strstr($filter_name, 'pre_option_') !== false ){
206
  //we're calling an option to be overridden by the default language
207
  $option_name = str_replace('pre_option_','',$filter_name);
208
  //don't use EM_ML::get_option as it creates an endless loop for options without a translation
multilingual/em-ml-placeholders.php CHANGED
File without changes
multilingual/em-ml-search.php CHANGED
File without changes
multilingual/em-ml.php CHANGED
@@ -19,6 +19,11 @@ class EM_ML{
19
  * @var string The currently active language of this site, meaning the language being displayed to the user. Example: 'en_US' for American English.
20
  */
21
  static public $current_language;
 
 
 
 
 
22
  /**
23
  * @var boolean Flag for whether EM is multilingual ready, false by default, set after init() has been executed first time.
24
  */
@@ -77,6 +82,29 @@ class EM_ML{
77
  public static function get_langs(){
78
  return self::$langs;
79
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
  /**
82
  * Shortcut for EM_ML_Options::get_option. Gets translated option.
19
  * @var string The currently active language of this site, meaning the language being displayed to the user. Example: 'en_US' for American English.
20
  */
21
  static public $current_language;
22
+ /**
23
+ * If switching languages temporarly, original current language stored here, null if we haven't switched.
24
+ * @var string
25
+ */
26
+ static public $current_language_restore;
27
  /**
28
  * @var boolean Flag for whether EM is multilingual ready, false by default, set after init() has been executed first time.
29
  */
82
  public static function get_langs(){
83
  return self::$langs;
84
  }
85
+
86
+ /**
87
+ * Switch to a language during runtime, useful if looping languages and doing things like getting options which are switched according to current language.
88
+ * @param string $lang
89
+ */
90
+ public static function switch_to_lang($lang){
91
+ if( empty(self::$current_language_restore) ) self::$current_language_restore = self::$current_language;
92
+ self::$current_language = $lang;
93
+ }
94
+
95
+ /**
96
+ * Restore the original current language we are loading this specific page in. Returns true if switched correctly, false if not.
97
+ * @param string $lang
98
+ * @return boolean
99
+ */
100
+ public static function restore_current_lang(){
101
+ if( !empty(self::$current_language_restore) ){
102
+ self::$current_language = self::$current_language_restore;
103
+ self::$current_language_restore = null;
104
+ return true;
105
+ }
106
+ return false;
107
+ }
108
 
109
  /**
110
  * Shortcut for EM_ML_Options::get_option. Gets translated option.
plugins/wp-seo.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ function em_wpseo_opengraph_desc( $desc ){
3
+ global $post;
4
+ return '123';
5
+ $edit_events_page_id = get_option( 'dbem_edit_events_page' );
6
+ $edit_locations_page_id = get_option( 'dbem_edit_locations_page' );
7
+ if( ($post->ID == $edit_events_page_id && $edit_events_page_id != 0) || ($post->ID == $edit_locations_page_id && $edit_locations_page_id != 0) ){
8
+ return '';
9
+ }
10
+ return $desc;
11
+ }
12
+ add_filter('wpseo_opengraph_desc', 'em_wpseo_opengraph_desc', 10000000);
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: bookings, calendar, tickets, events, buddypress, event management, google
5
  Text Domain: events-manager
6
  Requires at least: 3.5
7
  Tested up to: 4.9
8
- Stable tag: 5.8.1.2
9
 
10
  Fully featured event registration management including recurring events, locations management, calendar, Google map integration, booking management
11
 
@@ -99,6 +99,36 @@ See our [FAQ](http://wp-events-plugin.com/documentation/faq/) page, which is upd
99
  6. Manage attendees with various booking reports
100
 
101
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  = 5.8.1.3 =
103
  * fixed escaping error in bookings admin table introduced in 5.8.1.3
104
 
@@ -145,7 +175,7 @@ See our [FAQ](http://wp-events-plugin.com/documentation/faq/) page, which is upd
145
  * fixed potential incompatibilities with other plugins using wp_query_reset() on category pages, preventing our page formats from showing
146
  * fixed taxonomy archive pages returning zero results if taxonomy formatting is disabled and events are excluded from searches (WP Bug workaround)
147
  * fixed inconsistent line ending causing warnings with PHP compatibility checker
148
- * unified Tag and Category class functions into sets of parent class functionn
149
  * fixed PHP fatal error with BP when disabling notifications
150
  * fixed calendar day links being incorrect if another plugin adds querystring params to permalinks
151
  * added groupby, groupby_orderby and groupby_order arguments allowing grouping in search results for events and locations
5
  Text Domain: events-manager
6
  Requires at least: 3.5
7
  Tested up to: 4.9
8
+ Stable tag: 5.9
9
 
10
  Fully featured event registration management including recurring events, locations management, calendar, Google map integration, booking management
11
 
99
  6. Manage attendees with various booking reports
100
 
101
  == Changelog ==
102
+
103
+ = 5.9 =
104
+ * fixes applied to 5.8.1.2 merged into dev version
105
+ * added timezone support
106
+ * added new admin notice interface objects
107
+ * added new EM_Options option storage class
108
+ * fixed some PHP strict warnings regarding parent/child class method signatures
109
+ * fixed taxonomy pagination issues in AJAX (affecting tags specifically)
110
+ * fixed shortcode not getting parsed properly due to fix in 5.8.1.1 attempting to parse shortcode with supplied formats
111
+ * fixed non-standard YYYY-M-D date formats not being accepted in scope arguments
112
+ * improved multisite blog update interface
113
+ * added modular update logic to admin pages for future features
114
+ * further hardening against XSS strings
115
+ * fixed non-standard YYYY-M-D date formats not being accepted in scope arguments
116
+ * fixed duplicate slug issues when duplicating events
117
+ * removed all references of create_function for php 7.2 compatibility
118
+ * fixed documented 'postcode' search attribute not filtering results by that value
119
+ * fixed event duplication not copying other plugin meta data, such as ACF
120
+ * fixed EM_Bookings::get() producing SQL error if passing an array of booking IDs
121
+ * added em_event_post_scope_meta_query filter for admin-side custom scopes
122
+ * fixed bug where blank start/end times of tickets and booking cut-offs default to 12AM istead of event start time
123
+ * fixed preview mode not reflecting new event description
124
+ * fixed broken ical permalinks for individual subcategories
125
+ * changed recurrence warning strips from green to orange/blue at top of admin pages
126
+ * added 'ticket total' column to bookings export and split 'ticket price' from 'total' booking price when exporting split by ticket type
127
+ * fixed issues with caching not getting updated other plugins data such as ACF and possibly others
128
+ * fixed issue where logged out user didn't see login feedback message on booking form under certain setting combinations
129
+ * added EM_ML::restore_current_lang and EM_ML::switch_to_lang functions
130
+ * fixed language detection of bookings not being done early enough
131
+
132
  = 5.8.1.3 =
133
  * fixed escaping error in bookings admin table introduced in 5.8.1.3
134
 
175
  * fixed potential incompatibilities with other plugins using wp_query_reset() on category pages, preventing our page formats from showing
176
  * fixed taxonomy archive pages returning zero results if taxonomy formatting is disabled and events are excluded from searches (WP Bug workaround)
177
  * fixed inconsistent line ending causing warnings with PHP compatibility checker
178
+ * unified Tag and Category class functions into sets of parent class functions
179
  * fixed PHP fatal error with BP when disabling notifications
180
  * fixed calendar day links being incorrect if another plugin adds querystring params to permalinks
181
  * added groupby, groupby_orderby and groupby_order arguments allowing grouping in search results for events and locations
screenshot-1.png CHANGED
File without changes
screenshot-2.png CHANGED
File without changes
screenshot-3.png CHANGED
File without changes
screenshot-4.png CHANGED
File without changes
screenshot-5.png CHANGED
File without changes
screenshot-6.png CHANGED
File without changes
templates/buddypress/group-events.php CHANGED
@@ -54,22 +54,17 @@
54
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
55
  $rowno++;
56
  $class = ($rowno % 2) ? 'alternate' : '';
57
- // FIXME set to american
58
- $localised_start_date = date_i18n(get_option('dbem_date_format'), $EM_Event->start);
59
- $localised_end_date = date_i18n(get_option('dbem_date_format'), $EM_Event->end);
60
- $style = "";
61
- $today = date ( "Y-m-d" );
62
  $location_summary = "<b>" . $EM_Event->get_location()->name . "</b><br/>" . $EM_Event->get_location()->address . " - " . $EM_Event->get_location()->town;
63
 
64
- if ($EM_Event->start_date < $today && $EM_Event->end_date < $today){
65
  $class .= " past";
66
  }
67
  //Check pending approval events
68
  if ( !$EM_Event->status ){
69
  $class .= " pending";
70
- }
71
  ?>
72
- <tr class="event <?php echo trim($class); ?>" <?php echo $style; ?> id="event_<?php echo $EM_Event->event_id ?>">
73
  <?php /*
74
  <td>
75
  <input type='checkbox' class='row-selector' value='<?php echo $event->event_id; ?>' name='events[]' />
@@ -114,13 +109,9 @@
114
  </td>
115
 
116
  <td>
117
- <?php echo $localised_start_date; ?>
118
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
119
  <br />
120
- <?php
121
- //TODO Should 00:00 - 00:00 be treated as an all day event?
122
- echo substr ( $EM_Event->start_time, 0, 5 ) . " - " . substr ( $EM_Event->end_time, 0, 5 );
123
- ?>
124
  <br />
125
  <?php
126
  if ( $EM_Event->is_recurrence() && $EM_Event->can_manage('edit_events','edit_others_events') ) {
54
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
55
  $rowno++;
56
  $class = ($rowno % 2) ? 'alternate' : '';
 
 
 
 
 
57
  $location_summary = "<b>" . $EM_Event->get_location()->name . "</b><br/>" . $EM_Event->get_location()->address . " - " . $EM_Event->get_location()->town;
58
 
59
+ if( $EM_Event->start()->getTimestamp() < time() && $EM_Event->end()->getTimestamp() < time() ){
60
  $class .= " past";
61
  }
62
  //Check pending approval events
63
  if ( !$EM_Event->status ){
64
  $class .= " pending";
65
+ }
66
  ?>
67
+ <tr class="event <?php echo trim($class); ?>" id="event_<?php echo $EM_Event->event_id ?>">
68
  <?php /*
69
  <td>
70
  <input type='checkbox' class='row-selector' value='<?php echo $event->event_id; ?>' name='events[]' />
109
  </td>
110
 
111
  <td>
112
+ <?php echo $EM_Event->output_dates(); ?>
 
113
  <br />
114
+ <?php echo $EM_Event->output_times(); ?>
 
 
 
115
  <br />
116
  <?php
117
  if ( $EM_Event->is_recurrence() && $EM_Event->can_manage('edit_events','edit_others_events') ) {
templates/buddypress/my-bookings.php CHANGED
File without changes
templates/buddypress/my-events.php CHANGED
File without changes
templates/buddypress/my-group-events.php CHANGED
@@ -54,14 +54,9 @@
54
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
55
  $rowno++;
56
  $class = ($rowno % 2) ? 'alternate' : '';
57
- // FIXME set to american
58
- $localised_start_date = date_i18n(get_option('dbem_date_format'), $event->start);
59
- $localised_end_date = date_i18n(get_option('dbem_date_format'), $event->end);
60
- $style = "";
61
- $today = current_time('timestamp');
62
  $location_summary = "<b>" . $event->get_location()->name . "</b><br/>" . $event->get_location()->address . " - " . $event->get_location()->town;
63
 
64
- if ($event->start < $today && $event->end < $today){
65
  $class .= " past";
66
  }
67
  //Check pending approval events
@@ -69,7 +64,7 @@
69
  $class .= " pending";
70
  }
71
  ?>
72
- <tr class="event <?php echo trim($class); ?>" <?php echo $style; ?> id="event_<?php echo $event->event_id ?>">
73
  <?php /*
74
  <td>
75
  <input type='checkbox' class='row-selector' value='<?php echo $event->event_id; ?>' name='events[]' />
@@ -109,16 +104,9 @@
109
  </td>
110
 
111
  <td>
112
- <?php echo $localised_start_date; ?>
113
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
114
  <br />
115
- <?php
116
- if(!$event->event_all_day){
117
- echo date_i18n(get_option('time_format'), $event->start) . " - " . date_i18n(get_option('time_format'), $event->end);
118
- }else{
119
- echo get_option('dbem_event_all_day_message');
120
- }
121
- ?>
122
  </td>
123
  <td>
124
  <?php
54
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
55
  $rowno++;
56
  $class = ($rowno % 2) ? 'alternate' : '';
 
 
 
 
 
57
  $location_summary = "<b>" . $event->get_location()->name . "</b><br/>" . $event->get_location()->address . " - " . $event->get_location()->town;
58
 
59
+ if( $EM_Event->start()->getTimestamp() < time() && $EM_Event->end()->getTimestamp() < time() ){
60
  $class .= " past";
61
  }
62
  //Check pending approval events
64
  $class .= " pending";
65
  }
66
  ?>
67
+ <tr class="event <?php echo trim($class); ?>" id="event_<?php echo $event->event_id ?>">
68
  <?php /*
69
  <td>
70
  <input type='checkbox' class='row-selector' value='<?php echo $event->event_id; ?>' name='events[]' />
104
  </td>
105
 
106
  <td>
107
+ <?php echo $EM_Event->output_dates(); ?>
 
108
  <br />
109
+ <?php echo $EM_Event->output_times(); ?>
 
 
 
 
 
 
110
  </td>
111
  <td>
112
  <?php
templates/buddypress/my-locations.php CHANGED
File without changes
templates/formats/readme.txt CHANGED
File without changes
templates/forms/event-editor.php CHANGED
File without changes
templates/forms/event/bookings-ticket-form.php CHANGED
@@ -41,18 +41,18 @@ $col_count = absint($col_count); //now we know it's a number
41
  </label>
42
  <div class="ticket-dates-from-normal">
43
  <input type="text" name="ticket_start_pub" class="em-date-input-loc em-date-start" />
44
- <input type="hidden" name="em_tickets[<?php echo $col_count; ?>][ticket_start]" class="em-date-input ticket_start" value="<?php echo ( !empty($EM_Ticket->ticket_start) ) ? date("Y-m-d", $EM_Ticket->start_timestamp):''; ?>" />
45
  </div>
46
  <div class="ticket-dates-from-recurring">
47
  <input type="text" name="em_tickets[<?php echo $col_count; ?>][ticket_start_recurring_days]" size="3" value="<?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && is_numeric($EM_Ticket->ticket_meta['recurrences']['start_days'])) echo absint($EM_Ticket->ticket_meta['recurrences']['start_days']); ?>" />
48
  <?php esc_html_e('day(s)','events-manager'); ?>
49
  <select name="em_tickets[<?php echo $col_count; ?>][ticket_start_recurring_when]" class="ticket-dates-from-recurring-when">
50
- <option value="before" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['start_days']) && $EM_Ticket->ticket_meta['recurrences']['start_days'] <= 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('Before','events-manager'))); ?></option>
51
  <option value="after" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['start_days']) && $EM_Ticket->ticket_meta['recurrences']['start_days'] > 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('After','events-manager'))); ?></option>
52
  </select>
53
  </div>
54
  <?php echo esc_html_x('at', 'time','events-manager'); ?>
55
- <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="em_tickets[<?php echo $col_count; ?>][ticket_start_time]" value="<?php echo ( !empty($EM_Ticket->ticket_start) ) ? date( em_get_hour_format(), $EM_Ticket->start_timestamp):''; ?>" />
56
  </div>
57
  <div class="ticket-dates-to">
58
  <label title="<?php esc_attr_e('Add a start or end date (or both) to impose time constraints on ticket availability. Leave either blank for no upper/lower limit.','events-manager'); ?>">
@@ -60,18 +60,18 @@ $col_count = absint($col_count); //now we know it's a number
60
  </label>
61
  <div class="ticket-dates-to-normal">
62
  <input type="text" name="ticket_end_pub" class="em-date-input-loc em-date-end" />
63
- <input type="hidden" name="em_tickets[<?php echo $col_count; ?>][ticket_end]" class="em-date-input ticket_end" value="<?php echo ( !empty($EM_Ticket->ticket_end) ) ? date("Y-m-d", $EM_Ticket->end_timestamp):''; ?>" />
64
  </div>
65
  <div class="ticket-dates-to-recurring">
66
- <input type="text" name="em_tickets[<?php echo $col_count; ?>][ticket_end_recurring_days]" size="3" value="<?php if( !empty($EM_Ticket->ticket_meta['recurrences']['end_days']) ) echo absint($EM_Ticket->ticket_meta['recurrences']['end_days']); ?>" />
67
  <?php esc_html_e('day(s)','events-manager'); ?>
68
  <select name="em_tickets[<?php echo $col_count; ?>][ticket_end_recurring_when]" class="ticket-dates-to-recurring-when">
69
- <option value="before" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] <= 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('Before','events-manager'))); ?></option>
70
  <option value="after" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] > 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('After','events-manager'))); ?></option>
71
  </select>
72
  </div>
73
  <?php echo esc_html_x('at', 'time','events-manager'); ?>
74
- <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="em_tickets[<?php echo $col_count; ?>][ticket_end_time]" value="<?php echo ( !empty($EM_Ticket->ticket_end) ) ? date( em_get_hour_format(), $EM_Ticket->end_timestamp):''; ?>" />
75
  </div>
76
  </div>
77
  <?php if( !get_option('dbem_bookings_tickets_single') || count($EM_Ticket->get_event()->get_tickets()->tickets) > 1 ): ?>
41
  </label>
42
  <div class="ticket-dates-from-normal">
43
  <input type="text" name="ticket_start_pub" class="em-date-input-loc em-date-start" />
44
+ <input type="hidden" name="em_tickets[<?php echo $col_count; ?>][ticket_start]" class="em-date-input ticket_start" value="<?php echo ( !empty($EM_Ticket->ticket_start) ) ? $EM_Ticket->start()->format("Y-m-d"):''; ?>" />
45
  </div>
46
  <div class="ticket-dates-from-recurring">
47
  <input type="text" name="em_tickets[<?php echo $col_count; ?>][ticket_start_recurring_days]" size="3" value="<?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && is_numeric($EM_Ticket->ticket_meta['recurrences']['start_days'])) echo absint($EM_Ticket->ticket_meta['recurrences']['start_days']); ?>" />
48
  <?php esc_html_e('day(s)','events-manager'); ?>
49
  <select name="em_tickets[<?php echo $col_count; ?>][ticket_start_recurring_when]" class="ticket-dates-from-recurring-when">
50
+ <option value="before" <?php if( isset($EM_Ticket->ticket_meta['recurrences']['start_days']) && $EM_Ticket->ticket_meta['recurrences']['start_days'] <= 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('Before','events-manager'))); ?></option>
51
  <option value="after" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['start_days']) && $EM_Ticket->ticket_meta['recurrences']['start_days'] > 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('After','events-manager'))); ?></option>
52
  </select>
53
  </div>
54
  <?php echo esc_html_x('at', 'time','events-manager'); ?>
55
+ <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="em_tickets[<?php echo $col_count; ?>][ticket_start_time]" value="<?php echo ( !empty($EM_Ticket->ticket_start) ) ? $EM_Ticket->start()->format( em_get_hour_format() ):''; ?>" />
56
  </div>
57
  <div class="ticket-dates-to">
58
  <label title="<?php esc_attr_e('Add a start or end date (or both) to impose time constraints on ticket availability. Leave either blank for no upper/lower limit.','events-manager'); ?>">
60
  </label>
61
  <div class="ticket-dates-to-normal">
62
  <input type="text" name="ticket_end_pub" class="em-date-input-loc em-date-end" />
63
+ <input type="hidden" name="em_tickets[<?php echo $col_count; ?>][ticket_end]" class="em-date-input ticket_end" value="<?php echo ( !empty($EM_Ticket->ticket_end) ) ? $EM_Ticket->end()->format("Y-m-d"):''; ?>" />
64
  </div>
65
  <div class="ticket-dates-to-recurring">
66
+ <input type="text" name="em_tickets[<?php echo $col_count; ?>][ticket_end_recurring_days]" size="3" value="<?php if( isset($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] !== false ) echo absint($EM_Ticket->ticket_meta['recurrences']['end_days']); ?>" />
67
  <?php esc_html_e('day(s)','events-manager'); ?>
68
  <select name="em_tickets[<?php echo $col_count; ?>][ticket_end_recurring_when]" class="ticket-dates-to-recurring-when">
69
+ <option value="before" <?php if( isset($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] <= 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('Before','events-manager'))); ?></option>
70
  <option value="after" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] > 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('After','events-manager'))); ?></option>
71
  </select>
72
  </div>
73
  <?php echo esc_html_x('at', 'time','events-manager'); ?>
74
+ <input id="end-time" class="em-time-input em-time-end ticket-times-to-normal" type="text" size="8" maxlength="8" name="em_tickets[<?php echo $col_count; ?>][ticket_end_time]" value="<?php echo ( !empty($EM_Ticket->ticket_end) ) ? $EM_Ticket->end()->format( em_get_hour_format() ):''; ?>" />
75
  </div>
76
  </div>
77
  <?php if( !get_option('dbem_bookings_tickets_single') || count($EM_Ticket->get_event()->get_tickets()->tickets) > 1 ): ?>
templates/forms/event/bookings.php CHANGED
@@ -105,15 +105,15 @@ $reschedule_warnings = !empty($EM_Event->event_id) && $EM_Event->is_recurring()
105
  <span class="ticket_max"><?php echo ( !empty($EM_Ticket->ticket_max) ) ? esc_html($EM_Ticket->ticket_max):'-'; ?></span>
106
  </td>
107
  <td class="ticket-time">
108
- <span class="ticket_start ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? date(get_option('dbem_date_format'), $EM_Ticket->start_timestamp):''; ?></span>
109
  <span class="ticket_start_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['start_days']; ?></span>
110
  <span class="ticket_start_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['start_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span>
111
- <span class="ticket_start_time"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? date( em_get_hour_format(), $EM_Ticket->start_timestamp):''; ?></span>
112
  <br />
113
- <span class="ticket_end ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? date(get_option('dbem_date_format'), $EM_Ticket->end_timestamp):''; ?></span>
114
  <span class="ticket_end_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['end_days']; ?></span>
115
  <span class="ticket_end_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['end_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span>
116
- <span class="ticket_end_time"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? date( em_get_hour_format(), $EM_Ticket->end_timestamp):''; ?></span>
117
  </td>
118
  <td class="ticket-qty">
119
  <span class="ticket_available_spaces"><?php echo $EM_Ticket->get_available_spaces(); ?></span>/
@@ -185,7 +185,7 @@ $reschedule_warnings = !empty($EM_Event->event_id) && $EM_Event->is_recurring()
185
  </select>
186
  <?php _e('at','events-manager'); ?>
187
  </span>
188
- <input type="text" name="event_rsvp_time" class="em-time-input" maxlength="8" size="8" value="<?php echo date( em_get_hour_format(), $EM_Event->rsvp_end ); ?>" />
189
  <br />
190
  <em><?php esc_html_e('This is the definite date after which bookings will be closed for this event, regardless of individual ticket settings above. Default value will be the event start date.','events-manager'); ?></em>
191
  </p>
105
  <span class="ticket_max"><?php echo ( !empty($EM_Ticket->ticket_max) ) ? esc_html($EM_Ticket->ticket_max):'-'; ?></span>
106
  </td>
107
  <td class="ticket-time">
108
+ <span class="ticket_start ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? $EM_Ticket->start()->format(get_option('dbem_date_format')):''; ?></span>
109
  <span class="ticket_start_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['start_days']; ?></span>
110
  <span class="ticket_start_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['start_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span>
111
+ <span class="ticket_start_time"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? $EM_Ticket->start()->format( em_get_hour_format() ):''; ?></span>
112
  <br />
113
+ <span class="ticket_end ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? $EM_Ticket->end()->format(get_option('dbem_date_format')):''; ?></span>
114
  <span class="ticket_end_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['end_days']; ?></span>
115
  <span class="ticket_end_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['end_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span>
116
+ <span class="ticket_end_time"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? $EM_Ticket->end()->format( em_get_hour_format() ):''; ?></span>
117
  </td>
118
  <td class="ticket-qty">
119
  <span class="ticket_available_spaces"><?php echo $EM_Ticket->get_available_spaces(); ?></span>/
185
  </select>
186
  <?php _e('at','events-manager'); ?>
187
  </span>
188
+ <input type="text" name="event_rsvp_time" class="em-time-input" maxlength="8" size="8" value="<?php echo $EM_Event->rsvp_end()->format(em_get_hour_format()); ?>" />
189
  <br />
190
  <em><?php esc_html_e('This is the definite date after which bookings will be closed for this event, regardless of individual ticket settings above. Default value will be the event start date.','events-manager'); ?></em>
191
  </p>
templates/forms/event/recurring-when.php CHANGED
@@ -8,11 +8,19 @@ $classes = array();
8
  <div id="em-form-recurrence" class="event-form-recurrence event-form-when">
9
  <p class="em-time-range">
10
  <?php _e('Events start from','events-manager'); ?>
11
- <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_format, $EM_Event->start ); ?>" />
12
  <?php _e('to','events-manager'); ?>
13
- <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_format, $EM_Event->end ); ?>" />
14
  <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-allday" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> />
15
  </p>
 
 
 
 
 
 
 
 
16
  <div class="<?php if( !empty($EM_Event->event_id) ) echo 'em-recurrence-reschedule'; ?>">
17
  <?php if( !empty($EM_Event->event_id) ): ?>
18
  <div class="recurrence-reschedule-warning">
@@ -66,10 +74,10 @@ $classes = array();
66
  <p class="em-date-range">
67
  <?php _e ( 'Recurrences span from ', 'events-manager'); ?>
68
  <input class="em-date-start em-date-input-loc" type="text" />
69
- <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->event_start_date ?>" />
70
  <?php _e('to','events-manager'); ?>
71
  <input class="em-date-end em-date-input-loc" type="text" />
72
- <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->event_end_date ?>" />
73
  </p>
74
  <p class="em-duration-range">
75
  <?php echo sprintf(__('Each event spans %s day(s)','events-manager'), '<input id="end-days" type="text" size="8" maxlength="8" name="recurrence_days" value="'. $EM_Event->recurrence_days .'" />'); ?>
8
  <div id="em-form-recurrence" class="event-form-recurrence event-form-when">
9
  <p class="em-time-range">
10
  <?php _e('Events start from','events-manager'); ?>
11
+ <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo $EM_Event->start()->i18n($hours_format); ?>" />
12
  <?php _e('to','events-manager'); ?>
13
+ <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo $EM_Event->end()->i18n($hours_format); ?>" />
14
  <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-allday" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> />
15
  </p>
16
+ <?php if( get_option('dbem_timezone_enabled') ): ?>
17
+ <p class="em-timezone">
18
+ <label for="event-timezone"><?php esc_html_e('Timezone', 'events-manager'); ?></label>
19
+ <select id="event-timezone" name="event_timezone" aria-describedby="timezone-description">
20
+ <?php echo wp_timezone_choice( $EM_Event->get_timezone()->getName(), get_user_locale() ); ?>
21
+ </select>
22
+ </p>
23
+ <?php endif; ?>
24
  <div class="<?php if( !empty($EM_Event->event_id) ) echo 'em-recurrence-reschedule'; ?>">
25
  <?php if( !empty($EM_Event->event_id) ): ?>
26
  <div class="recurrence-reschedule-warning">
74
  <p class="em-date-range">
75
  <?php _e ( 'Recurrences span from ', 'events-manager'); ?>
76
  <input class="em-date-start em-date-input-loc" type="text" />
77
+ <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->start()->getDate(); ?>" />
78
  <?php _e('to','events-manager'); ?>
79
  <input class="em-date-end em-date-input-loc" type="text" />
80
+ <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->end()->getDate(); ?>" />
81
  </p>
82
  <p class="em-duration-range">
83
  <?php echo sprintf(__('Each event spans %s day(s)','events-manager'), '<input id="end-days" type="text" size="8" maxlength="8" name="recurrence_days" value="'. $EM_Event->recurrence_days .'" />'); ?>
templates/forms/event/when-with-recurring.php CHANGED
@@ -12,20 +12,28 @@ $admin_recurring = is_admin() && $EM_Event->is_recurring();
12
  <span class="em-recurring-text"><?php _e ( 'Recurrences span from ', 'events-manager'); ?></span>
13
  <span class="em-event-text"><?php _e ( 'From ', 'events-manager'); ?></span>
14
  <input class="em-date-start em-date-input-loc" type="text" />
15
- <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->event_start_date ?>" />
16
  <span class="em-recurring-text"><?php _e('to','events-manager'); ?></span>
17
  <span class="em-event-text"><?php _e('to','events-manager'); ?></span>
18
  <input class="em-date-end em-date-input-loc" type="text" />
19
- <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->event_end_date ?>" />
20
  </p>
21
  <p>
22
  <span class="em-recurring-text"><?php _e('Events start from','events-manager'); ?></span>
23
  <span class="em-event-text"><?php _e('Event starts at','events-manager'); ?></span>
24
- <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_format, $EM_Event->start ); ?>" />
25
  <?php _e('to','events-manager'); ?>
26
- <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_format, $EM_Event->end ); ?>" />
27
  <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-allday" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> />
28
  </p>
 
 
 
 
 
 
 
 
29
  <div class="em-recurring-text">
30
  <p>
31
  <?php _e ( 'This event repeats', 'events-manager'); ?>
12
  <span class="em-recurring-text"><?php _e ( 'Recurrences span from ', 'events-manager'); ?></span>
13
  <span class="em-event-text"><?php _e ( 'From ', 'events-manager'); ?></span>
14
  <input class="em-date-start em-date-input-loc" type="text" />
15
+ <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->start()->getDate(); ?>" />
16
  <span class="em-recurring-text"><?php _e('to','events-manager'); ?></span>
17
  <span class="em-event-text"><?php _e('to','events-manager'); ?></span>
18
  <input class="em-date-end em-date-input-loc" type="text" />
19
+ <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->end()->getDate(); ?>" />
20
  </p>
21
  <p>
22
  <span class="em-recurring-text"><?php _e('Events start from','events-manager'); ?></span>
23
  <span class="em-event-text"><?php _e('Event starts at','events-manager'); ?></span>
24
+ <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo $EM_Event->start()->i18n($hours_format); ?>" />
25
  <?php _e('to','events-manager'); ?>
26
+ <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo $EM_Event->end()->i18n($hours_format); ?>" />
27
  <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-allday" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> />
28
  </p>
29
+ <?php if( get_option('dbem_timezone_enabled') ): ?>
30
+ <p class="em-timezone">
31
+ <label for="event-timezone"><?php esc_html_e('Timezone', 'events-manager'); ?></label>
32
+ <select id="event-timezone" name="event_timezone" aria-describedby="timezone-description">
33
+ <?php echo wp_timezone_choice( $EM_Event->get_timezone()->getName(), get_user_locale() ); ?>
34
+ </select>
35
+ </p>
36
+ <?php endif; ?>
37
  <div class="em-recurring-text">
38
  <p>
39
  <?php _e ( 'This event repeats', 'events-manager'); ?>
templates/forms/event/when.php CHANGED
@@ -7,20 +7,28 @@ $required = apply_filters('em_required_html','<i>*</i>');
7
  <p class="em-date-range">
8
  <?php _e ( 'From ', 'events-manager'); ?>
9
  <input class="em-date-start em-date-input-loc" type="text" />
10
- <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->event_start_date ?>" />
11
  <?php _e('to','events-manager'); ?>
12
  <input class="em-date-end em-date-input-loc" type="text" />
13
- <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->event_end_date ?>" />
14
  </p>
15
  <p class="em-time-range">
16
  <span class="em-event-text"><?php _e('Event starts at','events-manager'); ?></span>
17
- <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_format, $EM_Event->start ); ?>" />
18
  <?php _e('to','events-manager'); ?>
19
- <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_format, $EM_Event->end ); ?>" />
20
  <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-all-day" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> />
21
  </p>
 
 
 
 
 
 
 
 
22
  <span id='event-date-explanation'>
23
- <?php _e( 'This event spans every day between the beginning and end date, with start/end times applying to each day.', 'events-manager'); ?>
24
  </span>
25
  </div>
26
  <?php if( false && get_option('dbem_recurrence_enabled') && $EM_Event->is_recurrence() ) : //in future, we could enable this and then offer a detach option alongside, which resets the recurrence id and removes the attachment to the recurrence set ?>
7
  <p class="em-date-range">
8
  <?php _e ( 'From ', 'events-manager'); ?>
9
  <input class="em-date-start em-date-input-loc" type="text" />
10
+ <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->start()->getDate();; ?>" />
11
  <?php _e('to','events-manager'); ?>
12
  <input class="em-date-end em-date-input-loc" type="text" />
13
+ <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->end()->getDate();; ?>" />
14
  </p>
15
  <p class="em-time-range">
16
  <span class="em-event-text"><?php _e('Event starts at','events-manager'); ?></span>
17
+ <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo $EM_Event->start()->format($hours_format); ?>" />
18
  <?php _e('to','events-manager'); ?>
19
+ <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo $EM_Event->end()->format($hours_format); ?>" />
20
  <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-all-day" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> />
21
  </p>
22
+ <?php if( get_option('dbem_timezone_enabled') ): ?>
23
+ <p class="em-timezone">
24
+ <label for="event-timezone"><?php esc_html_e('Timezone', 'events-manager'); ?></label>
25
+ <select id="event-timezone" name="event_timezone" aria-describedby="timezone-description">
26
+ <?php echo wp_timezone_choice( $EM_Event->get_timezone()->getName(), get_user_locale() ); ?>
27
+ </select>
28
+ </p>
29
+ <?php endif; ?>
30
  <span id='event-date-explanation'>
31
+ <?php esc_html_e( 'This event spans every day between the beginning and end date, with start/end times applying to each day.', 'events-manager'); ?>
32
  </span>
33
  </div>
34
  <?php if( false && get_option('dbem_recurrence_enabled') && $EM_Event->is_recurrence() ) : //in future, we could enable this and then offer a detach option alongside, which resets the recurrence id and removes the attachment to the recurrence set ?>
templates/forms/location-editor.php CHANGED
File without changes
templates/forms/readme.txt CHANGED
File without changes
templates/forms/ticket-form.php CHANGED
File without changes
templates/forms/tickets-form.php CHANGED
File without changes
templates/placeholders/attendees.php CHANGED
File without changes
templates/placeholders/bookingbutton.php CHANGED
File without changes
templates/placeholders/bookingform.php CHANGED
@@ -87,7 +87,7 @@ if( !$is_open && !is_user_logged_in() && $EM_Event->get_bookings()->is_open(true
87
  <?php if( preg_match('/https?:\/\//',get_option('dbem_bookings_submit_button')) ): //Settings have an image url (we assume). Use it here as the button.?>
88
  <input type="image" src="<?php echo get_option('dbem_bookings_submit_button'); ?>" class="em-booking-submit" id="em-booking-submit" />
89
  <?php else: //Display normal submit button ?>
90
- <input type="submit" class="em-booking-submit" id="em-booking-submit" value="<?php echo esc_attr(get_option('dbem_bookings_submit_button')); ?>" />
91
  <?php endif; ?>
92
  </div>
93
  <?php do_action('em_booking_form_footer_after_buttons', $EM_Event); //do not delete ?>
87
  <?php if( preg_match('/https?:\/\//',get_option('dbem_bookings_submit_button')) ): //Settings have an image url (we assume). Use it here as the button.?>
88
  <input type="image" src="<?php echo get_option('dbem_bookings_submit_button'); ?>" class="em-booking-submit" id="em-booking-submit" />
89
  <?php else: //Display normal submit button ?>
90
+ <input type="submit" class="<?php if(is_admin()) echo 'button-primary '; ?>em-booking-submit" id="em-booking-submit" value="<?php echo esc_attr(get_option('dbem_bookings_submit_button')); ?>" />
91
  <?php endif; ?>
92
  </div>
93
  <?php do_action('em_booking_form_footer_after_buttons', $EM_Event); //do not delete ?>
templates/placeholders/categories.php CHANGED
File without changes
templates/placeholders/locationmap.php CHANGED
File without changes
templates/placeholders/readme.txt CHANGED
File without changes
templates/tables/events.php CHANGED
@@ -74,14 +74,9 @@
74
  /* @var $EM_Event EM_Event */
75
  $rowno++;
76
  $class = ($rowno % 2) ? 'alternate' : '';
77
- // FIXME set to american
78
- $localised_start_date = date_i18n(get_option('dbem_date_format'), $EM_Event->start);
79
- $localised_end_date = date_i18n(get_option('dbem_date_format'), $EM_Event->end);
80
- $style = "";
81
- $today = current_time('timestamp');
82
  $location_summary = "<b>" . esc_html($EM_Event->get_location()->location_name) . "</b><br/>" . esc_html($EM_Event->get_location()->location_address) . " - " . esc_html($EM_Event->get_location()->location_town);
83
 
84
- if ($EM_Event->start < $today && $EM_Event->end < $today){
85
  $class .= " past";
86
  }
87
  //Check pending approval events
@@ -89,7 +84,7 @@
89
  $class .= " pending";
90
  }
91
  ?>
92
- <tr class="event <?php echo trim($class); ?>" <?php echo $style; ?> id="event_<?php echo $EM_Event->event_id ?>">
93
  <?php /*
94
  <td>
95
  <input type='checkbox' class='row-selector' value='<?php echo $EM_Event->event_id; ?>' name='events[]' />
@@ -124,18 +119,10 @@
124
  <td>
125
  <?php echo $location_summary; ?>
126
  </td>
127
-
128
  <td>
129
- <?php echo $localised_start_date; ?>
130
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
131
  <br />
132
- <?php
133
- if(!$EM_Event->event_all_day){
134
- echo date_i18n(get_option('time_format'), $EM_Event->start) . " - " . date_i18n(get_option('time_format'), $EM_Event->end);
135
- }else{
136
- echo get_option('dbem_event_all_day_message');
137
- }
138
- ?>
139
  </td>
140
  <td>
141
  <?php
74
  /* @var $EM_Event EM_Event */
75
  $rowno++;
76
  $class = ($rowno % 2) ? 'alternate' : '';
 
 
 
 
 
77
  $location_summary = "<b>" . esc_html($EM_Event->get_location()->location_name) . "</b><br/>" . esc_html($EM_Event->get_location()->location_address) . " - " . esc_html($EM_Event->get_location()->location_town);
78
 
79
+ if( $EM_Event->start()->getTimestamp() < time() && $EM_Event->end()->getTimestamp() < time() ){
80
  $class .= " past";
81
  }
82
  //Check pending approval events
84
  $class .= " pending";
85
  }
86
  ?>
87
+ <tr class="event <?php echo trim($class); ?>" id="event_<?php echo $EM_Event->event_id ?>">
88
  <?php /*
89
  <td>
90
  <input type='checkbox' class='row-selector' value='<?php echo $EM_Event->event_id; ?>' name='events[]' />
119
  <td>
120
  <?php echo $location_summary; ?>
121
  </td>
 
122
  <td>
123
+ <?php echo $EM_Event->output_dates(); ?>
 
124
  <br />
125
+ <?php echo $EM_Event->output_times(); ?>
 
 
 
 
 
 
126
  </td>
127
  <td>
128
  <?php
templates/templates/calendar-day.php CHANGED
File without changes
templates/templates/calendar-full.php CHANGED
File without changes
templates/templates/calendar-small.php CHANGED
File without changes
templates/templates/categories-list.php CHANGED
File without changes
templates/templates/category-single.php CHANGED
File without changes
templates/templates/event-single.php CHANGED
File without changes
templates/templates/events-calendar.php CHANGED
File without changes
templates/templates/events-list.php CHANGED
File without changes
templates/templates/events-search.php CHANGED
File without changes
templates/templates/ical.php CHANGED
@@ -5,22 +5,36 @@ $description_format = str_replace ( ">", "&gt;", str_replace ( "<", "&lt;", get_
5
  $location_format = str_replace ( ">", "&gt;", str_replace ( "<", "&lt;", get_option ( 'dbem_ical_location_format' ) ) );
6
  $parsed_url = parse_url(get_bloginfo('url'));
7
  $site_domain = preg_replace('/^www./', '', $parsed_url['host']);
 
8
 
9
  //figure out limits
10
  $ical_limit = get_option('dbem_ical_limit');
11
  $page_limit = $ical_limit > 50 || !$ical_limit ? 50:$ical_limit; //set a limit of 50 to output at a time, unless overall limit is lower
12
  //get passed on $args and merge with defaults
13
  $args = !empty($args) ? $args:array(); /* @var $args array */
14
- $args = array_merge(array('limit'=>$page_limit, 'page'=>'1', 'owner'=>false, 'orderby'=>'event_start_date', 'scope' => get_option('dbem_ical_scope') ), $args);
15
  $args = apply_filters('em_calendar_template_args',$args);
16
  //get first round of events to show, we'll start adding more via the while loop
17
  $EM_Events = EM_Events::get( $args );
 
18
 
19
  //calendar header
20
- $output = "BEGIN:VCALENDAR
21
  VERSION:2.0
22
  PRODID:-//wp-events-plugin.com//".EM_VERSION."//EN";
23
- echo preg_replace("/([^\r])\n/", "$1\r\n", $output);
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  //loop through events
26
  $count = 0;
@@ -28,13 +42,37 @@ while ( count($EM_Events) > 0 ){
28
  foreach ( $EM_Events as $EM_Event ) {
29
  /* @var $EM_Event EM_Event */
30
  if( $ical_limit != 0 && $count > $ical_limit ) break; //we've reached our maximum
 
 
 
 
 
 
 
 
 
 
 
31
  //calculate the times along with timezone offsets
32
  if($EM_Event->event_all_day){
33
- $dateStart = ';VALUE=DATE:'.date('Ymd',$EM_Event->start); //all day
34
- $dateEnd = ';VALUE=DATE:'.date('Ymd',$EM_Event->end + 86400); //add one day
 
35
  }else{
36
- $dateStart = ':'.get_gmt_from_date(date('Y-m-d H:i:s', $EM_Event->start), 'Ymd\THis\Z');
37
- $dateEnd = ':'.get_gmt_from_date(date('Y-m-d H:i:s', $EM_Event->end), 'Ymd\THis\Z');
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
  if( !empty($EM_Event->event_date_modified) && $EM_Event->event_date_modified != '0000-00-00 00:00:00' ){
40
  $dateModified = get_gmt_from_date($EM_Event->event_date_modified, 'Ymd\THis\Z');
@@ -88,28 +126,23 @@ if( $description ){
88
  //add featured image if exists
89
  if( $image ){
90
  $image = wordwrap("ATTACH;FMTTYPE=image/jpeg:".esc_url_raw($image), 74, "\n ", true);
91
- $output .= "
92
- {$image}";
93
  }
94
  //add categories if there are any
95
  if( !empty($categories) ){
96
  $categories = wordwrap("CATEGORIES:".implode(',', $categories), 74, "\n ", true);
97
- $output .= "
98
- {$categories}";
99
  }
100
  //Location if there is one
101
  if( $location ){
102
- $output .= "
103
- {$location}";
104
  //geo coordinates if they exist
105
  if( $geo ){
106
- $output .= "
107
- {$geo}";
108
  }
109
  //create apple-compatible feature for locations
110
  if( !empty($apple_structured_location) ){
111
- $output .= "
112
- {$apple_structured_location}";
113
  }
114
  }
115
  //end the event
@@ -130,6 +163,62 @@ END:VEVENT";
130
  }
131
  }
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  //calendar footer
134
- $output = "\r\n"."END:VCALENDAR";
135
- echo preg_replace("/([^\r])\n/", "$1\r\n", $output);
5
  $location_format = str_replace ( ">", "&gt;", str_replace ( "<", "&lt;", get_option ( 'dbem_ical_location_format' ) ) );
6
  $parsed_url = parse_url(get_bloginfo('url'));
7
  $site_domain = preg_replace('/^www./', '', $parsed_url['host']);
8
+ $timezone_support = defined('EM_ICAL_TIMEZONE_SUPPORT') ? EM_ICAL_TIMEZONE_SUPPORT : true;
9
 
10
  //figure out limits
11
  $ical_limit = get_option('dbem_ical_limit');
12
  $page_limit = $ical_limit > 50 || !$ical_limit ? 50:$ical_limit; //set a limit of 50 to output at a time, unless overall limit is lower
13
  //get passed on $args and merge with defaults
14
  $args = !empty($args) ? $args:array(); /* @var $args array */
15
+ $args = array_merge(array('limit'=>$page_limit, 'page'=>'1', 'owner'=>false, 'orderby'=>'event_start_date,event_start_time', 'scope' => get_option('dbem_ical_scope') ), $args);
16
  $args = apply_filters('em_calendar_template_args',$args);
17
  //get first round of events to show, we'll start adding more via the while loop
18
  $EM_Events = EM_Events::get( $args );
19
+ $timezones = array();
20
 
21
  //calendar header
22
+ $output_header = "BEGIN:VCALENDAR
23
  VERSION:2.0
24
  PRODID:-//wp-events-plugin.com//".EM_VERSION."//EN";
25
+
26
+ //if timezone is supported, we output the blog timezone here
27
+ if( $timezone_support ){
28
+ //get default blog timezone and output only if we're not in UTC or with manual offsets
29
+ $blog_timezone = EM_DateTimeZone::create()->getName();
30
+ if( !preg_match('/^UTC/', $blog_timezone) ){
31
+ $output_header .= "
32
+ TZID:{$blog_timezone}
33
+ X-WR-TIMEZONE:{$blog_timezone}";
34
+ }
35
+ }
36
+
37
+ echo preg_replace("/([^\r])\n/", "$1\r\n", $output_header);
38
 
39
  //loop through events
40
  $count = 0;
42
  foreach ( $EM_Events as $EM_Event ) {
43
  /* @var $EM_Event EM_Event */
44
  if( $ical_limit != 0 && $count > $ical_limit ) break; //we've reached our maximum
45
+ //figure out the timezone of this event, or if it's an offset and add to list of timezones and date ranges to define in VTIMEZONE
46
+ $show_timezone = $timezone_support && !preg_match('/^UTC/', $EM_Event->get_timezone()->getName());
47
+ if( $show_timezone ){
48
+ $timezone = $EM_Event->start()->getTimezone()->getName();
49
+ if( empty($timezones[$timezone]) ){
50
+ $timezones[$timezone] = array( $EM_Event->start()->getTimestamp(), $EM_Event->end()->getTimestamp() );
51
+ }else{
52
+ if( $timezones[$timezone][0] > $EM_Event->start()->getTimestamp() ) $timezones[$timezone][0] = $EM_Event->start()->getTimestamp();
53
+ if( $timezones[$timezone][1] < $EM_Event->end()->getTimestamp() ) $timezones[$timezone][1] = $EM_Event->end()->getTimestamp();
54
+ }
55
+ }
56
  //calculate the times along with timezone offsets
57
  if($EM_Event->event_all_day){
58
+ //we get local time since we're representing a date not a time
59
+ $dateStart = ';VALUE=DATE:'.$EM_Event->start()->format('Ymd'); //all day
60
+ $dateEnd = ';VALUE=DATE:'.$EM_Event->end()->copy()->add('P1D')->format('Ymd'); //add one day
61
  }else{
62
+ //get date output with timezone and local time if timezone output is enabled, or UTC time if not and/or if offset is manual
63
+ if( $show_timezone ){
64
+ //show local time and define a timezone
65
+ $dateStart = ':'.$EM_Event->start()->format('Ymd\THis');
66
+ $dateEnd = ':'.$EM_Event->end()->format('Ymd\THis');
67
+ }else{
68
+ //create a UTC equivalent time for all events irrespective of timezone
69
+ $dateStart = ':'.$EM_Event->start(true)->format('Ymd\THis\Z');
70
+ $dateEnd = ':'.$EM_Event->end(true)->format('Ymd\THis\Z');
71
+ }
72
+ }
73
+ if( $show_timezone ){
74
+ $dateStart = ';TZID='.$timezone . $dateStart;
75
+ $dateEnd = ';TZID='.$timezone . $dateEnd;
76
  }
77
  if( !empty($EM_Event->event_date_modified) && $EM_Event->event_date_modified != '0000-00-00 00:00:00' ){
78
  $dateModified = get_gmt_from_date($EM_Event->event_date_modified, 'Ymd\THis\Z');
126
  //add featured image if exists
127
  if( $image ){
128
  $image = wordwrap("ATTACH;FMTTYPE=image/jpeg:".esc_url_raw($image), 74, "\n ", true);
129
+ $output .= "\r\n" . $image;
 
130
  }
131
  //add categories if there are any
132
  if( !empty($categories) ){
133
  $categories = wordwrap("CATEGORIES:".implode(',', $categories), 74, "\n ", true);
134
+ $output .= "\r\n" . $categories;
 
135
  }
136
  //Location if there is one
137
  if( $location ){
138
+ $output .= "\r\n" . $location;
 
139
  //geo coordinates if they exist
140
  if( $geo ){
141
+ $output .= "\r\n" . $geo;
 
142
  }
143
  //create apple-compatible feature for locations
144
  if( !empty($apple_structured_location) ){
145
+ $output .= "\r\n" . $apple_structured_location;
 
146
  }
147
  }
148
  //end the event
163
  }
164
  }
165
 
166
+ //Now we sort out timezones and add it to the top of the output
167
+ if( $timezone_support && !empty($timezones) ){
168
+ $vtimezones = array();
169
+ foreach( $timezones as $timezone => $timezone_range ){
170
+ $vtimezones[$timezone] = array();
171
+ $previous_offset = false;
172
+ //get the range of transitions, with a year's cushion so we can calculate the TZOFFSETFROM value
173
+ $EM_DateTimeZone = EM_DateTimeZone::create($timezone);
174
+ $timezone_transitions = $EM_DateTimeZone->getTransitions($timezone_range[0] - YEAR_IN_SECONDS, $timezone_range[1] + YEAR_IN_SECONDS);
175
+ do{
176
+ $current_transition = current($timezone_transitions);
177
+ $transition_key = key($timezone_transitions);
178
+ $next_transition = next($timezone_transitions);
179
+ //format the offset to a UTC-OFFSET
180
+ $current_offset_sign = $current_transition['offset'] < 0 ? '-' : '+';
181
+ $current_offset_hours = absint(floor($current_transition['offset'] / HOUR_IN_SECONDS));
182
+ $current_offset_minute_seconds = absint($current_transition['offset']) - $current_offset_hours*HOUR_IN_SECONDS;
183
+ $current_offset_minutes = $current_offset_minute_seconds == 0 ? 0 : absint($current_offset_minute_seconds / MINUTE_IN_SECONDS);
184
+ $current_transition['offset'] = $current_offset_sign . str_pad($current_offset_hours, 2, "0", STR_PAD_LEFT) . str_pad($current_offset_minutes, 2, "0", STR_PAD_LEFT);
185
+ //skip transitions before and after the event date range, assuming we have some in between
186
+ if( !empty($next_transition) && $next_transition['ts'] < $timezone_range[0] ){
187
+ //remember previous offset
188
+ $previous_offset = $current_transition['offset'];
189
+ continue;
190
+ }
191
+ if( $current_transition['ts'] > $timezone_range[1] ) break;
192
+ //modify the transition array directly and add it to vtimezones array
193
+ unset( $current_transition['time'] );
194
+ $current_transition['isdst'] = $current_transition['isdst'] ? 'DAYLIGHT':'STANDARD';
195
+ $EM_DateTime = new EM_DateTime($current_transition['ts'], $EM_DateTimeZone);
196
+ $current_transition['ts'] = $EM_DateTime->format('Ymd\THis');
197
+ $current_transition['offsetfrom'] = $previous_offset === false ? $current_transition['offset'] : $previous_offset;
198
+ $vtimezones[$timezone][] = $current_transition;
199
+ //remember previous offset
200
+ $previous_offset = $current_transition['offset'];
201
+ } while( $next_transition !== false );
202
+ }
203
+ foreach( $vtimezones as $timezone => $timezone_transitions ){
204
+ $output = "
205
+ BEGIN:VTIMEZONE
206
+ TZID:{$timezone}
207
+ X-LIC-LOCATION:{$timezone}";
208
+ foreach( $timezone_transitions as $transition ){
209
+ $output .= "
210
+ BEGIN:{$transition['isdst']}
211
+ DTSTART:{$transition['ts']}
212
+ TZOFFSETFROM:{$transition['offsetfrom']}
213
+ TZOFFSETTO:{$transition['offset']}
214
+ TZNAME:{$transition['abbr']}
215
+ END:{$transition['isdst']}";
216
+ }
217
+ $output .= "
218
+ END:VTIMEZONE";
219
+ echo preg_replace("/([^\r])\n/", "$1\r\n", $output);
220
+ }
221
+ }
222
+
223
  //calendar footer
224
+ echo "\r\n"."END:VCALENDAR";
 
templates/templates/location-single.php CHANGED
File without changes
templates/templates/locations-list.php CHANGED
File without changes
templates/templates/map-global.php CHANGED
File without changes
templates/templates/my-bookings.php CHANGED
@@ -56,7 +56,7 @@
56
  ?>
57
  <tr>
58
  <td><?php echo $EM_Event->output("#_EVENTLINK"); ?></td>
59
- <td><?php echo date_i18n( get_option('dbem_date_format'), $EM_Event->start ); ?></td>
60
  <td><?php echo $EM_Booking->get_spaces() ?></td>
61
  <td>
62
  <?php echo $EM_Booking->get_status(); ?>
56
  ?>
57
  <tr>
58
  <td><?php echo $EM_Event->output("#_EVENTLINK"); ?></td>
59
+ <td><?php echo $EM_Event->start()->i18n( get_option('dbem_date_format') ); ?></td>
60
  <td><?php echo $EM_Booking->get_spaces() ?></td>
61
  <td>
62
  <?php echo $EM_Booking->get_status(); ?>
templates/templates/readme.txt CHANGED
File without changes
templates/templates/rss.php CHANGED
@@ -14,7 +14,7 @@ echo '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
14
  <link><?php echo EM_URI; ?></link>
15
  <description><?php echo esc_html(get_option('dbem_rss_main_description')); ?></description>
16
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
17
- <pubDate><?php echo date('D, d M Y H:i:s +0000', get_option('em_last_modified', current_time('timestamp',true))); ?></pubDate>
18
  <atom:link href="<?php echo esc_attr(EM_RSS_URI); ?>" rel="self" type="application/rss+xml" />
19
  <?php
20
  $description_format = str_replace ( ">", "&gt;", str_replace ( "<", "&lt;", get_option ( 'dbem_rss_description_format' ) ) );
@@ -36,7 +36,7 @@ echo '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
36
  <title><?php echo $EM_Event->output( get_option('dbem_rss_title_format'), "rss" ); ?></title>
37
  <link><?php echo $event_url; ?></link>
38
  <guid><?php echo $event_url; ?></guid>
39
- <pubDate><?php echo get_gmt_from_date(date('Y-m-d H:i:s', $EM_Event->start), 'D, d M Y H:i:s +0000'); ?></pubDate>
40
  <description><![CDATA[<?php echo $description; ?>]]></description>
41
  </item>
42
  <?php
14
  <link><?php echo EM_URI; ?></link>
15
  <description><?php echo esc_html(get_option('dbem_rss_main_description')); ?></description>
16
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
17
+ <pubDate><?php echo date('D, d M Y H:i:s +0000', get_option('em_last_modified')); ?></pubDate>
18
  <atom:link href="<?php echo esc_attr(EM_RSS_URI); ?>" rel="self" type="application/rss+xml" />
19
  <?php
20
  $description_format = str_replace ( ">", "&gt;", str_replace ( "<", "&lt;", get_option ( 'dbem_rss_description_format' ) ) );
36
  <title><?php echo $EM_Event->output( get_option('dbem_rss_title_format'), "rss" ); ?></title>
37
  <link><?php echo $event_url; ?></link>
38
  <guid><?php echo $event_url; ?></guid>
39
+ <pubDate><?php echo $EM_Event->start(true)->format('D, d M Y H:i:s +0000'); ?></pubDate>
40
  <description><![CDATA[<?php echo $description; ?>]]></description>
41
  </item>
42
  <?php
widgets/em-calendar.php CHANGED
@@ -7,6 +7,10 @@ class EM_Widget_Calendar extends WP_Widget {
7
 
8
  var $defaults = array();
9
 
 
 
 
 
10
  /** constructor */
11
  function __construct() {
12
  $this->defaults = array(
@@ -35,6 +39,7 @@ class EM_Widget_Calendar extends WP_Widget {
35
  $instance['year'] = $date[0];
36
  }else{
37
  $instance['month'] = date("m");
 
38
  }
39
 
40
  //Our Widget Content
@@ -73,4 +78,4 @@ class EM_Widget_Calendar extends WP_Widget {
73
  }
74
 
75
  }
76
- add_action('widgets_init', create_function('', 'return register_widget("EM_Widget_Calendar");'));
7
 
8
  var $defaults = array();
9
 
10
+ public static function init(){
11
+ return register_widget("EM_Widget_Calendar");
12
+ }
13
+
14
  /** constructor */
15
  function __construct() {
16
  $this->defaults = array(
39
  $instance['year'] = $date[0];
40
  }else{
41
  $instance['month'] = date("m");
42
+ $instance['year'] = date('Y');
43
  }
44
 
45
  //Our Widget Content
78
  }
79
 
80
  }
81
+ add_action('widgets_init', 'EM_Widget_Calendar::init');
widgets/em-events.php CHANGED
@@ -7,6 +7,10 @@ class EM_Widget extends WP_Widget {
7
 
8
  var $defaults;
9
 
 
 
 
 
10
  /** constructor */
11
  function __construct() {
12
  $this->defaults = array(
@@ -205,5 +209,5 @@ class EM_Widget extends WP_Widget {
205
  return $instance;
206
  }
207
  }
208
- add_action('widgets_init', create_function('', 'return register_widget("EM_Widget");'));
209
  ?>
7
 
8
  var $defaults;
9
 
10
+ public static function init(){
11
+ return register_widget("EM_Widget");
12
+ }
13
+
14
  /** constructor */
15
  function __construct() {
16
  $this->defaults = array(
209
  return $instance;
210
  }
211
  }
212
+ add_action('widgets_init', 'EM_Widget::init');
213
  ?>
widgets/em-locations.php CHANGED
@@ -7,6 +7,10 @@ class EM_Locations_Widget extends WP_Widget {
7
 
8
  var $defaults = array();
9
 
 
 
 
 
10
  /** constructor */
11
  function __construct() {
12
  $this->defaults = array(
@@ -128,5 +132,5 @@ class EM_Locations_Widget extends WP_Widget {
128
  <?php
129
  }
130
  }
131
- add_action('widgets_init', create_function('', 'return register_widget("EM_Locations_Widget");'));
132
  ?>
7
 
8
  var $defaults = array();
9
 
10
+ public static function init(){
11
+ return register_widget("EM_Locations_Widget");
12
+ }
13
+
14
  /** constructor */
15
  function __construct() {
16
  $this->defaults = array(
132
  <?php
133
  }
134
  }
135
+ add_action('widgets_init', 'EM_Locations_Widget::init');
136
  ?>