PluginProbe
wp-forecast / 9.6
wp-forecast v9.6
10.0 trunk 1.4 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3..5 3..8 3.0 3.1 3.2 3.3 3.4 3.6 All 86 releases
wp-forecast / wp-forecast-admin.php

wp-forecast-admin.php in wp-forecast 9.6, at wp-forecast-admin.php

1,526 lines 53.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /** This file is part of the wp-forecast plugin for WordPress
3 *
4 * Copyright 2006-2024 Hans Matzen (email : webmaster at tuxlog dot de)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * @package wp-forecast
21 */
22
23 /** Location array and counter init. */
24 $loc = array();
25 $i = 0;
26
27 // generic functions.
28 require_once 'funclib.php';
29 require_once 'func-openweathermap.php';
30 require_once 'func-openweathermap-v2.php';
31 require_once 'func-openmeteo.php';
32 require_once 'supp/supp.php';
33
34 /**
35 * Delete cache if parameters are changed, to make sure
36 * current data will be available with next call.
37 */
38 function wp_forecast_admin_init() {
39 $count = wpf_get_option( 'wp-forecast-count' );
40
41 // Query arguments.
42 $wpfqs = '';
43 if ( isset( $_SERVER['QUERY_STRING'] ) ) {
44 $wpfqs = sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) );
45 }
46
47 if ( ( 'page=wp-forecast-admin.php' == $wpfqs ) && ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] ) ) {
48 for ( $i = 0;$i < $count;$i++ ) {
49 $wpfcid = get_widget_id( $i );
50
51 // delete cache for old location.
52 wpf_update_option( 'wp-forecast-expire' . $wpfcid, '0' );
53 wpf_update_option( 'wp-forecast-cache' . $wpfcid, '' );
54 }
55 }
56
57 // add thickbox and jquery for checklist.
58 wp_enqueue_script( 'thickbox' );
59 wp_enqueue_style( 'thickbox' );
60
61 wp_localize_script( 'wpf_search', 'wpf_search', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
62 add_action( 'wp_ajax_nopriv_wpf_search_ajax', 'wpf_search_ajax' );
63 add_action( 'wp_ajax_wpf_search_ajax', 'wpf_search_ajax' );
64 add_action( 'wp_ajax_nopriv_wpf_check_ajax', 'wpf_check_ajax' );
65 add_action( 'wp_ajax_wpf_check_ajax', 'wpf_check_ajax' );
66
67 // add admin notice concerning the problems with accuweather.
68 add_action( 'admin_notices', 'wpf_accuweather_problem_notice' );
69 }
70
71 /**
72 * Ajax funktion fuer die suche im admin dialog.
73 */
74 function wpf_search_ajax() {
75 // check nonce3.
76 if ( ! isset( $_POST['wpf_nonce_3'] ) ) {
77 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
78 }
79 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpf_nonce_3'] ) ), 'wpf_nonce_3' ) ) {
80 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
81 }
82
83 $wpf_vars = get_wpf_opts( ( isset( $_POST['wpfcid'] ) ? sanitize_text_field( wp_unslash( $_POST['wpfcid'] ) ) : 'A' ) );
84 $av = $wpf_vars;
85 $locale = $wpf_vars['wpf_language'];
86
87 // get translations.
88 if ( function_exists( 'load_plugin_textdomain' ) ) {
89 add_filter( 'plugin_locale', 'wpf_lplug', 10, 2 );
90 load_plugin_textdomain( 'wp-forecast', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
91 remove_filter( 'plugin_locale', 'wpf_lplug', 10, 2 );
92 }
93
94 $res = '';
95 $res .= '<h2>' . esc_attr__( 'Searchresults', 'wp-forecast' ) . ':</h2>';
96
97 if ( trim( ( isset( $_POST['searchterm'] ) ? sanitize_text_field( wp_unslash( $_POST['searchterm'] ) ) : '' ) ) == '' ) {
98 $res .= '<p>' . esc_attr__( 'Please enter a non empty searchstring', 'wp-forecast' ) . '</p>';
99 } else {
100 $res .= '<p>' . esc_attr__( 'Please select a location', 'wp-forecast' ) . ':</p>';
101
102 // search locations for openmeteo.
103 $openmeteo_loc = get_loclist( $av['OPENMETEO_LOC_URI'], ( isset( $_POST['searchterm'] ) ? sanitize_text_field( wp_unslash( $_POST['searchterm'] ) ) : '' ) );
104
105 $i = 0;
106 // output searchresults.
107 $res .= '<table border="1" ><thead><tr><th>';
108 $res .= esc_attr__( 'Open-Meteo Hits', 'wp-forecast' );
109 $res .= '</th></tr></thead><tbody>';
110
111 $k = count( $openmeteo_loc );
112 $i = 0;
113
114 while ( $i < $k ) {
115 $res .= '<tr>';
116
117 $res .= '<td><a href="#" onclick="wpf_set_loc(\'' . addslashes( $openmeteo_loc[ $i ]['name'] ) . '\',' . $openmeteo_loc[ $i ]['latitude'] . ',' . $openmeteo_loc[ $i ]['longitude'] . ');" >';
118 $res .= $openmeteo_loc[ $i ]['name'] . ', ' . ( isset( $openmeteo_loc[ $i ]['admin1'] ) ? $openmeteo_loc[ $i ]['admin1'] : '' ) . ' </a></td>';
119 $res .= '</tr>';
120 $i++;
121 }
122 $res .= '</tbody></table>';
123 }
124
125 echo wp_kses( $res, wpf_allowed_tags() );
126 wp_die();
127 }
128
129 /**
130 * Ajax funktion fuer den Verbindungstest im admin dialog.
131 */
132 function wpf_check_ajax() {
133 $res = '';
134
135 // check nonce3.
136 if ( ! isset( $_POST['wpf_nonce_3'] ) ) {
137 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
138 }
139 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpf_nonce_3'] ) ), 'wpf_nonce_3' ) ) {
140 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
141 }
142
143 /**
144 * Check the URL $url.
145 *
146 * @param string $url The URL to check.
147 */
148 function check_url( $url ) {
149 $erg = array();
150
151 $wprr_args = array(
152 'timeout' => 30,
153 'headers' => array(
154 'Connection' => 'Close',
155 'Accept' => '*/*',
156 ),
157 );
158
159 // use generic WordPress function to retrieve data.
160 $s = time();
161 $resp = wp_remote_request( $url, $wprr_args );
162 $e = time();
163
164 $erg['duration'] = (int) ( $e - $s );
165
166 if ( is_wp_error( $resp ) ) {
167 $errcode = $resp->get_error_code();
168 $errmesg = $resp->get_error_message( $errcode );
169
170 $erg['error'] = $errcode . ' ' . $errmesg;
171 $erg['body'] = '';
172 $erg['len'] = '-1';
173 } else {
174 $erg['error'] = '';
175 $erg['body'] = $resp['body'];
176 $erg['len'] = strlen( $resp['body'] );
177 }
178 return $erg;
179 }
180
181 /**
182 * Show the result of the check.
183 *
184 * @param string $erg Contains the result string.
185 */
186 function show_check_result( $erg ) {
187 $out = '';
188 $space = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
189 if ( '' == $erg['error'] ) {
190 $out .= $space . 'Test was successfull.<br/>';
191 $out .= $space . 'Fetched ' . $erg['len'] . ' Bytes in ';
192 $out .= $erg['duration'] . ' seconds.<br/>';
193 $out .= 'Content was: ' . $erg['body'] . '<br/>';
194 } else {
195 $out .= $space . 'Test ends in error.<br/>';
196 $out .= $space . 'Error-Message was ' . $erg['error'] . '<br/>';
197 }
198 return $out;
199 }
200
201 $wpf_vars = get_wpf_opts( 'A' );
202
203 if ( ! empty( $_POST['provider'] ) ) {
204 $provider = sanitize_text_field( wp_unslash( $_POST['provider'] ) );
205 $res .= 'Checking for Weatherprovider ' . esc_attr( $provider ) . '<br />';
206
207 if ( 'OpenWeatherMapV3' == $provider ) {
208 if ( ! isset( $wpf_vars['apikey1'] ) ) {
209 $out .= __( 'You have to set the API-Key to test OpenWeatherMap.', 'wp-forecast' );
210 echo wp_kses( $out, wpf_allowed_tags() );
211 die();
212 }
213 $url = 'https://api.openweathermap.org/data/3.0/onecall?lat=50.11&lon=8.68&appid=' . $wpf_vars['apikey1'] . '&exclude=minutely,hourly&units=1&lang=en';
214 }
215
216 if ( 'OpenWeatherMap' == $provider ) {
217 if ( ! isset( $wpf_vars['apikey1'] ) ) {
218 $out .= __( 'You have to set the API-Key to test OpenWeatherMap.', 'wp-forecast' );
219 echo wp_kses( $out, wpf_allowed_tags() );
220 die();
221 }
222 $url = 'https://api.openweathermap.org/data/2.5/weather?lat=50.11&lon=8.68&appid=' . $wpf_vars['apikey1'] . '&exclude=minutely,hourly&units=1&lang=en';
223 }
224
225 if ( 'Open-Meteo' == $provider ) {
226 $url = 'https://api.open-meteo.com/v1/forecast?latitude=50.77664&longitude=6.08342&current_weather=true&timeformat=unixtime&timezone=GMT';
227 }
228
229 // checking for standard connection method.
230 $res .= 'Checking using WordPress wp_remote_get<br />';
231 $erg = check_url( $url );
232 $res .= show_check_result( $erg );
233 }
234
235 echo wp_kses( $res, wpf_allowed_tags() );
236 wp_die();
237 }
238
239 /**
240 * Add menuitem for options menu.
241 */
242 function wp_forecast_admin() {
243 $ap = add_menu_page( 'wp-Forecast', 'wp-Forecast', 'manage_options', basename( __FILE__ ), 'wpf_admin_form', plugins_url( '/wpf.png', __FILE__ ) );
244 add_action( 'load-' . $ap, 'wp_forecast_contextual_help' );
245 }
246
247 /**
248 * Print out hint for the widget control.
249 *
250 * @param array $args Parameters for amdin hint.
251 */
252 function wpf_admin_hint( $args = null ) {
253 $wpfcid = $args;
254
255 // check nonce.
256 if ( ! isset( $_POST['wpf_nonce_4'] ) ) {
257 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
258 }
259 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpf_nonce_4'] ) ), 'wpf_nonce_4' ) ) {
260 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
261 }
262
263 load_plugin_textdomain( 'wp-forecast', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
264
265 // code for widget title form.
266 $av = get_wpf_opts( $wpfcid );
267 $av['title'] = $newtitle;
268
269 if ( isset( $_POST[ 'wpf-submit-title' . $wpfcid ] ) ) {
270 $newtitle = ( isset( $_POST[ 'wpf-title-' . $wpfcid ] ) ? sanitize_text_field( wp_unslash( $_POST[ 'wpf-title-' . $wpfcid ] ) ) : '' );
271 }
272
273 if ( $av['title'] != $newtitle ) {
274 $av['title'] = $newtitle;
275 wpf_update_option( 'wp-forecast-opts' . $wpfcid, serialize( $av ) );
276 }
277
278 echo esc_attr__( 'Title:', 'wp-forecast' );
279 echo " <input style='width: 250px;' id='wpf-title-" . esc_attr( $wpfcid ) . "' name='wpf-title-" . esc_attr( $wpfcid ) . "' type='text' value='" . esc_attr( $av['title'] ) . "' />";
280 echo "<input type='hidden' id='wpf-submit-title" . esc_attr( $wpfcid ) . "' name='wpf-submit-title" . esc_attr( $wpfcid ) . "' value='1' />";
281 echo "<input name='wpf_nonce_4' type='hidden' value='<?php echo esc_attr( wp_create_nonce( 'wpf_nonce_4' ) ); ?>' />";
282 echo '<p>' . esc_attr__( 'widget_hint', 'wp-forecast' ) . '</p>';
283 }
284
285 /**
286 * Get the locationlist and return it in one long string.
287 *
288 * @param string $uri This contains the uri to fetch the list from.
289 * @param string $loc This contains the location identifier.
290 */
291 function get_loclist( $uri, $loc ) {
292 $data = array();
293
294 $url = $uri . 'name=' . urlencode( $loc ) . '&count=100&language=en&format=json';
295
296 // fetch the URL and decode it.
297 $json = wp_remote_get( $url );
298 if ( ! is_wp_error( $json ) ) {
299 $data = json_decode( $json['body'], true );
300 }
301
302 return $data['results'];
303 }
304
305
306 /**
307 * Form handler for the widgets.
308 *
309 * @param string $wpfcid Widget-ID.
310 * @param bool $widgetcall Is it a widget call.
311 */
312 function wpf_admin_form( $wpfcid = 'A', $widgetcall = 0 ) {
313 global $wpf_maxwidgets, $blog_id;
314
315 if ( function_exists( 'is_multisite' ) && is_multisite() && 1 != $blog_id && ! wpf_get_option( 'wpf_sa_allowed' ) ) {
316 wp_forecast_activate();
317 }
318
319 $count = wpf_get_option( 'wp-forecast-count' );
320 $wpf_delopt = wpf_get_option( 'wp-forecast-delopt' );
321 $wpf_ipstack = wpf_get_option( 'wp-forecast-ipstackapikey' );
322 $wpf_loadcss = wpf_get_option( 'wp-forecast-loadcss' );
323
324 // called via the options menu not from widgets.
325 if ( 0 == $widgetcall ) {
326 // load translation.
327 load_plugin_textdomain( 'wp-forecast', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
328
329 // if this is a post call to update global settings.
330 if ( isset( $_POST['wpf_global_settings_update'] ) ) {
331 // check nonce.
332 if ( ! isset( $_POST['wpf_nonce_1'] ) ) {
333 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
334 }
335 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpf_nonce_1'] ) ), 'wpf_nonce_1' ) ) {
336 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
337 }
338
339 // update max widgets.
340 $number = ( isset( $_POST['wp-forecast-count'] ) ? (int) $_POST['wp-forecast-count'] : 1 );
341 if ( $number > $wpf_maxwidgets ) {
342 $number = $wpf_maxwidgets;
343 }
344 if ( $number < 1 ) {
345 $number = 1;
346 }
347 $newcount = $number;
348
349 if ( $count != $newcount ) {
350 $count = $newcount;
351 wpf_update_option( 'wp-forecast-count', $count );
352 // add missing option to database.
353 wp_forecast_activate();
354 // init the new number of widgets.
355 widget_wp_forecast_init( $count );
356 }
357
358 // update delopt.
359 $wpf_delopt = ( array_key_exists( 'wp-forecast-delopt', $_POST ) ? (int) ( 'on' == $_POST['wp-forecast-delopt'] ) : false );
360 wpf_update_option( 'wp-forecast-delopt', $wpf_delopt );
361
362 // update ipstack apikey.
363 wpf_update_option( 'wp-forecast-ipstackapikey', ( isset( $_POST['wp-forecast-ipstackapikey'] ) ? sanitize_text_field( wp_unslash( $_POST['wp-forecast-ipstackapikey'] ) ) : '' ) );
364
365 // update loadcss.
366 $wpf_loadcss = ( array_key_exists( 'wp-forecast-loadcss', $_POST ) ? (int) ( 'on' == $_POST['wp-forecast-loadcss'] ) : false );
367 wpf_update_option( 'wp-forecast-loadcss', $wpf_loadcss );
368
369 $count = wpf_get_option( 'wp-forecast-count' );
370 $wpf_delopt = wpf_get_option( 'wp-forecast-delopt' );
371 $wpf_ipstack = wpf_get_option( 'wp-forecast-ipstackapikey' );
372 $wpf_loadcss = wpf_get_option( 'wp-forecast-loadcss' );
373
374 } // end of update global settings.
375
376 // start of form ---------------------------------------------------------------------------
377 //
378 // print out number of widgets selection.
379 $out = "<div class='wrap'>";
380 $out .= '<h2>WP-Forecast Widgets</h2>';
381 $out .= tl_add_supp();
382
383 // begin of global settings.
384 $out .= '<h2>' . esc_attr__( 'Global Settings', 'wp-forecast' ) . '</h2>';
385 $out .= "<form name='options' id='options' method='post' action='#'>";
386 $out .= '<input name="wpf_nonce_1" type="hidden" value="' . wp_create_nonce( 'wpf_nonce_1' ) . '" />';
387 $out .= '<table style="width:80%;"><tr><td>' . esc_attr__( 'How many wp-forecast widgets would you like?', 'wp-forecast' ) . '</td>';
388 $out .= '<td><select id="wp-forecast-count" name="wp-forecast-count">';
389
390 for ( $i = 1; $i <= $wpf_maxwidgets; ++$i ) {
391 $out .= "<option value='$i' ";
392 if ( $count == $i ) {
393 $out .= "selected='selected' ";
394 }
395 $out .= ">$i</option>";
396 }
397 $out .= '</select></td>';
398
399 // print out option deletion switch.
400 $out .= '<td>' . esc_attr__( 'Delete options during plugin deactivation?', 'wp-forecast' ) . '</td>';
401 $out .= "<td><input id='wp-forecast-delopt' name='wp-forecast-delopt' type='checkbox' ";
402 if ( $wpf_delopt ) {
403 $out .= 'checked="checked"';
404 }
405 $out .= ' />';
406 $out .= "</td></tr>\n";
407
408 // print out input field for ipstack api key.
409 $out .= "<tr><td><a href='http://www.ipstack.com' target='_blank'>" . esc_attr__( 'API key to use location from ipstack.com ', 'wp-forecast' ) . ':</a></td>';
410 $out .= "<td><input id='wp-forecast-ipstackapikey' name='wp-forecast-ipstackapikey' type='text' size='40' width='32' value='$wpf_ipstack' />";
411 $out .= "</td>\n";
412
413 // print out option loadcss.
414 $out .= '<td>' . esc_attr__( 'Do not load default CSS', 'wp-forecast' ) . '</td>';
415 $out .= "<td><input id='wp-forecast-loadcss' name='wp-forecast-loadcss' type='checkbox' ";
416 if ( $wpf_loadcss ) {
417 $out .= 'checked="checked"';
418 }
419 $out .= ' />';
420 $out .= "</td></tr>\n";
421
422 $out .= "</table>\n";
423
424 $out .= "<div class='submit'><input class='button-primary' type='submit' name='wpf_global_settings_update' value='" . esc_attr__( 'Update global options', 'wp-forecast' ) . " »' /></div>";
425 $out .= "</form></div>\n";
426 // end of global options.
427
428 $out .= '<div style="text-align:right;padding-right:20px;">';
429 $out .= '<a href="#TB_inline?height=1000&width=600&inlineId=wpf_check__&wpfcid=A" class="thickbox">';
430 $out .= esc_attr__( 'Check connection to Weatherprovider', 'wp-forecast' ) . '</a></div>' . "\n";
431
432 // print out widget selection form.
433 if ( $count > 1 ) {
434 $out .= "<form name='selwidget' id='selwidget' method='post' action='#'>";
435 $out .= '<input name="wpf_nonce_2" type="hidden" value="' . wp_create_nonce( 'wpf_nonce_2' ) . '" />';
436 $out .= '<div>' . esc_attr__( 'Available widgets', 'wp-forecast' ) . ': ';
437
438 $out .= "<select name='widgetid' size='1' >";
439 for ( $i = 0;$i < $count;$i++ ) {
440 $id = get_widget_id( $i );
441 $out .= "<option value='" . $id . "' ";
442
443 if (
444 (
445 array_key_exists( 'widgetid', $_POST ) &&
446 sanitize_text_field( wp_unslash( $_POST['widgetid'] ) ) == $id &&
447 isset( $_POST['set_widget'] )
448 ) || (
449 array_key_exists( 'wid', $_POST ) && isset( $_POST['info_update'] ) && sanitize_text_field( $_POST['wid'] == $id )
450 ) || (
451 array_key_exists( 'wid', $_POST ) && isset( $_POST['search_loc'] ) && sanitize_text_field( $_POST['wid'] == $id )
452 ) ) {
453 $out .= "selected='selected'";
454 }
455 $out .= '>' . $id . '</option>';
456 }
457 $out .= '</select>';
458
459 $out .= '<span class="submit"><input class="button" type="submit" name="set_widget" value="';
460 $out .= esc_attr__( 'Select widget', 'wp-forecast' ) . " »\" /></span></div></form>\n";
461 }
462
463 echo wp_kses( $out, wpf_allowed_tags() );
464 }
465
466 // if this is a post call, select widget.
467 if ( isset( $_POST['set_widget'] ) && 0 == $widgetcall ) {
468 // check nonce.
469 if ( ! isset( $_POST['wpf_nonce_2'] ) ) {
470 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
471 }
472 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpf_nonce_2'] ) ), 'wpf_nonce_2' ) ) {
473 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
474 }
475
476 $wpfcid = sanitize_text_field( wp_unslash( $_POST['widgetid'] ) );
477 }
478
479 // if this is any other post call.
480 if ( ( isset( $_POST['info_update'] ) && 0 == $widgetcall ) ||
481 ( isset( $_POST['set_loc'] ) && 0 == $widgetcall ) ||
482 ( isset( $_POST['search_loc'] ) && 0 == $widgetcall ) ) {
483
484 // check nonce.
485 if ( ! isset( $_POST['wpf_nonce_3'] ) ) {
486 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
487 }
488 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpf_nonce_3'] ) ), 'wpf_nonce_3' ) ) {
489 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
490 }
491
492 $wpfcid = ( isset( $_POST['wid'] ) ? sanitize_text_field( wp_unslash( $_POST['wid'] ) ) : 'A' );
493 }
494
495 // default is the first widget.
496 if ( '' == $wpfcid ) {
497 $wpfcid = 'A';
498 }
499
500 // call sub form.
501 wpf_sub_admin_form( $wpfcid, $widgetcall );
502 }
503
504
505 /**
506 * Form to modify wp-forecast setup
507 * the form also has a search function to search the wright location.
508 *
509 * @param string $wpfcid Widget ID.
510 * @param bool $widgetcall Is it a widgetcall.
511 */
512 function wpf_sub_admin_form( $wpfcid, $widgetcall ) {
513 global $blog_id;
514
515 // check nonce3.
516 if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] && isset( $_POST['info_update'] ) ) {
517 if ( ! isset( $_POST['wpf_nonce_3'] ) ) {
518 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
519 }
520 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpf_nonce_3'] ) ), 'wpf_nonce_3' ) ) {
521 die( "<br><br>Looks like you didn't send any credentials. Please reload the page. " );
522 }
523 }
524
525 // get parameters.
526 $av = get_wpf_opts( $wpfcid );
527 $allowed = maybe_unserialize( wpf_get_option( 'wpf_sa_allowed' ) );
528
529 $ismulti = false;
530 if ( function_exists( 'is_multisite' ) && is_multisite() && get_current_blog_id() != 1 ) {
531 $ismulti = true;
532 }
533
534 if ( function_exists( 'load_plugin_textdomain' ) ) {
535 load_plugin_textdomain( 'wp-forecast', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
536 }
537
538 // if this is a POST call, save new values.
539 if ( isset( $_POST['info_update'] ) ) {
540 $upflag = false;
541
542 $wpf_admin_fields = array(
543 'service',
544 'apikey1',
545 'location',
546 'loclongitude',
547 'loclatitude',
548 'visitorlocation',
549 'locname',
550 'location',
551 'refresh',
552 'provider',
553 'csssprites',
554 'windicon',
555 'fonticon',
556 'fonticon_color',
557 'pdforecast',
558 'pdfirstday',
559 'timeoffset',
560 'currtime',
561 'wpf_language',
562 'windunit',
563 'metric',
564 'ouv_safetime',
565 'ouv_ozone',
566 'ouv_uvmax',
567 'ouv_uv',
568 'ouv_apikey',
569 'ouv_alticons',
570 );
571
572 // fill up POST array with NULL vallues for unset keys.
573 foreach ( $wpf_admin_fields as $k ) {
574 if ( ! isset( $_POST[ $k ] ) ) {
575 $_POST[ $k ] = null;
576 }
577 }
578
579 // update fields if applicable.
580 foreach ( $wpf_admin_fields as $k ) {
581 $av[ $k ] = sanitize_text_field( wp_unslash( $_POST[ $k ] ) );
582 $upflag = true;
583 }
584 if ( '' == $av['metric'] ) {
585 $av['metric'] = '0';
586 }
587 if ( '' == $av['currtime'] ) {
588 $av['currtime'] = '0';
589 }
590 if ( '' == $av['windicon'] ) {
591 $av['windicon'] = '0';
592 }
593 if ( '' == $av['fonticon'] ) {
594 $av['fonticon'] = '0';
595 }
596 if ( '' == $av['fonticon_color'] ) {
597 $av['fonticon_color'] = '#924da3';
598 }
599 if ( '' == $av['ouv_uv'] ) {
600 $av['ouv_uv'] = '0';
601 }
602 if ( '' == $av['ouv_uvmax'] ) {
603 $av['ouv_uvmax'] = '0';
604 }
605 if ( '' == $av['ouv_ozone'] ) {
606 $av['ouv_ozone'] = '0';
607 }
608 if ( '' == $av['ouv_safetime'] ) {
609 $av['ouv_safetime'] = '0';
610 }
611 if ( '' == $av['ouv_alticons'] ) {
612 $av['ouv_alticons'] = '0';
613 }
614
615 if ( '' == $av['visitorlocation'] ) {
616 $av['visitorlocation'] = '0';
617 }
618
619 // set checkbox value to zero if not set.
620 // for forecast options.
621 $nd = array( 'day1', 'day2', 'day3', 'day4', 'day5', 'day6', 'day7', 'day8', 'day9', 'night1', 'night2', 'night3', 'night4', 'night5', 'night6', 'night7', 'night8', 'night9' );
622 foreach ( $nd as $i ) {
623 if ( ! isset( $_POST[ $i ] ) || '' == $_POST[ $i ] ) {
624 $_POST[ "$i" ] = '0';
625 }
626 }
627
628 // set empty checkboxes to 0.
629 $do = array(
630 'd_c_icon',
631 'd_c_time',
632 'd_c_short',
633 'd_c_temp',
634 'd_c_real',
635 'd_c_press',
636 'd_c_humid',
637 'd_c_wind',
638 'd_c_sunrise',
639 'd_c_sunset',
640 'd_d_icon',
641 'd_d_short',
642 'd_d_temp',
643 'd_d_wind',
644 'd_n_icon',
645 'd_n_short',
646 'd_n_temp',
647 'd_n_wind',
648 'd_c_date',
649 'd_d_date',
650 'd_n_date',
651 'd_c_copyright',
652 'd_c_wgusts',
653 'd_d_wgusts',
654 'd_n_wgusts',
655 'd_c_accuweather',
656 'd_c_aw_newwindow',
657 'd_c_uvindex',
658 'd_d_maxuv',
659 'd_n_maxuv',
660 'd_c_precipe',
661 'd_d_precipe',
662 'd_n_precipe',
663 );
664 foreach ( $do as $i ) {
665 if ( ! isset( $_POST[ $i ] ) || '' == $_POST[ $i ] ) {
666 $_POST[ "$i" ] = '0';
667 }
668 }
669
670 // build config string for dispconfig and update if necessary.
671 $newdispconfig = '';
672 foreach ( $do as $i ) {
673 $newdispconfig .= (int) $_POST[ $i ];
674 }
675
676 if ( ( ! $ismulti || isset( $allowed['ue_dispconfig'] ) ) && strcmp( $av['dispconfig'], $newdispconfig ) != 0 ) {
677 $av['dispconfig'] = $newdispconfig;
678 $upflag = true;
679 }
680
681 // build config string for forecast and update if necessary.
682 $newdaytime = ( isset( $_POST['day1'] ) ? (int) $_POST['day1'] : 0 )
683 . ( isset( $_POST['day2'] ) ? (int) $_POST['day2'] : 0 )
684 . ( isset( $_POST['day3'] ) ? (int) $_POST['day3'] : 0 )
685 . ( isset( $_POST['day4'] ) ? (int) $_POST['day4'] : 0 )
686 . ( isset( $_POST['day5'] ) ? (int) $_POST['day5'] : 0 )
687 . ( isset( $_POST['day6'] ) ? (int) $_POST['day6'] : 0 )
688 . ( isset( $_POST['day7'] ) ? (int) $_POST['day7'] : 0 )
689 . ( isset( $_POST['day8'] ) ? (int) $_POST['day8'] : 0 )
690 . ( isset( $_POST['day9'] ) ? (int) $_POST['day9'] : 0 );
691
692 if ( ( ! $ismulti || isset( $allowed['ue_forecast'] ) ) && $av['daytime'] != $newdaytime ) {
693 $av['daytime'] = $newdaytime;
694 $upflag = true;
695 }
696
697 $newnighttime = ( isset( $_POST['night1'] ) ? (int) $_POST['night1'] : 0 )
698 . ( isset( $_POST['night2'] ) ? (int) $_POST['night2'] : 0 )
699 . ( isset( $_POST['night3'] ) ? (int) $_POST['night3'] : 0 )
700 . ( isset( $_POST['night4'] ) ? (int) $_POST['night4'] : 0 )
701 . ( isset( $_POST['night5'] ) ? (int) $_POST['night5'] : 0 )
702 . ( isset( $_POST['night6'] ) ? (int) $_POST['night6'] : 0 )
703 . ( isset( $_POST['night7'] ) ? (int) $_POST['night7'] : 0 )
704 . ( isset( $_POST['night8'] ) ? (int) $_POST['night8'] : 0 )
705 . ( isset( $_POST['night9'] ) ? (int) $_POST['night9'] : 0 );
706
707 if ( ( ! $ismulti || isset( $allowed['ue_forecast'] ) ) && $av['nighttime'] != $newnighttime ) {
708 $av['nighttime'] = $newnighttime;
709 $upflag = true;
710 }
711
712 // put message after update.
713 echo "<div class='updated'><p><strong>";
714 if ( $upflag ) {
715 wpf_update_option( 'wp-forecast-opts' . $wpfcid, serialize( $av ) );
716 wpf_update_option( 'wp-forecast-expire' . $wpfcid, '0' );
717 echo esc_attr__( 'Settings successfully updated', 'wp-forecast' );
718 } else {
719 echo esc_attr__( 'You have to change a field to update settings.', 'wp-forecast' );
720 }
721 echo '</strong></p></div>';
722 }
723
724 // if this is a POST call, set location.
725 if ( isset( $_POST['set_loc'] ) ) {
726 if ( isset( $_POST['new_loc'] ) ) {
727 $av['location'] = sanitize_text_field( wp_unslash( $_POST['new_loc'] ) );
728 }
729 if ( isset( $_POST['provider'] ) ) {
730 $av['service'] = sanitize_text_field( wp_unslash( $_POST['provider'] ) );
731 }
732 }
733 ?>
734
735 <?php
736 if ( 0 == $widgetcall ) :
737 ?>
738 <div class="wrap">
739 <!-- add javascript for field control -->
740 <?php
741 include 'wp-forecast-js.php';
742 ?>
743 <form method="post" name='woptions' action='#'>
744 <input name="wpf_nonce_3" type="hidden" value="<?php echo esc_attr( wp_create_nonce( 'wpf_nonce_3' ) ); ?>" />
745 <?php endif; ?>
746 <input name='wid' type='hidden' value='<?php echo esc_attr( $wpfcid ); ?>'/>
747 <h2><?php echo esc_attr__( 'WP-Forecast Setup', 'wp-forecast' ) . ' (Widget ' . esc_attr( $wpfcid ) . ') '; ?></h2>
748 <?php
749 if ( 0 == $widgetcall ) :
750 ?>
751 <fieldset id="set1"><?php endif; ?>
752
753
754 <div style="float: left; width: 49%">
755 <p><b><?php echo esc_attr__( 'wp-forecast supports the free API from OpenMeteo, the OpenWeatherMap v2.5 FreeAPI or OneCall API v3. If you use OpenWeatherMap v3 please check if your plan includes the OneCall API.', 'wp-forecast' ); ?></b></p>
756 <p><b><?php echo esc_attr__( 'Weatherservice', 'wp-forecast' ); ?>:</b>
757 <select name="service" id="service" size="1" onchange="apifields(document.woptions.service.value);">
758 <option value="openweathermap"
759 <?php
760 if ( 'openweathermap' === $av['service'] ) {
761 echo 'selected="selected"';}
762 ?>
763 ><?php echo esc_attr__( 'OpenWeathermap', 'wp-forecast' ); ?></option>
764 <option value="openweathermap3"
765 <?php
766 if ( 'openweathermap3' === $av['service'] ) {
767 echo 'selected="selected"';}
768 ?>
769 ><?php echo esc_attr__( 'OpenWeatherMap v3', 'wp-forecast' ); ?></option>
770
771 <option value="openmeteo"
772 <?php
773 if ( 'openmeteo' === $av['service'] ) {
774 echo 'selected="selected"';}
775 ?>
776 ><?php echo esc_attr__( 'Open-Meteo', 'wp-forecast' ); ?></option>
777 </select>&nbsp;
778
779 <?php echo esc_attr__( 'API-Key', 'wp-forecast' ); ?>:
780 <input name="apikey1" id="apikey1" type="text" size="20" maxlength="80" value="<?php echo esc_attr( $av['apikey1'] ); ?>" /></p>
781 <script type="text/javascript">apifields(document.woptions.service.value);</script>
782
783 <p><b><?php echo esc_attr__( 'Location', 'wp-forecast' ); ?>:</b>
784 <input name="location" id="location" type="text" size="30" maxlength="80" value="<?php echo esc_attr( $av['location'] ); ?>"
785 <?php
786 if ( 1 === $widgetcall ) {
787 echo 'readonly';}
788 ?>
789 />
790
791 <a href="#TB_inline?height=1000&width=600&inlineId=wpf_search__&wpfcid=<?php echo esc_attr( $wpfcid ); ?>" class="thickbox">
792 <img alt="Search Icon" src="<?php echo esc_attr( plugin_dir_url( __FILE__ ) ); ?>/Searchicon16x16.png" /></a>
793 &nbsp;&nbsp;&nbsp;<input type="checkbox" name="visitorlocation" id="visitorlocation" value="1"
794 <?php
795 if ( isset( $av['visitorlocation'] ) && '1' === $av['visitorlocation'] ) {
796 echo 'checked="checked"';}
797 ?>
798 onchange="vlocfields_update();" /><b><?php echo esc_attr__( 'Use visitors location', 'wp-forecast' ); ?></b>
799 </p>
800
801 <p><b><?php echo esc_attr__( 'Latitude', 'wp-forecast' ); ?>:</b>
802 <input name="loclatitude" id="loclatitude" type="text" size="15" maxlength="10"
803 value="<?php echo ( isset( $av['loclatitude'] ) ? esc_attr( $av['loclatitude'] ) : '' ); ?>" />
804
805 <b><?php echo esc_attr__( 'Longitude', 'wp-forecast' ); ?>:</b>
806 <input name="loclongitude" id="loclongitude" type="text" size="15" maxlength="10"
807 value="<?php echo ( isset( $av['loclongitude'] ) ? esc_attr( $av['loclongitude'] ) : '' ); ?>" /></p>
808
809 <p><b><?php echo esc_attr__( 'Locationname', 'wp-forecast' ); ?>:</b>
810 <input name="locname" id="locname" type="text" size="30" maxlength="80" value="<?php echo esc_attr( $av['locname'] ); ?>" /></p>
811 <p><b><?php echo esc_attr__( 'Refresh cache after', 'wp-forecast' ); ?></b>
812 <input name="refresh" id="refresh" type="text" size="10" maxlength="6" value="<?php echo esc_attr( $av['refresh'] ); ?>"/>
813 <b><?php echo esc_attr__( 'secs.', 'wp-forecast' ); ?></b><br /></p>
814 <p><input type="checkbox" name="metric" id="metric" value="1"
815 <?php
816 if ( '1' === $av['metric'] ) {
817 echo 'checked="checked"';}
818 ?>
819 /> <b><?php echo esc_attr__( 'Use metric units', 'wp-forecast' ); ?></b>
820 </p>
821
822 <p><input type="checkbox" name="currtime" id="currtime" value="1"
823 <?php
824 if ( '1' === $av['currtime'] ) {
825 echo 'checked="checked"';
826 }
827 ?>
828 /> <b><?php echo esc_attr__( 'Use current time', 'wp-forecast' ); ?></b> / <b>
829 <?php echo esc_attr__( 'Time-Offset', 'wp-forecast' ); ?> :</b>
830 <input type="text" name="timeoffset" id="timeoffset" size="5" maxlength="5" value="<?php echo esc_attr( isset( $av['timeoffset'] ) ? $av['timeoffset'] : '' ); ?>" /> <b><?php echo esc_attr__( 'minutes', 'wp-forecast' ); ?></b>
831 </p>
832
833 <p><b><?php echo esc_attr__( 'Windspeed-Unit', 'wp-forecast' ); ?>: </b><select name="windunit" id="windunit" size="1">
834 <option value="ms"
835 <?php
836 if ( 'ms' === $av['windunit'] ) {
837 echo 'selected="selected"';}
838 ?>
839 ><?php echo esc_attr__( 'Meter/Second (m/s)', 'wp-forecast' ); ?></option>
840 <option value="kmh"
841 <?php
842 if ( 'kmh' === $av['windunit'] ) {
843 echo 'selected="selected"';}
844 ?>
845 ><?php echo esc_attr__( 'Kilometer/Hour (km/h)', 'wp-forecast' ); ?></option>
846 <option value="mph"
847 <?php
848 if ( 'mph' === $av['windunit'] ) {
849 echo 'selected="selected"';}
850 ?>
851 ><?php echo esc_attr__( 'Miles/Hour (mph)', 'wp-forecast' ); ?></option>
852 <option value="kts"
853 <?php
854 if ( 'kts' === $av['windunit'] ) {
855 echo 'selected="selected"';}
856 ?>
857 ><?php echo esc_attr__( 'Knots (kts)', 'wp-forecast' ); ?></option>
858 <option value="bft"
859 <?php
860 if ( 'bft' === $av['windunit'] ) {
861 echo 'selected="selected"';}
862 ?>
863 ><?php echo esc_attr__( 'Beaufort (bft)', 'wp-forecast' ); ?></option>
864 </select></p>
865
866
867
868
869 <p>
870 <b><?php echo esc_attr__( 'Language', 'wp-forecast' ); ?>: </b><select name="wpf_language" id="wpf_language" size="1">
871 <?php
872 $iso_arr = array( 'en_US', 'de_DE', 'bg_BG', 'bs_BA', 'hr_HR', 'cs_CZ', 'da_DK', 'nl_NL', 'fi_FI', 'fr_FR', 'el_EL', 'he_IL', 'hu_HU', 'id_ID', 'it_IT', 'nb_NO', 'fa_IR', 'pl_PL', 'pt_PT', 'ro_RO', 'ru_RU', 'sr_SR', 'sk_SK', 'es_ES', 'sv_SE', 'uk_UA' );
873 $lang_arr = array( 'english', 'deutsch', 'bulgarian', 'bosnian', 'croatian', 'czech', 'dansk', 'dutch', 'finnish', 'french', 'greek', 'hebrew', 'hungarian', 'indonesian', 'italian', 'norwegian', 'persian', 'polish', 'portugu&#234;s', 'romanian', 'russian', 'serbian', 'slovak', 'spanish', 'swedish', 'ukranian' );
874 $lopt = '';
875 $num = count( $iso_arr );
876 for ( $i = 0; $i < $num; $i++ ) {
877 $lopt .= '<option value="' . $iso_arr[ $i ] . '"';
878 if ( $av['wpf_language'] == $iso_arr[ $i ] ) {
879 // space as first characteer is important.
880 $lopt .= ' selected="selected"';
881 }
882 $lopt .= '>' . $lang_arr[ $i ];
883 $lopt .= '</option>';
884 }
885 echo wp_kses( $lopt, wpf_allowed_tags() );
886 ?>
887 </select></p>
888
889 <p><input type="checkbox" name="pdforecast" id="pdforecast" value="1"
890 <?php
891 if ( '1' === $av['pdforecast'] ) {
892 echo 'checked="checked"';}
893 ?>
894 onchange="pdfields_update();" /> <b><?php echo esc_attr__( 'Show forecast as ajax pull-down', 'wp-forecast' ); ?></b>
895 </p>
896
897 <p>
898 <b><?php echo esc_attr__( 'First day in pull-down', 'wp-forecast' ); ?>: </b><select name="pdfirstday" id="pdfirstday" size="1">
899 <?php
900 for ( $i = 0; $i < 10; $i++ ) {
901 echo "<option value='" . esc_attr( $i ) . "'";
902 if ( $i == $av['pdfirstday'] ) {
903 echo 'selected="selected"';
904 }
905 echo '>' . esc_attr( $i ) . '</option>';
906 }
907 ?>
908 </select></p>
909 <script type="text/javascript">pdfields_update();</script>
910
911 <p><input type="checkbox" name="fonticon" id="fonticon" value="1" onclick="fonticon_update();"
912 <?php
913 if ( '1' === $av['fonticon'] ) {
914 echo 'checked="checked"';
915 }
916 ?>
917 /> <b><?php echo esc_attr__( 'Use weatherfont for icons', 'wp-forecast' ); ?></b>
918 <input class="fonticon_color" name="fonticon_color" id="fonticon_color" type="text" value="<?php echo esc_attr( $av['fonticon_color'] ); ?>" />
919 <b><?php echo esc_attr__( 'Choose color for weatherfont icons', 'wp-forecast' ); ?></b>
920 </p>
921
922
923 <p><input type="checkbox" name="windicon" id="windicon" value="1"
924 <?php
925 if ( '1' === $av['windicon'] ) {
926 echo 'checked="checked"';}
927 ?>
928 /> <b><?php echo esc_attr__( 'Show wind condition as icon', 'wp-forecast' ); ?></b>
929 </p>
930 <p><input type="checkbox" name="csssprites" id="csssprites" value="1"
931 <?php
932 if ( '1' === $av['csssprites'] ) {
933 echo 'checked="checked"';}
934 ?>
935 /> <b><?php echo esc_attr__( 'Use CSS-Sprites for showing icons', 'wp-forecast' ); ?></b>
936 </p>
937 </div>
938 <script type="text/javascript">fonticon_update();</script>
939 <!-- start of right column -->
940 <div style="padding-left: 2%; float: left; width: 49%;">
941 <b><?php echo esc_attr__( 'Display Configuration', 'wp-forecast' ); ?></b>
942 <table>
943 <tr>
944 <td>&nbsp;</td>
945 <td><?php echo esc_attr__( 'Current Conditions', 'wp-forecast' ); ?></td>
946 <td><?php echo esc_attr__( 'Forecast Day', 'wp-forecast' ); ?></td>
947 <td><?php echo esc_attr__( 'Forecast Night', 'wp-forecast' ); ?></td>
948 </tr>
949 <tr>
950 <td><?php echo esc_attr__( 'Icon', 'wp-forecast' ); ?></td>
951 <td class='td-center'><input type="checkbox" name="d_c_icon" id="d_c_icon" value="1"
952 <?php
953 if ( substr( $av['dispconfig'], 0, 1 ) == '1' ) {
954 echo 'checked="checked"';}
955 ?>
956 /></td>
957 <td class='td-center'><input type="checkbox" name="d_d_icon" id="d_d_icon" value="1"
958 <?php
959 if ( substr( $av['dispconfig'], 10, 1 ) == '1' ) {
960 echo 'checked="checked"';}
961 ?>
962 /></td>
963 <td class='td-center'><input type="checkbox" name="d_n_icon" id="d_n_icon" value="1"
964 <?php
965 if ( substr( $av['dispconfig'], 14, 1 ) == '1' ) {
966 echo 'checked="checked"';}
967 ?>
968 /></td>
969 </tr>
970 <tr>
971 <td><?php echo esc_attr__( 'Date', 'wp-forecast' ); ?></td>
972 <td class='td-center'><input type="checkbox" name="d_c_date" id="d_c_date" value="1"
973 <?php
974 if ( substr( $av['dispconfig'], 18, 1 ) == '1' ) {
975 echo 'checked="checked"';}
976 ?>
977 /></td>
978 <td class='td-center'>&nbsp;</td>
979 <td class='td-center'>&nbsp;</td>
980 </tr>
981 <tr>
982 <td><?php echo esc_attr__( 'Time', 'wp-forecast' ); ?></td>
983 <td class='td-center'><input type="checkbox" name="d_c_time" id="d_c_time" value="1"
984 <?php
985 if ( substr( $av['dispconfig'], 1, 1 ) == '1' ) {
986 echo 'checked="checked"';}
987 ?>
988 /></td>
989 <td class='td-center'>&nbsp;</td>
990 <td class='td-center'>&nbsp;</td>
991 </tr>
992 <tr>
993 <td><?php echo esc_attr__( 'Short Description', 'wp-forecast' ); ?></td>
994 <td class='td-center'><input type="checkbox" name="d_c_short" id="d_c_short" value="1"
995 <?php
996 if ( substr( $av['dispconfig'], 2, 1 ) == '1' ) {
997 echo 'checked="checked"';}
998 ?>
999 /></td>
1000 <td class='td-center'><input type="checkbox" name="d_d_short" id="d_d_short" value="1"
1001 <?php
1002 if ( substr( $av['dispconfig'], 11, 1 ) == '1' ) {
1003 echo 'checked="checked"';}
1004 ?>
1005 /></td>
1006 <td class='td-center'><input type="checkbox" name="d_n_short" id="d_n_short" value="1"
1007 <?php
1008 if ( substr( $av['dispconfig'], 15, 1 ) == '1' ) {
1009 echo 'checked="checked"';}
1010 ?>
1011 /></td>
1012 </tr>
1013 <tr>
1014 <td><?php echo esc_attr__( 'Temperature', 'wp-forecast' ); ?></td>
1015 <td class='td-center'><input type="checkbox" name="d_c_temp" id="d_c_temp" value="1"
1016 <?php
1017 if ( substr( $av['dispconfig'], 3, 1 ) == '1' ) {
1018 echo 'checked="checked"';}
1019 ?>
1020 /></td>
1021 <td class='td-center'><input type="checkbox" name="d_d_temp" id="d_d_temp" value="1"
1022 <?php
1023 if ( substr( $av['dispconfig'], 12, 1 ) == '1' ) {
1024 echo 'checked="checked"';}
1025 ?>
1026 /></td>
1027 <td class='td-center'><input type="checkbox" name="d_n_temp" id="d_n_temp" value="1"
1028 <?php
1029 if ( substr( $av['dispconfig'], 16, 1 ) == '1' ) {
1030 echo 'checked="checked"';}
1031 ?>
1032 /></td>
1033 </tr>
1034 <tr>
1035 <td><?php echo esc_attr__( 'Realfeel', 'wp-forecast' ); ?></td>
1036 <td class='td-center'><input type="checkbox" name="d_c_real" id="d_c_real" value="1"
1037 <?php
1038 if ( substr( $av['dispconfig'], 4, 1 ) == '1' ) {
1039 echo 'checked="checked"';}
1040 ?>
1041 /></td>
1042 <td class='td-center'>&nbsp;</td>
1043 <td class='td-center'>&nbsp;</td>
1044 </tr>
1045 <tr>
1046 <td><?php echo esc_attr__( 'Pressure', 'wp-forecast' ); ?></td>
1047 <td class='td-center'><input type="checkbox" name="d_c_press" id="d_c_press" value="1"
1048 <?php
1049 if ( substr( $av['dispconfig'], 5, 1 ) == '1' ) {
1050 echo 'checked="checked"';}
1051 ?>
1052 /></td>
1053 <td class='td-center'>&nbsp;</td>
1054 <td class='td-center'>&nbsp;</td>
1055 </tr>
1056 <tr>
1057 <td><?php echo esc_attr__( 'Humidity', 'wp-forecast' ); ?></td>
1058 <td class='td-center'><input type="checkbox" name="d_c_humid" id="d_c_humid" value="1"
1059 <?php
1060 if ( substr( $av['dispconfig'], 6, 1 ) == '1' ) {
1061 echo 'checked="checked"';}
1062 ?>
1063 /></td>
1064 <td class='td-center'>&nbsp;</td>
1065 <td class='td-center'>&nbsp;</td>
1066 </tr>
1067 <tr>
1068 <td><?php echo esc_attr__( 'Wind', 'wp-forecast' ); ?></td>
1069 <td class='td-center'><input type="checkbox" name="d_c_wind" id="d_c_wind" value="1"
1070 <?php
1071 if ( substr( $av['dispconfig'], 7, 1 ) == '1' ) {
1072 echo 'checked="checked"';}
1073 ?>
1074 /></td>
1075 <td class='td-center'><input type="checkbox" name="d_d_wind" id="d_d_wind" value="1"
1076 <?php
1077 if ( substr( $av['dispconfig'], 13, 1 ) == '1' ) {
1078 echo 'checked="checked"';}
1079 ?>
1080 /></td>
1081 <td class='td-center'><input type="checkbox" name="d_n_wind" id="d_n_wind" value="1"
1082 <?php
1083 if ( substr( $av['dispconfig'], 17, 1 ) == '1' ) {
1084 echo 'checked="checked"';}
1085 ?>
1086 /></td>
1087 </tr>
1088 <tr>
1089 <td><?php echo esc_attr__( 'Windgusts', 'wp-forecast' ); ?></td>
1090 <td class='td-center'><input type="checkbox" name="d_c_wgusts" id="d_c_wgusts" value="1"
1091 <?php
1092 if ( substr( $av['dispconfig'], 22, 1 ) == '1' ) {
1093 echo 'checked="checked"';}
1094 ?>
1095 /></td>
1096 <td class='td-center'><input type="checkbox" name="d_d_wgusts" id="d_d_wgusts" value="1"
1097 <?php
1098 if ( substr( $av['dispconfig'], 23, 1 ) == '1' ) {
1099 echo 'checked="checked"';}
1100 ?>
1101 /></td>
1102 <td class='td-center'><input type="checkbox" name="d_n_wgusts" id="d_n_wgusts" value="1"
1103 <?php
1104 if ( substr( $av['dispconfig'], 24, 1 ) == '1' ) {
1105 echo 'checked="checked"';}
1106 ?>
1107 /></td>
1108 </tr>
1109
1110 <tr>
1111 <td><?php echo esc_attr__( 'Precipitation', 'wp-forecast' ); ?></td>
1112 <td class='td-center'><input type="checkbox" name="d_c_precipe" id="d_c_precipe" value="1"
1113 <?php
1114 if ( substr( $av['dispconfig'], 30, 1 ) == '1' ) {
1115 echo 'checked="checked"';}
1116 ?>
1117 /></td>
1118 <td class='td-center'><input type="checkbox" name="d_d_precipe" id="d_d_precipe" value="1"
1119 <?php
1120 if ( substr( $av['dispconfig'], 31, 1 ) == '1' ) {
1121 echo 'checked="checked"';}
1122 ?>
1123 /></td>
1124 <td class='td-center'><input type="checkbox" name="d_n_precipe" id="d_n_precipe" value="1"
1125 <?php
1126 if ( substr( $av['dispconfig'], 32, 1 ) == '1' ) {
1127 echo 'checked="checked"';}
1128 ?>
1129 /></td>
1130 </tr>
1131
1132 <tr>
1133 <td><?php echo esc_attr__( 'UV-Index', 'wp-forecast' ); ?></td>
1134 <td class='td-center'><input type="checkbox" name="d_c_uvindex" id="d_c_uvindex" value="1"
1135 <?php
1136 if ( substr( $av['dispconfig'], 27, 1 ) == '1' ) {
1137 echo 'checked="checked"';}
1138 ?>
1139 /></td>
1140 <td class='td-center'><input type="checkbox" name="d_d_maxuv" id="d_d_maxuv" value="1"
1141 <?php
1142 if ( substr( $av['dispconfig'], 28, 1 ) == '1' ) {
1143 echo 'checked="checked"';}
1144 ?>
1145 /></td>
1146 <td class='td-center'><input type="checkbox" name="d_n_maxuv" id="d_n_maxuv" value="1"
1147 <?php
1148 if ( substr( $av['dispconfig'], 29, 1 ) == '1' ) {
1149 echo 'checked="checked"';}
1150 ?>
1151 /></td>
1152 </tr>
1153
1154 <tr>
1155 <td><?php echo esc_attr__( 'Sunrise', 'wp-forecast' ); ?></td>
1156 <td class='td-center'><input type="checkbox" name="d_c_sunrise" id="d_c_sunrise" value="1"
1157 <?php
1158 if ( substr( $av['dispconfig'], 8, 1 ) == '1' ) {
1159 echo 'checked="checked"';}
1160 ?>
1161 /></td>
1162 <td class='td-center'>&nbsp;</td>
1163 <td class='td-center'>&nbsp;</td>
1164 </tr>
1165 <tr>
1166 <td><?php echo esc_attr__( 'Sunset', 'wp-forecast' ); ?></td>
1167 <td class='td-center'><input type="checkbox" name="d_c_sunset" id="d_c_sunset" value="1"
1168 <?php
1169 if ( substr( $av['dispconfig'], 9, 1 ) == '1' ) {
1170 echo 'checked="checked"';}
1171 ?>
1172 /></td>
1173 <td class='td-center'>&nbsp;</td>
1174 <td class='td-center'>&nbsp;</td>
1175 </tr>
1176 <tr>
1177 <td><?php echo esc_attr__( 'Copyright', 'wp-forecast' ); ?></td>
1178 <td class='td-center'><input type="checkbox" name="d_c_copyright" id="d_c_copyright" value="1"
1179 <?php
1180 if ( substr( $av['dispconfig'], 21, 1 ) == '1' ) {
1181 echo 'checked="checked"';}
1182 ?>
1183 /></td>
1184 <td class='td-center'>&nbsp;</td>
1185 <td class='td-center'>&nbsp;</td>
1186 </tr>
1187 <tr>
1188 <td><?php echo esc_attr__( 'Link to Weatherprovider', 'wp-forecast' ); ?></td>
1189 <td class='td-center'><input type="checkbox" name="d_c_accuweather" id="d_c_accuweather" value="1"
1190 <?php
1191 if ( substr( $av['dispconfig'], 25, 1 ) == '1' ) {
1192 echo 'checked="checked"';}
1193 ?>
1194 onchange="nwfields_update();" /></td>
1195 <td colspan="2" >(<?php echo esc_attr__( 'Open in new Window', 'wp-forecast' ); ?>:
1196 <input type="checkbox" name="d_c_aw_newwindow" id="d_c_aw_newwindow" value="1"
1197 <?php
1198 if ( substr( $av['dispconfig'], 26, 1 ) == '1' ) {
1199 echo 'checked="checked"';}
1200 ?>
1201 />)</td>
1202 </tr>
1203 </table>
1204 <br />
1205 <script type="text/javascript">nwfields_update();</script>
1206
1207 <b><?php echo esc_attr__( 'Forecast', 'wp-forecast' ); ?></b>
1208
1209 <table>
1210 <tr>
1211 <td>&nbsp;</td>
1212 <td><?php echo esc_attr__( 'All', 'wp-forecast' ); ?></td>
1213 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 1</td>
1214 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 2</td>
1215 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 3</td>
1216 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 4</td>
1217 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 5</td>
1218 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 6</td>
1219 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 7</td>
1220 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 8</td>
1221 <td><?php echo esc_attr__( 'Day', 'wp-forecast' ); ?> 9</td>
1222 </tr>
1223 <tr><td><?php echo esc_attr__( 'Daytime', 'wp-forecast' ); ?></td>
1224 <td><input type="checkbox" name="alldays" onclick="this.value=check('day')" /></td>
1225 <td><input type="checkbox" name="day1" id="day1" value="1"
1226 <?php
1227 if ( substr( $av['daytime'], 0, 1 ) == '1' ) {
1228 echo 'checked="checked"';}
1229 ?>
1230 /></td>
1231 <td><input type="checkbox" name="day2" id="day2" value="1"
1232 <?php
1233 if ( substr( $av['daytime'], 1, 1 ) == '1' ) {
1234 echo 'checked="checked"';}
1235 ?>
1236 /></td>
1237 <td><input type="checkbox" name="day3" id="day3" value="1"
1238 <?php
1239 if ( substr( $av['daytime'], 2, 1 ) == '1' ) {
1240 echo 'checked="checked"';}
1241 ?>
1242 /></td>
1243 <td><input type="checkbox" name="day4" id="day4" value="1"
1244 <?php
1245 if ( substr( $av['daytime'], 3, 1 ) == '1' ) {
1246 echo 'checked="checked"';}
1247 ?>
1248 /></td>
1249 <td><input type="checkbox" name="day5" id="day5" value="1"
1250 <?php
1251 if ( substr( $av['daytime'], 4, 1 ) == '1' ) {
1252 echo 'checked="checked"';}
1253 ?>
1254 /></td>
1255 <td><input type="checkbox" name="day6" id="day6" value="1"
1256 <?php
1257 if ( substr( $av['daytime'], 5, 1 ) == '1' ) {
1258 echo 'checked="checked"';}
1259 ?>
1260 /></td>
1261 <td><input type="checkbox" name="day7" id="day7" value="1"
1262 <?php
1263 if ( substr( $av['daytime'], 6, 1 ) == '1' ) {
1264 echo 'checked="checked"';}
1265 ?>
1266 /></td>
1267 <td><input type="checkbox" name="day8" id="day8" value="1"
1268 <?php
1269 if ( substr( $av['daytime'], 7, 1 ) == '1' ) {
1270 echo 'checked="checked"';}
1271 ?>
1272 /></td>
1273 <td><input type="checkbox" name="day9" id="day9" value="1"
1274 <?php
1275 if ( substr( $av['daytime'], 8, 1 ) == '1' ) {
1276 echo 'checked="checked"';}
1277 ?>
1278 /></td>
1279 </tr>
1280 <tr><td><?php echo esc_attr__( 'Nighttime', 'wp-forecast' ); ?></td>
1281 <td><input type="checkbox" name="allnight" onclick="this.value=check('night')" /></td>
1282 <td><input type="checkbox" name="night1" id="night1" value="1"
1283 <?php
1284 if ( substr( $av['nighttime'], 0, 1 ) == '1' ) {
1285 echo 'checked="checked"';}
1286 ?>
1287 /></td>
1288 <td><input type="checkbox" name="night2" id="night2" value="1"
1289 <?php
1290 if ( substr( $av['nighttime'], 1, 1 ) == '1' ) {
1291 echo 'checked="checked"';}
1292 ?>
1293 /></td>
1294 <td><input type="checkbox" name="night3" id="night3" value="1"
1295 <?php
1296 if ( substr( $av['nighttime'], 2, 1 ) == '1' ) {
1297 echo 'checked="checked"';}
1298 ?>
1299 /></td>
1300 <td><input type="checkbox" name="night4" id="night4" value="1"
1301 <?php
1302 if ( substr( $av['nighttime'], 3, 1 ) == '1' ) {
1303 echo 'checked="checked"';}
1304 ?>
1305 /></td>
1306 <td><input type="checkbox" name="night5" id="night5" value="1"
1307 <?php
1308 if ( substr( $av['nighttime'], 4, 1 ) == '1' ) {
1309 echo 'checked="checked"';}
1310 ?>
1311 /></td>
1312 <td><input type="checkbox" name="night6" id="night6" value="1"
1313 <?php
1314 if ( substr( $av['nighttime'], 5, 1 ) == '1' ) {
1315 echo 'checked="checked"';}
1316 ?>
1317 /></td>
1318 <td><input type="checkbox" name="night7" id="night7" value="1"
1319 <?php
1320 if ( substr( $av['nighttime'], 6, 1 ) == '1' ) {
1321 echo 'checked="checked"';}
1322 ?>
1323 /></td>
1324 <td><input type="checkbox" name="night8" id="night8" value="1"
1325 <?php
1326 if ( substr( $av['nighttime'], 7, 1 ) == '1' ) {
1327 echo 'checked="checked"';}
1328 ?>
1329 /></td>
1330 <td><input type="checkbox" name="night9" id="night9" value="1"
1331 <?php
1332 if ( substr( $av['nighttime'], 8, 1 ) == '1' ) {
1333 echo 'checked="checked"';}
1334 ?>
1335 /></td>
1336 </tr>
1337 </table>
1338 </div>
1339
1340 <?php
1341 if ( 0 === $widgetcall ) :
1342 ?>
1343 </fieldset><?php endif; ?>
1344
1345 <?php
1346 // OpenUV parameters.
1347 echo '<div>';
1348 echo "<b><a href='http://www.openuv.io' target='_blank'>" . esc_attr__( 'Use UV-Data from openuv.io', 'wp-forecast' ) . ':</a></b>&nbsp;&nbsp;&nbsp;';
1349
1350 echo esc_attr__( 'OpenUV - API-Key', 'wp-forecast' );
1351 echo ':<input name="ouv_apikey" id="ouv_apikey" type="text" size="40" maxlength="80" value="' . ( isset( $av['ouv_apikey'] ) ? esc_attr( $av['ouv_apikey'] ) : '' ) . '" />&nbsp;&nbsp;&nbsp;';
1352
1353 echo '<input type="checkbox" name="ouv_uv" id="oav_uv" value="1"';
1354 if ( isset( $av['ouv_uv'] ) && '1' === $av['ouv_uv'] ) {
1355 echo 'checked="checked"';
1356 }
1357 echo '/>';
1358 echo '<label for="oav_uv">' . esc_attr__( 'Show UV-Index', 'wp-forecast' ) . '&nbsp;&nbsp;&nbsp;</label>';
1359
1360 echo '<input type="checkbox" name="ouv_uvmax" id="oav_uvmax" value="1"';
1361 if ( isset( $av['ouv_uvmax'] ) && '1' === $av['ouv_uvmax'] ) {
1362 echo 'checked="checked"';
1363 }
1364 echo '/>';
1365 echo '<label for="oav_uvmax">' . esc_attr__( 'Show max. UV-Index', 'wp-forecast' ) . '&nbsp;&nbsp;&nbsp;</label>';
1366
1367 echo '<input type="checkbox" name="ouv_ozone" id="oav_ozone" value="1"';
1368 if ( isset( $av['ouv_ozone'] ) && '1' === $av['ouv_ozone'] ) {
1369 echo 'checked="checked"';
1370 }
1371 echo '/>';
1372 echo '<label for="oav_ozone">' . esc_attr__( 'Show Ozone', 'wp-forecast' ) . '&nbsp;&nbsp;&nbsp;</label>';
1373
1374 echo '<input type="checkbox" name="ouv_alticons" id="oav_alticons" value="1"';
1375 if ( isset( $av['ouv_alticons'] ) && '1' === $av['ouv_alticons'] ) {
1376 echo 'checked="checked"';
1377 }
1378 echo '/>';
1379 echo '<label for="oav_alticons">' . esc_attr__( 'Show alternative UV-icons', 'wp-forecast' ) . '&nbsp;&nbsp;&nbsp;</label>';
1380
1381 echo '</div>';
1382 ?>
1383
1384 <?php
1385 // submit button.
1386 if ( 0 === $widgetcall ) {
1387 echo "<div class='submit'><input class='button-primary' type='submit' name='info_update' value='" . esc_attr__( 'Update options', 'wp-forecast' ) . " »' /></div>";
1388 } else {
1389 echo "<input type='hidden' name='info_update' value='1' />";
1390 }
1391 ?>
1392
1393 </form>
1394
1395 <!-- -- ANFANG Suchdialog -->
1396 <div id="wpf_search__" style="display:none">
1397 <div class='wpf-search'>
1398 <form action='#' onsubmit="wpf_search(); return false;">
1399 <input name="wpf_nonce_3" id="wpf_nonce_3" type="hidden" value="<?php echo esc_attr( wp_create_nonce( 'wpf_nonce_3' ) ); ?>" />
1400 <?php
1401 // get locale.
1402 $locale = get_locale();
1403 if ( empty( $locale ) ) {
1404 $locale = 'en_US';
1405 }
1406 ?>
1407 <input id='wpf_search_language' type='hidden' value='<?php echo esc_attr( $locale ); ?>' />
1408 <input id='wpfcid' type='hidden' value='<?php echo esc_attr( $wpfcid ); ?>' />
1409
1410 <h3><?php esc_attr_e( 'Search location', 'wp-forecast' ); ?></h3>
1411 <p><b><?php esc_attr_e( 'Searchterm', 'wp-forecast' ); ?>:</b>
1412 <input id="searchloc" type="text" size="30" maxlength="30" />
1413 <a href="#" class='button-primary' style="color:#ffffff;" onclick='javascript:wpf_search();' id='search_loc'><?php esc_attr_e( 'Search location', 'wp-forecast' ); ?> »</a>
1414 <br /></p>
1415 <p><?php esc_attr_e( 'The search will be performed using OpenMeteo location database.', 'wp-forecast' ); ?></p>
1416 </form>
1417 </div>
1418 <hr />
1419 <div id="search_results"></div>
1420 </div>
1421 <!-- -- ENDE Suchdialog-->
1422
1423 <!-- -- ANFANG Check Dialog -->
1424 <div id="wpf_check__" style="display:none">
1425 <style>#message {margin:20px; padding:20px; background:#cccccc; color:#cc0000;}</style>
1426
1427 <div id="checkform" class="wrap" >
1428 <h2>
1429 <?php
1430 echo 'wp-forecast ';
1431 esc_attr_e( 'Connection-check', 'wp-forecast' );
1432 ?>
1433 </h2>
1434 <p><?php esc_attr_e( 'For OpenWeatherMap please enter your API-Key for Widget A before starting the connection test.', 'wp-forecast' ); ?></p>
1435 <form action='#' onsubmit="wpf_check(); return false;">
1436 <input name="wpf_nonce_3" type="hidden" value="<?php echo esc_attr( wp_create_nonce( 'wpf_nonce_3' ) ); ?>" />
1437 <table class="editform" cellspacing="5" cellpadding="5">
1438 <tr>
1439 <th scope="row"><label for="wprovider"><?php esc_attr_e( 'Select weatherprovider', 'wp-forecast' ); ?>:</label></th>
1440 <td><select name="wprovider" id="wprovider">
1441 <option value='Open-Meteo'>Open-Meteo</option>
1442 <option value='OpenWeatherMap'>OpenWeatherMap</option>
1443 <option value='OpenWeatherMapV3'>OpenWeatherMapV3</option>
1444 </select></td>
1445
1446 <tr><td><p class="submit">
1447 <input type="submit" name="startcheck" id="startcheck" value="<?php echo esc_attr_e( 'Start check', 'wp-forecast' ); ?> &raquo;" />
1448 <td><p class="submit">
1449 <input type="submit" name="cancel" id="cancel" value="<?php esc_attr_e( 'Close', 'wp-forecast' ); ?>" onclick="jQuery('div#check_log').html('');tb_remove();" /></p></td>
1450 </p></td></tr>
1451 </form></table>
1452 <hr />
1453
1454 <div id="check_log">Check log</div></div>
1455 </div>
1456 <!-- -- ENDE Check Dialog -->
1457
1458
1459
1460 </div>
1461 <?php
1462 echo '<script type="text/javascript">jQuery( document ).ready( function() { apifields(document.woptions.service.value); vlocfields_update();});';
1463 echo '</script>';
1464 }
1465
1466 /**
1467 * Add contextual help to WordPress admin Help menu.
1468 */
1469 function wp_forecast_contextual_help() {
1470
1471 $locale = get_locale();
1472 if ( empty( $locale ) ) {
1473 $locale = 'en_US';
1474 }
1475
1476 if ( function_exists( 'load_plugin_textdomain' ) ) {
1477 load_plugin_textdomain( 'wp-forecast', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
1478 }
1479
1480 $contextual_help = '<p>';
1481 $contextual_help .= esc_attr__(
1482 'If you are looking for instructions or help on wp-forecast,
1483 please use the following ressources. If you are stuck you can
1484 always write an email to',
1485 'wp-forecast'
1486 );
1487 $contextual_help .= ' <a href="mailto:support@tuxlog.de">support@tuxlog.de</a>.';
1488 $contextual_help .= '</p>';
1489 $contextual_help .= '<ul>';
1490 $contextual_help .= '<li><a href="http://www.tuxlog.de/wordpress/2008/wp-forecast-reference-v17-english/" target="_blank">';
1491 $contextual_help .= esc_attr__( 'English Manual', 'wp-forecast' );
1492 $contextual_help .= '</a></li>';
1493 $contextual_help .= '<li><a href=" http://www.tuxlog.de/wp-forecast-handbuch/" target="_blank">';
1494 $contextual_help .= esc_attr__( 'German Manual', 'wp-forecast' );
1495 $contextual_help .= '</a></li>';
1496 $contextual_help .= '<li><a href="http://www.tuxlog.de/wordpress/2009/checkliste-fur-wp-forecast-checklist-for-wp-worecast" target="_blank">';
1497 $contextual_help .= esc_attr__( 'Checklist for connection test', 'wp-forecast' );
1498 $contextual_help .= '</a></li>';
1499 $contextual_help .= '<li><a href="http://www.wordpress.org/extend/plugins/wp-forecast" target="_blank">';
1500 $contextual_help .= esc_attr__( 'wp-forecast on WordPress.org', 'wp-forecast' );
1501 $contextual_help .= '</a></li>';
1502 $contextual_help .= '<li><a href="http://www.tuxlog.de/wp-forecast/" target="_blank">';
1503 $contextual_help .= esc_attr__( 'German wp-forecast Site', 'wp-forecast' );
1504 $contextual_help .= '</a></li>';
1505 $contextual_help .= '<li><a href="http://www.tuxlog.de/wordpress/2012/wp-forecast-mit-wpml-nutzen" target="_blank">';
1506 $contextual_help .= esc_attr__( 'Using wp-forecast with WPML (german)', 'wp-forecast' );
1507 $contextual_help .= '</a></li>';
1508 $contextual_help .= '<li><a href="http://wordpress.org/plugins/wp-forecast/changelog/" target="_blank">';
1509 $contextual_help .= esc_attr__( 'Changelog', 'wp-forecast' );
1510 $contextual_help .= '</a></li></ul>';
1511 $contextual_help .= '<p>';
1512 $contextual_help .= esc_attr__( 'Links will open in new Window/Tab.', 'wp-forecast' );
1513 $contextual_help .= '</p>';
1514
1515 $screen = get_current_screen();
1516
1517 // Add my_help_tab if current screen is My Admin Page.
1518 $screen->add_help_tab(
1519 array(
1520 'id' => 'wpf_help_tab',
1521 'title' => esc_attr__( 'wp-forecast Help' ),
1522 'content' => $contextual_help,
1523 )
1524 );
1525 }
1526