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 / includes / live / live-connection.php

live-connection.php in MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings 7.2.1, at includes/live/live-connection.php

138 lines 4.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Direct MLS access authentication executor.
4 *
5 * Provider adapters own credential requirements and the exact login plan. This
6 * file performs the identical WordPress HTTP and transient work for those plans;
7 * it contains no provider names, credential maps, or provider-type switches.
8 *
9 * @package Mlsimport
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 /**
17 * Return the active Direct MLS provider and its authentication plan.
18 *
19 * @param array|null $config Optional already-loaded MLS configuration.
20 * @return array{provider:ResoBase,plan:array,config:array}
21 */
22 function mlsimport_live_auth_context( $config = null ): array {
23 $config = is_array( $config ) ? $config : mlsimport_live_config();
24 $type = isset( $config['type'] ) ? (string) $config['type'] : '';
25 $mls_id = isset( $config['mls_id'] ) ? $config['mls_id'] : 0;
26 $options = get_option( 'mlsimport_admin_options', array() );
27 $options = is_array( $options ) ? $options : array();
28 $provider = Mlsimport_Provider_Family::adapter( $type, $mls_id );
29
30 return array(
31 'provider' => $provider,
32 'plan' => $provider->direct_auth_plan( $options, $config ),
33 'config' => $config,
34 );
35 }
36
37 /**
38 * Whether the active provider has a complete Direct MLS login plan.
39 *
40 * @return bool
41 */
42 function mlsimport_live_credentials_present(): bool {
43 $config = mlsimport_live_config();
44 if ( array() === $config ) {
45 return false;
46 }
47
48 $context = mlsimport_live_auth_context( $config );
49 return ! empty( $context['plan']['success'] );
50 }
51
52 /**
53 * Resolve a Direct MLS access token from the provider-owned login plan.
54 *
55 * Stored-token plans return immediately. Expiring-token plans are executed and
56 * cached by mlsimport_live_execute_token_request(). Failures return an empty
57 * string; no secret, request body, or provider response is logged.
58 *
59 * @param array $config Per-MLS configuration.
60 * @return string Access token, or empty when login cannot be completed.
61 */
62 function mlsimport_live_access_token( array $config ): string {
63 $context = mlsimport_live_auth_context( $config );
64 $plan = $context['plan'];
65 if ( empty( $plan['success'] ) ) {
66 return '';
67 }
68
69 if ( 'stored_token' === $plan['mode'] ) {
70 return (string) $plan['token'];
71 }
72
73 return mlsimport_live_execute_token_request(
74 $context['provider']->type(),
75 $plan['request']
76 );
77 }
78
79 /**
80 * Execute and cache one provider-owned token request.
81 *
82 * Step 1 reuses a cached token or short failure marker. Step 2 sends JSON or
83 * form data exactly as requested by the adapter. Step 3 validates the response
84 * and caches either the access token or a five-minute failure marker.
85 *
86 * @param string $type Provider type, used only to name its transient.
87 * @param array $spec Adapter token request with url, body, and json keys.
88 * @return string Access token, or empty on failure.
89 */
90 function mlsimport_live_execute_token_request( string $type, array $spec ): string {
91 $transient = 'mlsimport_live_token_' . $type;
92 $cached = get_transient( $transient );
93 if ( is_string( $cached ) && '' !== $cached ) {
94 return 'fail' === $cached ? '' : $cached;
95 }
96
97 $args = array( 'timeout' => 15 );
98 if ( ! empty( $spec['json'] ) ) {
99 $args['headers'] = array( 'Content-Type' => 'application/json' );
100 $args['body'] = wp_json_encode( $spec['body'] );
101 } else {
102 $args['body'] = $spec['body'];
103 }
104
105 $response = wp_remote_post( $spec['url'], $args );
106 $body = json_decode( (string) wp_remote_retrieve_body( $response ), true );
107 $code = (int) wp_remote_retrieve_response_code( $response );
108 if ( is_wp_error( $response ) || 200 !== $code || ! is_array( $body ) || empty( $body['access_token'] ) ) {
109 set_transient( $transient, 'fail', 5 * MINUTE_IN_SECONDS );
110 return '';
111 }
112
113 $token = (string) $body['access_token'];
114 $ttl = isset( $body['expires_in'] )
115 ? max( 60, (int) $body['expires_in'] - 60 )
116 : HOUR_IN_SECONDS - 60;
117 set_transient( $transient, $token, $ttl );
118
119 return $token;
120 }
121
122 /**
123 * Build the bearer headers for one Direct MLS listing or media request.
124 *
125 * @return array Empty when provider login fails.
126 */
127 function mlsimport_live_auth_headers(): array {
128 $token = mlsimport_live_access_token( mlsimport_live_config() );
129 if ( '' === $token ) {
130 return array();
131 }
132
133 return array(
134 'Authorization' => 'Bearer ' . $token,
135 'Accept' => 'application/json',
136 );
137 }
138