PluginProbe
Themify Event Post / trunk
Themify Event Post vtrunk
1.3.7 trunk 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6
themify-event-post / includes / functions.php

functions.php in Themify Event Post trunk, at includes/functions.php

1,169 lines 35.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! function_exists( 'themify_event_post_map' ) ) :
4 /**
5 * Render a Google Maps instance
6 *
7 * @return string
8 */
9 function themify_event_post_map( $args = array() ) {
10
11 $args = wp_parse_args( $args, array(
12 'address' => '99 Blue Jays Way, Toronto, Ontario, Canada',
13 'width' => '100%',
14 'height' => '300px',
15 'zoom' => 15,
16 'type' => 'ROADMAP',
17 'scroll_wheel' => 'yes',
18 'draggable_disable_mobile_map' => 'yes',
19 'draggable' => 'yes',
20 ) );
21
22 if ( class_exists( 'Themify_Google_Maps',false ) ) {
23 ob_start();
24 the_widget( 'Themify_Google_Maps', array(
25 'address_map' => $args['address'],
26 'width' => str_replace( 'px', '', $args['width'] ),
27 'height' => str_replace( 'px', '', $args['height'] ),
28 'zoom_map' => $args['zoom'],
29 'type_map' => $args['type'],
30 'scrollwheel_map' => $args['scroll_wheel'] === 'no' ? 'disable' : 'enable',
31 'draggable_map' => $args['draggable'] === 'no' ? 'disable' : 'enable',
32 'draggable_disable_mobile_map' => $args['draggable_disable_mobile_map'],
33 ) );
34 return ob_get_clean();
35 }
36
37 extract( $args );
38
39 /* if no unit is provided for width and height, use "px" */
40 if( ! preg_match( '/[px|%]$/', $width ) ) {
41 $width = $width . 'px';
42 }
43 if( ! preg_match( '/[px|%]$/', $height ) ) {
44 $height = $height . 'px';
45 }
46
47 if ( 'yes' === $draggable && 'yes' === $draggable_disable_mobile_map && wp_is_mobile() ) {
48 $draggable = 'disable';
49 }
50 $num = rand( 0, 10000 );
51 $data['address'] = $address;
52 $data['num'] = $num;
53 $data['zoom'] = $zoom;
54 $data['type'] = $type;
55 $data['scroll'] = $scroll_wheel ==='yes';
56 $data['drag'] = $draggable==='yes';
57 return '
58 <div class="tep_map_container">
59 <div data-map=\''.esc_attr( json_encode( $data ) ).'\' id="themify_map_canvas_' . esc_attr( $num ) . '" style="display: block;width:' . esc_attr( $width ) . ';height:' . esc_attr( $height ) . ';" class="map-container tep_map"></div>
60 </div>';
61 }
62 endif;
63
64 if ( ! function_exists( 'themify_event_post_get_repeat_date' ) ) :
65 /**
66 * Displays repeated dates
67 *
68 * @since 1.0.0
69 */
70 function themify_event_post_get_repeat_date( $type, $number, $date, $time ) {
71 $result = '';
72 switch( $type ) {
73 case 'day':
74 $result = '<span class="event-day">'. sprintf( _n( 'Every day','Every %s days', $number, 'themify-event-post' ), $number ).'</span>';
75 break;
76 case 'week':
77 $result = '<span class="event-day">'. sprintf( _n( 'Every week on %2$s', 'Every %s weeks on %s', $number, 'themify-event-post' ), $number , date_i18n( 'l', strtotime( $date ) ) ).'</span>';
78 break;
79 case 'year':
80 $result = '<span class="event-day">'. sprintf( _n( 'Every year on %2$s', 'Every %s years on %s', $number, 'themify-event-post' ), $number, date_i18n( 'M d', strtotime( $date ) ) ).'</span>';
81 break;
82 }
83 if ( $result && $time ) {
84 $result .= '<span class="event-time-at">' ._x( ' @ ', 'Connector between date and time (with spaces around itself) in event date and time.', 'themify-event-post' ). '</span> <span class="event-time">'.date_i18n( get_option( 'time_format' ), strtotime( $time ) ).'</span>' ;
85 }
86
87 return apply_filters( 'themify_event_date_repeat', $result, $type, $number, $date, $time );
88 }
89 endif;
90
91 function themify_event_is_repeated() {
92 $repeat = get_post_meta( get_the_id(), 'repeat', true );
93 if ( $repeat ) {
94 $repeat_x = intval( get_post_meta( get_the_id(), 'repeat_x', true ) );
95 if ( $repeat_x <= 0 ) {
96 $repeat = false;
97 }
98 }
99
100 return $repeat;
101 }
102
103 if ( ! function_exists( 'themify_event_post_date' ) ) :
104 /**
105 * Displays Start Date and End Date properly formatted
106 *
107 * @since 1.0.0
108 */
109 function themify_event_post_date( $date_format = null, $time_format = null ) {
110 if(get_post_meta( get_the_id(), 'to_be_announced', true )==='on'){
111 echo '<time class="tep_date"><span class="event-start-date">'.__('To be announced','themify-event-post').'</span></time>';
112 return;
113 }
114 $start_date = get_post_meta( get_the_id(), 'start_date', true );
115 $end_date = get_post_meta( get_the_id(), 'end_date', true );
116 $repeat = themify_event_is_repeated();
117 $hide_event_end = get_post_meta( get_the_id(), 'event_end_date_hide', true );
118
119 if ( $start_date || $end_date ) {
120 $date_format = $date_format ?: get_option( 'date_format' );
121 $time_format = $time_format ?: get_option( 'time_format' );
122 echo '<time class="tep_date">';
123
124 if( $start_date ) {
125 $stamp = date_create( $start_date, new DateTimeZone( 'UTC' ) );
126 if ( $stamp ) {
127 $stamp = $stamp->format( 'U' );
128 echo '<span class="event-start-date">';
129 $start_date_parts = explode( ' ', $start_date );
130 if( $repeat ) {
131 echo themify_event_post_get_repeat_date( $repeat, intval( get_post_meta( get_the_id(), 'repeat_x', true ) ), $start_date_parts[0], $start_date_parts[1] );
132 } else {
133 echo '<span class="event-day"> '.date_i18n( $date_format, $stamp ) .'</span> <span class="event-time-at">'. _x( ' @ ', 'Connector between date and time (with spaces around itself) in event date and time.', 'themify-event-post' ) .'</span> <span class="event-time">' . date_i18n( $time_format, $stamp ) .'</span>';
134 }
135 echo '</span>';
136 }
137 }
138 if( !$hide_event_end && ! $repeat && $end_date ) {
139 $stamp = date_create( $end_date, new DateTimeZone( 'UTC' ) );
140 if ( $stamp ) {
141 $stamp = $stamp->format( 'U' );
142 echo '<span class="event-end-date">';
143 $end_date_parts = explode( ' ', $end_date );
144 echo ! isset( $start_date_parts ) || $start_date_parts[0] != $end_date_parts[0] ?'<span class="event-date-separator">'. _x( ' - ', 'Character to provide a hint that this is the event end date and time.', 'themify-event-post' ) .'</span>
145 <span class="event-day">' . date_i18n( $date_format, $stamp ) .'</span>' :' <span class="event-date-separator"> - </span>';
146 if ( isset( $start_date_parts[0] ) && $start_date_parts[0] != $end_date_parts[0] ) {
147 echo '<span class="event-time-at">'. _x( ' @ ', 'Connector between date and time (with spaces around itself) in event date and time.', 'themify-event-post' ).'</span>';
148 }
149 echo '<span class="event-time">' . date_i18n( $time_format, $stamp ) . '</span>';
150 echo '</span>';
151 }
152 }
153
154 echo '</time>';
155 }
156 }
157 endif;
158
159 if ( ! function_exists( 'themify_event_type' ) ) :
160 /**
161 * Displays event type if set
162 *
163 * @since 1.1.2
164 */
165 function themify_event_type() {
166 $post_id = get_the_ID();
167 $e_type=get_post_meta( $post_id, 'event_attendance', true );
168 if(empty($e_type)){
169 return;
170 }
171 echo sprintf('<div class="tep_type">%s</div>',$e_type);
172 }
173 endif;
174
175 if ( ! function_exists( 'themify_event_organizer' ) ) :
176 /**
177 * Displays organizer meta
178 *
179 * @since 1.1.2
180 */
181 function themify_event_organizer() {
182 $post_id = get_the_ID();
183 $name=get_post_meta( $post_id, 'organizer_name', true );
184 if(empty($name)){
185 return;
186 }
187 $url=esc_url(get_post_meta( $post_id, 'organizer_url', true ));
188 ob_start();
189 ?>
190 <div class="tep_organizer">
191 <?php if(!empty($url)): ?>
192 <a href="<?php echo $url ?>" target="_blank">
193 <?php endif; ?>
194 <?php echo esc_html( $name ); ?>
195 <?php if(!empty($url)): ?>
196 </a>
197 <?php endif; ?>
198 </div>
199 <?php
200 ob_end_flush();
201 }
202 endif;
203
204 if ( ! function_exists( 'themify_event_performer' ) ) :
205 /**
206 * Displays organizer meta
207 *
208 * @since 1.1.2
209 */
210 function themify_event_performer() {
211 $post_id = get_the_ID();
212 $name=get_post_meta( $post_id, 'performer_name', true );
213 if(empty($name)){
214 return;
215 }
216 ob_start();
217 ?>
218 <div class="tep_performer">
219 <?php echo esc_html( $name ); ?>
220 </div>
221 <?php
222 ob_end_flush();
223 }
224 endif;
225
226 if ( ! function_exists( 'themify_event_post_pagenav' ) ) :
227 /**
228 * Renders page navigation for Event posts
229 *
230 * @return string
231 */
232 function themify_event_post_pagenav( $args = array() ) {
233 $args = wp_parse_args( $args, array(
234 'paged' => 1,
235 'total_posts' => 0,
236 'posts_per_page' => 0,
237 'pages_to_show' => 5,
238 'offset' => 0,
239 'before' => '',
240 'after' => '',
241 ) );
242 extract( $args );
243
244 // $query->found_posts does not take offset into account, we need to manually adjust that
245 if ( (int) $offset) {
246 $total_posts = $total_posts - (int) $offset;
247 }
248
249 $max_page = ceil( $total_posts / $posts_per_page );
250 $out = '';
251
252 if ( empty( $paged ) ) {
253 $paged = 1;
254 }
255 $pages_to_show_minus_1 = $pages_to_show - 1;
256 $half_page_start = floor($pages_to_show_minus_1 / 2);
257 $half_page_end = ceil($pages_to_show_minus_1 / 2);
258 $start_page = $paged - $half_page_start;
259 if ($start_page <= 0) {
260 $start_page = 1;
261 }
262 $end_page = $paged + $half_page_end;
263 if (($end_page - $start_page) != $pages_to_show_minus_1) {
264 $end_page = $start_page + $pages_to_show_minus_1;
265 }
266 if ($end_page > $max_page) {
267 $start_page = $max_page - $pages_to_show_minus_1;
268 $end_page = $max_page;
269 }
270 if ($start_page <= 0) {
271 $start_page = 1;
272 }
273
274 if ($max_page > 1) {
275
276 if ( class_exists( 'Themify_Enqueue_Assets',false ) && ! empty( Themify_Enqueue_Assets::$themeVersion ) && Themify_Enqueue_Assets::$themeVersion !== null ) {
277 Themify_Enqueue_Assets::loadThemeStyleModule( 'pagenav' );
278 }
279
280 $out .= $before . '<div class="pagenav tf_clearfix">';
281 if ($start_page >= 2 && $pages_to_show < $max_page) {
282 $first_page_text = "&laquo;";
283 $out .= '<a href="' . esc_url(get_pagenum_link()) . '" title="' . esc_attr($first_page_text) . '" class="number">' . $first_page_text . '</a>';
284 }
285 if ($pages_to_show < $max_page)
286 $out .= get_previous_posts_link('&lt;');
287 for ($i = $start_page; $i <= $end_page; $i++) {
288 if ($i == $paged) {
289 $out .= ' <span class="number current">' . $i . '</span> ';
290 } else {
291 $out .= ' <a href="' . esc_url(get_pagenum_link($i)) . '" class="number">' . $i . '</a> ';
292 }
293 }
294 if ($pages_to_show < $max_page)
295 $out .= get_next_posts_link('&gt;');
296 if ($end_page < $max_page) {
297 $last_page_text = "&raquo;";
298 $out .= '<a href="' . esc_url(get_pagenum_link($max_page)) . '" title="' . esc_attr($last_page_text) . '" class="number">' . $last_page_text . '</a>';
299 }
300 $out .= '</div>' . $after;
301 }
302 return $out;
303 }
304 endif;
305
306 if ( ! function_exists( 'themify_event_post_get_paged_query' ) ) :
307 /**
308 * Gets "paged" query var
309 *
310 * @return int
311 */
312 function themify_event_post_get_paged_query() {
313 global $wp;
314 $page = 1;
315 $qpaged = get_query_var( 'paged' );
316 if ( ! empty( $qpaged ) ) {
317 $page = $qpaged;
318 } else {
319 $qpaged = wp_parse_args( $wp->matched_query );
320 if ( isset( $qpaged['paged'] ) && $qpaged['paged'] > 0 ) {
321 $page = $qpaged['paged'];
322 }
323 }
324 return $page;
325 }
326 endif;
327
328 if ( ! function_exists( 'themify_event_post_get_image' ) ) :
329 /**
330 * Display post thumbnail
331 *
332 * @return string
333 * @since 1.0.8
334 */
335 function themify_event_post_get_image( $args = array() ) {
336 if ( ! has_post_thumbnail() ) {
337 return '';
338 }
339
340 global $wp_version;
341
342 /**
343 * List of parameters
344 * @var array
345 */
346 $args = wp_parse_args( $args, array(
347 'id' => '',
348 'ignore' => '',
349 'width' => '',
350 'height' => '',
351 'before' => '<figure class="tep_image">',
352 'after' => '</figure>',
353 'class' => '',
354 'alt' => '',
355 'title' => '',
356 'unlink' => false,
357 'image_meta' => true,
358 'crop' => true,
359 ) );
360 extract( $args );
361
362 $id = (int) get_post_thumbnail_id(); /* Image script works with thumbnail IDs as well as URLs, use ID which is faster */
363
364 $temp = themify_events_do_img( $id, $width, $height, (bool) $args['crop'] );
365 $img_url = $temp['url'];
366
367 // Build final image
368 $out = '';
369 if ( $args['image_meta'] == true ) {
370 $out .= "<meta itemprop=\"width\" content=\"{$width}\">";
371 $out .= "<meta itemprop=\"height\" content=\"{$height}\">";
372 $out .= "<meta itemprop=\"url\" content=\"{$img_url}\">";
373 }
374 $out .= "<img src=\"{$img_url}\"";
375 if ( $width ) {
376 $out .= " width=\"{$width}\"";
377 }
378 if ( $height ) {
379 $out .= " height=\"{$height}\"";
380 }
381 $args['class'] .= ' wp-post-image wp-image-' . $id; /* add attachment_id class to img tag */
382
383 if ( ! empty( $args['class'] ) ) {
384 $out .= " class=\"{$args['class']}\"";
385 }
386
387 // Add title attribute only if explicitly set in $args
388 if ( ! empty( $args['title'] ) ) {
389 $out .= ' title="' . esc_attr( $args['title'] ) . '"';
390 }
391
392 // If alt was passed as parameter, use it. Otherwise use alt text by attachment id if it was fetched or post title.
393 $out_alt = '';
394 if ( ! empty( $args['alt'] ) ) {
395 $out_alt = $args['alt'] === 'false' ? '' : $args['alt'];
396 } elseif ( ! empty( $img_alt ) ) {
397 $out_alt = $img_alt;
398 } else {
399 if ( ! empty( $args['title'] ) ) {
400 $out_alt = $args['title'];
401 } elseif ( $id ) {
402 $p = get_post( $id );
403 if ( $p ) {
404 $out_alt = $p->post_title;
405 }
406 } else {
407 $out_alt = the_title_attribute( 'echo=0' );
408 }
409 }
410 $out .= ' alt="' . esc_attr( $out_alt ) . '" />';
411
412 if ( ! $unlink ) {
413 $args['before'] .= sprintf( '<a href="%s">', get_permalink() );
414 $args['after'] = '</a>' . $args['after'];
415 }
416
417 $out = $args['before'] . $out . $args['after'];
418
419 if( version_compare( $wp_version, '4.4', '>=' ) ) {
420 $out = function_exists('wp_filter_content_tags') ? wp_filter_content_tags($out) : wp_make_content_images_responsive( $out );
421 }
422
423 return $out;
424 }
425 endif;
426
427 if ( ! function_exists( 'themify_event_post_title' ) ) :
428 /**
429 * Display title for event posts
430 *
431 * @return string|null
432 * @since 1.0.1
433 */
434 function themify_event_post_title( $args = array() ) {
435 extract( wp_parse_args( $args, array(
436 'post' => 0,
437 'tag' => 'h2',
438 'class' => 'tep_post_title entry-title',
439 'before' => '',
440 'after' => '',
441 'before_title' => '',
442 'after_title' => '',
443 'echo' => true,
444 'unlink' => false,
445 ), 'post_title' ) );
446
447 $post = get_post( $post );
448 $title = get_the_title( $post );
449 if ( strlen( $title ) == 0 ) {
450 return;
451 }
452
453 $link_before = $unlink ? '' : '<a href="' . get_permalink() .'">';
454 $link_after = $unlink ? '' : '</a>';
455
456 $before = "{$before} <{$tag} class=\"{$class}\">{$before_title}{$link_before}";
457 $after = "{$link_after}{$after_title} </{$tag}>{$after}";
458
459 $title = $before . $title . $after;
460
461 if ( $echo ) {
462 echo $title;
463 } else {
464 return $title;
465 }
466 }
467 endif;
468
469 /**
470 * Get a WP_Query parameters from the shortcode attributes
471 *
472 * @param $atts the array of shortcode parameters supplied by user
473 * @param $shortcode the name of shortcode calling, provides "shortcode_atts_$shortcode" filter
474 * @param $defaults allows overriding the default shortcode atts, before being replaced by $atts
475 *
476 * @return array
477 */
478 function themify_event_post_parse_shortcode_ids( $category ) {
479
480 if ( ! is_array( $category ) ) {
481 $category = array_map( 'trim', explode( ',', $category ) );
482 }
483
484 $ids_in = $ids_not_in = $slugs_in = $slugs_not_in = array();
485 foreach ( $category as $v ) {
486 $v = trim( $v );
487 $except = '-' !== $v[0];
488 if ( is_numeric( $v ) ) {
489 if( $except === true ) {
490 $ids_in[] = $v;
491 } else {
492 $ids_not_in[] = abs( $v );
493 }
494 }
495 else{
496 if( $except === true ) {
497 $slugs_in[] = $v;
498 } else {
499 $slugs_not_in[] = substr( $v, 1 );
500 }
501 }
502 }
503 return array( $ids_in, $ids_not_in, $slugs_in, $slugs_not_in );
504 }
505
506 /**
507 * Parses $args to return a formatted array for WP_Query object
508 *
509 * @return array
510 * @since 1.0.2
511 */
512 function themify_event_post_past_posts_clauses( $clauses, $query ) {
513 if ( empty( $query->query_vars['tep_past_filter'] ) ) {
514 return $clauses;
515 }
516
517 global $wpdb;
518 $now = current_time( 'Y-m-d H:i' );
519
520 $clauses['join'] .= $wpdb->prepare(
521 " INNER JOIN {$wpdb->postmeta} AS tep_ed ON ({$wpdb->posts}.ID = tep_ed.post_id AND tep_ed.meta_key = 'end_date' AND tep_ed.meta_value != '' AND tep_ed.meta_value < %s) ",
522 $now
523 );
524
525 if ( ! empty( $query->query_vars['tep_event_date_order'] ) ) {
526 $clauses['join'] .= " INNER JOIN {$wpdb->postmeta} AS tep_sd ON ({$wpdb->posts}.ID = tep_sd.post_id AND tep_sd.meta_key = 'start_date') ";
527 $order = ( isset( $query->query_vars['order'] ) && 'asc' === strtolower( $query->query_vars['order'] ) ) ? 'ASC' : 'DESC';
528 $clauses['orderby'] = "tep_sd.meta_value {$order}";
529 }
530
531 return $clauses;
532 }
533
534 function themify_event_post_apply_event_meta_query( $query_args, $event_meta ) {
535 if ( ! empty( $event_meta['past_filter'] ) ) {
536 $query_args['tep_past_filter'] = true;
537 if ( ! empty( $event_meta['event_date_order'] ) ) {
538 $query_args['tep_event_date_order'] = true;
539 }
540 if ( null !== $event_meta['orderby'] ) {
541 $query_args['orderby'] = $event_meta['orderby'];
542 }
543 return $query_args;
544 }
545
546 if ( null !== $event_meta['meta_query'] ) {
547 $query_args['meta_query'] = $event_meta['meta_query'];
548 }
549 if ( null !== $event_meta['orderby'] ) {
550 $query_args['orderby'] = $event_meta['orderby'];
551 }
552 if ( null !== $event_meta['meta_key'] ) {
553 $query_args['meta_key'] = $event_meta['meta_key'];
554 }
555
556 return $query_args;
557 }
558
559 function themify_event_post_build_event_meta_query( $show, $orderby, $now ) {
560 $meta = array(
561 'meta_query' => null,
562 'orderby' => null,
563 'meta_key' => null,
564 'past_filter' => false,
565 'event_date_order' => false,
566 );
567
568 if ( $show === 'upcoming' && $orderby === 'event_date' ) {
569 $meta['meta_query'] = array(
570 'relation' => 'OR',
571 'start_date_clause' => array(
572 'key' => 'start_date',
573 'value' => $now,
574 'compare' => '>=',
575 ),
576 array(
577 'key' => 'end_date',
578 'value' => $now,
579 'compare' => '>=',
580 ),
581 array(
582 'key' => 'repeat',
583 'value' => 'none',
584 'compare' => '!=',
585 ),
586 );
587 $meta['orderby'] = 'start_date_clause';
588 } elseif ( $show === 'past' ) {
589 $meta['past_filter'] = true;
590 if ( $orderby === 'event_date' ) {
591 $meta['event_date_order'] = true;
592 $meta['orderby'] = 'none';
593 }
594 } elseif ( $show === 'upcoming' ) {
595 $meta['meta_query'] = array(
596 'relation' => 'OR',
597 array(
598 'key' => 'end_date',
599 'value' => $now,
600 'compare' => '>=',
601 ),
602 array(
603 'key' => 'start_date',
604 'value' => $now,
605 'compare' => '>=',
606 ),
607 array(
608 'key' => 'repeat',
609 'value' => 'none',
610 'compare' => '!=',
611 ),
612 );
613 }
614
615 if ( $orderby === 'event_date' && null === $meta['orderby'] && empty( $meta['past_filter'] ) ) {
616 $meta['orderby'] = 'meta_value';
617 $meta['meta_key'] = 'start_date';
618 }
619
620 return $meta;
621 }
622
623 function themify_event_post_parse_query( $args = array() ) {
624 $defaults = array(
625 'post_type' => 'event',
626 'taxonomy' => 'event-category',
627 'taxonomy_relation' => 'AND',
628 'limit' => 3,
629 'offset' => 0,
630 'category' => '0', // integer category ID
631 'orderby' => 'event_date', // date, title, rand, event_date
632 'order' => 'DESC', // ASC
633 'show' => 'upcoming',
634 'id' => '',
635 );
636 $args = shortcode_atts( $defaults, $args );
637 extract( $args );
638
639 $paged = themify_event_post_get_paged_query();
640 $query_args = array(
641 'post_type' => $post_type,
642 'offset' => ( ( $paged - 1 ) * (int) $limit ) + (int) $offset,
643 'posts_per_page' => $limit,
644 'suppress_filters' => false,
645 'orderby' => $orderby,
646 'order' => $order,
647 );
648
649 if ( ! empty( $args['id'] ) ) {
650 $query_args['p'] = $args['id'];
651 return $query_args;
652 }
653
654 // handle weird way Builder saves query_cat field types
655 $category = preg_replace( '/\|[multiple|single]*$/', '', $category );
656
657 if ( '0' !== $category && ! empty( $category ) ) {
658
659 list( $ids_in, $ids_not_in, $slugs_in, $slugs_not_in ) = themify_event_post_parse_shortcode_ids( $category );
660
661 $query_args['tax_query'] = array(
662 'relation' => $taxonomy_relation
663 );
664 if ( ! empty( $ids_in ) ) {
665 $query_args['tax_query'][] = array(
666 'taxonomy' => $taxonomy,
667 'field' => 'id',
668 'terms' => $ids_in
669 );
670 }
671 if ( ! empty( $ids_not_in ) ) {
672 $query_args['tax_query'][] = array(
673 'taxonomy' => $taxonomy,
674 'field' => 'id',
675 'terms' => array_map( 'abs', $ids_not_in ),
676 'operator' => 'NOT IN'
677 );
678 }
679 if ( ! empty( $slugs_in ) ) {
680 $query_args['tax_query'][] = array(
681 'taxonomy' => $taxonomy,
682 'field' => 'slug',
683 'terms' => $slugs_in
684 );
685 }
686 if ( ! empty( $slugs_not_in ) ) {
687 $query_args['tax_query'][] = array(
688 'taxonomy' => $taxonomy,
689 'field' => 'slug',
690 'terms' => $slugs_not_in,
691 'operator' => 'NOT IN'
692 );
693 }
694 }
695
696 $now = current_time( 'Y-m-d H:i' );
697 $event_meta = themify_event_post_build_event_meta_query( $show, $orderby, $now );
698 $query_args = themify_event_post_apply_event_meta_query( $query_args, $event_meta );
699
700 if ( $show === 'past' ) {
701 $query_args['order'] = $order;
702 }
703
704 return $query_args;
705 }
706
707 if ( ! function_exists( 'themify_event_post_json_ld_generator' ) ) :
708 /**
709 * Generate the JSON-LD structure data
710 *
711 * @return string|null
712 * @since 1.0.1
713 */
714 function themify_event_post_json_ld_generator( $args = array() ) {
715 $schema = array(
716 '@context'=>'https://schema.org',
717 '@type'=>'Event',
718 'name'=>$args['name'],
719 'startDate'=>$args['start_date'],
720 'endDate'=>$args['end_date'],
721 'location'=>array(
722 '@type'=>'Place',
723 'name'=>$args['place'],
724 'address'=>array(
725 '@type'=>'PostalAddress',
726 'streetAddress'=>$args['address']
727 )
728 ),
729 'image'=>!empty($args['image']) ? array($args['image']) : array(),
730 'description'=>$args['decription'],
731 'offers'=>array(
732 '@type'=>'Offer',
733 'url'=>$args['buy_ticket'],
734 'price'=>$args['ticket_price'],
735 'priceCurrency'=>$args['ticket_currency'],
736 'validFrom'=>$args['ticket_purchase_start'],
737 'validThrough'=>$args['ticket_purchase_end'],
738 'availability'=>''
739 ),
740 'performer'=>array(
741 '@type'=>'',
742 'name'=>''
743 ),
744 'organizer'=>array(
745 '@type'=>'',
746 'name'=>'',
747 'url'=>''
748 ),
749 'eventAttendanceMode'=>'',
750 'eventStatus'=>'',
751 );
752
753 $timezone = new DateTimeZone( wp_timezone_string() );
754 if (!empty($args['event_attendance'])) $schema['eventAttendanceMode'] = 'https://schema.org/' . $args['event_attendance'] . 'EventAttendanceMode';
755 else unset($schema['eventAttendanceMode']);
756
757 if (empty($args['event_status'])) $args['event_status'] = 'Scheduled';
758 $schema['eventStatus'] = 'https://schema.org/Event' . $args['event_status'];
759
760 if (!empty($args['organizer_name']) || !empty($args['organizer_url'])){
761 $schema['organizer']['@type'] = $args['organizer'];
762 $schema['organizer']['name'] = $args['organizer_name'];
763 $schema['organizer']['url'] = $args['organizer_url'];
764 } else unset($schema['organizer']);
765
766 if (!empty($args['performer_name'])){
767 $schema['performer']['@type'] = $args['performer'];
768 $schema['performer']['name'] = $args['performer_name'];
769 } else unset($schema['performer']);
770
771 if (!empty($args['ticket_availability'])) $schema['offers']['availability'] = 'https://schema.org/' . $args['ticket_availability'];
772 else unset($schema['offers']['availability']);
773
774 if ( ! empty( $schema['startDate'] ) ) {
775 $schema['startDate'] = date_create( $schema['startDate'], $timezone )->format( 'c' );
776 }
777
778 if ( ! empty( $schema['endDate'] ) ) {
779 $schema['endDate'] = date_create( $schema['endDate'], $timezone )->format( 'c' );
780 }
781
782 if ( ! empty( $schema['validFrom'] ) ) {
783 $schema['validFrom'] = date_create( $schema['validFrom'], $timezone )->format( 'c' );
784 }
785
786 if ( ! empty( $schema['validThrough'] ) ) {
787 $schema['validThrough'] = date_create( $schema['validThrough'], $timezone )->format( 'c' );
788 }
789
790 $output =
791 '<script type="application/ld+json">'
792 . json_encode( array( $schema ) )
793 . '</script>';
794
795 return $output;
796 }
797 endif;
798
799 /**
800 * Resize images dynamically using wp built in functions
801 *
802 * @param string|int $image Image URL or an attachment ID
803 * @param int $width
804 * @param int $height
805 * @param bool $crop
806 * @return array
807 */
808 function themify_events_do_img( $image, $width, $height, $crop = false ) {
809 $attachment_id = null;
810 $img_url = null;
811
812 $width = is_numeric( $width ) ? $width : '';
813 $height = is_numeric( $height ) ? $height : '';
814 // if an attachment ID has been sent
815 if( is_int( $image ) ) {
816 $post = get_post( $image );
817 if( $post ) {
818 $attachment_id = $post->ID;
819 $img_url = wp_get_attachment_url( $attachment_id );
820 }
821 } else {
822 // URL has been passed to the function
823 $img_url = esc_url( $image );
824
825 // Check if the image is an attachment. If it's external return url, width and height.
826 $upload_dir = wp_get_upload_dir();
827 $base_url = preg_replace( '/https?:\/\/(www\.)?/', '', $upload_dir['baseurl'] ); // Removes protocol and WWW
828 if( ! preg_match( '/' . str_replace( '/', '\/', $base_url ) . '/', $img_url ) ) {
829 return array(
830 'url' =>$img_url,
831 'width' => $width,
832 'height' => $height,
833 );
834 }
835
836 // Finally, run a custom database query to get the attachment ID from the modified attachment URL
837 $attachment_id = themify_events_get_attachment_id_from_url( $img_url, $base_url );
838 }
839 // Fetch attachment meta data. Up to this point we know the attachment ID is valid.
840 $meta = $attachment_id ?wp_get_attachment_metadata( $attachment_id ):null;
841
842 // missing metadata. bail.
843 if ( ! is_array( $meta ) ) {
844 return array(
845 'url' => $img_url,
846 'width' => $width,
847 'height' => $height,
848 );
849 }
850
851 // Perform calculations when height or width = 0
852 if( empty( $width ) ) {
853 $width = 0;
854 }
855 if ( empty( $height ) ) {
856 // If width and height or original image are available as metadata
857 if ( !empty( $meta['width'] ) && !empty( $meta['height'] ) ) {
858 // Divide width by original image aspect ratio to obtain projected height
859 // The floor function is used so it returns an int and metadata can be written
860 $height = floor( $width / ( $meta['width'] / $meta['height'] ) );
861 } else {
862 $height = 0;
863 }
864 }
865 // Check if resized image already exists
866 if ( is_array( $meta ) && isset( $meta['sizes']["resized-{$width}x{$height}"] ) ) {
867 $size = $meta['sizes']["resized-{$width}x{$height}"];
868 if( isset( $size['width'],$size['height'] )) {
869 setlocale( LC_CTYPE, get_locale() . '.UTF-8' );
870 $split_url = explode( '/', $img_url );
871
872 if( ! isset( $size['mime-type'] ) || $size['mime-type'] !== 'image/gif' ) {
873 $split_url[ count( $split_url ) - 1 ] = $size['file'];
874 }
875
876 return array(
877 'url' => implode( '/', $split_url ),
878 'width' => $width,
879 'height' => $height,
880 'attachment_id' => $attachment_id,
881 );
882 }
883 }
884
885 // Requested image size doesn't exists, so let's create one
886 if ( true == $crop ) {
887 add_filter( 'image_resize_dimensions', 'themify_events_img_resize_dimensions', 10, 5 );
888 }
889 // Patch meta because if we're here, there's a valid attachment ID for sure, but maybe the meta data is not ok.
890 if ( empty( $meta ) ) {
891 $meta['sizes'] = array( 'large' => array() );
892 }
893 // Generate image returning an array with image url, width and height. If image can't generated, original url, width and height are used.
894 $image = themify_events_make_image_size( $attachment_id, $width, $height, $meta, $img_url );
895
896 if ( true == $crop ) {
897 remove_filter( 'image_resize_dimensions', 'themify_events_img_resize_dimensions', 10 );
898 }
899 $image['attachment_id'] = $attachment_id;
900 return $image;
901 }
902
903 /**
904 * Creates new image size.
905 *
906 * @uses get_attached_file()
907 * @uses image_make_intermediate_size()
908 * @uses wp_update_attachment_metadata()
909 * @uses get_post_meta()
910 * @uses update_post_meta()
911 *
912 * @param int $attachment_id
913 * @param int $width
914 * @param int $height
915 * @param array $meta
916 * @param string $img_url
917 *
918 * @return array
919 */
920 function themify_events_make_image_size( $attachment_id, $width, $height, $meta, $img_url ) {
921 if($width!==0 || $height!==0){
922 setlocale( LC_CTYPE, get_locale() . '.UTF-8' );
923 $attached_file = get_attached_file( $attachment_id );
924
925 $default_size = function_exists( 'themify_get' )
926 ? themify_get( 'setting-img_php_base_size', 'large', true )
927 : 'large';
928 $source_size = apply_filters( 'themify_image_script_source_size', $default_size );
929 if ( $source_size !== 'full' && isset( $meta['sizes'][ $source_size ]['file'] ) )
930 $attached_file = str_replace( $meta['file'], trailingslashit( dirname( $meta['file'] ) ) . $meta['sizes'][ $source_size ]['file'], $attached_file );
931
932 $resized = image_make_intermediate_size( $attached_file, $width, $height, true );
933 if ( $resized && ! is_wp_error( $resized ) ) {
934
935 // Save the new size in meta data
936 $key = sprintf( 'resized-%dx%d', $width, $height );
937 $meta['sizes'][$key] = $resized;
938 $img_url = str_replace( basename( $img_url ), $resized['file'], $img_url );
939
940 wp_update_attachment_metadata( $attachment_id, $meta );
941
942 // Save size in backup sizes so it's deleted when original attachment is deleted.
943 $backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
944 if ( ! is_array( $backup_sizes ) ) $backup_sizes = array();
945 $backup_sizes[$key] = $resized;
946 update_post_meta( $attachment_id, '_wp_attachment_backup_sizes', $backup_sizes );
947 $img_url=esc_url($img_url);
948 }
949 }
950 // Return original image url, width and height.
951 return array(
952 'url' => $img_url,
953 'width' => $width,
954 'height' => $height
955 );
956 }
957
958 /**
959 * Disable the min commands to choose the minimum dimension, thus enabling image enlarging.
960 *
961 * @param $default
962 * @param $orig_w
963 * @param $orig_h
964 * @param $dest_w
965 * @param $dest_h
966 * @return array
967 */
968 function themify_events_img_resize_dimensions( $default, $orig_w, $orig_h, $dest_w, $dest_h ) {
969 // set portion of the original image that we can size to $dest_w x $dest_h
970 $aspect_ratio = $orig_w / $orig_h;
971 $new_w = $dest_w;
972 $new_h = $dest_h;
973
974 if ( !$new_w ) {
975 $new_w = (int)( $new_h * $aspect_ratio );
976 }
977
978 if ( !$new_h ) {
979 $new_h = (int)( $new_w / $aspect_ratio );
980 }
981
982 $size_ratio = max( $new_w / $orig_w, $new_h / $orig_h );
983
984 $crop_w = round( $new_w / $size_ratio );
985 $crop_h = round( $new_h / $size_ratio );
986
987 $s_x = floor( ( $orig_w - $crop_w ) / 2 );
988 $s_y = floor( ( $orig_h - $crop_h ) / 2 );
989
990 // the return array matches the parameters to imagecopyresampled()
991 // int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h
992 return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );
993 }
994
995 /**
996 * Get attachment ID for image from its url.
997 *
998 * @param string $url
999 * @param string $base_url
1000 * @return bool|null|string
1001 */
1002 function themify_events_get_attachment_id_from_url( $url = '', $base_url = '' ) {
1003 // If this is the URL of an auto-generated thumbnail, get the URL of the original image
1004 $url = preg_replace( '/-\d+x\d+(?=\.(jpg|jpeg|png|gif|webp)$)/i', '', $url );
1005
1006 $id = attachment_url_to_postid( $url );
1007 return $id;
1008 }
1009
1010 /**
1011 * Template function to display the ticket price for an event.
1012 * Must be used inside the loop, or provide a post_id|WP_Post object for $post param.
1013 *
1014 * @since 1.2.5
1015 */
1016 function themify_event_post_get_price( $post = null, $before = '', $after = '' ) {
1017 $post = get_post( $post );
1018 $price = get_post_meta( $post->ID, 'buy_tickets_price', true );
1019 if ( empty( $price ) ) {
1020 return '';
1021 }
1022
1023 $currency = get_post_meta( $post->ID, 'buy_tickets_currency', true );
1024 if ( empty( $currency ) ) {
1025 $currency = Themify_Event_Post::get_instance()->get_option( 'currency' );
1026 }
1027 $currency_pos = Themify_Event_Post::get_instance()->get_option( 'currency_pos', 'right_space' );
1028 switch ( $currency_pos ) {
1029 case 'left':
1030 $format = '%2$s%1$s';
1031 break;
1032 case 'right':
1033 $format = '%1$s%2$s';
1034 break;
1035 case 'left_space':
1036 $format = '%2$s %1$s';
1037 break;
1038 default:
1039 $format = '%1$s %2$s';
1040 }
1041
1042 return $before . sprintf( $format, $price, $currency ) . $after;
1043 }
1044
1045 if ( ! function_exists( 'themify_event_post_edit_link' ) ) :
1046 function themify_event_post_edit_link() {
1047 if ( function_exists( 'themify_post_edit_link' ) ) {
1048 themify_post_edit_link();
1049 } else {
1050 edit_post_link();
1051 }
1052 }
1053 endif;
1054
1055 if ( ! function_exists( 'themify_event_get_buy_ticket' ) ) :
1056 function themify_event_get_buy_ticket( $post = null ) : string {
1057 $post = get_post( $post );
1058 $output = '';
1059 if ( $buy_ticket = get_post_meta( $post->ID, 'buy_tickets', true ) ) {
1060 $buy_tickets_label = get_post_meta( $post->ID, 'buy_tickets_label', true );
1061 if ( ! $buy_tickets_label ) {
1062 $buy_tickets_label = __( 'Buy Tickets', 'themify-event-post' );
1063 }
1064
1065 $is_visible = true;
1066 $start_date = get_post_meta( $post->ID, 'ticket_purchase_start_date', true );
1067 $end_date = get_post_meta( $post->ID, 'ticket_purchase_end_date', true );
1068 $time = time();
1069 if (
1070 ( $start_date && $time < strtotime( $start_date ) )
1071 || ( $end_date && $time > strtotime( $end_date ) )
1072 ) {
1073 $is_visible = false;
1074 }
1075
1076 $attr = [
1077 'target' => '_blank',
1078 'class' => 'tep_ticket_link'
1079 ];
1080 if ( $is_visible ) {
1081 $attr['href'] = $buy_ticket;
1082 } else {
1083 $attr['href'] = '#';
1084 $attr['class'] .= ' tep_ticket_disabled';
1085 $attr['data-tep_tooltip'] = __( 'Purchase is not available at the moment.', 'themify-event-post' );
1086 }
1087
1088 $buy_tickets_label .= themify_event_post_get_price( null, ' - ' );
1089 $output = sprintf( '<a %s>%s</a>', themify_event_build_atts( $attr ), wp_kses_post( $buy_tickets_label ) );
1090 }
1091
1092 return $output;
1093 }
1094 endif;
1095
1096 if ( ! function_exists( 'themify_event_buy_ticket' ) ) :
1097 function themify_event_buy_ticket( $before = '<p class="tep_ticket">', $after = '</p>' ) {
1098 $buy_button = themify_event_get_buy_ticket();
1099 if ( $buy_button ) {
1100 echo $before, $buy_button, $after;
1101 }
1102 }
1103 endif;
1104
1105 function themify_event_is_visible( $post = null ) : bool {
1106 $post = get_post( $post );
1107
1108 $end_date = get_post_meta( $post->ID, 'end_date', true );
1109 $time = time();
1110 if ( $end_date && $time > strtotime( $end_date ) ) {
1111 return false;
1112 }
1113
1114 return true;
1115 }
1116
1117 function themify_event_build_atts( $atts = array() ) : string {
1118 $attribute_string = '';
1119 foreach ( $atts as $attr => $value ) {
1120 if ( false !== $value && '' !== $value && is_scalar( $value ) ) {
1121 $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
1122 $attribute_string .= ' ' . $attr . '="' . $value . '"';
1123 }
1124 }
1125 return $attribute_string;
1126 }
1127
1128 /**
1129 * Sanitize user-provided shortcode wrapper templates.
1130 *
1131 * WordPress core unescapes shortcode attributes (e.g. "\\x3c" -> "<").
1132 * Without sanitization, template_before/template_after can be used for XSS.
1133 *
1134 * @param string $html Wrapper HTML.
1135 * @return string Sanitized HTML.
1136 */
1137 function themify_event_post_sanitize_template_wrapper( $html ) : string {
1138 if ( $html === '' || ! is_string( $html ) ) {
1139 return '';
1140 }
1141
1142 $allowed = array(
1143 'div' => array( 'class' => true, 'id' => true, 'role' => true, 'aria-label' => true, 'aria-hidden' => true ),
1144 'span' => array( 'class' => true, 'id' => true, 'role' => true, 'aria-label' => true, 'aria-hidden' => true ),
1145 'p' => array( 'class' => true, 'id' => true ),
1146 'br' => array(),
1147 'ul' => array( 'class' => true, 'id' => true ),
1148 'ol' => array( 'class' => true, 'id' => true ),
1149 'li' => array( 'class' => true, 'id' => true ),
1150 'a' => array( 'href' => true, 'class' => true, 'id' => true, 'rel' => true, 'target' => true, 'title' => true, 'aria-label' => true ),
1151 'strong' => array(),
1152 'em' => array(),
1153 'b' => array(),
1154 'i' => array(),
1155 'h1' => array( 'class' => true, 'id' => true ),
1156 'h2' => array( 'class' => true, 'id' => true ),
1157 'h3' => array( 'class' => true, 'id' => true ),
1158 'h4' => array( 'class' => true, 'id' => true ),
1159 'h5' => array( 'class' => true, 'id' => true ),
1160 'h6' => array( 'class' => true, 'id' => true ),
1161 'section' => array( 'class' => true, 'id' => true, 'role' => true, 'aria-label' => true ),
1162 'article' => array( 'class' => true, 'id' => true, 'role' => true, 'aria-label' => true ),
1163 'header' => array( 'class' => true, 'id' => true ),
1164 'footer' => array( 'class' => true, 'id' => true ),
1165 'nav' => array( 'class' => true, 'id' => true, 'role' => true, 'aria-label' => true ),
1166 );
1167
1168 return wp_kses( $html, $allowed );
1169 }