PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk 1.2.0 All 47 releases
fluent-cart / app / Models / ShippingMethod.php

ShippingMethod.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Models/ShippingMethod.php

168 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Models;
4
5
6 use FluentCart\App\Helpers\AddressHelper;
7 use FluentCart\App\Models\Concerns\CanSearch;
8 use FluentCart\Framework\Database\Orm\Relations\BelongsTo;
9
10 /**
11 * Shipping Method Model - DB Model for Shipping Methods
12 *
13 * @package FluentCart\App\Models
14 * @version 1.0.0
15 */
16 class ShippingMethod extends Model
17 {
18 use CanSearch;
19
20 protected $table = 'fct_shipping_methods';
21
22 protected $appends = ['formatted_states'];
23
24 /**
25 * The attributes that are mass assignable.
26 *
27 * @var array
28 */
29 protected $fillable = [
30 'zone_id',
31 'title',
32 'type',
33 'settings',
34 'amount',
35 'is_enabled',
36 'order',
37 'states',
38 'meta'
39 ];
40
41 protected $attributes = [
42 'states' => '[]',
43 ];
44
45 /**
46 * The attributes that should be cast.
47 *
48 * @var array
49 */
50 protected $casts = [
51 'settings' => 'array',
52 'states' => 'array',
53 'is_enabled' => 'boolean'
54 ];
55
56 /**
57 * Get the zone that this method belongs to.
58 */
59 public function zone(): BelongsTo
60 {
61 return $this->belongsTo(ShippingZone::class, 'zone_id', 'id');
62 }
63
64 public function scopeApplicableToCountry($query, $country, $state)
65 {
66
67 $query = $query->whereHas('zone', function ($query) use ($country) {
68 $query->where(function ($q) use ($country) {
69 $q->whereIn('region', [$country, 'all'])
70 ->orWhere('region', 'selection');
71 });
72 $query->where(function ($q) {
73 $q->whereNull('shipping_class_id')
74 ->orWhere('shipping_class_id', 0);
75 });
76 });
77
78 // SQLite-compatible substring extraction
79 $isSqlite = defined('DB_ENGINE') && DB_ENGINE === 'sqlite';
80 // SQLite: Use simple string search instead of JSON functions
81 if ($isSqlite) {
82 $query = $query->where(function ($q) use ($state) {
83 // Handle empty states
84 $q->where('states', '[]')
85 ->orWhereNull('states'); // fallback if states column is NULL
86
87 if ($state) {
88 // Check if the state exists in the array (simple string search)
89 // Escape LIKE wildcards to prevent wildcard injection on public endpoint
90 $escapedState = str_replace(['%', '_'], ['\\%', '\\_'], $state);
91 $q->orWhere('states', 'LIKE', '%"' . $escapedState . '"%');
92 }
93 });
94 } else {
95 // MySQL: Use JSON functions for filtering
96 $query = $query->where(function ($q) use ($state) {
97 $q->whereJsonLength('states', 0);
98
99 if ($state) {
100 // Shipping methods containing the state
101 $q->orWhereJsonContains('states', $state);
102 }
103 });
104 }
105 $query->orderBy('amount', 'DESC');
106
107 return $query->where('is_enabled', 1);
108 }
109
110 /**
111 * Get shipping methods applicable to a country, with post-filtering for multi-country selection zones.
112 *
113 * @param string $country
114 * @param string|null $state
115 * @return \FluentCart\Framework\Database\Orm\Collection
116 */
117 public static function getApplicableForCountry(string $country, $state = null)
118 {
119 $methods = static::applicableToCountry($country, $state)
120 ->with('zone')
121 ->get();
122
123 // Post-filter 'selection' zones that don't actually match this country
124 return $methods->filter(function ($method) use ($country) {
125 if (!$method->zone || $method->zone->region !== 'selection') {
126 return true;
127 }
128 return $method->zone->appliesToCountry($country);
129 });
130 }
131
132 public function getFormattedStatesAttribute()
133 {
134
135 if (is_array($this->states)) {
136 $states = array_map(function ($region) {
137 return AddressHelper::getStateNameByCode($region, $this->zone->region);
138 }, $this->states);
139 return $states;
140 }
141 return [];
142 }
143
144 public function setMetaAttribute($value)
145 {
146
147 if ($value) {
148 $decoded = \json_encode($value);
149 if (!($decoded)) {
150 $decoded = '[]';
151 }
152 } else {
153 $decoded = '[]';
154 }
155
156 $this->attributes['meta'] = $decoded;
157 }
158
159 public function getMetaAttribute($value)
160 {
161 if (!$value) {
162 return [];
163 }
164
165 return \json_decode($value, true);
166 }
167 }
168