PluginProbe ʕ •ᴥ•ʔ
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments / 4.5.0
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments v4.5.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 2 months ago Concerns 6 months ago Traits 2 weeks ago Wordpress 1 year ago AbandonedCheckout.php 1 year ago AbandonedCheckoutProtocol.php 3 years ago Account.php 10 months ago AccountPortalSession.php 3 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 6 months ago AutoFee.php 5 months ago AutoFeeProtocol.php 5 months ago BalanceTransaction.php 1 year ago Batch.php 2 days ago Brand.php 4 months 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 9 months ago Checkout.php 2 months ago Click.php 1 year ago Collection.php 3 months ago CommissionStructure.php 2 years ago Component.php 4 months ago Coupon.php 2 months ago Customer.php 2 weeks ago CustomerLink.php 3 years ago CustomerNotificationProtocol.php 3 years ago CustomerPortalProtocol.php 1 year ago DatabaseModel.php 2 months ago Discount.php 1 year ago DisplayCurrency.php 1 year ago Dispute.php 9 months ago Download.php 3 years ago Event.php 3 years ago Export.php 2 years ago ExternalApiModel.php 3 months ago Fee.php 1 year ago Form.php 3 years ago Fulfillment.php 1 year ago FulfillmentItem.php 1 year ago GalleryItem.php 9 months ago GalleryItemAttachment.php 5 months ago GalleryItemImageAttachment.php 3 months ago GalleryItemMedia.php 1 year ago GalleryItemProductMedia.php 1 month ago GalleryItemVideoAttachment.php 3 months ago Import.php 6 months ago ImportRow.php 2 months ago IncomingWebhook.php 1 year ago Integration.php 2 years ago IntegrationCatalog.php 2 days ago Invoice.php 1 year ago License.php 1 year ago LineItem.php 9 months ago ManualPaymentMethod.php 1 year ago Media.php 1 month ago Model.php 2 days ago ModelInterface.php 3 years ago Order.php 2 weeks ago OrderProtocol.php 3 years ago ParcelTemplate.php 3 months ago PaymentFailure.php 1 year ago PaymentInstrument.php 2 months ago PaymentIntent.php 1 year ago PaymentMethod.php 1 year ago Payout.php 1 year ago PayoutGroup.php 2 years ago Period.php 1 year ago PlatformFee.php 1 year ago PortalSession.php 3 years ago Price.php 6 months ago Processor.php 1 year ago Product.php 2 days ago ProductCollection.php 1 year ago ProductCollectionImport.php 6 months ago ProductGroup.php 1 year ago ProductImport.php 6 months ago ProductMedia.php 4 months ago Promotion.php 1 year ago ProvisionalAccount.php 2 months ago Purchase.php 2 years ago Referral.php 1 year ago ReferralItem.php 2 years ago Refund.php 1 year ago RefundItem.php 1 year ago RegisteredWebhook.php 2 months ago ReturnItem.php 2 years ago ReturnReason.php 2 years ago ReturnRequest.php 1 year ago Review.php 4 months ago ReviewProtocol.php 4 months ago RuleSchema.php 5 months ago ServiceFee.php 1 year ago ShippingChoice.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 3 years ago Subscription.php 2 weeks ago SubscriptionProtocol.php 3 years ago Swap.php 1 year ago TaxOverride.php 2 years ago TaxProtocol.php 3 years ago TaxRegistration.php 1 year ago TaxZone.php 3 years ago Upload.php 3 years ago Upsell.php 1 year ago UpsellFunnel.php 1 year ago User.php 1 month ago Variant.php 2 days 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
460 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 #[\ReturnTypeWillChange]
368 public function offsetGet( $offset ) {
369 return $this->getAttribute( $offset );
370 }
371
372 /**
373 * Set offset value.
374 *
375 * @param mixed $offset Array offset.
376 * @param mixed $value Offset value.
377 * @return void
378 */
379 public function offsetSet( $offset, $value ): void {
380 $this->setAttribute( $offset, $value );
381 }
382
383 /**
384 * Unset offset.
385 *
386 * @param mixed $offset Array offset.
387 * @return void
388 */
389 public function offsetUnset( $offset ): void {
390 unset( $this->attributes[ $offset ] );
391 }
392
393 /**
394 * JsonSerializable implementation
395 */
396 #[\ReturnTypeWillChange]
397 public function jsonSerialize() {
398 return $this->toArray();
399 }
400
401 /**
402 * Get the model attributes
403 *
404 * @return array
405 */
406 public function getAttributes() {
407 return json_decode( wp_json_encode( $this->attributes ), true );
408 }
409
410 /**
411 * Get the instance as an array.
412 *
413 * @return array
414 */
415 public function toArray() {
416 $attributes = $this->getAttributes();
417
418 // hoist up the acf attributes to the top level.
419 $acf = $this->attributes['acf'];
420 $attributes = array_merge( $acf, $attributes );
421
422 // Check if any accessor is available and call it.
423 foreach ( get_class_methods( $this ) as $method ) {
424 if ( 'get' === substr( $method, 0, 3 ) && 'Attribute' === substr( $method, -9 ) ) {
425 $key = str_replace( [ 'get', 'Attribute' ], '', $method );
426 if ( $key ) {
427 $pieces = preg_split( '/(?=[A-Z])/', $key );
428 $pieces = array_map( 'strtolower', array_filter( $pieces ) );
429 $key = implode( '_', $pieces );
430 $value = array_key_exists( $key, $this->attributes ) ? $this->attributes[ $key ] : null;
431 $attributes[ $key ] = $this->{$method}( $value );
432 }
433 }
434 }
435
436 // Check if any attribute is a model and call toArray.
437 array_walk_recursive(
438 $attributes,
439 function ( &$value ) {
440 if ( is_a( $value, Arrayable::class ) ) {
441 $value = $value->toArray();
442 }
443 }
444 );
445
446 return $attributes;
447 }
448
449 /**
450 * Get the attribute
451 *
452 * @param string $key Attribute name.
453 *
454 * @return mixed
455 */
456 public function __get( $key ) {
457 return $this->getAttribute( $key );
458 }
459 }
460