diff --git a/packages/admin/config/components.php b/packages/admin/config/components.php
index 3e4520347..c18d20e98 100644
--- a/packages/admin/config/components.php
+++ b/packages/admin/config/components.php
@@ -37,6 +37,7 @@
| Shops Livewire Components
|--------------------------------------------------------------------------
*/
+
'attributes.browse' => Components\Attributes\Browse::class,
'attributes.create' => Components\Attributes\Create::class,
'attributes.edit' => Components\Attributes\Edit::class,
diff --git a/packages/admin/config/models.php b/packages/admin/config/models.php
deleted file mode 100644
index c0d3337b4..000000000
--- a/packages/admin/config/models.php
+++ /dev/null
@@ -1,58 +0,0 @@
- Brand::class,
-
- /*
- * Eloquent model should be used to retrieve your categories. Of course,
- * it is often just the "Category" model but you may use whatever you like.
- *
- * The model you want to use as a Category model needs to extends the
- * `\Shopper\Core\Models\Category` model.
- */
- 'category' => Category::class,
-
- /*
- * Eloquent model should be used to retrieve your collections. Of course,
- * it is often just the "Collection" model but you may use whatever you like.
- *
- * The model you want to use as a Collection model needs to extends the
- * `\Shopper\Core\Models\Collection` model.
- */
- 'collection' => Collection::class,
-
- /*
- * Eloquent model should be used to retrieve your products. Of course,
- * it is often just the "Product" model but you may use whatever you like.
- *
- * The model you want to use as a Product model needs to extends the
- * `\Shopper\Core\Models\Product` model.
- */
- 'product' => Product::class,
-
- /*
- * Eloquent model should be used to retrieve your channels. Of course,
- * it is often just the "Channel" model but you may use whatever you like.
- *
- * The model you want to use as a Channel model needs to extends the
- * `\Shopper\Core\Models\Channel` model.
- */
- 'channel' => Channel::class,
-
-];
diff --git a/packages/admin/config/settings.php b/packages/admin/config/settings.php
index ac7e03b6d..4f7a62778 100644
--- a/packages/admin/config/settings.php
+++ b/packages/admin/config/settings.php
@@ -10,7 +10,7 @@
|--------------------------------------------------------------------------
|
| The menu for the generation of the page settings and layout.
- | BladeUIKit Heroicon is the icon used. See https://blade-ui-kit.com/blade-icons?set=1
+ | BladeUIKit UntitledUI is the icon used. See https://blade-ui-kit.com/blade-icons?set=74
|
*/
diff --git a/packages/admin/resources/lang/en/notifications.php b/packages/admin/resources/lang/en/notifications.php
index ce1f851b8..464f4a924 100644
--- a/packages/admin/resources/lang/en/notifications.php
+++ b/packages/admin/resources/lang/en/notifications.php
@@ -4,9 +4,60 @@
return [
+ 'actions' => [
+ 'create' => ':item successfully added',
+ 'update' => ':item successfully updated',
+ 'remove' => ':item successfully removed',
+ ],
+
+ 'attributes' => [
+ 'remove' => 'The attribute has successfully removed',
+ 'enable' => 'The attribute has successfully enabled',
+ 'disable' => 'The attribute has successfully disabled',
+ ],
+
+ 'auth' => [
+ 'password' => 'This password does not match our records.',
+ ],
+
+ 'analytics' => 'Your analytics configurations have been correctly updated',
+
+ 'store_info' => 'Shop informations have been successfully updated',
+
+ 'inventory' => [
+ 'removed' => 'Inventory Successfully removed.',
+ ],
+
+ 'initialize' => 'Store successfully setup, you can now manage everything.',
+
+ 'legal' => 'Your legal policy has been successfully updated',
+
'users_roles' => [
'role_added' => 'A role has been successfully created',
+ 'role_deleted' => 'Role deleted successfully.',
'admin_deleted' => 'Admin deleted successfully',
+ 'permission_add' => 'A new permission has been create and add to this role',
+ 'permission_revoke' => 'Permission :permission has been revoked to this role',
+ 'permission_allow' => 'Permission :permission has been given to this role',
+ 'password_changed' => 'You have been successfully updated your password',
+ 'current_password' => 'That is not your current password.',
+ 'profile_update' => 'Your profile have been successfully updated',
+ 'two_factor_enabled' => 'You have successfully enabled two-factor authentication',
+ 'two_factor_disabled' => 'You have successfully disabled two-factor authentication',
+ 'two_factor_generate' => 'You have successfully regenerated your two-factor authentication recovery codes.',
+ ],
+
+ 'orders' => [
+ 'archived' => 'Order successfully archived',
+ ],
+
+ 'payment' => [
+ 'add' => 'Your payment method have been correctly added!',
+ 'update' => 'Your payment method have been correctly updated',
+ ],
+
+ 'products' => [
+ 'remove' => 'The :item has been correctly removed.',
],
];
diff --git a/packages/admin/resources/lang/en/pages/brands.php b/packages/admin/resources/lang/en/pages/brands.php
index 210932ac3..285b3ee27 100644
--- a/packages/admin/resources/lang/en/pages/brands.php
+++ b/packages/admin/resources/lang/en/pages/brands.php
@@ -9,9 +9,4 @@
'empty_brand' => 'No brand',
- 'notifications' => [
- 'created' => 'Brand successfully added!',
- 'updated' => 'Brand successfully updated!',
- ],
-
];
diff --git a/packages/admin/resources/lang/en/pages/categories.php b/packages/admin/resources/lang/en/pages/categories.php
index 1bc6fd1dc..ee6d5095b 100644
--- a/packages/admin/resources/lang/en/pages/categories.php
+++ b/packages/admin/resources/lang/en/pages/categories.php
@@ -10,9 +10,4 @@
'empty_parent' => 'No parent category',
'parent' => 'in :parent',
- 'notifications' => [
- 'created' => 'Category successfully added!',
- 'updated' => 'Category successfully updated!',
- ],
-
];
diff --git a/packages/admin/resources/lang/en/pages/products.php b/packages/admin/resources/lang/en/pages/products.php
index 66d8393e4..b75c5b33a 100644
--- a/packages/admin/resources/lang/en/pages/products.php
+++ b/packages/admin/resources/lang/en/pages/products.php
@@ -117,6 +117,8 @@
'empty' => 'No adjustments made to inventory.',
'movement' => 'Quantity Movement',
'initial' => 'Initial inventory',
+ 'add' => 'Manually added',
+ 'remove' => 'Manually removed',
],
'seo' => [
diff --git a/packages/admin/resources/lang/en/status.php b/packages/admin/resources/lang/en/status.php
index 1f83b33fa..618831a77 100644
--- a/packages/admin/resources/lang/en/status.php
+++ b/packages/admin/resources/lang/en/status.php
@@ -3,9 +3,15 @@
declare(strict_types=1);
return [
+
+ 'cancelled' => 'Cancelled',
+ 'completed' => 'Completed',
+ 'paid' => 'Paid',
+ 'partial-refund' => 'Partially refunded',
'pending' => 'Pending',
'registered' => 'Registered',
- 'paid' => 'Paid',
- 'completed' => 'Completed',
- 'cancelled' => 'Cancelled',
+ 'treatment' => 'Treatment',
+ 'refunded' => 'Refunded',
+ 'rejected' => 'Rejected',
+
];
diff --git a/packages/admin/resources/lang/en/words.php b/packages/admin/resources/lang/en/words.php
index cc7a8d6aa..e4fd2622f 100644
--- a/packages/admin/resources/lang/en/words.php
+++ b/packages/admin/resources/lang/en/words.php
@@ -15,6 +15,7 @@
'review' => 'Review',
'account' => 'Account',
'users' => 'Users',
+ 'user' => 'User',
'analytics' => 'Analytics',
'system' => 'System',
'purchased' => 'Purchased',
@@ -25,6 +26,9 @@
'per_page_items' => 'Per page items',
'not_available' => 'Not available',
'available' => 'Available',
+ 'stock' => 'Stock',
+ 'permission' => 'Permission',
+ 'role' => 'Role',
'payment_method' => 'Payment Method',
'shipping_method' => 'Shipping method',
diff --git a/packages/admin/resources/lang/fr/notifications.php b/packages/admin/resources/lang/fr/notifications.php
index 930edad61..4d2f19cb2 100644
--- a/packages/admin/resources/lang/fr/notifications.php
+++ b/packages/admin/resources/lang/fr/notifications.php
@@ -4,9 +4,60 @@
return [
+ 'actions' => [
+ 'create' => ':item ajouté avec succès',
+ 'update' => ':item mis à jour avec succès',
+ 'remove' => ':item supprimé(e) avec succès',
+ ],
+
+ 'attributes' => [
+ 'remove' => 'L\'attribut a été supprimé avec succès',
+ 'enable' => 'L\'attribut a été activé avec succès',
+ 'disable' => 'L\'attribut a été désactivé avec succès',
+ ],
+
+ 'auth' => [
+ 'password' => 'Ce mot de passe ne correspond pas à nos archives',
+ ],
+
+ 'analytics' => 'Vos configurations analytiques ont été correctement mises à jour',
+
+ 'store_info' => 'Les informations sur le magasin ont été mises à jour avec succès',
+
+ 'inventory' => [
+ 'removed' => 'Inventaire supprimé avec succès',
+ ],
+
+ 'initialize' => 'Le magasin ayant été configuré avec succès, vous pouvez maintenant tout gérer',
+
+ 'legal' => 'Votre politique juridique a été mise à jour avec succès',
+
'users_roles' => [
+ 'role_deleted' => 'Rôle supprimé avec succès',
'role_added' => 'Un nouveau rôle a été ajouté avec succès',
'admin_deleted' => 'Admin supprimé avec succès',
+ 'permission_add' => 'Une nouvelle autorisation a été créée et ajoutée à ce rôle',
+ 'permission_revoke' => 'La permission :permission a été révoquée pour ce rôle',
+ 'permission_allow' => 'La permission :permission a été donnée à ce rôle',
+ 'password_changed' => 'Vous avez mis à jour votre mot de passe avec succès',
+ 'current_password' => 'Ce n\'est pas votre mot de passe actuel',
+ 'profile_update' => 'Votre profil a été mis à jour avec succès',
+ 'two_factor_enabled' => 'Vous avez activé avec succès l\'authentification à deux facteurs',
+ 'two_factor_disabled' => 'Vous avez désactivé avec succès l\'authentification à deux facteurs',
+ 'two_factor_generate' => 'Vous avez régénéré avec succès vos codes de récupération de l\'authentification à deux facteurs',
+ ],
+
+ 'orders' => [
+ 'archived' => 'Commande archivée avec succès',
+ ],
+
+ 'payment' => [
+ 'add' => 'Votre méthode de paiement a été correctement ajoutée',
+ 'update' => 'Votre mode de paiement a été correctement mis à jour',
+ ],
+
+ 'products' => [
+ 'remove' => ':item a été correctement supprimé',
],
];
diff --git a/packages/admin/resources/lang/fr/pages/brands.php b/packages/admin/resources/lang/fr/pages/brands.php
index 33004bcc3..860a4c9a6 100644
--- a/packages/admin/resources/lang/fr/pages/brands.php
+++ b/packages/admin/resources/lang/fr/pages/brands.php
@@ -9,9 +9,4 @@
'empty_brand' => 'Aucune marque',
- 'notifications' => [
- 'created' => 'Marque ajoutée avec succès !',
- 'updated' => 'Marque mise à jour avec succès !',
- ],
-
];
diff --git a/packages/admin/resources/lang/fr/pages/categories.php b/packages/admin/resources/lang/fr/pages/categories.php
index 71801a108..190fb839f 100644
--- a/packages/admin/resources/lang/fr/pages/categories.php
+++ b/packages/admin/resources/lang/fr/pages/categories.php
@@ -10,9 +10,4 @@
'empty_parent' => 'Pas de catégorie parente',
'parent' => 'dans :parent',
- 'notifications' => [
- 'created' => 'Catégorie ajoutée avec succès!',
- 'updated' => 'Catégorie mise à jour avec succès!',
- ],
-
];
diff --git a/packages/admin/resources/lang/fr/pages/products.php b/packages/admin/resources/lang/fr/pages/products.php
index e3e48521b..a66361286 100644
--- a/packages/admin/resources/lang/fr/pages/products.php
+++ b/packages/admin/resources/lang/fr/pages/products.php
@@ -117,6 +117,8 @@
'empty' => 'Aucun ajustement n\'a été effectué sur l\'inventaire.',
'movement' => 'Mouvement des quantités',
'initial' => 'Stock initial',
+ 'add' => 'Ajout manuel',
+ 'remove' => 'Retrait manuel',
],
'seo' => [
diff --git a/packages/admin/resources/lang/fr/status.php b/packages/admin/resources/lang/fr/status.php
index ed3767bf5..57a73ad43 100644
--- a/packages/admin/resources/lang/fr/status.php
+++ b/packages/admin/resources/lang/fr/status.php
@@ -3,9 +3,15 @@
declare(strict_types=1);
return [
+
+ 'cancelled' => 'Annulé',
+ 'completed' => 'Complète',
+ 'paid' => 'Payé',
'pending' => 'En attente',
'registered' => 'Enregistré',
- 'paid' => 'Payé',
- 'completed' => 'Complète',
- 'cancelled' => 'Annulé',
+ 'treatment' => 'Traitement',
+ 'refunded' => 'Remboursé',
+ 'rejected' => 'Rejeté',
+ 'partial-refund' => 'Remboursement partiel',
+
];
diff --git a/packages/admin/resources/lang/fr/words.php b/packages/admin/resources/lang/fr/words.php
index d06756b07..a6f35f794 100644
--- a/packages/admin/resources/lang/fr/words.php
+++ b/packages/admin/resources/lang/fr/words.php
@@ -15,6 +15,7 @@
'review' => 'Avis',
'account' => 'Compte',
'users' => 'Utilisateurs',
+ 'user' => 'Utilisateur',
'analytics' => 'Analytics',
'system' => 'Système',
'purchased' => 'Acheté',
@@ -25,8 +26,11 @@
'per_page_items' => 'Éléments par page',
'not_available' => 'Indisponible',
'available' => 'Disponible',
+ 'stock' => 'Stock',
+ 'permission' => 'Permission',
+ 'role' => 'Rôle',
- 'payment_method' => 'Moyen de paiement',
+ 'payment_method' => 'Méthode de paiement',
'shipping_method' => 'Mode de livraison',
'no_shipping' => 'Pas de méthode d\'expédition',
'estimated' => 'Délai de livraison estimé',
@@ -42,7 +46,7 @@
'to' => 'à',
'of' => 'de',
'results' => 'résultats',
- 'media' => 'Media',
+ 'media' => 'Média',
'hide' => 'Masquer',
'show' => 'Afficher',
diff --git a/packages/admin/resources/views/components/learn-more.blade.php b/packages/admin/resources/views/components/learn-more.blade.php
index 6324d1d91..7a90675a0 100644
--- a/packages/admin/resources/views/components/learn-more.blade.php
+++ b/packages/admin/resources/views/components/learn-more.blade.php
@@ -5,7 +5,7 @@
{{ __('shopper::components.learn_more') }}
-
+
{{ $name }}
diff --git a/packages/admin/resources/views/livewire/account/dropdown.blade.php b/packages/admin/resources/views/livewire/account/dropdown.blade.php
index 66ad452a3..5a0177c38 100644
--- a/packages/admin/resources/views/livewire/account/dropdown.blade.php
+++ b/packages/admin/resources/views/livewire/account/dropdown.blade.php
@@ -14,8 +14,12 @@ class="mt-4 relative rounded-lg p-2 group hover:bg-white dark:hover:bg-secondary
- {{ $user->full_name }}
- {{ $user->email }}
+
+ {{ $user->full_name }}
+
+
+ {{ $user->email }}
+
diff --git a/packages/admin/src/Exports/ProductInventoryExport.php b/packages/admin/src/Exports/ProductInventoryExport.php
index b7ca3f64a..d5e8c9fc4 100644
--- a/packages/admin/src/Exports/ProductInventoryExport.php
+++ b/packages/admin/src/Exports/ProductInventoryExport.php
@@ -21,12 +21,12 @@ public function headings(): array
{
return [
'#',
- __('Product'),
- __('Stock'),
- __('Event'),
- __('Inventory'),
- __('User'),
- __('Date'),
+ __('shopper::words.product'),
+ __('shopper::words.stock'),
+ __('shopper::words.event'),
+ __('shopper::words.location'),
+ __('shopper::words.user'),
+ __('shopper::words.date'),
];
}
diff --git a/packages/admin/src/Http/Livewire/Components/Account/Devices.php b/packages/admin/src/Http/Livewire/Components/Account/Devices.php
index e258309c4..61a8936cb 100644
--- a/packages/admin/src/Http/Livewire/Components/Account/Devices.php
+++ b/packages/admin/src/Http/Livewire/Components/Account/Devices.php
@@ -16,7 +16,7 @@ class Devices extends Component
{
public function getSessionsProperty(): Collection
{
- if ('database' !== config('session.driver')) {
+ if (config('session.driver') !== 'database') {
return collect();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Account/Password.php b/packages/admin/src/Http/Livewire/Components/Account/Password.php
index 29408454f..234be5d08 100644
--- a/packages/admin/src/Http/Livewire/Components/Account/Password.php
+++ b/packages/admin/src/Http/Livewire/Components/Account/Password.php
@@ -32,12 +32,11 @@ public function save(): void
$this->reset('current_password', 'password', 'password_confirmation');
Notification::make()
- ->title(__('Password Changed!'))
- ->body(__('You have been successfully updated your password!'))
+ ->body(__('shopper::notifications.users_roles.password_changed'))
->success()
->send();
} else {
- session()->flash('error', __('That is not your current password.'));
+ session()->flash('error', __('shopper::notifications.users_roles.current_password'));
}
}
diff --git a/packages/admin/src/Http/Livewire/Components/Account/Profile.php b/packages/admin/src/Http/Livewire/Components/Account/Profile.php
index 9ae074033..2a00aac39 100644
--- a/packages/admin/src/Http/Livewire/Components/Account/Profile.php
+++ b/packages/admin/src/Http/Livewire/Components/Account/Profile.php
@@ -9,6 +9,7 @@
use Illuminate\Validation\Rule;
use Livewire\Component;
use Livewire\WithFileUploads;
+use Shopper\Core\Models\User;
use Shopper\Core\Rules\RealEmailValidator;
use Shopper\Traits\HasAuthenticated;
@@ -29,12 +30,13 @@ class Profile extends Component
public function mount(): void
{
+ /** @var User $user */
$user = $this->getUser();
- $this->first_name = $user->first_name; // @phpstan-ignore-line
- $this->last_name = $user->last_name; // @phpstan-ignore-line
- $this->email = $user->email; // @phpstan-ignore-line
- $this->phone_number = $user->phone_number; // @phpstan-ignore-line
+ $this->first_name = $user->first_name;
+ $this->last_name = $user->last_name;
+ $this->email = $user->email;
+ $this->phone_number = $user->phone_number;
}
public function updatedPicture(): void
@@ -77,8 +79,7 @@ public function save(): void
$this->emit('updatedProfile');
Notification::make()
- ->title(__('Profile Updated'))
- ->body(__('Your profile have been successfully updated!'))
+ ->body(__('shopper::notifications.users_roles.profile_update'))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Account/TwoFactor.php b/packages/admin/src/Http/Livewire/Components/Account/TwoFactor.php
index 56500db9e..6917f4ab5 100644
--- a/packages/admin/src/Http/Livewire/Components/Account/TwoFactor.php
+++ b/packages/admin/src/Http/Livewire/Components/Account/TwoFactor.php
@@ -41,7 +41,7 @@ public function enableTwoFactorAuthentication(EnableTwoFactorAuthentication $ena
$this->showingRecoveryCodes = true;
Notification::make()
- ->body(__('You have successfully enabled two-factor authentication.'))
+ ->body(__('shopper::notifications.users_roles.two_factor_enabled'))
->success()
->send();
}
@@ -66,7 +66,7 @@ public function regenerateRecoveryCodes(GenerateNewRecoveryCodes $generate): voi
$this->showingRecoveryCodes = true;
Notification::make()
- ->body(__('You have successfully regenerated your two-factor authentication recovery codes.'))
+ ->body(__('shopper::notifications.users_roles.two_factor_generate'))
->success()
->send();
}
@@ -80,7 +80,7 @@ public function disableTwoFactorAuthentication(DisableTwoFactorAuthentication $d
$disable(Shopper::auth()->user());
Notification::make()
- ->body(__('You have successfully disabled two-factor authentication.'))
+ ->body(__('shopper::notifications.users_roles.two_factor_disabled'))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Brands/Create.php b/packages/admin/src/Http/Livewire/Components/Brands/Create.php
index 905e6af97..17a7fd0bb 100644
--- a/packages/admin/src/Http/Livewire/Components/Brands/Create.php
+++ b/packages/admin/src/Http/Livewire/Components/Brands/Create.php
@@ -28,7 +28,7 @@ public function store(): void
$brand->addMedia($this->fileUrl)->toMediaCollection(config('shopper.core.storage.collection_name'));
}
- session()->flash('success', __('shopper::pages/brands.notifications.created'));
+ session()->flash('success', __('shopper::notifications.actions.create', ['item' => __('shopper::words.brand')]));
$this->redirectRoute('shopper.brands.index');
}
diff --git a/packages/admin/src/Http/Livewire/Components/Brands/Edit.php b/packages/admin/src/Http/Livewire/Components/Brands/Edit.php
index 84c9270f6..8227115e9 100644
--- a/packages/admin/src/Http/Livewire/Components/Brands/Edit.php
+++ b/packages/admin/src/Http/Livewire/Components/Brands/Edit.php
@@ -47,7 +47,7 @@ public function store(): void
$this->brand->addMedia($this->fileUrl)->toMediaCollection(config('shopper.core.storage.collection_name'));
}
- session()->flash('success', __('shopper::pages/brands.notifications.updated'));
+ session()->flash('success', __('shopper::notifications.actions.update', ['item' => __('shopper::words.brand')]));
$this->redirectRoute('shopper.brands.index');
}
diff --git a/packages/admin/src/Http/Livewire/Components/Categories/Create.php b/packages/admin/src/Http/Livewire/Components/Categories/Create.php
index aaf7dfa7e..a368406a3 100644
--- a/packages/admin/src/Http/Livewire/Components/Categories/Create.php
+++ b/packages/admin/src/Http/Livewire/Components/Categories/Create.php
@@ -30,7 +30,7 @@ public function store(): void
$category->addMedia($this->fileUrl)->toMediaCollection(config('shopper.core.storage.collection_name'));
}
- session()->flash('success', __('shopper::pages/categories.notifications.created'));
+ session()->flash('success', __('shopper::notifications.actions.create', ['item' => __('shopper::words.category')]));
$this->redirectRoute('shopper.categories.index');
}
diff --git a/packages/admin/src/Http/Livewire/Components/Categories/Edit.php b/packages/admin/src/Http/Livewire/Components/Categories/Edit.php
index e74286e23..3d66254aa 100644
--- a/packages/admin/src/Http/Livewire/Components/Categories/Edit.php
+++ b/packages/admin/src/Http/Livewire/Components/Categories/Edit.php
@@ -52,7 +52,7 @@ public function store(): void
$this->category->addMedia($this->fileUrl)->toMediaCollection(config('shopper.core.storage.collection_name'));
}
- session()->flash('success', __('shopper::pages/categories.notifications.updated'));
+ session()->flash('success', __('shopper::notifications.actions.update', ['item' => __('shopper::words.category')]));
$this->redirectRoute('shopper.categories.index');
}
diff --git a/packages/admin/src/Http/Livewire/Components/Collections/Create.php b/packages/admin/src/Http/Livewire/Components/Collections/Create.php
index efa4e1000..c898e0b16 100644
--- a/packages/admin/src/Http/Livewire/Components/Collections/Create.php
+++ b/packages/admin/src/Http/Livewire/Components/Collections/Create.php
@@ -7,6 +7,8 @@
use Carbon\Carbon;
use Illuminate\Contracts\View\View;
use Livewire\Component;
+use Shopper\Core\Enum\CollectionType;
+use Shopper\Core\Models\Collection;
use Shopper\Core\Models\CollectionRule;
use Shopper\Core\Repositories\Ecommerce\CollectionRepository;
use Shopper\Core\Traits\Attributes\WithConditions;
@@ -62,6 +64,7 @@ public function store(): void
{
$this->validate($this->rules());
+ /** @var Collection $collection */
$collection = (new CollectionRepository())->create([
'name' => $this->name,
'slug' => $this->name,
@@ -74,14 +77,13 @@ public function store(): void
]);
if ($this->fileUrl) {
- // @phpstan-ignore-next-line
$collection->addMedia($this->fileUrl)->toMediaCollection(config('shopper.core.storage.collection_name'));
}
- if ('auto' === $this->type && count($this->conditions) > 0 && $this->rule) {
+ if ($this->type === CollectionType::AUTO->value && count($this->conditions) > 0 && $this->rule) {
foreach ($this->rule as $key => $value) {
CollectionRule::query()->create([
- 'collection_id' => $collection->id, // @phpstan-ignore-line
+ 'collection_id' => $collection->id,
'rule' => $this->rule[$key],
'operator' => $this->operator[$key],
'value' => $this->value[$key],
@@ -92,7 +94,7 @@ public function store(): void
$this->resetConditionsFields();
}
- session()->flash('success', __('Collection successfully added!'));
+ session()->flash('success', __('shopper::notifications.actions.create', ['item' => __('shopper::words.collection')]));
$this->redirectRoute('shopper.collections.edit', $collection);
}
diff --git a/packages/admin/src/Http/Livewire/Components/Collections/Edit.php b/packages/admin/src/Http/Livewire/Components/Collections/Edit.php
index 0d06be7b2..97cd0bc47 100644
--- a/packages/admin/src/Http/Livewire/Components/Collections/Edit.php
+++ b/packages/admin/src/Http/Livewire/Components/Collections/Edit.php
@@ -92,7 +92,7 @@ public function store(): void
$this->collection->addMedia($this->fileUrl)->toMediaCollection(config('shopper.core.storage.collection_name'));
}
- session()->flash('success', __('Collection successfully updated!'));
+ session()->flash('success', __('shopper::notifications.actions.update', ['item' => __('shopper::words.collection')]));
$this->redirectRoute('shopper.collections.index');
}
diff --git a/packages/admin/src/Http/Livewire/Components/Customers/Addresses.php b/packages/admin/src/Http/Livewire/Components/Customers/Addresses.php
index dbc8fb1d4..303dfab08 100644
--- a/packages/admin/src/Http/Livewire/Components/Customers/Addresses.php
+++ b/packages/admin/src/Http/Livewire/Components/Customers/Addresses.php
@@ -21,7 +21,11 @@ public function mount($adresses): void
public function render(): View
{
return view('shopper::livewire.customers.addresses', [
- 'addresses' => Cache::remember('customer-addresses', 60 * 60 * 24, fn () => $this->addresses),
+ 'addresses' => Cache::remember(
+ key: 'customer-addresses',
+ ttl: 60 * 60 * 24,
+ callback: fn () => $this->addresses
+ ),
]);
}
}
diff --git a/packages/admin/src/Http/Livewire/Components/Customers/Create.php b/packages/admin/src/Http/Livewire/Components/Customers/Create.php
index d82d32c52..b1acd128d 100644
--- a/packages/admin/src/Http/Livewire/Components/Customers/Create.php
+++ b/packages/admin/src/Http/Livewire/Components/Customers/Create.php
@@ -7,7 +7,9 @@
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;
+use Shopper\Core\Models\Address;
use Shopper\Core\Models\Country;
+use Shopper\Core\Models\User;
use Shopper\Core\Repositories\UserRepository;
use Shopper\Core\Rules\Phone;
use Shopper\Core\Traits\Attributes\WithAddress;
@@ -38,6 +40,7 @@ public function store(): void
{
$this->validate($this->rules());
+ /** @var User $customer */
$customer = (new UserRepository())->create([
'last_name' => $this->last_name,
'first_name' => $this->first_name,
@@ -48,10 +51,8 @@ public function store(): void
'opt_in' => $this->opt_in,
]);
- // @phpstan-ignore-next-line
$customer->assignRole(config('shopper.core.users.default_role'));
- // @phpstan-ignore-next-line
$customer->addresses()->create([
'first_name' => $this->address_first_name,
'last_name' => $this->address_last_name,
@@ -62,14 +63,14 @@ public function store(): void
'street_address' => $this->street_address,
'street_address_plus' => $this->street_address_plus,
'is_default' => true,
- 'type' => 'shipping',
+ 'type' => Address::TYPE_SHIPPING,
]);
if ($this->send_mail) {
- $customer->notify(new CustomerSendCredentials($this->password)); // @phpstan-ignore-line
+ $customer->notify(new CustomerSendCredentials($this->password));
}
- session()->flash('success', __('Customer successfully added!'));
+ session()->flash('success', __('shopper::notifications.actions.create', ['item' => __('shopper::words.customer')]));
$this->redirectRoute('shopper.customers.show', $customer);
}
@@ -95,7 +96,10 @@ public function rules(): array
public function render(): View
{
return view('shopper::livewire.customers.create', [
- 'countries' => Cache::get('countries-settings', fn () => Country::orderBy('name')->get()),
+ 'countries' => Cache::get(
+ key: 'countries-settings',
+ default: fn () => Country::query()->orderBy('name')->get()
+ ),
]);
}
}
diff --git a/packages/admin/src/Http/Livewire/Components/Customers/Profile.php b/packages/admin/src/Http/Livewire/Components/Customers/Profile.php
index ac4f5a90d..f4933e538 100644
--- a/packages/admin/src/Http/Livewire/Components/Customers/Profile.php
+++ b/packages/admin/src/Http/Livewire/Components/Customers/Profile.php
@@ -59,11 +59,7 @@ public function saveFirstName(): void
{
$this->validate(['firstName' => 'sometimes|required']);
- $this->updateValue(
- 'first_name',
- $this->firstName,
- __('Customer First name updated successfully.')
- );
+ $this->updateValue(field: 'first_name', value: $this->firstName);
$this->firstNameUpdate = false;
$this->emit('profileUpdate');
@@ -73,11 +69,7 @@ public function saveLastName(): void
{
$this->validate(['lastName' => 'sometimes|required']);
- $this->updateValue(
- 'last_name',
- $this->lastName,
- __('Customer Last name updated successfully.')
- );
+ $this->updateValue(field: 'last_name', value: $this->lastName);
$this->lastNameUpdate = false;
$this->emit('profileUpdate');
@@ -94,11 +86,7 @@ public function saveEmail(): void
],
]);
- $this->updateValue(
- 'email',
- $this->email,
- __('Customer Email address updated successfully.')
- );
+ $this->updateValue(field: 'email', value: $this->email);
$this->emailUpdate = false;
$this->emit('profileUpdate');
@@ -112,11 +100,7 @@ public function cancelEmail(): void
public function saveBirthDate(): void
{
- $this->updateValue(
- 'birth_date',
- $this->birthDate,
- __('Customer birth date updated successfully.')
- );
+ $this->updateValue(field: 'birth_date', value: $this->birthDate);
$this->birthDateUpdate = false;
$this->birthDateFormatted = $this->customer->birth_date_formatted;
@@ -124,22 +108,14 @@ public function saveBirthDate(): void
public function saveGender(): void
{
- $this->updateValue(
- 'gender',
- $this->gender,
- __('Customer gender updated successfully.')
- );
+ $this->updateValue(field: 'gender', value: $this->gender);
$this->genderUpdate = false;
}
public function updatedOptIn(): void
{
- $this->updateValue(
- 'opt_in',
- $this->optIn,
- __("You have updated the customer's marketing email subscription.")
- );
+ $this->updateValue(field: 'opt_in', value: $this->optIn);
}
public function render(): View
@@ -147,13 +123,12 @@ public function render(): View
return view('shopper::livewire.customers.profile');
}
- private function updateValue(string $field, mixed $value, string $message): void
+ private function updateValue(string $field, mixed $value): void
{
$this->customer->update([$field => $value]);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
- ->body($message)
+ ->body(__('shopper::notifications.actions.update', ['item' => __('shopper::words.customer')]))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Customers/Show.php b/packages/admin/src/Http/Livewire/Components/Customers/Show.php
index defde3ea5..38d7c6068 100644
--- a/packages/admin/src/Http/Livewire/Components/Customers/Show.php
+++ b/packages/admin/src/Http/Livewire/Components/Customers/Show.php
@@ -53,7 +53,7 @@ public function store(): void
'first_name' => $this->first_name,
]);
- session()->flash('success', __('Customer successfully updated!'));
+ session()->flash('success', __('shopper::notifications.actions.update', ['item' => __('shopper::words.customer')]));
$this->redirectRoute('shopper.customers.index');
}
diff --git a/packages/admin/src/Http/Livewire/Components/Discounts/Browse.php b/packages/admin/src/Http/Livewire/Components/Discounts/Browse.php
index 7a692ae3f..5e6b5751e 100644
--- a/packages/admin/src/Http/Livewire/Components/Discounts/Browse.php
+++ b/packages/admin/src/Http/Livewire/Components/Discounts/Browse.php
@@ -36,11 +36,11 @@ public function render(): View
'total' => Discount::query()->count(),
'discounts' => Discount::query()->where('code', 'like', '%' . $this->search . '%')
->where(function (Builder $query): void {
- if (null !== $this->isActive) {
+ if ($this->isActive !== null) {
$query->where('is_active', (bool) ($this->isActive));
}
- if (null !== $this->date) {
+ if ($this->date !== null) {
$query->whereDate('start_at', $this->date)
->orWhereDate('end_at', $this->date);
}
diff --git a/packages/admin/src/Http/Livewire/Components/Discounts/Create.php b/packages/admin/src/Http/Livewire/Components/Discounts/Create.php
index e19fb4efd..5d13351d6 100644
--- a/packages/admin/src/Http/Livewire/Components/Discounts/Create.php
+++ b/packages/admin/src/Http/Livewire/Components/Discounts/Create.php
@@ -38,7 +38,7 @@ public function rules(): array
public function store(): void
{
- if ('none' !== $this->minRequired) {
+ if ($this->minRequired !== 'none') {
$this->validate(['minRequiredValue' => 'required']);
}
@@ -55,7 +55,7 @@ public function store(): void
'value' => $this->value,
'apply_to' => $this->apply,
'min_required' => $this->minRequired,
- 'min_required_value' => 'none' !== $this->minRequired ? $this->minRequiredValue : null,
+ 'min_required_value' => $this->minRequired !== 'none' ? $this->minRequiredValue : null,
'eligibility' => $this->eligibility,
'usage_limit' => $this->usage_limit ?? null,
'usage_limit_per_user' => $this->usage_limit_per_user,
@@ -63,7 +63,7 @@ public function store(): void
'end_at' => $this->dateEnd ? Carbon::createFromFormat('Y-m-d H:i', $this->dateEnd)->toDateTimeString() : null,
]);
- if ('products' === $this->apply) {
+ if ($this->apply === 'products') {
// Associate the discount to all the selected products.
foreach ($this->selectedProducts as $productId) {
DiscountDetail::query()->create([
@@ -75,7 +75,7 @@ public function store(): void
}
}
- if ('customers' === $this->eligibility) {
+ if ($this->eligibility === 'customers') {
// Associate the discount to all the selected users.
foreach ($this->selectedCustomers as $customerId) {
DiscountDetail::query()->create([
diff --git a/packages/admin/src/Http/Livewire/Components/Discounts/Edit.php b/packages/admin/src/Http/Livewire/Components/Discounts/Edit.php
index 236d3f2a9..4eb9ecb11 100644
--- a/packages/admin/src/Http/Livewire/Components/Discounts/Edit.php
+++ b/packages/admin/src/Http/Livewire/Components/Discounts/Edit.php
@@ -38,7 +38,7 @@ public function mount(Discount $discount): void
$this->apply = $discount->apply_to;
$this->eligibility = $discount->eligibility;
$this->usage_limit = $discount->usage_limit;
- $this->usage_number = null !== $discount->usage_limit;
+ $this->usage_number = $discount->usage_limit !== null;
$this->usage_limit_per_user = $discount->usage_limit_per_user;
$this->is_active = $discount->is_active;
$this->dateStart = $discount->start_at->format('Y-m-d H:m');
@@ -53,9 +53,11 @@ public function mount(Discount $discount): void
->where('condition', 'eligibility')
->get();
$customers = collect();
+
foreach ($customerConditions as $customerCondition) {
$customers->push($customerCondition->discountable);
}
+
$this->selectedCustomers = $customers->pluck('id')->all();
$this->customers = (new UserRepository())
@@ -70,9 +72,11 @@ public function mount(Discount $discount): void
->where('condition', 'apply_to')
->get();
$products = collect();
+
foreach ($productConditions as $productCondition) {
$products->push($productCondition->discountable);
}
+
$this->selectedProducts = $products->pluck('id')->all();
$this->products = (new ProductRepository())
@@ -99,7 +103,7 @@ public function rules(): array
public function store(): void
{
- if ('none' !== $this->minRequired) {
+ if ($this->minRequired !== 'none') {
$this->validate(['minRequiredValue' => 'required']);
}
@@ -116,7 +120,7 @@ public function store(): void
'value' => $this->value,
'apply_to' => $this->apply,
'min_required' => $this->minRequired,
- 'min_required_value' => 'none' !== $this->minRequired ? $this->minRequiredValue : null,
+ 'min_required_value' => $this->minRequired !== 'none' ? $this->minRequiredValue : null,
'eligibility' => $this->eligibility,
'usage_limit' => $this->usage_limit ?? null,
'usage_limit_per_user' => $this->usage_limit_per_user,
@@ -124,7 +128,7 @@ public function store(): void
'end_at' => $this->dateEnd ? Carbon::createFromFormat('Y-m-d H:i', $this->dateEnd)->toDateTimeString() : null,
]);
- if ('products' === $this->apply) {
+ if ($this->apply === 'products') {
$this->discount->items()
->where('condition', 'apply_to')
->whereNotIn('discountable_id', $this->selectedProducts)
@@ -143,7 +147,7 @@ public function store(): void
$this->discount->items()->where('condition', 'apply_to')->delete();
}
- if ('customers' === $this->eligibility) {
+ if ($this->eligibility === 'customers') {
$this->discount->items()
->where('condition', 'eligibility')
->whereNotIn('discountable_id', $this->selectedCustomers)
diff --git a/packages/admin/src/Http/Livewire/Components/Discounts/WithDiscountActions.php b/packages/admin/src/Http/Livewire/Components/Discounts/WithDiscountActions.php
index a0dd95876..ba63364f9 100644
--- a/packages/admin/src/Http/Livewire/Components/Discounts/WithDiscountActions.php
+++ b/packages/admin/src/Http/Livewire/Components/Discounts/WithDiscountActions.php
@@ -21,11 +21,11 @@ public function isEmpty(): bool
public function getProductSize(): string
{
- if (0 === count($this->selectedProducts)) {
+ if (count($this->selectedProducts) === 0) {
return mb_strtolower(__('shopper::layout.sidebar.products'));
}
- if (1 === count($this->selectedProducts)) {
+ if (count($this->selectedProducts) === 1) {
return $this->products->first()->name; // @phpstan-ignore-line
}
@@ -34,11 +34,11 @@ public function getProductSize(): string
public function getCustomSize(): ?string
{
- if (0 === count($this->selectedCustomers) || 'everyone' === $this->eligibility) {
+ if (count($this->selectedCustomers) === 0 || $this->eligibility === 'everyone') {
return __('shopper::words.everyone');
}
- if (1 === count($this->selectedCustomers)) {
+ if (count($this->selectedCustomers) === 1) {
return __('shopper::words.for_name', ['name' => $this->customers->first()->first_name]); // @phpstan-ignore-line
}
@@ -55,15 +55,15 @@ public function getDateWord(): ?string
$startDate = new Carbon($this->dateStart);
$endDate = new Carbon($this->dateEnd);
- if ($today->equalTo($startDate) && $today->equalTo($endDate) && null !== $this->dateEnd) {
+ if ($today->equalTo($startDate) && $today->equalTo($endDate) && $this->dateEnd !== null) {
return __('shopper::pages/discounts.active_today');
}
- if ($today->equalTo($startDate) && null === $this->dateEnd) {
+ if ($today->equalTo($startDate) && $this->dateEnd === null) {
return __('shopper::pages/discounts.active_from_today');
}
- if ($today->notEqualTo($startDate) && null === $this->dateEnd) {
+ if ($today->notEqualTo($startDate) && $this->dateEnd === null) {
return __('shopper::pages/discounts.active_from', ['date' => $startDate->format('d M')]);
}
@@ -71,14 +71,14 @@ public function getDateWord(): ?string
return __('shopper::pages/discounts.active_date', ['date' => $startDate->format('d M')]);
}
- if ($startDate->notEqualTo($endDate) && $startDate->lessThan($endDate) && null !== $this->dateEnd) {
+ if ($startDate->notEqualTo($endDate) && $startDate->lessThan($endDate) && $this->dateEnd !== null) {
return __('shopper::pages/discounts.active_from_to', [
'start' => $startDate->format('d M'),
'end' => $endDate->format('d M'),
]);
}
- if ($startDate->greaterThan($endDate) && null !== $this->dateEnd) {
+ if ($startDate->greaterThan($endDate) && $this->dateEnd !== null) {
$this->dateEnd = Carbon::createFromFormat('Y-m-d H:i', $this->dateStart)->toDateString();
return __('shopper::pages/discounts.active_date', ['date' => $startDate->format('d M')]);
@@ -89,7 +89,7 @@ public function getDateWord(): ?string
public function getUsageLimitMessage(): ?string
{
- if ($this->usage_number && null !== $this->usage_limit && (int) $this->usage_limit > 0) {
+ if ($this->usage_number && $this->usage_limit !== null && (int) $this->usage_limit > 0) {
$message = trans_choice('shopper::words.discount_use', $this->usage_limit, ['count' => $this->usage_limit]);
$message .= $this->usage_limit_per_user ? ', ' . __('shopper::pages/discounts.one_per_customer') : '';
diff --git a/packages/admin/src/Http/Livewire/Components/Forms/Uploads/Multiple.php b/packages/admin/src/Http/Livewire/Components/Forms/Uploads/Multiple.php
index a2b8672e6..9df21546d 100644
--- a/packages/admin/src/Http/Livewire/Components/Forms/Uploads/Multiple.php
+++ b/packages/admin/src/Http/Livewire/Components/Forms/Uploads/Multiple.php
@@ -52,8 +52,7 @@ public function removeMedia(int $id): void
$this->emitSelf('fileDeleted');
Notification::make()
- ->title(__('Removed'))
- ->body(__('Media removed from the storage.'))
+ ->body(__('shopper::notifications.actions.remove', ['item' => __('shopper::words.media')]))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Forms/Uploads/Single.php b/packages/admin/src/Http/Livewire/Components/Forms/Uploads/Single.php
index 84f7040a8..116bf69ec 100644
--- a/packages/admin/src/Http/Livewire/Components/Forms/Uploads/Single.php
+++ b/packages/admin/src/Http/Livewire/Components/Forms/Uploads/Single.php
@@ -47,8 +47,7 @@ public function removeMedia(int $id): void
$this->media = null;
Notification::make()
- ->title(__('Removed'))
- ->body(__('Media removed from the storage.'))
+ ->body(__('shopper::notifications.actions.remove', ['item' => __('shopper::words.media')]))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Orders/Show.php b/packages/admin/src/Http/Livewire/Components/Orders/Show.php
index 5bc69287e..098cafaaa 100644
--- a/packages/admin/src/Http/Livewire/Components/Orders/Show.php
+++ b/packages/admin/src/Http/Livewire/Components/Orders/Show.php
@@ -9,6 +9,11 @@
use Livewire\Component;
use Livewire\WithPagination;
use Shopper\Core\Enum\OrderStatus;
+use Shopper\Core\Events\Orders\AddNote;
+use Shopper\Core\Events\Orders\Cancel;
+use Shopper\Core\Events\Orders\Completed;
+use Shopper\Core\Events\Orders\Paid;
+use Shopper\Core\Events\Orders\Registered;
use Shopper\Core\Models\Address;
use Shopper\Core\Models\Order;
@@ -31,7 +36,7 @@ public function cancelOrder(): void
{
$this->order->update(['status' => OrderStatus::CANCELLED->value]);
- event(new \Shopper\Core\Events\Orders\Cancel($this->order));
+ event(new Cancel($this->order));
Notification::make()
->body(__('shopper::pages/orders.notifications.cancelled'))
@@ -45,7 +50,7 @@ public function leaveNotes(): void
$this->order->update(['notes' => $this->notes]);
- event(new \Shopper\Core\Events\Orders\AddNote($this->order));
+ event(new AddNote($this->order));
Notification::make()
->body(__('shopper::pages/orders.notifications.note_added'))
@@ -57,7 +62,7 @@ public function register(): void
{
$this->order->update(['status' => OrderStatus::REGISTER->value]);
- event(new \Shopper\Core\Events\Orders\Registered($this->order));
+ event(new Registered($this->order));
Notification::make()
->body(__('shopper::pages/orders.notifications.registered'))
@@ -69,7 +74,7 @@ public function markPaid(): void
{
$this->order->update(['status' => OrderStatus::PAID->value]);
- event(new \Shopper\Core\Events\Orders\Paid($this->order));
+ event(new Paid($this->order));
Notification::make()
->body(__('shopper::pages/orders.notifications.paid'))
@@ -81,7 +86,7 @@ public function markComplete(): void
{
$this->order->update(['status' => OrderStatus::COMPLETED->value]);
- event(new \Shopper\Core\Events\Orders\Completed($this->order));
+ event(new Completed($this->order));
Notification::make()
->body(__('shopper::pages/orders.notifications.completed'))
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Attributes/Text.php b/packages/admin/src/Http/Livewire/Components/Products/Attributes/Text.php
index 6335f0940..b21f7b0e0 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Attributes/Text.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Attributes/Text.php
@@ -38,7 +38,7 @@ public function mount(int $productId, string $type, int $attributeId): void
->where('product_id', $this->productId)
->where('attribute_id', $this->attributeId)
->first();
- $this->value = $this->model?->attribute_custom_value; // @phpstan-ignore-line
+ $this->value = $this->model?->attribute_custom_value;
}
public function onTrixValueUpdate(string $value): void
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Create.php b/packages/admin/src/Http/Livewire/Components/Products/Create.php
index 9dcd8bf24..841161553 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Create.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Create.php
@@ -8,6 +8,7 @@
use Milon\Barcode\Facades\DNS1DFacade;
use Shopper\Core\Models\Channel;
use Shopper\Core\Models\Inventory;
+use Shopper\Core\Models\Product;
use Shopper\Core\Repositories\Ecommerce\BrandRepository;
use Shopper\Core\Repositories\Ecommerce\CategoryRepository;
use Shopper\Core\Repositories\Ecommerce\CollectionRepository;
@@ -74,6 +75,7 @@ public function store(): void
{
$this->validate($this->rules());
+ /** @var Product $product */
$product = (new ProductRepository())->create([
'name' => $this->name,
'slug' => $this->name,
@@ -86,7 +88,7 @@ public function store(): void
'price_amount' => $this->price_amount,
'cost_amount' => $this->cost_amount,
'type' => $this->type,
- 'requires_shipping' => $this->requiresShipping,
+ 'require_shipping' => $this->requiresShipping,
'backorder' => $this->backorder,
'published_at' => $this->publishedAt ?? now(),
'seo_title' => $this->seoTitle,
@@ -104,31 +106,26 @@ public function store(): void
if (collect($this->files)->isNotEmpty()) {
collect($this->files)->each(
- // @phpstan-ignore-next-line
fn ($file) => $product->addMedia($file)->toMediaCollection(config('shopper.core.storage.collection_name'))
);
}
if (collect($this->category_ids)->isNotEmpty()) {
- // @phpstan-ignore-next-line
$product->categories()->attach($this->category_ids);
}
if (collect($this->collection_ids)->isNotEmpty()) {
- // @phpstan-ignore-next-line
$product->collections()->attach($this->collection_ids);
}
- // @phpstan-ignore-next-line
$product->channels()->attach($this->defaultChannel->id);
if ($this->quantity && count($this->quantity) > 0) {
foreach ($this->quantity as $inventory => $value) {
- // @phpstan-ignore-next-line
$product->mutateStock(
- $inventory,
- (int) $value,
- [
+ inventoryId: $inventory,
+ quantity: (int) $value,
+ arguments: [
'event' => __('shopper::pages/products.inventory.initial'),
'old_quantity' => $value,
]
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Form/Edit.php b/packages/admin/src/Http/Livewire/Components/Products/Form/Edit.php
index e0d119002..748dad96b 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Form/Edit.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Form/Edit.php
@@ -117,7 +117,6 @@ public function store(): void
$this->emit('productHasUpdated', $this->productId);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
->body(__('shopper::pages/products.notifications.update'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Form/Inventory.php b/packages/admin/src/Http/Livewire/Components/Products/Form/Inventory.php
index 606e155f0..e688f5017 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Form/Inventory.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Form/Inventory.php
@@ -62,7 +62,6 @@ public function store(): void
]);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
->body(__('shopper::pages/products.notifications.stock_update'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Form/RelatedProducts.php b/packages/admin/src/Http/Livewire/Components/Products/Form/RelatedProducts.php
index c05f4f33f..e95c0d4f3 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Form/RelatedProducts.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Form/RelatedProducts.php
@@ -32,7 +32,6 @@ public function remove(int $id): void
$this->emitSelf('onProductsAddInRelated');
Notification::make()
- ->title(__('shopper::layout.status.delete'))
->body(__('shopper::pages/products.notifications.remove_related'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Form/Seo.php b/packages/admin/src/Http/Livewire/Components/Products/Form/Seo.php
index 39fcfed6b..30184149f 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Form/Seo.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Form/Seo.php
@@ -53,7 +53,6 @@ public function store(): void
$this->emit('productHasUpdated', $this->productId);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
->body(__('shopper::pages/products.notifications.seo_update'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Form/Shipping.php b/packages/admin/src/Http/Livewire/Components/Products/Form/Shipping.php
index fa599dc6f..b9d83377f 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Form/Shipping.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Form/Shipping.php
@@ -52,7 +52,6 @@ public function store(): void
$this->emit('productHasUpdated', $this->productId);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
->body(__('shopper::pages/products.notifications.shipping_update'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Form/Variants.php b/packages/admin/src/Http/Livewire/Components/Products/Form/Variants.php
index dedce4f58..8cdc877e5 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Form/Variants.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Form/Variants.php
@@ -54,7 +54,6 @@ public function remove(int $id): void
$this->dispatchBrowserEvent('item-removed');
Notification::make()
- ->title(__('shopper::layout.status.delete'))
->body(__('shopper::pages/products.notifications.variation_delete'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Products/Variant.php b/packages/admin/src/Http/Livewire/Components/Products/Variant.php
index f6cffb429..5c988ad09 100644
--- a/packages/admin/src/Http/Livewire/Components/Products/Variant.php
+++ b/packages/admin/src/Http/Livewire/Components/Products/Variant.php
@@ -93,7 +93,6 @@ public function store(): void
$this->emitSelf('onVariantUpdated');
Notification::make()
- ->title(__('shopper::layout.status.updated'))
->body(__('shopper::pages/products.notifications.variation_update'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Reviews/Show.php b/packages/admin/src/Http/Livewire/Components/Reviews/Show.php
index 908fc4835..76281a406 100644
--- a/packages/admin/src/Http/Livewire/Components/Reviews/Show.php
+++ b/packages/admin/src/Http/Livewire/Components/Reviews/Show.php
@@ -27,7 +27,6 @@ public function updatedApproved(): void
$this->review->update(['approved' => ! $this->review->approved]);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
->body(__('shopper::pages/products.reviews.approved_message'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Analytics.php b/packages/admin/src/Http/Livewire/Components/Settings/Analytics.php
index 5b4395890..23b92a364 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Analytics.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Analytics.php
@@ -76,8 +76,7 @@ public function store(): void
}
Notification::make()
- ->title(__('shopper::layout.status.updated'))
- ->body(__('Your analytics configurations have been correctly updated'))
+ ->body(__('shopper::notifications.analytics'))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/General.php b/packages/admin/src/Http/Livewire/Components/Settings/General.php
index 8e1a75ffe..6262e106e 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/General.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/General.php
@@ -126,8 +126,7 @@ public function store(): void
}
Notification::make()
- ->title(__('shopper::layout.status.updated'))
- ->body(__('Shop informations have been correctly updated'))
+ ->body(__('shopper::notifications.store_info'))
->success()
->send();
}
@@ -173,8 +172,7 @@ public function deleteCover(): void
$this->shop_cover = null;
Notification::make()
- ->title(__('shopper::layout.status.delete'))
- ->body(__('Shop cover have been correctly removed'))
+ ->body(__('shopper::notifications.store_info'))
->success()
->send();
}
@@ -182,8 +180,14 @@ public function deleteCover(): void
public function render(): View
{
return view('shopper::livewire.settings.general', [
- 'countries' => Cache::rememberForever('countries', fn () => Country::query()->orderBy('name')->get()),
- 'currencies' => Cache::rememberForever('currencies', fn () => Currency::all()),
+ 'countries' => Cache::rememberForever(
+ key: 'countries',
+ callback: fn () => Country::query()->orderBy('name')->get()
+ ),
+ 'currencies' => Cache::rememberForever(
+ key: 'currencies',
+ callback: fn () => Currency::all()
+ ),
]);
}
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Legal/Privacy.php b/packages/admin/src/Http/Livewire/Components/Settings/Legal/Privacy.php
index 1cd8d05ea..8a4b83267 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Legal/Privacy.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Legal/Privacy.php
@@ -29,8 +29,7 @@ public function store(): void
$this->storeValues(__($this->title), $this->content, $this->isEnabled);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
- ->body(__('Your privacy policy has been successfully updated'))
+ ->body(__('shopper::notifications.legal'))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Legal/Refund.php b/packages/admin/src/Http/Livewire/Components/Settings/Legal/Refund.php
index c9801a6fe..4b9083fed 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Legal/Refund.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Legal/Refund.php
@@ -29,8 +29,7 @@ public function store(): void
$this->storeValues(__($this->title), $this->content, $this->isEnabled);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
- ->body(__('Your refund policy has been successfully updated'))
+ ->body(__('shopper::notifications.legal'))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Legal/Shipping.php b/packages/admin/src/Http/Livewire/Components/Settings/Legal/Shipping.php
index ba1d81cdf..4d2ed6687 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Legal/Shipping.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Legal/Shipping.php
@@ -29,8 +29,7 @@ public function store(): void
$this->storeValues(__($this->title), $this->content, $this->isEnabled);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
- ->body(__('Your shipping policy has been successfully updated'))
+ ->body(__('shopper::notifications.legal'))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Legal/Terms.php b/packages/admin/src/Http/Livewire/Components/Settings/Legal/Terms.php
index bb9b1d628..2224eb551 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Legal/Terms.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Legal/Terms.php
@@ -29,8 +29,7 @@ public function store(): void
$this->storeValues(__($this->title), $this->content, $this->isEnabled);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
- ->body(__('Your terms of use has been successfully updated'))
+ ->body(__('shopper::notifications.legal'))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Management/CreateAdminUser.php b/packages/admin/src/Http/Livewire/Components/Settings/Management/CreateAdminUser.php
index e31549706..6c4cb2f9c 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Management/CreateAdminUser.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Management/CreateAdminUser.php
@@ -9,6 +9,7 @@
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Password;
use Shopper\Core\Models\Role;
+use Shopper\Core\Models\User;
use Shopper\Core\Repositories\UserRepository;
use Shopper\Core\Rules\Phone;
use Shopper\Core\Rules\RealEmailValidator;
@@ -78,6 +79,7 @@ public function store(): void
{
$this->validate($this->rules(), $this->messages());
+ /** @var User $user */
$user = (new UserRepository())->create([
'email' => $this->email,
'first_name' => $this->first_name,
@@ -88,15 +90,16 @@ public function store(): void
'email_verified_at' => now()->toDateTimeString(),
]);
+ /** @var Role $role */
$role = Role::findById((int) $this->role_id);
- $user->assignRole([$role->name]); // @phpstan-ignore-line
+ $user->assignRole([$role->name]);
if ($this->send_mail) {
- $user->notify(new AdminSendCredentials($this->password)); // @phpstan-ignore-line
+ $user->notify(new AdminSendCredentials($this->password));
}
- session()->flash('success', __('Admin :user added successfully.', ['user' => $user->full_name])); // @phpstan-ignore-line
+ session()->flash('success', __('shopper::notifications.actions.create', ['item' => $user->full_name]));
$this->redirectRoute('shopper.settings.users');
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Management/Management.php b/packages/admin/src/Http/Livewire/Components/Settings/Management/Management.php
index 874e4acab..77def4996 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Management/Management.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Management/Management.php
@@ -25,7 +25,6 @@ public function removeUser(int $id): void
$this->dispatchBrowserEvent('user-removed');
Notification::make()
- ->title(__('shopper::layout.forms.actions.deleted'))
->body(__('shopper::notifications.users_roles.admin_deleted'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Management/Permissions.php b/packages/admin/src/Http/Livewire/Components/Settings/Management/Permissions.php
index 9f58c10cf..e3c57f274 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Management/Permissions.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Management/Permissions.php
@@ -23,22 +23,21 @@ public function permissionAdded(int $id): void
public function togglePermission(int $id): void
{
+ /** @var Permission $permission */
$permission = Permission::query()->find($id);
if ($this->role->hasPermissionTo($permission->name)) {
$this->role->revokePermissionTo($permission->name);
Notification::make()
- ->title(__('Revoke Permission'))
- ->body(__('Permission :permission has been revoked to this role.', ['permission' => $permission->display_name])) // @phpstan-ignore-line
+ ->body(__('shopper::notifications.users_roles.permission_revoke', ['permission' => $permission->display_name]))
->success()
->send();
} else {
$this->role->givePermissionTo($permission->name);
Notification::make()
- ->title(__('Allow Permission'))
- ->body(__('Permission :permission has been given to this role.', ['permission' => $permission->display_name])) // @phpstan-ignore-line
+ ->body(__('shopper::notifications.users_roles.permission_allow', ['permission' => $permission->display_name]))
->success()
->send();
}
@@ -49,8 +48,7 @@ public function removePermission(int $id): void
Permission::query()->find($id)->delete();
Notification::make()
- ->title(__('Deleted'))
- ->body(__('The permission has been correctly removed'))
+ ->body(__('shopper::notifications.actions.remove', ['item' => __('shopper::words.permission')]))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Management/Role.php b/packages/admin/src/Http/Livewire/Components/Settings/Management/Role.php
index 30a55ff5c..17a5c8ae4 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Management/Role.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Management/Role.php
@@ -32,11 +32,8 @@ public function save(): void
$this->validate([
'name' => [
'required',
- Rule::unique('roles', 'name')->ignore($this->role->id),
+ Rule::unique(config('permission.table_names')['roles'], 'name')->ignore($this->role->id),
],
- ], [
- 'name.required' => __('The role name is required.'),
- 'name.unique' => __('This name is already used.'),
]);
RoleModel::query()->find($this->role->id)->update([
@@ -46,8 +43,7 @@ public function save(): void
]);
Notification::make()
- ->title(__('shopper::components.tables.status.updated'))
- ->body(__('Role updated successfully'))
+ ->body(__('shopper::notifications.actions.update', ['item' => __('shopper::words.role')]))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Management/UsersRole.php b/packages/admin/src/Http/Livewire/Components/Settings/Management/UsersRole.php
index d7f0b500a..849a9afec 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Management/UsersRole.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Management/UsersRole.php
@@ -22,22 +22,21 @@ public function removeUser(int $id): void
$this->dispatchBrowserEvent('user-removed');
Notification::make()
- ->title(__('Deleted'))
- ->body(__('Admin deleted successfully'))
+ ->body(__('shopper::notifications.users_roles.admin_deleted'))
->success()
->send();
}
public function render(): View
{
- $users = (new UserRepository())
- ->makeModel()
- ->whereHas('roles', function (Builder $query): void {
- $query->where('name', $this->role->name);
- })
- ->orderBy('created_at', 'desc')
- ->get();
-
- return view('shopper::livewire.settings.management.users-role', compact('users'));
+ return view('shopper::livewire.settings.management.users-role', [
+ 'users' => (new UserRepository())
+ ->makeModel()
+ ->whereHas('roles', function (Builder $query): void {
+ $query->where('name', $this->role->name);
+ })
+ ->orderBy('created_at', 'desc')
+ ->get(),
+ ]);
}
}
diff --git a/packages/admin/src/Http/Livewire/Components/Settings/Payments/General.php b/packages/admin/src/Http/Livewire/Components/Settings/Payments/General.php
index 2f9a18af5..dc62328dc 100644
--- a/packages/admin/src/Http/Livewire/Components/Settings/Payments/General.php
+++ b/packages/admin/src/Http/Livewire/Components/Settings/Payments/General.php
@@ -20,13 +20,14 @@ class General extends Component
public function toggleStatus(int $id, int $status): void
{
- PaymentMethod::query()->find($id)->update(['is_enabled' => ! (1 === $status)]);
+ PaymentMethod::query()
+ ->find($id)
+ ->update(['is_enabled' => ! ($status === 1)]);
$this->dispatchBrowserEvent('toggle-saved-' . $id);
Notification::make()
- ->title(__('shopper::layout.status.updated'))
- ->body(__('Your payment method status have been correctly updated'))
+ ->body(__('shopper::notifications.payment.update'))
->success()
->send();
}
@@ -38,8 +39,7 @@ public function removePayment(int $id): void
$this->dispatchBrowserEvent('item-update');
Notification::make()
- ->title(__('Deleted'))
- ->body(__('Your payment method have been correctly removed'))
+ ->body(__('shopper::notifications.actions.remove', ['item' => __('shopper::words.payment_method')]))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Modals/AddVariant.php b/packages/admin/src/Http/Livewire/Modals/AddVariant.php
index 67dd1e16c..8bd2b1063 100644
--- a/packages/admin/src/Http/Livewire/Modals/AddVariant.php
+++ b/packages/admin/src/Http/Livewire/Modals/AddVariant.php
@@ -7,6 +7,7 @@
use Filament\Notifications\Notification;
use Illuminate\Contracts\View\View;
use LivewireUI\Modal\ModalComponent;
+use Shopper\Core\Models\Product;
use Shopper\Core\Repositories\Ecommerce\ProductRepository;
use Shopper\Core\Repositories\InventoryRepository;
use Shopper\Http\Livewire\Components\Products\WithAttributes;
@@ -51,6 +52,7 @@ public function save(): void
{
$this->validate($this->rules());
+ /** @var Product $product */
$product = (new ProductRepository())->create([
'name' => $this->name,
'slug' => $this->name,
@@ -67,14 +69,12 @@ public function save(): void
if (collect($this->files)->isNotEmpty()) {
collect($this->files)->each(
- // @phpstan-ignore-next-line
fn ($file) => $product->addMedia($file)->toMediaCollection(config('shopper.core.storage.collection_name'))
);
}
if ($this->quantity && count($this->quantity) > 0) {
foreach ($this->quantity as $inventory => $value) {
- // @phpstan-ignore-next-line
$product->mutateStock(
$inventory,
(int) $value,
diff --git a/packages/admin/src/Http/Livewire/Modals/ArchiveOrder.php b/packages/admin/src/Http/Livewire/Modals/ArchiveOrder.php
index 3982f3cdb..c7fe4e96a 100644
--- a/packages/admin/src/Http/Livewire/Modals/ArchiveOrder.php
+++ b/packages/admin/src/Http/Livewire/Modals/ArchiveOrder.php
@@ -21,7 +21,7 @@ public function archived(): void
{
$this->order->delete();
- session()->flash('success', __('Order successfully archived'));
+ session()->flash('success', __('shopper::notifications.orders.archived'));
$this->redirectRoute('shopper.orders.index');
}
diff --git a/packages/admin/src/Http/Livewire/Modals/ConfirmPassword.php b/packages/admin/src/Http/Livewire/Modals/ConfirmPassword.php
index b3b566563..615ace54d 100644
--- a/packages/admin/src/Http/Livewire/Modals/ConfirmPassword.php
+++ b/packages/admin/src/Http/Livewire/Modals/ConfirmPassword.php
@@ -25,7 +25,7 @@ public function confirmPassword(): void
{
if (! app(ConfirmPasswordAction::class)(Shopper::auth(), Shopper::auth()->user(), $this->confirmablePassword)) {
throw ValidationException::withMessages([
- 'confirmable_password' => [__('This password does not match our records.')],
+ 'confirmable_password' => [__('shopper::notifications.auth.password')],
]);
}
diff --git a/packages/admin/src/Http/Livewire/Modals/CreatePaymentMethod.php b/packages/admin/src/Http/Livewire/Modals/CreatePaymentMethod.php
index 3504cc3d2..b5e903216 100644
--- a/packages/admin/src/Http/Livewire/Modals/CreatePaymentMethod.php
+++ b/packages/admin/src/Http/Livewire/Modals/CreatePaymentMethod.php
@@ -52,8 +52,7 @@ public function save(): void
}
Notification::make()
- ->title(__('Saved'))
- ->body(__('Your payment method have been correctly added!'))
+ ->body(__('shopper::notifications.payment.add'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Modals/CreatePermission.php b/packages/admin/src/Http/Livewire/Modals/CreatePermission.php
index b15d6350c..8da27a1db 100644
--- a/packages/admin/src/Http/Livewire/Modals/CreatePermission.php
+++ b/packages/admin/src/Http/Livewire/Modals/CreatePermission.php
@@ -34,6 +34,7 @@ public function save(): void
'display_name' => 'required|max:75',
]);
+ /** @var Permission $permission */
$permission = Permission::query()->create([
'name' => $this->name,
'group_name' => $this->group,
@@ -46,8 +47,7 @@ public function save(): void
$this->dispatchBrowserEvent('permission-added');
Notification::make()
- ->title(__('Saved'))
- ->body(__('A new permission has been create and add to this role!'))
+ ->body(__('shopper::notifications.users_roles.permission_add'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Modals/CreateRole.php b/packages/admin/src/Http/Livewire/Modals/CreateRole.php
index 47cbade7c..0690c5e06 100644
--- a/packages/admin/src/Http/Livewire/Modals/CreateRole.php
+++ b/packages/admin/src/Http/Livewire/Modals/CreateRole.php
@@ -19,10 +19,7 @@ class CreateRole extends ModalComponent
public function save(): void
{
- $this->validate(['name' => 'required|unique:roles'], [
- 'name.required' => __('The role name is required.'),
- 'name.unique' => __('This name is already used.'),
- ]);
+ $this->validate(['name' => 'required|unique:' . config('permission.table_names')['roles']]);
Role::create([
'name' => $this->name,
diff --git a/packages/admin/src/Http/Livewire/Modals/DeleteInventory.php b/packages/admin/src/Http/Livewire/Modals/DeleteInventory.php
index d7808732c..eb5f0740a 100644
--- a/packages/admin/src/Http/Livewire/Modals/DeleteInventory.php
+++ b/packages/admin/src/Http/Livewire/Modals/DeleteInventory.php
@@ -24,7 +24,7 @@ public function delete(): void
{
Inventory::query()->find($this->inventoryId)->delete();
- session()->flash('success', __('Inventory Successfully removed.'));
+ session()->flash('success', __('shopper::notifications.inventory.removed'));
$this->redirectRoute('shopper.settings.inventories.index');
}
diff --git a/packages/admin/src/Http/Livewire/Modals/DeleteProduct.php b/packages/admin/src/Http/Livewire/Modals/DeleteProduct.php
index 5f2b1d703..4bb5c7a4d 100644
--- a/packages/admin/src/Http/Livewire/Modals/DeleteProduct.php
+++ b/packages/admin/src/Http/Livewire/Modals/DeleteProduct.php
@@ -30,17 +30,13 @@ public function delete(): void
event(new ProductDeleted($product));
- if ('product' === $this->type) {
- $product->delete();
- } else {
- $product->forceDelete();
- }
+ session()->flash('success', __('shopper::notifications.products.remove', ['item' => $this->type]));
- session()->flash('success', __('The :item has been correctly removed.', ['item' => $this->type]));
-
- if ('product' === $this->type) {
+ if ($this->type === 'product') {
+ $product->delete();
$this->redirectRoute('shopper.products.index');
} else {
+ $product->forceDelete();
$this->redirect($this->route);
}
}
diff --git a/packages/admin/src/Http/Livewire/Modals/DeleteRole.php b/packages/admin/src/Http/Livewire/Modals/DeleteRole.php
index 0da823a86..399e7e35f 100644
--- a/packages/admin/src/Http/Livewire/Modals/DeleteRole.php
+++ b/packages/admin/src/Http/Livewire/Modals/DeleteRole.php
@@ -21,7 +21,7 @@ public function delete(): void
{
Role::query()->find($this->roleId)->delete();
- session()->flash('success', __('Role deleted successfully.'));
+ session()->flash('success', __('shopper::notifications.users_roles.role_deleted'));
$this->redirectRoute('shopper.settings.users');
}
diff --git a/packages/admin/src/Http/Livewire/Modals/LogoutOthersBrowser.php b/packages/admin/src/Http/Livewire/Modals/LogoutOthersBrowser.php
index 1fb5a759f..752bf0070 100644
--- a/packages/admin/src/Http/Livewire/Modals/LogoutOthersBrowser.php
+++ b/packages/admin/src/Http/Livewire/Modals/LogoutOthersBrowser.php
@@ -25,7 +25,7 @@ public function logoutOtherBrowserSessions(StatefulGuard $guard): void
// @phpstan-ignore-next-line
if (! Hash::check($this->password, auth()->user()->password)) {
- throw ValidationException::withMessages(['password' => [__('This password does not match our records.')]]);
+ throw ValidationException::withMessages(['password' => [__('shopper::notifications.auth.password')]]);
}
$guard->logoutOtherDevices($this->password); // @phpstan-ignore-line
diff --git a/packages/admin/src/Http/Livewire/Modals/ProductsLists.php b/packages/admin/src/Http/Livewire/Modals/ProductsLists.php
index 747c2c9d5..bc7166fc8 100644
--- a/packages/admin/src/Http/Livewire/Modals/ProductsLists.php
+++ b/packages/admin/src/Http/Livewire/Modals/ProductsLists.php
@@ -6,6 +6,7 @@
use Filament\Notifications\Notification;
use Illuminate\Contracts\View\View;
+use Illuminate\Database\Eloquent\Collection;
use LivewireUI\Modal\ModalComponent;
use Shopper\Core\Repositories\Ecommerce\CollectionRepository;
use Shopper\Core\Repositories\Ecommerce\ProductRepository;
@@ -31,7 +32,7 @@ public static function modalMaxWidth(): string
return '2xl';
}
- public function getProductsProperty()
+ public function getProductsProperty(): Collection
{
return (new ProductRepository())
->where('name', '%' . $this->search . '%', 'like')
diff --git a/packages/admin/src/Http/Livewire/Modals/UpdatePaymentMethod.php b/packages/admin/src/Http/Livewire/Modals/UpdatePaymentMethod.php
index c4c383925..c8c503092 100644
--- a/packages/admin/src/Http/Livewire/Modals/UpdatePaymentMethod.php
+++ b/packages/admin/src/Http/Livewire/Modals/UpdatePaymentMethod.php
@@ -70,7 +70,7 @@ public function save(): void
Notification::make()
->title(__('shopper::components.tables.status.updated'))
- ->body(__('Your payment method have been correctly updated'))
+ ->body(__('shopper::notifications.payment.update'))
->success()
->send();
diff --git a/packages/admin/src/Http/Livewire/Modals/UpdateValue.php b/packages/admin/src/Http/Livewire/Modals/UpdateValue.php
index b732f59d3..458ce7d7f 100644
--- a/packages/admin/src/Http/Livewire/Modals/UpdateValue.php
+++ b/packages/admin/src/Http/Livewire/Modals/UpdateValue.php
@@ -24,6 +24,7 @@ class UpdateValue extends ModalComponent
public function mount(string $name, string $type, int $id): void
{
+ /** @var AttributeValue $value */
$value = AttributeValue::query()->find($id);
$this->valueId = $id;
diff --git a/packages/admin/src/Http/Livewire/Pages/Auth/ForgotPassword.php b/packages/admin/src/Http/Livewire/Pages/Auth/ForgotPassword.php
index 6d74bc60c..a6b9be68b 100644
--- a/packages/admin/src/Http/Livewire/Pages/Auth/ForgotPassword.php
+++ b/packages/admin/src/Http/Livewire/Pages/Auth/ForgotPassword.php
@@ -22,7 +22,7 @@ public function sendResetPasswordLink(): void
$response = $this->broker()->sendResetLink(['email' => $this->email]);
- if (Password::RESET_LINK_SENT === $response) {
+ if ($response === Password::RESET_LINK_SENT) {
session()->flash('success', trans($response));
return;
diff --git a/packages/admin/src/Http/Livewire/Pages/Auth/ResetPassword.php b/packages/admin/src/Http/Livewire/Pages/Auth/ResetPassword.php
index c7145f236..665b555e2 100644
--- a/packages/admin/src/Http/Livewire/Pages/Auth/ResetPassword.php
+++ b/packages/admin/src/Http/Livewire/Pages/Auth/ResetPassword.php
@@ -39,12 +39,12 @@ public function resetPassword(): void
]);
$response = $this->broker()->reset(
- [
+ credentials: [
'token' => $this->token,
'email' => $this->email,
'password' => $this->password,
],
- function ($user, string $password): void {
+ callback: function ($user, string $password): void {
$user->password = Hash::make($password);
$user->save();
@@ -52,7 +52,7 @@ function ($user, string $password): void {
}
);
- if (Password::PASSWORD_RESET === $response) {
+ if ($response === Password::PASSWORD_RESET) {
$this->redirectRoute('shopper.dashboard');
}
diff --git a/packages/admin/src/Http/Livewire/Pages/Initialization.php b/packages/admin/src/Http/Livewire/Pages/Initialization.php
index 0b7fab1cf..8f94fa3bb 100644
--- a/packages/admin/src/Http/Livewire/Pages/Initialization.php
+++ b/packages/admin/src/Http/Livewire/Pages/Initialization.php
@@ -127,7 +127,7 @@ public function store(): void
$this->storeHasSetup();
- session()->flash('success', __('Store successfully setup, you can now manage everything.'));
+ session()->flash('success', __('shopper::notifications.initialize'));
$this->redirectRoute('shopper.dashboard');
}
diff --git a/packages/admin/src/Http/Livewire/Tables/AttributesTable.php b/packages/admin/src/Http/Livewire/Tables/AttributesTable.php
index 660342bd4..26cf56536 100644
--- a/packages/admin/src/Http/Livewire/Tables/AttributesTable.php
+++ b/packages/admin/src/Http/Livewire/Tables/AttributesTable.php
@@ -57,7 +57,7 @@ public function deleteSelected(): void
Notification::make()
->title(__('shopper::components.tables.status.delete'))
- ->body(__('The attribute has successfully removed!'))
+ ->body(__('shopper::notifications.attributes.remove'))
->success()
->send();
}
@@ -76,7 +76,7 @@ public function enabled(): void
Notification::make()
->title(__('shopper::components.tables.status.updated'))
- ->body(__('The attribute has successfully enabled!'))
+ ->body(__('shopper::notifications.attributes.enable'))
->success()
->send();
}
@@ -89,11 +89,13 @@ public function enabled(): void
public function disabled(): void
{
if (count($this->getSelected()) > 0) {
- Attribute::query()->whereIn('id', $this->getSelected())->update(['is_enabled' => false]);
+ Attribute::query()
+ ->whereIn('id', $this->getSelected())
+ ->update(['is_enabled' => false]);
Notification::make()
->title(__('shopper::components.tables.status.updated'))
- ->body(__('The attribute has successfully disabled!'))
+ ->body(__('shopper::notifications.attributes.disable'))
->success()
->send();
}
diff --git a/packages/admin/src/Http/Livewire/Tables/CollectionsTable.php b/packages/admin/src/Http/Livewire/Tables/CollectionsTable.php
index 3242038d7..03c6a77fe 100644
--- a/packages/admin/src/Http/Livewire/Tables/CollectionsTable.php
+++ b/packages/admin/src/Http/Livewire/Tables/CollectionsTable.php
@@ -45,7 +45,7 @@ public function deleteSelected(): void
Notification::make()
->title(__('shopper::components.tables.status.delete'))
- ->body(__('The attribute has successfully disabled!'))
+ ->body(__('shopper::components.tables.messages.delete', ['name' => mb_strtolower(__('shopper::words.collection'))]))
->success()
->send();
}
diff --git a/packages/admin/src/ShopperServiceProvider.php b/packages/admin/src/ShopperServiceProvider.php
index 6831018fb..034895e61 100644
--- a/packages/admin/src/ShopperServiceProvider.php
+++ b/packages/admin/src/ShopperServiceProvider.php
@@ -35,7 +35,6 @@ final class ShopperServiceProvider extends PackageServiceProvider
'admin',
'auth',
'components',
- 'models',
'routes',
'settings',
];
diff --git a/packages/admin/src/helpers.php b/packages/admin/src/helpers.php
index 583ead344..eab1f1210 100644
--- a/packages/admin/src/helpers.php
+++ b/packages/admin/src/helpers.php
@@ -15,16 +15,3 @@ function is_active(array $routes): bool
return (bool) call_user_func_array([app('router'), 'is'], $routes);
}
}
-
-if (! function_exists('isoToEmoji')) {
- function isoToEmoji(string $code): string
- {
- return implode(
- '',
- array_map(
- fn (string $letter) => mb_chr(ord($letter) % 32 + 0x1F1E5),
- mb_str_split($code)
- )
- );
- }
-}
diff --git a/packages/core/config/core.php b/packages/core/config/core.php
index 6684230a1..9d52a7b85 100644
--- a/packages/core/config/core.php
+++ b/packages/core/config/core.php
@@ -62,18 +62,6 @@
'disk_name' => 'public',
],
- /*
- |--------------------------------------------------------------------------
- | Locale Configuration
- |--------------------------------------------------------------------------
- |
- | Shopper PHP locale determines the default locale that will be used
- | by the model date format function ->formatLocalized().
- |
- */
-
- 'locale' => 'en_EN',
-
/*
|--------------------------------------------------------------------------
| Barcode type
diff --git a/packages/core/config/media.php b/packages/core/config/media.php
index 3e073596f..29f663453 100644
--- a/packages/core/config/media.php
+++ b/packages/core/config/media.php
@@ -37,4 +37,15 @@
],
],
+ /*
+ |--------------------------------------------------------------------------
+ | Fallback image URL
+ |--------------------------------------------------------------------------
+ |
+ | If your media collection does not contain any items, this image should be displayed
+ |
+ */
+
+ 'fallback' => '/shopper/images/placeholder.jpg',
+
];
diff --git a/packages/core/config/models.php b/packages/core/config/models.php
new file mode 100644
index 000000000..ab9b0d247
--- /dev/null
+++ b/packages/core/config/models.php
@@ -0,0 +1,72 @@
+ \Shopper\Core\Models\Brand::class,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Category Model
+ |--------------------------------------------------------------------------
+ |
+ | Eloquent model should be used to retrieve your categories. Of course,
+ | If you want to change this to use a custom model, your model needs to extends the
+ | \Shopper\Core\Models\Category model.
+ |
+ */
+
+ 'category' => \Shopper\Core\Models\Category::class,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Collection Model
+ |--------------------------------------------------------------------------
+ |
+ | Eloquent model should be used to retrieve your collections. Of course,
+ | if you want to change this to use a custom model, your model needs to extends the
+ | \Shopper\Core\Models\Collection model.
+ |
+ */
+
+ 'collection' => \Shopper\Core\Models\Collection::class,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Product Model
+ |--------------------------------------------------------------------------
+ |
+ | Eloquent model should be used to retrieve your products. Of course,
+ | If you want to change this to use a custom model, your model needs to extends the
+ | \Shopper\Core\Models\Product model.
+ |
+ */
+
+ 'product' => \Shopper\Core\Models\Product::class,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Channel Model
+ |--------------------------------------------------------------------------
+ |
+ | Eloquent model should be used to retrieve your channels. Of course,
+ | If you want to change this to use a custom model, your model needs to extends the
+ | \Shopper\Core\Models\Channel model.
+ |
+ */
+
+ 'channel' => \Shopper\Core\Models\Channel::class,
+
+];
diff --git a/packages/core/database/migrations/2020_00_02_000002_create_inventories_table.php b/packages/core/database/migrations/2020_00_02_000002_create_inventories_table.php
index 1a625b952..5a28b551f 100644
--- a/packages/core/database/migrations/2020_00_02_000002_create_inventories_table.php
+++ b/packages/core/database/migrations/2020_00_02_000002_create_inventories_table.php
@@ -34,11 +34,10 @@ public function up(): void
$this->addCommonFields($table);
$table->morphs('stockable');
- $table->string('reference_type')->nullable();
- $table->unsignedBigInteger('reference_id')->nullable();
+ $table->nullableMorphs('reference');
$table->integer('quantity');
$table->integer('old_quantity')->default(0);
- $table->text('event')->nullable();
+ $table->string('event', 75)->nullable();
$table->text('description')->nullable();
$this->addForeignKey($table, 'inventory_id', $this->getTableName('inventories'), false);
diff --git a/packages/core/database/migrations/2020_00_02_000006_create_products_table.php b/packages/core/database/migrations/2020_00_02_000006_create_products_table.php
index 935f1003b..076ab84ab 100644
--- a/packages/core/database/migrations/2020_00_02_000006_create_products_table.php
+++ b/packages/core/database/migrations/2020_00_02_000006_create_products_table.php
@@ -27,7 +27,7 @@ public function up(): void
$table->enum('type', ['deliverable', 'downloadable'])->nullable();
$table->boolean('backorder')->default(false);
$table->boolean('requires_shipping')->default(false);
- $table->dateTimeTz('published_at')->default(now())->nullable();
+ $table->dateTimeTz('published_at')->default(now());
$this->addSeoFields($table);
$this->addShippingFields($table);
diff --git a/packages/core/database/migrations/2020_00_03_000004_create_order_refunds_table.php b/packages/core/database/migrations/2020_00_03_000004_create_order_refunds_table.php
index c3bc3dc8b..7f2d99738 100644
--- a/packages/core/database/migrations/2020_00_03_000004_create_order_refunds_table.php
+++ b/packages/core/database/migrations/2020_00_03_000004_create_order_refunds_table.php
@@ -15,7 +15,7 @@ public function up(): void
$table->longText('refund_reason')->nullable();
$table->string('refund_amount')->nullable();
- $table->enum('status', ['pending', 'treatment', 'partial-refund', 'refunded', 'cancelled', 'rejected'])->default('pending');
+ $table->string('status')->default(\Shopper\Core\Enum\OrderRefundStatus::PENDING->value);
$table->longText('notes');
$this->addForeignKey($table, 'order_id', $this->getTableName('orders'), false);
diff --git a/packages/core/database/migrations/2023_09_21_063717_rename_requires_shipping_columns_on_products_table.php b/packages/core/database/migrations/2023_09_21_063717_rename_requires_shipping_columns_on_products_table.php
new file mode 100644
index 000000000..6eb7d5dc1
--- /dev/null
+++ b/packages/core/database/migrations/2023_09_21_063717_rename_requires_shipping_columns_on_products_table.php
@@ -0,0 +1,17 @@
+getTableName('products'), function (Blueprint $table): void {
+ $table->renameColumn(from: 'requires_shipping', to: 'require_shipping');
+ });
+ }
+};
diff --git a/packages/core/database/seeders/LegalsPageTableSeeder.php b/packages/core/database/seeders/LegalsPageTableSeeder.php
index 01b46e103..6313c6e0a 100644
--- a/packages/core/database/seeders/LegalsPageTableSeeder.php
+++ b/packages/core/database/seeders/LegalsPageTableSeeder.php
@@ -16,28 +16,28 @@ public function run(): void
Legal::query()->create([
'title' => $title = __('shopper::pages/settings.legal.refund'),
- 'slug' => str_slug($title),
+ 'slug' => $title,
'is_enabled' => true,
'content' => null,
]);
Legal::query()->create([
'title' => $title = __('shopper::pages/settings.legal.privacy'),
- 'slug' => str_slug($title),
+ 'slug' => $title,
'is_enabled' => true,
'content' => null,
]);
Legal::query()->create([
'title' => $title = __('shopper::pages/settings.legal.terms_of_use'),
- 'slug' => str_slug($title),
+ 'slug' => $title,
'is_enabled' => true,
'content' => null,
]);
Legal::query()->create([
'title' => $title = __('shopper::pages/settings.legal.shipping'),
- 'slug' => str_slug($title),
+ 'slug' => $title,
'is_enabled' => true,
'content' => null,
]);
diff --git a/packages/core/src/CoreServiceProvider.php b/packages/core/src/CoreServiceProvider.php
index c60ec65ca..69ecee0df 100644
--- a/packages/core/src/CoreServiceProvider.php
+++ b/packages/core/src/CoreServiceProvider.php
@@ -15,14 +15,15 @@ final class CoreServiceProvider extends ServiceProvider
protected array $configFiles = [
'core',
'media',
+ 'models',
];
protected string $root = __DIR__ . '/..';
public function boot(): void
{
- setlocale(LC_TIME, config('shopper.core.locale'));
- Carbon::setLocale(config('shopper.core.locale'));
+ setlocale(LC_ALL, config('app.locale'));
+ Carbon::setLocale(config('app.locale'));
}
public function register(): void
diff --git a/packages/core/src/Enum/CollectionType.php b/packages/core/src/Enum/CollectionType.php
new file mode 100644
index 000000000..add3703f6
--- /dev/null
+++ b/packages/core/src/Enum/CollectionType.php
@@ -0,0 +1,12 @@
+ __('shopper::status.pending'),
- self::TREATMENT => __('Treatment'),
- self::PARTIAL_REFUND => __('Partially refunded'),
- self::REFUNDED => __('Refunded'),
- self::REJECTED => __('Rejected'),
+ self::TREATMENT => __('shopper::status.treatment'),
+ self::PARTIAL_REFUND => __('shopper::status.partial-refund'),
+ self::REFUNDED => __('shopper::status.refunded'),
+ self::REJECTED => __('shopper::status.rejected'),
self::CANCELLED => __('shopper::status.cancelled'),
};
}
diff --git a/packages/core/src/Enum/OrderStatus.php b/packages/core/src/Enum/OrderStatus.php
index 83736ae08..b494068af 100644
--- a/packages/core/src/Enum/OrderStatus.php
+++ b/packages/core/src/Enum/OrderStatus.php
@@ -7,9 +7,13 @@
enum OrderStatus: string
{
case PENDING = 'pending';
+
case REGISTER = 'registered';
+
case PAID = 'completed';
+
case COMPLETED = 'cancelled';
+
case CANCELLED = 'paid';
public function badge(): string
diff --git a/packages/core/src/Helpers/Migration.php b/packages/core/src/Helpers/Migration.php
index 4cbced77a..42de3c7fc 100644
--- a/packages/core/src/Helpers/Migration.php
+++ b/packages/core/src/Helpers/Migration.php
@@ -6,6 +6,9 @@
use Illuminate\Database\Migrations\Migration as BaseMigration;
use Illuminate\Database\Schema\Blueprint;
+use Shopper\Core\Enum\Dimension\Length;
+use Shopper\Core\Enum\Dimension\Volume;
+use Shopper\Core\Enum\Dimension\Weight;
abstract class Migration extends BaseMigration
{
@@ -39,26 +42,26 @@ public function addSeoFields(Blueprint $table): void
public function addShippingFields(Blueprint $table): void
{
+ $table->string('weight_unit')->default(Weight::KG->value);
$table->decimal('weight_value', 10, 5)->nullable()
->default(0.00)
->unsigned();
- $table->string('weight_unit')->default('kg');
+ $table->string('height_unit')->default(Length::CM->value);
$table->decimal('height_value', 10, 5)->nullable()
->default(0.00)
->unsigned();
- $table->string('height_unit')->default('cm');
+ $table->string('width_unit')->default(Length::CM->value);
$table->decimal('width_value', 10, 5)->nullable()
->default(0.00)
->unsigned();
- $table->string('width_unit')->default('cm');
+ $table->string('depth_unit')->default(Length::CM->value);
$table->decimal('depth_value', 10, 5)->nullable()
->default(0.00)
->unsigned();
- $table->string('depth_unit')->default('cm');
+ $table->string('volume_unit')->default(Volume::L->value);
$table->decimal('volume_value', 10, 5)->nullable()
->default(0.00)
->unsigned();
- $table->string('volume_unit')->default('l');
}
public function addForeignKey(Blueprint $table, string $columnName, string $tableName, bool $nullable = true): void
diff --git a/packages/core/src/Models/Address.php b/packages/core/src/Models/Address.php
index 0b2c2ad29..6b4e883bc 100644
--- a/packages/core/src/Models/Address.php
+++ b/packages/core/src/Models/Address.php
@@ -4,6 +4,7 @@
namespace Shopper\Core\Models;
+use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -14,7 +15,7 @@
* @property string|null $first_name
* @property bool $is_default
*/
-class Address extends Model
+final class Address extends Model
{
use HasFactory;
@@ -67,16 +68,18 @@ public function getTable(): string
return shopper_table('user_addresses');
}
- public function getFullNameAttribute(): string
+ public function fullName(): Attribute
{
- return $this->last_name
- ? $this->first_name . ' ' . $this->last_name
- : $this->first_name;
+ return Attribute::make(
+ get: fn () => $this->first_name
+ ? $this->first_name . ' ' . $this->last_name
+ : $this->last_name
+ );
}
public function isDefault(): bool
{
- return true === $this->is_default;
+ return $this->is_default === true;
}
public function user(): BelongsTo
diff --git a/packages/core/src/Models/Attribute.php b/packages/core/src/Models/Attribute.php
index 98fffc46b..7c3c6cbc9 100644
--- a/packages/core/src/Models/Attribute.php
+++ b/packages/core/src/Models/Attribute.php
@@ -22,7 +22,7 @@
* @property string|null $icon
* @property \Illuminate\Database\Eloquent\Collection|array $values
*/
-class Attribute extends Model
+final class Attribute extends Model
{
use HasFactory;
use HasSlug;
diff --git a/packages/core/src/Models/AttributeProduct.php b/packages/core/src/Models/AttributeProduct.php
index b1f2d0472..4cd011767 100644
--- a/packages/core/src/Models/AttributeProduct.php
+++ b/packages/core/src/Models/AttributeProduct.php
@@ -9,7 +9,12 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
-class AttributeProduct extends Model
+/**
+ * @property-read int $id
+ * @property string|null $attribute_custom_value
+ * @property AttributeValue|null $value
+ */
+final class AttributeProduct extends Model
{
use HasFactory;
@@ -27,10 +32,10 @@ public function getTable(): string
return shopper_table('attribute_product');
}
- public function realValue(): AttributeCast
+ protected function realValue(): AttributeCast
{
return AttributeCast::make(
- get: fn () => $this->attribute_custom_value ?? $this->value->value,
+ get: fn () => $this->attribute_custom_value ?? $this->value?->value,
);
}
diff --git a/packages/core/src/Models/AttributeValue.php b/packages/core/src/Models/AttributeValue.php
index 5992416ec..9328827e9 100644
--- a/packages/core/src/Models/AttributeValue.php
+++ b/packages/core/src/Models/AttributeValue.php
@@ -14,7 +14,7 @@
* @property string $key
* @property int $position
*/
-class AttributeValue extends Model
+final class AttributeValue extends Model
{
use HasFactory;
diff --git a/packages/core/src/Models/Brand.php b/packages/core/src/Models/Brand.php
index ab27833e1..714c138c7 100644
--- a/packages/core/src/Models/Brand.php
+++ b/packages/core/src/Models/Brand.php
@@ -9,12 +9,14 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Shopper\Core\Traits\HasMedia;
+use Shopper\Core\Traits\HasSlug;
use Spatie\MediaLibrary\HasMedia as SpatieHasMedia;
class Brand extends Model implements SpatieHasMedia
{
use HasFactory;
use HasMedia;
+ use HasSlug;
protected $guarded = [];
diff --git a/packages/core/src/Models/Carrier.php b/packages/core/src/Models/Carrier.php
index 504b9d0ba..5d73303c3 100644
--- a/packages/core/src/Models/Carrier.php
+++ b/packages/core/src/Models/Carrier.php
@@ -8,7 +8,7 @@
use Illuminate\Database\Eloquent\Model;
use Shopper\Core\Traits\HasSlug;
-class Carrier extends Model
+final class Carrier extends Model
{
use HasSlug;
diff --git a/packages/core/src/Models/Channel.php b/packages/core/src/Models/Channel.php
index 6b7ec48ff..054965d3c 100644
--- a/packages/core/src/Models/Channel.php
+++ b/packages/core/src/Models/Channel.php
@@ -26,7 +26,7 @@ public function getTable(): string
return shopper_table('channels');
}
- public function scopeIsDefault(Builder $query): Builder
+ public function scopeDefault(Builder $query): Builder
{
return $query->where('is_default', true);
}
diff --git a/packages/core/src/Models/Collection.php b/packages/core/src/Models/Collection.php
index 776543790..8121d8c6b 100644
--- a/packages/core/src/Models/Collection.php
+++ b/packages/core/src/Models/Collection.php
@@ -9,10 +9,18 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
+use Shopper\Core\Enum\CollectionType;
use Shopper\Core\Traits\HasMedia;
use Shopper\Core\Traits\HasSlug;
use Spatie\MediaLibrary\HasMedia as SpatieHasMedia;
+/**
+ * @property-read int $id
+ * @property string $type
+ * @property string $name
+ * @property string $slug
+ * @property string|null $description
+ */
class Collection extends Model implements SpatieHasMedia
{
use HasFactory;
@@ -32,17 +40,17 @@ public function getTable(): string
public function scopeManual(Builder $query): Builder
{
- return $query->where('type', 'manual');
+ return $query->where('type', CollectionType::MANUAL->value);
}
public function scopeAutomatic(Builder $query): Builder
{
- return $query->where('type', 'auto');
+ return $query->where('type', CollectionType::AUTO->value);
}
public function isAutomatic(): bool
{
- return 'auto' === $this->type; // @phpstan-ignore-line
+ return $this->type === CollectionType::AUTO->value;
}
public function isManual(): bool
diff --git a/packages/core/src/Models/Country.php b/packages/core/src/Models/Country.php
index 9e3e9c407..e120f432a 100644
--- a/packages/core/src/Models/Country.php
+++ b/packages/core/src/Models/Country.php
@@ -6,7 +6,7 @@
use Illuminate\Database\Eloquent\Model;
-class Country extends Model
+final class Country extends Model
{
public $timestamps = false;
diff --git a/packages/core/src/Models/Discount.php b/packages/core/src/Models/Discount.php
index c03d1718e..e7b60886b 100644
--- a/packages/core/src/Models/Discount.php
+++ b/packages/core/src/Models/Discount.php
@@ -22,7 +22,7 @@
* @property \Illuminate\Support\Carbon $start_at
* @property \Illuminate\Support\Carbon|null $end_at
*/
-class Discount extends Model
+final class Discount extends Model
{
use HasFactory;
diff --git a/packages/core/src/Models/DiscountDetail.php b/packages/core/src/Models/DiscountDetail.php
index b36139f03..4dbb4fdcb 100644
--- a/packages/core/src/Models/DiscountDetail.php
+++ b/packages/core/src/Models/DiscountDetail.php
@@ -9,7 +9,7 @@
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
-class DiscountDetail extends Model
+final class DiscountDetail extends Model
{
use HasFactory;
diff --git a/packages/core/src/Models/Geolocation.php b/packages/core/src/Models/Geolocation.php
index 5b80214b7..8eba627d2 100644
--- a/packages/core/src/Models/Geolocation.php
+++ b/packages/core/src/Models/Geolocation.php
@@ -5,8 +5,9 @@
namespace Shopper\Core\Models;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
-class Geolocation extends Model
+final class Geolocation extends Model
{
protected $guarded = [];
@@ -14,4 +15,14 @@ public function getTable(): string
{
return shopper_table('users_geolocation_history');
}
+
+ public function user(): BelongsTo
+ {
+ return $this->belongsTo(config('auth.providers.users.model', User::class), 'user_id');
+ }
+
+ public function order(): BelongsTo
+ {
+ return $this->belongsTo(Order::class, 'order_id');
+ }
}
diff --git a/packages/core/src/Models/Inventory.php b/packages/core/src/Models/Inventory.php
index e0c9bc1df..ada380ddd 100644
--- a/packages/core/src/Models/Inventory.php
+++ b/packages/core/src/Models/Inventory.php
@@ -4,6 +4,7 @@
namespace Shopper\Core\Models;
+use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -22,7 +23,7 @@
* @property string|null $phone_number
* @property bool $is_default
*/
-class Inventory extends Model
+final class Inventory extends Model
{
use HasFactory;
@@ -54,6 +55,11 @@ public function getTable(): string
return shopper_table('inventories');
}
+ public function scopeDefault(Builder $query): Builder
+ {
+ return $query->where('is_default', true);
+ }
+
public function country(): BelongsTo
{
return $this->belongsTo(Country::class, 'country_id');
diff --git a/packages/core/src/Models/InventoryHistory.php b/packages/core/src/Models/InventoryHistory.php
index 32f5680aa..3a902326b 100644
--- a/packages/core/src/Models/InventoryHistory.php
+++ b/packages/core/src/Models/InventoryHistory.php
@@ -4,12 +4,22 @@
namespace Shopper\Core\Models;
+use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
-class InventoryHistory extends Model
+/**
+ * @property-read int $id
+ * @property int $quantity
+ * @property int $old_quantity
+ * @property string|null $event
+ * @property string|null $description
+ * @property int $user_id
+ * @property int $inventory_id
+ */
+final class InventoryHistory extends Model
{
use HasFactory;
@@ -19,11 +29,11 @@ class InventoryHistory extends Model
'reference_type',
'reference_id',
'inventory_id',
+ 'user_id',
'event',
'quantity',
'old_quantity',
'description',
- 'user_id',
];
protected $appends = [
@@ -35,14 +45,13 @@ public function getTable(): string
return shopper_table('inventory_histories');
}
- public function getAdjustmentAttribute(): string
+ public function adjustment(): Attribute
{
- // @phpstan-ignore-next-line
- if ($this->old_quantity > 0) {
- return '+' . $this->old_quantity;
- }
-
- return (string) $this->old_quantity;
+ return Attribute::make(
+ get: fn () => $this->old_quantity > 0
+ ? '+' . $this->old_quantity
+ : $this->old_quantity
+ );
}
public function inventory(): BelongsTo
diff --git a/packages/core/src/Models/Legal.php b/packages/core/src/Models/Legal.php
index bcbcca6dc..4aea5c7bb 100644
--- a/packages/core/src/Models/Legal.php
+++ b/packages/core/src/Models/Legal.php
@@ -8,7 +8,7 @@
use Illuminate\Database\Eloquent\Model;
use Shopper\Core\Traits\HasSlug;
-class Legal extends Model
+final class Legal extends Model
{
use HasSlug;
diff --git a/packages/core/src/Models/Order.php b/packages/core/src/Models/Order.php
index 8387fccd5..0b1d9f64e 100644
--- a/packages/core/src/Models/Order.php
+++ b/packages/core/src/Models/Order.php
@@ -20,7 +20,7 @@
* @property OrderStatus $status
* @property int $shipping_total
*/
-class Order extends Model
+final class Order extends Model
{
use HasFactory;
use HasPrice;
diff --git a/packages/core/src/Models/OrderItem.php b/packages/core/src/Models/OrderItem.php
index b86bab99a..b2c2cd3e1 100644
--- a/packages/core/src/Models/OrderItem.php
+++ b/packages/core/src/Models/OrderItem.php
@@ -14,7 +14,7 @@
* @property int $quantity
* @property int $unit_price_amount
*/
-class OrderItem extends Model
+final class OrderItem extends Model
{
use HasFactory;
diff --git a/packages/core/src/Models/OrderRefund.php b/packages/core/src/Models/OrderRefund.php
index 573d9815f..9a3cb48ae 100644
--- a/packages/core/src/Models/OrderRefund.php
+++ b/packages/core/src/Models/OrderRefund.php
@@ -9,7 +9,7 @@
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Shopper\Core\Enum\OrderRefundStatus;
-class OrderRefund extends Model
+final class OrderRefund extends Model
{
use HasFactory;
@@ -48,7 +48,7 @@ protected function setDefaultOrderRefundStatus(): void
$this->setRawAttributes(
array_merge(
$this->attributes,
- ['status' => OrderRefundStatus::PENDING->value()]
+ ['status' => OrderRefundStatus::PENDING->value]
),
true
);
diff --git a/packages/core/src/Models/OrderShipping.php b/packages/core/src/Models/OrderShipping.php
index 979705b95..bf2d903d7 100644
--- a/packages/core/src/Models/OrderShipping.php
+++ b/packages/core/src/Models/OrderShipping.php
@@ -8,7 +8,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
-class OrderShipping extends Model
+final class OrderShipping extends Model
{
use HasFactory;
diff --git a/packages/core/src/Models/PaymentMethod.php b/packages/core/src/Models/PaymentMethod.php
index 0580a4e1a..c7a3078e5 100644
--- a/packages/core/src/Models/PaymentMethod.php
+++ b/packages/core/src/Models/PaymentMethod.php
@@ -18,7 +18,7 @@
* @property string|null $link_url
* @property string|null $instructions
*/
-class PaymentMethod extends Model
+final class PaymentMethod extends Model
{
use HasFactory;
use HasSlug;
diff --git a/packages/core/src/Models/Permission.php b/packages/core/src/Models/Permission.php
index 99181db96..0c4a948b7 100644
--- a/packages/core/src/Models/Permission.php
+++ b/packages/core/src/Models/Permission.php
@@ -6,6 +6,12 @@
use Spatie\Permission\Models\Permission as SpatiePermission;
+/**
+ * @property-read int $id
+ * @property string $name
+ * @property string|null $display_name
+ * @property bool $can_be_removed
+ */
final class Permission extends SpatiePermission
{
protected $casts = [
diff --git a/packages/core/src/Models/Product.php b/packages/core/src/Models/Product.php
index 1f17f9135..13e187da4 100644
--- a/packages/core/src/Models/Product.php
+++ b/packages/core/src/Models/Product.php
@@ -12,6 +12,9 @@
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Shopper\Core\Contracts\ReviewRateable;
+use Shopper\Core\Enum\Dimension\Length;
+use Shopper\Core\Enum\Dimension\Volume;
+use Shopper\Core\Enum\Dimension\Weight;
use Shopper\Core\Helpers\Price;
use Shopper\Core\Traits\CanHaveDiscount;
use Shopper\Core\Traits\HasMedia;
@@ -28,6 +31,8 @@
* @property int|null $price_amount
* @property int|null $old_price_amount
* @property int|null $cost_amount
+ * @property \Carbon\Carbon|null $published_at
+ * @property-read int $stock
*/
class Product extends Model implements SpatieHasMedia, ReviewRateable
{
@@ -48,6 +53,10 @@ class Product extends Model implements SpatieHasMedia, ReviewRateable
'requires_shipping' => 'boolean',
'backorder' => 'boolean',
'published_at' => 'datetime',
+ 'depth_unit' => Length::class,
+ 'height_unit' => Length::class,
+ 'volume_unit' => Volume::class,
+ 'weight_unit' => Weight::class,
];
public function getTable(): string
@@ -112,7 +121,7 @@ public function getCostAmount(): ?Price
return Price::from($this->cost_amount);
}
- public function getVariationsStockAttribute(): int
+ public function variationsStock(): Attribute
{
$stock = 0;
@@ -122,7 +131,9 @@ public function getVariationsStockAttribute(): int
}
}
- return $stock;
+ return Attribute::make(
+ get: fn () => $stock,
+ );
}
public function scopePublish(Builder $query): Builder
diff --git a/packages/core/src/Models/Review.php b/packages/core/src/Models/Review.php
index 3ae778745..7129dd777 100644
--- a/packages/core/src/Models/Review.php
+++ b/packages/core/src/Models/Review.php
@@ -14,7 +14,7 @@
* @property-read int $id
* @property bool $approved
*/
-class Review extends Model
+final class Review extends Model
{
use HasFactory;
diff --git a/packages/core/src/Models/Setting.php b/packages/core/src/Models/Setting.php
index 4bc15a802..652e0eca8 100644
--- a/packages/core/src/Models/Setting.php
+++ b/packages/core/src/Models/Setting.php
@@ -47,9 +47,9 @@ public static function lockedAttributesDisplayName(string $key): string
'shop_phone_number' => __('shopper::layout.forms.label.phone_number'),
'shop_lng' => __('shopper::layout.forms.label.longitude'),
'shop_lat' => __('shopper::layout.forms.label.latitude'),
- 'shop_facebook_link' => __('Facebook'),
- 'shop_instagram_link' => __('Twitter'),
- 'shop_twitter_link' => __('Instagram'),
+ 'shop_facebook_link' => __('shopper::words.socials.facebook'),
+ 'shop_instagram_link' => __('shopper::words.socials.twitter'),
+ 'shop_twitter_link' => __('shopper::words.socials.instagram'),
'google_analytics_add_js' => __('shopper::layout.forms.label.ga_additional_script'),
][$key];
}
diff --git a/packages/core/src/Models/User.php b/packages/core/src/Models/User.php
index 6d79dd7ca..c7ff1261c 100644
--- a/packages/core/src/Models/User.php
+++ b/packages/core/src/Models/User.php
@@ -6,6 +6,7 @@
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
@@ -17,9 +18,14 @@
/**
* @property-read int $id
+ * @property-read string $full_name
+ * @property-read string $picture
* @property string|null $first_name
* @property string $last_name
* @property string $email
+ * @property string $avatar_type
+ * @property string|null $avatar_location
+ * @property string|null $phone_number
* @property Carbon|null $email_verified_at
* @property Carbon|null $birth_date
* @property string|null $two_factor_recovery_codes
@@ -81,34 +87,36 @@ public function isAdmin(): bool
public function isVerified(): bool
{
- return null !== $this->email_verified_at;
+ return $this->email_verified_at !== null;
}
- public function getFullNameAttribute(): string
+ public function fullName(): Attribute
{
- return $this->first_name
- ? $this->first_name . ' ' . $this->last_name
- : $this->last_name;
+ return Attribute::make(
+ get: fn () => $this->first_name
+ ? $this->first_name . ' ' . $this->last_name
+ : $this->last_name
+ );
}
- public function getBirthDateFormattedAttribute(): string
+ public function birthDateFormatted(): Attribute
{
- if ($this->birth_date) {
- return $this->birth_date->formatLocalized('%d, %B %Y');
- }
-
- return __('shopper::words.not_defined');
+ return Attribute::make(
+ get: fn () => $this->birth_date
+ ? $this->birth_date->isoFormat('%d, %B %Y')
+ : __('shopper::words.not_defined')
+ );
}
- public function getRolesLabelAttribute(): string
+ public function rolesLabel(): Attribute
{
$roles = $this->roles()->pluck('display_name')->toArray();
- if (count($roles)) {
- return implode(', ', array_map(fn ($item) => ucwords($item), $roles));
- }
-
- return 'N/A';
+ return Attribute::make(
+ get: fn () => count($roles)
+ ? implode(', ', array_map(fn ($item) => ucwords($item), $roles))
+ : 'N/A'
+ );
}
public function scopeResearch(Builder $query, $term): Builder
diff --git a/packages/core/src/Traits/ArrayableEnum.php b/packages/core/src/Traits/ArrayableEnum.php
new file mode 100644
index 000000000..c52723390
--- /dev/null
+++ b/packages/core/src/Traits/ArrayableEnum.php
@@ -0,0 +1,23 @@
+realStock) {
+ if ($this->realStock === 0) {
return;
}
@@ -48,18 +48,18 @@ public function decrementStock(): void
public function updateCurrentStock(): void
{
- if (0 === $this->value) {
+ if ($this->value === 0) {
return;
}
$this->validate(['value' => 'required|integer']);
if ($this->realStock >= $this->stock) {
- $this->product->increaseStock(
+ $this->product->mutateStock(
$this->inventory,
$this->value,
[
- 'event' => __('Manually added'),
+ 'event' => __('shopper::pages/products.inventory.add'),
'old_quantity' => $this->value,
]
);
@@ -68,7 +68,7 @@ public function updateCurrentStock(): void
$this->inventory,
$this->value,
[
- 'event' => __('Manually removed'),
+ 'event' => __('shopper::pages/products.inventory.remove'),
'old_quantity' => $this->value,
]
);
diff --git a/packages/core/src/Traits/HasMedia.php b/packages/core/src/Traits/HasMedia.php
index 313943379..85448d141 100644
--- a/packages/core/src/Traits/HasMedia.php
+++ b/packages/core/src/Traits/HasMedia.php
@@ -17,7 +17,7 @@ public function registerMediaCollections(): void
$this->addMediaCollection(config('shopper.core.storage.collection_name'))
->useDisk(config('shopper.core.storage.disk_name'))
->acceptsMimeTypes(config('shopper.media.accepts_mime_types'))
- ->useFallbackUrl(url('/shopper/images/placeholder.jpg'));
+ ->useFallbackUrl(url(config('shopper.media.fallback_url')));
}
public function registerMediaConversions(Media $media = null): void
diff --git a/packages/core/src/Traits/HasProfilePhoto.php b/packages/core/src/Traits/HasProfilePhoto.php
index 87cf66ae2..025f0b2ca 100644
--- a/packages/core/src/Traits/HasProfilePhoto.php
+++ b/packages/core/src/Traits/HasProfilePhoto.php
@@ -4,17 +4,18 @@
namespace Shopper\Core\Traits;
+use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Support\Facades\Storage;
trait HasProfilePhoto
{
- public function getPictureAttribute(): string
+ public function picture(): Attribute
{
- if ('storage' === $this->avatar_type) {
- return Storage::disk(config('shopper.core.storage.disk_name'))->url($this->avatar_location);
- }
-
- return $this->defaultProfilePhotoUrl();
+ return Attribute::make(
+ get: fn () => $this->avatar_type === 'storage'
+ ? Storage::disk(config('shopper.core.storage.disk_name'))->url($this->avatar_location)
+ : $this->defaultProfilePhotoUrl()
+ );
}
protected function defaultProfilePhotoUrl(): string
diff --git a/packages/core/src/Traits/HasStock.php b/packages/core/src/Traits/HasStock.php
index 473a1885d..3ede704f1 100644
--- a/packages/core/src/Traits/HasStock.php
+++ b/packages/core/src/Traits/HasStock.php
@@ -5,6 +5,7 @@
namespace Shopper\Core\Traits;
use DateTimeInterface;
+use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
@@ -12,12 +13,19 @@
trait HasStock
{
- public function getStockAttribute(): int
+ public function stock(): Attribute
{
- return $this->stock();
+ return Attribute::make(
+ get: fn () => $this->getStock(),
+ );
}
- public function stock(DateTimeInterface $date = null): int
+ public function inStock(int $quantity = 1): bool
+ {
+ return $this->stock > 0 && $this->stock >= $quantity;
+ }
+
+ public function getStock(DateTimeInterface $date = null): int
{
$date = $date ?: Carbon::now();
@@ -44,7 +52,7 @@ public function stockInventory(int $inventoryId, string $date = null): int
->sum('quantity');
}
- public function increaseStock(int $inventoryId, int $quantity = 1, array $arguments = []): InventoryHistory
+ public function mutateStock(int $inventoryId, int $quantity = 1, array $arguments = []): InventoryHistory
{
return $this->createStockMutation($quantity, $inventoryId, $arguments);
}
@@ -54,11 +62,6 @@ public function decreaseStock(int $inventoryId, int $quantity = 1, array $argume
return $this->createStockMutation(-1 * abs($quantity), $inventoryId, $arguments);
}
- public function mutateStock(int $inventoryId, int $quantity = 1, array $arguments = []): InventoryHistory
- {
- return $this->createStockMutation($quantity, $inventoryId, $arguments);
- }
-
public function clearStock(int $inventoryId = null, int $newQuantity = null, array $arguments = []): bool
{
$this->inventoryHistories()->delete();
@@ -70,11 +73,6 @@ public function clearStock(int $inventoryId = null, int $newQuantity = null, arr
return true;
}
- public function inStock(int $quantity = 1): bool
- {
- return $this->stock > 0 && $this->stock >= $quantity;
- }
-
public function setStock(int $newQuantity, int $inventoryId, array $arguments = []): ?InventoryHistory
{
$currentStock = $this->stock;
@@ -87,12 +85,7 @@ public function setStock(int $newQuantity, int $inventoryId, array $arguments =
return $this->createStockMutation($deltaStock, $inventoryId, $arguments);
}
- public function inventoryHistories(): MorphMany
- {
- return $this->morphMany(InventoryHistory::class, 'stockable')->orderBy('created_at', 'desc');
- }
-
- protected function createStockMutation(int $quantity, int $inventoryId, array $arguments = []): InventoryHistory
+ public function createStockMutation(int $quantity, int $inventoryId, array $arguments = []): InventoryHistory
{
$reference = Arr::get($arguments, 'reference');
@@ -111,4 +104,9 @@ protected function createStockMutation(int $quantity, int $inventoryId, array $a
return $this->inventoryHistories()->create($createArguments);
}
+
+ public function inventoryHistories(): MorphMany
+ {
+ return $this->morphMany(InventoryHistory::class, 'stockable')->orderBy('created_at', 'desc');
+ }
}
diff --git a/packages/core/src/helpers.php b/packages/core/src/helpers.php
index a3103a64e..8f0607844 100644
--- a/packages/core/src/helpers.php
+++ b/packages/core/src/helpers.php
@@ -16,7 +16,9 @@
if (! function_exists('generate_number')) {
function generate_number(): string
{
- $lastOrder = Order::query()->orderBy('id', 'desc')->limit(1)->first();
+ $lastOrder = Order::query()->orderBy('id', 'desc')
+ ->limit(1)
+ ->first();
$generator = [
'start_sequence_from' => 1,
@@ -46,7 +48,7 @@ function shopper_version(): string
if (! function_exists('shopper_table')) {
function shopper_table(string $table): string
{
- if ('' !== config('shopper.core.table_prefix')) {
+ if (config('shopper.core.table_prefix') !== '') {
return config('shopper.core.table_prefix') . $table;
}
@@ -120,17 +122,32 @@ function shopper_setting(string $key): mixed
}
if (! function_exists('useTryCatch')) {
- function useTryCatch(Closure $closure): array
+ function useTryCatch(Closure $closure, Closure $catchable = null): array
{
$result = null;
$throwable = null;
+ $catch = $catchable ?? fn (Throwable $exception) => $exception;
+
try {
$result = $closure();
} catch (Throwable $exception) {
- $throwable = $exception;
+ $throwable = $catch($exception);
}
return [$throwable, $result];
}
}
+
+if (! function_exists('isoToEmoji')) {
+ function isoToEmoji(string $code): string
+ {
+ return implode(
+ '',
+ array_map(
+ fn (string $letter) => mb_chr(ord($letter) % 32 + 0x1F1E5),
+ mb_str_split($code)
+ )
+ );
+ }
+}