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

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