Plugin Directory

Changeset 1398584


Ignore:
Timestamp:
04/18/2016 08:20:30 PM (10 years ago)
Author:
fareharbor
Message:

Version 3.0: Item grids, etc.

Location:
fareharbor
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • fareharbor/trunk/fareharbor.php

    r1261996 r1398584  
    11<?php
    22  /*
    3     Plugin Name: FareHarbor Reservation Calendars
     3    Plugin Name: FareHarbor
    44    Plugin URI: https://fareharbor.com/help/setup/wordpress-plugin/
    5     Description: Adds shortcodes for adding FareHarbor embeds to your site
    6     Version: 2.1
     5    Description: Easily add FareHarbor reservation calendars and buttons to your site
     6    Version: 3.0
    77    Author: FareHarbor
    88    Author URI: https://fareharbor.com
    99  */
    10  
    11   defined('ABSPATH') or die("What are you looking at?");
    12  
    13   add_shortcode("fareharbor", "fh_shortcode");
    14   add_shortcode("lightframe", "lightframe_shortcode");
    15   add_shortcode("partners", "partners_shortcode");
    16  
    17   // Defaults
    18  
    19   DEFINE('FH_SHORTNAME', '');
    20   DEFINE('FH_EMBED_TYPE', 'calendar-small');
    21   DEFINE('FH_ITEMS', '');
    22   DEFINE('FH_LIGHTFRAME', 'yes');
    23   DEFINE('FH_ASN', '');
    24   DEFINE('FH_ASN_REF', '');
    25   DEFINE('FH_REF', '');
    26   DEFINE('FH_CLASS', '');
    27   DEFINE('FH_ID', '');
    28  
    29   DEFINE('FH_FULL_ITEMS', 'no');
    30   DEFINE('FH_API_VIEW', 'items');
    31   DEFINE('FH_API_VIEW_ITEM', '');
    32   DEFINE('FH_API_VIEW_AVAILABILITY', '');
    33 
    34   DEFINE('FH_PARTNERS_INCLUDE', '');
    35  
    36   // Process the info returned from a shortcode
    37   // ---------------------------------------------
    38  
    39   function fh_sanitize_csv( $value ) {
    40     $value = str_replace(" ", "", $value);
    41     $value =  rtrim($value, ",");
    42     return $value;
     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 );
    4350  }
    4451
    45   function fh_process_attrs( $attrs ) {
    46     if( is_array($attrs) ) {
    47 
    48       // Trim whitespace
    49  
    50       $attrs = array_map('trim', $attrs);
    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
    52476       // Strip smart quotes, because WordPress returns them as part of the value if the shortcode was set up using them
    53    
    54       $attrs = str_replace(
    55         array("\xe2\x80\x98", "\xe2\x80\x99", "\xe2\x80\x9c", "\xe2\x80\x9d", chr(145), chr(146), chr(147), chr(148)),
    56         array('', '', '', '', '', '', '', ''),
    57       $attrs);
    58      
    59       // Process options and assign defaults if needed
    60      
    61       $attrs = shortcode_atts(array(
    62         "shortname" => FH_SHORTNAME,
    63         "items" => FH_ITEMS,
    64         "asn" => FH_ASN,
    65         "asn_ref" => FH_ASN_REF,
    66         "ref" => FH_REF,
    67         "lightframe" => FH_LIGHTFRAME,
    68         "full_items" => FH_FULL_ITEMS,
    69         "sheet" => '',
    70        
    71         // [fareharbor] only
    72        
    73         "type" => FH_EMBED_TYPE,
    74         "lightframe" => FH_LIGHTFRAME,
    75  
    76         // [lightframe] only
    77  
    78         "class" => FH_CLASS,
    79         "id" => FH_ID,
    80         "view" => FH_API_VIEW,
    81         "view_item" => FH_API_VIEW_ITEM,
    82         "view_availability" => FH_API_VIEW_AVAILABILITY,
    83    
    84         // [partners] only
    85    
    86         "include" => FH_PARTNERS_INCLUDE
    87  
    88       ), $attrs);
    89      
     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
    90493      // Clean up item IDs and included companies because users can't be trusted
    91      
    92       $attrs["items"] = fh_sanitize_csv( $attrs["items"] );
    93       $attrs["view_item"] = fh_sanitize_csv( $attrs["view_item"] );
    94       $attrs["include"] = fh_sanitize_csv( $attrs["include"] );
    95    
    96       return $attrs;
    97 
    98     }
    99   }
    100  
    101   function fh_url() {
    102     $env_url = defined('FH_ENVIRONMENT') ? FH_ENVIRONMENT . '.fareharbor.com' : 'fareharbor.com';
    103     return $env_url;
    104   }
    105 
    106   // [fareharbor] shortcode
    107   // ---------------------------------------------
    108 
    109   function fh_shortcode( $attrs ) {
    110    
    111     $fh_options = fh_process_attrs( $attrs );
    112  
    113     $output = ''; 
    114  
    115     // Bail if a shortname isn't provided
    116 
    117     if ( empty( $fh_options["shortname"] ) ) {
    118  
    119       $output .= '<p>Please provide a FareHarbor shortname. (Format: <code>shortname="yourshortname"</code>)</p>';
    120      
    121     } else {
    122    
    123       $output = '<script src="https://' . fh_url() . '/embeds/script/';
    124 
    125       // Types: Clean up "small" and "large" options, otherwise use passed type
    126 
    127       switch ( $fh_options["type"] ) {
    128         case "small":
    129           $output .= "calendar-small";
    130           break;
    131         case "large":
    132           $output .= "calendar";
    133           break;
    134         default:
    135           $output .= $fh_options["type"];
    136       }
    137      
    138       $output .= '/';
    139 
    140       // Shortname
    141 
    142       $output .= $fh_options["shortname"] . '/';
    143  
    144       // Items, if any were included
    145      
    146       if ( !empty( $fh_options["items"] ) ) {
    147         $output .= 'items/' . $fh_options["items"] . '/';
    148       }
    149      
    150       // Build query string of options. "lightframe" is always included, with either yes or no.
    151 
    152       $output .= '?';
    153 
    154       $fh_query_string_options = array('lightframe' => $fh_options["lightframe"]);
    155 
    156       if ( !empty( $fh_options["asn"] ) ) {     
    157         $fh_query_string_options["asn"] = $fh_options["asn"];
    158        
    159         if( !empty( $fh_options["asn_ref"] ) ) {
    160           $fh_query_string_options["asn-ref"] = $fh_options["asn_ref"];
    161         }
    162       }
    163      
    164       if ( !empty( $fh_options["ref"] ) ) {
    165         $fh_query_string_options["ref"] = $fh_options["ref"];
    166       }
    167      
    168       if ( !empty( $fh_options["sheet"] ) ) {
    169         $fh_query_string_options["sheet"] = $fh_options["sheet"];
    170       }
    171      
    172       $output .= http_build_query($fh_query_string_options);
    173 
    174      
    175       $output .= '"></script>';
    176     }
    177  
    178     return $output;
    179   }
    180 
    181   // [lightframe][/lightframe] shortcode
    182   // ---------------------------------------------
    183  
    184   function lightframe_shortcode( $attrs, $content = null ) {
    185 
    186     $attrs = fh_process_attrs( $attrs );
    187    
    188     $output = '';
    189 
    190     if ( empty( $attrs["shortname"] ) ) {
    191  
    192       $output .= '<p>Please provide a FareHarbor shortname. (Format: <code>shortname="yourshortname"</code>)</p>';
    193      
    194     } elseif ( empty( $attrs["view_item"] ) && !empty( $attrs["view_availability"] ) ) { 
    195 
    196         echo '<p>Please provide <code>view_item</code> if using <code>view_availability</code.</p>';
    197 
    198     } else {
    199  
    200       // Fallback URL
    201       // ---------------------------------------------
    202      
    203       $fallback_url = 'https://' . fh_url() . '/';
    204       $fallback_url .= $attrs["shortname"] . '/items/';
    205 
    206       if( !empty( $attrs["items"] ) ) {
    207        
    208         // If filtering but just to one item, link to it
    209 
    210         $fallback_items = explode(',', $attrs["items"]);
    211        
    212         if( count($fallback_items) == 1 ) {
    213           $fallback_url .= $fallback_items[0] . '/';
    214          
    215           if( $attrs["full_items"] == 'no' ) {
    216             $fallback_url .= 'calendar/';
     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' ] = '';
    217509          }
    218510        }
    219511
    220       } else {
    221 
    222         if( $attrs["view"] == 'all-availability' ) {
    223           $fallback_url .= 'calendar/';
    224         }
    225  
    226         if( !empty( $attrs["view_item"] ) ) {
    227           $fallback_url .= $attrs["view_item"] . '/';
     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>
    228937         
    229           if( $attrs["full_items"] == 'no' && empty( $attrs["view_availability"] ) ) {
    230             $fallback_url .= 'calendar/';
    231           }
    232         }
    233        
    234         if( !empty( $attrs["view_availability"] ) ) {
    235           $fallback_url .= 'availability/' . $attrs["view_availability"] . '/book/';
    236         }
     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;
    237994
    238995      }
    239996
    240       $fallback_url_query_string = array();
    241 
    242       if ( !empty( $attrs["asn"] ) ) {     
    243         $fallback_url_query_string["asn"] = $attrs["asn"];
    244        
    245         if( !empty( $attrs["asn_ref"] ) ) {
    246           $fallback_url_query_string["asn-ref"] = $attrs["asn_ref"];
    247         }
    248       }
    249      
    250       if ( !empty( $attrs["ref"] ) ) {
    251         $fallback_url_query_string["ref"] = $attrs["ref"];
    252       }
    253      
    254       if ( !empty( $attrs["sheet"] ) ) {
    255         $fallback_url_query_string["sheet"] = $attrs["sheet"];
    256       }
    257      
    258       if( !empty( $fallback_url_query_string ) ) {
    259         $fallback_url .= '?';
    260         $fallback_url .= http_build_query($fallback_url_query_string);
    261       }
    262 
    263       // $lightframe_options array, to be JSONified for Lightframe API call
    264       // ---------------------------------------------
    265      
    266       $lightframe_options["shortname"] = $attrs["shortname"];
    267      
    268       // We should still set a default for full_items, but avoid writing it in if it's just a 'no'
    269 
    270       if ( $attrs["full_items"] != 'no' ) { 
    271         $lightframe_options["fullItems"] = $attrs["full_items"];
    272       }
    273      
    274       if ( !empty( $attrs["asn"] ) ) {     
    275         $lightframe_options["asn"] = $attrs["asn"];
    276        
    277         if( !empty( $attrs["asn_ref"] ) ) {
    278           $lightframe_options["asnRef"] = $attrs["asn_ref"];
    279         }
    280       }
    281      
    282       if ( !empty( $attrs["ref"] ) ) {
    283         $lightframe_options["ref"] = $attrs["ref"];
    284       }
    285      
    286       if ( !empty( $attrs["sheet"] ) ) {
    287         $lightframe_options["sheet"] = $attrs["sheet"];
    288       }
    289 
    290       if ( !empty( $attrs["items"] ) ) {
    291         $lightframe_options["items"] = array($attrs["items"]); // Put these in an array so it gets brackets
    292       }
    293      
    294       // If the view is a string type, just write it in
    295 
    296       if ($attrs["view"] == 'items' || $attrs["view"] == 'all-availability') {
    297         $lightframe_options["view"] = $attrs["view"];
    298       }
    299      
    300       // If the view is not a string type, you need to pass just view_item= OR view_item= and view_availability=
    301 
    302       if( !empty( $attrs["view_item"] ) && empty( $attrs["view_availability"] )) {
    303         $lightframe_options["view"] = array( 'item' => $attrs["view_item"] );
    304       }
    305      
    306       if( !empty( $attrs["view_item"] ) && !empty( $attrs["view_availability"] )) {
    307         $lightframe_options["view"] = array( 'item' => $attrs["view_item"], 'availability' => $attrs["view_availability"] );
    308       }
    309 
    310       // Put it all together now
    311       // ---------------------------------------------
    312 
    313         $output .= '<a href="' . $fallback_url . '" ';
    314        
    315       if ( !empty( $attrs["class"] ) ) {
    316         $output .= 'class="' . $attrs["class"] .'" ';
    317       }
    318      
    319       if ( !empty( $attrs["id"] ) ) {
    320         $output .= 'id="' . $attrs["id"] .'" ';
    321       }
    322    
    323       $output .= 'onclick="FH.open(' . str_replace('"',"'", json_encode($lightframe_options)) . '); return false;">';
    324      
    325       $output .= do_shortcode( $content ) . '</a>';
    326     }
    327 
    328     return $output;
     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
    3291043  }
    330  
    331   // [partners] shortcode
    332   // ---------------------------------------------
    333 
    334   function partners_shortcode( $attrs ) {
    335    
    336     $attrs = fh_process_attrs( $attrs );
    337  
    338     $output = '';
    339  
    340     // Bail if a shortname isn't provided
    341 
    342     if ( empty( $attrs["shortname"] ) ) {
    343  
    344       $output .= '<p>Please provide a FareHarbor shortname. (Format: <code>shortname="yourshortname"</code>)</p>';
    345      
    346     } else {
    347    
    348       $output = '<script src="https://' . fh_url() . '/embeds/script/partners/';
    349      
    350       $output .= $attrs["shortname"] . '/';
    351      
    352       // Build query string of options
    353 
    354       $output .= '?';
    355      
    356       // lightframe is always included
    357 
    358       $fh_query_string_options = array('lightframe' => $attrs["lightframe"]);
    359      
    360       // For safety, always set asn, just to the shortname if asn isn't given
    361      
    362       $fh_query_string_options["asn"] = !empty( $attrs["asn"] ) ? $attrs["asn"] : $attrs["shortname"];
    363 
    364       if( !empty( $attrs["asn_ref"] ) ) {
    365         $fh_query_string_options["asn-ref"] = $attrs["asn_ref"];
    366       }
    367      
    368       if ( !empty( $attrs["ref"] ) ) {
    369         $fh_query_string_options["ref"] = $attrs["ref"];
    370       }
    371      
    372       if ( $attrs["full_items"] != 'no' ) { 
    373         $fh_query_string_options["full-items"] = $attrs["full_items"];
    374       }
    375 
    376       if ( !empty( $attrs["include"] ) ) {
    377         $fh_query_string_options["include"] = $attrs["include"];
    378       }
    379      
    380       $output .= http_build_query($fh_query_string_options);
    381      
    382       $output .= '"></script>';
    383     }
    384  
    385     return $output;
    386   }
    387 
    388   // Add API script to footer
    389   // ---------------------------------------------
    390  
    391   add_action('wp_footer', 'lightframe_api_footer');
    392   function lightframe_api_footer() {
    393     echo '<!-- FareHarbor plugin activated --><script src="https://' . fh_url() . '/embeds/api/v1/"></script>';
    394   }
    395 ?>
  • fareharbor/trunk/readme.txt

    r1261996 r1398584  
    11=== Plugin Name ===
    22Contributors: fareharbor
    3 Tags: reservations, booking calendar, booking, booking plugin, reservation calendar, booking system
     3Tags: reservations, booking calendar, booking, reservation plugin, reservation calendar, booking system
    44Requires at least: 3.0
    5 Tested up to: 4.3.1
     5Tested up to: 4.5
    66Stable tag: trunk
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
    99
    10 Adds shortcodes for FareHarbor reservation booking calendar embeds and buttons to your site
     10Easily add FareHarbor reservation calendars, booking embeds, and buttons to your site.
    1111
    1212== Description ==
    1313
    14 Adds shortcodes that makes it easy to embed FareHarbor's free booking reservation calendars or buttons on your site. Learn more about the FareHarbor reservation system at [fareharbor.com](https://fareharbor.com/ "Free reservation software").
     14Adds shortcodes that make it easy to embed FareHarbor booking calendars and buttons on your site. Learn more about the FareHarbor reservation system at [fareharbor.com](https://fareharbor.com/ " Enterprise-level reservation software").
    1515
    16 Usage example: `[fareharbor shortname="companyname" items="500" lightframe="yes"]`.
     16Includes shortcodes for embedded calendars (`[fareharbor]`), embedded grids of activities (`[itemgrid]`), and buttons that open a booking overlay (`[lightframe]`).
    1717
    1818For more examples and available options, please visit <https://fareharbor.com/help/setup/wordpress-plugin/>.
     
    3535## Then
    3636
    37 Use the `[fareharbor shortname="companyname"]` or `[lightframe shortname="companyname"][/lightframe]` shortcodes in your posts or pages.
     37Use the `[fareharbor shortname="companyname"]`, `[lightframe shortname="companyname"][/lightframe]`, `[partners shortname="companyname" include="company1,company2"]`, and `[itemgrid shortname="companyname"]` shortcodes in your posts or pages.
    3838
    3939== Screenshots ==
    4040
    41 1. Generated reservations calendar
    42 2. Lightframe booking options: customers book your activity without leaving your website
     411. Generated embedded reservations calendar
     422. Lightframe booking overlay: customers book your activity without leaving your website
    4343
    4444== Changelog ==
    4545
     46= 2.2 =
     47* Add support for [itemgrid] shortcode
     48* Add support for an even better mobile booking experience via `fallback="simple"` shortcode option
     49* Add a settings page (Settings > FareHarbor)
     50* Allow setting shortcode option defaults in the settings page and via filters.
     51* Add support for including a FareHarbor Buttons stylesheet on all pages.
     52
    4653= 2.1 =
    47 * Add support for specifying price sheet to use while booking
     54* Add support for specifying price sheets to use while booking
    4855
    4956= 2.0 =
Note: See TracChangeset for help on using the changeset viewer.