PageRenderTime 66ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

/100Cities.php

https://github.com/wp-plugins/100-cities
PHP | 574 lines | 491 code | 40 blank | 43 comment | 95 complexity | 2830a3a4ed6eb84849ba6dadb51cfb85 MD5 | raw file
  1. <?php
  2. /*
  3. Plugin Name: 100Cities
  4. Plugin URI: http://www.knok.com/100-cities/
  5. Text Domain: onehundredcities
  6. Description: a plugin to show the one of the 100 cities to home swap before you die
  7. Version: 1.0
  8. Author: Jonay Pelluz
  9. Author URI: http://www.jonaypelluz.com
  10. License: GPL2
  11. Copyright 2013 Jonay Pelluz (email : jonaypelluz@gmail.com)
  12. This program is free software; you can redistribute it and/or modify
  13. it under the terms of the GNU General Public License, version 2, as
  14. published by the Free Software Foundation.
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU General Public License for more details.
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. if (!function_exists('is_admin')) {
  24. header('Status: 403 Forbidden');
  25. header('HTTP/1.1 403 Forbidden');
  26. exit();
  27. }
  28. //Textdomain for the translation
  29. $textdomain = 'onehundredcities';
  30. //Load translation
  31. load_plugin_textdomain($textdomain, false, dirname( plugin_basename(__FILE__) ) . '/lang');
  32. //Pre Wordpress - 2.6 compatibility
  33. if (!defined('WP_CONTENT_URL')){
  34. define('WP_CONTENT_URL', get_option('siteurl') . '/wp-content' );
  35. }
  36. if (!defined('WP_CONTENT_DIR')){
  37. define('WP_CONTENT_DIR', ABSPATH . 'wp-content');
  38. }
  39. if(!class_exists("OneHundredCities")){
  40. class OneHundredCities {
  41. protected $options_page,$plugin_path,$plugin_url;
  42. protected $feed_url = "http://www.knok.com/100-cities/tag/"; //You can change this for your own feed base by location
  43. protected $data; //We get options store data, we control this data from the admin page;
  44. protected $default_lang = "eng"; //You default language, if it isn't set by the widget or include the plugin uses this one
  45. protected $default_panoramio_photos = 3; //Default quantity of panoramio photos to get
  46. protected $active_tag = null;
  47. protected $active_category = null;
  48. //Change template here if you want to use your own
  49. protected $basic_template = '100Cities_basic.php';
  50. //Change the size of the map depending on the size of the container, and zoom
  51. protected $map_width = '350';
  52. protected $map_zoom = 8;
  53. //TODO: Allow all default variables to be passed as array.
  54. function __construct(){
  55. $this->plugin_path = dirname(__FILE__);
  56. $this->plugin_url = WP_PLUGIN_URL . '/100-cities';
  57. if(is_admin()){
  58. if(!class_exists("OneHundredCities_Options")) {
  59. require($this->plugin_path . '/100Cities-options.php');
  60. }
  61. $this->options_page = new OneHundredCities_Options();
  62. }
  63. //Get save plugin options data
  64. $this->data = json_decode(get_option('one-hundred-cities-data'));
  65. //Check if tag page or category page options are active, and insert plugin
  66. if($this->data->tags == 1 || $this->data->categories == 1){
  67. add_action( 'pre_get_posts', array($this, 'check_page_type'));
  68. }
  69. //Add plugin template if shortcode is found in post
  70. add_shortcode( 'onehundredcities', array($this, 'insert_cities_template') );
  71. //Loading custom CSS
  72. wp_register_style('google_font', 'http://fonts.googleapis.com/css?family=Archivo+Narrow');
  73. wp_enqueue_style('google_font');
  74. if($this->data->css != 1){
  75. wp_enqueue_style('widgets_init', $this->plugin_url . '/assets/100Cities.css');
  76. } else {
  77. wp_enqueue_style('widgets_init', $this->plugin_url . '/assets/default-100Cities.css');
  78. }
  79. }
  80. function check_page_type( $query ){
  81. //Check page type
  82. if($this->data->tags == 1 && $query->is_tag()){
  83. $this->active_tag = $query->query_vars['tag'];
  84. add_action('wp_meta', array($this, 'insert_plugin_if_tag'));
  85. }
  86. if($this->data->categories == 1 && $query->is_category()){
  87. $this->active_category = $query->query_vars['category'];
  88. }
  89. }
  90. function insert_plugin_if_tag(){
  91. echo $this->insert_cities_template( array( 'location' => $this->active_tag ) );
  92. }
  93. function check_rss_exists( $url ){
  94. $file_headers = @get_headers($url);
  95. if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
  96. return false;
  97. } else {
  98. return true;
  99. }
  100. }
  101. //removes equal array values
  102. function custom_array_unique($array, $keep_key_assoc = false) {
  103. $duplicate_keys = array();
  104. $tmp = array();
  105. foreach ($array as $key=>$val) {
  106. //Convert objects to arrays, in_array() does not support objects
  107. if (is_object($val))
  108. $val = (array)$val;
  109. if (!in_array($val, $tmp))
  110. $tmp[] = $val;
  111. else
  112. $duplicate_keys[] = $key;
  113. }
  114. foreach ($duplicate_keys as $key)
  115. unset($array[$key]);
  116. return $keep_key_assoc ? $array : array_values($array);
  117. }
  118. function get_photos_panoramio( $geo, $location, $count ){
  119. if($count == false){
  120. $count = $this->default_panoramio_photos;
  121. }
  122. $file_name = "panoramio_" . $count . "_" . strtolower(str_replace(" ","-",$location)) . ".log";
  123. $data = $this->get_cache_data($file_name);
  124. if(!$data){
  125. if(!empty($geo)){
  126. $radius = 0.045;
  127. $geoLat = $geo['lat'];
  128. $geoLng = $geo['lng'];
  129. $panoramio_url = "http://www.panoramio.com/map/get_panoramas.php?set=public&from=0&to=" . $count . "&minx=" . ( $geoLng - $radius ) . "&miny=" . ( $geoLat - $radius ) . "&maxx=" . ( $geoLng + $radius ) . "&maxy=" . ( $geoLat + $radius ) . "&size=small&mapfilter=true";
  130. $panoramio = json_decode(file_get_contents($panoramio_url), true);
  131. $data = $panoramio['photos'];
  132. }
  133. if(!empty($data)){
  134. $this->write_cache($data, $file_name);
  135. }
  136. }
  137. return $data;
  138. }
  139. //Get related posts for a given location
  140. function get_data_by_location( $location, $lng, $custom_feed ){
  141. $file_name = "articles_" . strtolower(str_replace(" ","-",$location)) . "_" . $lng . ".log";
  142. $data = $this->get_cache_data($file_name);
  143. if(!$data){
  144. if(isset($custom_feed) && $custom_feed != false){
  145. $url = $custom_feed;
  146. } else {
  147. $url = $this->feed_url . str_replace(" ", "-", strtolower($location)) . "/feed/";
  148. }
  149. if($this->check_rss_exists($url)){
  150. $doc = new DOMDocument();
  151. $doc->load($url);
  152. if($doc->getElementsByTagName('item')){
  153. $i = 0;
  154. foreach ($doc->getElementsByTagName('item') as $node) {
  155. $data['title'] = $node->getElementsByTagName('title')->item(0)->nodeValue;
  156. $data['link'] = strtok($node->getElementsByTagName('link')->item(0)->nodeValue, "?");
  157. $data['pubDate'] = date("M, d Y", strtotime($node->getElementsByTagName('pubDate')->item(0)->nodeValue));
  158. $data['description'] = utf8_decode(htmlentities(strip_tags($node->getElementsByTagName('description')->item(0)->nodeValue)));
  159. $data['description'] = preg_replace('/&a?m?p?;?#8217;/', "'", $data['description']);
  160. break;
  161. }
  162. if(!empty($data)){
  163. $this->write_cache($data, $file_name);
  164. }
  165. }
  166. }
  167. }
  168. return $data;
  169. }
  170. function get_cache_data($file_name, $time = false) {
  171. if(!$time){ $time = 60*60*24*2; }
  172. $file_url = $this->plugin_path . "/cache/" . $file_name;
  173. if (file_exists($file_url) && ((time()-filemtime($file_url)) < $time)){
  174. $str = file_get_contents($file_url);
  175. return unserialize($str);
  176. }
  177. }
  178. function write_cache($data, $file_name) {
  179. $file_url = $this->plugin_path . "/cache/" . $file_name;
  180. $fp = fopen($file_url, 'w');
  181. fwrite($fp, serialize($data));
  182. fclose($fp);
  183. }
  184. function insert_cities_template( $atts ) {
  185. if(!isset($atts['div'])){
  186. $atts['div'] = $this->data->div;
  187. }
  188. if($atts['div'] == 'block'){
  189. $atts['map_width'] = '900';
  190. }
  191. if(isset($atts['wiki']) && $atts['wiki'] == 'off'){
  192. $atts['wiki'] = 0; //Zero means, It won't get printed
  193. } else {
  194. $atts['wiki'] = $this->data->wikipedia;
  195. }
  196. if(isset($atts['gmaps']) && $atts['gmaps'] == 'off'){
  197. $atts['gmaps'] = 0;
  198. } else {
  199. $atts['gmaps'] = $this->data->gmaps;
  200. }
  201. if(isset($atts['panoramio']) && $atts['panoramio'] == 'off'){
  202. $atts['panoramio'] = 0;
  203. } else {
  204. $atts['panoramio'] = $this->data->panoramio;
  205. }
  206. if(isset($atts['articles']) && $atts['articles'] == 'off'){
  207. $atts['articles'] = 0;
  208. } else {
  209. $atts['articles'] = $this->data->articles;
  210. }
  211. if(isset($atts['logo']) && $atts['logo'] == 'off'){
  212. $atts['logo'] = 0;
  213. } else {
  214. $atts['logo'] = $this->data->logo;
  215. }
  216. if(!isset($atts['weather']) && $atts['weather'] == 'off'){
  217. $atts['weather'] = 0;
  218. } else {
  219. $atts['weather'] = $this->data->weather;
  220. }
  221. if(!isset($atts['mapzoom'])){
  222. $atts['mapzoom'] = $this->map_zoom;
  223. }
  224. if(!isset($atts['panoramiocount']) || $atts['panoramiocount'] == 0 || $atts['panoramiocount'] == ""){
  225. $atts['panoramiocount'] = false;
  226. }
  227. if(!isset($atts['lang'])){
  228. $atts['lang'] = $this->default_lang; //Default lang is English
  229. }
  230. $atts['articles_feed'] = $this->data->articles_feed;
  231. if(isset($atts['location'])){
  232. return $this->get_city_info( $atts );
  233. } else {
  234. return "";
  235. }
  236. }
  237. function get_geo_location($location){
  238. $geo_file_name = "geo_" . strtolower(str_replace(" ","-",$location)) . ".log";
  239. $data = $this->get_cache_data($geo_file_name);
  240. if(empty($data)){
  241. $data = array();
  242. $gmap_url = "http://maps.googleapis.com/maps/api/geocode/json?address=" . urlencode($location) . "&sensor=false";
  243. $json = json_decode(file_get_contents($gmap_url), true);
  244. if(isset($json['results'][0]['geometry']['location']['lat'])){
  245. $data['lat'] = $json['results'][0]['geometry']['location']['lat'];
  246. $data['lng'] = $json['results'][0]['geometry']['location']['lng'];
  247. $this->write_cache($data, $geo_file_name);
  248. }
  249. }
  250. return $data;
  251. }
  252. function get_city_info( $params ){
  253. $data['geo'] = $this->get_geo_location( $params['location'] );
  254. $data['location'] = $params['location'];
  255. $data['div'] = $params['div'];
  256. if($params['wiki'] == 1){
  257. $data['wiki'] = $this->get_wikipedia_info( $params['lang'], $params['location'] );
  258. }
  259. if($params['gmaps'] == 1){
  260. if(isset($params['map_width'])){
  261. $data['map_width'] = $params['map_width'];
  262. } else {
  263. $data['map_width'] = $this->map_width;
  264. }
  265. $data['zoom'] = $params['mapzoom'];
  266. }
  267. if($params['articles'] == 1){
  268. if($params['articles_feed'] != ""){
  269. $data['location_url'] = "";
  270. $data['location_post'] = $this->get_data_by_location( $params['location'], $params['lang'], $params['articles_feed'] );
  271. } else {
  272. $data['location_url'] = $this->feed_url . str_replace(" ", "-", strtolower($params['location'])) . "/";
  273. $data['location_post'] = $this->get_data_by_location( $params['location'], $params['lang'], false );
  274. $data['location_name'] = __("more posts about","onehundredcities") . " " . $params['location'] . " &raquo;";
  275. }
  276. $data['location_title'] = __("Related posts","onehundredcities");
  277. }
  278. if($params['panoramio'] == 1 && !empty($data['geo'])){
  279. $data['panoramio_photos'] = $this->get_photos_panoramio( $data['geo'], $params['location'], $params['panoramiocount']);
  280. }
  281. if($params['logo'] == 1){
  282. $data['logo'] = $this->get_own_info();
  283. }
  284. if($params['weather'] == 1){
  285. $data['weather'] = $this->get_weather($data['geo'], $params['location']);
  286. }
  287. if(!empty($data)){
  288. $template = $this->load_template( $this->plugin_path . '/templates/' . $this->basic_template, $data );
  289. return $template;
  290. }
  291. return false;
  292. }
  293. function get_weather($geo, $location){
  294. $file_name = "weather_" . strtolower(str_replace(" ","-",$location)) . ".log";
  295. $time = 60*60*24;
  296. $data = $this->get_cache_data($file_name, $time);
  297. if(empty($data) && !empty($geo)){
  298. $data = array();
  299. $url = "http://api.openweathermap.org/data/2.5/forecast/daily?lat=" . $geo['lat'] . "&lon=" . $geo['lng'];
  300. $params = json_decode($this->curl_url($url));
  301. $data['weather-desc'] = $params->list[0]->weather[0]->description;
  302. $data['wind-speed'] = $this->ms_to_kmh(intval($params->list[0]->speed)) . " km/h";
  303. $data['humidity'] = $params->list[0]->humidity . "% Humidity";
  304. $data['temperature'] = $this->kelvin_to_celsius(intval($params->list[0]->temp->day)) . "掳C";
  305. $this->write_cache($data, $file_name);
  306. }
  307. return $data;
  308. }
  309. function ms_to_kmh( $ms ){
  310. return $ms*3.6;
  311. }
  312. function get_own_info(){
  313. //Default for all
  314. $data['title'] = __("Home exchange","onehundredcities") . " | Knok";
  315. $data['link'] = __("Home-link","onehundredcities");
  316. $data['img'] = $this->plugin_url . "/assets/logo-knok.png";
  317. return $data;
  318. }
  319. function kelvin_to_celsius( $kelvin ){
  320. return $kelvin - 273.15;
  321. }
  322. function install(){
  323. $data['gmaps'] = 1;
  324. $data['wikipedia'] = 1;
  325. $data['panoramio'] = 1;
  326. $data['articles'] = 1;
  327. $data['articles_feed'] = '';
  328. $data['tags'] = 0;
  329. $data['categories'] = 0;
  330. $data['logo'] = 1;
  331. $data['div'] = 'float';
  332. $data['css'] = 1;
  333. $data['weather'] = 1;
  334. update_option('one-hundred-cities-data', json_encode($data));
  335. }
  336. function load_template( $file, $params ) {
  337. if (is_file($file)) {
  338. ob_start();
  339. extract($params);
  340. include $file;
  341. return ob_get_clean();
  342. }
  343. return false;
  344. }
  345. function curl_url($url){
  346. $data = false;
  347. if(function_exists('curl_init')){
  348. $ch = curl_init($url);
  349. curl_setopt($ch, CURLOPT_HTTPGET, true);
  350. curl_setopt($ch, CURLOPT_POST, false);
  351. curl_setopt($ch, CURLOPT_HEADER, false);
  352. curl_setopt($ch, CURLOPT_NOBODY, false);
  353. curl_setopt($ch, CURLOPT_VERBOSE, false);
  354. curl_setopt($ch, CURLOPT_REFERER, "");
  355. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  356. curl_setopt($ch, CURLOPT_MAXREDIRS, 4);
  357. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  358. curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; he; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8");
  359. $data = curl_exec($ch);
  360. } else {
  361. $data = file_get_contents($url);
  362. }
  363. return $data;
  364. }
  365. function get_wikipedia_info( $lng, $location ) {
  366. $file_name = "wiki_" . strtolower(str_replace(" ","-",$location)) . "_" . $lng . ".log";
  367. $data = $this->get_cache_data($file_name);
  368. if(!$data){
  369. $lng_array = array(
  370. "eng" => "en",
  371. "esp" => "es"
  372. );
  373. $page = json_decode($this->curl_url("http://" . $lng_array[$lng] . ".wikipedia.org/w/api.php?action=query&indexpageids=&prop=revisions&titles=" . urlencode($location) ."&rvprop=content&format=json"));
  374. foreach($page->query->pageids as $result){
  375. $pageid = $result;
  376. break;
  377. }
  378. $object_name = '*';
  379. $wiki_content = $page->query->pages->$pageid->revisions[0]->$object_name; //We call it unestable, but it it is beyond that :-)
  380. //Cleaning wiki content
  381. $results = array();
  382. $searches = array(
  383. '/<ref(.*)?>(.*)?<\/ref>/'
  384. ,'/<small(.*)?>(.*)?<\/small>/'
  385. ,'/<\/?ref\s?(.*)?\s?\/?>/'
  386. ,'/\((.*)\)/'
  387. ,'/{(.*)}/'
  388. ,'/\[(.*)\]/'
  389. ,'/<!--(.*)-->/'
  390. );
  391. $wiki_content = preg_replace($searches, ' ' ,$wiki_content);
  392. preg_match_all('/\|(.*)=(.*)/', $wiki_content, $results, PREG_SET_ORDER);
  393. //Filtering cleaner results
  394. $results_filtered = array();
  395. foreach($results as $result){
  396. if(substr_count($result[0],'|') > 1){
  397. $rs = explode('|',$result[0]);
  398. foreach($rs as $rs_s){
  399. array_push($results_filtered, $rs_s);
  400. }
  401. } else {
  402. array_push($results_filtered, $result[0]);
  403. }
  404. }
  405. //Final string cleaning, it is when we get the data from wikipedia
  406. $searches = array("/=/","/\|/","/\n/","/'''?/","/\s\s+/");
  407. $replacements = array(' = ',' ',' ',' ',' ');
  408. //English wikipedia
  409. $array_names['eng'] = array(
  410. 'area_total_sq_mi =' => 'area'
  411. ,'area_total_km2 = ' => 'area'
  412. ,'population_est =' => 'population'
  413. ,'population_total =' => 'population'
  414. ,'established_date =' => 'settled'
  415. ,'TotalAreaUS =' => 'area'
  416. ,'2000Pop =' => 'population'
  417. ,'area_km2 =' => 'area'
  418. ,'population_estimate =' => 'population'
  419. ,'area km2 =' => 'area'
  420. ,'population =' => 'population'
  421. ,'2010Pop =' => 'population'
  422. );
  423. //Spanish wikipedia
  424. $array_names['esp'] = array(
  425. 'superficie =' => 'area'
  426. ,'poblaci贸n =' => 'population'
  427. );
  428. $data = array();
  429. foreach($results_filtered as $param){
  430. if(strlen($param) < 200 && strpos($param, "=") && $param != ""){
  431. $param = trim(preg_replace($searches, $replacements, $param));
  432. $i = 0;
  433. foreach($array_names[$lng] as $nm => $val){
  434. $pos = strpos($param, $nm);
  435. if($pos !== false){
  436. $param = trim(str_replace($nm, "", substr($param, $pos, strlen($param))));
  437. if(strlen($param) > 2){
  438. switch($val){
  439. case 'area':
  440. if(!isset($area_done)){
  441. $param = '<b>' . __("Area","onehundredcities") . ':</b> ' . $param;
  442. if(($i == 0 || $i == 5) && $lng == 'eng'){
  443. $param .= ' sq mi';
  444. } else {
  445. $param .= ' km2';
  446. }
  447. array_push($data, $param);
  448. $area_done = true;
  449. }
  450. break;
  451. case 'population':
  452. if(!isset($population_done)){
  453. $param = '<b>' . __("Population","onehundredcities") . ':</b> ' . $param;
  454. array_push($data, $param);
  455. $population_done = true;
  456. }
  457. break;
  458. case 'settled':
  459. if(!isset($settled_done)){
  460. $param = '<b>' . __("Settled","onehundredcities") . ':</b> ' . $param;
  461. array_push($data, $param);
  462. $settled_done = true;
  463. }
  464. break;
  465. }
  466. }
  467. }
  468. $i++;
  469. }
  470. }
  471. }
  472. $new_page = $this->curl_url("http://" . $lng_array[$lng] . ".wikipedia.org/w/api.php?action=opensearch&search=" . urlencode($location) ."&format=xml&limit=1");
  473. $xml = simplexml_load_string($new_page);
  474. $description = (string) preg_replace('/\([^)]*\)/s', '', $xml->Section->Item->Description);
  475. $description = preg_replace('/\s\s+/s', ' ', $description);
  476. $new_data = array(
  477. 'title' => (string) $xml->Section->Item->Text,
  478. 'description' => $description,
  479. 'url' => (string) $xml->Section->Item->Url,
  480. 'extra' => $data
  481. );
  482. if((string)$xml->Section->Item->Description) {
  483. $this->write_cache($new_data, $file_name);
  484. return $new_data;
  485. } else {
  486. return "";
  487. }
  488. } else {
  489. return $data;
  490. }
  491. }
  492. } // End of Class
  493. }
  494. function wp_cityinfo($location, $lng = 'eng'){
  495. if(class_exists("OneHundredCities") && !$OneHundredCities){
  496. $OneHundredCities = new OneHundredCities();
  497. }
  498. $data['location'] = $location;
  499. $data['lang'] = $lng;
  500. echo $OneHundredCities->insert_cities_template( $data );
  501. }
  502. add_action( 'init', 'init_one_hundred_cities');
  503. function init_one_hundred_cities(){
  504. if(class_exists("OneHundredCities") && !isset($OneHundredCities)){
  505. $OneHundredCities = new OneHundredCities();
  506. }
  507. }
  508. //Include Widget Class
  509. include('100Cities-widget.php');
  510. add_action('widgets_init', 'register_cities_widget');
  511. function register_cities_widget() {
  512. register_widget('OneHundredCitiesWidget');
  513. }
  514. register_activation_hook( __FILE__, array('OneHundredCities', 'install'));
  515. //End of file