PluginProbe
Depicter — Popup & Slider Builder / trunk
Depicter — Popup & Slider Builder vtrunk
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / app / src / DataSources / GooglePlaces.php

GooglePlaces.php in Depicter — Popup & Slider Builder trunk, at app/src/DataSources/GooglePlaces.php

289 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Depicter\DataSources;
3
4 use Averta\Core\Utility\Str;
5 use Averta\WordPress\Utility\JSON;
6 use Depicter\GuzzleHttp\Client;
7 use Depicter\GuzzleHttp\Exception\GuzzleException;
8
9 class GooglePlaces extends DataSourceBase implements DataSourceInterface
10 {
11
12 /**
13 * DataSource name
14 *
15 * @var string
16 */
17 protected string $type = 'googlePlaces';
18
19 /**
20 * DataSource properties
21 *
22 * @var array
23 */
24 protected array $properties = [];
25
26 /**
27 * Default input params for retrieving dataSource records
28 *
29 * @var array
30 */
31 protected array $defaultInputParams = [
32 'id' => null,
33 'minRating' => 0,
34 'dateStart' => '',
35 'dateEnd' => ''
36 ];
37
38 /**
39 * Google places api endpoint
40 *
41 * @var string
42 */
43 protected string $api = "https://places.googleapis.com/v1/places";
44
45
46 /**
47 * Asset groups of this DataSource
48 *
49 * @var array
50 */
51 protected array $assetGroupNames = ['googlePlace', 'googlePlaceReview'];
52
53
54 /**
55 * Get list of datasheets and corresponding required arguments
56 *
57 * @param array $args
58 *
59 * @return array
60 */
61 public function getDataSheetArgs( array $args = [] )
62 {
63 $result = $this->getRecords( $this->prepare( $args ) );
64
65 return ! empty( $result['success'] ) ? $result['hits'] : [];
66 }
67
68 /**
69 * Retrieves the list of records based on query params
70 *
71 * @param $args
72 *
73 * @return array
74 */
75 protected function getRecords( $args )
76 {
77 if ( empty( $args['id'] ) ) {
78 return [];
79 }
80
81 return $this->getReviews( $args );
82 }
83
84 /**
85 * Renders preview for query params
86 *
87 * @param array $args
88 *
89 * @return array
90 */
91 public function previewRecords( array $args = [] )
92 {
93 $args = $this->prepare( $args );
94
95 return $this->getRecords( $args );
96 }
97
98 /**
99 * Checks if Google Places API Key is set
100 *
101 * @return string
102 */
103 public function hasValidApiKey()
104 {
105 return ! empty( $this->getApiKey() );
106 }
107
108 /**
109 * Retrieves Google Places API Key
110 *
111 * @return string
112 */
113 private function getApiKey()
114 {
115 return \Depicter::options()->get( 'google_places_api_key', '' );
116 }
117
118 /**
119 * Searches in places by a keyword
120 *
121 * @param string $search Search keyword
122 *
123 * @return array
124 */
125 public function searchPlaces( $search )
126 {
127 if ( ! $apiKey = $this->getApiKey() ) {
128 return [
129 'success' => false,
130 'errors' => [
131 __( 'Google Places Api Key not found.', 'depicter' )
132 ]
133 ];
134 }
135
136 $client = new Client();
137
138 try{
139 $response = $client->post( $this->api . ":searchText", [
140 'headers' => [
141 'Content-Type' => 'application/json',
142 'X-Goog-Api-Key' => $apiKey,
143 'X-Goog-FieldMask' => 'places.id,places.displayName,places.formattedAddress'
144 ],
145 'json' => [
146 'textQuery' => $search
147 ]
148 ] );
149
150 if ( $response->getStatusCode() == 200 ) {
151 $placesInfo = JSON::decode( $response->getBody()->getContents(), true );
152 $hits = array_map( function( $place ) {
153 return [
154 'id' => $place['id'],
155 'label' => $place['displayName']['text'],
156 'address' => $place['formattedAddress'],
157 'language' => $place['displayName']['languageCode']
158 ];
159 }, $placesInfo['places'] ?? [] );
160
161 return [
162 'success' => true,
163 'hits' => $hits
164 ];
165 }
166 } catch ( GuzzleException $e ){
167 $message = $e->getMessage();
168 // extract error message from google api response
169 if ( preg_match( '/"message"\s*:\s*"([^"]+)"/', $e->getMessage(), $matches ) ) {
170 $message = $matches[1] ?? '';
171 }
172
173 return [
174 'success' => false,
175 'errors' => [$message]
176 ];
177 }
178
179 return [
180 'success' => false,
181 'errors' => [__( 'Something goes wrong. Please try again later.', 'depicter' )]
182 ];
183 }
184
185 /**
186 * Retrieves a place details and reviews from Google Places API
187 *
188 * @param $args
189 *
190 * @return array
191 * @throws \Exception
192 */
193 private function getReviews( $args = [] )
194 {
195 if ( ! $apiKey = $this->getApiKey() ) {
196 return [
197 'success' => false,
198 'errors' => [
199 __( 'Google Places Api Key not found.', 'depicter' )
200 ]
201 ];
202 }
203
204 $cacheKey = 'g_place_' . $args['id'];
205 if ( ! $place = \Depicter::cache( 'base' )->get( $cacheKey ) ) {
206 $client = new Client();
207
208 try{
209 $response = $client->get( $this->api . '/' . $args['id'], [
210 'headers' => [
211 'Content-Type' => 'application/json',
212 'X-Goog-Api-Key' => $apiKey,
213 'X-Goog-FieldMask' => 'displayName,formattedAddress,reviews,userRatingCount,rating'
214 ]
215 ] );
216
217 if ( $response->getStatusCode() == 200 ) {
218 $place = JSON::decode( $response->getBody()->getContents(), true );
219 \Depicter::cache( 'base' )->set( $cacheKey, $place, DAY_IN_SECONDS );
220 } else {
221 return [
222 'success' => false,
223 'errors' => [__( 'Something goes wrong. Please try again later.', 'depicter' )]
224 ];
225 }
226 } catch ( GuzzleException $e ){
227 $message = $e->getMessage();
228 // extract error message from google api response
229 if ( preg_match( '/"message"\s*:\s*"([^"]+)"/', $e->getMessage(), $matches ) ) {
230 $message = $matches[1] ?? '';
231 }
232
233 return [
234 'success' => false,
235 'errors' => [$message]
236 ];
237 }
238 }
239
240 $hits = [];
241 $reviews = $place['reviews'] ?? [];
242 foreach ( $reviews as $review ) {
243 // skip the review if rating is less than minRating
244 $reviewRating = (float) ( $review['rating'] ?? 0 );
245 if ( ! empty( $args['minRating'] ) && ( $args['minRating'] > $reviewRating ) ) {
246 continue;
247 }
248
249 if ( ! empty( $args['dateStart'] ) && ( strtotime( $args['dateStart'] ) > strtotime( $review['publishTime'] ) ) ) {
250 continue;
251 }
252
253 if ( ! empty( $args['dateEnd'] ) && ( strtotime( $args['dateEnd'] ) < strtotime( $review['publishTime'] ) ) ) {
254 continue;
255 }
256
257 $authorSrc = explode( '=', $review['authorAttribution']['photoUri'] )['0'] ?? '';
258 $authorSrc .= '=s400';
259
260 $hits[] = [
261 'id' => explode( '/', $review['name'] )['3'] ?? '', // extract the review ID
262 'placeName' => $place['displayName']['text'],
263 'placeAverageRating' => $place['rating'] ?? '',
264 'placeRatingCount' => $place['userRatingCount'] ?? '',
265 'relativeDate' => $review['relativePublishTimeDescription'],
266 'date' => $review['publishTime'] ?? '',
267 'rating' => $review['rating'] ?? '',
268 'excerpt' => Str::trimByChars( $review['originalText']['text'], 235 ),
269 'content' => $review['originalText']['text'],
270 'authorPhoto' => $authorSrc,
271 'author' => [
272 'name' => $review['authorAttribution']['displayName'],
273 'url' => $review['authorAttribution']['uri'],
274 'photo' => [
275 'src' => $authorSrc,
276 'width' => 400,
277 'height' => 400
278 ]
279 ]
280 ];
281 }
282
283 return [
284 'success' => true,
285 'hits' => $hits
286 ];
287 }
288 }
289