PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.3.20
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.3.20
1.6.5 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 All 48 releases
fluent-cart / app / Models / ShippingMethod.php

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

165 lines 4.4 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->whereNull('shipping_class_id');
73 });
74
75 // SQLite-compatible substring extraction
76 $isSqlite = defined('DB_ENGINE') && DB_ENGINE === 'sqlite';
77 // SQLite: Use simple string search instead of JSON functions
78 if ($isSqlite) {
79 $query = $query->where(function ($q) use ($state) {
80 // Handle empty states
81 $q->where('states', '[]')
82 ->orWhereNull('states'); // fallback if states column is NULL
83
84 if ($state) {
85 // Check if the state exists in the array (simple string search)
86 // Escape LIKE wildcards to prevent wildcard injection on public endpoint
87 $escapedState = str_replace(['%', '_'], ['\\%', '\\_'], $state);
88 $q->orWhere('states', 'LIKE', '%"' . $escapedState . '"%');
89 }
90 });
91 } else {
92 // MySQL: Use JSON functions for filtering
93 $query = $query->where(function ($q) use ($state) {
94 $q->whereJsonLength('states', 0);
95
96 if ($state) {
97 // Shipping methods containing the state
98 $q->orWhereJsonContains('states', $state);
99 }
100 });
101 }
102 $query->orderBy('amount', 'DESC');
103
104 return $query->where('is_enabled', 1);
105 }
106
107 /**
108 * Get shipping methods applicable to a country, with post-filtering for multi-country selection zones.
109 *
110 * @param string $country
111 * @param string|null $state
112 * @return \FluentCart\Framework\Database\Orm\Collection
113 */
114 public static function getApplicableForCountry(string $country, $state = null)
115 {
116 $methods = static::applicableToCountry($country, $state)
117 ->with('zone')
118 ->get();
119
120 // Post-filter 'selection' zones that don't actually match this country
121 return $methods->filter(function ($method) use ($country) {
122 if (!$method->zone || $method->zone->region !== 'selection') {
123 return true;
124 }
125 return $method->zone->appliesToCountry($country);
126 });
127 }
128
129 public function getFormattedStatesAttribute()
130 {
131
132 if (is_array($this->states)) {
133 $states = array_map(function ($region) {
134 return AddressHelper::getStateNameByCode($region, $this->zone->region);
135 }, $this->states);
136 return $states;
137 }
138 return [];
139 }
140
141 public function setMetaAttribute($value)
142 {
143
144 if ($value) {
145 $decoded = \json_encode($value);
146 if (!($decoded)) {
147 $decoded = '[]';
148 }
149 } else {
150 $decoded = '[]';
151 }
152
153 $this->attributes['meta'] = $decoded;
154 }
155
156 public function getMetaAttribute($value)
157 {
158 if (!$value) {
159 return [];
160 }
161
162 return \json_decode($value, true);
163 }
164 }
165