The Events Calendar - Version 4.0.1

Version Description

Download this release

Release Info

Developer borkweb
Plugin Icon The Events Calendar
Version 4.0.1
Comparing to
See all releases

Code changes from version 4.0 to 4.0.1

Files changed (47) hide show
  1. common/src/Tribe/Admin/Notice/Plugin_Upgrade_Notice.php +239 -0
  2. common/src/Tribe/Date_Utils.php +62 -0
  3. common/src/Tribe/Main.php +1 -1
  4. common/src/resources/css/tribe-common-admin.css +26 -3
  5. common/src/resources/images/tribe-loading@2x.gif +0 -0
  6. common/tribe-autoload.php +7 -0
  7. readme.txt +22 -5
  8. src/Tribe/Admin/Bar/Admin_Bar.php +68 -0
  9. src/Tribe/Admin/Bar/Configurator_Interface.php +14 -0
  10. src/Tribe/Admin/Bar/Default_Configurator.php +113 -0
  11. src/Tribe/Admin/Notices/Base_Notice.php +29 -0
  12. src/Tribe/Admin/Notices/Notice_Interface.php +25 -0
  13. src/Tribe/Admin/Timezone_Updater.php +1 -1
  14. src/Tribe/Admin_List.php +15 -10
  15. src/Tribe/Constants.php +76 -0
  16. src/Tribe/Event_Tickets/Attendees_Report.php +94 -0
  17. src/Tribe/Event_Tickets/Main.php +59 -0
  18. src/Tribe/Importer/File_Importer_Events.php +5 -0
  19. src/Tribe/Main.php +40 -134
  20. src/Tribe/Timezones.php +1 -3
  21. src/Tribe/Utils/DST.php +73 -0
  22. src/Tribe/iCal.php +7 -3
  23. src/admin-views/new-organizer-meta-section.php +6 -0
  24. src/functions/template-tags/date.php +14 -61
  25. src/functions/template-tags/general.php +32 -4
  26. src/functions/utils/array.php +23 -0
  27. src/resources/js/tribe-events-ajax-calendar.js +6 -11
  28. src/resources/js/tribe-events-ajax-calendar.min.js +1 -1
  29. src/resources/js/tribe-events-bar.js +4 -4
  30. src/resources/js/tribe-events.js +96 -96
  31. src/resources/js/tribe-settings.min.js +1 -1
  32. src/views/modules/meta/details.php +1 -1
  33. src/views/single-event.php +1 -1
  34. tests.md +4 -0
  35. the-events-calendar.php +1 -1
  36. vendor/tickets/common/codeception.dist.yml +0 -63
  37. vendor/tickets/common/src/Tribe/Admin/Notice/Plugin_Upgrade_Notice.php +239 -0
  38. vendor/tickets/common/src/Tribe/Date_Utils.php +62 -0
  39. vendor/tickets/common/src/Tribe/Main.php +1 -1
  40. vendor/tickets/common/src/resources/css/tribe-common-admin.css +26 -3
  41. vendor/tickets/common/src/resources/images/tribe-loading@2x.gif +0 -0
  42. vendor/tickets/common/tribe-autoload.php +7 -0
  43. vendor/tickets/event-tickets.php +1 -1
  44. vendor/tickets/readme.txt +54 -7
  45. vendor/tickets/src/Tribe/Main.php +1 -1
  46. vendor/tickets/src/Tribe/RSVP.php +1 -1
  47. vendor/tickets/src/admin-views/attendees.php +18 -56
common/src/Tribe/Admin/Notice/Plugin_Upgrade_Notice.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * When appropriate, displays a plugin upgrade message "inline" within the plugin
4
+ * admin screen.
5
+ *
6
+ * This is drawn from the Upgrade Notice section of the plugin readme.txt file (ie,
7
+ * the one belonging to the current stable accessible via WP SVN - at least by
8
+ * default).
9
+ */
10
+ class Tribe__Admin__Notice__Plugin_Upgrade_Notice {
11
+ /**
12
+ * Currently installed version of the plugin
13
+ *
14
+ * @var string
15
+ */
16
+ protected $current_version = '';
17
+
18
+ /**
19
+ * The plugin path as it is within the plugins directory, ie
20
+ * "some-plugin/main-file.php".
21
+ *
22
+ * @var string
23
+ */
24
+ protected $plugin_path = '';
25
+
26
+ /**
27
+ * Contains the plugin upgrade notice (empty if none are available).
28
+ *
29
+ * @var string
30
+ */
31
+ protected $upgrade_notice = '';
32
+
33
+
34
+ /**
35
+ * Test for and display any plugin upgrade messages (if any are available) inline
36
+ * beside the plugin listing itself.
37
+ *
38
+ * The optional third param is the object which actually checks to see if there
39
+ * are any upgrade notices worth displaying. If not provided, an object of the
40
+ * default type will be created (which connects to WP SVN).
41
+ *
42
+ * @param string $current_version
43
+ * @param string $plugin_path (ie "plugin-dir/main-file.php")
44
+ */
45
+ public function __construct( $current_version, $plugin_path ) {
46
+ $this->current_version = $current_version;
47
+ $this->plugin_path = $plugin_path;
48
+
49
+ add_action( "in_plugin_update_message-$plugin_path", array( $this, 'maybe_run' ) );
50
+ }
51
+
52
+ /**
53
+ * Test if there is a plugin upgrade notice and displays it if so.
54
+ *
55
+ * Expects to fire during "in_plugin_update_message-{plugin_path}", therefore
56
+ * this should only run if WordPress has detected that an upgrade is indeed
57
+ * available.
58
+ */
59
+ public function maybe_run() {
60
+ $this->test_for_upgrade_notice();
61
+
62
+ if ( $this->upgrade_notice ) {
63
+ $this->display_message();
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Tests to see if an upgrade notice is available.
69
+ */
70
+ protected function test_for_upgrade_notice() {
71
+ $cache_key = $this->cache_key();
72
+ $this->upgrade_notice = get_transient( $cache_key );
73
+
74
+ if ( false === $this->upgrade_notice ) {
75
+ $this->discover_upgrade_notice();
76
+ }
77
+
78
+ set_transient( $cache_key, $this->upgrade_notice, $this->cache_expiration() );
79
+ }
80
+
81
+ /**
82
+ * Returns a cache key unique to the current plugin path and version, that
83
+ * still fits within the 45-char limit of regular WP transient keys.
84
+ *
85
+ * @return string
86
+ */
87
+ protected function cache_key() {
88
+ return 'tribe_plugin_upgrade_notice-' . hash( 'crc32b', $this->plugin_path . $this->current_version );
89
+ }
90
+
91
+ /**
92
+ * Returns the period of time (in seconds) for which to cache plugin upgrade messages.
93
+ *
94
+ * @return int
95
+ */
96
+ protected function cache_expiration() {
97
+ /**
98
+ * Number of seconds to cache plugin upgrade messages for.
99
+ *
100
+ * Defaults to one day, which provides a decent balance between efficiency savings
101
+ * and allowing for the possibility that some upgrade messages may be changed or
102
+ * rescinded.
103
+ *
104
+ * @var int $cache_expiration
105
+ */
106
+ return (int) apply_filters( 'tribe_plugin_upgrade_notice_expiration', DAY_IN_SECONDS, $this->plugin_path );
107
+ }
108
+
109
+ /**
110
+ * Looks at the current stable plugin readme.txt and parses to try and find the first
111
+ * available upgrade notice relating to a plugin version higher than this one.
112
+ *
113
+ * By default, WP SVN is the source.
114
+ */
115
+ protected function discover_upgrade_notice() {
116
+ /**
117
+ * The URL for the current plugin readme.txt file.
118
+ *
119
+ * @var string $url
120
+ * @var string $plugin_path
121
+ */
122
+ $readme_url = apply_filters( 'tribe_plugin_upgrade_readme_url',
123
+ $this->form_wp_svn_readme_url(),
124
+ $this->plugin_path
125
+ );
126
+
127
+ if ( ! empty( $readme_url ) ) {
128
+ $response = wp_safe_remote_get( $readme_url );
129
+ }
130
+
131
+ if ( ! empty( $response ) && ! is_wp_error( $response ) ) {
132
+ $readme = $response['body'];
133
+ }
134
+
135
+ if ( ! empty( $readme ) ) {
136
+ $this->parse_for_upgrade_notice( $readme );
137
+ $this->format_upgrade_notice();
138
+ }
139
+
140
+ /**
141
+ * The upgrade notice for the current plugin (may be empty).
142
+ *
143
+ * @var string $upgrade_notice
144
+ * @var string $plugin_path
145
+ */
146
+ return apply_filters( 'tribe_plugin_upgrade_notice',
147
+ $this->upgrade_notice,
148
+ $this->plugin_path
149
+ );
150
+ }
151
+
152
+ /**
153
+ * Forms the expected URL to the trunk readme.txt file as it is on WP SVN
154
+ * or an empty string if for any reason it cannot be determined.
155
+ *
156
+ * @return string
157
+ */
158
+ protected function form_wp_svn_readme_url() {
159
+ $parts = explode( '/', $this->plugin_path );
160
+ $slug = empty( $parts[0] ) ? '' : $parts[0];
161
+ return esc_url( "https://plugins.svn.wordpress.org/$slug/trunk/readme.txt" );
162
+ }
163
+
164
+ /**
165
+ * Given a standard Markdown-format WP readme.txt file, finds the first upgrade
166
+ * notice (if any) for a version higher than $this->current_version.
167
+ *
168
+ * @param string $readme
169
+ * @return string
170
+ */
171
+ protected function parse_for_upgrade_notice( $readme ) {
172
+ $in_upgrade_notice = false;
173
+ $in_version_notice = false;
174
+ $readme_text = fopen( "data:://text/plain,$readme", 'r' );
175
+
176
+ while ( $line = fgets( $readme_text ) ) {
177
+ // Once we leave the Upgrade Notice section (ie, we encounter a new section header), bail
178
+ if ( $in_upgrade_notice && 0 === strpos( $line, '==' ) ) {
179
+ break;
180
+ }
181
+
182
+ // Look out for the start of the Upgrade Notice section
183
+ if ( ! $in_upgrade_notice && preg_match( '/^==\s*Upgrade\s+Notice\s*==/i', $line ) ) {
184
+ $in_upgrade_notice = true;
185
+ }
186
+
187
+ // Also test to see if we have left the version specific note (ie, we encounter a new sub heading or header)
188
+ if ( $in_upgrade_notice && $in_version_notice && 0 === strpos( $line, '=' ) ) {
189
+ break;
190
+ }
191
+
192
+ // Look out for the first applicable version-specific note within the Upgrade Notice section
193
+ if ( $in_upgrade_notice && ! $in_version_notice && preg_match( '/^=\s*([0-9\.]{3,})\s*=/', $line, $matches ) ) {
194
+ // Is this a higher version than currently installed?
195
+ if ( version_compare( $matches[1], $this->current_version, '>' ) ) {
196
+ $in_version_notice = true;
197
+ }
198
+ }
199
+
200
+ // Copy the details of the upgrade notice for the first higher version we find
201
+ if ( $in_upgrade_notice && $in_version_notice ) {
202
+ $this->upgrade_notice .= $line;
203
+ }
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Convert the plugin version header and any links from Markdown to HTML.
209
+ */
210
+ protected function format_upgrade_notice() {
211
+ // Convert [links](http://...) to <a href="..."> tags
212
+ $this->upgrade_notice = preg_replace(
213
+ '/\[([^\]]*)\]\(([^\)]*)\)/',
214
+ '<a href="${2}">${1}</a>',
215
+ $this->upgrade_notice
216
+ );
217
+
218
+ // Convert =4.0= headings to <h4 class="version">4.0</h4> tags
219
+ $this->upgrade_notice = preg_replace(
220
+ '/=\s*([a-zA-Z0-9\.]{3,})\s*=/',
221
+ '<h4 class="version">${1}</h4>',
222
+ $this->upgrade_notice
223
+ );
224
+ }
225
+
226
+ /**
227
+ * Render the actual upgrade notice.
228
+ *
229
+ * Please note if plugin-specific styling is required for the message, you can
230
+ * use an ID generated by WordPress for one of the message's parent elements
231
+ * which takes the form "{plugin_name}-update". Example:
232
+ *
233
+ * #the-events-calendar-update .tribe-plugin-update-message { ... }
234
+ */
235
+ public function display_message() {
236
+ $notice = wp_kses_post( $this->upgrade_notice );
237
+ echo "<div class='tribe-plugin-update-message'> $notice </div>";
238
+ }
239
+ }
common/src/Tribe/Date_Utils.php CHANGED
@@ -721,6 +721,68 @@ if ( ! class_exists( 'Tribe__Date_Utils' ) ) {
721
  _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_timestamp' );
722
  return self::is_timestamp( $timestamp );
723
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
724
  // @codingStandardsIgnoreEnd
725
  }
 
726
  }
721
  _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_timestamp' );
722
  return self::is_timestamp( $timestamp );
723
  }
724
+
725
+ /**
726
+ * Gets the timestamp of a day in week, month and year context.
727
+ *
728
+ * Kudos to [icedwater StackOverflow user](http://stackoverflow.com/users/1091386/icedwater) in
729
+ * [his answer](http://stackoverflow.com/questions/924246/get-the-first-or-last-friday-in-a-month).
730
+ *
731
+ * Usage examples:
732
+ * "The second Wednesday of March 2015" - `get_day_timestamp( 3, 2, 3, 2015, 1)`
733
+ * "The last Friday of December 2015" - `get_day_timestamp( 5, 1, 12, 2015, -1)`
734
+ * "The first Monday of April 2016 - `get_day_timestamp( 1, 1, 4, 2016, 1)`
735
+ * "The penultimate Thursday of January 2012" - `get_day_timestamp( 4, 2, 1, 2012, -1)`
736
+ *
737
+ * @param int $day_of_week The day representing the number in the week, Monday is `1`, Tuesday is `2`, Sunday is `7`
738
+ * @param int $week_in_month The week number in the month; first week is `1`, second week is `2`; when direction is reverse
739
+ * then `1` is last week of the month, `2` is penultimate week of the month and so on.
740
+ * @param int $month The month number in the year, January is `1`
741
+ * @param int $year The year number, e.g. "2015"
742
+ * @param int $week_direction Either `1` or `-1`; the direction for the search referring to the week, defaults to `1`
743
+ * to specify weeks in natural order so:
744
+ * $week_direction `1` and $week_in_month `1` means "first week of the month"
745
+ * $week_direction `1` and $week_in_month `3` means "third week of the month"
746
+ * $week_direction `-1` and $week_in_month `1` means "last week of the month"
747
+ * $week_direction `-1` and $week_in_month `2` means "penultimmate week of the month"
748
+ *
749
+ * @return int The day timestamp
750
+ */
751
+ public static function get_weekday_timestamp( $day_of_week, $week_in_month, $month, $year, $week_direction = 1 ) {
752
+ if (
753
+ ! (
754
+ is_numeric( $day_of_week )
755
+ && is_numeric( $week_in_month )
756
+ && is_numeric( $month )
757
+ && is_numeric( $year )
758
+ && is_numeric( $week_direction )
759
+ && in_array( $week_direction, array( - 1, 1 ) )
760
+ )
761
+ ) {
762
+ return false;
763
+ }
764
+
765
+ if ( $week_direction > 0 ) {
766
+ $startday = 1;
767
+ } else {
768
+ $startday = date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
769
+ }
770
+
771
+ $start = mktime( 0, 0, 0, $month, $startday, $year );
772
+ $weekday = date( 'N', $start );
773
+
774
+ if ( $week_direction * $day_of_week >= $week_direction * $weekday ) {
775
+ $offset = - $week_direction * 7;
776
+ } else {
777
+ $offset = 0;
778
+ }
779
+
780
+ $offset += $week_direction * ( $week_in_month * 7 ) + ( $day_of_week - $weekday );
781
+
782
+ return mktime( 0, 0, 0, $month, $startday + $offset, $year );
783
+ }
784
+
785
  // @codingStandardsIgnoreEnd
786
  }
787
+
788
  }
common/src/Tribe/Main.php CHANGED
@@ -17,7 +17,7 @@ class Tribe__Main {
17
  const OPTIONNAME = 'tribe_events_calendar_options';
18
  const OPTIONNAMENETWORK = 'tribe_events_calendar_network_options';
19
 
20
- const VERSION = '3.12a1';
21
  const FEED_URL = 'https://theeventscalendar.com/feed/';
22
 
23
  protected $plugin_context;
17
  const OPTIONNAME = 'tribe_events_calendar_options';
18
  const OPTIONNAMENETWORK = 'tribe_events_calendar_network_options';
19
 
20
+ const VERSION = '4.0.1';
21
  const FEED_URL = 'https://theeventscalendar.com/feed/';
22
 
23
  protected $plugin_context;
common/src/resources/css/tribe-common-admin.css CHANGED
@@ -20,6 +20,32 @@ td.tribe_message {padding-bottom: 10px !important;}
20
  #tribe-upgrade {margin:20px 0 30px; border:1px solid #ccc; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; padding:0 20px 20px; background:#f6f6f6;}
21
  #tribe-upgrade .message {border-style:solid; border-width:1px; padding:6px 12px; -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; background-color:#FFFFE0; border-color:#E6DB55;}
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  /* = Settings Screen
24
  =============================================*/
25
  .tribe-settings-form { max-width: 1000px; }
@@ -346,9 +372,6 @@ only screen and (min--moz-device-pixel-ratio: 2),
346
  only screen and (-o-min-device-pixel-ratio: 2/1),
347
  only screen and (-webkit-min-device-pixel-ratio: 2),
348
  only screen and (min-device-pixel-ratio: 2) {
349
- .events-cal #icon-edit {
350
- background-image: url(../images/events-screen-icon@2x.png);
351
- }
352
  #tribe-loading span {
353
  background-image: url(../images/tribe-loading@2x.gif);
354
  }
20
  #tribe-upgrade {margin:20px 0 30px; border:1px solid #ccc; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; padding:0 20px 20px; background:#f6f6f6;}
21
  #tribe-upgrade .message {border-style:solid; border-width:1px; padding:6px 12px; -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; background-color:#FFFFE0; border-color:#E6DB55;}
22
 
23
+ /* = Plugin Screen
24
+ =============================================*/
25
+ table.plugins .tribe-plugin-update-message {
26
+ background: #d54e21; /* taken from colour scheme in list-tables.css */
27
+ color: white;
28
+ display: inline-table;
29
+ padding: 10px 12px;
30
+ margin: 6px 0px;
31
+ }
32
+
33
+ table.plugins .tribe-plugin-update-message h4 {
34
+ display: inline;
35
+ font-weight: bold;
36
+ margin-right: 8px;
37
+ }
38
+
39
+ table.plugins .tribe-plugin-update-message h4:after {
40
+ content: ' \00BB ';
41
+ }
42
+
43
+
44
+ table.plugins .tribe-plugin-update-message a {
45
+ color: white;
46
+ text-decoration: underline;
47
+ }
48
+
49
  /* = Settings Screen
50
  =============================================*/
51
  .tribe-settings-form { max-width: 1000px; }
372
  only screen and (-o-min-device-pixel-ratio: 2/1),
