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

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