| @@ -1,472 +1,536 @@ | ||
| 1 | 1 | <?php |
| 2 | +/** | |
| 3 | + * Plugin Name: wp-forecast | |
| 4 | + * Plugin URI: http://www.tuxlog.de | |
| 5 | + * Description: wp-forecast is a highly customizable plugin for WordPress, showing weather-data from Open-Meteo or OpenWeathermMap. | |
| 6 | + * Version: 9.6 | |
| 7 | + * Author: Hans Matzen | |
| 8 | + * Author URI: http://www.tuxlog.de | |
| 9 | + * License: GPLv2 | |
| 10 | + * License URI: https://www.gnu.org/licenses/gpl-2.0.html | |
| 11 | + * Domain Path: lang | |
| 12 | + * Text Domain: wp-forecast | |
| 13 | + * | |
| 14 | + * @package wp-forecast | |
| 15 | + */ | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * Copyright 2006-2025 Hans Matzen | |
| 19 | + * | |
| 20 | + * This program is free software; you can redistribute it and/or modify | |
| 21 | + * it under the terms of the GNU General Public License as published by | |
| 22 | + * the Free Software Foundation; either version 2 of the License, or | |
| 23 | + * (at your option) any later version. | |
| 24 | + * | |
| 25 | + * This program is distributed in the hope that it will be useful, | |
| 26 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 27 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 28 | + * GNU General Public License for more details. | |
| 29 | + * | |
| 30 | + * You should have received a copy of the GNU General Public License | |
| 31 | + * along with this program; if not, write to the Free Software | |
| 32 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 33 | + */ | |
| 34 | + | |
| 35 | +// | |
| 36 | +// maximal number of widgets to use. | |
| 37 | +// | |
| 38 | +$wpf_maxwidgets = 8; | |
| 39 | + | |
| 2 | 40 | /* |
| 3 | -Plugin Name: wp-forecast | |
| 4 | -Plugin URI: http://www.tuxlog.de | |
| 5 | -Description: wp-forecast is a highly customizable plugin for wordpress, showing weather-data from accuweather.com. | |
| 6 | -Version: 3.5 | |
| 7 | -Author: Hans Matzen | |
| 8 | -Author URI: http://www.tuxlog.de | |
| 9 | -*/ | |
| 41 | + ---------- no parameters to change after this point -------------------- | |
| 42 | + */ | |
| 43 | +// define path to wp-forecast plugin. | |
| 44 | +define( 'WPF_PATH', plugin_dir_path( __FILE__ ) ); | |
| 10 | 45 | |
| 11 | -/* | |
| 12 | - Copyright 2006-2011 Hans Matzen | |
| 46 | +// OpenWeathermap functions. | |
| 47 | +require_once 'func-openweathermap.php'; | |
| 48 | +require_once 'func-openweathermap-v2.php'; | |
| 49 | +// Open-Meteo functions. | |
| 50 | +require_once 'func-openmeteo.php'; | |
| 13 | 51 | |
| 14 | - This program is free software; you can redistribute it and/or modify | |
| 15 | - it under the terms of the GNU General Public License as published by | |
| 16 | - the Free Software Foundation; either version 2 of the License, or | |
| 17 | - (at your option) any later version. | |
| 52 | +// OpenUV data functions. | |
| 53 | +require_once 'func-openuv.php'; | |
| 54 | +// ipstack functions. | |
| 55 | +require_once 'func-ipstack.php'; | |
| 18 | 56 | |
| 19 | - This program is distributed in the hope that it will be useful, | |
| 20 | - but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 21 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 22 | - GNU General Public License for more details. | |
| 57 | +// generic functions. | |
| 58 | +require_once 'funclib.php'; | |
| 59 | +// include setup functions. | |
| 60 | +require_once 'wpf-setup.php'; | |
| 61 | +// include admin options page. | |
| 62 | +require_once 'wp-forecast-admin.php'; | |
| 63 | +// display functions. | |
| 64 | +require_once 'wp-forecast-show.php'; | |
| 65 | +// shortcodes. | |
| 66 | +require_once 'shortcodes.php'; | |
| 67 | +// support for WordPress autoupdate. | |
| 68 | +require_once 'wpf-autoupdate.php'; | |
| 69 | +// virtual page class. | |
| 70 | +require_once 'class-wpf-virtualpage.php'; | |
| 23 | 71 | |
| 24 | - You should have received a copy of the GNU General Public License | |
| 25 | - along with this program; if not, write to the Free Software | |
| 26 | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 27 | -*/ | |
| 28 | 72 | |
| 73 | +global $blog_id; | |
| 29 | 74 | |
| 30 | -// | |
| 31 | -// only use this in case of severe problems accessing the admin dialog | |
| 32 | -// | |
| 33 | -// preselected transport method for fetching the weather data | |
| 34 | -// valid values are | |
| 35 | -// curl - uses libcurl | |
| 36 | -// fsockopen - uses fsockopen | |
| 37 | -// streams - uses fopen with streams | |
| 38 | -// exthttp - uses pecl http extension | |
| 39 | -// this will override every setting from the admin dialog | |
| 40 | -// you have to assure that the chosen transport is supported by the | |
| 41 | -// wordpress class WP_Http; | |
| 42 | -// | |
| 43 | -static $wp_forecast_pre_transport=""; | |
| 75 | +/** | |
| 76 | + * Set cache with weather data for current parameters | |
| 77 | + * a wrapper function called via the init hook. | |
| 78 | + */ | |
| 79 | +function wp_forecast_init() { | |
| 80 | + $count = (int) wpf_get_option( 'wp-forecast-count' ); | |
| 44 | 81 | |
| 45 | -// | |
| 46 | -// maximal number of widgets to use | |
| 47 | -// | |
| 48 | -$wpf_maxwidgets=20; | |
| 82 | + $weather = array(); | |
| 49 | 83 | |
| 50 | -// | |
| 51 | -// set to 0 for no debugging information | |
| 52 | -// set to 1 for call stack | |
| 53 | -// set to 2 for call stack including xml parser | |
| 54 | -// | |
| 55 | -static $wpf_debug=0; | |
| 84 | + for ( $i = 0;$i < $count;$i++ ) { | |
| 85 | + $wpfcid = get_widget_id( $i ); | |
| 56 | 86 | |
| 87 | + $wpf_vars = get_wpf_opts( $wpfcid ); | |
| 57 | 88 | |
| 58 | -/* ---------- no parameters to change after this point -------------------- */ | |
| 89 | + // use visitors location for weather and UV. | |
| 90 | + if ( isset( $wpf_vars['visitorlocation'] ) && $wpf_vars['visitorlocation'] ) { | |
| 91 | + // get users ip address. | |
| 92 | + $vip = ipstack_get_visitor_ip(); | |
| 59 | 93 | |
| 60 | -// accuweather data functions | |
| 61 | -require_once("func_accu.php"); | |
| 62 | -// weatherbug data functions | |
| 63 | -require_once("func_bug.php"); | |
| 64 | -// google data functions | |
| 65 | -require_once("func_google.php"); | |
| 94 | + // get location information about ip address. | |
| 95 | + $vloc = ipstack_get_data( wpf_get_option( 'wp-forecast-ipstackapikey' ), $vip ); | |
| 66 | 96 | |
| 67 | -// generic functions | |
| 68 | -require_once("funclib.php"); | |
| 69 | -// include setup functions | |
| 70 | -require_once("wpf_setup.php"); | |
| 71 | -// include admin options page | |
| 72 | -require_once("wp-forecast-admin.php"); | |
| 73 | -// display functions | |
| 74 | -require_once("wp-forecast-show.php"); | |
| 75 | -// shortcodes | |
| 76 | -require_once("shortcodes.php"); | |
| 77 | -// support for wordpress autoupdate | |
| 78 | -require_once("wpf_autoupdate.php"); | |
| 79 | -// super admin dialog | |
| 80 | -require_once("wpf_sa_admin.php"); | |
| 97 | + // find matching locations from open-meteo. | |
| 98 | + // search locations for openmeteo. | |
| 99 | + $openmeteo_loc = get_loclist( $wpf_vars['OPENMETEO_LOC_URI'], ( ! isset( $vloc['city'] ) ? '' : $vloc['city'] ) ); | |
| 81 | 100 | |
| 101 | + // guess the locations which might be correct matching the country. | |
| 102 | + $locations = array(); | |
| 82 | 103 | |
| 83 | -global $blog_id; | |
| 104 | + // prefilter list of found locations to reduce runtime. | |
| 105 | + foreach ( $openmeteo_loc as $al ) { | |
| 106 | + if ( strpos( $al['country'], $vloc['country_name'] ) !== false ) { | |
| 107 | + $locations[] = $al; | |
| 108 | + } | |
| 109 | + } | |
| 84 | 110 | |
| 85 | -// | |
| 86 | -// set cache with weather data for current parameters | |
| 87 | -// a wrapper function called via the init hook | |
| 88 | -// | |
| 111 | + if ( count( $locations ) == 1 ) { | |
| 112 | + // if there is only one location in the array take this one. | |
| 113 | + $wpf_vars['location'] = $locations[0]['name']; | |
| 114 | + $wpf_vars['locname'] = $locations[0]['name']; | |
| 115 | + $wpf_vars['loclatitude'] = $locations[0]['latitude']; | |
| 116 | + $wpf_vars['loclongitude'] = $locations[0]['longitude']; | |
| 117 | + } else { | |
| 118 | + // get the weather data of all the weather locations in the array and find the best match on lat and lon. | |
| 119 | + $ldist = 99000.0; | |
| 120 | + $lat1 = ( ! isset( $vloc['latitude'] ) ? '' : $vloc['latitude'] ); | |
| 121 | + $lon1 = ( ! isset( $vloc['longitude'] ) ? '' : $vloc['longitude'] ); | |
| 122 | + $tloc = ''; | |
| 123 | + $tname = ''; | |
| 124 | + foreach ( $locations as $ll ) { | |
| 125 | + $lat2 = $ll['latitude']; | |
| 126 | + $lon2 = $ll['longitude']; | |
| 127 | + $cdist = distanceCalculation( $lat1, $lon1, $lat2, $lon2 ); | |
| 89 | 128 | |
| 90 | -function wp_forecast_init() | |
| 91 | -{ | |
| 92 | - pdebug(1,"Start of function wp_forecast_init ()"); | |
| 129 | + if ( $cdist < $ldist ) { | |
| 130 | + $ldist = $cdist; | |
| 131 | + $tloc = $ll['name']; | |
| 132 | + $tname = $ll['name']; | |
| 133 | + $tlat = $ll['latitude']; | |
| 134 | + $tlon = $ll['longitude']; | |
| 135 | + } | |
| 136 | + } | |
| 93 | 137 | |
| 94 | - // first of all check if we have to set a hard given | |
| 95 | - // transport method | |
| 96 | - if (isset($wp_forecast_pre_transport) && | |
| 97 | - wpf_get_option("wp-forecast-pre-transport") != $wp_forecast_pre_transport ) | |
| 98 | - { | |
| 99 | - pdebug(1,"Setting hard coded transport method to $wp_forecast_pre_transport"); | |
| 100 | - wpf_update_option("wp-forecast-pre-transport",$wp_forecast_pre_transport); | |
| 101 | - } | |
| 138 | + if ( '' != $tloc ) { | |
| 139 | + $wpf_vars['locname'] = $tname; | |
| 140 | + $wpf_vars['location'] = $tloc; | |
| 141 | + $wpf_vars['loclatitude'] = $tlan; | |
| 142 | + $wpf_vars['loclongitude'] = $tlon; | |
| 143 | + } else { | |
| 144 | + // nothing found set default values. | |
| 145 | + $wpf_vars['location'] = 'Berlin Alexanderplatz'; | |
| 146 | + $wpf_vars['locname'] = 'Berlin Alexanderplatz'; | |
| 147 | + $wpf_vars['loclatitude'] = '52.521918'; | |
| 148 | + $wpf_vars['loclongitude'] = '13.413215'; | |
| 149 | + } | |
| 150 | + } | |
| 102 | 151 | |
| 103 | - $count=(int) wpf_get_option('wp-forecast-count'); | |
| 104 | - | |
| 105 | - $weather=array(); | |
| 106 | - | |
| 107 | - for ($i=0;$i<$count;$i++) | |
| 108 | - { | |
| 109 | - $wpfcid=get_widget_id($i); | |
| 110 | - | |
| 111 | - $wpf_vars=get_wpf_opts($wpfcid); | |
| 152 | + // make sure weather data is updated. | |
| 153 | + $wpf_vars['expire'] = 0; | |
| 112 | 154 | |
| 113 | - if ($wpf_vars['expire'] < time()) | |
| 114 | - { | |
| 115 | - switch ($wpf_vars['service']) | |
| 116 | - { | |
| 117 | - case "accu": | |
| 118 | - $w = accu_get_weather($wpf_vars['ACCU_BASE_URI'], | |
| 119 | - $wpf_vars['location'], | |
| 120 | - $wpf_vars['metric']); | |
| 121 | - // next line is beta for non utf8 charactes in weatherdata | |
| 122 | - $weather=accu_xml_parser(utf8_encode($w)); | |
| 123 | - //$weather=accu_xml_parser($w); | |
| 124 | - break; | |
| 125 | - | |
| 126 | - case "bug": | |
| 127 | - $w1 = bug_get_weather($wpf_vars['BUG_BASE_URI'],$wpf_vars['apikey1'], | |
| 128 | - $wpf_vars['location'],$wpf_vars['metric']); | |
| 129 | - $weather1=bug_xml_parser($w1); | |
| 130 | - $w2 = bug_get_weather($wpf_vars['BUG_FORC_URI'],$wpf_vars['apikey1'], | |
| 131 | - $wpf_vars['location'],$wpf_vars['metric']); | |
| 132 | - $weather2=bug_xml_parser($w2); | |
| 133 | - $weather = array_merge($weather2,$weather1); | |
| 134 | - break; | |
| 155 | + // update wpf_vars in case we changed lat and lon. | |
| 156 | + wpf_update_option( 'wp-forecast-opts' . $wpfcid, serialize( $wpf_vars ) ); | |
| 157 | + } | |
| 135 | 158 | |
| 136 | - case "com": | |
| 137 | - // to be done | |
| 138 | - break; | |
| 139 | - | |
| 140 | - case "google": | |
| 141 | - $w = google_get_weather($wpf_vars['GOOGLE_BASE_URI'], | |
| 142 | - $wpf_vars['location'], | |
| 143 | - substr($wpf_vars['wpf_language'],0,2)); | |
| 144 | - $weather=google_xml_parser(utf8_encode($w)); | |
| 145 | - break; | |
| 146 | - } | |
| 159 | + // check if we have to fetch the weather data or if we can use the cache. | |
| 160 | + if ( $wpf_vars['expire'] < time() ) { | |
| 161 | + switch ( $wpf_vars['service'] ) { | |
| 162 | + case 'openweathermap': | |
| 163 | + $w = openweathermap_get_weather_v2( $wpf_vars['OPENWEATHERMAP_BASE_URI'], $wpf_vars['apikey1'], $wpf_vars['loclatitude'], $wpf_vars['loclongitude'], $wpf_vars['metric'] ); | |
| 164 | + $weather = openweathermap_get_data_v2( $w, $wpf_vars ); | |
| 165 | + break; | |
| 147 | 166 | |
| 148 | - pdebug(1,"Fetched xml was:\n".$w); | |
| 167 | + case 'openweathermap3': | |
| 168 | + $w = openweathermap_get_weather( $wpf_vars['OPENWEATHERMAP_BASE_URI_V3'], $wpf_vars['apikey1'], $wpf_vars['loclatitude'], $wpf_vars['loclongitude'], $wpf_vars['metric'] ); | |
| 169 | + $weather = openweathermap_get_data( $w, $wpf_vars ); | |
| 170 | + break; | |
| 171 | + case 'openmeteo': | |
| 172 | + $w = openmeteo_get_weather( $wpf_vars['OPENMETEO_BASE_URI'], $wpf_vars['loclatitude'], $wpf_vars['loclongitude'], $wpf_vars['metric'] ); | |
| 173 | + $weather = openmeteo_get_data( $w, $wpf_vars ); | |
| 174 | + break; | |
| 175 | + } | |
| 149 | 176 | |
| 150 | - // store weather to database and set expire time | |
| 151 | - // if the current data wasnt available use old data | |
| 152 | - if ( count($weather)>0) | |
| 153 | - { | |
| 154 | - wpf_update_option("wp-forecast-cache".$wpfcid, serialize($weather)); | |
| 155 | - if ( empty($weather['failure']) or $weather['failure'] == "" ) | |
| 156 | - wpf_update_option("wp-forecast-expire".$wpfcid, time()+$wpf_vars['refresh']); | |
| 157 | - else | |
| 158 | - wpf_update_option("wp-forecast-expire".$wpfcid, 0); | |
| 159 | - } | |
| 177 | + // get OpenUV data if wanted. | |
| 178 | + if ( isset( $wpf_vars['ouv_apikey'] ) && trim( $wpf_vars['ouv_apikey'] ) != '' ) { | |
| 179 | + $ouv = openuv_get_data( $wpf_vars['ouv_apikey'], $weather['lat'], $weather['lon'] ); | |
| 180 | + if ( is_wp_error( $ouv ) ) { | |
| 181 | + $weather['openuv'] = ''; | |
| 182 | + $weather['failure'] = $ouv->get_error_message(); | |
| 183 | + } else { | |
| 184 | + $weather['openuv'] = $ouv; | |
| 185 | + } | |
| 186 | + } | |
| 187 | + | |
| 188 | + // store weather to database and set expire time. | |
| 189 | + // if the current data wasnt available use old data. | |
| 190 | + if ( count( $weather ) > 0 ) { | |
| 191 | + wpf_update_option( 'wp-forecast-cache' . $wpfcid, serialize( $weather ) ); | |
| 192 | + if ( empty( $weather['failure'] ) || '' == $weather['failure'] ) { | |
| 193 | + wpf_update_option( 'wp-forecast-expire' . $wpfcid, time() + $wpf_vars['refresh'] ); | |
| 194 | + } else { | |
| 195 | + wpf_update_option( 'wp-forecast-expire' . $wpfcid, 0 ); | |
| 196 | + } | |
| 197 | + } | |
| 198 | + } | |
| 160 | 199 | } |
| 161 | - } | |
| 162 | - | |
| 163 | - // javascript hinzufügen fuer ajax widget | |
| 164 | - wp_enqueue_script('wpf_update', | |
| 165 | - '/' . PLUGINDIR . '/wp-forecast/wpf_update.js', | |
| 166 | - array('jquery'), "9999"); | |
| 167 | 200 | |
| 168 | - pdebug(1,"End of function wp_forecast_init ()"); | |
| 201 | + // javascript hinzufügen fuer ajax widget. | |
| 202 | + if ( ! is_admin() && get_option( 'wpf_sem_ajaxload' ) > 0 ) { | |
| 203 | + wp_enqueue_script( 'wpf_update', plugins_url( 'wpf_update.js', __FILE__ ), array( 'jquery' ), '9999' ); | |
| 204 | + } | |
| 205 | + // javascript hinzufügen für suche im admin dialog. | |
| 206 | + if ( is_admin() ) { | |
| 207 | + wp_enqueue_script( 'wp-color-picker' ); | |
| 208 | + wp_enqueue_script( 'wp-forecast-search', plugins_url( 'wp-forecast-admin.js', __FILE__ ), array( 'jquery' ), '9999' ); | |
| 209 | + } | |
| 210 | + | |
| 211 | + // add css attribute display to the list of safe css styles for pulldown widget. | |
| 212 | + add_filter( | |
| 213 | + 'safe_style_css', | |
| 214 | + function( $styles ) { | |
| 215 | + $styles[] = 'display'; | |
| 216 | + return $styles; | |
| 217 | + } | |
| 218 | + ); | |
| 169 | 219 | } |
| 170 | 220 | |
| 171 | 221 | |
| 172 | -// | |
| 173 | -// this function is called from your template | |
| 174 | -// to insert your weather data at the place you want it to be | |
| 175 | -// support to select language on a per call basis from Robert Lang | |
| 176 | -// | |
| 177 | -function wp_forecast_widget($args=array(),$wpfcid="A", $language_override=null) | |
| 178 | -{ | |
| 222 | +/** | |
| 223 | + * This function is called from your template | |
| 224 | + * to insert your weather data at the place you want it to be | |
| 225 | + * support to select language on a per call basis from Robert Lang. | |
| 226 | + * | |
| 227 | + * @param array $args Default parameters. | |
| 228 | + * @param string $wpfcid The Widget ID. | |
| 229 | + * @param string $language_override ISO Code of the language. | |
| 230 | + */ | |
| 231 | +function wp_forecast_widget( $args = array(), $wpfcid = 'A', $language_override = null ) { | |
| 232 | + if ( '?' == $wpfcid ) { | |
| 233 | + $wpf_vars = get_wpf_opts( 'A' ); | |
| 234 | + } else { | |
| 235 | + $wpf_vars = get_wpf_opts( $wpfcid ); | |
| 236 | + } | |
| 179 | 237 | |
| 180 | - pdebug(1,"Start of function wp_forecast_widget (".$wpfcid.")"); | |
| 181 | - | |
| 182 | - if ($wpfcid == "?") | |
| 183 | - $wpf_vars=get_wpf_opts("A"); | |
| 184 | - else | |
| 185 | - $wpf_vars=get_wpf_opts($wpfcid); | |
| 238 | + if ( ! empty( $language_override ) ) { | |
| 239 | + $wpf_vars['wpf_language'] = $language_override; | |
| 240 | + } | |
| 186 | 241 | |
| 187 | - if (!empty($language_override)) { | |
| 188 | - $wpf_vars['wpf_language']=$language_override; | |
| 189 | - } | |
| 242 | + if ( '?' == $wpfcid ) { | |
| 243 | + $weather = maybe_unserialize( wpf_get_option( 'wp-forecast-cacheA' ) ); | |
| 244 | + } else { | |
| 245 | + $weather = maybe_unserialize( wpf_get_option( 'wp-forecast-cache' . $wpfcid ) ); | |
| 246 | + } | |
| 190 | 247 | |
| 191 | - if ($wpfcid == "?") | |
| 192 | - $weather=maybe_unserialize(wpf_get_option("wp-forecast-cacheA")); | |
| 193 | - else | |
| 194 | - $weather=maybe_unserialize(wpf_get_option("wp-forecast-cache".$wpfcid)); | |
| 248 | + show( $wpfcid, $args, $wpf_vars ); | |
| 249 | +} | |
| 195 | 250 | |
| 196 | - show($wpfcid,$args,$wpf_vars); | |
| 251 | +/** | |
| 252 | + * This is the wrapper function for displaying from sidebar.php | |
| 253 | + * and not as a widget. since the parameters are different we need this. | |
| 254 | + * | |
| 255 | + * @param string $wpfcid The Widget ID. | |
| 256 | + * @param string $language_override ISO Code of the language. | |
| 257 | + */ | |
| 258 | +function wp_forecast( $wpfcid = 'A', $language_override = null ) { | |
| 259 | + wp_forecast_widget( array(), $wpfcid, $language_override ); | |
| 260 | +} | |
| 197 | 261 | |
| 198 | - pdebug(1,"End of function wp_forecast_widget ()"); | |
| 199 | -} | |
| 262 | +/** | |
| 263 | + * A function to show a range of widgets at once. | |
| 264 | + * | |
| 265 | + * @param int $from Lowest widget number to display. | |
| 266 | + * @param int $to Highest widget number to display. | |
| 267 | + * @param int $numpercol Number of widgets per column. | |
| 268 | + * @param string $language_override ISO Code of the language. | |
| 269 | + */ | |
| 270 | +function wp_forecast_range( $from = 0, $to = 0, $numpercol = 1, $language_override = null ) { | |
| 271 | + global $wpf_maxwidgets; | |
| 272 | + $wcount = 1; | |
| 200 | 273 | |
| 201 | -// | |
| 202 | -// this is the wrapper function for displaying from sidebar.php | |
| 203 | -// and not as a widget. since the parameters are different we need this | |
| 204 | -// | |
| 205 | -function wp_forecast($wpfcid="A", $language_override=null) | |
| 206 | -{ | |
| 207 | - pdebug(1,"Start of function wp_forecast ()"); | |
| 208 | - | |
| 209 | - wp_forecast_widget( array(), $wpfcid, $language_override); | |
| 274 | + // check min and max limit. | |
| 275 | + if ( $from < 0 ) { | |
| 276 | + $from = 0; | |
| 277 | + } | |
| 210 | 278 | |
| 211 | - pdebug(1,"End of function wp_forecast ()"); | |
| 212 | -} | |
| 279 | + if ( $to > $wpf_maxwidgets ) { | |
| 280 | + $to = $wpf_maxwidgets; | |
| 281 | + } | |
| 213 | 282 | |
| 214 | -// | |
| 215 | -// a function to show a range of widgets at once | |
| 216 | -// | |
| 217 | -function wp_forecast_range($from=0, $to=0, $numpercol=1, $language_override=null) | |
| 218 | -{ | |
| 219 | - global $wpf_maxwidgets; | |
| 220 | - $wcount=1; | |
| 283 | + // output table header. | |
| 284 | + echo '<table><tr>'; | |
| 221 | 285 | |
| 222 | - // check min and max limit | |
| 223 | - if ($from < 0) | |
| 224 | - $from = 0; | |
| 225 | - | |
| 226 | - if ($to > $wpf_maxwidgets) | |
| 227 | - $to = $wpf_maxwidgets; | |
| 228 | - | |
| 229 | - // output table header | |
| 230 | - echo "<table><tr>"; | |
| 286 | + // out put widgets in a table. | |
| 287 | + for ( $i = $from;$i <= $to;$i++ ) { | |
| 231 | 288 | |
| 232 | - // out put widgets in a table | |
| 233 | - for ($i=$from;$i<=$to;$i++) { | |
| 289 | + if ( 1 == $wcount % $numpercol ) { | |
| 290 | + echo '<tr>'; | |
| 291 | + } | |
| 234 | 292 | |
| 235 | - if ( $wcount % $numpercol == 1) | |
| 236 | - echo "<tr>"; | |
| 293 | + echo '<td>'; | |
| 294 | + wp_forecast( get_widget_id( $i ), $language_override ); | |
| 295 | + echo '</td>'; | |
| 237 | 296 | |
| 238 | - echo "<td>"; | |
| 239 | - wp_forecast( get_widget_id($i), $language_override); | |
| 240 | - echo "</td>"; | |
| 297 | + if ( ( 0 == $wcount % $numpercol ) && ( $i < $to ) ) { | |
| 298 | + echo '</tr>'; | |
| 299 | + } | |
| 241 | 300 | |
| 242 | - if ( ($wcount % $numpercol == 0) and ($i< $to)) | |
| 243 | - echo "</tr>"; | |
| 301 | + ++$wcount; | |
| 302 | + } | |
| 244 | 303 | |
| 245 | - $wcount += 1; | |
| 246 | - } | |
| 247 | - | |
| 248 | - // output table footer | |
| 249 | - echo "</tr></table>"; | |
| 304 | + // output table footer. | |
| 305 | + echo '</tr></table>'; | |
| 250 | 306 | } |
| 251 | 307 | |
| 252 | -// | |
| 253 | -// a function to show a set of widgets at once | |
| 254 | -// | |
| 255 | -function wp_forecast_set($wset, $numpercol=1, $language_override=null) | |
| 256 | -{ | |
| 257 | - global $wpf_maxwidgets; | |
| 258 | - $wcount=1; | |
| 259 | - $wset_max= count($wset)-1; | |
| 308 | +/** | |
| 309 | + * A function to show a set of widgets at once. | |
| 310 | + * | |
| 311 | + * @param array $wset Array with numbers of widgets to display. | |
| 312 | + * @param int $numpercol Number of widgets per column. | |
| 313 | + * @param string $language_override ISO Code of the language. | |
| 314 | + */ | |
| 315 | +function wp_forecast_set( $wset, $numpercol = 1, $language_override = null ) { | |
| 316 | + global $wpf_maxwidgets; | |
| 317 | + $wcount = 1; | |
| 318 | + $wset_max = count( $wset ) - 1; | |
| 260 | 319 | |
| 261 | - // output table header | |
| 262 | - echo "<table><tr>"; | |
| 320 | + // output table header. | |
| 321 | + echo '<table><tr>'; | |
| 263 | 322 | |
| 264 | - // out put widgets in a table | |
| 265 | - for ($i=0;$i<=$wset_max;$i++) { | |
| 323 | + // out put widgets in a table. | |
| 324 | + for ( $i = 0;$i <= $wset_max;$i++ ) { | |
| 266 | 325 | |
| 267 | - if ( $wcount % $numpercol == 1) | |
| 268 | - echo "<tr>"; | |
| 326 | + if ( 1 == $wcount % $numpercol ) { | |
| 327 | + echo '<tr>'; | |
| 328 | + } | |
| 269 | 329 | |
| 270 | - echo "<td>"; | |
| 271 | - wp_forecast( $wset[$i], $language_override); | |
| 272 | - echo "</td>"; | |
| 330 | + echo '<td>'; | |
| 331 | + wp_forecast( $wset[ $i ], $language_override ); | |
| 332 | + echo '</td>'; | |
| 273 | 333 | |
| 274 | - if ( ($wcount % $numpercol == 0) and ($i< $wset_max)) | |
| 275 | - echo "</tr>"; | |
| 334 | + if ( ( 0 == $wcount % $numpercol ) && ( $i < $wset_max ) ) { | |
| 335 | + echo '</tr>'; | |
| 336 | + } | |
| 276 | 337 | |
| 277 | - $wcount += 1; | |
| 278 | - } | |
| 279 | - | |
| 280 | - // output table footer | |
| 281 | - echo "</tr></table>"; | |
| 338 | + ++$wcount; | |
| 339 | + } | |
| 340 | + | |
| 341 | + // output table footer. | |
| 342 | + echo '</tr></table>'; | |
| 282 | 343 | } |
| 283 | 344 | |
| 284 | -// | |
| 285 | -// returns the widget data as an array | |
| 286 | -// | |
| 287 | -function wp_forecast_data($wpfcid="A", $language_override=null) | |
| 288 | -{ | |
| 289 | - pdebug(1,"Start of function wp_forecast_data ()"); | |
| 290 | - | |
| 291 | - $wpf_vars=get_wpf_opts($wpfcid); | |
| 345 | +/** | |
| 346 | + * Returns the widget data as an array. | |
| 347 | + * | |
| 348 | + * @param string $wpfcid The Widget ID. | |
| 349 | + * @param string $language_override ISO Code of the language. | |
| 350 | + */ | |
| 351 | +function wp_forecast_data( $wpfcid = 'A', $language_override = null ) { | |
| 352 | + $wpf_vars = get_wpf_opts( $wpfcid ); | |
| 292 | 353 | |
| 293 | - if (!empty($language_override)) { | |
| 294 | - $wpf_vars['wpf_language']=$language_override; | |
| 295 | - } | |
| 354 | + if ( ! empty( $language_override ) ) { | |
| 355 | + $wpf_vars['wpf_language'] = $language_override; | |
| 356 | + } | |
| 296 | 357 | |
| 297 | - extract($wpf_vars); | |
| 298 | - $w=maybe_unserialize(wpf_get_option("wp-forecast-cache".$wpfcid)); | |
| 358 | + $w = maybe_unserialize( wpf_get_option( 'wp-forecast-cache' . $wpfcid ) ); | |
| 299 | 359 | |
| 300 | - $weather_arr=array(); | |
| 360 | + $weather_arr = array(); | |
| 301 | 361 | |
| 302 | - // read service dependent weather data | |
| 303 | - switch ($wpf_vars['service']) { | |
| 304 | - case "accu": | |
| 305 | - $weather_arr= accu_forecast_data($wpfcid,$language_override); | |
| 306 | - break; | |
| 307 | - case "bug": | |
| 308 | - $weather_arr= bug_forecast_data($wpfcid,$language_override); | |
| 309 | - break; | |
| 310 | - case "com": | |
| 311 | - // to be done | |
| 312 | - break; | |
| 313 | - case "google": | |
| 314 | - $weather_arr= google_forecast_data($wpfcid,$language_override); | |
| 315 | - break; | |
| 316 | - } | |
| 362 | + // read service dependent weather data. | |
| 363 | + switch ( $wpf_vars['service'] ) { | |
| 364 | + case 'openweathermap': | |
| 365 | + $weather_arr = openweathermap_forecast_data_v2( $wpfcid, $language_override ); | |
| 366 | + break; | |
| 367 | + case 'openweathermap3': | |
| 368 | + $weather_arr = openweathermap_forecast_data( $wpfcid, $language_override ); | |
| 369 | + break; | |
| 370 | + case 'openmeteo': | |
| 371 | + $weather_arr = openmeteo_forecast_data( $wpfcid, $language_override ); | |
| 372 | + break; | |
| 373 | + } | |
| 317 | 374 | |
| 318 | - return $weather_arr; | |
| 319 | - | |
| 320 | - pdebug(1,"End of function wp_forecast_data ()"); | |
| 321 | - | |
| 375 | + // add openuv data to weather_arr. | |
| 376 | + if ( is_array( $w ) && array_key_exists( 'openuv', $w ) ) { | |
| 377 | + $weather_arr['openuv'] = $w['openuv']; | |
| 378 | + } else { | |
| 379 | + $weather_arr['openuv'] = array(); | |
| 380 | + } | |
| 381 | + | |
| 382 | + return $weather_arr; | |
| 322 | 383 | } |
| 323 | 384 | |
| 324 | 385 | |
| 325 | -// | |
| 326 | -// set the choosen number of widgets, set at the widget page | |
| 327 | -// | |
| 328 | -function wpf_widget_setup() { | |
| 329 | - global $wpf_maxwidgets; | |
| 386 | +/** | |
| 387 | + * Register the wp-forecast widget | |
| 388 | + */ | |
| 389 | +function reg_wpf_widget() { | |
| 390 | + return register_widget( 'wpf_widget' ); | |
| 391 | +} | |
| 392 | +/** | |
| 393 | + * Register the UV Widget | |
| 394 | + */ | |
| 395 | +function reg_wpf_uv_widget() { | |
| 396 | + return register_widget( 'WpfUvWidget' ); | |
| 397 | +} | |
| 330 | 398 | |
| 331 | - pdebug(1,"Start of function wpf_widget_setup ()"); | |
| 332 | - | |
| 333 | - $count = $newcount = wpf_get_option('wp-forecast-count'); | |
| 334 | - if ( isset($_POST['wpf-count-submit']) ) { | |
| 335 | - $number = (int) $_POST['wp-forecast-count']; | |
| 336 | - if ( $number > $wpf_maxwidgets ) $number = $wpf_maxwidgets; | |
| 337 | - if ( $number < 1 ) $number = 1; | |
| 338 | - $newcount = $number; | |
| 339 | - } | |
| 340 | - if ( $count != $newcount ) { | |
| 341 | - $count = $newcount; | |
| 342 | - wpf_update_option('wp-forecast-count', $count); | |
| 343 | - // add missing option to database | |
| 344 | - wp_forecast_activate(); | |
| 345 | - // init the new number of widgets | |
| 346 | - widget_wp_forecast_init($count); | |
| 347 | - } | |
| 399 | +/** | |
| 400 | + * Init the wp-forecast widgets. | |
| 401 | + */ | |
| 402 | +function widget_wp_forecast_init() { | |
| 403 | + global $wp_version,$wpf_maxwidgets, $wpf_lang_dict; | |
| 348 | 404 | |
| 349 | - pdebug(1,"End of function wpf_widget_setup ()"); | |
| 350 | -} | |
| 405 | + // include widget class. | |
| 406 | + require_once 'class-wpf-widget.php'; | |
| 407 | + require_once 'class-wpfuvwidget.php'; | |
| 351 | 408 | |
| 352 | -// | |
| 353 | -// form snippet to set the number of wanted widgets from | |
| 354 | -// the widget page | |
| 355 | -// | |
| 356 | -function wpf_widget_page() { | |
| 357 | - global $wpf_maxwidgets; | |
| 358 | - | |
| 359 | - pdebug(1,"Start of function wpf_widget_page ()"); | |
| 360 | - | |
| 361 | - $count = $newcount = wpf_get_option('wp-forecast-count'); | |
| 362 | - | |
| 363 | - // get locale | |
| 364 | - $locale = get_locale(); | |
| 365 | - if ( empty($locale) ) | |
| 366 | - $locale = 'en_US'; | |
| 367 | - // load translation | |
| 368 | - if(function_exists('load_textdomain')) { | |
| 369 | - load_textdomain("wp-forecast_".$locale,ABSPATH . "wp-content/plugins/wp-forecast/lang/".$locale.".mo"); | |
| 370 | - } | |
| 409 | + $count = (int) wpf_get_option( 'wp-forecast-count' ); | |
| 371 | 410 | |
| 411 | + // check for widget support. | |
| 412 | + if ( ! function_exists( 'register_sidebar_widget' ) ) { | |
| 413 | + return; | |
| 414 | + } | |
| 372 | 415 | |
| 373 | - $out = "<div class='wrap'><form method='POST'>"; | |
| 374 | - $out .= "<h2>WP-Forecast Widgets</h2>"; | |
| 375 | - $out .= "<p style='line-height: 30px;'>".__('How many wp-forecast widgets would you like?',"wp-forecast_".$locale)." "; | |
| 376 | - $out .= "<select id='wp-forecast-count' name='wp-forecast-count' value='".$count."'>"; | |
| 416 | + // add fetch weather data to init the cache before any headers are sent. | |
| 417 | + add_action( 'init', 'wp_forecast_init' ); | |
| 418 | + add_action( 'admin_init', 'wp_forecast_admin_init' ); | |
| 377 | 419 | |
| 378 | - for ( $i = 1; $i <= $wpf_maxwidgets; ++$i ) { | |
| 379 | - $out .= "<option value='$i' "; | |
| 380 | - if ($count==$i) | |
| 381 | - $out .= "selected='selected' "; | |
| 382 | - $out .= ">$i</option>"; | |
| 383 | - } | |
| 384 | - $out .= "</select> <span class='submit'><input type='submit' name='wpf-count-submit' id='wpf-count-submit' value=".esc_attr(__('Save'))." /></span></p></form></div>"; | |
| 385 | - echo $out; | |
| 420 | + // add css. | |
| 421 | + add_action( 'wp_enqueue_scripts', 'wp_forecast_css' ); | |
| 386 | 422 | |
| 387 | - pdebug(1,"End of function wpf_widget_page ()"); | |
| 388 | -} | |
| 423 | + for ( $i = 0;$i <= $wpf_maxwidgets;$i++ ) { | |
| 424 | + $wpfcid = get_widget_id( $i ); | |
| 389 | 425 | |
| 390 | -function widget_wp_forecast_init() | |
| 391 | -{ | |
| 426 | + // register our widget and add a control. | |
| 427 | + // translators: %s is for the Widget ID. | |
| 428 | + $name = sprintf( __( 'wp-forecast %s' ), $wpfcid ); | |
| 429 | + $id = "wp-forecast-$wpfcid"; | |
| 392 | 430 | |
| 393 | - global $wp_version,$wpf_maxwidgets; | |
| 431 | + // translators: %s is for the widget ID. | |
| 432 | + $uvname = sprintf( __( 'wp-forecast-uv %s' ), $wpfcid ); | |
| 433 | + $uvid = "wp-forecast-uv-$wpfcid"; | |
| 394 | 434 | |
| 395 | - pdebug(1,"Start of function widget_wp_forecast_init ()"); | |
| 396 | - | |
| 397 | - $count=(int) wpf_get_option('wp-forecast-count'); | |
| 435 | + // add widget. | |
| 436 | + add_action( 'widgets_init', 'reg_wpf_widget' ); | |
| 437 | + add_action( 'widgets_init', 'reg_wpf_uv_widget' ); | |
| 398 | 438 | |
| 399 | - // check for widget support | |
| 400 | - if ( !function_exists('register_sidebar_widget') ) | |
| 401 | - return; | |
| 439 | + wp_unregister_sidebar_widget( $i >= $count ? 'wp_forecast_widget' . $wpfcid : '' ); | |
| 402 | 440 | |
| 403 | - // add fetch weather data to init the cache before any headers are sent | |
| 404 | - add_action('init','wp_forecast_init'); | |
| 405 | - add_action('init','wp_forecast_admin_init'); | |
| 406 | - | |
| 407 | - // add css in header | |
| 408 | - add_action('wp_head', 'wp_forecast_css'); | |
| 409 | - | |
| 410 | - // javascript hinzufügen | |
| 411 | - //wp_enqueue_script('wpf_update', | |
| 412 | -// '/' . PLUGINDIR . '/wp-forecast/wpf_update.js', | |
| 413 | -// array('jquery'), "9999"); | |
| 441 | + wp_register_widget_control( | |
| 442 | + $id, | |
| 443 | + $name, | |
| 444 | + $i < $count ? 'wpf_admin_hint' : '', | |
| 445 | + array( | |
| 446 | + 'width' => 300, | |
| 447 | + 'height' => 150, | |
| 448 | + ) | |
| 449 | + ); | |
| 414 | 450 | |
| 415 | - for ($i=0;$i<=$wpf_maxwidgets;$i++) { | |
| 416 | - $wpfcid = get_widget_id( $i ); | |
| 451 | + wp_unregister_widget_control( $i >= $count ? 'wpf_admin_hint' . $wpfcid : '' ); | |
| 452 | + } | |
| 453 | +} | |
| 417 | 454 | |
| 418 | - // register our widget and add a control | |
| 419 | - $name = sprintf(__('wp-forecast %s'), $wpfcid); | |
| 420 | - $id = "wp-forecast-$wpfcid"; | |
| 421 | - | |
| 422 | - | |
| 423 | - // include widget class (new widget api) | |
| 424 | - require_once("class-wpf_widget.php"); | |
| 425 | - // register class | |
| 426 | - add_action('widgets_init', create_function('', 'return register_widget("wpf_widget");')); | |
| 427 | - | |
| 428 | - wp_unregister_sidebar_widget($i >= $count ? 'wp_forecast_widget'.$wpfcid:''); | |
| 429 | - | |
| 430 | - wp_register_widget_control($id, $name, $i < $count ? 'wpf_admin_hint' : '', | |
| 431 | - array('width' => 300, 'height' => 150)); | |
| 432 | - | |
| 433 | - wp_unregister_widget_control($i >= $count ? 'wpf_admin_hint'.$wpfcid : ''); | |
| 434 | - } | |
| 455 | +/** | |
| 456 | + * Filters the REQUEST_URI for virtual page slug | |
| 457 | + * to show weather in an iframe. | |
| 458 | + */ | |
| 459 | +function wpf_filter_url() { | |
| 460 | + $url = ( isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' ); | |
| 461 | + $url = trim( parse_url( $url, PHP_URL_PATH ), '/' ); | |
| 435 | 462 | |
| 436 | - // add actions for setup the count of wanted wpf widgets | |
| 437 | - add_action('sidebar_admin_setup', 'wpf_widget_setup'); | |
| 438 | - add_action('sidebar_admin_page', 'wpf_widget_page'); | |
| 463 | + // determine if it is a wpf virtual page call. | |
| 464 | + if ( strpos( $url, 'wp-forecast-direct' ) !== false ) { | |
| 465 | + $wpfcid = ( isset( $_GET['wpfcid'] ) ? sanitize_text_field( wp_unslash( $_GET['wpfcid'] ) ) : 'A' ); | |
| 466 | + $language_override = ( isset( $_GET['language_override'] ) ? sanitize_text_field( wp_unslash( $_GET['language_override'] ) ) : '' ); | |
| 467 | + $header = ( isset( $_GET['header'] ) ? sanitize_text_field( wp_unslash( $_GET['header'] ) ) : '' ); | |
| 468 | + $selector = ( isset( $_GET['selector'] ) ? sanitize_text_field( wp_unslash( $_GET['selector'] ) ) : '' ); | |
| 439 | 469 | |
| 440 | - // add filters for transport method check | |
| 441 | - add_filter('use_fsockopen_transport','wpf_check_fsockopen'); | |
| 442 | - add_filter('use_fopen_transport','wpf_check_fopen'); | |
| 443 | - add_filter('use_streams_transport','wpf_check_streams'); | |
| 444 | - add_filter('use_http_extension_transport','wpf_check_exthttp'); | |
| 445 | - add_filter('use_curl_transport','wpf_check_curl'); | |
| 470 | + if ( '1' == $selector ) { | |
| 471 | + $selector = '?'; | |
| 472 | + } | |
| 473 | + $args = array(); | |
| 474 | + $wpf_vars = get_wpf_opts( $wpfcid ); | |
| 446 | 475 | |
| 447 | - pdebug(1,"End of function widget_wp_forecast_init ()"); | |
| 476 | + if ( ! empty( $language_override ) ) { | |
| 477 | + $wpf_vars['wpf_language'] = $language_override; | |
| 478 | + } | |
| 448 | 479 | |
| 449 | -} | |
| 480 | + $weather = maybe_unserialize( wpf_get_option( 'wp-forecast-cache' . $wpfcid ) ); | |
| 450 | 481 | |
| 482 | + // only show weather html without page or header. | |
| 483 | + if ( ! $header || 0 == $header ) { | |
| 484 | + show( $selector . $wpfcid, $args, $wpf_vars ); | |
| 485 | + exit; | |
| 486 | + } | |
| 451 | 487 | |
| 488 | + if ( 1 == $header ) { | |
| 489 | + echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n"; | |
| 490 | + echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="' . esc_attr( str_replace( '_', '-', $wpf_vars['wpf_language'] ) ) . '">' . "\n"; | |
| 491 | + echo "<head><title>wp-forecast iframe</title>\n"; | |
| 492 | + echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />' . "\n"; | |
| 493 | + echo '<style>' . wp_kses( wp_forecast_get_nowp_css(), wpf_allowed_tags() ) . '</style>' . "\n"; | |
| 494 | + echo "</head>\n<body>\n"; | |
| 452 | 495 | |
| 453 | -// MAIN | |
| 496 | + show( $selector . $wpfcid, $args, $wpf_vars ); | |
| 454 | 497 | |
| 455 | -pdebug(1,"Start of MAIN"); | |
| 498 | + echo "</body></html>\n"; | |
| 499 | + exit; | |
| 500 | + } | |
| 456 | 501 | |
| 457 | -// activating deactivating the plugin | |
| 458 | -register_activation_hook(__FILE__,'wp_forecast_activate'); | |
| 459 | -register_deactivation_hook(__FILE__,'wp_forecast_deactivate'); | |
| 502 | + if ( 2 == $header ) { | |
| 503 | + // create weather html. | |
| 504 | + // add css. | |
| 505 | + add_action( 'wp_enqueue_scripts', 'wp_forecast_css_nowp' ); | |
| 506 | + ob_start(); | |
| 507 | + show( $selector . $wpfcid, $args, $wpf_vars ); | |
| 508 | + $out = ob_get_contents(); | |
| 509 | + ob_end_clean(); | |
| 460 | 510 | |
| 461 | -// add option page | |
| 462 | -add_action('admin_menu', 'wp_forecast_admin'); | |
| 511 | + // create virtual page and display it. | |
| 512 | + $args = array( | |
| 513 | + 'slug' => 'wp-forecast-direct', | |
| 514 | + 'title' => 'wp-forecast weather', | |
| 515 | + 'content' => $out, | |
| 516 | + ); | |
| 517 | + $pg4 = new Wpf_VirtualPage( $args ); | |
| 518 | + } | |
| 519 | + } | |
| 520 | +} | |
| 463 | 521 | |
| 464 | -// add super admin options page (check for super admin is done inside) | |
| 465 | -add_action('admin_menu', 'wpmu_forecast_admin'); | |
| 466 | 522 | |
| 523 | +// MAIN. | |
| 524 | + | |
| 525 | +// activating deactivating the plugin. | |
| 526 | +register_activation_hook( __FILE__, 'wp_forecast_activate' ); | |
| 527 | +register_deactivation_hook( __FILE__, 'wp_forecast_deactivate' ); | |
| 528 | + | |
| 529 | +// add option page. | |
| 530 | +add_action( 'admin_menu', 'wp_forecast_admin' ); | |
| 531 | + | |
| 467 | 532 | // Run our code later in case this loads prior to any required plugins. |
| 468 | -add_action('plugins_loaded', 'widget_wp_forecast_init'); | |
| 533 | +add_action( 'plugins_loaded', 'widget_wp_forecast_init' ); | |
| 469 | 534 | |
| 470 | - | |
| 471 | -pdebug(1,"End of MAIN"); | |
| 472 | -?> | |
| 535 | +// add virtual page filter. | |
| 536 | +add_action( 'init', 'wpf_filter_url' ); | |