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

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