PluginProbe
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings / 7.2.1
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings v7.2.1
7.2.1 7.2 7.1.2 7.1.1 7.1 7.0.4 7.0.6 7.0.7 6.3.8 6.3.7 6.3.6 6.3.5 6.3.4 6.3.3 6.3.1 trunk 5.7.3 5.7.5 5.8.1 5.8.2 5.8.3 5.8.4 5.8.6 6.0.4 6.0.5 All 36 releases
mlsimport / enviroment / ProviderResoClasses.php

ProviderResoClasses.php in MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings 7.2.1, at enviroment/ProviderResoClasses.php

264 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Provider Family adapters that did not previously have WordPress classes.
4 *
5 * Each class is intentionally separate even where the first implementation is
6 * small. Provider credentials and request behavior are added to the matching
7 * class, so a later difference never becomes another provider-name switch in a
8 * caller. Existing Bridge, Spark, Trestle, MLS Grid, and Bright classes remain
9 * in their original files.
10 *
11 * @package MLSImport
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 /** Provider adapter for Regional Multiple Listing Service (RMLS). */
19 class RmlsResoClass extends ResoBase {
20 /** @var string Stable provider type. */
21 protected $provider_type = 'rmls';
22
23 /** @var bool RMLS sends its saved bearer token unchanged. */
24 protected $direct_uses_stored_token = true;
25
26 /** Format RMLS sync times as full OData DateTimeOffset literals. */
27 protected function format_stored_timestamp( $value ) {
28 return $this->format_utc_timestamp( $value, true, true );
29 }
30
31 /** Return RMLS's required default and maximum page size. */
32 protected function direct_query_rules() {
33 return array(
34 'default_limit' => 25,
35 'max_limit' => 25,
36 );
37 }
38 }
39
40 /** Provider adapter for Utah Real Estate. */
41 class UtahRealEstateResoClass extends ResoBase {
42 /** @var string Stable provider type. */
43 protected $provider_type = 'utah_real_estate';
44
45 /** @var bool Utah Real Estate sends its saved bearer token unchanged. */
46 protected $direct_uses_stored_token = true;
47 }
48
49 /** Provider adapter for Realcomp. */
50 class RealcompResoClass extends ResoBase {
51 /** @var string Stable provider type. */
52 protected $provider_type = 'realcomp';
53
54 /** @var string[] Realcomp currently uses the saved Trestle credential slots. */
55 protected $provider_credential_fields = array(
56 'mlsimport_tresle_client_id',
57 'mlsimport_tresle_client_secret',
58 );
59
60 /** Format Realcomp sync times with required seconds and UTC suffix. */
61 protected function format_stored_timestamp( $value ) {
62 return $this->format_utc_timestamp( $value, false, true );
63 }
64
65 /** Return Realcomp's required default page size. */
66 protected function direct_query_rules() {
67 return array( 'default_limit' => 25 );
68 }
69
70 /** Build Realcomp's JSON token request. */
71 protected function direct_token_request( array $saved_options, array $config ) {
72 return array(
73 'url' => 'https://auth.realcomp.com/Token',
74 'body' => array(
75 'client_id' => trim( (string) $saved_options['mlsimport_tresle_client_id'] ),
76 'client_secret' => trim( (string) $saved_options['mlsimport_tresle_client_secret'] ),
77 'audience' => 'rcapi.realcomp.com',
78 ),
79 'json' => true,
80 );
81 }
82 }
83
84 /** Provider adapter for Realtor.ca / CREA DDF. */
85 class RealtorCaResoClass extends ResoBase {
86 /** @var string Stable provider type. */
87 protected $provider_type = 'realtorca';
88
89 /** @var string[] CREA DDF client credentials. */
90 protected $provider_credential_fields = array(
91 'mlsimport_realtorca_client_id',
92 'mlsimport_realtorca_client_secret',
93 );
94
95 /** Format CREA DDF sync times as full UTC DateTimeOffset literals. */
96 protected function format_stored_timestamp( $value ) {
97 return $this->format_utc_timestamp( $value, true, true );
98 }
99
100 /** Remove PropertyType because CREA DDF does not expose that task filter. */
101 public function prepare_import_task_fields( array $fields ) {
102 unset( $fields['PropertyType'] );
103 return $fields;
104 }
105
106 /** Build CREA DDF's client-credentials token request. */
107 protected function direct_token_request( array $saved_options, array $config ) {
108 return array(
109 'url' => 'https://identity.crea.ca/connect/token',
110 'body' => array(
111 'client_id' => trim( (string) $saved_options['mlsimport_realtorca_client_id'] ),
112 'client_secret' => trim( (string) $saved_options['mlsimport_realtorca_client_secret'] ),
113 'grant_type' => 'client_credentials',
114 'scope' => 'DDFApi_Read',
115 ),
116 'json' => false,
117 );
118 }
119 }
120
121 /** Provider adapter for Rapattoni. */
122 class RapattoniResoClass extends ResoBase {
123 /** @var string Stable provider type. */
124 protected $provider_type = 'rapattoni';
125
126 /** @var string[] Rapattoni password-grant credentials. */
127 protected $provider_credential_fields = array(
128 'mlsimport_rapattoni_client_id',
129 'mlsimport_rapattoni_client_secret',
130 'mlsimport_rapattoni_username',
131 'mlsimport_rapattoni_password',
132 );
133
134 /** Make PropertyType single-select because Rapattoni requires one Class. */
135 public function prepare_import_task_fields( array $fields ) {
136 if ( isset( $fields['PropertyType'] ) ) {
137 $fields['PropertyType']['multiple'] = 'no';
138 }
139 return $fields;
140 }
141
142 /**
143 * Require and normalize Rapattoni's single PropertyType request value.
144 *
145 * @param array $arguments Shared Stored-mode request arguments.
146 * @param string $last_date Last Successful Sync Time, or empty.
147 * @return array{success:bool,arguments:array,error:?array}
148 */
149 public function prepare_stored_request( array $arguments, $last_date = '' ) {
150 // The existing UI can supply either a scalar or a one-item selection array.
151 $property_type = isset( $arguments['property_type'] )
152 ? $arguments['property_type']
153 : '';
154 if ( is_array( $property_type ) ) {
155 $property_type = isset( $property_type[0] ) ? $property_type[0] : '';
156 }
157 $property_type = trim( (string) $property_type );
158
159 // Stop before the SaaS call when Rapattoni's required class is absent.
160 if ( '' === $property_type ) {
161 return array(
162 'success' => false,
163 'arguments' => $arguments,
164 'error' => array(
165 'code' => 'missing_property_type',
166 'message' => 'This MLS requires one Property Action Category.',
167 ),
168 );
169 }
170
171 // Rapattoni expects one value with spaces removed inside a one-item list.
172 $arguments['property_type'] = array( str_replace( ' ', '', $property_type ) );
173 return parent::prepare_stored_request( $arguments, $last_date );
174 }
175
176 /** Normalize Rapattoni's PropertyPictures collection to standard Media. */
177 public function read_direct_response( $status_code, $body ) {
178 $outcome = parent::read_direct_response( $status_code, $body );
179 if ( empty( $outcome['success'] ) ) {
180 return $outcome;
181 }
182
183 foreach ( $outcome['records'] as $index => $record ) {
184 if ( is_array( $record ) && empty( $record['Media'] ) && ! empty( $record['PropertyPictures'] ) ) {
185 $outcome['records'][ $index ]['Media'] = $record['PropertyPictures'];
186 }
187 }
188 return $outcome;
189 }
190
191 /** Return Rapattoni's Class parameter and numeric listing-key ordering rules. */
192 protected function direct_query_rules() {
193 return array(
194 'skip_listing_type_filter' => true,
195 'class_parameter' => true,
196 'default_orderby' => 'ListingKeyNumeric',
197 );
198 }
199
200 /** Build Rapattoni's password-grant token request from its MLS token URL. */
201 protected function direct_token_request( array $saved_options, array $config ) {
202 $token_url = isset( $config['api_token_url'] ) ? trim( (string) $config['api_token_url'] ) : '';
203 if ( '' === $token_url ) {
204 return null;
205 }
206
207 return array(
208 'url' => $token_url,
209 'body' => array(
210 'client_id' => trim( (string) $saved_options['mlsimport_rapattoni_client_id'] ),
211 'client_secret' => trim( (string) $saved_options['mlsimport_rapattoni_client_secret'] ),
212 'username' => trim( (string) $saved_options['mlsimport_rapattoni_username'] ),
213 'password' => trim( (string) $saved_options['mlsimport_rapattoni_password'] ),
214 'grant_type' => 'password',
215 ),
216 'json' => false,
217 );
218 }
219 }
220
221 /** Provider adapter for Paragon. */
222 class ParagonResoClass extends ResoBase {
223 /** @var string Stable provider type. */
224 protected $provider_type = 'paragon';
225
226 /** @var bool Paragon Direct MLS access is not currently implemented. */
227 protected $direct_access_supported = false;
228
229 /** @var string[] Paragon client credentials used by Stored mode. */
230 protected $provider_credential_fields = array(
231 'mlsimport_paragon_client_id',
232 'mlsimport_paragon_client_secret',
233 );
234 }
235
236 /** Provider adapter for ConnectMLS. */
237 class ConnectMlsResoClass extends ResoBase {
238 /** @var string Stable provider type. */
239 protected $provider_type = 'connectmls';
240
241 /** @var bool ConnectMLS Direct MLS access is not currently implemented. */
242 protected $direct_access_supported = false;
243
244 /** @var string[] ConnectMLS account credentials. */
245 protected $provider_credential_fields = array(
246 'mlsimport_connectmls_username',
247 'mlsimport_connectmls_password',
248 );
249 }
250
251 /** Provider adapter for PropTx / AMPRE. */
252 class ProptxResoClass extends ResoBase {
253 /** @var string Stable provider type. */
254 protected $provider_type = 'proptx';
255
256 /** @var bool PropTx Direct MLS access is not currently implemented. */
257 protected $direct_access_supported = false;
258
259 /** Format PropTx sync times as full OData DateTimeOffset literals. */
260 protected function format_stored_timestamp( $value ) {
261 return $this->format_utc_timestamp( $value, true, true );
262 }
263 }
264