GeoMashup
[ class tree: GeoMashup ] [ index: GeoMashup ] [ all elements ]

Source for file geo-mashup-options.php

Documentation is available at geo-mashup-options.php

  1. <?php
  2. /**
  3.  * Management of Geo Mashup saved options.
  4.  *
  5.  * @package GeoMashup
  6.  */
  7.  
  8. /**
  9.  * A singleton to manage Geo Mashup saved options.
  10.  * 
  11.  * @since 1.2
  12.  * @access public
  13.  * @package GeoMashup
  14.  */
  15.     /**
  16.      * Valid options with default values.
  17.      * 
  18.      * @since 1.2
  19.      * @var array 
  20.      */
  21.     public $default_options = array (
  22.         'overall' => array (
  23.             'version' => '',
  24.             'google_key' => '',
  25.             'mashup_page' => '',
  26.             'category_link_separator' => '::',
  27.             'category_link_text' => 'map',
  28.             'category_zoom' => 'auto',
  29.             'add_category_links' => 'false',
  30.             'copy_geodata' => 'false',
  31.             'theme_stylesheet_with_maps' => 'false',
  32.             'located_post_types' => array'post''page' ),
  33.             'located_object_name' => array
  34.                 'post' => 'deprecated',
  35.                 'user' => 'false',
  36.                 'comment' => 'false' ),
  37.             'enable_reverse_geocoding' => 'true',
  38.             'adsense_code' => 'partner-pub-5088093001880917',
  39.             'geonames_username' => 'geomashup',
  40.              'map_api' => 'googlev3',
  41.             'import_custom_field' => '' ),
  42.         'global_map' => array (
  43.             'width' => '400',
  44.             'height' => '400',
  45.             'map_type' => 'G_NORMAL_MAP',
  46.             'zoom' => 'auto',
  47.             'background_color' => 'c0c0c0',
  48.             'category_color' => array ),
  49.             'category_line_zoom' => array ),
  50.             'map_control' => 'GSmallZoomControl3D',
  51.             'add_map_type_control' => array(),
  52.             'add_overview_control' => 'false',
  53.             'add_google_bar' => 'false',
  54.             'enable_scroll_wheel_zoom' => 'false',
  55.             'show_post' => 'false',
  56.             'show_future' => 'false',
  57.             'marker_select_info_window' => 'true',
  58.             'marker_select_highlight' => 'false',
  59.             'marker_select_center' => 'false',
  60.             'marker_select_attachments' => 'false',
  61.             'max_posts' => '',
  62.             'auto_info_open' => 'true',
  63.             'click_to_load' => 'false',
  64.             'click_to_load_text' => '',
  65.              'cluster_max_zoom' => '',
  66.              'cluster_lib' => 'clustermarker'    ),
  67.         'single_map' => array (
  68.             'width' => '400',
  69.             'height' => '400',
  70.             'map_control' => 'GSmallZoomControl3D',
  71.             'map_type' => 'G_NORMAL_MAP',
  72.             'zoom' => '11',
  73.             'background_color' => 'c0c0c0',
  74.             'add_overview_control' => 'false',
  75.             'add_map_type_control' => array(),
  76.             'add_google_bar' => 'false',
  77.             'enable_scroll_wheel_zoom' => 'false',
  78.             'click_to_load' => 'false',
  79.              'click_to_load_text' => '' )
  80.         'context_map' => array (
  81.             'width' => '200',
  82.             'height' => '200',
  83.             'map_control' => 'GSmallZoomControl3D',
  84.             'map_type' => 'G_NORMAL_MAP',
  85.             'zoom' => 'auto',
  86.             'background_color' => 'c0c0c0',
  87.             'add_overview_control' => 'false',
  88.             'add_map_type_control' => array(),
  89.             'add_google_bar' => 'false',
  90.             'enable_scroll_wheel_zoom' => 'false',
  91.             'marker_select_info_window' => 'true',
  92.             'marker_select_highlight' => 'false',
  93.             'marker_select_center' => 'false',
  94.             'marker_select_attachments' => 'false',
  95.             'click_to_load' => 'false',
  96.              'click_to_load_text' => '' ) );
  97.  
  98.     /**
  99.      * Map of old option names to new ones.
  100.      * 
  101.      * @since 1.2
  102.      * @var array 
  103.      */
  104.     private $conversions array (
  105.         'google_key' => array 'overall''google_key' ),
  106.         'mashup_page' => array 'overall''mashup_page' ),
  107.         'category_link_separator' => array 'overall''category_link_separator' ),
  108.         'category_link_text' => array 'overall''category_link_text' ),
  109.         'category_zoom' => array 'overall''category_zoom' ),
  110.         'add_category_links' => array 'overall''add_category_links' ),
  111.         'theme_stylesheet_with_maps' => array 'overall''theme_stylesheet_with_maps' ),
  112.         'map_width' => array 'global_map''width' ),
  113.         'map_height' => array 'global_map''height' ),
  114.         'map_type' => array 'global_map''map_type' ),
  115.         'zoom_level' => array 'global_map''zoom' ),
  116.         'category_color' => array 'global_map''category_color' ),
  117.         'category_line_zoom' => array 'global_map''category_line_zoom' ),
  118.         'map_control' => array 'global_map''map_control' ),
  119.         'add_map_type_control' => array 'global_map''add_map_type_control' ),
  120.         'add_overview_control' => array 'global_map''add_overview_control' ),
  121.         'show_post' => array 'global_map''show_post' ),
  122.         'show_future' => array 'global_map''show_future' ),
  123.         'max_posts' => array 'global_map''max_posts' ),
  124.         'auto_info_open' => array 'global_map''auto_info_open' ),
  125.         'auto_open_info_window' => array 'global_map''auto_info_open' ),
  126.         'click_to_load' => array 'global_map''click_to_load' ),
  127.         'click_to_load_text' => array 'global_map''click_to_load_text' ),
  128.         'in_post_map_control' => array 'single_map''map_control' ),
  129.         'in_post_map_width' => array 'single_map''width' ),
  130.         'in_post_map_height' => array 'single_map''height' ),
  131.         'in_post_map_type' => array 'single_map''map_type' ),
  132.         'in_post_zoom_level' => array 'single_map''zoom' ),
  133.         'in_post_add_overview_control' => array 'single_map''add_overview_control' ),
  134.         'in_post_add_map_type_control' => array 'single_map''add_map_type_control' ),
  135.         'in_post_click_to_load' => array 'single_map''click_to_load' ),
  136.         'in_post_click_to_load_text' => array 'single_map''click_to_load_text' ) );
  137.  
  138.     /**
  139.      * Options keys whose values aren't predictable.
  140.      * 
  141.      * @since 1.2
  142.      * @var array 
  143.      */
  144.     private $freeform_option_keys array 'category_color''category_line_zoom''add_map_type_control''located_post_types' );
  145.  
  146.     /**
  147.      * Valid map types.
  148.      * 
  149.      * @since 1.2
  150.      * @var array 
  151.      */
  152.     public $valid_map_types = array 'G_NORMAL_MAP''G_SATELLITE_MAP''G_HYBRID_MAP''G_PHYSICAL_MAP''G_SATELLITE_3D_MAP' );
  153.  
  154.     /**
  155.      * Saved option values.
  156.      *
  157.      * Use the GeoMashupOptions::get() method for access.
  158.      * 
  159.      * @since 1.2
  160.      * @var array 
  161.      */
  162.     private $options;
  163.  
  164.     /**
  165.      * Old option values that can't be converted.
  166.      * 
  167.      * @since 1.2
  168.      * @var array 
  169.      */
  170.     private $corrupt_options '';
  171.  
  172.     /**
  173.      * Validation messages.
  174.      * 
  175.      * @since 1.2
  176.      * @var array 
  177.      */
  178.     private $validation_errors array();
  179.  
  180.     /**
  181.      * PHP5 constructor
  182.      *
  183.      * Should be used only in this file.
  184.      * 
  185.      * @since 1.2
  186.      * @return void 
  187.      */
  188.     function __construct({
  189.         $shared_google_api_key get_option 'google_api_key' );
  190.         if $shared_google_api_key {
  191.             $this->default_options['overall']['google_key'$shared_google_api_key;
  192.         }
  193.         $this->options $this->default_options;
  194.         $settings get_option 'geo_mashup_options' );
  195.         if is_array $settings ) ) {
  196.             $settings $this->convert_old_settings $settings );
  197.             $this->options $this->valid_options $settings$this->default_options$add_missing true );
  198.         else {
  199.             $failed_options $settings;
  200.             if is_string $settings && !empty $settings ) ) {
  201.                 $this->corrupt_options $settings;
  202.             }
  203.         }
  204.     }
  205.  
  206.     /**
  207.      * Change old option names.
  208.      * 
  209.      * @since 1.2
  210.      *
  211.      * @param array $settings Existing settings.
  212.      * @return array Converted settings.
  213.      */
  214.     private function convert_old_settings$settings {
  215.         foreach $this->conversions as $old_key => $new_keys {
  216.             if isset $settings[$old_key) ) {
  217.                 $settings[$new_keys[0]][$new_keys[1]] $settings[$old_key];
  218.                 unset $settings[$old_key);
  219.             }
  220.         }
  221.         if isset$settings['overall']['located_object_name']['post']and 'true' == $settings['overall']['located_object_name']['post'{
  222.             $settings['overall']['located_object_name']['post''deprecated';
  223.             if empty$settings['overall']['located_post_types']['post') )
  224.                 $settings['overall']['located_post_types'array'post''page' );
  225.         }
  226.         return $settings;
  227.     }
  228.  
  229.     /**
  230.      * Write current values to the database.
  231.      * 
  232.      * @since 1.2
  233.      *
  234.      * @return bool Success or failure.
  235.      */
  236.     public function save({
  237.         $saved false;
  238.         if ($this->options == $this->valid_options $this->options ) ) {
  239.             $saved update_option('geo_mashup_options'$this->options);
  240.             
  241.             // Share our Google API key
  242.             $google_api_key $this->options['overall']['google_key'];
  243.             if !empty $google_api_key && !get_option 'google_api_key' ) ) {
  244.                 update_option'google_api_key'$google_api_key );
  245.             }
  246.         }
  247.         return $saved;
  248.     }
  249.  
  250.     /**
  251.      * Get a saved option value.
  252.      * 
  253.      * <code>
  254.      * $single_map_options_array = $geo_mashup_options->get( 'single_map' );
  255.      * $google_key = $geo_mashup_options->get( 'overall', 'google_key' );
  256.      * $add_global_satellite_map = $geo_mashup_options->get( 'global_map', 'add_map_type_control', 'G_SATELLITE_MAP' );
  257.      * </code>
  258.      *
  259.      * @since 1.2
  260.      *
  261.      * @param string $key1 Highest level key.
  262.      * @param string $key2 Second level key.
  263.      * @param string $key3 Third level key.
  264.      * @return string|arrayThe option value or values.
  265.      */
  266.     public function get$key1$key2 null$key3 null {
  267.         $subset array();
  268.         if is_null $key2 ) ) {
  269.             // Getting first dimension options
  270.             if is_array $key1 ) ) {
  271.                 foreach $key1 as $key $subset[$key= isset$this->options[$key$this->options[$keynull;
  272.                 return $subset;
  273.             else {
  274.                 return isset$this->options[$key1$this->options[$key1null;
  275.             }
  276.         else if is_null $key3 ) ) {
  277.             // Getting second dimension options
  278.             if is_array $key2 ) ) {
  279.                 foreach $key2 as $key $subset[$key= isset$this->options[$key1][$key$this->options[$key1][$keynull;
  280.                 return $subset;
  281.             else {
  282.                 return isset$this->options[$key1][$key2$this->options[$key1][$key2null;
  283.             
  284.         else {
  285.             // Getting third dimension options
  286.             if is_array $key3 ) ) {
  287.                 foreach $key3 as $key $subset[$key= isset$this->options[$key1][$key2][$key$this->options[$key1][$key2][$keynull;
  288.                 return $subset;
  289.             else {
  290.                 return isset$this->options[$key1][$key2][$key3$this->options[$key1][$key2][$key3null;
  291.             }
  292.         }
  293.     }
  294.  
  295.     /**
  296.      * Import valid options from an array.
  297.      * 
  298.      * @since 1.2
  299.      *
  300.      * @param array $option_array Associative array of option names and values.
  301.      */
  302.     public function set_valid_options$option_array {
  303.         $this->validation_errors array );
  304.         $this->options $this->valid_options $option_array );
  305.     }
  306.  
  307.     /**
  308.      * Remove invalid option keys from an array, and replace invalid values with defaults.
  309.      *
  310.      * @since 1.2
  311.      *
  312.      * @param array $option_array An array of options to validate.
  313.      * @param array $defaults Optional array of valid default values.
  314.      * @param boolean $add_missing Set if input is not from a form, so missing values are not unchecked checkboxes and should get default values.
  315.      * @return array Valid options.
  316.      */
  317.     private function valid_options$option_array$defaults null$add_missing false {
  318.         $valid_options array );
  319.         if is_null $defaults ) ) {
  320.             $defaults empty $this->options ) ) $this->default_options : $this->options;
  321.         }
  322.         if !is_array$option_array ) ) return $defaults;
  323.  
  324.         foreach $defaults as $key => $default_value {
  325.             if isset$option_array[$key&& $this->is_valid $key$option_array[$key) ) {
  326.                 if is_array $option_array[$key&& !in_array $key$this->freeform_option_keys ) ) {
  327.                     // Validate options in sub-arrays, except freeform array options, whose keys aren't known
  328.                     $valid_options[$key$this->valid_options $option_array[$key]$default_value );
  329.                 else {
  330.                     // Use the valid non-array value
  331.                     $valid_options[$key$option_array[$key];
  332.                 }
  333.             else {
  334.                 // Value in question is invalid
  335.                 if $add_missing and empty $option_array[$keyand in_array ($default_valuearray 'true''false' ) ) ) {
  336.                     // Convert empty booleans to false to handle unchecked checkboxes
  337.                     $valid_options[$key'false';
  338.                 else 
  339.                     $valid_options[$key$default_value;
  340.                 }
  341.             }
  342.         }
  343.         return $valid_options;
  344.     }
  345.  
  346.     /**
  347.      * Check an option key and value for validity.
  348.      * 
  349.      * @since 1.2
  350.      *
  351.      * @param string $key Option key.
  352.      * @param mixed $value Option value, modified in some cases.
  353.      * @return bool True if valid.
  354.      */
  355.     public function is_valid$key&$value {
  356.         switch $key {
  357.             case 'map_type':
  358.                 if !in_array $value$this->valid_map_types ) ) {
  359.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  360.                         __(', which must be a valid map type (see documentation)''GeoMashup') );
  361.                     return false;
  362.                 }
  363.                 return true;
  364.  
  365.             case 'add_map_type_control':
  366.                 if !is_array $value ) ) {
  367.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  368.                         __(', which must be an array of valid map types (see documentation)''GeoMashup') );
  369.                     return false;
  370.                 }
  371.                 foreach$value as $map_type {
  372.                     if !in_array $map_type$this->valid_map_types ) ) {
  373.                         array_push $this->validation_errors'"'$map_type '" ' __('is invalid for''GeoMashup'' ' $key .
  374.                             __(', which must be a valid map type (see documentation)''GeoMashup') );
  375.                         return false;
  376.                     }
  377.                 }
  378.                 return true;
  379.  
  380.             case 'map_control':
  381.                 $valid_map_controls array 'GSmallZoomControl''GSmallMapControl''GLargeMapControl''GLargeMapControl3D''GSmallZoomControl3D' );
  382.                 if !in_array $value$valid_map_controls ) ) {
  383.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  384.                         __(', which must be a valid map control (see documentation)''GeoMashup') );
  385.                     return false;
  386.                 }
  387.                 return true;
  388.  
  389.             case 'map_api':
  390.                 $valid_apis array'google''openlayers''googlev3' );
  391.                 if !in_array $value$valid_apis ) ) {
  392.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  393.                         __(', which must be a valid map provider.''GeoMashup') );
  394.                     return false;
  395.                 }
  396.                 return true;
  397.  
  398.             case 'cluster_lib':
  399.                 $valid_libs array'clustermarker''markerclusterer' );
  400.                 if !in_array$value$valid_libs ) ) {
  401.                     array_push$this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  402.                         __(', which must be a valid clustering library.''GeoMashup') );
  403.                     return false;
  404.                 }
  405.                 return true;
  406.  
  407.             // strings without HTML
  408.             case 'adsense_code':
  409.                 if empty$value ) )
  410.                     $value 'partner-pub-5088093001880917';
  411.             case 'geonames_user':
  412.                 if empty$value ) )
  413.                     $value 'geomashup';
  414.             case 'category_link_separator':
  415.             case 'category_link_text':
  416.             case 'click_to_load_text':
  417.             case 'import_custom_field':
  418.                 if empty $value ) ) return true;
  419.             case 'google_key':
  420.             case 'version':
  421.             case 'mashup_page':
  422.                 if !is_string $value ) ) {
  423.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  424.                         __(', which must be a string''GeoMashup') );
  425.                     return false;
  426.                 }
  427.                 if preg_match"/<.*>/"$value ) ) {
  428.                     array_push $this->validation_errors'"'esc_html$value '" ' __('is invalid for''GeoMashup'' ' $key .
  429.                         __(', which must not contain XML tags.''GeoMashup') );
  430.                     return false;
  431.                 }
  432.                 return true;
  433.  
  434.             // numbers
  435.             case 'max_posts':
  436.                 if empty $value ) ) return true;
  437.             case 'width':
  438.             case 'height':
  439.                 if substr $value-== '%' && is_numeric substr $value0-) ) ) return true;
  440.                 if !is_numeric $value ) ) {
  441.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  442.                         __(', which must be a number''GeoMashup') );
  443.                     return false;
  444.                 }
  445.                 return true;
  446.  
  447.             // show_future: boolean or 'only'
  448.             case 'show_future':
  449.                 if 'only' == $value 
  450.                     return true;
  451.  
  452.             // booleans
  453.             case 'auto_info_open':
  454.             case 'add_category_links':
  455.             case 'add_overview_control':
  456.             case 'add_google_bar':
  457.             case 'copy_geodata':
  458.             case 'enable_scroll_wheel_zoom':
  459.             case 'marker_select_info_window':
  460.             case 'marker_select_highlight':
  461.             case 'marker_select_center':
  462.             case 'marker_select_attachments':
  463.             case 'theme_stylesheet_with_maps':
  464.             case 'show_post':
  465.             case 'click_to_load':
  466.             case 'user':
  467.             case 'comment':
  468.             case 'enable_reverse_geocoding':
  469.                 if empty $value ) ) {
  470.                     // fail quietly - it will be converted to false
  471.                     return false;
  472.                 else if $value != 'true' && $value != 'false' 
  473.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  474.                         __(', which must be "true" or "false"''GeoMashup') );
  475.                     return false;
  476.                 }
  477.                 return true;
  478.  
  479.             // arrays
  480.             case 'overall':
  481.             case 'global_map':
  482.             case 'single_map':
  483.             case 'context_map':
  484.             case 'category_color':
  485.             case 'category_line_zoom':
  486.             case 'located_post_types':
  487.             case 'located_object_name':
  488.                 if !is_array $value ) ) {
  489.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  490.                         __(', which must be an array''GeoMashup') );
  491.                     return false;
  492.                 }
  493.                 return true;
  494.  
  495.             // zoom levels
  496.             case 'cluster_max_zoom':
  497.                 if empty $value ) ) return true;
  498.             case 'zoom':
  499.             case 'category_zoom':
  500.                 if $value == 'auto' return true;
  501.                 if !is_numeric $value || $value || $value GEO_MASHUP_MAX_ZOOM {
  502.                     array_push $this->validation_errors'"'$value '" ' __('is invalid for''GeoMashup'' ' $key .
  503.                         __(', which must be a number from 0 to ''GeoMashup'GEO_MASHUP_MAX_ZOOM );
  504.                     return false;
  505.                 }
  506.                 return true;
  507.  
  508.             // deprecated
  509.             case 'post':
  510.                 if 'deprecated' != $value {
  511.                     array_push$this->validation_errors'"'$value '" ' __'is invalid for''GeoMashup' ' ' $key .
  512.                         __', which is a deprecated option''GeoMashup' ) );
  513.                     return false;
  514.                 }
  515.             default:
  516.                 return false;
  517.         }
  518.     }
  519. }
  520.  
  521. /**
  522.  * @global GeoMashupOptions The global instance of the GeoMashupOptions class.
  523.  */
  524. global $geo_mashup_options;
  525. $geo_mashup_options new GeoMashupOptions();

Documentation generated on Sat, 09 Jul 2011 21:54:44 -0700 by phpDocumentor 1.4.3