PluginProbe ʕ •ᴥ•ʔ
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments / 3.2.1
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments v3.2.1
4.7.0 4.6.6 4.6.5 4.6.4 4.6.3 4.6.2 4.6.1 4.6.0 4.5.1 4.5.0 4.4.2 4.4.1 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.3 4.2.2 4.2.1 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.11.1 1.11.2 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.9.0 1.9.1 1.9.2 1.9.3 1.9.4 1.9.5 2.0.0 2.0.1 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.10.0 2.10.1 2.11.0 2.11.1 2.11.2 2.11.3 2.11.4 2.12.0 2.13.0 2.14.0 2.14.1 2.15.0 2.15.1 2.16.0 2.16.1 2.16.2 2.16.3 2.17.0 2.17.1 2.17.2 2.18.0 2.19.0 2.19.2 2.19.3 2.19.4 2.2.0 2.2.1 2.20.0 2.20.1 2.20.2 2.20.3 2.20.4 2.20.5 2.20.6 2.21.0 2.22.0 2.22.1 2.23.0 2.24.0 2.25.0 2.25.1 2.25.2 2.26.0 2.27.0 2.27.1 2.28.0 2.29.0 2.29.1 2.29.2 2.29.3 2.29.4 2.3.0 2.3.1 2.30.0 2.31.0 2.31.1 2.31.2 2.31.3 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.40.0 2.40.1 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.9.0 3.0.0 3.0.0-RC1 3.0.0-RC2 3.0.0-beta1 3.0.0-beta2 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.10.0 3.10.1 3.11.0 3.12.0 3.13.0 3.13.1 3.13.2 3.13.3 3.13.4 3.14.0 3.15.0 3.15.1 3.15.2 3.15.3 3.15.4 3.15.5 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.16.6 3.16.7 3.16.8 3.17.0 3.17.1 3.17.2 3.17.3 3.17.4 3.17.5 3.17.6 3.18.0 3.19.0 3.19.1 3.19.2 3.2.0 3.2.1 3.2.2 3.20.0 3.20.1 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 4.0.0 4.0.1 4.0.2 4.0.3 trunk 4.1.0 0.2.19.1 4.1.1 1.0.0 4.2.0 1.0.1 1.0.2
surecart / app / src / Models / ExternalApiModel.php
surecart / app / src / Models Last commit date
Blocks 1 year ago Concerns 1 year ago Traits 1 year ago AbandonedCheckout.php 1 year ago AbandonedCheckoutProtocol.php 3 years ago Account.php 3 years ago AccountPortalSession.php 4 years ago Activation.php 1 year ago Affiliation.php 1 year ago AffiliationProduct.php 1 year ago AffiliationProtocol.php 2 years ago AffiliationRequest.php 1 year ago ApiToken.php 3 years ago BalanceTransaction.php 1 year ago Brand.php 4 years ago BulkAction.php 2 years ago Bump.php 1 year ago BuyLink.php 2 years ago CancellationAct.php 1 year ago CancellationReason.php 3 years ago Charge.php 1 year ago Checkout.php 1 year ago Click.php 1 year ago Collection.php 2 years ago CommissionStructure.php 2 years ago Component.php 4 years ago Coupon.php 1 year ago Customer.php 1 year ago CustomerLink.php 4 years ago CustomerNotificationProtocol.php 4 years ago CustomerPortalProtocol.php 1 year ago DatabaseModel.php 1 year ago Discount.php 1 year ago Download.php 4 years ago Event.php 4 years ago Export.php 2 years ago ExternalApiModel.php 1 year ago Form.php 3 years ago Fulfillment.php 1 year ago FulfillmentItem.php 1 year ago GalleryItem.php 1 year ago GalleryItemAttachment.php 1 year ago GalleryItemMedia.php 1 year ago GalleryItemProductMedia.php 1 year ago IncomingWebhook.php 1 year ago Integration.php 2 years ago IntegrationCatalog.php 1 year ago Invoice.php 1 year ago License.php 1 year ago LineItem.php 1 year ago ManualPaymentMethod.php 1 year ago Media.php 1 year ago Model.php 1 year ago ModelInterface.php 4 years ago Order.php 1 year ago OrderProtocol.php 4 years ago PaymentFailure.php 1 year ago PaymentInstrument.php 1 year ago PaymentIntent.php 4 years ago PaymentMethod.php 1 year ago Payout.php 1 year ago PayoutGroup.php 2 years ago Period.php 1 year ago PortalSession.php 4 years ago Price.php 1 year ago Processor.php 1 year ago Product.php 1 year ago ProductCollection.php 1 year ago ProductGroup.php 1 year ago ProductMedia.php 1 year ago Promotion.php 1 year ago ProvisionalAccount.php 2 years ago Purchase.php 2 years ago Referral.php 1 year ago ReferralItem.php 2 years ago Refund.php 1 year ago RegisteredWebhook.php 2 years ago ReturnItem.php 2 years ago ReturnReason.php 2 years ago ReturnRequest.php 1 year ago ShippingMethod.php 3 years ago ShippingProfile.php 3 years ago ShippingProtocol.php 3 years ago ShippingRate.php 3 years ago ShippingZone.php 3 years ago Statistic.php 4 years ago Subscription.php 1 year ago SubscriptionProtocol.php 4 years ago TaxOverride.php 2 years ago TaxProtocol.php 4 years ago TaxRegistration.php 1 year ago TaxZone.php 4 years ago Upload.php 4 years ago Upsell.php 1 year ago UpsellFunnel.php 1 year ago User.php 2 years ago Variant.php 1 year ago VariantOption.php 2 years ago VariantOptionValue.php 1 year ago VariantValue.php 2 years ago VerificationCode.php 3 years ago Webhook.php 1 year ago WebhookRegistration.php 2 years ago
ExternalApiModel.php
458 lines
1 <?php
2
3 namespace SureCart\Models;
4
5 use ArrayAccess;
6 use JsonSerializable;
7 use SureCart\Concerns\Arrayable;
8 use SureCart\Models\Concerns\Facade;
9
10 /**
11 * External API Model class
12 */
13 abstract class ExternalApiModel implements ArrayAccess, JsonSerializable, Arrayable, ModelInterface {
14 use Facade;
15
16 /**
17 * Rest API endpoint
18 *
19 * @var string
20 */
21 protected $endpoint = '';
22
23 /**
24 * Keeps track of booted models
25 *
26 * @var array
27 */
28 protected static $booted = [];
29
30 /**
31 * Keeps track of model events
32 *
33 * @var array
34 */
35 protected static $events = [];
36
37 /**
38 * Stores model attributes
39 *
40 * @var array
41 */
42 protected $attributes = [];
43
44 /**
45 * Original attributes for dirty handling
46 *
47 * @var array
48 */
49 protected $original = [];
50
51 /**
52 * Query arguments
53 *
54 * @var array
55 */
56 protected $query = [];
57
58 /**
59 * Default query parameters
60 *
61 * @var array
62 */
63 protected $default_query = [];
64
65 /**
66 * Stores model relations
67 *
68 * @var array
69 */
70 protected $relations = [];
71
72 /**
73 * Fillable model items
74 *
75 * @var array
76 */
77 protected $fillable = [ '*' ];
78
79 /**
80 * Guarded model items
81 *
82 * @var array
83 */
84 protected $guarded = [];
85
86 /**
87 * Path to the static data file
88 *
89 * @var string
90 */
91 protected $base_url = '';
92
93 /**
94 * Model constructor
95 *
96 * @param array $attributes Optional attributes.
97 */
98 public function __construct( $attributes = [] ) {
99 if ( is_string( $attributes ) ) {
100 $attributes = [ 'id' => $attributes ];
101 }
102
103 $this->bootModel();
104 $this->syncOriginal();
105 $this->fill( $attributes );
106 }
107
108 /**
109 * Find a specific model with an id.
110 *
111 * @param string $id Id of the model.
112 *
113 * @return $this|\WP_Error
114 */
115 protected function find( $id = '' ) {
116 if ( $this->fireModelEvent( 'finding' ) === false ) {
117 return false;
118 }
119
120 $result = $this->makeRequest( [ 'id' => $id ] );
121
122 if ( is_wp_error( $result ) ) {
123 return new $result->get_error_message();
124 }
125
126 $attributes = json_decode( wp_remote_retrieve_body( $result ), true );
127
128 $this->fireModelEvent( 'found' );
129 $this->syncOriginal();
130 $this->fill( $attributes );
131
132 return $this;
133 }
134
135 /**
136 * Get all items matching the current query
137 *
138 * @return array
139 */
140 protected function get() {
141 $result = $this->makeRequest();
142
143 if ( is_wp_error( $result ) ) {
144 return $result->get_error_message();
145 }
146
147 $result = json_decode( wp_remote_retrieve_body( $result ), true );
148
149 foreach ( $result as $key => $item ) {
150 $result[ $key ] = new static( $item );
151 }
152
153 return $result;
154 }
155
156 /**
157 * Make a request to the API.
158 *
159 * @param array $args Array of arguments.
160 *
161 * @return array|WP_Error
162 */
163 protected function makeRequest( $args = [] ) {
164 $endpoint = ! empty( $args['id'] ) ? $this->endpoint . '/' . $args['id'] : $this->endpoint;
165 $url = add_query_arg(
166 array_merge( $this->default_query, $this->query ),
167 $this->base_url . $endpoint
168 );
169
170 // Create a unique transient key based on the URL.
171 $transient_key = 'sc_remote_request_' . md5( $url );
172
173 // Try to get cached response from transient.
174 $cached_response = get_transient( $transient_key );
175 if ( false !== $cached_response ) {
176 return $cached_response;
177 }
178
179 // Make the request if no cache exists in transient.
180 $response = wp_remote_get(
181 $url,
182 [
183 'timeout' => 20,
184 ]
185 );
186
187 // Cache successful responses for 24 hours.
188 if ( ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response ) ) {
189 set_transient( $transient_key, $response, DAY_IN_SECONDS );
190 }
191
192 return $response;
193 }
194
195 /**
196 * Sync the original attributes with the current
197 *
198 * @return $this
199 */
200 protected function syncOriginal() {
201 $this->original = $this->attributes;
202 return $this;
203 }
204
205 /**
206 * Boot the model if not already booted
207 *
208 * @return void
209 */
210 protected function bootModel() {
211 $class = $this->getCalledClassName();
212 if ( ! isset( static::$booted[ $class ] ) ) {
213 static::$booted[ $class ] = true;
214 static::boot();
215 }
216 }
217
218 /**
219 * The "boot" method of the model.
220 *
221 * @return void
222 */
223 protected static function boot() {
224 // Override in child classes if needed
225 }
226
227 /**
228 * Get the called class name
229 *
230 * @return string
231 */
232 protected function getCalledClassName() {
233 return get_called_class();
234 }
235
236 /**
237 * Fill the model with an array of attributes.
238 *
239 * @param array $attributes Attributes to fill.
240 * @return $this
241 */
242 public function fill( $attributes ) {
243 foreach ( $attributes as $key => $value ) {
244 if ( $this->isFillable( $key ) ) {
245 $this->setAttribute( $key, $value );
246 }
247 }
248 return $this;
249 }
250
251 /**
252 * Determine if the given attribute may be mass assigned.
253 *
254 * @param string $key Attribute key.
255 * @return bool
256 */
257 public function isFillable( $key ) {
258 if ( in_array( $key, $this->guarded, true ) ) {
259 return false;
260 }
261 return $this->fillable === [ '*' ] || in_array( $key, $this->fillable, true );
262 }
263
264 /**
265 * Set a given attribute on the model.
266 *
267 * @param string $key Attribute key.
268 * @param mixed $value Attribute value.
269 * @return mixed
270 */
271 public function setAttribute( $key, $value ) {
272 $this->attributes[ $key ] = $value;
273 return $this;
274 }
275
276 /**
277 * Calls a mutator based on set{Attribute}Attribute
278 *
279 * @param string $key Attribute key.
280 * @param mixed $type 'get' or 'set'.
281 *
282 * @return string|false
283 */
284 public function getMutator( $key, $type ) {
285 $key = ucwords( str_replace( [ '-', '_' ], ' ', $key ) );
286
287 $method = $type . str_replace( ' ', '', $key ) . 'Attribute';
288
289 if ( method_exists( $this, $method ) ) {
290 return $method;
291 }
292
293 return false;
294 }
295
296 /**
297 * Check if the attribute exists.
298 *
299 * @param string $key Attribute key.
300 * @return bool
301 */
302 public function hasAttribute( $key ) {
303 return isset( $this->attributes[ $key ] );
304 }
305
306 /**
307 * Get an attribute from the model.
308 *
309 * @param string $key Attribute key.
310 * @return mixed
311 */
312 public function getAttribute( $key ) {
313 $attribute = null;
314
315 if ( $this->hasAttribute( $key ) ) {
316 $attribute = $this->attributes[ $key ];
317 }
318
319 $getter = $this->getMutator( $key, 'get' );
320
321 if ( $getter ) {
322 return $this->{$getter}( $attribute );
323 } elseif ( ! is_null( $attribute ) ) {
324 return $attribute;
325 }
326 }
327
328 /**
329 * Fire the given event for the model.
330 *
331 * @param string $event Event name.
332 * @return mixed
333 */
334 protected function fireModelEvent( $event ) {
335 if ( ! isset( static::$events[ $event ] ) ) {
336 return true;
337 }
338
339 foreach ( static::$events[ $event ] as $callback ) {
340 if ( is_callable( $callback ) ) {
341 $result = call_user_func( $callback, $this );
342 if ( false === $result ) {
343 return false;
344 }
345 }
346 }
347
348 return true;
349 }
350
351 /**
352 * Check if offset exists.
353 *
354 * @param mixed $offset Array offset.
355 * @return bool
356 */
357 public function offsetExists( $offset ): bool {
358 return isset( $this->attributes[ $offset ] );
359 }
360
361 /**
362 * Get offset value.
363 *
364 * @param mixed $offset Array offset.
365 * @return mixed
366 */
367 public function offsetGet( $offset ): mixed {
368 return $this->getAttribute( $offset );
369 }
370
371 /**
372 * Set offset value.
373 *
374 * @param mixed $offset Array offset.
375 * @param mixed $value Offset value.
376 * @return void
377 */
378 public function offsetSet( $offset, $value ): void {
379 $this->setAttribute( $offset, $value );
380 }
381
382 /**
383 * Unset offset.
384 *
385 * @param mixed $offset Array offset.
386 * @return void
387 */
388 public function offsetUnset( $offset ): void {
389 unset( $this->attributes[ $offset ] );
390 }
391
392 /**
393 * JsonSerializable implementation
394 */
395 public function jsonSerialize(): mixed {
396 return $this->toArray();
397 }
398
399 /**
400 * Get the model attributes
401 *
402 * @return array
403 */
404 public function getAttributes() {
405 return json_decode( wp_json_encode( $this->attributes ), true );
406 }
407
408 /**
409 * Get the instance as an array.
410 *
411 * @return array
412 */
413 public function toArray() {
414 $attributes = $this->getAttributes();
415
416 // hoist up the acf attributes to the top level.
417 $acf = $this->attributes['acf'];
418 $attributes = array_merge( $acf, $attributes );
419
420 // Check if any accessor is available and call it.
421 foreach ( get_class_methods( $this ) as $method ) {
422 if ( 'get' === substr( $method, 0, 3 ) && 'Attribute' === substr( $method, -9 ) ) {
423 $key = str_replace( [ 'get', 'Attribute' ], '', $method );
424 if ( $key ) {
425 $pieces = preg_split( '/(?=[A-Z])/', $key );
426 $pieces = array_map( 'strtolower', array_filter( $pieces ) );
427 $key = implode( '_', $pieces );
428 $value = array_key_exists( $key, $this->attributes ) ? $this->attributes[ $key ] : null;
429 $attributes[ $key ] = $this->{$method}( $value );
430 }
431 }
432 }
433
434 // Check if any attribute is a model and call toArray.
435 array_walk_recursive(
436 $attributes,
437 function ( &$value ) {
438 if ( is_a( $value, Arrayable::class ) ) {
439 $value = $value->toArray();
440 }
441 }
442 );
443
444 return $attributes;
445 }
446
447 /**
448 * Get the attribute
449 *
450 * @param string $key Attribute name.
451 *
452 * @return mixed
453 */
454 public function __get( $key ) {
455 return $this->getAttribute( $key );
456 }
457 }
458