Advertisement
Guest User

Untitled

a guest
May 22nd, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.03 KB | None | 0 0
  1. <?php
  2. /**
  3. * Created by ra.
  4. * Date: 9/28/2015
  5. */
  6.  
  7.  
  8. class td_weather
  9. {
  10.  
  11. private static $caching_time = 10800; // 3 hours
  12. //private static $owm_api_key = 'f5dc074e364b4d0bbaacbab0030031a3';
  13.  
  14. // private static $owm_api_keys = array (
  15. // //'4d99fdabeab40f86485ab0cdefab561b',
  16. // );
  17.  
  18. /**
  19. * Used by all the shortcodes + widget to render the weather. The top bar has a separate function bellow
  20. * @param $atts
  21. * @param $block_uid
  22. * @param $template string -> block_template | top_bar_template
  23. * @return string
  24. */
  25. static function render_generic($atts, $block_uid, $template = 'block_template')
  26. {
  27.  
  28. if (empty($atts['w_key']) and empty($atts['w_location'])) {
  29. return td_util::get_block_error('Weather widget', "Configure this block/widget's settings to get weather");
  30. }
  31.  
  32. if (empty($atts['w_location'])) {
  33. return td_util::get_block_error('Weather widget', "<strong>Location</strong> is empty. Configure this block/widget and enter a location and we will show the weather from that location :)");
  34. }
  35.  
  36. if (empty($atts['w_key'])) {
  37. return td_util::get_block_error('Weather widget', "<strong>Api key</strong> is empty. Configure this block/widget and enter an api key :)");
  38. }
  39.  
  40.  
  41. $current_unit = 0; // 0 - metric
  42. $current_temp_label = 'C';
  43. $current_speed_label = 'kmh';
  44.  
  45. if (!empty($atts['w_units'])) {
  46. $current_unit = 1; // imperial
  47. $current_temp_label = 'F';
  48. $current_speed_label = 'mph';
  49. }
  50.  
  51. // prepare the data and do an api call
  52. $weather_data = array(
  53. 'block_uid' => '',
  54. 'location' => $atts['w_location'],
  55. 'api_location' => $atts['w_location'], // the current location. It is updated by the wheater API
  56. 'api_language' => '', //this is set down bellow
  57. 'api_key' => $atts['w_key'],
  58. 'today_icon' => '',
  59. 'today_icon_text' => '',
  60. 'today_temp' => array(
  61. 0, // metric
  62. 0 // imperial
  63. ),
  64. 'today_humidity' => '',
  65. 'today_wind_speed' => array(
  66. 0, // metric
  67. 0 // imperial
  68. ),
  69. 'today_min' => array(
  70. 0, // metric
  71. 0 // imperial
  72. ),
  73. 'today_max' => array(
  74. 0, // metric
  75. 0 // imperial
  76. ),
  77. 'today_clouds' => 0,
  78. 'current_unit' => $current_unit,
  79. 'forecast' => array()
  80. );
  81.  
  82.  
  83. // disable the cache for debugging
  84. //td_remote_cache::_disable_cache();
  85. $weather_data_status = self::get_weather_data($atts, $weather_data);
  86.  
  87. // check if we have an error and return that
  88. if ($weather_data_status != 'api_fail_cache' and $weather_data_status != 'api' and $weather_data_status != 'cache') {
  89. return $weather_data_status;
  90. }
  91.  
  92. // we have to patch the cached data - to make sure we have the REAL block_uid that is now on the page
  93. $weather_data['block_uid'] = $block_uid;
  94.  
  95.  
  96. // render the HTML
  97. $buffy = '<!-- td weather source: ' . $weather_data_status . ' -->';
  98.  
  99.  
  100. if ($template == 'block_template') {
  101. // renders the block template
  102. $buffy .= self::render_block_template($atts, $weather_data, $current_temp_label, $current_speed_label, $block_uid);
  103. } else {
  104. // render the top menu template
  105. $buffy .= self::render_top_bar_template($atts, $weather_data, $current_temp_label);
  106. }
  107.  
  108.  
  109. // do not add any items to tdWeather if we're on the front end editor / ajax front end editor
  110. if (!td_util::tdc_is_live_editor_iframe() && !td_util::tdc_is_live_editor_ajax()) {
  111. // render the JS
  112. ob_start();
  113. ?>
  114. <script>
  115. jQuery().ready(function () {
  116. tdWeather.addItem(<?php echo json_encode($weather_data) ?>);
  117. });
  118. </script>
  119. <?php
  120. // $script_buffer = ob_get_clean();
  121. // $js_script = "\n". td_util::remove_script_tag($script_buffer);
  122. td_js_buffer::add_to_footer("\n" . td_util::remove_script_tag(ob_get_clean()));
  123. }
  124.  
  125. return $buffy;
  126. }
  127.  
  128.  
  129. /**
  130. * renders the template that is used in the top bar of the site
  131. * @param $atts - the atts that the block gets
  132. * @param $weather_data - the precomputed weather data
  133. * @param $current_temp_label - C/F
  134. *
  135. * @return string - HTML the rendered template
  136. */
  137. private static function render_top_bar_template($atts, $weather_data, $current_temp_label)
  138. {
  139. $current_unit = $weather_data['current_unit'];
  140. ob_start();
  141. ?>
  142. <div class="td-weather-top-widget" id="<?php echo $weather_data['block_uid'] ?>">
  143. <i class="td-icons <?php echo $weather_data['today_icon'] ?>"></i>
  144. <div class="td-weather-now" data-block-uid="<?php echo $weather_data['block_uid'] ?>">
  145. <span class="td-big-degrees"><?php echo $weather_data['today_temp'][$current_unit] ?></span>
  146. <span class="td-weather-unit"><?php echo $current_temp_label ?></span>
  147. </div>
  148. <div class="td-weather-header">
  149. <div class="td-weather-city"><?php echo $weather_data['api_location'] ?></div>
  150. </div>
  151. </div>
  152. <?php
  153. return ob_get_clean();
  154. }
  155.  
  156.  
  157. /**
  158. * renders the template that is used on all weather blocks and widgets
  159. * @param $atts - the atts that the block gets
  160. * @param $weather_data - the precomputed weather data
  161. * @param $current_temp_label - C/F
  162. * @param $current_speed_label - mph/kmh
  163. * @param $block_uid the unique id of the block
  164. * @return string - HTML the rendered template
  165. */
  166. private static function render_block_template($atts, $weather_data, $current_temp_label, $current_speed_label, $block_uid)
  167. {
  168. $current_unit = $weather_data['current_unit'];
  169. ob_start();
  170. ?>
  171.  
  172. <div class="td-weather-header">
  173. <div class="td-weather-city"><?php echo $weather_data['api_location'] ?></div>
  174. <div class="td-weather-condition"><?php echo $weather_data['today_icon_text'] ?></div>
  175. <i class="td-location-icon td-icons-location" data-block-uid="<?php echo $weather_data['block_uid'] ?>"></i>
  176. </div>
  177.  
  178. <div class="td-weather-set-location">
  179. <form class="td-manual-location-form" action="#" data-block-uid="<?php echo $weather_data['block_uid'] ?>">
  180. <input id="<?php echo $weather_data['block_uid'] ?>" class="td-location-set-input" type="text"
  181. name="location" value="">
  182. <label>enter location</label>
  183. </form>
  184. </div>
  185.  
  186. <div class="td-weather-temperature">
  187. <div class="td-weather-temp-wrap">
  188. <div class="td-weather-animated-icon">
  189. <span
  190. class="td_animation_sprite-27-100-80-0-0-1 <?php echo $weather_data['today_icon'] ?> td-w-today-icon"
  191. data-td-block-uid="<?php echo $block_uid ?>"></span>
  192. </div>
  193. <div class="td-weather-now" data-block-uid="<?php echo $weather_data['block_uid'] ?>">
  194. <span class="td-big-degrees"><?php echo $weather_data['today_temp'][$current_unit] ?></span>
  195. <span class="td-circle">&deg;</span>
  196. <span class="td-weather-unit"><?php echo $current_temp_label; ?></span>
  197. </div>
  198. <div class="td-weather-lo-hi">
  199. <div class="td-weather-degrees-wrap">
  200. <i class="td-up-icon td-icons-arrows-up"></i>
  201. <span
  202. class="td-small-degrees td-w-high-temp"><?php echo $weather_data['today_max'][$current_unit] ?></span>
  203. <span class="td-circle">&deg;</span>
  204. </div>
  205. <div class="td-weather-degrees-wrap">
  206. <i class="td-down-icon td-icons-arrows-down"></i>
  207. <span
  208. class="td-small-degrees td-w-low-temp"><?php echo $weather_data['today_min'][$current_unit] ?></span>
  209. <span class="td-circle">&deg;</span>
  210. </div>
  211. </div>
  212. </div>
  213. </div>
  214.  
  215. <div class="td-weather-info-wrap">
  216. <div class="td-weather-information">
  217. <div class="td-weather-section-1">
  218. <i class="td-icons-drop"></i>
  219. <span class="td-weather-parameter td-w-today-humidity"><?php echo $weather_data['today_humidity'] ?>
  220. %</span>
  221. </div>
  222. <div class="td-weather-section-2">
  223. <i class="td-icons-wind"></i>
  224. <span
  225. class="td-weather-parameter td-w-today-wind-speed"><?php echo $weather_data['today_wind_speed'][$current_unit] . $current_speed_label; ?></span>
  226. </div>
  227. <div class="td-weather-section-3">
  228. <i class="td-icons-cloud"></i>
  229. <span class="td-weather-parameter td-w-today-clouds"><?php echo $weather_data['today_clouds'] ?>
  230. %</span>
  231. </div>
  232. </div>
  233.  
  234.  
  235. <div class="td-weather-week">
  236. <?php
  237. $count = 0;
  238. foreach ($weather_data['forecast'] as $forecast_index => $day_forecast) {
  239. if ($count === 5) {
  240. break;
  241. }
  242. ?>
  243. <div class="td-weather-days">
  244. <div class="td-day-<?php echo $forecast_index ?>"><?php echo $day_forecast['day_name'] ?></div>
  245.  
  246. <div class="td-day-degrees">
  247. <span
  248. class="td-degrees-<?php echo $forecast_index ?>"><?php echo $day_forecast['day_temp'][$current_unit] ?></span>
  249. <span class="td-circle">&deg;</span>
  250. </div>
  251. </div>
  252. <?php
  253. $count++;
  254. }
  255. ?>
  256. </div>
  257. </div>
  258.  
  259. <?php
  260. return ob_get_clean();
  261. }
  262.  
  263.  
  264. /**
  265. * @param $atts
  266. * @param $weather_data - the precomputed weather data
  267. * @return bool|string
  268. * - bool:true - we have the $weather_data (from cache or from a real request)
  269. * - string - error message
  270. */
  271. private static function get_weather_data($atts, &$weather_data)
  272. {
  273. if (empty($atts['w_language'])) {
  274. $atts['w_language'] = 'en';
  275. $sytem_locale = get_locale();
  276. $available_locales = array('en', 'es', 'sp', 'fr', 'it', 'de', 'pt', 'ro', 'pl', 'ru', 'uk', 'ua', 'fi', 'nl', 'bg', 'sv', 'se', 'ca', 'tr', 'hr', 'zh', 'zh_tw', 'zh_cn', 'hu');
  277.  
  278. // CHECK FOR LOCALE
  279. if (in_array($sytem_locale, $available_locales)) {
  280. $atts['w_language'] = $sytem_locale;
  281. }
  282. // CHECK FOR LOCALE BY FIRST TWO DIGITS
  283. if (in_array(substr($sytem_locale, 0, 2), $available_locales)) {
  284. $atts['w_language'] = substr($sytem_locale, 0, 2);
  285. }
  286. }
  287.  
  288.  
  289. $cache_key = strtolower($atts['w_location'] . '_' . $atts['w_language'] . '_' . $weather_data['current_unit']);
  290. if (td_remote_cache::is_expired(__CLASS__, $cache_key) === true) {
  291. // cache is expired - do a request
  292. $today_api_data = self::owm_get_today_data($atts, $weather_data);
  293. $forecast_api_data = self::owm_get_five_days_data($atts, $weather_data);
  294.  
  295. // check the api call response
  296. if ($today_api_data !== true or $forecast_api_data !== true) {
  297. // we have an error on one of the apis
  298. $weather_data = td_remote_cache::get(__CLASS__, $cache_key);
  299. if ($weather_data === false) { // miss and io error... shit / die
  300. return self::error('Weather API error: ' . $today_api_data . ' ' . $forecast_api_data);
  301. }
  302.  
  303. td_remote_cache::extend(__CLASS__, $cache_key, self::$caching_time);
  304. return 'api_fail_cache';
  305. }
  306.  
  307. td_remote_cache::set(__CLASS__, $cache_key, $weather_data, self::$caching_time); //we have a reply and we set it
  308. return 'api';
  309.  
  310. } else {
  311. // cache is valid
  312. $weather_data = td_remote_cache::get(__CLASS__, $cache_key);
  313. return 'cache';
  314. }
  315.  
  316. }
  317.  
  318.  
  319. /**
  320. * adds to the &$weather_data the information for today's forecast from OWM
  321. * @param $atts - the shortcode atts
  322. * @param $weather_data - BYREF weather data - this function will add to it
  323. *
  324. * @return bool|string
  325. * - true: if everything is ok
  326. * - string: the error message, if there was an error
  327. */
  328. private static function owm_get_today_data($atts, &$weather_data)
  329. {
  330. $today_weather_url = 'https://api.openweathermap.org/data/2.5/weather?id=' . urlencode($atts['w_location']) . '&lang=' . $atts['w_language'] . '&units=metric&appid=' . $weather_data['api_key'];
  331. //print("<pre>".print_r($today_weather_url,true)."</pre>");
  332.  
  333. $json_api_response = td_remote_http::get_page($today_weather_url, __CLASS__);
  334.  
  335. //print("<pre> json city weather API response: ".print_r($json_api_response,true)."</pre>");
  336.  
  337.  
  338. // fail
  339. if ($json_api_response === false) {
  340. td_log::log(__FILE__, __FUNCTION__, 'Api call failed', $today_weather_url);
  341. return 'Error getting remote data for today forecast. Please check your server configuration';
  342. }
  343.  
  344. // try to decode the json
  345. $api_response = @json_decode($json_api_response, true);
  346. if ($api_response === null and json_last_error() !== JSON_ERROR_NONE) {
  347. td_log::log(__FILE__, __FUNCTION__, 'Error decoding the json', $api_response);
  348. return 'Error decoding the json from OpenWeatherMap';
  349. }
  350.  
  351. if ($api_response['cod'] != 200) {
  352. if ($api_response['cod'] == 404) {
  353. return 'City not found'; // fix the incorect error message form the api :|
  354. }
  355. if (isset($api_response['message'])) {
  356. return $api_response['message'];
  357. }
  358. return 'OWM code != 200. No message provided';
  359. }
  360.  
  361. //print_r($api_response);
  362.  
  363.  
  364. // set the language of the api
  365. $weather_data['api_language'] = $atts['w_language'];
  366.  
  367. // current location
  368. if (isset($api_response['name'])) {
  369. $weather_data['api_location'] = $api_response['name'];
  370. }
  371.  
  372. // min max current temperature
  373. if (isset($api_response['main']['temp'])) {
  374. $weather_data['today_temp'][0] = round($api_response['main']['temp'], 1);
  375. $weather_data['today_temp'][1] = self::celsius_to_fahrenheit($api_response['main']['temp']);
  376. }
  377. if (isset($api_response['main']['temp_min'])) {
  378. $weather_data['today_min'][0] = round($api_response['main']['temp_min'], 1);
  379. $weather_data['today_min'][1] = self::celsius_to_fahrenheit($api_response['main']['temp_min']);
  380. }
  381. if (isset($api_response['main']['temp_max'])) {
  382. $weather_data['today_max'][0] = round($api_response['main']['temp_max'], 1);
  383. $weather_data['today_max'][1] = self::celsius_to_fahrenheit($api_response['main']['temp_max']);
  384. }
  385.  
  386. // humidity
  387. if (isset($api_response['main']['humidity'])) {
  388. $weather_data['today_humidity'] = round($api_response['main']['humidity']);
  389. }
  390.  
  391. // wind speed and direction
  392. if (isset($api_response['wind']['speed'])) {
  393. $weather_data['today_wind_speed'][0] = round($api_response['wind']['speed'], 1);
  394. $weather_data['today_wind_speed'][1] = self::kmph_to_mph($api_response['wind']['speed']);
  395. }
  396.  
  397. // forecast description
  398. if (isset($api_response['weather'][0]['description'])) {
  399. $weather_data['today_icon_text'] = $api_response['weather'][0]['description'];
  400. }
  401.  
  402. // clouds
  403. if (isset($api_response['clouds']['all'])) {
  404. $weather_data['today_clouds'] = round($api_response['clouds']['all']);
  405. }
  406.  
  407. // icon
  408. if (isset($api_response['weather'][0]['icon'])) {
  409. $icons = array(
  410. // day
  411. '01d' => 'clear-sky-d',
  412. '02d' => 'few-clouds-d',
  413. '03d' => 'scattered-clouds-d',
  414. '04d' => 'broken-clouds-d',
  415. '09d' => 'shower-rain-d', // ploaie hardcore
  416. '10d' => 'rain-d', // ploaie light
  417. '11d' => 'thunderstorm-d',
  418. '13d' => 'snow-d',
  419. '50d' => 'mist-d',
  420.  
  421. //night
  422. '01n' => 'clear-sky-n',
  423. '02n' => 'few-clouds-n',
  424. '03n' => 'scattered-clouds-n',
  425. '04n' => 'broken-clouds-n',
  426. '09n' => 'shower-rain-n', // ploaie hardcore
  427. '10n' => 'rain-n', // ploaie light
  428. '11n' => 'thunderstorm-n',
  429. '13n' => 'snow-n',
  430. '50n' => 'mist-n',
  431. );
  432.  
  433. $weather_data['today_icon'] = 'clear-sky-d'; // the default icon :) if we get an error or strange icons as a reply
  434. if (isset($icons[$api_response['weather'][0]['icon']])) {
  435. $weather_data['today_icon'] = $icons[$api_response['weather'][0]['icon']];
  436. }
  437. } // end icon
  438.  
  439. return true; // return true if ~everything is ok
  440. }
  441.  
  442. /**
  443. * adds to the &$weather_data the information for the next 5 days
  444. * @param $atts - the shortcode atts
  445. * @param $weather_data - BYREF weather data - this function will add to it
  446. *
  447. * @return bool|string
  448. * - true: if everything is ok
  449. * - string: the error message, if there was an error
  450. */
  451. private static function owm_get_five_days_data($atts, &$weather_data)
  452. {
  453. // request 7 days because the current day may be today in a different timezone
  454. $today_weather_url = 'https://api.openweathermap.org/data/2.5/forecast?id=' . urlencode($atts['w_location']) . '&lang=' . $atts['w_language'] . '&units=metric&cnt=35&appid=' . $weather_data['api_key'];
  455. //print("<pre>".print_r($today_weather_url,true)."</pre>");
  456.  
  457. $json_api_response = td_remote_http::get_page($today_weather_url, __CLASS__);
  458.  
  459. //print("<pre> json city forecast API response: ".print_r($json_api_response,true)."</pre>");
  460.  
  461.  
  462. // fail
  463. if ($json_api_response === false) {
  464. td_log::log(__FILE__, __FUNCTION__, 'Api call failed', $today_weather_url);
  465. return 'Error getting remote data for 5 days forecast. Please check your server configuration';
  466. }
  467.  
  468. // try to decode the json
  469. $api_response = @json_decode($json_api_response, true);
  470. if ($api_response === null and json_last_error() !== JSON_ERROR_NONE) {
  471. td_log::log(__FILE__, __FUNCTION__, 'Error decoding the json', $api_response);
  472. return 'Error decoding the json from OpenWeatherMap';
  473. }
  474.  
  475. // today in format like: 20150210
  476. //$today_date = date('Y-m-d', current_time('timestamp', 0));
  477.  
  478. if (!empty($api_response['list']) and is_array($api_response['list'])) {
  479. $tmp_temps = array();
  480.  
  481. foreach ($api_response['list'] as $index => $day_forecast) {
  482.  
  483. if (
  484. !empty($day_forecast['dt'])
  485. and !empty($day_forecast['main']['temp'])
  486. ) {// because the api return UTC time and we may have different timezones on the server. Avoid showing the same day twice
  487.  
  488. $current_day = date('j', $day_forecast['dt']);
  489.  
  490. if (!isset($tmp_temps[$current_day])) {
  491. $tmp_temps[$current_day]= array (
  492. 'timestamp' => $day_forecast['dt'],
  493. 'day_name' => date_i18n('D', $day_forecast['dt']),
  494. 'day_temp' => array(
  495. round($day_forecast['main']['temp_max']), // metric
  496. round(self::celsius_to_fahrenheit($day_forecast['main']['temp_max'])) //imperial
  497. ),
  498. 'owm_day_index' => $index, // used in js to update only the displayed days when we do api calls from JS
  499. );
  500. } else {
  501.  
  502. if ($tmp_temps[$current_day]['day_temp'][0] < round($day_forecast['main']['temp_max'])) {
  503.  
  504. $tmp_temps[$current_day]['day_temp'][0] = round($day_forecast['main']['temp_max']); // metric
  505. $tmp_temps[$current_day]['day_temp'][1] = round(self::celsius_to_fahrenheit($day_forecast['main']['temp_max'])); //imperial
  506. }
  507. }
  508. }
  509.  
  510. }
  511.  
  512. $weather_data['forecast'] = array_values($tmp_temps);
  513. return true;
  514. }
  515. return false; // return true if ~everything is ok
  516. }
  517.  
  518.  
  519. /**
  520. * convert celsius to fahrenheit + rounding (no decimals if result > 100 or one decimal if result < 100)
  521. * @param $celsius_degrees
  522. * @return float
  523. */
  524. private static function celsius_to_fahrenheit($celsius_degrees)
  525. {
  526. $f_degrees = $celsius_degrees * 9 / 5 + 32;
  527.  
  528. $rounded_val = round($f_degrees, 1);
  529. if ($rounded_val > 99.9) { // if the value is bigger than 100, round it with no zecimals
  530. return round($f_degrees);
  531. }
  532.  
  533. return $rounded_val;
  534. }
  535.  
  536.  
  537. /**
  538. * rounding to .1
  539. * @param $kmph
  540. * @return float
  541. */
  542. private static function kmph_to_mph($kmph)
  543. {
  544. return round($kmph * 0.621371192, 1);
  545. }
  546.  
  547.  
  548. /**
  549. * Show an error if the user is logged in. It does not check for admin
  550. * @param $msg
  551. * @return string
  552. */
  553. private static function error($msg)
  554. {
  555. if (is_user_logged_in()) {
  556. return $msg;
  557. }
  558. return '';
  559. }
  560.  
  561.  
  562. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement