Version Description
Download this release
Release Info
Developer | calvinyeh |
Plugin | All-in-One Event Calendar |
Version | 2.5.24 |
Comparing to | |
See all releases |
Code changes from version 2.5.23 to 2.5.24
- all-in-one-event-calendar.php +23 -23
- app/config/constants.php +476 -476
- app/controller/calendar-feeds.php +65 -65
- app/controller/content-filter.php +44 -44
- app/controller/extension-license.php +96 -96
- app/controller/extension.php +253 -253
- app/controller/front.php +1155 -1149
- app/controller/import-export.php +91 -91
- app/controller/javascript-widget.php +232 -232
- app/controller/javascript.php +901 -901
- app/controller/shutdown.php +84 -84
- app/model/api/api-abstract.php +585 -526
- app/model/api/api-features.php +42 -19
- app/model/api/api-feeds.php +308 -308
- app/model/api/api-registration.php +238 -238
- app/model/api/api-settings.php +1 -1
- app/model/api/api-ticketing.php +863 -863
- app/model/app.php +18 -18
- app/model/event-compatibility.php +89 -89
- app/model/event.php +880 -880
- app/model/event/creating.php +489 -486
- app/model/event/entity.php +355 -355
- app/model/event/instance.php +368 -368
- app/model/event/legacy.php +122 -122
- app/model/event/parent.php +345 -345
- app/model/event/taxonomy.php +170 -170
- app/model/event/trashing.php +186 -186
- app/model/filter/auth_ids.php +3 -3
- app/model/filter/cat_ids.php +3 -3
- app/model/filter/instance_ids.php +3 -3
- app/model/filter/int.php +55 -55
- app/model/filter/interface.php +27 -27
- app/model/filter/post_ids.php +3 -3
- app/model/filter/tag_ids.php +3 -3
- app/model/filter/taxonomy.php +79 -79
- app/model/meta-user.php +79 -79
- app/model/meta.php +166 -166
- app/model/option.php +98 -98
- app/model/review.php +165 -165
- app/model/search.php +863 -863
- app/model/settings-view.php +144 -144
- app/model/settings.php +1049 -1049
- app/model/taxonomy.php +174 -174
- app/view/admin/abstract.php +53 -53
- app/view/admin/add-new-event.php +559 -534
- app/view/admin/add-ons.php +80 -80
- app/view/admin/all-events.php +239 -239
- app/view/admin/calendar-feeds.php +90 -90
- app/view/admin/event-category.php +225 -225
- app/view/admin/get-repeat-box.php +653 -653
- app/view/admin/get-tax-box.php +16 -16
- app/view/admin/nav.php +22 -22
- app/view/admin/organize.php +87 -87
- app/view/admin/samples.php +62 -0
- app/view/admin/settings.php +322 -322
- app/view/admin/theme-options.php +210 -210
- app/view/admin/theme-switching.php +46 -46
- app/view/admin/tickets.php +179 -179
- app/view/admin/widget-creator.php +127 -127
- app/view/calendar/fallbacks.php +28 -28
- app/view/calendar/page.php +508 -508
- app/view/calendar/shortcode.php +0 -0
all-in-one-event-calendar.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* Description: A calendar system with month, week, day, agenda views, upcoming events widget, color-coded categories, recurrence, and import/export of .ics feeds.
|
6 |
* Author: Time.ly Network Inc.
|
7 |
* Author URI: https://time.ly/
|
8 |
-
* Version: 2.5.
|
9 |
* Text Domain: all-in-one-event-calendar
|
10 |
* Domain Path: /language
|
11 |
*/
|
@@ -13,52 +13,52 @@ $ai1ec_base_dir = dirname( __FILE__ );
|
|
13 |
$ai1ec_base_url = plugins_url( '', __FILE__ );
|
14 |
|
15 |
$ai1ec_config_path = $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'app' .
|
16 |
-
|
17 |
|
18 |
// Include configuration files and initiate global constants as they are used
|
19 |
// By the error/exception handler too.
|
20 |
foreach ( array( 'constants-local.php', 'constants.php' ) as $file ) {
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
}
|
25 |
|
26 |
if ( ! function_exists( 'ai1ec_initiate_constants' ) ) {
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
}
|
31 |
ai1ec_initiate_constants( $ai1ec_base_dir, $ai1ec_base_url );
|
32 |
|
33 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
34 |
-
|
35 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
36 |
-
|
37 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
38 |
-
|
39 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
40 |
-
|
41 |
-
|
42 |
$ai1ec_exception_handler = new Ai1ec_Exception_Handler(
|
43 |
-
|
44 |
-
|
45 |
);
|
46 |
|
47 |
|
48 |
// if the user clicked the link to reactivate the plugin
|
49 |
if ( isset( $_GET[Ai1ec_Exception_Handler::DB_REACTIVATE_PLUGIN] ) ) {
|
50 |
-
|
51 |
}
|
52 |
$soft_disable_message = $ai1ec_exception_handler->get_disabled_message();
|
53 |
if ( false !== $soft_disable_message ) {
|
54 |
-
|
55 |
}
|
56 |
|
57 |
$prev_er_handler = set_error_handler(
|
58 |
-
|
59 |
);
|
60 |
$prev_ex_handler = set_exception_handler(
|
61 |
-
|
62 |
);
|
63 |
$ai1ec_exception_handler->set_prev_er_handler( $prev_er_handler );
|
64 |
$ai1ec_exception_handler->set_prev_ex_handler( $prev_ex_handler );
|
@@ -66,16 +66,16 @@ $ai1ec_exception_handler->set_prev_ex_handler( $prev_ex_handler );
|
|
66 |
// Regular startup sequence starts here
|
67 |
|
68 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
69 |
-
|
70 |
|
71 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
72 |
-
|
73 |
|
74 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'app' .
|
75 |
-
|
76 |
|
77 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'app' .
|
78 |
-
|
79 |
|
80 |
$ai1ec_loader = new Ai1ec_Loader( $ai1ec_base_dir );
|
81 |
@ini_set( 'unserialize_callback_func', 'spl_autoload_call' );
|
5 |
* Description: A calendar system with month, week, day, agenda views, upcoming events widget, color-coded categories, recurrence, and import/export of .ics feeds.
|
6 |
* Author: Time.ly Network Inc.
|
7 |
* Author URI: https://time.ly/
|
8 |
+
* Version: 2.5.24
|
9 |
* Text Domain: all-in-one-event-calendar
|
10 |
* Domain Path: /language
|
11 |
*/
|
13 |
$ai1ec_base_url = plugins_url( '', __FILE__ );
|
14 |
|
15 |
$ai1ec_config_path = $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'app' .
|
16 |
+
DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR;
|
17 |
|
18 |
// Include configuration files and initiate global constants as they are used
|
19 |
// By the error/exception handler too.
|
20 |
foreach ( array( 'constants-local.php', 'constants.php' ) as $file ) {
|
21 |
+
if ( is_file( $ai1ec_config_path . $file ) ) {
|
22 |
+
require_once $ai1ec_config_path . $file;
|
23 |
+
}
|
24 |
}
|
25 |
|
26 |
if ( ! function_exists( 'ai1ec_initiate_constants' ) ) {
|
27 |
+
throw new Ai1ec_Exception(
|
28 |
+
'No constant file was found.'
|
29 |
+
);
|
30 |
}
|
31 |
ai1ec_initiate_constants( $ai1ec_base_dir, $ai1ec_base_url );
|
32 |
|
33 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
34 |
+
DIRECTORY_SEPARATOR . 'exception' . DIRECTORY_SEPARATOR . 'ai1ec.php';
|
35 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
36 |
+
DIRECTORY_SEPARATOR . 'exception' . DIRECTORY_SEPARATOR . 'error.php';
|
37 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
38 |
+
DIRECTORY_SEPARATOR . 'exception' . DIRECTORY_SEPARATOR . 'handler.php';
|
39 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
40 |
+
DIRECTORY_SEPARATOR . 'http' . DIRECTORY_SEPARATOR . 'response' .
|
41 |
+
DIRECTORY_SEPARATOR . 'helper.php';
|
42 |
$ai1ec_exception_handler = new Ai1ec_Exception_Handler(
|
43 |
+
'Ai1ec_Exception',
|
44 |
+
'Ai1ec_Error_Exception'
|
45 |
);
|
46 |
|
47 |
|
48 |
// if the user clicked the link to reactivate the plugin
|
49 |
if ( isset( $_GET[Ai1ec_Exception_Handler::DB_REACTIVATE_PLUGIN] ) ) {
|
50 |
+
$ai1ec_exception_handler->reactivate_plugin();
|
51 |
}
|
52 |
$soft_disable_message = $ai1ec_exception_handler->get_disabled_message();
|
53 |
if ( false !== $soft_disable_message ) {
|
54 |
+
return $ai1ec_exception_handler->show_notices( $soft_disable_message );
|
55 |
}
|
56 |
|
57 |
$prev_er_handler = set_error_handler(
|
58 |
+
array( $ai1ec_exception_handler, 'handle_error' )
|
59 |
);
|
60 |
$prev_ex_handler = set_exception_handler(
|
61 |
+
array( $ai1ec_exception_handler, 'handle_exception' )
|
62 |
);
|
63 |
$ai1ec_exception_handler->set_prev_er_handler( $prev_er_handler );
|
64 |
$ai1ec_exception_handler->set_prev_ex_handler( $prev_ex_handler );
|
66 |
// Regular startup sequence starts here
|
67 |
|
68 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
69 |
+
DIRECTORY_SEPARATOR . 'bootstrap' . DIRECTORY_SEPARATOR . 'loader.php';
|
70 |
|
71 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'lib' .
|
72 |
+
DIRECTORY_SEPARATOR . 'global-functions.php';
|
73 |
|
74 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'app' .
|
75 |
+
DIRECTORY_SEPARATOR . 'controller' . DIRECTORY_SEPARATOR . 'extension.php';
|
76 |
|
77 |
require $ai1ec_base_dir . DIRECTORY_SEPARATOR . 'app' .
|
78 |
+
DIRECTORY_SEPARATOR . 'controller' . DIRECTORY_SEPARATOR . 'extension-license.php';
|
79 |
|
80 |
$ai1ec_loader = new Ai1ec_Loader( $ai1ec_base_dir );
|
81 |
@ini_set( 'unserialize_callback_func', 'spl_autoload_call' );
|
app/config/constants.php
CHANGED
@@ -13,481 +13,481 @@
|
|
13 |
*/
|
14 |
function ai1ec_initiate_constants( $ai1ec_base_dir, $ai1ec_base_url ) {
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
define( 'AI1EC_VERSION', '2.5.
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
DIRECTORY_SEPARATOR . AI1EC_JS_FOLDER );
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
}
|
13 |
*/
|
14 |
function ai1ec_initiate_constants( $ai1ec_base_dir, $ai1ec_base_url ) {
|
15 |
|
16 |
+
// ===============
|
17 |
+
// = Plugin Path =
|
18 |
+
// ===============
|
19 |
+
if ( ! defined( 'AI1EC_PATH' ) ) {
|
20 |
+
define( 'AI1EC_PATH', $ai1ec_base_dir );
|
21 |
+
}
|
22 |
+
|
23 |
+
// =======================
|
24 |
+
// = Extensions base dir =
|
25 |
+
// =======================
|
26 |
+
if ( ! defined( 'AI1EC_EXTENSIONS_BASEDIR' ) ) {
|
27 |
+
define(
|
28 |
+
'AI1EC_EXTENSIONS_BASEDIR',
|
29 |
+
dirname( $ai1ec_base_dir ) . DIRECTORY_SEPARATOR
|
30 |
+
);
|
31 |
+
}
|
32 |
+
|
33 |
+
// ===============
|
34 |
+
// = Plugin Name =
|
35 |
+
// ===============
|
36 |
+
if ( ! defined( 'AI1EC_PLUGIN_NAME' ) ) {
|
37 |
+
define( 'AI1EC_PLUGIN_NAME', 'all-in-one-event-calendar' );
|
38 |
+
}
|
39 |
+
|
40 |
+
// ===================
|
41 |
+
// = Plugin Basename =
|
42 |
+
// ===================
|
43 |
+
if ( ! defined( 'AI1EC_PLUGIN_BASENAME' ) ) {
|
44 |
+
$plugin = AI1EC_PATH . DIRECTORY_SEPARATOR . AI1EC_PLUGIN_NAME . '.php';
|
45 |
+
define( 'AI1EC_PLUGIN_BASENAME', plugin_basename( $plugin ) );
|
46 |
+
unset( $plugin );
|
47 |
+
}
|
48 |
+
|
49 |
+
// ==================
|
50 |
+
// = Plugin Version =
|
51 |
+
// ==================
|
52 |
+
if ( ! defined( 'AI1EC_VERSION' ) ) {
|
53 |
+
define( 'AI1EC_VERSION', '2.5.24' );
|
54 |
+
}
|
55 |
+
|
56 |
+
// ================
|
57 |
+
// = RSS FEED URL =
|
58 |
+
// ================
|
59 |
+
if ( ! defined( 'AI1EC_RSS_FEED' ) ) {
|
60 |
+
define( 'AI1EC_RSS_FEED', 'https://time.ly/blog/feed/' );
|
61 |
+
}
|
62 |
+
|
63 |
+
// =================
|
64 |
+
// = Language Path =
|
65 |
+
// =================
|
66 |
+
if ( ! defined( 'AI1EC_LANGUAGE_PATH' ) ) {
|
67 |
+
define(
|
68 |
+
'AI1EC_LANGUAGE_PATH',
|
69 |
+
AI1EC_PLUGIN_NAME . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR
|
70 |
+
);
|
71 |
+
}
|
72 |
+
// ================
|
73 |
+
// = Cron Version =
|
74 |
+
// ================
|
75 |
+
if ( ! defined( 'AI1EC_CRON_VERSION' ) ) {
|
76 |
+
define( 'AI1EC_CRON_VERSION', AI1EC_VERSION );
|
77 |
+
}
|
78 |
+
if ( ! defined( 'AI1EC_U_CRON_VERSION' ) ) {
|
79 |
+
define( 'AI1EC_U_CRON_VERSION', AI1EC_VERSION );
|
80 |
+
}
|
81 |
+
if ( ! defined( 'AI1EC_U_CRON_FREQ' ) ) {
|
82 |
+
define( 'AI1EC_U_CRON_FREQ', 'hourly' );
|
83 |
+
}
|
84 |
+
|
85 |
+
// ==============
|
86 |
+
// = Plugin Url =
|
87 |
+
// ==============
|
88 |
+
if ( ! defined( 'AI1EC_URL' ) ) {
|
89 |
+
define( 'AI1EC_URL', $ai1ec_base_url );
|
90 |
+
}
|
91 |
+
// ===============
|
92 |
+
// = VENDOR PATH =
|
93 |
+
// ===============
|
94 |
+
if ( ! defined( 'AI1EC_VENDOR_PATH' ) ) {
|
95 |
+
define(
|
96 |
+
'AI1EC_VENDOR_PATH',
|
97 |
+
AI1EC_PATH . DIRECTORY_SEPARATOR . 'vendor' .
|
98 |
+
DIRECTORY_SEPARATOR
|
99 |
+
);
|
100 |
+
}
|
101 |
+
|
102 |
+
// ===============
|
103 |
+
// = ADMIN PATH =
|
104 |
+
// ===============
|
105 |
+
if ( ! defined( 'AI1EC_ADMIN_PATH' ) ) {
|
106 |
+
define(
|
107 |
+
'AI1EC_ADMIN_PATH',
|
108 |
+
AI1EC_PATH . DIRECTORY_SEPARATOR . 'public' .
|
109 |
+
DIRECTORY_SEPARATOR . 'admin' . DIRECTORY_SEPARATOR
|
110 |
+
);
|
111 |
+
}
|
112 |
+
|
113 |
+
// ===============
|
114 |
+
// = ADMIN URL =
|
115 |
+
// ===============
|
116 |
+
if ( ! defined( 'AI1EC_ADMIN_URL' ) ) {
|
117 |
+
define(
|
118 |
+
'AI1EC_ADMIN_URL',
|
119 |
+
AI1EC_URL . '/public/admin/'
|
120 |
+
);
|
121 |
+
}
|
122 |
+
|
123 |
+
// ==============
|
124 |
+
// = CACHE PATH =
|
125 |
+
// ==============
|
126 |
+
if ( ! defined( 'AI1EC_CACHE_PATH' ) ) {
|
127 |
+
define(
|
128 |
+
'AI1EC_CACHE_PATH',
|
129 |
+
AI1EC_PATH . DIRECTORY_SEPARATOR . 'cache' .
|
130 |
+
DIRECTORY_SEPARATOR
|
131 |
+
);
|
132 |
+
}
|
133 |
+
|
134 |
+
// ==============
|
135 |
+
// = CACHE URL =
|
136 |
+
// ==============
|
137 |
+
if ( ! defined( 'AI1EC_CACHE_URL' ) ) {
|
138 |
+
define(
|
139 |
+
'AI1EC_CACHE_URL',
|
140 |
+
AI1EC_URL . '/cache/'
|
141 |
+
);
|
142 |
+
}
|
143 |
+
|
144 |
+
// ==============
|
145 |
+
// = TWIG CACHE PATH =
|
146 |
+
// ==============
|
147 |
+
if ( ! defined( 'AI1EC_TWIG_CACHE_PATH' ) ) {
|
148 |
+
define(
|
149 |
+
'AI1EC_TWIG_CACHE_PATH',
|
150 |
+
AI1EC_CACHE_PATH . 'twig' .
|
151 |
+
DIRECTORY_SEPARATOR
|
152 |
+
);
|
153 |
+
}
|
154 |
+
|
155 |
+
// ======================
|
156 |
+
// = Default theme name =
|
157 |
+
// ======================
|
158 |
+
if ( ! defined( 'AI1EC_DEFAULT_THEME_NAME' ) ) {
|
159 |
+
define( 'AI1EC_DEFAULT_THEME_NAME', 'vortex' );
|
160 |
+
}
|
161 |
+
// ================
|
162 |
+
// = THEME FOLDER =
|
163 |
+
// ================
|
164 |
+
if ( ! defined( 'AI1EC_THEME_FOLDER' ) ) {
|
165 |
+
define( 'AI1EC_THEME_FOLDER', 'themes-ai1ec' );
|
166 |
+
}
|
167 |
+
|
168 |
+
// =======================
|
169 |
+
// = DEFAULT THEME PATH =
|
170 |
+
// =======================
|
171 |
+
if ( ! defined( 'AI1EC_DEFAULT_THEME_ROOT' ) ) {
|
172 |
+
define(
|
173 |
+
'AI1EC_DEFAULT_THEME_ROOT',
|
174 |
+
AI1EC_PATH . DIRECTORY_SEPARATOR . 'public' .
|
175 |
+
DIRECTORY_SEPARATOR . AI1EC_THEME_FOLDER
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
// =======================
|
180 |
+
// = DEFAULT THEME PATH =
|
181 |
+
// =======================
|
182 |
+
if ( ! defined( 'AI1EC_DEFAULT_THEME_PATH' ) ) {
|
183 |
+
define(
|
184 |
+
'AI1EC_DEFAULT_THEME_PATH',
|
185 |
+
AI1EC_DEFAULT_THEME_ROOT . DIRECTORY_SEPARATOR .
|
186 |
+
AI1EC_DEFAULT_THEME_NAME
|
187 |
+
);
|
188 |
+
}
|
189 |
+
|
190 |
+
// ===================
|
191 |
+
// = AI1EC Theme URL =
|
192 |
+
// ===================
|
193 |
+
if ( ! defined( 'AI1EC_THEMES_URL' ) ) {
|
194 |
+
define(
|
195 |
+
'AI1EC_THEMES_URL',
|
196 |
+
AI1EC_URL . '/public/' . AI1EC_THEME_FOLDER
|
197 |
+
);
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
// =====================
|
202 |
+
// = AI1EC Core themes =
|
203 |
+
// =====================
|
204 |
+
if ( ! defined( 'AI1EC_CORE_THEMES' ) ) {
|
205 |
+
define( 'AI1EC_CORE_THEMES', 'vortex,umbra,gamma,plana' );
|
206 |
+
}
|
207 |
+
|
208 |
+
// ===================
|
209 |
+
// = AI1EC Theme URL =
|
210 |
+
// ===================
|
211 |
+
if ( ! defined( 'AI1EC_THEMES_URL' ) ) {
|
212 |
+
define( 'AI1EC_THEMES_URL', AI1EC_URL . '/public/' . AI1EC_THEME_FOLDER . '/' );
|
213 |
+
}
|
214 |
+
|
215 |
+
// =================
|
216 |
+
// = Admin CSS URL =
|
217 |
+
// =================
|
218 |
+
if ( ! defined( 'AI1EC_ADMIN_THEME_CSS_URL' ) ) {
|
219 |
+
define( 'AI1EC_ADMIN_THEME_CSS_URL', AI1EC_URL .'/public/admin/css/' );
|
220 |
+
}
|
221 |
+
|
222 |
+
// =================
|
223 |
+
// = Admin Font URL =
|
224 |
+
// =================
|
225 |
+
if ( ! defined( 'AI1EC_ADMIN_THEME_FONT_URL' ) ) {
|
226 |
+
define( 'AI1EC_ADMIN_THEME_FONT_URL', AI1EC_URL .'/public/admin/font/' );
|
227 |
+
}
|
228 |
+
|
229 |
+
// =================
|
230 |
+
// = Admin Js URL =
|
231 |
+
// =================
|
232 |
+
if ( ! defined( 'AI1EC_ADMIN_THEME_JS_URL' ) ) {
|
233 |
+
define( 'AI1EC_ADMIN_THEME_JS_URL', AI1EC_URL .'/public/js/' );
|
234 |
+
}
|
235 |
+
|
236 |
+
// =============
|
237 |
+
// = POST TYPE =
|
238 |
+
// =============
|
239 |
+
if ( ! defined( 'AI1EC_POST_TYPE' ) ) {
|
240 |
+
define( 'AI1EC_POST_TYPE', 'ai1ec_event' );
|
241 |
+
}
|
242 |
+
|
243 |
+
// ==============
|
244 |
+
// = SCRIPT URL =
|
245 |
+
// ==============
|
246 |
+
if ( ! defined( 'AI1EC_SCRIPT_URL' ) ) {
|
247 |
+
define(
|
248 |
+
'AI1EC_SCRIPT_URL',
|
249 |
+
get_option( 'home' ) . '/?plugin=' . AI1EC_PLUGIN_NAME
|
250 |
+
);
|
251 |
+
}
|
252 |
+
|
253 |
+
// =========================================
|
254 |
+
// = BASE URL FOR ALL CALENDAR ADMIN PAGES =
|
255 |
+
// =========================================
|
256 |
+
if ( ! defined( 'AI1EC_ADMIN_BASE_URL' ) ) {
|
257 |
+
define( 'AI1EC_ADMIN_BASE_URL', 'edit.php?post_type=' . AI1EC_POST_TYPE );
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
// =====================================================
|
262 |
+
// = THEME OPTIONS PAGE BASE URL (wrap in admin_url()) =
|
263 |
+
// =====================================================
|
264 |
+
if ( ! defined( 'AI1EC_THEME_OPTIONS_BASE_URL' ) ) {
|
265 |
+
define( 'AI1EC_THEME_OPTIONS_BASE_URL', AI1EC_ADMIN_BASE_URL . '&page=' . AI1EC_PLUGIN_NAME . '-edit-css' );
|
266 |
+
}
|
267 |
+
|
268 |
+
// =======================================================
|
269 |
+
// = THEME SELECTION PAGE BASE URL (wrap in admin_url()) =
|
270 |
+
// =======================================================
|
271 |
+
if ( ! defined( 'AI1EC_THEME_SELECTION_BASE_URL' ) ) {
|
272 |
+
define(
|
273 |
+
'AI1EC_THEME_SELECTION_BASE_URL',
|
274 |
+
AI1EC_ADMIN_BASE_URL . '&page=' . AI1EC_PLUGIN_NAME . '-themes'
|
275 |
+
);
|
276 |
+
}
|
277 |
+
|
278 |
+
|
279 |
+
// =====================================================
|
280 |
+
// = FEED SETTINGS PAGE BASE URL (wrap in admin_url()) =
|
281 |
+
// =====================================================
|
282 |
+
if ( ! defined( 'AI1EC_FEED_SETTINGS_BASE_URL' ) ) {
|
283 |
+
define( 'AI1EC_FEED_SETTINGS_BASE_URL', AI1EC_ADMIN_BASE_URL . '&page=' . AI1EC_PLUGIN_NAME . '-feeds' );
|
284 |
+
}
|
285 |
+
|
286 |
+
// ================================================
|
287 |
+
// = SETTINGS PAGE BASE URL (wrap in admin_url()) =
|
288 |
+
// ================================================
|
289 |
+
if ( ! defined( 'AI1EC_SETTINGS_BASE_URL' ) ) {
|
290 |
+
define(
|
291 |
+
'AI1EC_SETTINGS_BASE_URL',
|
292 |
+
AI1EC_ADMIN_BASE_URL . '&page=' . AI1EC_PLUGIN_NAME . '-settings'
|
293 |
+
);
|
294 |
+
}
|
295 |
+
|
296 |
+
// ==============
|
297 |
+
// = EXPORT URL =
|
298 |
+
// ==============
|
299 |
+
if ( ! defined( 'AI1EC_EXPORT_URL' ) ) {
|
300 |
+
// ====================================================
|
301 |
+
// = Convert http:// to webcal:// in AI1EC_SCRIPT_URL =
|
302 |
+
// = (webcal:// protocol does not support https://) =
|
303 |
+
// ====================================================
|
304 |
+
$webcal_url = preg_replace( '/^https?:\/\//', 'webcal://', AI1EC_SCRIPT_URL );
|
305 |
+
define(
|
306 |
+
'AI1EC_EXPORT_URL',
|
307 |
+
$webcal_url . '&controller=ai1ec_exporter_controller' .
|
308 |
+
'&action=export_events'
|
309 |
+
);
|
310 |
+
unset( $webcal_url );
|
311 |
+
}
|
312 |
+
|
313 |
+
if ( ! defined( 'AI1EC_CA_ROOT_PEM' ) ) {
|
314 |
+
define(
|
315 |
+
'AI1EC_CA_ROOT_PEM',
|
316 |
+
AI1EC_PATH . DIRECTORY_SEPARATOR . 'ca_cert' .
|
317 |
+
DIRECTORY_SEPARATOR . 'ca_cert.pem'
|
318 |
+
);
|
319 |
+
}
|
320 |
+
|
321 |
+
// ====================
|
322 |
+
// = SPECIAL SETTINGS =
|
323 |
+
// ====================
|
324 |
+
|
325 |
+
// Set AI1EC_EVENT_PLATFORM to TRUE to turn WordPress into an events-only
|
326 |
+
// platform. For a multi-site install, setting this to TRUE is equivalent to a
|
327 |
+
// super-administrator selecting the
|
328 |
+
// "Turn this blog into an events-only platform" checkbox
|
329 |
+
// on the Calendar Settings page of every blog on the network.
|
330 |
+
// This mode, when enabled on blogs where this plugin is active, hides all
|
331 |
+
// administrative functions unrelated to events and the calendar (except to
|
332 |
+
// super-administrators), and sets default WordPress settings appropriate for
|
333 |
+
// pure event management.
|
334 |
+
if ( ! defined( 'AI1EC_EVENT_PLATFORM' ) ) {
|
335 |
+
define( 'AI1EC_EVENT_PLATFORM', false );
|
336 |
+
}
|
337 |
+
|
338 |
+
// If i choose to use the calendar url as the base for events permalinks,
|
339 |
+
// i must specify another name for the events archive.
|
340 |
+
if ( ! defined( 'AI1EC_ALTERNATIVE_ARCHIVE_URL' ) ) {
|
341 |
+
define( 'AI1EC_ALTERNATIVE_ARCHIVE_URL', 'ai1ec_events_archive' );
|
342 |
+
}
|
343 |
+
|
344 |
+
// ===================
|
345 |
+
// = AI1EC Theme URL =
|
346 |
+
// ===================
|
347 |
+
if ( ! defined( 'AI1EC_THEMES_URL_LEGACY' ) ) {
|
348 |
+
define( 'AI1EC_THEMES_URL_LEGACY', WP_CONTENT_URL . '/' . AI1EC_THEME_FOLDER );
|
349 |
+
}
|
350 |
+
|
351 |
+
// =====================
|
352 |
+
// = Default theme url legacy=
|
353 |
+
// =====================
|
354 |
+
if ( ! defined( 'AI1EC_DEFAULT_THEME_URL_LEGACY' ) ) {
|
355 |
+
define( 'AI1EC_DEFAULT_THEME_URL_LEGACY', AI1EC_THEMES_URL . '/' . AI1EC_DEFAULT_THEME_NAME . '/' );
|
356 |
+
}
|
357 |
+
|
358 |
+
// =====================
|
359 |
+
// = Default theme url =
|
360 |
+
// =====================
|
361 |
+
if ( ! defined( 'AI1EC_DEFAULT_THEME_URL' ) ) {
|
362 |
+
define( 'AI1EC_DEFAULT_THEME_URL', AI1EC_THEMES_URL . '/' . AI1EC_DEFAULT_THEME_NAME . '/' );
|
363 |
+
}
|
364 |
+
|
365 |
+
// ===================
|
366 |
+
// = CSS Folder name =
|
367 |
+
// ===================
|
368 |
+
if ( ! defined( 'AI1EC_CSS_FOLDER' ) ) {
|
369 |
+
define( 'AI1EC_CSS_FOLDER', 'css' );
|
370 |
+
}
|
371 |
+
|
372 |
+
// ==================
|
373 |
+
// = JS Folder name =
|
374 |
+
// ==================
|
375 |
+
if ( ! defined( 'AI1EC_JS_FOLDER' ) ) {
|
376 |
+
define( 'AI1EC_JS_FOLDER', 'js' );
|
377 |
+
}
|
378 |
+
|
379 |
+
// =====================
|
380 |
+
// = Image folder name =
|
381 |
+
// =====================
|
382 |
+
if ( ! defined( 'AI1EC_IMG_FOLDER' ) ) {
|
383 |
+
define( 'AI1EC_IMG_FOLDER', 'img' );
|
384 |
+
}
|
385 |
+
|
386 |
+
|
387 |
+
|
388 |
+
// ========================
|
389 |
+
// = Admin theme CSS path =
|
390 |
+
// ========================
|
391 |
+
if ( ! defined( 'AI1EC_ADMIN_THEME_CSS_PATH' ) ) {
|
392 |
+
define( 'AI1EC_ADMIN_THEME_CSS_PATH', AI1EC_ADMIN_PATH . AI1EC_CSS_FOLDER );
|
393 |
+
}
|
394 |
+
|
395 |
+
// =======================
|
396 |
+
// = Admin theme JS path =
|
397 |
+
// =======================
|
398 |
+
if ( ! defined( 'AI1EC_ADMIN_THEME_JS_PATH' ) ) {
|
399 |
+
define( 'AI1EC_ADMIN_THEME_JS_PATH', AI1EC_PATH . DIRECTORY_SEPARATOR . 'public' .
|
400 |
DIRECTORY_SEPARATOR . AI1EC_JS_FOLDER );
|
401 |
+
}
|
402 |
+
|
403 |
+
// =================
|
404 |
+
// = Admin IMG URL =
|
405 |
+
// =================
|
406 |
+
if ( ! defined( 'AI1EC_ADMIN_THEME_IMG_URL' ) ) {
|
407 |
+
define( 'AI1EC_ADMIN_THEME_IMG_URL', AI1EC_URL . '/public/admin/' . AI1EC_IMG_FOLDER );
|
408 |
+
}
|
409 |
+
|
410 |
+
// ====================
|
411 |
+
// = Add-ons list URL =
|
412 |
+
// ====================
|
413 |
+
if ( ! defined( 'AI1EC_TIMELY_ADDONS_URI' ) ) {
|
414 |
+
define( 'AI1EC_TIMELY_ADDONS_URI', 'https://time.ly/?action=addons_list' );
|
415 |
+
}
|
416 |
+
|
417 |
+
// Enable All-in-One-Event-Calendar to work in debug mode, which means,
|
418 |
+
// that cache is ignored, extra output may appear at places, etc.
|
419 |
+
// Do not set this to any other value than `false` on production even if
|
420 |
+
// you know what you are doing, because you will waste valuable
|
421 |
+
// resources - save the Earth, at least.
|
422 |
+
if ( ! defined( 'AI1EC_DEBUG' ) ) {
|
423 |
+
define( 'AI1EC_DEBUG', false );
|
424 |
+
}
|
425 |
+
|
426 |
+
// Enable Ai1EC cache functionality. If you set this to false, only cache
|
427 |
+
// that is based on request, will remain active.
|
428 |
+
// This is pointless in any case other than development, where literary
|
429 |
+
// every second refresh needs to take fresh copy of everything.
|
430 |
+
if ( ! defined( 'AI1EC_CACHE' ) ) {
|
431 |
+
define( 'AI1EC_CACHE', true );
|
432 |
+
}
|
433 |
+
|
434 |
+
if ( ! defined( 'AI1EC_DISABLE_FILE_CACHE' ) ) {
|
435 |
+
define( 'AI1EC_DISABLE_FILE_CACHE', false );
|
436 |
+
}
|
437 |
+
|
438 |
+
// A value identifying that cache is not available.
|
439 |
+
// Used in place of actual path for cache to use.
|
440 |
+
// Named constant allows reuse of a single typed variable.
|
441 |
+
if ( ! defined( 'AI1EC_CACHE_UNAVAILABLE' ) ) {
|
442 |
+
define( 'AI1EC_CACHE_UNAVAILABLE', 'AI1EC_CACHE_UNAVAILABLE' );
|
443 |
+
}
|
444 |
+
|
445 |
+
// Defines if backward (<= 2.1.5) theme compatibility is enabled or not.
|
446 |
+
if ( ! defined( 'AI1EC_THEME_COMPATIBILITY_FER' ) ) {
|
447 |
+
define( 'AI1EC_THEME_COMPATIBILITY_FER', true );
|
448 |
+
}
|
449 |
+
|
450 |
+
// Defines amount of needed free memory to compile LESS files.
|
451 |
+
if ( ! defined( 'AI1EC_LESS_MIN_AVAIL_MEMORY' ) ) {
|
452 |
+
define( 'AI1EC_LESS_MIN_AVAIL_MEMORY', '24M' );
|
453 |
+
}
|
454 |
+
|
455 |
+
// Defines if LESS files are parsed at every request
|
456 |
+
if ( ! defined( 'AI1EC_PARSE_LESS_FILES_AT_EVERY_REQUEST' ) ) {
|
457 |
+
define( 'AI1EC_PARSE_LESS_FILES_AT_EVERY_REQUEST', false );
|
458 |
+
}
|
459 |
+
|
460 |
+
// Defines a list of FER-enabled templates.
|
461 |
+
if ( ! defined( 'AI1EC_FER_ENABLED_TEMPLATES_LIST' ) ) {
|
462 |
+
define(
|
463 |
+
'AI1EC_FER_ENABLED_TEMPLATES_LIST',
|
464 |
+
'agenda,oneday,week,month,posterboard,stream'
|
465 |
+
);
|
466 |
+
}
|
467 |
+
|
468 |
+
// Defines API URL.
|
469 |
+
if ( ! defined( 'AI1EC_API_URL' ) ) {
|
470 |
+
define(
|
471 |
+
'AI1EC_API_URL',
|
472 |
+
'https://api.time.ly/api/'
|
473 |
+
);
|
474 |
+
}
|
475 |
+
|
476 |
+
// Defines Tickets checkout URL.
|
477 |
+
if ( ! defined( 'AI1EC_TICKETS_CHECKOUT_URL' ) ) {
|
478 |
+
define(
|
479 |
+
'AI1EC_TICKETS_CHECKOUT_URL',
|
480 |
+
'https://api.time.ly/events/{event_id}/checkout'
|
481 |
+
);
|
482 |
+
}
|
483 |
+
|
484 |
+
// ================================================
|
485 |
+
// = Force WordPress updates command link =
|
486 |
+
// ================================================
|
487 |
+
if ( ! defined( 'AI1EC_FORCE_UPDATES_URL' ) ) {
|
488 |
+
define(
|
489 |
+
'AI1EC_FORCE_UPDATES_URL',
|
490 |
+
AI1EC_ADMIN_BASE_URL . '&ai1ec_force_updates=true'
|
491 |
+
);
|
492 |
+
}
|
493 |
}
|
app/controller/calendar-feeds.php
CHANGED
@@ -11,74 +11,74 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Controller_Calendar_Feeds extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
|
84 |
}
|
11 |
*/
|
12 |
class Ai1ec_Controller_Calendar_Feeds extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var array Holds the instances of registered plugins.
|
16 |
+
*/
|
17 |
+
protected $_plugins = array();
|
18 |
|
19 |
+
/**
|
20 |
+
* Add plugin to the internal array.
|
21 |
+
*
|
22 |
+
* This assure us that the plugins extends our base abstract class.
|
23 |
+
*
|
24 |
+
* @param Ai1ec_Connector_Plugin $plugin Plugin to add.
|
25 |
+
*
|
26 |
+
* @return void
|
27 |
+
*/
|
28 |
+
public function add_plugin( Ai1ec_Connector_Plugin $plugin ) {
|
29 |
+
$plugin->initialize_settings_if_not_set();
|
30 |
+
$this->_plugins[] = $plugin;
|
31 |
+
}
|
32 |
|
33 |
+
/**
|
34 |
+
* Get an instance of a plugin class
|
35 |
+
*
|
36 |
+
* @param string $class
|
37 |
+
* @throws Exception
|
38 |
+
* @return Ai1ec_Connector_Plugin
|
39 |
+
*/
|
40 |
+
public function get_plugin_instance( $class ) {
|
41 |
+
foreach ( $this->_plugins as $plugin ) {
|
42 |
+
if( get_class( $plugin ) === $class ) {
|
43 |
+
return $plugin;
|
44 |
+
}
|
45 |
+
}
|
46 |
+
throw new Exception( "Class not found" );
|
47 |
+
}
|
48 |
|
49 |
+
/**
|
50 |
+
* Give the plugins the possibility to handle data posted in the calendar feeds page
|
51 |
+
*
|
52 |
+
* @return void
|
53 |
+
*/
|
54 |
+
public function handle_feeds_page_post() {
|
55 |
+
// Iterate over the plugins and call the methods
|
56 |
+
foreach ( $this->_plugins as $plugin ) {
|
57 |
+
$plugin->handle_feeds_page_post();
|
58 |
+
}
|
59 |
+
}
|
60 |
|
61 |
+
/**
|
62 |
+
* Render the tab header for each plugin
|
63 |
+
*
|
64 |
+
* @param $active_feed
|
65 |
+
* The tab that should be visualized
|
66 |
+
*/
|
67 |
+
public function render_tab_headers() {
|
68 |
+
foreach ( $this->_plugins as $plugin ) {
|
69 |
+
$plugin->render_tab_header();
|
70 |
+
}
|
71 |
+
}
|
72 |
+
/**
|
73 |
+
* Render the tab body for each plugin
|
74 |
+
*
|
75 |
+
* @param $active_feed
|
76 |
+
* The tab that should be visualized
|
77 |
+
*/
|
78 |
+
public function render_tab_contents() {
|
79 |
+
foreach ( $this->_plugins as $plugin ) {
|
80 |
+
$plugin->render_tab_content();
|
81 |
+
}
|
82 |
+
}
|
83 |
|
84 |
}
|
app/controller/content-filter.php
CHANGED
@@ -11,52 +11,52 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Controller_Content_Filter extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
}
|
11 |
*/
|
12 |
class Ai1ec_Controller_Content_Filter extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* Content filters lib.
|
16 |
+
* @var Ai1ec_Content_Filters
|
17 |
+
*/
|
18 |
+
protected $_content_filter;
|
19 |
|
20 |
+
/**
|
21 |
+
* Setting _strict_compatibility_content_filtering.
|
22 |
+
* @var bool
|
23 |
+
*/
|
24 |
+
protected $_strict_compatibility_content_filtering;
|
25 |
|
26 |
+
/**
|
27 |
+
* Constructor.
|
28 |
+
*
|
29 |
+
* @param Ai1ec_Registry_Object $registry Registry object.
|
30 |
+
*
|
31 |
+
* @return void Method does not return.
|
32 |
+
*/
|
33 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
34 |
+
parent::__construct( $registry );
|
35 |
+
$this->_content_filter = $registry->get( 'content.filter' );
|
36 |
+
$this->_strict_compatibility_content_filtering =
|
37 |
+
$registry->get( 'model.settings' )
|
38 |
+
->get( 'strict_compatibility_content_filtering' );
|
39 |
+
}
|
40 |
|
41 |
+
/**
|
42 |
+
* Clears all the_content filters excluding few defaults.
|
43 |
+
*
|
44 |
+
* @return void Method does not return.
|
45 |
+
*/
|
46 |
+
public function clear_the_content_filters() {
|
47 |
+
if ( $this->_strict_compatibility_content_filtering ) {
|
48 |
+
$this->_content_filter->clear_the_content_filters();
|
49 |
+
}
|
50 |
+
}
|
51 |
|
52 |
+
/**
|
53 |
+
* Restores the_content filters.
|
54 |
+
*
|
55 |
+
* @return void Method does not return.
|
56 |
+
*/
|
57 |
+
public function restore_the_content_filters() {
|
58 |
+
if ( $this->_strict_compatibility_content_filtering ) {
|
59 |
+
$this->_content_filter->restore_the_content_filters();
|
60 |
+
}
|
61 |
+
}
|
62 |
}
|
app/controller/extension-license.php
CHANGED
@@ -11,109 +11,109 @@
|
|
11 |
*/
|
12 |
abstract class Ai1ec_Base_License_Controller extends Ai1ec_Base_Extension_Controller {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
|
58 |
-
|
59 |
-
|
60 |
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
|
119 |
}
|
11 |
*/
|
12 |
abstract class Ai1ec_Base_License_Controller extends Ai1ec_Base_Extension_Controller {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string Settings entry name for license key.
|
16 |
+
*/
|
17 |
+
protected $_licence;
|
18 |
|
19 |
+
/**
|
20 |
+
* @var string Settings entry name for license status output.
|
21 |
+
*/
|
22 |
+
protected $_licence_status;
|
23 |
|
24 |
+
/**
|
25 |
+
* @var string Licensing API endpoint URI.
|
26 |
+
*/
|
27 |
+
protected $_store = 'https://time.ly/';
|
28 |
|
29 |
+
/**
|
30 |
+
* Get label to be used for license input field.
|
31 |
+
*
|
32 |
+
* @return string Localized label field.
|
33 |
+
*/
|
34 |
+
abstract public function get_license_label();
|
35 |
|
36 |
+
/**
|
37 |
+
* @param Ai1ec_Registry_Object $registry
|
38 |
+
*/
|
39 |
+
public function initialize_licence_actions() {
|
40 |
+
$this->_register_licence_actions();
|
41 |
+
$this->_register_licence_fields();
|
42 |
+
}
|
43 |
|
44 |
+
/**
|
45 |
+
* Add the extension tab if not present
|
46 |
+
*
|
47 |
+
* @param array $tabs
|
48 |
+
* @return array
|
49 |
+
*/
|
50 |
+
public function add_tabs( array $tabs ) {
|
51 |
+
if ( ! isset( $tabs['extensions'] ) ) {
|
52 |
+
$tabs['extensions'] = array(
|
53 |
+
'name' => Ai1ec_I18n::__( 'Add-ons' ),
|
54 |
+
'items' => array(),
|
55 |
+
);
|
56 |
+
}
|
57 |
|
58 |
+
return $tabs;
|
59 |
+
}
|
60 |
|
61 |
+
/**
|
62 |
+
* Register action for licences.
|
63 |
+
*/
|
64 |
+
protected function _register_licence_actions() {
|
65 |
+
$dispatcher = $this->_registry->get( 'event.dispatcher' );
|
66 |
+
// we need the super class so we use get_class()
|
67 |
+
$class = explode( '_', get_class( $this ) );
|
68 |
+
$controller = strtolower( end( $class ) );
|
69 |
+
$dispatcher->register_filter(
|
70 |
+
'ai1ec_add_setting_tabs',
|
71 |
+
array( 'controller.' . $controller, 'add_tabs' )
|
72 |
+
);
|
73 |
+
}
|
74 |
|
75 |
+
/**
|
76 |
+
* Register fields for licence
|
77 |
+
*/
|
78 |
+
protected function _register_licence_fields() {
|
79 |
+
$plugin_id = $this->get_machine_name();
|
80 |
+
$this->_licence = 'ai1ec_licence_' . $plugin_id;
|
81 |
+
$this->_licence_status = 'ai1ec_licence_status_' . $plugin_id;
|
82 |
+
$options = array(
|
83 |
+
$this->_licence => array(
|
84 |
+
'type' => 'string',
|
85 |
+
'version' => $this->get_version(),
|
86 |
+
'renderer' => array(
|
87 |
+
'class' => 'input',
|
88 |
+
'group-class' => 'ai1ec-col-sm-7',
|
89 |
+
'tab' => 'extensions',
|
90 |
+
'item' => 'licenses',
|
91 |
+
'type' => 'normal',
|
92 |
+
'label' => $this->get_license_label(),
|
93 |
+
'status' => $this->_licence_status,
|
94 |
+
),
|
95 |
+
'default' => '',
|
96 |
+
),
|
97 |
+
$this->_licence_status => array(
|
98 |
+
'type' => 'string',
|
99 |
+
'version' => $this->get_version(),
|
100 |
+
'default' => 'invalid',
|
101 |
+
),
|
102 |
+
);
|
103 |
+
$settings = $this->_registry->get( 'model.settings' );
|
104 |
+
foreach ( $options as $key => $option ) {
|
105 |
+
$renderer = null;
|
106 |
+
if ( isset( $option['renderer'] ) ) {
|
107 |
+
$renderer = $option['renderer'];
|
108 |
+
}
|
109 |
+
$settings->register(
|
110 |
+
$key,
|
111 |
+
$option['default'],
|
112 |
+
$option['type'],
|
113 |
+
$renderer,
|
114 |
+
$option['version']
|
115 |
+
);
|
116 |
+
}
|
117 |
+
}
|
118 |
|
119 |
}
|
app/controller/extension.php
CHANGED
@@ -11,281 +11,281 @@
|
|
11 |
*/
|
12 |
abstract class Ai1ec_Base_Extension_Controller {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
}
|
223 |
|
224 |
-
|
225 |
-
* Since the call the to the uninstall hook it's static, if a different behaviour
|
226 |
-
* is needed also this call must be overridden.
|
227 |
-
*/
|
228 |
-
protected function _register_uninstall_hook() {
|
229 |
-
register_uninstall_hook(
|
230 |
-
$this->get_file(),
|
231 |
-
array( get_class( $this ), 'on_uninstall' )
|
232 |
-
);
|
233 |
-
}
|
234 |
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
}
|
246 |
-
$settings->register(
|
247 |
-
$name,
|
248 |
-
$params['value'],
|
249 |
-
$params['type'],
|
250 |
-
$renderer,
|
251 |
-
$this->get_version()
|
252 |
-
);
|
253 |
-
}
|
254 |
-
}
|
255 |
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
|
291 |
}
|
11 |
*/
|
12 |
abstract class Ai1ec_Base_Extension_Controller {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var Ai1ec_Registry_Object
|
16 |
+
*/
|
17 |
+
protected $_registry;
|
18 |
|
19 |
+
/**
|
20 |
+
* @var array
|
21 |
+
*/
|
22 |
+
protected $_settings;
|
23 |
|
24 |
+
/**
|
25 |
+
* @var Ai1ec_Registry_Object
|
26 |
+
*/
|
27 |
+
protected static $_registry_static;
|
28 |
|
29 |
+
/**
|
30 |
+
* @var array
|
31 |
+
*/
|
32 |
+
protected static $_settings_static;
|
33 |
|
34 |
+
/**
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
protected static $_schema;
|
38 |
|
39 |
+
/**
|
40 |
+
* Get the long name of the extension
|
41 |
+
*/
|
42 |
+
abstract public function get_name();
|
43 |
|
44 |
+
/**
|
45 |
+
* Get the machine name of the extension
|
46 |
+
*/
|
47 |
+
abstract public function get_machine_name();
|
48 |
|
49 |
+
/**
|
50 |
+
* Get the version of the extension
|
51 |
+
*/
|
52 |
+
abstract public function get_version();
|
53 |
|
54 |
+
/**
|
55 |
+
* Get the name of the main plugin file
|
56 |
+
*/
|
57 |
+
abstract public function get_file();
|
58 |
|
59 |
+
/**
|
60 |
+
* Add extension specific settings
|
61 |
+
*/
|
62 |
+
abstract protected function _get_settings();
|
63 |
|
64 |
+
/**
|
65 |
+
* Register action/filters/shortcodes for the extension
|
66 |
+
*
|
67 |
+
* @param Ai1ec_Event_Dispatcher $dispatcher
|
68 |
+
*/
|
69 |
+
abstract protected function _register_actions(
|
70 |
+
Ai1ec_Event_Dispatcher $dispatcher
|
71 |
+
);
|
72 |
|
73 |
+
/**
|
74 |
+
* Perform the basic compatibility check.
|
75 |
+
*
|
76 |
+
* @param string $ai1ec_version
|
77 |
+
*
|
78 |
+
* @return boolean
|
79 |
+
*/
|
80 |
+
public function check_compatibility( $ai1ec_version ) {
|
81 |
+
return version_compare(
|
82 |
+
$ai1ec_version,
|
83 |
+
$this->minimum_core_required(),
|
84 |
+
'>='
|
85 |
+
);
|
86 |
+
}
|
87 |
|
88 |
+
/**
|
89 |
+
* @return string
|
90 |
+
*/
|
91 |
+
public function minimum_core_required() {
|
92 |
+
return '2.0.7';
|
93 |
+
}
|
94 |
+
/**
|
95 |
+
* Removes options when uninstalling the plugin.
|
96 |
+
*/
|
97 |
+
public static function on_uninstall() {
|
98 |
+
global $wpdb;
|
99 |
+
if ( ! current_user_can( 'activate_plugins' ) ) {
|
100 |
+
return;
|
101 |
+
}
|
102 |
+
$settings = self::$_registry_static->get( 'model.settings' );
|
103 |
+
foreach ( self::$_settings_static as $name => $params ) {
|
104 |
+
$settings->remove_option( $name );
|
105 |
+
}
|
106 |
+
$schema = self::$_schema;
|
107 |
+
foreach ( $schema['tables'] as $table_name ) {
|
108 |
+
// Delete table events
|
109 |
+
$wpdb->query( 'DROP TABLE IF EXISTS ' . $table_name );
|
110 |
+
}
|
111 |
+
}
|
112 |
|
113 |
+
/**
|
114 |
+
* Public constructor
|
115 |
+
*/
|
116 |
+
public function __construct() {
|
117 |
+
global $wpdb;
|
118 |
+
self::$_schema = $this->_get_schema( $wpdb->prefix );
|
119 |
+
$settings = $this->_get_settings();
|
120 |
+
$this->_settings = $settings;
|
121 |
+
self::$_settings_static = $settings;
|
122 |
+
}
|
123 |
|
124 |
+
/**
|
125 |
+
* initialize the extension.
|
126 |
+
*/
|
127 |
+
public function init( Ai1ec_Registry_Object $registry ) {
|
128 |
+
$this->_registry = $registry;
|
129 |
+
// static properties are needed as uninstall hook must be static
|
130 |
+
// http://wpseek.com/register_uninstall_hook/
|
131 |
+
self::$_registry_static = $registry;
|
132 |
+
register_deactivation_hook(
|
133 |
+
$this->get_file(),
|
134 |
+
array( $this, 'on_deactivation' )
|
135 |
+
);
|
136 |
|
137 |
+
$this->_install_schema( $registry );
|
138 |
+
$this->_register_actions( $registry->get( 'event.dispatcher' ) );
|
139 |
+
$this->_add_settings( $registry->get( 'model.settings' ) );
|
140 |
+
$this->_perform_upgrade( $registry );
|
141 |
+
if ( method_exists( $this, 'initialize_licence_actions' ) ) {
|
142 |
+
$this->initialize_licence_actions();
|
143 |
+
}
|
144 |
+
}
|
145 |
|
146 |
+
/**
|
147 |
+
* Hides settings on deactivation.
|
148 |
+
*/
|
149 |
+
public function on_deactivation() {
|
150 |
+
if ( ! current_user_can( 'activate_plugins' ) ) {
|
151 |
+
return;
|
152 |
+
}
|
153 |
+
$plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
|
154 |
+
$referer = 'deactivate-plugin_' . $plugin;
|
155 |
+
// if we are disabling the plugin in the exception handler, this can't be done.
|
156 |
+
// but i want to disable options
|
157 |
+
if ( function_exists( '_get_list_table' ) ) {
|
158 |
+
$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
|
159 |
+
$action = $wp_list_table->current_action();
|
160 |
+
if ( 'deactivate-selected' === $action ) {
|
161 |
+
$referer = 'bulk-plugins';
|
162 |
+
}
|
163 |
+
check_admin_referer( $referer );
|
164 |
+
}
|
165 |
+
$settings = $this->_registry->get( 'model.settings' );
|
166 |
+
foreach ( $this->_settings as $name => $params ) {
|
167 |
+
$settings->hide_option( $name );
|
168 |
+
}
|
169 |
+
}
|
170 |
|
171 |
+
/**
|
172 |
+
* Show the settings
|
173 |
+
*/
|
174 |
+
public function show_settings( Ai1ec_Registry_Object $registry ) {
|
175 |
+
$settings = $registry->get( 'model.settings' );
|
176 |
+
foreach ( $this->_settings as $name => $params ) {
|
177 |
+
if ( isset( $params['renderer'] ) ) {
|
178 |
+
$settings->show_option( $name, $params['renderer'] );
|
179 |
+
}
|
180 |
+
}
|
181 |
+
$settings->set( 'allow_statistics', true );
|
182 |
+
}
|
183 |
|
184 |
+
/**
|
185 |
+
* If extensions need to add tables, they will need to override the function to add a schema.
|
186 |
+
*
|
187 |
+
* @param string $prefix Database prefix to use for table names.
|
188 |
+
*
|
189 |
+
* @return array An array with two keys, schema and tables which are used
|
190 |
+
* for installing and dropping the table.
|
191 |
+
*/
|
192 |
+
protected static function _get_schema( $prefix ) {
|
193 |
+
return array(
|
194 |
+
'tables' => array(),
|
195 |
+
'schema' => '',
|
196 |
+
);
|
197 |
+
}
|
198 |
|
199 |
+
/**
|
200 |
+
* Performe upgarde actions based on extension version
|
201 |
+
*
|
202 |
+
* @param Ai1ec_Registry_Object $registry
|
203 |
+
*/
|
204 |
+
protected function _perform_upgrade( Ai1ec_Registry_Object $registry ) {
|
205 |
+
$version_variable = 'ai1ec_' . $this->get_machine_name() .
|
206 |
+
'_version';
|
207 |
+
$option = $registry->get( 'model.option' );
|
208 |
+
$version = $option->get( $version_variable );
|
209 |
+
if ( $version !== $this->get_version() ) {
|
210 |
+
$registry->get( 'model.settings' )->perform_upgrade_actions();
|
211 |
+
$this->_perform_upgrade_actions();
|
212 |
+
$option->set( $version_variable, $this->get_version(), true );
|
213 |
+
}
|
214 |
+
}
|
215 |
|
216 |
+
/**
|
217 |
+
* Function called on add on upgrade.
|
218 |
+
* Can be overridden by add ons for extra behaviour
|
219 |
+
*/
|
220 |
+
protected function _perform_upgrade_actions() {
|
|
|
|
|
221 |
|
222 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
+
/**
|
225 |
+
* Since the call the to the uninstall hook it's static, if a different behaviour
|
226 |
+
* is needed also this call must be overridden.
|
227 |
+
*/
|
228 |
+
protected function _register_uninstall_hook() {
|
229 |
+
register_uninstall_hook(
|
230 |
+
$this->get_file(),
|
231 |
+
array( get_class( $this ), 'on_uninstall' )
|
232 |
+
);
|
233 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
|
235 |
+
/**
|
236 |
+
* Adds extension settings
|
237 |
+
*
|
238 |
+
* @param Ai1ec_Settings $settings
|
239 |
+
*/
|
240 |
+
protected function _add_settings( Ai1ec_Settings $settings ) {
|
241 |
+
foreach ( $this->_settings as $name => $params ) {
|
242 |
+
$renderer = null;
|
243 |
+
if ( isset( $params['renderer'] ) ) {
|
244 |
+
$renderer = $params['renderer'];
|
245 |
+
}
|
246 |
+
$settings->register(
|
247 |
+
$name,
|
248 |
+
$params['value'],
|
249 |
+
$params['type'],
|
250 |
+
$renderer,
|
251 |
+
$this->get_version()
|
252 |
+
);
|
253 |
+
}
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Check if the schema needs to be updated
|
258 |
+
*
|
259 |
+
* @param Ai1ec_Registry_Object $registry
|
260 |
+
* @throws Ai1ec_Database_Update_Exception
|
261 |
+
*/
|
262 |
+
protected function _install_schema( Ai1ec_Registry_Object $registry ) {
|
263 |
+
$option = $registry->get( 'model.option' );
|
264 |
+
$schema = self::$_schema;
|
265 |
+
if (
|
266 |
+
is_admin() &&
|
267 |
+
! empty( $schema['schema'] )
|
268 |
+
) {
|
269 |
+
$db_version_variable = 'ai1ec_' . $this->get_machine_name() .
|
270 |
+
'_db_version';
|
271 |
+
$version = sha1( $schema['schema'] );
|
272 |
+
if (
|
273 |
+
$option->get( $db_version_variable ) !== $version
|
274 |
+
) {
|
275 |
+
if (
|
276 |
+
$registry->get( 'database.helper' )->apply_delta(
|
277 |
+
$schema['schema']
|
278 |
+
)
|
279 |
+
) {
|
280 |
+
$option->set( $db_version_variable, $version );
|
281 |
+
} else {
|
282 |
+
throw new Ai1ec_Database_Update_Exception(
|
283 |
+
'Database upgrade for ' . $this->get_name() .
|
284 |
+
' failed'
|
285 |
+
);
|
286 |
+
}
|
287 |
+
}
|
288 |
+
}
|
289 |
+
}
|
290 |
|
291 |
}
|
app/controller/front.php
CHANGED
@@ -11,1211 +11,1217 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Front_Controller {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
845 |
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
} else { // ! is_admin()
|
876 |
-
$dispatcher->register_action(
|
877 |
-
'after_setup_theme',
|
878 |
-
array( 'theme.loader', 'execute_theme_functions' )
|
879 |
-
);
|
880 |
-
$dispatcher->register_action(
|
881 |
-
'the_post',
|
882 |
-
array( 'post.content', 'check_content' ),
|
883 |
-
PHP_INT_MAX
|
884 |
-
);
|
885 |
-
$dispatcher->register_action(
|
886 |
-
'send_headers',
|
887 |
-
array( 'request.redirect', 'handle_categories_and_tags' )
|
888 |
-
);
|
889 |
-
$dispatcher->register_action(
|
890 |
-
'wp_head',
|
891 |
-
array( 'view.event.single', 'add_meta_tags' )
|
892 |
-
);
|
893 |
-
}
|
894 |
-
}
|
895 |
-
/**
|
896 |
-
* Outputs menu icon between head tags
|
897 |
-
*/
|
898 |
-
public function admin_head() {
|
899 |
-
global $wp_version;
|
900 |
-
$argv = array(
|
901 |
-
'before_font_icons' => version_compare( $wp_version, '3.8', '<' ),
|
902 |
-
'admin_theme_img_url' => AI1EC_ADMIN_THEME_IMG_URL,
|
903 |
-
'admin_theme_font_url' => AI1EC_ADMIN_THEME_FONT_URL,
|
904 |
-
);
|
905 |
-
$this->_registry->get( 'theme.loader' )
|
906 |
-
->get_file( 'timely-menu-icon.twig', $argv, true )
|
907 |
-
->render();
|
908 |
-
}
|
909 |
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
foreach ( $options as $item ) { // avoid array_filter + is_numeric
|
945 |
-
$item = (int)$item;
|
946 |
-
if ( $item > 0 ) {
|
947 |
-
$filtered[] = $item;
|
948 |
-
}
|
949 |
-
}
|
950 |
-
unset( $options );
|
951 |
-
if ( empty( $filtered ) ) {
|
952 |
-
return NULL;
|
953 |
-
}
|
954 |
-
return implode( ',', $filtered );
|
955 |
-
}
|
956 |
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
984 |
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
997 |
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
}
|
1011 |
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
}
|
1026 |
-
}
|
1027 |
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
|
|
|
|
|
|
|
|
1071 |
|
1072 |
-
|
1073 |
-
|
1074 |
-
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
|
|
1082 |
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
|
|
|
|
1091 |
|
1092 |
-
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
$db = $this->_registry->get( 'dbi.dbi' );
|
1101 |
-
$table_name = $db->get_table_name( 'ai1ec_event_category_colors' );
|
1102 |
-
$db_h = $this->_registry->get( 'database.helper' );
|
1103 |
-
if ( $db_h->table_exists( $table_name ) ) { // if old table exists otherwise ignore it
|
1104 |
-
// Migrate color information
|
1105 |
-
$dest_table = $db->get_table_name( 'ai1ec_event_category_meta' );
|
1106 |
-
$colors = $db->select(
|
1107 |
-
$table_name,
|
1108 |
-
array( 'term_id', 'term_color'),
|
1109 |
-
ARRAY_A
|
1110 |
-
);
|
1111 |
-
if ( ! empty( $colors ) ) {
|
1112 |
-
foreach ( $colors as $color ) {
|
1113 |
-
$db->insert( $dest_table, $color );
|
1114 |
-
}
|
1115 |
-
}
|
1116 |
-
// Drop the old table
|
1117 |
-
$db->query( 'DROP TABLE IF EXISTS ' . $table_name );
|
1118 |
-
}
|
1119 |
-
}
|
1120 |
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1129 |
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
|
1134 |
-
|
|
|
|
|
|
|
1135 |
|
1136 |
-
|
1137 |
-
|
1138 |
-
|
1139 |
-
|
1140 |
-
|
1141 |
|
1142 |
-
|
1143 |
-
|
1144 |
-
|
1145 |
-
|
|
|
1146 |
|
1147 |
-
|
1148 |
-
|
1149 |
-
|
1150 |
-
|
1151 |
-
*/
|
1152 |
-
public function get_current_db_schema() {
|
1153 |
-
$dbi = $this->_registry->get( 'dbi.dbi' );
|
1154 |
-
// =======================
|
1155 |
-
// = Create table events =
|
1156 |
-
// =======================
|
1157 |
-
$table_name = $dbi->get_table_name( 'ai1ec_events' );
|
1158 |
-
$sql = "CREATE TABLE $table_name (
|
1159 |
-
post_id bigint(20) NOT NULL,
|
1160 |
-
start int(10) UNSIGNED NOT NULL,
|
1161 |
-
end int(10) UNSIGNED,
|
1162 |
-
timezone_name varchar(50),
|
1163 |
-
allday tinyint(1) NOT NULL,
|
1164 |
-
instant_event tinyint(1) NOT NULL DEFAULT 0,
|
1165 |
-
recurrence_rules longtext,
|
1166 |
-
exception_rules longtext,
|
1167 |
-
recurrence_dates longtext,
|
1168 |
-
exception_dates longtext,
|
1169 |
-
venue varchar(255),
|
1170 |
-
country varchar(255),
|
1171 |
-
address varchar(255),
|
1172 |
-
city varchar(255),
|
1173 |
-
province varchar(255),
|
1174 |
-
postal_code varchar(32),
|
1175 |
-
show_map tinyint(1),
|
1176 |
-
contact_name varchar(255),
|
1177 |
-
contact_phone varchar(32),
|
1178 |
-
contact_email varchar(128),
|
1179 |
-
contact_url varchar(255),
|
1180 |
-
cost varchar(255),
|
1181 |
-
ticket_url varchar(255),
|
1182 |
-
ical_feed_url varchar(255),
|
1183 |
-
ical_source_url varchar(255),
|
1184 |
-
ical_organizer varchar(255),
|
1185 |
-
ical_contact varchar(255),
|
1186 |
-
ical_uid varchar(255),
|
1187 |
-
show_coordinates tinyint(1),
|
1188 |
-
latitude decimal(20,15),
|
1189 |
-
longitude decimal(20,15),
|
1190 |
-
force_regenerate tinyint(1) NOT NULL DEFAULT 0,
|
1191 |
-
PRIMARY KEY (post_id),
|
1192 |
-
KEY feed_source (ical_feed_url)
|
1193 |
-
) CHARACTER SET utf8;";
|
1194 |
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
1203 |
-
|
1204 |
-
|
1205 |
-
|
1206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1207 |
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
-
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
|
1216 |
-
|
1217 |
-
|
|
|
|
|
1218 |
|
1219 |
-
|
1220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1221 |
}
|
11 |
*/
|
12 |
class Ai1ec_Front_Controller {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var Ai1ec_Registry_Object The Object registry.
|
16 |
+
*/
|
17 |
+
protected $_registry;
|
18 |
|
19 |
+
/**
|
20 |
+
* @var bool Whether the domain has alredy been loaded or not.
|
21 |
+
*/
|
22 |
+
protected $_domain_loaded = false;
|
23 |
|
24 |
+
/**
|
25 |
+
* @var string The pagebase used by Ai1ec_Href_Helper.
|
26 |
+
*/
|
27 |
+
protected $_pagebase_for_href;
|
28 |
|
29 |
+
/**
|
30 |
+
* @var Ai1ec_Request_Parser Instance of the request pa
|
31 |
+
*/
|
32 |
+
protected $_request;
|
33 |
|
34 |
+
/**
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
protected $_default_theme;
|
38 |
|
39 |
+
/**
|
40 |
+
* Initializes the default theme property.
|
41 |
+
*/
|
42 |
+
public function __construct() {
|
43 |
+
// Initialize default theme.
|
44 |
+
$this->_default_theme = array(
|
45 |
+
'theme_dir' => AI1EC_DEFAULT_THEME_PATH,
|
46 |
+
'theme_root' => AI1EC_DEFAULT_THEME_ROOT,
|
47 |
+
'theme_url' => AI1EC_THEMES_URL . '/' . AI1EC_DEFAULT_THEME_NAME,
|
48 |
+
'stylesheet' => AI1EC_DEFAULT_THEME_NAME,
|
49 |
+
'legacy' => false,
|
50 |
+
);
|
51 |
+
}
|
52 |
|
53 |
+
/**
|
54 |
+
* Initialize the controller.
|
55 |
+
*
|
56 |
+
* @param Ai1ec_Loader $ai1ec_loader Instance of Ai1EC classes loader
|
57 |
+
*
|
58 |
+
* @return void
|
59 |
+
*/
|
60 |
+
public function initialize( $ai1ec_loader ) {
|
61 |
+
ai1ec_start();
|
62 |
+
$this->_init( $ai1ec_loader );
|
63 |
+
$this->_initialize_dispatcher();
|
64 |
+
$lessphp = $this->_registry->get( 'less.lessphp' );
|
65 |
+
$lessphp->initialize_less_variables_if_not_set();
|
66 |
+
$this->_registry->get( 'controller.shutdown' )
|
67 |
+
->register( 'ai1ec_stop' );
|
68 |
+
add_action( 'plugins_loaded', array( $this, 'register_extensions' ), 1 );
|
69 |
+
add_action( 'after_setup_theme', array( $this, 'register_themes' ), 1 );
|
70 |
+
add_action( 'init', array( $lessphp, 'invalidate_css_cache_if_requested' ) );
|
71 |
+
}
|
72 |
|
73 |
+
/**
|
74 |
+
* Let other objects access default theme
|
75 |
+
*
|
76 |
+
* @return array
|
77 |
+
*/
|
78 |
+
public function get_default_theme() {
|
79 |
+
return $this->_default_theme;
|
80 |
+
}
|
81 |
|
82 |
+
/**
|
83 |
+
* Remove unwanted menus
|
84 |
+
*/
|
85 |
+
public function admin_menu() {
|
86 |
+
remove_submenu_page(
|
87 |
+
'edit.php?post_type=ai1ec_event',
|
88 |
+
'edit-tags.php?taxonomy=events_tags&post_type=ai1ec_event'
|
89 |
+
);
|
90 |
+
}
|
91 |
|
92 |
+
/**
|
93 |
+
* Notify extensions and pass them instance of objects registry.
|
94 |
+
*
|
95 |
+
* @return void
|
96 |
+
*/
|
97 |
+
public function register_extensions() {
|
98 |
+
do_action( 'ai1ec_loaded', $this->_registry );
|
99 |
+
}
|
100 |
|
101 |
+
/**
|
102 |
+
* Notify themes and pass them instance of objects registry.
|
103 |
+
*
|
104 |
+
* @return void
|
105 |
+
*/
|
106 |
+
public function register_themes() {
|
107 |
+
do_action( 'ai1ec_after_themes_setup', $this->_registry );
|
108 |
+
}
|
109 |
|
110 |
+
/**
|
111 |
+
* Returns the registry object
|
112 |
+
*
|
113 |
+
* @param mixed $discard not used. Always return the registry.
|
114 |
+
*
|
115 |
+
* @return Ai1ec_Registry_Object
|
116 |
+
*/
|
117 |
+
public function return_registry( $discard ) {
|
118 |
+
return $this->_registry;
|
119 |
+
}
|
120 |
|
121 |
+
/**
|
122 |
+
* If WIDGET_PARAMETER is set.
|
123 |
+
*
|
124 |
+
* @return boolean
|
125 |
+
*/
|
126 |
+
protected function is_widget() {
|
127 |
+
return isset(
|
128 |
+
$_GET[Ai1ec_Controller_Javascript_Widget::WIDGET_PARAMETER]
|
129 |
+
);
|
130 |
+
}
|
131 |
|
132 |
+
/**
|
133 |
+
* If Advanced JS cache enabled.
|
134 |
+
*
|
135 |
+
* @return boolean
|
136 |
+
*/
|
137 |
+
protected function if_js_cache_enabled() {
|
138 |
+
$settings = $this->_registry->get( 'model.settings' );
|
139 |
+
return $settings->get( 'cache_dynamic_js' );
|
140 |
+
}
|
141 |
|
142 |
+
/**
|
143 |
+
* If LEGACY_WIDGET_PARAMETER is set.
|
144 |
+
*
|
145 |
+
* @return boolean
|
146 |
+
*/
|
147 |
+
protected function is_legacy_widget() {
|
148 |
+
return isset(
|
149 |
+
$_GET[Ai1ec_Controller_Javascript_Widget::LEGACY_WIDGET_PARAMETER]
|
150 |
+
);
|
151 |
+
}
|
152 |
|
153 |
+
/**
|
154 |
+
* Execute commands if our plugin must handle the request.
|
155 |
+
*
|
156 |
+
* @wp_hook init
|
157 |
+
*
|
158 |
+
* @return void
|
159 |
+
*/
|
160 |
+
public function route_request() {
|
161 |
+
$this->_process_request();
|
162 |
+
// get the resolver
|
163 |
+
$resolver = $this->_registry->get(
|
164 |
+
'command.resolver',
|
165 |
+
$this->_request
|
166 |
+
);
|
167 |
+
// get the command
|
168 |
+
$commands = $resolver->get_commands();
|
169 |
+
// if we have a command
|
170 |
+
if ( ! empty( $commands ) ) {
|
171 |
+
foreach( $commands as $command ) {
|
172 |
+
$result = $command->execute();
|
173 |
+
if ( $command->stop_execution() ) {
|
174 |
+
return $result;
|
175 |
+
}
|
176 |
+
}
|
177 |
+
}
|
178 |
+
}
|
179 |
|
180 |
+
/**
|
181 |
+
* Initializes the URL router used by our plugin.
|
182 |
+
*
|
183 |
+
* @wp_hook init
|
184 |
+
*
|
185 |
+
* @return void
|
186 |
+
*/
|
187 |
+
public function initialize_router() {
|
188 |
+
/* @var $cal_state Ai1ec_Calendar_State */
|
189 |
+
$cal_state = $this->_registry->get( 'calendar.state' );
|
190 |
+
$cal_state->set_routing_initialization( true );
|
191 |
+
$settings = $this->_registry->get( 'model.settings' );
|
192 |
+
$cal_page = $settings->get( 'calendar_page_id' );
|
193 |
|
194 |
+
if (
|
195 |
+
! $cal_page ||
|
196 |
+
$cal_page < 1
|
197 |
+
) { // Routing may not be affected in any way if no calendar page exists.
|
198 |
+
$cal_state->set_routing_initialization( false );
|
199 |
+
return null;
|
200 |
+
}
|
201 |
+
$router = $this->_registry->get( 'routing.router' );
|
202 |
+
$localization_helper = $this->_registry->get( 'p28n.wpml' );
|
203 |
+
$page_base = '';
|
204 |
+
$clang = '';
|
205 |
|
206 |
+
if ( $localization_helper->is_wpml_active() ) {
|
207 |
+
$trans = $localization_helper
|
208 |
+
->get_wpml_translations_of_page(
|
209 |
+
$cal_page,
|
210 |
+
true
|
211 |
+
);
|
212 |
+
$clang = $localization_helper->get_language();
|
213 |
+
if ( isset( $trans[$clang] ) ) {
|
214 |
+
$cal_page = $trans[$clang];
|
215 |
+
}
|
216 |
+
}
|
217 |
+
$template_link_helper = $this->_registry->get( 'template.link.helper' );
|
218 |
|
219 |
+
if ( ! get_post( $cal_page ) ) {
|
220 |
+
$cal_state->set_routing_initialization( false );
|
221 |
+
return null;
|
222 |
+
}
|
223 |
|
224 |
+
$page_base = $template_link_helper->get_page_link(
|
225 |
+
$cal_page
|
226 |
+
);
|
227 |
|
228 |
+
$page_base = Ai1ec_Wp_Uri_Helper::get_pagebase( $page_base );
|
229 |
+
$page_link = 'index.php?page_id=' .
|
230 |
+
$cal_page;
|
231 |
+
$pagebase_for_href = Ai1ec_Wp_Uri_Helper::get_pagebase_for_links(
|
232 |
+
get_page_link( $cal_page ),
|
233 |
+
$clang
|
234 |
+
);
|
235 |
|
236 |
+
// save the pagebase to set up the factory later
|
237 |
+
$application = $this->_registry->get( 'bootstrap.registry.application' );
|
238 |
+
$application->set( 'calendar_base_page', $pagebase_for_href );
|
239 |
+
$option = $this->_registry->get( 'model.option' );
|
240 |
|
241 |
+
// If the calendar is set as the front page, disable permalinks.
|
242 |
+
// They would not be legal under a Windows server. See:
|
243 |
+
// https://issues.apache.org/bugzilla/show_bug.cgi?id=41441
|
244 |
|
245 |
+
if (
|
246 |
+
$option->get( 'permalink_structure' ) &&
|
247 |
+
( int ) get_option( 'page_on_front' ) !==
|
248 |
+
( int ) $cal_page
|
249 |
+
) {
|
250 |
+
$application->set( 'permalinks_enabled', true );
|
251 |
+
}
|
252 |
|
253 |
+
$router->asset_base( $page_base )
|
254 |
+
->register_rewrite( $page_link );
|
255 |
+
$cal_state->set_routing_initialization( false );
|
256 |
+
}
|
257 |
|
258 |
+
/**
|
259 |
+
* Initialize the system.
|
260 |
+
*
|
261 |
+
* Perform all the inizialization needed for the system.
|
262 |
+
* Throws some uncatched exception for critical failures.
|
263 |
+
* Plugin will be disabled by the exception handler on those failures.
|
264 |
+
*
|
265 |
+
* @param Ai1ec_Loader $ai1ec_loader Instance of Ai1EC classes loader
|
266 |
+
*
|
267 |
+
* @throws Ai1ec_Constants_Not_Set_Exception
|
268 |
+
* @throws Ai1ec_Database_Update_Exception
|
269 |
+
* @throws Ai1ec_Database_Schema_Exception
|
270 |
+
*
|
271 |
+
* @return void Method does not return
|
272 |
+
*/
|
273 |
+
protected function _init( $ai1ec_loader ) {
|
274 |
+
$exception = null;
|
275 |
+
// Load the textdomain
|
276 |
+
add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
|
277 |
+
try {
|
278 |
+
// Initialize the registry object
|
279 |
+
$this->_initialize_registry( $ai1ec_loader );
|
280 |
+
$this->_registry->get( 'event.dispatcher' )->register_filter(
|
281 |
+
'ai1ec_perform_scheme_update',
|
282 |
+
array( 'database.datetime-migration', 'filter_scheme_update' )
|
283 |
+
);
|
284 |
+
// Procedures to take when upgrading plugin version
|
285 |
+
$this->_plugin_upgrade_procedures();
|
286 |
+
// Load the css if needed
|
287 |
+
$this->_load_css_if_needed();
|
288 |
+
// Initialize the crons
|
289 |
+
$this->_install_crons();
|
290 |
+
// Register the activation hook
|
291 |
+
$this->_initialize_schema();
|
292 |
+
// set the default theme if not set
|
293 |
+
$this->_add_default_theme_if_not_set();
|
294 |
+
} catch ( Ai1ec_Constants_Not_Set_Exception $e ) {
|
295 |
+
// This is blocking, throw it and disable the plugin
|
296 |
+
$exception = $e;
|
297 |
+
} catch ( Ai1ec_Database_Update_Exception $e ) {
|
298 |
+
// Blocking throw it so that the plugin is disabled
|
299 |
+
$exception = $e;
|
300 |
+
} catch ( Ai1ec_Database_Schema_Exception $e ) {
|
301 |
+
// Blocking throw it so that the plugin is disabled
|
302 |
+
$exception = $e;
|
303 |
+
} catch ( Ai1ec_Scheduling_Exception $e ) {
|
304 |
+
// not blocking
|
305 |
+
}
|
306 |
|
307 |
+
if ( null !== $exception ) {
|
308 |
+
throw $exception;
|
309 |
+
}
|
310 |
+
}
|
311 |
|
312 |
+
/**
|
313 |
+
* Set the default theme if no theme is set, or populate theme info array if
|
314 |
+
* insufficient information is currently being stored.
|
315 |
+
*
|
316 |
+
* @uses apply_filters() Calls 'ai1ec_pre_save_current_theme' hook to allow
|
317 |
+
* overwriting of theme information before being stored.
|
318 |
+
*/
|
319 |
+
protected function _add_default_theme_if_not_set() {
|
320 |
+
$option = $this->_registry->get( 'model.option' );
|
321 |
+
$theme = $option->get( 'ai1ec_current_theme', array() );
|
322 |
+
$update = false;
|
323 |
+
// Theme setting is undefined; default to Vortex.
|
324 |
+
if ( empty( $theme ) ) {
|
325 |
+
$theme = $this->_default_theme;
|
326 |
+
$update = true;
|
327 |
+
}
|
328 |
+
// Legacy settings; in 1.x the active theme was stored as a bare string,
|
329 |
+
// and they were located in a different folder than they are now.
|
330 |
+
else if ( is_string( $theme ) ) {
|
331 |
+
$theme_name = strtolower( $theme );
|
332 |
+
$core_themes = explode( ',', AI1EC_CORE_THEMES );
|
333 |
+
$legacy = ! in_array( $theme_name, $core_themes );
|
334 |
|
335 |
+
if ( $legacy ) {
|
336 |
+
$root = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . AI1EC_THEME_FOLDER;
|
337 |
+
$url = WP_CONTENT_URL . '/' . AI1EC_THEME_FOLDER . '/' . $theme_name;
|
338 |
+
} else {
|
339 |
+
$root = AI1EC_DEFAULT_THEME_ROOT;
|
340 |
+
$url = AI1EC_THEMES_URL . '/' . $theme_name;
|
341 |
+
}
|
342 |
+
// if it's from 1.x, move folders to avoid confusion
|
343 |
+
if ( apply_filters( 'ai1ec_move_themes_to_backup', true ) ) {
|
344 |
+
$this->_registry->get( 'theme.search' )
|
345 |
+
->move_themes_to_backup( $core_themes );
|
346 |
+
}
|
347 |
+
// Ensure existence of theme directory.
|
348 |
+
if ( ! is_dir( $root . DIRECTORY_SEPARATOR . $theme_name ) ) {
|
349 |
+
// It's missing; something is wrong with this theme. Reset theme to
|
350 |
+
// Vortex and warn the user accordingly.
|
351 |
+
$option->set( 'ai1ec_current_theme', $this->_default_theme );
|
352 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
353 |
+
$notification->store(
|
354 |
+
sprintf(
|
355 |
+
Ai1ec_I18n::__(
|
356 |
+
'Your active calendar theme could not be properly initialized. The default theme has been activated instead. Please visit %s and try reactivating your theme manually.'
|
357 |
+
),
|
358 |
+
'<a href="' . ai1ec_admin_url( AI1EC_THEME_SELECTION_BASE_URL ) . '">' .
|
359 |
+
Ai1ec_I18n::__( 'Calendar Themes' ) . '</a>'
|
360 |
+
),
|
361 |
+
'error',
|
362 |
+
1
|
363 |
+
);
|
364 |
+
}
|
365 |
|
366 |
+
$theme = array(
|
367 |
+
'theme_dir' => $root . DIRECTORY_SEPARATOR . $theme_name,
|
368 |
+
'theme_root' => $root,
|
369 |
+
'theme_url' => $url,
|
370 |
+
'stylesheet' => $theme_name,
|
371 |
+
'legacy' => $legacy,
|
372 |
+
);
|
373 |
+
$update = true;
|
374 |
+
}
|
375 |
+
// Ensure 'theme_url' is defined, as this property was added after the first
|
376 |
+
// public beta release.
|
377 |
+
else if ( ! isset( $theme['theme_url'] ) ) {
|
378 |
+
if ( $theme['legacy'] ) {
|
379 |
+
$theme['theme_url'] = WP_CONTENT_URL . '/' . AI1EC_THEME_FOLDER . '/' .
|
380 |
+
$theme['stylesheet'];
|
381 |
+
} else {
|
382 |
+
$theme['theme_url'] = AI1EC_THEMES_URL . '/' . $theme['stylesheet'];
|
383 |
+
}
|
384 |
+
$update = true;
|
385 |
+
}
|
386 |
|
387 |
+
if ( $update ) {
|
388 |
+
$theme = apply_filters( 'ai1ec_pre_save_current_theme', $theme );
|
389 |
+
$option->set( 'ai1ec_current_theme', $theme );
|
390 |
+
}
|
391 |
+
}
|
392 |
|
393 |
+
/**
|
394 |
+
* Adds actions handled by the front controller.
|
395 |
+
*/
|
396 |
+
protected function _add_front_controller_actions() {
|
397 |
+
// Initialize router. I use add_action as the dispatcher would just add
|
398 |
+
// overhead.
|
399 |
+
add_action(
|
400 |
+
'init',
|
401 |
+
array( $this, 'initialize_router' ),
|
402 |
+
PHP_INT_MAX - 1
|
403 |
+
);
|
404 |
+
add_action(
|
405 |
+
'widgets_init',
|
406 |
+
array( 'Ai1ec_View_Admin_Widget', 'register_widget' )
|
407 |
+
);
|
408 |
|
409 |
+
if (
|
410 |
+
$this->is_widget() ||
|
411 |
+
$this->is_legacy_widget()
|
412 |
+
) {
|
413 |
+
$this->_registry->get( 'event.dispatcher' )->register_action(
|
414 |
+
'init',
|
415 |
+
array( 'controller.javascript-widget', 'render_js_widget' ),
|
416 |
+
PHP_INT_MAX
|
417 |
+
);
|
418 |
+
}
|
419 |
|
420 |
+
// Route the request.
|
421 |
+
$action = 'template_redirect';
|
422 |
+
if ( is_admin() ) {
|
423 |
+
$action = 'init';
|
424 |
+
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
425 |
+
}
|
426 |
+
add_action( $action, array( $this, 'route_request' ) );
|
427 |
+
add_filter( 'ai1ec_registry', array( $this, 'return_registry' ) );
|
428 |
+
}
|
429 |
|
430 |
+
/**
|
431 |
+
* Initialize the dispatcher.
|
432 |
+
*
|
433 |
+
* Complete this when writing the dispatcher.
|
434 |
+
*
|
435 |
+
* @return void
|
436 |
+
*/
|
437 |
+
protected function _initialize_dispatcher() {
|
438 |
+
$dispatcher = $this->_registry->get( 'event.dispatcher' );
|
439 |
+
$dispatcher->register_action(
|
440 |
+
'init',
|
441 |
+
array( 'post.custom-type', 'register' )
|
442 |
+
);
|
443 |
+
$this->_add_front_controller_actions();
|
444 |
+
if ( isset( $_GET[Ai1ec_Javascript_Controller::LOAD_JS_PARAMETER] ) ) {
|
445 |
+
$dispatcher->register_action(
|
446 |
+
'wp_loaded',
|
447 |
+
array( 'controller.javascript', 'render_js' )
|
448 |
+
);
|
449 |
+
}
|
450 |
+
$dispatcher->register_action(
|
451 |
+
'before_delete_post',
|
452 |
+
array( 'model.event.trashing', 'before_delete_post' ),
|
453 |
+
0,
|
454 |
+
3
|
455 |
+
);
|
456 |
+
$dispatcher->register_action(
|
457 |
+
'delete_post',
|
458 |
+
array( 'model.event.trashing', 'delete' )
|
459 |
+
);
|
460 |
+
$dispatcher->register_action(
|
461 |
+
'wp_trash_post',
|
462 |
+
array( 'model.event.trashing', 'trash_post' )
|
463 |
+
);
|
464 |
+
$dispatcher->register_action(
|
465 |
+
'trashed_post',
|
466 |
+
array( 'model.event.trashing', 'trashed_post' )
|
467 |
+
);
|
468 |
+
$dispatcher->register_action(
|
469 |
+
'untrash_post',
|
470 |
+
array( 'model.event.trashing', 'untrash_post' )
|
471 |
+
);
|
472 |
+
$dispatcher->register_action(
|
473 |
+
'untrashed_post',
|
474 |
+
array( 'model.event.trashing', 'untrashed_post' )
|
475 |
+
);
|
476 |
+
$dispatcher->register_action(
|
477 |
+
'pre_http_request',
|
478 |
+
array( 'http.request', 'pre_http_request' ),
|
479 |
+
10,
|
480 |
+
3
|
481 |
+
);
|
482 |
+
$dispatcher->register_action(
|
483 |
+
'http_request_args',
|
484 |
+
array( 'http.request', 'init_certificate' ),
|
485 |
+
10,
|
486 |
+
2
|
487 |
+
);
|
488 |
+
// add the filter to let the organize page work
|
489 |
+
$dispatcher->register_action(
|
490 |
+
'admin_init',
|
491 |
+
array( 'view.admin.organize', 'add_taxonomy_actions' ),
|
492 |
+
10000
|
493 |
+
);
|
494 |
+
$dispatcher->register_action(
|
495 |
+
'plugins_loaded',
|
496 |
+
array( 'theme.loader', 'clean_cache_on_upgrade' ),
|
497 |
+
PHP_INT_MAX
|
498 |
+
);
|
499 |
+
$dispatcher->register_filter(
|
500 |
+
'get_the_excerpt',
|
501 |
+
array( 'view.event.content', 'event_excerpt' ),
|
502 |
+
11
|
503 |
+
);
|
504 |
+
remove_filter( 'the_excerpt', 'wpautop', 10 );
|
505 |
+
$dispatcher->register_filter(
|
506 |
+
'the_excerpt',
|
507 |
+
array( 'view.event.content', 'event_excerpt_noautop' ),
|
508 |
+
11
|
509 |
+
);
|
510 |
+
$dispatcher->register_filter(
|
511 |
+
'robots_txt',
|
512 |
+
array( 'robots.helper', 'rules' ),
|
513 |
+
10,
|
514 |
+
2
|
515 |
+
);
|
516 |
+
$dispatcher->register_filter(
|
517 |
+
'ai1ec_dbi_debug',
|
518 |
+
array( 'http.request', 'debug_filter' )
|
519 |
+
);
|
520 |
+
$dispatcher->register_filter(
|
521 |
+
'ai1ec_dbi_debug',
|
522 |
+
array( 'compatibility.cli', 'disable_db_debug' )
|
523 |
+
);
|
524 |
+
// editing a child instance
|
525 |
+
if ( isset( $_SERVER['SCRIPT_NAME'] ) && basename( $_SERVER['SCRIPT_NAME'] ) === 'post.php' ) {
|
526 |
+
$dispatcher->register_action(
|
527 |
+
'admin_action_editpost',
|
528 |
+
array( 'model.event.parent', 'admin_init_post' )
|
529 |
+
);
|
530 |
+
$dispatcher->register_filter(
|
531 |
+
'user_has_cap',
|
532 |
+
array( 'content.filter', 'display_trash_link' ),
|
533 |
+
10,
|
534 |
+
2
|
535 |
+
);
|
536 |
+
}
|
537 |
+
// post row action for parent/child
|
538 |
+
$dispatcher->register_action(
|
539 |
+
'post_row_actions',
|
540 |
+
array( 'model.event.parent', 'post_row_actions' ),
|
541 |
+
100,
|
542 |
+
2
|
543 |
+
);
|
544 |
+
// Category colors
|
545 |
+
$dispatcher->register_action(
|
546 |
+
'events_categories_add_form_fields',
|
547 |
+
array( 'view.admin.event-category', 'events_categories_add_form_fields' )
|
548 |
+
);
|
549 |
+
$dispatcher->register_action(
|
550 |
+
'events_categories_edit_form_fields',
|
551 |
+
array( 'view.admin.event-category', 'events_categories_edit_form_fields' )
|
552 |
+
);
|
553 |
+
$dispatcher->register_action(
|
554 |
+
'created_events_categories',
|
555 |
+
array( 'view.admin.event-category', 'created_events_categories' )
|
556 |
+
);
|
557 |
+
$dispatcher->register_action(
|
558 |
+
'edited_events_categories',
|
559 |
+
array( 'view.admin.event-category', 'edited_events_categories' )
|
560 |
+
);
|
561 |
+
$dispatcher->register_action(
|
562 |
+
'manage_edit-events_categories_columns',
|
563 |
+
array( 'view.admin.event-category', 'manage_event_categories_columns' )
|
564 |
+
);
|
565 |
+
$dispatcher->register_action(
|
566 |
+
'manage_events_categories_custom_column',
|
567 |
+
array( 'view.admin.event-category', 'manage_events_categories_custom_column' ),
|
568 |
+
10,
|
569 |
+
3
|
570 |
+
);
|
571 |
|
572 |
+
// register ICS cron action
|
573 |
+
$dispatcher->register_action(
|
574 |
+
Ai1ecIcsConnectorPlugin::HOOK_NAME,
|
575 |
+
array( 'calendar-feed.ics', 'cron' )
|
576 |
+
);
|
577 |
+
$dispatcher->register_shortcode(
|
578 |
+
'ai1ec',
|
579 |
+
array( 'view.calendar.shortcode', 'shortcode' )
|
580 |
+
);
|
581 |
+
$dispatcher->register_action(
|
582 |
+
'updated_option',
|
583 |
+
array( 'model.settings', 'wp_options_observer' ),
|
584 |
+
PHP_INT_MAX - 1,
|
585 |
+
3
|
586 |
+
);
|
587 |
|
588 |
+
$dispatcher->register_action(
|
589 |
+
'ai1ec_settings_updated',
|
590 |
+
array( 'compatibility.check', 'ai1ec_settings_observer' ),
|
591 |
+
PHP_INT_MAX - 1,
|
592 |
+
2
|
593 |
+
);
|
594 |
+
if ( $this->if_js_cache_enabled() ) {
|
595 |
+
$dispatcher->register_action(
|
596 |
+
'ai1ec_settings_updated',
|
597 |
+
array( 'controller.javascript', 'revalidate_cache' ),
|
598 |
+
PHP_INT_MAX - 1
|
599 |
+
);
|
600 |
+
$dispatcher->register_action(
|
601 |
+
'ai1ec_settings_updated',
|
602 |
+
array( 'controller.javascript-widget', 'revalidate_cache' ),
|
603 |
+
PHP_INT_MAX - 1
|
604 |
+
);
|
605 |
+
}
|
606 |
|
607 |
+
if ( is_admin() ) {
|
608 |
+
// Import suggested event
|
609 |
+
$dispatcher->register_action(
|
610 |
+
'wp_ajax_ai1ec_import_suggested_event',
|
611 |
+
array( 'calendar-feed.ics', 'add_discover_events_feed_subscription' )
|
612 |
+
);
|
613 |
+
// Remove suggested event
|
614 |
+
$dispatcher->register_action(
|
615 |
+
'wp_ajax_ai1ec_remove_suggested_event',
|
616 |
+
array( 'calendar-feed.ics', 'delete_individual_event_subscription' )
|
617 |
+
);
|
618 |
+
// Search for events
|
619 |
+
$dispatcher->register_action(
|
620 |
+
'wp_ajax_ai1ec_search_events',
|
621 |
+
array( 'calendar-feed.suggested', 'search_events' )
|
622 |
+
);
|
623 |
+
// get the repeat box
|
624 |
+
$dispatcher->register_action(
|
625 |
+
'wp_ajax_ai1ec_get_repeat_box',
|
626 |
+
array( 'view.admin.get-repeat-box', 'get_repeat_box' )
|
627 |
+
);
|
628 |
+
// get the tax options box
|
629 |
+
$dispatcher->register_action(
|
630 |
+
'wp_ajax_ai1ec_get_tax_box',
|
631 |
+
array( 'view.admin.get-tax-box', 'get_tax_box' )
|
632 |
+
);
|
633 |
+
// add dismissable notice handler
|
634 |
+
$dispatcher->register_action(
|
635 |
+
'wp_ajax_ai1ec_dismiss_notice',
|
636 |
+
array( 'notification.admin', 'dismiss_notice' )
|
637 |
+
);
|
638 |
+
// save rrurle and convert it to text
|
639 |
+
$dispatcher->register_action(
|
640 |
+
'wp_ajax_ai1ec_rrule_to_text',
|
641 |
+
array( 'view.admin.get-repeat-box', 'convert_rrule_to_text' )
|
642 |
+
);
|
643 |
+
// display ticketing details in the events list
|
644 |
+
$dispatcher->register_action(
|
645 |
+
'wp_ajax_ai1ec_show_ticket_details',
|
646 |
+
array( 'view.admin.all-events', 'show_ticket_details' )
|
647 |
+
);
|
648 |
+
// display attendees list
|
649 |
+
$dispatcher->register_action(
|
650 |
+
'wp_ajax_ai1ec_show_attendees',
|
651 |
+
array( 'view.admin.all-events', 'show_attendees' )
|
652 |
+
);
|
653 |
+
// CSS and templates for ticketing options
|
654 |
+
$dispatcher->register_action(
|
655 |
+
'restrict_manage_posts',
|
656 |
+
array( 'view.admin.all-events', 'add_ticketing_styling' )
|
657 |
+
);
|
658 |
+
// taxonomy filter
|
659 |
+
$dispatcher->register_action(
|
660 |
+
'restrict_manage_posts',
|
661 |
+
array( 'view.admin.all-events', 'taxonomy_filter_restrict_manage_posts' )
|
662 |
+
);
|
663 |
+
$dispatcher->register_action(
|
664 |
+
'parse_query',
|
665 |
+
array( 'view.admin.all-events', 'taxonomy_filter_post_type_request' )
|
666 |
+
);
|
667 |
+
$dispatcher->register_action(
|
668 |
+
'admin_menu',
|
669 |
+
array( 'view.admin.calendar-feeds', 'add_page' )
|
670 |
+
);
|
671 |
+
$dispatcher->register_action(
|
672 |
+
'current_screen',
|
673 |
+
array( 'view.admin.calendar-feeds', 'add_meta_box' )
|
674 |
+
);
|
675 |
+
$dispatcher->register_action(
|
676 |
+
'admin_menu',
|
677 |
+
array( 'view.admin.add-ons', 'add_page' )
|
678 |
+
);
|
679 |
+
$dispatcher->register_action(
|
680 |
+
'admin_menu',
|
681 |
+
array( 'view.admin.theme-switching', 'add_page' )
|
682 |
+
);
|
683 |
+
$dispatcher->register_action(
|
684 |
+
'admin_menu',
|
685 |
+
array( 'view.admin.theme-options', 'add_page' )
|
686 |
+
);
|
687 |
+
$dispatcher->register_action(
|
688 |
+
'current_screen',
|
689 |
+
array( 'view.admin.theme-options', 'add_meta_box' )
|
690 |
+
);
|
691 |
+
$dispatcher->register_action(
|
692 |
+
'admin_menu',
|
693 |
+
array( 'view.admin.settings', 'add_page' )
|
694 |
+
);
|
695 |
+
$dispatcher->register_action(
|
696 |
+
'current_screen',
|
697 |
+
array( 'view.admin.settings', 'add_meta_box' )
|
698 |
+
);
|
699 |
+
$dispatcher->register_action(
|
700 |
+
'init',
|
701 |
+
array( 'controller.javascript', 'load_admin_js' )
|
702 |
+
);
|
703 |
+
$dispatcher->register_action(
|
704 |
+
'admin_menu',
|
705 |
+
array( 'view.admin.samples', 'add_page' ),
|
706 |
+
100,
|
707 |
+
1
|
708 |
+
);
|
709 |
+
$dispatcher->register_action(
|
710 |
+
'wp_ajax_ai1ec_add_ics',
|
711 |
+
array( 'calendar-feed.ics', 'add_ics_feed' )
|
712 |
+
);
|
713 |
+
$dispatcher->register_action(
|
714 |
+
'wp_ajax_ai1ec_delete_ics',
|
715 |
+
array( 'calendar-feed.ics', 'delete_feeds_and_events' )
|
716 |
+
);
|
717 |
+
$dispatcher->register_action(
|
718 |
+
'wp_ajax_ai1ec_update_ics',
|
719 |
+
array( 'calendar-feed.ics', 'update_ics_feed' )
|
720 |
+
);
|
721 |
+
$dispatcher->register_action(
|
722 |
+
'wp_ajax_ai1ec_feeds_page_post',
|
723 |
+
array( 'calendar-feed.ics', 'handle_feeds_page_post' )
|
724 |
+
);
|
725 |
+
$dispatcher->register_action(
|
726 |
+
'wp_ajax_ai1ec_send_feedback_message',
|
727 |
+
array( 'model.review', 'send_feedback_message' )
|
728 |
+
);
|
729 |
+
$dispatcher->register_action(
|
730 |
+
'wp_ajax_ai1ec_save_feedback_review',
|
731 |
+
array( 'model.review', 'save_feedback_review' )
|
732 |
+
);
|
733 |
+
$dispatcher->register_action(
|
734 |
+
'network_admin_notices',
|
735 |
+
array( 'notification.admin', 'send' )
|
736 |
+
);
|
737 |
+
$dispatcher->register_action(
|
738 |
+
'admin_notices',
|
739 |
+
array( 'notification.admin', 'send' )
|
740 |
+
);
|
741 |
+
$dispatcher->register_action(
|
742 |
+
'admin_footer-edit.php',
|
743 |
+
array( 'clone.renderer-helper', 'duplicate_custom_bulk_admin_footer' )
|
744 |
+
);
|
745 |
+
$dispatcher->register_filter(
|
746 |
+
'post_row_actions',
|
747 |
+
array( 'clone.renderer-helper', 'ai1ec_duplicate_post_make_duplicate_link_row' ),
|
748 |
+
100,
|
749 |
+
2
|
750 |
+
);
|
751 |
+
$dispatcher->register_action(
|
752 |
+
'add_meta_boxes',
|
753 |
+
array( 'view.admin.add-new-event', 'event_meta_box_container' )
|
754 |
+
);
|
755 |
+
$dispatcher->register_action(
|
756 |
+
'edit_form_after_title',
|
757 |
+
array( 'view.admin.add-new-event', 'event_inline_alert' )
|
758 |
+
);
|
759 |
+
$dispatcher->register_action(
|
760 |
+
'save_post',
|
761 |
+
array( 'model.event.creating', 'save_post' ),
|
762 |
+
10,
|
763 |
+
3
|
764 |
+
);
|
765 |
+
$dispatcher->register_action(
|
766 |
+
'pre_post_update',
|
767 |
+
array( 'model.event.creating', 'pre_post_update' ),
|
768 |
+
0,
|
769 |
+
2
|
770 |
+
);
|
771 |
+
$dispatcher->register_action(
|
772 |
+
'wp_insert_post_data',
|
773 |
+
array( 'model.event.creating', 'wp_insert_post_data' )
|
774 |
+
);
|
775 |
+
$dispatcher->register_action(
|
776 |
+
'manage_ai1ec_event_posts_custom_column',
|
777 |
+
array( 'view.admin.all-events', 'custom_columns' ),
|
778 |
+
10,
|
779 |
+
2
|
780 |
+
);
|
781 |
+
$dispatcher->register_filter(
|
782 |
+
'manage_ai1ec_event_posts_columns',
|
783 |
+
array( 'view.admin.all-events', 'change_columns' )
|
784 |
+
);
|
785 |
+
$dispatcher->register_filter(
|
786 |
+
'manage_edit-ai1ec_event_sortable_columns',
|
787 |
+
array( 'view.admin.all-events', 'sortable_columns' )
|
788 |
+
);
|
789 |
+
$dispatcher->register_filter(
|
790 |
+
'posts_orderby',
|
791 |
+
array( 'view.admin.all-events', 'orderby' ),
|
792 |
+
10,
|
793 |
+
2
|
794 |
+
);
|
795 |
+
$dispatcher->register_filter(
|
796 |
+
'ai1ec_count_future_events',
|
797 |
+
array( 'view.admin.all-events', 'count_future_events' ),
|
798 |
+
10,
|
799 |
+
1
|
800 |
+
);
|
801 |
+
$dispatcher->register_filter(
|
802 |
+
'post_updated_messages',
|
803 |
+
array( 'view.event.post', 'post_updated_messages' )
|
804 |
+
);
|
805 |
+
add_action( 'admin_head', array( $this, 'admin_head' ) );
|
806 |
+
$dispatcher->register_action(
|
807 |
+
'plugin_action_links_' . AI1EC_PLUGIN_BASENAME,
|
808 |
+
array( 'view.admin.nav', 'plugin_action_links' )
|
809 |
+
);
|
810 |
+
$dispatcher->register_action(
|
811 |
+
'wp_ajax_ai1ec_rescan_cache',
|
812 |
+
array( 'twig.cache', 'rescan' )
|
813 |
+
);
|
814 |
+
$dispatcher->register_action(
|
815 |
+
'admin_init',
|
816 |
+
array( 'environment.check', 'run_checks' )
|
817 |
+
);
|
818 |
+
$dispatcher->register_action(
|
819 |
+
'activated_plugin',
|
820 |
+
array( 'environment.check', 'check_addons_activation' )
|
821 |
+
);
|
822 |
+
$dispatcher->register_filter(
|
823 |
+
'upgrader_post_install',
|
824 |
+
array( 'environment.check', 'check_bulk_addons_activation' )
|
825 |
+
);
|
826 |
+
if ( $this->if_js_cache_enabled() ) {
|
827 |
+
$dispatcher->register_action(
|
828 |
+
'activated_plugin',
|
829 |
+
array( 'controller.javascript', 'revalidate_cache' )
|
830 |
+
);
|
831 |
+
$dispatcher->register_action(
|
832 |
+
'deactivated_plugin',
|
833 |
+
array( 'controller.javascript', 'revalidate_cache' )
|
834 |
+
);
|
835 |
+
$dispatcher->register_action(
|
836 |
+
'upgrader_post_install',
|
837 |
+
array( 'controller.javascript', 'revalidate_cache' )
|
838 |
+
);
|
839 |
+
$dispatcher->register_action(
|
840 |
+
'activated_plugin',
|
841 |
+
array( 'controller.javascript-widget', 'revalidate_cache' )
|
842 |
+
);
|
843 |
+
$dispatcher->register_action(
|
844 |
+
'deactivated_plugin',
|
845 |
+
array( 'controller.javascript-widget', 'revalidate_cache' )
|
846 |
+
);
|
847 |
+
$dispatcher->register_action(
|
848 |
+
'upgrader_post_install',
|
849 |
+
array( 'controller.javascript-widget', 'revalidate_cache' )
|
850 |
+
);
|
851 |
|
852 |
+
}
|
853 |
+
// Widget Creator
|
854 |
+
$dispatcher->register_action(
|
855 |
+
'admin_enqueue_scripts',
|
856 |
+
array( 'css.admin', 'admin_enqueue_scripts' )
|
857 |
+
);
|
858 |
+
$dispatcher->register_action(
|
859 |
+
'current_screen',
|
860 |
+
array( 'view.admin.widget-creator', 'add_meta_box' )
|
861 |
+
);
|
862 |
+
$dispatcher->register_action(
|
863 |
+
'admin_menu',
|
864 |
+
array( 'view.admin.widget-creator', 'add_page' )
|
865 |
+
);
|
866 |
+
$dispatcher->register_filter(
|
867 |
+
'pre_set_site_transient_update_plugins',
|
868 |
+
array( 'calendar.updates', 'check_updates' )
|
869 |
+
);
|
870 |
+
$dispatcher->register_filter(
|
871 |
+
'plugins_api',
|
872 |
+
array( 'calendar.updates', 'plugins_api_filter' ),
|
873 |
+
10,
|
874 |
+
3
|
875 |
+
);
|
876 |
+
$dispatcher->register_action(
|
877 |
+
'admin_menu',
|
878 |
+
array( 'view.admin.tickets', 'add_page' )
|
879 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
880 |
|
881 |
+
} else { // ! is_admin()
|
882 |
+
$dispatcher->register_action(
|
883 |
+
'after_setup_theme',
|
884 |
+
array( 'theme.loader', 'execute_theme_functions' )
|
885 |
+
);
|
886 |
+
$dispatcher->register_action(
|
887 |
+
'the_post',
|
888 |
+
array( 'post.content', 'check_content' ),
|
889 |
+
PHP_INT_MAX
|
890 |
+
);
|
891 |
+
$dispatcher->register_action(
|
892 |
+
'send_headers',
|
893 |
+
array( 'request.redirect', 'handle_categories_and_tags' )
|
894 |
+
);
|
895 |
+
$dispatcher->register_action(
|
896 |
+
'wp_head',
|
897 |
+
array( 'view.event.single', 'add_meta_tags' )
|
898 |
+
);
|
899 |
+
}
|
900 |
+
}
|
901 |
+
/**
|
902 |
+
* Outputs menu icon between head tags
|
903 |
+
*/
|
904 |
+
public function admin_head() {
|
905 |
+
global $wp_version;
|
906 |
+
$argv = array(
|
907 |
+
'before_font_icons' => version_compare( $wp_version, '3.8', '<' ),
|
908 |
+
'admin_theme_img_url' => AI1EC_ADMIN_THEME_IMG_URL,
|
909 |
+
'admin_theme_font_url' => AI1EC_ADMIN_THEME_FONT_URL,
|
910 |
+
);
|
911 |
+
$this->_registry->get( 'theme.loader' )
|
912 |
+
->get_file( 'timely-menu-icon.twig', $argv, true )
|
913 |
+
->render();
|
914 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
915 |
|
916 |
+
/**
|
917 |
+
* _add_defaults method
|
918 |
+
*
|
919 |
+
* Add (merge) default options to given query variable.
|
920 |
+
*
|
921 |
+
* @param string settingsquery variable to ammend
|
922 |
+
*
|
923 |
+
* @return string|NULL Modified variable values or NULL on failure
|
924 |
+
*
|
925 |
+
* @global Ai1ec_Settings $ai1ec_settings Instance of settings object
|
926 |
+
* to pull data from
|
927 |
+
* @staticvar array $mapper Mapping of query names to
|
928 |
+
* default in settings
|
929 |
+
*/
|
930 |
+
protected function _add_defaults( $name ) {
|
931 |
+
$settings = $this->_registry->get( 'model.settings' );
|
932 |
+
static $mapper = array(
|
933 |
+
'cat' => 'categories',
|
934 |
+
'tag' => 'tags',
|
935 |
+
);
|
936 |
+
$rq_name = 'ai1ec_' . $name . '_ids';
|
937 |
+
if (
|
938 |
+
! isset( $mapper[$name] ) ||
|
939 |
+
! array_key_exists( $rq_name, $this->_request )
|
940 |
+
) {
|
941 |
+
return NULL;
|
942 |
+
}
|
943 |
+
$options = explode( ',', $this->_request[$rq_name] );
|
944 |
+
$property = 'default_' . $mapper[$name];
|
945 |
+
$options = array_merge(
|
946 |
+
$options,
|
947 |
+
$settings->get( $property )
|
948 |
+
);
|
949 |
+
$filtered = array();
|
950 |
+
foreach ( $options as $item ) { // avoid array_filter + is_numeric
|
951 |
+
$item = (int)$item;
|
952 |
+
if ( $item > 0 ) {
|
953 |
+
$filtered[] = $item;
|
954 |
+
}
|
955 |
+
}
|
956 |
+
unset( $options );
|
957 |
+
if ( empty( $filtered ) ) {
|
958 |
+
return NULL;
|
959 |
+
}
|
960 |
+
return implode( ',', $filtered );
|
961 |
+
}
|
962 |
|
963 |
+
/**
|
964 |
+
* Process_request function.
|
965 |
+
*
|
966 |
+
* Initialize/validate custom request array, based on contents of $_REQUEST,
|
967 |
+
* to keep track of this component's request variables.
|
968 |
+
*
|
969 |
+
* @return void
|
970 |
+
**/
|
971 |
+
protected function _process_request() {
|
972 |
+
$settings = $this->_registry->get( 'model.settings' );
|
973 |
+
$this->_request = $this->_registry->get( 'http.request.parser' );
|
974 |
+
$aco = $this->_registry->get( 'acl.aco' );
|
975 |
+
$page_id = $settings->get( 'calendar_page_id' );
|
976 |
+
if (
|
977 |
+
! $aco->is_admin() &&
|
978 |
+
$page_id &&
|
979 |
+
is_page( $page_id )
|
980 |
+
) {
|
981 |
+
foreach ( array( 'cat', 'tag' ) as $name ) {
|
982 |
+
$implosion = $this->_add_defaults( $name );
|
983 |
+
if ( $implosion ) {
|
984 |
+
$this->request['ai1ec_' . $name . '_ids'] = $implosion;
|
985 |
+
$_REQUEST['ai1ec_' . $name . '_ids'] = $implosion;
|
986 |
+
}
|
987 |
+
}
|
988 |
+
}
|
989 |
+
}
|
990 |
|
991 |
+
/**
|
992 |
+
* Initialize cron functions.
|
993 |
+
*
|
994 |
+
* @throws Ai1ec_Scheduling_Exception
|
995 |
+
*
|
996 |
+
* @return void
|
997 |
+
*/
|
998 |
+
protected function _install_crons() {
|
999 |
+
$scheduling = $this->_registry->get( 'scheduling.utility' );
|
1000 |
+
$hook_name = 'ai1ec_n_cron';
|
1001 |
+
$scheduling->delete( $hook_name );
|
1002 |
+
}
|
|
|
1003 |
|
1004 |
+
/**
|
1005 |
+
* Initialize the registry object.
|
1006 |
+
*
|
1007 |
+
* @param Ai1ec_Loader $ai1ec_loader Instance of Ai1EC classes loader
|
1008 |
+
*
|
1009 |
+
* @return void Method does not return
|
1010 |
+
*/
|
1011 |
+
protected function _initialize_registry( $ai1ec_loader ) {
|
1012 |
+
global $ai1ec_registry;
|
1013 |
+
$this->_registry = new Ai1ec_Registry_Object( $ai1ec_loader );
|
1014 |
+
Ai1ec_Time_Utility::set_registry( $this->_registry );
|
1015 |
+
$ai1ec_registry = $this->_registry;
|
1016 |
+
}
|
|
|
|
|
1017 |
|
1018 |
+
/**
|
1019 |
+
* Loads the CSS for the plugin
|
1020 |
+
*
|
1021 |
+
*/
|
1022 |
+
protected function _load_css_if_needed() {
|
1023 |
+
// ==================================
|
1024 |
+
// = Add the hook to render the css =
|
1025 |
+
// ==================================
|
1026 |
+
if ( isset( $_GET[Ai1ec_Css_Frontend::QUERY_STRING_PARAM] ) ) {
|
1027 |
+
// we need to wait for the extension to be registered if the css
|
1028 |
+
// needs to be compiled. Will find a better way when compiling css.
|
1029 |
+
$css_controller = $this->_registry->get( 'css.frontend' );
|
1030 |
+
add_action( 'plugins_loaded', array( $css_controller, 'render_css' ), 2 );
|
1031 |
+
}
|
1032 |
+
}
|
1033 |
|
1034 |
+
/**
|
1035 |
+
* Load the texdomain for the plugin.
|
1036 |
+
*
|
1037 |
+
* @wp_hook plugins_loaded
|
1038 |
+
*
|
1039 |
+
* @return void
|
1040 |
+
*/
|
1041 |
+
public function load_textdomain() {
|
1042 |
+
if ( false === $this->_domain_loaded ) {
|
1043 |
+
load_plugin_textdomain(
|
1044 |
+
AI1EC_PLUGIN_NAME, false, AI1EC_LANGUAGE_PATH
|
1045 |
+
);
|
1046 |
+
$this->_domain_loaded = true;
|
1047 |
+
}
|
1048 |
+
}
|
1049 |
|
1050 |
+
/**
|
1051 |
+
* Check if the schema is up to date.
|
1052 |
+
*
|
1053 |
+
* @throws Ai1ec_Database_Schema_Exception
|
1054 |
+
* @throws Ai1ec_Database_Update_Exception
|
1055 |
+
*
|
1056 |
+
* @return void
|
1057 |
+
*/
|
1058 |
+
protected function _initialize_schema() {
|
1059 |
+
$option = $this->_registry->get( 'model.option' );
|
1060 |
+
$schema_sql = $this->get_current_db_schema();
|
1061 |
+
$version = sha1( $schema_sql );
|
1062 |
+
// If existing DB version is not consistent with current plugin's version,
|
1063 |
+
// or does not exist, then create/update table structure using dbDelta().
|
1064 |
+
if ( $option->get( 'ai1ec_db_version' ) != $version ) {
|
1065 |
|
1066 |
+
$errors = $this->_registry->get( 'database.applicator' )
|
1067 |
+
->check_db_consistency_for_date_migration() ;
|
1068 |
+
if ( ! empty( $errors ) ) {
|
1069 |
+
$message = Ai1ec_I18n::__(
|
1070 |
+
'Your database is found to be corrupt. Likely previous update has failed. Please restore All-in-One Event Calendar tables from a backup and retry.<br>Following errors were found:<br>%s'
|
1071 |
+
);
|
1072 |
+
$message = sprintf( $message, implode( $errors, '<br>' ) );
|
1073 |
+
throw new Ai1ec_Database_Update_Exception( $message );
|
1074 |
+
}
|
1075 |
+
$this->_registry->get( 'database.applicator' )
|
1076 |
+
->remove_instance_duplicates();
|
1077 |
|
1078 |
+
if (
|
1079 |
+
apply_filters( 'ai1ec_perform_scheme_update', true ) &&
|
1080 |
+
$this->_registry->get( 'database.helper' )->apply_delta(
|
1081 |
+
$schema_sql
|
1082 |
+
)
|
1083 |
+
) {
|
1084 |
+
$option->set( 'ai1ec_db_version', $version );
|
1085 |
+
} else {
|
1086 |
+
throw new Ai1ec_Database_Update_Exception();
|
1087 |
+
}
|
1088 |
|
1089 |
+
// If the schema structure upgrade is complete move contents
|
1090 |
+
$categories_key = 'ai1ec_category_meta_ported';
|
1091 |
+
if ( ! $option->get( $categories_key ) ) {
|
1092 |
+
$this->_migrate_categories_meta();
|
1093 |
+
$option->set( $categories_key, true );
|
1094 |
+
}
|
1095 |
+
}
|
1096 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1097 |
|
1098 |
+
/**
|
1099 |
+
* Transform categories meta information.
|
1100 |
+
*
|
1101 |
+
* Use new `meta` table instead of legacy `colors` table.
|
1102 |
+
*
|
1103 |
+
* @return void Method does not return.
|
1104 |
+
*/
|
1105 |
+
protected function _migrate_categories_meta() {
|
1106 |
+
$db = $this->_registry->get( 'dbi.dbi' );
|
1107 |
+
$table_name = $db->get_table_name( 'ai1ec_event_category_colors' );
|
1108 |
+
$db_h = $this->_registry->get( 'database.helper' );
|
1109 |
+
if ( $db_h->table_exists( $table_name ) ) { // if old table exists otherwise ignore it
|
1110 |
+
// Migrate color information
|
1111 |
+
$dest_table = $db->get_table_name( 'ai1ec_event_category_meta' );
|
1112 |
+
$colors = $db->select(
|
1113 |
+
$table_name,
|
1114 |
+
array( 'term_id', 'term_color'),
|
1115 |
+
ARRAY_A
|
1116 |
+
);
|
1117 |
+
if ( ! empty( $colors ) ) {
|
1118 |
+
foreach ( $colors as $color ) {
|
1119 |
+
$db->insert( $dest_table, $color );
|
1120 |
+
}
|
1121 |
+
}
|
1122 |
+
// Drop the old table
|
1123 |
+
$db->query( 'DROP TABLE IF EXISTS ' . $table_name );
|
1124 |
+
}
|
1125 |
+
}
|
1126 |
|
1127 |
+
/**
|
1128 |
+
* Procedures to take when upgrading plugin version
|
1129 |
+
*
|
1130 |
+
* @return void
|
1131 |
+
*/
|
1132 |
+
protected function _plugin_upgrade_procedures() {
|
1133 |
+
$option = $this->_registry->get( 'model.option' );
|
1134 |
+
$version = AI1EC_VERSION;
|
1135 |
|
1136 |
+
if ( $option->get( 'ai1ec_version' ) != $version ) {
|
1137 |
+
try {
|
1138 |
+
// Force regeneration of JS cache
|
1139 |
+
$this->_registry->get( 'controller.javascript' )->revalidate_cache();
|
1140 |
+
$this->_registry->get( 'controller.javascript-widget' )->revalidate_cache();
|
1141 |
|
1142 |
+
// Run upgrade commands
|
1143 |
+
$settings = $this->_registry->get( 'model.settings' );
|
1144 |
+
$settings->perform_upgrade_actions();
|
1145 |
+
} catch ( Exception $e ) {
|
1146 |
+
}
|
1147 |
|
1148 |
+
// Update plugin version
|
1149 |
+
$option->set( 'ai1ec_version', $version );
|
1150 |
+
}
|
1151 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1152 |
|
1153 |
+
/**
|
1154 |
+
* Get current database schema as a multi SQL statement.
|
1155 |
+
*
|
1156 |
+
* @return string Multiline SQL statement.
|
1157 |
+
*/
|
1158 |
+
public function get_current_db_schema() {
|
1159 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
1160 |
+
// =======================
|
1161 |
+
// = Create table events =
|
1162 |
+
// =======================
|
1163 |
+
$table_name = $dbi->get_table_name( 'ai1ec_events' );
|
1164 |
+
$sql = "CREATE TABLE $table_name (
|
1165 |
+
post_id bigint(20) NOT NULL,
|
1166 |
+
start int(10) UNSIGNED NOT NULL,
|
1167 |
+
end int(10) UNSIGNED,
|
1168 |
+
timezone_name varchar(50),
|
1169 |
+
allday tinyint(1) NOT NULL,
|
1170 |
+
instant_event tinyint(1) NOT NULL DEFAULT 0,
|
1171 |
+
recurrence_rules longtext,
|
1172 |
+
exception_rules longtext,
|
1173 |
+
recurrence_dates longtext,
|
1174 |
+
exception_dates longtext,
|
1175 |
+
venue varchar(255),
|
1176 |
+
country varchar(255),
|
1177 |
+
address varchar(255),
|
1178 |
+
city varchar(255),
|
1179 |
+
province varchar(255),
|
1180 |
+
postal_code varchar(32),
|
1181 |
+
show_map tinyint(1),
|
1182 |
+
contact_name varchar(255),
|
1183 |
+
contact_phone varchar(32),
|
1184 |
+
contact_email varchar(128),
|
1185 |
+
contact_url varchar(255),
|
1186 |
+
cost varchar(255),
|
1187 |
+
ticket_url varchar(255),
|
1188 |
+
ical_feed_url varchar(255),
|
1189 |
+
ical_source_url varchar(255),
|
1190 |
+
ical_organizer varchar(255),
|
1191 |
+
ical_contact varchar(255),
|
1192 |
+
ical_uid varchar(255),
|
1193 |
+
show_coordinates tinyint(1),
|
1194 |
+
latitude decimal(20,15),
|
1195 |
+
longitude decimal(20,15),
|
1196 |
+
force_regenerate tinyint(1) NOT NULL DEFAULT 0,
|
1197 |
+
PRIMARY KEY (post_id),
|
1198 |
+
KEY feed_source (ical_feed_url)
|
1199 |
+
) CHARACTER SET utf8;";
|
1200 |
|
1201 |
+
// ==========================
|
1202 |
+
// = Create table instances =
|
1203 |
+
// ==========================
|
1204 |
+
$table_name = $dbi->get_table_name( 'ai1ec_event_instances' );
|
1205 |
+
$sql .= "CREATE TABLE $table_name (
|
1206 |
+
id bigint(20) NOT NULL AUTO_INCREMENT,
|
1207 |
+
post_id bigint(20) NOT NULL,
|
1208 |
+
start int(10) UNSIGNED NOT NULL,
|
1209 |
+
end int(10) UNSIGNED NOT NULL,
|
1210 |
+
PRIMARY KEY (id),
|
1211 |
+
UNIQUE KEY evt_instance (post_id,start)
|
1212 |
+
) CHARACTER SET utf8;";
|
1213 |
|
1214 |
+
// ================================
|
1215 |
+
// = Create table category colors =
|
1216 |
+
// ================================
|
1217 |
+
$table_name = $dbi->get_table_name( 'ai1ec_event_category_meta' );
|
1218 |
+
$sql .= "CREATE TABLE $table_name (
|
1219 |
+
term_id bigint(20) NOT NULL,
|
1220 |
+
term_color varchar(255) NOT NULL,
|
1221 |
+
term_image varchar(254) NULL DEFAULT NULL,
|
1222 |
+
PRIMARY KEY (term_id)
|
1223 |
+
) CHARACTER SET utf8;";
|
1224 |
+
|
1225 |
+
return $sql;
|
1226 |
+
}
|
1227 |
}
|
app/controller/import-export.php
CHANGED
@@ -11,102 +11,102 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Import_Export_Controller {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
}
|
11 |
*/
|
12 |
class Ai1ec_Import_Export_Controller {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var array The registered engines.
|
16 |
+
*/
|
17 |
+
protected $_engines = array();
|
18 |
|
19 |
|
20 |
+
/**
|
21 |
+
* @var Ai1ec_Registry_Object
|
22 |
+
*/
|
23 |
+
protected $_registry;
|
24 |
|
25 |
+
/**
|
26 |
+
* @var array Import / export params.
|
27 |
+
*/
|
28 |
+
protected $_params;
|
29 |
|
30 |
+
/**
|
31 |
+
* This controller is instanciated only if we need to import/export something.
|
32 |
+
*
|
33 |
+
* When it is instanciated it allows other engines to be injected through a
|
34 |
+
* filter. If we do not plan to ship core engines, let's skip the
|
35 |
+
* $core_engines param.
|
36 |
+
*
|
37 |
+
* @param Ai1ec_Registry_Object $registry
|
38 |
+
* @param array $core_engines
|
39 |
+
* @param array $params
|
40 |
+
*/
|
41 |
+
public function __construct(
|
42 |
+
Ai1ec_Registry_Object $registry,
|
43 |
+
array $core_engines = array( 'ics', 'api-ics' ),
|
44 |
+
array $params = array()
|
45 |
+
) {
|
46 |
+
$this->_registry = $registry;
|
47 |
+
$known_engines = apply_filters(
|
48 |
+
'ai1ec_register_import_export_engines',
|
49 |
+
$core_engines
|
50 |
+
);
|
51 |
+
$this->_params = $params;
|
52 |
+
foreach ( $known_engines as $engine ) {
|
53 |
+
$this->register( $engine );
|
54 |
+
}
|
55 |
+
}
|
56 |
|
57 |
+
/**
|
58 |
+
* Register an import-export engine.
|
59 |
+
*
|
60 |
+
* @param string $engine
|
61 |
+
*/
|
62 |
+
public function register( $engine ) {
|
63 |
+
$this->_engines[$engine] = true;
|
64 |
+
}
|
65 |
|
66 |
+
/**
|
67 |
+
* Import events into the calendar.
|
68 |
+
*
|
69 |
+
* @param string $engine
|
70 |
+
* @param array $args
|
71 |
+
*
|
72 |
+
* @throws Ai1ec_Engine_Not_Set_Exception If the engine is not set.
|
73 |
+
* @throws Ai1ec_Parse_Exception If an error happens during parse.
|
74 |
+
*
|
75 |
+
* @return int The number of imported events
|
76 |
+
*/
|
77 |
+
public function import_events( $engine, array $args ) {
|
78 |
+
if ( ! isset( $this->_engines[$engine] ) ) {
|
79 |
+
throw new Ai1ec_Engine_Not_Set_Exception(
|
80 |
+
'The engine ' . $engine . 'is not registered.'
|
81 |
+
);
|
82 |
+
}
|
83 |
+
// external engines must register themselves into the registry.
|
84 |
+
$engine = $this->_registry->get( 'import-export.' . $engine );
|
85 |
+
$exception = null;
|
86 |
+
try {
|
87 |
+
return $engine->import( $args );
|
88 |
+
} catch ( Ai1ec_Parse_Exception $parse_exception ) {
|
89 |
+
$exception = $parse_exception;
|
90 |
+
}
|
91 |
+
throw $exception;
|
92 |
+
}
|
93 |
|
94 |
+
/**
|
95 |
+
* Export the events using the specified engine.
|
96 |
+
*
|
97 |
+
* @param string $engine
|
98 |
+
* @param array $args
|
99 |
+
*
|
100 |
+
* @throws Ai1ec_Engine_Not_Set_Exception
|
101 |
+
*/
|
102 |
+
public function export_events( $engine, array $args ) {
|
103 |
+
if ( ! isset( $this->_engines[$engine] ) ) {
|
104 |
+
throw new Ai1ec_Engine_Not_Set_Exception(
|
105 |
+
'The engine ' . $engine . 'is not registered.'
|
106 |
+
);
|
107 |
+
}
|
108 |
+
// external engines must register themselves into the registry.
|
109 |
+
$engine = $this->_registry->get( 'import-export.' . $engine );
|
110 |
+
return $engine->export( $args, $this->_params );
|
111 |
+
}
|
112 |
}
|
app/controller/javascript-widget.php
CHANGED
@@ -11,238 +11,238 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Controller_Javascript_Widget extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
JS;
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
|
248 |
}
|
11 |
*/
|
12 |
class Ai1ec_Controller_Javascript_Widget extends Ai1ec_Base {
|
13 |
|
14 |
+
const WIDGET_PARAMETER = 'ai1ec_js_widget';
|
15 |
+
const LEGACY_WIDGET_PARAMETER = 'ai1ec_super_widget';
|
16 |
+
const WIDGET_JS_CACHE_FILE = '/public/js_cache/ai1ec_js_widget.js';
|
17 |
+
|
18 |
+
protected $_widgets = array();
|
19 |
+
|
20 |
+
|
21 |
+
public function add_widget( $widget_id, $widget_class ) {
|
22 |
+
$this->_widgets[$widget_id] = $widget_class;
|
23 |
+
}
|
24 |
+
|
25 |
+
public function get_widgets() {
|
26 |
+
return $this->_widgets;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Adds Super Widget JS to admin screen.
|
31 |
+
*
|
32 |
+
* @param array $files
|
33 |
+
* @param string $page_to_load
|
34 |
+
*
|
35 |
+
* @return array
|
36 |
+
*/
|
37 |
+
public function add_js( array $files, $page_to_load ) {
|
38 |
+
if ( 'admin_settings.js' === $page_to_load ) {
|
39 |
+
$files[] = AI1ECSW_PATH . '/public/js/pages/admin_settings.js';
|
40 |
+
}
|
41 |
+
return $files;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @param array $data
|
46 |
+
* @return array
|
47 |
+
*/
|
48 |
+
public function add_js_translation( array $data ) {
|
49 |
+
$data['set_calendar_page'] = __(
|
50 |
+
'You must choose the Calendar page before using the Super Widget',
|
51 |
+
AI1EC_PLUGIN_NAME
|
52 |
+
);
|
53 |
+
return $data;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Sets the flag to revalidate cached js files on next render.
|
58 |
+
*/
|
59 |
+
public function revalidate_cache() {
|
60 |
+
$this->_registry->get( 'model.option' )->set( 'jswidgetupdated', '0' );
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Renders everything that's needed for the embedded widget.
|
65 |
+
*/
|
66 |
+
public function render_js_widget() {
|
67 |
+
|
68 |
+
if ( isset( $_GET['render'] ) && 'true' === $_GET['render'] ) {
|
69 |
+
if ( isset( $_GET[self::WIDGET_PARAMETER] ) ){
|
70 |
+
$widget = $_GET[self::WIDGET_PARAMETER];
|
71 |
+
} else if ( isset( $_GET[self::LEGACY_WIDGET_PARAMETER] ) ) {
|
72 |
+
$widget = $_GET[self::LEGACY_WIDGET_PARAMETER];
|
73 |
+
}
|
74 |
+
$widget_class = null;
|
75 |
+
if ( isset( $this->_widgets[$widget] ) ) {
|
76 |
+
$widget_class = $this->_widgets[$widget];
|
77 |
+
}
|
78 |
+
if ( null === $widget_class ) {
|
79 |
+
return;
|
80 |
+
}
|
81 |
+
$widget_instance = $this->_registry->get( $widget_class );
|
82 |
+
$this->render_content( $widget_instance );
|
83 |
+
} else {
|
84 |
+
if (
|
85 |
+
! $this->_registry->get( 'model.settings' )->get( 'cache_dynamic_js' ) ||
|
86 |
+
'1' != $this->_registry->get( 'model.option' )->get( 'jswidgetupdated' ) ||
|
87 |
+
! $this->_registry->get( 'filesystem.checker' )->check_file_exists(
|
88 |
+
AI1EC_PATH . self::WIDGET_JS_CACHE_FILE,
|
89 |
+
true
|
90 |
+
)
|
91 |
+
) {
|
92 |
+
$this->render_javascript();
|
93 |
+
} else {
|
94 |
+
header(
|
95 |
+
'Location: '
|
96 |
+
. plugin_dir_url( 'all-in-one-event-calendar/public/js_cache/.' )
|
97 |
+
. 'ai1ec_js_widget.js'
|
98 |
+
);
|
99 |
+
exit( 0 );
|
100 |
+
}
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
public function render_javascript() {
|
105 |
+
|
106 |
+
header( 'Content-Type: application/javascript' );
|
107 |
+
header(
|
108 |
+
'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 31536000 ) . ' GMT'
|
109 |
+
);
|
110 |
+
header( 'Cache-Control: public, max-age=31536000' );
|
111 |
+
|
112 |
+
$jscontroller = $this->_registry->get( 'controller.javascript' );
|
113 |
+
$css_controller = $this->_registry->get( 'css.frontend' );
|
114 |
+
$require_main = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR . 'require.js';
|
115 |
+
$widget_file = AI1EC_PATH . '/public/js/widget/common_widget.js';
|
116 |
+
$translation = $jscontroller->get_frontend_translation_data();
|
117 |
+
$page_id = $this->_registry->get(
|
118 |
+
'model.settings'
|
119 |
+
)->get( 'calendar_page_id' );
|
120 |
+
$permalink = get_permalink(
|
121 |
+
$page_id
|
122 |
+
);
|
123 |
+
$full_permalink = $this->_registry->get(
|
124 |
+
'template.link.helper'
|
125 |
+
)->get_full_permalink( $page_id );
|
126 |
+
// load the css to hardcode, saving a call
|
127 |
+
$css_rules = $css_controller->get_compiled_css();
|
128 |
+
$css_rules = addslashes( $css_rules );
|
129 |
+
$translation['permalinks_structure'] = $this->
|
130 |
+
_registry->get( 'model.option' )->get( 'permalink_structure' );
|
131 |
+
$translation['calendar_url'] = preg_replace( '/^https?:/', '', $permalink );
|
132 |
+
$translation['full_calendar_url'] = preg_replace( '/^https?:/', '', $full_permalink );
|
133 |
+
// Let extensions add their scripts.
|
134 |
+
// look at Extended Views or Super Widget for examples
|
135 |
+
$extension_urls = array();
|
136 |
+
$extension_urls = apply_filters(
|
137 |
+
'ai1ec_render_js',
|
138 |
+
$extension_urls,
|
139 |
+
'ai1ec_widget.js'
|
140 |
+
);
|
141 |
+
// Removing http:// or https:// from extension URLs
|
142 |
+
foreach ( $extension_urls as &$extension_url ) {
|
143 |
+
$extension_url = preg_replace( '/https?:/', '', $extension_url );
|
144 |
+
}
|
145 |
+
|
146 |
+
$translation['extension_urls'] = $extension_urls;
|
147 |
+
// the single event page js is loaded dinamically.
|
148 |
+
$translation['event_page'] = array(
|
149 |
+
'id' => 'ai1ec_event',
|
150 |
+
'url' => preg_replace( '/^https?:/', '', AI1EC_URL ) . '/public/js/pages/event.js',
|
151 |
+
);
|
152 |
+
$translation_module = $jscontroller->create_require_js_module(
|
153 |
+
Ai1ec_Javascript_Controller::FRONTEND_CONFIG_MODULE,
|
154 |
+
$translation
|
155 |
+
);
|
156 |
+
// get requirejs
|
157 |
+
$require = file_get_contents( $require_main );
|
158 |
+
$main_widget = file_get_contents( $widget_file );
|
159 |
+
$require_config = $jscontroller->create_require_js_config_object();
|
160 |
+
$config = $jscontroller->create_require_js_module(
|
161 |
+
'ai1ec_config',
|
162 |
+
$jscontroller->get_translation_data()
|
163 |
+
);
|
164 |
+
// get jquery
|
165 |
+
$jquery = $jscontroller->get_jquery_version_based_on_browser(
|
166 |
+
isset( $_SERVER['HTTP_USER_AGENT'] )
|
167 |
+
? $_SERVER['HTTP_USER_AGENT']
|
168 |
+
: ''
|
169 |
+
);
|
170 |
+
|
171 |
+
$domready = $jscontroller->get_module(
|
172 |
+
'domReady.js'
|
173 |
+
);
|
174 |
+
$frontend = $jscontroller->get_module(
|
175 |
+
'scripts/common_scripts/frontend/common_frontend.js'
|
176 |
+
);
|
177 |
+
|
178 |
+
// compress data if possible
|
179 |
+
$compatibility_ob = $this->_registry->get( 'compatibility.ob' );
|
180 |
+
$js = <<<JS
|
181 |
+
/******** Called once Require.js has loaded ******/
|
182 |
+
|
183 |
+
(function() {
|
184 |
+
|
185 |
+
var timely_css = document.createElement( 'style' );
|
186 |
+
timely_css.innerHTML = '$css_rules';
|
187 |
+
( document.getElementsByTagName( "head" )[0] || document.documentElement ).appendChild( timely_css );
|
188 |
+
// bring in requires
|
189 |
+
$require
|
190 |
+
// make timely global
|
191 |
+
window.timely = timely;
|
192 |
+
$require_config
|
193 |
+
// Load other modules
|
194 |
+
$translation_module
|
195 |
+
$config
|
196 |
+
$jquery
|
197 |
+
$frontend
|
198 |
+
|
199 |
+
// start up the widget
|
200 |
+
$main_widget
|
201 |
+
})(); // We call our anonymous function immediately
|
202 |
JS;
|
203 |
+
$compatibility_ob->gzip_if_possible( $js );
|
204 |
+
|
205 |
+
if (
|
206 |
+
$this->_registry->get( 'model.settings' )->get( 'cache_dynamic_js' ) &&
|
207 |
+
(
|
208 |
+
'0' === $this->_registry->get( 'model.option' )->get( 'jswidgetupdated' ) ||
|
209 |
+
! $this->_registry->get( 'filesystem.checker' )->check_file_exists(
|
210 |
+
AI1EC_PATH . self::WIDGET_JS_CACHE_FILE,
|
211 |
+
true
|
212 |
+
)
|
213 |
+
)
|
214 |
+
) {
|
215 |
+
try {
|
216 |
+
$js_path = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR;
|
217 |
+
$js_saved = file_put_contents(
|
218 |
+
$js_path . '../js_cache/ai1ec_js_widget.js',
|
219 |
+
$js
|
220 |
+
);
|
221 |
+
if ( $js_saved ) {
|
222 |
+
$this->_registry->get( 'model.option' )->set( 'jswidgetupdated', '1' );
|
223 |
+
}
|
224 |
+
} catch ( Exception $e ) {
|
225 |
+
$this->_registry->get( 'model.settings' )->set( 'cache_dynamic_js', false );
|
226 |
+
}
|
227 |
+
}
|
228 |
+
exit( 0 );
|
229 |
+
}
|
230 |
+
|
231 |
+
public function render_content( Ai1ec_Embeddable $widget_instance ) {
|
232 |
+
$args = array();
|
233 |
+
$defaults = $widget_instance->get_js_widget_configurable_defaults();
|
234 |
+
foreach ( $defaults as $id => $value ) {
|
235 |
+
if ( isset( $_GET[$id] ) ) {
|
236 |
+
$args[$id] = $_GET[$id];
|
237 |
+
}
|
238 |
+
}
|
239 |
+
$html = $widget_instance->javascript_widget( $args );
|
240 |
+
$jsonp = $this->_registry->get( 'http.response.render.strategy.jsonp' );
|
241 |
+
$jsonp->render(
|
242 |
+
array(
|
243 |
+
'data' => array( 'html' => $html )
|
244 |
+
)
|
245 |
+
);
|
246 |
+
}
|
247 |
|
248 |
}
|
app/controller/javascript.php
CHANGED
@@ -10,908 +10,908 @@
|
|
10 |
*/
|
11 |
class Ai1ec_Javascript_Controller {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
JSC;
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
|
917 |
}
|
10 |
*/
|
11 |
class Ai1ec_Javascript_Controller {
|
12 |
|
13 |
+
// The js handle used when enqueueing
|
14 |
+
const JS_HANDLE = 'ai1ec_requirejs';
|
15 |
|
16 |
+
// The namespace for require.js functions
|
17 |
+
const REQUIRE_NAMESPACE = 'timely';
|
18 |
+
|
19 |
+
// the name of the configuration module for the frontend
|
20 |
+
const FRONTEND_CONFIG_MODULE = 'ai1ec_calendar';
|
21 |
+
|
22 |
+
//the name of the get parameter we use for loading js
|
23 |
+
const LOAD_JS_PARAMETER = 'ai1ec_render_js';
|
24 |
+
|
25 |
+
// just load backend scripts
|
26 |
+
const LOAD_ONLY_BACKEND_SCRIPTS = 'common_backend';
|
27 |
+
|
28 |
+
// just load backend scripts
|
29 |
+
const LOAD_ONLY_FRONTEND_SCRIPTS = 'common_frontend';
|
30 |
+
|
31 |
+
// Are we in the backend
|
32 |
+
const IS_BACKEND_PARAMETER = 'is_backend';
|
33 |
+
|
34 |
+
// Are we on the calendar page
|
35 |
+
const IS_CALENDAR_PAGE = 'is_calendar_page';
|
36 |
+
|
37 |
+
// this is the value of IS_BACKEND_PARAMETER which triggers loading of backend script
|
38 |
+
const TRUE_PARAM = 'true';
|
39 |
+
|
40 |
+
// the javascript file for event page
|
41 |
+
const EVENT_PAGE_JS = 'event.js';
|
42 |
+
|
43 |
+
// the javascript file for calendar page
|
44 |
+
const CALENDAR_PAGE_JS = 'calendar.js';
|
45 |
+
|
46 |
+
// the file for the calendar feedsa page
|
47 |
+
const CALENDAR_FEEDS_PAGE = 'calendar_feeds.js';
|
48 |
+
|
49 |
+
// add new event page js
|
50 |
+
const ADD_NEW_EVENT_PAGE = 'add_new_event.js';
|
51 |
+
|
52 |
+
// event category page js
|
53 |
+
const EVENT_CATEGORY_PAGE = 'event_category.js';
|
54 |
+
|
55 |
+
// less variable editing page
|
56 |
+
const LESS_VARIBALES_PAGE = 'less_variables_editing.js';
|
57 |
+
|
58 |
+
// settings page
|
59 |
+
const SETTINGS_PAGE = 'admin_settings.js';
|
60 |
+
|
61 |
+
//widget creator page
|
62 |
+
const WIDGET_CREATOR = 'widget-creator.js';
|
63 |
+
|
64 |
+
//ticketing page
|
65 |
+
const TICKETING = 'ticketing.js';
|
66 |
+
|
67 |
+
//cache file
|
68 |
+
const CALENDAR_JS_CACHE_FILE = '/public/js_cache/calendar.js';
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @var Ai1ec_Registry_Object
|
72 |
+
*/
|
73 |
+
private $_registry;
|
74 |
+
|
75 |
+
/**
|
76 |
+
* The core js pages to load.
|
77 |
+
* Used to avoid errors when extensions add pages.
|
78 |
+
*
|
79 |
+
* @var array
|
80 |
+
*/
|
81 |
+
private $_core_pages = array(
|
82 |
+
self::CALENDAR_FEEDS_PAGE => true,
|
83 |
+
self::ADD_NEW_EVENT_PAGE => true,
|
84 |
+
self::EVENT_CATEGORY_PAGE => true,
|
85 |
+
self::LESS_VARIBALES_PAGE => true,
|
86 |
+
self::SETTINGS_PAGE => true,
|
87 |
+
self::EVENT_PAGE_JS => true,
|
88 |
+
self::CALENDAR_PAGE_JS => true,
|
89 |
+
self::WIDGET_CREATOR => true,
|
90 |
+
self::TICKETING => true,
|
91 |
+
);
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Holds an instance of the settings object
|
95 |
+
*
|
96 |
+
* @var Ai1ec_Settings
|
97 |
+
*/
|
98 |
+
private $_settings;
|
99 |
+
|
100 |
+
/**
|
101 |
+
* @var Ai1ec_Locale
|
102 |
+
*/
|
103 |
+
private $_locale;
|
104 |
+
|
105 |
+
/**
|
106 |
+
* @var Ai1ec_Scripts
|
107 |
+
*/
|
108 |
+
private $_scripts_helper;
|
109 |
+
|
110 |
+
/**
|
111 |
+
* @var Ai1ec_Acl_Aco
|
112 |
+
*/
|
113 |
+
private $_aco;
|
114 |
+
|
115 |
+
/**
|
116 |
+
* @var Ai1ec_Template_Link_Helper
|
117 |
+
*/
|
118 |
+
private $_template_link_helper;
|
119 |
+
|
120 |
+
/**
|
121 |
+
* @var bool
|
122 |
+
*/
|
123 |
+
protected $_frontend_scripts_loaded = false;
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Public constructor.
|
127 |
+
*
|
128 |
+
* @param Ai1ec_Registry_Object $registry
|
129 |
+
*
|
130 |
+
* @return void
|
131 |
+
*/
|
132 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
133 |
+
$this->_registry = $registry;
|
134 |
+
$this->_settings = $registry->get( 'model.settings' );
|
135 |
+
$this->_locale = $registry->get( 'p28n.wpml' );
|
136 |
+
$this->_aco = $registry->get( 'acl.aco' );
|
137 |
+
$this->_template_link_helper = $registry->get( 'template.link.helper' );
|
138 |
+
// this will need to be modified
|
139 |
+
$this->_scripts_helper = $registry->get( 'script.helper' );
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Load javascript files for frontend pages.
|
144 |
+
*
|
145 |
+
* @wp-hook ai1ec_load_frontend_js
|
146 |
+
*
|
147 |
+
* @param $is_calendar_page boolean Whether we are displaying the main
|
148 |
+
* calendar page or not
|
149 |
+
*
|
150 |
+
* @return void
|
151 |
+
*/
|
152 |
+
public function load_frontend_js( $is_calendar_page, $is_shortcode = false ) {
|
153 |
+
$page = null;
|
154 |
+
|
155 |
+
// ======
|
156 |
+
// = JS =
|
157 |
+
// ======
|
158 |
+
if( $this->_are_we_accessing_the_single_event_page() === true ) {
|
159 |
+
$page = self::EVENT_PAGE_JS;
|
160 |
+
}
|
161 |
+
if( $is_calendar_page === true ) {
|
162 |
+
$page = self::CALENDAR_PAGE_JS;
|
163 |
+
}
|
164 |
+
if( null !== $page ) {
|
165 |
+
$this->add_link_to_render_js( $page, false );
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Render the javascript for the appropriate page.
|
171 |
+
*
|
172 |
+
* @return void
|
173 |
+
*/
|
174 |
+
public function render_js() {
|
175 |
+
$js_path = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR;
|
176 |
+
$common_js = '';
|
177 |
+
$js_cache = $this->_settings->get( 'cache_dynamic_js' );
|
178 |
+
|
179 |
+
if ( ! isset( $_GET[self::LOAD_JS_PARAMETER] ) ) {
|
180 |
+
return null;
|
181 |
+
}
|
182 |
+
$page_to_load = $_GET[self::LOAD_JS_PARAMETER];
|
183 |
+
$scripts_updated = $this->_registry->get( 'model.option' )->get( 'calendarjsupdated' );
|
184 |
+
|
185 |
+
if (
|
186 |
+
$js_cache &&
|
187 |
+
$page_to_load === self::CALENDAR_PAGE_JS &&
|
188 |
+
'1' === $scripts_updated &&
|
189 |
+
$this->_registry->get( 'filesystem.checker' )->check_file_exists(
|
190 |
+
AI1EC_PATH . self::CALENDAR_JS_CACHE_FILE,
|
191 |
+
true
|
192 |
+
)
|
193 |
+
) {
|
194 |
+
Ai1ec_Http_Response_Helper::stop( 0 );
|
195 |
+
return;
|
196 |
+
}
|
197 |
+
|
198 |
+
if (
|
199 |
+
isset( $_GET[self::IS_BACKEND_PARAMETER] ) &&
|
200 |
+
$_GET[self::IS_BACKEND_PARAMETER] === self::TRUE_PARAM
|
201 |
+
) {
|
202 |
+
$common_js = file_get_contents( $js_path . 'pages/common_backend.js' );
|
203 |
+
} else if (
|
204 |
+
$page_to_load === self::EVENT_PAGE_JS ||
|
205 |
+
$page_to_load === self::CALENDAR_PAGE_JS ||
|
206 |
+
$page_to_load === self::LOAD_ONLY_FRONTEND_SCRIPTS
|
207 |
+
) {
|
208 |
+
if (
|
209 |
+
$page_to_load === self::LOAD_ONLY_FRONTEND_SCRIPTS &&
|
210 |
+
true === $this->_frontend_scripts_loaded
|
211 |
+
) {
|
212 |
+
return;
|
213 |
+
}
|
214 |
+
if ( false === $this->_frontend_scripts_loaded ) {
|
215 |
+
$common_js = file_get_contents(
|
216 |
+
$js_path . 'pages/common_frontend.js'
|
217 |
+
);
|
218 |
+
$this->_frontend_scripts_loaded = true;
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
// Create the config object for Require.js.
|
223 |
+
$require_config = $this->create_require_js_config_object();
|
224 |
+
|
225 |
+
// Load Require.js script.
|
226 |
+
$require = file_get_contents( $js_path . 'require.js' );
|
227 |
+
|
228 |
+
// Load appropriate jQuery script based on browser.
|
229 |
+
$jquery = $this->get_jquery_version_based_on_browser(
|
230 |
+
isset( $_SERVER['HTTP_USER_AGENT'] )
|
231 |
+
? $_SERVER['HTTP_USER_AGENT']
|
232 |
+
: ''
|
233 |
+
);
|
234 |
+
|
235 |
+
// Load the main script for the page.
|
236 |
+
$page_js = '';
|
237 |
+
if ( isset( $this->_core_pages[$page_to_load] ) ) {
|
238 |
+
$page_js = file_get_contents( $js_path . 'pages/' . $page_to_load );
|
239 |
+
}
|
240 |
+
|
241 |
+
// Load translation module.
|
242 |
+
$translation = $this->get_frontend_translation_data();
|
243 |
+
$permalink = $this->_template_link_helper
|
244 |
+
->get_permalink( $this->_settings->get( 'calendar_page_id' ) );
|
245 |
+
$full_permalink = $this->_template_link_helper
|
246 |
+
->get_full_permalink( $this->_settings->get( 'calendar_page_id' ) );
|
247 |
+
$translation['calendar_url'] = $permalink;
|
248 |
+
$translation['full_calendar_url'] = $full_permalink;
|
249 |
+
$translation_module = $this->create_require_js_module(
|
250 |
+
self::FRONTEND_CONFIG_MODULE,
|
251 |
+
$translation
|
252 |
+
);
|
253 |
+
|
254 |
+
// Load Ai1ec config script.
|
255 |
+
$config = $this->create_require_js_module(
|
256 |
+
'ai1ec_config',
|
257 |
+
$this->get_translation_data()
|
258 |
+
);
|
259 |
+
|
260 |
+
// Let extensions add their scripts.
|
261 |
+
$extension_files = array();
|
262 |
+
$extension_files = apply_filters(
|
263 |
+
'ai1ec_render_js',
|
264 |
+
$extension_files,
|
265 |
+
$page_to_load
|
266 |
+
);
|
267 |
+
$ext_js = '';
|
268 |
+
|
269 |
+
foreach ( $extension_files as $file ) {
|
270 |
+
$ext_js .= file_get_contents( $file );
|
271 |
+
}
|
272 |
+
|
273 |
+
// Finally, load the page_ready script to execute code that must run after
|
274 |
+
// all scripts have been loaded.
|
275 |
+
$page_ready = file_get_contents(
|
276 |
+
$js_path . 'scripts/common_scripts/page_ready.js'
|
277 |
+
);
|
278 |
+
|
279 |
+
$javascript = $require . $require_config . $translation_module .
|
280 |
+
$config . $jquery . $common_js . $ext_js . $page_js . $page_ready;
|
281 |
+
// add to blank spaces to fix issues with js
|
282 |
+
// being truncated onn some installs
|
283 |
+
$javascript .= ' ';
|
284 |
+
|
285 |
+
if (
|
286 |
+
$js_cache &&
|
287 |
+
$page_to_load === self::CALENDAR_PAGE_JS &&
|
288 |
+
(
|
289 |
+
'0' === $scripts_updated ||
|
290 |
+
! $this->_registry->get( 'filesystem.checker' )->check_file_exists(
|
291 |
+
AI1EC_PATH . self::CALENDAR_JS_CACHE_FILE,
|
292 |
+
true
|
293 |
+
)
|
294 |
+
)
|
295 |
+
) {
|
296 |
+
$js_saved = false;
|
297 |
+
try {
|
298 |
+
$js_saved = file_put_contents(
|
299 |
+
$js_path . '../js_cache/' . self::CALENDAR_PAGE_JS,
|
300 |
+
$javascript
|
301 |
+
);
|
302 |
+
if ( $js_saved ) {
|
303 |
+
$this->_registry->get( 'model.option' )->set( 'calendarjsupdated', '1' );
|
304 |
+
}
|
305 |
+
} catch ( Exception $e ) {
|
306 |
+
$this->_settings->set( 'cache_dynamic_js', false );
|
307 |
+
}
|
308 |
+
}
|
309 |
+
|
310 |
+
$this->_echo_javascript( $javascript );
|
311 |
+
}
|
312 |
+
|
313 |
+
|
314 |
+
/**
|
315 |
+
* Sets the flag to revalidate cached js files on next render.
|
316 |
+
*/
|
317 |
+
public function revalidate_cache() {
|
318 |
+
$this->_registry->get( 'model.option' )->set( 'calendarjsupdated', '0' );
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Get a compiled javascript file ( used by extensions )
|
323 |
+
*
|
324 |
+
* @param string $name
|
325 |
+
*
|
326 |
+
* @return string
|
327 |
+
*/
|
328 |
+
public function get_module( $name ) {
|
329 |
+
$js_path = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR;
|
330 |
+
return file_get_contents( $js_path . $name );
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Check what file needs to be loaded and add the correct link.
|
335 |
+
*
|
336 |
+
* @wp-hook init
|
337 |
+
*
|
338 |
+
* @return void
|
339 |
+
*/
|
340 |
+
public function load_admin_js() {
|
341 |
+
// Initialize dashboard view
|
342 |
+
|
343 |
+
$script_to_load = FALSE;
|
344 |
+
if ( $this->are_we_on_calendar_feeds_page() === TRUE ) {
|
345 |
+
// Load script for the importer plugins
|
346 |
+
$script_to_load[] = self::CALENDAR_FEEDS_PAGE;
|
347 |
+
}
|
348 |
+
// Start the scripts for the event category page
|
349 |
+
if ( $this->_are_we_editing_event_categories() === TRUE ) {
|
350 |
+
// Load script required when editing categories
|
351 |
+
$script_to_load[] = self::EVENT_CATEGORY_PAGE;
|
352 |
+
}
|
353 |
+
if ( $this->_are_we_editing_less_variables() === TRUE ) {
|
354 |
+
// Load script required when editing categories
|
355 |
+
$script_to_load[] = self::LESS_VARIBALES_PAGE;
|
356 |
+
}
|
357 |
+
// Load the js needed when you edit an event / add a new event
|
358 |
+
if (
|
359 |
+
true === $this->_are_we_creating_a_new_event() ||
|
360 |
+
true === $this->_are_we_editing_an_event()
|
361 |
+
) {
|
362 |
+
// Load script for adding / modifying events
|
363 |
+
$script_to_load[] = self::ADD_NEW_EVENT_PAGE;
|
364 |
+
}
|
365 |
+
if ( true === $this->_are_we_accessing_the_calendar_settings_page() ) {
|
366 |
+
$script_to_load[] = self::SETTINGS_PAGE;
|
367 |
+
}
|
368 |
+
if ( true === $this->_are_we_creating_widgets() ) {
|
369 |
+
$script_to_load[] = self::WIDGET_CREATOR;
|
370 |
+
}
|
371 |
+
if (
|
372 |
+
true === $this->_are_we_managing_tickets() ||
|
373 |
+
true === $this->_are_we_managing_events_list()
|
374 |
+
) {
|
375 |
+
$script_to_load[] = self::TICKETING;
|
376 |
+
}
|
377 |
+
if ( false === $script_to_load ) {
|
378 |
+
$script_to_load[] = apply_filters( 'ai1ec_backend_js', self::LOAD_ONLY_BACKEND_SCRIPTS );
|
379 |
+
}
|
380 |
+
foreach ($script_to_load as $value) {
|
381 |
+
$this->add_link_to_render_js( $value, true );
|
382 |
+
}
|
383 |
+
}
|
384 |
+
|
385 |
+
/**
|
386 |
+
* Loads version 1.9 or 2.0 of jQuery based on user agent.
|
387 |
+
* If $user_agent is null (due to lack of HTTP header) we always serve
|
388 |
+
* jQuery 2.0.
|
389 |
+
*
|
390 |
+
* @param string $user_agent
|
391 |
+
*
|
392 |
+
* @return string
|
393 |
+
*/
|
394 |
+
public function get_jquery_version_based_on_browser( $user_agent ) {
|
395 |
+
$js_path = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR;
|
396 |
+
$jquery = 'jquery_timely20.js';
|
397 |
+
|
398 |
+
preg_match( '/MSIE (.*?);/', $user_agent, $matches );
|
399 |
+
if ( count( $matches ) > 1 ) {
|
400 |
+
//Then we're using IE
|
401 |
+
$version = (int) $matches[1];
|
402 |
+
if ( $version <= 8 ) {
|
403 |
+
//IE 8 or under!
|
404 |
+
$jquery = 'jquery_timely19.js';
|
405 |
+
}
|
406 |
+
}
|
407 |
+
return file_get_contents( $js_path . $jquery );
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* Creates a requirejs module that can be used for translations
|
412 |
+
*
|
413 |
+
* @param string $object_name
|
414 |
+
* @param array $data
|
415 |
+
*
|
416 |
+
* @return string
|
417 |
+
*/
|
418 |
+
public function create_require_js_module( $object_name, array $data ) {
|
419 |
+
foreach ( (array) $data as $key => $value ) {
|
420 |
+
if ( ! is_scalar( $value ) )
|
421 |
+
continue;
|
422 |
+
$data[$key] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8');
|
423 |
+
}
|
424 |
+
$json_data = json_encode( $data );
|
425 |
+
$prefix = self::REQUIRE_NAMESPACE;
|
426 |
+
$script = "$prefix.define( '$object_name', $json_data );";
|
427 |
+
|
428 |
+
return $script;
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Create the array needed for translation and passing other settings to JS.
|
433 |
+
*
|
434 |
+
* @return $data array the dynamic data array
|
435 |
+
*/
|
436 |
+
public function get_translation_data() {
|
437 |
+
|
438 |
+
$force_ssl_admin = force_ssl_admin();
|
439 |
+
if ( $force_ssl_admin && ! is_ssl() ) {
|
440 |
+
force_ssl_admin( false );
|
441 |
+
}
|
442 |
+
$ajax_url = ai1ec_admin_url( 'admin-ajax.php' );
|
443 |
+
force_ssl_admin( $force_ssl_admin );
|
444 |
+
$settings = $this->_registry->get( 'model.settings' );
|
445 |
+
$locale = $this->_registry->get( 'p28n.wpml' );
|
446 |
+
$blog_timezone = $this->_registry->get( 'model.option' )
|
447 |
+
->get( 'gmt_offset' );
|
448 |
+
$application = $this->_registry->get( 'bootstrap.registry.application' );
|
449 |
+
$data = array(
|
450 |
+
'calendar_feeds_nonce' => wp_create_nonce( 'ai1ec_ics_feed_nonce'),
|
451 |
+
// ICS feed error messages
|
452 |
+
'duplicate_feed_message' => esc_html(
|
453 |
+
Ai1ec_I18n::__( 'This feed is already being imported.' )
|
454 |
+
),
|
455 |
+
'invalid_url_message' => esc_html(
|
456 |
+
Ai1ec_I18n::__( 'Please enter a valid iCalendar URL.' )
|
457 |
+
),
|
458 |
+
'invalid_website_message' => esc_html(
|
459 |
+
Ai1ec_I18n::__( 'Please enter a valid Website URL.' )
|
460 |
+
),
|
461 |
+
'invalid_registration_message' => esc_html(
|
462 |
+
Ai1ec_I18n::__( 'Please enter a valid Registration URL, starting with https:// or http://.' )
|
463 |
+
),
|
464 |
+
'invalid_email_message' => esc_html(
|
465 |
+
Ai1ec_I18n::__( 'Please enter a valid email address.' )
|
466 |
+
),
|
467 |
+
'choose_image_message' => Ai1ec_I18n::__( 'Choose Image' ),
|
468 |
+
'now' => $this->_registry->get( 'date.system' )
|
469 |
+
->current_time(),
|
470 |
+
'size_less_variable_not_ok' => Ai1ec_I18n::__(
|
471 |
+
'The value you have entered is not a valid CSS length.'
|
472 |
+
),
|
473 |
+
'confirm_reset_theme' => Ai1ec_I18n::__(
|
474 |
+
'Are you sure you want to reset your theme options to their default values?'
|
475 |
+
),
|
476 |
+
'error_message_not_valid_lat' => Ai1ec_I18n::__(
|
477 |
+
'Please enter a valid latitude. A valid latitude is comprised between +90 and -90.'
|
478 |
+
),
|
479 |
+
'error_message_not_valid_long' => Ai1ec_I18n::__(
|
480 |
+
'Please enter a valid longitude. A valid longitude is comprised between +180 and -180.'
|
481 |
+
),
|
482 |
+
'error_message_not_entered_lat' => Ai1ec_I18n::__(
|
483 |
+
'When the "Input coordinates" checkbox is checked, "Latitude" is a required field.'
|
484 |
+
),
|
485 |
+
'error_message_not_entered_long' => Ai1ec_I18n::__(
|
486 |
+
'When the "Input coordinates" checkbox is checked, "Longitude" is a required field.'
|
487 |
+
),
|
488 |
+
'ai1ec_contact_url_not_valid' => Ai1ec_I18n::__(
|
489 |
+
'The URL you have entered in the <b>Organizer Contact Info</b> > <b>Website URL</b> seems to be invalid.'
|
490 |
+
),
|
491 |
+
'ai1ec_ticket_ext_url_not_valid' => Ai1ec_I18n::__(
|
492 |
+
'The URL you have entered in the <b>Event Cost and Tickets</b> > <b>Tickets or Registration URL</b> seems to be invalid.'
|
493 |
+
),
|
494 |
+
'ai1ec_contact_email_not_valid' => Ai1ec_I18n::__(
|
495 |
+
'The Email you have entered in the <b>Organizer Contact Info</b> > <b>E-mail</b> seems to be invalid.'
|
496 |
+
),
|
497 |
+
'general_url_not_valid' => Ai1ec_I18n::__(
|
498 |
+
'Please remember that URLs must start with either "http://" or "https://".'
|
499 |
+
),
|
500 |
+
'calendar_loading' => Ai1ec_I18n::__(
|
501 |
+
'Loading…'
|
502 |
+
),
|
503 |
+
'ticketing_required_fields' => Ai1ec_I18n::__(
|
504 |
+
'<b>Required or incorrect fields for Ticketing are outlined red.</b>'
|
505 |
+
),
|
506 |
+
'ticketing_repeat_not_supported' => Ai1ec_I18n::__( '<b>The Repeat option was selected but recurrence is not supported by Event with Tickets.</b>'
|
507 |
+
),
|
508 |
+
'ticketing_no_tickets_included' => Ai1ec_I18n::__( '<b>
|
509 |
+
The Event has the cost option Tickets selected but no ticket was included.</b>'
|
510 |
+
),
|
511 |
+
'discovery_event_success' => Ai1ec_I18n::__(
|
512 |
+
'Event was imported successfully.'
|
513 |
+
),
|
514 |
+
'discovery_event_error' => Ai1ec_I18n::__(
|
515 |
+
'An error occurred when importing event. Please, try later.'
|
516 |
+
),
|
517 |
+
'language' => $this->_registry->get( 'p28n.wpml' )->get_lang(),
|
518 |
+
'ajax_url' => $ajax_url,
|
519 |
+
// 24h time format for time pickers
|
520 |
+
'twentyfour_hour' => $settings->get( 'input_24h_time' ),
|
521 |
+
// Date format for date pickers
|
522 |
+
'date_format' => $settings->get( 'input_date_format' ),
|
523 |
+
// Names for months in date picker header (escaping is done in wp_localize_script)
|
524 |
+
'month_names' => $locale->get_localized_month_names(),
|
525 |
+
// Names for days in date picker header (escaping is done in wp_localize_script)
|
526 |
+
'day_names' => $locale->get_localized_week_names(),
|
527 |
+
// Start the week on this day in the date picker
|
528 |
+
'week_start_day' => $settings->get( 'week_start_day' ),
|
529 |
+
'week_view_starts_at' => $settings->get( 'week_view_starts_at' ),
|
530 |
+
'week_view_ends_at' => $settings->get( 'week_view_ends_at' ),
|
531 |
+
'google_maps_api_key' => $settings->get( 'google_maps_api_key' ),
|
532 |
+
'blog_timezone' => $blog_timezone,
|
533 |
+
'affix_filter_menu' => $settings->get( 'affix_filter_menu' ),
|
534 |
+
'affix_vertical_offset_md' => $settings->get( 'affix_vertical_offset_md' ),
|
535 |
+
'affix_vertical_offset_lg' => $settings->get( 'affix_vertical_offset_lg' ),
|
536 |
+
'affix_vertical_offset_sm' => $settings->get( 'affix_vertical_offset_sm' ),
|
537 |
+
'affix_vertical_offset_xs' => $settings->get( 'affix_vertical_offset_xs' ),
|
538 |
+
'calendar_page_id' => $settings->get( 'calendar_page_id' ),
|
539 |
+
'region' => ( $settings->get( 'geo_region_biasing' ) ) ? $locale->get_region() : '',
|
540 |
+
'site_url' => trailingslashit(
|
541 |
+
ai1ec_get_site_url()
|
542 |
+
),
|
543 |
+
'javascript_widgets' => array(),
|
544 |
+
'widget_creator' => array(
|
545 |
+
'preview' => Ai1ec_I18n::__( 'Preview:' ),
|
546 |
+
'preview_loading' => Ai1ec_I18n::__(
|
547 |
+
'Loading preview <i class="ai1ec-fa ai1ec-fa-spin ai1ec-fa-spinner"></i>'
|
548 |
+
)
|
549 |
+
),
|
550 |
+
'ticketing' => array(
|
551 |
+
'details' => Ai1ec_I18n::__( 'Ticketing Details' ),
|
552 |
+
'hide_details' => Ai1ec_I18n::__( 'Hide Ticketing Details' ),
|
553 |
+
'loading_details' => Ai1ec_I18n::__( 'Loading tickets details...' ),
|
554 |
+
'type_and_price' => Ai1ec_I18n::__( 'Type and price' ),
|
555 |
+
'info' => Ai1ec_I18n::__( 'Info' ),
|
556 |
+
'information' => Ai1ec_I18n::__( 'Information' ),
|
557 |
+
'report' => Ai1ec_I18n::__( 'Report' ),
|
558 |
+
'sale_dates' => Ai1ec_I18n::__( 'Sale dates' ),
|
559 |
+
'limits' => Ai1ec_I18n::__( 'Limits' ),
|
560 |
+
'actions' => Ai1ec_I18n::__( 'Actions' ),
|
561 |
+
'sold' => Ai1ec_I18n::__( 'Sold:' ),
|
562 |
+
'left' => Ai1ec_I18n::__( 'Left:' ),
|
563 |
+
'start' => Ai1ec_I18n::__( 'Start:' ),
|
564 |
+
'end' => Ai1ec_I18n::__( 'End:' ),
|
565 |
+
'min' => Ai1ec_I18n::__( 'Min:' ),
|
566 |
+
'max' => Ai1ec_I18n::__( 'Max:' ),
|
567 |
+
'attendees' => Ai1ec_I18n::__( 'Attendees' ),
|
568 |
+
'hide_attendees' => Ai1ec_I18n::__( 'Hide Attendees' ),
|
569 |
+
'attendees_list' => Ai1ec_I18n::__( 'Attendees List' ),
|
570 |
+
'guest_name' => Ai1ec_I18n::__( 'Guest Name' ),
|
571 |
+
'status' => Ai1ec_I18n::__( 'Status' ),
|
572 |
+
'email' => Ai1ec_I18n::__( 'Email' ),
|
573 |
+
'no_attendees' => Ai1ec_I18n::__( 'No attendees for this ticket type.' ),
|
574 |
+
'edit' => Ai1ec_I18n::__( 'Edit' ),
|
575 |
+
'code' => Ai1ec_I18n::__( 'Code' ),
|
576 |
+
'unlimited' => Ai1ec_I18n::__( 'Unlimited' ),
|
577 |
+
'open_for_sale' => Ai1ec_I18n::__( 'Open for sale' ),
|
578 |
+
'no_delete_text' => Ai1ec_I18n::__( 'You have sold tickets for this ticket type. Please change it\'s status to "Canceled" and make refunds to all users that purchased tickets.' ),
|
579 |
+
'cancel_message' => Ai1ec_I18n::__( 'You have sold tickets for this ticket type. Please make refunds to all users that purchased tickets' )
|
580 |
+
),
|
581 |
+
'review' => array(
|
582 |
+
'message_sent' => Ai1ec_I18n::__( 'Your message has been sent. Thank you for your feedback.' ),
|
583 |
+
'message_error' => Ai1ec_I18n::__( 'Your message has not been sent. Please try again or contact us.' )
|
584 |
+
),
|
585 |
+
'load_views_error' => Ai1ec_I18n::__(
|
586 |
+
'Something went wrong while fetching events.<br>The request status is: %STATUS% <br>The error thrown was: %ERROR%'
|
587 |
+
),
|
588 |
+
'load_views_error_popup_title' => Ai1ec_I18n::__( 'Response text received from server' ),
|
589 |
+
'load_views_error_link_popup' => Ai1ec_I18n::__( 'Click here for technical details' ),
|
590 |
+
'cookie_path' => $this->_registry->get(
|
591 |
+
'cookie.utility'
|
592 |
+
)->get_path_for_cookie(),
|
593 |
+
'disable_autocompletion' => $settings->get( 'disable_autocompletion' ),
|
594 |
+
'end_must_be_after_start' => __( 'The end date can\'t be earlier than the start date.', AI1EC_PLUGIN_NAME ),
|
595 |
+
'show_at_least_six_hours' => __( 'For week and day view, you must select an interval of at least 6 hours.', AI1EC_PLUGIN_NAME ),
|
596 |
+
'ai1ec_permalinks_enabled' => $application->get( 'permalinks_enabled' ),
|
597 |
+
);
|
598 |
+
return apply_filters( 'ai1ec_js_translations', $data );
|
599 |
+
}
|
600 |
+
|
601 |
+
/**
|
602 |
+
* Get the array with translated data for the frontend
|
603 |
+
*
|
604 |
+
* @return array
|
605 |
+
*/
|
606 |
+
public function get_frontend_translation_data() {
|
607 |
+
$data = array(
|
608 |
+
'export_url' => AI1EC_EXPORT_URL,
|
609 |
+
);
|
610 |
+
|
611 |
+
// Replace desired CSS selector with calendar, if selector has been set
|
612 |
+
$calendar_selector = $this->_settings->get( 'calendar_css_selector' );
|
613 |
+
if( $calendar_selector ) {
|
614 |
+
$page = get_post(
|
615 |
+
$this->_settings->get( 'calendar_page_id' )
|
616 |
+
);
|
617 |
+
$data['selector'] = $calendar_selector;
|
618 |
+
$data['title'] = $page->post_title;
|
619 |
+
}
|
620 |
+
|
621 |
+
// DEPRECATED: Only still here for backwards compatibility with Ai1ec 1.x.
|
622 |
+
$data['fonts'] = array();
|
623 |
+
$fonts_dir = AI1EC_DEFAULT_THEME_URL . 'font_css/';
|
624 |
+
$data['fonts'][] = array(
|
625 |
+
'name' => 'League Gothic',
|
626 |
+
'url' => $fonts_dir . 'font-league-gothic.css',
|
627 |
+
);
|
628 |
+
$data['fonts'][] = array(
|
629 |
+
'name' => 'fontawesome',
|
630 |
+
'url' => $fonts_dir . 'font-awesome.css',
|
631 |
+
);
|
632 |
+
return $data;
|
633 |
+
}
|
634 |
+
|
635 |
+
/**
|
636 |
+
* Echoes the Javascript if not cached.
|
637 |
+
*
|
638 |
+
* Echoes the javascript with the correct content.
|
639 |
+
* Since the content is dinamic, i use the hash function.
|
640 |
+
*
|
641 |
+
* @param string $javascript
|
642 |
+
*
|
643 |
+
* @return void
|
644 |
+
*/
|
645 |
+
private function _echo_javascript( $javascript ) {
|
646 |
+
$conditional_get = new HTTP_ConditionalGet( array(
|
647 |
+
'contentHash' => md5( $javascript )
|
648 |
+
)
|
649 |
+
);
|
650 |
+
$conditional_get->sendHeaders();
|
651 |
+
if ( ! $conditional_get->cacheIsValid ) {
|
652 |
+
$http_encoder = $this->_registry->get(
|
653 |
+
'http.encoder',
|
654 |
+
array(
|
655 |
+
'content' => $javascript,
|
656 |
+
'type' => 'text/javascript'
|
657 |
+
)
|
658 |
+
);
|
659 |
+
$compression_level = null;
|
660 |
+
if ( $this->_registry->get( 'model.settings' )->get( 'disable_gzip_compression' ) ) {
|
661 |
+
// set the compression level to 0 to disable it.
|
662 |
+
$compression_level = 0;
|
663 |
+
}
|
664 |
+
$http_encoder->encode( $compression_level );
|
665 |
+
$http_encoder->sendAll();
|
666 |
+
}
|
667 |
+
Ai1ec_Http_Response_Helper::stop( 0 );
|
668 |
+
}
|
669 |
+
|
670 |
+
/**
|
671 |
+
* Create the config object for requirejs.
|
672 |
+
*
|
673 |
+
* @return string
|
674 |
+
*/
|
675 |
+
public function create_require_js_config_object() {
|
676 |
+
$js_url = AI1EC_ADMIN_THEME_JS_URL;
|
677 |
+
$version = AI1EC_VERSION;
|
678 |
+
$namespace = self::REQUIRE_NAMESPACE;
|
679 |
+
$config = <<<JSC
|
680 |
+
$namespace.require.config( {
|
681 |
+
waitSeconds : 15,
|
682 |
+
urlArgs : 'ver=$version',
|
683 |
+
baseUrl : '$js_url'
|
684 |
+
} );
|
685 |
JSC;
|
686 |
+
return $config;
|
687 |
+
}
|
688 |
+
|
689 |
+
/**
|
690 |
+
* Check if we are in the calendar feeds page
|
691 |
+
*
|
692 |
+
* @return boolean TRUE if we are in the calendar feeds page FALSE otherwise
|
693 |
+
*/
|
694 |
+
public function are_we_on_calendar_feeds_page() {
|
695 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
696 |
+
return FALSE;
|
697 |
+
}
|
698 |
+
|
699 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
700 |
+
$post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : FALSE;
|
701 |
+
$page = isset( $_GET['page'] ) ? $_GET['page'] : FALSE;
|
702 |
+
if( $post_type === FALSE || $page === FALSE ) {
|
703 |
+
return FALSE;
|
704 |
+
}
|
705 |
+
$is_calendar_feed_page = $path_details['basename'] === 'edit.php' &&
|
706 |
+
$post_type === 'ai1ec_event' &&
|
707 |
+
$page === 'all-in-one-event-calendar-feeds';
|
708 |
+
return $is_calendar_feed_page;
|
709 |
+
}
|
710 |
+
|
711 |
+
/**
|
712 |
+
* Add the link to render the javascript
|
713 |
+
*
|
714 |
+
* @param string $page
|
715 |
+
* @param boolean $backend
|
716 |
+
*
|
717 |
+
* @return void
|
718 |
+
*/
|
719 |
+
public function add_link_to_render_js( $page, $backend ) {
|
720 |
+
$load_backend_script = 'false';
|
721 |
+
if ( true === $backend ) {
|
722 |
+
$load_backend_script = self::TRUE_PARAM;
|
723 |
+
}
|
724 |
+
$is_calendar_page = false;
|
725 |
+
if(
|
726 |
+
true === is_page( $this->_settings->get( 'calendar_page_id' ) ) ||
|
727 |
+
self::CALENDAR_PAGE_JS === $page
|
728 |
+
) {
|
729 |
+
$is_calendar_page = self::TRUE_PARAM;
|
730 |
+
}
|
731 |
+
|
732 |
+
$url = add_query_arg(
|
733 |
+
array(
|
734 |
+
// Add the page to load
|
735 |
+
self::LOAD_JS_PARAMETER => $page,
|
736 |
+
// If we are in the backend, we must load the common scripts
|
737 |
+
self::IS_BACKEND_PARAMETER => $load_backend_script,
|
738 |
+
// If we are on the calendar page we must load the correct option
|
739 |
+
self::IS_CALENDAR_PAGE => $is_calendar_page,
|
740 |
+
),
|
741 |
+
trailingslashit( ai1ec_get_site_url() )
|
742 |
+
);
|
743 |
+
if (
|
744 |
+
$this->_settings->get( 'cache_dynamic_js' ) &&
|
745 |
+
$is_calendar_page &&
|
746 |
+
'1' === $this->_registry->get( 'model.option' )->get( 'calendarjsupdated' ) &&
|
747 |
+
$this->_registry->get( 'filesystem.checker' )->check_file_exists(
|
748 |
+
AI1EC_PATH . self::CALENDAR_JS_CACHE_FILE,
|
749 |
+
true
|
750 |
+
)
|
751 |
+
) {
|
752 |
+
$url = plugin_dir_url( 'all-in-one-event-calendar/public/js_cache/.' ) . $page;
|
753 |
+
}
|
754 |
+
|
755 |
+
if ( true === $backend ) {
|
756 |
+
$this->_scripts_helper->enqueue_script(
|
757 |
+
self::JS_HANDLE,
|
758 |
+
$url,
|
759 |
+
array( 'postbox' ),
|
760 |
+
true
|
761 |
+
);
|
762 |
+
} else {
|
763 |
+
$this->_scripts_helper->enqueue_script(
|
764 |
+
self::JS_HANDLE,
|
765 |
+
$url,
|
766 |
+
array(),
|
767 |
+
false
|
768 |
+
);
|
769 |
+
}
|
770 |
+
}
|
771 |
+
|
772 |
+
/**
|
773 |
+
* check if we are editing an event
|
774 |
+
*
|
775 |
+
* @return boolean TRUE if we are editing an event FALSE otherwise
|
776 |
+
*/
|
777 |
+
private function _are_we_editing_an_event() {
|
778 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
779 |
+
return FALSE;
|
780 |
+
}
|
781 |
+
|
782 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
783 |
+
$post_id = isset( $_GET['post'] ) ? $_GET['post'] : FALSE;
|
784 |
+
$action = isset( $_GET['action'] ) ? $_GET['action'] : FALSE;
|
785 |
+
if( $post_id === FALSE || $action === FALSE ) {
|
786 |
+
return FALSE;
|
787 |
+
}
|
788 |
+
|
789 |
+
$editing = (
|
790 |
+
'post.php' === $path_details['basename'] &&
|
791 |
+
'edit' === $action &&
|
792 |
+
$this->_aco->is_our_post_type( $post_id )
|
793 |
+
);
|
794 |
+
return $editing;
|
795 |
+
}
|
796 |
+
|
797 |
+
/**
|
798 |
+
* check if we are viewing events list
|
799 |
+
*
|
800 |
+
* @return boolean TRUE if we are on the events list FALSE otherwise
|
801 |
+
*/
|
802 |
+
private function _are_we_managing_events_list() {
|
803 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
804 |
+
return FALSE;
|
805 |
+
}
|
806 |
+
|
807 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
808 |
+
$post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : FALSE;
|
809 |
+
if ( FALSE === $post_type ) {
|
810 |
+
return FALSE;
|
811 |
+
}
|
812 |
+
$page = isset( $_GET['page'] ) ? $_GET['page'] : '';
|
813 |
+
$events_list = (
|
814 |
+
'edit.php' === $path_details['basename'] &&
|
815 |
+
'ai1ec_event' === $post_type &&
|
816 |
+
ai1ec_is_blank( $page )
|
817 |
+
);
|
818 |
+
return $events_list;
|
819 |
+
}
|
820 |
+
|
821 |
+
/**
|
822 |
+
* check if we are creating a new event
|
823 |
+
*
|
824 |
+
* @return boolean TRUE if we are creating a new event FALSE otherwise
|
825 |
+
*/
|
826 |
+
private function _are_we_creating_a_new_event() {
|
827 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
828 |
+
return FALSE;
|
829 |
+
}
|
830 |
+
|
831 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
832 |
+
$post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : '';
|
833 |
+
return $path_details['basename'] === 'post-new.php' &&
|
834 |
+
$post_type === AI1EC_POST_TYPE;
|
835 |
+
}
|
836 |
+
|
837 |
+
/**
|
838 |
+
* Check if we are accessing the settings page
|
839 |
+
*
|
840 |
+
* @return boolean TRUE if we are accessing the settings page FALSE otherwise
|
841 |
+
*/
|
842 |
+
private function _are_we_accessing_the_calendar_settings_page() {
|
843 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
844 |
+
return FALSE;
|
845 |
+
}
|
846 |
+
|
847 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
848 |
+
$page = isset( $_GET['page'] ) ? $_GET['page'] : '';
|
849 |
+
return $path_details['basename'] === 'edit.php' &&
|
850 |
+
$page === AI1EC_PLUGIN_NAME . '-settings';
|
851 |
+
}
|
852 |
+
|
853 |
+
protected function _are_we_creating_widgets() {
|
854 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
855 |
+
return FALSE;
|
856 |
+
}
|
857 |
+
|
858 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
859 |
+
$page = isset( $_GET['page'] ) ? $_GET['page'] : '';
|
860 |
+
return $path_details['basename'] === 'edit.php' &&
|
861 |
+
$page === AI1EC_PLUGIN_NAME . '-widget-creator';
|
862 |
+
}
|
863 |
+
|
864 |
+
protected function _are_we_managing_tickets() {
|
865 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
866 |
+
return FALSE;
|
867 |
+
}
|
868 |
+
|
869 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
870 |
+
$page = isset( $_GET['page'] ) ? $_GET['page'] : '';
|
871 |
+
return $path_details['basename'] === 'edit.php' &&
|
872 |
+
$page === AI1EC_PLUGIN_NAME . '-tickets';
|
873 |
+
}
|
874 |
+
|
875 |
+
/**
|
876 |
+
* Check if we are editing less variables
|
877 |
+
*
|
878 |
+
* @return boolean TRUE if we are accessing a single event page FALSE otherwise
|
879 |
+
*/
|
880 |
+
private function _are_we_editing_less_variables() {
|
881 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
882 |
+
return FALSE;
|
883 |
+
}
|
884 |
+
|
885 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
886 |
+
$page = isset( $_GET['page'] ) ? $_GET['page'] : '';
|
887 |
+
return $path_details['basename'] === 'edit.php' && $page === AI1EC_PLUGIN_NAME . '-edit-css';
|
888 |
+
}
|
889 |
+
|
890 |
+
/**
|
891 |
+
* Check if we are accessing the events category page
|
892 |
+
*
|
893 |
+
* @return boolean TRUE if we are accessing the events category page FALSE otherwise
|
894 |
+
*/
|
895 |
+
private function _are_we_editing_event_categories() {
|
896 |
+
if ( !isset( $_SERVER['SCRIPT_NAME'] ) ) {
|
897 |
+
return FALSE;
|
898 |
+
}
|
899 |
+
|
900 |
+
$path_details = pathinfo( $_SERVER['SCRIPT_NAME'] );
|
901 |
+
$post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : '';
|
902 |
+
return (
|
903 |
+
$path_details['basename'] === 'edit-tags.php' ||
|
904 |
+
$path_details['basename'] === 'term.php'
|
905 |
+
) && $post_type === AI1EC_POST_TYPE;
|
906 |
+
}
|
907 |
+
|
908 |
+
/**
|
909 |
+
* Check if we are accessing a single event page
|
910 |
+
*
|
911 |
+
* @return boolean TRUE if we are accessing a single event page FALSE otherwise
|
912 |
+
*/
|
913 |
+
private function _are_we_accessing_the_single_event_page() {
|
914 |
+
return $this->_aco->is_our_post_type();
|
915 |
+
}
|
916 |
|
917 |
}
|
app/controller/shutdown.php
CHANGED
@@ -11,95 +11,95 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Shutdown_Controller {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
|
32 |
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
|
105 |
}
|
11 |
*/
|
12 |
class Ai1ec_Shutdown_Controller {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var array Map of object names and class names they represent to preserve
|
16 |
+
*/
|
17 |
+
protected $_preserve = array(
|
18 |
+
'wpdb' => 'wpdb',
|
19 |
+
'wp_object_cache' => 'WP_Object_Cache',
|
20 |
+
);
|
21 |
|
22 |
+
/**
|
23 |
+
* @var array Map of object names and their representation from global scope
|
24 |
+
*/
|
25 |
+
protected $_restorables = array();
|
26 |
|
27 |
+
/**
|
28 |
+
* @var array List of callbacks to be executed during shutdown sequence
|
29 |
+
*/
|
30 |
+
protected $_callbacks = array();
|
31 |
|
32 |
|
33 |
+
/**
|
34 |
+
* Destructor
|
35 |
+
*
|
36 |
+
* Here processing of globals is made - values are replaced, callbacks
|
37 |
+
* are executed and globals are restored to the previous state.
|
38 |
+
*
|
39 |
+
* @return void Destructor does not return
|
40 |
+
*/
|
41 |
+
public function __destruct() {
|
42 |
+
// replace globals from our internal store
|
43 |
+
$restore = array();
|
44 |
+
foreach ( $this->_preserve as $name => $class ) {
|
45 |
+
if (
|
46 |
+
! isset( $GLOBALS[$name] ) ||
|
47 |
+
! ( $GLOBALS[$name] instanceof $class )
|
48 |
+
) {
|
49 |
+
$restore[$name] = NULL;
|
50 |
+
if ( isset( $GLOBALS[$name] ) ) {
|
51 |
+
$restore[$name] = $GLOBALS[$name];
|
52 |
+
}
|
53 |
+
$GLOBALS[$name] = $this->_restorables[$name];
|
54 |
+
}
|
55 |
+
}
|
56 |
+
// execute callbacks
|
57 |
+
foreach ( $this->_callbacks as $callback ) {
|
58 |
+
call_user_func( $callback );
|
59 |
+
}
|
60 |
+
// restore globals to previous state
|
61 |
+
foreach ( $restore as $name => $object ) {
|
62 |
+
if ( NULL === $object ) {
|
63 |
+
unset( $GLOBALS[$name] );
|
64 |
+
} else {
|
65 |
+
$GLOBALS[$name] = $object;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
// destroy local references
|
69 |
+
foreach ( $this->_restorables as $name => $object ) {
|
70 |
+
unset( $object, $this->_restorables[$name] );
|
71 |
+
}
|
72 |
+
if ( AI1EC_DEBUG ) {
|
73 |
+
// __destruct is called twice if facebook extension is installed
|
74 |
+
// still can't find the reason, this fixes it but prevent other plugins
|
75 |
+
// __destruct() so let's just use it in dev until we fix this.
|
76 |
+
exit();
|
77 |
+
}
|
78 |
+
}
|
79 |
|
80 |
+
/**
|
81 |
+
* Register a callback to be executed during shutdown sequence
|
82 |
+
*
|
83 |
+
* @param callback $callback Valid PHP callback
|
84 |
+
*
|
85 |
+
* @return Ai1ec_Shutdown_Utility Self instance for chaining
|
86 |
+
*/
|
87 |
+
public function register( $callback ) {
|
88 |
+
$this->_callbacks[] = $callback;
|
89 |
+
return $this;
|
90 |
+
}
|
91 |
|
92 |
+
/**
|
93 |
+
* Constructor
|
94 |
+
*
|
95 |
+
* Here global variables are referenced locally to ensure their preservation
|
96 |
+
*
|
97 |
+
* @return void Constructor does not return
|
98 |
+
*/
|
99 |
+
public function __construct() {
|
100 |
+
foreach ( $this->_preserve as $name => $class ) {
|
101 |
+
$this->_restorables[$name] = $GLOBALS[$name];
|
102 |
+
}
|
103 |
+
}
|
104 |
|
105 |
}
|
app/model/api/api-abstract.php
CHANGED
@@ -10,557 +10,616 @@
|
|
10 |
*/
|
11 |
abstract class Ai1ec_Api_Abstract extends Ai1ec_App {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
protected function save_ticketing_settings( $message, $enabled, $token, $calendar_id, $account ) {
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
103 |
* Check if the current WP instance has payments settings configured
|
104 |
*/
|
105 |
public function has_payment_settings() {
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
}
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
|
147 |
|
148 |
public function get_timely_token() {
|
149 |
return $this->get_ticketing_settings( 'token' );
|
150 |
-
}
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
|
334 |
/**
|
335 |
* Check if the current WP instance is signed into the API
|
336 |
*/
|
337 |
public function is_signed() {
|
338 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
}
|
340 |
|
341 |
/**
|
342 |
* Get the current email account
|
343 |
*/
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
public function get_current_calendar() {
|
352 |
-
|
353 |
}
|
354 |
|
355 |
/**
|
356 |
* Get the last message return by Signup or Signup process
|
357 |
*/
|
358 |
public function get_sign_message() {
|
359 |
-
|
360 |
-
}
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
565 |
|
566 |
}
|
10 |
*/
|
11 |
abstract class Ai1ec_Api_Abstract extends Ai1ec_App {
|
12 |
|
13 |
+
const WP_OPTION_KEY = 'ai1ec_api_settings';
|
14 |
+
const DEFAULT_TIMEOUT = 30;
|
15 |
+
|
16 |
+
protected $_settings;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Post construction routine.
|
20 |
+
*
|
21 |
+
* Override this method to perform post-construction tasks.
|
22 |
+
*
|
23 |
+
* @return void Return from this method is ignored.
|
24 |
+
*/
|
25 |
+
protected function _initialize() {
|
26 |
+
$this->_settings = $this->_registry->get( 'model.settings' );
|
27 |
+
}
|
28 |
+
|
29 |
+
protected function get_ticketing_settings( $find_attribute = null, $default_value_attribute = null ) {
|
30 |
+
$api_settings = get_option( self::WP_OPTION_KEY, null );
|
31 |
+
if ( ! is_array( $api_settings ) ) {
|
32 |
+
$api_settings = array(
|
33 |
+
'enabled' => $this->_settings->get( 'ticketing_enabled' ),
|
34 |
+
'message' => $this->_settings->get( 'ticketing_message' ),
|
35 |
+
'token' => $this->_settings->get( 'ticketing_token' ),
|
36 |
+
'calendar_id' => $this->_settings->get( 'ticketing_calendar_id' )
|
37 |
+
);
|
38 |
+
update_option( self::WP_OPTION_KEY, $api_settings );
|
39 |
+
$this->_settings->set( 'ticketing_message' , '' );
|
40 |
+
$this->_settings->set( 'ticketing_enabled' , false );
|
41 |
+
$this->_settings->set( 'ticketing_token' , '' );
|
42 |
+
$this->_settings->set( 'ticketing_calendar_id', null );
|
43 |
+
}
|
44 |
+
if ( is_null( $find_attribute ) ) {
|
45 |
+
return $api_settings;
|
46 |
+
} else {
|
47 |
+
if ( isset( $api_settings[$find_attribute] ) ) {
|
48 |
+
return $api_settings[$find_attribute];
|
49 |
+
} else {
|
50 |
+
return $default_value_attribute;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @param String $message last message received from the Sign up or Sign in process
|
57 |
+
* @param bool $enabled true or false is ticket is enabled
|
58 |
+
* @param string $token autenthication token
|
59 |
+
* @param int @calendar_id remote id of the calendar
|
60 |
+
* @param string $account Email used to create the account
|
61 |
+
*/
|
62 |
protected function save_ticketing_settings( $message, $enabled, $token, $calendar_id, $account ) {
|
63 |
+
$api_settings = $this->get_ticketing_settings();
|
64 |
+
$api_settings['message'] = $message;
|
65 |
+
$api_settings['enabled'] = $enabled;
|
66 |
+
$api_settings['token'] = $token;
|
67 |
+
$api_settings['calendar_id'] = $calendar_id;
|
68 |
+
$api_settings['account'] = $account;
|
69 |
+
return update_option( self::WP_OPTION_KEY, $api_settings );
|
70 |
+
}
|
71 |
+
|
72 |
+
protected function clear_ticketing_settings() {
|
73 |
+
delete_option( self::WP_OPTION_KEY );
|
74 |
+
|
75 |
+
// Clear transient API data
|
76 |
+
delete_transient( 'ai1ec_api_feeds_subscriptions' );
|
77 |
+
delete_transient( 'ai1ec_api_subscriptions' );
|
78 |
+
delete_transient( 'ai1ec_api_features' );
|
79 |
+
delete_transient( 'ai1ec_api_checked' );
|
80 |
+
|
81 |
+
$this->check_settings();
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Save the Payment settings localy (same saved on the API)
|
86 |
+
* @param array Preferences to save
|
87 |
+
*/
|
88 |
+
public function save_payment_settings( array $values ) {
|
89 |
+
$api_settings = $this->get_ticketing_settings();
|
90 |
+
if ( null !== $values ) {
|
91 |
+
$api_settings['payment_settings'] = $values;
|
92 |
+
} else {
|
93 |
+
unset( $api_settings['payment_settings'] );
|
94 |
+
}
|
95 |
+
return update_option( self::WP_OPTION_KEY, $api_settings );
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Get the saved payments settings (the same saved on the API)
|
100 |
+
*/
|
101 |
+
public function get_payment_settings() {
|
102 |
+
return $this->get_ticketing_settings( 'payment_settings' );
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
* Check if the current WP instance has payments settings configured
|
107 |
*/
|
108 |
public function has_payment_settings() {
|
109 |
+
$payment_settings = $this->get_payment_settings();
|
110 |
+
if ( null === $payment_settings ) {
|
111 |
+
//code to migrate the settings save on ticketing api and
|
112 |
+
//bring them to the core side
|
113 |
+
$payment_settings = $this->get_payment_preferences();
|
114 |
+
if ( is_object( $payment_settings ) ) {
|
115 |
+
$payment_settings = (array) $payment_settings;
|
116 |
+
}
|
117 |
+
$this->save_payment_settings( (array) $payment_settings );
|
118 |
+
}
|
119 |
+
return ( null !== $payment_settings &&
|
120 |
+
'paypal' === $payment_settings['payment_method'] &&
|
121 |
+
false === ai1ec_is_blank( $payment_settings['paypal_email'] ) ) ;
|
122 |
+
}
|
123 |
+
|
124 |
+
|
125 |
+
/**
|
126 |
+
* @return object Response from API, or empty defaults
|
127 |
+
*/
|
128 |
+
public function get_payment_preferences() {
|
129 |
+
$calendar_id = $this->_get_ticket_calendar();
|
130 |
+
$settings = null;
|
131 |
+
if ( 0 < $calendar_id ) {
|
132 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . "calendars/$calendar_id/payment",
|
133 |
+
null, //no body
|
134 |
+
true //decode response body
|
135 |
+
);
|
136 |
+
if ( $this->is_response_success( $response ) ) {
|
137 |
+
$settings = $response->body;
|
138 |
+
}
|
139 |
+
}
|
140 |
+
if ( is_null( $settings ) ) {
|
141 |
+
return (object) array( 'payment_method'=>'paypal', 'paypal_email'=> '', 'first_name'=>'', 'last_name'=>'', 'currency'=> 'USD' );
|
142 |
+
} else {
|
143 |
+
if ( ! isset( $settings->currency ) ) {
|
144 |
+
$settings->currency = 'USD';
|
145 |
+
}
|
146 |
+
return $settings;
|
147 |
+
}
|
148 |
+
}
|
149 |
|
150 |
|
151 |
public function get_timely_token() {
|
152 |
return $this->get_ticketing_settings( 'token' );
|
153 |
+
}
|
154 |
+
|
155 |
+
protected function save_calendar_id ( $calendar_id ) {
|
156 |
+
$api_settings = $this->get_ticketing_settings();
|
157 |
+
$api_settings['calendar_id'] = $calendar_id;
|
158 |
+
return update_option( self::WP_OPTION_KEY, $api_settings );
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Get the header array with authorization token
|
163 |
+
*/
|
164 |
+
protected function _get_headers( $custom_headers = null ) {
|
165 |
+
$headers = array(
|
166 |
+
'content-type' => 'application/json'
|
167 |
+
);
|
168 |
+
$headers['Authorization'] = 'Basic ' . $this->get_ticketing_settings( 'token', '' );
|
169 |
+
if ( null !== $custom_headers ) {
|
170 |
+
foreach ( $custom_headers as $key => $value ) {
|
171 |
+
if ( null === $value ) {
|
172 |
+
unset( $headers[$key] );
|
173 |
+
} else {
|
174 |
+
$headers[$key] = $value;
|
175 |
+
}
|
176 |
+
}
|
177 |
+
}
|
178 |
+
return $headers;
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Create a standarized message to return
|
183 |
+
* 1) If the API respond with http code 400 and with a JSON body, so, we will consider the API message to append in the base message.
|
184 |
+
* 2) If the API does not responde with http code 400 or does not have a valid a JSON body, we will show the API URL and the http message error.
|
185 |
+
*/
|
186 |
+
protected function _transform_error_message( $base_message, $response, $url, $ask_for_reload = false ) {
|
187 |
+
$api_error = $this->get_api_error_msg( $response );
|
188 |
+
$result = null;
|
189 |
+
if ( false === ai1ec_is_blank( $api_error ) ) {
|
190 |
+
$result = sprintf(
|
191 |
+
__( '%s.<br/>Detail: %s.', AI1EC_PLUGIN_NAME ),
|
192 |
+
$base_message, $api_error
|
193 |
+
);
|
194 |
+
} else {
|
195 |
+
if ( is_wp_error( $response ) ) {
|
196 |
+
$error_message = sprintf(
|
197 |
+
__( 'API URL: %s.<br/>Detail: %s', AI1EC_PLUGIN_NAME ),
|
198 |
+
$url,
|
199 |
+
$response->get_error_message()
|
200 |
+
);
|
201 |
+
} else {
|
202 |
+
$error_message = sprintf(
|
203 |
+
__( 'API URL: %s.<br/>Detail: %s - %s', AI1EC_PLUGIN_NAME ),
|
204 |
+
$url,
|
205 |
+
wp_remote_retrieve_response_code( $response ),
|
206 |
+
wp_remote_retrieve_response_message( $response )
|
207 |
+
);
|
208 |
+
$mailto = '<a href="mailto:labs@time.ly" target="_top">labs@time.ly</a>';
|
209 |
+
if ( true === $ask_for_reload ) {
|
210 |
+
$result = sprintf(
|
211 |
+
__( '%s. Please reload this page to try again. If this error persists, please contact us at %s. In your report please include the information below.<br/>%s.', AI1EC_PLUGIN_NAME ),
|
212 |
+
$base_message,
|
213 |
+
$mailto,
|
214 |
+
$error_message
|
215 |
+
);
|
216 |
+
} else {
|
217 |
+
$result = sprintf(
|
218 |
+
__( '%s. Please try again. If this error persists, please contact us at %s. In your report please include the information below.<br/>%s.', AI1EC_PLUGIN_NAME ),
|
219 |
+
$base_message,
|
220 |
+
$mailto,
|
221 |
+
$error_message
|
222 |
+
);
|
223 |
+
}
|
224 |
+
}
|
225 |
+
}
|
226 |
+
$result = trim( $result );
|
227 |
+
$result = str_replace( '..', '.', $result );
|
228 |
+
$result = str_replace( '.,', '.', $result );
|
229 |
+
return $result;
|
230 |
+
}
|
231 |
+
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Search for the API message error
|
235 |
+
*/
|
236 |
+
public function get_api_error_msg( $response ) {
|
237 |
+
if ( isset( $response ) && false === is_wp_error( $response ) ) {
|
238 |
+
$response_body = json_decode( $response['body'], true );
|
239 |
+
if ( is_array( $response_body ) &&
|
240 |
+
isset( $response_body['errors'] ) ) {
|
241 |
+
$errors = $response_body['errors'];
|
242 |
+
if ( false === is_array( $errors )) {
|
243 |
+
$errors = array( $errors );
|
244 |
+
}
|
245 |
+
$messages = null;
|
246 |
+
foreach ($errors as $key => $value) {
|
247 |
+
if ( false === ai1ec_is_blank( $value ) ) {
|
248 |
+
if ( is_array( $value ) ) {
|
249 |
+
$value = implode ( ', ', $value );
|
250 |
+
}
|
251 |
+
$messages[] = $value;
|
252 |
+
}
|
253 |
+
}
|
254 |
+
if ( null !== $messages && false === empty( $messages ) ) {
|
255 |
+
return implode ( ', ', $messages);
|
256 |
+
}
|
257 |
+
}
|
258 |
+
}
|
259 |
+
return null;
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Get the ticket calendar from settings, if the calendar does not exists in
|
264 |
+
* settings, then we will try to find on the API
|
265 |
+
* @return string JSON.
|
266 |
+
*/
|
267 |
+
protected function _get_ticket_calendar( $createIfNotExists = true ) {
|
268 |
+
$ticketing_calendar_id = $this->get_ticketing_settings( 'calendar_id', 0 );
|
269 |
+
if ( 0 < $ticketing_calendar_id ) {
|
270 |
+
return $ticketing_calendar_id;
|
271 |
+
} else {
|
272 |
+
if ( ! $createIfNotExists ) {
|
273 |
+
return 0;
|
274 |
+
}
|
275 |
+
// Try to find the calendar in the API
|
276 |
+
$ticketing_calendar_id = $this->_find_user_calendar();
|
277 |
+
if ( 0 < $ticketing_calendar_id ) {
|
278 |
+
$this->save_calendar_id( $ticketing_calendar_id );
|
279 |
+
|
280 |
+
return $ticketing_calendar_id;
|
281 |
+
} else {
|
282 |
+
// If the calendar doesn't exist in the API, create a new one
|
283 |
+
$ticketing_calendar_id = $this->_create_calendar();
|
284 |
+
if ( 0 < $ticketing_calendar_id ) {
|
285 |
+
$this->save_calendar_id( $ticketing_calendar_id );
|
286 |
+
|
287 |
+
return $ticketing_calendar_id;
|
288 |
+
} else {
|
289 |
+
return 0;
|
290 |
+
}
|
291 |
+
}
|
292 |
+
}
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Find the existent calendar when the user is signing in
|
297 |
+
*/
|
298 |
+
protected function _find_user_calendar() {
|
299 |
+
$body = array(
|
300 |
+
'title' => get_bloginfo( 'name' ),
|
301 |
+
'url' => ai1ec_site_url()
|
302 |
+
);
|
303 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . 'calendars',
|
304 |
+
json_encode( $body )
|
305 |
+
);
|
306 |
+
if ( $this->is_response_success( $response ) ) {
|
307 |
+
if ( is_array( $response->body ) ) {
|
308 |
+
return $response->body[0]->id;
|
309 |
+
} else {
|
310 |
+
return $response->body->id;
|
311 |
+
}
|
312 |
+
} else {
|
313 |
+
return 0;
|
314 |
+
}
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Create a calendar when the user is signup
|
319 |
+
*/
|
320 |
+
protected function _create_calendar() {
|
321 |
+
$body = array(
|
322 |
+
'title' => get_bloginfo( 'name' ),
|
323 |
+
'url' => ai1ec_site_url(),
|
324 |
+
'timezone' => $this->_settings->get( 'timezone_string' )
|
325 |
+
);
|
326 |
+
$response = $this->request_api( 'POST', AI1EC_API_URL . 'calendars',
|
327 |
+
json_encode( $body )
|
328 |
+
);
|
329 |
+
if ( $this->is_response_success( $response ) ) {
|
330 |
+
return $response->body->id;
|
331 |
+
} else {
|
332 |
+
$this->log_error( $response, 'Created calendar' );
|
333 |
+
return 0;
|
334 |
+
}
|
335 |
+
}
|
336 |
|
337 |
/**
|
338 |
* Check if the current WP instance is signed into the API
|
339 |
*/
|
340 |
public function is_signed() {
|
341 |
+
return ( true === $this->get_ticketing_settings( 'enabled', false ) );
|
342 |
+
}
|
343 |
+
|
344 |
+
public function check_settings( $force = false ) {
|
345 |
+
$checked = get_transient( 'ai1ec_api_checked' );
|
346 |
+
|
347 |
+
if ( false === $checked || $force ) {
|
348 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
349 |
+
|
350 |
+
$failList = array();
|
351 |
+
foreach ( Ai1ec_Api_Features::FEATURES as $key => $value ) {
|
352 |
+
if ( empty( $value ) ) {
|
353 |
+
continue;
|
354 |
+
}
|
355 |
+
if ( ( ! $this->is_signed() || ! $this->has_subscription_active( $key ) ) && call_user_func( 'is'.'_'.'pl'.'ug'.'in'.'_'.'ac'.'ti'.'ve', $value ) ) {
|
356 |
+
$failList[] = $value;
|
357 |
+
}
|
358 |
+
}
|
359 |
+
|
360 |
+
if ( count( $failList ) > 0 ) {
|
361 |
+
call_user_func( 'de'.'act'.'iv'.'ate'.'_'.'pl'.'ug'.'ins', $failList );
|
362 |
+
|
363 |
+
$message = 'Your ' .
|
364 |
+
'All-in-One Event Calendar ' .
|
365 |
+
'has the ' .
|
366 |
+
'following ' .
|
367 |
+
'plugins ' .
|
368 |
+
'installed ' .
|
369 |
+
'but they are ' .
|
370 |
+
'disabled. '.
|
371 |
+
'To keep ' .
|
372 |
+
'them ' .
|
373 |
+
'enabled'.
|
374 |
+
', simply '.
|
375 |
+
'keep ' .
|
376 |
+
'your calendar ' .
|
377 |
+
'logged in ' .
|
378 |
+
'to your '.
|
379 |
+
'Timely account.' .
|
380 |
+
'<br /><br />';
|
381 |
+
|
382 |
+
foreach ( $failList as $failed ) {
|
383 |
+
$message .= '- ' . explode( '/', $failed )[0] . '<br />';
|
384 |
+
}
|
385 |
+
|
386 |
+
$this->show_error( $message );
|
387 |
+
}
|
388 |
+
|
389 |
+
set_transient( 'ai1ec_api_checked', true, 5 * 60 );
|
390 |
+
}
|
391 |
}
|
392 |
|
393 |
/**
|
394 |
* Get the current email account
|
395 |
*/
|
396 |
+
public function get_current_account() {
|
397 |
+
return $this->get_ticketing_settings( 'account', '' );
|
398 |
+
}
|
399 |
|
400 |
+
/**
|
401 |
+
* Get the current calendar id
|
402 |
+
*/
|
403 |
public function get_current_calendar() {
|
404 |
+
return $this->get_ticketing_settings( 'calendar_id', 0 );
|
405 |
}
|
406 |
|
407 |
/**
|
408 |
* Get the last message return by Signup or Signup process
|
409 |
*/
|
410 |
public function get_sign_message() {
|
411 |
+
return $this->get_ticketing_settings( 'message', '' );
|
412 |
+
}
|
413 |
+
|
414 |
+
/**
|
415 |
+
* Clear the last message return by Signup or Signup process
|
416 |
+
*/
|
417 |
+
public function clear_sign_message() {
|
418 |
+
$api_settings = $this->get_ticketing_settings();
|
419 |
+
$api_settings['message'] = '';
|
420 |
+
return update_option( self::WP_OPTION_KEY, $api_settings );
|
421 |
+
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* @return array List of subscriptions and limits
|
425 |
+
*/
|
426 |
+
protected function get_subscriptions( $force_refresh = false ) {
|
427 |
+
$subscriptions = get_transient( 'ai1ec_api_subscriptions' );
|
428 |
+
|
429 |
+
if ( false === $subscriptions || $force_refresh || ( defined( 'AI1EC_DEBUG' ) && AI1EC_DEBUG ) ) {
|
430 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . 'calendars/' . $this->_get_ticket_calendar() . '/subscriptions',
|
431 |
+
null,
|
432 |
+
true
|
433 |
+
);
|
434 |
+
if ( $this->is_response_success( $response ) ) {
|
435 |
+
$subscriptions = (array) $response->body;
|
436 |
+
} else {
|
437 |
+
$subscriptions = array();
|
438 |
+
}
|
439 |
+
|
440 |
+
// Save for 5 minutes
|
441 |
+
$minutes = 5;
|
442 |
+
set_transient( 'ai1ec_api_subscriptions', $subscriptions, $minutes * 60 );
|
443 |
+
}
|
444 |
+
|
445 |
+
return $subscriptions;
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
* Check if calendar should have a specific feature enabled
|
450 |
+
*/
|
451 |
+
public function has_subscription_active( $feature ) {
|
452 |
+
$subscriptions = $this->get_subscriptions();
|
453 |
+
|
454 |
+
return array_key_exists( $feature, $subscriptions );
|
455 |
+
}
|
456 |
+
|
457 |
+
/**
|
458 |
+
* Check if feature has reached its limit
|
459 |
+
*/
|
460 |
+
public function subscription_has_reached_limit( $feature ) {
|
461 |
+
$has_reached_limit = true;
|
462 |
+
|
463 |
+
$provided = $this->subscription_get_quantity_limit( $feature );
|
464 |
+
$used = $this->subscription_get_used_quantity( $feature );
|
465 |
+
|
466 |
+
if ( $provided - $used > 0 ) {
|
467 |
+
$has_reached_limit = false;
|
468 |
+
}
|
469 |
+
|
470 |
+
return $has_reached_limit;
|
471 |
+
}
|
472 |
+
|
473 |
+
/**
|
474 |
+
* Get feature quantity limit
|
475 |
+
*/
|
476 |
+
public function subscription_get_quantity_limit( $feature ) {
|
477 |
+
$provided = 0;
|
478 |
+
|
479 |
+
$subscriptions = $this->get_subscriptions();
|
480 |
+
|
481 |
+
if ( array_key_exists( $feature, $subscriptions ) ) {
|
482 |
+
$quantity = (array) $subscriptions[$feature];
|
483 |
+
|
484 |
+
$provided = $quantity['provided'];
|
485 |
+
}
|
486 |
+
|
487 |
+
return $provided;
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* Get feature used quantity
|
492 |
+
*/
|
493 |
+
public function subscription_get_used_quantity( $feature ) {
|
494 |
+
$used = 0;
|
495 |
+
|
496 |
+
$subscriptions = $this->get_subscriptions();
|
497 |
+
|
498 |
+
if ( array_key_exists( $feature, $subscriptions ) ) {
|
499 |
+
$quantity = (array) $subscriptions[$feature];
|
500 |
+
|
501 |
+
$used = $quantity['used'];
|
502 |
+
}
|
503 |
+
|
504 |
+
return $used;
|
505 |
+
}
|
506 |
+
|
507 |
+
/**
|
508 |
+
* Make the request to the API endpons
|
509 |
+
* @param $url The end part of the url to make the request.
|
510 |
+
* $body The body to send the message
|
511 |
+
* $method POST | GET | PUT, etc
|
512 |
+
* or send a customized message to be showed in case of error
|
513 |
+
* $decode_response_body TRUE (default) to decode the body response
|
514 |
+
* @return stdClass with the the fields:
|
515 |
+
* is_error TRUE or FALSE
|
516 |
+
* error in case of is_error be true
|
517 |
+
* body in case of is_error be false
|
518 |
+
*/
|
519 |
+
protected function request_api( $method, $url, $body = null, $decode_response_body = true, $custom_headers = null ) {
|
520 |
+
$request = array(
|
521 |
+
'method' => $method,
|
522 |
+
'headers' => $this->_get_headers( $custom_headers ),
|
523 |
+
'timeout' => self::DEFAULT_TIMEOUT
|
524 |
+
);
|
525 |
+
if ( ! is_null( $body ) ) {
|
526 |
+
$request[ 'body' ] = $body;
|
527 |
+
}
|
528 |
+
$response = wp_remote_request( $url, $request );
|
529 |
+
$result = new stdClass();
|
530 |
+
$result->url = $url;
|
531 |
+
$result->raw = $response;
|
532 |
+
if ( is_wp_error( $response ) ) {
|
533 |
+
$result->is_error = true;
|
534 |
+
$result->error = $response->get_error_message();
|
535 |
+
} else {
|
536 |
+
$result->response_code = wp_remote_retrieve_response_code( $response );
|
537 |
+
if ( 200 === $result->response_code ) {
|
538 |
+
if ( true === $decode_response_body ) {
|
539 |
+
$result->body = json_decode( $response['body'] );
|
540 |
+
if ( false === is_null( $result->body ) ) {
|
541 |
+
$result->is_error = false;
|
542 |
+
} else {
|
543 |
+
$result->is_error = true;
|
544 |
+
$result->error = __( 'Error decoding the response', AI1EC_PLUGIN_NAME );
|
545 |
+
unset( $result->body );
|
546 |
+
}
|
547 |
+
} else {
|
548 |
+
$result->is_error = false;
|
549 |
+
$result->body = $response['body'];
|
550 |
+
}
|
551 |
+
} else {
|
552 |
+
$result->is_error = true;
|
553 |
+
$result->error = wp_remote_retrieve_response_message( $response );
|
554 |
+
}
|
555 |
+
}
|
556 |
+
return $result;
|
557 |
+
}
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Make a post request to the api
|
561 |
+
* @param rest_endpoint Partial URL that can include {calendar_id} that will be replaced by the current calendar signed
|
562 |
+
*/
|
563 |
+
public function call_api( $method, $endpoint, $body = null, $decode_response_body = true, $custom_headers = null ) {
|
564 |
+
$calendar_id = $this->_get_ticket_calendar();
|
565 |
+
if ( 0 >= $calendar_id ) {
|
566 |
+
return false;
|
567 |
+
}
|
568 |
+
$url = AI1EC_API_URL . str_replace( '{calendar_id}', $calendar_id, $endpoint );
|
569 |
+
$body = json_encode( $body );
|
570 |
+
return $this->request_api( $method, $url, $body, $decode_response_body, $custom_headers );
|
571 |
+
}
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Save an error notification to be showed to the user on WP header of the page
|
575 |
+
* @param $response The response got from request_api method.
|
576 |
+
* $custom_error_message The custom message to show before the detailed message
|
577 |
+
* @return full error message
|
578 |
+
*/
|
579 |
+
protected function save_error_notification( $response, $custom_error_response ) {
|
580 |
+
$error_message = $this->_transform_error_message(
|
581 |
+
$custom_error_response,
|
582 |
+
$response->raw,
|
583 |
+
$response->url,
|
584 |
+
true
|
585 |
+
);
|
586 |
+
$response->error_message = $error_message;
|
587 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
588 |
+
$notification->store( $error_message, 'error', 0, array( Ai1ec_Notification_Admin::RCPT_ADMIN ), false );
|
589 |
+
error_log( $custom_error_response . ': ' . $error_message . ' - raw error: ' . print_r( $response->raw, true ) );
|
590 |
+
return $error_message;
|
591 |
+
}
|
592 |
+
|
593 |
+
/**
|
594 |
+
* Save an error notification to be showed to the user on WP header of the page
|
595 |
+
* @param $response The response got from request_api method.
|
596 |
+
* $custom_error_message The custom message to show before the detailed message
|
597 |
+
* @return full error message
|
598 |
+
*/
|
599 |
+
protected function log_error( $response, $custom_error_response ) {
|
600 |
+
$error_message = $this->_transform_error_message(
|
601 |
+
$custom_error_response,
|
602 |
+
$response->raw,
|
603 |
+
$response->url,
|
604 |
+
true
|
605 |
+
);
|
606 |
+
error_log( $custom_error_response . ': ' . $error_message . ' - raw error: ' . print_r( $response->raw, true ) );
|
607 |
+
return $error_message;
|
608 |
+
}
|
609 |
+
|
610 |
+
protected function show_error( $error_message ) {
|
611 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
612 |
+
$notification->store( $error_message, 'error', 0, array( Ai1ec_Notification_Admin::RCPT_ADMIN ), false );
|
613 |
+
error_log( $error_message);
|
614 |
+
return $error_message;
|
615 |
+
}
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Useful method to check if the response of request_api is a successful message
|
619 |
+
*/
|
620 |
+
public function is_response_success( $response ) {
|
621 |
+
return $response != null &&
|
622 |
+
( !isset( $response->is_error ) || ( isset( $response->is_error ) && false === $response->is_error ) );
|
623 |
+
}
|
624 |
|
625 |
}
|
app/model/api/api-features.php
CHANGED
@@ -1,22 +1,45 @@
|
|
1 |
<?php
|
2 |
class Ai1ec_Api_Features {
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
}
|
1 |
<?php
|
2 |
class Ai1ec_Api_Features {
|
3 |
+
|
4 |
+
const CODE_API_ACCESS = 'api-access';
|
5 |
+
const CODE_TICKETING = 'ticketing';
|
6 |
+
const CODE_TWITTER = 'twitter';
|
7 |
+
const CODE_FRONTEND_SUBMISSIONS = 'frontend-submissions';
|
8 |
+
const CODE_CSV_IMPORT = 'csv-import';
|
9 |
+
const CODE_SUPER_WIDGET = 'super-widget';
|
10 |
+
const CODE_EXTENDED_VIEWS = 'extended-views';
|
11 |
+
const CODE_BIG_FILTERING = 'big-filtering';
|
12 |
+
const CODE_CUSTOM_FILTERS = 'custom-filter-groups';
|
13 |
+
const CODE_DISCOVER_EVENTS = 'discover-events';
|
14 |
+
const CODE_EVENT_PROMOTE = 'event-promote';
|
15 |
+
const CODE_FACEBOOK_INTEGRATION = 'facebook-integration';
|
16 |
+
const CODE_FEATURED_EVENTS = 'featured-events';
|
17 |
+
const CODE_MAILCHIMP = 'mailchimp';
|
18 |
+
const CODE_PHRASE_OVERRIDE = 'phrase-override';
|
19 |
+
const CODE_POPOVERS = 'popovers';
|
20 |
+
const CODE_SAVE_AND_SHARE = 'save-and-share';
|
21 |
+
const CODE_VENUES = 'venues';
|
22 |
+
const CODE_IMPORT_FEEDS = 'import-feeds';
|
23 |
+
|
24 |
+
const FEATURES = array(
|
25 |
+
self::CODE_API_ACCESS => '',
|
26 |
+
self::CODE_TICKETING => '',
|
27 |
+
self::CODE_TWITTER => 'all-in-one-event-calendar-twitter-integration/all-in-one-event-calendar-twitter-integration.php',
|
28 |
+
self::CODE_FRONTEND_SUBMISSIONS => 'all-in-one-event-calendar-frontend-submissions/all-in-one-event-calendar-frontend-submissions.php',
|
29 |
+
self::CODE_CSV_IMPORT => 'all-in-one-event-calendar-csv-feed/all-in-one-event-calendar-csv-feed.php',
|
30 |
+
self::CODE_SUPER_WIDGET => 'all-in-one-event-calendar-super-widget/all-in-one-event-calendar-super-widget.php',
|
31 |
+
self::CODE_EXTENDED_VIEWS => 'all-in-one-event-calendar-extended-views/all-in-one-event-calendar-extended-views.php',
|
32 |
+
self::CODE_BIG_FILTERING => 'all-in-one-event-calendar-big-filtering/all-in-one-event-calendar-big-filtering.php',
|
33 |
+
self::CODE_CUSTOM_FILTERS => 'all-in-one-event-calendar-custom-filter-groups/all-in-one-event-calendar-custom-filter-groups.php',
|
34 |
+
self::CODE_DISCOVER_EVENTS => '',
|
35 |
+
self::CODE_EVENT_PROMOTE => 'all-in-one-event-calendar-event-promote/all-in-one-event-calendar-event-promote.php',
|
36 |
+
self::CODE_FACEBOOK_INTEGRATION => 'all-in-one-event-calendar-facebook-integration/all-in-one-event-calendar-facebook-integration.php',
|
37 |
+
self::CODE_FEATURED_EVENTS => 'all-in-one-event-calendar-featured-events/all-in-one-event-calendar-featured-events.php',
|
38 |
+
self::CODE_MAILCHIMP => 'all-in-one-event-calendar-mailchimp/all-in-one-event-calendar-mailchimp.php',
|
39 |
+
self::CODE_PHRASE_OVERRIDE => 'all-in-one-event-calendar-phrase-override/all-in-one-event-calendar-phrase-override.php',
|
40 |
+
self::CODE_POPOVERS => 'all-in-one-event-calendar-popovers/all-in-one-event-calendar-popovers.php',
|
41 |
+
self::CODE_SAVE_AND_SHARE => 'all-in-one-event-calendar-save-and-share/all-in-one-event-calendar-save-and-share.php',
|
42 |
+
self::CODE_VENUES => 'all-in-one-event-calendar-venue/all-in-one-event-calendar-venue.php',
|
43 |
+
self::CODE_IMPORT_FEEDS => '',
|
44 |
+
);
|
45 |
}
|
app/model/api/api-feeds.php
CHANGED
@@ -10,312 +10,312 @@
|
|
10 |
*/
|
11 |
class Ai1ec_Api_Feeds extends Ai1ec_Api_Abstract {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
}
|
10 |
*/
|
11 |
class Ai1ec_Api_Feeds extends Ai1ec_Api_Abstract {
|
12 |
|
13 |
+
// Feed status
|
14 |
+
// c = Feed not migrated yet to API
|
15 |
+
// a = Feed migrated to API (all events)
|
16 |
+
// b = Feed migrated to API (individual events were selected)
|
17 |
+
public static $FEED_NOT_MIGRATED_CODE = 'c';
|
18 |
+
public static $FEED_API_ALL_EVENTS_CODE = 'a';
|
19 |
+
public static $FEED_API_SOME_EVENTS_CODE = 'b';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Post construction routine.
|
23 |
+
*
|
24 |
+
* Override this method to perform post-construction tasks.
|
25 |
+
*
|
26 |
+
* @return void Return from this method is ignored.
|
27 |
+
*/
|
28 |
+
protected function _initialize() {
|
29 |
+
parent::_initialize();
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Get static var (for PHP 5.2 compatibility)
|
34 |
+
*
|
35 |
+
* @param String $var
|
36 |
+
*/
|
37 |
+
public function getStaticVar($var) {
|
38 |
+
return self::$$var;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Getting a suggested events list.
|
43 |
+
* @return stClass Response using the following format:
|
44 |
+
* [total] => 10
|
45 |
+
* [per_page] => 8
|
46 |
+
* [current_page] => 1
|
47 |
+
* [last_page] => 2
|
48 |
+
* [next_page_url] =>
|
49 |
+
* [prev_page_url] =>
|
50 |
+
* [from] => 1
|
51 |
+
* [to] => 8
|
52 |
+
* [data] => Array list of suggested events
|
53 |
+
*/
|
54 |
+
public function get_suggested_events() {
|
55 |
+
$calendar_id = $this->_get_ticket_calendar();
|
56 |
+
if ( 0 >= $calendar_id ) {
|
57 |
+
throw new Exception( 'Calendar ID not found' );
|
58 |
+
}
|
59 |
+
|
60 |
+
$body = null;
|
61 |
+
if (
|
62 |
+
isset( $_POST[ 'lat' ] ) &&
|
63 |
+
isset( $_POST[ 'lng' ] ) &&
|
64 |
+
isset( $_POST[ 'radius' ] )
|
65 |
+
) {
|
66 |
+
$body = array(
|
67 |
+
'lat' => $_POST[ 'lat' ],
|
68 |
+
'lng' => $_POST[ 'lng' ],
|
69 |
+
'radius' => $_POST[ 'radius' ]
|
70 |
+
);
|
71 |
+
}
|
72 |
+
|
73 |
+
$page = isset( $_POST[ 'page' ] ) ? $_POST[ 'page' ] : 1;
|
74 |
+
$max = isset( $_POST[ 'max' ] ) ? $_POST[ 'max' ] : 8;
|
75 |
+
$term = isset( $_POST[ 'term' ] ) && $_POST[ 'term' ]
|
76 |
+
? urlencode( $_POST[ 'term' ] )
|
77 |
+
: '*';
|
78 |
+
$location = isset( $_POST[ 'location' ] ) && $_POST[ 'location' ]
|
79 |
+
? '&location=' . urlencode( $_POST[ 'location' ] )
|
80 |
+
: '';
|
81 |
+
|
82 |
+
$url = AI1EC_API_URL .
|
83 |
+
"calendars/$calendar_id/discover/events?page=$page&max=$max&term=$term" .
|
84 |
+
$location;
|
85 |
+
|
86 |
+
$response = $this->request_api( 'GET', $url,
|
87 |
+
null !== $body ? json_encode( $body ) : null,
|
88 |
+
true //decode body response
|
89 |
+
);
|
90 |
+
|
91 |
+
if ( $this->is_response_success( $response ) ) {
|
92 |
+
return $response->body;
|
93 |
+
} else {
|
94 |
+
$this->save_error_notification(
|
95 |
+
$response,
|
96 |
+
__( 'We were unable to get the Suggested Events from Time.ly Network', AI1EC_PLUGIN_NAME )
|
97 |
+
);
|
98 |
+
throw new Exception( 'We were unable to get the Suggested Events from Time.ly Network' );
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Call the API to Process and Import the Feed
|
104 |
+
*/
|
105 |
+
public function import_feed( $entry ) {
|
106 |
+
$calendar_id = $this->_get_ticket_calendar();
|
107 |
+
if ( 0 >= $calendar_id ) {
|
108 |
+
throw new Exception( 'Calendar ID not found' );
|
109 |
+
}
|
110 |
+
$response = $this->request_api( 'POST', AI1EC_API_URL . 'calendars/' . $calendar_id . '/feeds/import',
|
111 |
+
json_encode( array(
|
112 |
+
'url' => $entry['feed_url'],
|
113 |
+
'categories' => $entry['feed_category'],
|
114 |
+
'tags' => $entry['feed_tags'],
|
115 |
+
'allow_comments' => $entry['comments_enabled'],
|
116 |
+
'show_maps' => $entry['map_display_enabled'],
|
117 |
+
'import_any_tag_and_categories' => $entry['keep_tags_categories'],
|
118 |
+
'preserve_imported_events' => $entry['keep_old_events'],
|
119 |
+
'assign_default_utc' => $entry['import_timezone']
|
120 |
+
) )
|
121 |
+
);
|
122 |
+
|
123 |
+
if ( $this->is_response_success( $response ) ) {
|
124 |
+
// Refresh list of subscriptions and limits
|
125 |
+
$this->get_subscriptions( true );
|
126 |
+
|
127 |
+
return $response->body;
|
128 |
+
} else {
|
129 |
+
$this->save_error_notification(
|
130 |
+
$response,
|
131 |
+
__( 'We were unable to import feed', AI1EC_PLUGIN_NAME )
|
132 |
+
);
|
133 |
+
throw new Exception( $this->get_api_error_msg( $response->raw ) );
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Call the API to get the feed
|
139 |
+
*/
|
140 |
+
public function get_feed( $feed_id ) {
|
141 |
+
$calendar_id = $this->_get_ticket_calendar();
|
142 |
+
if ( 0 >= $calendar_id ) {
|
143 |
+
throw new Exception( 'Calendar ID not found' );
|
144 |
+
}
|
145 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . 'calendars/' . $calendar_id . '/feeds/get/' . $feed_id,
|
146 |
+
json_encode( array( "max" => "9999" ) )
|
147 |
+
);
|
148 |
+
|
149 |
+
if ( $this->is_response_success( $response ) ) {
|
150 |
+
return $response->body;
|
151 |
+
} else {
|
152 |
+
$this->save_error_notification(
|
153 |
+
$response,
|
154 |
+
__( 'We were unable to get feed data', AI1EC_PLUGIN_NAME )
|
155 |
+
);
|
156 |
+
throw new Exception( $this->get_api_error_msg( $response->raw ) );
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Call the API to get list of feed subscriptions
|
162 |
+
*/
|
163 |
+
public function get_feed_subscriptions( $force_refresh = false ) {
|
164 |
+
$feeds_subscriptions = get_transient( 'ai1ec_api_feeds_subscriptions' );
|
165 |
+
|
166 |
+
if ( $force_refresh || false === $feeds_subscriptions ) {
|
167 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . 'calendars/' . $this->_get_ticket_calendar() . '/feeds/list',
|
168 |
+
null,
|
169 |
+
true
|
170 |
+
);
|
171 |
+
|
172 |
+
if ( $this->is_response_success( $response ) ) {
|
173 |
+
$feeds_subscriptions = (array) $response->body;
|
174 |
+
} else {
|
175 |
+
$feeds_subscriptions = array();
|
176 |
+
}
|
177 |
+
|
178 |
+
// Save for 5 minutes
|
179 |
+
$minutes = 5;
|
180 |
+
set_transient( 'ai1ec_api_feeds_subscriptions', $feeds_subscriptions, $minutes * 60 );
|
181 |
+
}
|
182 |
+
|
183 |
+
return $feeds_subscriptions;
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Sync feed subscriptions
|
188 |
+
*/
|
189 |
+
public function get_and_sync_feed_subscriptions() {
|
190 |
+
$feeds_subscriptions = $this->get_feed_subscriptions();
|
191 |
+
|
192 |
+
$db = $this->_registry->get( 'dbi.dbi' );
|
193 |
+
$table_name = $db->get_table_name( 'ai1ec_event_feeds' );
|
194 |
+
|
195 |
+
// Select all feeds
|
196 |
+
$rows = $db->select(
|
197 |
+
$table_name,
|
198 |
+
array(
|
199 |
+
'feed_id',
|
200 |
+
'feed_url',
|
201 |
+
'feed_name',
|
202 |
+
'feed_category',
|
203 |
+
'feed_tags',
|
204 |
+
'comments_enabled',
|
205 |
+
'map_display_enabled',
|
206 |
+
'keep_tags_categories',
|
207 |
+
'keep_old_events',
|
208 |
+
'import_timezone'
|
209 |
+
)
|
210 |
+
);
|
211 |
+
|
212 |
+
// Iterate over API response
|
213 |
+
foreach( $feeds_subscriptions as $api_feed ) {
|
214 |
+
$found = false;
|
215 |
+
|
216 |
+
foreach ( $rows as $row ) {
|
217 |
+
// Check if URL is the same
|
218 |
+
if ( trim( $row->feed_url ) === trim( $api_feed->url ) ) {
|
219 |
+
$found = true;
|
220 |
+
|
221 |
+
// Update feed
|
222 |
+
$db->update(
|
223 |
+
$table_name,
|
224 |
+
array(
|
225 |
+
'comments_enabled' => $api_feed->allow_comments,
|
226 |
+
'map_display_enabled' => $api_feed->show_maps,
|
227 |
+
'keep_tags_categories' => $api_feed->import_any_tag_and_categories,
|
228 |
+
'keep_old_events' => $api_feed->preserve_imported_events,
|
229 |
+
'import_timezone' => $api_feed->assign_default_utc,
|
230 |
+
'feed_name' => $api_feed->feed_id
|
231 |
+
),
|
232 |
+
array(
|
233 |
+
'feed_id' => $row->feed_id
|
234 |
+
)
|
235 |
+
);
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
// Not found in local database.. Insert
|
240 |
+
if ( ! $found ) {
|
241 |
+
$entry = array(
|
242 |
+
'feed_url' => $api_feed->url,
|
243 |
+
'feed_name' => $api_feed->feed_id,
|
244 |
+
'feed_category' => $api_feed->categories,
|
245 |
+
'feed_tags' => $api_feed->tags,
|
246 |
+
'comments_enabled' => $api_feed->allow_comments,
|
247 |
+
'map_display_enabled' => $api_feed->show_maps,
|
248 |
+
'keep_tags_categories' => $api_feed->import_any_tag_and_categories,
|
249 |
+
'keep_old_events' => $api_feed->preserve_imported_events,
|
250 |
+
'import_timezone' => $api_feed->assign_default_utc
|
251 |
+
);
|
252 |
+
$format = array( '%s', '%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d' );
|
253 |
+
$db->insert(
|
254 |
+
$table_name,
|
255 |
+
$entry,
|
256 |
+
$format
|
257 |
+
);
|
258 |
+
}
|
259 |
+
}
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Call the API to subscribe feed
|
264 |
+
*/
|
265 |
+
public function subscribe_feed( $feed_id, $feed_event_uid = '' ) {
|
266 |
+
$calendar_id = $this->_get_ticket_calendar();
|
267 |
+
if ( 0 >= $calendar_id ) {
|
268 |
+
throw new Exception( 'Calendar ID not found' );
|
269 |
+
}
|
270 |
+
|
271 |
+
$response = $this->request_api( 'POST', AI1EC_API_URL . 'calendars/' . $calendar_id . '/feeds/subscribe',
|
272 |
+
json_encode( array(
|
273 |
+
'feed_id' => $feed_id,
|
274 |
+
'feed_event_uid' => $feed_event_uid
|
275 |
+
) )
|
276 |
+
);
|
277 |
+
|
278 |
+
// Refresh list of subscriptions and limits
|
279 |
+
$this->get_subscriptions( true );
|
280 |
+
|
281 |
+
if ( $this->is_response_success( $response ) ) {
|
282 |
+
return $response->body;
|
283 |
+
} else {
|
284 |
+
$this->save_error_notification(
|
285 |
+
$response,
|
286 |
+
__( 'We were unable to subscribe feed', AI1EC_PLUGIN_NAME )
|
287 |
+
);
|
288 |
+
throw new Exception( $this->get_api_error_msg( $response->raw ) );
|
289 |
+
}
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Call the API to unsubscribe feed
|
294 |
+
*/
|
295 |
+
public function unsubscribe_feed( $feed_id, $feed_event_uid = '' ) {
|
296 |
+
$calendar_id = $this->_get_ticket_calendar();
|
297 |
+
if ( 0 >= $calendar_id ) {
|
298 |
+
throw new Exception( 'Calendar ID not found' );
|
299 |
+
}
|
300 |
+
|
301 |
+
$response = $this->request_api( 'POST', AI1EC_API_URL . 'calendars/' . $calendar_id . '/feeds/unsubscribe',
|
302 |
+
json_encode( array(
|
303 |
+
'feed_id' => $feed_id,
|
304 |
+
'feed_event_uid' => $feed_event_uid
|
305 |
+
) )
|
306 |
+
);
|
307 |
+
|
308 |
+
// Refresh list of subscriptions and limits
|
309 |
+
$this->get_subscriptions( true );
|
310 |
+
|
311 |
+
if ( $this->is_response_success( $response ) ) {
|
312 |
+
return $response->body;
|
313 |
+
} else {
|
314 |
+
$this->save_error_notification(
|
315 |
+
$response,
|
316 |
+
__( 'We were unable to unsubscribe feed', AI1EC_PLUGIN_NAME )
|
317 |
+
);
|
318 |
+
throw new Exception( $this->get_api_error_msg( $response->raw ) );
|
319 |
+
}
|
320 |
+
}
|
321 |
}
|
app/model/api/api-registration.php
CHANGED
@@ -10,243 +10,243 @@
|
|
10 |
*/
|
11 |
class Ai1ec_Api_Registration extends Ai1ec_Api_Abstract {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
|
252 |
}
|
10 |
*/
|
11 |
class Ai1ec_Api_Registration extends Ai1ec_Api_Abstract {
|
12 |
|
13 |
+
/**
|
14 |
+
* Post construction routine.
|
15 |
+
*
|
16 |
+
* Override this method to perform post-construction tasks.
|
17 |
+
*
|
18 |
+
* @return void Return from this method is ignored.
|
19 |
+
*/
|
20 |
+
protected function _initialize() {
|
21 |
+
parent::_initialize();
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @return object Response body in JSON.
|
26 |
+
*/
|
27 |
+
public function signin() {
|
28 |
+
$body['email'] = $_POST['ai1ec_email'];
|
29 |
+
$body['password'] = $_POST['ai1ec_password'];
|
30 |
+
$body['calendar_type'] = $_POST['ai1ec_calendar_type'];
|
31 |
+
$response = $this->request_api( 'POST', AI1EC_API_URL . 'auth/authenticate', json_encode( $body ), true, array( 'Authorization' => null ) );
|
32 |
+
if ( $this->is_response_success( $response ) ) {
|
33 |
+
$response_body = (array) $response->body;
|
34 |
+
// Save calendar ID as 0 first, otherwise the auth data won't be saved in the database before creating/finding the calendar
|
35 |
+
$this->save_ticketing_settings( $response_body['message'], true, $response_body['auth_token'], 0, $body['email'] );
|
36 |
+
// Now save the calendar ID
|
37 |
+
$this->save_calendar_id( $this->_get_ticket_calendar() );
|
38 |
+
$this->has_payment_settings();
|
39 |
+
$this->get_subscriptions( true );
|
40 |
+
$this->sync_api_settings();
|
41 |
+
} else {
|
42 |
+
$error_message = $this->save_error_notification( $response, __( 'We were unable to Sign you In for Time.ly Network', AI1EC_PLUGIN_NAME ) );
|
43 |
+
$this->save_ticketing_settings( $error_message, false, '', 0, null );
|
44 |
+
}
|
45 |
+
return $response;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @return object Response body in JSON.
|
50 |
+
*/
|
51 |
+
public function signup() {
|
52 |
+
$body['name'] = $_POST['ai1ec_name'];
|
53 |
+
$body['email'] = $_POST['ai1ec_email'];
|
54 |
+
$body['password'] = $_POST['ai1ec_password'];
|
55 |
+
$body['password_confirmation'] = $_POST['ai1ec_password_confirmation'];
|
56 |
+
$body['phone'] = $_POST['ai1ec_phone'];
|
57 |
+
$body['calendar_type'] = $_POST['ai1ec_calendar_type'];
|
58 |
+
$body['terms'] = $_POST['ai1ec_terms'];
|
59 |
+
$response = $this->request_api( 'POST', AI1EC_API_URL . 'auth/register', json_encode( $body ), true );
|
60 |
+
if ( $this->is_response_success( $response ) ) {
|
61 |
+
$response_body = (array) $response->body;
|
62 |
+
// Save calendar ID as 0 first, otherwise the auth data won't be saved in the database before creating the calendar
|
63 |
+
$this->save_ticketing_settings( $response_body['Registration'], true, $response_body['auth_token'] , 0, $body['email'] );
|
64 |
+
// Now save the calendar ID
|
65 |
+
$this->save_calendar_id( $this->_create_calendar() );
|
66 |
+
$this->has_payment_settings();
|
67 |
+
$this->get_subscriptions( true );
|
68 |
+
$this->sync_api_settings();
|
69 |
+
} else {
|
70 |
+
$error_message = $this->save_error_notification( $response, __( 'We were unable to Sign you Up for Time.ly Network', AI1EC_PLUGIN_NAME ) );
|
71 |
+
$this->save_ticketing_settings( $error_message, false, '', 0, null );
|
72 |
+
}
|
73 |
+
return $response;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* @return object Response body in JSON.
|
78 |
+
*/
|
79 |
+
protected function availability() {
|
80 |
+
$api_features = get_transient( 'ai1ec_api_features' );
|
81 |
+
|
82 |
+
if ( false === $api_features || ( defined( 'AI1EC_DEBUG' ) && AI1EC_DEBUG ) ) {
|
83 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . 'feature/availability', null, true );
|
84 |
+
|
85 |
+
if ( $this->is_response_success( $response ) ) {
|
86 |
+
$api_features = (array) $response->body;
|
87 |
+
} else {
|
88 |
+
$api_features = array();
|
89 |
+
}
|
90 |
+
|
91 |
+
// Save for 5 minutes
|
92 |
+
$minutes = 5;
|
93 |
+
set_transient( 'ai1ec_api_features', $api_features, $minutes * 60 );
|
94 |
+
}
|
95 |
+
|
96 |
+
return $api_features;
|
97 |
+
}
|
98 |
+
|
99 |
+
protected function is_feature_available( $feature_code ) {
|
100 |
+
$availability = $this->availability();
|
101 |
+
|
102 |
+
if ( ! is_null( $availability ) ) {
|
103 |
+
foreach ( $availability as $value ) {
|
104 |
+
if ( isset( $value->code ) && $feature_code === $value->code
|
105 |
+
&& isset( $value->available ) && true === $value->available ) {
|
106 |
+
return true;
|
107 |
+
}
|
108 |
+
}
|
109 |
+
}
|
110 |
+
return false;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* @return object Response body in JSON.
|
115 |
+
*/
|
116 |
+
protected function settings() {
|
117 |
+
$calendar_settings = get_transient( 'ai1ec_calendar_settings' );
|
118 |
+
|
119 |
+
if ( false === $calendar_settings || ( defined( 'AI1EC_DEBUG' ) && AI1EC_DEBUG ) ) {
|
120 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . 'calendars/' . $this->_get_ticket_calendar() . '/settings', null, true );
|
121 |
+
|
122 |
+
if ( $this->is_response_success( $response ) ) {
|
123 |
+
$calendar_settings = (array) $response->body;
|
124 |
+
} else {
|
125 |
+
$calendar_settings = array();
|
126 |
+
}
|
127 |
+
|
128 |
+
// Save for 5 minutes
|
129 |
+
$minutes = 5;
|
130 |
+
set_transient( 'ai1ec_calendar_settings', $calendar_settings, $minutes * 60 );
|
131 |
+
}
|
132 |
+
|
133 |
+
return $calendar_settings;
|
134 |
+
}
|
135 |
+
|
136 |
+
public function is_api_sign_up_available() {
|
137 |
+
return $this->is_feature_available( Ai1ec_Api_Features::CODE_API_ACCESS );
|
138 |
+
}
|
139 |
+
|
140 |
+
public function is_ticket_available() {
|
141 |
+
return $this->is_feature_available( Ai1ec_Api_Features::CODE_TICKETING );
|
142 |
+
}
|
143 |
+
|
144 |
+
public function is_ticket_enabled() {
|
145 |
+
return $this->has_subscription_active( Ai1ec_Api_Features::CODE_TICKETING );
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Clean the ticketing settings on WP database only
|
150 |
+
*/
|
151 |
+
public function signout() {
|
152 |
+
$calendar_id = $this->_get_ticket_calendar( false );
|
153 |
+
if ( 0 >= $calendar_id ) {
|
154 |
+
$this->clear_ticketing_settings();
|
155 |
+
return false;
|
156 |
+
}
|
157 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . "calendars/$calendar_id/signout", null, true );
|
158 |
+
// Consider "Unauthorized" status (401) a valid response
|
159 |
+
if ( $this->is_response_success( $response ) || 401 === wp_remote_retrieve_response_code( $response->raw ) ) {
|
160 |
+
$this->clear_ticketing_settings();
|
161 |
+
return array( 'message' => '' );
|
162 |
+
} else {
|
163 |
+
$error_message = $this->save_error_notification( $response, __( 'We were unable to Sign you Out of Time.ly Network', AI1EC_PLUGIN_NAME ) );
|
164 |
+
return array( 'message' => $error_message );
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* @return object Response body from API.
|
170 |
+
*/
|
171 |
+
public function save_payment_preferences() {
|
172 |
+
$calendar_id = $this->_get_ticket_calendar();
|
173 |
+
if ( 0 >= $calendar_id ) {
|
174 |
+
return false;
|
175 |
+
}
|
176 |
+
$settings = array(
|
177 |
+
'payment_method' => $_POST['ai1ec_payment_method'],
|
178 |
+
'paypal_email' => $_POST['ai1ec_paypal_email'],
|
179 |
+
'first_name' => $_POST['ai1ec_first_name'],
|
180 |
+
'last_name' => $_POST['ai1ec_last_name'],
|
181 |
+
'currency' => $_POST['ai1ec_currency']
|
182 |
+
);
|
183 |
+
$custom_headers['content-type'] = 'application/x-www-form-urlencoded';
|
184 |
+
$response = $this->request_api( 'PUT', AI1EC_API_URL . 'calendars/' . $calendar_id . '/payment',
|
185 |
+
$settings,
|
186 |
+
true, //decode response body
|
187 |
+
$custom_headers
|
188 |
+
);
|
189 |
+
if ( $this->is_response_success( $response ) ) {
|
190 |
+
$this->save_payment_settings( $settings );
|
191 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
192 |
+
$notification->store(
|
193 |
+
__( 'Payment preferences were saved.', AI1EC_PLUGIN_NAME ),
|
194 |
+
'updated',
|
195 |
+
0,
|
196 |
+
array( Ai1ec_Notification_Admin::RCPT_ADMIN ),
|
197 |
+
false
|
198 |
+
);
|
199 |
+
return $response->body;
|
200 |
+
} else {
|
201 |
+
$this->save_error_notification( $response,
|
202 |
+
__( 'Payment preferences were not saved.', AI1EC_PLUGIN_NAME )
|
203 |
+
);
|
204 |
+
return false;
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
public function _order_comparator( $order1, $order2 ) {
|
209 |
+
return strcmp( $order1->created_at, $order2->created_at ) * -1;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* @return object Response body in JSON.
|
214 |
+
*/
|
215 |
+
public function get_purchases() {
|
216 |
+
$response = $this->request_api( 'GET', AI1EC_API_URL . 'calendars/' . $this->_get_ticket_calendar() . '/sales',
|
217 |
+
null, //body
|
218 |
+
true //decode response body
|
219 |
+
);
|
220 |
+
if ( $this->is_response_success( $response ) ) {
|
221 |
+
$result = $response->body;
|
222 |
+
if ( isset( $result->orders ) ) {
|
223 |
+
usort( $result->orders, array( "Ai1ec_Api_Registration", "_order_comparator" ) );
|
224 |
+
return $result->orders;
|
225 |
+
} else {
|
226 |
+
return array();
|
227 |
+
}
|
228 |
+
} else {
|
229 |
+
$this->save_error_notification( $response,
|
230 |
+
__( 'We were unable to get the Sales information from Time.ly Network', AI1EC_PLUGIN_NAME )
|
231 |
+
);
|
232 |
+
return array();
|
233 |
+
}
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Sync settings from API after signing in
|
238 |
+
*/
|
239 |
+
public function sync_api_settings() {
|
240 |
+
// Sync feeds subscriptions
|
241 |
+
try {
|
242 |
+
$api_feed = $this->_registry->get( 'model.api.api-feeds' );
|
243 |
+
$api_feed->get_and_sync_feed_subscriptions();
|
244 |
+
} catch ( Exception $e ) {
|
245 |
+
$error_message = 'Some feeds were not imported to Time.ly Network. Error: ' . $e->getMessage();
|
246 |
+
|
247 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
248 |
+
$notification->store( $error_message, 'error', 0, array( Ai1ec_Notification_Admin::RCPT_ADMIN ), false );
|
249 |
+
}
|
250 |
+
}
|
251 |
|
252 |
}
|
app/model/api/api-settings.php
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
<?php
|
2 |
class Ai1ec_Api_Settings {
|
3 |
-
|
4 |
}
|
1 |
<?php
|
2 |
class Ai1ec_Api_Settings {
|
3 |
+
const FACEBOOK_API_KEY = 'facebook_api_key';
|
4 |
}
|
app/model/api/api-ticketing.php
CHANGED
@@ -10,648 +10,648 @@
|
|
10 |
*/
|
11 |
class Ai1ec_Api_Ticketing extends Ai1ec_Api_Abstract {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
451 |
}
|
452 |
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
return (object) array( 'data' => array(), 'error' => $error_message );
|
473 |
-
}
|
474 |
-
}
|
475 |
-
|
476 |
-
/**
|
477 |
-
* @return string JSON.
|
478 |
-
*/
|
479 |
-
public function get_ticket_types( $post_id, $get_canceled = true ) {
|
480 |
-
$api_event_id = $this->get_api_event_id( $post_id );
|
481 |
-
if ( ! $api_event_id ) {
|
482 |
-
return json_encode( array( 'data' => array() ) );
|
483 |
-
}
|
484 |
-
$response = $this->request_api( 'GET', $this->get_api_event_url( $post_id ) . 'events/' . $api_event_id . '/ticket_types',
|
485 |
-
array( 'get_canceled' => ( true === $get_canceled ? 1 : 0 ) )
|
486 |
-
);
|
487 |
-
if ( $this->is_response_success( $response ) ) {
|
488 |
-
if ( isset( $response->body->ticket_types ) ) {
|
489 |
-
foreach ( $response->body->ticket_types as $ticket_api ) {
|
490 |
-
$this->_unparse_tickets_type_from_api_structure( $ticket_api );
|
491 |
-
}
|
492 |
-
return json_encode( array( 'data' => $response->body->ticket_types ) );
|
493 |
-
} else {
|
494 |
-
return json_encode( array( 'data' => array() ) );
|
495 |
-
}
|
496 |
-
} else {
|
497 |
-
$error_message = $this->_transform_error_message(
|
498 |
-
__( 'We were unable to get the Tickets Details from Time.ly Ticketing', AI1EC_PLUGIN_NAME ),
|
499 |
-
$response->raw, $response->url,
|
500 |
-
true
|
501 |
-
);
|
502 |
-
return json_encode( array( 'data' => array(), 'error' => $error_message ) );
|
503 |
-
}
|
504 |
-
}
|
505 |
-
|
506 |
-
/**
|
507 |
-
* @return object Response body in JSON.
|
508 |
-
*/
|
509 |
-
public function get_tickets( $post_id ) {
|
510 |
-
$api_event_id = $this->get_api_event_id( $post_id );
|
511 |
-
if ( ! $api_event_id ) {
|
512 |
-
return json_encode( array( 'data' => array() ) );
|
513 |
-
}
|
514 |
-
$request = array(
|
515 |
-
'headers' => $this->_get_headers(),
|
516 |
-
'timeout' => parent::DEFAULT_TIMEOUT
|
517 |
-
);
|
518 |
-
$url = $this->get_api_event_url( $post_id ) . 'events/' . $api_event_id . '/tickets';
|
519 |
-
$response = wp_remote_get( $url, $request );
|
520 |
-
$response_code = wp_remote_retrieve_response_code( $response );
|
521 |
-
if ( 200 === $response_code ) {
|
522 |
-
return $response['body'];
|
523 |
-
} else {
|
524 |
-
$error_message = $this->_transform_error_message(
|
525 |
-
__( 'We were unable to get the Tickets Attendees from Time.ly Ticketing', AI1EC_PLUGIN_NAME ),
|
526 |
-
$response, $url,
|
527 |
-
true
|
528 |
-
);
|
529 |
-
return json_encode( array( 'data' => array(), 'error' => $error_message ) );
|
530 |
-
}
|
531 |
-
}
|
532 |
-
|
533 |
-
/**
|
534 |
-
* Check if a Ticket Event was imported from an ICS Feed
|
535 |
-
*/
|
536 |
-
public function is_ticket_event_imported( $post_id ) {
|
537 |
-
$data = $this->get_api_event_data( $post_id );
|
538 |
-
if ( isset( $data[self::ATTR_EVENT_ID] ) && isset( $data[self::ATTR_ICS_API_URL] ) ) {
|
539 |
-
return ( ! ai1ec_is_blank ( $data[self::ATTR_ICS_API_URL] ) );
|
540 |
-
} else {
|
541 |
-
return false;
|
542 |
-
}
|
543 |
-
|
544 |
-
}
|
545 |
-
|
546 |
-
/**
|
547 |
-
* Check if the Ticket Event was created using a different account
|
548 |
-
* The user probably created the event from one account, signed out and
|
549 |
-
* is currently signed in with a new account
|
550 |
-
*/
|
551 |
-
public function is_ticket_event_from_another_account( $post_id ) {
|
552 |
-
$data = $this->get_api_event_data( $post_id );
|
553 |
-
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
554 |
-
if ( isset( $data[self::ATTR_ACCOUNT] ) ) {
|
555 |
-
return ( $this->get_current_account() != $data[self::ATTR_ACCOUNT] );
|
556 |
-
} else {
|
557 |
-
return false;
|
558 |
-
}
|
559 |
-
} else {
|
560 |
-
return false;
|
561 |
-
}
|
562 |
-
}
|
563 |
-
|
564 |
-
/**
|
565 |
-
* Get the API account where the event was created
|
566 |
-
* @param int $post_id Post ID
|
567 |
-
* @param bool $default_null True to return NULL if the value does not exist, false to return the configured API URL
|
568 |
-
*/
|
569 |
-
public function get_api_event_account( $post_id ) {
|
570 |
-
$data = $this->get_api_event_data( $post_id );
|
571 |
-
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
572 |
-
if ( isset( $data[self::ATTR_ACCOUNT] ) ) {
|
573 |
-
return $data[self::ATTR_ACCOUNT];
|
574 |
-
} else {
|
575 |
-
return null;
|
576 |
-
}
|
577 |
-
} else {
|
578 |
-
return null;
|
579 |
-
}
|
580 |
-
}
|
581 |
-
|
582 |
-
/**
|
583 |
* Check if the response that came from the API is the event not found
|
584 |
*/
|
585 |
-
private function _is_event_notfound_error( $response ) {
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
}
|
598 |
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
public function update_api_event_fields( WP_Post $post, $api_fields_values, $post_action = 'trash', $ajax_action = false ) {
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
} else {
|
654 |
-
|
655 |
}
|
656 |
}
|
657 |
|
@@ -660,242 +660,242 @@ class Ai1ec_Api_Ticketing extends Ai1ec_Api_Abstract {
|
|
660 |
* @return NULL in case of success or an error string in case of error
|
661 |
*/
|
662 |
public function delete_api_event( $post_id, $post_action = 'delete', $ajax_action = false ) {
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
} else {
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
}
|
705 |
}
|
706 |
|
707 |
-
|
708 |
* Clear the event metadata used by Event from the post id
|
709 |
* @param int $post_id Post ID
|
710 |
*/
|
711 |
public function clear_event_metadata( $post_id ) {
|
712 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
713 |
}
|
714 |
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
}
|
816 |
-
|
817 |
-
/**
|
818 |
-
* Get the Buy Ticket URL of the event
|
819 |
-
* @param int $post_id Post ID
|
820 |
-
*/
|
821 |
-
public function get_api_event_buy_ticket_url ( $post_id ) {
|
822 |
-
$data = $this->get_api_event_data( $post_id );
|
823 |
-
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
824 |
-
$api_event_id = $data[self::ATTR_EVENT_ID];
|
825 |
-
if ( isset( $data[self::ATTR_ICS_CHECKOUT_URL] ) ) {
|
826 |
-
$checkout_url = $data[self::ATTR_ICS_CHECKOUT_URL];
|
827 |
-
} else {
|
828 |
-
$checkout_url = AI1EC_TICKETS_CHECKOUT_URL;
|
829 |
-
}
|
830 |
-
return str_replace( '{event_id}', $api_event_id, $checkout_url );
|
831 |
-
} else {
|
832 |
-
return null;
|
833 |
-
}
|
834 |
-
}
|
835 |
-
|
836 |
-
/**
|
837 |
-
* Get tax options modal
|
838 |
-
* @param int $event_id Event ID (optional)
|
839 |
-
*/
|
840 |
-
public function get_tax_options_modal( $post_id = null ) {
|
841 |
-
$calendar_id = $this->_get_ticket_calendar();
|
842 |
-
$event_id = $this->get_api_event_id( $post_id );
|
843 |
-
$response = $this->request_api( 'GET',
|
844 |
-
AI1EC_API_URL . "calendars/$calendar_id/tax_options" .
|
845 |
-
( is_null( $event_id ) ? '' : "?event_id=$event_id" )
|
846 |
-
);
|
847 |
-
return (object) array( 'data' => $response->raw, 'error' => false );
|
848 |
-
}
|
849 |
-
|
850 |
-
/**
|
851 |
-
* Get tax options modal
|
852 |
-
* @param int $event_id Event ID (optional)
|
853 |
-
*/
|
854 |
-
public function get_tax_options_modal_ep() {
|
855 |
-
$calendar_id = $this->_get_ticket_calendar();
|
856 |
-
$response = $this->request_api( 'GET',
|
857 |
-
AI1EC_API_URL . "eventpromote/$calendar_id/tax_options"
|
858 |
-
);
|
859 |
-
return (object) array( 'data' => $response->raw, 'error' => false );
|
860 |
-
}
|
861 |
-
|
862 |
-
/**
|
863 |
-
* Save the API event data
|
864 |
-
* @param int $post_id Post ID
|
865 |
-
* @param int $api_event_id (optional) Id of the event on the API
|
866 |
-
* @param string $ics_api_url (optional) API URL of the event on the API (used when importing an ICS feed)
|
867 |
-
* @param string $ics_checkout_url (optional) API CHECKOUT URL of the event on the API (used when importing an ICS feed)
|
868 |
-
* @param string $currency (optional) Currency code of the event
|
869 |
-
* @param string $thumbnail_id (optional) Id of the Thumbnail (Featured Image id)
|
870 |
-
*/
|
871 |
-
public function save_api_event_data( $post_id, $api_event_id, $ics_api_url = null, $ics_checkout_url = null, $currency = null, $thumbnail_id = null ) {
|
872 |
-
if ( ai1ec_is_blank( $api_event_id ) ) {
|
873 |
-
throw new Error( 'Api event id should never be null' );
|
874 |
-
}
|
875 |
-
$api_data[self::ATTR_EVENT_ID] = $api_event_id;
|
876 |
-
$api_data[self::ATTR_ICS_API_URL] = $ics_api_url;
|
877 |
-
$api_data[self::ATTR_ICS_CHECKOUT_URL] = $ics_checkout_url;
|
878 |
-
$api_data[self::ATTR_CURRENCY] = $currency;
|
879 |
-
$api_data[self::ATTR_THUMBNAIL_ID] = $thumbnail_id;
|
880 |
-
if ( ai1ec_is_blank( $ics_api_url ) ) {
|
881 |
-
$api_data[self::ATTR_ACCOUNT] = $this->get_current_account();
|
882 |
-
$api_data[self::ATTR_CALENDAR_ID] = $this->get_current_calendar();
|
883 |
-
}
|
884 |
-
$previous_data = $this->get_api_event_data( $post_id );
|
885 |
-
$new_data = array();
|
886 |
-
if ( is_array( $previous_data ) ) {
|
887 |
-
foreach ( $previous_data as $key => $value) {
|
888 |
-
$new_data[$key] = $value;
|
889 |
-
}
|
890 |
-
}
|
891 |
-
foreach ( $api_data as $key => $value ) {
|
892 |
-
if ( ai1ec_is_blank( $value ) ) {
|
893 |
-
unset( $new_data[$key] );
|
894 |
-
} else {
|
895 |
-
$new_data[$key] = $api_data[$key];
|
896 |
-
}
|
897 |
-
}
|
898 |
-
return update_post_meta( $post_id, self::API_EVENT_DATA, $new_data, $previous_data );
|
899 |
-
}
|
900 |
|
901 |
}
|
10 |
*/
|
11 |
class Ai1ec_Api_Ticketing extends Ai1ec_Api_Abstract {
|
12 |
|
13 |
+
const API_EVENT_DATA = '_ai1ec_api_event_id';
|
14 |
+
|
15 |
+
const ATTR_EVENT_ID = 'api_event_id';
|
16 |
+
const ATTR_THUMBNAIL_ID = 'thumbnail_id';
|
17 |
+
const ATTR_ICS_CHECKOUT_URL = 'ics_checkout_url';
|
18 |
+
const ATTR_ICS_API_URL = 'ics_api_url';
|
19 |
+
const ATTR_ACCOUNT = 'account';
|
20 |
+
const ATTR_CALENDAR_ID = 'calendar_id';
|
21 |
+
const ATTR_CURRENCY = 'currency';
|
22 |
+
|
23 |
+
const MAX_TICKET_TO_BUY_DEFAULT = 25;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Post construction routine.
|
27 |
+
*
|
28 |
+
* Override this method to perform post-construction tasks.
|
29 |
+
*
|
30 |
+
* @return void Return from this method is ignored.
|
31 |
+
*/
|
32 |
+
protected function _initialize() {
|
33 |
+
parent::_initialize();
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Count the valid Tickets Types (not removed) included inside the Ticket Event
|
38 |
+
*/
|
39 |
+
private function _count_valid_tickets( $post_ticket_types ) {
|
40 |
+
if (false === isset( $post_ticket_types ) || 0 === count( $post_ticket_types ) ) {
|
41 |
+
return 0;
|
42 |
+
} else {
|
43 |
+
$count = 0;
|
44 |
+
foreach ( $post_ticket_types as $ticket_type_ite ) {
|
45 |
+
if ( !isset( $ticket_type_ite['remove'] ) ) {
|
46 |
+
$count++;
|
47 |
+
}
|
48 |
+
}
|
49 |
+
return $count;
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Return an error if the Ticket Event is not owned by the Current account
|
55 |
+
*/
|
56 |
+
private function _prevent_update_ticket_event( Ai1ec_Event $event, $ajax_action = false ) {
|
57 |
+
if ( $this->is_ticket_event_imported( $event->get( 'post_id' ) ) ) {
|
58 |
+
//prevent changes on Ticket Events that were imported
|
59 |
+
$error = __( 'This Event was replicated from another site. Changes are not allowed.', AI1EC_PLUGIN_NAME );
|
60 |
+
if ( ! $ajax_action ) {
|
61 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
62 |
+
$notification->store(
|
63 |
+
$error,
|
64 |
+
'error',
|
65 |
+
0,
|
66 |
+
array( Ai1ec_Notification_Admin::RCPT_ADMIN ),
|
67 |
+
false
|
68 |
+
);
|
69 |
+
}
|
70 |
+
return $error;
|
71 |
+
}
|
72 |
+
if ( $this->is_ticket_event_from_another_account( $event->get( 'post_id' ) ) ) {
|
73 |
+
//prevent changes on Ticket Events that were imported
|
74 |
+
$error = sprintf(
|
75 |
+
__( 'This Event was created using a different account %s. Changes are not allowed.', AI1EC_PLUGIN_NAME ),
|
76 |
+
$this->get_api_event_account( $event->get( 'post_id' ) )
|
77 |
+
);
|
78 |
+
if ( ! $ajax_action ) {
|
79 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
80 |
+
$notification->store(
|
81 |
+
$error,
|
82 |
+
'error',
|
83 |
+
0,
|
84 |
+
array( Ai1ec_Notification_Admin::RCPT_ADMIN ),
|
85 |
+
false
|
86 |
+
);
|
87 |
+
}
|
88 |
+
return $error;
|
89 |
+
}
|
90 |
+
return null;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Run some validations inside the _POST request to check if the Event
|
95 |
+
* submmited is a valid event for Tickets
|
96 |
+
* @return NULL in case of success or a Message in case of error
|
97 |
+
*/
|
98 |
+
private function _is_valid_post( Ai1ec_Event $event, $updating ) {
|
99 |
+
$message = null;
|
100 |
+
if ( ( isset( $_POST['ai1ec_rdate'] ) && ! empty( $_POST['ai1ec_rdate'] ) ) ||
|
101 |
+
( isset( $_POST['ai1ec_repeat'] ) && ! empty( $_POST['ai1ec_repeat'] ) )
|
102 |
+
) {
|
103 |
+
$message = __( 'The Repeat option was selected but recurrence is not supported by Event with Tickets.', AI1EC_PLUGIN_NAME );
|
104 |
+
} else if ( isset( $_POST['ai1ec_tickets_loading_error'] ) ) {
|
105 |
+
//do not update tickets because is unsafe. There was a problem to load the tickets,
|
106 |
+
//the customer received the same message when the event was loaded.
|
107 |
+
$message = $_POST['ai1ec_tickets_loading_error'];
|
108 |
+
} else if ( false === ai1ec_is_blank( $event->get( 'ical_feed_url' ) ) ) {
|
109 |
+
//prevent ticket creating inside Regular Events Imported events
|
110 |
+
$message = __( 'This Event was replicated from another site. Any changes on Tickets were discarded.', AI1EC_PLUGIN_NAME );
|
111 |
+
} else {
|
112 |
+
$error = $this->_prevent_update_ticket_event( $event );
|
113 |
+
if ( null !== $error ) {
|
114 |
+
$message = $error;
|
115 |
+
} else if ( ! isset( $_POST['ai1ec_tickets'] ) || 0 === $this->_count_valid_tickets( $_POST['ai1ec_tickets'] ) ) {
|
116 |
+
$message = __( 'The Event has the cost option Ticket selected but no ticket was included.', AI1EC_PLUGIN_NAME );
|
117 |
+
} else if ( false === $this->has_payment_settings() ) {
|
118 |
+
$message = __( 'You need to save the payments settings to create ticket events.', AI1EC_PLUGIN_NAME );
|
119 |
+
} else if ( ! isset( $_POST['tax_options'] ) && ! $updating ) {
|
120 |
+
$message = __( 'Tax and Invoice options are required.', AI1EC_PLUGIN_NAME );
|
121 |
+
}
|
122 |
+
}
|
123 |
+
if ( null !== $message ) {
|
124 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
125 |
+
$notification->store( $message, 'error', 0, array( Ai1ec_Notification_Admin::RCPT_ADMIN ), false );
|
126 |
+
return $message;
|
127 |
+
}
|
128 |
+
return null;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Create or update a Ticket Event on API server
|
133 |
+
* @return object Response body in JSON.
|
134 |
+
*/
|
135 |
+
public function store_event( Ai1ec_Event $event, WP_Post $post, $updating ) {
|
136 |
+
|
137 |
+
$error = $this->_is_valid_post( $event, $updating );
|
138 |
+
if ( null !== $error ) {
|
139 |
+
return $error;
|
140 |
+
}
|
141 |
+
$api_event_id = $this->get_api_event_id( $event->get( 'post_id' ) );
|
142 |
+
$is_new = ! $api_event_id;
|
143 |
+
$fields = array( 'visibility' => $_POST['visibility'] );
|
144 |
+
if ( isset( $_POST['tax_options'] ) ) {
|
145 |
+
$fields['tax_options'] = $_POST['tax_options'];
|
146 |
+
}
|
147 |
+
$body_data = $this->parse_event_fields_to_api_structure(
|
148 |
+
$event,
|
149 |
+
$post,
|
150 |
+
$_POST['ai1ec_tickets'],
|
151 |
+
$fields
|
152 |
+
);
|
153 |
+
$url = AI1EC_API_URL . 'events';
|
154 |
+
if ( $api_event_id ) {
|
155 |
+
$url = $url . '/' . $api_event_id;
|
156 |
+
}
|
157 |
+
|
158 |
+
//get the thumbnail id saved previously
|
159 |
+
$api_data = $this->get_api_event_data( $event->get( 'post_id' ) );
|
160 |
+
if ( isset( $api_data[self::ATTR_THUMBNAIL_ID] ) ) {
|
161 |
+
$event_thumbnail_id = $api_data[self::ATTR_THUMBNAIL_ID];
|
162 |
+
} else {
|
163 |
+
$event_thumbnail_id = 0;
|
164 |
+
}
|
165 |
+
//get the current thumbnail id
|
166 |
+
$post_thumbnail_id = get_post_thumbnail_id( $event->get( 'post_id' ) );
|
167 |
+
if ( false === isset( $post_thumbnail_id ) ) {
|
168 |
+
$post_thumbnail_id = 0;
|
169 |
+
}
|
170 |
+
$update_image = ( $event_thumbnail_id !== $post_thumbnail_id );
|
171 |
+
$payload = '';
|
172 |
+
$custom_headers = null;
|
173 |
+
|
174 |
+
if ( true === $update_image && 0 < $post_thumbnail_id ) {
|
175 |
+
$boundary = wp_generate_password( 24 );
|
176 |
+
$custom_headers['content-type'] = 'multipart/form-data; boundary=' . $boundary;
|
177 |
+
$body_data['update_image'] = '1';
|
178 |
+
foreach ($body_data as $key => $value) {
|
179 |
+
if ( is_array( $value ) ) {
|
180 |
+
$index = 0;
|
181 |
+
foreach ( $value as $arr_key => $arr_value ) {
|
182 |
+
if ( is_array( $arr_value ) ) {
|
183 |
+
foreach ( $arr_value as $child_key => $child_value ) {
|
184 |
+
$payload .= '--' . $boundary;
|
185 |
+
$payload .= "\r\n";
|
186 |
+
$payload .= 'Content-Disposition: form-data; name="' . $key . '[' . $index . '][' . $child_key . ']"' . "\r\n";
|
187 |
+
$payload .= "\r\n";
|
188 |
+
$payload .= $child_value;
|
189 |
+
$payload .= "\r\n";
|
190 |
+
}
|
191 |
+
} else {
|
192 |
+
$payload .= '--' . $boundary;
|
193 |
+
$payload .= "\r\n";
|
194 |
+
$payload .= 'Content-Disposition: form-data; name="tax_options[' . $arr_key . ']"' . "\r\n";
|
195 |
+
$payload .= "\r\n";
|
196 |
+
$payload .= $arr_value;
|
197 |
+
$payload .= "\r\n";
|
198 |
+
}
|
199 |
+
$index++;
|
200 |
+
}
|
201 |
+
} else {
|
202 |
+
$payload .= '--' . $boundary;
|
203 |
+
$payload .= "\r\n";
|
204 |
+
$payload .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n";
|
205 |
+
$payload .= "\r\n";
|
206 |
+
$payload .= $value;
|
207 |
+
$payload .= "\r\n";
|
208 |
+
}
|
209 |
+
}
|
210 |
+
$file_path = get_attached_file ( $post_thumbnail_id );
|
211 |
+
$file_type = wp_check_filetype ( $file_path );
|
212 |
+
$payload .= '--' . $boundary;
|
213 |
+
$payload .= "\r\n";
|
214 |
+
$payload .= 'Content-Disposition: form-data; name="image_id"; filename="' . basename( $file_path ) . '"' . "\r\n";
|
215 |
+
$payload .= 'Content-Type: ' . $file_type['type'] . "\r\n";
|
216 |
+
$payload .= "\r\n";
|
217 |
+
$payload .= file_get_contents( $file_path );
|
218 |
+
$payload .= "\r\n";
|
219 |
+
$payload .= '--' . $boundary . '--';
|
220 |
+
} else {
|
221 |
+
$body_data['update_image'] = (true === $update_image) ? '1' : '0';
|
222 |
+
$payload = json_encode( $body_data );
|
223 |
+
}
|
224 |
+
$response = $this->request_api( 'POST', $url, $payload,
|
225 |
+
true, //true to decode response body
|
226 |
+
$custom_headers
|
227 |
+
);
|
228 |
+
if ( $this->is_response_success( $response ) ) {
|
229 |
+
$api_event_id = $response->body->id;
|
230 |
+
if ( isset( $response->body->currency ) ) {
|
231 |
+
$currency = $response->body->currency;
|
232 |
+
} else {
|
233 |
+
$currency = 'USD';
|
234 |
+
}
|
235 |
+
$currency = $response->body->currency;
|
236 |
+
if ( $post_thumbnail_id <= 0 ) {
|
237 |
+
$post_thumbnail_id = null;
|
238 |
+
}
|
239 |
+
$this->save_api_event_data( $event->get( 'post_id') , $api_event_id, null, null, $currency, $post_thumbnail_id );
|
240 |
+
return true;
|
241 |
+
} else {
|
242 |
+
$error_message = '';
|
243 |
+
if ( $is_new ) {
|
244 |
+
$error_message = __( 'We were unable to create the Event on Time.ly Ticketing', AI1EC_PLUGIN_NAME );
|
245 |
+
} else {
|
246 |
+
$error_message = __( 'We were unable to update the Event on Time.ly Ticketing', AI1EC_PLUGIN_NAME );
|
247 |
+
}
|
248 |
+
return $this->save_error_notification( $response, $error_message );
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Parse the fields of an Event to the structure used by API
|
254 |
+
*/
|
255 |
+
public function parse_event_fields_to_api_structure( Ai1ec_Event $event , WP_Post $post, $post_ticket_types, $api_fields_values ) {
|
256 |
+
$calendar_id = $this->_get_ticket_calendar();
|
257 |
+
if ( $calendar_id <= 0 ) {
|
258 |
+
return null;
|
259 |
+
}
|
260 |
+
|
261 |
+
//fields of ai1ec events table used by API
|
262 |
+
$body['latitude'] = $event->get( 'latitude' );
|
263 |
+
$body['longitude'] = $event->get( 'longitude' );
|
264 |
+
$body['post_id'] = $event->get( 'post_id' );
|
265 |
+
$body['calendar_id'] = $calendar_id;
|
266 |
+
$body['dtstart'] = $event->get( 'start' )->format_to_javascript();
|
267 |
+
$body['dtend'] = $event->getenddate()->format_to_javascript();
|
268 |
+
$body['timezone'] = $event->get( 'timezone_name' );
|
269 |
+
$body['venue_name'] = $event->get( 'venue' );
|
270 |
+
$body['address'] = $event->get( 'address' );
|
271 |
+
$body['city'] = $event->get( 'city' );
|
272 |
+
$body['province'] = $event->get( 'province' );
|
273 |
+
$body['postal_code'] = $event->get( 'postal_code' );
|
274 |
+
$body['country'] = $event->get( 'country' );
|
275 |
+
$body['contact_name'] = $event->get( 'contact_name' );
|
276 |
+
$body['contact_phone'] = $event->get( 'contact_phone' );
|
277 |
+
$body['contact_email'] = $event->get( 'contact_email' );
|
278 |
+
$body['contact_website'] = $event->get( 'contact_url' );
|
279 |
+
$body['uid'] = $event->get_uid();
|
280 |
+
$body['title'] = $post->post_title;
|
281 |
+
$body['description'] = $post->post_content;
|
282 |
+
$body['url'] = get_permalink( $post->ID );
|
283 |
+
$body['status'] = $post->post_status;
|
284 |
+
|
285 |
+
$utc_current_time = $this->_registry->get( 'date.time')->format_to_javascript();
|
286 |
+
$body['created_at'] = $utc_current_time;
|
287 |
+
$body['updated_at'] = $utc_current_time;
|
288 |
+
|
289 |
+
//removing blank values
|
290 |
+
foreach ($body as $key => $value) {
|
291 |
+
if ( ai1ec_is_blank( $value ) ) {
|
292 |
+
unset( $body[ $key ] );
|
293 |
+
}
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( is_null( $api_fields_values ) || 0 == count( $api_fields_values ) ) {
|
297 |
+
$api_fields_values = array( 'status' => 'closed', 'ai1ec_version' => AI1EC_VERSION );
|
298 |
+
} else {
|
299 |
+
if ( ! isset( $api_fields_values['ai1ec_version'] ) ) {
|
300 |
+
$api_fields_values['ai1ec_version'] = AI1EC_VERSION;
|
301 |
+
}
|
302 |
+
foreach ( $api_fields_values as $key => $value ) {
|
303 |
+
$body[$key] = $api_fields_values[$key];
|
304 |
+
if ( 'visibility' === $key ) {
|
305 |
+
if ( 0 === strcasecmp( 'private', $value ) ) {
|
306 |
+
$body['status'] = 'private';
|
307 |
+
} else if ( 0 === strcasecmp( 'password', $value ) ) {
|
308 |
+
$body['status'] = 'password';
|
309 |
+
}
|
310 |
+
}
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
$tickets_types = array();
|
315 |
+
if ( ! is_null( $post_ticket_types ) ) {
|
316 |
+
$index = 0;
|
317 |
+
foreach ( $post_ticket_types as $ticket_type_ite ) {
|
318 |
+
if ( false === isset( $ticket_type_ite['id'] ) &&
|
319 |
+
isset( $ticket_type_ite['remove'] ) ) {
|
320 |
+
//ignoring new tickets that didn't go to api yet
|
321 |
+
continue;
|
322 |
+
}
|
323 |
+
$tickets_types[$index++] = $this->_parse_tickets_type_post_to_api_structure(
|
324 |
+
$ticket_type_ite,
|
325 |
+
$event
|
326 |
+
);
|
327 |
+
}
|
328 |
+
}
|
329 |
+
$body['ticket_types'] = $tickets_types;
|
330 |
+
|
331 |
+
return $body;
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Parse the fields of a Ticket Type to the structure used by API
|
336 |
+
*/
|
337 |
+
protected function _parse_tickets_type_post_to_api_structure( $ticket_type_ite, $event ) {
|
338 |
+
$utc_current_time = $this->_registry->get( 'date.time' )->format_to_javascript();
|
339 |
+
if ( isset( $ticket_type_ite['id'] ) ) {
|
340 |
+
$ticket_type['id'] = $ticket_type_ite['id'];
|
341 |
+
$ticket_type['created_at'] = $ticket_type_ite['created_at'];
|
342 |
+
} else {
|
343 |
+
$ticket_type['created_at'] = $utc_current_time;
|
344 |
+
}
|
345 |
+
if ( isset( $ticket_type_ite['remove'] ) ) {
|
346 |
+
$ticket_type['deleted_at'] = $utc_current_time;
|
347 |
+
}
|
348 |
+
$ticket_type['name'] = $ticket_type_ite['ticket_name'];
|
349 |
+
$ticket_type['description'] = $ticket_type_ite['description'];
|
350 |
+
$ticket_type['price'] = $ticket_type_ite['ticket_price'];
|
351 |
+
if ( 0 === strcasecmp( 'on', $ticket_type_ite['unlimited'] ) ) {
|
352 |
+
$ticket_type['quantity'] = null;
|
353 |
+
} else {
|
354 |
+
$ticket_type['quantity'] = $ticket_type_ite['quantity'];
|
355 |
+
}
|
356 |
+
$ticket_type['buy_min_qty'] = $ticket_type_ite['buy_min_limit'];
|
357 |
+
if ( ai1ec_is_blank( $ticket_type_ite['buy_max_limit'] ) ) {
|
358 |
+
$ticket_type['buy_max_qty'] = null;
|
359 |
+
} else {
|
360 |
+
$ticket_type['buy_max_qty'] = $ticket_type_ite['buy_max_limit'];
|
361 |
+
}
|
362 |
+
if ( 0 === strcasecmp( 'on', $ticket_type_ite['availibility'] ) ) {
|
363 |
+
//immediate availability
|
364 |
+
$timezone_start_time = $this->_registry->get( 'date.time' );
|
365 |
+
$timezone_start_time->set_timezone( $event->get('timezone_name') );
|
366 |
+
$ticket_type['immediately'] = true;
|
367 |
+
$ticket_type['sale_start_date'] = $timezone_start_time->format_to_javascript( $event->get('timezone_name') );
|
368 |
+
$ticket_type['sale_end_date'] = $event->get( 'end' )->format_to_javascript();
|
369 |
+
} else {
|
370 |
+
$ticket_type['immediately'] = false;
|
371 |
+
$ticket_type['sale_start_date'] = $ticket_type_ite['ticket_sale_start_date'];
|
372 |
+
$ticket_type['sale_end_date'] = $ticket_type_ite['ticket_sale_end_date'];
|
373 |
+
}
|
374 |
+
$ticket_type['updated_at'] = $utc_current_time;
|
375 |
+
$ticket_type['status'] = $ticket_type_ite['ticket_status'];
|
376 |
+
return $ticket_type;
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Unparse the fields of API structure to the Ticket Type
|
381 |
+
*/
|
382 |
+
protected function _unparse_tickets_type_from_api_structure( $ticket_type_api ) {
|
383 |
+
$ticket_type = $ticket_type_api;
|
384 |
+
$ticket_type->ticket_name = $ticket_type_api->name;
|
385 |
+
$ticket_type->ticket_price = $ticket_type_api->price;
|
386 |
+
$ticket_type->buy_min_limit = $ticket_type_api->buy_min_qty;
|
387 |
+
if ( null === $ticket_type_api->buy_max_qty ) {
|
388 |
+
$ticket_type->buy_max_limit = self::MAX_TICKET_TO_BUY_DEFAULT;
|
389 |
+
} else {
|
390 |
+
$ticket_type->buy_max_limit = $ticket_type_api->buy_max_qty;
|
391 |
+
}
|
392 |
+
if ( true === ( ( bool ) $ticket_type_api->immediately ) ) {
|
393 |
+
$ticket_type->availibility = 'on';
|
394 |
+
} else {
|
395 |
+
$ticket_type->availibility = 'off';
|
396 |
+
}
|
397 |
+
$ticket_type->ticket_sale_start_date = $ticket_type_api->sale_start_date; //YYYY-MM-YY HH:NN:SS
|
398 |
+
$ticket_type->ticket_sale_end_date = $ticket_type_api->sale_end_date; //YYYY-MM-YY HH:NN:SS
|
399 |
+
$ticket_type->ticket_status = $ticket_type_api->status;
|
400 |
+
if ( 'open' === $ticket_type_api->status ) {
|
401 |
+
$ticket_type->ticket_status_label = __( 'Open for sale', AI1EC_PLUGIN_NAME );
|
402 |
+
} else if ( 'closed' === $ticket_type_api->status ) {
|
403 |
+
$ticket_type->ticket_status_label = __( 'Sale ended', AI1EC_PLUGIN_NAME );
|
404 |
+
} else if ( 'canceled' === $ticket_type_api->status ) {
|
405 |
+
$ticket_type->ticket_status_label = __( 'Canceled', AI1EC_PLUGIN_NAME );
|
406 |
+
} else {
|
407 |
+
$ticket_type->ticket_status_label = $ticket_type_api->status;
|
408 |
+
}
|
409 |
+
if ( false === isset( $ticket_type_api->quantity ) ||
|
410 |
+
null === $ticket_type_api->quantity ) {
|
411 |
+
$ticket_type->unlimited = 'on';
|
412 |
+
} else {
|
413 |
+
$ticket_type->unlimited = 'off';
|
414 |
+
}
|
415 |
+
$ticket_type->ticket_type_id = $ticket_type_api->id;
|
416 |
+
$ticket_type->available = $ticket_type_api->available;
|
417 |
+
$ticket_type->availability = $this->_parse_availability_message( $ticket_type_api->availability );
|
418 |
+
|
419 |
+
//derived property to set the max quantity of dropdown
|
420 |
+
if ( $ticket_type->available !== null ) {
|
421 |
+
if ( $ticket_type->available > $ticket_type->buy_max_limit ) {
|
422 |
+
$ticket_type->buy_max_available = $ticket_type->buy_max_limit;
|
423 |
+
} else {
|
424 |
+
$ticket_type->buy_max_available = $ticket_type->available;
|
425 |
+
}
|
426 |
+
} else {
|
427 |
+
$ticket_type->buy_max_available = $ticket_type->buy_max_limit;
|
428 |
+
}
|
429 |
+
return $ticket_type;
|
430 |
+
}
|
431 |
+
|
432 |
+
public function _parse_availability_message( $availability ){
|
433 |
+
if ( ai1ec_is_blank ( $availability ) ) {
|
434 |
+
return null;
|
435 |
+
} else {
|
436 |
+
switch ($availability) {
|
437 |
+
case 'past_event':
|
438 |
+
return __( 'Past Event' );
|
439 |
+
case 'event_closed':
|
440 |
+
return __( 'Event closed' );
|
441 |
+
case 'not_available_yet':
|
442 |
+
return __( 'Not available yet' );
|
443 |
+
case 'sale_closed':
|
444 |
+
return __( 'Sale closed' );
|
445 |
+
case 'sold_out':
|
446 |
+
return __( 'Sold out' );
|
447 |
+
default:
|
448 |
+
return __( 'Not available' );
|
449 |
+
}
|
450 |
+
}
|
451 |
+
}
|
452 |
+
|
453 |
+
public function get_event( $post_id ) {
|
454 |
+
$api_event_id = $this->get_api_event_id( $post_id );
|
455 |
+
if ( ! $api_event_id ) {
|
456 |
+
return (object) array( 'data' => array() );
|
457 |
+
}
|
458 |
+
$response = $this->request_api( 'GET', $this->get_api_event_url( $post_id ) . 'events/' . $api_event_id . '/edit' );
|
459 |
+
if ( $this->is_response_success( $response ) ) {
|
460 |
+
if ( isset( $response->body->ticket_types ) ) {
|
461 |
+
foreach ( $response->body->ticket_types as $ticket_api ) {
|
462 |
+
$this->_unparse_tickets_type_from_api_structure( $ticket_api );
|
463 |
+
}
|
464 |
+
}
|
465 |
+
return (object) array( 'data' => $response->body );
|
466 |
+
} else {
|
467 |
+
$error_message = $this->_transform_error_message(
|
468 |
+
__( 'We were unable to get the Event Details from Time.ly Ticketing', AI1EC_PLUGIN_NAME ),
|
469 |
+
$response->raw, $response->url,
|
470 |
+
true
|
471 |
+
);
|
472 |
+
return (object) array( 'data' => array(), 'error' => $error_message );
|
473 |
+
}
|
474 |
+
}
|
475 |
+
|
476 |
+
/**
|
477 |
+
* @return string JSON.
|
478 |
+
*/
|
479 |
+
public function get_ticket_types( $post_id, $get_canceled = true ) {
|
480 |
+
$api_event_id = $this->get_api_event_id( $post_id );
|
481 |
+
if ( ! $api_event_id ) {
|
482 |
+
return json_encode( array( 'data' => array() ) );
|
483 |
+
}
|
484 |
+
$response = $this->request_api( 'GET', $this->get_api_event_url( $post_id ) . 'events/' . $api_event_id . '/ticket_types',
|
485 |
+
array( 'get_canceled' => ( true === $get_canceled ? 1 : 0 ) )
|
486 |
+
);
|
487 |
+
if ( $this->is_response_success( $response ) ) {
|
488 |
+
if ( isset( $response->body->ticket_types ) ) {
|
489 |
+
foreach ( $response->body->ticket_types as $ticket_api ) {
|
490 |
+
$this->_unparse_tickets_type_from_api_structure( $ticket_api );
|
491 |
+
}
|
492 |
+
return json_encode( array( 'data' => $response->body->ticket_types ) );
|
493 |
+
} else {
|
494 |
+
return json_encode( array( 'data' => array() ) );
|
495 |
+
}
|
496 |
+
} else {
|
497 |
+
$error_message = $this->_transform_error_message(
|
498 |
+
__( 'We were unable to get the Tickets Details from Time.ly Ticketing', AI1EC_PLUGIN_NAME ),
|
499 |
+
$response->raw, $response->url,
|
500 |
+
true
|
501 |
+
);
|
502 |
+
return json_encode( array( 'data' => array(), 'error' => $error_message ) );
|
503 |
+
}
|
504 |
+
}
|
505 |
+
|
506 |
+
/**
|
507 |
+
* @return object Response body in JSON.
|
508 |
+
*/
|
509 |
+
public function get_tickets( $post_id ) {
|
510 |
+
$api_event_id = $this->get_api_event_id( $post_id );
|
511 |
+
if ( ! $api_event_id ) {
|
512 |
+
return json_encode( array( 'data' => array() ) );
|
513 |
+
}
|
514 |
+
$request = array(
|
515 |
+
'headers' => $this->_get_headers(),
|
516 |
+
'timeout' => parent::DEFAULT_TIMEOUT
|
517 |
+
);
|
518 |
+
$url = $this->get_api_event_url( $post_id ) . 'events/' . $api_event_id . '/tickets';
|
519 |
+
$response = wp_remote_get( $url, $request );
|
520 |
+
$response_code = wp_remote_retrieve_response_code( $response );
|
521 |
+
if ( 200 === $response_code ) {
|
522 |
+
return $response['body'];
|
523 |
+
} else {
|
524 |
+
$error_message = $this->_transform_error_message(
|
525 |
+
__( 'We were unable to get the Tickets Attendees from Time.ly Ticketing', AI1EC_PLUGIN_NAME ),
|
526 |
+
$response, $url,
|
527 |
+
true
|
528 |
+
);
|
529 |
+
return json_encode( array( 'data' => array(), 'error' => $error_message ) );
|
530 |
+
}
|
531 |
+
}
|
532 |
+
|
533 |
+
/**
|
534 |
+
* Check if a Ticket Event was imported from an ICS Feed
|
535 |
+
*/
|
536 |
+
public function is_ticket_event_imported( $post_id ) {
|
537 |
+
$data = $this->get_api_event_data( $post_id );
|
538 |
+
if ( isset( $data[self::ATTR_EVENT_ID] ) && isset( $data[self::ATTR_ICS_API_URL] ) ) {
|
539 |
+
return ( ! ai1ec_is_blank ( $data[self::ATTR_ICS_API_URL] ) );
|
540 |
+
} else {
|
541 |
+
return false;
|
542 |
+
}
|
543 |
+
|
544 |
+
}
|
545 |
+
|
546 |
+
/**
|
547 |
+
* Check if the Ticket Event was created using a different account
|
548 |
+
* The user probably created the event from one account, signed out and
|
549 |
+
* is currently signed in with a new account
|
550 |
+
*/
|
551 |
+
public function is_ticket_event_from_another_account( $post_id ) {
|
552 |
+
$data = $this->get_api_event_data( $post_id );
|
553 |
+
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
554 |
+
if ( isset( $data[self::ATTR_ACCOUNT] ) ) {
|
555 |
+
return ( $this->get_current_account() != $data[self::ATTR_ACCOUNT] );
|
556 |
+
} else {
|
557 |
+
return false;
|
558 |
+
}
|
559 |
+
} else {
|
560 |
+
return false;
|
561 |
+
}
|
562 |
}
|
563 |
|
564 |
+
/**
|
565 |
+
* Get the API account where the event was created
|
566 |
+
* @param int $post_id Post ID
|
567 |
+
* @param bool $default_null True to return NULL if the value does not exist, false to return the configured API URL
|
568 |
+
*/
|
569 |
+
public function get_api_event_account( $post_id ) {
|
570 |
+
$data = $this->get_api_event_data( $post_id );
|
571 |
+
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
572 |
+
if ( isset( $data[self::ATTR_ACCOUNT] ) ) {
|
573 |
+
return $data[self::ATTR_ACCOUNT];
|
574 |
+
} else {
|
575 |
+
return null;
|
576 |
+
}
|
577 |
+
} else {
|
578 |
+
return null;
|
579 |
+
}
|
580 |
+
}
|
581 |
+
|
582 |
+
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
583 |
* Check if the response that came from the API is the event not found
|
584 |
*/
|
585 |
+
private function _is_event_notfound_error( $response ) {
|
586 |
+
if ( isset( $response->response_code ) && 404 === $response->response_code ) {
|
587 |
+
if ( isset( $response->body ) ) {
|
588 |
+
if ( is_array( $response->body ) &&
|
589 |
+
isset( $response->body['message'] ) ) {
|
590 |
+
if ( false !== stripos( $response->body['message'], 'event not found') ) {
|
591 |
+
return true;
|
592 |
+
}
|
593 |
+
}
|
594 |
+
}
|
595 |
+
}
|
596 |
+
return false;
|
597 |
}
|
598 |
|
599 |
+
/**
|
600 |
+
* @return NULL in case of success or an error string in case of error
|
601 |
+
*/
|
602 |
public function update_api_event_fields( WP_Post $post, $api_fields_values, $post_action = 'trash', $ajax_action = false ) {
|
603 |
+
$post_id = $post->ID;
|
604 |
+
$api_event_id = $this->get_api_event_id( $post_id );
|
605 |
+
if ( ! $api_event_id ) {
|
606 |
+
return null;
|
607 |
+
}
|
608 |
+
try {
|
609 |
+
$event = $this->_registry->get( 'model.event', $post_id );
|
610 |
+
} catch ( Ai1ec_Event_Not_Found_Exception $excpt ) {
|
611 |
+
$message = __( 'Event not found inside the database.', AI1EC_PLUGIN_NAME );
|
612 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
613 |
+
$notification->store( $message, 'error', 0, array( Ai1ec_Notification_Admin::RCPT_ADMIN ), false );
|
614 |
+
return $message;
|
615 |
+
}
|
616 |
+
if ( 'update' === $post_action ) {
|
617 |
+
$error = $this->_prevent_update_ticket_event( $event, $ajax_action );
|
618 |
+
if ( null !== $error ) {
|
619 |
+
return $error;
|
620 |
+
}
|
621 |
+
} else {
|
622 |
+
if ( $this->is_ticket_event_imported( $post_id ) ) {
|
623 |
+
return null;
|
624 |
+
}
|
625 |
+
if ( $this->is_ticket_event_from_another_account( $post_id ) ) {
|
626 |
+
return null;
|
627 |
+
}
|
628 |
+
}
|
629 |
+
$headers = $this->_get_headers();
|
630 |
+
$body_data = $this->parse_event_fields_to_api_structure(
|
631 |
+
$event,
|
632 |
+
$post,
|
633 |
+
null, //does not update ticket types, just chaging the api fields specified
|
634 |
+
$api_fields_values
|
635 |
+
);
|
636 |
+
$response = $this->request_api( 'POST',
|
637 |
+
AI1EC_API_URL . "events/$api_event_id",
|
638 |
+
json_encode( $body_data ),
|
639 |
+
true //true to decode response body
|
640 |
+
);
|
641 |
+
if ( ! $this->is_response_success( $response ) ) {
|
642 |
+
if ( $this->_is_event_notfound_error( $response ) ) {
|
643 |
+
if ( isset( $api_fields_values['status'] ) &&
|
644 |
+
'trash' === $api_fields_values['status'] ) {
|
645 |
+
//this is an exception, the event was deleted on API server, but for some reason
|
646 |
+
//the metada was not unset, in this case leave the event be
|
647 |
+
//move to trash
|
648 |
+
return null;
|
649 |
+
}
|
650 |
+
}
|
651 |
+
$message = $this->save_error_notification( $response, __( 'We were unable to Update the Event on Time.ly Network', AI1EC_PLUGIN_NAME ) );
|
652 |
+
return $message;
|
653 |
+
} else {
|
654 |
+
return null;
|
655 |
}
|
656 |
}
|
657 |
|
660 |
* @return NULL in case of success or an error string in case of error
|
661 |
*/
|
662 |
public function delete_api_event( $post_id, $post_action = 'delete', $ajax_action = false ) {
|
663 |
+
$api_event_id = $this->get_api_event_id( $post_id );
|
664 |
+
if ( ! $api_event_id ) {
|
665 |
+
return null;
|
666 |
+
}
|
667 |
+
if ( 'update' === $post_action ) {
|
668 |
+
try {
|
669 |
+
$event = $this->_registry->get( 'model.event', $post_id );
|
670 |
+
} catch ( Ai1ec_Event_Not_Found_Exception $excpt ) {
|
671 |
+
$message = __( 'Event not found inside the database.', AI1EC_PLUGIN_NAME );
|
672 |
+
$notification = $this->_registry->get( 'notification.admin' );
|
673 |
+
$notification->store( $message, 'error', 0, array( Ai1ec_Notification_Admin::RCPT_ADMIN ), false );
|
674 |
+
return $message;
|
675 |
+
}
|
676 |
+
$error = $this->_prevent_update_ticket_event( $event, $ajax_action );
|
677 |
+
if ( null !== $error ) {
|
678 |
+
return $error;
|
679 |
+
}
|
680 |
+
} else {
|
681 |
+
if ( $this->is_ticket_event_imported( $post_id ) ) {
|
682 |
+
$this->clear_event_metadata( $post_id );
|
683 |
+
return null;
|
684 |
+
}
|
685 |
+
if ( $this->is_ticket_event_from_another_account( $post_id ) ) {
|
686 |
+
$this->clear_event_metadata( $post_id );
|
687 |
+
return null;
|
688 |
+
}
|
689 |
+
}
|
690 |
+
$response = $this->request_api( 'DELETE',
|
691 |
+
AI1EC_API_URL . "events/$api_event_id",
|
692 |
+
true //true to decode response body
|
693 |
+
);
|
694 |
+
if ( $this->is_response_success( $response ) ) {
|
695 |
+
$this->clear_event_metadata( $post_id );
|
696 |
+
return null;
|
697 |
+
} else {
|
698 |
+
if ( $this->_is_event_notfound_error( $response ) ) {
|
699 |
+
$this->clear_event_metadata( $post_id );
|
700 |
+
return null;
|
701 |
+
}
|
702 |
+
$message = $this->save_error_notification( $response, __( 'We were unable to remove the Event on Time.ly Network', AI1EC_PLUGIN_NAME ) );
|
703 |
+
return $message;
|
704 |
}
|
705 |
}
|
706 |
|
707 |
+
/**
|
708 |
* Clear the event metadata used by Event from the post id
|
709 |
* @param int $post_id Post ID
|
710 |
*/
|
711 |
public function clear_event_metadata( $post_id ) {
|
712 |
+
delete_post_meta( $post_id, self::API_EVENT_DATA );
|
713 |
+
}
|
714 |
+
|
715 |
+
public function get_api_event_data( $post_id ) {
|
716 |
+
$data = get_post_meta(
|
717 |
+
$post_id,
|
718 |
+
self::API_EVENT_DATA,
|
719 |
+
true
|
720 |
+
);
|
721 |
+
if ( ai1ec_is_blank ( $data ) ) {
|
722 |
+
return null;
|
723 |
+
} else if ( is_numeric( $data ) ) {
|
724 |
+
//migrate the old metadata into one
|
725 |
+
$new_data[self::ATTR_EVENT_ID] = $data;
|
726 |
+
$value = get_post_meta( $post_id, '_ai1ec_thumbnail_id', true );
|
727 |
+
if ( false === ai1ec_is_blank( $value ) ) {
|
728 |
+
$new_data[self::ATTR_THUMBNAIL_ID] = $value;
|
729 |
+
}
|
730 |
+
$value = get_post_meta( $post_id, '_ai1ec_ics_checkout_url', true );
|
731 |
+
if ( false === ai1ec_is_blank( $value ) ) {
|
732 |
+
$new_data[self::ATTR_ICS_CHECKOUT_URL] = $value;
|
733 |
+
}
|
734 |
+
$value = get_post_meta( $post_id, '_ai1ec_ics_api_url' , true );
|
735 |
+
if ( ai1ec_is_blank( $value ) ) {
|
736 |
+
//not imported ticket event
|
737 |
+
$new_data[self::ATTR_ACCOUNT] = $this->get_current_account();
|
738 |
+
$new_data[self::ATTR_CALENDAR_ID] = $this->get_current_calendar();
|
739 |
+
} else {
|
740 |
+
$new_data[self::ATTR_ICS_API_URL] = $value;
|
741 |
+
}
|
742 |
+
$new_data[self::ATTR_CURRENCY] = 'USD';
|
743 |
+
update_post_meta( $post_id, self::API_EVENT_DATA, $new_data );
|
744 |
+
return $new_data;
|
745 |
+
} else if ( is_array( $data ) ) {
|
746 |
+
return $data;
|
747 |
+
} else {
|
748 |
+
wp_die( 'Error geting the api data' );
|
749 |
+
}
|
750 |
+
}
|
751 |
+
|
752 |
+
/**
|
753 |
+
* Get the id of the event on the API
|
754 |
+
* @param int $post_id Post ID
|
755 |
+
*/
|
756 |
+
public function get_api_event_id( $post_id ) {
|
757 |
+
$data = $this->get_api_event_data( $post_id );
|
758 |
+
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
759 |
+
return $data[self::ATTR_EVENT_ID];
|
760 |
+
} else {
|
761 |
+
return null;
|
762 |
+
}
|
763 |
+
}
|
764 |
+
|
765 |
+
/**
|
766 |
+
* Get the API URL of the event
|
767 |
+
* @param int $post_id Post ID
|
768 |
+
* @param bool $default_null True to return NULL if the value does not exist, false to return the configured API URL
|
769 |
+
*/
|
770 |
+
public function get_api_event_url ( $post_id ) {
|
771 |
+
$data = $this->get_api_event_data( $post_id );
|
772 |
+
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
773 |
+
if ( isset( $data[self::ATTR_ICS_API_URL] ) ) {
|
774 |
+
return $data[self::ATTR_ICS_API_URL];
|
775 |
+
} else {
|
776 |
+
return AI1EC_API_URL;
|
777 |
+
}
|
778 |
+
} else {
|
779 |
+
return null;
|
780 |
+
}
|
781 |
+
}
|
782 |
+
|
783 |
+
/**
|
784 |
+
* Get the Currency of the event
|
785 |
+
* @param int $post_id Post ID
|
786 |
+
*/
|
787 |
+
public function get_api_event_currency ( $post_id ) {
|
788 |
+
$data = $this->get_api_event_data( $post_id );
|
789 |
+
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
790 |
+
if ( isset( $data[self::ATTR_CURRENCY] ) ) {
|
791 |
+
return $data[self::ATTR_CURRENCY];
|
792 |
+
} else {
|
793 |
+
return 'USD';
|
794 |
+
}
|
795 |
+
} else {
|
796 |
+
return null;
|
797 |
+
}
|
798 |
}
|
799 |
|
800 |
+
/**
|
801 |
+
* Get the Checkout url of the event
|
802 |
+
* @param int $post_id Post ID
|
803 |
+
*/
|
804 |
+
public function get_api_event_checkout_url ( $post_id ) {
|
805 |
+
$data = $this->get_api_event_data( $post_id );
|
806 |
+
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
807 |
+
if ( isset( $data[self::ATTR_ICS_CHECKOUT_URL] ) ) {
|
808 |
+
return $data[self::ATTR_ICS_CHECKOUT_URL];
|
809 |
+
} else {
|
810 |
+
return AI1EC_TICKETS_CHECKOUT_URL;
|
811 |
+
}
|
812 |
+
} else {
|
813 |
+
return null;
|
814 |
+
}
|
815 |
+
}
|
816 |
+
|
817 |
+
/**
|
818 |
+
* Get the Buy Ticket URL of the event
|
819 |
+
* @param int $post_id Post ID
|
820 |
+
*/
|
821 |
+
public function get_api_event_buy_ticket_url ( $post_id ) {
|
822 |
+
$data = $this->get_api_event_data( $post_id );
|
823 |
+
if ( isset( $data[self::ATTR_EVENT_ID] ) ) {
|
824 |
+
$api_event_id = $data[self::ATTR_EVENT_ID];
|
825 |
+
if ( isset( $data[self::ATTR_ICS_CHECKOUT_URL] ) ) {
|
826 |
+
$checkout_url = $data[self::ATTR_ICS_CHECKOUT_URL];
|
827 |
+
} else {
|
828 |
+
$checkout_url = AI1EC_TICKETS_CHECKOUT_URL;
|
829 |
+
}
|
830 |
+
return str_replace( '{event_id}', $api_event_id, $checkout_url );
|
831 |
+
} else {
|
832 |
+
return null;
|
833 |
+
}
|
834 |
+
}
|
835 |
+
|
836 |
+
/**
|
837 |
+
* Get tax options modal
|
838 |
+
* @param int $event_id Event ID (optional)
|
839 |
+
*/
|
840 |
+
public function get_tax_options_modal( $post_id = null ) {
|
841 |
+
$calendar_id = $this->_get_ticket_calendar();
|
842 |
+
$event_id = $this->get_api_event_id( $post_id );
|
843 |
+
$response = $this->request_api( 'GET',
|
844 |
+
AI1EC_API_URL . "calendars/$calendar_id/tax_options" .
|
845 |
+
( is_null( $event_id ) ? '' : "?event_id=$event_id" )
|
846 |
+
);
|
847 |
+
return (object) array( 'data' => $response->raw, 'error' => false );
|
848 |
+
}
|
849 |
+
|
850 |
+
/**
|
851 |
+
* Get tax options modal
|
852 |
+
* @param int $event_id Event ID (optional)
|
853 |
+
*/
|
854 |
+
public function get_tax_options_modal_ep() {
|
855 |
+
$calendar_id = $this->_get_ticket_calendar();
|
856 |
+
$response = $this->request_api( 'GET',
|
857 |
+
AI1EC_API_URL . "eventpromote/$calendar_id/tax_options"
|
858 |
+
);
|
859 |
+
return (object) array( 'data' => $response->raw, 'error' => false );
|
860 |
+
}
|
861 |
+
|
862 |
+
/**
|
863 |
+
* Save the API event data
|
864 |
+
* @param int $post_id Post ID
|
865 |
+
* @param int $api_event_id (optional) Id of the event on the API
|
866 |
+
* @param string $ics_api_url (optional) API URL of the event on the API (used when importing an ICS feed)
|
867 |
+
* @param string $ics_checkout_url (optional) API CHECKOUT URL of the event on the API (used when importing an ICS feed)
|
868 |
+
* @param string $currency (optional) Currency code of the event
|
869 |
+
* @param string $thumbnail_id (optional) Id of the Thumbnail (Featured Image id)
|
870 |
+
*/
|
871 |
+
public function save_api_event_data( $post_id, $api_event_id, $ics_api_url = null, $ics_checkout_url = null, $currency = null, $thumbnail_id = null ) {
|
872 |
+
if ( ai1ec_is_blank( $api_event_id ) ) {
|
873 |
+
throw new Error( 'Api event id should never be null' );
|
874 |
+
}
|
875 |
+
$api_data[self::ATTR_EVENT_ID] = $api_event_id;
|
876 |
+
$api_data[self::ATTR_ICS_API_URL] = $ics_api_url;
|
877 |
+
$api_data[self::ATTR_ICS_CHECKOUT_URL] = $ics_checkout_url;
|
878 |
+
$api_data[self::ATTR_CURRENCY] = $currency;
|
879 |
+
$api_data[self::ATTR_THUMBNAIL_ID] = $thumbnail_id;
|
880 |
+
if ( ai1ec_is_blank( $ics_api_url ) ) {
|
881 |
+
$api_data[self::ATTR_ACCOUNT] = $this->get_current_account();
|
882 |
+
$api_data[self::ATTR_CALENDAR_ID] = $this->get_current_calendar();
|
883 |
+
}
|
884 |
+
$previous_data = $this->get_api_event_data( $post_id );
|
885 |
+
$new_data = array();
|
886 |
+
if ( is_array( $previous_data ) ) {
|
887 |
+
foreach ( $previous_data as $key => $value) {
|
888 |
+
$new_data[$key] = $value;
|
889 |
+
}
|
890 |
+
}
|
891 |
+
foreach ( $api_data as $key => $value ) {
|
892 |
+
if ( ai1ec_is_blank( $value ) ) {
|
893 |
+
unset( $new_data[$key] );
|
894 |
+
} else {
|
895 |
+
$new_data[$key] = $api_data[$key];
|
896 |
+
}
|
897 |
+
}
|
898 |
+
return update_post_meta( $post_id, self::API_EVENT_DATA, $new_data, $previous_data );
|
899 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
900 |
|
901 |
}
|
app/model/app.php
CHANGED
@@ -10,25 +10,25 @@
|
|
10 |
*/
|
11 |
class Ai1ec_App extends Ai1ec_Base {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
|
33 |
|
34 |
}
|
10 |
*/
|
11 |
class Ai1ec_App extends Ai1ec_Base {
|
12 |
|
13 |
+
/**
|
14 |
+
* Initiate base objects.
|
15 |
+
*
|
16 |
+
* @param Ai1ec_Registry_Object $registry
|
17 |
+
* @internal param \Ai1ec_Registry_Object $system Injectable system object.
|
18 |
+
*/
|
19 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
20 |
+
parent::__construct( $registry );
|
21 |
+
$this->_initialize();
|
22 |
+
}
|
23 |
|
24 |
+
/**
|
25 |
+
* Post construction routine.
|
26 |
+
*
|
27 |
+
* Override this method to perform post-construction tasks.
|
28 |
+
*
|
29 |
+
* @return void Return from this method is ignored.
|
30 |
+
*/
|
31 |
+
protected function _initialize() {}
|
32 |
|
33 |
|
34 |
}
|
app/model/event-compatibility.php
CHANGED
@@ -11,101 +11,101 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Event_Compatibility extends Ai1ec_Event {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
}
|
11 |
*/
|
12 |
class Ai1ec_Event_Compatibility extends Ai1ec_Event {
|
13 |
|
14 |
+
/**
|
15 |
+
* Getter.
|
16 |
+
*
|
17 |
+
* @param string $name Property name.
|
18 |
+
*
|
19 |
+
* @return mixed Property value.
|
20 |
+
*/
|
21 |
+
public function __get( $name ) {
|
22 |
+
$value = $this->get( $name );
|
23 |
+
if ( null !== $value ) {
|
24 |
+
return $value;
|
25 |
+
}
|
26 |
+
return $this->get_runtime( $name );
|
27 |
+
}
|
28 |
|
29 |
+
/**
|
30 |
+
* Isset magic function.
|
31 |
+
*
|
32 |
+
* @param string $name Property name.
|
33 |
+
*
|
34 |
+
* @return bool True of false.
|
35 |
+
*/
|
36 |
+
public function __isset( $name ) {
|
37 |
+
$method_name = 'get' . $name;
|
38 |
+
if ( method_exists( $this, $method_name ) ) {
|
39 |
+
return false;
|
40 |
+
}
|
41 |
+
return ( null !== $this->$name );
|
42 |
+
}
|
43 |
|
44 |
+
/**
|
45 |
+
* Twig timespan short method.
|
46 |
+
*
|
47 |
+
* @return string Value.
|
48 |
+
*/
|
49 |
+
public function gettimespan_short() {
|
50 |
+
return $this->_registry->get( 'view.event.time' )
|
51 |
+
->get_timespan_html( $this, 'short' );
|
52 |
+
}
|
53 |
|
54 |
+
/**
|
55 |
+
* Twig is_allday method.
|
56 |
+
*
|
57 |
+
* @return bool Value.
|
58 |
+
*/
|
59 |
+
public function getis_allday() {
|
60 |
+
return $this->is_allday();
|
61 |
+
}
|
62 |
|
63 |
+
/**
|
64 |
+
* Twig is_multiday method.
|
65 |
+
*
|
66 |
+
* @return bool Value.
|
67 |
+
*/
|
68 |
+
public function getis_multiday() {
|
69 |
+
return $this->is_multiday();
|
70 |
+
}
|
71 |
|
72 |
+
/**
|
73 |
+
* Returns Event instance permalink for FER compatibility.
|
74 |
+
*
|
75 |
+
* @return string Event instance permalink.
|
76 |
+
*/
|
77 |
+
public function getpermalink() {
|
78 |
+
return $this->get_runtime( 'instance_permalink' );
|
79 |
+
}
|
80 |
|
81 |
+
/**
|
82 |
+
* Returns Event timespan for popup.
|
83 |
+
*
|
84 |
+
* @return string
|
85 |
+
*/
|
86 |
+
public function getpopup_timespan() {
|
87 |
+
return $this->_registry->get( 'twig.ai1ec-extension' )
|
88 |
+
->timespan( $this, 'short' );
|
89 |
+
}
|
90 |
|
91 |
+
/**
|
92 |
+
* Returns Avatar not wrapped in <a> tag.
|
93 |
+
*
|
94 |
+
* @return string
|
95 |
+
*/
|
96 |
+
public function getavatar_not_wrapped() {
|
97 |
+
return $this->getavatar( false );
|
98 |
+
}
|
99 |
|
100 |
+
/**
|
101 |
+
* Returns Event avatar URL.
|
102 |
+
*
|
103 |
+
* @return string Event avatar URL.
|
104 |
+
* @throws Ai1ec_Bootstrap_Exception
|
105 |
+
*/
|
106 |
+
public function getavatar_url() {
|
107 |
+
return $this->_registry->get(
|
108 |
+
'view.event.avatar'
|
109 |
+
)->get_event_avatar_url( $this );
|
110 |
+
}
|
111 |
}
|
app/model/event.php
CHANGED
@@ -11,885 +11,885 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Event extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
|
895 |
}
|
11 |
*/
|
12 |
class Ai1ec_Event extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var Ai1ec_Event_Entity Data store object reference.
|
16 |
+
*/
|
17 |
+
protected $_entity = null;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var array Map of fields that require special care during set/get
|
21 |
+
* operations. Values have following meanings:
|
22 |
+
* [0] - both way care required;
|
23 |
+
* [1] - only `set` operations require care;
|
24 |
+
* [-1] - only `get` (for storage) operations require care.
|
25 |
+
*/
|
26 |
+
protected $_swizzable = array(
|
27 |
+
'cost' => 0,
|
28 |
+
'start' => -1,
|
29 |
+
'end' => -1,
|
30 |
+
'timezone_name' => -1,
|
31 |
+
'recurrence_dates' => 1,
|
32 |
+
'exception_dates' => 1,
|
33 |
+
);
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @var array Runtime properties
|
37 |
+
*/
|
38 |
+
protected $_runtime_props = array();
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @var bool|null Boolean cache-definition indicating if event is multiday.
|
42 |
+
*/
|
43 |
+
protected $_is_multiday = null;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Wrapper to get property value.
|
47 |
+
*
|
48 |
+
* @param string $property Name of property to get.
|
49 |
+
* @param mixed $default Default value to return.
|
50 |
+
*
|
51 |
+
* @return mixed Actual property.
|
52 |
+
*/
|
53 |
+
public function get( $property, $default = null ) {
|
54 |
+
return $this->_entity->get( $property, $default );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Get properties generated at runtime
|
59 |
+
*
|
60 |
+
* @param string $property
|
61 |
+
*
|
62 |
+
* @return string
|
63 |
+
*/
|
64 |
+
public function get_runtime( $property, $default = '' ) {
|
65 |
+
return isset( $this->_runtime_props[$property] ) ?
|
66 |
+
$this->_runtime_props[$property] :
|
67 |
+
$default;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Set properties generated at runtime
|
72 |
+
*
|
73 |
+
* @param string $property
|
74 |
+
* @param string $value
|
75 |
+
*/
|
76 |
+
public function set_runtime( $property, $value ) {
|
77 |
+
$this->_runtime_props[$property] = $value;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Handle property initiation.
|
82 |
+
*
|
83 |
+
* Decides, how to extract value stored in permanent storage.
|
84 |
+
*
|
85 |
+
* @param string $property Name of property to handle
|
86 |
+
* @param mixed $value Value, read from permanent storage
|
87 |
+
*
|
88 |
+
* @return bool Success
|
89 |
+
*/
|
90 |
+
public function set( $property, $value ) {
|
91 |
+
if (
|
92 |
+
isset( $this->_swizzable[$property] ) &&
|
93 |
+
$this->_swizzable[$property] >= 0
|
94 |
+
) {
|
95 |
+
$method = '_handle_property_construct_' . $property;
|
96 |
+
$value = $this->{$method}( $value );
|
97 |
+
}
|
98 |
+
$this->_entity->set( $property, $value );
|
99 |
+
return $this;
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Set the event is all day, during the specified number of days
|
104 |
+
*
|
105 |
+
* @param number $length
|
106 |
+
*/
|
107 |
+
public function set_all_day( $length = 1 ) {
|
108 |
+
// set allday as true
|
109 |
+
$this->set( 'allday', true );
|
110 |
+
$start = $this->get( 'start' );
|
111 |
+
// reset time component
|
112 |
+
$start->set_time( 0, 0, 0 );
|
113 |
+
$end = $this->_registry->get( 'date.time', $start );
|
114 |
+
// set the correct length
|
115 |
+
$end->adjust_day( $length );
|
116 |
+
$this->set( 'end', $end );
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Set the event as if it has no end time
|
121 |
+
*/
|
122 |
+
public function set_no_end_time() {
|
123 |
+
$this->set( 'instant_event', true );
|
124 |
+
$start = $this->get( 'start' );
|
125 |
+
$end = $this->_registry->get( 'date.time', $start );
|
126 |
+
$end->set_time(
|
127 |
+
$start->format( 'H' ),
|
128 |
+
$start->format( 'i' ) + 15,
|
129 |
+
$start->format( 's' )
|
130 |
+
);
|
131 |
+
$this->set( 'end', $end );
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Set object fields from arbitrary array.
|
136 |
+
*
|
137 |
+
* @param array $data Supposedly map of fields to initiate.
|
138 |
+
*
|
139 |
+
* @return Ai1ec_Event Instance of self for chaining.
|
140 |
+
*/
|
141 |
+
public function initialize_from_array( array $data ) {
|
142 |
+
|
143 |
+
// =======================================================
|
144 |
+
// = Assign each event field the value from the database =
|
145 |
+
// =======================================================
|
146 |
+
foreach ( $this->_entity->list_properties() as $property ) {
|
147 |
+
if ( 'post' !== $property && isset( $data[$property] ) ) {
|
148 |
+
$this->set( $property, $data[$property] );
|
149 |
+
unset( $data[$property] );
|
150 |
+
}
|
151 |
+
}
|
152 |
+
if ( isset( $data['post'] ) ) {
|
153 |
+
$this->set( 'post', (object)$data['post'] );
|
154 |
+
} else {
|
155 |
+
// ========================================
|
156 |
+
// = Remaining fields are the post fields =
|
157 |
+
// ========================================
|
158 |
+
$this->set( 'post', (object)$data );
|
159 |
+
}
|
160 |
+
return $this;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Delete the events from all tables
|
165 |
+
*/
|
166 |
+
public function delete() {
|
167 |
+
// delete post (this will trigger deletion of cached events, and
|
168 |
+
// remove the event from events table)
|
169 |
+
wp_delete_post( $this->get( 'post_id' ), true );
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Initialize object from ID.
|
174 |
+
*
|
175 |
+
* Attempts to retrieve entity from database and if succeeds - uses
|
176 |
+
* {@see self::initialize_from_array} to initiate actual values.
|
177 |
+
*
|
178 |
+
* @param int $post_id ID of post (event) to initiate.
|
179 |
+
* @param int|bool $instance ID of event instance, false for base event.
|
180 |
+
*
|
181 |
+
* @return Ai1ec_Event Instance of self for chaining.
|
182 |
+
*
|
183 |
+
* @throws Ai1ec_Event_Not_Found_Exception If entity is not locatable.
|
184 |
+
*/
|
185 |
+
public function initialize_from_id( $post_id, $instance = false ) {
|
186 |
+
$post = get_post( $post_id );
|
187 |
+
if ( ! $post || $post->post_status == 'auto-draft' ) {
|
188 |
+
throw new Ai1ec_Event_Not_Found_Exception(
|
189 |
+
'Post with ID \'' . $post_id .
|
190 |
+
'\' could not be retrieved from the database.'
|
191 |
+
);
|
192 |
+
}
|
193 |
+
$post_id = (int)$post_id;
|
194 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
195 |
+
|
196 |
+
$left_join = '';
|
197 |
+
$select_sql = '
|
198 |
+
e.post_id,
|
199 |
+
e.timezone_name,
|
200 |
+
e.recurrence_rules,
|
201 |
+
e.exception_rules,
|
202 |
+
e.allday,
|
203 |
+
e.instant_event,
|
204 |
+
e.recurrence_dates,
|
205 |
+
e.exception_dates,
|
206 |
+
e.venue,
|
207 |
+
e.country,
|
208 |
+
e.address,
|
209 |
+
e.city,
|
210 |
+
e.province,
|
211 |
+
e.postal_code,
|
212 |
+
e.show_map,
|
213 |
+
e.contact_name,
|
214 |
+
e.contact_phone,
|
215 |
+
e.contact_email,
|
216 |
+
e.contact_url,
|
217 |
+
e.cost,
|
218 |
+
e.ticket_url,
|
219 |
+
e.ical_feed_url,
|
220 |
+
e.ical_source_url,
|
221 |
+
e.ical_organizer,
|
222 |
+
e.ical_contact,
|
223 |
+
e.ical_uid,
|
224 |
+
e.longitude,
|
225 |
+
e.latitude,
|
226 |
+
e.show_coordinates,
|
227 |
+
GROUP_CONCAT( ttc.term_id ) AS categories,
|
228 |
+
GROUP_CONCAT( ttt.term_id ) AS tags
|
229 |
+
';
|
230 |
+
|
231 |
+
if (
|
232 |
+
false !== $instance &&
|
233 |
+
is_numeric( $instance ) &&
|
234 |
+
$instance > 0
|
235 |
+
) {
|
236 |
+
$select_sql .= ', IF( aei.start IS NOT NULL, aei.start, e.start ) as start,' .
|
237 |
+
' IF( aei.start IS NOT NULL, aei.end, e.end ) as end ';
|
238 |
+
|
239 |
+
$instance = (int)$instance;
|
240 |
+
$this->set( 'instance_id', $instance );
|
241 |
+
$left_join = 'LEFT JOIN ' . $dbi->get_table_name( 'ai1ec_event_instances' ) .
|
242 |
+
' aei ON aei.id = ' . $instance . ' AND e.post_id = aei.post_id ';
|
243 |
+
} else {
|
244 |
+
$select_sql .= ', e.start as start, e.end as end, e.allday ';
|
245 |
+
if ( -1 === (int)$instance ) {
|
246 |
+
$select_sql .= ', aei.id as instance_id ';
|
247 |
+
$left_join = 'LEFT JOIN ' .
|
248 |
+
$dbi->get_table_name( 'ai1ec_event_instances' ) .
|
249 |
+
' aei ON e.post_id = aei.post_id ' .
|
250 |
+
'AND e.start = aei.start AND e.end = aei.end ';
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
// =============================
|
255 |
+
// = Fetch event from database =
|
256 |
+
// =============================
|
257 |
+
$query = 'SELECT ' . $select_sql . '
|
258 |
+
FROM ' . $dbi->get_table_name( 'ai1ec_events' ) . ' e
|
259 |
+
LEFT JOIN ' .
|
260 |
+
$dbi->get_table_name( 'term_relationships' ) . ' tr
|
261 |
+
ON ( e.post_id = tr.object_id )
|
262 |
+
LEFT JOIN ' . $dbi->get_table_name( 'term_taxonomy' ) . ' ttc
|
263 |
+
ON (
|
264 |
+
tr.term_taxonomy_id = ttc.term_taxonomy_id AND
|
265 |
+
ttc.taxonomy = \'events_categories\'
|
266 |
+
)
|
267 |
+
LEFT JOIN ' . $dbi->get_table_name( 'term_taxonomy' ) . ' ttt
|
268 |
+
ON (
|
269 |
+
tr.term_taxonomy_id = ttt.term_taxonomy_id AND
|
270 |
+
ttt.taxonomy = \'events_tags\'
|
271 |
+
)
|
272 |
+
' . $left_join . '
|
273 |
+
WHERE e.post_id = ' . $post_id . '
|
274 |
+
GROUP BY e.post_id';
|
275 |
+
|
276 |
+
$event = $dbi->get_row( $query, ARRAY_A );
|
277 |
+
if ( null === $event || null === $event['post_id'] ) {
|
278 |
+
throw new Ai1ec_Event_Not_Found_Exception(
|
279 |
+
'Event with ID \'' . $post_id .
|
280 |
+
'\' could not be retrieved from the database.'
|
281 |
+
);
|
282 |
+
}
|
283 |
+
|
284 |
+
$event['post'] = $post;
|
285 |
+
return $this->initialize_from_array( $event );
|
286 |
+
}
|
287 |
+
|
288 |
+
public function getenddate() {
|
289 |
+
$end = $this->get( 'end' );
|
290 |
+
if ( $this->is_allday() ) {
|
291 |
+
$end->set_time(
|
292 |
+
$end->format( 'H' ),
|
293 |
+
$end->format( 'i' ),
|
294 |
+
$end->format( 's' ) - 1
|
295 |
+
);
|
296 |
+
}
|
297 |
+
return $end;
|
298 |
+
}
|
299 |
+
/**
|
300 |
+
* Returns enddate specific info.
|
301 |
+
*
|
302 |
+
* @return array Date info structure.
|
303 |
+
*/
|
304 |
+
public function getenddate_info() {
|
305 |
+
$end = $this->getenddate();
|
306 |
+
return array(
|
307 |
+
'month' => $this->get( 'end' )->format_i18n( 'M' ),
|
308 |
+
'day' => $this->get( 'end' )->format_i18n( 'j' ),
|
309 |
+
'weekday' => $this->get( 'end' )->format_i18n( 'D' ),
|
310 |
+
'year' => $this->get( 'end' )->format_i18n( 'Y' ),
|
311 |
+
);
|
312 |
+
}
|
313 |
+
|
314 |
+
/**
|
315 |
+
* Create new event object, using provided data for initialization.
|
316 |
+
*
|
317 |
+
* @param Ai1ec_Registry_Object $registry Injected object registry.
|
318 |
+
* @param int|array|null $data Look up post with id $data, or
|
319 |
+
* initialize fields with associative
|
320 |
+
* array $data containing both post
|
321 |
+
* and event fields.
|
322 |
+
* @param int|bool $instance Optionally instance ID. When ID
|
323 |
+
* value is -1 then it is
|
324 |
+
* retrieved from db.
|
325 |
+
*
|
326 |
+
* @throws Ai1ec_Invalid_Argument_Exception When $data is not one
|
327 |
+
* of int|array|null.
|
328 |
+
* @throws Ai1ec_Event_Not_Found_Exception When $data relates to
|
329 |
+
* non-existent ID.
|
330 |
+
*
|
331 |
+
*/
|
332 |
+
function __construct(
|
333 |
+
Ai1ec_Registry_Object $registry,
|
334 |
+
$data = null,
|
335 |
+
$instance = false
|
336 |
+
) {
|
337 |
+
parent::__construct( $registry );
|
338 |
+
$this->_entity = $this->_registry->get( 'model.event.entity' );
|
339 |
+
if ( null === $data ) {
|
340 |
+
return; // empty object
|
341 |
+
} else if ( is_numeric( $data ) ) {
|
342 |
+
$this->initialize_from_id( $data, $instance );
|
343 |
+
} else if ( is_array( $data ) ) {
|
344 |
+
$this->initialize_from_array( $data );
|
345 |
+
} else {
|
346 |
+
throw new Ai1ec_Invalid_Argument_Exception(
|
347 |
+
'Argument to constructor must be integer, array or null' .
|
348 |
+
', not ' . var_export( $data, true )
|
349 |
+
);
|
350 |
+
}
|
351 |
+
|
352 |
+
if ( $this->is_allday() ) {
|
353 |
+
try {
|
354 |
+
$timezone = $this->_registry->get( 'date.timezone' )
|
355 |
+
->get( $this->get( 'timezone_name' ) );
|
356 |
+
$this->_entity->set_preferred_timezone( $timezone );
|
357 |
+
} catch ( Exception $excpt ) {
|
358 |
+
// ignore
|
359 |
+
}
|
360 |
+
}
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* Twig method for retrieving avatar.
|
365 |
+
*
|
366 |
+
* @param bool $wrap_permalink Whether to wrap avatar in <a> element or not
|
367 |
+
*
|
368 |
+
* @return string Avatar markup
|
369 |
+
*/
|
370 |
+
public function getavatar( $wrap_permalink = true ) {
|
371 |
+
return $this->_registry->
|
372 |
+
get( 'view.event.avatar' )->get_event_avatar(
|
373 |
+
$this,
|
374 |
+
$this->_registry->get( 'view.calendar.fallbacks' )->get_all(),
|
375 |
+
'',
|
376 |
+
$wrap_permalink
|
377 |
+
);
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Returns whether Event has geo information.
|
382 |
+
*
|
383 |
+
* @return bool True or false.
|
384 |
+
*/
|
385 |
+
public function has_geoinformation() {
|
386 |
+
$latitude = floatval( $this->get( 'latitude') );
|
387 |
+
$longitude = floatval( $this->get( 'longitude' ) );
|
388 |
+
return (
|
389 |
+
(
|
390 |
+
$latitude >= 0.000000000000001 ||
|
391 |
+
$latitude <= -0.000000000000001
|
392 |
+
) &&
|
393 |
+
(
|
394 |
+
$longitude >= 0.000000000000001 ||
|
395 |
+
$longitude <= -0.000000000000001
|
396 |
+
)
|
397 |
+
);
|
398 |
+
}
|
399 |
+
|
400 |
+
protected function _handle_property_construct_recurrence_dates( $value ) {
|
401 |
+
if ( $value ) {
|
402 |
+
$this->_entity->set( 'recurrence_rules', 'RDATE=' . $value );
|
403 |
+
}
|
404 |
+
return $value;
|
405 |
+
}
|
406 |
+
|
407 |
+
protected function _handle_property_construct_exception_dates( $value ) {
|
408 |
+
if ( $value ) {
|
409 |
+
$this->_entity->set( 'exception_rules', 'EXDATE=' . $value );
|
410 |
+
}
|
411 |
+
return $value;
|
412 |
+
}
|
413 |
+
|
414 |
+
/**
|
415 |
+
* Handle `cost` value reading from permanent storage.
|
416 |
+
*
|
417 |
+
* @param string $value Value stored in permanent storage
|
418 |
+
*
|
419 |
+
* @return bool Success: true, always
|
420 |
+
*/
|
421 |
+
protected function _handle_property_construct_cost( $value ) {
|
422 |
+
$test_value = false;
|
423 |
+
if (
|
424 |
+
isset( $value{1} ) && (
|
425 |
+
':' === $value{1} || ';' === $value{1}
|
426 |
+
)
|
427 |
+
) {
|
428 |
+
$test_value = unserialize( $value );
|
429 |
+
}
|
430 |
+
$cost = $is_free = NULL;
|
431 |
+
if ( false === $test_value ) {
|
432 |
+
$cost = trim( $value );
|
433 |
+
$is_free = false;
|
434 |
+
} else {
|
435 |
+
extract( $test_value, EXTR_IF_EXISTS );
|
436 |
+
}
|
437 |
+
$this->_entity->set( 'is_free', (bool)$is_free );
|
438 |
+
return (string)$cost;
|
439 |
+
}
|
440 |
+
|
441 |
+
public function get_uid_pattern() {
|
442 |
+
static $format = null;
|
443 |
+
if ( null === $format ) {
|
444 |
+
$site_url = parse_url( ai1ec_get_site_url() );
|
445 |
+
$format = 'ai1ec-%d@' . $site_url['host'];
|
446 |
+
if ( isset( $site_url['path'] ) ) {
|
447 |
+
$format .= $site_url['path'];
|
448 |
+
}
|
449 |
+
}
|
450 |
+
return $format;
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* Get UID to be used for current event.
|
455 |
+
*
|
456 |
+
* The generated format is cached in static variable within this function
|
457 |
+
* to re-use when generating UIDs for different entries.
|
458 |
+
*
|
459 |
+
* @return string Generated UID.
|
460 |
+
*
|
461 |
+
* @staticvar string $format Cached format.
|
462 |
+
*/
|
463 |
+
public function get_uid() {
|
464 |
+
$ical_uid = $this->get( 'ical_uid' );
|
465 |
+
if ( ! empty( $ical_uid ) ) {
|
466 |
+
return $ical_uid;
|
467 |
+
}
|
468 |
+
return sprintf( $this->get_uid_pattern(), $this->get( 'post_id' ) );
|
469 |
+
}
|
470 |
+
|
471 |
+
/**
|
472 |
+
* Check if event is free.
|
473 |
+
*
|
474 |
+
* @return bool Free status.
|
475 |
+
*/
|
476 |
+
public function is_free() {
|
477 |
+
return (bool)$this->get( 'is_free' );
|
478 |
+
}
|
479 |
+
|
480 |
+
/**
|
481 |
+
* Check if event is taking all day.
|
482 |
+
*
|
483 |
+
* @return bool True for all-day long events.
|
484 |
+
*/
|
485 |
+
public function is_allday() {
|
486 |
+
return (bool)$this->get( 'allday' );
|
487 |
+
}
|
488 |
+
|
489 |
+
/**
|
490 |
+
* Check if event has virtually no time.
|
491 |
+
*
|
492 |
+
* @return bool True for instant events.
|
493 |
+
*/
|
494 |
+
public function is_instant() {
|
495 |
+
return (bool)$this->get( 'instant_event' );
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Check if event is taking multiple days.
|
500 |
+
*
|
501 |
+
* Uses object-wide variable {@see self::$_is_multiday} to store
|
502 |
+
* calculated value after first call.
|
503 |
+
*
|
504 |
+
* @return bool True for multiday events.
|
505 |
+
*/
|
506 |
+
public function is_multiday() {
|
507 |
+
if ( null === $this->_is_multiday ) {
|
508 |
+
$start = $this->get( 'start' );
|
509 |
+
$end = $this->get( 'end' );
|
510 |
+
$diff = $end->diff_sec( $start );
|
511 |
+
$this->_is_multiday = $diff > 86400 &&
|
512 |
+
$start->format( 'Y-m-d' ) !== $end->format( 'Y-m-d' );
|
513 |
+
}
|
514 |
+
return $this->_is_multiday;
|
515 |
+
}
|
516 |
+
|
517 |
+
/**
|
518 |
+
* Get the duration of the event
|
519 |
+
*
|
520 |
+
* @return number
|
521 |
+
*/
|
522 |
+
public function get_duration() {
|
523 |
+
$duration = $this->get_runtime( 'duration', null );
|
524 |
+
if ( null === $duration ) {
|
525 |
+
$duration = $this->get( 'end' )->format() -
|
526 |
+
$this->get( 'start' )->format();
|
527 |
+
$this->set_runtime( 'duration', $duration );
|
528 |
+
}
|
529 |
+
return $duration;
|
530 |
+
}
|
531 |
+
|
532 |
+
/**
|
533 |
+
* Create/update entity representation.
|
534 |
+
*
|
535 |
+
* Saves the current event data to the database. If $this->post_id exists,
|
536 |
+
* but $update is false, creates a new record in the ai1ec_events table of
|
537 |
+
* this event data, but does not try to create a new post. Else if $update
|
538 |
+
* is true, updates existing event record. If $this->post_id is empty,
|
539 |
+
* creates a new post AND record in the ai1ec_events table for this event.
|
540 |
+
*
|
541 |
+
* @param bool $update Whether to update an existing event or create a
|
542 |
+
* new one
|
543 |
+
* @param bool $backward_compatibility The (wpdb) ofr the new wordpress 4.4
|
544 |
+
* now inserts NULL as null values. The previous version, if you insert a NULL
|
545 |
+
* value in an int value, the values saved would be 0 instead of null.
|
546 |
+
* @return int The post_id of the new or existing event.
|
547 |
+
*/
|
548 |
+
function save( $update = false, $backward_compatibility = true ) {
|
549 |
+
do_action( 'ai1ec_pre_save_event', $this, $update );
|
550 |
+
if ( ! $update ) {
|
551 |
+
$response = apply_filters( 'ai1ec_event_save_new', $this );
|
552 |
+
if ( is_wp_error( $response ) ) {
|
553 |
+
throw new Ai1ec_Event_Create_Exception(
|
554 |
+
'Failed to create event: ' . $response->get_error_message()
|
555 |
+
);
|
556 |
+
}
|
557 |
+
}
|
558 |
+
|
559 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
560 |
+
$columns = $this->prepare_store_entity();
|
561 |
+
$format = $this->prepare_store_format( $columns, $backward_compatibility );
|
562 |
+
$table_name = $dbi->get_table_name( 'ai1ec_events' );
|
563 |
+
$post_id = $columns['post_id'];
|
564 |
+
|
565 |
+
if ( $this->get( 'end' )->is_empty() ) {
|
566 |
+
$this->set_no_end_time();
|
567 |
+
}
|
568 |
+
if ( $post_id ) {
|
569 |
+
$success = false;
|
570 |
+
if ( ! $update ) {
|
571 |
+
$success = $dbi->insert(
|
572 |
+
$table_name,
|
573 |
+
$columns,
|
574 |
+
$format
|
575 |
+
);
|
576 |
+
} else {
|
577 |
+
$success = $dbi->update(
|
578 |
+
$table_name,
|
579 |
+
$columns,
|
580 |
+
array( 'post_id' => $columns['post_id'] ),
|
581 |
+
$format,
|
582 |
+
array( '%d' )
|
583 |
+
);
|
584 |
+
}
|
585 |
+
if ( false === $success ) {
|
586 |
+
return false;
|
587 |
+
}
|
588 |
+
|
589 |
+
} else {
|
590 |
+
// ===================
|
591 |
+
// = Insert new post =
|
592 |
+
// ===================
|
593 |
+
$post_id = wp_insert_post( $this->get( 'post' ), false );
|
594 |
+
if ( 0 === $post_id ) {
|
595 |
+
return false;
|
596 |
+
}
|
597 |
+
$this->set( 'post_id', $post_id );
|
598 |
+
$columns['post_id'] = $post_id;
|
599 |
+
|
600 |
+
// =========================
|
601 |
+
// = Insert new event data =
|
602 |
+
// =========================
|
603 |
+
if ( false === $dbi->insert( $table_name, $columns, $format ) ) {
|
604 |
+
return false;
|
605 |
+
}
|
606 |
+
}
|
607 |
+
|
608 |
+
$taxonomy = $this->_registry->get(
|
609 |
+
'model.event.taxonomy',
|
610 |
+
$post_id
|
611 |
+
);
|
612 |
+
$cats = $this->get( 'categories' );
|
613 |
+
if (
|
614 |
+
is_array( $cats ) &&
|
615 |
+
! empty( $cats )
|
616 |
+
) {
|
617 |
+
$taxonomy->set_categories( $cats );
|
618 |
+
}
|
619 |
+
$tags = $this->get( 'tags' );
|
620 |
+
if (
|
621 |
+
is_array( $tags ) &&
|
622 |
+
! empty( $tags )
|
623 |
+
) {
|
624 |
+
$taxonomy->set_tags( $tags );
|
625 |
+
}
|
626 |
+
|
627 |
+
if (
|
628 |
+
$feed = $this->get( 'feed' ) &&
|
629 |
+
isset( $feed->feed_id )
|
630 |
+
) {
|
631 |
+
$taxonomy->set_feed( $feed );
|
632 |
+
}
|
633 |
+
|
634 |
+
// give other plugins / extensions the ability to do things
|
635 |
+
// when saving, like fetching authors which i removed as it's not core.
|
636 |
+
do_action( 'ai1ec_save_event' );
|
637 |
+
|
638 |
+
$instance_model = $this->_registry->get( 'model.event.instance' );
|
639 |
+
$instance_model->recreate( $this );
|
640 |
+
|
641 |
+
do_action( 'ai1ec_event_saved', $post_id, $this, $update );
|
642 |
+
return $post_id;
|
643 |
+
}
|
644 |
+
|
645 |
+
/**
|
646 |
+
* Prepare fields format flags to use in database operations.
|
647 |
+
*
|
648 |
+
* @param array $columns Array of columns with data to insert.
|
649 |
+
*
|
650 |
+
* @return array List of format flags to use in integrations with DBI.
|
651 |
+
*/
|
652 |
+
public function prepare_store_format( array &$columns, $backward_compatibility = true ) {
|
653 |
+
$format = array(
|
654 |
+
'%d', // post_id
|
655 |
+
'%d', // start
|
656 |
+
'%d', // end
|
657 |
+
'%s', // timezone_name
|
658 |
+
'%d', // allday
|
659 |
+
'%d', // instant_event
|
660 |
+
'%s', // recurrence_rules
|
661 |
+
'%s', // exception_rules
|
662 |
+
'%s', // recurrence_dates
|
663 |
+
'%s', // exception_dates
|
664 |
+
'%s', // venue
|
665 |
+
'%s', // country
|
666 |
+
'%s', // address
|
667 |
+
'%s', // city
|
668 |
+
'%s', // province
|
669 |
+
'%s', // postal_code
|
670 |
+
'%d', // show_map
|
671 |
+
'%s', // contact_name
|
672 |
+
'%s', // contact_phone
|
673 |
+
'%s', // contact_email
|
674 |
+
'%s', // contact_url
|
675 |
+
'%s', // cost
|
676 |
+
'%s', // ticket_url
|
677 |
+
'%s', // ical_feed_url
|
678 |
+
'%s', // ical_source_url
|
679 |
+
'%s', // ical_uid
|
680 |
+
'%d', // show_coordinates
|
681 |
+
'%f', // latitude
|
682 |
+
'%f', // longitude
|
683 |
+
);
|
684 |
+
|
685 |
+
if ( $backward_compatibility ) {
|
686 |
+
$columns_count = count( $columns );
|
687 |
+
if ( count( $format ) !== $columns_count ) {
|
688 |
+
throw new Ai1ec_Event_Not_Found_Exception(
|
689 |
+
'Data columns count differs from format columns count'
|
690 |
+
);
|
691 |
+
}
|
692 |
+
$index = 0;
|
693 |
+
foreach ( $columns as $key => $value ) {
|
694 |
+
if ( '%d' === $format[ $index ] ) {
|
695 |
+
if ( is_null( $value ) ) {
|
696 |
+
$columns[ $key ] = 0;
|
697 |
+
}
|
698 |
+
}
|
699 |
+
$index++;
|
700 |
+
}
|
701 |
+
}
|
702 |
+
|
703 |
+
return $format;
|
704 |
+
}
|
705 |
+
|
706 |
+
/**
|
707 |
+
* Prepare event entity {@see self::$_entity} for persistent storage.
|
708 |
+
*
|
709 |
+
* Creates an array of database fields and corresponding values.
|
710 |
+
*
|
711 |
+
* @return array Map of fields to store.
|
712 |
+
*/
|
713 |
+
public function prepare_store_entity() {
|
714 |
+
$entity = array(
|
715 |
+
'post_id' => $this->storage_format( 'post_id' ),
|
716 |
+
'start' => $this->storage_format( 'start' ),
|
717 |
+
'end' => $this->storage_format( 'end' ),
|
718 |
+
'timezone_name' => $this->storage_format( 'timezone_name' ),
|
719 |
+
'allday' => $this->storage_format( 'allday' ),
|
720 |
+
'instant_event' => $this->storage_format( 'instant_event' ),
|
721 |
+
'recurrence_rules' => $this->storage_format( 'recurrence_rules' ),
|
722 |
+
'exception_rules' => $this->storage_format( 'exception_rules' ),
|
723 |
+
'recurrence_dates' => $this->storage_format( 'recurrence_dates' ),
|
724 |
+
'exception_dates' => $this->storage_format( 'exception_dates' ),
|
725 |
+
'venue' => $this->storage_format( 'venue' ),
|
726 |
+
'country' => $this->storage_format( 'country' ),
|
727 |
+
'address' => $this->storage_format( 'address' ),
|
728 |
+
'city' => $this->storage_format( 'city' ),
|
729 |
+
'province' => $this->storage_format( 'province' ),
|
730 |
+
'postal_code' => $this->storage_format( 'postal_code' ),
|
731 |
+
'show_map' => $this->storage_format( 'show_map' ),
|
732 |
+
'contact_name' => $this->storage_format( 'contact_name' ),
|
733 |
+
'contact_phone' => $this->storage_format( 'contact_phone' ),
|
734 |
+
'contact_email' => $this->storage_format( 'contact_email' ),
|
735 |
+
'contact_url' => $this->storage_format( 'contact_url' ),
|
736 |
+
'cost' => $this->storage_format( 'cost' ),
|
737 |
+
'ticket_url' => $this->storage_format( 'ticket_url' ),
|
738 |
+
'ical_feed_url' => $this->storage_format( 'ical_feed_url' ),
|
739 |
+
'ical_source_url' => $this->storage_format( 'ical_source_url' ),
|
740 |
+
'ical_uid' => $this->storage_format( 'ical_uid' ),
|
741 |
+
'show_coordinates' => $this->storage_format( 'show_coordinates' ),
|
742 |
+
'latitude' => $this->storage_format( 'latitude', '' ),
|
743 |
+
'longitude' => $this->storage_format( 'longitude', '' ),
|
744 |
+
);
|
745 |
+
return $entity;
|
746 |
+
}
|
747 |
+
|
748 |
+
/**
|
749 |
+
* Compact field for writing to persistent storage.
|
750 |
+
*
|
751 |
+
* @param string $field Name of field to compact.
|
752 |
+
* @param mixed $default Default value to use for undescribed fields.
|
753 |
+
*
|
754 |
+
* @return mixed Value or $default.
|
755 |
+
*/
|
756 |
+
public function storage_format( $field, $default = null ) {
|
757 |
+
$value = $this->_entity->get( $field, $default );
|
758 |
+
if (
|
759 |
+
isset( $this->_swizzable[$field] ) &&
|
760 |
+
$this->_swizzable[$field] <= 0
|
761 |
+
) {
|
762 |
+
$value = $this->{ '_handle_property_destruct_' . $field }( $value );
|
763 |
+
}
|
764 |
+
return $value;
|
765 |
+
}
|
766 |
+
|
767 |
+
/**
|
768 |
+
* Allow properties to be modified after cloning.
|
769 |
+
*
|
770 |
+
* @return void
|
771 |
+
*/
|
772 |
+
public function __clone() {
|
773 |
+
$this->_entity = clone $this->_entity;
|
774 |
+
}
|
775 |
+
|
776 |
+
/**
|
777 |
+
* Decode timezone to use for event.
|
778 |
+
*
|
779 |
+
* Following algorythm is used to detect a value:
|
780 |
+
* - take value provided in input;
|
781 |
+
* - if empty - take value associated with start time;
|
782 |
+
* - if empty - take current environment timezone.
|
783 |
+
*
|
784 |
+
* @param string $timezone_name Timezone provided in input.
|
785 |
+
*
|
786 |
+
* @return string Timezone name to use for event in future.
|
787 |
+
*/
|
788 |
+
protected function _handle_property_destruct_timezone_name(
|
789 |
+
$timezone_name
|
790 |
+
) {
|
791 |
+
if ( empty( $timezone_name ) ) {
|
792 |
+
$timezone_name = $this->get( 'start' )->get_timezone();
|
793 |
+
if ( empty( $timezone_name ) ) {
|
794 |
+
$timezone_name = $this->_registry->get( 'date.timezone' )
|
795 |
+
->get_default_timezone();
|
796 |
+
}
|
797 |
+
}
|
798 |
+
return $timezone_name;
|
799 |
+
}
|
800 |
+
|
801 |
+
/**
|
802 |
+
* Format datetime to UNIX timestamp for storage.
|
803 |
+
*
|
804 |
+
* @param Ai1ec_Date_Time $start Datetime object to compact.
|
805 |
+
*
|
806 |
+
* @return int UNIX timestamp.
|
807 |
+
*/
|
808 |
+
protected function _handle_property_destruct_start( Ai1ec_Date_Time $start ) {
|
809 |
+
return $start->format_to_gmt();
|
810 |
+
}
|
811 |
+
|
812 |
+
/**
|
813 |
+
* Format datetime to UNIX timestamp for storage.
|
814 |
+
*
|
815 |
+
* @param Ai1ec_Date_Time $end Datetime object to compact.
|
816 |
+
*
|
817 |
+
* @return int UNIX timestamp.
|
818 |
+
*/
|
819 |
+
protected function _handle_property_destruct_end( Ai1ec_Date_Time $end ) {
|
820 |
+
return $end->format_to_gmt();
|
821 |
+
}
|
822 |
+
|
823 |
+
/**
|
824 |
+
* Handle `cost` writing to permanent storage.
|
825 |
+
*
|
826 |
+
* @param string $cost Value of cost.
|
827 |
+
*
|
828 |
+
* @return string Serialized value to store.
|
829 |
+
*/
|
830 |
+
protected function _handle_property_destruct_cost( $cost ) {
|
831 |
+
$cost = array(
|
832 |
+
'cost' => $cost,
|
833 |
+
'is_free' => false,
|
834 |
+
);
|
835 |
+
if ( $this->get( 'is_free' ) ) {
|
836 |
+
$cost['is_free'] = true;
|
837 |
+
}
|
838 |
+
return serialize( $cost );
|
839 |
+
}
|
840 |
+
|
841 |
+
/**
|
842 |
+
* Get the submitter information array
|
843 |
+
* @return array (
|
844 |
+
* is_organizer => 1 if the organizer is the submitter,
|
845 |
+
* email => if is_organizer is 0, them this property has the email of the submitter,
|
846 |
+
* name => if is_organizer is 0, them this property has the name of the submitter
|
847 |
+
* )
|
848 |
+
*/
|
849 |
+
public function get_submitter_info() {
|
850 |
+
$post_id = $this->get( 'post_id' );
|
851 |
+
if ( empty( $post_id ) ) {
|
852 |
+
return null;
|
853 |
+
}
|
854 |
+
$submitter_info = get_post_meta(
|
855 |
+
$post_id,
|
856 |
+
'_submitter_info',
|
857 |
+
true
|
858 |
+
);
|
859 |
+
if ( false == ai1ec_is_blank( $submitter_info ) ) {
|
860 |
+
$submitter_info = json_decode( $submitter_info, true );
|
861 |
+
if ( is_array( $submitter_info ) ) {
|
862 |
+
return $submitter_info;
|
863 |
+
}
|
864 |
+
}
|
865 |
+
return null;
|
866 |
+
}
|
867 |
+
|
868 |
+
/**
|
869 |
+
* Save the submitter information into post metadata
|
870 |
+
*/
|
871 |
+
public function save_submitter_info( $is_submitter, $submitter_email, $submitter_name ) {
|
872 |
+
$post_id = $this->get( 'post_id' );
|
873 |
+
if ( empty( $post_id ) ) {
|
874 |
+
throw new Exception( 'Post id empty' );
|
875 |
+
}
|
876 |
+
$save = false;
|
877 |
+
if ( 1 === intval( $is_submitter ) ) {
|
878 |
+
$submitter_info['is_organizer'] = 1;
|
879 |
+
if ( false === ai1ec_is_blank( $this->get( 'contact_email' ) ) ) {
|
880 |
+
$save = true;
|
881 |
+
}
|
882 |
+
} else {
|
883 |
+
$submitter_info['is_organizer'] = 0;
|
884 |
+
if ( false === ai1ec_is_blank( $submitter_email ) ) {
|
885 |
+
$submitter_info['email'] = trim( $submitter_email );
|
886 |
+
$submitter_info['name'] = trim( $submitter_name );
|
887 |
+
$save = true;
|
888 |
+
}
|
889 |
+
}
|
890 |
+
if ( $save ) {
|
891 |
+
update_post_meta( $post_id, '_submitter_info', json_encode( $submitter_info ) );
|
892 |
+
}
|
893 |
+
}
|
894 |
|
895 |
}
|
app/model/event/creating.php
CHANGED
@@ -11,496 +11,499 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Event_Creating extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
|
|
|
|
|
|
376 |
}
|
377 |
|
378 |
protected function current_action() {
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
}
|
392 |
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
|
506 |
}
|
11 |
*/
|
12 |
class Ai1ec_Event_Creating extends Ai1ec_Base {
|
13 |
|
14 |
+
protected function is_valid_event( $post ) {
|
15 |
+
// verify this came from the our screen and with proper authorization,
|
16 |
+
// because save_post can be triggered at other times
|
17 |
+
if (
|
18 |
+
! isset( $_POST[AI1EC_POST_TYPE] ) ||
|
19 |
+
! wp_verify_nonce( $_POST[AI1EC_POST_TYPE], 'ai1ec' )
|
20 |
+
) {
|
21 |
+
return false;
|
22 |
+
}
|
23 |
+
|
24 |
+
if (
|
25 |
+
isset( $post->post_status ) &&
|
26 |
+
'auto-draft' === $post->post_status
|
27 |
+
) {
|
28 |
+
return false;
|
29 |
+
}
|
30 |
+
|
31 |
+
// verify if this is not inline-editing
|
32 |
+
if (
|
33 |
+
isset( $_REQUEST['action'] ) &&
|
34 |
+
'inline-save' === $_REQUEST['action']
|
35 |
+
) {
|
36 |
+
return false;
|
37 |
+
}
|
38 |
+
|
39 |
+
// verify that the post_type is that of an event
|
40 |
+
if ( $post->post_type !== AI1EC_POST_TYPE ) {
|
41 |
+
return false;
|
42 |
+
}
|
43 |
+
|
44 |
+
return true;
|
45 |
+
}
|
46 |
+
|
47 |
+
private function _parse_post_to_event( $post_id ) {
|
48 |
+
|
49 |
+
/**
|
50 |
+
* =====================================================================
|
51 |
+
*
|
52 |
+
* CHANGE CODE BELLOW TO HAVE FOLLOWING PROPERTIES:
|
53 |
+
* - be initializiable from model;
|
54 |
+
* - have sane defaults;
|
55 |
+
* - avoid that cluster of isset and ternary operator.
|
56 |
+
*
|
57 |
+
* =====================================================================
|
58 |
+
*/
|
59 |
+
|
60 |
+
$all_day = isset( $_POST['ai1ec_all_day_event'] ) ? 1 : 0;
|
61 |
+
$instant_event = isset( $_POST['ai1ec_instant_event'] ) ? 1 : 0;
|
62 |
+
$timezone_name = isset( $_POST['ai1ec_timezone_name'] ) ? $_POST['ai1ec_timezone_name'] : 'sys.default';
|
63 |
+
$start_time = isset( $_POST['ai1ec_start_time'] ) ? $_POST['ai1ec_start_time'] : '';
|
64 |
+
$end_time = isset( $_POST['ai1ec_end_time'] ) ? $_POST['ai1ec_end_time'] : '';
|
65 |
+
$venue = isset( $_POST['ai1ec_venue'] ) ? $_POST['ai1ec_venue'] : '';
|
66 |
+
$address = isset( $_POST['ai1ec_address'] ) ? $_POST['ai1ec_address'] : '';
|
67 |
+
$city = isset( $_POST['ai1ec_city'] ) ? $_POST['ai1ec_city'] : '';
|
68 |
+
$province = isset( $_POST['ai1ec_province'] ) ? $_POST['ai1ec_province'] : '';
|
69 |
+
$postal_code = isset( $_POST['ai1ec_postal_code'] ) ? $_POST['ai1ec_postal_code'] : '';
|
70 |
+
$country = isset( $_POST['ai1ec_country'] ) ? $_POST['ai1ec_country'] : '';
|
71 |
+
$google_map = isset( $_POST['ai1ec_google_map'] ) ? 1 : 0;
|
72 |
+
$cost = isset( $_POST['ai1ec_cost'] ) ? $_POST['ai1ec_cost'] : '';
|
73 |
+
$is_free = isset( $_POST['ai1ec_is_free'] ) ? (bool)$_POST['ai1ec_is_free'] : false;
|
74 |
+
$ticket_url = isset( $_POST['ai1ec_ticket_url'] ) ? $_POST['ai1ec_ticket_url'] : '';
|
75 |
+
$contact_name = isset( $_POST['ai1ec_contact_name'] ) ? $_POST['ai1ec_contact_name'] : '';
|
76 |
+
$contact_phone = isset( $_POST['ai1ec_contact_phone'] ) ? $_POST['ai1ec_contact_phone'] : '';
|
77 |
+
$contact_email = isset( $_POST['ai1ec_contact_email'] ) ? $_POST['ai1ec_contact_email'] : '';
|
78 |
+
$contact_url = isset( $_POST['ai1ec_contact_url'] ) ? $_POST['ai1ec_contact_url'] : '';
|
79 |
+
$show_coordinates = isset( $_POST['ai1ec_input_coordinates'] )? 1 : 0;
|
80 |
+
$longitude = isset( $_POST['ai1ec_longitude'] ) ? $_POST['ai1ec_longitude'] : '';
|
81 |
+
$latitude = isset( $_POST['ai1ec_latitude'] ) ? $_POST['ai1ec_latitude'] : '';
|
82 |
+
$cost_type = isset( $_POST['ai1ec_cost_type'] ) ? $_POST['ai1ec_cost_type'] : '';
|
83 |
+
$rrule = null;
|
84 |
+
$exrule = null;
|
85 |
+
$exdate = null;
|
86 |
+
$rdate = null;
|
87 |
+
|
88 |
+
if ( 'external' !== $cost_type ) {
|
89 |
+
$ticket_url = '';
|
90 |
+
}
|
91 |
+
|
92 |
+
$this->_remap_recurrence_dates();
|
93 |
+
// if rrule is set, convert it from local to UTC time
|
94 |
+
if (
|
95 |
+
isset( $_POST['ai1ec_repeat'] ) &&
|
96 |
+
! empty( $_POST['ai1ec_repeat'] )
|
97 |
+
) {
|
98 |
+
$rrule = $_POST['ai1ec_rrule'];
|
99 |
+
}
|
100 |
+
|
101 |
+
// add manual dates
|
102 |
+
if (
|
103 |
+
isset( $_POST['ai1ec_exdate'] ) &&
|
104 |
+
! empty( $_POST['ai1ec_exdate'] )
|
105 |
+
) {
|
106 |
+
$exdate = $_POST['ai1ec_exdate'];
|
107 |
+
}
|
108 |
+
if (
|
109 |
+
isset( $_POST['ai1ec_rdate'] ) &&
|
110 |
+
! empty( $_POST['ai1ec_rdate'] )
|
111 |
+
) {
|
112 |
+
$rdate = $_POST['ai1ec_rdate'];
|
113 |
+
}
|
114 |
+
|
115 |
+
// if exrule is set, convert it from local to UTC time
|
116 |
+
if (
|
117 |
+
isset( $_POST['ai1ec_exclude'] ) &&
|
118 |
+
! empty( $_POST['ai1ec_exclude'] ) &&
|
119 |
+
( null !== $rrule || null !== $rdate ) // no point for exclusion, if repetition is not set
|
120 |
+
) {
|
121 |
+
$exrule = $this->_registry->get( 'recurrence.rule' )->merge_exrule(
|
122 |
+
$_POST['ai1ec_exrule'],
|
123 |
+
$rrule
|
124 |
+
);
|
125 |
+
}
|
126 |
+
|
127 |
+
$is_new = false;
|
128 |
+
try {
|
129 |
+
$event = $this->_registry->get(
|
130 |
+
'model.event',
|
131 |
+
$post_id ? $post_id : null
|
132 |
+
);
|
133 |
+
} catch ( Ai1ec_Event_Not_Found_Exception $excpt ) {
|
134 |
+
// Post exists, but event data hasn't been saved yet. Create new event
|
135 |
+
// object.
|
136 |
+
$is_new = true;
|
137 |
+
$event = $this->_registry->get( 'model.event' );
|
138 |
+
}
|
139 |
+
$formatted_timezone = $this->_registry->get( 'date.timezone' )
|
140 |
+
->get_name( $timezone_name );
|
141 |
+
if ( empty( $timezone_name ) || ! $formatted_timezone ) {
|
142 |
+
$timezone_name = 'sys.default';
|
143 |
+
}
|
144 |
+
|
145 |
+
unset( $formatted_timezone );
|
146 |
+
$start_time_entry = $this->_registry
|
147 |
+
->get( 'date.time', $start_time, $timezone_name );
|
148 |
+
$end_time_entry = $this->_registry
|
149 |
+
->get( 'date.time', $end_time, $timezone_name );
|
150 |
+
|
151 |
+
$timezone_name = $start_time_entry->get_timezone();
|
152 |
+
if ( null === $timezone_name ) {
|
153 |
+
$timezone_name = $start_time_entry->get_default_format_timezone();
|
154 |
+
}
|
155 |
+
|
156 |
+
$event->set( 'post_id', $post_id );
|
157 |
+
$event->set( 'start', $start_time_entry );
|
158 |
+
if ( $instant_event ) {
|
159 |
+
$event->set_no_end_time();
|
160 |
+
} else {
|
161 |
+
$event->set( 'end', $end_time_entry );
|
162 |
+
$event->set( 'instant_event', false );
|
163 |
+
}
|
164 |
+
$event->set( 'timezone_name', $timezone_name );
|
165 |
+
$event->set( 'allday', $all_day );
|
166 |
+
$event->set( 'venue', $venue );
|
167 |
+
$event->set( 'address', $address );
|
168 |
+
$event->set( 'city', $city );
|
169 |
+
$event->set( 'province', $province );
|
170 |
+
$event->set( 'postal_code', $postal_code );
|
171 |
+
$event->set( 'country', $country );
|
172 |
+
$event->set( 'show_map', $google_map );
|
173 |
+
$event->set( 'cost', $cost );
|
174 |
+
$event->set( 'is_free', $is_free );
|
175 |
+
$event->set( 'ticket_url', $ticket_url );
|
176 |
+
$event->set( 'contact_name', $contact_name );
|
177 |
+
$event->set( 'contact_phone', $contact_phone );
|
178 |
+
$event->set( 'contact_email', $contact_email );
|
179 |
+
$event->set( 'contact_url', $contact_url );
|
180 |
+
$event->set( 'recurrence_rules', $rrule );
|
181 |
+
$event->set( 'exception_rules', $exrule );
|
182 |
+
$event->set( 'exception_dates', $exdate );
|
183 |
+
$event->set( 'recurrence_dates', $rdate );
|
184 |
+
$event->set( 'show_coordinates', $show_coordinates );
|
185 |
+
$event->set( 'longitude', trim( $longitude ) );
|
186 |
+
$event->set( 'latitude', trim( $latitude ) );
|
187 |
+
$event->set( 'ical_uid', $event->get_uid() );
|
188 |
+
|
189 |
+
return array(
|
190 |
+
'event' => $event,
|
191 |
+
'is_new' => $is_new
|
192 |
+
);
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Saves meta post data.
|
197 |
+
*
|
198 |
+
* @wp_hook save_post
|
199 |
+
*
|
200 |
+
* @param int $post_id Post ID.
|
201 |
+
* @param object $post Post object.
|
202 |
+
* @param update
|
203 |
+
*
|
204 |
+
* @return object|null Saved Ai1ec_Event object if successful or null.
|
205 |
+
*/
|
206 |
+
public function save_post( $post_id, $post, $update ) {
|
207 |
+
|
208 |
+
if ( false === $this->is_valid_event( $post ) ) {
|
209 |
+
return null;
|
210 |
+
}
|
211 |
+
|
212 |
+
// LABEL:magicquotes
|
213 |
+
// remove WordPress `magical` slashes - we work around it ourselves
|
214 |
+
$_POST = stripslashes_deep( $_POST );
|
215 |
+
|
216 |
+
$data = $this->_parse_post_to_event( $post_id );
|
217 |
+
if ( ! $data ) {
|
218 |
+
return null;
|
219 |
+
}
|
220 |
+
$event = $data['event'];
|
221 |
+
$is_new = $data[ 'is_new'];
|
222 |
+
|
223 |
+
$banner_image = isset( $_POST['ai1ec_banner_image'] ) ? $_POST['ai1ec_banner_image'] : '';
|
224 |
+
$cost_type = isset( $_POST['ai1ec_cost_type'] ) ? $_POST['ai1ec_cost_type'] : '';
|
225 |
+
|
226 |
+
update_post_meta( $post_id, 'ai1ec_banner_image', $banner_image );
|
227 |
+
if ( $cost_type ) {
|
228 |
+
update_post_meta( $post_id, '_ai1ec_cost_type', $cost_type );
|
229 |
+
}
|
230 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
231 |
+
if ( $update === false ) {
|
232 |
+
//this method just creates the API event, the update action
|
233 |
+
//is treated by another hook (pre_update_event inside api )
|
234 |
+
if ( 'tickets' === $cost_type ) {
|
235 |
+
$result = $api->store_event( $event, $post, false );
|
236 |
+
if ( true !== $result ) {
|
237 |
+
$_POST['_ticket_store_event_error'] = $result;
|
238 |
+
} else {
|
239 |
+
update_post_meta(
|
240 |
+
$post_id,
|
241 |
+
'_ai1ec_timely_tickets_url',
|
242 |
+
$api->get_api_event_buy_ticket_url( $event->get( 'post_id' ) )
|
243 |
+
);
|
244 |
+
}
|
245 |
+
}
|
246 |
+
}
|
247 |
+
if ( 'tickets' === $cost_type ) {
|
248 |
+
update_post_meta(
|
249 |
+
$post_id,
|
250 |
+
'_ai1ec_timely_tickets_url',
|
251 |
+
$api->get_api_event_buy_ticket_url( $event->get( 'post_id' ) )
|
252 |
+
);
|
253 |
+
} else {
|
254 |
+
delete_post_meta(
|
255 |
+
$post_id,
|
256 |
+
'_ai1ec_timely_tickets_url'
|
257 |
+
);
|
258 |
+
}
|
259 |
+
|
260 |
+
// let other extensions save their fields.
|
261 |
+
do_action( 'ai1ec_save_post', $event );
|
262 |
+
|
263 |
+
$event->save( ! $is_new );
|
264 |
+
|
265 |
+
// LABEL:magicquotes
|
266 |
+
// restore `magic` WordPress quotes to maintain compatibility
|
267 |
+
$_POST = add_magic_quotes( $_POST );
|
268 |
+
|
269 |
+
$api = $this->_registry->get( 'model.api.api-registration' );
|
270 |
+
$api->check_settings();
|
271 |
+
|
272 |
+
return $event;
|
273 |
+
}
|
274 |
+
|
275 |
+
private function get_sendback_page( $post_id ) {
|
276 |
+
$sendback = wp_get_referer();
|
277 |
+
$page_base = Ai1ec_Wp_Uri_Helper::get_pagebase( $sendback ); //$_SERVER['REQUEST_URI'] );
|
278 |
+
if ( 'post.php' === $page_base ) {
|
279 |
+
return get_edit_post_link( $post_id, 'url' );
|
280 |
+
} else {
|
281 |
+
return admin_url( 'edit.php?post_type=ai1ec_event' );
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Handle PRE (ticket event) update.
|
287 |
+
* Just handle the Ticket Events, other kind of post are ignored
|
288 |
+
* @wp_hook pre_post_update
|
289 |
+
*
|
290 |
+
*/
|
291 |
+
public function pre_post_update ( $post_id, $new_post_data ) {
|
292 |
+
|
293 |
+
// LABEL:magicquotes
|
294 |
+
// remove WordPress `magical` slashes - we work around it ourselves
|
295 |
+
$_POST = stripslashes_deep( $_POST );
|
296 |
+
|
297 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
298 |
+
$action = $this->current_action();
|
299 |
+
switch( $action ) {
|
300 |
+
case 'inline-save': //quick edit from edit page
|
301 |
+
$fields = array();
|
302 |
+
if ( false === ai1ec_is_blank( $_REQUEST['post_title'] ) ) {
|
303 |
+
$fields['title'] = $_REQUEST['post_title'];
|
304 |
+
}
|
305 |
+
if ( false === ai1ec_is_blank( $_REQUEST['_status'] ) ) {
|
306 |
+
$fields['status'] = $_REQUEST['_status'];
|
307 |
+
}
|
308 |
+
if ( isset( $_REQUEST['keep_private'] ) && 'private' === $_REQUEST['keep_private'] ) {
|
309 |
+
$fields['visibility'] = 'private';
|
310 |
+
} else if ( isset( $_REQUEST['post_password'] ) && false === ai1ec_is_blank( $_REQUEST['post_password'] ) ) {
|
311 |
+
$fields['visibility'] = 'password';
|
312 |
+
}
|
313 |
+
if ( 0 < count( $fields ) ) {
|
314 |
+
$post = get_post( $post_id );
|
315 |
+
$ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
|
316 |
+
$message = $api->update_api_event_fields( $post, $fields, 'update', $ajax );
|
317 |
+
if ( null !== $message ) {
|
318 |
+
if ( $ajax ) {
|
319 |
+
wp_die( $message );
|
320 |
+
} else {
|
321 |
+
wp_redirect( $this->get_sendback_page( $post_id ) );
|
322 |
+
exit();
|
323 |
+
}
|
324 |
+
}
|
325 |
+
}
|
326 |
+
return;
|
327 |
+
case 'edit': //bulk edition from edit page
|
328 |
+
$fields = array();
|
329 |
+
if ( false === ai1ec_is_blank( $_REQUEST['_status'] ) ) {
|
330 |
+
$fields['status'] = $_REQUEST['_status'];
|
331 |
+
}
|
332 |
+
if ( 0 < count( $fields ) ) {
|
333 |
+
$post = get_post( $post_id );
|
334 |
+
$ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
|
335 |
+
$message = $api->update_api_event_fields( $post, $fields, 'update', $ajax );
|
336 |
+
if ( null !== $message ) {
|
337 |
+
if ( $ajax ) {
|
338 |
+
wp_die( $message );
|
339 |
+
} else {
|
340 |
+
wp_redirect( $this->get_sendback_page( $post_id ) );
|
341 |
+
exit();
|
342 |
+
}
|
343 |
+
}
|
344 |
+
}
|
345 |
+
return;
|
346 |
+
case 'editpost': //edition from post page
|
347 |
+
$new_post_data['ID'] = $post_id;
|
348 |
+
$post = new WP_Post( (object) $new_post_data );
|
349 |
+
if ( false === $this->is_valid_event( $post ) ) {
|
350 |
+
break;
|
351 |
+
}
|
352 |
+
$data = $this->_parse_post_to_event( $post_id );
|
353 |
+
if ( ! $data ) {
|
354 |
+
break;
|
355 |
+
}
|
356 |
+
$event = $data['event'];
|
357 |
+
$cost_type = isset( $_REQUEST['ai1ec_cost_type'] ) ? $_REQUEST['ai1ec_cost_type'] : '';
|
358 |
+
if ( 'tickets' === $cost_type ) {
|
359 |
+
$result = $api->store_event( $event, $post, true );
|
360 |
+
if ( true !== $result ) {
|
361 |
+
wp_redirect( $this->get_sendback_page( $post_id ) );
|
362 |
+
exit();
|
363 |
+
}
|
364 |
+
} else {
|
365 |
+
$message = $api->delete_api_event( $post_id, 'update', false );
|
366 |
+
if ( null !== $message ) {
|
367 |
+
wp_redirect( $this->get_sendback_page( $post_id ) );
|
368 |
+
exit();
|
369 |
+
}
|
370 |
+
}
|
371 |
+
break;
|
372 |
+
default:
|
373 |
+
break;
|
374 |
+
}
|
375 |
+
|
376 |
+
// LABEL:magicquotes
|
377 |
+
// restore `magic` WordPress quotes to maintain compatibility
|
378 |
+
$_POST = add_magic_quotes( $_POST );
|
379 |
}
|
380 |
|
381 |
protected function current_action() {
|
382 |
+
$action = '';
|
383 |
+
if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) {
|
384 |
+
$action = 'delete';
|
385 |
+
} else {
|
386 |
+
if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) {
|
387 |
+
$action = $_REQUEST['action'];
|
388 |
+
}
|
389 |
+
if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) {
|
390 |
+
$action = $_REQUEST['action2'];
|
391 |
+
}
|
392 |
+
}
|
393 |
+
return $action;
|
394 |
}
|
395 |
|
396 |
+
/**
|
397 |
+
* _create_duplicate_post method
|
398 |
+
*
|
399 |
+
* Create copy of event by calling {@uses wp_insert_post} function.
|
400 |
+
* Using 'post_parent' to add hierarchy.
|
401 |
+
*
|
402 |
+
* @param array $data Event instance data to copy
|
403 |
+
*
|
404 |
+
* @return int|bool New post ID or false on failure
|
405 |
+
**/
|
406 |
+
public function create_duplicate_post() {
|
407 |
+
if ( ! isset( $_POST['post_ID'] ) ) {
|
408 |
+
return false;
|
409 |
+
}
|
410 |
+
$clean_fields = array(
|
411 |
+
'ai1ec_repeat' => NULL,
|
412 |
+
'ai1ec_rrule' => '',
|
413 |
+
'ai1ec_exrule' => '',
|
414 |
+
'ai1ec_exdate' => '',
|
415 |
+
'post_ID' => NULL,
|
416 |
+
'post_name' => NULL,
|
417 |
+
'ai1ec_instance_id' => NULL,
|
418 |
+
);
|
419 |
+
$old_post_id = $_POST['post_ID'];
|
420 |
+
$instance_id = $_POST['ai1ec_instance_id'];
|
421 |
+
foreach ( $clean_fields as $field => $to_value ) {
|
422 |
+
if ( NULL === $to_value ) {
|
423 |
+
unset( $_POST[$field] );
|
424 |
+
} else {
|
425 |
+
$_POST[$field] = $to_value;
|
426 |
+
}
|
427 |
+
}
|
428 |
+
$_POST = _wp_translate_postdata( false, $_POST );
|
429 |
+
$_POST['post_parent'] = $old_post_id;
|
430 |
+
$post_id = wp_insert_post( $_POST );
|
431 |
+
$this->_registry->get( 'model.event.parent' )->event_parent(
|
432 |
+
$post_id,
|
433 |
+
$old_post_id,
|
434 |
+
$instance_id
|
435 |
+
);
|
436 |
+
return $post_id;
|
437 |
+
}
|
438 |
+
|
439 |
+
/**
|
440 |
+
* Cleans calendar shortcodes from event content.
|
441 |
+
*
|
442 |
+
* @param array $data An array of slashed post data.
|
443 |
+
* @param array $postarr An array of sanitized, but otherwise unmodified post data.
|
444 |
+
*
|
445 |
+
* @return array An array of slashed post data.
|
446 |
+
*/
|
447 |
+
public function wp_insert_post_data( $data ) {
|
448 |
+
global $shortcode_tags;
|
449 |
+
if (
|
450 |
+
! isset( $data['post_type'] ) ||
|
451 |
+
! isset( $data['post_content'] ) ||
|
452 |
+
AI1EC_POST_TYPE !== $data['post_type'] ||
|
453 |
+
empty( $shortcode_tags ) ||
|
454 |
+
! is_array( $shortcode_tags ) ||
|
455 |
+
false === strpos( $data['post_content'], '[' )
|
456 |
+
) {
|
457 |
+
return $data;
|
458 |
+
}
|
459 |
+
$pattern = get_shortcode_regex();
|
460 |
+
$data['post_content'] = preg_replace_callback(
|
461 |
+
"/$pattern/s",
|
462 |
+
array( $this, 'strip_shortcode_tag' ),
|
463 |
+
$data['post_content']
|
464 |
+
);
|
465 |
+
return $data;
|
466 |
+
}
|
467 |
+
|
468 |
+
/**
|
469 |
+
* Reutrns shortcode or stripped content for given shortcode.
|
470 |
+
* Currently regex callback function passes as $tag argument 7-element long
|
471 |
+
* array.
|
472 |
+
* First element ($tag[0]) is not modified full shortcode text.
|
473 |
+
* Third element ($tag[2]) is pure shortcode identifier.
|
474 |
+
* Sixth element ($tag[5]) contains shortcode content if any
|
475 |
+
* [ai1ec_test]content[/ai1ec].
|
476 |
+
*
|
477 |
+
* @param array $tag Incoming data.
|
478 |
+
*
|
479 |
+
* @return string Shortcode replace tag.
|
480 |
+
*/
|
481 |
+
public function strip_shortcode_tag( $tag ) {
|
482 |
+
if (
|
483 |
+
count( $tag ) < 7 ||
|
484 |
+
'ai1ec' !== substr( $tag[2], 0, 5 ) ||
|
485 |
+
! apply_filters( 'ai1ec_content_remove_shortcode_' . $tag[2], false )
|
486 |
+
) {
|
487 |
+
return $tag[0];
|
488 |
+
}
|
489 |
+
return $tag[5];
|
490 |
+
}
|
491 |
+
|
492 |
+
protected function _remap_recurrence_dates() {
|
493 |
+
if (
|
494 |
+
isset( $_POST['ai1ec_exclude'] ) &&
|
495 |
+
'EXDATE' === substr( $_POST['ai1ec_exrule'], 0, 6 )
|
496 |
+
) {
|
497 |
+
$_POST['ai1ec_exdate'] = substr( $_POST['ai1ec_exrule'], 7 );
|
498 |
+
unset( $_POST['ai1ec_exclude'], $_POST['ai1ec_exrule'] );
|
499 |
+
}
|
500 |
+
if (
|
501 |
+
isset( $_POST['ai1ec_repeat'] ) &&
|
502 |
+
'RDATE' === substr( $_POST['ai1ec_rrule'], 0, 5 )
|
503 |
+
) {
|
504 |
+
$_POST['ai1ec_rdate'] = substr( $_POST['ai1ec_rrule'], 6 );
|
505 |
+
unset( $_POST['ai1ec_repeat'], $_POST['ai1ec_rrule'] );
|
506 |
+
}
|
507 |
+
}
|
508 |
|
509 |
}
|
app/model/event/entity.php
CHANGED
@@ -11,361 +11,361 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Event_Entity extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
|
370 |
|
371 |
}
|
11 |
*/
|
12 |
class Ai1ec_Event_Entity extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* Get list of object properties.
|
16 |
+
*
|
17 |
+
* Special value `registry` ({@see Ai1ec_Registry_Object}) is excluded.
|
18 |
+
*
|
19 |
+
* @return array List of accessible properties.
|
20 |
+
*
|
21 |
+
* @staticvar array $known List of properties.
|
22 |
+
*/
|
23 |
+
public function list_properties() {
|
24 |
+
static $known = null;
|
25 |
+
if ( null === $known ) {
|
26 |
+
$known = array();
|
27 |
+
foreach ( $this as $name => $value ) {
|
28 |
+
$name = substr( $name, 1 );
|
29 |
+
if ( 'registry' === $name ) {
|
30 |
+
continue;
|
31 |
+
}
|
32 |
+
$known[] = $name;
|
33 |
+
}
|
34 |
+
}
|
35 |
+
return $known;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Handle cloning properly to resist property changes.
|
40 |
+
*
|
41 |
+
* @return void
|
42 |
+
*/
|
43 |
+
public function __clone() {
|
44 |
+
$this->_start = $this->_registry->get( 'date.time', $this->_start );
|
45 |
+
$this->_end = $this->_registry->get( 'date.time', $this->_end );
|
46 |
+
$this->_post = clone $this->_post;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Change stored property.
|
51 |
+
*
|
52 |
+
* @param string $name Name of property to change.
|
53 |
+
* @param mixed $value Arbitrary value to use.
|
54 |
+
*
|
55 |
+
* @return Ai1ec_Event_Entity Instance of self for chaining.
|
56 |
+
*
|
57 |
+
* @staticvar array $time_fields Map of fields holding a value of
|
58 |
+
* {@see Ai1ec_Date_Time}, which
|
59 |
+
* require modification instead of
|
60 |
+
* replacement.
|
61 |
+
*/
|
62 |
+
public function set( $name, $value ) {
|
63 |
+
static $time_fields = array(
|
64 |
+
'start' => true,
|
65 |
+
'end' => true,
|
66 |
+
);
|
67 |
+
if ( 'registry' === $name ) {
|
68 |
+
return $this; // short-circuit: protection mean.
|
69 |
+
}
|
70 |
+
if ( 'timezone_name' === $name && empty( $value ) ) {
|
71 |
+
return $this; // protection against invalid TZ values.
|
72 |
+
}
|
73 |
+
$field = '_' . $name;
|
74 |
+
if ( isset( $time_fields[$name] ) ) {
|
75 |
+
// object of Ai1ec_Date_Time type is now handled in it itself
|
76 |
+
$this->{$field}->set_date_time(
|
77 |
+
$value,
|
78 |
+
( null === $this->_timezone_name )
|
79 |
+
? 'UTC'
|
80 |
+
: $this->_timezone_name
|
81 |
+
);
|
82 |
+
$this->adjust_preferred_timezone();
|
83 |
+
} else {
|
84 |
+
$this->{$field} = $value;
|
85 |
+
}
|
86 |
+
if ( 'timezone_name' === $name ) {
|
87 |
+
$this->_start->set_timezone( $value );
|
88 |
+
$this->_end ->set_timezone( $value );
|
89 |
+
$this->adjust_preferred_timezone();
|
90 |
+
}
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Optionally adjust preferred (display) timezone.
|
96 |
+
*
|
97 |
+
* @return bool|DateTimeZone False or new timezone.
|
98 |
+
*
|
99 |
+
* @staticvar bool $do_adjust True when adjustment should be performed.
|
100 |
+
*/
|
101 |
+
public function adjust_preferred_timezone() {
|
102 |
+
static $do_adjust = null;
|
103 |
+
if ( null === $do_adjust ) {
|
104 |
+
$do_adjust = !$this->_registry
|
105 |
+
->get( 'model.settings' )
|
106 |
+
->get( 'always_use_calendar_timezone', false );
|
107 |
+
}
|
108 |
+
if ( ! $do_adjust ) {
|
109 |
+
return false;
|
110 |
+
}
|
111 |
+
$timezone = $this->_registry->get( 'date.timezone' )->get(
|
112 |
+
$this->_timezone_name
|
113 |
+
);
|
114 |
+
$this->set_preferred_timezone( $timezone );
|
115 |
+
return $timezone;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Set preferred timezone to datetime fields.
|
120 |
+
*
|
121 |
+
* @param DateTimeZone $timezone Preferred timezone instance.
|
122 |
+
*
|
123 |
+
* @return void
|
124 |
+
*/
|
125 |
+
public function set_preferred_timezone( DateTimeZone $timezone ) {
|
126 |
+
$this->_start->set_preferred_timezone( $timezone );
|
127 |
+
$this->_end ->set_preferred_timezone( $timezone );
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Get a value of some property.
|
132 |
+
*
|
133 |
+
* @param string $name Name of property to get.
|
134 |
+
* @param mixed $default Value to return if property is not defined.
|
135 |
+
*
|
136 |
+
* @return mixed Found value or $default.
|
137 |
+
*/
|
138 |
+
public function get( $name, $default = null ) {
|
139 |
+
if ( ! isset( $this->{ '_' . $name } ) ) {
|
140 |
+
return $default;
|
141 |
+
}
|
142 |
+
return $this->{ '_' . $name };
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Initialize values to some sane defaults.
|
147 |
+
*
|
148 |
+
* @param Ai1ec_Registry_Object $registry Injected registry.
|
149 |
+
*
|
150 |
+
* @return void
|
151 |
+
*/
|
152 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
153 |
+
parent::__construct( $registry );
|
154 |
+
$this->_start = $this->_registry->get( 'date.time' );
|
155 |
+
$this->_end = $this->_registry->get( 'date.time', '+1 hour' );
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* @var object Instance of WP_Post object.
|
160 |
+
*/
|
161 |
+
private $_post;
|
162 |
+
|
163 |
+
/**
|
164 |
+
* @var int Post ID.
|
165 |
+
*/
|
166 |
+
private $_post_id;
|
167 |
+
|
168 |
+
/**
|
169 |
+
* @var int|null Uniquely identifies the recurrence instance of this event
|
170 |
+
* object. Value may be null.
|
171 |
+
*/
|
172 |
+
private $_instance_id;
|
173 |
+
|
174 |
+
/**
|
175 |
+
* @var string Name of timezone to use for event times.
|
176 |
+
*/
|
177 |
+
private $_timezone_name;
|
178 |
+
|
179 |
+
/**
|
180 |
+
* @var Ai1ec_Date_Time Start date-time specifier
|
181 |
+
*/
|
182 |
+
private $_start;
|
183 |
+
|
184 |
+
/**
|
185 |
+
* @var Ai1ec_Date_Time End date-time specifier
|
186 |
+
*/
|
187 |
+
private $_end;
|
188 |
+
|
189 |
+
/**
|
190 |
+
* @var bool Whether this copy of the event was broken up for rendering and
|
191 |
+
* the start time is not its "real" start time.
|
192 |
+
*/
|
193 |
+
private $_start_truncated;
|
194 |
+
|
195 |
+
/**
|
196 |
+
* @var bool Whether this copy of the event was broken up for rendering and
|
197 |
+
* the end time is not its "real" end time.
|
198 |
+
*/
|
199 |
+
private $_end_truncated;
|
200 |
+
|
201 |
+
/**
|
202 |
+
* @var int If event is all-day long
|
203 |
+
*/
|
204 |
+
private $_allday;
|
205 |
+
|
206 |
+
/**
|
207 |
+
* @var int If event has no duration
|
208 |
+
*/
|
209 |
+
private $_instant_event;
|
210 |
+
|
211 |
+
/**
|
212 |
+
* ==========================
|
213 |
+
* = Recurrence information =
|
214 |
+
* ==========================
|
215 |
+
*/
|
216 |
+
|
217 |
+
/**
|
218 |
+
* @var string Recurrence rules
|
219 |
+
*/
|
220 |
+
private $_recurrence_rules;
|
221 |
+
|
222 |
+
/**
|
223 |
+
* @var string Exception rules
|
224 |
+
*/
|
225 |
+
private $_exception_rules;
|
226 |
+
|
227 |
+
/**
|
228 |
+
* @var string Recurrence dates
|
229 |
+
*/
|
230 |
+
private $_recurrence_dates;
|
231 |
+
|
232 |
+
/**
|
233 |
+
* @var string Exception dates
|
234 |
+
*/
|
235 |
+
private $_exception_dates;
|
236 |
+
|
237 |
+
/**
|
238 |
+
* @var string Venue name - free text
|
239 |
+
*/
|
240 |
+
private $_venue;
|
241 |
+
|
242 |
+
/**
|
243 |
+
* @var string Country name - free text
|
244 |
+
*/
|
245 |
+
private $_country;
|
246 |
+
|
247 |
+
/**
|
248 |
+
* @var string Address information - free text
|
249 |
+
*/
|
250 |
+
private $_address;
|
251 |
+
|
252 |
+
/**
|
253 |
+
* @var string City name - free text
|
254 |
+
*/
|
255 |
+
private $_city;
|
256 |
+
|
257 |
+
/**
|
258 |
+
* @var string Province free text definition
|
259 |
+
*/
|
260 |
+
private $_province;
|
261 |
+
|
262 |
+
/**
|
263 |
+
* @var int Postal code
|
264 |
+
*/
|
265 |
+
private $_postal_code;
|
266 |
+
|
267 |
+
/**
|
268 |
+
* @var int Set to true to display map
|
269 |
+
*/
|
270 |
+
private $_show_map;
|
271 |
+
|
272 |
+
/**
|
273 |
+
* @var int Set to true to show coordinates in description
|
274 |
+
*/
|
275 |
+
private $_show_coordinates;
|
276 |
+
|
277 |
+
/**
|
278 |
+
* @var float GEO information - longitude
|
279 |
+
*/
|
280 |
+
private $_longitude;
|
281 |
+
|
282 |
+
/**
|
283 |
+
* @var float GEO information - latitude
|
284 |
+
*/
|
285 |
+
private $_latitude;
|
286 |
+
|
287 |
+
/**
|
288 |
+
* @var string Event contact information - contact person
|
289 |
+
*/
|
290 |
+
private $_contact_name;
|
291 |
+
|
292 |
+
/**
|
293 |
+
* @var string Event contact information - phone number
|
294 |
+
*/
|
295 |
+
private $_contact_phone;
|
296 |
+
|
297 |
+
/**
|
298 |
+
* @var string Event contact information - email address
|
299 |
+
*/
|
300 |
+
private $_contact_email;
|
301 |
+
|
302 |
+
/**
|
303 |
+
* @var string Event contact information - external URL.
|
304 |
+
*/
|
305 |
+
private $_contact_url;
|
306 |
+
|
307 |
+
/**
|
308 |
+
* @var string Defines event cost.
|
309 |
+
*/
|
310 |
+
private $_cost;
|
311 |
+
|
312 |
+
/**
|
313 |
+
* @var bool Indicates, whereas event is free.
|
314 |
+
*/
|
315 |
+
private $_is_free;
|
316 |
+
|
317 |
+
/**
|
318 |
+
* @var string Link to buy tickets
|
319 |
+
*/
|
320 |
+
private $_ticket_url;
|
321 |
+
|
322 |
+
// ====================================
|
323 |
+
// = iCalendar feed (.ics) properties =
|
324 |
+
// ====================================
|
325 |
+
|
326 |
+
/**
|
327 |
+
* @var string URI of source ICAL feed.
|
328 |
+
*/
|
329 |
+
private $_ical_feed_url;
|
330 |
+
|
331 |
+
/**
|
332 |
+
* @var string|null URI of source ICAL entity.
|
333 |
+
*/
|
334 |
+
private $_ical_source_url;
|
335 |
+
|
336 |
+
/**
|
337 |
+
* @var string Organiser details
|
338 |
+
*/
|
339 |
+
private $_ical_organizer;
|
340 |
+
|
341 |
+
/**
|
342 |
+
* @var string Contact details
|
343 |
+
*/
|
344 |
+
private $_ical_contact;
|
345 |
+
|
346 |
+
/**
|
347 |
+
* @var string|int UID of ICAL feed
|
348 |
+
*/
|
349 |
+
private $_ical_uid;
|
350 |
+
|
351 |
+
// ===============================
|
352 |
+
// = taxonomy-related properties =
|
353 |
+
// ===============================
|
354 |
+
|
355 |
+
/**
|
356 |
+
* @var string Associated event tag names (*not* IDs), joined by commas.
|
357 |
+
*/
|
358 |
+
private $_tags;
|
359 |
+
|
360 |
+
/**
|
361 |
+
* @var string Associated event category IDs, joined by commas.
|
362 |
+
*/
|
363 |
+
private $_categories;
|
364 |
+
|
365 |
+
/**
|
366 |
+
* @var string Associated event feed object
|
367 |
+
*/
|
368 |
+
private $_feed;
|
369 |
|
370 |
|
371 |
}
|
app/model/event/instance.php
CHANGED
@@ -11,397 +11,397 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Event_Instance extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
|
177 |
-
|
178 |
-
|
179 |
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
|
317 |
-
|
318 |
-
|
319 |
|
320 |
-
|
321 |
-
|
322 |
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
|
363 |
-
|
364 |
-
|
365 |
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
}
|
11 |
*/
|
12 |
class Ai1ec_Event_Instance extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var Ai1ec_Dbi Instance of database abstraction.
|
16 |
+
*/
|
17 |
+
protected $_dbi = null;
|
18 |
|
19 |
+
/**
|
20 |
+
* DBI utils.
|
21 |
+
*
|
22 |
+
* @var Ai1ec_Dbi_Utils
|
23 |
+
*/
|
24 |
+
protected $_dbi_utils;
|
25 |
|
26 |
+
/**
|
27 |
+
* Store locally instance of Ai1ec_Dbi.
|
28 |
+
*
|
29 |
+
* @param Ai1ec_Registry_Object $registry Injected object registry.
|
30 |
+
*
|
31 |
+
*/
|
32 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
33 |
+
parent::__construct( $registry );
|
34 |
+
$this->_dbi = $this->_registry->get( 'dbi.dbi' );
|
35 |
+
$this->_dbi_utils = $this->_registry->get( 'dbi.dbi-utils' );
|
36 |
+
}
|
37 |
|
38 |
+
/**
|
39 |
+
* Remove entries for given post. Optionally delete particular instance.
|
40 |
+
*
|
41 |
+
* @param int $post_id Event ID to remove instances for.
|
42 |
+
* @param int|null $instance_id Instance ID, or null for all.
|
43 |
+
*
|
44 |
+
* @return int|bool Number of entries removed, or false on failure.
|
45 |
+
*/
|
46 |
+
public function clean( $post_id, $instance_id = null ) {
|
47 |
+
$where = array( 'post_id' => $post_id );
|
48 |
+
$format = array( '%d' );
|
49 |
+
if ( null !== $instance_id ) {
|
50 |
+
$where['id'] = $instance_id;
|
51 |
+
$format[] = '%d';
|
52 |
+
}
|
53 |
+
return $this->_dbi->delete( 'ai1ec_event_instances', $where, $format );
|
54 |
+
}
|
55 |
|
56 |
+
/**
|
57 |
+
* Remove and then create instance entries for given event.
|
58 |
+
*
|
59 |
+
* @param Ai1ec_Event $event Instance of event to recreate entries for.
|
60 |
+
*
|
61 |
+
* @return bool Success.
|
62 |
+
*/
|
63 |
+
public function recreate( Ai1ec_Event $event ) {
|
64 |
+
$old_instances = $this->_load_instances( $event->get( 'post_id' ) );
|
65 |
+
$instances = $this->_create_instances_collection( $event );
|
66 |
+
$insert = array();
|
67 |
+
foreach ( $instances as $instance ) {
|
68 |
+
if ( ! isset( $old_instances[$instance['start'] . ':' . $instance['end']] ) ) {
|
69 |
+
$insert[] = $instance;
|
70 |
+
continue;
|
71 |
+
}
|
72 |
+
unset( $old_instances[$instance['start'] . ':' . $instance['end']] );
|
73 |
+
}
|
74 |
+
$this->_remove_instances_by_ids( array_values( $old_instances ) );
|
75 |
+
$this->_add_instances( $insert );
|
76 |
+
return true;
|
77 |
+
}
|
78 |
|
79 |
+
/**
|
80 |
+
* Create list of recurrent instances.
|
81 |
+
*
|
82 |
+
* @param Ai1ec_Event $event Event to generate instances for.
|
83 |
+
* @param array $event_instance First instance contents.
|
84 |
+
* @param int $_start Timestamp of first occurence.
|
85 |
+
* @param int $duration Event duration in seconds.
|
86 |
+
* @param string $timezone Target timezone.
|
87 |
+
*
|
88 |
+
* @return array List of event instances.
|
89 |
+
*/
|
90 |
+
public function create_instances_by_recurrence(
|
91 |
+
Ai1ec_Event $event,
|
92 |
+
array $event_instance,
|
93 |
+
$_start,
|
94 |
+
$duration,
|
95 |
+
$timezone
|
96 |
+
) {
|
97 |
+
$restore_timezone = date_default_timezone_get();
|
98 |
+
$recurrence_parser = $this->_registry->get( 'recurrence.rule' );
|
99 |
+
$events = array();
|
100 |
|
101 |
+
$start = $event_instance['start'];
|
102 |
+
$wdate = $startdate = $enddate
|
103 |
+
= $this->_parsed_date_array( $_start, $timezone );
|
104 |
+
$enddate['year'] = $enddate['year'] + 10;
|
105 |
+
$exclude_dates = array();
|
106 |
+
$recurrence_dates = array();
|
107 |
+
if ( $recurrence_dates = $event->get( 'recurrence_dates' ) ) {
|
108 |
+
$recurrence_dates = $this->_populate_recurring_dates(
|
109 |
+
$recurrence_dates,
|
110 |
+
$startdate,
|
111 |
+
$timezone
|
112 |
+
);
|
113 |
+
}
|
114 |
+
if ( $exception_dates = $event->get( 'exception_dates' ) ) {
|
115 |
+
$exclude_dates = $this->_populate_recurring_dates(
|
116 |
+
$exception_dates,
|
117 |
+
$startdate,
|
118 |
+
$timezone
|
119 |
+
);
|
120 |
+
}
|
121 |
+
if ( $event->get( 'exception_rules' ) ) {
|
122 |
+
// creat an array for the rules
|
123 |
+
$exception_rules = $recurrence_parser
|
124 |
+
->build_recurrence_rules_array(
|
125 |
+
$event->get( 'exception_rules' )
|
126 |
+
);
|
127 |
+
unset($exception_rules['EXDATE']);
|
128 |
+
if ( ! empty( $exception_rules ) ) {
|
129 |
+
$exception_rules = iCalUtilityFunctions::_setRexrule(
|
130 |
+
$exception_rules
|
131 |
+
);
|
132 |
+
$result = array();
|
133 |
+
date_default_timezone_set( $timezone );
|
134 |
+
// The first array is the result and it is passed by reference
|
135 |
+
iCalUtilityFunctions::_recur2date(
|
136 |
+
$exclude_dates,
|
137 |
+
$exception_rules,
|
138 |
+
$wdate,
|
139 |
+
$startdate,
|
140 |
+
$enddate
|
141 |
+
);
|
142 |
+
date_default_timezone_set( $restore_timezone );
|
143 |
+
}
|
144 |
+
}
|
145 |
+
$recurrence_rules = $recurrence_parser
|
146 |
+
->build_recurrence_rules_array(
|
147 |
+
$event->get( 'recurrence_rules' )
|
148 |
+
);
|
149 |
|
150 |
+
$recurrence_rules = iCalUtilityFunctions::_setRexrule( $recurrence_rules );
|
151 |
+
if ( $recurrence_rules ) {
|
152 |
+
date_default_timezone_set( $timezone );
|
153 |
+
iCalUtilityFunctions::_recur2date(
|
154 |
+
$recurrence_dates,
|
155 |
+
$recurrence_rules,
|
156 |
+
$wdate,
|
157 |
+
$startdate,
|
158 |
+
$enddate
|
159 |
+
);
|
160 |
+
date_default_timezone_set( $restore_timezone );
|
161 |
+
}
|
162 |
|
163 |
+
if ( ! is_array( $recurrence_dates ) ) {
|
164 |
+
$recurrence_dates = array();
|
165 |
+
}
|
166 |
+
$recurrence_dates = array_keys( $recurrence_dates );
|
167 |
+
// Add the instances
|
168 |
+
foreach ( $recurrence_dates as $timestamp ) {
|
169 |
+
// The arrays are in the form timestamp => true so an isset call is what we need
|
170 |
+
if ( ! isset( $exclude_dates[$timestamp] ) ) {
|
171 |
+
$event_instance['start'] = $timestamp;
|
172 |
+
$event_instance['end'] = $timestamp + $duration;
|
173 |
+
$events[$timestamp] = $event_instance;
|
174 |
+
}
|
175 |
+
}
|
176 |
|
177 |
+
return $events;
|
178 |
+
}
|
179 |
|
180 |
+
/**
|
181 |
+
* Generate and store instance entries in database for given event.
|
182 |
+
*
|
183 |
+
* @param Ai1ec_Event $event Instance of event to create entries for.
|
184 |
+
*
|
185 |
+
* @return bool Success.
|
186 |
+
*/
|
187 |
+
public function create( Ai1ec_Event $event ) {
|
188 |
+
$instances = $this->_create_instances_collection( $event );
|
189 |
+
$this->_add_instances( $instances );
|
190 |
+
return true;
|
191 |
+
}
|
192 |
|
193 |
+
/**
|
194 |
+
* Check if given date match dates in EXDATES rule.
|
195 |
+
*
|
196 |
+
* @param string $date Date to check.
|
197 |
+
* @param string $ics_rule ICS EXDATES rule.
|
198 |
+
* @param string $timezone Timezone to evaluate value in.
|
199 |
+
*
|
200 |
+
* @return bool True if given date is in rule.
|
201 |
+
*/
|
202 |
+
public function date_match_exdates( $date, $ics_rule, $timezone ) {
|
203 |
+
$ranges = $this->_get_date_ranges( $ics_rule, $timezone );
|
204 |
+
foreach ( $ranges as $interval ) {
|
205 |
+
if ( $date >= $interval[0] && $date <= $interval[1] ) {
|
206 |
+
return true;
|
207 |
+
}
|
208 |
+
if ( $date <= $interval[0] ) {
|
209 |
+
break;
|
210 |
+
}
|
211 |
+
}
|
212 |
+
return false;
|
213 |
+
}
|
214 |
|
215 |
+
/**
|
216 |
+
* Prepare date range list for fast exdate search.
|
217 |
+
*
|
218 |
+
* NOTICE: timezone is relevant in only first run.
|
219 |
+
*
|
220 |
+
* @param string $date_list ICS list provided from data model.
|
221 |
+
* @param string $timezone Timezone in which to evaluate.
|
222 |
+
*
|
223 |
+
* @return array List of date ranges, sorted in increasing order.
|
224 |
+
*/
|
225 |
+
protected function _get_date_ranges( $date_list, $timezone ) {
|
226 |
+
static $ranges = array();
|
227 |
+
if ( ! isset( $ranges[$date_list] ) ) {
|
228 |
+
$ranges[$date_list] = array();
|
229 |
+
$exploded = explode( ',', $date_list );
|
230 |
+
sort( $exploded );
|
231 |
+
foreach ( $exploded as $date ) {
|
232 |
+
// COMMENT on `rtrim( $date, 'Z' )`:
|
233 |
+
// user selects exclusion date in event timezone thus it
|
234 |
+
// must be parsed as such as opposed to UTC which happen
|
235 |
+
// when 'Z' is preserved.
|
236 |
+
$date = $this->_registry
|
237 |
+
->get( 'date.time', rtrim( $date, 'Z' ), $timezone )
|
238 |
+
->format_to_gmt();
|
239 |
+
$ranges[$date_list][] = array(
|
240 |
+
$date,
|
241 |
+
$date + (24 * 60 * 60) - 1
|
242 |
+
);
|
243 |
+
}
|
244 |
+
}
|
245 |
+
return $ranges[$date_list];
|
246 |
+
}
|
247 |
|
248 |
+
protected function _populate_recurring_dates( $rule, array $start_struct, $timezone ) {
|
249 |
+
$start = clone $start_struct['_dt'];
|
250 |
+
$dates = array();
|
251 |
+
foreach ( explode( ',', $rule ) as $date ) {
|
252 |
+
$i_date = clone $start;
|
253 |
+
$spec = sscanf( $date, '%04d%02d%02d' );
|
254 |
+
$i_date->set_date(
|
255 |
+
$spec[0],
|
256 |
+
$spec[1],
|
257 |
+
$spec[2]
|
258 |
+
);
|
259 |
+
$dates[$i_date->format_to_gmt()] = $i_date;
|
260 |
+
}
|
261 |
+
return $dates;
|
262 |
+
}
|
263 |
|
264 |
+
protected function _parsed_date_array( $startdate, $timezone ) {
|
265 |
+
$datetime = $this->_registry->get( 'date.time', $startdate, $timezone );
|
266 |
+
$parsed = array(
|
267 |
+
'year' => intval( $datetime->format( 'Y' ) ),
|
268 |
+
'month' => intval( $datetime->format( 'm' ) ),
|
269 |
+
'day' => intval( $datetime->format( 'd' ) ),
|
270 |
+
'hour' => intval( $datetime->format( 'H' ) ),
|
271 |
+
'min' => intval( $datetime->format( 'i' ) ),
|
272 |
+
'sec' => intval( $datetime->format( 's' ) ),
|
273 |
+
'tz' => $datetime->get_timezone(),
|
274 |
+
'_dt' => $datetime,
|
275 |
+
);
|
276 |
+
return $parsed;
|
277 |
+
}
|
278 |
|
279 |
+
/**
|
280 |
+
* Returns current instances map.
|
281 |
+
*
|
282 |
+
* @param int post_id Post ID.
|
283 |
+
*
|
284 |
+
* @return array Array of data.
|
285 |
+
*/
|
286 |
+
protected function _load_instances( $post_id ) {
|
287 |
+
$query = $this->_dbi->prepare(
|
288 |
+
'SELECT `id`, `start`, `end` FROM ' .
|
289 |
+
$this->_dbi->get_table_name( 'ai1ec_event_instances' ) .
|
290 |
+
' WHERE post_id = %d',
|
291 |
+
$post_id
|
292 |
+
);
|
293 |
+
$results = $this->_dbi->get_results( $query );
|
294 |
+
$instances = array();
|
295 |
+
foreach ( $results as $result ) {
|
296 |
+
$instances[(int)$result->start . ':' . (int)$result->end] = (int)$result->id;
|
297 |
+
}
|
298 |
+
return $instances;
|
299 |
+
}
|
300 |
|
301 |
+
/**
|
302 |
+
* Generate and store instance entries in database for given event.
|
303 |
+
*
|
304 |
+
* @param Ai1ec_Event $event Instance of event to create entries for.
|
305 |
+
*
|
306 |
+
* @return bool Success.
|
307 |
+
*/
|
308 |
+
protected function _create_instances_collection( Ai1ec_Event $event ) {
|
309 |
+
$events = array();
|
310 |
+
$event_item = array(
|
311 |
+
'post_id' => $event->get( 'post_id' ),
|
312 |
+
'start' => $event->get( 'start' )->format_to_gmt(),
|
313 |
+
'end' => $event->get( 'end' )->format_to_gmt(),
|
314 |
+
);
|
315 |
+
$duration = $event->get( 'end' )->diff_sec( $event->get( 'start' ) );
|
316 |
|
317 |
+
$_start = $event->get( 'start' )->format_to_gmt();
|
318 |
+
$_end = $event->get( 'end' )->format_to_gmt();
|
319 |
|
320 |
+
// Always cache initial instance
|
321 |
+
$events[$_start] = $event_item;
|
322 |
|
323 |
+
if ( $event->get( 'recurrence_rules' ) || $event->get( 'recurrence_dates' ) ) {
|
324 |
+
$start_timezone = $this->_registry->get( 'model.option' )
|
325 |
+
->get( 'timezone_string' );
|
326 |
+
if ( empty( $start_timezone ) ) {
|
327 |
+
$start_timezone = $this->_registry->get( 'date.timezone' )->get_default_timezone();
|
328 |
+
}
|
329 |
|
330 |
+
$events += $this->create_instances_by_recurrence(
|
331 |
+
$event,
|
332 |
+
$event_item,
|
333 |
+
$_start,
|
334 |
+
$duration,
|
335 |
+
$start_timezone
|
336 |
+
);
|
337 |
+
}
|
338 |
|
339 |
+
$search_helper = $this->_registry->get( 'model.search' );
|
340 |
+
foreach ( $events as &$event_item ) {
|
341 |
+
// Find out if this event instance is already accounted for by an
|
342 |
+
// overriding 'RECURRENCE-ID' of the same iCalendar feed (by comparing the
|
343 |
+
// UID, start date, recurrence). If so, then do not create duplicate
|
344 |
+
// instance of event.
|
345 |
+
$start = $event_item['start'];
|
346 |
+
$matching_event_id = null;
|
347 |
+
if ( $event->get( 'ical_uid' ) ) {
|
348 |
+
$matching_event_id = $search_helper->get_matching_event_id(
|
349 |
+
$event->get( 'ical_uid' ),
|
350 |
+
$event->get( 'ical_feed_url' ),
|
351 |
+
$event->get( 'start' ),
|
352 |
+
false,
|
353 |
+
$event->get( 'post_id' )
|
354 |
+
);
|
355 |
+
}
|
356 |
|
357 |
+
// If no other instance was found
|
358 |
+
if ( null !== $matching_event_id ) {
|
359 |
+
$event_item = false;
|
360 |
+
}
|
361 |
+
}
|
362 |
|
363 |
+
return array_filter( $events );
|
364 |
+
}
|
365 |
|
366 |
+
/**
|
367 |
+
* Removes ai1ec_event_instances entries using their IDS.
|
368 |
+
*
|
369 |
+
* @param array $ids Collection of IDS.
|
370 |
+
*
|
371 |
+
* @return bool Result.
|
372 |
+
*/
|
373 |
+
protected function _remove_instances_by_ids( array $ids ) {
|
374 |
+
if ( empty( $ids ) ) {
|
375 |
+
return false;
|
376 |
+
}
|
377 |
+
$query = 'DELETE FROM ' . $this->_dbi->get_table_name(
|
378 |
+
'ai1ec_event_instances'
|
379 |
+
) . ' WHERE id IN (';
|
380 |
+
$ids = array_filter( array_map( 'intval', $ids ) );
|
381 |
+
$query .= implode( ',', $ids ) . ')';
|
382 |
+
$this->_dbi->query( $query );
|
383 |
+
return true;
|
384 |
+
}
|
385 |
|
386 |
+
/**
|
387 |
+
* Adds new instances collection.
|
388 |
+
*
|
389 |
+
* @param array $instances Collection of instances.
|
390 |
+
*
|
391 |
+
* @return void
|
392 |
+
*/
|
393 |
+
protected function _add_instances( array $instances ) {
|
394 |
+
$chunks = array_chunk( $instances, 50 );
|
395 |
+
foreach ( $chunks as $chunk ) {
|
396 |
+
$query = 'INSERT INTO ' . $this->_dbi->get_table_name(
|
397 |
+
'ai1ec_event_instances'
|
398 |
+
) . '(`post_id`, `start`, `end`) VALUES';
|
399 |
+
$chunk = array_map(
|
400 |
+
array( $this->_dbi_utils, 'array_value_to_sql_value' ),
|
401 |
+
$chunk
|
402 |
+
);
|
403 |
+
$query .= implode( ',', $chunk );
|
404 |
+
$this->_dbi->query( $query );
|
405 |
+
}
|
406 |
+
}
|
407 |
}
|
app/model/event/legacy.php
CHANGED
@@ -11,138 +11,138 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Event_Legacy extends Ai1ec_Event {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
|
148 |
}
|
11 |
*/
|
12 |
class Ai1ec_Event_Legacy extends Ai1ec_Event {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var array map of method => class for legacy code.
|
16 |
+
*/
|
17 |
+
protected static $_classes = array(
|
18 |
+
'get_category_colors' => 'taxonomy',
|
19 |
+
'get_color_style' => 'taxonomy',
|
20 |
+
'get_categories_html' => 'taxonomy',
|
21 |
+
'get_tags_html' => 'taxonomy',
|
22 |
+
'get_category_text_color' => 'taxonomy',
|
23 |
+
'get_category_bg_color' => 'taxonomy',
|
24 |
+
'get_faded_color' => 'color',
|
25 |
+
'get_rgba_color' => 'color',
|
26 |
+
'get_event_avatar' => 'avatar',
|
27 |
+
'get_event_avatar_url' => 'avatar',
|
28 |
+
'get_post_thumbnail_url' => 'avatar',
|
29 |
+
'get_content_img_url' => 'avatar',
|
30 |
+
'get_short_location' => 'location',
|
31 |
+
'get_location' => 'location',
|
32 |
+
'get_map_view' => 'location',
|
33 |
+
'get_latlng' => 'location',
|
34 |
+
'get_gmap_url' => 'location',
|
35 |
+
'get_tickets_url_label' => 'ticket',
|
36 |
+
'get_contact_html' => 'ticket',
|
37 |
+
'get_timespan_html' => 'time',
|
38 |
+
'get_exclude_html' => 'time',
|
39 |
+
'get_back_to_calendar_button_html' => 'content',
|
40 |
+
'get_post_excerpt' => 'content',
|
41 |
+
);
|
42 |
|
43 |
+
public function get_long_end_date( $adjust = 0 ) {
|
44 |
+
$time = $this->_registry->get( 'view.event.time' );
|
45 |
+
$end = $this->_registry->get( 'date.time', $this->get( 'end' ) );
|
46 |
+
if ( ! empty( $adjust ) ) {
|
47 |
+
$end->set_time(
|
48 |
+
$end->format( 'H' ),
|
49 |
+
$end->format( 'i' ),
|
50 |
+
$adjust
|
51 |
+
);
|
52 |
+
}
|
53 |
+
return $time->get_long_date( $end );
|
54 |
+
}
|
55 |
|
56 |
+
public function get_long_start_date() {
|
57 |
+
$time = $this->_registry->get( 'view.event.time' );
|
58 |
+
return $time->get_long_date( $this->get( 'start' ) );
|
59 |
+
}
|
60 |
|
61 |
+
public function get_multiday() {
|
62 |
+
return $this->is_multiday();
|
63 |
+
}
|
64 |
|
65 |
+
public function get_recurrence_html() {
|
66 |
+
$rrule = $this->_registry->get( 'recurrence.rule' );
|
67 |
+
return $rrule->rrule_to_text( $this->get( 'recurrence_rules' ) );
|
68 |
+
}
|
69 |
|
70 |
+
public function get_short_end_date() {
|
71 |
+
$time = $this->_registry->get( 'view.event.time' );
|
72 |
+
$end = $this->_registry->get( 'date.time', $this->get( 'end' ) );
|
73 |
+
$end->set_time(
|
74 |
+
$end->format( 'H' ),
|
75 |
+
$end->format( 'i' ),
|
76 |
+
-1
|
77 |
+
);
|
78 |
+
return $time->get_short_date( $end );
|
79 |
+
}
|
80 |
|
81 |
+
public function get_short_end_time() {
|
82 |
+
$time = $this->_registry->get( 'view.event.time' );
|
83 |
+
return $time->get_short_time( $this->get( 'end' ) );
|
84 |
+
}
|
85 |
|
86 |
+
public function get_short_start_date() {
|
87 |
+
$time = $this->_registry->get( 'view.event.time' );
|
88 |
+
return $time->get_short_date( $this->get( 'start' ) );
|
89 |
+
}
|
90 |
|
91 |
+
public function get_short_start_time() {
|
92 |
+
$time = $this->_registry->get( 'view.event.time' );
|
93 |
+
return $time->get_short_time( $this->get( 'start' ) );
|
94 |
+
}
|
95 |
|
96 |
+
/**
|
97 |
+
* Handles legacy property setters.
|
98 |
+
*
|
99 |
+
* @param string $property Name of property being set.
|
100 |
+
* @param mixed $value Value attempted to set.
|
101 |
+
*
|
102 |
+
* @return Ai1ec_Event Instance of self for chaining.
|
103 |
+
*/
|
104 |
+
public function __set( $property, $value ) {
|
105 |
+
return $this->set( $property, $value );
|
106 |
+
}
|
107 |
|
108 |
+
/**
|
109 |
+
* Handle property accessors.
|
110 |
+
*
|
111 |
+
* @param string $name Property name
|
112 |
+
*
|
113 |
+
* @return mixed Property value
|
114 |
+
*/
|
115 |
+
public function __get( $name ) {
|
116 |
+
$method = 'get_' . $name;
|
117 |
+
if ( method_exists( $this, $name ) ) {
|
118 |
+
return $this->{$method}();
|
119 |
+
}
|
120 |
+
return $this->get( $name );
|
121 |
+
}
|
122 |
|
123 |
+
/**
|
124 |
+
* Handle legacy methods calls.
|
125 |
+
*
|
126 |
+
* @param string $method Legacy method name.
|
127 |
+
* @param array $arguments Arguments passed to method.
|
128 |
+
*
|
129 |
+
* @return mixed
|
130 |
+
*
|
131 |
+
* @throws Ai1ec_Invalid_Argument_Exception If there is no method handler.
|
132 |
+
*/
|
133 |
+
public function __call( $method, $arguments ) {
|
134 |
+
if ( ! isset( self::$_classes[$method] ) ) {
|
135 |
+
throw new Ai1ec_Invalid_Argument_Exception(
|
136 |
+
'Requested method \'' . $method . '\' is unknown'
|
137 |
+
);
|
138 |
+
}
|
139 |
+
array_unshift( $arguments, $this );
|
140 |
+
$class = 'view.event.' . self::$_classes[$method];
|
141 |
+
return $this->_registry->dispatch(
|
142 |
+
$class,
|
143 |
+
$method,
|
144 |
+
$arguments
|
145 |
+
);
|
146 |
+
}
|
147 |
|
148 |
}
|
app/model/event/parent.php
CHANGED
@@ -9,358 +9,358 @@
|
|
9 |
*/
|
10 |
class Ai1ec_Event_Parent extends Ai1ec_Base {
|
11 |
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
}
|
9 |
*/
|
10 |
class Ai1ec_Event_Parent extends Ai1ec_Base {
|
11 |
|
12 |
+
/**
|
13 |
+
* event_parent method
|
14 |
+
*
|
15 |
+
* Get/set event parent
|
16 |
+
*
|
17 |
+
* @param int $event_id ID of checked event
|
18 |
+
* @param int $parent_id ID of new parent [optional=NULL, acts as getter]
|
19 |
+
* @param int $instance_id ID of old instance id
|
20 |
+
*
|
21 |
+
* @return int|bool Value depends on mode:
|
22 |
+
* Getter: {@see self::get_parent_event()} for details
|
23 |
+
* Setter: true on success.
|
24 |
+
*/
|
25 |
+
public function event_parent(
|
26 |
+
$event_id,
|
27 |
+
$parent_id = null,
|
28 |
+
$instance_id = null
|
29 |
+
) {
|
30 |
+
$meta_key = '_ai1ec_event_parent';
|
31 |
+
if ( null === $parent_id ) {
|
32 |
+
return $this->get_parent_event( $event_id );
|
33 |
+
}
|
34 |
+
$meta_value = json_encode( array(
|
35 |
+
'created' => $this->_registry->get( 'date.system' )->current_time(),
|
36 |
+
'instance' => $instance_id,
|
37 |
+
) );
|
38 |
+
return add_post_meta( $event_id, $meta_key, $meta_value, true );
|
39 |
+
}
|
40 |
|
41 |
+
/**
|
42 |
+
* Get parent ID for given event
|
43 |
+
*
|
44 |
+
* @param int $current_id Current event ID
|
45 |
+
*
|
46 |
+
* @return int|bool ID of parent event or bool(false)
|
47 |
+
*/
|
48 |
+
public function get_parent_event( $current_id ) {
|
49 |
+
static $parents = null;
|
50 |
+
if ( null === $parents ) {
|
51 |
+
$parents = $this->_registry->get( 'cache.memory' );
|
52 |
+
}
|
53 |
+
$current_id = (int)$current_id;
|
54 |
+
if ( null === ( $parent_id = $parents->get( $current_id ) ) ) {
|
55 |
+
$db = $this->_registry->get( 'dbi.dbi' );
|
56 |
+
/* @var $db Ai1ec_Dbi */
|
57 |
+
$query = '
|
58 |
+
SELECT parent.ID, parent.post_status
|
59 |
+
FROM
|
60 |
+
' . $db->get_table_name( 'posts' ) . ' AS child
|
61 |
+
INNER JOIN ' . $db->get_table_name( 'posts' ) . ' AS parent
|
62 |
+
ON ( parent.ID = child.post_parent )
|
63 |
+
WHERE child.ID = ' . $current_id;
|
64 |
+
$parent = $db->get_row( $query );
|
65 |
+
if (
|
66 |
+
empty( $parent ) ||
|
67 |
+
'trash' === $parent->post_status
|
68 |
+
) {
|
69 |
+
$parent_id = false;
|
70 |
+
} else {
|
71 |
+
$parent_id = $parent->ID;
|
72 |
+
}
|
73 |
+
$parents->set( $current_id, $parent_id );
|
74 |
+
unset( $query );
|
75 |
+
}
|
76 |
+
return $parent_id;
|
77 |
+
}
|
78 |
|
79 |
+
/**
|
80 |
+
* Returns a list of modified (children) event objects
|
81 |
+
*
|
82 |
+
* @param int $parent_id ID of parent event
|
83 |
+
* @param bool $include_trash Includes trashed when `true` [optional=false]
|
84 |
+
*
|
85 |
+
* @return array List (might be empty) of Ai1ec_Event objects
|
86 |
+
*/
|
87 |
+
public function get_child_event_objects(
|
88 |
+
$parent_id,
|
89 |
+
$include_trash = false
|
90 |
+
) {
|
91 |
+
$db = $this->_registry->get( 'dbi.dbi' );
|
92 |
+
/* @var $db Ai1ec_Dbi */
|
93 |
+
$parent_id = (int)$parent_id;
|
94 |
+
$sql_query = 'SELECT ID FROM ' . $db->get_table_name( 'posts' ) .
|
95 |
+
' WHERE post_parent = ' . $parent_id;
|
96 |
+
$children = (array)$db->get_col( $sql_query );
|
97 |
+
$objects = array();
|
98 |
+
foreach ( $children as $child_id ) {
|
99 |
+
try {
|
100 |
+
$instance = $this->_registry->get( 'model.event', $child_id );
|
101 |
+
if (
|
102 |
+
$include_trash ||
|
103 |
+
'trash' !== $instance->get( 'post' )->post_status
|
104 |
+
) {
|
105 |
+
$objects[$child_id] = $instance;
|
106 |
+
}
|
107 |
+
} catch ( Ai1ec_Event_Not_Found_Exception $exception ) {
|
108 |
+
// ignore
|
109 |
+
}
|
110 |
+
}
|
111 |
+
return $objects;
|
112 |
+
}
|
113 |
|
114 |
+
/**
|
115 |
+
* admin_init_post method
|
116 |
+
*
|
117 |
+
* Bind to admin_action_editpost action to override default save
|
118 |
+
* method when user is editing single instance.
|
119 |
+
* New post is created with some fields unset.
|
120 |
+
*/
|
121 |
+
public function admin_init_post( ) {
|
122 |
+
if (
|
123 |
+
isset( $_POST['ai1ec_instance_id'] ) &&
|
124 |
+
isset( $_POST['action'] ) &&
|
125 |
+
'editpost' === $_POST['action']
|
126 |
+
) {
|
127 |
+
$old_post_id = $_POST['post_ID'];
|
128 |
+
$instance_id = $_POST['ai1ec_instance_id'];
|
129 |
+
$post_id = $this->_registry->get( 'model.event.creating' )
|
130 |
+
->create_duplicate_post();
|
131 |
+
if ( false !== $post_id ) {
|
132 |
+
$this->_handle_instances(
|
133 |
+
$this->_registry->get( 'model.event', $post_id ),
|
134 |
+
$this->_registry->get( 'model.event', $old_post_id ),
|
135 |
+
$instance_id
|
136 |
+
);
|
137 |
+
$this->_registry->get( 'model.event.instance' )->clean(
|
138 |
+
$old_post_id,
|
139 |
+
$instance_id
|
140 |
+
);
|
141 |
+
$location = add_query_arg(
|
142 |
+
'message',
|
143 |
+
1,
|
144 |
+
get_edit_post_link( $post_id, 'url' )
|
145 |
+
);
|
146 |
+
wp_redirect(
|
147 |
+
apply_filters(
|
148 |
+
'redirect_post_location',
|
149 |
+
$location,
|
150 |
+
$post_id
|
151 |
+
)
|
152 |
+
);
|
153 |
+
exit();
|
154 |
+
}
|
155 |
+
}
|
156 |
+
}
|
157 |
|
158 |
+
/**
|
159 |
+
* Inject base event edit link for modified instances
|
160 |
+
*
|
161 |
+
* Modified instances are events, belonging to some parent having recurrence
|
162 |
+
* rule, and having some of it's properties altered.
|
163 |
+
*
|
164 |
+
* @param array $actions List of defined actions
|
165 |
+
* @param stdClass $post Instance being rendered (WP_Post class instance in WP 3.5+)
|
166 |
+
*
|
167 |
+
* @return array Optionally modified $actions list
|
168 |
+
*/
|
169 |
+
public function post_row_actions( $actions, $post ) {
|
170 |
+
if ( $this->_registry->get( 'acl.aco' )->is_our_post_type( $post ) ) {
|
171 |
+
$parent_post_id = $this->event_parent( $post->ID );
|
172 |
+
if (
|
173 |
+
$parent_post_id &&
|
174 |
+
NULL !== ( $parent_post = get_post( $parent_post_id ) ) &&
|
175 |
+
isset( $parent_post->post_status ) &&
|
176 |
+
'trash' !== $parent_post->post_status
|
177 |
+
) {
|
178 |
+
$parent_link = get_edit_post_link(
|
179 |
+
$parent_post_id,
|
180 |
+
'display'
|
181 |
+
);
|
182 |
+
$actions['ai1ec_parent'] = sprintf(
|
183 |
+
'<a href="%s" title="%s">%s</a>',
|
184 |
+
wp_nonce_url( $parent_link ),
|
185 |
+
sprintf(
|
186 |
+
__( 'Edit “%s”', AI1EC_PLUGIN_NAME ),
|
187 |
+
apply_filters(
|
188 |
+
'the_title',
|
189 |
+
$parent_post->post_title,
|
190 |
+
$parent_post->ID
|
191 |
+
)
|
192 |
+
),
|
193 |
+
__( 'Base Event', AI1EC_PLUGIN_NAME )
|
194 |
+
);
|
195 |
+
}
|
196 |
+
}
|
197 |
+
return $actions;
|
198 |
+
}
|
199 |
|
200 |
+
/**
|
201 |
+
* add_exception_date method
|
202 |
+
*
|
203 |
+
* Add exception (date) to event.
|
204 |
+
*
|
205 |
+
* @param int $post_id Event edited post ID
|
206 |
+
* @param mixed $date Parseable date representation to exclude
|
207 |
+
*
|
208 |
+
* @return bool Success
|
209 |
+
*/
|
210 |
+
public function add_exception_date( $post_id, Ai1ec_Date_Time $date ) {
|
211 |
+
$event = $this->_registry->get( 'model.event', $post_id );
|
212 |
+
$dates_list = explode( ',', $event->get( 'exception_dates' ) );
|
213 |
+
if ( empty( $dates_list[0] ) ) {
|
214 |
+
unset( $dates_list[0] );
|
215 |
+
}
|
216 |
+
$date->set_time( 0, 0, 0 );
|
217 |
+
$dates_list[] = $date->format(
|
218 |
+
'Ymd\THis\Z'
|
219 |
+
);
|
220 |
+
$event->set( 'exception_dates', implode( ',', $dates_list ) );
|
221 |
+
return $event->save( true );
|
222 |
+
}
|
223 |
|
224 |
+
/**
|
225 |
+
* Handles instances saving and switching if needed. If original event
|
226 |
+
* and created event have different start dates proceed in old style
|
227 |
+
* otherwise find next instance, switch original start date to next
|
228 |
+
* instance start date. If there are no next instances mark event as
|
229 |
+
* non recurring. Filter also exception dates if are past.
|
230 |
+
*
|
231 |
+
* @param Ai1ec_Event $created_event Created event object.
|
232 |
+
* @param Ai1ec_Event $original_event Original event object.
|
233 |
+
*
|
234 |
+
* @return void Method does not return.
|
235 |
+
*/
|
236 |
+
protected function _handle_instances(
|
237 |
+
Ai1ec_Event $created_event,
|
238 |
+
Ai1ec_Event $original_event,
|
239 |
+
$instance_id
|
240 |
+
) {
|
241 |
+
$ce_start = $created_event->get( 'start' );
|
242 |
+
$oe_start = $original_event->get( 'start' );
|
243 |
+
if (
|
244 |
+
$ce_start->format() !== $oe_start->format()
|
245 |
+
) {
|
246 |
+
$this->add_exception_date(
|
247 |
+
$original_event->get( 'post_id' ),
|
248 |
+
$ce_start
|
249 |
+
);
|
250 |
+
return;
|
251 |
+
}
|
252 |
+
$next_instance = $this->_find_next_instance(
|
253 |
+
$original_event->get( 'post_id' ),
|
254 |
+
$instance_id
|
255 |
+
);
|
256 |
+
if ( ! $next_instance ) {
|
257 |
+
$original_event->set( 'recurrence_rules', null );
|
258 |
+
$original_event->save( true );
|
259 |
+
return;
|
260 |
+
}
|
261 |
+
$original_event->set(
|
262 |
+
'start',
|
263 |
+
$this->_registry->get( 'date.time', $next_instance->get( 'start' ) )
|
264 |
+
);
|
265 |
+
$original_event->set(
|
266 |
+
'end',
|
267 |
+
$this->_registry->get( 'date.time', $next_instance->get( 'end' ) )
|
268 |
+
);
|
269 |
+
$edates = $this->_filter_exception_dates( $original_event );
|
270 |
+
$original_event->set( 'exception_dates', implode( ',', $edates ) );
|
271 |
+
$recurrence_rules = $original_event->get( 'recurrence_rules' );
|
272 |
+
$rules_info = $this->_registry->get( 'recurrence.rule' )
|
273 |
+
->build_recurrence_rules_array( $recurrence_rules );
|
274 |
+
if ( isset( $rules_info['COUNT'] ) ) {
|
275 |
+
$next_instances_count = $this->_count_next_instances(
|
276 |
+
$original_event->get( 'post_id' ),
|
277 |
+
$instance_id
|
278 |
+
);
|
279 |
+
$rules_info['COUNT'] = (int)$next_instances_count + count( $edates );
|
280 |
+
$rules = '';
|
281 |
+
if ( $rules_info['COUNT'] <= 1 ) {
|
282 |
+
$rules_info = array();
|
283 |
+
}
|
284 |
+
foreach ( $rules_info as $key => $value ) {
|
285 |
+
$rules .= $key . '=' . $value . ';';
|
286 |
+
}
|
287 |
+
$original_event->set(
|
288 |
+
'recurrence_rules',
|
289 |
+
$rules
|
290 |
+
);
|
291 |
+
}
|
292 |
+
$original_event->save( true );
|
293 |
+
}
|
294 |
|
295 |
+
/**
|
296 |
+
* Returns next instance.
|
297 |
+
*
|
298 |
+
* @param int $post_id Post ID.
|
299 |
+
* @param int $instance_id Instance ID.
|
300 |
+
*
|
301 |
+
* @return null|Ai1ec_Event Result.
|
302 |
+
*/
|
303 |
+
protected function _find_next_instance( $post_id, $instance_id ) {
|
304 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
305 |
+
$table_instances = $dbi->get_table_name( 'ai1ec_event_instances' );
|
306 |
+
$table_posts = $dbi->get_table_name( 'posts' );
|
307 |
+
$query = $dbi->prepare(
|
308 |
+
'SELECT i.id FROM ' . $table_instances . ' i JOIN ' .
|
309 |
+
$table_posts . ' p ON (p.ID = i.post_id) ' .
|
310 |
+
'WHERE i.post_id = %d AND i.id > %d ' .
|
311 |
+
'AND p.post_status = \'publish\' ' .
|
312 |
+
'ORDER BY id ASC LIMIT 1',
|
313 |
+
$post_id,
|
314 |
+
$instance_id
|
315 |
+
);
|
316 |
+
$next_instance_id = $dbi->get_var( $query );
|
317 |
+
if ( ! $next_instance_id ) {
|
318 |
+
return null;
|
319 |
+
}
|
320 |
+
return $this->_registry->get( 'model.search' )
|
321 |
+
->get_event( $post_id, $next_instance_id );
|
322 |
+
}
|
323 |
|
324 |
+
/**
|
325 |
+
* Counts future instances.
|
326 |
+
*
|
327 |
+
* @param int $post_id Post ID.
|
328 |
+
* @param int $instance_id Instance ID.
|
329 |
+
*
|
330 |
+
* @return int Result.
|
331 |
+
*/
|
332 |
+
protected function _count_next_instances( $post_id, $instance_id ) {
|
333 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
334 |
+
$table_instances = $dbi->get_table_name( 'ai1ec_event_instances' );
|
335 |
+
$table_posts = $dbi->get_table_name( 'posts' );
|
336 |
+
$query = $dbi->prepare(
|
337 |
+
'SELECT COUNT(i.id) FROM ' . $table_instances . ' i JOIN ' .
|
338 |
+
$table_posts . ' p ON (p.ID = i.post_id) ' .
|
339 |
+
'WHERE i.post_id = %d AND i.id > %d ' .
|
340 |
+
'AND p.post_status = \'publish\'',
|
341 |
+
$post_id,
|
342 |
+
$instance_id
|
343 |
+
);
|
344 |
+
return (int)$dbi->get_var( $query );
|
345 |
+
}
|
346 |
|
347 |
+
/**
|
348 |
+
* Filters past or out of range exception dates.
|
349 |
+
*
|
350 |
+
* @param Ai1ec_Event $event Event.
|
351 |
+
*
|
352 |
+
* @return array Filtered exception dates.
|
353 |
+
*/
|
354 |
+
protected function _filter_exception_dates( Ai1ec_Event $event ) {
|
355 |
+
$start = (int)$event->get( 'start' )->format();
|
356 |
+
$exception_dates = explode( ',', $event->get( 'exception_dates' ) );
|
357 |
+
$dates = array();
|
358 |
+
foreach ( $exception_dates as $date ) {
|
359 |
+
$ex_date = (int)$this->_registry->get( 'date.time', $date )->format();
|
360 |
+
if ( $ex_date > $start ) {
|
361 |
+
$dates[] = $date;
|
362 |
+
}
|
363 |
+
}
|
364 |
+
return $dates;
|
365 |
+
}
|
366 |
}
|
app/model/event/taxonomy.php
CHANGED
@@ -12,185 +12,185 @@
|
|
12 |
|
13 |
class Ai1ec_Event_Taxonomy extends Ai1ec_Base {
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
}
|
12 |
|
13 |
class Ai1ec_Event_Taxonomy extends Ai1ec_Base {
|
14 |
|
15 |
+
/**
|
16 |
+
* @var string Name of categories taxonomy.
|
17 |
+
*/
|
18 |
+
const CATEGORIES = 'events_categories';
|
19 |
|
20 |
+
/**
|
21 |
+
* @var string Name of tags taxonomy.
|
22 |
+
*/
|
23 |
+
const TAGS = 'events_tags';
|
24 |
|
25 |
+
/**
|
26 |
+
* @var string Name of feeds taxonomy.
|
27 |
+
*/
|
28 |
+
const FEEDS = 'events_feeds';
|
29 |
|
30 |
+
/**
|
31 |
+
* @var int ID of related post object
|
32 |
+
*/
|
33 |
+
protected $_post_id = 0;
|
34 |
|
35 |
+
/**
|
36 |
+
* Store event ID in local variable.
|
37 |
+
*
|
38 |
+
* @param int $post_id ID of post being managed.
|
39 |
+
*
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
+
public function __construct( Ai1ec_Registry_Object $registry, $post_id = 0 ) {
|
43 |
+
parent::__construct( $registry );
|
44 |
+
$this->_post_id = (int)$post_id;
|
45 |
+
}
|
46 |
|
47 |
+
/**
|
48 |
+
* Get ID of term. Optionally create it if it doesn't exist.
|
49 |
+
*
|
50 |
+
* @param string $term Name of term to create.
|
51 |
+
* @param string $taxonomy Name of taxonomy to contain term within.
|
52 |
+
* @param bool $is_id Set to true if $term is ID.
|
53 |
+
* @param array $attrs Attributes to creatable entity.
|
54 |
+
*
|
55 |
+
* @return array|bool Associative array with term_id
|
56 |
+
* and taxonomy keys or false on error
|
57 |
+
*/
|
58 |
+
public function initiate_term(
|
59 |
+
$term,
|
60 |
+
$taxonomy,
|
61 |
+
$is_id = false,
|
62 |
+
array $attrs = array()
|
63 |
+
) {
|
64 |
+
// cast to int to have it working with term_exists
|
65 |
+
$term = ( $is_id ) ? (int) $term : $term;
|
66 |
+
$term_to_check = term_exists( $term, $taxonomy );
|
67 |
+
$to_return = array(
|
68 |
+
'taxonomy' => $taxonomy
|
69 |
+
);
|
70 |
+
// if term doesn't exist, create it.
|
71 |
+
if ( 0 === $term_to_check || null === $term_to_check ) {
|
72 |
+
$alias_to_use = apply_filters( 'ai1ec_ics_import_alias', $term );
|
73 |
+
// the filter will either return null, the term_id to use or the original $term
|
74 |
+
// if the filter is not run. Thus in need to check that $term !== $alias_to_use
|
75 |
+
if ( $alias_to_use && $alias_to_use !== $term ) {
|
76 |
+
$to_return['term_id'] = (int) $alias_to_use;
|
77 |
+
// check that the term matches the taxonomy
|
78 |
+
$tax = $this->get_taxonomy_for_term_id( term_exists( (int) $alias_to_use ) );
|
79 |
+
$to_return['taxonomy'] = $tax->taxonomy;
|
80 |
+
} else {
|
81 |
+
$term_to_check = wp_insert_term( $term, $taxonomy, $attrs );
|
82 |
+
if ( is_wp_error( $term_to_check ) ) {
|
83 |
+
return false;
|
84 |
+
}
|
85 |
+
$term_to_check = (object)$term_to_check;
|
86 |
+
$to_return['term_id'] = (int)$term_to_check->term_id;
|
87 |
+
}
|
88 |
+
} else {
|
89 |
+
$term_id = is_array( $term_to_check )
|
90 |
+
? $term_to_check['term_id']
|
91 |
+
: $term_to_check;
|
92 |
+
$to_return['term_id'] = (int)$term_id;
|
93 |
+
// when importing categories, use the mapping of the current site
|
94 |
+
// so place the term in the current taxonomy
|
95 |
+
if ( self::CATEGORIES === $taxonomy ) {
|
96 |
+
// check that the term matches the taxonomy
|
97 |
+
$tax = $this->get_taxonomy_for_term_id( $term_id );
|
98 |
+
$to_return['taxonomy'] = $tax->taxonomy;
|
99 |
+
}
|
100 |
|
101 |
+
}
|
102 |
+
return $to_return;
|
103 |
+
}
|
104 |
|
105 |
+
/**
|
106 |
+
* Wrapper for terms setting to post.
|
107 |
+
*
|
108 |
+
* @param array $terms List of terms to set.
|
109 |
+
* @param string $taxonomy Name of taxonomy to set terms to.
|
110 |
+
* @param bool $append When true post may have multiple same instances.
|
111 |
+
*
|
112 |
+
* @return bool Success.
|
113 |
+
*/
|
114 |
+
public function set_terms( array $terms, $taxonomy, $append = false ) {
|
115 |
+
$result = wp_set_post_terms(
|
116 |
+
$this->_post_id,
|
117 |
+
$terms,
|
118 |
+
$taxonomy,
|
119 |
+
$append
|
120 |
+
);
|
121 |
+
if ( is_wp_error( $result ) ) {
|
122 |
+
return false;
|
123 |
+
}
|
124 |
+
return $result;
|
125 |
+
}
|
126 |
|
127 |
+
/**
|
128 |
+
* Update event categories.
|
129 |
+
*
|
130 |
+
* @param array $categories List of category IDs.
|
131 |
+
*
|
132 |
+
* @return bool Success.
|
133 |
+
*/
|
134 |
+
public function set_categories( array $categories ) {
|
135 |
+
return $this->set_terms( $categories, self::CATEGORIES );
|
136 |
+
}
|
137 |
|
138 |
+
/**
|
139 |
+
* Update event tags.
|
140 |
+
*
|
141 |
+
* @param array $tags List of tag IDs.
|
142 |
+
*
|
143 |
+
* @return bool Success.
|
144 |
+
*/
|
145 |
+
public function set_tags( array $tags ) {
|
146 |
+
return $this->set_terms( $tags, self::TAGS );
|
147 |
+
}
|
148 |
|
149 |
+
/**
|
150 |
+
* Update event feed description.
|
151 |
+
*
|
152 |
+
* @param object $feed Feed object.
|
153 |
+
*
|
154 |
+
* @return bool Success.
|
155 |
+
*/
|
156 |
+
public function set_feed( $feed ) {
|
157 |
+
$feed_name = $feed->feed_url;
|
158 |
+
// If the feed is not from an imported file, parse the url.
|
159 |
+
if ( ! isset( $feed->feed_imported_file ) ) {
|
160 |
+
$url_components = parse_url( $feed->feed_url );
|
161 |
+
$feed_name = $url_components['host'];
|
162 |
+
}
|
163 |
+
$term = $this->initiate_term(
|
164 |
+
$feed_name,
|
165 |
+
self::FEEDS,
|
166 |
+
false,
|
167 |
+
array(
|
168 |
+
'description' => $feed->feed_url,
|
169 |
+
)
|
170 |
+
);
|
171 |
+
if ( false === $term ) {
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
$term_id = $term['term_id'];
|
175 |
+
return $this->set_terms( array( $term_id ), self::FEEDS );
|
176 |
+
}
|
177 |
|
178 |
+
/**
|
179 |
+
* Get the taxonomy name from term id
|
180 |
+
*
|
181 |
+
* @param int $term
|
182 |
+
*
|
183 |
+
* @return stdClass The taxonomy nane
|
184 |
+
*/
|
185 |
+
public function get_taxonomy_for_term_id( $term_id ) {
|
186 |
+
$db = $this->_registry->get( 'dbi.dbi' );
|
187 |
+
return $db->get_row(
|
188 |
+
$db->prepare(
|
189 |
+
'SELECT terms_taxonomy.taxonomy FROM ' . $db->get_table_name( 'terms' ) .
|
190 |
+
' AS terms INNER JOIN ' .
|
191 |
+
$db->get_table_name( 'term_taxonomy' ) .
|
192 |
+
' AS terms_taxonomy USING(term_id) '.
|
193 |
+
'WHERE terms.term_id = %d LIMIT 1', $term_id )
|
194 |
+
);
|
195 |
+
}
|
196 |
}
|
app/model/event/trashing.php
CHANGED
@@ -15,202 +15,202 @@
|
|
15 |
*/
|
16 |
class Ai1ec_Event_Trashing extends Ai1ec_Base {
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
public function untrash_post ( $post_id ) {
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
public function before_delete_post( $post_id ) {
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
|
216 |
}
|
15 |
*/
|
16 |
class Ai1ec_Event_Trashing extends Ai1ec_Base {
|
17 |
|
18 |
+
/**
|
19 |
+
* Trash/untrash/deletes child posts
|
20 |
+
*
|
21 |
+
* @param id $post_id
|
22 |
+
* @param string $action
|
23 |
+
*/
|
24 |
+
protected function _manage_children( $post_id, $action ) {
|
25 |
+
try {
|
26 |
+
$ai1ec_event = $this->_registry->get( 'model.event', $post_id );
|
27 |
+
if (
|
28 |
+
$ai1ec_event->get( 'post' ) &&
|
29 |
+
$ai1ec_event->get( 'recurrence_rules' )
|
30 |
+
) {
|
31 |
+
// when untrashing also get trashed object
|
32 |
+
$children = $this->_registry->get( 'model.event.parent' )
|
33 |
+
->get_child_event_objects( $ai1ec_event->get( 'post_id' ), $action === 'untrash' );
|
34 |
+
$function = 'wp_' . $action . '_post';
|
35 |
+
foreach ( $children as $child ) {
|
36 |
+
$function( $child->get( 'post_id' ) );
|
37 |
+
}
|
38 |
+
}
|
39 |
+
} catch ( Ai1ec_Event_Not_Found_Exception $exception ) {
|
40 |
+
// ignore - not an event
|
41 |
+
}
|
42 |
+
}
|
43 |
|
44 |
+
/**
|
45 |
+
* Trashes child posts
|
46 |
+
*
|
47 |
+
* @param int $post_id
|
48 |
+
*/
|
49 |
+
public function trash_children( $post_id ) {
|
50 |
+
$this->_manage_children( $post_id, 'trash' );
|
51 |
+
}
|
52 |
|
53 |
+
/**
|
54 |
+
* Delete child posts
|
55 |
+
*
|
56 |
+
* @param int $post_id
|
57 |
+
*/
|
58 |
+
public function delete_children( $post_id ) {
|
59 |
+
$this->_manage_children( $post_id, 'delete' );
|
60 |
+
}
|
61 |
|
62 |
+
/**
|
63 |
+
* Untrashes child posts
|
64 |
+
*
|
65 |
+
* @param int $post_id
|
66 |
+
*/
|
67 |
+
public function untrash_children( $post_id ) {
|
68 |
+
$this->_manage_children( $post_id, 'untrash' );
|
69 |
+
}
|
70 |
|
71 |
+
/**
|
72 |
+
* Handle PRE (event) trashing.
|
73 |
+
*
|
74 |
+
* @wp_hook trash_post
|
75 |
+
*
|
76 |
+
* @param int $post_id ID of post, which was trashed.
|
77 |
+
*
|
78 |
+
* @return bool Success.
|
79 |
+
*/
|
80 |
+
public function trash_post( $post_id ) {
|
81 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
82 |
+
$post = get_post( $post_id );
|
83 |
+
$restored_status = get_post_meta( $post_id, '_wp_trash_meta_status', true );
|
84 |
+
$fields = array(
|
85 |
+
'status' => 'trash'
|
86 |
+
);
|
87 |
+
$ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
|
88 |
+
$message = $api->update_api_event_fields( $post, $fields, 'trash', $ajax );
|
89 |
+
if ( null !== $message ) {
|
90 |
+
if ( $ajax ) {
|
91 |
+
wp_die( $message );
|
92 |
+
} else {
|
93 |
+
wp_redirect( $this->get_sendback_page( $post_id ) );
|
94 |
+
exit();
|
95 |
+
}
|
96 |
+
}
|
97 |
+
return true;
|
98 |
+
}
|
99 |
|
100 |
+
/**
|
101 |
+
* Handle POST (event) trashing.
|
102 |
+
*
|
103 |
+
* @wp_hook trashed_post
|
104 |
+
*
|
105 |
+
* @param int $post_id ID of post, which was trashed.
|
106 |
+
*
|
107 |
+
* @return bool Success.
|
108 |
+
*/
|
109 |
+
public function trashed_post( $post_id ) {
|
110 |
+
return $this->trash_children( $post_id );
|
111 |
+
}
|
112 |
|
113 |
+
private function get_sendback_page( $post_id ) {
|
114 |
+
$sendback = wp_get_referer();
|
115 |
+
$page_base = Ai1ec_Wp_Uri_Helper::get_pagebase( $sendback ); //$_SERVER['REQUEST_URI'] );
|
116 |
+
if ( 'post.php' === $page_base ) {
|
117 |
+
return get_edit_post_link( $post_id, 'url' );
|
118 |
+
} else {
|
119 |
+
return admin_url( 'edit.php?post_type=ai1ec_event' );
|
120 |
+
}
|
121 |
+
}
|
122 |
|
123 |
+
/**
|
124 |
+
* Handle PRE (event) untrashing.
|
125 |
+
*
|
126 |
+
* @wp_hook untrash_post
|
127 |
+
*
|
128 |
+
* @param int $post_id ID of post, which was untrashed.
|
129 |
+
*
|
130 |
+
* @return bool Success. Interrupt the action with exit is
|
131 |
+
* the integration with API fails
|
132 |
+
*/
|
133 |
+
public function untrash_post ( $post_id ) {
|
134 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
135 |
+
$post = get_post( $post_id );
|
136 |
+
$restored_status = get_post_meta( $post_id, '_wp_trash_meta_status', true );
|
137 |
+
$fields = array(
|
138 |
+
'status' => $restored_status
|
139 |
+
);
|
140 |
+
$ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
|
141 |
+
$message = $api->update_api_event_fields( $post, $fields, 'untrash', $ajax );
|
142 |
+
if ( null !== $message ) {
|
143 |
+
if ( $ajax ) {
|
144 |
+
wp_die( $message );
|
145 |
+
} else {
|
146 |
+
wp_redirect( $this->get_sendback_page( $post_id ) );
|
147 |
+
exit();
|
148 |
+
}
|
149 |
+
}
|
150 |
+
return true;
|
151 |
+
}
|
152 |
|
153 |
+
/**
|
154 |
+
* Handle POST (event) untrashing.
|
155 |
+
*
|
156 |
+
* @wp_hook untrashed_post
|
157 |
+
*
|
158 |
+
* @param int $post_id ID of post, which was untrashed.
|
159 |
+
*
|
160 |
+
* @return bool Success.
|
161 |
+
*/
|
162 |
+
public function untrashed_post( $post_id ) {
|
163 |
+
return $this->untrash_children( $post_id );
|
164 |
+
}
|
165 |
|
166 |
+
/**
|
167 |
+
* Handle PRE (event) deletion.
|
168 |
+
*
|
169 |
+
* Executed before post is deleted, but after meta is removed.
|
170 |
+
*
|
171 |
+
* @wp_hook delete_post
|
172 |
+
*
|
173 |
+
* @param int $post_id ID of post, which was trashed.
|
174 |
+
*
|
175 |
+
* @return bool Success. Interrupt the action with exit is
|
176 |
+
* the integration with API fails
|
177 |
+
*/
|
178 |
public function before_delete_post( $post_id ) {
|
179 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
180 |
+
$ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
|
181 |
+
$message = $api->delete_api_event( $post_id, 'delete', $ajax );
|
182 |
+
if ( null !== $message ) {
|
183 |
+
if ( $ajax ) {
|
184 |
+
wp_die( $message );
|
185 |
+
} else {
|
186 |
+
wp_redirect( $this->get_sendback_page( $post_id ) );
|
187 |
+
exit();
|
188 |
+
}
|
189 |
+
}
|
190 |
+
return true;
|
191 |
+
}
|
192 |
|
193 |
+
/**
|
194 |
+
* Handle POST (event) deletion.
|
195 |
+
*
|
196 |
+
* Executed before post is deleted, but after meta is removed.
|
197 |
+
*
|
198 |
+
* @wp_hook delete_post
|
199 |
+
*
|
200 |
+
* @param int $post_id ID of post, which was trashed.
|
201 |
+
*
|
202 |
+
* @return bool Success.
|
203 |
+
*/
|
204 |
+
public function delete( $post_id ) {
|
205 |
+
$post_id = (int)$post_id;
|
206 |
+
$where = array( 'post_id' => (int)$post_id );
|
207 |
+
$format = array( '%d' );
|
208 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
209 |
+
$success = $this->delete_children( $post_id );
|
210 |
+
$success = $dbi->delete( 'ai1ec_events', $where, $format );
|
211 |
+
$success = $this->_registry->get( 'model.event.instance' )->clean( $post_id );
|
212 |
+
unset( $where, $dbi );
|
213 |
+
return $success;
|
214 |
+
}
|
215 |
|
216 |
}
|
app/model/filter/auth_ids.php
CHANGED
@@ -11,8 +11,8 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Filter_Authors extends Ai1ec_Filter_Int {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
|
18 |
}
|
11 |
*/
|
12 |
class Ai1ec_Filter_Authors extends Ai1ec_Filter_Int {
|
13 |
|
14 |
+
public function get_field() {
|
15 |
+
return 'p.post_author';
|
16 |
+
}
|
17 |
|
18 |
}
|
app/model/filter/cat_ids.php
CHANGED
@@ -11,8 +11,8 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Filter_Categories extends Ai1ec_Filter_Taxonomy {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
|
18 |
}
|
11 |
*/
|
12 |
class Ai1ec_Filter_Categories extends Ai1ec_Filter_Taxonomy {
|
13 |
|
14 |
+
public function get_taxonomy() {
|
15 |
+
return 'events_categories';
|
16 |
+
}
|
17 |
|
18 |
}
|
app/model/filter/instance_ids.php
CHANGED
@@ -11,8 +11,8 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Filter_Posts_By_Instance extends Ai1ec_Filter_Int {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
|
18 |
}
|
11 |
*/
|
12 |
class Ai1ec_Filter_Posts_By_Instance extends Ai1ec_Filter_Int {
|
13 |
|
14 |
+
public function get_field() {
|
15 |
+
return 'i.id';
|
16 |
+
}
|
17 |
|
18 |
}
|
app/model/filter/int.php
CHANGED
@@ -11,65 +11,65 @@
|
|
11 |
*/
|
12 |
abstract class Ai1ec_Filter_Int implements Ai1ec_Filter_Interface {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
|
75 |
}
|
11 |
*/
|
12 |
abstract class Ai1ec_Filter_Int implements Ai1ec_Filter_Interface {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var Ai1ec_Registry_Object Injected object registry.
|
16 |
+
*/
|
17 |
+
protected $_registry = null;
|
18 |
|
19 |
+
/**
|
20 |
+
* @var array Sanitized input values with only positive integers kept.
|
21 |
+
*/
|
22 |
+
protected $_values = array();
|
23 |
|
24 |
+
/**
|
25 |
+
* Sanitize input values upon construction.
|
26 |
+
*
|
27 |
+
* @param Ai1ec_Registry_Object $registry Injected registry.
|
28 |
+
* @param array $filter_values Values to sanitize.
|
29 |
+
*
|
30 |
+
* @return void
|
31 |
+
*/
|
32 |
+
public function __construct(
|
33 |
+
Ai1ec_Registry_Object $registry,
|
34 |
+
array $filter_values = array()
|
35 |
+
) {
|
36 |
+
$this->_registry = $registry;
|
37 |
+
$this->_values = array_filter(
|
38 |
+
array_map(
|
39 |
+
array( $this->_registry->get( 'primitive.int' ), 'positive' ),
|
40 |
+
$filter_values
|
41 |
+
)
|
42 |
+
);
|
43 |
+
}
|
44 |
|
45 |
+
/**
|
46 |
+
* These simple filters does not require new joins.
|
47 |
+
*
|
48 |
+
* @return string Empty string is returned.
|
49 |
+
*/
|
50 |
+
public function get_join() {
|
51 |
+
return '';
|
52 |
+
}
|
53 |
|
54 |
+
/**
|
55 |
+
* Get condition part of query for single field.
|
56 |
+
*
|
57 |
+
* @param string $inner_operator Inner logics to use. It is ignored.
|
58 |
+
*
|
59 |
+
* @return string Conditional snippet for query.
|
60 |
+
*/
|
61 |
+
public function get_where( $inner_operator = null ) {
|
62 |
+
if ( empty( $this->_values ) ) {
|
63 |
+
return '';
|
64 |
+
}
|
65 |
+
return $this->get_field() . ' IN ( ' . join( ',', $this->_values ) . ' )';
|
66 |
+
}
|
67 |
|
68 |
+
/**
|
69 |
+
* Require ancestors to override this to build correct conditional snippet.
|
70 |
+
*
|
71 |
+
* @return string Column alias to use in condition.
|
72 |
+
*/
|
73 |
+
abstract public function get_field();
|
74 |
|
75 |
}
|
app/model/filter/interface.php
CHANGED
@@ -11,34 +11,34 @@
|
|
11 |
*/
|
12 |
interface Ai1ec_Filter_Interface {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
}
|
11 |
*/
|
12 |
interface Ai1ec_Filter_Interface {
|
13 |
|
14 |
+
/**
|
15 |
+
* Store user-input locally.
|
16 |
+
*
|
17 |
+
* @param Ai1ec_Registry_Object $registry Injected registry.
|
18 |
+
* @param array $filter_values User provided input.
|
19 |
+
*
|
20 |
+
* @return void
|
21 |
+
*/
|
22 |
+
public function __construct(
|
23 |
+
Ai1ec_Registry_Object $registry,
|
24 |
+
array $filter_values = array()
|
25 |
+
);
|
26 |
|
27 |
+
/**
|
28 |
+
* Return SQL snippet for `FROM` part.
|
29 |
+
*
|
30 |
+
* @return string Valid SQL snippet for `FROM` part.
|
31 |
+
*/
|
32 |
+
public function get_join();
|
33 |
|
34 |
+
/**
|
35 |
+
* Return SQL snippet for `WHERE` part.
|
36 |
+
*
|
37 |
+
* Snippet should not be put in brackets - this will be performed
|
38 |
+
* in upper level.
|
39 |
+
*
|
40 |
+
* @return string Valid SQL snippet.
|
41 |
+
*/
|
42 |
+
public function get_where();
|
43 |
|
44 |
}
|
app/model/filter/post_ids.php
CHANGED
@@ -11,8 +11,8 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Filter_Posts extends Ai1ec_Filter_Int {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
|
18 |
}
|
11 |
*/
|
12 |
class Ai1ec_Filter_Posts extends Ai1ec_Filter_Int {
|
13 |
|
14 |
+
public function get_field() {
|
15 |
+
return 'e.post_id';
|
16 |
+
}
|
17 |
|
18 |
}
|
app/model/filter/tag_ids.php
CHANGED
@@ -11,8 +11,8 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Filter_Tags extends Ai1ec_Filter_Taxonomy {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
|
18 |
}
|
11 |
*/
|
12 |
class Ai1ec_Filter_Tags extends Ai1ec_Filter_Taxonomy {
|
13 |
|
14 |
+
public function get_taxonomy() {
|
15 |
+
return 'events_tags';
|
16 |
+
}
|
17 |
|
18 |
}
|
app/model/filter/taxonomy.php
CHANGED
@@ -11,89 +11,89 @@
|
|
11 |
*/
|
12 |
abstract class Ai1ec_Filter_Taxonomy extends Ai1ec_Filter_Int {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
|
99 |
}
|
11 |
*/
|
12 |
abstract class Ai1ec_Filter_Taxonomy extends Ai1ec_Filter_Int {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var Ai1ec_Dbi Instance of database interface.
|
16 |
+
*/
|
17 |
+
protected $_dbi = null;
|
18 |
|
19 |
+
/**
|
20 |
+
* Sanitize input values upon construction.
|
21 |
+
*
|
22 |
+
* @param Ai1ec_Registry_Object $registry Injected registry.
|
23 |
+
* @param array $filter_values Values to sanitize.
|
24 |
+
*
|
25 |
+
* @return void
|
26 |
+
*/
|
27 |
+
public function __construct(
|
28 |
+
Ai1ec_Registry_Object $registry,
|
29 |
+
array $filter_values = array()
|
30 |
+
) {
|
31 |
+
parent::__construct( $registry, $filter_values );
|
32 |
+
$this->_dbi = $this->_registry->get( 'dbi.dbi' );
|
33 |
+
}
|
34 |
|
35 |
+
/**
|
36 |
+
* Build SQL snippet for `FROM` particle.
|
37 |
+
*
|
38 |
+
* @return string Valid SQL snippet.
|
39 |
+
*/
|
40 |
+
public function get_join() {
|
41 |
+
if ( empty( $this->_values ) ) {
|
42 |
+
return '';
|
43 |
+
}
|
44 |
+
$sql_query =
|
45 |
+
'LEFT JOIN `{{RELATIONSHIPS_TABLE}}` AS `{{RELATIONSHIP_ALIAS}}` ' .
|
46 |
+
'ON ( `e` . `post_id` = `{{RELATIONSHIP_ALIAS}}` . `object_id` ) ' .
|
47 |
+
'LEFT JOIN `{{TAXONOMY_TABLE}}` AS `{{TAXONOMY_ALIAS}}` ' .
|
48 |
+
'ON (' .
|
49 |
+
'`{{RELATIONSHIP_ALIAS}}` . `term_taxonomy_id` = ' .
|
50 |
+
'`{{TAXONOMY_ALIAS}}` . `term_taxonomy_id` ' .
|
51 |
+
'AND `{{TAXONOMY_ALIAS}}` . taxonomy = {{TAXONOMY}} ' .
|
52 |
+
')';
|
53 |
+
return str_replace(
|
54 |
+
array(
|
55 |
+
'{{RELATIONSHIPS_TABLE}}',
|
56 |
+
'{{RELATIONSHIP_ALIAS}}',
|
57 |
+
'{{TAXONOMY_TABLE}}',
|
58 |
+
'{{TAXONOMY_ALIAS}}',
|
59 |
+
'{{TAXONOMY}}',
|
60 |
+
),
|
61 |
+
array(
|
62 |
+
$this->_dbi->get_table_name( 'term_relationships' ),
|
63 |
+
$this->_table_alias( 'term_relationships' ),
|
64 |
+
$this->_dbi->get_table_name( 'term_taxonomy' ),
|
65 |
+
$this->_table_alias( 'term_taxonomy' ),
|
66 |
+
'\'' . addslashes( $this->get_taxonomy() ) . '\'',
|
67 |
+
),
|
68 |
+
$sql_query
|
69 |
+
);
|
70 |
+
}
|
71 |
|
72 |
+
/**
|
73 |
+
* Required by parent class. Using internal abstractions.
|
74 |
+
*
|
75 |
+
* @return string Field name to use in `WHERE` particle.
|
76 |
+
*/
|
77 |
+
public function get_field() {
|
78 |
+
return $this->_table_alias( 'term_taxonomy' ) . '.term_id';
|
79 |
+
}
|
80 |
|
81 |
+
/**
|
82 |
+
* Return the qualified name for the taxonomy.
|
83 |
+
*
|
84 |
+
* @return string Valid taxonomy name (see `term_taxonomy` table).
|
85 |
+
*/
|
86 |
+
abstract public function get_taxonomy();
|
87 |
|
88 |
+
/**
|
89 |
+
* Generate table alias given taxonomy.
|
90 |
+
*
|
91 |
+
* @param string $table Table to generate alias for.
|
92 |
+
*
|
93 |
+
* @return string Table alias.
|
94 |
+
*/
|
95 |
+
protected function _table_alias( $table ) {
|
96 |
+
return $table . '_' . $this->get_taxonomy();
|
97 |
+
}
|
98 |
|
99 |
}
|
app/model/meta-user.php
CHANGED
@@ -12,85 +12,85 @@
|
|
12 |
*/
|
13 |
class Ai1ec_Meta_User extends Ai1ec_Meta {
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
|
96 |
}
|
12 |
*/
|
13 |
class Ai1ec_Meta_User extends Ai1ec_Meta {
|
14 |
|
15 |
+
/**
|
16 |
+
* Get meta value for current user.
|
17 |
+
*
|
18 |
+
* @param string $meta_key Name of meta entry to get for current user.
|
19 |
+
* @param mixed $default Value to return if no entry found.
|
20 |
+
*
|
21 |
+
* @return mixed Current user's option or $default if none found.
|
22 |
+
*/
|
23 |
+
public function get_current( $meta_key, $default = null ) {
|
24 |
+
$user_id = 0;
|
25 |
+
if ( is_callable( 'wp_get_current_user' ) ) {
|
26 |
+
$user = wp_get_current_user();
|
27 |
+
$user_id = (int)$user->ID;
|
28 |
+
unset( $user );
|
29 |
+
}
|
30 |
+
if ( $user_id <= 0 ) {
|
31 |
+
return $default;
|
32 |
+
}
|
33 |
+
return $this->get( $user_id, $meta_key, $default );
|
34 |
+
}
|
35 |
|
36 |
+
/**
|
37 |
+
* user_selected_tz method
|
38 |
+
*
|
39 |
+
* Get/set user selected (preferred) timezone.
|
40 |
+
* If only {@see $user_id} is provided - method acts as getter.
|
41 |
+
* Otherwise it acts as setter.
|
42 |
+
*
|
43 |
+
* @param int $user_id ID of user whose timezone is being checked/changed
|
44 |
+
* @param string $new_value New timezone string value to set user preferrence
|
45 |
+
* @param bool $force_update Set to true to force value update instead of add
|
46 |
+
*
|
47 |
+
* @return mixed Return value depends on activity:
|
48 |
+
* - [getter] string User preferred timezone name (might be empty string)
|
49 |
+
* - [setter] bool Success of preferrence change
|
50 |
+
*/
|
51 |
+
public function user_selected_tz(
|
52 |
+
$user_id,
|
53 |
+
$new_value = NULL,
|
54 |
+
$force_update = false
|
55 |
+
) {
|
56 |
+
$meta_key = 'ai1ec_timezone';
|
57 |
+
$user_id = (int)$user_id;
|
58 |
+
$old_value = $this->get(
|
59 |
+
$user_id,
|
60 |
+
$meta_key,
|
61 |
+
NULL,
|
62 |
+
true
|
63 |
+
);
|
64 |
+
if ( NULL !== $new_value ) {
|
65 |
+
if ( ! in_array( $new_value, timezone_identifiers_list() ) ) {
|
66 |
+
return false;
|
67 |
+
}
|
68 |
+
$success = false;
|
69 |
+
if ( true === $force_update || ! empty( $old_value ) ) {
|
70 |
+
$success = update_user_meta(
|
71 |
+
$user_id,
|
72 |
+
$meta_key,
|
73 |
+
$new_value,
|
74 |
+
$old_value
|
75 |
+
);
|
76 |
+
} else {
|
77 |
+
$success = add_user_meta(
|
78 |
+
$user_id,
|
79 |
+
$meta_key,
|
80 |
+
$new_value,
|
81 |
+
true
|
82 |
+
);
|
83 |
+
if ( false === $success ) {
|
84 |
+
return $this->user_selected_tz(
|
85 |
+
$user_id,
|
86 |
+
$new_value,
|
87 |
+
true
|
88 |
+
);
|
89 |
+
}
|
90 |
+
}
|
91 |
+
return $success;
|
92 |
+
}
|
93 |
+
return $old_value;
|
94 |
+
}
|
95 |
|
96 |
}
|
app/model/meta.php
CHANGED
@@ -12,183 +12,183 @@
|
|
12 |
*/
|
13 |
abstract class Ai1ec_Meta extends Ai1ec_App {
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
|
194 |
}
|
12 |
*/
|
13 |
abstract class Ai1ec_Meta extends Ai1ec_App {
|
14 |
|
15 |
+
/**
|
16 |
+
* @var string Name of base object for storage.
|
17 |
+
*/
|
18 |
+
protected $_object = '';
|
19 |
|
20 |
+
/**
|
21 |
+
* @var Ai1ec_Cache_Memory In-memory cache operator.
|
22 |
+
*/
|
23 |
+
protected $_cache = null;
|
24 |
|
25 |
+
/**
|
26 |
+
* Initialize instance-specific in-memory cache storage.
|
27 |
+
*
|
28 |
+
* @return void Method does not return.
|
29 |
+
*/
|
30 |
+
protected function _initialize() {
|
31 |
+
$class = get_class( $this );
|
32 |
+
$this->_object = strtolower(
|
33 |
+
substr( $class, strlen( __CLASS__ ) + 1 )
|
34 |
+
);
|
35 |
+
$this->_cache = $this->_registry->get( 'cache.memory' );
|
36 |
+
}
|
37 |
|
38 |
+
/**
|
39 |
+
* Create new entry if it does not exist and cache provided value.
|
40 |
+
*
|
41 |
+
* @param string $object_id ID of object to store.
|
42 |
+
* @param string $key Key particle for ID to store.
|
43 |
+
* @param mixed $value Serializable value to store.
|
44 |
+
*
|
45 |
+
* @return bool Success.
|
46 |
+
*/
|
47 |
+
final public function add( $object_id, $key, $value ) {
|
48 |
+
if ( ! $this->_add( $object_id, $key, $value ) ) {
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
$this->_cache->set( $this->_cache_key( $object_id, $key ), $value );
|
52 |
+
return true;
|
53 |
+
}
|
54 |
|
55 |
+
/**
|
56 |
+
* Update existing entry and cache it's value.
|
57 |
+
*
|
58 |
+
* @param string $object_id ID of object to store.
|
59 |
+
* @param string $key Key particle for ID to store.
|
60 |
+
* @param mixed $value Serializable value to store.
|
61 |
+
*
|
62 |
+
* @return bool Success.
|
63 |
+
*/
|
64 |
+
final public function update( $object_id, $key, $value ) {
|
65 |
+
if ( ! $this->_update( $object_id, $key, $value ) ) {
|
66 |
+
return false;
|
67 |
+
}
|
68 |
+
$this->_cache->set( $this->_cache_key( $object_id, $key ), $value );
|
69 |
+
return true;
|
70 |
+
}
|
71 |
|
72 |
+
/**
|
73 |
+
* Get object value - from cache or actual store.
|
74 |
+
*
|
75 |
+
* @param string $object_id ID of object to get.
|
76 |
+
* @param string $key Key particle for ID to get.
|
77 |
+
* @param mixed $default Value to return if nothing found.
|
78 |
+
*
|
79 |
+
* @return mixed Value stored or {$default}.
|
80 |
+
*/
|
81 |
+
final public function get( $object_id, $key, $default = null ) {
|
82 |
+
$cache_key = $this->_cache_key( $object_id, $key );
|
83 |
+
$value = $this->_cache->get( $cache_key, $default );
|
84 |
+
if ( $default === $value ) {
|
85 |
+
$value = $this->_get( $object_id, $key );
|
86 |
+
$this->_cache->set( $cache_key, $value );
|
87 |
+
}
|
88 |
+
return $value;
|
89 |
+
}
|
90 |
|
91 |
+
/**
|
92 |
+
* Create or update an entry cache new value.
|
93 |
+
*
|
94 |
+
* @param string $object_id ID of object to store.
|
95 |
+
* @param string $key Key particle for ID to store.
|
96 |
+
* @param mixed $value Serializable value to store.
|
97 |
+
*
|
98 |
+
* @return bool Success.
|
99 |
+
*/
|
100 |
+
final public function set( $object_id, $key, $value ) {
|
101 |
+
if ( ! $this->get( $object_id, $key ) ) {
|
102 |
+
if ( ! $this->_add( $object_id, $key, $value ) ) {
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
} else {
|
106 |
+
if ( ! $this->_update( $object_id, $key, $value ) ) {
|
107 |
+
return false;
|
108 |
+
}
|
109 |
+
}
|
110 |
+
$this->_cache->set( $this->_cache_key( $object_id, $key ), $value );
|
111 |
+
return true;
|
112 |
+
}
|
113 |
|
114 |
+
/**
|
115 |
+
* Remove object entry based on ID and key.
|
116 |
+
*
|
117 |
+
* @param string $object_id ID of object to remove.
|
118 |
+
* @param string $key Key particle for ID to remove.
|
119 |
+
*
|
120 |
+
* @return bool Success.
|
121 |
+
*/
|
122 |
+
final public function delete( $object_id, $key ) {
|
123 |
+
$this->_cache->delete( $this->_cache_key( $object_id, $key ) );
|
124 |
+
return $this->_delete( $object_id, $key );
|
125 |
+
}
|
126 |
|
127 |
+
/**
|
128 |
+
* Get object value from actual store.
|
129 |
+
*
|
130 |
+
* @param string $object_id ID of object to get.
|
131 |
+
* @param string $key Key particle for ID to get.
|
132 |
+
*
|
133 |
+
* @return mixed Value as found.
|
134 |
+
*/
|
135 |
+
protected function _get( $object_id, $key ) {
|
136 |
+
$function = 'get_' . $this->_object . '_meta';
|
137 |
+
return $function( $object_id, $key, true );
|
138 |
+
}
|
139 |
|
140 |
+
/**
|
141 |
+
* Create new entry if it does not exist.
|
142 |
+
*
|
143 |
+
* @param string $object_id ID of object to store.
|
144 |
+
* @param string $key Key particle for ID to store.
|
145 |
+
* @param mixed $value Serializable value to store.
|
146 |
+
*
|
147 |
+
* @return bool Success.
|
148 |
+
*/
|
149 |
+
protected function _add( $object_id, $key, $value ) {
|
150 |
+
$function = 'add_' . $this->_object . '_meta';
|
151 |
+
return $function( $object_id, $key, $value, true );
|
152 |
+
}
|
153 |
|
154 |
+
/**
|
155 |
+
* Update existing entry.
|
156 |
+
*
|
157 |
+
* @param string $object_id ID of object to store.
|
158 |
+
* @param string $key Key particle for ID to store.
|
159 |
+
* @param mixed $value Serializable value to store.
|
160 |
+
*
|
161 |
+
* @return bool Success.
|
162 |
+
*/
|
163 |
+
protected function _update( $object_id, $key, $value ) {
|
164 |
+
$function = 'update_' . $this->_object . '_meta';
|
165 |
+
return $function( $object_id, $key, $value );
|
166 |
+
}
|
167 |
|
168 |
+
/**
|
169 |
+
* Remove object entry based on ID and key.
|
170 |
+
*
|
171 |
+
* @param string $object_id ID of object to remove.
|
172 |
+
* @param string $key Key particle for ID to remove.
|
173 |
+
*
|
174 |
+
* @return bool Success.
|
175 |
+
*/
|
176 |
+
protected function _delete( $object_id, $key ) {
|
177 |
+
$function = 'delete_' . $this->_object . '_meta';
|
178 |
+
return $function( $object_id, $key );
|
179 |
+
}
|
180 |
|
181 |
+
/**
|
182 |
+
* Generate key for use with cache engine.
|
183 |
+
*
|
184 |
+
* @param string $object_id ID of object.
|
185 |
+
* @param string $key Key particle for ID.
|
186 |
+
*
|
187 |
+
* @return string Single identifier for given keys.
|
188 |
+
*/
|
189 |
+
protected function _cache_key( $object_id, $key ) {
|
190 |
+
static $separator = "\0";
|
191 |
+
return $object_id . $separator . $key;
|
192 |
+
}
|
193 |
|
194 |
}
|
app/model/option.php
CHANGED
@@ -10,111 +10,111 @@
|
|
10 |
*/
|
11 |
class Ai1ec_Option extends Ai1ec_App {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
|
108 |
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
|
120 |
}
|
10 |
*/
|
11 |
class Ai1ec_Option extends Ai1ec_App {
|
12 |
|
13 |
+
/**
|
14 |
+
* @var Ai1ec_Cache_Memory In-memory cache storage engine for fast access.
|
15 |
+
*/
|
16 |
+
protected $_cache = null;
|
17 |
|
18 |
+
/**
|
19 |
+
* @var Ai1ec_Registry_Object instance of the registry object.
|
20 |
+
*/
|
21 |
+
protected $_registry;
|
22 |
|
23 |
+
/**
|
24 |
+
* Add cache instance to object scope.
|
25 |
+
*
|
26 |
+
* @param Ai1ec_Registry_Object $registry Registry object.
|
27 |
+
*
|
28 |
+
* @return Ai1ec_Option
|
29 |
+
*/
|
30 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
31 |
+
$this->_registry = $registry;
|
32 |
+
$this->_cache = $registry->get( 'cache.memory' );
|
33 |
+
}
|
34 |
|
35 |
+
/**
|
36 |
+
* Create an option if it does not exist.
|
37 |
+
*
|
38 |
+
* @param string $name Key to put value under.
|
39 |
+
* @param mixed $value Value to put to storage.
|
40 |
+
* @param bool $autoload Set to true to load on start.
|
41 |
+
*
|
42 |
+
* @return bool Success.
|
43 |
+
*/
|
44 |
+
public function add( $name, $value, $autoload = false ) {
|
45 |
+
$autoload = $this->_parse_autoload( $autoload );
|
46 |
+
if ( ! add_option( $name, $value, '', $autoload ) ) {
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
$this->_cache->set( $name, $value );
|
50 |
+
return true;
|
51 |
+
}
|
52 |
|
53 |
+
/**
|
54 |
+
* Create an option if it does not exist, or update existing.
|
55 |
+
*
|
56 |
+
* @param string $name Key to put value under.
|
57 |
+
* @param mixed $value Value to put to storage.
|
58 |
+
* @param bool $autoload Set to true to load on start.
|
59 |
+
*
|
60 |
+
* @return bool Success.
|
61 |
+
*/
|
62 |
+
public function set( $name, $value, $autoload = false ) {
|
63 |
+
$comparator = "\0t\0";
|
64 |
+
if ( $this->get( $name, $comparator ) === $comparator ) {
|
65 |
+
return $this->add( $name, $value, $autoload );
|
66 |
+
}
|
67 |
+
if ( ! update_option( $name, $value ) ) {
|
68 |
+
return false;
|
69 |
+
}
|
70 |
+
$this->_cache->set( $name, $value );
|
71 |
+
return true;
|
72 |
+
}
|
73 |
|
74 |
+
/**
|
75 |
+
* Get a value from storage.
|
76 |
+
*
|
77 |
+
* @param string $name Key to retrieve.
|
78 |
+
* @param mixed $default Value to return if key was not set previously.
|
79 |
+
*
|
80 |
+
* @return mixed Value from storage or {$default}.
|
81 |
+
*/
|
82 |
+
public function get( $name, $default = null ) {
|
83 |
+
$value = $this->_cache->get( $name, $default );
|
84 |
+
if ( $default === $value ) {
|
85 |
+
$value = get_option( $name, $default );
|
86 |
+
$this->_cache->set( $name, $value );
|
87 |
+
}
|
88 |
+
return $value;
|
89 |
+
}
|
90 |
|
91 |
+
/**
|
92 |
+
* Delete value from storage.
|
93 |
+
*
|
94 |
+
* @param string $name Key to delete.
|
95 |
+
*
|
96 |
+
* @wp_hook deleted_option Fire after deletion.
|
97 |
+
*
|
98 |
+
* @return bool Success.
|
99 |
+
*/
|
100 |
+
public function delete( $name ) {
|
101 |
+
$this->_cache->delete( $name );
|
102 |
+
if ( 'deleted_option' === current_filter() ) {
|
103 |
+
return true; // avoid loops
|
104 |
+
}
|
105 |
+
return delete_option( $name );
|
106 |
+
}
|
107 |
|
108 |
|
109 |
+
/**
|
110 |
+
* Convert autoload flag input to value recognized by WordPress.
|
111 |
+
*
|
112 |
+
* @param bool $input Autoload flag value.
|
113 |
+
*
|
114 |
+
* @return string Autoload identifier.
|
115 |
+
*/
|
116 |
+
protected function _parse_autoload( $input ) {
|
117 |
+
return $input ? 'yes' : 'no';
|
118 |
+
}
|
119 |
|
120 |
}
|
app/model/review.php
CHANGED
@@ -3,193 +3,193 @@
|
|
3 |
/**
|
4 |
* Class to manage the review made by the user.
|
5 |
* The data are saved inside the wp_option table
|
6 |
-
*
|
7 |
* @author Time.ly Network Inc.
|
8 |
*
|
9 |
* @package AI1ECCFG
|
10 |
*/
|
11 |
class Ai1ec_Review extends Ai1ec_Base {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
|
113 |
-
|
114 |
-
|
115 |
-
$current_user = wp_get_current_user();
|
116 |
$review_args = array();
|
117 |
if ( $current_user instanceof WP_User ) {
|
118 |
$review_args['contact_name'] = $current_user->display_name;
|
119 |
$review_args['contact_email'] = $current_user->user_email;
|
120 |
} else {
|
121 |
-
|
122 |
-
|
123 |
}
|
124 |
$review_args['site_url'] = get_option( 'siteurl' );
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
}
|
3 |
/**
|
4 |
* Class to manage the review made by the user.
|
5 |
* The data are saved inside the wp_option table
|
6 |
+
*
|
7 |
* @author Time.ly Network Inc.
|
8 |
*
|
9 |
* @package AI1ECCFG
|
10 |
*/
|
11 |
class Ai1ec_Review extends Ai1ec_Base {
|
12 |
|
13 |
+
const EMAIL_FEEDBACK_DESTINATION = 'info@time.ly';
|
14 |
+
const OPTION_KEY = '_ai1ec_review';
|
15 |
+
const FEEDBACK_FIELD = 'feedback';
|
16 |
+
const RELEASE_DATE_FIELD = 'release_date';
|
17 |
+
const PUBLISHED_THRESHOLD = 15;
|
18 |
+
const FUTURE_EVENTS_THRESHOLD = 3;
|
19 |
+
const WEEK_OFFSET_SEC_FIELD = 604800; //1 week in seconds (7 * 86400)
|
20 |
|
21 |
+
/**
|
22 |
+
* review colletion.
|
23 |
+
*
|
24 |
+
* @var array
|
25 |
+
*/
|
26 |
+
protected $_review_items = array();
|
27 |
|
28 |
+
/**
|
29 |
+
* Option class.
|
30 |
+
*
|
31 |
+
* @var Ai1ec_Option
|
32 |
+
*/
|
33 |
+
protected $_option;
|
34 |
|
35 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
36 |
+
parent::__construct( $registry );
|
37 |
+
$this->_option = $registry->get( 'model.option' );
|
38 |
+
$this->_review_items = $this->_get_array( self::OPTION_KEY );
|
39 |
+
}
|
40 |
|
41 |
+
private function _get_array( $option_key ) {
|
42 |
+
$items = $this->_option->get( $option_key );
|
43 |
+
if ( ! is_array( $items ) ) {
|
44 |
+
$items = array();
|
45 |
+
}
|
46 |
+
return $items;
|
47 |
+
}
|
48 |
|
49 |
+
private function _get_field( $field_name, $default_value ) {
|
50 |
+
if ( isset( $this->_review_items[$field_name] ) ) {
|
51 |
+
$value = $this->_review_items[$field_name];
|
52 |
+
if ( ai1ec_is_blank( $value ) ) {
|
53 |
+
return $default_value;
|
54 |
+
} else {
|
55 |
+
return $value;
|
56 |
+
}
|
57 |
+
} else {
|
58 |
+
return $default_value;
|
59 |
+
}
|
60 |
+
}
|
61 |
|
62 |
+
protected function _save( array $values ) {
|
63 |
+
foreach ($values as $key => $value) {
|
64 |
+
$this->_review_items[$key] = $value;
|
65 |
+
}
|
66 |
+
$this->_option->set( self::OPTION_KEY, $this->_review_items );
|
67 |
+
return true;
|
68 |
+
}
|
69 |
|
70 |
+
protected function _is_show_box_review() {
|
71 |
+
//only show for admins
|
72 |
+
if ( false === is_admin() ) {
|
73 |
+
return false;
|
74 |
+
}
|
75 |
+
$user_id = get_current_user_id();
|
76 |
+
if ( empty( $user_id ) ) {
|
77 |
+
return false;
|
78 |
+
}
|
79 |
+
//if the user already gave his feedback does not ask him again
|
80 |
+
if ( $this->_has_feedback( $user_id ) ) {
|
81 |
+
return false;
|
82 |
+
}
|
83 |
+
$release_date_str = $this->_get_field( self::RELEASE_DATE_FIELD, '' );
|
84 |
+
if ( ai1ec_is_blank( $release_date_str ) ) {
|
85 |
+
//the first time this page is loaded is save the moment as the release date
|
86 |
+
//to just ask the user a review after 2 weeks
|
87 |
+
$this->_save( array(
|
88 |
+
self::RELEASE_DATE_FIELD => $this->_registry->get( 'date.time' )->format()
|
89 |
+
) );
|
90 |
+
return false;
|
91 |
+
} else {
|
92 |
+
$current_time = $this->_registry->get( 'date.time' );
|
93 |
+
$release_date = $this->_registry->get( 'date.time', $release_date_str );
|
94 |
+
$diff_sec = $release_date->diff_sec( $current_time );
|
95 |
+
//verify is passed 2 weeks after we release this feature
|
96 |
+
if ( $diff_sec < self::WEEK_OFFSET_SEC_FIELD ) {
|
97 |
+
return false;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
//count the published events
|
101 |
+
$event_count = count_user_posts( $user_id, AI1EC_POST_TYPE, true );
|
102 |
+
if ( $event_count < self::PUBLISHED_THRESHOLD ) {
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
//count the future events
|
106 |
+
$count_future_events = apply_filters( 'ai1ec_count_future_events', $user_id );
|
107 |
+
if ( $count_future_events < self::FUTURE_EVENTS_THRESHOLD ) {
|
108 |
+
return false;
|
109 |
+
}
|
110 |
+
return true;
|
111 |
+
}
|
112 |
|
113 |
+
public function get_content( $theme_loader ) {
|
114 |
+
if ( $this->_is_show_box_review() ) {
|
115 |
+
$current_user = wp_get_current_user();
|
116 |
$review_args = array();
|
117 |
if ( $current_user instanceof WP_User ) {
|
118 |
$review_args['contact_name'] = $current_user->display_name;
|
119 |
$review_args['contact_email'] = $current_user->user_email;
|
120 |
} else {
|
121 |
+
$review_args['contact_name'] = '';
|
122 |
+
$review_args['contact_email'] = '';
|
123 |
}
|
124 |
$review_args['site_url'] = get_option( 'siteurl' );
|
125 |
+
$theme_loader = $this->_registry->get( 'theme.loader' );
|
126 |
+
return $theme_loader->get_file( 'box_ask_customer_review.php', $review_args, true )->get_content();
|
127 |
+
} else {
|
128 |
+
return null;
|
129 |
+
}
|
130 |
+
}
|
131 |
|
132 |
+
public function save_feedback_review() {
|
133 |
+
$user_id = get_current_user_id();
|
134 |
+
if ( empty( $user_id ) ) {
|
135 |
+
throw new Exception( 'User not identified' );
|
136 |
+
}
|
137 |
+
if ( ai1ec_is_blank( $_POST['feedback'] ) ||
|
138 |
+
!in_array( $_POST['feedback'], array( 'y', 'n' ) ) ) {
|
139 |
+
throw new Exception( 'The field is not filled or invalid' );
|
140 |
+
}
|
141 |
+
$values = $this->_get_field( self::FEEDBACK_FIELD, null );
|
142 |
+
if ( null === $values ) {
|
143 |
+
$values = array();
|
144 |
+
}
|
145 |
+
$values[ $user_id ] = $_POST['feedback'];
|
146 |
+
$this->_save( array(
|
147 |
+
self::FEEDBACK_FIELD => $values
|
148 |
+
) );
|
149 |
+
}
|
150 |
|
151 |
+
protected function _has_feedback( $user_id ) {
|
152 |
+
$values = $this->_get_field( self::FEEDBACK_FIELD, null );
|
153 |
+
if ( null === $values ) {
|
154 |
+
return false;
|
155 |
+
}
|
156 |
+
$user = (string) $user_id;
|
157 |
+
$value = isset( $values[$user] ) ? $values[$user] : '';
|
158 |
+
return 0 === strcasecmp( 'y', $value ) || 0 === strcasecmp( 'n', $value );
|
159 |
+
}
|
160 |
|
161 |
+
public function send_feedback_message() {
|
162 |
+
if ( ai1ec_is_blank( $_POST['name'] ) ||
|
163 |
+
ai1ec_is_blank( $_POST['email'] ) ||
|
164 |
+
ai1ec_is_blank( $_POST['site'] ) ||
|
165 |
+
ai1ec_is_blank( $_POST['message'] )
|
166 |
+
) {
|
167 |
+
throw new Exception( 'All fields are required' );
|
168 |
+
}
|
169 |
+
$subject = __( 'Feedback provided by user', AI1EC_PLUGIN_NAME );
|
170 |
+
$content = sprintf( '<b>%s:</b><br/>%s<br/><br/><b>%s:</b><br/>%s<br/><br/><b>%s:</b><br/>%s<br/><br/><b>%s:</b><br/>%s',
|
171 |
+
__( 'Name', AI1EC_PLUGIN_NAME ),
|
172 |
+
$_POST['name'],
|
173 |
+
__( 'E-mail', AI1EC_PLUGIN_NAME ),
|
174 |
+
$_POST['email'],
|
175 |
+
__( 'Site URL', AI1EC_PLUGIN_NAME ),
|
176 |
+
$_POST['site'],
|
177 |
+
__( 'Message', AI1EC_PLUGIN_NAME ),
|
178 |
+
nl2br( $_POST['message'] )
|
179 |
+
);
|
180 |
+
$dispatcher = $this->_registry->get(
|
181 |
+
'notification.email',
|
182 |
+
$content,
|
183 |
+
explode( ',', self::EMAIL_FEEDBACK_DESTINATION ),
|
184 |
+
$subject
|
185 |
+
);
|
186 |
+
$headers = array(
|
187 |
+
'Content-type: text/html',
|
188 |
+
sprintf( 'From: %s <%s>', $_POST['name'], $_POST['email'])
|
189 |
+
);
|
190 |
+
if ( $dispatcher->send( $headers ) ) {
|
191 |
+
$_POST['feedback'] = 'n';
|
192 |
+
$this->save_feedback_review();
|
193 |
+
}
|
194 |
+
}
|
195 |
}
|
app/model/search.php
CHANGED
@@ -11,868 +11,868 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Event_Search extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
|
878 |
}
|
11 |
*/
|
12 |
class Ai1ec_Event_Search extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var Ai1ec_Dbi instance
|
16 |
+
*/
|
17 |
+
private $_dbi = null;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Caches the ids of the last 'between' query
|
21 |
+
*
|
22 |
+
* @var array
|
23 |
+
*/
|
24 |
+
protected $_ids_between_cache = array();
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Creates local DBI instance.
|
28 |
+
*/
|
29 |
+
public function __construct( Ai1ec_Registry_Object $registry ){
|
30 |
+
parent::__construct( $registry );
|
31 |
+
$this->_dbi = $this->_registry->get( 'dbi.dbi' );
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @return array
|
36 |
+
*/
|
37 |
+
public function get_cached_between_ids() {
|
38 |
+
return $this->_ids_between_cache;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Fetches the event object with the given post ID.
|
43 |
+
*
|
44 |
+
* Uses the WP cache to make this more efficient if possible.
|
45 |
+
*
|
46 |
+
* @param int $post_id The ID of the post associated.
|
47 |
+
* @param bool|int $instance_id Instance ID, to fetch post details for.
|
48 |
+
*
|
49 |
+
* @return Ai1ec_Event The associated event object.
|
50 |
+
*/
|
51 |
+
public function get_event( $post_id, $instance_id = false ) {
|
52 |
+
$post_id = (int)$post_id;
|
53 |
+
$instance_id = (int)$instance_id;
|
54 |
+
if ( $instance_id < 1 ) {
|
55 |
+
$instance_id = false;
|
56 |
+
}
|
57 |
+
return $this->_registry->get( 'model.event', $post_id, $instance_id );
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Return events falling within some time range.
|
62 |
+
*
|
63 |
+
* Return all events starting after the given start time and before the
|
64 |
+
* given end time that the currently logged in user has permission to view.
|
65 |
+
* If $spanning is true, then also include events that span this
|
66 |
+
* period. All-day events are returned first.
|
67 |
+
*
|
68 |
+
* @param Ai1ec_Date_Time $start Limit to events starting after this.
|
69 |
+
* @param Ai1ec_Date_Time $end Limit to events starting before this.
|
70 |
+
* @param array $filter Array of filters for the events returned:
|
71 |
+
* ['cat_ids'] => list of category IDs;
|
72 |
+
* ['tag_ids'] => list of tag IDs;
|
73 |
+
* ['post_ids'] => list of post IDs;
|
74 |
+
* ['auth_ids'] => list of author IDs;
|
75 |
+
* ['instance_ids'] => list of events
|
76 |
+
* instance ids;
|
77 |
+
* @param bool $spanning Also include events that span this period.
|
78 |
+
* @param bool $single_day This parameter is added for oneday view.
|
79 |
+
* Query should find events lasting in
|
80 |
+
* particular day instead of checking dates
|
81 |
+
* range. If you need to call this method
|
82 |
+
* with $single_day set to true consider
|
83 |
+
* using method get_events_for_day. This
|
84 |
+
* parameter matters only if $spanning is set
|
85 |
+
* to false.
|
86 |
+
*
|
87 |
+
* @return array List of matching event objects.
|
88 |
+
*/
|
89 |
+
public function get_events_between(
|
90 |
+
Ai1ec_Date_Time $start,
|
91 |
+
Ai1ec_Date_Time $end,
|
92 |
+
array $filter = array(),
|
93 |
+
$spanning = false,
|
94 |
+
$single_day = false
|
95 |
+
) {
|
96 |
+
// Query arguments
|
97 |
+
$args = array(
|
98 |
+
$start->format_to_gmt(),
|
99 |
+
$end->format_to_gmt(),
|
100 |
+
);
|
101 |
+
|
102 |
+
// Get post status Where snippet and associated SQL arguments
|
103 |
+
$where_parameters = $this->_get_post_status_sql();
|
104 |
+
$post_status_where = $where_parameters['post_status_where'];
|
105 |
+
$args = array_merge( $args, $where_parameters['args'] );
|
106 |
+
|
107 |
+
// Get the Join (filter_join) and Where (filter_where) statements based
|
108 |
+
// on $filter elements specified
|
109 |
+
$filter = $this->_get_filter_sql( $filter );
|
110 |
+
|
111 |
+
$ai1ec_localization_helper = $this->_registry->get( 'p28n.wpml' );
|
112 |
+
|
113 |
+
$wpml_join_particle = $ai1ec_localization_helper
|
114 |
+
->get_wpml_table_join( 'p.ID' );
|
115 |
+
|
116 |
+
$wpml_where_particle = $ai1ec_localization_helper
|
117 |
+
->get_wpml_table_where();
|
118 |
+
|
119 |
+
if ( $spanning ) {
|
120 |
+
$spanning_string = 'i.end > %d AND i.start < %d ';
|
121 |
+
} elseif ( $single_day ) {
|
122 |
+
$spanning_string = 'i.end >= %d AND i.start <= %d ';
|
123 |
+
} else {
|
124 |
+
$spanning_string = 'i.start BETWEEN %d AND %d ';
|
125 |
+
}
|
126 |
+
|
127 |
+
$sql = '
|
128 |
+
SELECT
|
129 |
+
`p`.*,
|
130 |
+
`e`.`post_id`,
|
131 |
+
`i`.`id` AS `instance_id`,
|
132 |
+
`i`.`start` AS `start`,
|
133 |
+
`i`.`end` AS `end`,
|
134 |
+
`e`.`timezone_name` AS `timezone_name`,
|
135 |
+
`e`.`allday` AS `event_allday`,
|
136 |
+
`e`.`recurrence_rules`,
|
137 |
+
`e`.`exception_rules`,
|
138 |
+
`e`.`recurrence_dates`,
|
139 |
+
`e`.`exception_dates`,
|
140 |
+
`e`.`venue`,
|
141 |
+
`e`.`country`,
|
142 |
+
`e`.`address`,
|
143 |
+
`e`.`city`,
|
144 |
+
`e`.`province`,
|
145 |
+
`e`.`postal_code`,
|
146 |
+
`e`.`instant_event`,
|
147 |
+
`e`.`show_map`,
|
148 |
+
`e`.`contact_name`,
|
149 |
+
`e`.`contact_phone`,
|
150 |
+
`e`.`contact_email`,
|
151 |
+
`e`.`contact_url`,
|
152 |
+
`e`.`cost`,
|
153 |
+
`e`.`ticket_url`,
|
154 |
+
`e`.`ical_feed_url`,
|
155 |
+
`e`.`ical_source_url`,
|
156 |
+
`e`.`ical_organizer`,
|
157 |
+
`e`.`ical_contact`,
|
158 |
+
`e`.`ical_uid`,
|
159 |
+
`e`.`longitude`,
|
160 |
+
`e`.`latitude`
|
161 |
+
FROM
|
162 |
+
' . $this->_dbi->get_table_name( 'ai1ec_events' ) . ' e
|
163 |
+
INNER JOIN
|
164 |
+
' . $this->_dbi->get_table_name( 'posts' ) . ' p
|
165 |
+
ON ( `p`.`ID` = `e`.`post_id` )
|
166 |
+
' . $wpml_join_particle . '
|
167 |
+
INNER JOIN
|
168 |
+
' . $this->_dbi->get_table_name( 'ai1ec_event_instances' ) . ' i
|
169 |
+
ON ( `e`.`post_id` = `i`.`post_id` )
|
170 |
+
' . $filter['filter_join'] . '
|
171 |
+
WHERE
|
172 |
+
post_type = \'' . AI1EC_POST_TYPE . '\'
|
173 |
+
' . $wpml_where_particle . '
|
174 |
+
AND
|
175 |
+
' . $spanning_string . '
|
176 |
+
' . $filter['filter_where'] . '
|
177 |
+
' . $post_status_where . '
|
178 |
+
GROUP BY
|
179 |
+
`i`.`id`
|
180 |
+
ORDER BY
|
181 |
+
`e` . `allday` DESC,
|
182 |
+
`i` . `start` ASC,
|
183 |
+
`p` . `post_title` ASC';
|
184 |
+
|
185 |
+
$query = $this->_dbi->prepare( $sql, $args );
|
186 |
+
$events = $this->_dbi->get_results( $query, ARRAY_A );
|
187 |
+
|
188 |
+
$id_list = array();
|
189 |
+
$id_instance_list = array();
|
190 |
+
foreach ( $events as $event ) {
|
191 |
+
|
192 |
+
if ( ! in_array( $event['post_id'], $id_list, true ) ) {
|
193 |
+
$id_list[] = $event['post_id'];
|
194 |
+
}
|
195 |
+
|
196 |
+
$id_instance_list[] = array(
|
197 |
+
'id' => $event['post_id'],
|
198 |
+
'instance_id' => $event['instance_id'],
|
199 |
+
);
|
200 |
+
}
|
201 |
+
|
202 |
+
if ( ! empty( $id_list ) ) {
|
203 |
+
update_meta_cache( 'post', $id_list );
|
204 |
+
$this->_ids_between_cache = $id_instance_list;
|
205 |
+
}
|
206 |
+
|
207 |
+
foreach ( $events as &$event ) {
|
208 |
+
$event['allday'] = $this->_is_all_day( $event );
|
209 |
+
$event = $this->_registry->get( 'model.event', $event );
|
210 |
+
}
|
211 |
+
|
212 |
+
return $events;
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* get_events_relative_to function
|
217 |
+
*
|
218 |
+
* Return all events starting after the given reference time, limiting the
|
219 |
+
* result set to a maximum of $limit items, offset by $page_offset. A
|
220 |
+
* negative $page_offset can be provided, which will return events *before*
|
221 |
+
* the reference time, as expected.
|
222 |
+
*
|
223 |
+
* @param int $time limit to events starting after this (local) UNIX time
|
224 |
+
* @param int $limit return a maximum of this number of items
|
225 |
+
* @param int $page_offset offset the result set by $limit times this number
|
226 |
+
* @param array $filter Array of filters for the events returned.
|
227 |
+
* ['cat_ids'] => non-associatative array of category IDs
|
228 |
+
* ['tag_ids'] => non-associatative array of tag IDs
|
229 |
+
* ['post_ids'] => non-associatative array of post IDs
|
230 |
+
* ['auth_ids'] => non-associatative array of author IDs
|
231 |
+
* ['instance_ids'] => non-associatative array of author IDs
|
232 |
+
* @param int $last_day Last day (time), that was displayed.
|
233 |
+
* NOTE FROM NICOLA: be careful, if you want a query with events
|
234 |
+
* that have a start date which is greater than today, pass 0 as
|
235 |
+
* this parameter. If you pass false ( or pass nothing ) you end up with a query
|
236 |
+
* with events that finish before today. I don't know the rationale
|
237 |
+
* behind this but that's how it works
|
238 |
+
* @param bool $unique Whether display only unique events and don't
|
239 |
+
* duplicate results with other instances or not.
|
240 |
+
*
|
241 |
+
* @return array five-element array:
|
242 |
+
* ['events'] an array of matching event objects
|
243 |
+
* ['prev'] true if more previous events
|
244 |
+
* ['next'] true if more next events
|
245 |
+
* ['date_first'] UNIX timestamp (date part) of first event
|
246 |
+
* ['date_last'] UNIX timestamp (date part) of last event
|
247 |
+
*/
|
248 |
+
public function get_events_relative_to(
|
249 |
+
$time,
|
250 |
+
$limit = 0,
|
251 |
+
$page_offset = 0,
|
252 |
+
$filter = array(),
|
253 |
+
$last_day = false,
|
254 |
+
$unique = false
|
255 |
+
) {
|
256 |
+
$localization_helper = $this->_registry->get( 'p28n.wpml' );
|
257 |
+
$settings = $this->_registry->get( 'model.settings' );
|
258 |
+
|
259 |
+
|
260 |
+
// Even if there ARE more than 5 times the limit results - we shall not
|
261 |
+
// try to fetch and display these, as it would crash system
|
262 |
+
$limit = preg_replace('/\D/', '', $limit);
|
263 |
+
$upper_boundary = $limit;
|
264 |
+
if (
|
265 |
+
$settings->get( 'agenda_include_entire_last_day' ) &&
|
266 |
+
( false !== $last_day )
|
267 |
+
) {
|
268 |
+
$upper_boundary *= 5;
|
269 |
+
}
|
270 |
+
|
271 |
+
// Convert timestamp to GMT time
|
272 |
+
$time = $this->_registry->get(
|
273 |
+
'date.system'
|
274 |
+
)->get_current_rounded_time();
|
275 |
+
// Get post status Where snippet and associated SQL arguments
|
276 |
+
$where_parameters = $this->_get_post_status_sql();
|
277 |
+
$post_status_where = $where_parameters['post_status_where'];
|
278 |
+
|
279 |
+
// Get the Join (filter_join) and Where (filter_where) statements based
|
280 |
+
// on $filter elements specified
|
281 |
+
$filter = $this->_get_filter_sql( $filter );
|
282 |
+
|
283 |
+
// Query arguments
|
284 |
+
$args = array( $time );
|
285 |
+
$args = array_merge( $args, $where_parameters['args'] );
|
286 |
+
|
287 |
+
if( $page_offset >= 0 ) {
|
288 |
+
$first_record = $page_offset * $limit;
|
289 |
+
} else {
|
290 |
+
$first_record = ( -$page_offset - 1 ) * $limit;
|
291 |
+
}
|
292 |
+
|
293 |
+
|
294 |
+
$wpml_join_particle = $localization_helper
|
295 |
+
->get_wpml_table_join( 'p.ID' );
|
296 |
+
|
297 |
+
$wpml_where_particle = $localization_helper
|
298 |
+
->get_wpml_table_where();
|
299 |
+
|
300 |
+
$filter_date_clause = ( $page_offset >= 0 )
|
301 |
+
? 'i.end >= %d '
|
302 |
+
: 'i.start < %d ';
|
303 |
+
$order_direction = ( $page_offset >= 0 ) ? 'ASC' : 'DESC';
|
304 |
+
if ( false !== $last_day ) {
|
305 |
+
if ( 0 == $last_day ) {
|
306 |
+
$last_day = $time;
|
307 |
+
}
|
308 |
+
$filter_date_clause = ' i.end ';
|
309 |
+
if ( $page_offset < 0 ) {
|
310 |
+
$filter_date_clause .= '<';
|
311 |
+
$order_direction = 'DESC';
|
312 |
+
} else {
|
313 |
+
$filter_date_clause .= '>';
|
314 |
+
$order_direction = 'ASC';
|
315 |
+
}
|
316 |
+
$filter_date_clause .= ' %d ';
|
317 |
+
$args[0] = $last_day;
|
318 |
+
$first_record = 0;
|
319 |
+
}
|
320 |
+
$query = $this->_dbi->prepare(
|
321 |
+
'SELECT DISTINCT p.*, e.post_id, i.id AS instance_id, ' .
|
322 |
+
'i.start AS start, ' .
|
323 |
+
'i.end AS end, ' .
|
324 |
+
'e.allday AS event_allday, ' .
|
325 |
+
'e.recurrence_rules, e.exception_rules, e.ticket_url, e.instant_event, e.recurrence_dates, e.exception_dates, ' .
|
326 |
+
'e.venue, e.country, e.address, e.city, e.province, e.postal_code, ' .
|
327 |
+
'e.show_map, e.contact_name, e.contact_phone, e.contact_email, e.cost, ' .
|
328 |
+
'e.ical_feed_url, e.ical_source_url, e.ical_organizer, e.ical_contact, e.ical_uid, e.timezone_name, e.longitude, e.latitude ' .
|
329 |
+
'FROM ' . $this->_dbi->get_table_name( 'ai1ec_events' ) . ' e ' .
|
330 |
+
'INNER JOIN ' . $this->_dbi->get_table_name( 'posts' ) . ' p ON e.post_id = p.ID ' .
|
331 |
+
$wpml_join_particle .
|
332 |
+
' INNER JOIN ' . $this->_dbi->get_table_name( 'ai1ec_event_instances' ) . ' i ON e.post_id = i.post_id ' .
|
333 |
+
$filter['filter_join'] .
|
334 |
+
" WHERE post_type = '" . AI1EC_POST_TYPE . "' " .
|
335 |
+
' AND ' . $filter_date_clause .
|
336 |
+
$wpml_where_particle .
|
337 |
+
$filter['filter_where'] .
|
338 |
+
$post_status_where .
|
339 |
+
( $unique ? ' GROUP BY e.post_id' : '' ) .
|
340 |
+
// Reverse order when viewing negative pages, to get correct set of
|
341 |
+
// records. Then reverse results later to order them properly.
|
342 |
+
' ORDER BY i.start ' . $order_direction .
|
343 |
+
', post_title ' . $order_direction .
|
344 |
+
' LIMIT ' . $first_record . ', ' . $upper_boundary,
|
345 |
+
$args
|
346 |
+
);
|
347 |
+
|
348 |
+
$events = $this->_dbi->get_results( $query, ARRAY_A );
|
349 |
+
|
350 |
+
// Limit the number of records to convert to data-object
|
351 |
+
$events = $this->_limit_result_set(
|
352 |
+
$events,
|
353 |
+
$limit,
|
354 |
+
( false !== $last_day )
|
355 |
+
);
|
356 |
+
|
357 |
+
// Reorder records if in negative page offset
|
358 |
+
if( $page_offset < 0 ) {
|
359 |
+
$events = array_reverse( $events );
|
360 |
+
}
|
361 |
+
|
362 |
+
$date_first = $date_last = NULL;
|
363 |
+
|
364 |
+
foreach ( $events as &$event ) {
|
365 |
+
$event['allday'] = $this->_is_all_day( $event );
|
366 |
+
$event = $this->_registry->get( 'model.event', $event );
|
367 |
+
if ( null === $date_first ) {
|
368 |
+
$date_first = $event->get( 'start' );
|
369 |
+
}
|
370 |
+
$date_last = $event->get( 'start' );
|
371 |
+
}
|
372 |
+
$date_first = $this->_registry->get( 'date.time', $date_first );
|
373 |
+
$date_last = $this->_registry->get( 'date.time', $date_last );
|
374 |
+
// jus show next/prev links, in case no event found is shown.
|
375 |
+
$next = true;
|
376 |
+
$prev = true;
|
377 |
+
|
378 |
+
return array(
|
379 |
+
'events' => $events,
|
380 |
+
'prev' => $prev,
|
381 |
+
'next' => $next,
|
382 |
+
'date_first' => $date_first,
|
383 |
+
'date_last' => $date_last,
|
384 |
+
);
|
385 |
+
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* get_events_relative_to_reference function
|
389 |
+
*
|
390 |
+
* Return all events starting after the given date reference, limiting the
|
391 |
+
* result set to a maximum of $limit items, offset by $page_offset. A
|
392 |
+
* negative $page_offset can be provided, which will return events *before*
|
393 |
+
* the reference time, as expected.
|
394 |
+
*
|
395 |
+
* @param int $date_reference if page_offset is greater than or equal to zero, events with start date greater than the date_reference will be returned
|
396 |
+
* otherwise events with start date less than the date_reference will be returned.
|
397 |
+
* @param int $limit return a maximum of this number of items
|
398 |
+
* @param int $page_offset offset the result set by $limit times this number
|
399 |
+
* @param array $filter Array of filters for the events returned.
|
400 |
+
* ['cat_ids'] => non-associatative array of category IDs
|
401 |
+
* ['tag_ids'] => non-associatative array of tag IDs
|
402 |
+
* ['post_ids'] => non-associatative array of post IDs
|
403 |
+
* ['auth_ids'] => non-associatative array of author IDs
|
404 |
+
* ['instance_ids'] => non-associatative array of author IDs
|
405 |
+
* @param bool $unique Whether display only unique events and don't
|
406 |
+
* duplicate results with other instances or not.
|
407 |
+
*
|
408 |
+
* @return array five-element array:
|
409 |
+
* ['events'] an array of matching event objects
|
410 |
+
* ['prev'] true if more previous events
|
411 |
+
* ['next'] true if more next events
|
412 |
+
* ['date_first'] UNIX timestamp (date part) of first event
|
413 |
+
* ['date_last'] UNIX timestamp (date part) of last event
|
414 |
+
*/
|
415 |
+
public function get_events_relative_to_reference( $date_reference, $limit = 0, $page_offset = 0, $filter = array(), $unique = false ) {
|
416 |
+
$localization_helper = $this->_registry->get( 'p28n.wpml' );
|
417 |
+
$settings = $this->_registry->get( 'model.settings' );
|
418 |
+
|
419 |
+
// Even if there ARE more than 5 times the limit results - we shall not
|
420 |
+
// try to fetch and display these, as it would crash system
|
421 |
+
$limit = preg_replace( '/\D/', '', $limit );
|
422 |
+
|
423 |
+
// Convert timestamp to GMT time
|
424 |
+
if ( 0 == $date_reference ) {
|
425 |
+
$timezone = $this->_registry->get( 'date.timezone' )->get( $settings->get( 'timezone_string' ) );
|
426 |
+
$current_time = new DateTime( 'now' );
|
427 |
+
$current_time->setTimezone( $timezone );
|
428 |
+
$time = $current_time->format( 'U' );
|
429 |
+
} else {
|
430 |
+
$time = $date_reference;
|
431 |
+
}
|
432 |
+
|
433 |
+
// Get post status Where snippet and associated SQL arguments
|
434 |
+
$where_parameters = $this->_get_post_status_sql();
|
435 |
+
$post_status_where = $where_parameters['post_status_where'];
|
436 |
+
|
437 |
+
// Get the Join (filter_join) and Where (filter_where) statements based
|
438 |
+
// on $filter elements specified
|
439 |
+
$filter = $this->_get_filter_sql( $filter );
|
440 |
+
|
441 |
+
// Query arguments
|
442 |
+
$args = array( $time );
|
443 |
+
$args = array_merge( $args, $where_parameters['args'] );
|
444 |
+
|
445 |
+
if ( 0 == $date_reference ) {
|
446 |
+
if ( $page_offset >= 0 ) {
|
447 |
+
$filter_date_clause = 'i.end >= %d ';
|
448 |
+
$order_direction = 'ASC';
|
449 |
+
} else {
|
450 |
+
$filter_date_clause = 'i.start < %d ';
|
451 |
+
$order_direction = 'DESC';
|
452 |
+
}
|
453 |
+
} else {
|
454 |
+
if ( $page_offset < 0 ) {
|
455 |
+
$filter_date_clause = 'i.end < %d ';
|
456 |
+
$order_direction = 'DESC';
|
457 |
+
} else {
|
458 |
+
$filter_date_clause = 'i.end >= %d ';
|
459 |
+
$order_direction = 'ASC';
|
460 |
+
}
|
461 |
+
}
|
462 |
+
if ( $page_offset >= 0 ) {
|
463 |
+
$first_record = $page_offset * $limit;
|
464 |
+
} else {
|
465 |
+
$first_record = ( - $page_offset - 1 ) * $limit;
|
466 |
+
}
|
467 |
+
$wpml_join_particle = $localization_helper->get_wpml_table_join( 'p.ID' );
|
468 |
+
$wpml_where_particle = $localization_helper->get_wpml_table_where();
|
469 |
+
|
470 |
+
$query = $this->_dbi->prepare(
|
471 |
+
'SELECT DISTINCT p.*, e.post_id, i.id AS instance_id, ' . 'i.start AS start, ' . 'i.end AS end, ' .
|
472 |
+
'e.allday AS event_allday, ' .
|
473 |
+
'e.recurrence_rules, e.exception_rules, e.ticket_url, e.instant_event, e.recurrence_dates, e.exception_dates, ' .
|
474 |
+
'e.venue, e.country, e.address, e.city, e.province, e.postal_code, ' .
|
475 |
+
'e.show_map, e.contact_name, e.contact_phone, e.contact_email, e.cost, ' .
|
476 |
+
'e.ical_feed_url, e.ical_source_url, e.ical_organizer, e.ical_contact, e.ical_uid, e.timezone_name, e.longitude, e.latitude ' .
|
477 |
+
'FROM ' . $this->_dbi->get_table_name( 'ai1ec_events' ) . ' e ' . 'INNER JOIN ' .
|
478 |
+
$this->_dbi->get_table_name( 'posts' ) . ' p ON e.post_id = p.ID ' . $wpml_join_particle .
|
479 |
+
' INNER JOIN ' . $this->_dbi->get_table_name( 'ai1ec_event_instances' ) . ' i ON e.post_id = i.post_id ' .
|
480 |
+
$filter['filter_join'] . " WHERE post_type = '" . AI1EC_POST_TYPE . "' " . ' AND ' . $filter_date_clause .
|
481 |
+
$wpml_where_particle . $filter['filter_where'] . $post_status_where .
|
482 |
+
( $unique ? ' GROUP BY e.post_id' : '' ) .
|
483 |
+
// Reverse order when viewing negative pages, to get correct set of
|
484 |
+
// records. Then reverse results later to order them properly.
|
485 |
+
' ORDER BY i.start ' . $order_direction . ', post_title ' . $order_direction . ' LIMIT ' . $first_record .
|
486 |
+
', ' . ( $limit + 1 ),
|
487 |
+
$args );
|
488 |
+
|
489 |
+
$events = $this->_dbi->get_results( $query, ARRAY_A );
|
490 |
+
|
491 |
+
if ( $page_offset >= 0 ) {
|
492 |
+
$prev = true;
|
493 |
+
$next = ( count( $events ) > $limit );
|
494 |
+
if ( $next ) {
|
495 |
+
array_pop( $events );
|
496 |
+
}
|
497 |
+
} else {
|
498 |
+
$prev = ( count( $events ) > $limit );
|
499 |
+
if ( $prev ) {
|
500 |
+
array_pop( $events );
|
501 |
+
}
|
502 |
+
$next = true;
|
503 |
+
}
|
504 |
+
|
505 |
+
// Reorder records if in negative page offset
|
506 |
+
if ( $page_offset < 0 ) {
|
507 |
+
$events = array_reverse( $events );
|
508 |
+
}
|
509 |
+
|
510 |
+
$date_first = $date_last = NULL;
|
511 |
+
|
512 |
+
foreach ( $events as &$event ) {
|
513 |
+
$event['allday'] = $this->_is_all_day( $event );
|
514 |
+
$event = $this->_registry->get( 'model.event', $event );
|
515 |
+
if ( null === $date_first ) {
|
516 |
+
$date_first = $event->get( 'start' );
|
517 |
+
}
|
518 |
+
$date_last = $event->get( 'start' );
|
519 |
+
}
|
520 |
+
$date_first = $this->_registry->get( 'date.time', $date_first );
|
521 |
+
$date_last = $this->_registry->get( 'date.time', $date_last );
|
522 |
+
|
523 |
+
return array(
|
524 |
+
'events' => $events,
|
525 |
+
'prev' => $prev,
|
526 |
+
'next' => $next,
|
527 |
+
'date_first' => $date_first,
|
528 |
+
'date_last' => $date_last );
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Returns events for given day. Event must start before end of day and must
|
533 |
+
* ends after beginning of day.
|
534 |
+
*
|
535 |
+
* @param Ai1ec_Date_Time $day Date object.
|
536 |
+
* @param array $filter Search filters;
|
537 |
+
*
|
538 |
+
* @return array List of events.
|
539 |
+
*/
|
540 |
+
public function get_events_for_day(
|
541 |
+
Ai1ec_Date_Time $day,
|
542 |
+
array $filter = array()
|
543 |
+
) {
|
544 |
+
$end_of_day = $this->_registry->get( 'date.time', $day )
|
545 |
+
->set_time( 23, 59, 59 );
|
546 |
+
$start_of_day = $this->_registry->get( 'date.time', $day )
|
547 |
+
->set_time( 0, 0, 0 );
|
548 |
+
return $this->get_events_between(
|
549 |
+
$start_of_day,
|
550 |
+
$end_of_day,
|
551 |
+
$filter,
|
552 |
+
false,
|
553 |
+
true
|
554 |
+
);
|
555 |
+
}
|
556 |
+
|
557 |
+
/**
|
558 |
+
* Get ID of event in database, matching imported one.
|
559 |
+
*
|
560 |
+
* Return event ID by iCalendar UID, feed url, start time and whether the
|
561 |
+
* event has recurrence rules (to differentiate between an event with a UID
|
562 |
+
* defining the recurrence pattern, and other events with with the same UID,
|
563 |
+
* which are just RECURRENCE-IDs).
|
564 |
+
*
|
565 |
+
* @param int $uid iCalendar UID property
|
566 |
+
* @param string $feed Feed URL
|
567 |
+
* @param int $start Start timestamp (GMT)
|
568 |
+
* @param bool $has_recurrence Whether the event has recurrence rules
|
569 |
+
* @param int|null $exclude_post_id Do not match against this post ID
|
570 |
+
*
|
571 |
+
* @return object|null ID of matching event post, or NULL if no match
|
572 |
+
*/
|
573 |
+
public function get_matching_event_id(
|
574 |
+
$uid,
|
575 |
+
$feed,
|
576 |
+
$start,
|
577 |
+
$has_recurrence = false,
|
578 |
+
$exclude_post_id = null
|
579 |
+
) {
|
580 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
581 |
+
$table_name = $dbi->get_table_name( 'ai1ec_events' );
|
582 |
+
$query = 'SELECT `post_id` FROM ' . $table_name . '
|
583 |
+
WHERE
|
584 |
+
ical_feed_url = %s
|
585 |
+
AND ical_uid = %s
|
586 |
+
AND start = %d ' .
|
587 |
+
( $has_recurrence ? 'AND NOT ' : 'AND ' ) .
|
588 |
+
' ( recurrence_rules IS NULL OR recurrence_rules = \'\' )';
|
589 |
+
$args = array( $feed, $uid );
|
590 |
+
if ( $start instanceof Ai1ec_Date_Time ) {
|
591 |
+
$args[] = $start->format();
|
592 |
+
} else {
|
593 |
+
$args[] = (int)$start;
|
594 |
+
}
|
595 |
+
if ( null !== $exclude_post_id ) {
|
596 |
+
$query .= ' AND post_id <> %d';
|
597 |
+
$args[] = $exclude_post_id;
|
598 |
+
}
|
599 |
+
|
600 |
+
return $dbi->get_var( $dbi->prepare( $query, $args ) );
|
601 |
+
}
|
602 |
+
|
603 |
+
/**
|
604 |
+
* Get event by UID. UID must be unique.
|
605 |
+
*
|
606 |
+
* NOTICE: deletes events with that UID if they have different URLs.
|
607 |
+
*
|
608 |
+
* @param string $uid UID from feed.
|
609 |
+
* @param string $uid Feed URL.
|
610 |
+
*
|
611 |
+
* @return int|null Matching Event ID or NULL if none found.
|
612 |
+
*/
|
613 |
+
public function get_matching_event_by_uid_and_url( $uid, $url ) {
|
614 |
+
if ( ! isset( $uid{1} ) ) {
|
615 |
+
return null;
|
616 |
+
}
|
617 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
618 |
+
$table_name = $dbi->get_table_name( 'ai1ec_events' );
|
619 |
+
$argv = array( $url, $uid, $url );
|
620 |
+
// fix issue where invalid feed URLs were assigned
|
621 |
+
$update = 'UPDATE ' . $table_name . ' SET `ical_feed_url` = %s' .
|
622 |
+
' WHERE `ical_uid` = %s AND `ical_feed_url` != %s';
|
623 |
+
$query = $dbi->prepare( $update, $argv);
|
624 |
+
$success = $dbi->query( $query );
|
625 |
+
|
626 |
+
// retrieve actual feed ID if any
|
627 |
+
$select = 'SELECT `post_id` FROM `' . $table_name .
|
628 |
+
'` WHERE `ical_uid` = %s';
|
629 |
+
return $dbi->get_var( $dbi->prepare( $select, array( $uid ) ) );
|
630 |
+
}
|
631 |
+
|
632 |
+
/**
|
633 |
+
* Get event ids for the passed feed url
|
634 |
+
*
|
635 |
+
* @param string $feed_url
|
636 |
+
*/
|
637 |
+
public function get_event_ids_for_feed( $feed_url ) {
|
638 |
+
$dbi = $this->_registry->get( 'dbi.dbi' );
|
639 |
+
$table_name = $dbi->get_table_name( 'ai1ec_events' );
|
640 |
+
$query = 'SELECT `post_id` FROM ' . $table_name .
|
641 |
+
' WHERE ical_feed_url = %s';
|
642 |
+
return $dbi->get_col( $dbi->prepare( $query, array( $feed_url ) ) );
|
643 |
+
}
|
644 |
+
|
645 |
+
/**
|
646 |
+
* Returns events instances closest to today.
|
647 |
+
*
|
648 |
+
* @param array $events_ids Events ids filter.
|
649 |
+
*
|
650 |
+
* @return array Events collection.
|
651 |
+
* @throws Ai1ec_Bootstrap_Exception
|
652 |
+
*/
|
653 |
+
public function get_instances_closest_to_today( array $events_ids = array() ) {
|
654 |
+
$where_events_ids = '';
|
655 |
+
if ( ! empty( $events_ids ) ) {
|
656 |
+
$where_events_ids = 'i.post_id IN ('
|
657 |
+
. implode( ',', $events_ids ) . ') AND ';
|
658 |
+
}
|
659 |
+
$query = 'SELECT i.id, i.post_id FROM ' .
|
660 |
+
$this->_dbi->get_table_name( 'ai1ec_event_instances' ) .
|
661 |
+
' i WHERE ' .
|
662 |
+
$where_events_ids .
|
663 |
+
' i.start > %d ' .
|
664 |
+
' GROUP BY i.post_id';
|
665 |
+
/** @var $today Ai1ec_Date_Time */
|
666 |
+
$today = $this->_registry->get( 'date.time', 'now', 'sys.default' );
|
667 |
+
$today->set_time( 0, 0, 0 );
|
668 |
+
$query = $this->_dbi->prepare( $query, $today->format( 'U' ) );
|
669 |
+
$results = $this->_dbi->get_results( $query );
|
670 |
+
$events = array();
|
671 |
+
foreach ( $results as $result ) {
|
672 |
+
$events[] = $this->get_event(
|
673 |
+
$result->post_id,
|
674 |
+
$result->id
|
675 |
+
);
|
676 |
+
}
|
677 |
+
|
678 |
+
return $events;
|
679 |
+
}
|
680 |
+
|
681 |
+
/**
|
682 |
+
* Check if given event must be treated as all-day event.
|
683 |
+
*
|
684 |
+
* Event instances that span 24 hours are treated as all-day.
|
685 |
+
* NOTICE: event is passed in before being transformed into
|
686 |
+
* Ai1ec_Event object, with Ai1ec_Date_Time fields.
|
687 |
+
*
|
688 |
+
* @param array $event Event data returned from database.
|
689 |
+
*
|
690 |
+
* @return bool True if event is all-day event.
|
691 |
+
*/
|
692 |
+
protected function _is_all_day( array $event ) {
|
693 |
+
if ( isset( $event['event_allday'] ) && $event['event_allday'] ) {
|
694 |
+
return true;
|
695 |
+
}
|
696 |
+
|
697 |
+
if ( ! isset( $event['start'] ) || ! isset( $event['end'] ) ) {
|
698 |
+
return false;
|
699 |
+
}
|
700 |
+
|
701 |
+
return ( 86400 === $event['end'] - $event['start'] );
|
702 |
+
}
|
703 |
+
|
704 |
+
/**
|
705 |
+
* _limit_result_set function
|
706 |
+
*
|
707 |
+
* Slice given number of events from list, with exception when all
|
708 |
+
* events from last day shall be included.
|
709 |
+
*
|
710 |
+
* @param array $events List of events to slice
|
711 |
+
* @param int $limit Number of events to slice-off
|
712 |
+
* @param bool $last_day Set to true to include all events from last day ignoring {$limit}
|
713 |
+
*
|
714 |
+
* @return array Sliced events list
|
715 |
+
*/
|
716 |
+
protected function _limit_result_set(
|
717 |
+
array $events,
|
718 |
+
$limit,
|
719 |
+
$last_day
|
720 |
+
) {
|
721 |
+
$limited_events = array();
|
722 |
+
$start_day_previous = 0;
|
723 |
+
foreach ( $events as $event ) {
|
724 |
+
$start_day = date(
|
725 |
+
'Y-m-d',
|
726 |
+
$event['start']
|
727 |
+
);
|
728 |
+
--$limit; // $limit = $limit - 1;
|
729 |
+
if ( $limit < 0 ) {
|
730 |
+
if ( true === $last_day ) {
|
731 |
+
if ( $start_day != $start_day_previous ) {
|
732 |
+
break;
|
733 |
+
}
|
734 |
+
} else {
|
735 |
+
break;
|
736 |
+
}
|
737 |
+
}
|
738 |
+
$limited_events[] = $event;
|
739 |
+
$start_day_previous = $start_day;
|
740 |
+
}
|
741 |
+
return $limited_events;
|
742 |
+
}
|
743 |
+
|
744 |
+
/**
|
745 |
+
* _get_post_status_sql function
|
746 |
+
*
|
747 |
+
* Returns SQL snippet for properly matching event posts, as well as array
|
748 |
+
* of arguments to pass to $this_dbi->prepare, in function argument
|
749 |
+
* references.
|
750 |
+
* Nothing is returned by the function.
|
751 |
+
*
|
752 |
+
* @return array An array containing post_status_where: the sql string,
|
753 |
+
* args: the arguments for prepare()
|
754 |
+
*/
|
755 |
+
protected function _get_post_status_sql() {
|
756 |
+
$args = array();
|
757 |
+
|
758 |
+
// Query the correct post status
|
759 |
+
if (
|
760 |
+
current_user_can( 'administrator' ) ||
|
761 |
+
current_user_can( 'editor' )
|
762 |
+
) {
|
763 |
+
// User has privilege of seeing all published and private
|
764 |
+
$post_status_where = 'AND post_status IN ( %s, %s ) ';
|
765 |
+
$args[] = 'publish';
|
766 |
+
$args[] = 'private';
|
767 |
+
} elseif ( is_user_logged_in() ) {
|
768 |
+
// User has privilege of seeing all published and only their own
|
769 |
+
// private posts.
|
770 |
+
|
771 |
+
// Get user ID
|
772 |
+
$user_id = 0;
|
773 |
+
if ( is_callable( 'wp_get_current_user' ) ) {
|
774 |
+
$user = wp_get_current_user();
|
775 |
+
$user_id = (int)$user->ID;
|
776 |
+
unset( $user );
|
777 |
+
}
|
778 |
+
|
779 |
+
// include post_status = published
|
780 |
+
// OR
|
781 |
+
// post_status = private AND post_author = userID
|
782 |
+
$post_status_where =
|
783 |
+
'AND ( ' .
|
784 |
+
'post_status = %s ' .
|
785 |
+
'OR ( post_status = %s AND post_author = %d ) ' .
|
786 |
+
') ';
|
787 |
+
|
788 |
+
$args[] = 'publish';
|
789 |
+
$args[] = 'private';
|
790 |
+
$args[] = $user_id;
|
791 |
+
} else {
|
792 |
+
// User can only see published posts.
|
793 |
+
$post_status_where = 'AND post_status = %s ';
|
794 |
+
$args[] = 'publish';
|
795 |
+
}
|
796 |
+
|
797 |
+
return array(
|
798 |
+
'post_status_where' => $post_status_where,
|
799 |
+
'args' => $args
|
800 |
+
);
|
801 |
+
}
|
802 |
+
|
803 |
+
/**
|
804 |
+
* Take filter and return SQL options.
|
805 |
+
*
|
806 |
+
* Takes an array of filtering options and turns it into JOIN and WHERE
|
807 |
+
* statements for running an SQL query limited to the specified options.
|
808 |
+
*
|
809 |
+
* @param array $filter Array of filters for the events returned:
|
810 |
+
* ['cat_ids'] => list of category IDs
|
811 |
+
* ['tag_ids'] => list of tag IDs
|
812 |
+
* ['post_ids'] => list of event post IDs
|
813 |
+
* ['auth_ids'] => list of event author IDs
|
814 |
+
* ['instance_ids'] => list of event instance IDs
|
815 |
+
*
|
816 |
+
* @return array The modified filter array to having:
|
817 |
+
* ['filter_join'] the Join statements for the SQL
|
818 |
+
* ['filter_where'] the Where statements for the SQL
|
819 |
+
*/
|
820 |
+
protected function _get_filter_sql( $filter ) {
|
821 |
+
$filter_join = $filter_where = array();
|
822 |
+
foreach ( $filter as $filter_type => $filter_ids ) {
|
823 |
+
$filter_object = null;
|
824 |
+
try {
|
825 |
+
if ( empty( $filter_ids ) ) {
|
826 |
+
$filter_ids = array();
|
827 |
+
}
|
828 |
+
$filter_object = $this->_registry->get(
|
829 |
+
'model.filter.' . $filter_type,
|
830 |
+
$filter_ids
|
831 |
+
);
|
832 |
+
if ( ! ( $filter_object instanceof Ai1ec_Filter_Interface ) ) {
|
833 |
+
throw new Ai1ec_Bootstrap_Exception(
|
834 |
+
'Filter \'' . get_class( $filter_object ) .
|
835 |
+
'\' is not instance of Ai1ec_Filter_Interface'
|
836 |
+
);
|
837 |
+
}
|
838 |
+
} catch ( Ai1ec_Bootstrap_Exception $exception ) {
|
839 |
+
continue;
|
840 |
+
}
|
841 |
+
$filter_join[] = $filter_object->get_join();
|
842 |
+
$filter_where[] = $filter_object->get_where();
|
843 |
+
}
|
844 |
+
|
845 |
+
$filter_join = array_filter( $filter_join );
|
846 |
+
$filter_where = array_filter( $filter_where );
|
847 |
+
$filter_join = join( ' ', $filter_join );
|
848 |
+
if ( count( $filter_where ) > 0 ) {
|
849 |
+
$operator = $this->get_distinct_types_operator();
|
850 |
+
$filter_where = $operator . '( ' .
|
851 |
+
implode( ' ) ' . $operator . ' ( ', $filter_where ) .
|
852 |
+
' ) ';
|
853 |
+
} else {
|
854 |
+
$filter_where = '';
|
855 |
+
}
|
856 |
+
|
857 |
+
return $filter + compact( 'filter_where', 'filter_join' );
|
858 |
+
}
|
859 |
+
|
860 |
+
/**
|
861 |
+
* Get operator for joining distinct filters in WHERE.
|
862 |
+
*
|
863 |
+
* @return string SQL operator.
|
864 |
+
*/
|
865 |
+
public function get_distinct_types_operator() {
|
866 |
+
static $operators = array( 'AND' => 1, 'OR' => 2 );
|
867 |
+
$default = 'AND';
|
868 |
+
$where_operator = strtoupper( trim( (string)apply_filters(
|
869 |
+
'ai1ec_filter_distinct_types_logic',
|
870 |
+
$default
|
871 |
+
) ) );
|
872 |
+
if ( ! isset( $operators[$where_operator] ) ) {
|
873 |
+
$where_operator = $default;
|
874 |
+
}
|
875 |
+
return $where_operator;
|
876 |
+
}
|
877 |
|
878 |
}
|
app/model/settings-view.php
CHANGED
@@ -10,158 +10,158 @@
|
|
10 |
*/
|
11 |
class Ai1ec_Settings_View extends Ai1ec_App {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
|
167 |
}
|
10 |
*/
|
11 |
class Ai1ec_Settings_View extends Ai1ec_App {
|
12 |
|
13 |
+
/**
|
14 |
+
* @var string Name of settings option to use for views map.
|
15 |
+
*/
|
16 |
+
const SETTING_VIEWS_MAP = 'enabled_views';
|
17 |
|
18 |
+
/**
|
19 |
+
* @var Ai1ec_Settings Instance
|
20 |
+
*/
|
21 |
+
protected $_settings = null;
|
22 |
|
23 |
+
/**
|
24 |
+
* Acquire Settings model instance for future reference.
|
25 |
+
*
|
26 |
+
* @return void
|
27 |
+
*/
|
28 |
+
protected function _initialize() {
|
29 |
+
$this->_settings = $this->_registry->get( 'model.settings' );
|
30 |
+
}
|
31 |
|
32 |
+
/**
|
33 |
+
* Add a view if not set.
|
34 |
+
*
|
35 |
+
* @param array $view
|
36 |
+
*/
|
37 |
+
public function add( array $view ) {
|
38 |
+
$enabled_views = $this->_get();
|
39 |
+
if ( isset( $enabled_views[$view['name']] ) ) {
|
40 |
+
if ( $enabled_views[$view['name']]['longname'] === $view['longname'] ) {
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
$enabled_views[$view['name']]['longname'] = $view['longname'];
|
44 |
+
} else {
|
45 |
+
// Copy relevant settings to local view array; account for possible missing
|
46 |
+
// mobile settings during upgrade (assign defaults).
|
47 |
+
$enabled_views[$view['name']] = array(
|
48 |
+
'enabled' => $view['enabled'],
|
49 |
+
'default' => $view['default'],
|
50 |
+
'enabled_mobile' => isset( $view['enabled_mobile'] ) ?
|
51 |
+
$view['enabled_mobile'] : $view['enabled'],
|
52 |
+
'default_mobile' => isset( $view['default_mobile'] ) ?
|
53 |
+
$view['default_mobile'] : $view['default'],
|
54 |
+
'longname' => $view['longname'],
|
55 |
+
);
|
56 |
+
}
|
57 |
+
$this->_set( $enabled_views );
|
58 |
+
}
|
59 |
|
60 |
+
/**
|
61 |
+
* Remove a view.
|
62 |
+
*
|
63 |
+
* @param string $view
|
64 |
+
*/
|
65 |
+
public function remove( $view ) {
|
66 |
+
$enabled_views = $this->_get();
|
67 |
+
if ( isset( $enabled_views[$view] ) ) {
|
68 |
+
unset( $enabled_views[$view] );
|
69 |
+
$this->_set( $enabled_views );
|
70 |
+
}
|
71 |
+
}
|
72 |
|
73 |
+
/**
|
74 |
+
* Retrieve all configured views.
|
75 |
+
*
|
76 |
+
* @return array Map of configured view aliases and their details.
|
77 |
+
*/
|
78 |
+
public function get_all() {
|
79 |
+
return $this->_get();
|
80 |
+
}
|
81 |
|
82 |
+
/**
|
83 |
+
* Get name of view to be rendered for requested alias.
|
84 |
+
*
|
85 |
+
* @param string $view Name of view requested.
|
86 |
+
*
|
87 |
+
* @return string Name of view to be rendered.
|
88 |
+
*
|
89 |
+
* @throws Ai1ec_Settings_Exception If no views are configured.
|
90 |
+
*/
|
91 |
+
public function get_configured( $view ) {
|
92 |
+
$enabled_views = $this->_get();
|
93 |
+
if ( empty( $enabled_views ) ) {
|
94 |
+
throw new Ai1ec_Settings_Exception( 'No view is enabled' );
|
95 |
+
}
|
96 |
+
if (
|
97 |
+
isset( $enabled_views[$view] ) &&
|
98 |
+
$enabled_views[$view]['enabled' . ( wp_is_mobile() ? '_mobile' : '' ) ]
|
99 |
+
) {
|
100 |
+
return $view;
|
101 |
+
}
|
102 |
+
return $this->get_default();
|
103 |
+
}
|
104 |
|
105 |
+
/**
|
106 |
+
* Get default view to render.
|
107 |
+
*
|
108 |
+
*
|
109 |
+
* @return
|
110 |
+
*/
|
111 |
+
public function get_default() {
|
112 |
+
$enabled_views = $this->_get();
|
113 |
+
$default = null;
|
114 |
+
// Check mobile settings first, if in mobile mode.
|
115 |
+
if (
|
116 |
+
! $this->_registry->get( 'compatibility.cli' )->is_cli() &&
|
117 |
+
wp_is_mobile()
|
118 |
+
) {
|
119 |
+
foreach ( $enabled_views as $view => $details ) {
|
120 |
+
if (
|
121 |
+
isset( $details['default_mobile'] ) &&
|
122 |
+
$details['default_mobile'] &&
|
123 |
+
$details['enabled_mobile']
|
124 |
+
) {
|
125 |
+
$default = $view;
|
126 |
+
break;
|
127 |
+
}
|
128 |
+
}
|
129 |
+
}
|
130 |
+
// Either not in mobile mode or no mobile settings available; look up
|
131 |
+
// desktop settings.
|
132 |
+
if ( null === $default ) {
|
133 |
+
foreach ( $enabled_views as $view => $details ) {
|
134 |
+
if ( $details['default'] && $details['enabled'] ) {
|
135 |
+
$default = $view;
|
136 |
+
break;
|
137 |
+
}
|
138 |
+
}
|
139 |
+
}
|
140 |
+
// No enabled view found, but we need to pick one, so pick the first view.
|
141 |
+
if ( null === $default ) {
|
142 |
+
$default = (string)current( array_keys( $enabled_views ) );
|
143 |
+
}
|
144 |
+
return $default;
|
145 |
+
}
|
146 |
|
147 |
+
/**
|
148 |
+
* Retrieve views maps from storage.
|
149 |
+
*
|
150 |
+
* @return array Current views map.
|
151 |
+
*/
|
152 |
+
protected function _get() {
|
153 |
+
return (array)$this->_settings->get( self::SETTING_VIEWS_MAP, array() );
|
154 |
+
}
|
155 |
|
156 |
+
/**
|
157 |
+
* Update views map.
|
158 |
+
*
|
159 |
+
* @param array $enabled_views Map of enabled views.
|
160 |
+
*
|
161 |
+
* @return bool Success.
|
162 |
+
*/
|
163 |
+
protected function _set( array $enabled_views ) {
|
164 |
+
return $this->_settings->set( self::SETTING_VIEWS_MAP, $enabled_views );
|
165 |
+
}
|
166 |
|
167 |
}
|
app/model/settings.php
CHANGED
@@ -10,335 +10,335 @@
|
|
10 |
*/
|
11 |
class Ai1ec_Settings extends Ai1ec_App {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
/**
|
229 |
-
* Do things needed on every plugin upgrade.
|
230 |
-
*/
|
231 |
-
public function perform_upgrade_actions() {
|
232 |
-
update_option( 'ai1ec_force_flush_rewrite_rules', true );
|
233 |
-
update_option( 'ai1ec_invalidate_css_cache', true );
|
234 |
-
update_option( Ai1ec_Theme_Loader::OPTION_FORCE_CLEAN, true );
|
235 |
-
}
|
236 |
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
$this->_change_update_status( true );
|
246 |
-
}
|
247 |
-
}
|
248 |
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
|
|
271 |
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
public function wp_options_observer( $option, $old_value, $value ) {
|
283 |
-
$options = $this->get_options();
|
284 |
-
if (
|
285 |
-
self::WP_OPTION_KEY === $option ||
|
286 |
-
empty( $options )
|
287 |
-
) {
|
288 |
-
return;
|
289 |
-
}
|
290 |
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
->get( self::WP_OPTION_KEY, array() );
|
309 |
-
$this->_change_update_status( false );
|
310 |
-
$test_version = false;
|
311 |
-
if ( is_array( $values ) ) { // always assign existing values, if any
|
312 |
-
$this->_options = $values;
|
313 |
-
if ( isset( $values['calendar_page_id'] ) ) {
|
314 |
-
$test_version = $values['calendar_page_id']['version'];
|
315 |
-
}
|
316 |
-
}
|
317 |
-
// check for updated translations
|
318 |
-
$this->_register_standard_values();
|
319 |
-
if ( // process meta updates changes
|
320 |
-
empty( $values ) || (
|
321 |
-
false !== $test_version &&
|
322 |
-
AI1EC_VERSION !== $test_version
|
323 |
-
)
|
324 |
-
) {
|
325 |
-
$this->_register_standard_values();
|
326 |
-
$this->_update_name_translations();
|
327 |
-
$this->_change_update_status( true );
|
328 |
-
} else if ( $values instanceof Ai1ec_Settings ) { // process legacy
|
329 |
-
$this->_parse_legacy( $values );
|
330 |
-
$this->_change_update_status( true );
|
331 |
-
}
|
332 |
-
$this->_registry->get( 'controller.shutdown' )->register(
|
333 |
-
array( $this, 'shutdown' )
|
334 |
-
);
|
335 |
-
}
|
336 |
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
$this->_standard_options = array(
|
343 |
'enabling_ticket_invitation_page' => array(
|
344 |
'type' => 'string',
|
@@ -348,747 +348,747 @@ class Ai1ec_Settings extends Ai1ec_App {
|
|
348 |
'type' => 'boolean',
|
349 |
'default' => false,
|
350 |
),
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
1072 |
-
|
1073 |
-
|
1074 |
-
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
|
1092 |
-
|
1093 |
|
1094 |
}
|
10 |
*/
|
11 |
class Ai1ec_Settings extends Ai1ec_App {
|
12 |
|
13 |
+
/**
|
14 |
+
* @constant string Name of WordPress options key used to store settings.
|
15 |
+
*/
|
16 |
+
const WP_OPTION_KEY = 'ai1ec_settings';
|
17 |
|
18 |
+
/**
|
19 |
+
* @var array Map of value names and their representations.
|
20 |
+
*/
|
21 |
+
protected $_options = array();
|
22 |
|
23 |
+
/**
|
24 |
+
* @var bool Indicator for modified object state.
|
25 |
+
*/
|
26 |
+
protected $_updated = false;
|
27 |
|
28 |
+
/**
|
29 |
+
* @var array The core options of the plugin.
|
30 |
+
*/
|
31 |
+
protected $_standard_options;
|
32 |
|
33 |
+
/**
|
34 |
+
* Register new option to be used.
|
35 |
+
*
|
36 |
+
* @param string $option Name of option.
|
37 |
+
* @param mixed $value The value.
|
38 |
+
* @param string $type Option type to be used for validation.
|
39 |
+
* @param string $renderer Name of class to render the option.
|
40 |
+
*
|
41 |
+
* @return Ai1ec_Settings Instance of self for chaining.
|
42 |
+
*/
|
43 |
+
public function register(
|
44 |
+
$option,
|
45 |
+
$value,
|
46 |
+
$type,
|
47 |
+
$renderer,
|
48 |
+
$version = '2.0.0'
|
49 |
+
) {
|
50 |
|
51 |
+
if ( 'deprecated' === $type ) {
|
52 |
+
unset( $this->_options[$option] );
|
53 |
+
} else if (
|
54 |
+
! isset( $this->_options[$option] ) ||
|
55 |
+
! isset( $this->_options[$option]['version'] ) ||
|
56 |
+
(string)$this->_options[$option]['version'] !== (string)$version ||
|
57 |
+
(
|
58 |
+
isset( $renderer['label'] ) &&
|
59 |
+
isset( $this->_options[$option]['renderer'] ) &&
|
60 |
+
(string)$this->_options[$option]['renderer']['label'] !== (string)$renderer['label']
|
61 |
+
) ||
|
62 |
+
(
|
63 |
+
isset( $renderer['help'] ) &&
|
64 |
+
( ! isset( $this->_options[$option]['renderer']['help'] ) || // handle the case when you are adding help
|
65 |
+
(string)$this->_options[$option]['renderer']['help'] !== (string)$renderer['help'] )
|
66 |
+
)
|
67 |
+
) {
|
68 |
+
$this->_options[$option] = array(
|
69 |
+
'value' => ( isset( $this->_options[$option] ) )
|
70 |
+
? $this->_options[$option]['value']
|
71 |
+
: $value,
|
72 |
+
'type' => $type,
|
73 |
+
'legacy' => false,
|
74 |
+
'version' => $version,
|
75 |
+
);
|
76 |
+
if ( null !== $renderer ) {
|
77 |
+
$this->_options[$option]['renderer'] = $renderer;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
return $this;
|
81 |
+
}
|
82 |
|
83 |
+
/**
|
84 |
+
* Gets the options.
|
85 |
+
*
|
86 |
+
* @return array:
|
87 |
+
*/
|
88 |
+
public function get_options() {
|
89 |
+
return $this->_options;
|
90 |
+
}
|
91 |
|
92 |
+
/**
|
93 |
+
* Get field options as registered.
|
94 |
+
*
|
95 |
+
* @param string $option Name of option field to describe.
|
96 |
+
*
|
97 |
+
* @return array|null Description or null if nothing is found.
|
98 |
+
*/
|
99 |
+
public function describe( $option ) {
|
100 |
+
if ( ! isset( $this->_options[$option] ) ) {
|
101 |
+
return null;
|
102 |
+
}
|
103 |
+
return $this->_options[$option];
|
104 |
+
}
|
105 |
|
106 |
+
/**
|
107 |
+
* Get value for option.
|
108 |
+
*
|
109 |
+
* @param string $option Name of option to get value for.
|
110 |
+
* @param mixed $default Value to return if option is not found.
|
111 |
+
*
|
112 |
+
* @return mixed Value or $default if none is found.
|
113 |
+
*/
|
114 |
+
public function get( $option, $default = null ) {
|
115 |
+
// notice, that `null` is not treated as a value
|
116 |
+
if ( ! isset( $this->_options[$option] ) ) {
|
117 |
+
return $default;
|
118 |
+
}
|
119 |
+
return $this->_options[$option]['value'];
|
120 |
+
}
|
121 |
|
122 |
+
/**
|
123 |
+
* Set new value for previously initialized option.
|
124 |
+
*
|
125 |
+
* @param string $option Name of option to update.
|
126 |
+
* @param mixed $value Actual value to be used for option.
|
127 |
+
*
|
128 |
+
* @throws Ai1ec_Settings_Exception
|
129 |
+
*
|
130 |
+
* @return Ai1ec_Settings Instance of self for chaining.
|
131 |
+
*/
|
132 |
+
public function set( $option, $value ) {
|
133 |
+
if ( ! isset( $this->_options[$option] ) ) {
|
134 |
+
throw new Ai1ec_Settings_Exception(
|
135 |
+
'Option "' . $option . '" was not registered'
|
136 |
+
);
|
137 |
+
}
|
138 |
+
if ( 'array' === $this->_options[$option]['type'] ) {
|
139 |
+
if (
|
140 |
+
! is_array( $this->_options[$option]['value'] ) ||
|
141 |
+
! is_array( $value ) ||
|
142 |
+
$value != $this->_options[$option]['value']
|
143 |
+
) {
|
144 |
+
$this->_options[$option]['value'] = $value;
|
145 |
+
$this->_change_update_status ( true );
|
146 |
+
}
|
147 |
+
} else if (
|
148 |
+
(string)$value !== (string)$this->_options[$option]['value']
|
149 |
+
) {
|
150 |
+
$this->_options[$option]['value'] = $value;
|
151 |
+
$this->_change_update_status ( true );
|
152 |
+
}
|
153 |
+
return $this;
|
154 |
+
}
|
155 |
|
156 |
+
/**
|
157 |
+
* Parse legacy values into new structure.
|
158 |
+
*
|
159 |
+
* @param mixed $values Expected legacy representation.
|
160 |
+
*
|
161 |
+
* @return array Parsed values representation, or input cast as array.
|
162 |
+
*/
|
163 |
+
protected function _parse_legacy( Ai1ec_Settings $values ) {
|
164 |
+
$variables = get_object_vars( $values );
|
165 |
+
$default_tags_cat = array();
|
166 |
+
$legacy = array();
|
167 |
+
foreach ( $variables as $key => $value ) {
|
168 |
+
if ( 'default_categories' === $key ) {
|
169 |
+
$default_tags_cat['categories'] = $value;
|
170 |
+
continue;
|
171 |
+
}
|
172 |
+
if ( 'default_tags' === $key ) {
|
173 |
+
$default_tags_cat['tags'] = $value;
|
174 |
+
continue;
|
175 |
+
}
|
176 |
+
$type = 'string';
|
177 |
+
if ( is_array( $value ) ) {
|
178 |
+
$type = 'array';
|
179 |
+
} elseif ( is_bool( $value ) ) {
|
180 |
+
$type = 'bool';
|
181 |
+
} elseif ( is_int( $value ) ) {
|
182 |
+
$type = 'int';
|
183 |
+
}
|
184 |
+
if ( isset( $this->_options[$key] ) ) {
|
185 |
+
$this->_options[$key]['value'] = $value;
|
186 |
+
} else {
|
187 |
+
$legacy[$key] = array(
|
188 |
+
'value' => $value,
|
189 |
+
'type' => $type,
|
190 |
+
'legacy' => true,
|
191 |
+
'version' => AI1EC_VERSION
|
192 |
+
);
|
193 |
+
}
|
194 |
+
}
|
195 |
+
$this->_options['default_tags_categories']['value'] = $default_tags_cat;
|
196 |
+
$this->_options['legacy_options'] = $legacy;
|
197 |
+
}
|
198 |
|
199 |
+
/**
|
200 |
+
* Write object representation to persistence layer.
|
201 |
+
*
|
202 |
+
* Upon successful write to persistence layer the objects internal
|
203 |
+
* state {@see self::$_updated} is updated respectively.
|
204 |
+
*
|
205 |
+
* @return bool Success.
|
206 |
+
*/
|
207 |
+
public function persist() {
|
208 |
+
$success = $this->_registry->get( 'model.option' )
|
209 |
+
->set( self::WP_OPTION_KEY, $this->_options );
|
210 |
+
if ( $success ) {
|
211 |
+
$this->_change_update_status( false );
|
212 |
+
}
|
213 |
+
return $success;
|
214 |
+
}
|
215 |
|
216 |
+
/**
|
217 |
+
* Remove an option if is set.
|
218 |
+
*
|
219 |
+
* @param string $option
|
220 |
+
*/
|
221 |
+
public function remove_option( $option ) {
|
222 |
+
if ( isset( $this->_options[$option] ) ) {
|
223 |
+
unset( $this->_options[$option] );
|
224 |
+
$this->_change_update_status( true );
|
225 |
+
}
|
226 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
228 |
+
/**
|
229 |
+
* Do things needed on every plugin upgrade.
|
230 |
+
*/
|
231 |
+
public function perform_upgrade_actions() {
|
232 |
+
update_option( 'ai1ec_force_flush_rewrite_rules', true );
|
233 |
+
update_option( 'ai1ec_invalidate_css_cache', true );
|
234 |
+
update_option( Ai1ec_Theme_Loader::OPTION_FORCE_CLEAN, true );
|
235 |
+
}
|
|
|
|
|
|
|
236 |
|
237 |
+
/**
|
238 |
+
* Hide an option by unsetting it's renderer
|
239 |
+
*
|
240 |
+
* @param string $option
|
241 |
+
*/
|
242 |
+
public function hide_option( $option ) {
|
243 |
+
if ( isset( $this->_options[$option] ) ) {
|
244 |
+
unset( $this->_options[$option]['renderer'] );
|
245 |
+
$this->_change_update_status( true );
|
246 |
+
}
|
247 |
+
}
|
248 |
|
249 |
+
/**
|
250 |
+
* Show an option by setting it's renderer
|
251 |
+
*
|
252 |
+
* @param string $option
|
253 |
+
*/
|
254 |
+
public function show_option( $option, array $renderer ) {
|
255 |
+
if ( isset( $this->_options[$option] ) ) {
|
256 |
+
$this->_options[$option]['renderer'] = $renderer;
|
257 |
+
$this->_change_update_status( true );
|
258 |
+
}
|
259 |
+
}
|
260 |
|
261 |
+
/**
|
262 |
+
* Check object state and update it's database representation as needed.
|
263 |
+
*
|
264 |
+
* @return void Destructor does not return.
|
265 |
+
*/
|
266 |
+
public function shutdown() {
|
267 |
+
if ( $this->_updated ) {
|
268 |
+
$this->persist();
|
269 |
+
}
|
270 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
|
272 |
+
/**
|
273 |
+
* Observes wp_options changes. If any matches related setting then
|
274 |
+
* updates that setting.
|
275 |
+
*
|
276 |
+
* @param string $option Name of the updated option.
|
277 |
+
* @param mixed $old_value The old option value.
|
278 |
+
* @param mixed $value The new option value.
|
279 |
+
*
|
280 |
+
* @return void Method does not return.
|
281 |
+
*/
|
282 |
+
public function wp_options_observer( $option, $old_value, $value ) {
|
283 |
+
$options = $this->get_options();
|
284 |
+
if (
|
285 |
+
self::WP_OPTION_KEY === $option ||
|
286 |
+
empty( $options )
|
287 |
+
) {
|
288 |
+
return;
|
289 |
+
}
|
290 |
|
291 |
+
if (
|
292 |
+
isset( $options[$option] ) &&
|
293 |
+
'wp_option' === $options[$option]['type'] &&
|
294 |
+
$this->get( $option ) !== $value
|
295 |
+
) {
|
296 |
+
$this->set( $option, $value );
|
297 |
+
}
|
298 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
|
300 |
+
/**
|
301 |
+
* Initiate options map from storage.
|
302 |
+
*
|
303 |
+
* @return void Return from this method is ignored.
|
304 |
+
*/
|
305 |
+
protected function _initialize() {
|
306 |
+
$this->_set_standard_values();
|
307 |
+
$values = $this->_registry->get( 'model.option' )
|
308 |
+
->get( self::WP_OPTION_KEY, array() );
|
309 |
+
$this->_change_update_status( false );
|
310 |
+
$test_version = false;
|
311 |
+
if ( is_array( $values ) ) { // always assign existing values, if any
|
312 |
+
$this->_options = $values;
|
313 |
+
if ( isset( $values['calendar_page_id'] ) ) {
|
314 |
+
$test_version = $values['calendar_page_id']['version'];
|
315 |
+
}
|
316 |
+
}
|
317 |
+
// check for updated translations
|
318 |
+
$this->_register_standard_values();
|
319 |
+
if ( // process meta updates changes
|
320 |
+
empty( $values ) || (
|
321 |
+
false !== $test_version &&
|
322 |
+
AI1EC_VERSION !== $test_version
|
323 |
+
)
|
324 |
+
) {
|
325 |
+
$this->_register_standard_values();
|
326 |
+
$this->_update_name_translations();
|
327 |
+
$this->_change_update_status( true );
|
328 |
+
} else if ( $values instanceof Ai1ec_Settings ) { // process legacy
|
329 |
+
$this->_parse_legacy( $values );
|
330 |
+
$this->_change_update_status( true );
|
331 |
+
}
|
332 |
+
$this->_registry->get( 'controller.shutdown' )->register(
|
333 |
+
array( $this, 'shutdown' )
|
334 |
+
);
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Set the standard values for the options of the core plugin.
|
339 |
+
*
|
340 |
+
*/
|
341 |
+
protected function _set_standard_values() {
|
342 |
$this->_standard_options = array(
|
343 |
'enabling_ticket_invitation_page' => array(
|
344 |
'type' => 'string',
|
348 |
'type' => 'boolean',
|
349 |
'default' => false,
|
350 |
),
|
351 |
+
'ai1ec_db_version' => array(
|
352 |
+
'type' => 'int',
|
353 |
+
'default' => false,
|
354 |
+
),
|
355 |
+
'feeds_page' => array(
|
356 |
+
'type' => 'string',
|
357 |
+
'default' => false,
|
358 |
+
),
|
359 |
+
'settings_page' => array(
|
360 |
+
'type' => 'string',
|
361 |
+
'default' => false,
|
362 |
+
),
|
363 |
+
'less_variables_page' => array(
|
364 |
+
'type' => 'string',
|
365 |
+
'default' => false,
|
366 |
+
),
|
367 |
+
'input_date_format' => array(
|
368 |
+
'type' => 'string',
|
369 |
+
'default' => 'd/m/yyyy',
|
370 |
+
),
|
371 |
+
'plugins_options' => array(
|
372 |
+
'type' => 'array',
|
373 |
+
'default' => array(),
|
374 |
+
),
|
375 |
+
'show_tracking_popup' => array(
|
376 |
+
'type' => 'deprecated',
|
377 |
+
'default' => true,
|
378 |
+
),
|
379 |
+
'ticketing_message' => array(
|
380 |
+
'type' => 'string',
|
381 |
+
'default' => false,
|
382 |
+
),
|
383 |
+
'ticketing_token' => array(
|
384 |
+
'type' => 'string',
|
385 |
+
'default' => '',
|
386 |
+
),
|
387 |
+
'ticketing_enabled' => array(
|
388 |
+
'type' => 'boolean',
|
389 |
+
'default' => false,
|
390 |
+
),
|
391 |
+
'ticketing_calendar_id' => array(
|
392 |
+
'type' => 'int',
|
393 |
+
'default' => 0,
|
394 |
+
),
|
395 |
+
'calendar_page_id' => array(
|
396 |
+
'type' => 'mixed',
|
397 |
+
'renderer' => array(
|
398 |
+
'class' => 'calendar-page-selector',
|
399 |
+
'tab' => 'viewing-events',
|
400 |
+
'item' => 'viewing-events',
|
401 |
+
'label' => Ai1ec_I18n::__( 'Calendar page' )
|
402 |
+
),
|
403 |
+
'default' => false,
|
404 |
+
),
|
405 |
+
'week_start_day' => array(
|
406 |
+
'type' => 'int',
|
407 |
+
'renderer' => array(
|
408 |
+
'class' => 'select',
|
409 |
+
'tab' => 'viewing-events',
|
410 |
+
'item' => 'viewing-events',
|
411 |
+
'label' => Ai1ec_I18n::__( 'Week starts on' ),
|
412 |
+
'options' => 'get_weekdays',
|
413 |
+
),
|
414 |
+
'default' => $this->_registry->get( 'model.option' )->get(
|
415 |
+
'start_of_week'
|
416 |
+
),
|
417 |
+
),
|
418 |
+
'enabled_views' => array(
|
419 |
+
'type' => 'array',
|
420 |
+
'renderer' => array(
|
421 |
+
'class' => 'enabled-views',
|
422 |
+
'tab' => 'viewing-events',
|
423 |
+
'item' => 'viewing-events',
|
424 |
+
'label' => Ai1ec_I18n::__( 'Available views' ),
|
425 |
+
),
|
426 |
+
'default' => array(
|
427 |
+
'agenda' => array(
|
428 |
+
'enabled' => true,
|
429 |
+
'default' => true,
|
430 |
+
'enabled_mobile' => true,
|
431 |
+
'default_mobile' => true,
|
432 |
+
'longname' => _n_noop(
|
433 |
+
'Agenda',
|
434 |
+
'Agenda',
|
435 |
+
AI1EC_PLUGIN_NAME
|
436 |
+
),
|
437 |
+
),
|
438 |
+
'oneday' => array(
|
439 |
+
'enabled' => true,
|
440 |
+
'default' => false,
|
441 |
+
'enabled_mobile' => true,
|
442 |
+
'default_mobile' => false,
|
443 |
+
'longname' => _n_noop(
|
444 |
+
'Day',
|
445 |
+
'Day',
|
446 |
+
AI1EC_PLUGIN_NAME
|
447 |
+
),
|
448 |
+
),
|
449 |
+
'month' => array(
|
450 |
+
'enabled' => true,
|
451 |
+
'default' => false,
|
452 |
+
'enabled_mobile' => true,
|
453 |
+
'default_mobile' => false,
|
454 |
+
'longname' => _n_noop(
|
455 |
+
'Month',
|
456 |
+
'Month',
|
457 |
+
AI1EC_PLUGIN_NAME
|
458 |
+
),
|
459 |
+
),
|
460 |
+
'week' => array(
|
461 |
+
'enabled' => true,
|
462 |
+
'default' => false,
|
463 |
+
'enabled_mobile' => true,
|
464 |
+
'default_mobile' => false,
|
465 |
+
'longname' => _n_noop(
|
466 |
+
'Week',
|
467 |
+
'Week',
|
468 |
+
AI1EC_PLUGIN_NAME
|
469 |
+
),
|
470 |
+
),
|
471 |
+
),
|
472 |
+
),
|
473 |
+
'timezone_string' => array(
|
474 |
+
'type' => 'wp_option',
|
475 |
+
'renderer' => array(
|
476 |
+
'class' => 'select',
|
477 |
+
'tab' => 'viewing-events',
|
478 |
+
'item' => 'viewing-events',
|
479 |
+
'label' => Ai1ec_I18n::__( 'Timezone' ),
|
480 |
+
'options' => 'Ai1ec_Date_Timezone:get_timezones',
|
481 |
+
),
|
482 |
+
'default' => $this->_registry->get( 'model.option' )->get(
|
483 |
+
'timezone_string'
|
484 |
+
),
|
485 |
+
),
|
486 |
+
'default_tags_categories' => array(
|
487 |
+
'type' => 'array',
|
488 |
+
'renderer' => array(
|
489 |
+
'class' => 'tags-categories',
|
490 |
+
'tab' => 'viewing-events',
|
491 |
+
'item' => 'viewing-events',
|
492 |
+
'label' => Ai1ec_I18n::__( 'Preselected calendar filters' ),
|
493 |
+
'help' => Ai1ec_I18n::__(
|
494 |
+
'To clear, hold ⌘/<abbr class="initialism">CTRL</abbr> and click selection.'
|
495 |
+
)
|
496 |
+
),
|
497 |
+
'default' => array(
|
498 |
+
'categories' => array(),
|
499 |
+
'tags' => array(),
|
500 |
+
),
|
501 |
+
),
|
502 |
+
'exact_date' => array(
|
503 |
+
'type' => 'string',
|
504 |
+
'renderer' => array(
|
505 |
+
'class' => 'input',
|
506 |
+
'tab' => 'viewing-events',
|
507 |
+
'item' => 'viewing-events',
|
508 |
+
'label' => Ai1ec_I18n::__( 'Default calendar start date (optional)' ),
|
509 |
+
'type' => 'date',
|
510 |
+
),
|
511 |
+
'default' => '',
|
512 |
+
),
|
513 |
+
'agenda_events_per_page' => array(
|
514 |
+
'type' => 'int',
|
515 |
+
'renderer' => array(
|
516 |
+
'class' => 'input',
|
517 |
+
'tab' => 'viewing-events',
|
518 |
+
'item' => 'viewing-events',
|
519 |
+
'label' => Ai1ec_I18n::__( 'Agenda pages show at most' ),
|
520 |
+
'type' => 'append',
|
521 |
+
'append' => 'events',
|
522 |
+
'validator' => 'numeric',
|
523 |
+
),
|
524 |
+
'default' => 10,
|
525 |
+
),
|
526 |
+
'week_view_starts_at' => array(
|
527 |
+
'type' => 'int',
|
528 |
+
'renderer' => array(
|
529 |
+
'class' => 'input',
|
530 |
+
'tab' => 'viewing-events',
|
531 |
+
'item' => 'viewing-events',
|
532 |
+
'label' => Ai1ec_I18n::__( 'Week/Day view starts at' ),
|
533 |
+
'type' => 'append',
|
534 |
+
'append' => 'hrs',
|
535 |
+
'validator' => 'numeric',
|
536 |
+
),
|
537 |
+
'default' => 8,
|
538 |
+
),
|
539 |
+
'week_view_ends_at' => array(
|
540 |
+
'type' => 'int',
|
541 |
+
'renderer' => array(
|
542 |
+
'class' => 'input',
|
543 |
+
'tab' => 'viewing-events',
|
544 |
+
'item' => 'viewing-events',
|
545 |
+
'label' => Ai1ec_I18n::__( 'Week/Day view ends at' ),
|
546 |
+
'type' => 'append',
|
547 |
+
'append' => 'hrs',
|
548 |
+
'validator' => 'numeric',
|
549 |
+
),
|
550 |
+
'default' => 24,
|
551 |
+
),
|
552 |
+
'google_maps_api_key' => array(
|
553 |
+
'type' => 'string',
|
554 |
+
'renderer' => array(
|
555 |
+
'class' => 'input',
|
556 |
+
'tab' => 'viewing-events',
|
557 |
+
'item' => 'viewing-events',
|
558 |
+
'label' => Ai1ec_I18n::__(
|
559 |
+
'<span class="ai1ec-tooltip-toggle"
|
560 |
+
data-original-title="Google may request for an API key in order to show the map">
|
561 |
+
Google Maps API Key</span> (<a target="_blank" href="https://developers.google.com/maps/documentation/javascript/get-api-key#get-an-api-key">Get an API key</a>)'
|
562 |
+
),
|
563 |
+
'type' => 'normal'
|
564 |
+
),
|
565 |
+
'default' => '',
|
566 |
+
),
|
567 |
+
'month_word_wrap' => array(
|
568 |
+
'type' => 'bool',
|
569 |
+
'renderer' => array(
|
570 |
+
'class' => 'checkbox',
|
571 |
+
'tab' => 'viewing-events',
|
572 |
+
'item' => 'viewing-events',
|
573 |
+
'label' => Ai1ec_I18n::__(
|
574 |
+
'<strong>Word-wrap event stubs</strong> in Month view'
|
575 |
+
),
|
576 |
+
'help' => Ai1ec_I18n::__(
|
577 |
+
'Only applies to events that span a single day.'
|
578 |
+
),
|
579 |
+
),
|
580 |
+
'default' => false,
|
581 |
+
),
|
582 |
+
'agenda_include_entire_last_day' => array(
|
583 |
+
'type' => 'bool',
|
584 |
+
'renderer' => array(
|
585 |
+
'class' => 'checkbox',
|
586 |
+
'tab' => 'viewing-events',
|
587 |
+
'item' => 'viewing-events',
|
588 |
+
'label' => Ai1ec_I18n::__(
|
589 |
+
'In <span class="ai1ec-tooltip-toggle"
|
590 |
+
data-original-title="These include Agenda view,
|
591 |
+
the Upcoming Events widget, and some extended views.">
|
592 |
+
Agenda-like views</span>, <strong>include all events
|
593 |
+
from last day shown</strong>'
|
594 |
+
)
|
595 |
+
),
|
596 |
+
'default' => false,
|
597 |
+
),
|
598 |
+
'agenda_events_expanded' => array(
|
599 |
+
'type' => 'bool',
|
600 |
+
'renderer' => array(
|
601 |
+
'class' => 'checkbox',
|
602 |
+
'tab' => 'viewing-events',
|
603 |
+
'item' => 'viewing-events',
|
604 |
+
'label' => Ai1ec_I18n::__(
|
605 |
+
'Keep all events <strong>expanded</strong> in Agenda view'
|
606 |
+
)
|
607 |
+
),
|
608 |
+
'default' => false,
|
609 |
+
),
|
610 |
+
'show_year_in_agenda_dates' => array(
|
611 |
+
'type' => 'bool',
|
612 |
+
'renderer' => array(
|
613 |
+
'class' => 'checkbox',
|
614 |
+
'tab' => 'viewing-events',
|
615 |
+
'item' => 'viewing-events',
|
616 |
+
'label' => Ai1ec_I18n::__(
|
617 |
+
'<strong>Show year</strong> in calendar date labels'
|
618 |
+
)
|
619 |
+
),
|
620 |
+
'default' => false,
|
621 |
+
),
|
622 |
+
'show_location_in_title' => array(
|
623 |
+
'type' => 'bool',
|
624 |
+
'renderer' => array(
|
625 |
+
'class' => 'checkbox',
|
626 |
+
'tab' => 'viewing-events',
|
627 |
+
'item' => 'viewing-events',
|
628 |
+
'label' => Ai1ec_I18n::__(
|
629 |
+
'<strong>Show location in event titles</strong> in calendar views'
|
630 |
+
)
|
631 |
+
),
|
632 |
+
'default' => true,
|
633 |
+
),
|
634 |
+
'exclude_from_search' => array(
|
635 |
+
'type' => 'bool',
|
636 |
+
'renderer' => array(
|
637 |
+
'class' => 'checkbox',
|
638 |
+
'tab' => 'viewing-events',
|
639 |
+
'item' => 'viewing-events',
|
640 |
+
'label' => Ai1ec_I18n::__(
|
641 |
+
'<strong>Exclude</strong> events from search results'
|
642 |
+
)
|
643 |
+
),
|
644 |
+
'default' => false,
|
645 |
+
),
|
646 |
+
'turn_off_subscription_buttons' => array(
|
647 |
+
'type' => 'bool',
|
648 |
+
'renderer' => array(
|
649 |
+
'class' => 'checkbox',
|
650 |
+
'tab' => 'viewing-events',
|
651 |
+
'item' => 'viewing-events',
|
652 |
+
'label' => Ai1ec_I18n::__(
|
653 |
+
'Hide <strong>Subscribe</strong>/<strong>Add to Calendar</strong> buttons in calendar and single event views '
|
654 |
+
)
|
655 |
+
),
|
656 |
+
'default' => false,
|
657 |
+
),
|
658 |
+
'disable_get_calendar_button' => array(
|
659 |
+
'type' => 'bool',
|
660 |
+
'renderer' => array(
|
661 |
+
'class' => 'checkbox',
|
662 |
+
'tab' => 'viewing-events',
|
663 |
+
'item' => 'viewing-events',
|
664 |
+
'label' => Ai1ec_I18n::__(
|
665 |
+
'Hide <strong>Get a Timely Calendar</strong> button'
|
666 |
+
)
|
667 |
+
),
|
668 |
+
'default' => true,
|
669 |
+
),
|
670 |
+
'hide_maps_until_clicked' => array(
|
671 |
+
'type' => 'bool',
|
672 |
+
'renderer' => array(
|
673 |
+
'class' => 'checkbox',
|
674 |
+
'tab' => 'viewing-events',
|
675 |
+
'item' => 'viewing-events',
|
676 |
+
'label' => Ai1ec_I18n::__(
|
677 |
+
' Hide <strong>Google Maps</strong> until clicked'
|
678 |
+
)
|
679 |
+
),
|
680 |
+
'default' => false,
|
681 |
+
),
|
682 |
+
'affix_filter_menu' => array(
|
683 |
+
'type' => 'bool',
|
684 |
+
'renderer' => array(
|
685 |
+
'class' => 'checkbox',
|
686 |
+
'tab' => 'viewing-events',
|
687 |
+
'item' => 'viewing-events',
|
688 |
+
'label' => Ai1ec_I18n::__(
|
689 |
+
' <strong>Affix filter menu</strong> to top of window when it scrolls out of view'
|
690 |
+
),
|
691 |
+
'help' => Ai1ec_I18n::__(
|
692 |
+
'Only applies to first visible calendar found on the page.'
|
693 |
+
),
|
694 |
+
),
|
695 |
+
'default' => false,
|
696 |
+
),
|
697 |
+
'affix_vertical_offset_md' => array(
|
698 |
+
'type' => 'int',
|
699 |
+
'renderer' => array(
|
700 |
+
'class' => 'input',
|
701 |
+
'tab' => 'viewing-events',
|
702 |
+
'item' => 'viewing-events',
|
703 |
+
'label' => Ai1ec_I18n::__( 'Offset affixed filter bar vertically by' ),
|
704 |
+
'type' => 'append',
|
705 |
+
'append' => 'pixels',
|
706 |
+
'validator' => 'numeric',
|
707 |
+
),
|
708 |
+
'default' => 0,
|
709 |
+
),
|
710 |
+
'affix_vertical_offset_lg' => array(
|
711 |
+
'type' => 'int',
|
712 |
+
'renderer' => array(
|
713 |
+
'class' => 'input',
|
714 |
+
'tab' => 'viewing-events',
|
715 |
+
'item' => 'viewing-events',
|
716 |
+
'label' =>
|
717 |
+
'<i class="ai1ec-fa ai1ec-fa-lg ai1ec-fa-fw ai1ec-fa-desktop"></i> ' .
|
718 |
+
Ai1ec_I18n::__( 'Wide screens only (≥ 1200px)' ),
|
719 |
+
'type' => 'append',
|
720 |
+
'append' => 'pixels',
|
721 |
+
'validator' => 'numeric',
|
722 |
+
),
|
723 |
+
'default' => 0,
|
724 |
+
),
|
725 |
+
'affix_vertical_offset_sm' => array(
|
726 |
+
'type' => 'int',
|
727 |
+
'renderer' => array(
|
728 |
+
'class' => 'input',
|
729 |
+
'tab' => 'viewing-events',
|
730 |
+
'item' => 'viewing-events',
|
731 |
+
'label' =>
|
732 |
+
'<i class="ai1ec-fa ai1ec-fa-lg ai1ec-fa-fw ai1ec-fa-tablet"></i> ' .
|
733 |
+
Ai1ec_I18n::__( 'Tablets only (< 980px)' ),
|
734 |
+
'type' => 'append',
|
735 |
+
'append' => 'pixels',
|
736 |
+
'validator' => 'numeric',
|
737 |
+
),
|
738 |
+
'default' => 0,
|
739 |
+
),
|
740 |
+
'affix_vertical_offset_xs' => array(
|
741 |
+
'type' => 'int',
|
742 |
+
'renderer' => array(
|
743 |
+
'class' => 'input',
|
744 |
+
'tab' => 'viewing-events',
|
745 |
+
'item' => 'viewing-events',
|
746 |
+
'label' =>
|
747 |
+
'<i class="ai1ec-fa ai1ec-fa-lg ai1ec-fa-fw ai1ec-fa-mobile"></i> ' .
|
748 |
+
Ai1ec_I18n::__( 'Phones only (< 768px)' ),
|
749 |
+
'type' => 'append',
|
750 |
+
'append' => 'pixels',
|
751 |
+
'validator' => 'numeric',
|
752 |
+
),
|
753 |
+
'default' => 0,
|
754 |
+
),
|
755 |
+
'strict_compatibility_content_filtering' => array(
|
756 |
+
'type' => 'bool',
|
757 |
+
'renderer' => array(
|
758 |
+
'class' => 'checkbox',
|
759 |
+
'tab' => 'viewing-events',
|
760 |
+
'item' => 'viewing-events',
|
761 |
+
'label' => Ai1ec_I18n::__(
|
762 |
+
'Strict compatibility content filtering'
|
763 |
+
),
|
764 |
+
),
|
765 |
+
'default' => false,
|
766 |
+
),
|
767 |
+
'hide_featured_image' => array(
|
768 |
+
'type' => 'bool',
|
769 |
+
'renderer' => array(
|
770 |
+
'class' => 'checkbox',
|
771 |
+
'tab' => 'viewing-events',
|
772 |
+
'item' => 'viewing-events',
|
773 |
+
'label' => Ai1ec_I18n::__(
|
774 |
+
' <strong>Hide featured image</strong> from event details page'
|
775 |
+
),
|
776 |
+
'help' => Ai1ec_I18n::__(
|
777 |
+
"Select this option if your theme already displays each post's featured image."
|
778 |
+
),
|
779 |
+
),
|
780 |
+
'default' => false,
|
781 |
+
),
|
782 |
+
'input_date_format' => array(
|
783 |
+
'type' => 'string',
|
784 |
+
'renderer' => array(
|
785 |
+
'class' => 'select',
|
786 |
+
'tab' => 'editing-events',
|
787 |
+
'label' => Ai1ec_I18n::__(
|
788 |
+
'Input dates in this format'
|
789 |
+
),
|
790 |
+
'options' => array(
|
791 |
+
array(
|
792 |
+
'text' => Ai1ec_I18n::__( 'Default (d/m/yyyy)' ),
|
793 |
+
'value' => 'def'
|
794 |
+
),
|
795 |
+
array(
|
796 |
+
'text' => Ai1ec_I18n::__( 'US (m/d/yyyy)' ),
|
797 |
+
'value' => 'us'
|
798 |
+
),
|
799 |
+
array(
|
800 |
+
'text' => Ai1ec_I18n::__( 'ISO 8601 (yyyy-m-d)' ),
|
801 |
+
'value' => 'iso'
|
802 |
+
),
|
803 |
+
array(
|
804 |
+
'text' => Ai1ec_I18n::__( 'Dotted (m.d.yyyy)' ),
|
805 |
+
'value' => 'dot'
|
806 |
+
),
|
807 |
+
),
|
808 |
+
),
|
809 |
+
'default' => 'def',
|
810 |
+
),
|
811 |
+
'input_24h_time' => array(
|
812 |
+
'type' => 'bool',
|
813 |
+
'renderer' => array(
|
814 |
+
'class' => 'checkbox',
|
815 |
+
'tab' => 'editing-events',
|
816 |
+
'label' => Ai1ec_I18n::__(
|
817 |
+
' Use <strong>24h time</strong> in time pickers'
|
818 |
+
)
|
819 |
+
),
|
820 |
+
'default' => false,
|
821 |
+
),
|
822 |
+
'disable_autocompletion' => array(
|
823 |
+
'type' => 'bool',
|
824 |
+
'renderer' => array(
|
825 |
+
'class' => 'checkbox',
|
826 |
+
'tab' => 'editing-events',
|
827 |
+
'label' => Ai1ec_I18n::__(
|
828 |
+
'<strong>Disable address autocomplete</strong> function'
|
829 |
+
)
|
830 |
+
),
|
831 |
+
'default' => false,
|
832 |
+
),
|
833 |
+
'geo_region_biasing' => array(
|
834 |
+
'type' => 'bool',
|
835 |
+
'renderer' => array(
|
836 |
+
'class' => 'checkbox',
|
837 |
+
'tab' => 'editing-events',
|
838 |
+
'label' => Ai1ec_I18n::__(
|
839 |
+
'Use the configured <strong>region</strong> (WordPress locale) to bias the address autocomplete function '
|
840 |
+
)
|
841 |
+
),
|
842 |
+
'default' => false,
|
843 |
+
),
|
844 |
+
'show_publish_button' => array(
|
845 |
+
'type' => 'deprecated',
|
846 |
+
'renderer' => null,
|
847 |
+
'default' => false,
|
848 |
+
),
|
849 |
+
'show_create_event_button' => array(
|
850 |
+
'type' => 'bool',
|
851 |
+
'renderer' => array(
|
852 |
+
'class' => 'checkbox',
|
853 |
+
'tab' => 'extensions',
|
854 |
+
'label' => Ai1ec_I18n::__(
|
855 |
+
' Show the old <strong>Post Your Event</strong> button above the calendar to privileged users'
|
856 |
+
),
|
857 |
+
'help' => Ai1ec_I18n::__(
|
858 |
+
'Install the <a target="_blank" href="https://time.ly/">Interactive Frontend Extension</a> for the <strong>frontend Post Your Event form</strong>.'
|
859 |
+
),
|
860 |
+
),
|
861 |
+
'default' => true,
|
862 |
+
),
|
863 |
+
'embedding' => array(
|
864 |
+
'type' => 'html',
|
865 |
+
'renderer' => array(
|
866 |
+
'class' => 'html',
|
867 |
+
'tab' => 'advanced',
|
868 |
+
'item' => 'embedded-views',
|
869 |
+
),
|
870 |
+
'default' => null,
|
871 |
+
),
|
872 |
+
'calendar_css_selector' => array(
|
873 |
+
'type' => 'string',
|
874 |
+
'renderer' => array(
|
875 |
+
'class' => 'input',
|
876 |
+
'tab' => 'advanced',
|
877 |
+
'item' => 'advanced',
|
878 |
+
'label' => Ai1ec_I18n::__( 'Move calendar into this DOM element' ),
|
879 |
+
'type' => 'normal',
|
880 |
+
'help' => Ai1ec_I18n::__(
|
881 |
+
'Optional. Use this JavaScript-based shortcut to place the
|
882 |
+
calendar a DOM element other than the usual page content container
|
883 |
+
if you are unable to create an appropriate page template
|
884 |
+
for the calendar page. To use, enter a
|
885 |
+
<a target="_blank" href="https://api.jquery.com/category/selectors/">
|
886 |
+
jQuery selector</a> that evaluates to a single DOM element.
|
887 |
+
Any existing markup found within the target will be replaced
|
888 |
+
by the calendar.'
|
889 |
+
),
|
890 |
+
),
|
891 |
+
'default' => '',
|
892 |
+
),
|
893 |
+
'skip_in_the_loop_check' => array(
|
894 |
+
'type' => 'bool',
|
895 |
+
'renderer' => array(
|
896 |
+
'class' => 'checkbox',
|
897 |
+
'tab' => 'advanced',
|
898 |
+
'item' => 'advanced',
|
899 |
+
'label' => Ai1ec_I18n::__(
|
900 |
+
'<strong>Skip <tt>in_the_loop()</tt> check </strong> that protects against multiple calendar output'
|
901 |
+
),
|
902 |
+
'help' => Ai1ec_I18n::__(
|
903 |
+
'Try enabling this option if your calendar does not appear on the calendar page. It is needed for compatibility with a small number of themes that call <tt>the_content()</tt> from outside of The Loop. Leave disabled otherwise.'
|
904 |
+
),
|
905 |
+
),
|
906 |
+
'default' => false,
|
907 |
+
),
|
908 |
+
'disable_gzip_compression' => array(
|
909 |
+
'type' => 'bool',
|
910 |
+
'renderer' => array(
|
911 |
+
'class' => 'checkbox',
|
912 |
+
'tab' => 'advanced',
|
913 |
+
'item' => 'advanced',
|
914 |
+
'label' => Ai1ec_I18n::__(
|
915 |
+
'Disable <strong>gzip</strong> compression.'
|
916 |
+
),
|
917 |
+
'help' => Ai1ec_I18n::__(
|
918 |
+
'Use this option if calendar is unresponsive. <a target="_blank" href="https://time.ly/document/user-guide/troubleshooting/disable-gzip-compression/">Read more</a> about the issue. (From version 2.1 onwards, gzip is disabled by default for maximum compatibility.)'
|
919 |
+
),
|
920 |
+
),
|
921 |
+
'default' => true,
|
922 |
+
),
|
923 |
+
'ai1ec_use_frontend_rendering' => array(
|
924 |
+
'type' => 'bool',
|
925 |
+
'renderer' => array(
|
926 |
+
'class' => 'checkbox',
|
927 |
+
'tab' => 'advanced',
|
928 |
+
'item' => 'advanced',
|
929 |
+
'label' => Ai1ec_I18n::__(
|
930 |
+
'Use frontend rendering.'
|
931 |
+
),
|
932 |
+
'help' => Ai1ec_I18n::__(
|
933 |
+
'Renders calendar views on the client rather than the server; can improve performance.'
|
934 |
+
),
|
935 |
+
),
|
936 |
+
'default' => true,
|
937 |
+
),
|
938 |
+
'cache_dynamic_js' => array(
|
939 |
+
'type' => 'bool',
|
940 |
+
'renderer' => array(
|
941 |
+
'class' => 'checkbox',
|
942 |
+
'tab' => 'advanced',
|
943 |
+
'item' => 'advanced',
|
944 |
+
'label' => Ai1ec_I18n::__(
|
945 |
+
'Use advanced JS cache.'
|
946 |
+
),
|
947 |
+
'help' => Ai1ec_I18n::__(
|
948 |
+
'Cache dynamically generated JS files. Improves performance.'
|
949 |
+
),
|
950 |
+
),
|
951 |
+
'default' => true,
|
952 |
+
),
|
953 |
+
'render_css_as_link' => array(
|
954 |
+
'type' => 'bool',
|
955 |
+
'renderer' => array(
|
956 |
+
'class' => 'checkbox',
|
957 |
+
'tab' => 'advanced',
|
958 |
+
'item' => 'advanced',
|
959 |
+
'label' => Ai1ec_I18n::__(
|
960 |
+
'<strong>Link CSS</strong> in <code><head></code> section when file cache is unavailable.'
|
961 |
+
),
|
962 |
+
'help' => Ai1ec_I18n::__(
|
963 |
+
'Use this option if file cache is unavailable and you would prefer to serve CSS as a link rather than have it output inline.'
|
964 |
+
),
|
965 |
+
),
|
966 |
+
'default' => false,
|
967 |
+
),
|
968 |
+
'edit_robots_txt' => array(
|
969 |
+
'type' => 'string',
|
970 |
+
'renderer' => array(
|
971 |
+
'class' => 'textarea',
|
972 |
+
'tab' => 'advanced',
|
973 |
+
'item' => 'advanced',
|
974 |
+
'label' => Ai1ec_I18n::__( 'Current <strong>robots.txt</strong> on this site' ),
|
975 |
+
'type' => 'normal',
|
976 |
+
'rows' => 6,
|
977 |
+
'readonly' => 'readonly',
|
978 |
+
'help' => Ai1ec_I18n::__(
|
979 |
+
'The Robot Exclusion Standard, also known as the Robots Exclusion Protocol or
|
980 |
+
<code><a href="https://en.wikipedia.org/wiki/Robots.txt" target="_blank">robots.txt</a></code>
|
981 |
+
protocol, is a convention for cooperating web crawlers and other web robots
|
982 |
+
about accessing all or part of a website that is otherwise publicly viewable.
|
983 |
+
You can change it manually by editing <code>robots.txt</code> in your root WordPress directory.'
|
984 |
+
),
|
985 |
+
),
|
986 |
+
'default' => '',
|
987 |
+
),
|
988 |
+
'allow_statistics' => array(
|
989 |
+
'type' => 'bool',
|
990 |
+
'renderer' => array(
|
991 |
+
'class' => 'checkbox',
|
992 |
+
'tab' => 'advanced',
|
993 |
+
'item' => 'advanced',
|
994 |
+
'label' => sprintf(
|
995 |
+
Ai1ec_I18n::__(
|
996 |
+
'<strong>Publicize, promote, and share my events</strong> marked as public on the Timely network. (<a href="%s" target="_blank">Learn more »</a>)'
|
997 |
+
),
|
998 |
+
'https://time.ly/event-search-calendar'
|
999 |
+
),
|
1000 |
+
),
|
1001 |
+
'default' => false,
|
1002 |
+
),
|
1003 |
+
'legacy_options' => array(
|
1004 |
+
'type' => 'legacy_options',
|
1005 |
+
'default' => null,
|
1006 |
+
),
|
1007 |
+
'ics_cron_freq' => array(
|
1008 |
+
'type' => 'string',
|
1009 |
+
'default' => 'hourly',
|
1010 |
+
),
|
1011 |
+
'twig_cache' => array(
|
1012 |
+
'type' => 'string',
|
1013 |
+
'renderer' => array(
|
1014 |
+
'class' => 'cache',
|
1015 |
+
'tab' => 'advanced',
|
1016 |
+
'item' => 'cache',
|
1017 |
+
'label' => sprintf(
|
1018 |
+
Ai1ec_I18n::__(
|
1019 |
+
'Templates cache improves site performance'
|
1020 |
+
)
|
1021 |
+
),
|
1022 |
+
),
|
1023 |
+
'default' => '',
|
1024 |
+
),
|
1025 |
+
'always_use_calendar_timezone' => array(
|
1026 |
+
'type' => 'bool',
|
1027 |
+
'renderer' => array(
|
1028 |
+
'class' => 'checkbox',
|
1029 |
+
'tab' => 'viewing-events',
|
1030 |
+
'item' => 'viewing-events',
|
1031 |
+
'label' => Ai1ec_I18n::__(
|
1032 |
+
'Display events in <strong>calendar time zone</strong>'
|
1033 |
+
),
|
1034 |
+
'help' => Ai1ec_I18n::__(
|
1035 |
+
'If this box is checked events will appear in the calendar time zone with time zone information displayed on the event details page.'
|
1036 |
+
),
|
1037 |
+
),
|
1038 |
+
'default' => false,
|
1039 |
+
),
|
1040 |
+
);
|
1041 |
+
}
|
1042 |
|
1043 |
+
/**
|
1044 |
+
* Register the standard setting values.
|
1045 |
+
*
|
1046 |
+
* @return void Method doesn't return.
|
1047 |
+
*/
|
1048 |
+
protected function _register_standard_values() {
|
1049 |
+
foreach ( $this->_standard_options as $key => $option ) {
|
1050 |
+
$renderer = null;
|
1051 |
+
$value = $option['default'];
|
1052 |
+
if ( isset( $option['renderer'] ) ) {
|
1053 |
+
$renderer = $option['renderer'];
|
1054 |
+
}
|
1055 |
+
$this->register(
|
1056 |
+
$key,
|
1057 |
+
$value,
|
1058 |
+
$option['type'],
|
1059 |
+
$renderer,
|
1060 |
+
AI1EC_VERSION
|
1061 |
+
);
|
1062 |
+
}
|
1063 |
+
}
|
1064 |
|
1065 |
+
/**
|
1066 |
+
* Update translated strings, after introduction of `_noop` functions.
|
1067 |
+
*
|
1068 |
+
* @return void
|
1069 |
+
*/
|
1070 |
+
protected function _update_name_translations() {
|
1071 |
+
$translations = $this->_standard_options['enabled_views']['default'];
|
1072 |
+
$current = $this->get( 'enabled_views' );
|
1073 |
+
foreach ( $current as $key => $view ) {
|
1074 |
+
if ( isset( $translations[$key] ) ) {
|
1075 |
+
$current[$key]['longname'] = $translations[$key]['longname'];
|
1076 |
+
}
|
1077 |
+
}
|
1078 |
+
$this->set( 'enabled_views', $current );
|
1079 |
+
}
|
1080 |
|
1081 |
+
/**
|
1082 |
+
* Change `updated` flag value.
|
1083 |
+
*
|
1084 |
+
* @param bool $new_status Status to change to.
|
1085 |
+
*
|
1086 |
+
* @return bool Previous status flag value.
|
1087 |
+
*/
|
1088 |
+
protected function _change_update_status( $new_status ) {
|
1089 |
+
$previous = $this->_updated;
|
1090 |
+
$this->_updated = (bool)$new_status;
|
1091 |
+
return $previous;
|
1092 |
+
}
|
1093 |
|
1094 |
}
|
app/model/taxonomy.php
CHANGED
@@ -10,187 +10,187 @@
|
|
10 |
*/
|
11 |
class Ai1ec_Taxonomy extends Ai1ec_Base {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
/**
|
175 |
-
* Returns the color of the Event Category having the given term ID.
|
176 |
-
*
|
177 |
-
* @param int $term_id The ID of the Event Category.
|
178 |
-
*
|
179 |
-
* @return string|null Color to use
|
180 |
-
*/
|
181 |
-
public function get_category_color( $term_id ) {
|
182 |
-
return $this->get_category_field( $term_id, 'color' );
|
183 |
-
}
|
184 |
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
|
196 |
}
|
10 |
*/
|
11 |
class Ai1ec_Taxonomy extends Ai1ec_Base {
|
12 |
|
13 |
+
/**
|
14 |
+
* @var array Map of taxonomy values.
|
15 |
+
*/
|
16 |
+
protected $_taxonomy_map = array(
|
17 |
+
'events_categories' => array(),
|
18 |
+
'events_tags' => array(),
|
19 |
+
);
|
20 |
|
21 |
+
/**
|
22 |
+
* Callback to pre-populate taxonomies before exporting ics.
|
23 |
+
* All taxonomies which are not tags are exported as event_categories
|
24 |
+
*
|
25 |
+
* @param array $post_ids List of Post IDs to inspect.
|
26 |
+
*
|
27 |
+
* @return void
|
28 |
+
*/
|
29 |
+
public function prepare_meta_for_ics( array $post_ids ) {
|
30 |
+
$taxonomies = get_object_taxonomies( AI1EC_POST_TYPE );
|
31 |
+
$categories = array();
|
32 |
+
$excluded_categories = array(
|
33 |
+
'events_tags' => true,
|
34 |
+
'events_feeds' => true
|
35 |
+
);
|
36 |
+
foreach ( $taxonomies as $taxonomy ) {
|
37 |
+
if ( isset( $excluded_categories[$taxonomy] ) ) {
|
38 |
+
continue;
|
39 |
+
}
|
40 |
+
$categories[] = $taxonomy;
|
41 |
+
}
|
42 |
+
foreach ( $post_ids as $post_id ) {
|
43 |
+
$post_id = (int)$post_id;
|
44 |
+
$this->_taxonomy_map['events_categories'][$post_id] = array();
|
45 |
+
$this->_taxonomy_map['events_tags'][$post_id] = array();
|
46 |
+
}
|
47 |
+
$tags = wp_get_object_terms(
|
48 |
+
$post_ids,
|
49 |
+
array( 'events_tags' ),
|
50 |
+
array( 'fields' => 'all_with_object_id' )
|
51 |
+
);
|
52 |
+
foreach ( $tags as $term ) {
|
53 |
+
$this->_taxonomy_map[$term->taxonomy][$term->object_id][] = $term;
|
54 |
+
}
|
55 |
+
$category_terms = wp_get_object_terms(
|
56 |
+
$post_ids,
|
57 |
+
$categories,
|
58 |
+
array( 'fields' => 'all_with_object_id' )
|
59 |
+
);
|
60 |
+
foreach ( $category_terms as $term ) {
|
61 |
+
$this->_taxonomy_map['events_categories'][$term->object_id][] = $term;
|
62 |
+
}
|
63 |
+
}
|
64 |
|
65 |
+
/**
|
66 |
+
* Callback to pre-populate taxonomies before processing.
|
67 |
+
*
|
68 |
+
* @param array $post_ids List of Post IDs to inspect.
|
69 |
+
*
|
70 |
+
* @return void
|
71 |
+
*/
|
72 |
+
public function update_meta( array $post_ids ) {
|
73 |
+
foreach ( $post_ids as $post_id ) {
|
74 |
+
$post_id = (int)$post_id;
|
75 |
+
$this->_taxonomy_map['events_categories'][$post_id] = array();
|
76 |
+
$this->_taxonomy_map['events_tags'][$post_id] = array();
|
77 |
+
}
|
78 |
+
$terms = wp_get_object_terms(
|
79 |
+
$post_ids,
|
80 |
+
array( 'events_categories', 'events_tags' ),
|
81 |
+
array( 'fields' => 'all_with_object_id' )
|
82 |
+
);
|
83 |
+
foreach ( $terms as $term ) {
|
84 |
+
$this->_taxonomy_map[$term->taxonomy][$term->object_id][] = $term;
|
85 |
+
}
|
86 |
+
}
|
87 |
|
88 |
+
/**
|
89 |
+
* Re-fetch category entries map from database.
|
90 |
+
*
|
91 |
+
* @return array Map of category entries.
|
92 |
+
*/
|
93 |
+
public function fetch_category_map() {
|
94 |
+
$category_map = array();
|
95 |
+
$records = (array)$this->_registry->get( 'dbi.dbi' )->select(
|
96 |
+
'ai1ec_event_category_meta',
|
97 |
+
array( 'term_id', 'term_image', 'term_color' )
|
98 |
+
);
|
99 |
+
foreach ( $records as $row ) {
|
100 |
+
$image = $color = null;
|
101 |
+
if ( $row->term_image ) {
|
102 |
+
$image = $row->term_image;
|
103 |
+
}
|
104 |
+
if ( $row->term_color ) {
|
105 |
+
$color = $row->term_color;
|
106 |
+
}
|
107 |
+
$category_map[(int)$row->term_id] = compact( 'image', 'color' );
|
108 |
+
}
|
109 |
+
return $category_map;
|
110 |
+
}
|
111 |
|
112 |
+
/**
|
113 |
+
* Get taxonomy values for specified post.
|
114 |
+
*
|
115 |
+
* @param int $post_id Actual Post ID to check.
|
116 |
+
* @param string $taxonomy Name of taxonomy to retrieve values for.
|
117 |
+
*
|
118 |
+
* @return array List of terms (stdClass'es) associated with post.
|
119 |
+
*/
|
120 |
+
public function get_post_taxonomy( $post_id, $taxonomy ) {
|
121 |
+
$post_id = (int)$post_id;
|
122 |
+
if ( ! isset( $this->_taxonomy_map[$taxonomy][$post_id] ) ) {
|
123 |
+
$definition = wp_get_post_terms( $post_id, $taxonomy );
|
124 |
+
if ( empty( $definition ) || is_wp_error( $definition ) ) {
|
125 |
+
$definition = array();
|
126 |
+
}
|
127 |
+
$this->_taxonomy_map[$taxonomy][$post_id] = $definition;
|
128 |
+
}
|
129 |
+
return $this->_taxonomy_map[$taxonomy][$post_id];
|
130 |
+
}
|
131 |
|
132 |
+
/**
|
133 |
+
* Get post (event) categories taxonomy.
|
134 |
+
*
|
135 |
+
* @param int $post_id Checked post ID.
|
136 |
+
*
|
137 |
+
* @return array List of categories (stdClass'es) associated with event.
|
138 |
+
*/
|
139 |
+
public function get_post_categories( $post_id ) {
|
140 |
+
return $this->get_post_taxonomy( $post_id, 'events_categories' );
|
141 |
+
}
|
142 |
|
143 |
+
/**
|
144 |
+
* Get post (event) tags taxonomy.
|
145 |
+
*
|
146 |
+
* @param int $post_id Checked post ID.
|
147 |
+
*
|
148 |
+
* @return array List of tags (stdClass'es) associated with event.
|
149 |
+
*/
|
150 |
+
public function get_post_tags( $post_id ) {
|
151 |
+
return $this->get_post_taxonomy( $post_id, 'events_tags' );
|
152 |
+
}
|
153 |
|
154 |
+
/**
|
155 |
+
* Get cached category description field.
|
156 |
+
*
|
157 |
+
* @param int $term_id Category ID.
|
158 |
+
* @param string $field Name of field, one of 'image', 'color'.
|
159 |
+
*
|
160 |
+
* @return string|null Field value or null if entry is not found.
|
161 |
+
*/
|
162 |
+
public function get_category_field( $term_id, $field ) {
|
163 |
+
static $category_meta = null;
|
164 |
+
if ( null === $category_meta ) {
|
165 |
+
$category_meta = $this->fetch_category_map();
|
166 |
+
}
|
167 |
+
$term_id = (int)$term_id;
|
168 |
+
if ( ! isset( $category_meta[$term_id] ) ) {
|
169 |
+
return null;
|
170 |
+
}
|
171 |
+
return $category_meta[$term_id][$field];
|
172 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
|
174 |
+
/**
|
175 |
+
* Returns the color of the Event Category having the given term ID.
|
176 |
+
*
|
177 |
+
* @param int $term_id The ID of the Event Category.
|
178 |
+
*
|
179 |
+
* @return string|null Color to use
|
180 |
+
*/
|
181 |
+
public function get_category_color( $term_id ) {
|
182 |
+
return $this->get_category_field( $term_id, 'color' );
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Returns the image of the Event Category having the given term ID.
|
187 |
+
*
|
188 |
+
* @param int $term_id The ID of the Event Category.
|
189 |
+
*
|
190 |
+
* @return string|null Image url to use.
|
191 |
+
*/
|
192 |
+
public function get_category_image( $term_id ) {
|
193 |
+
return $this->get_category_field( $term_id, 'image' );
|
194 |
+
}
|
195 |
|
196 |
}
|
app/view/admin/abstract.php
CHANGED
@@ -11,66 +11,66 @@
|
|
11 |
*/
|
12 |
abstract class Ai1ec_View_Admin_Abstract extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
|
76 |
}
|
11 |
*/
|
12 |
abstract class Ai1ec_View_Admin_Abstract extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
protected $_page_id;
|
18 |
|
19 |
+
/**
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
protected $_page_suffix;
|
23 |
|
24 |
+
/**
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
protected $_api_registration;
|
28 |
|
29 |
+
/**
|
30 |
+
* Standard constructor
|
31 |
+
*
|
32 |
+
* @param Ai1ec_Registry_Object $registry
|
33 |
+
*/
|
34 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
35 |
+
parent::__construct( $registry );
|
36 |
+
$exploded_class = explode( '_', get_class( $this ) );
|
37 |
+
$this->_page_suffix = strtolower( end( $exploded_class ) );
|
38 |
+
$this->_api_registration = $this->_registry->get( 'model.api.api-registration' );
|
39 |
+
}
|
40 |
|
41 |
+
/**
|
42 |
+
* Get the url of the page
|
43 |
+
*
|
44 |
+
* @return string
|
45 |
+
*/
|
46 |
+
public function get_url() {
|
47 |
+
return add_query_arg(
|
48 |
+
array(
|
49 |
+
'post_type' => AI1EC_POST_TYPE,
|
50 |
+
'page' => AI1EC_PLUGIN_NAME . '-' . $this->_page_suffix,
|
51 |
+
),
|
52 |
+
ai1ec_admin_url( 'edit.php' )
|
53 |
+
);
|
54 |
+
}
|
55 |
|
56 |
+
/**
|
57 |
+
* Adds the page to the correct menu.
|
58 |
+
*/
|
59 |
+
abstract public function add_page();
|
60 |
|
61 |
+
/**
|
62 |
+
* Adds the page to the correct menu.
|
63 |
+
*/
|
64 |
+
abstract public function add_meta_box();
|
65 |
|
66 |
+
/**
|
67 |
+
* Display the page html
|
68 |
+
*/
|
69 |
+
abstract public function display_page();
|
70 |
|
71 |
+
/**
|
72 |
+
* Handle post, likely to be deprecated to use commands.
|
73 |
+
*/
|
74 |
+
abstract public function handle_post();
|
75 |
|
76 |
}
|
app/view/admin/add-new-event.php
CHANGED
@@ -13,539 +13,564 @@
|
|
13 |
*/
|
14 |
class Ai1ec_View_Add_New_Event extends Ai1ec_Base {
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
550 |
|
551 |
}
|
13 |
*/
|
14 |
class Ai1ec_View_Add_New_Event extends Ai1ec_Base {
|
15 |
|
16 |
+
/**
|
17 |
+
* Create hook to display event meta box when creating or editing an event.
|
18 |
+
*
|
19 |
+
* @wp_hook add_meta_boxes
|
20 |
+
*
|
21 |
+
* @return void
|
22 |
+
*/
|
23 |
+
public function event_meta_box_container() {
|
24 |
+
add_meta_box(
|
25 |
+
AI1EC_POST_TYPE,
|
26 |
+
Ai1ec_I18n::__( 'Event Details' ),
|
27 |
+
array( $this, 'meta_box_view' ),
|
28 |
+
AI1EC_POST_TYPE,
|
29 |
+
'normal',
|
30 |
+
'high'
|
31 |
+
);
|
32 |
+
|
33 |
+
add_meta_box(
|
34 |
+
AI1EC_POST_TYPE . '_features',
|
35 |
+
Ai1ec_I18n::__( 'Empower your calendar, build your community' ),
|
36 |
+
array( $this, 'features_info' ),
|
37 |
+
AI1EC_POST_TYPE,
|
38 |
+
'side',
|
39 |
+
'low'
|
40 |
+
);
|
41 |
+
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Add Event Details meta box to the Add/Edit Event screen in the dashboard.
|
46 |
+
*
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
+
public function features_info( $post ) {
|
50 |
+
$message = __(
|
51 |
+
'<ul class="ai1ec-features-list"><li><a href="https://time.ly/hub" target="_blank">Pull events from other calendars</a></li><li><a href="https://time.ly/hub" target="_blank">Pull events from Facebook</a></li><li><a href="https://time.ly/hub" target="_blank">Add a Newsletter</a></li><li><a href="https://time.ly/hub" target="_blank">Get public event submissions</a></li><li><a href="https://time.ly/hub" target="_blank">Charge people to post events</a></li><li><a href="https://time.ly/hub" target="_blank">Add social sharing</a></li><li><a href="https://time.ly/hub" target="_blank">And more</a></li></ul>',
|
52 |
+
AI1EC_PLUGIN_NAME
|
53 |
+
);
|
54 |
+
|
55 |
+
echo $message;
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Add Event Details meta box to the Add/Edit Event screen in the dashboard.
|
61 |
+
*
|
62 |
+
* @return void
|
63 |
+
*/
|
64 |
+
public function meta_box_view( $post ) {
|
65 |
+
|
66 |
+
$theme_loader = $this->_registry->get( 'theme.loader' );
|
67 |
+
$empty_event = $this->_registry->get( 'model.event' );
|
68 |
+
|
69 |
+
// ==================
|
70 |
+
// = Default values =
|
71 |
+
// ==================
|
72 |
+
// ATTENTION - When adding new fields to the event remember that you must
|
73 |
+
// also set up the duplicate-controller.
|
74 |
+
// TODO: Fix this duplication.
|
75 |
+
$all_day_event = '';
|
76 |
+
$instant_event = '';
|
77 |
+
$start = $this->_registry->get( 'date.time' );
|
78 |
+
$end = $this->_registry->get( 'date.time', '+1 hour' );
|
79 |
+
$timezone_name = null;
|
80 |
+
$timezones_list = $this->_registry->get( 'date.timezone' )->get_timezones( true );
|
81 |
+
$show_map = false;
|
82 |
+
$google_map = '';
|
83 |
+
$venue = '';
|
84 |
+
$country = '';
|
85 |
+
$address = '';
|
86 |
+
$city = '';
|
87 |
+
$province = '';
|
88 |
+
$postal_code = '';
|
89 |
+
$contact_name = '';
|
90 |
+
$contact_phone = '';
|
91 |
+
$contact_email = '';
|
92 |
+
$contact_url = '';
|
93 |
+
$cost = '';
|
94 |
+
$is_free = '';
|
95 |
+
$cost_type = 'free';
|
96 |
+
$rrule = '';
|
97 |
+
$rrule_text = '';
|
98 |
+
$repeating_event = false;
|
99 |
+
$exrule = '';
|
100 |
+
$exrule_text = '';
|
101 |
+
$exclude_event = false;
|
102 |
+
$exdate = '';
|
103 |
+
$show_coordinates = false;
|
104 |
+
$longitude = '';
|
105 |
+
$latitude = '';
|
106 |
+
$coordinates = '';
|
107 |
+
$ticket_url = '';
|
108 |
+
|
109 |
+
$instance_id = false;
|
110 |
+
if ( isset( $_REQUEST['instance'] ) ) {
|
111 |
+
$instance_id = absint( $_REQUEST['instance'] );
|
112 |
+
}
|
113 |
+
if ( $instance_id ) {
|
114 |
+
add_filter(
|
115 |
+
'print_scripts_array',
|
116 |
+
array( $this, 'disable_autosave' )
|
117 |
+
);
|
118 |
+
}
|
119 |
+
|
120 |
+
try {
|
121 |
+
// on some php version, nested try catch blocks fail and the exception would never be caught.
|
122 |
+
// this is why we use this approach.
|
123 |
+
$excpt = null;
|
124 |
+
$event = null;
|
125 |
+
try {
|
126 |
+
$event = $this->_registry->get(
|
127 |
+
'model.event',
|
128 |
+
get_the_ID(),
|
129 |
+
$instance_id
|
130 |
+
);
|
131 |
+
} catch ( Ai1ec_Event_Not_Found_Exception $excpt ) {
|
132 |
+
$ai1ec_localization_helper = $this->_registry
|
133 |
+
->get( 'p28n.wpml' );
|
134 |
+
$translatable_id = $ai1ec_localization_helper
|
135 |
+
->get_translatable_id();
|
136 |
+
if ( false !== $translatable_id ) {
|
137 |
+
$event = $this->_registry->get(
|
138 |
+
'model.event',
|
139 |
+
$translatable_id,
|
140 |
+
$instance_id
|
141 |
+
);
|
142 |
+
}
|
143 |
+
}
|
144 |
+
if ( null !== $excpt ) {
|
145 |
+
throw $excpt;
|
146 |
+
}
|
147 |
+
|
148 |
+
// Existing event was found. Initialize form values with values from
|
149 |
+
// event object.
|
150 |
+
$all_day_event = $event->is_allday() ? 'checked' : '';
|
151 |
+
$instant_event = $event->is_instant() ? 'checked' : '';
|
152 |
+
|
153 |
+
$start = $event->get( 'start' );
|
154 |
+
$end = $event->get( 'end' );
|
155 |
+
$timezone_name = $event->get( 'timezone_name' );
|
156 |
+
|
157 |
+
$multi_day = $event->is_multiday();
|
158 |
+
|
159 |
+
$show_map = $event->get( 'show_map' );
|
160 |
+
$google_map = $show_map ? 'checked="checked"' : '';
|
161 |
+
|
162 |
+
$show_coordinates = $event->get( 'show_coordinates' );
|
163 |
+
$coordinates = $show_coordinates ? 'checked="checked"' : '';
|
164 |
+
$longitude = (float)$event->get( 'longitude', 0 );
|
165 |
+
$latitude = (float)$event->get( 'latitude', 0 );
|
166 |
+
// There is a known bug in Wordpress (https://core.trac.wordpress.org/ticket/15158) that saves 0 to the DB instead of null.
|
167 |
+
// We handle a special case here to avoid having the fields with a value of 0 when the user never inputted any coordinates
|
168 |
+
if ( ! $show_coordinates ) {
|
169 |
+
$longitude = '';
|
170 |
+
$latitude = '';
|
171 |
+
}
|
172 |
+
|
173 |
+
$venue = $event->get( 'venue' );
|
174 |
+
$country = $event->get( 'country' );
|
175 |
+
$address = $event->get( 'address' );
|
176 |
+
$city = $event->get( 'city' );
|
177 |
+
$province = $event->get( 'province' );
|
178 |
+
$postal_code = $event->get( 'postal_code' );
|
179 |
+
$contact_name = $event->get( 'contact_name' );
|
180 |
+
$contact_phone = $event->get( 'contact_phone' );
|
181 |
+
$contact_email = $event->get( 'contact_email' );
|
182 |
+
$contact_url = $event->get( 'contact_url' );
|
183 |
+
$cost = $event->get( 'cost' );
|
184 |
+
$ticket_url = $event->get( 'ticket_url' );
|
185 |
+
$rrule = $event->get( 'recurrence_rules' );
|
186 |
+
$exrule = $event->get( 'exception_rules' );
|
187 |
+
$exdate = $event->get( 'exception_dates' );
|
188 |
+
$repeating_event = ! empty( $rrule );
|
189 |
+
$exclude_event = ! empty( $exrule );
|
190 |
+
|
191 |
+
$is_free = '';
|
192 |
+
$free = $event->is_free();
|
193 |
+
if ( ! empty( $free ) ) {
|
194 |
+
$is_free = 'checked="checked" ';
|
195 |
+
$cost = '';
|
196 |
+
}
|
197 |
+
|
198 |
+
if ( $repeating_event ) {
|
199 |
+
$rrule_text = ucfirst(
|
200 |
+
$this->_registry->get( 'recurrence.rule' )
|
201 |
+
->rrule_to_text( $rrule )
|
202 |
+
);
|
203 |
+
}
|
204 |
+
|
205 |
+
if ( $exclude_event ) {
|
206 |
+
$exrule_text = ucfirst(
|
207 |
+
$this->_registry->get( 'recurrence.rule' )
|
208 |
+
->rrule_to_text( $exrule )
|
209 |
+
);
|
210 |
+
}
|
211 |
+
} catch ( Ai1ec_Event_Not_Found_Exception $excpt ) {
|
212 |
+
// Event does not exist.
|
213 |
+
// Leave form fields undefined (= zero-length strings)
|
214 |
+
$event = null;
|
215 |
+
}
|
216 |
+
|
217 |
+
// Time zone; display if set.
|
218 |
+
$timezone = '';
|
219 |
+
$timezone_string = null;
|
220 |
+
$date_timezone = $this->_registry->get( 'date.timezone' );
|
221 |
+
|
222 |
+
if (
|
223 |
+
! empty( $timezone_name ) &&
|
224 |
+
$local_name = $date_timezone->get_name( $timezone_name )
|
225 |
+
) {
|
226 |
+
$timezone_string = $local_name;
|
227 |
+
}
|
228 |
+
if ( null === $timezone_string ) {
|
229 |
+
$timezone_string = $date_timezone->get_default_timezone();
|
230 |
+
}
|
231 |
+
|
232 |
+
if ( $timezone_string ) {
|
233 |
+
$timezone = $this->_registry->get( 'date.system' )
|
234 |
+
->get_gmt_offset_expr( $timezone_string );
|
235 |
+
}
|
236 |
+
|
237 |
+
if ( empty( $timezone_name ) ) {
|
238 |
+
/**
|
239 |
+
* Actual Olsen timezone name is used when value is to be directly
|
240 |
+
* exposed to user in some mean. It's possible to use named const.
|
241 |
+
* `'sys.default'` only when passing value to date.time library.
|
242 |
+
*/
|
243 |
+
$timezone_name = $date_timezone->get_default_timezone();
|
244 |
+
}
|
245 |
+
|
246 |
+
// This will store each of the accordion tabs' markup, and passed as an
|
247 |
+
// argument to the final view.
|
248 |
+
$boxes = array();
|
249 |
+
$parent_event_id = null;
|
250 |
+
if ( $event ) {
|
251 |
+
$parent_event_id = $this->_registry->get( 'model.event.parent' )
|
252 |
+
->event_parent( $event->get( 'post_id' ) );
|
253 |
+
}
|
254 |
+
// ===============================
|
255 |
+
// = Display event time and date =
|
256 |
+
// ===============================
|
257 |
+
$args = array(
|
258 |
+
'all_day_event' => $all_day_event,
|
259 |
+
'instant_event' => $instant_event,
|
260 |
+
'start' => $start,
|
261 |
+
'end' => $end,
|
262 |
+
'repeating_event' => $repeating_event,
|
263 |
+
'rrule' => $rrule,
|
264 |
+
'rrule_text' => $rrule_text,
|
265 |
+
'exclude_event' => $exclude_event,
|
266 |
+
'exrule' => $exrule,
|
267 |
+
'exrule_text' => $exrule_text,
|
268 |
+
'timezone' => $timezone,
|
269 |
+
'timezone_string' => $timezone_string,
|
270 |
+
'timezone_name' => $timezone_name,
|
271 |
+
'exdate' => $exdate,
|
272 |
+
'parent_event_id' => $parent_event_id,
|
273 |
+
'instance_id' => $instance_id,
|
274 |
+
'timezones_list' => $timezones_list,
|
275 |
+
);
|
276 |
+
|
277 |
+
$boxes[] = $theme_loader
|
278 |
+
->get_file( 'box_time_and_date.php', $args, true )
|
279 |
+
->get_content();
|
280 |
+
|
281 |
+
// =================================================
|
282 |
+
// = Display event location details and Google map =
|
283 |
+
// =================================================
|
284 |
+
$args = array(
|
285 |
+
'select_venue' => apply_filters( 'ai1ec_admin_pre_venue_html', '' ),
|
286 |
+
'save_venue' => apply_filters( 'ai1ec_admin_post_venue_html', '' ),
|
287 |
+
'venue' => $venue,
|
288 |
+
'country' => $country,
|
289 |
+
'address' => $address,
|
290 |
+
'city' => $city,
|
291 |
+
'province' => $province,
|
292 |
+
'postal_code' => $postal_code,
|
293 |
+
'google_map' => $google_map,
|
294 |
+
'show_map' => $show_map,
|
295 |
+
'show_coordinates' => $show_coordinates,
|
296 |
+
'longitude' => $longitude,
|
297 |
+
'latitude' => $latitude,
|
298 |
+
'coordinates' => $coordinates,
|
299 |
+
);
|
300 |
+
$boxes[] = $theme_loader
|
301 |
+
->get_file( 'box_event_location.php', $args, true )
|
302 |
+
->get_content();
|
303 |
+
|
304 |
+
// ===================================
|
305 |
+
// = Display event ticketing options =
|
306 |
+
// ===================================
|
307 |
+
if ( $event ) {
|
308 |
+
$cost_type = get_post_meta(
|
309 |
+
$event->get( 'post_id' ),
|
310 |
+
'_ai1ec_cost_type',
|
311 |
+
true
|
312 |
+
);
|
313 |
+
if ( ! $cost_type ) {
|
314 |
+
if ( $ticket_url || $cost ) {
|
315 |
+
$cost_type = 'external';
|
316 |
+
} else {
|
317 |
+
$cost_type = 'free';
|
318 |
+
}
|
319 |
+
}
|
320 |
+
}
|
321 |
+
|
322 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
323 |
+
$api_reg = $this->_registry->get( 'model.api.api-registration' );
|
324 |
+
$ticketing = $api_reg->is_signed() && $api_reg->is_ticket_available() && $api_reg->is_ticket_enabled();
|
325 |
+
$message = $api->get_sign_message();
|
326 |
+
$ticket_error = null;
|
327 |
+
$ticket_event_imported = false;
|
328 |
+
$tickets = array( null );
|
329 |
+
$tax_options = null;
|
330 |
+
|
331 |
+
if ( ! $api_reg->is_ticket_available() ) {
|
332 |
+
$message = __(
|
333 |
+
'Ticketing is currently not available for this website. Please, try again later.',
|
334 |
+
AI1EC_PLUGIN_NAME
|
335 |
+
);
|
336 |
+
} else if ( ! $api_reg->is_ticket_enabled() ) {
|
337 |
+
$message = __(
|
338 |
+
'Timely Ticketing saves time & money. Create ticketing/registration right here and now. You do not pay any ticketing fees (other than regular PayPal transaction costs). Create as many ticketing/registration as you\'d like.<br /><br />Ticketing feature is not enabled for this website. Please sign up for Ticketing plan <a href="https://time.ly/tickets-existing-users/" target="_blank">here</a>.',
|
339 |
+
AI1EC_PLUGIN_NAME
|
340 |
+
);
|
341 |
+
}
|
342 |
+
|
343 |
+
if ( $event ) {
|
344 |
+
$is_ticket_event = ! is_null( $api->get_api_event_id( $event->get( 'post_id' ) ) );
|
345 |
+
$ticket_event_account = $api->get_api_event_account( $event->get( 'post_id' ) );
|
346 |
+
$ticket_event_imported = $api->is_ticket_event_imported( $event->get( 'post_id' ) );
|
347 |
+
if ( $ticketing || $ticket_event_imported ) {
|
348 |
+
if ( 'tickets' === $cost_type ) {
|
349 |
+
if ( $ticket_event_imported ) {
|
350 |
+
$response = json_decode( $api->get_ticket_types( $event->get( 'post_id' ) ) );
|
351 |
+
if ( isset( $response->data ) && 0 < count( $response->data ) ) {
|
352 |
+
$tickets = array_merge( $tickets, $response->data );
|
353 |
+
}
|
354 |
+
if ( isset( $response->error ) ) {
|
355 |
+
$ticket_error = $response->error;
|
356 |
+
}
|
357 |
+
} else {
|
358 |
+
$response = $api->get_event( $event->get( 'post_id' ) );
|
359 |
+
if ( isset( $response->data ) && 0 < count( $response->data ) ) {
|
360 |
+
$tickets = array_merge( $tickets, $response->data->ticket_types );
|
361 |
+
$tax_options = $response->data->tax_options;
|
362 |
+
}
|
363 |
+
if ( isset( $response->error ) ) {
|
364 |
+
$ticket_error = $response->error;
|
365 |
+
}
|
366 |
+
}
|
367 |
+
}
|
368 |
+
$uid = $event->get_uid();
|
369 |
+
} else {
|
370 |
+
$uid = $empty_event->get_uid();
|
371 |
+
}
|
372 |
+
$uid = $event->get_uid();
|
373 |
+
} else {
|
374 |
+
$is_ticket_event = false;
|
375 |
+
$ticket_event_account = '';
|
376 |
+
$uid = $empty_event->get_uid();
|
377 |
+
}
|
378 |
+
|
379 |
+
if ( $ticketing ) {
|
380 |
+
if ( $event ) {
|
381 |
+
$ticket_currency = $api->get_api_event_currency( $event->get( 'post_id' ) );
|
382 |
+
if ( $api->is_ticket_event_from_another_account( $event->get( 'post_id' ) ) ) {
|
383 |
+
$ticket_error = sprintf(
|
384 |
+
__( 'This Event was created using a different account %s. Changes are not allowed.', AI1EC_PLUGIN_NAME ),
|
385 |
+
$api->get_api_event_account( $event->get( 'post_id' ) )
|
386 |
+
);
|
387 |
+
}
|
388 |
+
}
|
389 |
+
if ( ! isset( $ticket_currency ) || is_null( $ticket_currency ) ) {
|
390 |
+
//for new ticket events get the currency from the payments settings
|
391 |
+
$payments_settings = $api->get_payment_settings();
|
392 |
+
if ( null !== $payments_settings ) {
|
393 |
+
$ticket_currency = $payments_settings['currency'];
|
394 |
+
} else {
|
395 |
+
$ticket_currency = 'USD';
|
396 |
+
}
|
397 |
+
}
|
398 |
+
} else {
|
399 |
+
$ticket_currency = '';
|
400 |
+
}
|
401 |
+
|
402 |
+
$args = array(
|
403 |
+
'cost' => $cost,
|
404 |
+
'cost_type' => $cost_type,
|
405 |
+
'ticket_url' => $ticket_url,
|
406 |
+
'event' => $empty_event,
|
407 |
+
'uid' => $uid,
|
408 |
+
'tickets' => $tickets,
|
409 |
+
'ticketing' => $ticketing,
|
410 |
+
'valid_payout_details' => $api->has_payment_settings(),
|
411 |
+
'tickets_message' => $message,
|
412 |
+
'start' => $start,
|
413 |
+
'end' => $end,
|
414 |
+
'tickets_loading_error' => $ticket_error,
|
415 |
+
'ticket_event_imported' => $ticket_event_imported,
|
416 |
+
'is_free' => $is_free,
|
417 |
+
'ticket_currency' => $ticket_currency,
|
418 |
+
'is_ticket_event' => $is_ticket_event,
|
419 |
+
'ticket_event_account' => $ticket_event_account,
|
420 |
+
'tax_options' => $tax_options
|
421 |
+
);
|
422 |
+
|
423 |
+
$boxes[] = $theme_loader
|
424 |
+
->get_file( 'box_event_cost.php', $args, true )
|
425 |
+
->get_content();
|
426 |
+
|
427 |
+
|
428 |
+
|
429 |
+
// =========================================
|
430 |
+
// = Display organizer contact information =
|
431 |
+
// =========================================
|
432 |
+
$submitter_html = null;
|
433 |
+
if ( $event ) {
|
434 |
+
$submitter_info = $event->get_submitter_info();
|
435 |
+
if ( null !== $submitter_info ) {
|
436 |
+
if ( 1 === $submitter_info['is_organizer'] ) {
|
437 |
+
$submitter_html = Ai1ec_I18n::__( '<span class="ai1ec-info-text">The event was submitted by this Organizer.</span>' );
|
438 |
+
} else if ( isset( $submitter_info['email'] ) ||
|
439 |
+
isset( $submitter_info['name'] ) ) {
|
440 |
+
$submitted_by = '';
|
441 |
+
if ( false === ai1ec_is_blank ( $submitter_info['name'] ) ) {
|
442 |
+
$submitted_by = sprintf( '<strong>%s</strong>', htmlspecialchars( $submitter_info['name'] ) );
|
443 |
+
}
|
444 |
+
if ( false === ai1ec_is_blank( $submitter_info['email'] ) ) {
|
445 |
+
if ( '' !== $submitted_by ) {
|
446 |
+
$submitted_by .= Ai1ec_I18n::__( ', email: ' );
|
447 |
+
}
|
448 |
+
$submitted_by .= sprintf( '<a href="mailto:%s" target="_top">%s</a>', $submitter_info['email'], $submitter_info['email'] ) ;
|
449 |
+
}
|
450 |
+
$submitter_html = sprintf( Ai1ec_I18n::__( '<span class="ai1ec-info-text">The event was submitted by %s.</span>' ),
|
451 |
+
$submitted_by
|
452 |
+
);
|
453 |
+
}
|
454 |
+
}
|
455 |
+
}
|
456 |
+
$args = array(
|
457 |
+
'contact_name' => $contact_name,
|
458 |
+
'contact_phone' => $contact_phone,
|
459 |
+
'contact_email' => $contact_email,
|
460 |
+
'contact_url' => $contact_url,
|
461 |
+
'event' => $empty_event,
|
462 |
+
'submitter_html' => $submitter_html
|
463 |
+
);
|
464 |
+
$boxes[] = $theme_loader
|
465 |
+
->get_file( 'box_event_contact.php', $args, true )
|
466 |
+
->get_content();
|
467 |
+
|
468 |
+
// ==========================
|
469 |
+
// = Parent/Child relations =
|
470 |
+
// ==========================
|
471 |
+
if ( $event ) {
|
472 |
+
$parent = $this->_registry->get( 'model.event.parent' )
|
473 |
+
->get_parent_event( $event->get( 'post_id' ) );
|
474 |
+
if ( $parent ) {
|
475 |
+
try {
|
476 |
+
$parent = $this->_registry->get( 'model.event', $parent );
|
477 |
+
} catch ( Ai1ec_Event_Not_Found_Exception $exception ) { // ignore
|
478 |
+
$parent = null;
|
479 |
+
}
|
480 |
+
}
|
481 |
+
if ( $parent ) {
|
482 |
+
$children = $this->_registry->get( 'model.event.parent' )
|
483 |
+
->get_child_event_objects( $event->get( 'post_id' ) );
|
484 |
+
$args = compact( 'parent', 'children' );
|
485 |
+
$args['registry'] = $this->_registry;
|
486 |
+
|
487 |
+
$boxes[] = $theme_loader->get_file(
|
488 |
+
'box_event_children.php',
|
489 |
+
$args,
|
490 |
+
true
|
491 |
+
)->get_content();
|
492 |
+
}
|
493 |
+
|
494 |
+
}
|
495 |
+
|
496 |
+
$boxes = apply_filters( 'ai1ec_add_new_event_boxes', $boxes, $event );
|
497 |
+
// Display the final view of the meta box.
|
498 |
+
$args = array(
|
499 |
+
'boxes' => $boxes,
|
500 |
+
);
|
501 |
+
|
502 |
+
if ( $this->_is_post_event( $post ) ) {
|
503 |
+
// ======================
|
504 |
+
// = Display Box Review =
|
505 |
+
// ======================
|
506 |
+
$review = $this->_registry->get( 'model.review' );
|
507 |
+
$review_content = $review->get_content( $theme_loader );
|
508 |
+
|
509 |
+
if ( false === ai1ec_is_blank( $review_content ) ) {
|
510 |
+
$args['review_box'] = $review_content;
|
511 |
+
}
|
512 |
+
}
|
513 |
+
|
514 |
+
echo $theme_loader
|
515 |
+
->get_file( 'add_new_event_meta_box.php', $args, true )
|
516 |
+
->get_content();
|
517 |
+
}
|
518 |
+
|
519 |
+
/**
|
520 |
+
* Add Banner Image meta box to the Add/Edit Event.
|
521 |
+
*
|
522 |
+
* @return void
|
523 |
+
*/
|
524 |
+
public function banner_meta_box_view( $post ) {
|
525 |
+
$banner_image_meta = get_post_meta( $post->ID, 'ai1ec_banner_image' );
|
526 |
+
$theme_loader = $this->_registry->get( 'theme.loader' );
|
527 |
+
$args = array(
|
528 |
+
'src' => $banner_image_meta && $banner_image_meta[0]
|
529 |
+
? $banner_image_meta[0] : false,
|
530 |
+
'set_text' => Ai1ec_I18n::__( 'Set banner image' ),
|
531 |
+
'remove_text' => Ai1ec_I18n::__( 'Remove banner image' ),
|
532 |
+
|
533 |
+
);
|
534 |
+
echo $theme_loader
|
535 |
+
->get_file( 'banner-image.twig', $args, true )
|
536 |
+
->get_content();
|
537 |
+
}
|
538 |
+
|
539 |
+
/**
|
540 |
+
* disable_autosave method
|
541 |
+
*
|
542 |
+
* Callback to disable autosave script
|
543 |
+
*
|
544 |
+
* @param array $input List of scripts registered
|
545 |
+
*
|
546 |
+
* @return array Modified scripts list
|
547 |
+
*/
|
548 |
+
public function disable_autosave( array $input ) {
|
549 |
+
wp_deregister_script( 'autosave' );
|
550 |
+
$autosave_key = array_search( 'autosave', $input );
|
551 |
+
if ( false === $autosave_key || ! is_scalar( $autosave_key ) ) {
|
552 |
+
unset( $input[$autosave_key] );
|
553 |
+
}
|
554 |
+
return $input;
|
555 |
+
}
|
556 |
+
|
557 |
+
/**
|
558 |
+
* Renders Bootstrap inline alert.
|
559 |
+
*
|
560 |
+
* @param WP_Post $post Post object.
|
561 |
+
*
|
562 |
+
* @return void Method does not return.
|
563 |
+
*/
|
564 |
+
public function event_inline_alert( $post ) {
|
565 |
+
if ( $this->_is_post_event( $post ) ) {
|
566 |
+
$theme_loader = $this->_registry->get( 'theme.loader' );
|
567 |
+
echo $theme_loader->get_file( 'box_inline_warning.php', null, true )
|
568 |
+
->get_content();
|
569 |
+
}
|
570 |
+
}
|
571 |
+
|
572 |
+
private function _is_post_event( $post ) {
|
573 |
+
return isset( $post->post_type ) && AI1EC_POST_TYPE === $post->post_type;
|
574 |
+
}
|
575 |
|
576 |
}
|
app/view/admin/add-ons.php
CHANGED
@@ -10,88 +10,88 @@
|
|
10 |
* @subpackage AI1EC.View
|
11 |
*/
|
12 |
class Ai1ec_View_Add_Ons extends Ai1ec_View_Admin_Abstract {
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
|
88 |
-
|
89 |
-
|
90 |
|
91 |
-
|
92 |
-
|
93 |
|
94 |
-
|
95 |
-
|
96 |
|
97 |
}
|
10 |
* @subpackage AI1EC.View
|
11 |
*/
|
12 |
class Ai1ec_View_Add_Ons extends Ai1ec_View_Admin_Abstract {
|
13 |
+
/**
|
14 |
+
* Adds page to the menu.
|
15 |
+
*
|
16 |
+
* @wp_hook admin_menu
|
17 |
+
*
|
18 |
+
* @return void
|
19 |
+
*/
|
20 |
+
public function add_page() {
|
21 |
+
// =======================
|
22 |
+
// = Calendar Add Ons Page =
|
23 |
+
// =======================
|
24 |
+
add_submenu_page(
|
25 |
+
AI1EC_ADMIN_BASE_URL,
|
26 |
+
Ai1ec_I18n::__( 'Add-ons' ),
|
27 |
+
Ai1ec_I18n::__( 'Add-ons' ),
|
28 |
+
'manage_ai1ec_feeds',
|
29 |
+
AI1EC_PLUGIN_NAME . '-add-ons',
|
30 |
+
array( $this, 'display_page' )
|
31 |
+
);
|
32 |
+
}
|
33 |
+
/**
|
34 |
+
* Display Add Ons list page.
|
35 |
+
*
|
36 |
+
* @return void
|
37 |
+
*/
|
38 |
+
public function display_page() {
|
39 |
+
wp_enqueue_style(
|
40 |
+
'ai1ec_addons.css',
|
41 |
+
AI1EC_ADMIN_THEME_CSS_URL . 'addons.css',
|
42 |
+
array(),
|
43 |
+
AI1EC_VERSION
|
44 |
+
);
|
45 |
+
$content = get_site_transient( 'ai1ec_timely_addons' );
|
46 |
+
$is_error = false;
|
47 |
+
if (
|
48 |
+
false === $content ||
|
49 |
+
(
|
50 |
+
defined( 'AI1EC_DEBUG' ) &&
|
51 |
+
AI1EC_DEBUG
|
52 |
+
)
|
53 |
+
) {
|
54 |
+
$is_error = true;
|
55 |
+
$feed = wp_remote_get( AI1EC_TIMELY_ADDONS_URI );
|
56 |
+
if ( ! is_wp_error( $feed ) ) {
|
57 |
+
$content = json_decode( wp_remote_retrieve_body( $feed ) );
|
58 |
+
if ( null !== $content ) {
|
59 |
+
set_site_transient( 'ai1ec_timely_addons', $content, 3600 );
|
60 |
+
$is_error = false;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
$this->_registry->get( 'theme.loader' )->get_file(
|
65 |
+
'add-ons-list/page.twig',
|
66 |
+
array(
|
67 |
+
'labels' => array(
|
68 |
+
'title' => Ai1ec_I18n::__(
|
69 |
+
'Add-ons for All In One Event Calendar'
|
70 |
+
),
|
71 |
+
'button_title' => Ai1ec_I18n::__(
|
72 |
+
'Browse All Add-ons'
|
73 |
+
),
|
74 |
+
'paragraph_content' => Ai1ec_I18n::__(
|
75 |
+
'These add-ons extend the functionality of the All-in-One Event Calendar.'
|
76 |
+
),
|
77 |
+
'error' => Ai1ec_I18n::__(
|
78 |
+
'There was an error retrieving the extensions list from the server. Please try again later.'
|
79 |
+
),
|
80 |
+
),
|
81 |
+
'content' => $content,
|
82 |
+
'is_error' => $is_error,
|
83 |
+
),
|
84 |
+
true
|
85 |
+
)->render();
|
86 |
+
}
|
87 |
|
88 |
+
public function add_meta_box() {
|
89 |
+
}
|
90 |
|
91 |
+
public function display_meta_box( $object, $box ) {
|
92 |
+
}
|
93 |
|
94 |
+
public function handle_post() {
|
95 |
+
}
|
96 |
|
97 |
}
|
app/view/admin/all-events.php
CHANGED
@@ -2,259 +2,259 @@
|
|
2 |
|
3 |
class Ai1ec_View_Admin_All_Events extends Ai1ec_Base {
|
4 |
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
|
38 |
-
|
39 |
-
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
|
260 |
}
|
2 |
|
3 |
class Ai1ec_View_Admin_All_Events extends Ai1ec_Base {
|
4 |
|
5 |
+
/**
|
6 |
+
* change_columns function
|
7 |
+
*
|
8 |
+
* Adds Event date/time column to our custom post type
|
9 |
+
* and renames Date column to Post Date
|
10 |
+
*
|
11 |
+
* @param array $columns Existing columns
|
12 |
+
*
|
13 |
+
* @return array Updated columns array
|
14 |
+
*/
|
15 |
+
public function change_columns( array $columns = array() ) {
|
16 |
+
$columns['author'] = __( 'Author', AI1EC_PLUGIN_NAME );
|
17 |
+
$columns['date'] = __( 'Post Date', AI1EC_PLUGIN_NAME );
|
18 |
+
$columns['ai1ec_event_date'] = __( 'Event date/time', AI1EC_PLUGIN_NAME );
|
19 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
20 |
+
if ( $api->is_signed() ) {
|
21 |
+
$columns['tickets'] = __( 'Ticket Types', AI1EC_PLUGIN_NAME );
|
22 |
+
}
|
23 |
+
return $columns;
|
24 |
+
}
|
25 |
|
26 |
+
/**
|
27 |
+
* orderby function
|
28 |
+
*
|
29 |
+
* Orders events by event date
|
30 |
+
*
|
31 |
+
* @param string $orderby Orderby sql
|
32 |
+
* @param object $wp_query
|
33 |
+
*
|
34 |
+
* @return void
|
35 |
+
**/
|
36 |
+
public function orderby( $orderby, $wp_query ) {
|
37 |
|
38 |
+
$db = $this->_registry->get( 'dbi.dbi' );
|
39 |
+
$aco = $this->_registry->get( 'acl.aco' );
|
40 |
|
41 |
+
if( true === $aco->is_all_events_page() ) {
|
42 |
+
$wp_query->query = wp_parse_args( $wp_query->query );
|
43 |
+
$table_name = $db->get_table_name( 'ai1ec_events' );
|
44 |
+
$posts = $db->get_table_name( 'posts' );
|
45 |
+
if( isset( $wp_query->query['orderby'] ) && 'ai1ec_event_date' === @$wp_query->query['orderby'] ) {
|
46 |
+
$orderby = "(SELECT start FROM {$table_name} WHERE post_id = {$posts}.ID) " . $wp_query->get('order');
|
47 |
+
} else if( empty( $wp_query->query['orderby'] ) || $wp_query->query['orderby'] === 'menu_order title' ) {
|
48 |
+
$orderby = "(SELECT start FROM {$table_name} WHERE post_id = {$posts}.ID) " . 'desc';
|
49 |
+
}
|
50 |
+
}
|
51 |
+
return $orderby;
|
52 |
+
}
|
53 |
|
54 |
+
/**
|
55 |
+
* custom_columns function
|
56 |
+
*
|
57 |
+
* Adds content for custom columns
|
58 |
+
*
|
59 |
+
* @return void
|
60 |
+
**/
|
61 |
+
public function custom_columns( $column, $post_id ) {
|
62 |
+
if ( 'ai1ec_event_date' === $column ) {
|
63 |
+
try {
|
64 |
+
$event = $this->_registry->get( 'model.event', $post_id );
|
65 |
+
$time = $this->_registry->get( 'view.event.time' );
|
66 |
+
echo $time->get_timespan_html( $event );
|
67 |
+
} catch ( Exception $e ) {
|
68 |
+
// event wasn't found, output empty string
|
69 |
+
echo '';
|
70 |
+
}
|
71 |
+
} else if ( 'tickets' === $column ) {
|
72 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
73 |
+
if ( $api->is_ticket_event_imported( $post_id ) ) {
|
74 |
+
echo '';
|
75 |
+
} else {
|
76 |
+
try {
|
77 |
+
$event = $this->_registry->get( 'model.event', $post_id );
|
78 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
79 |
+
$api_event_id = $api->get_api_event_id( $post_id );
|
80 |
+
if ( $api_event_id ) {
|
81 |
+
echo '<a href="#" class="ai1ec-has-tickets" data-post-id="'
|
82 |
+
. $post_id . '">'
|
83 |
+
. __( 'Ticketing Details', AI1EC_PLUGIN_NAME ) . '</a>';
|
84 |
+
}
|
85 |
|
86 |
+
} catch ( Exception $e ) {
|
87 |
+
// event wasn't found, output empty string
|
88 |
+
echo '';
|
89 |
+
}
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
|
94 |
+
/**
|
95 |
+
* sortable_columns function
|
96 |
+
*
|
97 |
+
* Enable sorting of columns
|
98 |
+
*
|
99 |
+
* @return void
|
100 |
+
**/
|
101 |
+
public function sortable_columns( $columns ) {
|
102 |
+
$columns['ai1ec_event_date'] = 'ai1ec_event_date';
|
103 |
+
$columns['author'] = 'author';
|
104 |
+
return $columns;
|
105 |
+
}
|
106 |
|
107 |
+
/**
|
108 |
+
* taxonomy_filter_restrict_manage_posts function
|
109 |
+
*
|
110 |
+
* Adds filter dropdowns for event categories and event tags.
|
111 |
+
* Adds filter dropdowns for event authors.
|
112 |
+
*
|
113 |
+
* @uses wp_dropdown_users To create a dropdown with current user selected.
|
114 |
+
*
|
115 |
+
* @return void
|
116 |
+
**/
|
117 |
+
function taxonomy_filter_restrict_manage_posts() {
|
118 |
+
global $typenow;
|
119 |
|
120 |
+
// =============================================
|
121 |
+
// = add the dropdowns only on the events page =
|
122 |
+
// =============================================
|
123 |
+
if( $typenow === AI1EC_POST_TYPE ) {
|
124 |
+
$filters = get_object_taxonomies( $typenow );
|
125 |
+
foreach( $filters as $tax_slug ) {
|
126 |
+
$tax_obj = get_taxonomy( $tax_slug );
|
127 |
+
wp_dropdown_categories( array(
|
128 |
+
'show_option_all' => __( 'Show All ', AI1EC_PLUGIN_NAME ) . $tax_obj->label,
|
129 |
+
'taxonomy' => $tax_slug,
|
130 |
+
'name' => $tax_obj->name,
|
131 |
+
'orderby' => 'name',
|
132 |
+
'selected' => isset( $_GET[$tax_slug] ) ? $_GET[$tax_slug] : '',
|
133 |
+
'hierarchical' => $tax_obj->hierarchical,
|
134 |
+
'show_count' => true,
|
135 |
+
'hide_if_empty' => true,
|
136 |
+
'value_field' => 'slug',
|
137 |
+
));
|
138 |
+
}
|
139 |
+
$args = array(
|
140 |
+
'name' => 'author',
|
141 |
+
'show_option_all' => __( 'Show All Authors', AI1EC_PLUGIN_NAME ),
|
142 |
+
);
|
143 |
+
if ( isset( $_GET['user'] ) ) {
|
144 |
+
$args['selected'] = (int)$_GET['user'];
|
145 |
+
}
|
146 |
+
wp_dropdown_users($args);
|
147 |
+
}
|
148 |
+
}
|
149 |
|
150 |
+
/**
|
151 |
+
* taxonomy_filter_post_type_request function
|
152 |
+
*
|
153 |
+
* Adds filtering of events list by event tags and event categories
|
154 |
+
*
|
155 |
+
* @return void
|
156 |
+
**/
|
157 |
+
public function taxonomy_filter_post_type_request( $query ) {
|
158 |
+
global $pagenow, $typenow;
|
159 |
+
if( 'edit.php' === $pagenow ) {
|
160 |
+
$filters = get_object_taxonomies( $typenow );
|
161 |
+
foreach( $filters as $tax_slug ) {
|
162 |
+
$var = &$query->query_vars[$tax_slug];
|
163 |
+
if( isset( $var ) ) {
|
164 |
+
$term = null;
|
165 |
|
166 |
+
if( is_numeric( $var ) ) {
|
167 |
+
$term = get_term_by( 'id', $var, $tax_slug );
|
168 |
+
} else {
|
169 |
+
$term = get_term_by( 'slug', $var, $tax_slug );
|
170 |
+
}
|
171 |
|
172 |
+
if( isset( $term->slug ) ) {
|
173 |
+
$var = $term->slug;
|
174 |
+
}
|
175 |
+
}
|
176 |
+
}
|
177 |
+
}
|
178 |
+
// ===========================
|
179 |
+
// = Order by Event date ASC =
|
180 |
+
// ===========================
|
181 |
+
if( 'ai1ec_event' === $typenow ) {
|
182 |
+
if ( ! array_key_exists( 'orderby', $query->query_vars ) ) {
|
183 |
+
$query->query_vars['orderby'] = 'ai1ec_event_date';
|
184 |
+
$query->query_vars['order'] = 'desc';
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}
|
188 |
|
189 |
+
/**
|
190 |
+
* CSS and templates files needed for ticketing.
|
191 |
+
*/
|
192 |
+
public function add_ticketing_styling() {
|
193 |
+
// Add CSS
|
194 |
+
$this->_registry->get( 'css.admin' )->admin_enqueue_scripts(
|
195 |
+
'ai1ec_event_page_all-in-one-event-calendar-settings'
|
196 |
+
);
|
197 |
+
$this->_registry->get( 'css.admin' )->process_enqueue(
|
198 |
+
array(
|
199 |
+
array( 'style', 'ticketing.css', ),
|
200 |
+
)
|
201 |
+
);
|
202 |
+
}
|
203 |
|
204 |
+
/**
|
205 |
+
* Get ticket details by Event id.
|
206 |
+
*/
|
207 |
+
public function show_ticket_details() {
|
208 |
+
$post_id = $_POST['ai1ec_event_id'];
|
209 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
210 |
+
if ( $api->is_ticket_event_from_another_account( $post_id ) ) {
|
211 |
+
$tickets = json_encode(
|
212 |
+
array( 'data' => array(), 'error' =>
|
213 |
+
sprintf(
|
214 |
+
__( 'This Event was created using a different account %s. Changes are not allowed.', AI1EC_PLUGIN_NAME ),
|
215 |
+
$api->get_api_event_account( $post_id )
|
216 |
+
)
|
217 |
+
) );
|
218 |
+
} else {
|
219 |
+
$tickets = $api->get_ticket_types( $post_id );
|
220 |
+
}
|
221 |
+
echo $tickets;
|
222 |
+
wp_die();
|
223 |
+
}
|
224 |
|
225 |
+
/**
|
226 |
+
* Get attendees list.
|
227 |
+
*/
|
228 |
+
public function show_attendees() {
|
229 |
+
$post_id = $_POST['ai1ec_event_id'];
|
230 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
231 |
+
$tickets = $api->get_tickets( $post_id );
|
232 |
+
echo $tickets;
|
233 |
+
wp_die();
|
234 |
+
}
|
235 |
|
236 |
+
/**
|
237 |
+
* count_future_events function
|
238 |
+
*
|
239 |
+
* @return Count future events
|
240 |
+
**/
|
241 |
+
public function count_future_events( $user_id = null ) {
|
242 |
+
if ( is_admin() ) {
|
243 |
+
$settings = $this->_registry->get( 'model.settings' );
|
244 |
+
$current_time = $this->_registry->get( 'date.time' );
|
245 |
+
$current_time->set_timezone( $settings->get( 'timezone_string' ) );
|
246 |
+
$current_time = $current_time->format_to_gmt();
|
247 |
+
$user_id = get_current_user_id();
|
248 |
+
$where = get_posts_by_author_sql( AI1EC_POST_TYPE, true, $user_id );
|
249 |
+
$db = $this->_registry->get( 'dbi.dbi' );
|
250 |
+
$posts = $db->get_table_name( 'posts' );
|
251 |
+
$table_name = $db->get_table_name( 'ai1ec_events' );
|
252 |
+
$sql = "SELECT COUNT(*) FROM $table_name INNER JOIN $posts on $table_name.post_id = {$posts}.ID"
|
253 |
+
. " $where AND $table_name.start > $current_time"; //future event
|
254 |
+
return $db->get_var( $sql );
|
255 |
+
} else {
|
256 |
+
return 0;
|
257 |
+
}
|
258 |
+
}
|
259 |
|
260 |
}
|
app/view/admin/calendar-feeds.php
CHANGED
@@ -11,102 +11,102 @@
|
|
11 |
*/
|
12 |
class Ai1ec_View_Calendar_Feeds extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
|
92 |
-
|
93 |
-
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
|
109 |
-
|
110 |
-
|
111 |
|
112 |
}
|
11 |
*/
|
12 |
class Ai1ec_View_Calendar_Feeds extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
+
/**
|
15 |
+
* Adds page to the menu.
|
16 |
+
*
|
17 |
+
* @wp_hook admin_menu
|
18 |
+
*
|
19 |
+
* @return void
|
20 |
+
*/
|
21 |
+
public function add_page() {
|
22 |
+
// =======================
|
23 |
+
// = Calendar Feeds Page =
|
24 |
+
// =======================
|
25 |
+
$calendar_feeds = add_submenu_page(
|
26 |
+
AI1EC_ADMIN_BASE_URL,
|
27 |
+
Ai1ec_I18n::__( 'Import Feeds' ),
|
28 |
+
Ai1ec_I18n::__( 'Import Feeds' ),
|
29 |
+
'manage_ai1ec_feeds',
|
30 |
+
AI1EC_PLUGIN_NAME . '-feeds',
|
31 |
+
array( $this, 'display_page' )
|
32 |
+
);
|
33 |
+
$this->_registry->get( 'model.settings' )
|
34 |
+
->set( 'feeds_page', $calendar_feeds );
|
35 |
+
}
|
36 |
|
37 |
+
/**
|
38 |
+
* Adds metabox to the page.
|
39 |
+
*
|
40 |
+
* @wp_hook admin_init
|
41 |
+
*
|
42 |
+
* @return void
|
43 |
+
*/
|
44 |
+
public function add_meta_box() {
|
45 |
+
// Add the 'ICS Import Settings' meta box.
|
46 |
+
add_meta_box(
|
47 |
+
'ai1ec-feeds',
|
48 |
+
Ai1ec_I18n::_x( 'Feed Subscriptions', 'meta box' ),
|
49 |
+
array( $this, 'display_meta_box' ),
|
50 |
+
$this->_registry->get( 'model.settings' )->get( 'feeds_page' ),
|
51 |
+
'left',
|
52 |
+
'default'
|
53 |
+
);
|
54 |
+
}
|
55 |
|
56 |
+
/**
|
57 |
+
* Display this plugin's feeds page in the admin.
|
58 |
+
*
|
59 |
+
* @return void
|
60 |
+
*/
|
61 |
+
public function display_page() {
|
62 |
+
$settings = $this->_registry->get( 'model.settings' );
|
63 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
64 |
+
$args = array(
|
65 |
+
'title' => __(
|
66 |
+
'All-in-One Event Calendar: Import Feeds',
|
67 |
+
AI1EC_PLUGIN_NAME
|
68 |
+
),
|
69 |
+
'settings_page' => $settings->get( 'feeds_page' ),
|
70 |
+
'calendar_settings' => false,
|
71 |
+
);
|
72 |
+
$file = $loader->get_file( 'feeds_settings.php', $args, true );
|
73 |
+
$file->render();
|
74 |
+
}
|
75 |
|
76 |
+
/**
|
77 |
+
* Renders the contents of the Calendar Feeds meta box.
|
78 |
+
*
|
79 |
+
* @return void
|
80 |
+
*/
|
81 |
+
public function display_meta_box( $object, $box ) {
|
82 |
+
// register the calendar feeds page.
|
83 |
+
$calendar_feeds = $this->_registry->get( 'controller.calendar-feeds' );
|
84 |
+
$feeds = array();
|
85 |
|
86 |
+
array_push( $feeds, $this->_registry->get( 'calendar-feed.import' ) );
|
87 |
+
// Check for user subscription - Discover events
|
88 |
+
if ($this->_api_registration->has_subscription_active( 'discover-events' ) ) {
|
89 |
+
array_push( $feeds, $this->_registry->get( 'calendar-feed.suggested' ) );
|
90 |
+
}
|
91 |
|
92 |
+
// Add ICS
|
93 |
+
array_push( $feeds, $this->_registry->get( 'calendar-feed.ics' ) );
|
94 |
|
95 |
+
$feeds = apply_filters( 'ai1ec_calendar_feeds', $feeds );
|
96 |
+
foreach ( $feeds as $feed ) {
|
97 |
+
$calendar_feeds->add_plugin( $feed );
|
98 |
+
}
|
99 |
+
$calendar_feeds->handle_feeds_page_post();
|
100 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
101 |
+
$file = $loader->get_file(
|
102 |
+
'box_feeds.php',
|
103 |
+
array( 'calendar_feeds' => $calendar_feeds ),
|
104 |
+
true
|
105 |
+
);
|
106 |
+
$file->render();
|
107 |
+
}
|
108 |
|
109 |
+
public function handle_post() {
|
110 |
+
}
|
111 |
|
112 |
}
|
app/view/admin/event-category.php
CHANGED
@@ -11,230 +11,230 @@
|
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_EventCategory extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
|
240 |
}
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_EventCategory extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* Inserts Color element at index 2 of columns array
|
16 |
+
*
|
17 |
+
* @param array $columns Array with event_category columns
|
18 |
+
*
|
19 |
+
* @return array Array with event_category columns where Color is inserted
|
20 |
+
* at index 2
|
21 |
+
*/
|
22 |
+
public function manage_event_categories_columns( $columns ) {
|
23 |
+
wp_enqueue_media();
|
24 |
+
$this->_registry->get( 'css.admin' )
|
25 |
+
->process_enqueue( array(
|
26 |
+
array( 'style', 'bootstrap.min.css' )
|
27 |
+
) );
|
28 |
+
return array_splice( $columns, 0, 3 ) + // get only first element
|
29 |
+
// insert at index 2
|
30 |
+
array( 'cat_color' => __( 'Color', AI1EC_PLUGIN_NAME ) ) +
|
31 |
+
// insert at index 3
|
32 |
+
array( 'cat_image' => __( 'Image', AI1EC_PLUGIN_NAME ) ) +
|
33 |
+
// insert rest of elements at the back
|
34 |
+
array_splice( $columns, 0 );
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Returns the color or image of the event category.
|
39 |
+
*
|
40 |
+
* That will be displayed on event category lists page in the backend.
|
41 |
+
*
|
42 |
+
* @param $not_set
|
43 |
+
* @param $column_name
|
44 |
+
* @param $term_id
|
45 |
+
* @internal param array $columns Array with event_category columns
|
46 |
+
*
|
47 |
+
* @return array Array with event_category columns where Color is inserted
|
48 |
+
* at index 2
|
49 |
+
*/
|
50 |
+
public function manage_events_categories_custom_column(
|
51 |
+
$not_set,
|
52 |
+
$column_name,
|
53 |
+
$term_id
|
54 |
+
) {
|
55 |
+
switch ( $column_name ) {
|
56 |
+
case 'cat_color':
|
57 |
+
return $this->_registry->get( 'view.event.taxonomy' )
|
58 |
+
->get_category_color_square( $term_id );
|
59 |
+
case 'cat_image':
|
60 |
+
return $this->_registry->get( 'view.event.taxonomy' )
|
61 |
+
->get_category_image_square( $term_id );
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Hook to process event categories creation
|
67 |
+
*
|
68 |
+
* @param $term_id
|
69 |
+
*
|
70 |
+
* @return void Method does not return.
|
71 |
+
*/
|
72 |
+
public function created_events_categories( $term_id ) {
|
73 |
+
$this->edited_events_categories( $term_id );
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* A callback method, triggered when `event_categories' are being edited.
|
78 |
+
*
|
79 |
+
* @param int $term_id ID of term (category) being edited.
|
80 |
+
*
|
81 |
+
* @return void Method does not return.
|
82 |
+
*/
|
83 |
+
public function edited_events_categories( $term_id ) {
|
84 |
+
if ( isset( $_POST['_inline_edit'] ) ) {
|
85 |
+
return;
|
86 |
+
}
|
87 |
+
|
88 |
+
$tag_color_value = '';
|
89 |
+
if ( ! empty( $_POST['tag-color-value'] ) ) {
|
90 |
+
$tag_color_value = (string)$_POST['tag-color-value'];
|
91 |
+
}
|
92 |
+
$tag_image_value = '';
|
93 |
+
if ( ! empty( $_POST['ai1ec_category_image_url'] ) ) {
|
94 |
+
$tag_image_value = (string)$_POST['ai1ec_category_image_url'];
|
95 |
+
}
|
96 |
+
if ( isset( $_POST['ai1ec_category_image_url_remove'] ) ) {
|
97 |
+
$tag_image_value = null;
|
98 |
+
}
|
99 |
+
|
100 |
+
$db = $this->_registry->get( 'dbi.dbi' );
|
101 |
+
$table_name = $db->get_table_name( 'ai1ec_event_category_meta' );
|
102 |
+
$term = $db->get_row( $db->prepare(
|
103 |
+
'SELECT term_id FROM ' . $table_name .
|
104 |
+
' WHERE term_id = %d',
|
105 |
+
$term_id
|
106 |
+
) );
|
107 |
+
|
108 |
+
if ( null === $term ) { // term does not exist, create it
|
109 |
+
$db->insert(
|
110 |
+
$table_name,
|
111 |
+
array(
|
112 |
+
'term_id' => $term_id,
|
113 |
+
'term_color' => $tag_color_value,
|
114 |
+
'term_image' => $tag_image_value,
|
115 |
+
),
|
116 |
+
array(
|
117 |
+
'%d',
|
118 |
+
'%s',
|
119 |
+
'%s',
|
120 |
+
)
|
121 |
+
);
|
122 |
+
} else { // term exist, update it
|
123 |
+
$db->update(
|
124 |
+
$table_name,
|
125 |
+
array(
|
126 |
+
'term_color' => $tag_color_value,
|
127 |
+
'term_image' => $tag_image_value
|
128 |
+
),
|
129 |
+
array( 'term_id' => $term_id ),
|
130 |
+
array( '%s', '%s' ),
|
131 |
+
array( '%d' )
|
132 |
+
);
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
public function show_color( $term = null ) {
|
137 |
+
|
138 |
+
$taxonomy = $this->_registry->get( 'model.taxonomy' );
|
139 |
+
$color = '';
|
140 |
+
if ( null !== $term ) {
|
141 |
+
$color = $taxonomy->get_category_color( $term->term_id );
|
142 |
+
}
|
143 |
+
|
144 |
+
$style = '';
|
145 |
+
$clr = '';
|
146 |
+
|
147 |
+
if ( $color ) {
|
148 |
+
$style = 'style="background-color: ' . $color . '"';
|
149 |
+
$clr = $color;
|
150 |
+
}
|
151 |
+
|
152 |
+
$args = array(
|
153 |
+
'style' => $style,
|
154 |
+
'color' => $clr,
|
155 |
+
'label' => Ai1ec_I18n::__( 'Category Color' ),
|
156 |
+
'description' => Ai1ec_I18n::__(
|
157 |
+
'Events in this category will be identified by this color'
|
158 |
+
),
|
159 |
+
'edit' => true,
|
160 |
+
);
|
161 |
+
|
162 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
163 |
+
$loader->get_file(
|
164 |
+
'setting/categories-color-picker.twig',
|
165 |
+
$args,
|
166 |
+
true
|
167 |
+
)->render();
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Edit category form
|
172 |
+
*
|
173 |
+
* @param $term
|
174 |
+
*
|
175 |
+
* @return void
|
176 |
+
*/
|
177 |
+
public function events_categories_edit_form_fields( $term ) {
|
178 |
+
$this->show_color( $term );
|
179 |
+
$taxonomy = $this->_registry->get( 'model.taxonomy' );
|
180 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
181 |
+
$image = $taxonomy->get_category_image( $term->term_id );
|
182 |
+
|
183 |
+
$style = 'style="display:none"';
|
184 |
+
|
185 |
+
if ( null !== $image ) {
|
186 |
+
$style = '';
|
187 |
+
}
|
188 |
+
|
189 |
+
// Category image
|
190 |
+
$args = array(
|
191 |
+
'image_src' => $image,
|
192 |
+
'image_style' => $style,
|
193 |
+
'section_name' => __( 'Category Image', AI1EC_PLUGIN_NAME ),
|
194 |
+
'label' => __( 'Add Image', AI1EC_PLUGIN_NAME ),
|
195 |
+
'remove_label' => __( 'Remove Image', AI1EC_PLUGIN_NAME ),
|
196 |
+
'description' => __(
|
197 |
+
'Assign an optional image to the category. Recommended size: square, minimum 400×400 pixels.',
|
198 |
+
AI1EC_PLUGIN_NAME
|
199 |
+
),
|
200 |
+
'edit' => true,
|
201 |
+
);
|
202 |
+
|
203 |
+
$loader->get_file(
|
204 |
+
'setting/categories-image.twig',
|
205 |
+
$args,
|
206 |
+
true
|
207 |
+
)->render();
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Add category form
|
212 |
+
*
|
213 |
+
* @return void
|
214 |
+
*/
|
215 |
+
public function events_categories_add_form_fields() {
|
216 |
+
|
217 |
+
$this->show_color();
|
218 |
+
|
219 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
220 |
+
|
221 |
+
// Category image
|
222 |
+
$args = array(
|
223 |
+
'image_src' => '',
|
224 |
+
'image_style' => 'style="display:none"',
|
225 |
+
'section_name' => __( 'Category Image', AI1EC_PLUGIN_NAME ),
|
226 |
+
'label' => __( 'Add Image', AI1EC_PLUGIN_NAME),
|
227 |
+
'description' => __( 'Assign an optional image to the category. Recommended size: square, minimum 400×400 pixels.', AI1EC_PLUGIN_NAME ),
|
228 |
+
'edit' => false,
|
229 |
+
);
|
230 |
+
|
231 |
+
$file = $loader->get_file(
|
232 |
+
'setting/categories-image.twig',
|
233 |
+
$args,
|
234 |
+
true
|
235 |
+
);
|
236 |
+
|
237 |
+
$file->render();
|
238 |
+
}
|
239 |
|
240 |
}
|
app/view/admin/get-repeat-box.php
CHANGED
@@ -10,661 +10,661 @@
|
|
10 |
* @subpackage AI1EC.View
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_Get_repeat_Box extends Ai1ec_Base {
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
<div class="ai1ec-btn-group-grid" id="<?php echo $name; ?>">
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
</div>
|
365 |
<input type="hidden" name="<?php echo $name; ?>"
|
366 |
-
|
367 |
<?php
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
}
|
10 |
* @subpackage AI1EC.View
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_Get_repeat_Box extends Ai1ec_Base {
|
13 |
+
/**
|
14 |
+
* get_repeat_box function
|
15 |
+
*
|
16 |
+
* @return string
|
17 |
+
**/
|
18 |
+
public function get_repeat_box() {
|
19 |
+
$time_system = $this->_registry->get( 'date.system' );
|
20 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
21 |
+
$repeat = (int) $_REQUEST["repeat"];
|
22 |
+
$repeat = $repeat == 1 ? 1 : 0;
|
23 |
+
$post_id = (int) $_REQUEST["post_id"];
|
24 |
+
$count = 100;
|
25 |
+
$end = 0;
|
26 |
+
$until = $time_system->current_time( true );
|
27 |
+
|
28 |
+
// try getting the event
|
29 |
+
try {
|
30 |
+
$event = $this->_registry->get( 'model.event', $post_id );
|
31 |
+
$rule = '';
|
32 |
+
|
33 |
+
if ( $repeat ) {
|
34 |
+
$rule = $event->get( 'recurrence_rules' )
|
35 |
+
? $event->get( 'recurrence_rules' )
|
36 |
+
: '';
|
37 |
+
} else {
|
38 |
+
$rule = $event->get( 'exception_rules' ) ?
|
39 |
+
$event->get( 'exception_rules' )
|
40 |
+
: '';
|
41 |
+
}
|
42 |
+
|
43 |
+
$rule = $this->_registry->get( 'recurrence.rule' )->filter_rule( $rule );
|
44 |
+
|
45 |
+
$rc = new SG_iCal_Recurrence(
|
46 |
+
new SG_iCal_Line( 'RRULE:' . $rule )
|
47 |
+
);
|
48 |
+
|
49 |
+
if ( $until = $rc->getUntil() ) {
|
50 |
+
$until = ( is_numeric( $until ) )
|
51 |
+
? $until
|
52 |
+
: strtotime( $until );
|
53 |
+
$end = 2;
|
54 |
+
} elseif ( $count = $rc->getCount() ) {
|
55 |
+
$count = ( is_numeric( $count ) ) ? $count : 100;
|
56 |
+
$end = 1;
|
57 |
+
}
|
58 |
+
} catch( Ai1ec_Event_Not_Found_Exception $e ) {
|
59 |
+
$rule = '';
|
60 |
+
$rc = new SG_iCal_Recurrence(
|
61 |
+
new SG_iCal_Line( 'RRULE:' )
|
62 |
+
);
|
63 |
+
}
|
64 |
+
|
65 |
+
$args = array(
|
66 |
+
'row_daily' => $this->row_daily(
|
67 |
+
false,
|
68 |
+
$rc->getInterval() ? $rc->getInterval() : 1
|
69 |
+
),
|
70 |
+
'row_weekly' => $this->row_weekly(
|
71 |
+
false,
|
72 |
+
$rc->getInterval() ? $rc->getInterval() : 1,
|
73 |
+
is_array( $rc->getByDay() ) ? $rc->getByDay() : array()
|
74 |
+
),
|
75 |
+
'row_monthly' => $this->row_monthly(
|
76 |
+
false,
|
77 |
+
$rc->getInterval() ? $rc->getInterval() : 1,
|
78 |
+
! $this->_is_monthday_empty( $rc ),
|
79 |
+
$rc->getByMonthDay() ? $rc->getByMonthDay() : array(),
|
80 |
+
$rc->getByDay() ? $rc->getByDay() : array()
|
81 |
+
),
|
82 |
+
'row_yearly' => $this->row_yearly(
|
83 |
+
false,
|
84 |
+
$rc->getInterval() ? $rc->getInterval() : 1,
|
85 |
+
is_array( $rc->getByMonth() ) ? $rc->getByMonth() : array()
|
86 |
+
),
|
87 |
+
'row_custom' => $this->row_custom(
|
88 |
+
false,
|
89 |
+
$this->get_date_array_from_rule( $rule )
|
90 |
+
),
|
91 |
+
'count' => $this->create_count_input(
|
92 |
+
'ai1ec_count',
|
93 |
+
$count
|
94 |
+
) . Ai1ec_I18n::__( 'times' ),
|
95 |
+
'end' => $this->create_end_dropdown( $end ),
|
96 |
+
'until' => $until,
|
97 |
+
'repeat' => $repeat,
|
98 |
+
'ending_type' => $end,
|
99 |
+
'selected_tab' => $rc->getFreq()
|
100 |
+
? strtolower( $rc->getFreq() )
|
101 |
+
: 'custom',
|
102 |
+
);
|
103 |
+
$output = array(
|
104 |
+
'error' => false,
|
105 |
+
'message' => $loader->get_file(
|
106 |
+
'box_repeat.php',
|
107 |
+
$args,
|
108 |
+
true
|
109 |
+
)->get_content(),
|
110 |
+
'repeat' => $repeat,
|
111 |
+
);
|
112 |
+
$json_strategy = $this->_registry->get( 'http.response.render.strategy.json' );
|
113 |
+
$json_strategy->render( array( 'data' => $output ) );
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* get_weekday_by_id function
|
118 |
+
*
|
119 |
+
* Returns weekday name in English
|
120 |
+
*
|
121 |
+
* @param int $day_id Day ID
|
122 |
+
*
|
123 |
+
* @return string
|
124 |
+
**/
|
125 |
+
public function get_weekday_by_id( $day_id, $by_value = false ) {
|
126 |
+
// do not translate this !!!
|
127 |
+
$week_days = array(
|
128 |
+
0 => 'SU',
|
129 |
+
1 => 'MO',
|
130 |
+
2 => 'TU',
|
131 |
+
3 => 'WE',
|
132 |
+
4 => 'TH',
|
133 |
+
5 => 'FR',
|
134 |
+
6 => 'SA',
|
135 |
+
);
|
136 |
+
|
137 |
+
if ( $by_value ) {
|
138 |
+
while ( $_name = current( $week_days ) ) {
|
139 |
+
if ( $_name == $day_id ) {
|
140 |
+
return key( $week_days );
|
141 |
+
}
|
142 |
+
next( $week_days );
|
143 |
+
}
|
144 |
+
return false;
|
145 |
+
}
|
146 |
+
return $week_days[$day_id];
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* convert_rrule_to_text method
|
151 |
+
*
|
152 |
+
* Convert a `recurrence rule' to text to display it on screen
|
153 |
+
*
|
154 |
+
* @return void
|
155 |
+
**/
|
156 |
+
public function convert_rrule_to_text() {
|
157 |
+
$error = false;
|
158 |
+
$message = '';
|
159 |
+
// check to see if RRULE is set
|
160 |
+
if ( isset( $_REQUEST['rrule'] ) ) {
|
161 |
+
// check to see if rrule is empty
|
162 |
+
if ( empty( $_REQUEST['rrule'] ) ) {
|
163 |
+
$error = true;
|
164 |
+
$message = Ai1ec_I18n::__(
|
165 |
+
'Recurrence rule cannot be empty.'
|
166 |
+
);
|
167 |
+
} else {
|
168 |
+
//list( $rule, $value ) = explode( '=', $_REQUEST['rrule'], 2 );
|
169 |
+
//if ( in_array( array(), $rule ) ) {
|
170 |
+
// $message = $this->_registry->get( 'recurrence.date' );
|
171 |
+
//
|
172 |
+
//} else {
|
173 |
+
$rrule = $this->_registry->get( 'recurrence.rule' );
|
174 |
+
// convert rrule to text
|
175 |
+
$message = ucfirst(
|
176 |
+
$rrule->rrule_to_text( $_REQUEST['rrule'] )
|
177 |
+
);
|
178 |
+
//}
|
179 |
+
}
|
180 |
+
} else {
|
181 |
+
$error = true;
|
182 |
+
$message = Ai1ec_I18n::__(
|
183 |
+
'Recurrence rule was not provided.'
|
184 |
+
);
|
185 |
+
}
|
186 |
+
$output = array(
|
187 |
+
'error' => $error,
|
188 |
+
'message' => get_magic_quotes_gpc()
|
189 |
+
? stripslashes( $message )
|
190 |
+
: $message,
|
191 |
+
);
|
192 |
+
|
193 |
+
$json_strategy = $this->_registry->get( 'http.response.render.strategy.json' );
|
194 |
+
$json_strategy->render( array( 'data' => $output ) );
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* create_end_dropdown function
|
199 |
+
*
|
200 |
+
* Outputs the dropdown list for the recurrence end option.
|
201 |
+
*
|
202 |
+
* @param int $selected The index of the selected option, if any
|
203 |
+
* @return void
|
204 |
+
**/
|
205 |
+
protected function create_end_dropdown( $selected = NULL ) {
|
206 |
+
ob_start();
|
207 |
+
|
208 |
+
$options = array(
|
209 |
+
0 => Ai1ec_I18n::__( 'Never' ),
|
210 |
+
1 => Ai1ec_I18n::__( 'After' ),
|
211 |
+
2 => Ai1ec_I18n::__( 'On date' ),
|
212 |
+
);
|
213 |
+
|
214 |
+
?>
|
215 |
+
<select name="ai1ec_end" id="ai1ec_end">
|
216 |
+
<?php foreach( $options as $key => $val ): ?>
|
217 |
+
<option value="<?php echo $key ?>"
|
218 |
+
<?php if( $key === $selected ) echo 'selected="selected"' ?>>
|
219 |
+
<?php echo $val ?>
|
220 |
+
</option>
|
221 |
+
<?php endforeach ?>
|
222 |
+
</select>
|
223 |
+
<?php
|
224 |
+
|
225 |
+
$output = ob_get_contents();
|
226 |
+
ob_end_clean();
|
227 |
+
|
228 |
+
return $output;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* row_daily function
|
233 |
+
*
|
234 |
+
* Returns daily selector
|
235 |
+
*
|
236 |
+
* @return void
|
237 |
+
**/
|
238 |
+
protected function row_daily( $visible = false, $selected = 1 ) {
|
239 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
240 |
+
|
241 |
+
$args = array(
|
242 |
+
'visible' => $visible,
|
243 |
+
'count' => $this->create_count_input(
|
244 |
+
'ai1ec_daily_count',
|
245 |
+
$selected,
|
246 |
+
365
|
247 |
+
) . Ai1ec_I18n::__( 'day(s)' ),
|
248 |
+
);
|
249 |
+
return $loader->get_file( 'row_daily.php', $args, true )
|
250 |
+
->get_content();
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* row_custom function
|
255 |
+
*
|
256 |
+
* Returns custom dates selector
|
257 |
+
*
|
258 |
+
* @return void
|
259 |
+
**/
|
260 |
+
protected function row_custom( $visible = false, $dates = array() ) {
|
261 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
262 |
+
|
263 |
+
$args = array(
|
264 |
+
'visible' => $visible,
|
265 |
+
'selected_dates' => implode( ',', $dates )
|
266 |
+
);
|
267 |
+
return $loader->get_file( 'row_custom.php', $args, true )
|
268 |
+
->get_content();
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Generates and returns "End after X times" input
|
273 |
+
*
|
274 |
+
* @param Integer|NULL $count Initial value of range input
|
275 |
+
*
|
276 |
+
* @return String Repeat dropdown
|
277 |
+
*/
|
278 |
+
protected function create_count_input( $name, $count = 100, $max = 365 ) {
|
279 |
+
ob_start();
|
280 |
+
|
281 |
+
if ( ! $count ) {
|
282 |
+
$count = 100;
|
283 |
+
}
|
284 |
+
?>
|
285 |
+
<input type="range" name="<?php echo $name ?>" id="<?php echo $name ?>"
|
286 |
+
min="1" max="<?php echo $max ?>"
|
287 |
+
<?php if ( $count ) echo 'value="' . $count . '"' ?> />
|
288 |
+
<?php
|
289 |
+
return ob_get_clean();
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* row_weekly function
|
294 |
+
*
|
295 |
+
* Returns weekly selector
|
296 |
+
*
|
297 |
+
* @return void
|
298 |
+
**/
|
299 |
+
protected function row_weekly(
|
300 |
+
$visible = false,
|
301 |
+
$count = 1,
|
302 |
+
array $selected = array()
|
303 |
+
) {
|
304 |
+
global $wp_locale;
|
305 |
+
$start_of_week = $this->_registry->get( 'model.option' )
|
306 |
+
->get( 'start_of_week', 1 );
|
307 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
308 |
+
|
309 |
+
$options = array();
|
310 |
+
// get days from start_of_week until the last day
|
311 |
+
for ( $i = $start_of_week; $i <= 6; ++$i ) {
|
312 |
+
$options[$this->get_weekday_by_id( $i )] = $wp_locale
|
313 |
+
->weekday_initial[$wp_locale->weekday[$i]];
|
314 |
+
}
|
315 |
+
|
316 |
+
// get days from 0 until start_of_week
|
317 |
+
if ( $start_of_week > 0 ) {
|
318 |
+
for ( $i = 0; $i < $start_of_week; $i++ ) {
|
319 |
+
$options[$this->get_weekday_by_id( $i )] = $wp_locale
|
320 |
+
->weekday_initial[$wp_locale->weekday[$i]];
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
$args = array(
|
325 |
+
'visible' => $visible,
|
326 |
+
'count' => $this->create_count_input(
|
327 |
+
'ai1ec_weekly_count',
|
328 |
+
$count,
|
329 |
+
52
|
330 |
+
) . Ai1ec_I18n::__( 'week(s)' ),
|
331 |
+
'week_days' => $this->create_list_element(
|
332 |
+
'ai1ec_weekly_date_select',
|
333 |
+
$options,
|
334 |
+
$selected
|
335 |
+
)
|
336 |
+
);
|
337 |
+
return $loader->get_file( 'row_weekly.php', $args, true )
|
338 |
+
->get_content();
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Creates a grid of weekday, day, or month selection buttons.
|
343 |
+
*
|
344 |
+
* @return string
|
345 |
+
*/
|
346 |
+
protected function create_list_element(
|
347 |
+
$name,
|
348 |
+
array $options = array(),
|
349 |
+
array $selected = array()
|
350 |
+
) {
|
351 |
+
ob_start();
|
352 |
+
?>
|
353 |
<div class="ai1ec-btn-group-grid" id="<?php echo $name; ?>">
|
354 |
+
<?php foreach ( $options as $key => $val ) : ?>
|
355 |
+
<div class="ai1ec-pull-left">
|
356 |
+
<a class="ai1ec-btn ai1ec-btn-default ai1ec-btn-block
|
357 |
+
<?php echo in_array( $key, $selected ) ? 'ai1ec-active' : ''; ?>">
|
358 |
+
<?php echo $val; ?>
|
359 |
+
</a>
|
360 |
+
<input type="hidden" name="<?php echo $name . '_' . $key; ?>"
|
361 |
+
value="<?php echo $key; ?>">
|
362 |
+
</div class="ai1ec-pull-left">
|
363 |
+
<?php endforeach; ?>
|
364 |
</div>
|
365 |
<input type="hidden" name="<?php echo $name; ?>"
|
366 |
+
value="<?php echo implode( ',', $selected ) ?>">
|
367 |
<?php
|
368 |
+
return ob_get_clean();
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* row_monthly function
|
373 |
+
*
|
374 |
+
* Returns monthly selector
|
375 |
+
*
|
376 |
+
* @return void
|
377 |
+
**/
|
378 |
+
protected function row_monthly(
|
379 |
+
$visible = false,
|
380 |
+
$count = 1,
|
381 |
+
$bymonthday = true,
|
382 |
+
$month = array(),
|
383 |
+
$day = array()
|
384 |
+
) {
|
385 |
+
global $wp_locale;
|
386 |
+
$start_of_week = $this->_registry->get( 'model.option' )
|
387 |
+
->get( 'start_of_week', 1 );
|
388 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
389 |
+
|
390 |
+
$options_wd = array();
|
391 |
+
// get days from start_of_week until the last day
|
392 |
+
for ( $i = $start_of_week; $i <= 6; ++$i ) {
|
393 |
+
$options_wd[$this->get_weekday_by_id( $i )] = $wp_locale
|
394 |
+
->weekday[$i];
|
395 |
+
}
|
396 |
+
|
397 |
+
// get days from 0 until start_of_week
|
398 |
+
if ( $start_of_week > 0 ) {
|
399 |
+
for ( $i = 0; $i < $start_of_week; $i++ ) {
|
400 |
+
$options_wd[$this->get_weekday_by_id( $i )] = $wp_locale
|
401 |
+
->weekday[$i];
|
402 |
+
}
|
403 |
+
}
|
404 |
+
|
405 |
+
// get options like 1st/2nd/3rd for "day number"
|
406 |
+
$options_dn = array( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5 );
|
407 |
+
foreach ( $options_dn as $_dn ) {
|
408 |
+
$options_dn[$_dn] = $this->_registry->get(
|
409 |
+
'date.time',
|
410 |
+
strtotime( $_dn . '-01-1998 12:00:00' )
|
411 |
+
)->format_i18n( 'jS' );
|
412 |
+
}
|
413 |
+
$options_dn['-1'] = Ai1ec_I18n::__( 'last' );
|
414 |
+
|
415 |
+
$byday_checked = $bymonthday ? '' : 'checked';
|
416 |
+
$byday_expanded = $bymonthday ? 'ai1ec-collapse' : 'ai1ec-in';
|
417 |
+
$bymonthday_checked = $bymonthday ? 'checked' : '';
|
418 |
+
$bymonthday_expanded = $bymonthday ? 'ai1ec-in' : 'ai1ec-collapse';
|
419 |
+
|
420 |
+
$args = array(
|
421 |
+
'visible' => $visible,
|
422 |
+
'count' => $this->create_count_input(
|
423 |
+
'ai1ec_monthly_count',
|
424 |
+
$count,
|
425 |
+
12
|
426 |
+
) . Ai1ec_I18n::__( 'month(s)' ),
|
427 |
+
'month' => $this->create_monthly_date_select(
|
428 |
+
$month
|
429 |
+
),
|
430 |
+
'day_nums' => $this->create_select_element(
|
431 |
+
'ai1ec_monthly_byday_num',
|
432 |
+
$options_dn,
|
433 |
+
$this->_get_day_number_from_byday( $day )
|
434 |
+
),
|
435 |
+
'week_days' => $this->create_select_element(
|
436 |
+
'ai1ec_monthly_byday_weekday',
|
437 |
+
$options_wd,
|
438 |
+
$this->_get_day_shortname_from_byday( $day )
|
439 |
+
),
|
440 |
+
'bymonthday_checked' => $bymonthday_checked,
|
441 |
+
'byday_checked' => $byday_checked,
|
442 |
+
'bymonthday_expanded' => $bymonthday_expanded,
|
443 |
+
'byday_expanded' => $byday_expanded,
|
444 |
+
);
|
445 |
+
return $loader->get_file( 'row_monthly.php', $args, true )
|
446 |
+
->get_content();
|
447 |
+
}
|
448 |
+
|
449 |
+
/**
|
450 |
+
* Creates selector for dates in monthly repeat tab.
|
451 |
+
*
|
452 |
+
* @return void
|
453 |
+
*/
|
454 |
+
protected function create_monthly_date_select( $selected = array() ) {
|
455 |
+
$options = array();
|
456 |
+
for ( $i = 1; $i <= 31; ++$i ) {
|
457 |
+
$options[$i] = $i;
|
458 |
+
}
|
459 |
+
return $this->create_list_element(
|
460 |
+
'ai1ec_montly_date_select',
|
461 |
+
$options,
|
462 |
+
$selected
|
463 |
+
);
|
464 |
+
}
|
465 |
+
|
466 |
+
/**
|
467 |
+
* create_on_the_select function
|
468 |
+
*
|
469 |
+
*
|
470 |
+
*
|
471 |
+
* @return string
|
472 |
+
**/
|
473 |
+
protected function create_on_the_select(
|
474 |
+
$f_selected = false,
|
475 |
+
$s_selected = false
|
476 |
+
) {
|
477 |
+
$ret = '';
|
478 |
+
|
479 |
+
$first_options = array(
|
480 |
+
'0' => Ai1ec_I18n::__( 'first' ),
|
481 |
+
'1' => Ai1ec_I18n::__( 'second' ),
|
482 |
+
'2' => Ai1ec_I18n::__( 'third' ),
|
483 |
+
'3' => Ai1ec_I18n::__( 'fourth' ),
|
484 |
+
'4' => '------',
|
485 |
+
'5' => Ai1ec_I18n::__( 'last' )
|
486 |
+
);
|
487 |
+
$ret = $this->create_select_element(
|
488 |
+
'ai1ec_monthly_each_select',
|
489 |
+
$first_options,
|
490 |
+
$f_selected,
|
491 |
+
array( 4 )
|
492 |
+
);
|
493 |
+
|
494 |
+
$second_options = array(
|
495 |
+
'0' => Ai1ec_I18n::__( 'Sunday' ),
|
496 |
+
'1' => Ai1ec_I18n::__( 'Monday' ),
|
497 |
+
'2' => Ai1ec_I18n::__( 'Tuesday' ),
|
498 |
+
'3' => Ai1ec_I18n::__( 'Wednesday' ),
|
499 |
+
'4' => Ai1ec_I18n::__( 'Thursday' ),
|
500 |
+
'5' => Ai1ec_I18n::__( 'Friday' ),
|
501 |
+
'6' => Ai1ec_I18n::__( 'Saturday' ),
|
502 |
+
'7' => '--------',
|
503 |
+
'8' => Ai1ec_I18n::__( 'day' ),
|
504 |
+
'9' => Ai1ec_I18n::__( 'weekday' ),
|
505 |
+
'10' => Ai1ec_I18n::__( 'weekend day' )
|
506 |
+
);
|
507 |
+
|
508 |
+
return $ret . $this->create_select_element(
|
509 |
+
'ai1ec_monthly_on_the_select',
|
510 |
+
$second_options,
|
511 |
+
$s_selected,
|
512 |
+
array( 7 )
|
513 |
+
);
|
514 |
+
}
|
515 |
+
|
516 |
+
/**
|
517 |
+
* create_select_element function
|
518 |
+
*
|
519 |
+
* Render HTML <select> element
|
520 |
+
*
|
521 |
+
* @param string $name Name of element to be rendered
|
522 |
+
* @param array $options Select <option> values as key=>value pairs
|
523 |
+
* @param string $selected Key to be marked as selected [optional=false]
|
524 |
+
* @param array $disabled_keys List of options to disable [optional=array]
|
525 |
+
*
|
526 |
+
* @return string Rendered <select> HTML element
|
527 |
+
**/
|
528 |
+
protected function create_select_element(
|
529 |
+
$name,
|
530 |
+
array $options = array(),
|
531 |
+
$selected = false,
|
532 |
+
array $disabled_keys = array()
|
533 |
+
) {
|
534 |
+
ob_start();
|
535 |
+
?>
|
536 |
+
<select name="<?php echo $name ?>" id="<?php echo $name ?>">
|
537 |
+
<?php foreach( $options as $key => $val ): ?>
|
538 |
+
<option value="<?php echo $key ?>"
|
539 |
+
<?php echo $key === $selected ? 'selected="selected"' : '' ?>
|
540 |
+
<?php echo in_array( $key, $disabled_keys ) ? 'disabled' : '' ?>>
|
541 |
+
<?php echo $val ?>
|
542 |
+
</option>
|
543 |
+
<?php endforeach ?>
|
544 |
+
</select>
|
545 |
+
<?php
|
546 |
+
return ob_get_clean();
|
547 |
+
}
|
548 |
+
|
549 |
+
/**
|
550 |
+
* row_yearly function
|
551 |
+
*
|
552 |
+
* Returns yearly selector
|
553 |
+
*
|
554 |
+
* @return void
|
555 |
+
**/
|
556 |
+
protected function row_yearly(
|
557 |
+
$visible = false,
|
558 |
+
$count = 1,
|
559 |
+
$year = array(),
|
560 |
+
$first = false,
|
561 |
+
$second = false
|
562 |
+
) {
|
563 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
564 |
+
|
565 |
+
$args = array(
|
566 |
+
'visible' => $visible,
|
567 |
+
'count' => $this->create_count_input(
|
568 |
+
'ai1ec_yearly_count',
|
569 |
+
$count,
|
570 |
+
10
|
571 |
+
) . Ai1ec_I18n::__( 'year(s)' ),
|
572 |
+
'year' => $this->create_yearly_date_select( $year ),
|
573 |
+
'on_the_select' => $this->create_on_the_select(
|
574 |
+
$first,
|
575 |
+
$second
|
576 |
+
),
|
577 |
+
);
|
578 |
+
return $loader->get_file( 'row_yearly.php', $args, true )
|
579 |
+
->get_content();
|
580 |
+
}
|
581 |
+
|
582 |
+
/**
|
583 |
+
* create_yearly_date_select function
|
584 |
+
*
|
585 |
+
*
|
586 |
+
*
|
587 |
+
* @return void
|
588 |
+
**/
|
589 |
+
protected function create_yearly_date_select( $selected = array() ) {
|
590 |
+
global $wp_locale;
|
591 |
+
$options = array();
|
592 |
+
for ( $i = 1; $i <= 12; ++$i ) {
|
593 |
+
$options[$i] = $wp_locale->month_abbrev[
|
594 |
+
$wp_locale->month[sprintf( '%02d', $i )]
|
595 |
+
];
|
596 |
+
}
|
597 |
+
return $this->create_list_element(
|
598 |
+
'ai1ec_yearly_date_select',
|
599 |
+
$options,
|
600 |
+
$selected
|
601 |
+
);
|
602 |
+
}
|
603 |
+
|
604 |
+
/**
|
605 |
+
* Converts recurrence rule to array of string of dates.
|
606 |
+
*
|
607 |
+
* @param string $rule RUle.
|
608 |
+
*
|
609 |
+
* @return array Array of dates or empty array.
|
610 |
+
* @throws Ai1ec_Bootstrap_Exception
|
611 |
+
*/
|
612 |
+
protected function get_date_array_from_rule( $rule ) {
|
613 |
+
if (
|
614 |
+
'RDATE' !== substr( $rule, 0, 5 ) &&
|
615 |
+
'EXDATE' !== substr( $rule, 0, 6 )
|
616 |
+
) {
|
617 |
+
return array();
|
618 |
+
}
|
619 |
+
$line = new SG_iCal_Line( 'RRULE:' . $rule );
|
620 |
+
$dates = $line->getDataAsArray();
|
621 |
+
$dates_as_strings = array();
|
622 |
+
foreach ( $dates as $date ) {
|
623 |
+
$date = str_replace( array( 'RDATE=', 'EXDATE=' ), '', $date );
|
624 |
+
$date = $this->_registry->get( 'date.time', $date )->set_preferred_timezone( 'UTC' );
|
625 |
+
$dates_as_strings[] = $date->format( 'm/d/Y' );
|
626 |
+
}
|
627 |
+
return $dates_as_strings;
|
628 |
+
}
|
629 |
+
|
630 |
+
/**
|
631 |
+
* Returns whether recurrence rule has non null ByMonthDay.
|
632 |
+
*
|
633 |
+
* @param SG_iCal_Recurrence $rc iCal class.
|
634 |
+
*
|
635 |
+
* @return bool True or false.
|
636 |
+
*/
|
637 |
+
protected function _is_monthday_empty( SG_iCal_Recurrence $rc ) {
|
638 |
+
return false === $rc->getByMonthDay();
|
639 |
+
}
|
640 |
+
|
641 |
+
/**
|
642 |
+
* Returns day number from by day array.
|
643 |
+
*
|
644 |
+
* @param array $day
|
645 |
+
*
|
646 |
+
* @return bool|int Day of false if empty array.
|
647 |
+
*/
|
648 |
+
protected function _get_day_number_from_byday( array $day ) {
|
649 |
+
return isset( $day[0] ) ? (int) $day[0] : false;
|
650 |
+
}
|
651 |
+
|
652 |
+
/**
|
653 |
+
* Returns string part from "ByDay" recurrence rule.
|
654 |
+
*
|
655 |
+
* @param array $day Element to parse.
|
656 |
+
*
|
657 |
+
* @return bool|string False if empty or not matched, otherwise short day
|
658 |
+
* name.
|
659 |
+
*/
|
660 |
+
protected function _get_day_shortname_from_byday( $day ) {
|
661 |
+
if ( empty( $day ) ) {
|
662 |
+
return false;
|
663 |
+
}
|
664 |
+
$value = $day[0];
|
665 |
+
if ( preg_match('/[-]?\d([A-Z]+)/', $value, $matches ) ) {
|
666 |
+
return $matches[1];
|
667 |
+
}
|
668 |
+
return false;
|
669 |
+
}
|
670 |
}
|
app/view/admin/get-tax-box.php
CHANGED
@@ -10,21 +10,21 @@
|
|
10 |
* @subpackage AI1EC.View
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_Get_Tax_Box extends Ai1ec_Base {
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
|
30 |
}
|
10 |
* @subpackage AI1EC.View
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_Get_Tax_Box extends Ai1ec_Base {
|
13 |
+
/**
|
14 |
+
* get_tax_box function
|
15 |
+
*
|
16 |
+
* @return string
|
17 |
+
**/
|
18 |
+
public function get_tax_box() {
|
19 |
+
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
20 |
+
$post_id = $_POST['ai1ec_event_id'];
|
21 |
+
$modal = $api->get_tax_options_modal( $post_id );
|
22 |
+
$output = array(
|
23 |
+
'error' => $modal->error,
|
24 |
+
'message' => $modal->data
|
25 |
+
);
|
26 |
+
$json_strategy = $this->_registry->get( 'http.response.render.strategy.json' );
|
27 |
+
$json_strategy->render( array( 'data' => $output ) );
|
28 |
+
}
|
29 |
|
30 |
}
|
app/view/admin/nav.php
CHANGED
@@ -10,27 +10,27 @@
|
|
10 |
*/
|
11 |
class Ai1ec_View_Admin_Navigation extends Ai1ec_Base {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
|
36 |
}
|
10 |
*/
|
11 |
class Ai1ec_View_Admin_Navigation extends Ai1ec_Base {
|
12 |
|
13 |
+
/**
|
14 |
+
* Adds a link to Settings page in plugin list page.
|
15 |
+
*
|
16 |
+
* @param array $links List of available links.
|
17 |
+
*
|
18 |
+
* @return array Modified links list.
|
19 |
+
*/
|
20 |
+
public function plugin_action_links( $links ) {
|
21 |
+
$settings_link = sprintf(
|
22 |
+
Ai1ec_I18n::__( '<a href="%s">Settings</a>' ),
|
23 |
+
ai1ec_admin_url( AI1EC_SETTINGS_BASE_URL )
|
24 |
+
);
|
25 |
+
array_unshift( $links, $settings_link );
|
26 |
+
if ( current_user_can( 'activate_plugins' ) ) {
|
27 |
+
$updates_link = sprintf(
|
28 |
+
Ai1ec_I18n::__( '<a href="%s">Check for updates</a>' ),
|
29 |
+
ai1ec_admin_url( AI1EC_FORCE_UPDATES_URL )
|
30 |
+
);
|
31 |
+
array_push( $links, $updates_link );
|
32 |
+
}
|
33 |
+
return $links;
|
34 |
+
}
|
35 |
|
36 |
}
|
app/view/admin/organize.php
CHANGED
@@ -11,95 +11,95 @@
|
|
11 |
*/
|
12 |
class Ai1ec_View_Organize extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
}
|
11 |
*/
|
12 |
class Ai1ec_View_Organize extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var array The taxonomies for events
|
16 |
+
*/
|
17 |
+
protected $_taxonomies = array();
|
18 |
|
19 |
+
/**
|
20 |
+
* Register actions to draw the headers
|
21 |
+
*/
|
22 |
+
public function add_taxonomy_actions() {
|
23 |
+
$taxonomies = get_object_taxonomies( AI1EC_POST_TYPE, 'object' );
|
24 |
+
$dispatcher = $this->_registry->get( 'event.dispatcher' );
|
25 |
+
$taxonomy_metadata = array(
|
26 |
+
'events_categories' => array(
|
27 |
+
'icon' => 'ai1ec-fa ai1ec-fa-folder-open'
|
28 |
+
),
|
29 |
+
'events_tags' => array(
|
30 |
+
'icon' => 'ai1ec-fa ai1ec-fa-tags'
|
31 |
+
)
|
32 |
+
);
|
33 |
+
$taxonomy_metadata = apply_filters(
|
34 |
+
'ai1ec_add_custom_groups',
|
35 |
+
$taxonomy_metadata
|
36 |
+
);
|
37 |
+
do_action( 'ai1ec_taxonomy_management_css' );
|
38 |
+
foreach ( $taxonomies as $taxonomy => $data ) {
|
39 |
+
if ( true === $data->public ) {
|
40 |
+
$active_taxonomy =
|
41 |
+
isset( $_GET['taxonomy'] ) &&
|
42 |
+
$taxonomy === $_GET['taxonomy'];
|
43 |
+
$edit_url = $edit_label = '';
|
44 |
+
if ( isset( $taxonomy_metadata[$taxonomy]['url'] ) ) {
|
45 |
+
$edit_url = $taxonomy_metadata[$taxonomy]['url'];
|
46 |
+
$edit_label = $taxonomy_metadata[$taxonomy]['edit_label'];
|
47 |
+
}
|
48 |
+
$this->_taxonomies[] = array(
|
49 |
+
'taxonomy_name' => $taxonomy,
|
50 |
+
'url' => add_query_arg(
|
51 |
+
array(
|
52 |
+
'post_type' => AI1EC_POST_TYPE,
|
53 |
+
'taxonomy' => $taxonomy
|
54 |
+
),
|
55 |
+
admin_url( 'edit-tags.php' )
|
56 |
+
),
|
57 |
+
'name' => $data->labels->name,
|
58 |
+
'active' => $active_taxonomy,
|
59 |
+
'icon' => isset( $taxonomy_metadata[$taxonomy] ) ?
|
60 |
+
$taxonomy_metadata[$taxonomy]['icon'] :
|
61 |
+
'',
|
62 |
+
'edit_url' => $edit_url,
|
63 |
+
'edit_label' => $edit_label,
|
64 |
+
);
|
65 |
|
66 |
+
if ( $active_taxonomy ) {
|
67 |
+
$dispatcher->register_action(
|
68 |
+
$taxonomy . '_pre_add_form',
|
69 |
+
array( 'view.admin.organize', 'render_header' )
|
70 |
+
);
|
71 |
+
$dispatcher->register_action(
|
72 |
+
$taxonomy . '_pre_edit_form',
|
73 |
+
array( 'view.admin.organize', 'render_header' )
|
74 |
+
);
|
75 |
+
}
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
|
80 |
+
/**
|
81 |
+
* Render tabbed header to manage taxonomies.
|
82 |
+
*/
|
83 |
+
public function render_header() {
|
84 |
+
echo $this->get_header();
|
85 |
+
}
|
86 |
|
87 |
+
/**
|
88 |
+
* Generate and return tabbed header to manage taxonomies.
|
89 |
+
*
|
90 |
+
* @return string HTML markup for tabbed header
|
91 |
+
*/
|
92 |
+
public function get_header() {
|
93 |
+
return $this->_registry->get( 'theme.loader' )->get_file(
|
94 |
+
'organize/header.twig',
|
95 |
+
array(
|
96 |
+
'taxonomies' => apply_filters(
|
97 |
+
'ai1ec_custom_taxonomies',
|
98 |
+
$this->_taxonomies
|
99 |
+
),
|
100 |
+
'text_title' => Ai1ec_I18n::__( 'Organize Events' ),
|
101 |
+
),
|
102 |
+
true
|
103 |
+
)->get_content();
|
104 |
+
}
|
105 |
}
|
app/view/admin/samples.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* The Calendar Samples page.
|
5 |
+
*
|
6 |
+
* @author Time.ly Network Inc.
|
7 |
+
* @since 2.1
|
8 |
+
*
|
9 |
+
* @package AI1EC
|
10 |
+
* @subpackage AI1EC.View
|
11 |
+
*/
|
12 |
+
class Ai1ec_View_Samples extends Ai1ec_View_Admin_Abstract {
|
13 |
+
/**
|
14 |
+
* Adds page to the menu.
|
15 |
+
*
|
16 |
+
* @wp_hook admin_menu
|
17 |
+
*
|
18 |
+
* @return void
|
19 |
+
*/
|
20 |
+
public function add_page() {
|
21 |
+
// =======================
|
22 |
+
// = Calendar Add Ons Page =
|
23 |
+
// =======================
|
24 |
+
add_submenu_page(
|
25 |
+
AI1EC_ADMIN_BASE_URL,
|
26 |
+
Ai1ec_I18n::__( 'Samples' ),
|
27 |
+
Ai1ec_I18n::__( 'Samples' ),
|
28 |
+
'manage_ai1ec_options',
|
29 |
+
AI1EC_PLUGIN_NAME . '-samples',
|
30 |
+
array( $this, 'display_page' )
|
31 |
+
);
|
32 |
+
}
|
33 |
+
/**
|
34 |
+
* Display Add Ons list page.
|
35 |
+
*
|
36 |
+
* @return void
|
37 |
+
*/
|
38 |
+
public function display_page() {
|
39 |
+
wp_enqueue_style(
|
40 |
+
'ai1ec_samples.css',
|
41 |
+
AI1EC_ADMIN_THEME_CSS_URL . 'samples.css',
|
42 |
+
array(),
|
43 |
+
AI1EC_VERSION
|
44 |
+
);
|
45 |
+
|
46 |
+
$this->_registry->get( 'theme.loader' )->get_file(
|
47 |
+
'samples.twig',
|
48 |
+
array(),
|
49 |
+
true
|
50 |
+
)->render();
|
51 |
+
}
|
52 |
+
|
53 |
+
public function add_meta_box() {
|
54 |
+
}
|
55 |
+
|
56 |
+
public function display_meta_box( $object, $box ) {
|
57 |
+
}
|
58 |
+
|
59 |
+
public function handle_post() {
|
60 |
+
}
|
61 |
+
|
62 |
+
}
|
app/view/admin/settings.php
CHANGED
@@ -11,338 +11,338 @@
|
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_Settings extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
$api = $this->_registry->get( 'model.api.api-registration' );
|
165 |
-
$signup_available = $api->is_api_sign_up_available();
|
166 |
-
$signed_to_api = $api->is_signed();
|
167 |
-
$ticketing_message = $api->get_sign_message();
|
168 |
-
$loader = $this->_registry->get( 'theme.loader' );
|
169 |
-
$account = $api->get_current_account();
|
170 |
-
$signup_args = array(
|
171 |
-
'api_signed' => $signed_to_api,
|
172 |
-
'signup_available' => $signup_available,
|
173 |
-
'title' => Ai1ec_I18n::__(
|
174 |
-
'Please, Sign In to Timely Network.'
|
175 |
-
),
|
176 |
-
'nonce' => array(
|
177 |
-
'action' => 'ai1ec_api_ticketing_signup',
|
178 |
-
'name' => 'ai1ec_api_ticketing_nonce',
|
179 |
-
'referrer' => false,
|
180 |
-
),
|
181 |
-
'api_action' =>
|
182 |
-
'?controller=front&action=ai1ec_api_ticketing_signup&plugin=' .
|
183 |
-
AI1EC_PLUGIN_NAME,
|
184 |
-
'required_text' => Ai1ec_I18n::__( 'This field is required.' ),
|
185 |
-
'register_text' => Ai1ec_I18n::__( 'Register' ),
|
186 |
-
'sign_in_text' => Ai1ec_I18n::__( 'Sign in' ),
|
187 |
-
'signed_in_text' => Ai1ec_I18n::__(
|
188 |
-
'You are signed in to <b>Timely Network</b> as ' . $account
|
189 |
-
),
|
190 |
-
'sign_out_text' => Ai1ec_I18n::__( 'Sign out' ),
|
191 |
-
'can_sign_out' => apply_filters( 'ai1ec_api_can_sign_out', true ),
|
192 |
-
'full_name_text' => Ai1ec_I18n::__( 'Full Name:' ),
|
193 |
-
'hide_form_text' => Ai1ec_I18n::__( 'Hide form' ),
|
194 |
-
'show_form_text' => Ai1ec_I18n::__( 'Show form' ),
|
195 |
-
'email_text' => Ai1ec_I18n::__( 'Email:' ),
|
196 |
-
'password_text' => Ai1ec_I18n::__( 'Password:' ),
|
197 |
-
'confirm_password_text' => Ai1ec_I18n::__( 'Confirm Password:' ),
|
198 |
-
'phone_number_text' => Ai1ec_I18n::__( 'Phone Number:' ),
|
199 |
-
'terms_text' => Ai1ec_I18n::__(
|
200 |
-
'I confirm that I have read, understand and agree with the <a href="https://time.ly/tos">terms of service</a>.'
|
201 |
-
),
|
202 |
-
'sign_out_warning' => Ai1ec_I18n::__(
|
203 |
-
'<h4>Attention Required:</h4>If you choose to sign-out of the API Timely Network this will close all the created tickets and remove user access to them. In this case, on the event page, users will see the status “Event closed”.'
|
204 |
-
),
|
205 |
-
'sign_out_cancel' => Ai1ec_I18n::__( 'Cancel' ),
|
206 |
-
'sign_out_confirm' => Ai1ec_I18n::__( 'Sign Out' ),
|
207 |
-
'sign_up_button_text' => Ai1ec_I18n::__( 'Sign Up' ),
|
208 |
-
'sign_in_button_text' => Ai1ec_I18n::__( 'Sign In' ),
|
209 |
-
'calendar_type_text' => Ai1ec_I18n::__( 'Calendar Type:' ),
|
210 |
-
'calendar_types' => array(
|
211 |
-
'tourism' => Ai1ec_I18n::__( 'Tourism' ),
|
212 |
-
'media' => Ai1ec_I18n::__( 'Media' ),
|
213 |
-
'community_hubs' => Ai1ec_I18n::__( 'Community Hubs' ),
|
214 |
-
'education' => Ai1ec_I18n::__( 'Education' ),
|
215 |
-
'venue_business' => Ai1ec_I18n::__( 'Venue/Business' ),
|
216 |
-
'artist_performer' => Ai1ec_I18n::__( 'Artist/Performer' ),
|
217 |
-
'church_spiritual' => Ai1ec_I18n::__( 'Church/Spiritual' ),
|
218 |
-
'association_group' => Ai1ec_I18n::__( 'Association/Group' ),
|
219 |
-
'other' => Ai1ec_I18n::__( 'Other' )
|
220 |
-
),
|
221 |
-
);
|
222 |
-
$loader->get_file( 'setting/api-signup.twig', $signup_args, true )->render();
|
223 |
-
|
224 |
-
|
225 |
-
$args = array(
|
226 |
-
'tabs' => $tabs,
|
227 |
-
'content_class' => 'ai1ec-form-horizontal',
|
228 |
-
'submit' => array(
|
229 |
-
'id' => 'ai1ec_save_settings',
|
230 |
-
'value' => '<i class="ai1ec-fa ai1ec-fa-save ai1ec-fa-fw"></i> ' .
|
231 |
-
Ai1ec_I18n::__( 'Save Settings' ),
|
232 |
-
'args' => array(
|
233 |
-
'class' => 'ai1ec-btn ai1ec-btn-primary ai1ec-btn-lg',
|
234 |
-
),
|
235 |
-
),
|
236 |
-
'pre_tabs_markup' => sprintf(
|
237 |
-
'<div class="ai1ec-gzip-causes-js-failure">' .
|
238 |
-
Ai1ec_I18n::__(
|
239 |
-
'If the form below is not working please follow <a href="%s">this link</a>.'
|
240 |
-
) .
|
241 |
-
'</div>',
|
242 |
-
wp_nonce_url(
|
243 |
-
add_query_arg( 'ai1ec_disable_gzip_compression', '1' ),
|
244 |
-
'ai1ec_disable_gzip_compression'
|
245 |
-
)
|
246 |
-
)
|
247 |
-
);
|
248 |
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
|
254 |
-
/**
|
255 |
-
* Based on the plugin options, decides what tabs to render.
|
256 |
-
*
|
257 |
-
*
|
258 |
-
*
|
259 |
-
* @param array $plugin_settings
|
260 |
-
* @param array $tabs
|
261 |
-
*
|
262 |
-
* @return array
|
263 |
-
*/
|
264 |
-
protected function _get_tabs_to_show( array $plugin_settings, array $tabs ) {
|
265 |
-
$index = 0;
|
266 |
-
$renderer = $this->_registry->get( 'html.element.setting-renderer' );
|
267 |
-
foreach ( $plugin_settings as $id => $setting ) {
|
268 |
-
// if the setting is shown
|
269 |
-
if ( isset ( $setting['renderer'] ) ) {
|
270 |
-
$tab_to_use = isset( $setting['renderer']['item'] ) ?
|
271 |
-
$setting['renderer']['item'] :
|
272 |
-
$setting['renderer']['tab'];
|
273 |
-
// check if it's the first one
|
274 |
-
if (
|
275 |
-
! isset ( $tabs[$tab_to_use]['elements'] )
|
276 |
-
) {
|
277 |
-
$tabs[$tab_to_use]['elements'] = array();
|
278 |
-
}
|
279 |
-
$setting['id'] = $id;
|
280 |
-
// render the settings
|
281 |
-
$weight = 10;
|
282 |
-
if ( isset( $setting['renderer']['weight'] ) ) {
|
283 |
-
$weight = (int)$setting['renderer']['weight'];
|
284 |
-
}
|
285 |
-
// NOTICE: do NOT change order of two first
|
286 |
-
// elements {weight,index}, otherwise sorting will fail.
|
287 |
-
$tabs[$tab_to_use]['elements'][] = array(
|
288 |
-
'weight' => $weight,
|
289 |
-
'index' => ++$index,
|
290 |
-
'html' => $renderer->render( $setting ),
|
291 |
-
);
|
292 |
-
// if the settings has an item tab, set the item as active.
|
293 |
-
if ( isset( $setting['renderer']['item'] ) ) {
|
294 |
-
if ( ! isset( $tabs[$setting['renderer']['tab']]['items_active'][$setting['renderer']['item']] ) ) {
|
295 |
-
$tabs[$setting['renderer']['tab']]['items_active'][$setting['renderer']['item']] = true;
|
296 |
-
}
|
297 |
-
}
|
298 |
-
}
|
299 |
-
}
|
300 |
-
$tabs_to_display = array();
|
301 |
-
// now let's see what tabs to display.
|
302 |
-
foreach ( $tabs as $name => $tab ) {
|
303 |
-
// sort by weights
|
304 |
-
if ( isset( $tab['elements'] ) ) {
|
305 |
-
asort( $tab['elements'] );
|
306 |
-
}
|
307 |
-
// if a tab has more than one item.
|
308 |
-
if ( isset( $tab['items'] ) ) {
|
309 |
-
// if no item is active, nothing is shown
|
310 |
-
if ( empty( $tab['items_active'] ) ) {
|
311 |
-
continue;
|
312 |
-
}
|
313 |
-
// if only one item is active, do not use the dropdown
|
314 |
-
if ( count( $tab['items_active'] ) === 1 ) {
|
315 |
-
$name = key($tab['items_active']);
|
316 |
-
$tab['name'] = $tab['items'][$name];
|
317 |
-
unset ( $tab['items'] );
|
318 |
-
} else {
|
319 |
-
// check active items for the dropdown
|
320 |
-
foreach ( $tab['items'] as $item => $longname ) {
|
321 |
-
if ( ! isset( $tab['items_active'][$item] ) ) {
|
322 |
-
unset( $tab['items'][$item] );
|
323 |
-
}
|
324 |
-
}
|
325 |
-
}
|
326 |
-
// lets make a check to avoid overriding tabs
|
327 |
-
if ( ! isset( $tabs_to_display[$name] ) ) {
|
328 |
-
$tabs_to_display[$name] = $tab;
|
329 |
-
} else {
|
330 |
-
$tabs_to_display[$name]['elements'] = $tab['elements'];
|
331 |
-
}
|
332 |
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
|
348 |
}
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_Settings extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string The nonce action
|
16 |
+
*/
|
17 |
+
CONST NONCE_ACTION = 'ai1ec_settings_save';
|
18 |
|
19 |
+
/**
|
20 |
+
* @var string The nonce name
|
21 |
+
*/
|
22 |
+
CONST NONCE_NAME = 'ai1ec_settings_nonce';
|
23 |
|
24 |
+
/* (non-PHPdoc)
|
25 |
+
* @see Ai1ec_View_Admin_Abstract::display_page()
|
26 |
+
*/
|
27 |
+
public function display_page() {
|
28 |
+
$settings = $this->_registry->get( 'model.settings' );
|
29 |
+
$args = array(
|
30 |
+
'title' => Ai1ec_I18n::__(
|
31 |
+
'All-in-One Event Calendar: Settings'
|
32 |
+
),
|
33 |
+
'nonce' => array(
|
34 |
+
'action' => self::NONCE_ACTION,
|
35 |
+
'name' => self::NONCE_NAME,
|
36 |
+
'referrer' => false,
|
37 |
+
),
|
38 |
+
'metabox' => array(
|
39 |
+
'screen' => $settings->get( 'settings_page' ),
|
40 |
+
'action' => 'left',
|
41 |
+
'object' => null
|
42 |
+
),
|
43 |
+
'support' => array(
|
44 |
+
'screen' => $settings->get( 'settings_page' ),
|
45 |
+
'action' => 'right',
|
46 |
+
'object' => null
|
47 |
+
),
|
48 |
+
'action' =>
|
49 |
+
ai1ec_admin_url(
|
50 |
+
'?controller=front&action=ai1ec_save_settings&plugin=' .
|
51 |
+
AI1EC_PLUGIN_NAME
|
52 |
+
),
|
53 |
+
);
|
54 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
55 |
+
$file = $loader->get_file( 'setting/page.twig', $args, true );
|
56 |
+
$file->render();
|
57 |
+
if ( apply_filters( 'ai1ec_robots_install', true ) ) {
|
58 |
+
$this->_registry->get( 'robots.helper' )->install();
|
59 |
+
}
|
60 |
+
}
|
61 |
|
62 |
+
/* (non-PHPdoc)
|
63 |
+
* @see Ai1ec_View_Admin_Abstract::add_page()
|
64 |
+
*/
|
65 |
+
public function add_page() {
|
66 |
+
$settings_page = add_submenu_page(
|
67 |
+
AI1EC_ADMIN_BASE_URL,
|
68 |
+
Ai1ec_I18n::__( 'Settings' ),
|
69 |
+
Ai1ec_I18n::__( 'Settings' ),
|
70 |
+
'manage_ai1ec_options',
|
71 |
+
AI1EC_PLUGIN_NAME . '-settings',
|
72 |
+
array( $this, 'display_page' )
|
73 |
+
);
|
74 |
+
$this->_registry->get( 'model.settings' )
|
75 |
+
->set( 'settings_page', $settings_page );
|
76 |
+
}
|
77 |
|
78 |
+
/**
|
79 |
+
* Adds metabox to the page.
|
80 |
+
*
|
81 |
+
* @wp_hook admin_init
|
82 |
+
*
|
83 |
+
* @return void
|
84 |
+
*/
|
85 |
+
public function add_meta_box() {
|
86 |
+
// Add the 'General Settings' meta box.
|
87 |
+
add_meta_box(
|
88 |
+
'ai1ec-general-settings',
|
89 |
+
Ai1ec_I18n::_x( 'General Settings', 'meta box' ),
|
90 |
+
array( $this, 'display_meta_box' ),
|
91 |
+
$this->_registry->get( 'model.settings' )->get( 'settings_page' ),
|
92 |
+
'left',
|
93 |
+
'default'
|
94 |
+
);
|
95 |
+
// Add the 'Timely' meta box.
|
96 |
+
add_meta_box(
|
97 |
+
'ai1ec-support',
|
98 |
+
Ai1ec_I18n::_x( 'Timely', 'meta box', AI1EC_PLUGIN_NAME ),
|
99 |
+
array( $this, 'support_meta_box' ),
|
100 |
+
$this->_registry->get( 'model.settings' )->get( 'settings_page' ),
|
101 |
+
'right',
|
102 |
+
'default'
|
103 |
+
);
|
104 |
+
}
|
105 |
|
106 |
+
/**
|
107 |
+
* Renders the Timely blog meta box
|
108 |
+
*
|
109 |
+
* @param mixed $object
|
110 |
+
* @param mixed $box
|
111 |
+
*/
|
112 |
+
public function support_meta_box( $object, $box ) {
|
113 |
+
$newsItems = $this->_registry->get( 'news.feed' )->import_feed();
|
114 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
115 |
+
$file = $loader->get_file(
|
116 |
+
'box_support.php',
|
117 |
+
array(
|
118 |
+
'news' => $newsItems,
|
119 |
+
),
|
120 |
+
true
|
121 |
+
);
|
122 |
+
$file->render();
|
123 |
+
}
|
124 |
|
125 |
+
/* (non-PHPdoc)
|
126 |
+
* @see Ai1ec_View_Admin_Abstract::handle_post()
|
127 |
+
*/
|
128 |
+
public function handle_post() {
|
129 |
+
}
|
130 |
|
131 |
+
/**
|
132 |
+
* Displays the meta box for the settings page.
|
133 |
+
*
|
134 |
+
* @param mixed $object
|
135 |
+
* @param mixed $box
|
136 |
+
*/
|
137 |
+
public function display_meta_box( $object, $box ) {
|
138 |
+
$tabs = array(
|
139 |
+
'viewing-events' => array(
|
140 |
+
'name' => Ai1ec_I18n::__( 'Viewing Events' ),
|
141 |
+
),
|
142 |
+
'editing-events' => array(
|
143 |
+
'name' => Ai1ec_I18n::__( 'Adding/Editing Events' ),
|
144 |
+
),
|
145 |
+
'advanced' => array(
|
146 |
+
'name' => Ai1ec_I18n::__( 'Advanced' ),
|
147 |
+
'items' => array(
|
148 |
+
'advanced' => Ai1ec_I18n::__( 'Advanced Settings' ),
|
149 |
+
'embedded-views' => Ai1ec_I18n::__( 'Shortcodes' ),
|
150 |
+
'email' => Ai1ec_I18n::__( 'Email Templates' ),
|
151 |
+
'apis' => Ai1ec_I18n::__( 'External Services' ),
|
152 |
+
'cache' => Ai1ec_I18n::__( 'Cache Report' ),
|
153 |
+
)
|
154 |
+
),
|
155 |
+
);
|
156 |
|
157 |
+
// let other extensions add tabs.
|
158 |
+
$tabs = apply_filters( 'ai1ec_add_setting_tabs', $tabs );
|
159 |
+
$settings = $this->_registry->get( 'model.settings' );
|
160 |
+
$plugin_settings = $settings->get_options();
|
161 |
+
$tabs = $this->_get_tabs_to_show( $plugin_settings, $tabs );
|
162 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
|
164 |
+
$api = $this->_registry->get( 'model.api.api-registration' );
|
165 |
+
$signup_available = $api->is_api_sign_up_available();
|
166 |
+
$signed_to_api = $api->is_signed();
|
167 |
+
$ticketing_message = $api->get_sign_message();
|
168 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
169 |
+
$account = $api->get_current_account();
|
170 |
+
$signup_args = array(
|
171 |
+
'api_signed' => $signed_to_api,
|
172 |
+
'signup_available' => $signup_available,
|
173 |
+
'title' => Ai1ec_I18n::__(
|
174 |
+
'Please, Sign In to Timely Network.'
|
175 |
+
),
|
176 |
+
'nonce' => array(
|
177 |
+
'action' => 'ai1ec_api_ticketing_signup',
|
178 |
+
'name' => 'ai1ec_api_ticketing_nonce',
|
179 |
+
'referrer' => false,
|
180 |
+
),
|
181 |
+
'api_action' =>
|
182 |
+
'?controller=front&action=ai1ec_api_ticketing_signup&plugin=' .
|
183 |
+
AI1EC_PLUGIN_NAME,
|
184 |
+
'required_text' => Ai1ec_I18n::__( 'This field is required.' ),
|
185 |
+
'register_text' => Ai1ec_I18n::__( 'Register' ),
|
186 |
+
'sign_in_text' => Ai1ec_I18n::__( 'Sign in' ),
|
187 |
+
'signed_in_text' => Ai1ec_I18n::__(
|
188 |
+
'You are signed in to <b>Timely Network</b> as ' . $account
|
189 |
+
),
|
190 |
+
'sign_out_text' => Ai1ec_I18n::__( 'Sign out' ),
|
191 |
+
'can_sign_out' => apply_filters( 'ai1ec_api_can_sign_out', true ),
|
192 |
+
'full_name_text' => Ai1ec_I18n::__( 'Full Name:' ),
|
193 |
+
'hide_form_text' => Ai1ec_I18n::__( 'Hide form' ),
|
194 |
+
'show_form_text' => Ai1ec_I18n::__( 'Show form' ),
|
195 |
+
'email_text' => Ai1ec_I18n::__( 'Email:' ),
|
196 |
+
'password_text' => Ai1ec_I18n::__( 'Password:' ),
|
197 |
+
'confirm_password_text' => Ai1ec_I18n::__( 'Confirm Password:' ),
|
198 |
+
'phone_number_text' => Ai1ec_I18n::__( 'Phone Number:' ),
|
199 |
+
'terms_text' => Ai1ec_I18n::__(
|
200 |
+
'I confirm that I have read, understand and agree with the <a href="https://time.ly/tos">terms of service</a>.'
|
201 |
+
),
|
202 |
+
'sign_out_warning' => Ai1ec_I18n::__(
|
203 |
+
'<h4>Attention Required:</h4>If you choose to sign-out of the API Timely Network this will close all the created tickets and remove user access to them. In this case, on the event page, users will see the status “Event closed”.'
|
204 |
+
),
|
205 |
+
'sign_out_cancel' => Ai1ec_I18n::__( 'Cancel' ),
|
206 |
+
'sign_out_confirm' => Ai1ec_I18n::__( 'Sign Out' ),
|
207 |
+
'sign_up_button_text' => Ai1ec_I18n::__( 'Sign Up' ),
|
208 |
+
'sign_in_button_text' => Ai1ec_I18n::__( 'Sign In' ),
|
209 |
+
'calendar_type_text' => Ai1ec_I18n::__( 'Calendar Type:' ),
|
210 |
+
'calendar_types' => array(
|
211 |
+
'tourism' => Ai1ec_I18n::__( 'Tourism' ),
|
212 |
+
'media' => Ai1ec_I18n::__( 'Media' ),
|
213 |
+
'community_hubs' => Ai1ec_I18n::__( 'Community Hubs' ),
|
214 |
+
'education' => Ai1ec_I18n::__( 'Education' ),
|
215 |
+
'venue_business' => Ai1ec_I18n::__( 'Venue/Business' ),
|
216 |
+
'artist_performer' => Ai1ec_I18n::__( 'Artist/Performer' ),
|
217 |
+
'church_spiritual' => Ai1ec_I18n::__( 'Church/Spiritual' ),
|
218 |
+
'association_group' => Ai1ec_I18n::__( 'Association/Group' ),
|
219 |
+
'other' => Ai1ec_I18n::__( 'Other' )
|
220 |
+
),
|
221 |
+
);
|
222 |
+
$loader->get_file( 'setting/api-signup.twig', $signup_args, true )->render();
|
223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
|
225 |
+
$args = array(
|
226 |
+
'tabs' => $tabs,
|
227 |
+
'content_class' => 'ai1ec-form-horizontal',
|
228 |
+
'submit' => array(
|
229 |
+
'id' => 'ai1ec_save_settings',
|
230 |
+
'value' => '<i class="ai1ec-fa ai1ec-fa-save ai1ec-fa-fw"></i> ' .
|
231 |
+
Ai1ec_I18n::__( 'Save Settings' ),
|
232 |
+
'args' => array(
|
233 |
+
'class' => 'ai1ec-btn ai1ec-btn-primary ai1ec-btn-lg',
|
234 |
+
),
|
235 |
+
),
|
236 |
+
'pre_tabs_markup' => sprintf(
|
237 |
+
'<div class="ai1ec-gzip-causes-js-failure">' .
|
238 |
+
Ai1ec_I18n::__(
|
239 |
+
'If the form below is not working please follow <a href="%s">this link</a>.'
|
240 |
+
) .
|
241 |
+
'</div>',
|
242 |
+
wp_nonce_url(
|
243 |
+
add_query_arg( 'ai1ec_disable_gzip_compression', '1' ),
|
244 |
+
'ai1ec_disable_gzip_compression'
|
245 |
+
)
|
246 |
+
)
|
247 |
+
);
|
248 |
+
|
249 |
+
$file = $loader->get_file( 'setting/bootstrap_tabs.twig', $args, true );
|
250 |
+
$file->render();
|
251 |
+
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Based on the plugin options, decides what tabs to render.
|
256 |
+
*
|
257 |
+
*
|
258 |
+
*
|
259 |
+
* @param array $plugin_settings
|
260 |
+
* @param array $tabs
|
261 |
+
*
|
262 |
+
* @return array
|
263 |
+
*/
|
264 |
+
protected function _get_tabs_to_show( array $plugin_settings, array $tabs ) {
|
265 |
+
$index = 0;
|
266 |
+
$renderer = $this->_registry->get( 'html.element.setting-renderer' );
|
267 |
+
foreach ( $plugin_settings as $id => $setting ) {
|
268 |
+
// if the setting is shown
|
269 |
+
if ( isset ( $setting['renderer'] ) ) {
|
270 |
+
$tab_to_use = isset( $setting['renderer']['item'] ) ?
|
271 |
+
$setting['renderer']['item'] :
|
272 |
+
$setting['renderer']['tab'];
|
273 |
+
// check if it's the first one
|
274 |
+
if (
|
275 |
+
! isset ( $tabs[$tab_to_use]['elements'] )
|
276 |
+
) {
|
277 |
+
$tabs[$tab_to_use]['elements'] = array();
|
278 |
+
}
|
279 |
+
$setting['id'] = $id;
|
280 |
+
// render the settings
|
281 |
+
$weight = 10;
|
282 |
+
if ( isset( $setting['renderer']['weight'] ) ) {
|
283 |
+
$weight = (int)$setting['renderer']['weight'];
|
284 |
+
}
|
285 |
+
// NOTICE: do NOT change order of two first
|
286 |
+
// elements {weight,index}, otherwise sorting will fail.
|
287 |
+
$tabs[$tab_to_use]['elements'][] = array(
|
288 |
+
'weight' => $weight,
|
289 |
+
'index' => ++$index,
|
290 |
+
'html' => $renderer->render( $setting ),
|
291 |
+
);
|
292 |
+
// if the settings has an item tab, set the item as active.
|
293 |
+
if ( isset( $setting['renderer']['item'] ) ) {
|
294 |
+
if ( ! isset( $tabs[$setting['renderer']['tab']]['items_active'][$setting['renderer']['item']] ) ) {
|
295 |
+
$tabs[$setting['renderer']['tab']]['items_active'][$setting['renderer']['item']] = true;
|
296 |
+
}
|
297 |
+
}
|
298 |
+
}
|
299 |
+
}
|
300 |
+
$tabs_to_display = array();
|
301 |
+
// now let's see what tabs to display.
|
302 |
+
foreach ( $tabs as $name => $tab ) {
|
303 |
+
// sort by weights
|
304 |
+
if ( isset( $tab['elements'] ) ) {
|
305 |
+
asort( $tab['elements'] );
|
306 |
+
}
|
307 |
+
// if a tab has more than one item.
|
308 |
+
if ( isset( $tab['items'] ) ) {
|
309 |
+
// if no item is active, nothing is shown
|
310 |
+
if ( empty( $tab['items_active'] ) ) {
|
311 |
+
continue;
|
312 |
+
}
|
313 |
+
// if only one item is active, do not use the dropdown
|
314 |
+
if ( count( $tab['items_active'] ) === 1 ) {
|
315 |
+
$name = key($tab['items_active']);
|
316 |
+
$tab['name'] = $tab['items'][$name];
|
317 |
+
unset ( $tab['items'] );
|
318 |
+
} else {
|
319 |
+
// check active items for the dropdown
|
320 |
+
foreach ( $tab['items'] as $item => $longname ) {
|
321 |
+
if ( ! isset( $tab['items_active'][$item] ) ) {
|
322 |
+
unset( $tab['items'][$item] );
|
323 |
+
}
|
324 |
+
}
|
325 |
+
}
|
326 |
+
// lets make a check to avoid overriding tabs
|
327 |
+
if ( ! isset( $tabs_to_display[$name] ) ) {
|
328 |
+
$tabs_to_display[$name] = $tab;
|
329 |
+
} else {
|
330 |
+
$tabs_to_display[$name]['elements'] = $tab['elements'];
|
331 |
+
}
|
332 |
+
|
333 |
+
} else {
|
334 |
+
// no items, just check for any element to display.
|
335 |
+
if ( isset( $tab['elements'] ) ) {
|
336 |
+
// lets make a check to avoid overriding tabs
|
337 |
+
if ( ! isset( $tabs_to_display[$name] ) ) {
|
338 |
+
$tabs_to_display[$name] = $tab;
|
339 |
+
} else {
|
340 |
+
$tabs_to_display[$name]['elements'] = $tab['elements'];
|
341 |
+
}
|
342 |
+
}
|
343 |
+
}
|
344 |
+
}
|
345 |
+
return $tabs_to_display;
|
346 |
+
}
|
347 |
|
348 |
}
|
app/view/admin/theme-options.php
CHANGED
@@ -11,214 +11,214 @@
|
|
11 |
*/
|
12 |
class Ai1ec_View_Theme_Options extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
}
|
11 |
*/
|
12 |
class Ai1ec_View_Theme_Options extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string The nonce action
|
16 |
+
*/
|
17 |
+
const NONCE_ACTION = 'ai1ec_theme_options_save';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var string The nonce name
|
21 |
+
*/
|
22 |
+
const NONCE_NAME = 'ai1ec_theme_options_nonce';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var string The id/name of the submit button.
|
26 |
+
*/
|
27 |
+
const SUBMIT_ID = 'ai1ec_save_themes_options';
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var string The id/name of the Reset button.
|
31 |
+
*/
|
32 |
+
const RESET_ID = 'ai1ec_reset_themes_options';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
public $title;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var string
|
41 |
+
*/
|
42 |
+
public $meta_box_id;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Adds the page to the correct menu.
|
46 |
+
*/
|
47 |
+
public function add_page() {
|
48 |
+
$theme_options_page = add_submenu_page(
|
49 |
+
AI1EC_ADMIN_BASE_URL,
|
50 |
+
Ai1ec_I18n::__( 'Theme Options' ),
|
51 |
+
Ai1ec_I18n::__( 'Theme Options' ),
|
52 |
+
'manage_ai1ec_options',
|
53 |
+
AI1EC_PLUGIN_NAME . '-edit-css',
|
54 |
+
array( $this, 'display_page' )
|
55 |
+
);
|
56 |
+
$settings = $this->_registry->get( 'model.settings' );
|
57 |
+
if ( false !== $settings->get( 'less_variables_page' ) ) {
|
58 |
+
// Make copy of Theme Options page at its old location.
|
59 |
+
$submenu['themes.php'][] = array(
|
60 |
+
Ai1ec_I18n::__( 'Calendar Theme Options' ),
|
61 |
+
'manage_ai1ec_options',
|
62 |
+
AI1EC_THEME_OPTIONS_BASE_URL,
|
63 |
+
);
|
64 |
+
};
|
65 |
+
$settings->set( 'less_variables_page', $theme_options_page );
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Add meta box for page.
|
70 |
+
*
|
71 |
+
* @wp_hook admin_init
|
72 |
+
*
|
73 |
+
* @return void
|
74 |
+
*/
|
75 |
+
public function add_meta_box() {
|
76 |
+
// Add the 'General Settings' meta box.
|
77 |
+
add_meta_box(
|
78 |
+
'ai1ec-less-variables-tabs',
|
79 |
+
Ai1ec_I18n::_x( 'Calendar Theme Options', 'meta box' ),
|
80 |
+
array( $this, 'display_meta_box' ),
|
81 |
+
$this->_registry->get( 'model.settings' )
|
82 |
+
->get( 'less_variables_page' ),
|
83 |
+
'left',
|
84 |
+
'default'
|
85 |
+
);
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Display the page html
|
90 |
+
*/
|
91 |
+
public function display_page() {
|
92 |
+
|
93 |
+
$settings = $this->_registry->get( 'model.settings' );
|
94 |
+
|
95 |
+
$args = array(
|
96 |
+
'title' => Ai1ec_I18n::__(
|
97 |
+
'Calendar Theme Options'
|
98 |
+
),
|
99 |
+
'nonce' => array(
|
100 |
+
'action' => self::NONCE_ACTION,
|
101 |
+
'name' => self::NONCE_NAME,
|
102 |
+
'referrer' => false,
|
103 |
+
),
|
104 |
+
'metabox' => array(
|
105 |
+
'screen' => $settings->get( 'themes_option_page' ),
|
106 |
+
'action' => 'left',
|
107 |
+
'object' => null
|
108 |
+
),
|
109 |
+
'action' =>
|
110 |
+
'?controller=front&action=ai1ec_save_theme_options&plugin=' . AI1EC_PLUGIN_NAME
|
111 |
+
);
|
112 |
+
|
113 |
+
$frontend = $this->_registry->get( 'css.frontend' );
|
114 |
+
|
115 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
116 |
+
|
117 |
+
$file = $loader->get_file( 'theme-options/page.twig', $args, true );
|
118 |
+
|
119 |
+
return $file->render();
|
120 |
+
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Displays the meta box for the settings page.
|
125 |
+
*
|
126 |
+
* @param mixed $object
|
127 |
+
* @param mixed $box
|
128 |
+
*/
|
129 |
+
public function display_meta_box( $object, $box ) {
|
130 |
+
|
131 |
+
$tabs = array(
|
132 |
+
'general' => array(
|
133 |
+
'name' => Ai1ec_I18n::__( 'General' ),
|
134 |
+
),
|
135 |
+
'table' => array(
|
136 |
+
'name' => Ai1ec_I18n::__( 'Tables' ),
|
137 |
+
),
|
138 |
+
'buttons' => array(
|
139 |
+
'name' => Ai1ec_I18n::__( 'Buttons' ),
|
140 |
+
),
|
141 |
+
'forms' => array(
|
142 |
+
'name' => Ai1ec_I18n::__( 'Forms' ),
|
143 |
+
),
|
144 |
+
'calendar' => array(
|
145 |
+
'name' => Ai1ec_I18n::__( 'Calendar general' ),
|
146 |
+
),
|
147 |
+
'month' => array(
|
148 |
+
'name' => Ai1ec_I18n::__( 'Month/week/day view' ),
|
149 |
+
),
|
150 |
+
'agenda' => array(
|
151 |
+
'name' => Ai1ec_I18n::__( 'Agenda view' ),
|
152 |
+
),
|
153 |
+
);
|
154 |
+
|
155 |
+
$tabs = apply_filters( 'ai1ec_less_variables_tabs', $tabs );
|
156 |
+
|
157 |
+
$less_variables = $this->_registry
|
158 |
+
->get( 'less.lessphp' )->get_saved_variables();
|
159 |
+
$tabs = $this->_get_tabs_to_show( $less_variables, $tabs );
|
160 |
+
|
161 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
162 |
+
$args = array(
|
163 |
+
'stacked' => true,
|
164 |
+
'content_class' => 'ai1ec-form-horizontal',
|
165 |
+
'tabs' => $tabs,
|
166 |
+
'submit' => array(
|
167 |
+
'id' => self::SUBMIT_ID,
|
168 |
+
'value' => '<i class="ai1ec-fa ai1ec-fa-save ai1ec-fa-fw"></i> ' .
|
169 |
+
Ai1ec_I18n::__( 'Save Options' ),
|
170 |
+
'args' => array(
|
171 |
+
'class' => 'ai1ec-btn ai1ec-btn-primary ai1ec-btn-lg',
|
172 |
+
),
|
173 |
+
),
|
174 |
+
'reset' => array(
|
175 |
+
'id' => self::RESET_ID,
|
176 |
+
'value' => '<i class="ai1ec-fa ai1ec-fa-undo ai1ec-fa-fw"></i> ' .
|
177 |
+
Ai1ec_I18n::__( 'Reset to Defaults' ),
|
178 |
+
'args' => array(
|
179 |
+
'class' => 'ai1ec-btn ai1ec-btn-danger ai1ec-btn-lg',
|
180 |
+
),
|
181 |
+
),
|
182 |
+
);
|
183 |
+
$file = $loader->get_file( 'theme-options/bootstrap_tabs.twig', $args, true );
|
184 |
+
$file->render();
|
185 |
+
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Return the theme options tabs
|
190 |
+
*
|
191 |
+
* @param array $less_variables
|
192 |
+
* @param array $tabs list of tabs
|
193 |
+
*
|
194 |
+
* @return array the array of tabs to display
|
195 |
+
*/
|
196 |
+
protected function _get_tabs_to_show( array $less_variables, array $tabs) {
|
197 |
+
|
198 |
+
// Inizialize the array of tabs that will be added to the layout
|
199 |
+
$bootstrap_tabs_to_add = array();
|
200 |
+
|
201 |
+
foreach( $tabs as $id => $tab ){
|
202 |
+
$tab['elements'] = array();
|
203 |
+
$bootstrap_tabs_to_add[$id] = $tab;
|
204 |
+
}
|
205 |
+
foreach ( $less_variables as $variable_id => $variable_attributes ) {
|
206 |
+
$variable_attributes['id'] = $variable_id;
|
207 |
+
$renderable = $this->_registry->get(
|
208 |
+
'less.variable.' . $variable_attributes['type'],
|
209 |
+
$variable_attributes
|
210 |
+
);
|
211 |
+
$bootstrap_tabs_to_add[$variable_attributes['tab']]['elements'][] = array(
|
212 |
+
'html' => $renderable->render()
|
213 |
+
);
|
214 |
+
}
|
215 |
+
return $bootstrap_tabs_to_add;
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Handle post, likely to be deprecated to use commands.
|
220 |
+
*/
|
221 |
+
public function handle_post() {
|
222 |
+
|
223 |
+
}
|
224 |
}
|
app/view/admin/theme-switching.php
CHANGED
@@ -11,58 +11,58 @@
|
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_Theme_Switching extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
|
23 |
-
|
24 |
-
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
|
62 |
-
|
63 |
-
|
64 |
|
65 |
-
|
66 |
-
|
67 |
|
68 |
}
|
11 |
*/
|
12 |
class Ai1ec_View_Admin_Theme_Switching extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
+
/* (non-PHPdoc)
|
15 |
+
* @see Ai1ec_View_Admin_Abstract::display_page()
|
16 |
+
*/
|
17 |
+
public function display_page() {
|
18 |
+
global $ct;
|
19 |
+
// defaults
|
20 |
+
$activated = isset( $_GET['activated'] ) ? true : false;
|
21 |
+
$deleted = false;
|
22 |
|
23 |
+
$_list_table = $this->_registry->get( 'theme.list' );
|
24 |
+
$_list_table->prepare_items();
|
25 |
|
26 |
+
$args = array(
|
27 |
+
'activated' => $activated,
|
28 |
+
'deleted' => $deleted,
|
29 |
+
'ct' => $ct,
|
30 |
+
'wp_list_table' => $_list_table,
|
31 |
+
'page_title' => Ai1ec_I18n::__(
|
32 |
+
'All-in-One Event Calendar: Themes'
|
33 |
+
),
|
34 |
+
);
|
35 |
|
36 |
+
add_thickbox();
|
37 |
+
wp_enqueue_script( 'theme-preview' );
|
38 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
39 |
|
40 |
+
$file = $loader->get_file( 'themes.php', $args, true );
|
41 |
+
return $file->render();
|
42 |
+
}
|
43 |
|
44 |
+
/* (non-PHPdoc)
|
45 |
+
* @see Ai1ec_View_Admin_Abstract::add_page()
|
46 |
+
*/
|
47 |
+
public function add_page() {
|
48 |
+
global $submenu;
|
49 |
+
// ===============
|
50 |
+
// = Themes Page =
|
51 |
+
// ===============
|
52 |
+
$themes_page = add_submenu_page(
|
53 |
+
AI1EC_ADMIN_BASE_URL,
|
54 |
+
Ai1ec_I18n::__( 'Calendar Themes' ),
|
55 |
+
Ai1ec_I18n::__( 'Calendar Themes' ),
|
56 |
+
'switch_ai1ec_themes',
|
57 |
+
AI1EC_PLUGIN_NAME . '-themes',
|
58 |
+
array( $this, 'display_page' )
|
59 |
+
);
|
60 |
+
}
|
61 |
|
62 |
+
public function add_meta_box() {
|
63 |
+
}
|
64 |
|
65 |
+
public function handle_post() {
|
66 |
+
}
|
67 |
|
68 |
}
|
app/view/admin/tickets.php
CHANGED
@@ -11,184 +11,184 @@
|
|
11 |
*/
|
12 |
class Ai1ec_View_Tickets extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
|
194 |
}
|
11 |
*/
|
12 |
class Ai1ec_View_Tickets extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string The nonce action
|
16 |
+
*/
|
17 |
+
const NONCE_ACTION = 'ai1ec_api_ticketing_signup';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var string The nonce name
|
21 |
+
*/
|
22 |
+
const NONCE_NAME = 'ai1ec_api_ticketing_nonce';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var string The id/name of the submit button.
|
26 |
+
*/
|
27 |
+
const SUBMIT_ID = 'ai1ec_api_ticketing_signup';
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Adds the page to the correct menu.
|
31 |
+
*/
|
32 |
+
public function add_page() {
|
33 |
+
add_submenu_page(
|
34 |
+
AI1EC_ADMIN_BASE_URL,
|
35 |
+
__( 'Ticketing', AI1EC_PLUGIN_NAME ),
|
36 |
+
__( 'Ticketing', AI1EC_PLUGIN_NAME ),
|
37 |
+
'manage_ai1ec_feeds',
|
38 |
+
AI1EC_PLUGIN_NAME . '-tickets',
|
39 |
+
array( $this, 'display_page' )
|
40 |
+
);
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Add meta box for page.
|
45 |
+
*
|
46 |
+
* @wp_hook admin_init
|
47 |
+
*
|
48 |
+
* @return void
|
49 |
+
*/
|
50 |
+
public function add_meta_box() {}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Display the page html
|
54 |
+
*/
|
55 |
+
public function display_page() {
|
56 |
+
|
57 |
+
$signed_to_api = $this->_api_registration->is_signed();
|
58 |
+
$signup_available = $this->_api_registration->is_api_sign_up_available();
|
59 |
+
$ticketing_available = $this->_api_registration->is_ticket_available();
|
60 |
+
$ticketing_enabled = $this->_api_registration->has_subscription_active( Ai1ec_Api_Features::CODE_TICKETING );
|
61 |
+
$ticketing_message = $this->_api_registration->get_sign_message();
|
62 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
63 |
+
|
64 |
+
if ( ! $signed_to_api ) {
|
65 |
+
|
66 |
+
if ( false === ai1ec_is_blank( $ticketing_message ) ) {
|
67 |
+
$this->_api_registration->clear_sign_message();
|
68 |
+
}
|
69 |
+
|
70 |
+
$args = array(
|
71 |
+
'title' => Ai1ec_I18n::__(
|
72 |
+
'Time.ly Ticketing'
|
73 |
+
),
|
74 |
+
'sign_up_text' => 'Please, <a href="edit.php?post_type=ai1ec_event&page=all-in-one-event-calendar-settings">Sign Up for a Timely Network account</a> to use Ticketing or Import Feeds.',
|
75 |
+
'signup_form' => Ai1ec_I18n::__( 'You need to sign up for a Timely Network account in order to use Ticketing or Import Feeds<br /><br />' ) .
|
76 |
+
(
|
77 |
+
$signup_available
|
78 |
+
? Ai1ec_I18n::__( '<a href="edit.php?post_type=ai1ec_event&page=all-in-one-event-calendar-settings" class="ai1ec-btn ai1ec-btn-primary ai1ec-btn-lg">Sign In to Timely Network</a>' )
|
79 |
+
: Ai1ec_I18n::__( '<b>Signing up for a Timely Network account is currently unavailable. Please, try again later.</b>' )
|
80 |
+
)
|
81 |
+
|
82 |
+
);
|
83 |
+
$file = $loader->get_file( 'ticketing/signup.twig', $args, true );
|
84 |
+
} elseif ( ! $ticketing_available ) {
|
85 |
+
$args = array(
|
86 |
+
'title' => Ai1ec_I18n::__(
|
87 |
+
'Time.ly Ticketing'
|
88 |
+
),
|
89 |
+
'sign_up_text' => '',
|
90 |
+
'signup_form' => 'Ticketing is currently not available for this website. Please, try again later.'
|
91 |
+
|
92 |
+
);
|
93 |
+
$file = $loader->get_file( 'ticketing/signup.twig', $args, true );
|
94 |
+
} elseif ( ! $ticketing_enabled ) {
|
95 |
+
$args = array(
|
96 |
+
'title' => Ai1ec_I18n::__(
|
97 |
+
'Time.ly Ticketing'
|
98 |
+
),
|
99 |
+
'sign_up_text' => '',
|
100 |
+
'signup_form' => 'Timely Ticketing saves time & money. Create ticketing/registration right here and now. You do not pay any ticketing fees (other than regular PayPal transaction costs). Create as many ticketing/registration as you\'d like.<br /><br />Ticketing feature is not enabled for this website. Please sign up for Ticketing plan <a href="https://time.ly/tickets-existing-users/" target="_blank">here</a>.'
|
101 |
+
);
|
102 |
+
$file = $loader->get_file( 'ticketing/signup.twig', $args, true );
|
103 |
+
} else {
|
104 |
+
$response = $this->_api_registration->get_payment_preferences();
|
105 |
+
$purchases = $this->_api_registration->get_purchases();
|
106 |
+
$args = array(
|
107 |
+
'title' => Ai1ec_I18n::__(
|
108 |
+
'Time.ly Ticketing'
|
109 |
+
),
|
110 |
+
'settings_text' => Ai1ec_I18n::__( 'Settings' ),
|
111 |
+
'sales_text' => Ai1ec_I18n::__( 'Sales' ),
|
112 |
+
'select_payment_text' => Ai1ec_I18n::__( 'Please provide your PayPal details.' ),
|
113 |
+
'cheque_text' => Ai1ec_I18n::__( 'Cheque' ),
|
114 |
+
'paypal_text' => Ai1ec_I18n::__( 'PayPal' ),
|
115 |
+
'currency_text' => Ai1ec_I18n::__( 'Preferred currency for tickets:' ),
|
116 |
+
'required_text' => Ai1ec_I18n::__( 'This field is required.' ),
|
117 |
+
'save_changes_text' => Ai1ec_I18n::__( 'Save Changes' ),
|
118 |
+
'date_text' => Ai1ec_I18n::__( 'Date' ),
|
119 |
+
'event_text' => Ai1ec_I18n::__( 'Event' ),
|
120 |
+
'purchaser_text' => Ai1ec_I18n::__( 'Purchaser' ),
|
121 |
+
'tickets_text' => Ai1ec_I18n::__( 'Tickets' ),
|
122 |
+
'email_text' => Ai1ec_I18n::__( 'Email' ),
|
123 |
+
'status_text' => Ai1ec_I18n::__( 'Status' ),
|
124 |
+
'total_text' => Ai1ec_I18n::__( 'Total' ),
|
125 |
+
'sign_out_button_text' => Ai1ec_I18n::__( 'Sign Out' ),
|
126 |
+
'payment_method' => $response->payment_method,
|
127 |
+
'paypal_email' => $response->paypal_email,
|
128 |
+
'first_name' => $response->first_name,
|
129 |
+
'last_name' => $response->last_name,
|
130 |
+
'currency' => $response->currency,
|
131 |
+
'nonce' => array(
|
132 |
+
'action' => self::NONCE_ACTION,
|
133 |
+
'name' => self::NONCE_NAME,
|
134 |
+
'referrer' => false,
|
135 |
+
),
|
136 |
+
'action' =>
|
137 |
+
'?controller=front&action=ai1ec_api_ticketing_signup&plugin=' .
|
138 |
+
AI1EC_PLUGIN_NAME,
|
139 |
+
'purchases' => $purchases,
|
140 |
+
'paypal_currencies' => array (
|
141 |
+
array( 'description' => Ai1ec_I18n::__( 'United States Dollar' ), 'code' => 'USD' ),
|
142 |
+
array( 'description' => Ai1ec_I18n::__( 'Canadian Dollar' ), 'code' => 'CAD' ),
|
143 |
+
array( 'description' => Ai1ec_I18n::__( 'Australian Dollar' ), 'code' => 'AUD' ),
|
144 |
+
array( 'description' => Ai1ec_I18n::__( 'Brazilian Real' ), 'code' => 'BRL', 'note' => Ai1ec_I18n::__( 'Note: This currency is supported as a payment currency and a currency balance for in-country PayPal accounts only.' ) ),
|
145 |
+
array( 'description' => Ai1ec_I18n::__( 'Czech Koruna' ), 'code' => 'CZK' ),
|
146 |
+
array( 'description' => Ai1ec_I18n::__( 'Danish Krone' ), 'code' => 'DKK' ),
|
147 |
+
array( 'description' => Ai1ec_I18n::__( 'Euro' ), 'code' => 'EUR' ),
|
148 |
+
array( 'description' => Ai1ec_I18n::__( 'Hong Kong Dollar' ), 'code' => 'HKD' ),
|
149 |
+
array( 'description' => Ai1ec_I18n::__( 'Hungarian Forint' ), 'code' => 'HUF', 'note' => Ai1ec_I18n::__( 'Note: Decimal amounts are not supported for this currency. Passing a decimal amount will throw an error.' ) ),
|
150 |
+
array( 'description' => Ai1ec_I18n::__( 'Israeli New Sheqel' ), 'code' => 'ILS' ),
|
151 |
+
array( 'description' => Ai1ec_I18n::__( 'Japanese Yen' ), 'code' => 'JPY', 'note' => Ai1ec_I18n::__( 'Note: This currency does not support decimals. Passing a decimal amount will throw an error. 1,000,000' ) ),
|
152 |
+
array( 'description' => Ai1ec_I18n::__( 'Malaysian Ringgit' ), 'code' => 'MYR', 'note' => Ai1ec_I18n::__( 'Note: This currency is supported as a payment currency and a currency balance for in-country PayPal accounts only.' ) ),
|
153 |
+
array( 'description' => Ai1ec_I18n::__( 'Mexican Peso' ), 'code' => 'MXN' ),
|
154 |
+
array( 'description' => Ai1ec_I18n::__( 'Norwegian Krone' ), 'code' => 'NOK' ),
|
155 |
+
array( 'description' => Ai1ec_I18n::__( 'New Zealand Dollar' ), 'code' => 'NZD' ),
|
156 |
+
array( 'description' => Ai1ec_I18n::__( 'Philippine Peso' ), 'code' => 'PHP' ),
|
157 |
+
array( 'description' => Ai1ec_I18n::__( 'Polish Zloty' ), 'code' => 'PLN' ),
|
158 |
+
array( 'description' => Ai1ec_I18n::__( 'Pound Sterling' ), 'code' => 'GBP' ),
|
159 |
+
array( 'description' => Ai1ec_I18n::__( 'Russian Ruble' ), 'code' => 'RUB', 'note' => Ai1ec_I18n::__( 'For in-border payments (payments made within Russia), the Russian Ruble is the only accepted currency. If you use another currency for in-border payments, the transaction will fail' ) ),
|
160 |
+
array( 'description' => Ai1ec_I18n::__( 'Singapore Dollar' ), 'code' => 'SGD' ),
|
161 |
+
array( 'description' => Ai1ec_I18n::__( 'Swedish Krona' ), 'code' => 'SEK' ),
|
162 |
+
array( 'description' => Ai1ec_I18n::__( 'Swiss Franc' ), 'code' => 'CHF' ),
|
163 |
+
array( 'description' => Ai1ec_I18n::__( 'Taiwan New Dollar' ), 'code' => 'TWD', 'note' => Ai1ec_I18n::__( 'Note: Decimal amounts are not supported for this currency. Passing a decimal amount will throw an error.' ) ),
|
164 |
+
array( 'description' => Ai1ec_I18n::__( 'Thai Baht' ), 'code' => 'THB' ),
|
165 |
+
)
|
166 |
+
);
|
167 |
+
$file = $loader->get_file( 'ticketing/manage.twig', $args, true );
|
168 |
+
}
|
169 |
+
|
170 |
+
$this->_registry->get( 'css.admin' )->admin_enqueue_scripts(
|
171 |
+
'ai1ec_event_page_all-in-one-event-calendar-settings'
|
172 |
+
);
|
173 |
+
$this->_registry->get( 'css.admin' )->process_enqueue(
|
174 |
+
array(
|
175 |
+
array( 'style', 'ticketing.css', ),
|
176 |
+
)
|
177 |
+
);
|
178 |
+
if ( isset( $_POST['ai1ec_save_settings'] ) ) {
|
179 |
+
$response = $this->_api_registration->save_payment_preferences();
|
180 |
+
|
181 |
+
// this redirect makes sure that the error messages appear on the screen
|
182 |
+
if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
|
183 |
+
header( "Location: " . $_SERVER['HTTP_REFERER'] );
|
184 |
+
}
|
185 |
+
}
|
186 |
+
return $file->render();
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Handle post, likely to be deprecated to use commands.
|
191 |
+
*/
|
192 |
+
public function handle_post(){}
|
193 |
|
194 |
}
|
app/view/admin/widget-creator.php
CHANGED
@@ -11,139 +11,139 @@
|
|
11 |
*/
|
12 |
class Ai1ec_View_Widget_Creator extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
|
148 |
|
149 |
}
|
11 |
*/
|
12 |
class Ai1ec_View_Widget_Creator extends Ai1ec_View_Admin_Abstract {
|
13 |
|
14 |
+
/**
|
15 |
+
* Adds page to the menu.
|
16 |
+
*
|
17 |
+
* @wp_hook admin_menu
|
18 |
+
*
|
19 |
+
* @return void
|
20 |
+
*/
|
21 |
+
public function add_page() {
|
22 |
+
add_submenu_page(
|
23 |
+
AI1EC_ADMIN_BASE_URL,
|
24 |
+
__( 'Widget Creator', AI1EC_PLUGIN_NAME ),
|
25 |
+
__( 'Widget Creator', AI1EC_PLUGIN_NAME ),
|
26 |
+
'manage_ai1ec_feeds',
|
27 |
+
AI1EC_PLUGIN_NAME . '-widget-creator',
|
28 |
+
array( $this, 'display_page' )
|
29 |
+
);
|
30 |
+
}
|
31 |
|
32 |
+
/**
|
33 |
+
* Display this plugin's feeds page in the admin.
|
34 |
+
*
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
+
public function display_page() {
|
38 |
+
$this->_registry->get( 'css.admin' )->admin_enqueue_scripts(
|
39 |
+
'ai1ec_event_page_all-in-one-event-calendar-settings'
|
40 |
+
);
|
41 |
+
$this->_registry->get( 'css.admin' )->process_enqueue(
|
42 |
+
array(
|
43 |
+
array( 'style', 'super-widget.css', ),
|
44 |
+
)
|
45 |
+
);
|
46 |
+
$args = array(
|
47 |
+
'title' => __(
|
48 |
+
'Widget Creator',
|
49 |
+
AI1EC_PLUGIN_NAME
|
50 |
+
),
|
51 |
+
'metabox' => array(
|
52 |
+
'screen' => 'ai1ec-super-widget',
|
53 |
+
'action' => 'left',
|
54 |
+
'object' => null
|
55 |
+
),
|
56 |
+
);
|
57 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
58 |
+
$file = $loader->get_file( 'widget-creator/page.twig', $args, true );
|
59 |
+
$file->render();
|
60 |
+
}
|
61 |
|
62 |
+
/* (non-PHPdoc)
|
63 |
+
* @see Ai1ec_View_Admin_Settings::handle_post()
|
64 |
+
*/
|
65 |
+
public function handle_post() {
|
66 |
+
}
|
67 |
|
68 |
+
/* (non-PHPdoc)
|
69 |
+
* @see Ai1ec_View_Admin_Settings::add_meta_box()
|
70 |
+
*/
|
71 |
+
public function add_meta_box() {
|
72 |
+
add_meta_box(
|
73 |
+
'ai1ec-widget-creator',
|
74 |
+
_x( 'Widget Creator', 'meta box', AI1EC_PLUGIN_NAME ),
|
75 |
+
array( $this, 'display_meta_box' ),
|
76 |
+
'ai1ec-super-widget',
|
77 |
+
'left',
|
78 |
+
'default'
|
79 |
+
);
|
80 |
+
}
|
81 |
|
82 |
+
/**
|
83 |
+
* Renders the settings
|
84 |
+
*
|
85 |
+
* @param array $settings
|
86 |
+
*
|
87 |
+
* @return array
|
88 |
+
*/
|
89 |
+
public function get_html_from_settings( array $settings ) {
|
90 |
+
$named_elements = array();
|
91 |
+
foreach ( $settings as $id => $setting ) {
|
92 |
+
$named_elements[$id] = $this->_registry->get(
|
93 |
+
'html.element.setting.' . $setting['renderer']['class'],
|
94 |
+
array(
|
95 |
+
'id' => $id,
|
96 |
+
'value' => $setting['value'],
|
97 |
+
'renderer' => $setting['renderer'],
|
98 |
+
)
|
99 |
+
)->render();
|
100 |
+
}
|
101 |
+
return $named_elements;
|
102 |
+
}
|
103 |
|
104 |
+
/* (non-PHPdoc)
|
105 |
+
* @see Ai1ec_View_Admin_Settings::display_meta_box()
|
106 |
+
*/
|
107 |
+
public function display_meta_box( $object, $box ) {
|
108 |
+
$widgets = $this->_registry->get( 'controller.javascript-widget' )
|
109 |
+
->get_widgets();
|
110 |
+
// this is just for the Super Widget which doesn't fully implement Ai1ec_Embeddable
|
111 |
+
$widgets = apply_filters( 'ai1ec_widget_creators_widgets', $widgets );
|
112 |
+
$tabs = array();
|
113 |
+
foreach ( $widgets as $widget_id => $widget_class ) {
|
114 |
+
$widget = $this->_registry->get( $widget_class );
|
115 |
+
$tabs[$widget_id] = array(
|
116 |
+
'name' => $widget->get_name(),
|
117 |
+
'icon' => $widget->get_icon(),
|
118 |
+
'requirements' => $widget->check_requirements(),
|
119 |
+
'elements' => $this->get_html_from_settings(
|
120 |
+
$widget->get_configurable_for_widget_creation()
|
121 |
+
)
|
122 |
+
);
|
123 |
+
}
|
124 |
|
125 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
126 |
+
$file = $loader->get_file(
|
127 |
+
'widget-creator/super-widget-contents.twig',
|
128 |
+
array(
|
129 |
+
'tabs' => $tabs,
|
130 |
+
'siteurl' => trailingslashit( preg_replace( '/^.*?:/', '', ai1ec_get_site_url() ) ),
|
131 |
+
'text_common_info' => Ai1ec_I18n::__( 'Use this tool to generate code snippets you can add to <strong>an external website</strong> to embed new calendars and widgets.' ),
|
132 |
+
'text_alert' => Ai1ec_I18n::__( '<h4>Attention!</h4><p>These widgets are designed to be embedded in <strong>external sites only</strong> and may cause conflicts if used within the same WordPress site.</p>' ),
|
133 |
+
'text_alternatives' => sprintf(
|
134 |
+
Ai1ec_I18n::__( '<p>Use <a href="%s"><strong>Appearance</strong> > <strong>Widgets</strong></a> to add event widgets to your WordPress site as you would any other widget, or use <a href="%s" target="_blank">shortcodes</a> to embed the full calendar.</strong></p>' ),
|
135 |
+
admin_url( 'widgets.php' ),
|
136 |
+
'https://time.ly/document/user-guide/using-calendar/display-multiple-calendars-site/'
|
137 |
+
),
|
138 |
+
'display_alert' => apply_filters( 'ai1ec_display_widget_creator_warning', true ),
|
139 |
+
'text_preview' => Ai1ec_I18n::__( 'Preview:' ),
|
140 |
+
'text_paste' => Ai1ec_I18n::__( 'Paste this code onto your site:' ),
|
141 |
+
'text_updated_code' => Ai1ec_I18n::__( 'This code will update to reflect changes made to the settings. Changing settings will not affect previously embedded widgets.' ),
|
142 |
+
),
|
143 |
+
true
|
144 |
+
);
|
145 |
+
$file->render();
|
146 |
+
}
|
147 |
|
148 |
|
149 |
}
|
app/view/calendar/fallbacks.php
CHANGED
@@ -11,35 +11,35 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Calendar_Avatar_Fallbacks extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
|
45 |
}
|
11 |
*/
|
12 |
class Ai1ec_Calendar_Avatar_Fallbacks extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* Default avatar fallbacks.
|
16 |
+
*
|
17 |
+
* @var array
|
18 |
+
*/
|
19 |
+
protected $_fallbacks = array(
|
20 |
+
'post_thumbnail',
|
21 |
+
'content_img',
|
22 |
+
'category_avatar',
|
23 |
+
);
|
24 |
|
25 |
+
/**
|
26 |
+
* Get registered fallbacks.
|
27 |
+
*
|
28 |
+
* @return array
|
29 |
+
*/
|
30 |
+
public function get_all() {
|
31 |
+
return apply_filters( 'ai1ec_avatar_fallbacks', $this->_fallbacks );
|
32 |
+
}
|
33 |
|
34 |
+
/**
|
35 |
+
* Register new avatar fallbacks.
|
36 |
+
*
|
37 |
+
* @param array $fallbacks Fallbacks.
|
38 |
+
*
|
39 |
+
* @return void Method does not return.
|
40 |
+
*/
|
41 |
+
public function set( array $fallbacks ) {
|
42 |
+
$this->_fallbacks = $fallbacks;
|
43 |
+
}
|
44 |
|
45 |
}
|
app/view/calendar/page.php
CHANGED
@@ -11,512 +11,512 @@
|
|
11 |
*/
|
12 |
class Ai1ec_Calendar_Page extends Ai1ec_Base {
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
}
|
11 |
*/
|
12 |
class Ai1ec_Calendar_Page extends Ai1ec_Base {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var Ai1ec_Memory_Utility Instance of memory to hold exact dates
|
16 |
+
*/
|
17 |
+
protected $_exact_dates = NULL;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Public constructor
|
21 |
+
*
|
22 |
+
* @param Ai1ec_Registry_Object $registry The registry object
|
23 |
+
*/
|
24 |
+
public function __construct( Ai1ec_Registry_Object $registry ) {
|
25 |
+
parent::__construct( $registry );
|
26 |
+
$this->_exact_dates = $registry->get( 'cache.memory' );
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Get the content if the calendar page
|
31 |
+
*
|
32 |
+
* @param Ai1ec_Request_Parser $request Request object.
|
33 |
+
* @param string $caller Method caller, expected one of
|
34 |
+
* ['shortcode', 'render-command']
|
35 |
+
* Defaults to 'render-command'.
|
36 |
+
*
|
37 |
+
* @return string Content.
|
38 |
+
*/
|
39 |
+
public function get_content(
|
40 |
+
Ai1ec_Request_Parser $request,
|
41 |
+
$caller = 'render-command'
|
42 |
+
) {
|
43 |
+
// Get args for the current view; required to generate HTML for views
|
44 |
+
// dropdown list, categories, tags, subscribe buttons, and of course the
|
45 |
+
// view itself.
|
46 |
+
$view_args = $this->get_view_args_for_view( $request );
|
47 |
+
|
48 |
+
try {
|
49 |
+
$action = $this->_registry->get( 'model.settings-view' )
|
50 |
+
->get_configured( $view_args['action'] );
|
51 |
+
} catch ( Ai1ec_Settings_Exception $exception ) {
|
52 |
+
// short-circuit and return error message
|
53 |
+
return '<div id="ai1ec-container"><div class="timely"><p>' .
|
54 |
+
Ai1ec_I18n::__(
|
55 |
+
'There was an error loading calendar. Please contact site administrator and inform him to configure calendar views.'
|
56 |
+
) .
|
57 |
+
'</p></div></div>';
|
58 |
+
}
|
59 |
+
$type = $request->get( 'request_type' );
|
60 |
+
$is_json = $this->_registry->get( 'http.request' )->is_json_required(
|
61 |
+
$view_args['request_format'], $action
|
62 |
+
);
|
63 |
+
|
64 |
+
// Add view-specific args to the current view args.
|
65 |
+
$exact_date = $this->get_exact_date( $request );
|
66 |
+
try {
|
67 |
+
$view_obj = $this->_registry->get(
|
68 |
+
'view.calendar.view.' . $action,
|
69 |
+
$request
|
70 |
+
);
|
71 |
+
} catch ( Ai1ec_Bootstrap_Exception $exc ) {
|
72 |
+
$this->_registry->get( 'notification.admin' )->store(
|
73 |
+
sprintf(
|
74 |
+
Ai1ec_I18n::__( 'Calendar was unable to initialize %s view and has reverted to Agenda view. Please check if you have installed the latest versions of calendar add-ons.' ),
|
75 |
+
ucfirst( $action )
|
76 |
+
),
|
77 |
+
'error',
|
78 |
+
0,
|
79 |
+
array( Ai1ec_Notification_Admin::RCPT_ADMIN ),
|
80 |
+
true
|
81 |
+
);
|
82 |
+
// don't disable calendar - just switch to agenda which should
|
83 |
+
// always exists
|
84 |
+
$action = 'agenda';
|
85 |
+
$view_obj = $this->_registry->get(
|
86 |
+
'view.calendar.view.' . $action,
|
87 |
+
$request
|
88 |
+
);
|
89 |
+
}
|
90 |
+
$view_args = $view_obj->get_extra_arguments( $view_args, $exact_date );
|
91 |
+
|
92 |
+
// Get HTML for views dropdown list.
|
93 |
+
$dropdown_args = $view_args;
|
94 |
+
if (
|
95 |
+
isset( $dropdown_args['time_limit'] ) &&
|
96 |
+
false !== $exact_date
|
97 |
+
) {
|
98 |
+
$dropdown_args['exact_date'] = $exact_date;
|
99 |
+
}
|
100 |
+
$views_dropdown =
|
101 |
+
$this->get_html_for_views_dropdown( $dropdown_args, $view_obj );
|
102 |
+
// Add views dropdown markup to view args.
|
103 |
+
$view_args['views_dropdown'] = $views_dropdown;
|
104 |
+
|
105 |
+
$settings = $this->_registry->get( 'model.settings' );
|
106 |
+
if ( $settings->get( 'ai1ec_use_frontend_rendering' ) ) {
|
107 |
+
$view_args['request_format'] = 'json';
|
108 |
+
}
|
109 |
+
|
110 |
+
// Get HTML for subscribe buttons.
|
111 |
+
$subscribe_buttons = $this->get_html_for_subscribe_buttons( $view_args );
|
112 |
+
|
113 |
+
// Get HTML for view itself.
|
114 |
+
$view = $view_obj->get_content( $view_args );
|
115 |
+
|
116 |
+
$router = $this->_registry->get( 'routing.router' );
|
117 |
+
$are_filters_set = $router->is_at_least_one_filter_set_in_request(
|
118 |
+
$view_args
|
119 |
+
);
|
120 |
+
|
121 |
+
if (
|
122 |
+
$is_json &&
|
123 |
+
( $view_args['no_navigation'] || $type !== 'html' )
|
124 |
+
) {
|
125 |
+
// send data both for json and jsonp as shortcodes are jsonp
|
126 |
+
return array(
|
127 |
+
'html' => $view,
|
128 |
+
'views_dropdown' => $views_dropdown,
|
129 |
+
'subscribe_buttons' => $subscribe_buttons,
|
130 |
+
'are_filters_set' => $are_filters_set,
|
131 |
+
'is_json' => $is_json,
|
132 |
+
);
|
133 |
+
|
134 |
+
} else {
|
135 |
+
$loader = $this->_registry->get( 'theme.loader' );
|
136 |
+
$empty = $loader->get_file( 'empty.twig', array(), false );
|
137 |
+
// Get HTML for categories and for tags
|
138 |
+
$taxonomy = $this->_registry->get( 'view.calendar.taxonomy' );
|
139 |
+
$categories = $taxonomy->get_html_for_categories(
|
140 |
+
$view_args
|
141 |
+
);
|
142 |
+
$tags = $taxonomy->get_html_for_tags(
|
143 |
+
$view_args,
|
144 |
+
true
|
145 |
+
);
|
146 |
+
|
147 |
+
// option to show filters in the super widget
|
148 |
+
// Define new arguments for overall calendar view
|
149 |
+
$filter_args = array(
|
150 |
+
'views_dropdown' => $views_dropdown,
|
151 |
+
'categories' => $categories,
|
152 |
+
'tags' => $tags,
|
153 |
+
'contribution_buttons' => apply_filters(
|
154 |
+
'ai1ec_contribution_buttons',
|
155 |
+
'',
|
156 |
+
$type,
|
157 |
+
$caller
|
158 |
+
),
|
159 |
+
'additional_buttons' => apply_filters(
|
160 |
+
'ai1ec_additional_buttons',
|
161 |
+
'',
|
162 |
+
$view_args
|
163 |
+
),
|
164 |
+
'show_dropdowns' => apply_filters(
|
165 |
+
'ai1ec_show_dropdowns',
|
166 |
+
true
|
167 |
+
),
|
168 |
+
'show_select2' => apply_filters(
|
169 |
+
'ai1ec_show_select2',
|
170 |
+
false
|
171 |
+
),
|
172 |
+
'span_for_select2' => apply_filters(
|
173 |
+
'ai1ec_span_for_select2',
|
174 |
+
''
|
175 |
+
),
|
176 |
+
'authors' => apply_filters(
|
177 |
+
'ai1ec_authors',
|
178 |
+
''
|
179 |
+
),
|
180 |
+
'save_view_btngroup' => apply_filters(
|
181 |
+
'ai1ec_save_view_btngroup',
|
182 |
+
$empty
|
183 |
+
),
|
184 |
+
'view_args' => $view_args,
|
185 |
+
'request' => $request,
|
186 |
+
);
|
187 |
+
|
188 |
+
$filter_menu = $loader->get_file(
|
189 |
+
'filter-menu.twig',
|
190 |
+
$filter_args,
|
191 |
+
false
|
192 |
+
)->get_content();
|
193 |
+
// hide filters in the SW
|
194 |
+
if ( 'true' !== $request->get( 'display_filters' ) && 'jsonp' === $type ) {
|
195 |
+
$filter_menu = '';
|
196 |
+
}
|
197 |
+
|
198 |
+
$calendar_args = array(
|
199 |
+
'version' => AI1EC_VERSION,
|
200 |
+
'filter_menu' => $filter_menu,
|
201 |
+
'view' => $view,
|
202 |
+
'subscribe_buttons' => $subscribe_buttons,
|
203 |
+
'disable_standard_filter_menu' => apply_filters(
|
204 |
+
'ai1ec_disable_standard_filter_menu',
|
205 |
+
false
|
206 |
+
),
|
207 |
+
'inline_js_calendar' => apply_filters(
|
208 |
+
'ai1ec_inline_js_calendar',
|
209 |
+
''
|
210 |
+
),
|
211 |
+
'after_view' => apply_filters(
|
212 |
+
'ai1ec_after_view',
|
213 |
+
''
|
214 |
+
),
|
215 |
+
'ai1ec_above_calendar' => apply_filters(
|
216 |
+
'ai1ec_above_calendar',
|
217 |
+
''
|
218 |
+
),
|
219 |
+
);
|
220 |
+
|
221 |
+
if ( is_array( $calendar_args['view'] ) ) {
|
222 |
+
$view_args['request_format'] = 'html';
|
223 |
+
$calendar_args['view'] = $view_obj->get_content( $view_args );
|
224 |
+
}
|
225 |
+
$calendar = $loader->get_file( 'calendar.twig', $calendar_args, false );
|
226 |
+
// if it's just html, only the calendar html must be returned.
|
227 |
+
if ( 'html' === $type ) {
|
228 |
+
return $calendar->get_content();
|
229 |
+
}
|
230 |
+
// send data both for json and jsonp as shortcodes are jsonp
|
231 |
+
return array(
|
232 |
+
'html' => $calendar->get_content(),
|
233 |
+
'views_dropdown' => $views_dropdown,
|
234 |
+
'subscribe_buttons' => $subscribe_buttons,
|
235 |
+
'are_filters_set' => $are_filters_set,
|
236 |
+
'is_json' => $is_json
|
237 |
+
);
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Render the HTML for the `subscribe' buttons.
|
243 |
+
*
|
244 |
+
* @param array $view_args Args to pass.
|
245 |
+
*
|
246 |
+
* @return string Rendered HTML to include in output.
|
247 |
+
*/
|
248 |
+
public function get_html_for_subscribe_buttons( array $view_args ) {
|
249 |
+
$settings = $this->_registry->get( 'model.settings' );
|
250 |
+
$turn_off_subscribe = $settings->get( 'turn_off_subscription_buttons' );
|
251 |
+
if ( $turn_off_subscribe ) {
|
252 |
+
return '';
|
253 |
+
}
|
254 |
+
|
255 |
+
$args = array(
|
256 |
+
'url_args' => '',
|
257 |
+
'is_filtered' => false,
|
258 |
+
'export_url' => AI1EC_EXPORT_URL,
|
259 |
+
'export_url_no_html' => AI1EC_EXPORT_URL . '&no_html=true',
|
260 |
+
'text_filtered' => Ai1ec_I18n::__( 'Subscribe to filtered calendar' ),
|
261 |
+
'text_subscribe' => Ai1ec_I18n::__( 'Subscribe' ),
|
262 |
+
'text_get_calendar' => Ai1ec_I18n::__( 'Get a Timely Calendar' ),
|
263 |
+
'show_get_calendar' => ! $settings->get( 'disable_get_calendar_button' ),
|
264 |
+
'text' => $this->_registry
|
265 |
+
->get( 'view.calendar.subscribe-button' )
|
266 |
+
->get_labels(),
|
267 |
+
'placement' => 'up',
|
268 |
+
);
|
269 |
+
if ( ! empty( $view_args['cat_ids'] ) ) {
|
270 |
+
$args['url_args'] .= '&ai1ec_cat_ids=' .
|
271 |
+
implode( ',', $view_args['cat_ids'] );
|
272 |
+
$args['is_filtered'] = true;
|
273 |
+
}
|
274 |
+
if ( ! empty( $view_args['tag_ids'] ) ) {
|
275 |
+
$args['url_args'] .= '&ai1ec_tag_ids=' .
|
276 |
+
implode( ',', $view_args['tag_ids'] );
|
277 |
+
$args['is_filtered'] = true;
|
278 |
+
}
|
279 |
+
if ( ! empty( $view_args['post_ids'] ) ) {
|
280 |
+
$args['url_args'] .= '&ai1ec_post_ids=' .
|
281 |
+
implode( ',', $view_args['post_ids'] );
|
282 |
+
$args['is_filtered'] = true;
|
283 |
+
}
|
284 |
+
$args = apply_filters(
|
285 |
+
'ai1ec_subscribe_buttons_arguments',
|
286 |
+
$args,
|
287 |
+
$view_args
|
288 |
+
);
|
289 |
+
$localization = $this->_registry->get( 'p28n.wpml' );
|
290 |
+
if (
|
291 |
+
NULL !== ( $use_lang = $localization->get_language() )
|
292 |
+
) {
|
293 |
+
$args['url_args'] .= '&lang=' . $use_lang;
|
294 |
+
}
|
295 |
+
$subscribe = $this->_registry->get( 'theme.loader' )
|
296 |
+
->get_file( 'subscribe-buttons.twig', $args, false );
|
297 |
+
return $subscribe->get_content();
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* This function generates the html for the view dropdowns.
|
302 |
+
*
|
303 |
+
* @param array $view_args Args passed to view
|
304 |
+
* @param Ai1ec_Calendar_View_Abstract $view View object
|
305 |
+
*/
|
306 |
+
protected function get_html_for_views_dropdown(
|
307 |
+
array $view_args,
|
308 |
+
Ai1ec_Calendar_View_Abstract $view
|
309 |
+
) {
|
310 |
+
$settings = $this->_registry->get( 'model.settings' );
|
311 |
+
$available_views = array();
|
312 |
+
$enabled_views = (array)$settings->get( 'enabled_views', array() );
|
313 |
+
$view_names = array();
|
314 |
+
$mode = wp_is_mobile() ? '_mobile' : '';
|
315 |
+
foreach ( $enabled_views as $key => $val ) {
|
316 |
+
$view_names[$key] = translate_nooped_plural(
|
317 |
+
$val['longname'],
|
318 |
+
1
|
319 |
+
);
|
320 |
+
// Find out if view is enabled in requested mode (mobile or desktop). If
|
321 |
+
// no mode-specific setting is available, fall back to desktop setting.
|
322 |
+
$view_enabled = isset( $enabled_views[$key]['enabled' . $mode] ) ?
|
323 |
+
$enabled_views[$key]['enabled' . $mode] :
|
324 |
+
$enabled_views[$key]['enabled'];
|
325 |
+
$values = array();
|
326 |
+
$options = $view_args;
|
327 |
+
if ( $view_enabled ) {
|
328 |
+
if ( $view instanceof Ai1ec_Calendar_View_Agenda ) {
|
329 |
+
if (
|
330 |
+
isset( $options['exact_date'] ) &&
|
331 |
+
! isset( $options['time_limit'] )
|
332 |
+
) {
|
333 |
+
$options['time_limit'] = $options['exact_date'];
|
334 |
+
}
|
335 |
+
unset( $options['exact_date'] );
|
336 |
+
} else {
|
337 |
+
unset( $options['time_limit'] );
|
338 |
+
}
|
339 |
+
unset( $options['month_offset'] );
|
340 |
+
unset( $options['week_offset'] );
|
341 |
+
unset( $options['oneday_offset'] );
|
342 |
+
$options['action'] = $key;
|
343 |
+
$values['desc'] = translate_nooped_plural(
|
344 |
+
$val['longname'],
|
345 |
+
1
|
346 |
+
);
|
347 |
+
if ( $settings->get( 'ai1ec_use_frontend_rendering' ) ) {
|
348 |
+
$options['request_format'] = 'json';
|
349 |
+
}
|
350 |
+
$href = $this->_registry->get( 'html.element.href', $options );
|
351 |
+
$values['href'] = $href->generate_href();
|
352 |
+
$available_views[$key] = $values;
|
353 |
+
}
|
354 |
+
};
|
355 |
+
$args = array(
|
356 |
+
'view_names' => $view_names,
|
357 |
+
'available_views' => $available_views,
|
358 |
+
'current_view' => $view_args['action'],
|
359 |
+
'data_type' => $view_args['data_type'],
|
360 |
+
);
|
361 |
+
|
362 |
+
$views_dropdown = $this->_registry->get( 'theme.loader' )
|
363 |
+
->get_file( 'views_dropdown.twig', $args, false );
|
364 |
+
return $views_dropdown->get_content();
|
365 |
+
}
|
366 |
+
|
367 |
+
/**
|
368 |
+
* Get the exact date from request if available, or else from settings.
|
369 |
+
*
|
370 |
+
* @param Ai1ec_Abstract_Query settings
|
371 |
+
*
|
372 |
+
* @return boolean|int
|
373 |
+
*/
|
374 |
+
private function get_exact_date( Ai1ec_Abstract_Query $request ) {
|
375 |
+
$settings = $this->_registry->get( 'model.settings' );
|
376 |
+
|
377 |
+
// Preprocess exact_date.
|
378 |
+
// Check to see if a date has been specified.
|
379 |
+
$exact_date = $request->get( 'exact_date' );
|
380 |
+
$use_key = $exact_date;
|
381 |
+
if ( null === ( $exact_date = $this->_exact_dates->get( $use_key ) ) ) {
|
382 |
+
$exact_date = $use_key;
|
383 |
+
// Let's check if we have a date
|
384 |
+
if ( false !== $exact_date ) {
|
385 |
+
// If it's not a timestamp
|
386 |
+
if ( ! Ai1ec_Validation_Utility::is_valid_time_stamp( $exact_date ) ) {
|
387 |
+
// Try to parse it
|
388 |
+
$exact_date = $this->return_gmtime_from_exact_date( $exact_date );
|
389 |
+
if ( false === $exact_date ) {
|
390 |
+
return null;
|
391 |
+
}
|
392 |
+
}
|
393 |
+
}
|
394 |
+
// Last try, let's see if an exact date is set in settings.
|
395 |
+
if ( false === $exact_date && $settings->get( 'exact_date' ) !== '' ) {
|
396 |
+
$exact_date = $this->return_gmtime_from_exact_date(
|
397 |
+
$settings->get( 'exact_date' )
|
398 |
+
);
|
399 |
+
}
|
400 |
+
$this->_exact_dates->set( $use_key, $exact_date );
|
401 |
+
}
|
402 |
+
return $exact_date;
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Decomposes an 'exact_date' parameter into month, day, year components based
|
407 |
+
* on date pattern defined in settings (assumed to be in local time zone),
|
408 |
+
* then returns a timestamp in GMT.
|
409 |
+
*
|
410 |
+
* @param string $exact_date 'exact_date' parameter passed to a view
|
411 |
+
* @return bool|int false if argument not provided or invalid,
|
412 |
+
* else UNIX timestamp in GMT
|
413 |
+
*/
|
414 |
+
private function return_gmtime_from_exact_date( $exact_date ) {
|
415 |
+
$input_format = $this->_registry->get( 'model.settings' )
|
416 |
+
->get( 'input_date_format' );
|
417 |
+
|
418 |
+
$date = Ai1ec_Validation_Utility::format_as_iso(
|
419 |
+
$exact_date,
|
420 |
+
$input_format
|
421 |
+
);
|
422 |
+
if ( false === $date ) {
|
423 |
+
$exact_date = false;
|
424 |
+
} else {
|
425 |
+
$exact_date = $this->_registry->get(
|
426 |
+
'date.time',
|
427 |
+
$date,
|
428 |
+
'sys.default'
|
429 |
+
)->format_to_gmt();
|
430 |
+
if ( $exact_date < 0 ) {
|
431 |
+
return false;
|
432 |
+
}
|
433 |
+
}
|
434 |
+
return $exact_date;
|
435 |
+
}
|
436 |
+
|
437 |
+
/**
|
438 |
+
* Returns the correct data attribute to use in views
|
439 |
+
*
|
440 |
+
* @param string $type
|
441 |
+
*/
|
442 |
+
private function return_data_type_for_request_type( $type ) {
|
443 |
+
$data_type = 'data-type="json"';
|
444 |
+
if ( $type === 'jsonp' ) {
|
445 |
+
$data_type = 'data-type="jsonp"';
|
446 |
+
}
|
447 |
+
return $data_type;
|
448 |
+
}
|
449 |
+
|
450 |
+
/**
|
451 |
+
* Get the parameters for the view from the request object
|
452 |
+
*
|
453 |
+
* @param Ai1ec_Abstract_Query $request
|
454 |
+
*
|
455 |
+
* @return array
|
456 |
+
*/
|
457 |
+
protected function get_view_args_for_view( Ai1ec_Abstract_Query $request ) {
|
458 |
+
$settings = $this->_registry->get( 'model.settings' );
|
459 |
+
// Define arguments for specific calendar sub-view (month, agenda, etc.)
|
460 |
+
// Preprocess action.
|
461 |
+
// Allow action w/ or w/o ai1ec_ prefix. Remove ai1ec_ if provided.
|
462 |
+
$action = $request->get( 'action' );
|
463 |
+
|
464 |
+
if ( 0 === strncmp( $action, 'ai1ec_', 6 ) ) {
|
465 |
+
$action = substr( $action, 6 );
|
466 |
+
}
|
467 |
+
$view_args = $request->get_dict(
|
468 |
+
apply_filters(
|
469 |
+
'ai1ec_view_args_for_view',
|
470 |
+
array(
|
471 |
+
'post_ids',
|
472 |
+
'auth_ids',
|
473 |
+
'cat_ids',
|
474 |
+
'tag_ids',
|
475 |
+
'events_limit',
|
476 |
+
'instance_ids',
|
477 |
+
)
|
478 |
+
)
|
479 |
+
);
|
480 |
+
$type = $request->get( 'request_type' );
|
481 |
+
if ( 'html' === $type ) {
|
482 |
+
$add_defaults = array(
|
483 |
+
'cat_ids' => 'categories',
|
484 |
+
'tag_ids' => 'tags',
|
485 |
+
);
|
486 |
+
foreach ( $add_defaults as $query => $default ) {
|
487 |
+
if ( empty( $view_args[$query] ) ) {
|
488 |
+
$setting = $settings->get( 'default_tags_categories' );
|
489 |
+
if ( isset( $setting[$default] ) ) {
|
490 |
+
$view_args[$query] = $setting[$default];
|
491 |
+
}
|
492 |
+
}
|
493 |
+
}
|
494 |
+
}
|
495 |
+
|
496 |
+
$view_args['data_type'] = $this->return_data_type_for_request_type(
|
497 |
+
$type
|
498 |
+
);
|
499 |
+
|
500 |
+
$view_args['request_format'] = $request->get( 'request_format' );
|
501 |
+
$exact_date = $this->get_exact_date( $request );
|
502 |
+
|
503 |
+
$view_args['no_navigation'] = $request->get( 'no_navigation' ) == true;
|
504 |
+
|
505 |
+
// Find out which view of the calendar page was requested, and render it
|
506 |
+
// accordingly.
|
507 |
+
$view_args['action'] = $action;
|
508 |
+
|
509 |
+
$view_args['request'] = $request;
|
510 |
+
$view_args = apply_filters(
|
511 |
+
'ai1ec_view_args_array',
|
512 |
+
$view_args
|
513 |
+
);
|
514 |
+
if ( null === $exact_date ) {
|
515 |
+
$href = $this->_registry->get( 'html.element.href', $view_args )
|
516 |
+
->generate_href();
|
517 |
+
return Ai1ec_Http_Response_Helper::redirect( $href, 307 );
|
518 |
+
|
519 |
+
}
|
520 |
+
return $view_args;
|
521 |
+
}
|
522 |
}
|
app/view/calendar/shortcode.php
CHANGED
@@ -10,147 +10,147 @@
|
|
10 |
*/
|
11 |
class Ai1ec_View_
|
10 |
*/
|
11 |
class Ai1ec_View_
|