PluginProbe
Flexmls® IDX Plugin / 2.3
Flexmls® IDX Plugin v2.3
4.0.1 4.0.0 3.18.2 trunk 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.9.6 2.0 2.1 2.2 2.3 2.3.1 2.3.2 2.3.3 2.4 2.4.1 2.4.2 3.0.0 3.0.1 3.0.10 3.0.11 All 157 releases
flexmls-idx / lib / flexmls-api-wp.php

flexmls-api-wp.php in Flexmls® IDX Plugin 2.3, at lib/flexmls-api-wp.php

551 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class flexmlsApiWP {
4
5 private $is_ready = false;
6 private $api_base = "api.flexmls.com"; // no trailing slash
7 private $location_search_url = "http://www.flexmls.com"; // http://www.flexmls.com
8 public $last_error_code = null;
9 public $last_error_mess = null;
10 public $last_count = 0;
11 public $last_count_pages = 0;
12 public $api_roles = null;
13 private $last_token = null;
14 private $last_token_expire = null;
15 private $send_debug = false;
16 private $jsObj;
17
18
19 function __construct() {
20 global $fmc_plugin_dir;
21
22 $api_ini_file = $fmc_plugin_dir . '/lib/api.ini';
23
24 if (file_exists($api_ini_file)) {
25 $local_settings = parse_ini_file($api_ini_file);
26 if (array_key_exists('api_base', $local_settings)) {
27 $this->api_base = trim($local_settings['api_base']);
28 }
29 if (array_key_exists('location_search_url', $local_settings)) {
30 $this->location_search_url = trim($local_settings['location_search_url']);
31 }
32 }
33
34 $options = get_option('fmc_settings');
35
36 if ( !empty($options['api_key']) && !empty($options['api_secret']) ) {
37 $this->is_ready = true;
38 }
39
40 // don't do any API calls for Mozilla's prefetch page function
41 if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') {
42 $this->is_ready = false;
43 }
44
45 $this->jsObj = new Moxiecode_JSON();
46
47 }
48
49
50 function __destruct() { }
51
52
53 function HasBasicRole() {
54 $api_settings = get_transient('fmc_api');
55
56 if ( is_array($api_settings['Roles']) ) {
57 if ( in_array('basic', $api_settings['Roles']) ) {
58 return true;
59 }
60 else {
61 return false;
62 }
63 }
64 else {
65 return false;
66 }
67
68 }
69
70 function GetTransformedIDXLink($link, $args = array()) {
71
72 $result = $this->MakeAPIRequest("GET", "/v1/redirect/idxlink/{$link}", $args, $data = array(), $auth = false, $cache_time = 2880);
73
74 if ($result === false) {
75 return false;
76 }
77
78 return $result[0]['Uri'];
79
80 }
81
82
83 function StandardFields() {
84 $result = $this->MakeAPIRequest("GET", "/v1/standardfields", array(), array(), $auth = false, $cache_time = 2880);
85 return $result;
86 }
87
88 function GetLocationSearchApiUrl() {
89 return $this->location_search_url;
90 }
91
92
93 function MarketStats($type, $options = "", $property_type = "", $location_name = "", $location_value = "") {
94
95 $args = array();
96
97 if (!empty($options)) {
98 $args['Options'] = $options;
99 }
100
101 if (!empty($property_type)) {
102 $args['PropertyTypeCode'] = $property_type;
103 }
104
105 if (!empty($location_name)) {
106 $args['LocationField'] = $location_name;
107 $args['LocationValue'] = $location_value;
108 }
109
110 $result = $this->MakeAPIRequest("GET", "/v1/marketstatistics/{$type}", $args, $data = array(), $auth = false, $cache_time = 2880);
111
112 if ($result === false) {
113 return false;
114 }
115
116 return $result[0];
117
118 }
119
120
121 function Authenticate($force = false) {
122 global $fmc_token;
123
124 if ($fmc_token == null || $force == true) {
125 $result = $this->MakeAPIRequest("POST", "/v1/session", $args, $data = array(), $auth = true, $cache_time = 0, $force);
126
127 if ($result === false) {
128 return false;
129 }
130
131 $this->last_token = $result[0]['AuthToken'];
132 $this->last_token_expire = $result[0]['Expires'];
133 set_transient('fmc_api', $result[0], 60*60*24*7);
134
135 }
136 }
137
138
139 function SendContact($contact_data) {
140 $args = array();
141
142 $data = array(
143 'Contacts' => array($contact_data),
144 'Notify' => flexmlsConnect::send_notification()
145 );
146
147 $result = $this->MakeAPIRequest("POST", "/v1/contacts", $args, $data, $auth = false);
148
149 if ($result === false) {
150 return false;
151 }
152
153 return $result;
154 }
155
156
157 function ConnectPrefs() {
158
159 $args = array();
160
161 $result = $this->MakeAPIRequest("GET", "/v1/connect/prefs", $args, $data = array(), $auth = false, $cache_time = 300);
162
163 if ($result === false) {
164 return false;
165 }
166
167 $records = array();
168 foreach ($result as $pref) {
169 $records[$pref['Name']] = $pref['Value'];
170 }
171 return $records;
172
173 }
174
175
176 function PropertyTypes() {
177
178 $args = array();
179
180 $result = $this->MakeAPIRequest("GET", "/v1/propertytypes", $args, $data = array(), $auth = false, $cache_time = 900);
181
182 if ($result === false) {
183 return false;
184 }
185
186 $records = array();
187 foreach ($result as $res) {
188 $records[$res['MlsCode']] = $res['MlsName'];
189 }
190
191 return $records;
192
193 }
194
195
196 function Listings($args = array()) {
197
198 $result = $this->MakeAPIRequest("GET", "/v1/listings", $args, $data = array(), $auth = false, $cache_time = 10);
199
200 if ($result === false) {
201 return false;
202 }
203
204 return $result;
205
206 }
207
208
209 function ListingPhotos($id) {
210
211 $args = array();
212
213 $result = $this->MakeAPIRequest("GET", "/v1/listings/".$id."/photos", $args, $data = array(), $auth = false, $cache_time = 10);
214
215 if ($result === false) {
216 return false;
217 }
218
219 return $result;
220
221 }
222
223
224 function MyListings($args = array()) {
225
226 $result = $this->MakeAPIRequest("GET", "/v1/my/listings", $args, $data = array(), $auth = false, $cache_time = 10);
227
228 if ($result === false) {
229 return false;
230 }
231
232 return $result;
233
234 }
235
236 function OfficeListings($args = array()) {
237
238 $result = $this->MakeAPIRequest("GET", "/v1/office/listings", $args, $data = array(), $auth = false, $cache_time = 10);
239
240 if ($result === false) {
241 return false;
242 }
243
244 return $result;
245
246 }
247
248 function CompanyListings($args = array()) {
249
250 $result = $this->MakeAPIRequest("GET", "/v1/company/listings", $args, $data = array(), $auth = false, $cache_time = 10);
251
252 if ($result === false) {
253 return false;
254 }
255
256 return $result;
257
258 }
259
260
261 function GetIDXLinks($tags = "") {
262
263 $args = array();
264
265 $tags = trim($tags);
266 if ( !empty($tags) ) {
267 $args['tags'] = $this->clean_comma_list($tags);
268 }
269
270 $result = $this->MakeAPIRequest("GET", "/v1/idxlinks", $args, $data = array(), $auth = false, $cache_time = 1200);
271
272 if ($result === false) {
273 return false;
274 }
275
276 return $result;
277
278 }
279
280
281 function SystemInfo() {
282
283 $args = array();
284
285 $result = $this->MakeAPIRequest("GET", "/v1/system", $args, $data = array(), $auth = false, $cache_time = 600);
286
287 if ($result === false) {
288 return false;
289 }
290
291 if (!array_key_exists('MlsId', $result[0])) {
292 $result[0]['Mls'] = $result[0]['Name'];
293 $result[0]['MlsId'] = $result[0]['Id'];
294 }
295
296 return $result[0];
297
298 }
299
300
301 /*
302 * Makes the API call to the flexmls API.
303 *
304 * @param string $method HTTP method to use when making the call. GET, POST, etc.
305 * @param string $uri HTTP request URI to hit with the request
306 * @param array $args array of key/value pairs of parameters. added to request depending on HTTP method
307 * @param array $caching array of caching settings. 'enabled' is true/false. 'minutes' defines how long if enabled
308 * @return mixed Returns array of parsed JSON results if successful. Returns false if API call fails
309 */
310 function MakeAPIRequest($method, $uri, $args = array(), $data = array(), $is_auth_request = false, $cache_time = 0, $a_retry = false) {
311 global $fmc_token;
312 global $fmc_instance_cache;
313 global $fmc_version;
314
315 if (!is_array($args)) {
316 $args = array();
317 }
318
319 $http_parameters = $args;
320
321 if ($this->is_ready == false) {
322 return;
323 }
324
325 // used to track where we received the data from
326 $data_source = null;
327
328 // retrieve all saved items
329 $options = get_option('fmc_settings');
330
331 // start with the basic part of the security string and add to it as we go
332 $sec_string = "{$options['api_secret']}ApiKey{$options['api_key']}";
333
334 $post_data = "";
335
336 if ($method == "POST" && count($data) > 0) {
337 // the request is to post some JSON data back to the API (like adding a contact)
338 $post_body = $this->json_encode( array('D' => $data ) );
339 }
340
341 if ($is_auth_request) {
342 $http_parameters['ApiKey'] = $options['api_key'];
343 }
344 else {
345 $http_parameters['AuthToken'] = $this->last_token;
346
347 // since this isn't an authentication request, add the ServicePath to the security string
348 $sec_string .= "ServicePath{$uri}";
349
350 ksort($http_parameters);
351
352 // add each of the HTTP query string parameters to the security string
353 foreach ($http_parameters as $k => $v) {
354 $sec_string .= $k . $v;
355 }
356 }
357
358 // add the JSON data to the end of the security string if it exists
359 $sec_string .= $post_body;
360
361 // calculate the security string as ApiSig
362 $api_sig = md5($sec_string);
363
364 $http_parameters['ApiSig'] = $api_sig;
365
366 // build the HTTP request essentials the way WordPress wants them
367 $http_args = array();
368 $http_args['method'] = strtoupper($method);
369 $http_args['timeout'] = 20;
370 $http_args['sslverify'] = false;
371 $http_args['headers']['User-Agent'] = "flexmls API WP PHP Client/1.0";
372 $http_args['headers']['X-flexmlsApi-User-Agent'] = "flexmls WordPress Plugin/{$fmc_version}";
373
374 if ($is_auth_request == true) {
375 $http_proto = "https://";
376 }
377 else {
378 $http_proto = "http://";
379 }
380
381 // start putting the URL parts together
382 $full_url = $http_proto . $this->api_base . $uri;
383 $cache_url = $http_proto . $this->api_base . $uri;
384
385 // take the parameter key/values and put them into a URL-like structure. key=value&key2=value2& etc.
386 $query_string = http_build_query($http_parameters);
387 // build a query string that we can cache against, since $http_parameters includes the ApiSig and AuthToken that we don't want
388 $cache_string = http_build_query($args);
389
390 if (!empty($query_string)) {
391 $full_url .= '?' . $query_string;
392 $cache_url .= '?' . $cache_string;
393 }
394
395 if ($method == "POST") {
396 // put the built parameter key/values as the body of the POST request
397 $http_args['body'] = $post_body;
398 $http_args['headers']['Content-Type'] = "application/json";
399 }
400
401 $cache_item_name = md5($cache_url);
402
403 // innocent until proven guilty
404 $served_from_cache = null;
405
406 // check if we should retrieve from cache
407 if ($method == "GET" && $cache_time > 0 && $a_retry == false) {
408 // retrieve the cache data for this particular request
409 $cache = get_transient('fmc_cache_'. $cache_item_name);
410
411 // check if the item's expire time has passed already
412 if ($cache !== false) {
413 // item exists and it hasn't expired yet, so we'll serve the request from cache
414 $served_from_cache = $cache;
415 }
416
417 }
418 elseif ($method == "GET" && $a_retry == false) {
419 if (!empty($fmc_instance_cache[ $cache_item_name ])) {
420 $served_from_cache = $fmc_instance_cache[ $cache_item_name ]['data'];
421 }
422 }
423
424 // since we didn't get any unexpired data from the cache, make the call
425 if ($served_from_cache == null) {
426 $return = wp_remote_request($full_url, $http_args);
427 $data_source = "live";
428 }
429 else {
430 // act like the API returned data when it was really the cache
431 $return = $served_from_cache;
432 $data_source = "cache";
433 }
434
435 if ( is_wp_error($return) ) {
436 $this->send_debug = true;
437 $this->last_error_code = "WP1";
438 $this->last_error_mess = "WordPress error";
439 return false;
440 }
441
442 // start handling the response
443
444 $json = $this->jsObj->decode($return['body']);
445
446 $this->last_error_code = $json['D']['Code'];
447 $this->last_error_mess = $json['D']['Message'];
448
449 if ( array_key_exists('Pagination', $json['D']) ) {
450 $this->last_count = $json['D']['Pagination']['TotalRows'];
451 $this->last_count_pages = $json['D']['Pagination']['TotalPages'];
452 }
453
454 if ( $json['D']['Success'] == true) {
455
456 // check a couple of conditions to see if we should update the cache
457 if ($cache_time > 0 && $data_source == "live" && $method == "GET" && !empty($return)) {
458
459 // update transient item which tracks cache items
460 $cache_tracker = get_transient('fmc_cache_tracker');
461 $cache_tracker[ $cache_item_name ] = true;
462 set_transient('fmc_cache_tracker', $cache_tracker, 60*60*24*7);
463
464 $cache_expire_length = $cache_time*60;
465 $return = $this->utf8_encode_mix($return);
466 $cache_set_result = set_transient('fmc_cache_'. $cache_item_name, $return, $cache_expire_length);
467 }
468 elseif ($data_source == "live" && $method == "GET" && !empty($return)) {
469 $fmc_instance_cache[ $cache_item_name ]['data'] = $return;
470 }
471
472 return $json['D']['Results'];
473
474 }
475 elseif ($a_retry == false && $is_auth_request == false && ($this->last_error_code == 1020 || $this->last_error_code == 1000) ) {
476 $this->Authenticate(true);
477 $return = $this->MakeAPIRequest($method, $uri, $args, $data, $is_auth_request, $cache_time, $a_retry = true);
478 return $return;
479 }
480 else {
481
482 if ($this->last_error_code == "") {
483 $this->last_error_code = "API Down";
484 $this->last_error_mess = "The flexmls IDX API didn't respond as expected.";
485 }
486
487 return false;
488 }
489
490 }
491
492
493 /*
494 * Take a value and clean it so it can be used as a parameter value in what's sent to the API.
495 *
496 * @param string $var Regular string of text to be cleaned
497 * @return string Cleaned string
498 */
499 function clean_comma_list($var) {
500
501 $return = "";
502
503 if ( strpos($var, ',') !== false ) {
504 // $var contains a comma so break it apart into a list...
505 $list = explode(",", $var);
506 // trim the extra spaces and weird characters from the beginning and end of each item in the list...
507 $list = array_map('trim', $list);
508 // and put it back together as a comma-separated string to be returned
509 $return = implode(",", $list);
510 }
511 else {
512 // trim the extra spaces and weird characters from the beginning and end of the string to be returned
513 $return = trim($var);
514 }
515
516 return $return;
517
518 }
519
520 // source: http://www.php.net/manual/en/function.utf8-encode.php#83777
521 function utf8_encode_mix($input, $encode_keys = false) {
522
523 if(is_array($input)) {
524 $result = array();
525 foreach($input as $k => $v) {
526 $key = ($encode_keys)? utf8_encode($k) : $k;
527 $result[$key] = $this->utf8_encode_mix( $v, $encode_keys);
528 }
529 }
530 elseif (is_object($input)) {
531 return $input;
532 }
533 else {
534 $result = utf8_encode($input);
535 }
536
537 return $result;
538
539 }
540
541 function json_encode($obj) {
542 $return = $this->jsObj->encode( $obj );
543
544 // Moxiecode's JSON encoder escapes single quotes when it shouldn't, so unescape those
545 $return = str_replace("\'", "'", $return);
546 return $return;
547 }
548
549
550 }
551