PluginProbe
FareHarbor for WordPress / 3.1
FareHarbor for WordPress v3.1
3.6.15 3.6.14 trunk 1.1 1.2 2.0 2.1 3.0 3.0.1 3.1 3.2 3.3 3.3.1 3.4 3.5 3.6 3.6.1 3.6.10 3.6.11 3.6.12 3.6.13 3.6.2 3.6.3 3.6.4 3.6.5 All 29 releases
fareharbor / fareharbor.php

fareharbor.php in FareHarbor for WordPress 3.1, at fareharbor.php

1,106 lines 31.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: FareHarbor Reservation Calendars
4 Plugin URI: https://fareharbor.com/help/setup/wordpress-plugin/
5 Description: Easily add FareHarbor reservation calendars and buttons to your site
6 Version: 3.1
7 Author: FareHarbor
8 Author URI: https://fareharbor.com
9 */
10
11 // Make sure this file isn't loaded on its own
12 // -----------------------------------------------
13
14 defined( 'ABSPATH' ) or die( 'Lost? <a href="/">Return home.</a>' );
15
16
17 // Register the shortcodes
18 // -----------------------------------------------
19
20 add_shortcode( 'fareharbor', array( 'fareharbor', 'fareharbor_shortcode' ) );
21 add_shortcode( 'lightframe', array( 'fareharbor', 'lightframe_shortcode' ) );
22 add_shortcode( 'partners', array( 'fareharbor', 'partners_shortcode' ) );
23 add_shortcode( 'itemgrid', array( 'fareharbor', 'itemgrid_shortcode' ) );
24 // add_shortcode( 'bookembed', array( 'fareharbor', 'bookembed_shortcode' ) );
25
26 // Register our Settings Page & Settings
27 // -----------------------------------------------
28
29 add_action( 'admin_menu', array( 'fareharbor', 'register_options_page' ) );
30 add_action( 'admin_init', array( 'fareharbor', 'register_settings' ) );
31
32
33 // Include the script in the footer
34 // -----------------------------------------------
35
36 add_action( 'wp_footer', array( 'fareharbor', 'lightframe_api_footer' ) );
37
38
39 // Maybe include fh-kit styles in header
40 // -----------------------------------------------
41 // Depends on option being set in the admin dashboard
42 add_action( 'wp_enqueue_scripts', array( 'fareharbor', 'maybe_enqueue_fh_kit_styles' ) );
43
44
45 // Add init hook
46 // -----------------------------------------------
47
48 add_action( 'init', array( 'fareharbor', 'init' ) );
49
50 // Global functions for potential backwards compatability
51 // -----------------------------------------------
52
53 function fh_shortcode( $attrs ) {
54 return fareharbor::fareharbor_shortcode( $attrs );
55 }
56
57 function lightframe_shortcode( $attrs, $content = '' ) {
58 return fareharbor::lightframe_shortcode( $attrs, $content );
59 }
60
61 function partners_shortcode( $attrs ) {
62 return fareharbor::partners_shortcode( $attrs );
63 }
64
65
66 // The important stuff
67 // -----------------------------------------------
68
69 final class fareharbor {
70
71 // This class is just a namespace for static methods & variables
72 private function __construct() {}
73
74 public static $version = '3.1';
75
76 // Update the saved version number in the wp_options table
77 // ===============================================
78
79 public static function init() {
80
81 if ( is_admin() && ( !defined( 'DOING_AJAX' ) || !DOING_AJAX ) )
82 update_option( 'fareharbor_version', self::$version );
83
84 }
85
86 // Script source
87 // ===============================================
88
89 public static function lightframe_api_footer() {
90
91 $src = 'https://' . self::url() . '/embeds/api/v1/';
92
93 if ( self::get_option( 'fh_auto_lightframe_enabled' ) )
94 $src .= '?autolightframe=yes';
95
96 echo "<!-- FareHarbor plugin activated --><script src=\"$src\"></script>";
97
98 }
99
100
101 // FH-Kit Styles
102 // ===============================================
103
104 public static function maybe_enqueue_fh_kit_styles() {
105
106 if ( self::is_lite() )
107 return;
108
109 if( !self::get_option( 'fh_buttons_active' ) )
110 return;
111
112 $query_string = self::get_option( 'fh_buttons_query' );
113
114 $query_string = strip_tags( $query_string );
115 $query_string = trim( $query_string );
116 $query_string = ltrim( $query_string, '?' );
117
118 $fh_kit_src = 'https://fh-kit.com/buttons/v1/';
119
120 if ( $query_string )
121 $fh_kit_src .= '?' . $query_string;
122
123 $fh_kit_src = apply_filters( 'fareharbor/buttons_style_src', $fh_kit_src );
124
125 // the 4th parameter is $version. Leaving it out causes WP to
126 // add ver={current-wp-version} to the url. passing null stops this.
127 wp_enqueue_style( 'fh-buttons', $fh_kit_src, array(), null );
128
129 }
130
131
132 // Default Arguments
133 // ===============================================
134
135 private static $shared_defaults,
136 $lightframe_defaults,
137 $calendar_defaults,
138 $partners_defaults,
139 $itemgrid_defaults,
140 $bookembed_defaults;
141
142 private static function init_defaults() {
143
144 if ( isset( self::$shared_defaults ) )
145 return;
146
147 self::$shared_defaults = array(
148
149 'shortname' => self::get_option( 'fh_default_shortname', '' ),
150 'items' => '',
151 'asn' => self::get_option( 'fh_default_asn', '' ),
152 'asn_ref' => self::get_option( 'fh_default_asn_ref', '' ),
153 'ref' => self::get_option( 'fh_default_ref', '' ),
154 'lightframe' => self::get_option( 'fh_default_lightframe', 'yes' ),
155 'full_items' => self::get_option( 'fh_default_full_items', 'no' ),
156 'sheet' => self::get_option( 'fh_default_sheet', '' ),
157 'fallback' => self::get_option( 'fh_default_fallback', '' ),
158
159 );
160
161 self::$bookembed_defaults =
162 self::$lightframe_defaults = array(
163
164 // 'class' => '',
165 // 'style' => '',
166 // 'id' => '',
167 'view' => 'items',
168 'view_item' => '',
169 'view_availability' => '',
170
171 );
172 self::$bookembed_defaults[ 'fallback' ] = '';
173
174 self::$calendar_defaults = array();
175
176 if ( self::get_option( 'fh_responsive_calendars', false ) )
177 self::$calendar_defaults[ 'type' ] = 'calendar';
178 else
179 self::$calendar_defaults[ 'type' ] = 'calendar-small';
180
181 self::$partners_defaults = array(
182
183 'include' => '',
184
185 );
186
187 self::$itemgrid_defaults = array();
188
189 }
190
191
192 // [lightframe][/lightframe] shortcode
193 // ===============================================
194
195 public static function lightframe_shortcode( $attrs, $content = '' ) {
196
197 $link_attrs = self::lightframe_link_attrs( $attrs );
198
199 if ( $error = self::maybe_handle_shortcode_error( $link_attrs ) )
200 return $error;
201
202 if ( !empty( $attrs[ 'class' ] ) )
203 $link_attrs[ 'class' ] = $attrs[ 'class' ];
204 elseif ( $default_class = self::get_option( 'fh_default_class' ) )
205 $link_attrs[ 'class' ] = $default_class;
206
207 if ( !empty( $attrs[ 'id' ] ) )
208 $link_attrs[ 'id' ] = $attrs[ 'id' ];
209
210 if ( !empty( $attrs[ 'style' ] ) )
211 $link_attrs[ 'style' ] = $attrs[ 'style' ];
212
213 $link_attrs = array_map( 'strip_tags', $link_attrs );
214
215 $link_attrs_string = '';
216 foreach ( $link_attrs as $name => $value )
217 $link_attrs_string .= " $name=\"$value\"";
218
219 if ( trim( $content ) )
220 $content = do_shortcode( $content );
221
222 return "<a$link_attrs_string>$content</a>";
223
224 }
225
226 public static function lightframe_link_attrs( $args ) {
227
228 if ( !isset( self::$lightframe_defaults ) )
229 self::init_defaults();
230
231 $args = self::process_args( $args, self::$lightframe_defaults, 'lightframe' );
232
233 if ( isset( $args[ 'error' ] ) )
234 return $args;
235
236 if ( $args[ 'view_availability' ] && !$args[ 'view_item' ] )
237 return array( 'error' => 'view_availability but no view_item' );
238
239 $fallback_url = self::lightframe_fallback_url( $args );
240
241 $api_options = self::lightframe_api_options( $args );
242 $json = strtr( json_encode( $api_options ), '"', "'" );
243
244 return array(
245 'href' => $fallback_url,
246 'target' => '_blank',
247 'onclick' => "FH.open($json); return false;",
248 );
249
250 }
251
252 private static function lightframe_fallback_url( $args, $is_bookembed = false ) {
253
254 // The bookembed url structure is very similar to the simple fallback url structure
255 $is_simple_fallback = ( $args[ 'fallback' ] === 'simple' ) || $is_bookembed;
256
257 $url = 'https://' . self::url() . '/';
258
259 if ( $is_bookembed )
260 $url .= 'embeds/script/book/';
261 elseif ( $is_simple_fallback )
262 $url .= 'embeds/book/';
263
264 $url .= $args[ 'shortname' ] . '/';
265
266 if ( !$is_simple_fallback
267 || $args[ 'view' ] === 'all-availability'
268 || $args[ 'view_item' ]
269 ) {
270 $url .= 'items/';
271 }
272
273 if ( $args[ 'view_item' ] ) {
274
275 $url .= $args[ 'view_item' ] . '/';
276
277 if ( $args[ 'view_availability' ] )
278 $url .= 'availability/' . $args[ 'view_availability' ] . '/book/';
279 elseif ( $args[ 'full_items' ] === 'no' )
280 $url .= 'calendar/';
281
282 } elseif ( $args[ 'view' ] === 'all-availability' ) {
283
284 $url .= 'calendar/';
285
286 }
287
288 $query = self::get_shared_args_array( $args, 'dash', $is_simple_fallback, false );
289
290 if ( $is_simple_fallback && $args[ 'items' ] )
291 $query[ 'selected-items' ] = $args[ 'items' ];
292
293 if ( !$is_bookembed ) {
294
295 $current_url = get_home_url();
296 if ( !$current_url ) {
297 $current_url = ( is_ssl() ? 'https' : 'http' ) . '://'
298 . ( !empty( $_SERVER[ 'HTTP_HOST' ] ) ? $_SERVER[ 'HTTP_HOST' ] : $_SERVER[ 'SERVER_NAME' ] );
299 }
300 $current_url .= $_SERVER[ 'REQUEST_URI' ];
301
302 if ( $is_simple_fallback )
303 $query[ 'referrer' ] = $current_url;
304
305 }
306
307 if ( $query )
308 $url .= '?' . http_build_query( $query );
309
310 return $url;
311
312 }
313
314 private static function lightframe_api_options( $args ) {
315
316 $lo = array( 'shortname' => $args[ 'shortname' ] );
317
318 // Filter the visible items
319 if ( $args[ 'items' ] )
320 // putting it in an array so it gets brackets in json_encode
321 $lo[ 'items' ] = explode( ',', $args[ 'items' ] );
322
323 // Set the view
324 if ( $args[ 'view_item' ] ) {
325
326 $lo[ 'view' ] = array( 'item' => $args[ 'view_item' ] );
327
328 if ( $args[ 'view_availability' ] )
329 $lo[ 'view' ][ 'availability' ] = $args[ 'view_availability' ];
330
331 } elseif ( in_array( $args[ 'view' ], array( 'items', 'all-availability' ), true ) ) {
332
333 $lo[ 'view' ] = $args[ 'view' ];
334
335 } else {
336
337 $lo[ 'view' ] = 'items';
338
339 }
340
341 // Modifiers: shared args like fallback, asn, asn_ref, etc.
342 $lo += self::get_shared_args_array( $args, 'camel', true, true );
343
344 return $lo;
345
346 }
347
348
349 // [bookembed] shortcode
350 // ===============================================
351
352 public static function bookembed_shortcode( $attrs ) {
353
354 $script_src = self::bookembed_script_src( $attrs );
355
356 $maybe_error = self::maybe_handle_shortcode_error( $script_src );
357 return $maybe_error ? $maybe_error : "<script src=\"$script_src\"></script>";
358
359 }
360
361 public static function bookembed_script_src( $args ) {
362
363 if ( !isset( self::$bookembed_defaults ) )
364 self::init_defaults();
365
366 $args = self::process_args( $args, self::$bookembed_defaults, 'bookembed' );
367
368 if ( isset( $args[ 'error' ] ) )
369 return $args;
370
371 if ( $args[ 'view_availability' ] && !$args[ 'view_item' ] )
372 return array( 'error' => 'view_availability but no view_item' );
373
374 return self::lightframe_fallback_url( $args, true );
375
376 }
377
378
379 // [fareharbor] shortcode (calendar)
380 // ===============================================
381
382 public static function fareharbor_shortcode( $attrs ) {
383
384 $script_src = self::calendar_script_src( $attrs );
385
386 $maybe_error = self::maybe_handle_shortcode_error( $script_src );
387 return $maybe_error ? $maybe_error : "<script src=\"$script_src\"></script>";
388
389 }
390
391 public static function calendar_script_src( $args ) {
392
393 if ( !isset( self::$calendar_defaults ) )
394 self::init_defaults();
395
396 $args = self::process_args( $args, self::$calendar_defaults, 'fareharbor' );
397
398 if ( isset( $args[ 'error' ] ) )
399 return $args;
400
401 $type = $args[ 'type' ];
402 if ( $type === 'small' )
403 $type = 'calendar-small';
404 elseif ( $type === 'large' || $type === 'responsive' )
405 $type = 'calendar';
406
407 $url_suffix = '';
408 if ( $args[ 'items' ] )
409 $url_suffix = 'items/' . $args[ 'items' ] . '/';
410
411 return self::embed_script_src( $type, $args, $url_suffix, array(), false );
412
413 }
414
415
416 // [partners] shortcode
417 // ===============================================
418
419 public static function partners_shortcode( $attrs ) {
420
421 $script_src = self::partners_script_src( $attrs );
422
423 $maybe_error = self::maybe_handle_shortcode_error( $script_src );
424 return $maybe_error ? $maybe_error : "<script src=\"$script_src\"></script>";
425
426 }
427
428 public static function partners_script_src( $args ) {
429
430 if ( !isset( self::$partners_defaults ) )
431 self::init_defaults();
432
433 $args = self::process_args( $args, self::$partners_defaults, 'partners' );
434
435 if ( isset( $args[ 'error' ] ) )
436 return $args;
437
438 $query = array();
439 if ( $args[ 'include' ] )
440 $query[ 'include' ] = $args[ 'include' ];
441
442 return self::embed_script_src( 'partners', $args, '', $query, true );
443
444 }
445
446
447 // [items] shortcode
448 // ===============================================
449
450 public static function itemgrid_shortcode( $attrs ) {
451
452 $script_src = self::itemgrid_script_src( $attrs );
453
454 $maybe_error = self::maybe_handle_shortcode_error( $script_src );
455 return $maybe_error ? $maybe_error : "<script src=\"$script_src\"></script>";
456
457 }
458
459
460 public static function itemgrid_script_src( $args ) {
461
462 if ( !isset( self::$itemgrid_defaults ) )
463 self::init_defaults();
464
465 $args = self::process_args( $args, self::$itemgrid_defaults, 'itemgrid' );
466
467 if ( isset( $args[ 'error' ] ) )
468 return $args;
469
470 $query = array();
471 if ( $args[ 'items' ] )
472 $query[ 'selected-items' ] = $args[ 'items' ];
473
474 return self::embed_script_src( 'items', $args, $url_suffix, $query, true );
475
476 }
477
478
479 // Shared Shortcode Functionality
480 // ===============================================
481
482 // Handling Argument Input
483 // -----------------------------------------------
484
485 private static function process_args( $args, $defaults, $shortcode_name ) {
486
487 if ( !isset( self::$shared_defaults ) )
488 self::init_defaults();
489
490 $defaults += self::$shared_defaults;
491
492 if ( !is_array( $args ) ) // Just in case.
493 $args = $defaults;
494
495 // Trim whitespace && Strip Tags
496 $args = array_map( array( __CLASS__, 'sanitize' ), $args );
497
498 // Strip smart quotes, because WordPress returns them as part of the value if the shortcode was set up using them
499 $args = str_replace(
500 array( "\xe2\x80\x98", "\xe2\x80\x99", "\xe2\x80\x9c", "\xe2\x80\x9d", chr(145), chr(146), chr(147), chr(148) ),
501 array( '', '', '', '', '', '', '', '' ),
502 $args
503 );
504
505 // Merge in defaults
506 $args = shortcode_atts( $defaults, $args, $shortcode_name );
507
508 // Confirm there's a shortname. All of our shortcodes require this
509 if ( !$args[ 'shortname' ] )
510 return array( 'error' => 'no shortname' );
511
512 // Shortnames only work if lowercase
513 $args[ 'shortname' ] = strtolower( $args[ 'shortname' ] );
514
515 // Clean up item IDs and included companies because users can't be trusted
516 $csv_keys = array( 'items', 'view_item', 'include' );
517 foreach ( $csv_keys as $key )
518 if ( isset( $args[ $key ] ) )
519 $args[ $key ] = self::sanitize_csv( $args[ $key ] );
520
521 if ( $shortcode_name === 'lightframe' || $shortcode_name === 'bookembed' ) {
522
523 if ( !$args[ 'view_item' ] ) {
524 // See if we're filtering to just one item
525 // in that case we treat it as if it were
526 // passed to view_item instead
527 $items_array = explode( ',', $args[ 'items' ] );
528 if ( count( $items_array ) === 1 ) {
529 $args[ 'view_item' ] = $items_array[0];
530 $args[ 'items' ] = '';
531 }
532 }
533
534 }
535
536 return $args;
537
538 }
539
540 public static function sanitize( $value ) {
541
542 return trim( strip_tags( $value ) );
543
544 }
545
546 private static function sanitize_csv( $value ) {
547
548 return rtrim( str_replace( ' ', '', $value ), ',' );
549
550 }
551
552
553 // Handling Errors
554 // -----------------------------------------------
555
556 private static $error_messages = array(
557
558 'no shortname'
559 => '<p>Please provide a FareHarbor shortname. (Format: <code>shortname="yourshortname"</code>)</p>',
560 'view_availability but no view_item'
561 => '<p>Please provide <code>view_item</code> if using <code>view_availability</code>.</p>',
562
563 );
564
565 private static function maybe_handle_shortcode_error( $output ) {
566
567 if ( is_array( $output ) && !empty( $output[ 'error' ] ) ) {
568
569 return isset( self::$error_messages[ $output[ 'error' ] ] )
570 ? self::$error_messages[ $output[ 'error' ] ]
571 : '<p>' . $output[ 'error' ] . '</p>';
572
573 }
574
575 return false;
576
577 }
578
579
580 // Scripts for embeds (in use by [partners] and [fareharbor])
581 // -----------------------------------------------
582
583 private static function embed_script_src( $type, $args, $url_suffix, $query, $include_full_items ) {
584
585 $script_src = 'https://' . self::url() . '/embeds/script/'
586 . $type
587 . '/'
588 . $args[ 'shortname' ]
589 . '/'
590 . $url_suffix;
591
592 $args[ 'lightframe' ] = strtolower( trim( $args[ 'lightframe' ] ) );
593 if ( $args[ 'lightframe' ] === 'no' )
594 $query += array( 'lightframe' => $args[ 'lightframe' ] );
595
596 $query += self::get_shared_args_array( $args, 'dash', $include_full_items, true );
597
598 $query_string = http_build_query( $query );
599
600 return $script_src . ( $query_string ? "?$query_string" : '' );
601
602 }
603
604
605 // Shared arguments
606 // -----------------------------------------------
607
608 private static function get_shared_args_array( $args, $casing, $include_full_items, $include_fallback ) {
609
610 $out = array();
611
612 if ( $include_fallback && in_array( $args[ 'fallback' ], array( 'simple', 'classic' ) ) )
613 $out[ 'fallback' ] = $args[ 'fallback' ];
614
615 if ( $include_full_items && $args[ 'full_items' ] !== 'no' )
616 $out[ 'full_items' ] = $args[ 'full_items' ];
617
618 if ( $args[ 'asn' ] ) {
619
620 $out[ 'asn' ] = $args[ 'asn' ];
621
622 if ( $args[ 'asn_ref' ] )
623 $out[ 'asn_ref' ] = $args[ 'asn_ref' ];
624
625 }
626
627 if ( $args[ 'ref' ] )
628 $out[ 'ref' ] = $args[ 'ref' ];
629
630 if ( $args[ 'sheet' ] )
631 $out[ 'sheet' ] = $args[ 'sheet' ];
632
633 return self::fix_array_key_casing( $out, $casing );
634
635 }
636
637 private static function fix_array_key_casing( $in, $casing ) {
638
639 $out = array();
640 foreach ( $in as $key => $value )
641 $out[ self::fix_casing( $key, $casing ) ] = $value;
642
643 return $out;
644
645 }
646
647 private static function fix_casing( $text, $casing ) {
648 // Assumes $text is already in snake_case
649 switch ( $casing ) {
650
651 case 'camel':
652
653 // ucwords() doesn't support a $delimeters param
654 // until php 5.4.32/5.5.16
655 $text = strtr( $text, '_', ' ' );
656 $text = ucwords( $text );
657 $text = str_replace( ' ', '', $text );
658 // lcfirst() doesn't exist until php 5.3.0
659 $text[0] = strtolower( $text[0] );
660 return $text;
661
662 case 'dash':
663
664 return strtr( $text, '_', '-' );
665
666 }
667
668 return $text;
669
670 }
671
672
673 // FareHarbor URL with optional FH_ENVIRONMENT
674 // -----------------------------------------------
675
676 private static function url() {
677
678 $environment = ( defined( 'FH_ENVIRONMENT' ) && FH_ENVIRONMENT ) ? FH_ENVIRONMENT : '';
679 $environment = apply_filters( 'fareharbor/environment', $environment );
680
681 return trim( $environment )
682 ? trim( $environment ) . '.fareharbor.com'
683 : 'fareharbor.com';
684
685 }
686
687
688 // Settings & Settings Pages
689 // ===============================================
690
691 // Settings
692 // -----------------------------------------------
693
694 private static function is_lite() {
695 // This filter allows fh-kit and the admin page
696 // to be turned off with:
697 // add_filter( 'fareharbor/lite', '__return_true' );
698 return apply_filters( 'fareharbor/lite', false );
699
700 }
701
702 private static $options;
703
704 private static function get_option( $option_name, $default = '', $filtered = true ) {
705
706 $filter_name = str_replace( 'fh_', '', $option_name );
707 $filter_name = str_replace( 'default_', 'defaults/', $filter_name );
708 $filter_name = str_replace( 'buttons_', 'buttons/', $filter_name );
709 $filter_name = "fareharbor/$filter_name";
710
711 if ( self::is_lite() )
712 return $filtered ? apply_filters( $filter_name, $default ) : $default;
713
714 if ( !isset( self::$options ) )
715 self::$options = get_option( 'fareharbor_settings' );
716
717 $value = isset( self::$options[ $option_name ] )
718 ? self::$options[ $option_name ]
719 : $default;
720
721 if ( $filtered )
722 $value = apply_filters( $filter_name, $value );
723
724 return $value;
725
726 }
727
728
729 // The settings page
730 // -----------------------------------------------
731
732 public static function register_options_page() {
733
734 if ( self::is_lite() )
735 return;
736
737 add_options_page(
738 'FareHarbor Plugin Settings',
739 'FareHarbor',
740 'manage_options',
741 __FILE__,
742 array( __CLASS__, 'render_options_page' )
743 );
744
745 }
746
747 public static function register_settings() {
748
749 if ( self::is_lite() )
750 return;
751
752 register_setting(
753 'fareharbor_settings',
754 'fareharbor_settings',
755 array( __CLASS__, 'validate_settings' )
756 );
757
758 add_settings_section(
759 'fh_about_section',
760 'About',
761 array( __CLASS__, 'render_fh_about_section_text' ),
762 __FILE__
763 );
764
765 add_settings_section(
766 'fh_shortcode_defaults_section',
767 'Shortcode Defaults',
768 array( __CLASS__, 'render_fh_shortcode_defaults_section_text' ),
769 __FILE__
770 );
771
772 add_settings_field(
773 'fh_default_shortname',
774 'shortname',
775 array( __CLASS__, 'render_input_field' ),
776 __FILE__,
777 'fh_shortcode_defaults_section',
778 array(
779 'option_name' => 'fh_default_shortname',
780 'description' => 'Your company\'s FareHarbor shortname.',
781 )
782 );
783
784 add_settings_field(
785 'fh_responsive_calendars',
786 'Responsive Calendars',
787 array( __CLASS__, 'render_input_field' ),
788 __FILE__,
789 'fh_shortcode_defaults_section',
790 array(
791 'option_name' => 'fh_responsive_calendars',
792 'type' => 'checkbox',
793 'label' => 'Use responsive calendars by default.',
794 'description' => 'This is the same as [fareharbor type="responsive"].',
795 )
796 );
797
798 add_settings_field(
799 'fh_default_fallback',
800 'fallback',
801 array( __CLASS__, 'render_select_field' ),
802 __FILE__,
803 'fh_shortcode_defaults_section',
804 array(
805 'option_name' => 'fh_default_fallback',
806 'choices' => array(
807 'simple',
808 'classic',
809 ),
810 'description' => 'On certain mobile and touch devices, the book form will open as a new page instead of in a Lightframe. Choose "simple" for this page to mirror the look and feel of the Lightframe. Choose "classic" to take the user to your FareHarbor shortname website (and to the appropriate item on that site, if applicable).',
811 )
812 );
813
814 add_settings_field(
815 'fh_default_asn',
816 'asn',
817 array( __CLASS__, 'render_input_field' ),
818 __FILE__,
819 'fh_shortcode_defaults_section',
820 array(
821 'option_name' => 'fh_default_asn',
822 'description' => 'The shortname of your partner company. Include if using the ASN network.',
823 )
824 );
825
826 add_settings_field(
827 'fh_default_asn_ref',
828 'asn_ref',
829 array( __CLASS__, 'render_input_field' ),
830 __FILE__,
831 'fh_shortcode_defaults_section',
832 array(
833 'option_name' => 'fh_default_asn_ref',
834 'description' => 'The voucher number that should be set for ASN bookings.',
835 )
836 );
837
838 add_settings_field(
839 'fh_default_ref',
840 'ref',
841 array( __CLASS__, 'render_input_field' ),
842 __FILE__,
843 'fh_shortcode_defaults_section',
844 array(
845 'option_name' => 'fh_default_ref',
846 'description' => 'The online booking reference that should be set for bookings',
847 )
848 );
849
850 add_settings_field(
851 'fh_default_sheet',
852 'sheet',
853 array( __CLASS__, 'render_input_field' ),
854 __FILE__,
855 'fh_shortcode_defaults_section',
856 array(
857 'option_name' => 'fh_default_sheet',
858 'description' => 'The price sheet that should be used while creating bookings.',
859 )
860 );
861
862 add_settings_field(
863 'fh_default_full_items',
864 'full_items',
865 array( __CLASS__, 'render_select_field' ),
866 __FILE__,
867 'fh_shortcode_defaults_section',
868 array(
869 'option_name' => 'fh_default_full_items',
870 'choices' => array(
871 'yes',
872 'no',
873 ),
874 'description' => 'Should the Lightframe that is opened include item descriptions and photos? Defaults to "no".',
875 )
876 );
877
878 add_settings_field(
879 'fh_default_lightframe',
880 'lightframe',
881 array( __CLASS__, 'render_select_field' ),
882 __FILE__,
883 'fh_shortcode_defaults_section',
884 array(
885 'option_name' => 'fh_default_lightframe',
886 'choices' => array(
887 'yes',
888 'no',
889 ),
890 'description' => 'Choose "yes" to open new bookings inside a Lightframe. Choose "no" to open them in an external page instead. Defaults to "yes".'
891 )
892 );
893
894 add_settings_field(
895 'fh_default_class',
896 'class',
897 array( __CLASS__, 'render_input_field' ),
898 __FILE__,
899 'fh_shortcode_defaults_section',
900 array(
901 'option_name' => 'fh_default_class',
902 'description' => 'The class option only applies to the [lightframe] shortcode.',
903 )
904 );
905
906 add_settings_section(
907 'fh_auto_lightframe_section',
908 'Automatic Lightframing',
909 array( __CLASS__, 'render_fh_auto_lightframe_section_text' ),
910 __FILE__
911 );
912
913 add_settings_field(
914 'fh_auto_lightframe_enabled',
915 'Auto Lightframing Activation',
916 array( __CLASS__, 'render_input_field' ),
917 __FILE__,
918 'fh_auto_lightframe_section',
919 array(
920 'option_name' => 'fh_auto_lightframe_enabled',
921 'type' => 'checkbox',
922 'label' => 'Enable auto Lightframing.',
923 )
924 );
925
926 add_settings_section(
927 'fh_buttons_section',
928 'FareHarbor Buttons',
929 array( __CLASS__, 'render_fh_buttons_section_text' ),
930 __FILE__
931 );
932
933 add_settings_field(
934 'fh_buttons_active',
935 'FH Buttons Activation',
936 array( __CLASS__, 'render_input_field' ),
937 __FILE__,
938 'fh_buttons_section',
939 array(
940 'option_name' => 'fh_buttons_active',
941 'type' => 'checkbox',
942 'label' => 'Load the FH Buttons stylesheet on all pages.',
943 )
944 );
945
946 add_settings_field(
947 'fh_buttons_query',
948 'Button Colors',
949 array( __CLASS__, 'render_input_field' ),
950 __FILE__,
951 'fh_buttons_section',
952 array(
953 'option_name' => 'fh_buttons_query',
954 'description' => 'Provide colors in the format <code>red=ff0000&green=00ff00</code>',
955 )
956 );
957
958 }
959
960 public static function validate_settings( $input ) {
961
962 // Strip tags and trim whitespace
963 $input = array_map( array( __CLASS__, 'sanitize' ), $input );
964
965 // Let's not pollute the DB with empty settings
966 $input = array_filter( $input );
967
968 // Shortnames only work when lowercase
969 if ( isset( $input[ 'fh_default_shortname' ] ) )
970 $input[ 'fh_default_shortname' ] = strtolower( $input[ 'fh_default_shortname' ] );
971
972 return $input;
973
974 }
975
976 public static function render_options_page() {
977
978 ?>
979
980 <div class="wrap">
981
982 <h2>FareHarbor Plugin Settings</h2>
983
984 <form action="options.php" method="post">
985
986 <?php settings_fields( 'fareharbor_settings' ); ?>
987
988 <?php do_settings_sections( __FILE__ ); ?>
989
990 <p class="submit">
991 <input name="Submit" type="submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" />
992 </p>
993
994 </form>
995
996 </div>
997
998 <?php
999
1000 }
1001
1002 public static function render_fh_about_section_text() {
1003
1004 echo '<p><b>This plugin requires a FareHarbor account to work.</b> FareHarbor provides powerful, intuitive, and highly customizable reservation software for activity and tourism businesses. We can help you enable online booking on your website using this plugin and a whole range of other features. Don\'t have an account? <a href="https://fareharbor.com/join/" target="_blank">Get in touch at fareharbor.com.</a></p><p>If you\'re already with FareHarbor, check out our <a href="https://fareharbor.com/help/setup/wordpress-plugin/" target="_blank">help center article</a> on how to get started with this plugin.</p>';
1005
1006 }
1007
1008 public static function render_fh_shortcode_defaults_section_text() {
1009
1010 echo '<p>Set default options for the [lightframe], [fareharbor], [itemgrid], and [partners] shortcodes here. The options written in when including a shortcode on a page will always take precedence over the default values entered below. <a href="https://fareharbor.com/help/setup/wordpress-plugin/#setting-defaults" target="_blank">Learn how default options work.</a></p>';
1011
1012 }
1013
1014 public static function render_fh_auto_lightframe_section_text() {
1015
1016 echo '<p>Open normal links to FareHarbor as Lightframe overlays, even if the [lightframe] shortcode isn&apos;t used.</p>';
1017
1018 }
1019
1020 public static function render_fh_buttons_section_text() {
1021
1022 echo '<p>FareHarbor can automatically load in a CSS stylesheet which includes classes to make your Lightframe links look like beautifully designed buttons.</p>';
1023
1024 }
1025
1026 public static function render_input_field( $args ) {
1027 // We use this function to render all of our options fields
1028 // $args is supplied as the last parameter to each
1029 // add_settings_field() call in fareharbor::register_settings()
1030 // This function is only run on our settings page in the admin
1031
1032 $type = isset( $args[ 'type' ] ) ? $args[ 'type' ] : 'text';
1033
1034 $option_name = $args[ 'option_name' ];
1035 $value = self::get_option( $option_name, '', false );
1036
1037 // Attributes all input tags need
1038 $attrs = array(
1039 'name' => "fareharbor_settings[$option_name]",
1040 'id' => $option_name,
1041 'type' => $type,
1042 );
1043
1044 // Type-specific attributes
1045 switch ( $type ) {
1046
1047 case 'text':
1048 $attrs[ 'size' ] = '40';
1049 $attrs[ 'value' ] = (string) $value;
1050 break;
1051
1052 case 'checkbox':
1053 if ( $value )
1054 $attrs[ 'checked' ] = 'checked';
1055 break;
1056
1057 }
1058
1059 // Merge in attributes supplied in the arguments
1060 if ( isset( $args[ 'attrs' ] ) )
1061 // attributes from the arguments will override the defaults
1062 $attrs = $args[ 'attrs' ] + $attrs;
1063
1064 // Actually generate the input tag
1065 $out = '<input';
1066 foreach ( $attrs as $name => $value )
1067 $out .= " $name=\"$value\"";
1068 $out .= ' />';
1069
1070 if ( !empty( $args[ 'label' ] ) )
1071 $out .= "<label for=\"$option_name\">{$args[ 'label' ]}</label>";
1072
1073 if ( !empty( $args[ 'description' ] ) )
1074 $out .= "<p class=\"description\">{$args[ 'description' ]}</p>";
1075
1076 // And print it onto the page
1077 echo $out;
1078
1079 }
1080
1081 public static function render_select_field( $args ) {
1082
1083 $option_name = $args[ 'option_name' ];
1084 $value = self::get_option( $option_name, '', false );
1085
1086 ?>
1087
1088 <select name="<?php echo "fareharbor_settings[$option_name]" ?>" id="<?php echo $option_name ?>">
1089
1090 <option value="" <?php selected( '', $value ); ?>></option>
1091
1092 <?php foreach ( $args[ 'choices' ] as $choice ) { ?>
1093 <option value="<?php echo $choice ?>" <?php selected( $choice, $value ) ?>><?php echo $choice ?></option>
1094 <?php } ?>
1095
1096 </select>
1097
1098 <?php
1099
1100 if ( !empty( $args[ 'description' ] ) )
1101 echo "<p class=\"description\">{$args[ 'description' ]}</p>";
1102
1103 }
1104
1105 }
1106