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

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