373
  only screen and (-webkit-min-device-pixel-ratio: 2),
374
  only screen and (min-device-pixel-ratio: 2) {
 
 
 
375
  #tribe-loading span {
376
  background-image: url(../images/tribe-loading@2x.gif);
377
  }
common/src/resources/images/tribe-loading@2x.gif ADDED
Binary file
common/tribe-autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ $src = dirname( __FILE__ ) . '/src';
3
+ require_once $src . '/Tribe/Autoloader.php';
4
+
5
+ $autoloader = Tribe__Autoloader::instance();
6
+ $autoloader->register_prefix('Tribe__',$src);
7
+ $autoloader->register_autoloader();
readme.txt CHANGED
@@ -4,8 +4,8 @@ Contributors: ModernTribe, borkweb, zbtirrell, barry.hughes, bordoni, brianjesse
4
  Tags: events, calendar, event, venue, organizer, dates, date, google maps, conference, workshop, concert, meeting, seminar, summit, class, modern tribe, tribe, widget
5
  Donate link: http://m.tri.be/29
6
  Requires at least: 3.9
7
- Tested up to: 4.3.1
8
- Stable tag: 4.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -207,7 +207,7 @@ The plugin is produced by <a href="http://m.tri.be/2s">Modern Tribe Inc</a>.
207
  <a href="https://profiles.wordpress.org/borkweb">Matthew Batchelder</a>
208
  <a href="https://profiles.wordpress.org/neillmcshea">Neill McShea</a>
209
  <a href="https://profiles.wordpress.org/mastromktg">Nick Mastromattei</a>
210
- <a href="https://profiles.wordpress.org/nicosantos”>Nico Santo</a>
211
  <a href="https://profiles.wordpress.org/peterchester">Peter Chester</a>
212
  <a href="https://profiles.wordpress.org/roblagatta">Rob La Gatta</a>
213
  <a href="https://profiles.wordpress.org/reid.peifer">Reid Peifer</a>
@@ -309,6 +309,24 @@ At no point during the 3.0 lifecycle will the major version change. But you can
309
 
310
  == Changelog ==
311
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  = [4.0] 2015-12-02 =
313
 
314
  * Security - A TON of escaping was added to our codebase thanks to the efforts of the always-helpful Andy Fragen (@afragen)
@@ -334,9 +352,9 @@ At no point during the 3.0 lifecycle will the major version change. But you can
334
  * Tweak - Drop the use of the generic CSS class "placeholder" in favor of "tribe-event-placeholder" (Thanks to Marc on the forums!)
335
  * Tweak - Adjusted the CSS padding on Admin Menu items for Events
336
  * Tweak - Various codesniffer fixes
 
337
  * Tweak - Error messages for empty Venue names
338
  * Tweak - Improve our responsiveness for the widget mini calendar, allowing smaller sidebars.
339
- * Tweak - tribe_get_vanue_link() no longer echoes if you ask it to return an <a> element
340
  * Tweak - No longer retrieve empty costs when fetching all costs for all events
341
  * Tweak - Change the priority of bootstrapping the-events-calendar to ensure it occurs before any of the TEC addons in the event some addons are upgraded to v4.0 later than TEC
342
  * Tweak - Adjust the logic used for adding a noindex/follow tag to event views
@@ -1070,4 +1088,3 @@ Please see the changelog for the complete list of changes in this release. Remem
1070
  = 2.0.3 =
1071
 
1072
  2.0.3 is a minor bug patch for 2.0. Are you upgrading from 1.6.5? Events 2.0 is a MAJOR upgrade, please backup your data and plan a little time in case you have to make any theme edits. Check out the upgrade tutorials in support on the tri.be website.
1073
-
4
  Tags: events, calendar, event, venue, organizer, dates, date, google maps, conference, workshop, concert, meeting, seminar, summit, class, modern tribe, tribe, widget
5
  Donate link: http://m.tri.be/29
6
  Requires at least: 3.9
7
+ Tested up to: 4.4
8
+ Stable tag: 4.0.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
207
  <a href="https://profiles.wordpress.org/borkweb">Matthew Batchelder</a>
208
  <a href="https://profiles.wordpress.org/neillmcshea">Neill McShea</a>
209
  <a href="https://profiles.wordpress.org/mastromktg">Nick Mastromattei</a>
210
+ <a href="https://profiles.wordpress.org/nicosantos">Nico Santo</a>
211
  <a href="https://profiles.wordpress.org/peterchester">Peter Chester</a>
212
  <a href="https://profiles.wordpress.org/roblagatta">Rob La Gatta</a>
213
  <a href="https://profiles.wordpress.org/reid.peifer">Reid Peifer</a>
309
 
310
  == Changelog ==
311
 
312
+ = [4.0.1] 2015-12-10 =
313
+
314
+ * Tweak - Add a warning message for major updates
315
+ * Tweak - For SEO reasons, use an h1 for the title rather than an h2 (props to wpexplorer for this fix)
316
+ * Tweak - Target the calendar view grid in JS using a simpler selector
317
+ * Fix - Resolved WP 4.4 related fatal on the Nav Menu page that prevented the admin footer from rendering/enqueuing JS
318
+ * Fix - Resolved bug where visiting /events/upcoming could sometimes result in an infinite redirect loop
319
+ * Fix - Removed `wp_trim_excerpt` and use only it's powers, fixing the excerpt problem
320
+ * Fix - Fixed bug where the mobile calendar view did not display the date for the date being viewed
321
+ * Fix - Fixed bug where the admin toolbar's Events > Import > CSV did not link to the CSV importer page
322
+ * Fix - Fixed issue where the events list in the admin dashboard were not ordered in an intuitive manner
323
+ * Fix - Resolved bug where sorting by event category or tag resulted in an error
324
+ * Fix - Fixed bug where full event content text was displayed where excerpts should have been displayed
325
+ * Fix - Resolved issue where events imported via CSV were excluded from single event navigation
326
+ * Fix - Fixed bug where /events/list would sometimes 404 on a new install
327
+ * Fix - Resolved bug where multiday all-day events displayed the end date as one day later than it should be when the End of Day Cut-off was set to something other than 12am
328
+ * Fix - Timezone handling fixed within generated iCal feeds
329
+
330
  = [4.0] 2015-12-02 =
331
 
332
  * Security - A TON of escaping was added to our codebase thanks to the efforts of the always-helpful Andy Fragen (@afragen)
352
  * Tweak - Drop the use of the generic CSS class "placeholder" in favor of "tribe-event-placeholder" (Thanks to Marc on the forums!)
353
  * Tweak - Adjusted the CSS padding on Admin Menu items for Events
354
  * Tweak - Various codesniffer fixes
355
+ * Tweak - tribe_get_venue_link() no longer echoes if you ask it to return an <a> element
356
  * Tweak - Error messages for empty Venue names
357
  * Tweak - Improve our responsiveness for the widget mini calendar, allowing smaller sidebars.
 
358
  * Tweak - No longer retrieve empty costs when fetching all costs for all events
359
  * Tweak - Change the priority of bootstrapping the-events-calendar to ensure it occurs before any of the TEC addons in the event some addons are upgraded to v4.0 later than TEC
360
  * Tweak - Adjust the logic used for adding a noindex/follow tag to event views
1088
  = 2.0.3 =
1089
 
1090
  2.0.3 is a minor bug patch for 2.0. Are you upgrading from 1.6.5? Events 2.0 is a MAJOR upgrade, please backup your data and plan a little time in case you have to make any theme edits. Check out the upgrade tutorials in support on the tri.be website.
 
src/Tribe/Admin/Bar/Admin_Bar.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Tribe__Events__Admin__Bar__Admin_Bar {
5
+
6
+ /**
7
+ * @var Tribe__Events__Admin__Bar__Admin_Bar
8
+ */
9
+ protected static $instance;
10
+ /**
11
+ * @var Tribe__Events__Constants
12
+ */
13
+ protected $constants;
14
+ /**
15
+ * @var Tribe__Events__Admin__Bar__Configurator_Interface
16
+ */
17
+ protected $config;
18
+
19
+ /**
20
+ * Singleton constructor for the class.
21
+ *
22
+ * @return Tribe__Events__Admin__Bar__Admin_Bar
23
+ */
24
+ public static function instance() {
25
+ if ( empty( self::$instance ) ) {
26
+ self::$instance = new self();
27
+ }
28
+
29
+ return self::$instance;
30
+ }
31
+
32
+ /**
33
+ * Tribe__Events__Admin__Bar__Admin_Bar constructor.
34
+ *
35
+ * @param Tribe__Events__Admin__Bar__Configurator_Interface $config An admin bar configurator.
36
+ * @param Tribe__Events__Constants $constants A constants access proxy.
37
+ */
38
+ public function __construct( Tribe__Events__Admin__Bar__Configurator_Interface $config = null, Tribe__Events__Constants $constants = null ) {
39
+ $this->config = $config ? $config : new Tribe__Events__Admin__Bar__Default_Configurator();
40
+ $this->constants = $constants ? $constants : new Tribe__Events__Constants();
41
+ }
42
+
43
+ /**
44
+ * Whether the Tribe Admin Bar is enabled or not.
45
+ *
46
+ * @return bool `false` if the `TRIBE_DISABLE_TOOLBAR_ITEMS` constant is `true` or the current screen is the network
47
+ * admin one, `true` otherwise.
48
+ */
49
+ public function is_enabled() {
50
+ $disabled = isset( $this->constants['TRIBE_DISABLE_TOOLBAR_ITEMS'] ) && $this->constants['TRIBE_DISABLE_TOOLBAR_ITEMS'];
51
+
52
+ return ( ! ( $disabled || is_network_admin() ) );
53
+ }
54
+
55
+ /**
56
+ * Adds menus, groups and nodes to the admin bar according the configuration.
57
+ *
58
+ * @param WP_Admin_Bar|null $wp_admin_bar
59
+ */
60
+ public function init( WP_Admin_Bar $wp_admin_bar = null ) {
61
+ if ( empty( $wp_admin_bar ) ) {
62
+ global /** @var WP_Admin_Bar $wp_admin_bar */
63
+ $wp_admin_bar;
64
+ }
65
+
66
+ $this->config->configure( $wp_admin_bar );
67
+ }
68
+ }
src/Tribe/Admin/Bar/Configurator_Interface.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ interface Tribe__Events__Admin__Bar__Configurator_Interface {
5
+
6
+ /**
7
+ * Configures an admin bar object adding menus, groups and nodes to it.
8
+ *
9
+ * @param WP_Admin_Bar $wp_admin_bar
10
+ *
11
+ * @return mixed
12
+ */
13
+ public function configure( WP_Admin_Bar $wp_admin_bar );
14
+ }
src/Tribe/Admin/Bar/Default_Configurator.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Tribe__Events__Admin__Bar__Default_Configurator implements Tribe__Events__Admin__Bar__Configurator_Interface {
5
+
6
+ /**
7
+ * Configures an admin bar object adding menus, groups and nodes to it.
8
+ *
9
+ * @param WP_Admin_Bar $wp_admin_bar
10
+ *
11
+ * @return array An array of menus to add to the admin bar.
12
+ */
13
+ public function configure( WP_Admin_Bar $wp_admin_bar ) {
14
+ $main = Tribe__Events__Main::instance();
15
+
16
+ $wp_admin_bar->add_menu( array(
17
+ 'id' => 'tribe-events',
18
+ 'title' => '<span class="ab-icon dashicons-before dashicons-calendar"></span>' . sprintf( __( '%s', 'the-events-calendar' ), $main->plural_event_label ),
19
+ 'href' => $main->getLink( 'home' ),
20
+ ) );
21
+
22
+ $wp_admin_bar->add_group( array(
23
+ 'id' => 'tribe-events-group',
24
+ 'parent' => 'tribe-events',
25
+ ) );
26
+
27
+ $wp_admin_bar->add_group( array(
28
+ 'id' => 'tribe-events-add-ons-group',
29
+ 'parent' => 'tribe-events',
30
+ ) );
31
+
32
+ $wp_admin_bar->add_group( array(
33
+ 'id' => 'tribe-events-settings-group',
34
+ 'parent' => 'tribe-events',
35
+ ) );
36
+ if ( current_user_can( 'edit_tribe_events' ) ) {
37
+ $wp_admin_bar->add_group( array(
38
+ 'id' => 'tribe-events-import-group',
39
+ 'parent' => 'tribe-events-add-ons-group',
40
+ ) );
41
+ }
42
+
43
+ $wp_admin_bar->add_menu( array(
44
+ 'id' => 'tribe-events-view-calendar',
45
+ 'title' => esc_html__( 'View Calendar', 'the-events-calendar' ),
46
+ 'href' => $main->getLink( 'home' ),
47
+ 'parent' => 'tribe-events-group',
48
+ ) );
49
+
50
+ if ( current_user_can( 'edit_tribe_events' ) ) {
51
+ $wp_admin_bar->add_menu( array(
52
+ 'id' => 'tribe-events-add-event',
53
+ 'title' => sprintf( esc_html__( 'Add %s', 'the-events-calendar' ), $main->singular_event_label ),
54
+ 'href' => trailingslashit( get_admin_url() ) . 'post-new.php?post_type=' . Tribe__Events__Main::POSTTYPE,
55
+ 'parent' => 'tribe-events-group',
56
+ ) );
57
+ }
58
+
59
+ if ( current_user_can( 'edit_tribe_events' ) ) {
60
+ $wp_admin_bar->add_menu( array(
61
+ 'id' => 'tribe-events-edit-events',
62
+ 'title' => sprintf( esc_html__( 'Edit %s', 'the-events-calendar' ), $main->plural_event_label ),
63
+ 'href' => trailingslashit( get_admin_url() ) . 'edit.php?post_type=' . Tribe__Events__Main::POSTTYPE,
64
+ 'parent' => 'tribe-events-group',
65
+ ) );
66
+ }
67
+
68
+ if ( current_user_can( 'publish_tribe_events' ) ) {
69
+ $import_node = $wp_admin_bar->get_node( 'tribe-events-import' );
70
+ if ( ! is_object( $import_node ) ) {
71
+ $wp_admin_bar->add_menu( array(
72
+ 'id' => 'tribe-events-import',
73
+ 'title' => esc_html__( 'Import', 'the-events-calendar' ),
74
+ 'parent' => 'tribe-events-import-group',
75
+ ) );
76
+ }
77
+ $wp_admin_bar->add_menu( array(
78
+ 'id' => 'tribe-csv-import',
79
+ 'title' => esc_html__( 'CSV', 'the-events-calendar' ),
80
+ 'href' => esc_url( add_query_arg( array(
81
+ 'post_type' => Tribe__Events__Main::POSTTYPE,
82
+ 'page' => 'events-importer',
83
+ 'tab' => 'csv-importer',
84
+ ), admin_url( 'edit.php' ) ) ),
85
+ 'parent' => 'tribe-events-import',
86
+ ) );
87
+ }
88
+
89
+ if ( current_user_can( 'manage_options' ) ) {
90
+
91
+ $hide_all_settings = Tribe__Settings_Manager::get_network_option( 'allSettingsTabsHidden', '0' );
92
+ if ( $hide_all_settings == '0' ) {
93
+ $wp_admin_bar->add_menu( array(
94
+ 'id' => 'tribe-events-settings',
95
+ 'title' => esc_html__( 'Settings', 'the-events-calendar' ),
96
+ 'href' => Tribe__Settings::instance()->get_url(),
97
+ 'parent' => 'tribe-events-settings-group',
98
+ ) );
99
+ }
100
+
101
+ // Only show help link if it's not blocked in network admin.
102
+ $hidden_settings_tabs = Tribe__Settings_Manager::get_network_option( 'hideSettingsTabs', array() );
103
+ if ( ! in_array( 'help', $hidden_settings_tabs ) ) {
104
+ $wp_admin_bar->add_menu( array(
105
+ 'id' => 'tribe-events-help',
106
+ 'title' => esc_html__( 'Help', 'the-events-calendar' ),
107
+ 'href' => Tribe__Settings::instance()->get_url( array( 'tab' => 'help' ) ),
108
+ 'parent' => 'tribe-events-settings-group',
109
+ ) );
110
+ }
111
+ }
112
+ }
113
+ }
src/Tribe/Admin/Notices/Base_Notice.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Tribe__Events__Admin__Notices__Base_Notice implements Tribe__Events__Admin__Notices__Notice_Interface {
5
+
6
+ /**
7
+ * Echoes the notice.
8
+ *
9
+ * @param string $message
10
+ * @param string $class
11
+ *
12
+ * @return void
13
+ */
14
+ public function render( $message, $class = 'updated' ) {
15
+ echo $this->get( $message, $class );
16
+ }
17
+
18
+ /**
19
+ * Return the notice content.
20
+ *
21
+ * @param string $message
22
+ * @param string $class
23
+ *
24
+ * @return string
25
+ */
26
+ public function get( $message, $class ) {
27
+ return sprintf( '<div class="%s"><p>%s</p></div>', esc_attr( $class ), $message );
28
+ }
29
+ }
src/Tribe/Admin/Notices/Notice_Interface.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ interface Tribe__Events__Admin__Notices__Notice_Interface {
5
+
6
+ /**
7
+ * Echoes the notice.
8
+ *
9
+ * @param string $message
10
+ * @param string $class
11
+ *
12
+ * @return void
13
+ */
14
+ public function render( $message, $class = 'updated' );
15
+
16
+ /**
17
+ * Return the notice content.
18
+ *
19
+ * @param string $message
20
+ * @param string $class
21
+ *
22
+ * @return string
23
+ */
24
+ public function get( $message, $class );
25
+ }
src/Tribe/Admin/Timezone_Updater.php CHANGED
@@ -95,7 +95,7 @@ class Tribe__Events__Admin__Timezone_Updater {
95
  * Sets up the Javascript needed to facilitate the ajax loop on the frontend.
96
  */
97
  public function notice_assets() {
98
- $plugin = Tribe__Main::instance();
99
  $script = trailingslashit( $plugin->plugin_url ) . 'src/resources/js/events-admin-timezone-updater.js';
100
  $handle = 'tribe-events-ajax-timezone-update';
101
 
95
  * Sets up the Javascript needed to facilitate the ajax loop on the frontend.
96
  */
97
  public function notice_assets() {
98
+ $plugin = Tribe__Events__Main::instance();
99
  $script = trailingslashit( $plugin->plugin_url ) . 'src/resources/js/events-admin-timezone-updater.js';
100
  $handle = 'tribe-events-ajax-timezone-update';
101
 
src/Tribe/Admin_List.php CHANGED
@@ -99,7 +99,7 @@ if ( ! class_exists( 'Tribe__Events__Admin_List' ) ) {
99
  }
100
 
101
  if ( ! empty( $clauses['orderby'] ) ) {
102
- $clauses['orderby'] .= ',';
103
  }
104
 
105
  $start_orderby = "tribe_event_start_date.meta_value {$sort_direction}";
@@ -111,7 +111,12 @@ if ( ! class_exists( 'Tribe__Events__Admin_List' ) ) {
111
  $date_orderby = "{$end_orderby}, {$start_orderby}";
112
  }
113
 
114
- $clauses['orderby'] .= $date_orderby;
 
 
 
 
 
115
 
116
  return $clauses;
117
  }
@@ -148,17 +153,17 @@ if ( ! class_exists( 'Tribe__Events__Admin_List' ) ) {
148
  // collect the terms in the desired taxonomy for the given post into a single string
149
  $smashed_terms_sql = "
150
  SELECT
151
- GROUP_CONCAT( wp_terms.name ORDER BY name ASC ) smashed_terms
152
  FROM
153
- wp_term_relationships
154
- LEFT JOIN wp_term_taxonomy ON (
155
- wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
156
  AND taxonomy = '%s'
157
  )
158
- LEFT JOIN wp_terms ON (
159
- wp_term_taxonomy.term_id = wp_terms.term_id
160
  )
161
- WHERE wp_term_relationships.object_id = wp_posts.ID
162
  ";
163
 
164
  $smashed_terms_sql = $wpdb->prepare( $smashed_terms_sql, $taxonomy );
@@ -276,7 +281,7 @@ if ( ! class_exists( 'Tribe__Events__Admin_List' ) ) {
276
  break;
277
 
278
  case 'end-date':
279
- echo tribe_get_end_date( $post_id, false );
280
  break;
281
  }
282
  }
99
  }
100
 
101
  if ( ! empty( $clauses['orderby'] ) ) {
102
+ $original_orderby = $clauses['orderby'];
103
  }
104
 
105
  $start_orderby = "tribe_event_start_date.meta_value {$sort_direction}";
111
  $date_orderby = "{$end_orderby}, {$start_orderby}";
112
  }
