PluginProbe
FareHarbor for WordPress / 3.3
FareHarbor for WordPress v3.3
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.3, at fareharbor.php

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