PageRenderTime 91ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/API.php

https://bitbucket.org/lewisdorigo/firefish
PHP | 313 lines | 237 code | 75 blank | 1 comment | 40 complexity | be574c301e9b9f5c429114564469812f MD5 | raw file
  1. <?php namespace Dorigo\FireFish;
  2. class API {
  3. private static $instance;
  4. private $path = 'rss/adverts/all.aspx';
  5. private $settings;
  6. private $postType;
  7. private $directory = 'drgo_firefish';
  8. private $cacheExpiry = 3600;
  9. private $cachePath;
  10. private $url;
  11. private $curl;
  12. public static function Init() {
  13. if(is_null(self::$instance)) {
  14. self::$instance = new self();
  15. }
  16. return self::$instance;
  17. }
  18. private function __construct() {
  19. $this->settings = Settings::Init();
  20. $this->postType = PostType::Init()->getPostType();
  21. $this->url = $this->settings->getOption('site_url');
  22. if(!$this->cachePath) {
  23. $uploads = wp_upload_dir();
  24. $cache = [
  25. $uploads['basedir'],
  26. $this->directory
  27. ];
  28. $this->cachePath = implode(DIRECTORY_SEPARATOR, [$uploads['basedir'], $this->directory]);
  29. }
  30. if(!file_exists($this->cachePath) || !is_dir($this->cachePath)) {
  31. mkdir($this->cachePath);
  32. }
  33. }
  34. public function getListings() {
  35. $listing = $this->request();
  36. if(!$listing || !isset($listing->channel) || !isset($listing->channel->item)) { return false; }
  37. $ids = [];
  38. $taxonomies = [
  39. 'job_type' => [],
  40. 'disipline' => [],
  41. 'role' => [],
  42. 'location_area' => [],
  43. 'location' => [],
  44. 'remuneration' => []
  45. ];
  46. global $wpdb;
  47. $query = "SELECT ID FROM {$wpdb->posts} INNER JOIN {$wpdb->postmeta} on {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID WHERE meta_key='_drgo_firefish_reference_number' AND meta_value = '%s'";
  48. foreach($listing->channel->item as $item) {
  49. $advert = $item->children('ffAdvert', true);
  50. $reference = (string) $advert->ReferenceNumber;
  51. $ids[] = $reference;
  52. $jobs = $wpdb->get_results(sprintf($query, $reference), OBJECT);
  53. $content = html_entity_decode((string) $item->description);
  54. $content = strip_tags($content, "<p><a><h1><h2><h3><h4><h5><h6><strong><em><br><b><i><ol><ul><li><dl><dd><dt>");
  55. if(empty($jobs)) {
  56. $date = strtotime((string) $item->pubDate);
  57. $title = (string) $advert->Title;
  58. $post_id = wp_insert_post([
  59. 'post_title' => $title,
  60. 'post_name' => sanitize_title("{$title} {$reference}"),
  61. 'post_type' => $this->postType,
  62. 'post_status' => 'publish',
  63. 'post_content' => $content,
  64. 'post_date' => date('Y-m-d H:i:s', $date)
  65. ]);
  66. if(is_wp_error($post_id)) {
  67. wp_die('An error occurred');
  68. }
  69. } else {
  70. $post_id = $jobs[0]->ID;
  71. }
  72. $taxonomies['job_type'][$post_id] = (string) $advert->JobType ?: false;
  73. $taxonomies['discipline'][$post_id] = (string) $advert->Discipline ?: false;
  74. $taxonomies['role'][$post_id] = (string) $advert->Role ?: false;
  75. $taxonomies['location_area'][$post_id] = (string) $advert->LocationArea ?: false;
  76. $taxonomies['location'][$post_id] = (string) $advert->Location ?: false;
  77. //$taxonomies['remuneration'][$post_id] = (string) $advert->Remuneration ?: false;
  78. $closing = strtotime((string) $advert->ClosingDate);
  79. update_post_meta($post_id, '_drgo_firefish_reference_number', $reference ?: false);
  80. update_post_meta($post_id, '_drgo_firefish_company_reference', (string) $advert->CompanyReferenceNumber ?: false);
  81. update_post_meta($post_id, '_drgo_firefish_link', (string) $item->link ?: false);
  82. update_post_meta($post_id, '_drgo_firefish_closing_date', date('Y-m-d H:i:s', $closing));
  83. update_post_meta($post_id, '_drgo_firefish_remuneration', (string) $advert->Remuneration);
  84. $oldContentHash = get_post_meta($post_id, '_drgo_firefish_content_hash', true);
  85. $oldTitleHash = get_post_meta($post_id, '_drgo_firefish_title_hash', true);
  86. $contentHash = md5((string) $content);
  87. $titleHash = md5((string) $advert->Title);
  88. $updatePost = [];
  89. if($titleHash !== $oldTitleHash) {
  90. $updatePost['post_title'] = (string) $advert->Title;
  91. update_post_meta($post_id, '_drgo_firefish_title_hash', $titleHash);
  92. }
  93. if($contentHash !== $oldContentHash) {
  94. $updatePost['post_content'] = $content;
  95. update_post_meta($post_id, '_drgo_firefish_content_hash', $contentHash);
  96. }
  97. if(!empty($updatePost)) {
  98. wp_update_post(array_merge(['ID' => $post_id], $updatePost));
  99. }
  100. $location = (string) $advert->Location ?: (string) $advert->LocationArea;
  101. if($location) {
  102. $this->getLatLng($post_id, $location);
  103. }
  104. }
  105. array_unique($ids);
  106. foreach($taxonomies as $name => $posts) {
  107. $taxonomy = "{$this->postType}_{$name}";
  108. foreach($posts as $post_id => $term) {
  109. update_post_meta($post_id, "_drgo_firefish_{$name}", $term);
  110. if(!$term) { continue; }
  111. $term_id = term_exists(sanitize_title($term), $taxonomy);
  112. if(!$term_id || $term_id === 0) {
  113. $term_id = wp_insert_term($term, $taxonomy, [
  114. 'slug' => sanitize_title($term)
  115. ]);
  116. if(is_wp_error($term_id)) {
  117. continue;
  118. }
  119. }
  120. $term_id = is_array($term_id) ? $term_id['term_id'] : $term_id;
  121. wp_set_object_terms($post_id, (int) $term_id, $taxonomy);
  122. }
  123. }
  124. $old_jobs = get_posts([
  125. 'post_type' => $this->postType,
  126. 'posts_per_page' => 1,
  127. 'post_status' => 'publish',
  128. 'meta_query' => [
  129. 'relation' => 'OR',
  130. [
  131. 'key' => '_drgo_firefish_reference_number',
  132. 'value' => $ids,
  133. 'compare' => 'NOT IN'
  134. ],
  135. [
  136. 'key' => '_drgo_firefish_reference_number',
  137. 'value' => '',
  138. 'compare' => 'NOT EXISTS'
  139. ]
  140. ]
  141. ]);
  142. foreach($old_jobs as $old_job) {
  143. wp_delete_post($old_job->ID);
  144. }
  145. return true;
  146. }
  147. private function getLatLng($post_id, $location = null) {
  148. if(!$post_id || !$location) { return false; }
  149. $apiKey = apply_filters('Dorigo\FireFish\GoogleAPI', '');
  150. if(!$apiKey) { return false; }
  151. $data = [
  152. 'address' => $location,
  153. 'region' => apply_filters('Dorigo\FireFish\GoogleRegion', 'uk'),
  154. 'key' => $apiKey
  155. ];
  156. $location = $this->request('maps/api/geocode/json', $data, $method="get", -1, 'https://maps.googleapis.com', 'json');
  157. if($location && isset($location->results) && !empty($location->results)) {
  158. $results = $location->results[0];
  159. update_post_meta($post_id, "_drgo_firefish_lat_lng", (array) $results->geometry->location);
  160. }
  161. }
  162. private function request($path = null, $data = [], $method = 'get', $cache = false, $url = null, $format = 'xml') {
  163. $path = $path ?: $this->path;
  164. $url = $url ?: $this->url;
  165. if(!$url || !$path) { return false; }
  166. $filename = $this->getFileName($path, $url, $data, $method);
  167. if($cache !== false && $cache !== null && $this->isInCache($filename, $cache)) {
  168. return $this->getFromCache($filename, $format);
  169. }
  170. $url = rtrim($url, '/').'/'.ltrim($path, '/');
  171. $this->curl = curl_init();
  172. switch($method) {
  173. case 'get':
  174. $url = $url.'?'.http_build_query($data);
  175. break;
  176. case 'post':
  177. curl_setopt($this->curl, CURLOPT_POST, true);
  178. curl_setopt($this->curl, CURLOPT_POSTFIELDS, $data);
  179. break;
  180. }
  181. curl_setopt($this->curl, CURLOPT_URL, $url);
  182. curl_setopt($this->curl, CURLINFO_HEADER_OUT, false);
  183. curl_setopt($this->curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
  184. curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
  185. curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true);
  186. curl_setopt($this->curl, CURLOPT_HEADER, false);
  187. $response = curl_exec($this->curl);
  188. if($cache) {
  189. file_put_contents($this->cachePath.DIRECTORY_SEPARATOR.$filename, $response);
  190. }
  191. if($response) {
  192. switch($format) {
  193. case 'xml':
  194. return new \SimpleXMLElement($response);
  195. break;
  196. case 'json':
  197. return json_decode($response);
  198. break;
  199. default:
  200. return $response;
  201. break;
  202. }
  203. } else {
  204. return false;
  205. }
  206. }
  207. protected function getFromCache($filename, $format = 'xml') {
  208. $filepath = $this->cachePath.DIRECTORY_SEPARATOR.$filename;
  209. if(file_exists($filepath)) {
  210. $contents = file_get_contents($filepath);
  211. switch($format) {
  212. case 'xml':
  213. return new \SimpleXMLElement($contents);
  214. break;
  215. case 'json':
  216. return json_decode($contents);
  217. break;
  218. default:
  219. return $contents;
  220. break;
  221. }
  222. } else {
  223. return [];
  224. }
  225. }
  226. protected function isInCache($filename, $expiry = null) {
  227. $filepath = $this->cachePath.DIRECTORY_SEPARATOR.$filename;
  228. if(!$expiry === null || $expiry === true || $expiry === false) {
  229. $expiry = $this->cacheExpiry;
  230. } else if($expiry < 0) {
  231. $expiry = PHP_INT_MAX;
  232. }
  233. return file_exists($filepath) && filemtime($filepath) > time() - $expiry;
  234. }
  235. protected function getFileName($path, $url, $data = [], $method = "get") {
  236. return md5($url.$path.json_encode($data).$method).".json";
  237. }
  238. }