113
 
114
+ // Add the date orderby rules *before* any pre-existing orderby rules (to stop them being "trumped")
115
+ $revised_orderby = empty( $original_orderby )
116
+ ? $date_orderby
117
+ : "$date_orderby, $original_orderby";
118
+
119
+ $clauses['orderby'] = $revised_orderby;
120
 
121
  return $clauses;
122
  }
153
  // collect the terms in the desired taxonomy for the given post into a single string
154
  $smashed_terms_sql = "
155
  SELECT
156
+ GROUP_CONCAT( $wpdb->terms.name ORDER BY name ASC ) smashed_terms
157
  FROM
158
+ $wpdb->term_relationships
159
+ LEFT JOIN $wpdb->term_taxonomy ON (
160
+ $wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id
161
  AND taxonomy = '%s'
162
  )
163
+ LEFT JOIN $wpdb->terms ON (
164
+ $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id
165
  )
166
+ WHERE $wpdb->term_relationships.object_id = $wpdb->posts.ID
167
  ";
168
 
169
  $smashed_terms_sql = $wpdb->prepare( $smashed_terms_sql, $taxonomy );
281
  break;
282
 
283
  case 'end-date':
284
+ echo tribe_get_display_end_date( $post_id, false );
285
  break;
286
  }
287
  }
src/Tribe/Constants.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Tribe__Events__Constants implements ArrayAccess {
5
+
6
+ /**
7
+ * @var bool Whether the class will define and read real constants or not.
8
+ */
9
+ protected $volatile;
10
+
11
+ /**
12
+ * @var array An array that will store volatile values if the class is used in volatile mode.
13
+ */
14
+ protected $volatile_values;
15
+
16
+ /**
17
+ * Tribe__Events__Constants constructor.
18
+ *
19
+ * @param bool $volatile If `true` the class will not define and read real constants.
20
+ */
21
+ public function __construct( $volatile = false ) {
22
+ $this->volatile = $volatile;
23
+ $this->volatile_values = array();
24
+ }
25
+
26
+ /**
27
+ * Whether a constant is defined or not.
28
+ *
29
+ * @param string $offset
30
+ *
31
+ * @return bool
32
+ */
33
+ public function offsetExists( $offset ) {
34
+ return $this->volatile ? isset( $this->volatile_values[ $offset ] ) : defined( $offset );
35
+ }
36
+
37
+ /**
38
+ * Gets a constant value.
39
+ *
40
+ * @param string $offset
41
+ *
42
+ * @return mixed
43
+ */
44
+ public function offsetGet( $offset ) {
45
+ return $this->volatile ? $this->volatile_values[ $offset ] : constant( $offset );
46
+ }
47
+
48
+ /**
49
+ * Sets the value of a constant if not already defined.
50
+ *
51
+ * @param string $offset
52
+ * @param mixed $value
53
+ */
54
+ public function offsetSet( $offset, $value ) {
55
+ if ( $this->volatile && ! isset( $this->volatile_values[ $offset ] ) ) {
56
+ $this->volatile_values[ $offset ] = $value;
57
+ } else {
58
+ if ( ! defined( $offset ) ) {
59
+ define( $offset, $value );
60
+ }
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Unsets a constant if in volatile mode.
66
+ *
67
+ * @param string $offset
68
+ */
69
+ public function offsetUnset( $offset ) {
70
+ if ( $this->volatile ) {
71
+ $this->volatile_values = array_diff( $this->volatile_values, array( $offset ) );
72
+ } else {
73
+ // no op
74
+ }
75
+ }
76
+ }
src/Tribe/Event_Tickets/Attendees_Report.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Events Calendar integration with Event Tickets Attendees Report class
4
+ *
5
+ * @package The Events Calendar
6
+ * @subpackage Event Tickets
7
+ * @since 4.0.1
8
+ */
9
+ class Tribe__Events__Event_Tickets__Attendees_Report {
10
+ /**
11
+ * Constructor
12
+ */
13
+ public function __construct() {
14
+ $this->add_hooks();
15
+ }
16
+
17
+ /**
18
+ * Adds hooks for injecting/overriding aspects of the Attendees Report from Event Tickets
19
+ *
20
+ * @since 4.0.1
21
+ */
22
+ public function add_hooks() {
23
+ add_action( 'tribe_tickets_attendees_event_details_list_top', array( $this, 'event_details_top' ) );
24
+ }
25
+
26
+ /**
27
+ * Injects event meta data into the Attendees report
28
+ */
29
+ public function event_details_top( $event_id ) {
30
+ if ( Tribe__Events__Main::POSTTYPE !== get_post_type( $event_id ) ) {
31
+ return;
32
+ }
33
+
34
+ $url = null;
35
+ if ( tribe_has_venue( $event_id ) ) {
36
+ $venue_id = tribe_get_venue_id( $event_id );
37
+
38
+ $url = get_post_meta( $venue_id, '_VenueURL', true );
39
+ if ( $url ) {
40
+ $url_path = @parse_url( $url, PHP_URL_PATH );
41
+ $display_url = @parse_url( $url, PHP_URL_HOST );
42
+ $display_url .= empty( $url_path ) && $url_path !== '/' ? '/&hellip;' : '';
43
+ $display_url = apply_filters( 'tribe_venue_display_url', $display_url, $url, $venue_id );
44
+ }
45
+ }
46
+
47
+ ?>
48
+ <li>
49
+ <strong><?php esc_html_e( 'Start Date / Time:', 'event-tickets' ) ?></strong>
50
+ <?php echo tribe_get_start_date( $event_id, false, tribe_get_datetime_format( true ) ) ?>
51
+ </li>
52
+
53
+ <li>
54
+ <strong><?php esc_html_e( 'End Date / Time:', 'event-tickets' ) ?></strong>
55
+ <?php echo tribe_get_end_date( $event_id, false, tribe_get_datetime_format( true ) ); ?>
56
+ </li>
57
+ <?php
58
+
59
+ if ( tribe_has_venue( $event_id ) ) {
60
+ ?>
61
+
62
+ <li class="venue-name">
63
+ <strong><?php echo tribe_get_venue_label_singular(); ?>: </strong>
64
+ <a href="<?php echo get_edit_post_link( $venue_id ); ?>" title="<?php esc_html_e( 'Edit Venue', 'the-events-calendar' ); ?>"><?php echo tribe_get_venue( $event_id ) ?></a>
65
+ </li>
66
+
67
+ <li class="venue-address">
68
+ <strong><?php _e( 'Address:', 'the-events-calendar' ); ?> </strong>
69
+ <?php echo tribe_get_full_address( $venue_id ); ?>
70
+ </li>
71
+
72
+ <?php
73
+ if ( $phone = tribe_get_phone( $venue_id ) ) {
74
+ ?>
75
+ <li class="venue-phone">
76
+ <strong><?php echo esc_html( __( 'Phone:', 'the-events-calendar' ) ); ?> </strong>
77
+ <?php echo esc_html( $phone ); ?>
78
+ </li>
79
+ <?php
80
+ }//end if
81
+
82
+ if ( $url ) {
83
+ ?>
84
+ <li class="venue-url">
85
+ <strong><?php echo esc_html( __( 'Website:', 'the-events-calendar' ) ); ?> </strong>
86
+ <a target="_blank" href="<?php echo esc_url( $url ); ?>">
87
+ <?php echo esc_html( $display_url ); ?>
88
+ </a>
89
+ </li>
90
+ <?php
91
+ }//end if
92
+ }
93
+ }
94
+ }
src/Tribe/Event_Tickets/Main.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Events Calendar integration with Event Tickets class
4
+ *
5
+ * @package The Events Calendar
6
+ * @subpackage Event Tickets
7
+ * @since 4.0.1
8
+ */
9
+ class Tribe__Events__Event_Tickets__Main {
10
+ /**
11
+ * Private variable holding the class instance
12
+ *
13
+ * @since 4.0.1
14
+ *
15
+ * @var Tribe__Events__Event_Tickets__Main
16
+ */
17
+ private static $instance;
18
+
19
+ /**
20
+ * Contains an instance of the Attendees Report integration class
21
+ * @since 4.0.1
22
+ * @var Tribe__Events__Event_Tickets__Attendees_Report
23
+ */
24
+ private $attendees_report;
25
+
26
+ /**
27
+ * Method to return the private instance of the class
28
+ *
29
+ * @since 4.0.1
30
+ * @return Tribe__Events__Event_Tickets__Main
31
+ */
32
+ public static function instance() {
33
+ if ( ! self::$instance ) {
34
+ self::$instance = new self;
35
+ }
36
+
37
+ return self::$instance;
38
+ }
39
+
40
+ /**
41
+ * Constructor
42
+ */
43
+ public function __construct() {
44
+ $this->attendees_report();
45
+ }
46
+
47
+ /**
48
+ * Attendees Report integration class object accessor method
49
+ */
50
+ public function attendees_report( $object = null ) {
51
+ if ( $object ) {
52
+ $this->attendees_report = $object;
53
+ } elseif ( ! $this->attendees_report ) {
54
+ $this->attendees_report = new Tribe__Events__Event_Tickets__Attendees_Report;
55
+ }
56
+
57
+ return $this->attendees_report;
58
+ }
59
+ }
src/Tribe/Importer/File_Importer_Events.php CHANGED
@@ -166,6 +166,11 @@ class Tribe__Events__Importer__File_Importer_Events extends Tribe__Events__Impor
166
  $event['tax_input']['post_tag'] = $tags;
167
  }
168
 
 
 
 
 
 
169
  $additional_fields = apply_filters( 'tribe_events_csv_import_event_additional_fields', array() );
170
  if ( ! empty ( $additional_fields ) ) {
171
  foreach ( $additional_fields as $key => $csv_column ) {
166
  $event['tax_input']['post_tag'] = $tags;
167
  }
168
 
169
+ // don't create the _EventHideFromUpcoming meta key/value pair if it doesn't need to be created
170
+ if ( ! $event['EventHideFromUpcoming'] ) {
171
+ unset( $event['EventHideFromUpcoming'] );
172
+ }
173
+
174
  $additional_fields = apply_filters( 'tribe_events_csv_import_event_additional_fields', array() );
175
  if ( ! empty ( $additional_fields ) ) {
176
  foreach ( $additional_fields as $key => $csv_column ) {
src/Tribe/Main.php CHANGED
@@ -32,7 +32,7 @@ if ( ! class_exists( 'Tribe__Events__Main' ) ) {
32
  const VENUE_POST_TYPE = 'tribe_venue';
33
  const ORGANIZER_POST_TYPE = 'tribe_organizer';
34
 
35
- const VERSION = '4.0';
36
  const MIN_ADDON_VERSION = '4.0';
37
  const WP_PLUGIN_URL = 'http://wordpress.org/extend/plugins/the-events-calendar/';
38
 
@@ -323,6 +323,7 @@ if ( ! class_exists( 'Tribe__Events__Main' ) ) {
323
  require_once $this->plugin_path . 'src/functions/advanced-functions/event.php';
324
  require_once $this->plugin_path . 'src/functions/advanced-functions/venue.php';
325
  require_once $this->plugin_path . 'src/functions/advanced-functions/organizer.php';
 
326
 
327
  // Load Deprecated Template Tags
328
  if ( ! defined( 'TRIBE_DISABLE_DEPRECATED_TAGS' ) ) {
@@ -521,7 +522,7 @@ if ( ! class_exists( 'Tribe__Events__Main' ) ) {
521
  add_action( 'admin_notices', array( $this, 'checkAddOnCompatibility' ) );
522
  }
523
 
524
- add_action( 'wp_before_admin_bar_render', array( $this, 'addToolbarItems' ), 10 );
525
  add_action( 'all_admin_notices', array( $this, 'addViewCalendar' ) );
526
  add_action( 'admin_head', array( $this, 'setInitialMenuMetaBoxes' ), 500 );
527
  add_action( 'plugin_action_links_' . trailingslashit( $this->plugin_dir ) . 'the-events-calendar.php', array( $this, 'addLinksToPluginActions' ) );
@@ -548,6 +549,8 @@ if ( ! class_exists( 'Tribe__Events__Main' ) ) {
548
 
549
  add_action( 'init', array( $this, 'filter_cron_schedules' ) );
550
 
 
 
551
  // Add support for tickets plugin
552
  add_action( 'tribe_tickets_ticket_added', array( 'Tribe__Events__API', 'update_event_cost' ) );
553
  add_action( 'tribe_tickets_ticket_deleted', array( 'Tribe__Events__API', 'update_event_cost' ) );
@@ -808,7 +811,17 @@ if ( ! class_exists( 'Tribe__Events__Main' ) ) {
808
  * Initializes any admin-specific code (expects to be called when admin_init fires).
809
  */
810
  public function admin_init() {
 
 
811
  $this->timezone_settings = new Tribe__Events__Admin__Timezone_Settings;
 
 
 
 
 
 
 
 
812
  }
813
 
814
  /**
@@ -1126,13 +1139,22 @@ if ( ! class_exists( 'Tribe__Events__Main' ) ) {
1126
  $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval( $_nav_menu_placeholder ) - 1 : - 1;
1127
  $archive_slug = $this->getLink();
1128
 
 
 
 
 
 
 
 
 
 
1129
  array_unshift(
1130
  $posts, (object) array(
1131
  'ID' => 0,
1132
  'object_id' => $_nav_menu_placeholder,
1133
  'post_content' => '',
1134
  'post_excerpt' => '',
1135
- 'post_title' => $post_type['args']->labels->all_items,
1136
  'post_type' => 'nav_menu_item',
1137
  'type' => 'custom',
1138
  'url' => $archive_slug,
@@ -2572,10 +2594,17 @@ if ( ! class_exists( 'Tribe__Events__Main' ) ) {
2572
  public function redirect_past_upcoming_view_urls() {
2573
 
2574
  if ( strpos( $_SERVER['REQUEST_URI'], $this->getRewriteSlug() . '/' . $this->pastSlug ) !== false ) {
2575
- wp_redirect( esc_url_raw( add_query_arg( array( 'tribe_event_display' => 'past' ), str_replace( '/' . $this->pastSlug . '/', '/' . $this->listSlug . '/', $_SERVER['REQUEST_URI'] ) ) ) );
 
 
 
 
2576
  die;
2577
  } elseif ( strpos( $_SERVER['REQUEST_URI'], $this->getRewriteSlug() . '/' . $this->upcomingSlug ) !== false ) {
2578
- wp_redirect( str_replace( '/' . $this->upcomingSlug . '/', '/' . $this->listSlug . '/', $_SERVER['REQUEST_URI'] ) );
 
 
 
2579
  die;
2580
  }
2581
 
@@ -4093,136 +4122,13 @@ if ( ! class_exists( 'Tribe__Events__Main' ) ) {
4093
  *
4094
  * @return null
4095
  */
4096
- public function addToolbarItems() {
4097
- if ( ( ! defined( 'TRIBE_DISABLE_TOOLBAR_ITEMS' ) || ! TRIBE_DISABLE_TOOLBAR_ITEMS ) && ! is_network_admin() ) {
4098
- global $wp_admin_bar;
4099
-
4100
- $wp_admin_bar->add_menu(
4101
- array(
4102
- 'id' => 'tribe-events',
4103
- 'title' => '<span class="ab-icon dashicons-before dashicons-calendar"></span>' . sprintf( __( '%s', 'the-events-calendar' ), $this->plural_event_label ),
4104
- 'href' => $this->getLink( 'home' ),
4105
- )
4106
- );
4107
-
4108
- $wp_admin_bar->add_group(
4109
- array(
4110
- 'id' => 'tribe-events-group',
4111
- 'parent' => 'tribe-events',
4112
- )
4113
- );
4114
-
4115
- $wp_admin_bar->add_group(
4116
- array(
4117
- 'id' => 'tribe-events-add-ons-group',
4118
- 'parent' => 'tribe-events',
4119
- )
4120
- );
4121
-
4122
- $wp_admin_bar->add_group(
4123
- array(
4124
- 'id' => 'tribe-events-settings-group',
4125
- 'parent' => 'tribe-events',
4126
- )
4127
- );
4128
- if ( current_user_can( 'edit_tribe_events' ) ) {
4129
- $wp_admin_bar->add_group(
4130
- array(
4131
- 'id' => 'tribe-events-import-group',
4132
- 'parent' => 'tribe-events-add-ons-group',
4133
- )
4134
- );
4135
- }
4136
-
4137
- $wp_admin_bar->add_menu(
4138
- array(
4139
- 'id' => 'tribe-events-view-calendar',
4140
- 'title' => esc_html__( 'View Calendar', 'the-events-calendar' ),
4141
- 'href' => $this->getLink( 'home' ),
4142
- 'parent' => 'tribe-events-group',
4143
- )
4144
- );
4145
-
4146
- if ( current_user_can( 'edit_tribe_events' ) ) {
4147
- $wp_admin_bar->add_menu(
4148
- array(
4149
- 'id' => 'tribe-events-add-event',
4150
- 'title' => sprintf( esc_html__( 'Add %s', 'the-events-calendar' ), $this->singular_event_label ),
4151
- 'href' => trailingslashit( get_admin_url() ) . 'post-new.php?post_type=' . self::POSTTYPE,
4152
- 'parent' => 'tribe-events-group',
4153
- )
4154
- );
4155
- }
4156
-
4157
- if ( current_user_can( 'edit_tribe_events' ) ) {
4158
- $wp_admin_bar->add_menu(
4159
- array(
4160
- 'id' => 'tribe-events-edit-events',
4161
- 'title' => sprintf( esc_html__( 'Edit %s', 'the-events-calendar' ), $this->plural_event_label ),
4162
- 'href' => trailingslashit( get_admin_url() ) . 'edit.php?post_type=' . self::POSTTYPE,
4163
- 'parent' => 'tribe-events-group',
4164
- )
4165
- );
4166
- }
4167
-
4168
- if ( current_user_can( 'publish_tribe_events' ) ) {
4169
- $import_node = $wp_admin_bar->get_node( 'tribe-events-import' );
4170
- if ( ! is_object( $import_node ) ) {
4171
- $wp_admin_bar->add_menu(
4172
- array(
4173
- 'id' => 'tribe-events-import',
4174
- 'title' => esc_html__( 'Import', 'the-events-calendar' ),
4175
- 'parent' => 'tribe-events-import-group',
4176
- )
4177
- );
4178
- }
4179
- $wp_admin_bar->add_menu(
4180
- array(
4181
- 'id' => 'tribe-csv-import',
4182
- 'title' => esc_html__( 'CSV', 'the-events-calendar' ),
4183
- 'href' => esc_url(
4184
- add_query_arg(
4185
- array(
4186
- 'post_type' => self::POSTTYPE,
4187
- 'page' => 'events-importer',
4188
- 'tab' => 'csv',
4189
- ),
4190
- admin_url( 'edit.php' )
4191
- )
4192
- ),
4193
- 'parent' => 'tribe-events-import',
4194
- )
4195
- );
4196
- }
4197
-
4198
- if ( current_user_can( 'manage_options' ) ) {
4199
-
4200
- $hide_all_settings = Tribe__Settings_Manager::get_network_option( 'allSettingsTabsHidden', '0' );
4201
- if ( $hide_all_settings == '0' ) {
4202
- $wp_admin_bar->add_menu(
4203
- array(
4204
- 'id' => 'tribe-events-settings',
4205
- 'title' => esc_html__( 'Settings', 'the-events-calendar' ),
4206
- 'href' => Tribe__Settings::instance()->get_url(),
4207
- 'parent' => 'tribe-events-settings-group',
4208
- )
4209
- );
4210
- }
4211
-
4212
- // Only show help link if it's not blocked in network admin.
4213
- $hidden_settings_tabs = Tribe__Settings_Manager::get_network_option( 'hideSettingsTabs', array() );
4214
- if ( ! in_array( 'help', $hidden_settings_tabs ) ) {
4215
- $wp_admin_bar->add_menu(
4216
- array(
4217
- 'id' => 'tribe-events-help',
4218
- 'title' => esc_html__( 'Help', 'the-events-calendar' ),
4219
- 'href' => Tribe__Settings::instance()->get_url( array( 'tab' => 'help' ) ),
4220
- 'parent' => 'tribe-events-settings-group',
4221
- )
4222
- );
4223
- }
4224
- }
4225
  }
 
 
4226
  }
4227
 
4228
  /**
32
  const VENUE_POST_TYPE = 'tribe_venue';
33
  const ORGANIZER_POST_TYPE = 'tribe_organizer';
34
 
35
+ const VERSION = '4.0.1';
36
  const MIN_ADDON_VERSION = '4.0';
37
  const WP_PLUGIN_URL = 'http://wordpress.org/extend/plugins/the-events-calendar/';
38
 
323
  require_once $this->plugin_path . 'src/functions/advanced-functions/event.php';
324
  require_once $this->plugin_path . 'src/functions/advanced-functions/venue.php';
325
  require_once $this->plugin_path . 'src/functions/advanced-functions/organizer.php';
326
+ require_once $this->plugin_path . 'src/functions/utils/array.php';
327
 
328
  // Load Deprecated Template Tags
329
  if ( ! defined( 'TRIBE_DISABLE_DEPRECATED_TAGS' ) ) {
522
  add_action( 'admin_notices', array( $this, 'checkAddOnCompatibility' ) );
523
  }
524
 
525
+ add_action( 'wp_before_admin_bar_render', array( $this, 'add_toolbar_items' ), 10 );
526
  add_action( 'all_admin_notices', array( $this, 'addViewCalendar' ) );
527
  add_action( 'admin_head', array( $this, 'setInitialMenuMetaBoxes' ), 500 );
528
  add_action( 'plugin_action_links_' . trailingslashit( $this->plugin_dir ) . 'the-events-calendar.php', array( $this, 'addLinksToPluginActions' ) );
549
 
550
  add_action( 'init', array( $this, 'filter_cron_schedules' ) );
551
 
552
+ add_action( 'plugins_loaded', array( 'Tribe__Events__Event_Tickets__Main', 'instance' ) );
553
+
554
  // Add support for tickets plugin
555
  add_action( 'tribe_tickets_ticket_added', array( 'Tribe__Events__API', 'update_event_cost' ) );
556
  add_action( 'tribe_tickets_ticket_deleted', array( 'Tribe__Events__API', 'update_event_cost' ) );
811
  * Initializes any admin-specific code (expects to be called when admin_init fires).
812
  */
813
  public function admin_init() {
814
+ global $pagenow;
815
+
816
  $this->timezone_settings = new Tribe__Events__Admin__Timezone_Settings;
817
+
818
+ // Right now it only makes sense to add these extra upgrade notices within the plugins.php screen
819
+ if ( 'plugins.php' === $pagenow ) {
820
+ new Tribe__Admin__Notice__Plugin_Upgrade_Notice(
821
+ self::VERSION,
822
+ $this->plugin_dir . 'the-events-calendar.php'
823
+ );
824
+ }
825
  }
826
 
827
  /**
1139
  $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval( $_nav_menu_placeholder ) - 1 : - 1;
1140
  $archive_slug = $this->getLink();
1141
 
1142
+ // In WP 4.4, $post_type is an object rather than an array
1143
+ if ( is_array( $post_type ) ) {
1144
+ // support pre WP 4.4
1145
+ $all_items = $post_type['args']->labels->all_items;
1146
+ } else {
1147
+ // support WP 4.4+
1148
+ $all_items = $post_type->labels->all_items;
1149
+ }
1150
+
1151
  array_unshift(
1152
  $posts, (object) array(
1153
  'ID' => 0,
1154
  'object_id' => $_nav_menu_placeholder,
1155
  'post_content' => '',
1156
  'post_excerpt' => '',
1157
+ 'post_title' => $all_items,
1158
  'post_type' => 'nav_menu_item',
1159
  'type' => 'custom',
1160
  'url' => $archive_slug,
2594
  public function redirect_past_upcoming_view_urls() {
2595
 
2596
  if ( strpos( $_SERVER['REQUEST_URI'], $this->getRewriteSlug() . '/' . $this->pastSlug ) !== false ) {
2597
+ $search = '#/' . $this->pastSlug . '/?#';
2598
+ $replace = '/' . $this->listSlug . '/';
2599
+ $redirect_url = preg_replace( $search, $replace, $_SERVER['REQUEST_URI'] );
2600
+ $redirect_url = esc_url_raw( add_query_arg( array( 'tribe_event_display' => 'past' ), $redirect_url ) );
2601
+ wp_redirect( $redirect_url );
2602
  die;
2603
  } elseif ( strpos( $_SERVER['REQUEST_URI'], $this->getRewriteSlug() . '/' . $this->upcomingSlug ) !== false ) {
2604
+ $search = '#/' . $this->upcomingSlug . '/?#';
2605
+ $replace = '/' . $this->listSlug . '/';
2606
+ $redirect_url = preg_replace( $search, $replace, $_SERVER['REQUEST_URI'] );
2607
+ wp_redirect( $redirect_url );
2608
  die;
2609
  }
2610
 
4122
  *
4123
  * @return null
4124
  */
4125
+ public function add_toolbar_items() {
4126
+ $admin_bar = Tribe__Events__Admin__Bar__Admin_Bar::instance();
4127
+ if ( ! $admin_bar->is_enabled() ) {
4128
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4129
  }
4130
+ global $wp_admin_bar;
4131
+ $admin_bar->init( $wp_admin_bar );
4132
  }
4133
 
4134
  /**
src/Tribe/Timezones.php CHANGED
@@ -314,9 +314,7 @@ class Tribe__Events__Timezones extends Tribe__Timezones {
314
 
315
  // If the event-specific timezone is suitable, we can obtain it without any conversion work
316
  if ( $use_event_tz || ( $use_site_tz && $site_zone_is_event_zone ) ) {
317
- $datetime = isset( $event->{"Event{$type}Date"} )
318
- ? $event->{"Event{$type}Date"}
319
- : get_post_meta( $event->ID, "_Event{$type}Date", true );
320
 
321
  return strtotime( $datetime );
322
  }
314
 
315
  // If the event-specific timezone is suitable, we can obtain it without any conversion work
316
  if ( $use_event_tz || ( $use_site_tz && $site_zone_is_event_zone ) ) {
317
+ $datetime = get_post_meta( $event->ID, "_Event{$type}Date", true );
 
 
318
 
319
  return strtotime( $datetime );
320
  }
src/Tribe/Utils/DST.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Tribe__Events__Utils__DST {
5
+
6
+ /**
7
+ * Whether the time is in DST or not.
8
+ *
9
+ * @var bool
10
+ */
11
+ protected $_in_dst;
12
+
13
+ /**
14
+ * @var string A UNIX timestamp
15
+ */
16
+ protected $time;
17
+
18
+ /**
19
+ * @var bool
20
+ */
21
+ protected $is_dst_cache;
22
+
23
+ /**
24
+ * Tribe__Events__Utils__DST constructor.
25
+ *
26
+ * @param int|string $time Either a UNIX timestamp or an english format date.
27
+ * @param null|bool $_in_dst An injectable DST status, meant for tests.
28
+ */
29
+ public function __construct( $time, $_in_dst = null ) {
30
+ if ( ! is_numeric( $time ) ) {
31
+ $time = strtotime( $time );
32
+ }
33
+
34
+ $this->time = $time;
35
+ $this->_in_dst = $_in_dst;
36
+ }
37
+
38
+ /**
39
+ * Whether the current time is in DST or not.
40
+ *
41
+ * @return bool
42
+ */
43
+ public function is_in_dst() {
44
+ if ( is_null($this->is_dst_cache) ) {
45
+ $default_timezone_backup = date_default_timezone_get();
46
+ $wp_timezone_string = get_option( 'timezone_string' );
47
+ $wp_timezone_string = empty( $wp_timezone_string ) ? $default_timezone_backup : $wp_timezone_string;
48
+
49
+ date_default_timezone_set( $wp_timezone_string );
50
+ $this->is_dst_cache = is_null( $this->_in_dst ) ? (bool) date( 'I', $this->time ) : $this->_in_dst;
51
+ date_default_timezone_set( $default_timezone_backup );
52
+ }
53
+
54
+ return $this->is_dst_cache;
55
+ }
56
+
57
+ /**
58
+ * Returns the time of the object aligned with another date object.
59
+ *
60
+ * If both in date or both not in DST the same time; if this time is in DST and the
61
+ * target date is not in DST then the time +1hr, else the time -1 hr.
62
+ *
63
+ * @param Tribe__Events__Utils__DST $dst Another DST object this one should be aligned with.
64
+ *
65
+ * @return int The DST aligned UNIX timestamp.
66
+ */
67
+ public function get_time_aligned_with( Tribe__Events__Utils__DST $dst ) {
68
+ $dst_aligned = $this->is_in_dst() == $dst->is_in_dst();
69
+ $offset = $dst->is_in_dst() - $this->is_in_dst();
70
+
71
+ return $dst_aligned ? $this->time : $this->time + $offset * 3600;
72
+ }
73
+ }
src/Tribe/iCal.php CHANGED
@@ -229,8 +229,8 @@ class Tribe__Events__iCal {
229
 
230
  $full_format = 'Ymd\THis';
231
  $time = (object) array(
232
- 'start' => self::wp_strtotime( $event_post->EventStartDate ),
233
- 'end' => self::wp_strtotime( $event_post->EventEndDate ),
234
  'modified' => self::wp_strtotime( $event_post->post_modified ),
235
  'created' => self::wp_strtotime( $event_post->post_date ),
236
  );
@@ -254,7 +254,11 @@ class Tribe__Events__iCal {
254
  $item[] = "DTSTART;VALUE=$type:" . $tzoned->start;
255
  $item[] = "DTEND;VALUE=$type:" . $tzoned->end;
256
  } else {
257
- $tz = get_option( 'timezone_string' );
 
 
 
 
258
  $item[] = 'DTSTART;TZID="'.$tz.'":' . $tzoned->start;
259
  $item[] = 'DTEND;TZID="'.$tz.'":' . $tzoned->end;
260
  }
229
 
230
  $full_format = 'Ymd\THis';
231
  $time = (object) array(
232
+ 'start' => tribe_get_start_date( $event_post->ID, false, 'U' ),
233
+ 'end' => tribe_get_end_date( $event_post->ID, false, 'U' ),
234
  'modified' => self::wp_strtotime( $event_post->post_modified ),
235
  'created' => self::wp_strtotime( $event_post->post_date ),
236
  );
254
  $item[] = "DTSTART;VALUE=$type:" . $tzoned->start;
255
  $item[] = "DTEND;VALUE=$type:" . $tzoned->end;
256
  } else {
257
+ // Are we using the sitewide timezone or the local event timezone?
258
+ $tz = Tribe__Events__Timezones::EVENT_TIMEZONE === Tribe__Events__Timezones::mode()
259
+ ? Tribe__Events__Timezones::get_event_timezone_string( $event_post->ID )
260
+ : Tribe__Events__Timezones::wp_timezone_string();
261
+
262
  $item[] = 'DTSTART;TZID="'.$tz.'":' . $tzoned->start;
263
  $item[] = 'DTEND;TZID="'.$tz.'":' . $tzoned->end;
264
  }
src/admin-views/new-organizer-meta-section.php CHANGED
@@ -56,6 +56,12 @@ $organizer_pto = get_post_type_object( Tribe__Events__Main::ORGANIZER_POST_TYPE
56
  $('#event_organizer').on('blur', '.organizer-name', function () {
57
  var input = $(this);
58
  var group = input.parents('tbody');
 
 
 
 
 
 
59
  $.post(ajaxurl,
60
  {
61
  action: 'tribe_event_validation',
56
  $('#event_organizer').on('blur', '.organizer-name', function () {
57
  var input = $(this);
58
  var group = input.parents('tbody');
59
+
60
+ // Not actually populated with anything? Don't bother validating
61
+ if ( ! input.val().length ) {
62
+ return;
63
+ }
64
+
65
  $.post(ajaxurl,
66
  {
67
  action: 'tribe_event_validation',
src/functions/template-tags/date.php CHANGED
@@ -96,76 +96,29 @@ if ( ! function_exists( 'tribe_get_end_time' ) ) {
96
  }
97
  }
98
 
99
- if ( ! function_exists( 'tribe_get_start_date' ) ) {
100
  /**
101
- * Start Date
102
  *
103
- * Returns the event start date and time
104
  *
105
  * @category Events
106
- * @param int $event (optional)
107
- * @param bool $displayTime If true shows date and time, if false only shows date
108
- * @param string $dateFormat Allows date and time formating using standard php syntax (http://php.net/manual/en/function.date.php)
109
- * @param string $timezone Timezone in which to present the date/time (or default behaviour if not set)
110
- * @return string|null Date
111
- */
112
- function tribe_get_start_date( $event = null, $displayTime = true, $dateFormat = '', $timezone = null ) {
113
- if ( is_null( $event ) ) {
114
- global $post;
115
- $event = $post;
116
- }
117
-
118
- if ( is_numeric( $event ) ) {
119
- $event = get_post( $event );
120
- }
121
-
122
- if ( ! is_object( $event ) ) {
123
- return '';
124
- }
125
-
126
- if ( tribe_event_is_all_day( $event ) ) {
127
- $displayTime = false;
128
- }
129
-
130
- $start_date = Tribe__Events__Timezones::event_start_timestamp( $event->ID, $timezone );
131
- return tribe_format_date( $start_date, $displayTime, $dateFormat );
132
- }
133
- }
134
-
135
- if ( ! function_exists( 'tribe_get_end_date' ) ) {
136
- /**
137
- * End Date
138
- *
139
- * Returns the event end date
140
- *
141
- * @category Events
142
- * @param int $event (optional)
143
- * @param bool $displayTime If true shows date and time, if false only shows date
144
- * @param string $dateFormat Allows date and time formating using standard php syntax (http://php.net/manual/en/function.date.php)
145
- * @param string $timezone Timezone in which to present the date/time (or default behaviour if not set)
146
  *
147
  * @return string|null Date
148
  */
149
- function tribe_get_end_date( $event = null, $displayTime = true, $dateFormat = '', $timezone = null ) {
150
- if ( is_null( $event ) ) {
151
- global $post;
152
- $event = $post;
153
- }
154
-
155
- if ( is_numeric( $event ) ) {
156
- $event = get_post( $event );
157
- }
158
 
159
- if ( ! is_object( $event ) ) {
160
- return '';
161
  }
162
 
163
- if ( tribe_event_is_all_day( $event ) ) {
164
- $displayTime = false;
165
- }
166
-
167
- $end_date = Tribe__Events__Timezones::event_end_timestamp( $event->ID, $timezone );
168
- return tribe_format_date( $end_date, $displayTime, $dateFormat );
169
  }
170
  }
171
 
@@ -216,4 +169,4 @@ if ( ! function_exists( 'tribe_event_is_on_date' ) ) {
216
 
217
  return apply_filters( 'tribe_event_is_on_date', $event_is_on_date, $date, $event );
218
  }
219
- }
96
  }
97
  }
98
 
99
+ if ( ! function_exists( 'tribe_get_display_end_date' ) ) {
100
  /**
101
+ * End Date formatted for display
102
  *
103
+ * Returns the event end date that observes the end of day cutoff
104
  *
105
  * @category Events
106
+ * @param int $event (optional)
107
+ * @param bool $display_time If true shows date and time, if false only shows date
108
+ * @param string $date_format Allows date and time formating using standard php syntax (http://php.net/manual/en/function.date.php)
109
+ * @param string $timezone Timezone in which to present the date/time (or default behaviour if not set)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  *
111
  * @return string|null Date
112
  */
113
+ function tribe_get_display_end_date( $event = null, $display_time = true, $date_format = '', $timezone = null ) {
114
+ $end_date = tribe_get_end_date( $event, true, 'U', $timezone );
115
+ $beginning_of_day = tribe_beginning_of_day( date( Tribe__Date_Utils::DBDATETIMEFORMAT, $end_date ) );
 
 
 
 
 
 
116
 
117
+ if ( tribe_event_is_multiday( $event ) && $end_date < strtotime( $beginning_of_day ) ) {
118
+ $end_date -= DAY_IN_SECONDS;
119
  }
120
 
121
+ return tribe_format_date( $end_date, $display_time, $date_format );
 
 
 
 
 
122
  }
123
  }
124
 
169
 
170
  return apply_filters( 'tribe_event_is_on_date', $event_is_on_date, $date, $event );
171
  }
172
+ }
src/functions/template-tags/general.php CHANGED
@@ -913,7 +913,18 @@ if ( class_exists( 'Tribe__Events__Main' ) ) {
913
  $inner .= tribe_get_start_date( $event, true, $format );
914
  $inner .= '</span>' . $time_range_separator;
915
  $inner .= '<span class="tribe-event-date-end">';
916
- $inner .= tribe_get_end_date( $event, true, $format2ndday );
 
 
 
 
 
 
 
 
 
 
 
917
  } else {
918
  $inner .= tribe_get_start_date( $event, false, $format ) . ( $time ? $datetime_separator . tribe_get_start_date( $event, false, $time_format ) : '' );
919
  $inner .= '</span>' . $time_range_separator;
@@ -1111,7 +1122,10 @@ if ( class_exists( 'Tribe__Events__Main' ) ) {
1111
  if ( isset( $deprecated ) ) {
1112
  _deprecated_argument( __FUNCTION__, '3.10' );
1113
  }
1114
- return tribe_get_option( 'tribeEnableViews', array( 'month' ) );
 
 
 
1115
  }
1116
 
1117
  /**
@@ -1316,8 +1330,22 @@ if ( class_exists( 'Tribe__Events__Main' ) ) {
1316
  // Remove "all" HTML based on what is allowed
1317
  $excerpt = wp_kses( $excerpt, $allowed_html );
1318
 
1319
- // Still treat this as an Excerpt on WP
1320
- $excerpt = wp_trim_excerpt( $excerpt );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1321
 
1322
  return wpautop( $excerpt );
1323
  }
913
  $inner .= tribe_get_start_date( $event, true, $format );
914
  $inner .= '</span>' . $time_range_separator;
915
  $inner .= '<span class="tribe-event-date-end">';
916
+
917
+ $end_date_full = tribe_get_end_date( $event, true, Tribe__Date_Utils::DBDATETIMEFORMAT );
918
+ $end_date_full_timestamp = strtotime( $end_date_full );
919
+
920
+ // if the end date is <= the beginning of the day, consider it the previous day
921
+ if ( $end_date_full_timestamp <= strtotime( tribe_beginning_of_day( $end_date_full ) ) ) {
922
+ $end_date = tribe_format_date( $end_date_full_timestamp - DAY_IN_SECONDS, false, $format2ndday );
923
+ } else {
924
+ $end_date = tribe_get_end_date( $event, false, $format2ndday );
925
+ }
926
+
927
+ $inner .= $end_date;
928
  } else {
929
  $inner .= tribe_get_start_date( $event, false, $format ) . ( $time ? $datetime_separator . tribe_get_start_date( $event, false, $time_format ) : '' );
930
  $inner .= '</span>' . $time_range_separator;
1122
  if ( isset( $deprecated ) ) {
1123
  _deprecated_argument( __FUNCTION__, '3.10' );
1124
  }
1125
+ return tribe_get_option( 'tribeEnableViews', array(
1126
+ 'list',
1127
+ 'month',
1128
+ ) );
1129
  }
1130
 
1131
  /**
1330
  // Remove "all" HTML based on what is allowed
1331
  $excerpt = wp_kses( $excerpt, $allowed_html );
1332
 
1333
+ /**
1334
+ * Filter the number of words in an excerpt.
1335
+ *
1336
+ * @param int $number The number of words. Default 55.
1337
+ */
1338
+ $excerpt_length = apply_filters( 'excerpt_length', 55 );
1339
+
1340
+ /**
1341
+ * Filter the string in the "more" link displayed after a trimmed excerpt.
1342
+ *
1343
+ * @param string $more_string The string shown within the more link.
1344
+ */
1345
+ $excerpt_more = apply_filters( 'excerpt_more', ' [&hellip;]' );
1346
+
1347
+ // Now we actually trim it
1348
+ $excerpt = wp_trim_words( $excerpt, $excerpt_length, $excerpt_more );
1349
 
1350
  return wpautop( $excerpt );
1351
  }
src/functions/utils/array.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Utility functions dealing with arrays
4
+ */
5
+
6
+ /**
7
+ * Drop-in replacement for array_unique(), designed to operate on an array of arrays
8
+ * where each inner array is populated with strings (or types that can be stringified
9
+ * while essentially keeping their unique value).
10
+ *
11
+ * @param array $original array_of_arrays
12
+ *
13
+ * @return array
14
+ */
15
+ function tribe_array_unique( array $original ) {
16
+ $unique = array();
17
+
18
+ foreach( $original as $inner ) {
19
+ $unique[ join( '|', $inner ) ] = $inner;
20
+ }
21
+
22
+ return array_values( $unique );
23
+ }
src/resources/js/tribe-events-ajax-calendar.js CHANGED
@@ -155,12 +155,6 @@
155
 
156
  data.has_events = $date.hasClass( 'tribe-events-has-events' );
157
 
158
- // Backwards compatibility
159
- // @todo "Check if we can remove this check"
160
- if ( data.has_events ) {
161
- data.date_name = '';
162
- }
163
-
164
  $triggers.removeClass( 'mobile-active' )
165
  // If full_date_name is empty then default to highlighting the first day of the current month
166
  .filter( _active ).addClass( 'mobile-active' );
@@ -180,7 +174,7 @@
180
 
181
  var $today = $wrapper.find( '.tribe-events-present' ),
182
  $mobile_trigger = $wrapper.find( '.mobile-trigger' ),
183
- $tribe_grid = $wrapper.find( '#tribe-events-content > .tribe-events-calendar' );
184
 
185
  if ( !$( '#tribe-mobile-container' ).length ) {
186
  $( '<div id="tribe-mobile-container" />' ).insertAfter( $tribe_grid );
@@ -408,12 +402,13 @@
408
  eventDate: ts.date
409
  };
410
 
 
 
411
  if ( ts.category ) {
412
- ts.params['tribe_event_category'] = ts.category;
 
413
  }
414
 
415
- ts.url_params = {};
416
-
417
  if ( td.default_permalinks ) {
418
  if( !ts.url_params.hasOwnProperty( 'post_type' ) ){
419
  ts.url_params['post_type'] = config.events_post_type;
@@ -430,7 +425,7 @@
430
 
431
  $( te ).trigger( 'tribe_ev_collectParams' );
432
 
433
- if ( ts.pushcount > 0 || ts.filters || td.default_permalinks ) {
434
  ts.do_string = true;
435
  ts.pushstate = false;
436
  }
155
 
156
  data.has_events = $date.hasClass( 'tribe-events-has-events' );
157
 
 
 
 
 
 
 
158
  $triggers.removeClass( 'mobile-active' )
159
  // If full_date_name is empty then default to highlighting the first day of the current month
160
  .filter( _active ).addClass( 'mobile-active' );
174
 
175
  var $today = $wrapper.find( '.tribe-events-present' ),
176
  $mobile_trigger = $wrapper.find( '.mobile-trigger' ),
177
+ $tribe_grid = $wrapper.find( document.getElementById( 'tribe-events-content' ) ).find( '.tribe-events-calendar' );
178
 
179
  if ( !$( '#tribe-mobile-container' ).length ) {
180
  $( '<div id="tribe-mobile-container" />' ).insertAfter( $tribe_grid );
402
  eventDate: ts.date
403
  };
404
 
405
+ ts.url_params = {};
406
+
407
  if ( ts.category ) {
408
+ ts.params.tribe_event_category = ts.category;
409
+ ts.url_params.tribe_events_cat = ts.category;
410
  }
411
 
 
 
412
  if ( td.default_permalinks ) {
413
  if( !ts.url_params.hasOwnProperty( 'post_type' ) ){
414
  ts.url_params['post_type'] = config.events_post_type;
425
 
426
  $( te ).trigger( 'tribe_ev_collectParams' );
427
 
428
+ if ( ts.pushcount > 0 || ts.filters || td.default_permalinks || ts.category ) {
429
  ts.do_string = true;
430
  ts.pushstate = false;
431
  }
src/resources/js/tribe-events-ajax-calendar.min.js CHANGED
@@ -1 +1 @@
1
- !function(a,b,c,d,e,f,g,h,i,j){c(b).ready(function(){function j(a){var b=c('.tribe-mobile-day[data-day="'+a+'"]'),d=c('.tribe-events-calendar td[data-day="'+a+'"]'),e=d.find(".tribe-events-viewmore"),f=d.find(".hentry");f.length&&(f.each(function(){var a=c(this);if(a.tribe_has_attr("data-tribejson")){var d=a.data("tribejson");b.append(tribe_tmpl("tribe_tmpl_month_mobile",d))}}),e.length&&b.append(e.clone()))}function k(a){var b=a.data("tribejson");b.date=a.attr("data-day");var c=a.parents(".tribe-events-calendar"),d=c.next("#tribe-mobile-container"),e=d.find(".tribe-mobile-day"),f=c.find(".mobile-trigger"),g='[data-day="'+b.date+'"]',h=e.filter(g);b.has_events=a.hasClass("tribe-events-has-events"),b.has_events&&(b.date_name=""),f.removeClass("mobile-active").filter(g).addClass("mobile-active"),e.hide(),h.length?h.show():(d.append(tribe_tmpl("tribe_tmpl_month_mobile_day_header",b)),j(b.date))}function l(){var a=t.find(".tribe-events-present"),b=t.find(".mobile-trigger"),d=t.find("#tribe-events-content > .tribe-events-calendar");if(c("#tribe-mobile-container").length||c('<div id="tribe-mobile-container" />').insertAfter(d),a.length&&a.is(".tribe-events-thismonth"))k(a);else{var e=b.filter(".tribe-events-thismonth").first();k(e)}}function m(){t.find(".tribe-events-calendar th").each(function(){var a=c(this),b=a.attr("data-day-abbr"),d=a.attr("title");q.is(".tribe-mobile")?a.text(b):a.text(d)})}function n(a){q.is(".tribe-mobile")?(m(),l()):a&&m()}function o(a){if("change_view"!=tribe_events_bar_action){if(a.preventDefault(),g.ajax_running)return;u.val().length?"0"!==g.datepicker_format?g.date=tribeDateFormat(u.bootstrapDatepicker("getDate"),"tribeMonthQuery"):g.date=u.val():v||(g.date=d.cur_date.slice(0,-3)),g.filter_cats?d.cur_url=c("#tribe-events-header").data("baseurl")+g.date+"/":d.default_permalinks?d.cur_url=w:d.cur_url=w+g.date+"/",g.popping=!1,f.pre_ajax(function(){p()})}}function p(){f.invalid_date(g.date)||(c(".tribe-events-calendar").tribe_spin(),g.pushcount=0,g.ajax_running=!0,g.popping||(g.params={action:"tribe_calendar",eventDate:g.date},g.category&&(g.params.tribe_event_category=g.category),g.url_params={},d.default_permalinks&&(g.url_params.hasOwnProperty("post_type")||(g.url_params.post_type=i.events_post_type),g.url_params.hasOwnProperty("eventDisplay")||(g.url_params.eventDisplay=g.view)),c(e).trigger("tribe_ev_serializeBar"),g.params=c.param(g.params),g.url_params=c.param(g.url_params),c(e).trigger("tribe_ev_collectParams"),g.pushcount>0||g.filters||d.default_permalinks?(g.do_string=!0,g.pushstate=!1):(g.do_string=!1,g.pushstate=!0)),h.pushstate&&!g.filter_cats?(c(e).trigger("tribe_ev_ajaxStart").trigger("tribe_ev_monthView_AjaxStart"),c.post(TribeCalendar.ajaxurl,g.params,function(a){if(g.initial_load=!1,f.enable_inputs("#tribe_events_filters_form","input, select"),a.success){g.ajax_running=!1,d.ajax_response={total_count:"",view:a.view,max_pages:"",tribe_paged:"",timestamp:(new Date).getTime()};var h="";h=c.isFunction(c.fn.parseHTML)?c.parseHTML(a.html):a.html,c("#tribe-events-content").replaceWith(h),n(!0),g.page_title=c("#tribe-events-header").data("title"),b.title=g.page_title,g.do_string&&(d.cur_url=d.cur_url+"?"+g.url_params,history.pushState({tribe_date:g.date,tribe_params:g.params},g.page_title,d.cur_url)),g.pushstate&&history.pushState({tribe_date:g.date,tribe_params:g.params},g.page_title,d.cur_url),c(e).trigger("tribe_ev_ajaxSuccess").trigger("tribe_ev_monthView_ajaxSuccess")}})):g.url_params.length?a.location=d.cur_url+"?"+g.url_params:a.location=d.cur_url)}var q=c("body"),r=c('[class^="tribe-events-nav-"] a'),s=f.get_url_param("tribe-bar-date"),t=c("#tribe-events"),u=c("#tribe-bar-date"),v=!1,w="/";"undefined"!=typeof i.events_base?w=i.events_base:r.length&&(w=r.first().attr("href").slice(0,-8)),d.default_permalinks&&(w=w.split("?")[0]),c(".tribe-events-calendar").length&&c("#tribe-events-bar").length&&s&&s.length>7&&(c("#tribe-bar-date-day").val(s.slice(-3)),u.val(s.substring(0,7)));var x="yyyy-mm";if("0"!==g.datepicker_format){var y=parseInt(g.datepicker_format),z="m"+g.datepicker_format.toString();x=d.datepicker_formats.month[y],s&&(s.length<=7&&(s+="-01"),u.val(tribeDateFormat(s,z)))}if(d.datepicker_opts={format:x,minViewMode:"months",autoclose:!0},u.bootstrapDatepicker(d.datepicker_opts).on("changeDate",function(a){g.mdate=a.date;var b=a.date.getFullYear(),e=("0"+(a.date.getMonth()+1)).slice(-2);if(v=!0,g.date=b+"-"+e,h.no_bar()||h.live_ajax()&&h.pushstate){if(g.ajax_running||g.updating_picker)return;g.filter_cats?d.cur_url=c("#tribe-events-header").data("baseurl")+g.date+"/":d.default_permalinks?d.cur_url=w:d.cur_url=w+g.date+"/",g.popping=!1,f.pre_ajax(function(){p()})}}),n(!0),c(e).on("tribe_ev_resizeComplete",function(){n(!0)}),h.pushstate&&!h.map_view()){var A="action=tribe_calendar&eventDate="+c("#tribe-events-header").data("date");d.params.length&&(A=A+"&"+d.params),g.category&&(A=A+"&tribe_event_category="+g.category),history.replaceState({tribe_params:A},g.page_title,location.href),c(a).on("popstate",function(a){var b=a.originalEvent.state;b&&(g.do_string=!1,g.pushstate=!1,g.popping=!0,g.params=b.tribe_params,f.pre_ajax(function(){p()}),f.set_form(g.params))})}c("#tribe-events").on("click",".tribe-events-nav-previous, .tribe-events-nav-next",function(a){if(a.preventDefault(),!g.ajax_running){var b=c(this).find("a");g.date=b.data("month"),g.mdate=g.date+"-01","0"!==g.datepicker_format?f.update_picker(tribeDateFormat(g.mdate,z)):f.update_picker(g.date),g.filter_cats?d.cur_url=c("#tribe-events-header").data("baseurl"):d.cur_url=b.attr("href"),d.default_permalinks&&(d.cur_url=d.cur_url.split("?")[0]),g.popping=!1,f.pre_ajax(function(){p()})}}).on("click","td.tribe-events-thismonth a",function(a){a.stopPropagation()}).on("click",'[id*="tribe-events-daynum-"] a',function(a){if(q.is(".tribe-mobile")){a.preventDefault();var b=c(this).closest(".mobile-trigger");k(b)}}).on("click",".mobile-trigger",function(a){q.is(".tribe-mobile")&&(a.preventDefault(),a.stopPropagation(),k(c(this)))}),f.snap("#tribe-bar-form","body","#tribe-events-footer .tribe-events-nav-previous, #tribe-events-footer .tribe-events-nav-next"),c("form#tribe-bar-form").on("submit",function(a){o(a)}),c(e).on("tribe_ev_runAjax",function(){p()}),c(e).on("tribe_ev_updatingRecurrence",function(){g.date=c("#tribe-events-header").data("date"),g.filter_cats?d.cur_url=c("#tribe-events-header").data("baseurl")+g.date+"/":d.default_permalinks?d.cur_url=w:d.cur_url=w+g.date+"/",g.popping=!1})})}(window,document,jQuery,tribe_ev.data,tribe_ev.events,tribe_ev.fn,tribe_ev.state,tribe_ev.tests,tribe_js_config,tribe_debug);
1
+ !function(a,b,c,d,e,f,g,h,i,j){c(b).ready(function(){function j(a){var b=c('.tribe-mobile-day[data-day="'+a+'"]'),d=c('.tribe-events-calendar td[data-day="'+a+'"]'),e=d.find(".tribe-events-viewmore"),f=d.find(".hentry");f.length&&(f.each(function(){var a=c(this);if(a.tribe_has_attr("data-tribejson")){var d=a.data("tribejson");b.append(tribe_tmpl("tribe_tmpl_month_mobile",d))}}),e.length&&b.append(e.clone()))}function k(a){var b=a.data("tribejson");b.date=a.attr("data-day");var c=a.parents(".tribe-events-calendar"),d=c.next("#tribe-mobile-container"),e=d.find(".tribe-mobile-day"),f=c.find(".mobile-trigger"),g='[data-day="'+b.date+'"]',h=e.filter(g);b.has_events=a.hasClass("tribe-events-has-events"),f.removeClass("mobile-active").filter(g).addClass("mobile-active"),e.hide(),h.length?h.show():(d.append(tribe_tmpl("tribe_tmpl_month_mobile_day_header",b)),j(b.date))}function l(){var a=t.find(".tribe-events-present"),d=t.find(".mobile-trigger"),e=t.find(b.getElementById("tribe-events-content")).find(".tribe-events-calendar");if(c("#tribe-mobile-container").length||c('<div id="tribe-mobile-container" />').insertAfter(e),a.length&&a.is(".tribe-events-thismonth"))k(a);else{var f=d.filter(".tribe-events-thismonth").first();k(f)}}function m(){t.find(".tribe-events-calendar th").each(function(){var a=c(this),b=a.attr("data-day-abbr"),d=a.attr("title");q.is(".tribe-mobile")?a.text(b):a.text(d)})}function n(a){q.is(".tribe-mobile")?(m(),l()):a&&m()}function o(a){if("change_view"!=tribe_events_bar_action){if(a.preventDefault(),g.ajax_running)return;u.val().length?"0"!==g.datepicker_format?g.date=tribeDateFormat(u.bootstrapDatepicker("getDate"),"tribeMonthQuery"):g.date=u.val():v||(g.date=d.cur_date.slice(0,-3)),g.filter_cats?d.cur_url=c("#tribe-events-header").data("baseurl")+g.date+"/":d.default_permalinks?d.cur_url=w:d.cur_url=w+g.date+"/",g.popping=!1,f.pre_ajax(function(){p()})}}function p(){f.invalid_date(g.date)||(c(".tribe-events-calendar").tribe_spin(),g.pushcount=0,g.ajax_running=!0,g.popping||(g.params={action:"tribe_calendar",eventDate:g.date},g.url_params={},g.category&&(g.params.tribe_event_category=g.category,g.url_params.tribe_events_cat=g.category),d.default_permalinks&&(g.url_params.hasOwnProperty("post_type")||(g.url_params.post_type=i.events_post_type),g.url_params.hasOwnProperty("eventDisplay")||(g.url_params.eventDisplay=g.view)),c(e).trigger("tribe_ev_serializeBar"),g.params=c.param(g.params),g.url_params=c.param(g.url_params),c(e).trigger("tribe_ev_collectParams"),g.pushcount>0||g.filters||d.default_permalinks||g.category?(g.do_string=!0,g.pushstate=!1):(g.do_string=!1,g.pushstate=!0)),h.pushstate&&!g.filter_cats?(c(e).trigger("tribe_ev_ajaxStart").trigger("tribe_ev_monthView_AjaxStart"),c.post(TribeCalendar.ajaxurl,g.params,function(a){if(g.initial_load=!1,f.enable_inputs("#tribe_events_filters_form","input, select"),a.success){g.ajax_running=!1,d.ajax_response={total_count:"",view:a.view,max_pages:"",tribe_paged:"",timestamp:(new Date).getTime()};var h="";h=c.isFunction(c.fn.parseHTML)?c.parseHTML(a.html):a.html,c("#tribe-events-content").replaceWith(h),n(!0),g.page_title=c("#tribe-events-header").data("title"),b.title=g.page_title,g.do_string&&(d.cur_url=d.cur_url+"?"+g.url_params,history.pushState({tribe_date:g.date,tribe_params:g.params},g.page_title,d.cur_url)),g.pushstate&&history.pushState({tribe_date:g.date,tribe_params:g.params},g.page_title,d.cur_url),c(e).trigger("tribe_ev_ajaxSuccess").trigger("tribe_ev_monthView_ajaxSuccess")}})):g.url_params.length?a.location=d.cur_url+"?"+g.url_params:a.location=d.cur_url)}var q=c("body"),r=c('[class^="tribe-events-nav-"] a'),s=f.get_url_param("tribe-bar-date"),t=c("#tribe-events"),u=c("#tribe-bar-date"),v=!1,w="/";"undefined"!=typeof i.events_base?w=i.events_base:r.length&&(w=r.first().attr("href").slice(0,-8)),d.default_permalinks&&(w=w.split("?")[0]),c(".tribe-events-calendar").length&&c("#tribe-events-bar").length&&s&&s.length>7&&(c("#tribe-bar-date-day").val(s.slice(-3)),u.val(s.substring(0,7)));var x="yyyy-mm";if("0"!==g.datepicker_format){var y=parseInt(g.datepicker_format),z="m"+g.datepicker_format.toString();x=d.datepicker_formats.month[y],s&&(s.length<=7&&(s+="-01"),u.val(tribeDateFormat(s,z)))}if(d.datepicker_opts={format:x,minViewMode:"months",autoclose:!0},u.bootstrapDatepicker(d.datepicker_opts).on("changeDate",function(a){g.mdate=a.date;var b=a.date.getFullYear(),e=("0"+(a.date.getMonth()+1)).slice(-2);if(v=!0,g.date=b+"-"+e,h.no_bar()||h.live_ajax()&&h.pushstate){if(g.ajax_running||g.updating_picker)return;g.filter_cats?d.cur_url=c("#tribe-events-header").data("baseurl")+g.date+"/":d.default_permalinks?d.cur_url=w:d.cur_url=w+g.date+"/",g.popping=!1,f.pre_ajax(function(){p()})}}),n(!0),c(e).on("tribe_ev_resizeComplete",function(){n(!0)}),h.pushstate&&!h.map_view()){var A="action=tribe_calendar&eventDate="+c("#tribe-events-header").data("date");d.params.length&&(A=A+"&"+d.params),g.category&&(A=A+"&tribe_event_category="+g.category),history.replaceState({tribe_params:A},g.page_title,location.href),c(a).on("popstate",function(a){var b=a.originalEvent.state;b&&(g.do_string=!1,g.pushstate=!1,g.popping=!0,g.params=b.tribe_params,f.pre_ajax(function(){p()}),f.set_form(g.params))})}c("#tribe-events").on("click",".tribe-events-nav-previous, .tribe-events-nav-next",function(a){if(a.preventDefault(),!g.ajax_running){var b=c(this).find("a");g.date=b.data("month"),g.mdate=g.date+"-01","0"!==g.datepicker_format?f.update_picker(tribeDateFormat(g.mdate,z)):f.update_picker(g.date),g.filter_cats?d.cur_url=c("#tribe-events-header").data("baseurl"):d.cur_url=b.attr("href"),d.default_permalinks&&(d.cur_url=d.cur_url.split("?")[0]),g.popping=!1,f.pre_ajax(function(){p()})}}).on("click","td.tribe-events-thismonth a",function(a){a.stopPropagation()}).on("click",'[id*="tribe-events-daynum-"] a',function(a){if(q.is(".tribe-mobile")){a.preventDefault();var b=c(this).closest(".mobile-trigger");k(b)}}).on("click",".mobile-trigger",function(a){q.is(".tribe-mobile")&&(a.preventDefault(),a.stopPropagation(),k(c(this)))}),f.snap("#tribe-bar-form","body","#tribe-events-footer .tribe-events-nav-previous, #tribe-events-footer .tribe-events-nav-next"),c("form#tribe-bar-form").on("submit",function(a){o(a)}),c(e).on("tribe_ev_runAjax",function(){p()}),c(e).on("tribe_ev_updatingRecurrence",function(){g.date=c("#tribe-events-header").data("date"),g.filter_cats?d.cur_url=c("#tribe-events-header").data("baseurl")+g.date+"/":d.default_permalinks?d.cur_url=w:d.cur_url=w+g.date+"/",g.popping=!1})})}(window,document,jQuery,tribe_ev.data,tribe_ev.events,tribe_ev.fn,tribe_ev.state,tribe_ev.tests,tribe_js_config,tribe_debug);
src/resources/js/tribe-events-bar.js CHANGED
@@ -165,10 +165,10 @@ var tribe_events_bar_action;
165
  'data-tribe-bar-order': i,
166
  'data-view' : displaying
167
  } ).html( [
168
- ' <a href="#">',
169
- ' <span class="tribe-icon-' + displaying + '">' + $view.text() + '</span>',
170
- '</a>'].join( "" )
171
- ).appendTo( '.tribe-bar-views-list' );
172
 
173
  } );
174
 
165
  'data-tribe-bar-order': i,
166
  'data-view' : displaying
167
  } ).html( [
168
+ ' <a href="#">',
169
+ ' <span class="tribe-icon-' + displaying + '">' + $view.text() + '</span>',
170
+ '</a>'].join( "" )
171
+ ).appendTo( '.tribe-bar-views-list' );
172
 
173
  } );
174
 
src/resources/js/tribe-events.js CHANGED
@@ -37,104 +37,104 @@ var tribe_debug = true;
37
 
38
  // @ifdef DEBUG
39
 
40
- /*!
41
- * JavaScript Debug - v0.4 - 6/22/2010
42
- * http://benalman.com/projects/javascript-debug-console-log/
43
- *
44
- * Copyright (c) 2010 "Cowboy" Ben Alman
45
- * Dual licensed under the MIT and GPL licenses.
46
- * http://benalman.com/about/license/
47
- *
48
- * With lots of help from Paul Irish!
49
- * http://paulirish.com/
50
- */
51
 
52
- window.debug = (function() {
53
- var window = this,
54
- aps = Array.prototype.slice,
55
- con = window.console,
56
- that = {},
57
- callback_func,
58
- callback_force,
59
- log_level = 9,
60
- log_methods = [ 'error', 'warn', 'info', 'debug', 'log' ],
61
- pass_methods = 'assert clear count dir dirxml exception group groupCollapsed groupEnd profile profileEnd table time timeEnd trace'.split( ' ' ),
62
- idx = pass_methods.length,
63
- logs = [];
64
-
65
- while ( --idx >= 0 ) {
66
- (function( method ) {
67
-
68
- that[ method ] = function() {
69
- log_level !== 0 && con && con[ method ]
70
- && con[ method ].apply( con, arguments );
71
- }
72
 
73
- })( pass_methods[idx] );
74
- }
75
 
76
- idx = log_methods.length;
77
- while ( --idx >= 0 ) {
78
- (function( idx, level ) {
79
 
80
- that[ level ] = function() {
81
- var args = aps.call( arguments ),
82
- log_arr = [ level ].concat( args );
83
 
84
- logs.push( log_arr );
85
- exec_callback( log_arr );
86
 
87
- if ( !con || !is_level( idx ) ) {
88
- return;
89
- }
90
 
91
- con.firebug ? con[ level ].apply( window, args )
92
- : con[ level ] ? con[ level ]( args )
93
- : con.log( args );
94
- };
95
 
96
- })( idx, log_methods[idx] );
97
- }
98
 
99
- function exec_callback( args ) {
100
- if ( callback_func && (callback_force || !con || !con.log) ) {
101
- callback_func.apply( window, args );
102
- }
103
  }
 
104
 
105
- that.setLevel = function( level ) {
106
- log_level = typeof level === 'number' ? level : 9;
107
- };
108
 
109
- function is_level( level ) {
110
- return log_level > 0
111
- ? log_level > level
112
- : log_methods.length + log_level <= level;
113
- }
114
 
115
- that.setCallback = function() {
116
- var args = aps.call( arguments ),
117
- max = logs.length,
118
- i = max;
119
 
120
- callback_func = args.shift() || null;
121
- callback_force = typeof args[0] === 'boolean' ? args.shift() : false;
122
 
123
- i -= typeof args[0] === 'number' ? args.shift() : max;
124
 
125
- while ( i < max ) {
126
- exec_callback( logs[i++] );
127
- }
128
- };
129
 
130
- return that;
131
- })();
132
 
133
- if ( Object.prototype.hasOwnProperty.call( window, 'tribe_ev' ) ) {
134
- tribe_ev.diagnostics = {
135
- init: []
136
- };
137
- }
138
  // @endif
139
 
140
  /**
@@ -318,22 +318,22 @@ Date.prototype.format = function( mask, utc ) {
318
  var name = id, string = /^[\w\-]+$/.test( id ) ? me.get( id ) : (name = 'template(string)', id); // no warnings
319
  var line = 1, body = (
320
  "try { " +
321
- (me.variable ? "var " + me.variable + " = this.stash;" : "with (this.stash) { ") +
322
- "this.ret += '" +
323
- string.
324
- replace( /\[\[/g, '\x11' ).replace( /\]\]/g, '\x13' ). // if you want other tag, just edit this line
325
- replace( /'(?![^\x11\x13]+?\x13)/g, '\\x27' ).
326
- replace( /^\s*|\s*$/g, '' ).
327
- replace( /\n/g,function() {
328
- return "';\nthis.line = " + (++line) + "; this.ret += '\\n"
329
- } ).
330
- replace( /\x11=raw(.+?)\x13/g, "' + ($1) + '" ).
331
- replace( /\x11=(.+?)\x13/g, "' + this.escapeHTML($1) + '" ).
332
- replace( /\x11(.+?)\x13/g, "'; $1; this.ret += '" ) +
333
- "'; " + (me.variable ? "" : "}") + "return this.ret;" +
334
- "} catch (e) { throw 'TemplateError: ' + e + ' (on " + name + "' + ' line ' + this.line + ')'; } " +
335
- "//@ sourceURL=" + name + "\n" // source map
336
- ).replace( /this\.ret \+= '';/g, '' );
337
  var func = new Function( body );
338
  var map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\x22': '&#x22;', '\x27': '&#x27;' };
339
  var escapeHTML = function( string ) {
37
 
38
  // @ifdef DEBUG
39
 
40
+ /*!
41
+ * JavaScript Debug - v0.4 - 6/22/2010
42
+ * http://benalman.com/projects/javascript-debug-console-log/
43
+ *
44
+ * Copyright (c) 2010 "Cowboy" Ben Alman
45
+ * Dual licensed under the MIT and GPL licenses.
46
+ * http://benalman.com/about/license/
47
+ *
48
+ * With lots of help from Paul Irish!
49
+ * http://paulirish.com/
50
+ */
51
 
52
+ window.debug = (function() {
53
+ var window = this,
54
+ aps = Array.prototype.slice,
55
+ con = window.console,
56
+ that = {},
57
+ callback_func,
58
+ callback_force,
59
+ log_level = 9,
60
+ log_methods = [ 'error', 'warn', 'info', 'debug', 'log' ],
61
+ pass_methods = 'assert clear count dir dirxml exception group groupCollapsed groupEnd profile profileEnd table time timeEnd trace'.split( ' ' ),
62
+ idx = pass_methods.length,
63
+ logs = [];
64
+
65
+ while ( --idx >= 0 ) {
66
+ (function( method ) {
67
+
68
+ that[ method ] = function() {
69
+ log_level !== 0 && con && con[ method ]
70
+ && con[ method ].apply( con, arguments );
71
+ }
72
 
73
+ })( pass_methods[idx] );
74
+ }
75
 
76
+ idx = log_methods.length;
77
+ while ( --idx >= 0 ) {
78
+ (function( idx, level ) {
79
 
80
+ that[ level ] = function() {
81
+ var args = aps.call( arguments ),
82
+ log_arr = [ level ].concat( args );
83
 
84
+ logs.push( log_arr );
85
+ exec_callback( log_arr );
86
 
87
+ if ( !con || !is_level( idx ) ) {
88
+ return;
89
+ }
90
 
91
+ con.firebug ? con[ level ].apply( window, args )
92
+ : con[ level ] ? con[ level ]( args )
93
+ : con.log( args );
94
+ };
95
 
96
+ })( idx, log_methods[idx] );
97
+ }
98
 
99
+ function exec_callback( args ) {
100
+ if ( callback_func && (callback_force || !con || !con.log) ) {
101
+ callback_func.apply( window, args );
 
102
  }
103
+ }
104
 
105
+ that.setLevel = function( level ) {
106
+ log_level = typeof level === 'number' ? level : 9;
107
+ };
108
 
109
+ function is_level( level ) {
110
+ return log_level > 0
111
+ ? log_level > level
112
+ : log_methods.length + log_level <= level;
113
+ }
114
 
115
+ that.setCallback = function() {
116
+ var args = aps.call( arguments ),
117
+ max = logs.length,
118
+ i = max;
119
 
120
+ callback_func = args.shift() || null;
121
+ callback_force = typeof args[0] === 'boolean' ? args.shift() : false;
122
 
123
+ i -= typeof args[0] === 'number' ? args.shift() : max;
124
 
125
+ while ( i < max ) {
126
+ exec_callback( logs[i++] );
127
+ }
128
+ };
129
 
130
+ return that;
131
+ })();
132
 
133
+ if ( Object.prototype.hasOwnProperty.call( window, 'tribe_ev' ) ) {
134
+ tribe_ev.diagnostics = {
135
+ init: []
136
+ };
137
+ }
138
  // @endif
139
 
140
  /**
318
  var name = id, string = /^[\w\-]+$/.test( id ) ? me.get( id ) : (name = 'template(string)', id); // no warnings
319
  var line = 1, body = (
320
  "try { " +
321
+ (me.variable ? "var " + me.variable + " = this.stash;" : "with (this.stash) { ") +
322
+ "this.ret += '" +
323
+ string.
324
+ replace( /\[\[/g, '\x11' ).replace( /\]\]/g, '\x13' ). // if you want other tag, just edit this line
325
+ replace( /'(?![^\x11\x13]+?\x13)/g, '\\x27' ).
326
+ replace( /^\s*|\s*$/g, '' ).
327
+ replace( /\n/g,function() {
328
+ return "';\nthis.line = " + (++line) + "; this.ret += '\\n"
329
+ } ).
330
+ replace( /\x11=raw(.+?)\x13/g, "' + ($1) + '" ).
331
+ replace( /\x11=(.+?)\x13/g, "' + this.escapeHTML($1) + '" ).
332
+ replace( /\x11(.+?)\x13/g, "'; $1; this.ret += '" ) +
333
+ "'; " + (me.variable ? "" : "}") + "return this.ret;" +
334
+ "} catch (e) { throw 'TemplateError: ' + e + ' (on " + name + "' + ' line ' + this.line + ')'; } " +
335
+ "//@ sourceURL=" + name + "\n" // source map
336
+ ).replace( /this\.ret \+= '';/g, '' );
337
  var func = new Function( body );
338
  var map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\x22': '&#x22;', '\x27': '&#x27;' };
339
  var escapeHTML = function( string ) {
src/resources/js/tribe-settings.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){function b(){a(".google-embed-size input").attr("checked")?a(".google-embed-field").slideDown():a(".google-embed-field").slideUp()}a(".tribe-field-dropdown_chosen select").chosen(),b(),a('[name="eventsDefaultVenueID"]').change(function(){}),a(".google-embed-size input").change(function(){b()})});
1
+ jQuery(document).ready(function(a){function b(){a(".google-embed-size input").attr("checked")?a(".google-embed-field").slideDown():a(".google-embed-field").slideUp()}a(".tribe-field-dropdown_chosen select").chosen(),b(),a(".google-embed-size input").change(b)});
src/views/modules/meta/details.php CHANGED
@@ -18,7 +18,7 @@ $start_time = tribe_get_start_date( null, false, $time_format );
18
  $start_ts = tribe_get_start_date( null, false, Tribe__Date_Utils::DBDATEFORMAT );
19
 
20
  $end_datetime = tribe_get_end_date();
21
- $end_date = tribe_get_end_date( null, false );
22
  $end_time = tribe_get_end_date( null, false, $time_format );
23
  $end_ts = tribe_get_end_date( null, false, Tribe__Date_Utils::DBDATEFORMAT );
24
 
18
  $start_ts = tribe_get_start_date( null, false, Tribe__Date_Utils::DBDATEFORMAT );
19
 
20
  $end_datetime = tribe_get_end_date();
21
+ $end_date = tribe_get_display_end_date( null, false );
22
  $end_time = tribe_get_end_date( null, false, $time_format );
23
  $end_ts = tribe_get_end_date( null, false, Tribe__Date_Utils::DBDATEFORMAT );
24
 
src/views/single-event.php CHANGED
@@ -30,7 +30,7 @@ $event_id = get_the_ID();
30
  <!-- Notices -->
31
  <?php tribe_the_notices() ?>
32
 
33
- <?php the_title( '<h2 class="tribe-events-single-event-title">', '</h2>' ); ?>
34
 
35
  <div class="tribe-events-schedule tribe-clearfix">
36
  <?php echo tribe_events_event_schedule_details( $event_id, '<h2>', '</h2>' ); ?>
30
  <!-- Notices -->
31
  <?php tribe_the_notices() ?>
32
 
33
+ <?php the_title( '<h1 class="tribe-events-single-event-title">', '</h1>' ); ?>
34
 
35
  <div class="tribe-events-schedule tribe-clearfix">
36
  <?php echo tribe_events_event_schedule_details( $event_id, '<h2>', '</h2>' ); ?>
tests.md CHANGED
@@ -43,5 +43,9 @@ Nothing different from a default Codeception environment so this command will ru
43
  Failing tests are ok in set up terms: the system works. Errors should be reported.
44
  Please refer to [Codeception documentation](http://codeception.com/docs) to learn about more run and configuaration options.
45
 
 
 
 
 
46
  ## Contributing to tests
47
  Should you come up with good utility methods, worthy database configurations and "cool additions" in general for the plugin tests feel free to open a PR and submit them for review.
43
  Failing tests are ok in set up terms: the system works. Errors should be reported.
44
  Please refer to [Codeception documentation](http://codeception.com/docs) to learn about more run and configuaration options.
45
 
46
+ If you'd like to run just the acceptance tests (or substitute for unir or functional) you can use a command like this:
47
+
48
+ vendor/bin/codecept run acceptance
49
+
50
  ## Contributing to tests
51
  Should you come up with good utility methods, worthy database configurations and "cool additions" in general for the plugin tests feel free to open a PR and submit them for review.
the-events-calendar.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: The Events Calendar
4
  Description: The Events Calendar is a carefully crafted, extensible plugin that lets you easily share your events. Beautiful. Solid. Awesome.
5
- Version: 4.0
6
  Author: Modern Tribe, Inc.
7
  Author URI: http://m.tri.be/1x
8
  Text Domain: the-events-calendar
2
  /*
3
  Plugin Name: The Events Calendar
4
  Description: The Events Calendar is a carefully crafted, extensible plugin that lets you easily share your events. Beautiful. Solid. Awesome.
5
+ Version: 4.0.1
6
  Author: Modern Tribe, Inc.
7
  Author URI: http://m.tri.be/1x
8
  Text Domain: the-events-calendar
vendor/tickets/common/codeception.dist.yml DELETED
@@ -1,63 +0,0 @@
1
- actor: Tester
2
- paths:
3
- tests: tests
4
- log: tests/_output
5
- data: tests/_data
6
- helpers: tests/_support
7
- settings:
8
- bootstrap: _bootstrap.php
9
- colors: true
10
- memory_limit: 1024M
11
- modules:
12
- config:
13
- Db:
14
- dsn: 'mysql:host=localhost;dbname=tec-tests'
15
- user: root
16
- password: password
17
- dump: tests/_data/wordpress.sql
18
- reconnect: true
19
- WPBrowser:
20
- url: 'http://tec.tri.be'
21
- adminUsername: admin
22
- adminPassword: password
23
- adminUrl: /wp-admin
24
- WPDb:
25
- dsn: 'mysql:host=localhost;dbname=tec-tests'
26
- user: root
27
- password: password
28
- dump: tests/_data/dump.sql
29
- populate: true
30
- cleanup: true
31
- url: 'http://tec.tri.be'
32
- tablePrefix: wptests_
33
- checkExistence: true
34
- update: true
35
- reconnect: true
36
- WPLoader:
37
- wpRootFolder: ~/www/wordpress
38
- dbName: tec-tests
39
- dbHost: localhost
40
- dbUser: root
41
- dbPassword: password
42
- wpDebug: true
43
- dbCharset: utf8
44
- dbCollate: ''
45
- tablePrefix: wptests_
46
- domain: tec.tri.be
47
- adminEmail: admin@tec.tri.ve
48
- title: 'Event Tickets Tests'
49
- phpBinary: php
50
- language: ''
51
- plugins:
52
- - tribe-common/tribe-common.php
53
- activatePlugins:
54
- - tribe-common/tribe-common.php
55
- WPWebDriver:
56
- url: 'http://tec.tri.be'
57
- browser: phantomjs
58
- port: 4444
59
- restart: true
60
- wait: 2
61
- adminUsername: admin
62
- adminPassword: password
63
- adminUrl: /wp-admin
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/tickets/common/src/Tribe/Admin/Notice/Plugin_Upgrade_Notice.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * When appropriate, displays a plugin upgrade message "inline" within the plugin
4
+ * admin screen.
5
+ *
6
+ * This is drawn from the Upgrade Notice section of the plugin readme.txt file (ie,
7
+ * the one belonging to the current stable accessible via WP SVN - at least by
8
+ * default).
9
+ */
10
+ class Tribe__Admin__Notice__Plugin_Upgrade_Notice {
11
+ /**
12
+ * Currently installed version of the plugin
13
+ *
14
+ * @var string
15
+ */
16
+ protected $current_version = '';
17
+
18
+ /**
19
+ * The plugin path as it is within the plugins directory, ie
20
+ * "some-plugin/main-file.php".
21
+ *
22
+ * @var string
23
+ */
24
+ protected $plugin_path = '';
25
+
26
+ /**
27
+ * Contains the plugin upgrade notice (empty if none are available).
28
+ *
29
+ * @var string
30
+ */
31
+ protected $upgrade_notice = '';
32
+
33
+
34
+ /**
35
+ * Test for and display any plugin upgrade messages (if any are available) inline
36
+ * beside the plugin listing itself.
37
+ *
38
+ * The optional third param is the object which actually checks to see if there
39
+ * are any upgrade notices worth displaying. If not provided, an object of the
40
+ * default type will be created (which connects to WP SVN).
41
+ *
42
+ * @param string $current_version
43
+ * @param string $plugin_path (ie "plugin-dir/main-file.php")
44
+ */
45
+ public function __construct( $current_version, $plugin_path ) {
46
+ $this->current_version = $current_version;
47
+ $this->plugin_path = $plugin_path;
48
+
49
+ add_action( "in_plugin_update_message-$plugin_path", array( $this, 'maybe_run' ) );
50
+ }
51
+
52
+ /**
53
+ * Test if there is a plugin upgrade notice and displays it if so.
54
+ *
55
+ * Expects to fire during "in_plugin_update_message-{plugin_path}", therefore
56
+ * this should only run if WordPress has detected that an upgrade is indeed
57
+ * available.
58
+ */
59
+ public function maybe_run() {
60
+ $this->test_for_upgrade_notice();
61
+
62
+ if ( $this->upgrade_notice ) {
63
+ $this->display_message();
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Tests to see if an upgrade notice is available.
69
+ */
70
+ protected function test_for_upgrade_notice() {
71
+ $cache_key = $this->cache_key();
72
+ $this->upgrade_notice = get_transient( $cache_key );
73
+
74
+ if ( false === $this->upgrade_notice ) {
75
+ $this->discover_upgrade_notice();
76
+ }
77
+
78
+ set_transient( $cache_key, $this->upgrade_notice, $this->cache_expiration() );
79
+ }
80
+
81
+ /**
82
+ * Returns a cache key unique to the current plugin path and version, that
83
+ * still fits within the 45-char limit of regular WP transient keys.
84
+ *
85
+ * @return string
86
+ */
87
+ protected function cache_key() {
88
+ return 'tribe_plugin_upgrade_notice-' . hash( 'crc32b', $this->plugin_path . $this->current_version );
89
+ }
90
+
91
+ /**
92
+ * Returns the period of time (in seconds) for which to cache plugin upgrade messages.
93
+ *
94
+ * @return int
95
+ */
96
+ protected function cache_expiration() {
97
+ /**
98
+ * Number of seconds to cache plugin upgrade messages for.
99
+ *
100
+ * Defaults to one day, which provides a decent balance between efficiency savings
101
+ * and allowing for the possibility that some upgrade messages may be changed or
102
+ * rescinded.
103
+ *
104
+ * @var int $cache_expiration
105
+ */
106
+ return (int) apply_filters( 'tribe_plugin_upgrade_notice_expiration', DAY_IN_SECONDS, $this->plugin_path );
107
+ }
108
+
109
+ /**
110
+ * Looks at the current stable plugin readme.txt and parses to try and find the first
111
+ * available upgrade notice relating to a plugin version higher than this one.
112
+ *
113
+ * By default, WP SVN is the source.
114
+ */
115
+ protected function discover_upgrade_notice() {
116
+ /**
117
+ * The URL for the current plugin readme.txt file.
118
+ *
119
+ * @var string $url
120
+ * @var string $plugin_path
121
+ */
122
+ $readme_url = apply_filters( 'tribe_plugin_upgrade_readme_url',
123
+ $this->form_wp_svn_readme_url(),
124
+ $this->plugin_path
125
+ );
126
+
127
+ if ( ! empty( $readme_url ) ) {
128
+ $response = wp_safe_remote_get( $readme_url );
129
+ }
130
+
131
+ if ( ! empty( $response ) && ! is_wp_error( $response ) ) {
132
+ $readme = $response['body'];
133
+ }
134
+
135
+ if ( ! empty( $readme ) ) {
136
+ $this->parse_for_upgrade_notice( $readme );
137
+ $this->format_upgrade_notice();
138
+ }
139
+
140
+ /**
141
+ * The upgrade notice for the current plugin (may be empty).
142
+ *
143
+ * @var string $upgrade_notice
144
+ * @var string $plugin_path
145
+ */
146
+ return apply_filters( 'tribe_plugin_upgrade_notice',
147
+ $this->upgrade_notice,
148
+ $this->plugin_path
149
+ );
150
+ }
151
+
152
+ /**
153
+ * Forms the expected URL to the trunk readme.txt file as it is on WP SVN
154
+ * or an empty string if for any reason it cannot be determined.
155
+ *
156
+ * @return string
157
+ */
158
+ protected function form_wp_svn_readme_url() {
159
+ $parts = explode( '/', $this->plugin_path );
160
+ $slug = empty( $parts[0] ) ? '' : $parts[0];
161
+ return esc_url( "https://plugins.svn.wordpress.org/$slug/trunk/readme.txt" );
162
+ }
163
+
164
+ /**
165
+ * Given a standard Markdown-format WP readme.txt file, finds the first upgrade
166
+ * notice (if any) for a version higher than $this->current_version.
167
+ *
168
+ * @param string $readme
169
+ * @return string
170
+ */
171
+ protected function parse_for_upgrade_notice( $readme ) {
172
+ $in_upgrade_notice = false;
173
+ $in_version_notice = false;
174
+ $readme_text = fopen( "data:://text/plain,$readme", 'r' );
175
+
176
+ while ( $line = fgets( $readme_text ) ) {
177
+ // Once we leave the Upgrade Notice section (ie, we encounter a new section header), bail
178
+ if ( $in_upgrade_notice && 0 === strpos( $line, '==' ) ) {
179
+ break;
180
+ }
181
+
182
+ // Look out for the start of the Upgrade Notice section
183
+ if ( ! $in_upgrade_notice && preg_match( '/^==\s*Upgrade\s+Notice\s*==/i', $line ) ) {
184
+ $in_upgrade_notice = true;
185
+ }
186
+
187
+ // Also test to see if we have left the version specific note (ie, we encounter a new sub heading or header)
188
+ if ( $in_upgrade_notice && $in_version_notice && 0 === strpos( $line, '=' ) ) {
189
+ break;
190
+ }
191
+
192
+ // Look out for the first applicable version-specific note within the Upgrade Notice section
193
+ if ( $in_upgrade_notice && ! $in_version_notice && preg_match( '/^=\s*([0-9\.]{3,})\s*=/', $line, $matches ) ) {
194
+ // Is this a higher version than currently installed?
195
+ if ( version_compare( $matches[1], $this->current_version, '>' ) ) {
196
+ $in_version_notice = true;
197
+ }
198
+ }
199
+
200
+ // Copy the details of the upgrade notice for the first higher version we find
201
+ if ( $in_upgrade_notice && $in_version_notice ) {
202
+ $this->upgrade_notice .= $line;
203
+ }
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Convert the plugin version header and any links from Markdown to HTML.
209
+ */
210
+ protected function format_upgrade_notice() {
211
+ // Convert [links](http://...) to <a href="..."> tags
212
+ $this->upgrade_notice = preg_replace(
213
+ '/\[([^\]]*)\]\(([^\)]*)\)/',
214
+ '<a href="${2}">${1}</a>',
215
+ $this->upgrade_notice
216
+ );
217
+
218
+ // Convert =4.0= headings to <h4 class="version">4.0</h4> tags
219
+ $this->upgrade_notice = preg_replace(
220
+ '/=\s*([a-zA-Z0-9\.]{3,})\s*=/',
221
+ '<h4 class="version">${1}</h4>',
222
+ $this->upgrade_notice
223
+ );
224
+ }
225
+
226
+ /**
227
+ * Render the actual upgrade notice.
228
+ *
229
+ * Please note if plugin-specific styling is required for the message, you can
230
+ * use an ID generated by WordPress for one of the message's parent elements
231
+ * which takes the form "{plugin_name}-update". Example:
232
+ *
233
+ * #the-events-calendar-update .tribe-plugin-update-message { ... }
234
+ */
235
+ public function display_message() {
236
+ $notice = wp_kses_post( $this->upgrade_notice );
237
+ echo "<div class='tribe-plugin-update-message'> $notice </div>";
238
+ }
239
+ }
vendor/tickets/common/src/Tribe/Date_Utils.php CHANGED
@@ -721,6 +721,68 @@ if ( ! class_exists( 'Tribe__Date_Utils' ) ) {
721
  _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_timestamp' );
722
  return self::is_timestamp( $timestamp );
723
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
724
  // @codingStandardsIgnoreEnd
725
  }
 
726
  }
721
  _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_timestamp' );
722
  return self::is_timestamp( $timestamp );
723
  }
724
+
725
+ /**
726
+ * Gets the timestamp of a day in week, month and year context.
727
+ *
728
+ * Kudos to [icedwater StackOverflow user](http://stackoverflow.com/users/1091386/icedwater) in
729
+ * [his answer](http://stackoverflow.com/questions/924246/get-the-first-or-last-friday-in-a-month).
730
+ *
731
+ * Usage examples:
732
+ * "The second Wednesday of March 2015" - `get_day_timestamp( 3, 2, 3, 2015, 1)`
733
+ * "The last Friday of December 2015" - `get_day_timestamp( 5, 1, 12, 2015, -1)`
734
+ * "The first Monday of April 2016 - `get_day_timestamp( 1, 1, 4, 2016, 1)`
735
+ * "The penultimate Thursday of January 2012" - `get_day_timestamp( 4, 2, 1, 2012, -1)`
736
+ *
737
+ * @param int $day_of_week The day representing the number in the week, Monday is `1`, Tuesday is `2`, Sunday is `7`
738
+ * @param int $week_in_month The week number in the month; first week is `1`, second week is `2`; when direction is reverse
739
+ * then `1` is last week of the month, `2` is penultimate week of the month and so on.
740
+ * @param int $month The month number in the year, January is `1`
741
+ * @param int $year The year number, e.g. "2015"
742
+ * @param int $week_direction Either `1` or `-1`; the direction for the search referring to the week, defaults to `1`
743
+ * to specify weeks in natural order so:
744
+ * $week_direction `1` and $week_in_month `1` means "first week of the month"
745
+ * $week_direction `1` and $week_in_month `3` means "third week of the month"
746
+ * $week_direction `-1` and $week_in_month `1` means "last week of the month"
747
+ * $week_direction `-1` and $week_in_month `2` means "penultimmate week of the month"
748
+ *
749
+ * @return int The day timestamp
750
+ */
751
+ public static function get_weekday_timestamp( $day_of_week, $week_in_month, $month, $year, $week_direction = 1 ) {
752
+ if (
753
+ ! (
754
+ is_numeric( $day_of_week )
755
+ && is_numeric( $week_in_month )
756
+ && is_numeric( $month )
757
+ && is_numeric( $year )
758
+ && is_numeric( $week_direction )
759
+ && in_array( $week_direction, array( - 1, 1 ) )
760
+ )
761
+ ) {
762
+ return false;
763
+ }
764
+
765
+ if ( $week_direction > 0 ) {
766
+ $startday = 1;
767
+ } else {
768
+ $startday = date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
769
+ }
770
+
771
+ $start = mktime( 0, 0, 0, $month, $startday, $year );
772
+ $weekday = date( 'N', $start );
773
+
774
+ if ( $week_direction * $day_of_week >= $week_direction * $weekday ) {
775
+ $offset = - $week_direction * 7;
776
+ } else {
777
+ $offset = 0;
778
+ }
779
+
780
+ $offset += $week_direction * ( $week_in_month * 7 ) + ( $day_of_week - $weekday );
781
+
782
+ return mktime( 0, 0, 0, $month, $startday + $offset, $year );
783
+ }
784
+
785
  // @codingStandardsIgnoreEnd
786
  }
787
+
788
  }
vendor/tickets/common/src/Tribe/Main.php CHANGED
@@ -17,7 +17,7 @@ class Tribe__Main {
17
  const OPTIONNAME = 'tribe_events_calendar_options';
18
  const OPTIONNAMENETWORK = 'tribe_events_calendar_network_options';
19
 
20
- const VERSION = '3.12a1';
21
  const FEED_URL = 'https://theeventscalendar.com/feed/';
22
 
23
  protected $plugin_context;
17
  const OPTIONNAME = 'tribe_events_calendar_options';
18
  const OPTIONNAMENETWORK = 'tribe_events_calendar_network_options';
19
 
20
+ const VERSION = '4.0.1';
21
  const FEED_URL = 'https://theeventscalendar.com/feed/';
22
 
23
  protected $plugin_context;
vendor/tickets/common/src/resources/css/tribe-common-admin.css CHANGED
@@ -20,6 +20,32 @@ td.tribe_message {padding-bottom: 10px !important;}
20
  #tribe-upgrade {margin:20px 0 30px; border:1px solid #ccc; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; padding:0 20px 20px; background:#f6f6f6;}
21
  #tribe-upgrade .message {border-style:solid; border-width:1px; padding:6px 12px; -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; background-color:#FFFFE0; border-color:#E6DB55;}
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  /* = Settings Screen
24
  =============================================*/
25
  .tribe-settings-form { max-width: 1000px; }
@@ -346,9 +372,6 @@ only screen and (min--moz-device-pixel-ratio: 2),
346
  only screen and (-o-min-device-pixel-ratio: 2/1),
347
  only screen and (-webkit-min-device-pixel-ratio: 2),
348
  only screen and (min-device-pixel-ratio: 2) {
349
- .events-cal #icon-edit {
350
- background-image: url(../images/events-screen-icon@2x.png);
351
- }
352
  #tribe-loading span {
353
  background-image: url(../images/tribe-loading@2x.gif);
354
  }
20
  #tribe-upgrade {margin:20px 0 30px; border:1px solid #ccc; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; padding:0 20px 20px; background:#f6f6f6;}
21
  #tribe-upgrade .message {border-style:solid; border-width:1px; padding:6px 12px; -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; background-color:#FFFFE0; border-color:#E6DB55;}
22
 
23
+ /* = Plugin Screen
24
+ =============================================*/
25
+ table.plugins .tribe-plugin-update-message {
26
+ background: #d54e21; /* taken from colour scheme in list-tables.css */
27
+ color: white;
28
+ display: inline-table;
29
+ padding: 10px 12px;
30
+ margin: 6px 0px;
31
+ }
32
+
33
+ table.plugins .tribe-plugin-update-message h4 {
34
+ display: inline;
35
+ font-weight: bold;
36
+ margin-right: 8px;
37
+ }
38
+
39
+ table.plugins .tribe-plugin-update-message h4:after {
40
+ content: ' \00BB ';
41
+ }
42
+
43
+
44
+ table.plugins .tribe-plugin-update-message a {
45
+ color: white;
46
+ text-decoration: underline;
47
+ }
48
+
49
  /* = Settings Screen
50
  =============================================*/
51
  .tribe-settings-form { max-width: 1000px; }
372
  only screen and (-o-min-device-pixel-ratio: 2/1),
373
  only screen and (-webkit-min-device-pixel-ratio: 2),
374
  only screen and (min-device-pixel-ratio: 2) {
 
 
 
375
  #tribe-loading span {
376
  background-image: url(../images/tribe-loading@2x.gif);
377
  }
vendor/tickets/common/src/resources/images/tribe-loading@2x.gif ADDED
Binary file
vendor/tickets/common/tribe-autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ $src = dirname( __FILE__ ) . '/src';
3
+ require_once $src . '/Tribe/Autoloader.php';
4
+
5
+ $autoloader = Tribe__Autoloader::instance();
6
+ $autoloader->register_prefix('Tribe__',$src);
7
+ $autoloader->register_autoloader();
vendor/tickets/event-tickets.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Description: Event Tickets allows you to sell tickets to events
4
- Version: 4.0
5
  Author: Modern Tribe, Inc.
6
  Author URI: http://m.tri.be/28
7
  License: GPLv2 or later
1
  <?php
2
  /*
3
  Description: Event Tickets allows you to sell tickets to events
4
+ Version: 4.0.1
5
  Author: Modern Tribe, Inc.
6
  Author URI: http://m.tri.be/28
7
  License: GPLv2 or later
vendor/tickets/readme.txt CHANGED
@@ -3,8 +3,8 @@
3
  Contributors: ModernTribe, borkweb, zbtirrell, barry.hughes, bordoni, brianjessee, brook-tribe, faction23, geoffgraham, ggwicz, jazbek, jbrinley, joshlimecuda, leahkoerper, lucatume, mastromktg, neillmcshea, nicosantos, peterchester, reid.peifer, roblagatta, shane.pearlman, thatdudebutch
4
  Tags: events, add-on, ticket sales, tickets, calendar, community, registration, api, dates, date, posts, workshop, conference, meeting, seminar, concert, summit, The Events Calendar, Events Calendar PRO, ticket integration, event ticketing, RSVP, Event Tickets, Event Tickets Plus
5
  Requires at least: 3.9
6
- Tested up to: 4.3.1
7
- Stable tag: 4.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -12,13 +12,55 @@ Event Tickets allows your visitors to RSVP to events on your site. Also works s
12
 
13
  == Description ==
14
 
15
- Event Tickets provides a simple way for visitors to RSVP to your events. You can add RSVP functionality to posts or pages. When paired with <a href="http://m.tri.be/18tg">The Events Calendar</a>, you can also add RSVP to your calendar listings.
 
 
16
 
17
- = Event Tickets =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  * Visitors can RSVP to events
20
- * Add RSVP to posts, pages, or event listings
 
21
  * Upgrade to <a href="http://m.tri.be/18th">Tickets Plus</a> to sell tickets using WooCommerce, Shopp, Easy Digital Downloads or WP-eCommerce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  == Installation ==
24
 
@@ -81,7 +123,7 @@ The plugin is produced by <a href="http://m.tri.be/18uc">Modern Tribe Inc</a>.
81
  * <a href="http://profiles.wordpress.org/users/mdbitz">Matthew Denton</a>
82
  * <a href="http://profiles.wordpress.org/users/neillmcshea">Neill McShea</a>
83
  * <a href="http://profiles.wordpress.org/users/mastromktg">Nick Mastromattei</a>
84
- * <a href="http://profiles.wordpress.org/users/nicosantos”>Nico Santo</a>
85
  * <a href="http://profiles.wordpress.org/users/peterchester">Peter Chester</a>
86
  * <a href="http://profiles.wordpress.org/users/roblagatta">Rob La Gatta</a>
87
  * <a href="http://profiles.wordpress.org/users/reid.peifer">Reid Peifer</a>
@@ -131,12 +173,17 @@ Our Premium Plugins:
131
  * <a href="http://m.tri.be/18ul" target="_blank">The Events Calendar PRO</a>
132
  * <a href="http://m.tri.be/18uo" target="_blank">The Events Calendar: Eventbrite Tickets</a>
133
  * <a href="http://m.tri.be/18uu" target="_blank">The Events Calendar: Community Events</a>
134
- * <a href="http://m.tri.be/18uy" target="_blank">The Events Calendar: Community Tickets
135
  * <a href="http://m.tri.be/18v0" target="_blank">The Events Calendar: Facebook Events</a>
136
  * <a href="http://m.tri.be/18v2" target="_blank">The Events Calendar: Filter Bar</a>
137
 
138
  == Changelog ==
139
 
 
 
 
 
 
140
  = [4.0] 2015-12-02 =
141
 
142
  * Initial release
3
  Contributors: ModernTribe, borkweb, zbtirrell, barry.hughes, bordoni, brianjessee, brook-tribe, faction23, geoffgraham, ggwicz, jazbek, jbrinley, joshlimecuda, leahkoerper, lucatume, mastromktg, neillmcshea, nicosantos, peterchester, reid.peifer, roblagatta, shane.pearlman, thatdudebutch
4
  Tags: events, add-on, ticket sales, tickets, calendar, community, registration, api, dates, date, posts, workshop, conference, meeting, seminar, concert, summit, The Events Calendar, Events Calendar PRO, ticket integration, event ticketing, RSVP, Event Tickets, Event Tickets Plus
5
  Requires at least: 3.9
6
+ Tested up to: 4.4
7
+ Stable tag: 4.0.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
12
 
13
  == Description ==
14
 
15
+ ><strong>A note about support:</strong> We’re here to help troubleshoot bugs, but should set expectations early that the support forums at WordPress.org are only checked once a week.
16
+ >
17
+ > Users looking for more timely/in-depth support are encouraged to check out <a href="http://m.tri.be/18th" target="_blank" title="[new window]">Event Tickets Plus</a>.
18
 
19
+ Event Tickets provides a simple way for visitors to RSVP to your events. As a standalone plugin, it enables you to add RSVP functionality to posts or pages. When paired with The Events Calendar, you can add that same RSVP functionality directly to your event listings.
20
+
21
+ Admins are able to access RSVP information from the backend, allowing them to check in registered attendees with ease when your event begins. For free events, Events Tickets allows you to own the entire event management process within your WordPress site.
22
+
23
+ = BUILT SOLID & SUPPORTED =
24
+
25
+ The team at Modern Tribe stands by our work and offers light support every Wednesday to the community via the WordPress.org support forums. Feel free to ask a question if you're having a problem with implementation or if you find bugs. Looking for help NOW or need a deeper level of support? Add the <a href="http://m.tri.be/18th">premium add-on plugin</a> and you get access to premium support forums with 24-48 hour response times on weekdays.
26
+
27
+ Enjoy using Event Tickets, know how to get under the hood and want to make money helping people? We're growing our community team and would love to hear from you. If you’re interested, <a href="http://m.tri.be/mk">check this out!</a>
28
+
29
+ = PLUG-N-PLAY & HIGHLY CUSTOMIZABLE =
30
+
31
+ Event Tickets is built to work out of the box: it doesn’t use a shortcode (nor is one available). Just turn it on, configure the settings to match your needs and you'll be taking RSVPs within minutes.
32
+
33
+ By developers, for developers... it's ready to be the foundation for your wildest hack sessions. Complete with a skeleton stylesheet to theme fast and efficiently, loads of tools including partial template overrides, a host of template tags, hooks and filters, <a href="http://m.tri.be/eu">careful documentation</a>, as well as a <a href="https://github.com/moderntribe">library of code snippets</a> on GitHub. Events Tickets is built FOR people who build websites.
34
+
35
+ Whether your vision is big or small, we have you in mind.
36
+
37
+ = FEATURES =
38
+
39
+ Just getting started? Definitely watch and read through the <a href="http://m.tri.be/18ti">New User Primer</a> before going much further.
40
 
41
  * Visitors can RSVP to events
42
+ * Add RSVP to posts, pages, or any custom post type
43
+ * Works out of the box with The Events Calendar
44
  * Upgrade to <a href="http://m.tri.be/18th">Tickets Plus</a> to sell tickets using WooCommerce, Shopp, Easy Digital Downloads or WP-eCommerce
45
+ * Completely responsive from mobile to tablet to desktop
46
+ * Tested on the major theme frameworks such as Avada, Genesis, Woo Themes, Thesis and many more.
47
+ * Internationalized & Translated
48
+ * Extensive Template Tags for Customization
49
+ * Hook & Filters up the wazoo
50
+
51
+ Looking for something else?
52
+
53
+
54
+ * Sell tickets, collect sales, and manage attendees all from within your WordPress dashboard! Combine our <a href="http://m.tri.be/18wg">Event Tickets Plus add-on</a> with your favorite ecommerce plugin (WooCommerce, Shopp, Easy Digital Downloads, or WP E-commerce).
55
+ * <a href="https://wordpress.org/plugins/the-events-calendar/" target="_blank">The Events Calendar</a> is the most popular calendar solution for WordPress. Team it up with Event Tickets and see the real magic happen.
56
+ * <a href="http://m.tri.be/2c">Events Calendar PRO</a>: recurring events, a whole range of new views ( week / map / photo / venue / organizer) & widgets (calendar / featured venue / week / event countdown), custom event attributes, default content, location search and a lot more.
57
+ * Have so many amazing events that your users get overwhelmed? Drop some filters on them with the <a href="http://m.tri.be/52" target="_blank">Filter Bar plugin</a>.
58
+ * Get your community involved by letting them submit events with our <a href="http://m.tri.be/18uu" target="_blank">Community Events</a> plugin. Take it to the next level by letting them sell tickets with the <a href="http://m.tri.be/18uy" target="_blank">Community Tickets</a> add-on!
59
+ <a href="https://www.facebook.com/theeventscalendar/" target="_blank">Join us on Facebook</a> to be part of our active community, check us out <a href="https://twitter.com/TheEventsCal" target="_blank">on Twitter</a>, and <a href="http://m.tri.be/rm">sign up for our newsletter</a> for release announcements and discounts.
60
+
61
+ = SUBMITTING PATCHES =
62
+
63
+ If you’ve identified a bug and want to submit a patch, we’d welcome it at our <a href="https://github.com/moderntribe/events-tickets" target="_blank">GitHub page for Event Tickets.</a> Simply cue up your proposed patch as a pull request, and we’ll review as part of our release cycle and merge into the codebase if appropriate from there. (If a pull request is rejected, we’ll do our best to tell you why). Users whose pull requests are accepted will receive credit in the plugin’s changelog. For more information, check out the readme at our GitHub page. Happy coding!
64
 
65
  == Installation ==
66
 
123
  * <a href="http://profiles.wordpress.org/users/mdbitz">Matthew Denton</a>
124
  * <a href="http://profiles.wordpress.org/users/neillmcshea">Neill McShea</a>
125
  * <a href="http://profiles.wordpress.org/users/mastromktg">Nick Mastromattei</a>
126
+ * <a href="http://profiles.wordpress.org/users/nicosantos">Nico Santo</a>
127
  * <a href="http://profiles.wordpress.org/users/peterchester">Peter Chester</a>
128
  * <a href="http://profiles.wordpress.org/users/roblagatta">Rob La Gatta</a>
129
  * <a href="http://profiles.wordpress.org/users/reid.peifer">Reid Peifer</a>
173
  * <a href="http://m.tri.be/18ul" target="_blank">The Events Calendar PRO</a>
174
  * <a href="http://m.tri.be/18uo" target="_blank">The Events Calendar: Eventbrite Tickets</a>
175
  * <a href="http://m.tri.be/18uu" target="_blank">The Events Calendar: Community Events</a>
176
+ * <a href="http://m.tri.be/18uy" target="_blank">The Events Calendar: Community Tickets</a>
177
  * <a href="http://m.tri.be/18v0" target="_blank">The Events Calendar: Facebook Events</a>
178
  * <a href="http://m.tri.be/18v2" target="_blank">The Events Calendar: Filter Bar</a>
179
 
180
  == Changelog ==
181
 
182
+ = [4.0.1] 2015-12-10 =
183
+
184
+ * Tweak - Removed The Events Calendar-specific fields from the Attendees Report as defaults. The Events Calendar will now hook into the report and inject event-specific fields
185
+ * Fix - Fixed issue where a retina-friendly loading gif was 404ing
186
+
187
  = [4.0] 2015-12-02 =
188
 
189
  * Initial release
vendor/tickets/src/Tribe/Main.php CHANGED
@@ -9,7 +9,7 @@ class Tribe__Tickets__Main {
9
  /**
10
  * Current version of this plugin
11
  */
12
- const VERSION = '4.0';
13
 
14
  /**
15
  * Min required The Events Calendar version
9
  /**
10
  * Current version of this plugin
11
  */
12
+ const VERSION = '4.0.1';
13
 
14
  /**
15
  * Min required The Events Calendar version
vendor/tickets/src/Tribe/RSVP.php CHANGED
@@ -282,7 +282,7 @@ class Tribe__Tickets__RSVP extends Tribe__Tickets__Tickets {
282
  $qty = max( intval( $_POST[ "quantity_{$product_id}" ] ), 0 );
283
 
284
  // Throw an error if Qty is bigger then Remaining
285
- if ( $qty > $ticket->remaining() ){
286
  $url = add_query_arg( 'rsvp_error', 2, get_permalink( $event_id ) );
287
  wp_redirect( esc_url_raw( $url ) );
288
  die;
282
  $qty = max( intval( $_POST[ "quantity_{$product_id}" ] ), 0 );
283
 
284
  // Throw an error if Qty is bigger then Remaining
285
+ if ( $ticket->managing_stock() && $qty > $ticket->remaining() ) {
286
  $url = add_query_arg( 'rsvp_error', 2, get_permalink( $event_id ) );
287
  wp_redirect( esc_url_raw( $url ) );
288
  die;
vendor/tickets/src/admin-views/attendees.php CHANGED
@@ -4,6 +4,7 @@ $this->attendees_table->prepare_items();
4
  $event_id = $this->attendees_table->event->ID;
5
  $event = $this->attendees_table->event;
6
  $tickets = Tribe__Tickets__Tickets::get_event_tickets( $event_id );
 
7
 
8
  $checkedin = Tribe__Tickets__Tickets::get_event_checkedin_attendees_count( $event_id );
9
  $total_sold = 0;
@@ -16,18 +17,6 @@ foreach ( $tickets as $ticket ) {
16
  $total_completed = $total_sold - $total_pending;
17
  }
18
 
19
- if ( function_exists( 'tribe_has_venue' ) && tribe_has_venue( $event_id ) ) {
20
- $venue_id = tribe_get_venue_id( $event_id );
21
-
22
- $url = get_post_meta( $venue_id, '_VenueURL', true );
23
- if ( $url ) {
24
- $url_path = parse_url( $url, PHP_URL_PATH );
25
- $display_url = parse_url( $url, PHP_URL_HOST );
26
- $display_url .= empty( $url_path ) && $url_path !== '/' ? '/&hellip;' : '';
27
- $display_url = apply_filters( 'tribe_venue_display_url', $display_url, $url, $venue_id );
28
- }
29
- }
30
-
31
  ?>
32
 
33
  <div class="wrap tribe-attendees-page">
@@ -42,53 +31,26 @@ if ( function_exists( 'tribe_has_venue' ) && tribe_has_venue( $event_id ) ) {
42
  <?php do_action( 'tribe_events_tickets_attendees_event_details_top', $event_id ); ?>
43
 
44
  <ul>
45
- <?php if ( function_exists( 'tribe_get_start_date' ) ): ?>
46
- <li>
47
- <strong><?php esc_html_e( 'Start Date / Time:', 'event-tickets' ) ?></strong>
48
- <?php echo tribe_get_start_date( $event_id, false, tribe_get_datetime_format( true ) ) ?>
49
- </li>
50
-
51
- <li>
52
- <strong><?php esc_html_e( 'End Date / Time:', 'event-tickets' ) ?></strong>
53
- <?php echo tribe_get_end_date( $event_id, false, tribe_get_datetime_format( true ) ); ?>
54
- </li>
55
- <?php endif; ?>
56
-
57
- <?php if ( function_exists( 'tribe_has_venue' ) && tribe_has_venue( $event_id ) ) {
58
  ?>
59
-
60
- <li class="venue-name">
61
- <strong><?php echo tribe_get_venue_label_singular(); ?>: </strong>
62
- <a href="<?php echo get_edit_post_link( $venue_id ); ?>" title="<?php esc_html_e( 'Edit Venue', 'event-tickets' ); ?>"><?php echo tribe_get_venue( $event_id ) ?></a>
63
- </li>
64
-
65
- <li class="venue-address">
66
- <strong><?php _e( 'Address:', 'event-tickets' ); ?> </strong>
67
- <?php echo tribe_get_full_address( $venue_id ); ?>
68
  </li>
69
-
70
  <?php
71
- if ( $phone = tribe_get_phone( $venue_id ) ) {
72
- ?>
73
- <li class="venue-phone">
74
- <strong><?php echo esc_html( __( 'Phone:', 'event-tickets' ) ); ?> </strong>
75
- <?php echo esc_html( $phone ); ?>
76
- </li>
77
- <?php
78
- }//end if
79
-
80
- if ( $url ) {
81
- ?>
82
- <li class="venue-url">
83
- <strong><?php echo esc_html( __( 'Website:', 'event-tickets' ) ); ?> </strong>
84
- <a target="_blank" href="<?php echo esc_url( $url ); ?>">
85
- <?php echo esc_html( $display_url ); ?>
86
- </a>
87
- </li>
88
- <?php
89
- }//end if
90
- }
91
- ?>
92
  </ul>
93
  <?php do_action( 'tribe_events_tickets_attendees_event_details_bottom', $event_id ); ?>
94
  </div>
4
  $event_id = $this->attendees_table->event->ID;
5
  $event = $this->attendees_table->event;
6
  $tickets = Tribe__Tickets__Tickets::get_event_tickets( $event_id );
7
+ $post_type_object = get_post_type_object( $event->post_type );
8
 
9
  $checkedin = Tribe__Tickets__Tickets::get_event_checkedin_attendees_count( $event_id );
10
  $total_sold = 0;
17
  $total_completed = $total_sold - $total_pending;
18
  }
19
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  ?>
21
 
22
  <div class="wrap tribe-attendees-page">
31
  <?php do_action( 'tribe_events_tickets_attendees_event_details_top', $event_id ); ?>
32
 
33
  <ul>
34
+ <?php
35
+ /**
36
+ * Provides an action that allows for the injections of fields at the top of the event details meta ul
37
+ *
38
+ * @var $event_id
39
+ */
40
+ do_action( 'tribe_tickets_attendees_event_details_list_top', $event_id );
 
 
 
 
 
 
41
  ?>
42
+ <li>
43
+ <strong><?php esc_html_e( 'Post Type:', 'event-tickets' ); ?></strong>
44
+ <?php echo esc_html( $post_type_object->labels->singular_name ); ?>
 
 
 
 
 
 
45
  </li>
 
46
  <?php
47
+ /**
48
+ * Provides an action that allows for the injections of fields at the bottom of the event details meta ul
49
+ *
50
+ * @var $event_id
51
+ */
52
+ do_action( 'tribe_tickets_attendees_event_details_list_bottom', $event_id );
53
+ ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  </ul>
55
  <?php do_action( 'tribe_events_tickets_attendees_event_details_bottom', $event_id ); ?>
56
  </div>