Merge branch 'trunk'

This commit is contained in:
Noah Lancien 2024-10-08 12:47:51 +02:00
commit d1941b6f7c
239 changed files with 6517 additions and 1485 deletions

View file

@ -73,3 +73,8 @@ SAML2_CONTACT_SUPPORT_EMAIL=
GOOGLE_RECAPTCHA_PUBLIC=
GOOGLE_RECAPTCHA_PRIVATE=
GOOGLE_RECAPTCHA_VERSION=
## MERCANET
MERCANET_SECRET=
MERCANET_MERCHAND_ID=
MERCANET_ENV=

View file

@ -16,7 +16,7 @@ class Kernel extends ConsoleKernel
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
protected function schedule(Schedule $schedule): void
{
$schedule->job(FetchDigitalRecruiterOffers::class)->daily();
$schedule->job(DeleteOldMessages::class)->dailyAt('14:15');
@ -28,7 +28,7 @@ class Kernel extends ConsoleKernel
*
* @return void
*/
protected function commands()
protected function commands(): void
{
$this->load(__DIR__ . '/Commands');

View file

@ -25,7 +25,6 @@ enum ActivityLogsEventEnum: int
self::deleted->name => 'Suppression',
];
/**
* Custom added classes definition
*/

View file

@ -0,0 +1,13 @@
<?php
namespace App\Enums\Arcadia;
use App\Traits\Enums\BaseEnum;
enum ArcadiaOrderType: int
{
use BaseEnum;
case cb = 1;
case check = 2;
}

View file

@ -25,7 +25,7 @@ enum BreedingTypeEnum: int
self::breedingHealth->name => 'La santé des volailles',
];
/**
/**
* Get all breeding pages.
*
* @return array

View file

@ -8,7 +8,7 @@ enum ContactFormCivility: int
{
use BaseEnum;
case m = 1;
case m = 1;
case mme = 2;
/**
@ -17,7 +17,7 @@ enum ContactFormCivility: int
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::m->name => 'M',
self::m->name => 'M',
self::mme->name => 'Mme',
];
}

View file

@ -45,13 +45,14 @@ enum ContactFormType: int
sur le site.',
self::others => 'Je souhaite faire une réclamation sur un jeu Le Gaulois ou je rencontre un problème
sur le site.',
self::nl => '',
};
}
/**
* Get the picto src/alt.
*
* @return string
* @return array
*/
public function picto(): array
{

View file

@ -0,0 +1,44 @@
<?php
namespace App\Enums\Mercanet;
use App\Traits\Enums\BaseEnum;
enum PaymentResponse: int
{
use BaseEnum;
case ok = 00;
case invalidIds = 03;
case invalidParameters = 12;
case canceled = 17;
case invalidRequestFormat = 30;
case securityIssue = 34;
case transactionAlreadyExists = 94;
case expired = 97;
case unreachableService = 99;
case internalIssue = 500;
/**
* Optionnal labels definition.
*
* @phpcs:disable Generic.Files.LineLength.TooLong
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::ok->name => 'Situation normale suivie du processus normal
d\'affichage des pages de paiement.',
self::invalidIds->name => 'L’identifiant commerçant ou le contrat acquéreur sont invalides.',
self::invalidParameters->name => 'Les paramètres de la transaction sont invalides. Vérifiez les
paramètres de la requête.',
self::canceled->name => 'Transaction annulée',
self::invalidRequestFormat->name => 'Le format de la requête est invalide.',
self::securityIssue->name => 'Problème de sécurité, par ex. le sceau calculé est incorrect.',
self::transactionAlreadyExists->name => 'La transaction existe déjà.',
self::expired->name => 'Délais expiré',
self::unreachableService->name => 'Service temporairement indisponible',
self::internalIssue->name => 'Erreur interne, eg: probleme appel CURL'
];
//phpcs:enable
}

View file

@ -0,0 +1,35 @@
<?php
namespace App\Enums\Mercanet;
use App\Traits\Enums\BaseEnum;
enum RedirectionStatusCode: int
{
use BaseEnum;
case redirect = 0;
case requestError03 = 3;
case requestError12 = 12;
case requestError30 = 30;
case requestError34 = 34;
case referenceAlreadyUsed = 94;
case serviceDisponibiltyIssue = 99;
case internalIssue = 500;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::redirect->name => 'Redirection Acceptée',
self::requestError03->name => 'Problème de request code 03',
self::requestError12->name => 'Problème de request code 12',
self::requestError30->name => 'Problème de request code 30',
self::requestError34->name => 'Problème de request code 34',
self::referenceAlreadyUsed->name => 'La référence de transaction à déja été utilisée',
self::serviceDisponibiltyIssue->name => 'Problème de disponibilité du service de paiement',
self::internalIssue->name => 'Erreur interne, eg: probleme appel CURL'
];
}

View file

@ -0,0 +1,37 @@
<?php
namespace App\Enums\Mercanet;
use App\Traits\Enums\BaseEnum;
enum TransactionResponse: int
{
use BaseEnum;
case accepted = 00;
case refused = 05;
case canceled = 17;
case fraud = 34;
case maxReached = 75;
case technicalIssue = 90;
case duplicate = 94;
case expired = 97;
case internalIssue = 500;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::accepted->name => 'Paiement accepté',
self::refused->name => 'Paiement refusé',
self::canceled->name => 'Paiement annulé',
self::fraud->name => 'Paiement refusé pour fraude',
self::maxReached->name => 'Paiement refusé pour nombre max essais atteint',
self::technicalIssue->name => 'Paiement refusé pour problème technique',
self::duplicate->name => 'Transaction dupliquée',
self::expired->name => 'Paiement expiré',
self::internalIssue->name => 'Erreur interne, eg: probleme appel CURL'
];
}

View file

@ -1,6 +1,6 @@
<?php
namespace App\Enums\Club;
namespace App\Enums\News;
use App\Traits\Enums\BaseEnum;

View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums\Shop;
use App\Traits\Enums\BaseEnum;
enum ContactFormCivility: int
{
use BaseEnum;
case m = 1;
case mme = 2;
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::m->name => 'M',
self::mme->name => 'Mme',
];
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\Enums\Shop;
use App\Traits\Enums\BaseEnum;
enum OrderStatus: int
{
use BaseEnum;
case waiting = 1;
case failed = 2;
case payed = 3;
case waitingCheck = 4;
case sentCheck = 5;
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::waiting->name => 'En attente',
self::failed->name => 'Échec',
self::payed->name => 'Réglée',
self::waitingCheck->name => 'En attente du chèque bancaire',
self::sentCheck->name => 'Envoi du chèque bancaire',
];
}

View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums\Shop;
use App\Traits\Enums\BaseEnum;
enum OrderType: int
{
use BaseEnum;
// case cb = 1;
case check = 2;
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
// self::cb->name => 'Carte Bancaire',
self::check->name => 'Chèque',
];
}

View file

@ -0,0 +1,41 @@
<?php
namespace App\Enums\Shop;
use App\Traits\Enums\BaseEnum;
enum SellItemsType: int
{
use BaseEnum;
case paper = 1;
case magnetic = 2;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::paper->name => 'Papier',
self::magnetic->name => 'Magnétique',
];
/**
* Custom added color definition.
*/
private const COLOR = [
self::paper->name => 'danger',
self::magnetic->name => 'warning',
];
/**
* Get color.
*
* @return string
*/
public function color(): string
{
return self::COLOR[$this->name];
}
}

View file

@ -4,4 +4,6 @@ namespace App\Exceptions;
use Exception;
class AbortContactMailer extends Exception {}
class AbortContactMailer extends Exception
{
}

View file

@ -0,0 +1,9 @@
<?php
namespace App\Exceptions;
use Exception;
class CBPayementError extends Exception
{
}

View file

@ -3,8 +3,6 @@
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@ -28,7 +26,7 @@ class LoginController extends Controller
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard(): StatefulGuard
protected function guard(): \Illuminate\Contracts\Auth\StatefulGuard
{
return Auth::guard('backend');
}
@ -38,7 +36,7 @@ class LoginController extends Controller
*
* @return \Illuminate\Contracts\View\View
*/
public function showLoginForm(): View
public function showLoginForm(): \Illuminate\Contracts\View\View
{
return view('bo.auth.login');
}
@ -59,7 +57,7 @@ class LoginController extends Controller
* @param \Illuminate\Http\Request $request
* @return boolean
*/
protected function attemptLogin(Request $request)
protected function attemptLogin(Request $request): bool
{
$credentials = $this->credentials($request);
// * Attempt login only using published users.

View file

@ -2,7 +2,7 @@
namespace App\Http\Controllers\Bo;
use App\Enums\Club\NewsClubTypeEnum;
use App\Enums\News\NewsClubTypeEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\NewsClubs\StoreNewsClubRequest;
use App\Http\Requests\Bo\NewsClubs\UpdateNewsClubRequest;

View file

@ -185,7 +185,10 @@ class ProductController extends Controller
public function update(UpdateProductRequest $request, Product $product): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $product) {
$product->fill(Arr::except($request->validated(), ['labels', 'productTypes', 'claims', 'nutritionnal_values']));
$product->fill(Arr::except(
$request->validated(),
['labels', 'productTypes', 'claims', 'nutritionnal_values']
));
$product->labels()->sync(collect($request->validated()['labels'] ?? [])->pluck('id'));
$product->productTypes()->sync(collect($request->validated()['productTypes'] ?? [])->pluck('id'));
$product->claims()->sync(collect($request->validated()['claims'] ?? [])->pluck('id'));

View file

@ -0,0 +1,176 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\SellItems\StoreSellItemRequest;
use App\Http\Requests\Bo\SellItems\UpdateSellItemRequest;
use App\Models\SellItem;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class SellItemController extends Controller
{
use UpdateModelPublished;
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(SellItem::class);
}
/**
* Display a listing of the resource.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function index(Request $request): \Illuminate\Contracts\View\View
{
/** @var \Illuminate\Database\Eloquent\Builder $query */
$query = SellItem::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$query,
$search,
null,
'name',
);
}
$searchFields = \implode(', ', [
trans('validation.attributes.name'),
]);
/** Sort columns with a query */
$this->sortQuery($query);
/** Custom pagination */
$sellItemModels = $this->paginate($query);
return view('bo.pages.sell_items.index', compact('sellItemModels', 'search', 'searchFields'));
}
/**
* Show the specified resource.
*
* @param \App\Models\SellItem $sellItem
* @return \Illuminate\Contracts\View\View
*/
public function show(SellItem $sellItem): \Illuminate\Contracts\View\View
{
return view('bo.pages.sell_items.show', ['sellItemModel' => $sellItem]);
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\SellItem $sellItem
* @return \Illuminate\Contracts\View\View
*/
public function create(SellItem $sellItem): \Illuminate\Contracts\View\View
{
return view('bo.pages.sell_items.create', ['sellItemModel' => $sellItem]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\SellItems\StoreSellItemRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreSellItemRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$sellItemModel = new SellItem();
$sellItemModel->fill($request->validated());
if ($sellItemModel->saveOrFail()) {
return redirect()->route('bo.sell_items.edit', $sellItemModel)
->with('success', trans('crud.messages.has_been_created', [
'model' => Str::ucfirst(trans_choice('models.classes.sell_item', 1))
]));
}
return redirect()->back()
->with('error', trans('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(trans_choice('models.classes.sell_item', 1))
]));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\SellItem $sellItem
* @return \Illuminate\Contracts\View\View
*/
public function edit(SellItem $sellItem): \Illuminate\Contracts\View\View
{
return view('bo.pages.sell_items.edit', ['sellItemModel' => $sellItem]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\SellItems\UpdateSellItemRequest $request
* @param \App\Models\SellItem $sellItem
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateSellItemRequest $request, SellItem $sellItem): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $sellItem) {
$sellItem->fill($request->validated());
if ($sellItem->saveOrFail()) {
return redirect()->route('bo.sell_items.edit', $sellItem)
->with('success', trans('crud.messages.has_been_updated', [
'model' => Str::ucfirst(trans_choice('models.classes.sell_item', 1))
]));
}
return redirect()->route('bo.sell_items.edit', $sellItem)
->with('error', trans('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(trans_choice('models.classes.sell_item', 1))
]));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\SellItem $sellItem
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(SellItem $sellItem): \Illuminate\Http\RedirectResponse
{
/** @var array<string,string> */
$previousQueries = [];
\parse_str(\parse_url(url()->previous(), \PHP_URL_QUERY), $previousQueries);
if ($sellItem->deleteOrFail()) {
return redirect()->route('bo.sell_items.index', $previousQueries)
->with('success', trans('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.sell_item', 1))
]));
}
return redirect()->back()
->with('error', trans('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.sell_item', 1))
]));
}
/**
* Duplicate the specified resource.
*
* @param \App\Models\SellItem $sellItem
* @return \Illuminate\Contracts\View\View
*/
public function duplicate(SellItem $sellItem): \Illuminate\Contracts\View\View
{
return $this->create($sellItem->replicate());
}
}

View file

@ -2,7 +2,7 @@
namespace App\Http\Controllers\Bo;
use App\Enums\Club\NewsClubTypeEnum;
use App\Enums\News\NewsClubTypeEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\SurveysAnswers\StoreSurveysAnswerRequest;
use App\Http\Requests\Bo\SurveysAnswers\UpdateSurveysAnswerRequest;
@ -242,10 +242,12 @@ class SurveysAnswerController extends Controller
return back()->with('error', trans('crud.messages.order_not_changed'));
}
return DB::transaction(function () use ($request, $className, $model) {
/** @var \App\Models\NewsClub $newsClubModel */
$newsClubModel = request()->route()->parameter('news_club');
/** @var \Illuminate\Database\Eloquent\Model|null */
$tmp = $className::query()
->when(request()->route()->parameter('news_club'), function (Builder $q) {
$q->where('news_club_id', request()->route()->parameter('news_club')->getKey());
->when($newsClubModel, function (Builder $q) use ($newsClubModel) {
$q->where('news_club_id', $newsClubModel->getKey());
})
->where('order', $request->direction ? '<' : '>', $model->getOriginal('order'))
->orderBy('order', $request->direction ? 'DESC' : 'ASC')

View file

@ -3,6 +3,7 @@
namespace App\Http\Controllers\Club\Auth;
use App\Http\Controllers\Controller;
use App\Lib\Utils;
use App\Models\Customer;
use Exception;
use Illuminate\Database\Eloquent\Model;
@ -10,6 +11,7 @@ use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
@ -65,21 +67,43 @@ class LoginController extends Controller
*/
protected function attemptLogin(Request $request): bool
{
$credentials = $this->credentials($request);
$credentials = $this->credentials($request);
$customerModel = Customer::query()->where('email', Arr::get($credentials, 'email'))->first();
$crmCustomer = CrmCustomer::findWithEmail(Arr::get($credentials, 'email'));
// Check database customer.
if (!$customerModel) {
return false;
}
// Check crm customer.
if (!$crmCustomer) {
return false;
}
/** @var \App\Models\Customer $customerModel */
$customerModel = new Customer(Arr::only($crmCustomer->jsonSerialize(), ['email']));
$customerModel->username = Utils::getUniquePseudo(
$crmCustomer->firstname,
$crmCustomer->lastname
);
$customerModel->hashcode = $crmCustomer->hashcode;
if (!$customerModel->saveOrFail()) {
return false;
}
} else {
// Check crm customer.
if (!$crmCustomer) {
$customerModel->delete();
return false;
}
} //end if
// Check CRM customer.
try {
CrmCustomer::login(Arr::get($credentials, 'email'), Arr::get($credentials, 'password'));
} catch (Exception $ex) {
Log::error($ex);
return false;
}
$this->guard()->loginUsingId($customerModel->getKey());
return true;
}

View file

@ -104,7 +104,7 @@ class VerificationController extends Controller
}
/**
* Get the post register / login redirect path.
* Get the post register/login redirect path.
*
* @return string
*/
@ -114,7 +114,7 @@ class VerificationController extends Controller
}
/**
* Set Crm Customer active
* Set crm customer active.
*
* @param \App\Models\Customer $customer
* @return void

View file

@ -55,7 +55,6 @@ class DiscountController extends Controller
'Content-Type' => 'application/pdf',
'Expires' => 'Sat, 26 Jul 1997 05:00:00 GMT',
'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT',
// For glory.
'X-Generator' => 'mPDF'
]);
}
@ -254,6 +253,4 @@ class DiscountController extends Controller
return false;
} //end try
}
// * STATIC Fetch BR
}

View file

@ -2,30 +2,455 @@
namespace App\Http\Controllers\Club;
use App\Enums\Customers\Civility;
use App\Enums\Mercanet\PaymentResponse;
use App\Enums\Mercanet\RedirectionStatusCode;
use App\Enums\Mercanet\TransactionResponse;
use App\Enums\Shop\OrderStatus;
use App\Enums\Shop\OrderType;
use App\Exceptions\CBPayementError;
use App\Http\Controllers\Controller;
use App\Http\Requests\Club\Shop\ShopBuyRequest;
use App\Jobs\Arcadia\SendOrderToArcadia;
use App\Jobs\Shop\SendShopMail;
use App\Lib\Mercanet\Mercanet;
use App\Models\DeliveryAddress;
use App\Models\Notification;
use App\Models\Order;
use App\Models\SellItem;
use Exception;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\QueryException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ShopController extends Controller
{
/**
* Show index page
* Shop index.
*
* @return \Illuminate\Contracts\View\View
*/
public function index(): \Illuminate\Contracts\View\View
{
return view('club.pages.shop.index');
$sellItemModels = SellItem::all();
return view('club.pages.shop.index', compact('sellItemModels'));
}
/**
* Show index page
* Ajax service to validate transaction details.
*
* @return \Illuminate\Contracts\View\View
* @param \App\Http\Requests\Club\Shop\ShopBuyRequest $request
* @return \Illuminate\Http\JsonResponse
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function create(): \Illuminate\Contracts\View\View
public function validateBuy(ShopBuyRequest $request): \Illuminate\Http\JsonResponse
{
/** @var \App\Models\Customer $customerModel */
$customerModel = auth('club')->user();
$crmCustomer = $customerModel->api_data;
return view('club.pages.shop.recap', compact('crmCustomer'));
// phpcs:enable
/** @var \App\Models\Customer */
$customerModel = auth('club')->user();
$items = [];
$orderTotalPrice = 0;
foreach ($request->cart as $item) {
$sellItem = SellItem::query()->where('id', $item['item']['id'])->firstOrFail();
$items[] = [
'id' => $sellItem->id,
'name' => $sellItem->name,
'quantity' => $item['count'],
'unitPrice' => $sellItem->price,
'totalPrice' => $item['count'] * $sellItem->price,
'subject' => $sellItem->arcadia_id
];
$orderTotalPrice += $item['count'] * $sellItem->price;
}
// * Pseudo mutex let database fail (unique ref) to check if order has already been processed
try {
$order = new Order();
$order->ref = str_replace('-', '', $request->ref);
$order->civility = Civility::make(intval($request->civility));
$order->payementType = OrderType::make(intval($request->payementMethod));
$order->status = OrderStatus::waiting;
$order->customer_id = $customerModel->getKey();
$order->fill($request->coords);
$order->saveOrFail();
} catch (QueryException $e) {
$order = Order::query()->where('ref', str_replace('-', '', $request->ref))->firstOrFail();
if ($order->payementType->equals(OrderType::check)) {
return response()->json(['redirect' => route(
'club.shop.validated',
compact('order')
)]);
}
// FIXME: uncomment when mercanet cb is ready.
// if ($order->payementType->equals(OrderType::cb)) {
// return response()->json(['redirect' => route(
// 'club.shop.payementCB',
// compact('order')
// )]);
// }
abort(500, sprintf('Order already exists but type is unkown %d', $order->id));
} //end try
$order->customer()->associate($customerModel);
foreach ($items as $item) {
$order->sellItems()->withTimestamps()->attach($item['id'], ['quantity' => $item['quantity']]);
}
$order->saveOrFail();
if ($request->shipping) {
$shipping = new DeliveryAddress();
$shipping->fill($request->shipping);
$shipping->order()->associate($order);
$shipping->saveOrFail();
}
switch ($request->payementMethod) {
// FIXME: uncomment when mercanet cb is ready.
// case OrderType::cb->value():
// \session()->put(sprintf('shop.order.%d.time', $order->id), \time());
// \session()->save();
// return response()->json(['redirect' => route('club.shop.payementCB', compact('order'))]);
case OrderType::check->value():
try {
\session()->put(sprintf('shop.order.%d.time', $order->id), \time());
\session()->save();
SendOrderToArcadia::dispatch($order);
SendShopMail::dispatch($order);
$order->status = OrderStatus::waitingCheck;
$order->saveOrFail();
} catch (Exception $e) {
report($e);
Log::critical(sprintf(
'Could not end customer transaction (save and send mail) in shop for order %d, %s',
$order->id,
$e->getMessage()
));
} finally {
return response()->json(['redirect' => route('club.shop.validated', compact('order'))]);
}
break;
// * not used
default:
abort(422);
} //end switch
}
/**
* Redirection After Ajax validate.
*
* @param \App\Models\Order $order
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Contracts\View\View
*/
public function validatedBuy(Order $order): \Illuminate\Http\RedirectResponse|\Illuminate\Contracts\View\View
{
Notification::getNotifications();
$time = session()->get(sprintf('shop.order.%d.time', $order->id), 0);
if (!($order->status->equals(OrderStatus::payed) || $order->status->equals(OrderStatus::waitingCheck))) {
return response()->redirectToRoute('club.shop.index');
}
// 4 minutes
if (($time + (60 * 4)) < \time()) {
return response()->redirectToRoute('club.shop.index');
}
return view('club.pages.shop.validated');
}
/**
* Pay with CB.
*
* @param \App\Models\Order $order
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
* @throws \App\Exceptions\CBPayementError Error response from Mercanet Lib.
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function payWithCb(Order $order): \Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
{
// phpcs:enable
Notification::getNotifications();
try {
$time = session()->get(sprintf('shop.order.%d.time', $order->id), 0);
if ($order->status->equals(OrderStatus::failed)) {
return view('club.pages.shop.error')
->with('error', trans('Commande annulée, veuillez réessayer'));
}
// 4 minutes
if (($time + (60 * 4)) < \time()) {
return view('club.pages.shop.error')
->with('error', trans('Délai d\'attente expiré, veuillez réessayer'));
}
$totalToPay = $order->sellItems->map(function ($sellItem) {
return $sellItem->pivot->quantity * $sellItem->price;
})->sum();
// * Convert total in cents
$totalToPay = (int)(\number_format((float)$totalToPay, 2) * 100);
$mercanet = $this->getMercanet($order);
$payment = $mercanet->QuickPayment($totalToPay, $order->ref);
switch ($payment->code) {
case RedirectionStatusCode::redirect->value():
return view('club.pages.shop.redirectMercanet', [
'url' => $payment->url,
'data' => $payment->data,
'version' => $payment->version
]);
case RedirectionStatusCode::referenceAlreadyUsed:
return response()->redirectToRoute('club.shop.index');
case RedirectionStatusCode::requestError03->value():
case RedirectionStatusCode::requestError12->value():
case RedirectionStatusCode::requestError30->value():
case RedirectionStatusCode::requestError34->value():
case RedirectionStatusCode::serviceDisponibiltyIssue->value():
$order->status = OrderStatus::failed;
$order->save();
throw new CBPayementError(sprintf(
"Error response from Mercanet Lib : %s\n %s",
RedirectionStatusCode::make(intval($payment->code))->label(),
json_encode($payment)
));
default:
$order->status = OrderStatus::failed;
$order->save();
throw new CBPayementError(sprintf(
'Un handled response from Mercanet Lib %s',
json_encode($payment)
));
} //end switch
} catch (ModelNotFoundException | CBPayementError $e) {
report($e);
Log::critical(sprintf(
'Could not end customer transaction in boutique for order %d, %s',
$order->id,
$e->getMessage()
));
return view('club.pages.shop.error')
->with('error', trans('La commande que vous venez de passer n\'a pu aboutir, veuillez réessayer'));
} //end try
}
/**
* Pas de validate ou custom request sur la réponse de mercanet,
* c'est la Lib mercanet qui fait.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Order $order
* @return \Illuminate\Http\Response|\Illuminate\Contracts\Routing\ResponseFactory
* @throws \App\Exceptions\CBPayementError Data were altered from response.
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function confirmCbFromMercanet(
Request $request,
Order $order
): \Illuminate\Http\Response|\Illuminate\Contracts\Routing\ResponseFactory {
// phpcs:enable
try {
\extract($this->getMercanetData($request));
/** @var \App\Models\Order */
$order = Order::query()->where('ref', $ref)->firstOrFail();
$mercanet = $this->getMercanet($order);
$mercanet->setResponse($request->post());
if (!$mercanet->isValid()) {
$order->status = OrderStatus::failed;
$order->save();
throw new CBPayementError('Data were altered from response');
}
switch ($responseCode) {
case TransactionResponse::accepted:
$order->status = OrderStatus::payed;
$order->save();
SendOrderToArcadia::dispatch($order);
SendShopMail::dispatch($order);
break;
case TransactionResponse::canceled:
case TransactionResponse::expired:
case TransactionResponse::refused:
case TransactionResponse::fraud:
case TransactionResponse::duplicate:
case TransactionResponse::maxReached:
if (
!$order->confirmMailSent and
!$order->status->equals(OrderStatus::payed)
) {
$order->status = OrderStatus::failed;
$order->save();
}
break;
case TransactionResponse::technicalIssue:
throw new CBPayementError(sprintf(
'Error from Mercanet Server %s on ref %s, %s',
$responseCode,
$ref,
json_encode($returnDatas)
));
default:
// * ERROR
if (
!$order->confirmMailSent and
!$order->status->equals(OrderStatus::payed)
) {
$order->status = OrderStatus::failed;
$order->save();
}
throw new CBPayementError(sprintf(
'Un handled response from Mercanet Server %s on ref %s',
$responseCode,
$ref,
json_encode($returnDatas)
));
} //end switch
} catch (ModelNotFoundException | CBPayementError | \Exception $e) {
report($e);
Log::critical(sprintf(
'Could not end customer transaction in boutique for order %d, %s',
$order->id,
$e->getMessage()
));
} finally {
return response('', 200);
} //end try
}
/**
*
* Pas de validate ou custom request sur la réponse de mercanet,
* c'est la Lib mercanet qui fait.
*
* @param Request $request
* @param Order $order
* @return \Illuminate\Contracts\View\View
* @throws \App\Exceptions\CBPayementError Data were altered from response.
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function confirmCb(Request $request, Order $order): \Illuminate\Contracts\View\View
{
// phpcs:enable
Notification::getNotifications();
try {
if ($order->status->equals(OrderStatus::failed)) {
return view('club.pages.shop.error');
}
if ($order->status->equals(OrderStatus::payed)) {
return view('club.pages.shop.validated');
}
$mercanet = $this->getMercanet($order);
$mercanet->setResponse($request->post());
if (!$mercanet->isValid()) {
try {
$order->status = OrderStatus::failed;
$order->saveOrFail();
} finally {
throw new CBPayementError("Data were altered from response");
}
}
\extract($this->getMercanetData($request));
switch ($responseCode) {
case PaymentResponse::ok:
try {
$status = $order->status;
$order->status = OrderStatus::payed;
$order->saveOrFail();
if ($status->equals(OrderStatus::waiting)) {
SendOrderToArcadia::dispatch($order);
SendShopMail::dispatch($order);
}
} catch (Exception $e) {
report($e);
Log::critical(sprintf(
'Could not end customer transaction (save and send mail) in boutique for order %d, %s',
$order->id,
$e->getMessage()
));
} finally {
return view('club.pages.shop.validated');
}
case PaymentResponse::canceled:
$order->status = OrderStatus::failed;
$order->saveOrFail();
return view('club.pages.shop.error');
case PaymentResponse::invalidIds:
case PaymentResponse::invalidRequestFormat:
case PaymentResponse::invalidParameters:
case PaymentResponse::unreachableService:
case PaymentResponse::securityIssue:
case PaymentResponse::transactionAlreadyExists:
case PaymentResponse::expired:
case PaymentResponse::internalIssue:
$order->status = OrderStatus::failed;
$order->saveOrFail();
throw new CBPayementError(sprintf(
"Error response from Mercanet Lib : %s\n %s",
PaymentResponse::make($responseCode)->label,
json_encode($returnDatas)
));
default:
$order->status = OrderStatus::failed;
$order->save();
throw new CBPayementError(sprintf(
'Un handled response from Mercanet Lib %s',
json_encode($returnDatas)
));
} //end switch
} catch (ModelNotFoundException | CBPayementError $e) {
report($e);
Log::critical(sprintf(
'Could not end customer transaction in boutique for order %d, %s',
$order->id,
$e->getMessage()
));
return view('club.pages.shop.error');
} //end try
}
/**
* Get initialized Mercanet object.
*
* @param \App\Models\Order $order
* @return \App\Lib\Mercanet\Mercanet
*/
private function getMercanet(Order $order): \App\Lib\Mercanet\Mercanet
{
return new Mercanet(
config('mercanet.secret'),
config('mercanet.merchantId'),
config('mercanet.env'),
route('club.shop.reglement.payementConfirmCB', $order),
route('club.shop.reglement.payementConfirmCBServ', $order)
);
}
/**
* Get Mercanet ref and responseCode for request.
*
* @param \Illuminate\Http\Request $request
* @return array<string,string> array['ref' => 'value', 'responseCode' => 'value']
*/
private function getMercanetData(Request $request): array
{
$formDatas = [];
$returnDatas = explode("|", $request->post('Data'));
foreach ($returnDatas as $item) {
$tmp = explode("=", $item);
$formDatas[$tmp[0]] = $tmp[1];
}
$ref = $formDatas['transactionReference'];
$responseCode = $formDatas['responseCode'];
return compact('ref', 'responseCode', 'returnDatas');
}
}

View file

@ -26,10 +26,7 @@ class BreederController extends Controller
return File::json(base_path('/public/departments.geojson'));
}
);
return response()->json(
[$departmentGeoJson]
);
return response()->json([$departmentGeoJson]);
}
/**
@ -39,7 +36,7 @@ class BreederController extends Controller
*/
public function getBreederCountPerDepartment(): \Illuminate\Http\JsonResponse
{
// TODO: mettre à jour le cache lors de l'édition/ajout/suppression d'un éleveur
// TODO: mettre à jour le cache lors de l'édition/ajout/suppression d'un éleveur.
$breederCountPerDepartment = Cache::rememberForever(
'breederCountPerDepartment',
function () {
@ -50,10 +47,7 @@ class BreederController extends Controller
->get()->toArray();
}
);
return response()->json(
$breederCountPerDepartment
);
return response()->json($breederCountPerDepartment);
}
/**
@ -65,7 +59,7 @@ class BreederController extends Controller
public function getDepartmentBreeders(Request $request): \Illuminate\Http\JsonResponse
{
// TODO: checker si le departement existe.
// TODO: mettre à jour le cache lors de l'édition/ajout/suppression d'un éleveur
// TODO: mettre à jour le cache lors de l'édition/ajout/suppression d'un éleveur.
$breeders = Cache::rememberForever(
sprintf('departmentBreeders%s', $request->DEPARTMENT),
function () use ($request) {
@ -76,10 +70,7 @@ class BreederController extends Controller
->get()->toArray();
}
);
return response()->json(
$breeders
);
return response()->json($breeders);
}
/**

View file

@ -3,21 +3,16 @@
namespace App\Http\Controllers\Fo;
use App\Enums\ContactFormType;
use App\Enums\Listen\ObjectEnum;
use App\Enums\StaticPageType;
use App\Exceptions\AbortContactMailer;
use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\ContactFormRequest;
use App\Jobs\Mails\SendArcadiaMail;
use App\Jobs\Mails\SendPasserelleMail;
use App\Lib\Helpers\FileStorageHelper;
use App\Models\MailContactData;
use App\Models\StaticPage;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
class ContactController extends Controller
@ -48,11 +43,11 @@ class ContactController extends Controller
// Send to Passerelle if it is a compalin about a product.
if ($request->type == ContactFormType::complain->value) {
$joinFilePath = null;
$joinFile = '';
$joinFilePath = null;
$joinFile = '';
$uniqIdDirectory = \uniqid();
if ($request->file('joinFile')) {
$joinFile = Storage::disk('local')->put(
$joinFile = Storage::disk('local')->put(
sprintf('public/tmp/%s', $uniqIdDirectory),
$request->file('joinFile')
);
@ -67,8 +62,11 @@ class ContactController extends Controller
return back()->with('success', __('Votre message a été envoyé avec succès'));
} catch (AbortContactMailer $e) {
Log::error('Fail to build mail from complain page ', ['exception' => $e]);
}
return back()->withInput()->with('error', 'Une erreur est survenue durant l\'envoi de votre message. Veuillez réessayer ultèrieurement.');
} //end try
return back()->withInput()->with(
'error',
'Une erreur est survenue durant l\'envoi de votre message. Veuillez réessayer ultérieurement.'
);
});
}
}

View file

@ -9,7 +9,6 @@ class ExportController extends Controller
/**
* Contact page.
*
* @param \App\Models\StaticPage $staticPageModel
* @return \Illuminate\Contracts\View\View
*/
public function nl(): \Illuminate\Contracts\View\View

View file

@ -70,7 +70,7 @@ class Kernel extends HttpKernel
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
'logoutusers' => \App\Http\Middleware\LogoutUnpublishedUsers::class,
];
}

View file

@ -18,7 +18,7 @@ class Authenticate extends Middleware
{
$logins = [
'backend' => route('bo.login'),
'club' => route('club.login')
'club' => route('club.login')
];
if (!$request->expectsJson()) {
// * Notify must login
@ -34,7 +34,6 @@ class Authenticate extends Middleware
}
return route('login');
}
return null;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Http\Middleware;
use Carbon\Carbon;
use Closure;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\URL;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class EnsureEmailIsVerified
{
/**
* Specify the redirect route for the middleware.
*
* @param string $route
* @return string
*/
public static function redirectTo(string $route): string
{
return static::class . ':' . $route;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $redirectToRoute
* @return mixed
*/
public function handle(Request $request, Closure $next, $redirectToRoute = null): mixed
{
/** @var \App\Models\Customer $customerModel */
$customerModel = $request->user();
if ($customerModel instanceof MustVerifyEmail) {
$crmCustomer = CrmCustomer::findWithEmail($customerModel->email);
// Check there is a crm customer.
if (!$crmCustomer) {
$customerModel->delete();
} else {
// Check the status of crm customer & customer model.
if ($crmCustomer->status !== $customerModel->hasVerifiedEmail()) {
$customerModel->email_verified_at = $crmCustomer->status ? Carbon::now() : null;
$customerModel->saveOrFail();
}
if (!$crmCustomer->status && !$customerModel->hasVerifiedEmail()) {
return $request->expectsJson()
? abort(403, 'Your email address is not verified.')
: Redirect::guest(URL::route($redirectToRoute ?: 'club.verification.notice'));
}
}
}
return $next($request);
}
}

View file

@ -4,7 +4,6 @@ namespace App\Http\Middleware;
use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class HtmlSanitizer
{
@ -16,8 +15,11 @@ class HtmlSanitizer
* @param string|array ...$params
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, \Closure $next, string|array ...$params): Response
{
public function handle(
Request $request,
\Closure $next,
string|array ...$params
): \Symfony\Component\HttpFoundation\Response {
$inputs = $request->all();
/** @var callable|null */
$cleanInput = null;

View file

@ -0,0 +1,28 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LogoutUnpublishedUsers
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
/** @var \App\Models\User|null $userModel */
$userModel = Auth::user();
if (!is_null($userModel) && !$userModel->published) {
Auth::logout();
return redirect()->route('bo.login')->with('warning', trans('auth.unpublished_user'));
}
return $next($request);
}
}

View file

@ -3,25 +3,26 @@
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
* @param string|null ...$guards
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
* @param string|null ...$guards
* @return \Symfony\Component\HttpFoundation\Response
* @throws \RuntimeException If guard is unhandled.
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
public function handle(Request $request, \Closure $next, ...$guards): Response
{
public function handle(
Request $request,
\Closure $next,
string|null ...$guards
): \Symfony\Component\HttpFoundation\Response {
// phpcs:enable phpcs:disable
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (auth($guard)->check()) {
switch ($guard) {
@ -37,7 +38,6 @@ class RedirectIfAuthenticated
}
}
}
return $next($request);
}
}

View file

@ -2,12 +2,10 @@
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Vite;
use Symfony\Component\HttpFoundation\Response;
class SecureHeaders
{
@ -26,14 +24,12 @@ class SecureHeaders
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Symfony\Component\HttpFoundation\Response
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
public function handle(Request $request, Closure $next): Response
public function handle(Request $request, \Closure $next): \Symfony\Component\HttpFoundation\Response
{
// phpcs:enable
// * For Vite DEV
$host = \parse_url(\config('app.url'), \PHP_URL_HOST);
View::share('nonce', $nonce = Vite::useCspNonce());
@ -105,7 +101,6 @@ class SecureHeaders
config('app.debug') ? "https://{$host}:4443" : '',
]) . ';'
];
$response->headers->set(
'Content-Security-Policy',
implode(' ', $cspPolicies) . $reportUri
@ -115,7 +110,7 @@ class SecureHeaders
}
/**
* Remove unwanted headers
* Remove unwanted headers.
*
* @param array $headerList
* @return void

View file

@ -21,8 +21,7 @@ class TrustProxies extends Middleware
*
* @var integer
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
protected $headers = Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |

View file

@ -0,0 +1,35 @@
<?php
namespace App\Http\Middleware;
use App\Lib\Helpers\ToolboxHelper;
use Closure;
use Illuminate\Http\Request;
class XssSanitizer
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$params
* @return mixed
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
public function handle(Request $request, Closure $next, mixed ...$params): mixed
{
// phpcs:enable phpcs:disable
$inputs = $request->all();
array_walk_recursive($inputs, function (&$input, $name) use ($params) {
if (in_array($name, $params)) {
$input = clean($input);
$input = ToolboxHelper::assertNoInternalUrls($name, $input);
} else {
$input = strip_tags($input);
}
});
$request->merge($inputs);
return $next($request);
}
}

View file

@ -2,7 +2,7 @@
namespace App\Http\Requests\Bo\NewsClubs;
use App\Enums\Club\NewsClubTypeEnum;
use App\Enums\News\NewsClubTypeEnum;
use App\Models\NewsClub;
use App\Rules\WysiwygLength;
use App\Traits\Requests\HasPicture;

View file

@ -2,7 +2,7 @@
namespace App\Http\Requests\Bo\NewsClubs;
use App\Enums\Club\NewsClubTypeEnum;
use App\Enums\News\NewsClubTypeEnum;
use Illuminate\Support\Facades\Gate;
class UpdateNewsClubRequest extends StoreNewsClubRequest

View file

@ -0,0 +1,76 @@
<?php
namespace App\Http\Requests\Bo\SellItems;
use App\Enums\Shop\SellItemsType;
use App\Models\SellItem;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rules\Enum;
class StoreSellItemRequest extends FormRequest
{
use HasPicture;
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return Gate::check('create', SellItem::class);
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation(): void
{
$this->mergePicture('picture');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
$rules = [
'name' => 'required|string|between:3,255',
'type' => ['required', new Enum(SellItemsType::class)],
'price' => 'required|numeric|between:0.1,100',
'picture_alt' => 'required|string|between:3,255',
'picture_title' => 'required|string|between:3,255',
'arcadia_id' => 'required|integer|between:0,1000',
'arcadia_weight' => 'required|integer|between:0,100',
];
return \array_merge(
$rules,
$this->pictureRules('picture', 450, 450, 450, 450),
);
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'name' => trans('validation.attributes.name'),
'type' => trans('validation.custom.type'),
'price' => trans('validation.attributes.price'),
'picture' => trans('validation.attributes.image'),
'picture_alt' => trans('validation.custom.attribute_alt'),
'picture_title' => trans('validation.custom.attribute_title'),
'arcadia_id' => trans('validation.custom.arcadia_id'),
'arcadia_weight' => trans('validation.custom.arcadia_weight'),
];
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace App\Http\Requests\Bo\SellItems;
use Illuminate\Support\Facades\Gate;
class UpdateSellItemRequest extends StoreSellItemRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return Gate::check('update', $this->route('sell_item'));
}
}

View file

@ -49,7 +49,7 @@ abstract class CustomerCollectionRequest extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
return [
'state' => [

View file

@ -12,7 +12,7 @@ class SaveCustomerCollectionRequest extends CustomerCollectionRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
$idEnumRule = '';
return array_merge(

View file

@ -12,7 +12,7 @@ class SearchCustomerCollectionRequest extends CustomerCollectionRequest
public function prepareForValidation(): void
{
$this->merge([
'pseudo' => $this->string('pseudo'),
'pseudo' => $this->string('pseudo'),
'departaimant' => $this->string('departaimant')
]);
parent::prepareForValidation();
@ -23,14 +23,14 @@ class SearchCustomerCollectionRequest extends CustomerCollectionRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
return array_merge(
parent::rules(),
[
'pseudo' => 'nullable',
'pseudo' => 'nullable',
'departaimant' => 'nullable',
'page' => 'required|numeric|min:1'
'page' => 'required|numeric|min:1'
]
);
}

View file

@ -23,7 +23,7 @@ class StoreCustomerRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return Auth::guard('club')->check();
}
@ -33,7 +33,7 @@ class StoreCustomerRequest extends FormRequest
*
* @return void
*/
public function prepareForValidation()
public function prepareForValidation(): void
{
try {
$this->currentCountry = Country::make(\intval($this->country));
@ -52,7 +52,7 @@ class StoreCustomerRequest extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
$countryList = implode(',', Country::getValidIsoAplha2Codes());
return [
@ -97,7 +97,7 @@ class StoreCustomerRequest extends FormRequest
*
* @return array
*/
public function attributes()
public function attributes(): array
{
return [
'lastname' => trans('validation.attributes.first_name'),

View file

@ -23,7 +23,7 @@ class UpdateCustomerRequest extends StoreCustomerRequest
*
* @return void
*/
public function prepareForValidation()
public function prepareForValidation(): void
{
parent::prepareForValidation();
$this->merge([

View file

@ -13,7 +13,7 @@ class UpdatePasswordRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return auth('club')->check();
}
@ -23,7 +23,7 @@ class UpdatePasswordRequest extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
/** @var \LDC\LDCCRM\Models\Customer $crmCustomer */
$crmCustomer = \auth('club')->user()->api_data;
@ -44,7 +44,7 @@ class UpdatePasswordRequest extends FormRequest
*
* @return array
*/
public function attributes()
public function attributes(): array
{
return [
'old_password' => trans('validation.custom.old_password'),

View file

@ -12,7 +12,7 @@ class BlockCustomerRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return Auth::guard('club')->check();
}
@ -22,7 +22,7 @@ class BlockCustomerRequest extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
return [
'username' => 'required|exists:customers,username'

View file

@ -14,7 +14,7 @@ class DeleteMessagesRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return Auth::guard('club')->check();
}
@ -24,7 +24,7 @@ class DeleteMessagesRequest extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
return [
'message' => [

View file

@ -24,7 +24,7 @@ class MarkAsReadRequest extends FormRequest
public function rules(): array
{
return [
'messageList' => 'required|array',
'messageList' => 'required|array',
'messageList.*' => 'numeric'
];
}

View file

@ -16,7 +16,7 @@ class SendMessageRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return Auth::guard('club')->check();
}
@ -26,11 +26,11 @@ class SendMessageRequest extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
return [
'message' => 'required|string|max:255|min:5',
'to' => [
'to' => [
'required',
Rule::exists('customers', 'username'),
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
@ -40,17 +40,17 @@ class SendMessageRequest extends FormRequest
$customer = Customer::query()->where('username', $value)->firstOrFail();
if (
BlockList::query()
->whereHas('customer', fn (Builder $q) => $q->where('id', $customer->id))
->whereHas('blocked', fn (Builder $q) => $q->where('id', $authCustomer->id))
->exists()
->whereHas('customer', fn (Builder $q) => $q->where('id', $customer->id))
->whereHas('blocked', fn (Builder $q) => $q->where('id', $authCustomer->id))
->exists()
) {
$fail(trans('Vous ne pouvez pas envoyer de message à cet utilisateur'));
}
if (
BlockList::query()
->whereHas('customer', fn (Builder $q) => $q->where('id', $authCustomer->id))
->whereHas('blocked', fn (Builder $q) => $q->where('id', $customer->id))
->exists()
->whereHas('customer', fn (Builder $q) => $q->where('id', $authCustomer->id))
->whereHas('blocked', fn (Builder $q) => $q->where('id', $customer->id))
->exists()
) {
$fail(trans('Vous avez bloqué cet utilisateur'));
}

View file

@ -0,0 +1,110 @@
<?php
namespace App\Http\Requests\Club\Shop;
use App\Enums\Shop\ContactFormCivility;
use App\Enums\Shop\OrderType;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
class ShopBuyRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return $this->ajax() ? true : false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [
'ref' => 'required|string|uuid|unique:orders,ref',
'coords' => 'required|array',
'coords.civility' => ['required', new Enum(ContactFormCivility::class)],
'coords.firstname' => 'required|string|between:3,255',
'coords.lastname' => 'required|string|between:3,255',
'coords.address' => 'required|string|between:3,255',
'coords.postcode' => 'required|postal_code:FR',
'coords.city' => 'required|string|between:3,255',
'coords.phone' => 'nullable|phone:FR|max:255',
'coords.email' => 'required|email:rfc,strict,dns,spoof,filter',
'shipping' => 'sometimes|array',
'shipping.civility' => ['required_with:shipping', new Enum(ContactFormCivility::class)],
'shipping.firstname' => 'required_with:shipping|string|between:3,255',
'shipping.lastname' => 'required_with:shipping|string|between:3,255',
'shipping.address' => 'required_with:shipping|string|between:3,255',
'shipping.postcode' => 'required_with:shipping|postal_code:FR',
'shipping.city' => 'required_with:shipping|string|between:3,255',
'shipping.phone' => 'nullable|phone:FR|max:255',
'cart' => 'required|array',
'cart.*' => 'required|distinct|min:1',
'cart.*.count' => 'required|numeric|min:1',
'cart.*.item.id' => 'required|numeric|exists:sell_items,id',
'payementMethod' => ['required', new Enum(OrderType::class)]
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'coords' => trans('vos coordonnées'),
'coords.civility' => trans('civilité dans vos coordonnées'),
'coords.firstname' => trans('prénom dans vos coordonnées'),
'coords.lastname' => trans('nom dans vos coordonnées'),
'coords.address' => trans('adresse dans vos coordonnées'),
'coords.postcode' => trans('code postal dans vos coordonnées'),
'coords.phone' => trans('téléphone dans vos coordonnées'),
'coords.city' => trans('ville dans vos coordonnées'),
'coords.email' => trans('e-mail dans vos coordonnées'),
'shipping' => trans('votre adresse de livraison'),
'shipping.civility' => trans('civilité dans votre adresse de livraison'),
'shipping.firstname' => trans('prénom dans votre adresse de livraison'),
'shipping.lastname' => trans('nom dans votre adresse de livraison'),
'shipping.address' => trans('adresse dans votre adresse de livraison'),
'shipping.postcode' => trans('code postal dans votre adresse de livraison'),
'shipping.phone' => trans('téléphone dans votre adresse de livraison'),
'shipping.city' => trans('ville dans votre adresse de livraison'),
'cart' => trans('panier'),
'cart.*' => trans('panier'),
'cart.*.count' => trans('nombre d\'éléments dans le panier'),
'cart.*.item.id' => trans('élément dans le panier'),
];
}
/**
* Get custom messages for validator errors.
*
* @return array
*/
public function messages(): array
{
return [
'coords.postcode.postal_code' => trans(
'Le champ :attribute accepte les codes postaux des pays suivants :countries (exemple: :examples).'
),
'shipping.postcode.postal_code' => trans(
'Le champ :attribute accepte les codes postaux des pays suivants :countries (exemple: :examples).'
),
'coords.phone.phone' => trans(
'Le champ :attribute est invalide, il accepte les numéros des pays suivants France.'
),
'shipping.phone.phone' => trans(
'Le champ :attribute est invalide, il accepte les numéros des pays suivants France.'
)
];
}
}

View file

@ -2,7 +2,7 @@
namespace App\Http\Requests\Club\Surveys;
use App\Enums\Club\NewsClubTypeEnum;
use App\Enums\News\NewsClubTypeEnum;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
@ -13,7 +13,7 @@ class StoreSurveyAnswerRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return Auth::guard('club')->check();
}
@ -38,7 +38,7 @@ class StoreSurveyAnswerRequest extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
return [
'news_club_id' => 'required|integer|exists:news_clubs,id',
@ -64,7 +64,7 @@ class StoreSurveyAnswerRequest extends FormRequest
*
* @return array
*/
public function attributes()
public function attributes(): array
{
return [
'news_club_id' => trans_choice('models.classes.news_club', 1),

View file

@ -5,10 +5,8 @@ namespace App\Http\Requests\Fo;
use App\Enums\ContactFormCivility;
use App\Enums\ContactFormType;
use App\Lib\Helpers\ToolboxHelper;
use Carbon\Carbon;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Enum;
class ContactFormRequest extends FormRequest
{
@ -36,39 +34,37 @@ class ContactFormRequest extends FormRequest
'required',
Rule::enum(ContactFormType::class)->only(ContactFormType::getContactTypes())
],
'civility' => [
'required',
Rule::enum(ContactFormCivility::class)
],
// * max arcadia 50 chars
'lastname' => 'required|min:2|max:50',
// * max arcadia 50 chars
'civility' => ['required', Rule::enum(ContactFormCivility::class)],
// Max arcadia 50 chars.
'lastname' => 'required|min:2|max:50',
// Max arcadia 50 chars.
'firstname' => 'required|min:2|max:50',
'address' => 'required|min:4',
'email' => 'required|email:rfc,dns,spoof',
'postal' => 'required|postal_code:FR',
// * max arcadia 10 chars
'town' => 'required|min:3|max:90',
'phone' => 'required|phone:FR',
'address' => 'required|min:4',
'email' => 'required|email:rfc,dns,spoof',
'postal' => 'required|postal_code:FR',
// Max arcadia 10 chars.
'town' => 'required|min:3|max:90',
'phone' => 'required|phone:FR',
// FIXME: uncomment when form on export page is ready.
// 'onepagesubject' => 'sometimes|min:10|max:250',
'message' => 'required|min:20|max:1900'
'message' => 'required|min:20|max:1900'
];
if (ContactFormType::make($this->input('type')) === ContactFormType::complain) {
$rules = array_merge(
$rules,
[
'productName' => 'required|min:2|max:100',
'productCode' => 'required|digits_between:8,13|min:1|max:9999999999999',
'buyPlace' => 'required|min:2|max:100',
'lotNumberName' => 'required|min:2|max:50',
'limitDateDay' => 'required|numeric|min:1|max:31',
'limitDateMonth' => 'required|numeric|min:1|max:31',
'limitDateYear' => 'required|numeric|min:2010|max:2050',
'consumptionDateDay' => 'required|numeric|min:1|max:31',
'productName' => 'required|min:2|max:100',
'productCode' => 'required|digits_between:8,13|min:1|max:9999999999999',
'buyPlace' => 'required|min:2|max:100',
'lotNumberName' => 'required|min:2|max:50',
'limitDateDay' => 'required|numeric|min:1|max:31',
'limitDateMonth' => 'required|numeric|min:1|max:31',
'limitDateYear' => 'required|numeric|min:2010|max:2050',
'consumptionDateDay' => 'required|numeric|min:1|max:31',
'consumptionDateMonth' => 'required|numeric|min:1|max:31',
'consumptionDateYear' => 'required|numeric|min:2010|max:2050',
'joinFile' => 'nullable|mimes:jpg,jpeg,png,pdf|max:2048'
'consumptionDateYear' => 'required|numeric|min:2010|max:2050',
'joinFile' => 'nullable|mimes:jpg,jpeg,png,pdf|max:2048'
],
);
}

View file

@ -0,0 +1,51 @@
<?php
namespace App\Jobs\Arcadia;
use App\Lib\Arcadia\HasOrderedAnItemData;
use App\Mail\Arcadia\HasOrderedAnItem;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendHasOrderedAnItemMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
/**
* @var \App\Lib\Arcadia\HasOrderedAnItemData
*/
private $itemData;
/**
* Create a new job instance.
*
* @param \App\Lib\Arcadia\HasOrderedAnItemData $itemData
* @return void
*/
public function __construct(HasOrderedAnItemData $itemData)
{
$this->itemData = $itemData;
}
/**
* Execute the job.
*
* @return void
* @throws \RuntimeException If no config email is set.
*/
public function handle(): void
{
$emailTo = \config('arcadia.item_ordered_email_to');
if (empty($emailTo)) {
throw new \RuntimeException('Empty arcadia.item_ordered_email_to config, could not send mail');
}
Mail::queueOn('database', (new HasOrderedAnItem($this->itemData))->to($emailTo));
}
}

View file

@ -0,0 +1,66 @@
<?php
namespace App\Jobs\Arcadia;
use App\Lib\Arcadia\HasOrderedAnItemData;
use App\Models\Order;
use App\Models\SellItem;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class SendOrderToArcadia implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
/** @var \App\Models\Order */
private $order;
/**
* Create a new job instance.
*
* @param \App\Models\Order $order
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Execute the job.
*
* @return void
*/
public function handle(): void
{
/** @var \App\Models\Order|\App\Models\DeliveryAddress */
$deliver = $this->order->deliveryAddress()->exists() ? $this->order->deliveryAddress : $this->order;
$this->order->sellItems->each(function (SellItem $sellItem) use ($deliver) {
// @phpstan-ignore-next-line
for ($i = 0; $i < $sellItem->pivot->quantity; $i++) {
\dispatch(new SendHasOrderedAnItemMail(
new HasOrderedAnItemData(
$this->order,
$sellItem,
$deliver->firstname,
$deliver->lastname,
$deliver->address,
null,
$deliver->city,
$deliver->postcode,
$deliver->phone
)
))->onConnection('database')->onQueue('database');
} //end for
});
Log::debug(sprintf('Order %d sent to arcadia', $this->order->id));
}
}

View file

@ -37,7 +37,6 @@ class FetchDigitalRecruiterOffers
config('services.digital_recruiter.url')
));
}
$this->parseDigitalRecruiterOffers(\collect($response->object()->ads));
}

View file

@ -10,7 +10,6 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
class SendPasserelleMail implements ShouldQueue
{
@ -20,19 +19,25 @@ class SendPasserelleMail implements ShouldQueue
/**
* To be serialized by jobs system
*
* @var MailContactData
* @var \App\Models\MailContactData
* */
private $data;
/**
* The path of a specific file.
*
* @var string
* */
private $file;
/**
* Create a new job instance.
*
* @param \App\Models\MailContactData $data
* @param string $file
* @return void
*/
public function __construct(MailContactData $data, mixed $file)
public function __construct(MailContactData $data, string $file)
{
$this->data = $data;
$this->file = $file;
@ -43,7 +48,7 @@ class SendPasserelleMail implements ShouldQueue
*
* @return void
*/
public function handle()
public function handle(): void
{
Mail::to(config('mail.contactsList.passerelle'))->send(new ContactComplainMail($this->data, $this->file));
if (file_exists($this->file)) {

View file

@ -0,0 +1,54 @@
<?php
namespace App\Jobs\Shop;
use App\Models\Order;
use App\Notifications\Shop\NewOrder;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class SendShopMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
/** @var \App\Models\Order $order */
protected $order;
/**
* Create a new job instance.
*
* @param \App\Models\Order $order
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Execute the job.
*
* @return void
*/
public function handle(): void
{
if (!$this->order->confirmMailSent) {
/** @var \App\Models\Customer $customerModel */
$customerModel = $this->order->customer;
$customerModel->notify(new NewOrder($this->order));
$this->order->confirmMailSent = true;
$this->order->saveOrFail();
Log::debug('Shop mail is sent', $this->order->toArray());
} else {
Log::debug('Shop mail is already sent', $this->order->toArray());
}
}
}

View file

@ -0,0 +1,144 @@
<?php
namespace App\Lib\Arcadia;
use App\Enums\Arcadia\ArcadiaOrderType;
use App\Models\Order;
use App\Models\SellItem;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
/**
* @property-read integer $operation
* @property-read integer $support_code
* @property-read string $label_type_support
* @property-read \Carbon\Carbon $order_date
* @property-read integer $order_num
* @property-read integer $state_order
* @property-read integer $package_unit_weight
* @property-read string $email
* @property-read string $firstname
* @property-read string $lastname
* @property-read string $address
* @property-read string|null $address2
* @property-read string $city
* @property-read string $postcode
* @property-read string|null $phone
*/
class HasOrderedAnItemData implements Jsonable, Arrayable
{
/**
* Store data in it.
*
* @var array
*/
private $data = [];
/**
* Accessibles properties.
*
* @var array
*/
private $properties = [
'operation',
'support_code',
'label_type_support',
'order_date',
'order_num',
'state_order',
'package_unit_weight',
'email',
'firstname',
'lastname',
'address',
'address2',
'city',
'postcode',
'phone'
];
/**
* Getter.
*
* @param string $name
* @return mixed
* @throws \Error On undefiend prop access.
*/
public function __get(string $name)
{
if (\in_array($name, $this->properties)) {
return $this->data[$name];
}
throw new \Error("Cannot access property {$name} it dos not exists");
}
/**
* Has ordered an item data.
*
* @param \App\Models\Order $order
* @param \App\Models\SellItem $sellItem
* @param string $firstname
* @param string $lastname
* @param string $address
* @param string|null $address2
* @param string $city
* @param string $postcode
* @param string|null $phone
* @return void
*/
public function __construct(
Order $order,
SellItem $sellItem,
string $firstname,
string $lastname,
string $address,
?string $address2,
string $city,
string $postcode,
?string $phone
) {
$this->data = [
'operation' => \intval(env('BOUTIQUE_ARCADIA_OP_CODE', 16)),
'support_code' => $sellItem->arcadia_id,
'label_type_support' => $sellItem->name,
'order_date' => $order->created_at,
'order_num' => $order->id,
'state_order' => ArcadiaOrderType::check->value(),
// FIXME: uncomment when mercanet cb is ready.
// 'state_order' => $order->payementType->equals(OrderType::cb) ?
// ArcadiaOrderType::cb->value() : ArcadiaOrderType::check->value(),
'package_unit_weight' => $sellItem->arcadia_weight,
'email' => $order->email,
'firstname' => $firstname,
'lastname' => $lastname,
'address' => $address,
'address2' => $address2,
'city' => $city,
'postcode' => $postcode,
'phone' => $phone
];
}
/**
* Convert the object to its JSON representation.
*
* @param integer $options
* @return string
* @phpcs:disable Squiz.Commenting.FunctionComment.ScalarTypeHintMissing
*/
public function toJson($options = 0): string
{
// phpcs:enable
return \json_encode($this->toArray(), $options);
}
/**
* Get the instance as an array.
*
* @return array
*/
public function toArray(): array
{
return $this->data;
}
}

View file

@ -15,13 +15,13 @@ use App\Lib\Link;
class MenuNode extends \stdClass
{
/**
* Get property
* Get property.
*
* @param string $name
* @return mixed
* @throws \TypeError If prop is undefined.
*/
public function __get(string $name)
public function __get(string $name): mixed
{
if (in_array($name, ['type', 'title', 'link', 'published'])) {
return $this->{$name};
@ -62,7 +62,7 @@ class MenuNode extends \stdClass
* @return void
* @throws \RuntimeException If $type is wrong.
*/
public static function assertTypeIsCorrect(int $type)
public static function assertTypeIsCorrect(int $type): void
{
try {
$type = MenuNodeType::make($type);

View file

@ -10,13 +10,13 @@ use Illuminate\Support\Collection;
class CollectionHelper
{
/**
* Paginate a collection
* Paginate a collection.
*
* @param \Illuminate\Support\Collection $results
* @param integer $pageSize
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
public static function paginate(Collection $results, int $pageSize): LengthAwarePaginator
public static function paginate(Collection $results, int $pageSize): \Illuminate\Pagination\LengthAwarePaginator
{
$page = Paginator::resolveCurrentPage('page');
@ -24,15 +24,18 @@ class CollectionHelper
}
/**
* Paginate a collection
* Paginate a collection.
*
* @param \Illuminate\Support\Collection $results
* @param integer $pageSize
* @param integer $page
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
public static function paginateManually(Collection $results, int $pageSize, int $page = 1): LengthAwarePaginator
{
public static function paginateManually(
Collection $results,
int $pageSize,
int $page = 1
): \Illuminate\Pagination\LengthAwarePaginator {
$total = $results->count();
return self::paginator($results->forPage($page, $pageSize), $total, $pageSize, $page, [
@ -51,14 +54,19 @@ class CollectionHelper
* @param array $options
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
protected static function paginator(Collection $items, int $total, int $perPage, int $currentPage, array $options)
{
protected static function paginator(
Collection $items,
int $total,
int $perPage,
int $currentPage,
array $options
): \Illuminate\Pagination\LengthAwarePaginator {
return Container::getInstance()->makeWith(LengthAwarePaginator::class, [
'items' => $items,
'total' => $total,
'perPage' => $perPage,
'items' => $items,
'total' => $total,
'perPage' => $perPage,
'currentPage' => $currentPage,
'options' => $options
'options' => $options
]);
}
}

View file

@ -5,7 +5,7 @@ namespace App\Lib\Helpers;
class ExceptionsHelper
{
/**
* Handle sentry event
* Handle sentry event.
*
* @param \Sentry\Event $event
* @return null|\Sentry\Event
@ -26,7 +26,7 @@ class ExceptionsHelper
}
/**
* Anonimize Sentry Exception bag
* Anonimize Sentry Exception bag.
*
* @param \Sentry\ExceptionDataBag $exceptionDataBag
* @return \Sentry\ExceptionDataBag
@ -42,7 +42,7 @@ class ExceptionsHelper
}
/**
* Anonymise sentry stacktrace
* Anonymise sentry stacktrace.
*
* @param \Sentry\Stacktrace $stackTrace
* @return \Sentry\Stacktrace
@ -70,7 +70,7 @@ class ExceptionsHelper
}
/**
* Get anonymized sentry params
* Get anonymized sentry params.
*
* @param mixed[] $params
* @return string[]
@ -103,9 +103,8 @@ class ExceptionsHelper
return $params;
}
/**
* Anonymize at least Sql queries
* Anonymize at least Sql queries.
*
* @param string $message
* @return string
@ -120,7 +119,7 @@ class ExceptionsHelper
}
/**
* Anonymize stack trace
* Anonymize stack trace.
*
* @param \Throwable $e
* @return string
@ -159,7 +158,7 @@ class ExceptionsHelper
}
/**
* Handle Args
* Handle Args.
*
* @param array $stack
* @return string

View file

@ -25,8 +25,6 @@ use Illuminate\Support\Str;
* The final path will be storage/modelfiles/posts/10/04/19/5f/black-cat-under-red-car-286071690833400.png
*
* ! No limits of file per folder will be handled.
*
* @author Munsch Jérémy <jeremy.munsch@ldc.fr>
*/
class FileStorageHelper
{

View file

@ -22,7 +22,7 @@ use Symfony\Component\Finder\SplFileInfo;
class ToolboxHelper
{
/**
* Censor string
* Censor string.
*
* @param string $string
* @return string
@ -38,8 +38,9 @@ class ToolboxHelper
}
return $censor->censorString($string, true)['clean'];
}
/**
* Run a terminal command and gives the output
* Run a terminal command and gives the output.
*
* @param array|string $command The command to execute on terminal.
* @param boolean $throw Wether to throw en esception on failure or not.
@ -53,7 +54,7 @@ class ToolboxHelper
* @throws \LogicException
* @throws \RuntimeException If the command fails.
*/
public static function runConsoleCommand(array|string $command, bool $throw = true): string | false
public static function runConsoleCommand(array|string $command, bool $throw = true): string|false
{
// phpcs:enable
$process = \Illuminate\Support\Facades\Process::command($command)->run();
@ -69,6 +70,8 @@ class ToolboxHelper
}
/**
* Return array merge recursive distinct.
*
* @param array<int|string, mixed> $array1
* @param array<int|string, mixed> $array2
*
@ -89,13 +92,13 @@ class ToolboxHelper
}
/**
* Validate recaptcha
* Validate recaptcha.
*
* @param \Illuminate\Http\Request $request
* @param boolean $isV3
* @return void
*/
public static function validateRecaptcha(Request $request, bool $isV3 = true)
public static function validateRecaptcha(Request $request, bool $isV3 = true): void
{
Validator::validate($request->all(), [
'g-recaptcha-response' => [
@ -147,7 +150,7 @@ class ToolboxHelper
* Only embed allowed are for MP4 self hosted videos right now
*
* https is force by ckeditor MediaElements which natively supports
* only cloud hosted medias (youtube, spotify etc..)
* only cloud hosted medias (youtube, spotify etc..).
*
* @param string $input
* @return string
@ -159,7 +162,7 @@ class ToolboxHelper
}
/**
* Assert That no Back Office url is present on txt
* Assert That no Back Office url is present on txt.
*
* @param string $field
* @param string $text
@ -202,7 +205,7 @@ class ToolboxHelper
}
/**
* Assert That only external url is present on txt
* Assert That only external url is present on txt.
*
* @param string $field
* @param string $text
@ -245,7 +248,7 @@ class ToolboxHelper
}
/**
* Mutltibyte string replace
* Mutltibyte string replace.
*
* @param array|string $search
* @param array|string $replace
@ -289,7 +292,7 @@ class ToolboxHelper
}
/**
* Asserts that the field is unique
* Asserts that the field is unique.
*
* @param string $table
* @param string $field
@ -305,7 +308,7 @@ class ToolboxHelper
string|int|float|bool|null|array $value,
?int $id = null,
?callable $query = null
) {
): void {
if (!$query) {
Validator::make([$field => $value], [
self::mbReplace('.', '\.', $field) => Rule::unique($table, $field)->ignore($id),
@ -326,7 +329,7 @@ class ToolboxHelper
}
/**
* Get original polyfill with autotranslate behavior
* Get original polyfill with autotranslate behavior.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $attribute
@ -352,7 +355,7 @@ class ToolboxHelper
}
/**
* Dynamic model query
* Dynamic model query.
*
* @param string $defaultLocale
* @param \Illuminate\Contracts\Database\Eloquent\Builder $q
@ -365,7 +368,7 @@ class ToolboxHelper
Builder $q,
string $column,
string $value
): Builder {
): \Illuminate\Contracts\Database\Eloquent\Builder {
$currentLocale = app()->currentLocale();
$locales = collect(config('app.locales'))
->mapWithKeys(fn (string $locale) => [$locale => $locale]);
@ -393,7 +396,7 @@ class ToolboxHelper
}
/**
* Generates an array from a dot separated string
* Generates an array from a dot separated string.
*
* @param string $path
* @param mixed $value
@ -412,7 +415,7 @@ class ToolboxHelper
}
/**
* Convert deeply an object to array
* Convert deeply an object to array.
*
* @param mixed $input
* @return array
@ -434,7 +437,7 @@ class ToolboxHelper
}
/**
* Convert deeply an array to object
* Convert deeply an array to object.
*
* @param mixed $input
* @return object
@ -456,7 +459,7 @@ class ToolboxHelper
}
/**
* Validate picture
* Validate picture.
*
* @param string $attribute
* @param string|null $value
@ -513,7 +516,7 @@ class ToolboxHelper
}
/**
* Get the file full path
* Get the file full path.
*
* @param string $value
* @param boolean $useStorage
@ -527,19 +530,19 @@ class ToolboxHelper
}
/**
* Get the file mimetype
* Get the file mimetype.
*
* @param string $value
* @param boolean $useStorage
* @return string|false
*/
private static function getUploadedFileMimeType(string $value, bool $useStorage)
private static function getUploadedFileMimeType(string $value, bool $useStorage): string|false
{
return !$useStorage ? File::mimeType($value) : Storage::mimeType($value);
}
/**
* Fetch class list from a specific namespace
* Fetch class list from a specific namespace.
*
* @param string $namespace
* @return array<string> An array of classe namespaces
@ -553,7 +556,7 @@ class ToolboxHelper
}
/**
* Get all classes from a specific namespace that implement a specific interface
* Get all classes from a specific namespace that implement a specific interface.
*
* @param string $namespace
* @param string $interface

View file

@ -11,10 +11,10 @@ use Stringable;
*
* @package App\Lib
*/
class Link implements Jsonable, Arrayable, \JsonSerializable, Stringable
class Link implements Jsonable, Arrayable, Stringable
{
/**
* Link
* Link.
*
* @param null|string $url A valid url.
* @param null|string $routeName A valid route name.
@ -77,9 +77,9 @@ class Link implements Jsonable, Arrayable, \JsonSerializable, Stringable
/**
* Get the instance as an array.
*
* @return array<'url'|'routeName',string|null>
* @return array<'url'|'routeName', string|null>
*/
public function toArray()
public function toArray(): array
{
return ['url' => $this->url, 'routeName' => $this->routeName];
}
@ -91,26 +91,14 @@ class Link implements Jsonable, Arrayable, \JsonSerializable, Stringable
* @return string
* @phpcs:disable Squiz.Commenting.FunctionComment.ScalarTypeHintMissing
*/
public function toJson($options = 0)
public function toJson($options = 0): string
{
// phpcs:enable
return \json_encode($this->jsonSerialize(), $options);
}
/**
* Convert the object into something JSON serializable.
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return $this->toArray();
return \json_encode($this->toArray(), $options);
}
/**
* @return string
*
* @throws \RuntimeException If the link cannot be converted to string.
*/
public function __toString()

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@ use App\Models\Customer;
use Illuminate\Support\Str;
/**
* Some utilities methods
* Some utilities methods.
*/
// phpcs:disable Generic.Files.LineLength.TooLong
class Utils
@ -111,7 +111,7 @@ class Utils
}
/**
* Multibyte strtr
* Multibyte strtr.
*
* @param string $str
* @param string|array $from
@ -131,7 +131,7 @@ class Utils
}
/**
* Generate an unique pseudo
* Generate an unique pseudo.
*
* @param string $firstname
* @param string $lastname

View file

@ -12,11 +12,11 @@ class CreateNotification
* @param \App\Events\NewNotification $event
* @return void
*/
public function handle(NewNotification $event)
public function handle(NewNotification $event): void
{
$event->model->notifiable()->create([
'type' => $event->type,
'content' => $event->content,
'type' => $event->type,
'content' => $event->content,
'customer_id' => $event->customer->id ?? null
]);
}

View file

@ -15,7 +15,7 @@ class PasswordHasReset
* @param \Illuminate\Auth\Events\PasswordReset $event
* @return void
*/
public function handle(PasswordReset $event)
public function handle(PasswordReset $event): void
{
/** @var \App\Models\Customer */
$customer = $event->user;

View file

@ -0,0 +1,103 @@
<?php
namespace App\Mail\Arcadia;
use App\Enums\Arcadia\ArcadiaOrderType;
use App\Lib\Arcadia\HasOrderedAnItemData;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class HasOrderedAnItem extends Mailable implements ShouldQueue
{
use Queueable;
use SerializesModels;
/**
* Email Data.
*
* @var \App\Lib\Arcadia\HasOrderedAnItemData
*/
private $data;
/**
* Create a new message instance.
*
* @param \App\Lib\Arcadia\HasOrderedAnItemData $data
* @return void
*/
public function __construct(HasOrderedAnItemData $data)
{
$this->data = $data;
}
/**
* Build the message.
*
* @return $this
* @throws \RuntimeException If generating XML fails.
*/
public function build()
{
$xml = $this->makeXml();
// * Format xml.
$doc = new \DOMDocument('1.0', 'utf-8');
$doc->xmlStandalone = true;
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->loadXML($xml);
$xml = $doc->saveXML();
if (!$xml) {
throw new \RuntimeException("Failed to make XML");
}
$fileName = Str::slug(sprintf(
'order_%s_%s_%s%s',
$this->data->order_num,
ArcadiaOrderType::make($this->data->state_order)->label(),
date('Ymd_His'),
\microtime(true)
)) . '.xml';
Storage::disk('arcadia')->put($fileName, $xml);
return $this->subject('Un object en vente à été commandé')
->markdown('emails.arcadiaOrders.default_markdown')
->attachData(
$xml,
$fileName,
['mime' => 'application/xml']
);
}
/**
* Render Arcadia xml for order.
*
* @return string
*/
private function makeXml(): string
{
return view('emails.arcadiaOrders.default_xml', [
'operation' => $this->data->operation,
'support_code' => $this->data->support_code,
'label_type_support' => $this->data->operation,
'order_date' => $this->data->order_date,
'order_num' => $this->data->order_num,
'orderType' => ArcadiaOrderType::make($this->data->state_order),
'package_unit_weight' => $this->data->package_unit_weight,
'lastname' => $this->data->lastname,
'firstname' => $this->data->firstname,
'email' => $this->data->email,
'address' => $this->data->address,
'address2' => $this->data->address2,
'city' => $this->data->city,
'phone' => $this->data->phone,
'postcode' => $this->data->postcode,
])->render();
}
}

View file

@ -7,7 +7,6 @@ use Illuminate\Bus\Queueable;
use Illuminate\Mail\Attachment;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class ContactComplainMail extends ContactMail
{
@ -17,16 +16,22 @@ class ContactComplainMail extends ContactMail
/**
* The order instance.
*
* @var MailContactData
* @var \App\Models\MailContactData
*/
protected $data;
/**
* The path of a specific file.
*
* @var string
*/
protected $file;
/**
* Create a new message instance.
*
* @param \App\Models\MailContactData $data
* @param string|null $file
* @param string|null $file
* @return void
*/
public function __construct(MailContactData $data, string|null $file)
@ -64,7 +69,7 @@ class ContactComplainMail extends ContactMail
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
* @return array<int, \Illuminate\Mail\Attachment>
*/
public function attachments(): array
{

View file

@ -18,7 +18,7 @@ class ContactMail extends Mailable
/**
* The order instance.
*
* @var MailContactData
* @var \App\Models\MailContactData
*/
protected $data;
@ -32,6 +32,7 @@ class ContactMail extends Mailable
/**
* Create a new message instance.
*
* @param \App\Models\MailContactData $data
* @return void
*/
public function __construct(MailContactData $data)
@ -63,14 +64,13 @@ class ContactMail extends Mailable
*/
protected function makeCsvFile(): string
{
// we create the CSV into memory
// FILENAME
// Creation of the CSV into memory.
$csv = Writer::createFromFileObject(new SplTempFileObject());
$csv->setDelimiter(';');
$csv->setEnclosure('"');
$csv->setOutputBOM(Bom::Utf8);
// we insert the CSV header
// Insert the CSV header.
$csv->insertOne([
'EMETTEUR_DATE',
'EMETTEUR_HEURE',

View file

@ -117,7 +117,6 @@ class ActivityLog extends Model
};
}
/**
* Get a value type as a string
* ! Use this for display purpose only

View file

@ -19,7 +19,7 @@ class BlockList extends Model
// * RELATIONSHIPS
/**
* Summary of customer
* Get the associated customer who has blocked another one.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@ -29,7 +29,7 @@ class BlockList extends Model
}
/**
*
* Obtain the associated client that has been blocked by another one.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View file

@ -136,7 +136,7 @@ class BrandAdvantage extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('publishedBrandAdvantagesOrderedByOrder');
self::getPublishedOrdered();

View file

@ -72,7 +72,7 @@ class ConsumptionMoment extends Model
// * METHODS
/**
* Asserts using validation that the title is unique
* Asserts using validation that the title is unique.
*
* @param string|null $title
* @param integer|null $id
@ -91,7 +91,7 @@ class ConsumptionMoment extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('consumptionMomentsOrderedBySlug');
self::getOrderedBySlug();

View file

@ -100,7 +100,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
// * METHODS
/**
* Asserts using validation that the email is unique
* Asserts using validation that the email is unique.
*
* @param mixed $id
* @param mixed $email
@ -113,7 +113,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
}
/**
* Asserts that the field is unique
* Asserts that the field is unique.
*
* @param mixed $id
* @param string $field
@ -134,7 +134,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
}
/**
* Get conversations with messages sorted by time
* Get conversations with messages sorted by time.
*
* @return array
*/
@ -218,7 +218,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
*
* @return void
*/
public function sendEmailVerificationNotification()
public function sendEmailVerificationNotification(): void
{
$this->deleteIfDoesNotExistsInCrm();
$this->notify(new VerifyEmail());
@ -230,7 +230,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
* @param mixed $token
* @return void
*/
public function sendPasswordResetNotification(mixed $token)
public function sendPasswordResetNotification(mixed $token): void
{
$this->deleteIfDoesNotExistsInCrm();
/** @var string $token */
@ -296,7 +296,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
}
/**
* Get api_data attribute, the crm Data of a customer
* Get api_data attribute, the crm Data of a customer.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
@ -348,7 +348,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
// * CRM CACHE
/**
* Clear cached apiData
* Clear cached apiData.
*
* @return void
*/
@ -360,24 +360,21 @@ class Customer extends Authenticatable implements MustVerifyEmail
}
/**
* Put customer crm part in cache
* Put customer crm part in cache.
*
* @template T
* @param string $uuid The customer uuid.
* @param string $part_name The part name for the cache path.
* @param \Closure(void):T $part The part to cache.
* @param integer $ttl Time to live in seconds for the cache part.
* @return T
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
* @param string $uuid The customer uuid.
* @param string $part_name The part name for the cache path.
* @param \Closure $part The part to cache.
* @param integer $ttl Time to live in seconds for the cache part.
* @return mixed
*/
public static function cacheCrm(string $uuid, string $part_name, \Closure $part, int $ttl = 60 * 60)
public static function cacheCrm(string $uuid, string $part_name, \Closure $part, int $ttl = 60 * 60): mixed
{
// phpcs:enable
return Cache::remember("customers.{$uuid}.{$part_name}", $ttl, $part);
}
/**
* Clear customer crm cache part or totally
* Clear customer crm cache part or totally.
*
* @param string $uuid
* @param string $part_name
@ -395,11 +392,11 @@ class Customer extends Authenticatable implements MustVerifyEmail
/**
* This mutate Customer attributes to array
* including only non critical properties and crm values
* (One that can be send to front office without security breach)
* (One that can be send to front office without security breach).
*
* @return array
*/
public function toArray()
public function toArray(): array
{
if ($this->hashcode) {
return collect(array_merge(
@ -427,7 +424,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
// * RELATIONSHIPS
/**
* Get all of the departaimant collections for the Customer
* Get all of the departaimant collections for the Customer.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
@ -437,7 +434,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
}
/**
* The notifications that belong to the Customer
* The notifications that belong to the Customer.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
@ -447,7 +444,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
}
/**
* The read notifications that belong to the Customer
* The read notifications that belong to the Customer.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
@ -457,7 +454,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
}
/**
* Get all of the messages for the Customer
* Get all of the messages for the Customer.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
@ -467,7 +464,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
}
/**
* Get all of the sentMessages for the Customer
* Get all of the sentMessages for the Customer.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/

View file

@ -0,0 +1,58 @@
<?php
namespace App\Models;
use App\Enums\Shop\ContactFormCivility;
use Illuminate\Database\Eloquent\Model;
/**
* @property integer $id
* @property \App\Enums\ContactFormCivility $civility
* @property string $lastname
* @property string $firstname
* @property string $address
* @property string $postcode
* @property string $phone
* @property string $city
* @property integer $order_id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
*/
class DeliveryAddress extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'civility',
'lastname',
'firstname',
'address',
'postcode',
'city',
'phone'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'civility' => ContactFormCivility::class
];
// * RELATIONSHIPS
/**
* Get the order that are assigned this delivery address.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function order(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Order::class);
}
}

View file

@ -127,7 +127,7 @@ class DemarcheSlide extends Model
}
/**
* Adjusts demarcheSlide status using current status and publish dates
* Adjusts demarcheSlide status using current status and publish dates.
*
* @param self $demarcheSlide
* @return void
@ -151,7 +151,7 @@ class DemarcheSlide extends Model
}
/**
* Getter the current status following planification dates planificated_status
* Getter the current status following planification dates planificated_status.
*
* @return boolean
*/
@ -189,7 +189,7 @@ class DemarcheSlide extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('publishedDemarcheSlidesOrderedByOrder');
self::getPublishedOrdered();

View file

@ -13,7 +13,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* Departaimants Model
* Has functions to store departaimants on multiple statuses
* Has functions to store departaimants on multiple statuses.
*
* @property \App\Enums\Departaimants\DepartaimantCollectionType $type
* @property integer $customer_id
@ -26,7 +26,6 @@ use Illuminate\Database\Eloquent\Model;
* @uses App\Enums\Departaimant
* @uses App\Enums\DepartaimantStatus
* @uses App\Enums\DepartaimantCollectionType
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
*/
class DepartaimantsCollection extends Model
{
@ -67,21 +66,21 @@ class DepartaimantsCollection extends Model
];
/**
* Columns prefix
* Columns prefix.
*
* @var string
*/
private static $columnTableNamePrefix = 'col';
/**
* Le prefix d'un table departaimant
* Le prefix d'un table departaimant.
*
* @var integer
*/
private static $tableFields = 4;
/**
* Le nombre de colonnes des departaimants
* Le nombre de colonnes des departaimants.
*
* * La largeur en bits d'un départaimant
* * to be set in construct
@ -131,7 +130,7 @@ class DepartaimantsCollection extends Model
// * RELATIONSHIPS
/**
* Get the customer that owns the DepartaimantsCollection
* Get the customer that owns the DepartaimantsCollection.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@ -143,7 +142,7 @@ class DepartaimantsCollection extends Model
// * METHODS
/**
* Add a Departaiment to this collection
* Add a Departaiment to this collection.
*
* @param \App\Enums\Departaimants\IDepartaimant $departaimant
* @return void
@ -154,7 +153,7 @@ class DepartaimantsCollection extends Model
}
/**
* Removes a Departaime from this collection
* Removes a Departaime from this collection.
*
* @param \App\Enums\Departaimants\IDepartaimant $departaimant
* @return void
@ -165,7 +164,7 @@ class DepartaimantsCollection extends Model
}
/**
* Checks if this collection has a Departaimant
* Checks if this collection has a Departaimant.
*
* @param \App\Enums\Departaimants\IDepartaimant $departaimant
* @return boolean
@ -176,7 +175,7 @@ class DepartaimantsCollection extends Model
}
/**
* Set the Departaimant to a specific status
* Set the Departaimant to a specific status.
*
* @param \App\Enums\Departaimants\IDepartaimant $departaimant
* @param \App\Enums\Departaimants\DepartaimantStatus $status
@ -192,7 +191,7 @@ class DepartaimantsCollection extends Model
}
/**
* Test the Departaimant status
* Test the Departaimant status.
*
* @param \App\Enums\Departaimants\IDepartaimant $departaimant
* @param \App\Enums\Departaimants\DepartaimantStatus $status
@ -213,7 +212,7 @@ class DepartaimantsCollection extends Model
}
/**
* Get all Customer which has their departaimant with a status
* Get all Customer which has their departaimant with a status.
*
* @param \App\Enums\Departaimants\DepartaimantCollectionType $depColtype
* @param \App\Enums\Departaimants\IDepartaimant $departaimant
@ -241,7 +240,7 @@ class DepartaimantsCollection extends Model
}
/**
* Get all Customer which has their departaimant with a status
* Get all Customer which has their departaimant with a status.
*
* @param array $departaimants
* @param \App\Enums\Departaimants\DepartaimantStatus $status
@ -279,7 +278,7 @@ class DepartaimantsCollection extends Model
}
/**
* Get the Departaimant status
* Get the Departaimant status.
*
* @param \App\Enums\Departaimants\IDepartaimant $departaimant
* @return \App\Enums\Departaimants\DepartaimantStatus
@ -299,7 +298,7 @@ class DepartaimantsCollection extends Model
}
/**
* Get a list of all the departaimants and their status
* Get a list of all the departaimants and their status.
*
* @uses \App\Enums\Departaimants\IDepartaimant
* @uses \App\Enums\Departaimants\DepartaimantStatus
@ -323,7 +322,7 @@ class DepartaimantsCollection extends Model
}
/**
* Get a list of all the departaimants and their status
* Get a list of all the departaimants and their status.
*
* @param \App\Enums\Departaimants\DepartaimantCollectionType $depColtype
* @param \App\Enums\Departaimants\DepartaimantStatus $status
@ -353,7 +352,7 @@ class DepartaimantsCollection extends Model
}
/**
* Set the Departaimant column to 0
* Set the Departaimant column to 0.
*
* @param \App\Enums\Departaimants\IDepartaimant $departaimant
* @return void
@ -367,8 +366,7 @@ class DepartaimantsCollection extends Model
}
/**
* Donne la 'table' (colonne SQL) dans laquelle se trouve
* le département
* Donne la 'table' (colonne SQL) dans laquelle se trouve le département.
*
* @param \App\Enums\Departaimants\DepartaimantCollectionType $depColtype
* @param \App\Enums\Departaimants\IDepartaimant $dep
@ -387,7 +385,7 @@ class DepartaimantsCollection extends Model
/**
* Donne la colonne (binaire) dans laquelle se trouve le département
* Dans sa 'table' (colonne SQL)
* dans sa 'table' (colonne SQL).
*
* @param \App\Enums\Departaimants\DepartaimantCollectionType $depColtype
* @param \App\Enums\Departaimants\IDepartaimant $dep
@ -408,7 +406,7 @@ class DepartaimantsCollection extends Model
}
/**
* Donne la valeur (masque binaire) d'un département
* Donne la valeur (masque binaire) d'un département.
*
* @param \App\Enums\Departaimants\IDepartaimant $dep
* @return integer
@ -419,7 +417,7 @@ class DepartaimantsCollection extends Model
}
/**
* Genère la liste des departements avec leur masques
* Genère la liste des departements avec leur masques.
*
* @param \App\Enums\Departaimants\DepartaimantCollectionType $depColtype
* @return array
@ -440,7 +438,7 @@ class DepartaimantsCollection extends Model
/**
* Get the with in bit length for a column
* that can be used to store data
* that can be used to store data.
*
* @return float
*/
@ -451,7 +449,7 @@ class DepartaimantsCollection extends Model
}
/**
* Get departaimant enum values
* Get departaimant enum values.
*
* @param \App\Enums\Departaimants\DepartaimantCollectionType $depColtype
* @return array
@ -463,7 +461,7 @@ class DepartaimantsCollection extends Model
}
/**
* Get a departaiment enum from a collection type
* Get a departaiment enum from a collection type.
*
* @param \App\Enums\Departaimants\DepartaimantCollectionType $depColtype
* @return string

View file

@ -112,7 +112,6 @@ class Discount extends Model
/**
* Static method to fetch br List.
*
* ! see fetchActiveBr for output object definition
*
* @return object|null

View file

@ -93,7 +93,7 @@ class GeneralSetting extends Model
*
* @return mixed
*/
public function getRouteKey()
public function getRouteKey(): mixed
{
/** @var \App\Enums\StaticPageType */
$enum = $this->getAttribute($this->getRouteKeyName());
@ -115,11 +115,11 @@ class GeneralSetting extends Model
// * GETTERS
/**
* Mutator for 'value' attribute
* Mutator for 'value' attribute.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
public function value(): Attribute
public function value(): \Illuminate\Database\Eloquent\Casts\Attribute
{
return Attribute::make(
get: fn($value): array => self::valueFromJson($this->type, $value),
@ -170,7 +170,7 @@ class GeneralSetting extends Model
}
/**
* Unserialize setting value
* Unserialize setting value.
*
* @param \App\Enums\Settings\SettingsType $type
* @param string $json
@ -197,7 +197,7 @@ class GeneralSetting extends Model
* @param \App\Enums\Settings\SettingsType $type
* @return void
*/
private static function resetCache(SettingsType $type)
private static function resetCache(SettingsType $type): void
{
Cache::forget(sprintf('%sGeneralSetting', $type->name));
self::getCachedGeneralSetting($type);
@ -207,9 +207,9 @@ class GeneralSetting extends Model
* Get cached general setting associated to a given type.
*
* @param \App\Enums\Settings\SettingsType $type
* @return \App\Models\StaticPage
* @return mixed
*/
public static function getCachedGeneralSetting(SettingsType $type)
public static function getCachedGeneralSetting(SettingsType $type): mixed
{
return Cache::rememberForever(
sprintf('%sGeneralSetting', $type->name),

View file

@ -117,7 +117,7 @@ class HistoricalMilestone extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('publishedHistoricalMilestonesOrdered');
self::getPublishedOrdered();

View file

@ -84,7 +84,7 @@ class KeyNumber extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('5publishedKeyNumbersOrderedByOrder');
self::get5PublishedOrdered();

View file

@ -8,7 +8,32 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
/**
* This class is used to store data in memory only, not in databases
* This class is used to store data in memory only, not in databases.
*
* @property \App\Enums\ContactFormCivility $civility Picto path.
* @property string $lastname Picto title attribute.
* @property string $firstname Picto alt attribute.
* @property string $address Legend of picto.
* @property string $email The origin of the text.
* @property string $postal Change order request.
* @property string $town Picto publish status.
* @property integer $phone Picto publish status.
* @property \App\Enums\ContactFormType $type Picto publish status.
* @property string $onepagesubject Picto publish status.
* @property string $message Picto publish status.
* @property string $joinFile Picto publish status.
* @property string $productName Picto publish status.
* @property string $productCode Picto publish status.
* @property string $buyPlace Picto publish status.
* @property string $lotNumberName Picto publish status.
* @property string $limitDateDay Picto publish status.
* @property string $limitDateMonth Picto publish status.
* @property string $limitDateYear Picto publish status.
* @property string $consumptionDateDay Picto publish status.
* @property string $consumptionDateMonth Picto publish status.
* @property string $consumptionDateYear Picto publish status.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*/
class MailContactData extends Model
{
@ -22,7 +47,7 @@ class MailContactData extends Model
/**
* The attributes that are mass assignable.
*
* @var array
* @var array<int, string>
*/
protected $fillable = [
'civility',
@ -55,31 +80,30 @@ class MailContactData extends Model
* @var array<string, string>
*/
protected $casts = [
'type' => ContactFormType::class,
'type' => ContactFormType::class,
'civility' => ContactFormCivility::class
];
/**
* The model's attributes.
*
* @var array
*/
protected $attributes = [
'productName' => '',
'productCode' => '',
'buyPlace' => '',
'lotNumberName' => 0,
'limitDateDay' => '00',
'limitDateMonth' => '00',
'limitDateYear' => '0000',
'consumptionDateDay' => '00',
'productName' => '',
'productCode' => '',
'buyPlace' => '',
'lotNumberName' => 0,
'limitDateDay' => '00',
'limitDateMonth' => '00',
'limitDateYear' => '0000',
'consumptionDateDay' => '00',
'consumptionDateMonth' => '00',
'consumptionDateYear' => '0000',
'consumptionDateYear' => '0000',
];
/**
* Export the model data to a Formatted Arcadia Data array
* Export the model data to a Formatted Arcadia Data array.
*
* @return array
*/
@ -105,7 +129,7 @@ class MailContactData extends Model
}
/**
* Export the model data to a Formatted Passerelle Data array
* Export the model data to a Formatted Passerelle Data array.
*
* * Removed
* 'EMETTEUR_OBJETDEMANDE' => "objet de la reclamation string",
@ -119,56 +143,45 @@ class MailContactData extends Model
{
// * CF PAsserrelle fields .csv
return [
// * Marque le Gaulois (Obligatoire)
'EMETTEUR_MARQUE' => 1,
// * Obligatoire
'EMETTEUR_DATE' => date("Y-m-d"),
// * Obligatoire
'EMETTEUR_HEURE' => date("h:i:s"),
'EMETTEUR_CIVILITE' => $this->civility->value,
// * Obligatoire Limité a 50
'EMETTEUR_NOM' => Str::limit($this->lastname, 50, ''),
// * Obligatoire
'EMETTEUR_PRENOM' => $this->firstname,
'EMETTEUR_ADRESSE1' => $this->address,
'EMETTEUR_ADRESSE2' => '',
'EMETTEUR_CP' => $this->postal,
// * Obligatoire
'EMETTEUR_VILLE' => $this->town,
'EMETTEUR_EMAIL' => $this->email,
'EMETTEUR_TELEPHONE' => $this->phone,
'EMETTEUR_PAYS' => 'France',
'EMETTEUR_NOM_PRODUIT' => $this->productName,
// * Obligatoire
'EMETTEUR_EAN13' => $this->productCode,
// Le Gaulois brand.
'EMETTEUR_MARQUE' => 1,
'EMETTEUR_DATE' => date("Y-m-d"),
'EMETTEUR_HEURE' => date("h:i:s"),
'EMETTEUR_CIVILITE' => $this->civility->value,
// Limited at 50 characters.
'EMETTEUR_NOM' => Str::limit($this->lastname, 50, ''),
'EMETTEUR_PRENOM' => $this->firstname,
'EMETTEUR_ADRESSE1' => $this->address,
'EMETTEUR_ADRESSE2' => '',
'EMETTEUR_CP' => $this->postal,
'EMETTEUR_VILLE' => $this->town,
'EMETTEUR_EMAIL' => $this->email,
'EMETTEUR_TELEPHONE' => $this->phone,
'EMETTEUR_PAYS' => 'France',
'EMETTEUR_NOM_PRODUIT' => $this->productName,
'EMETTEUR_EAN13' => $this->productCode,
'EMETTEUR_DATE_LIMITE_CONSO' => sprintf(
'%s/%s/%s',
$this->limitDateDay ?? '00',
$this->limitDateMonth ?? '00',
$this->limitDateYear ?? '0000'
),
'EMETTEUR_NUM_LOT' => $this->lotNumberName,
'EMETTEUR_MESSAGE' => $this->type->equals(ContactFormType::nl) ?
'EMETTEUR_NUM_LOT' => $this->lotNumberName,
'EMETTEUR_MESSAGE' => $this->type->equals(ContactFormType::nl) ?
sprintf('%s \n %s', $this->onepagesubject, $this->message) :
$this->message,
'EMETTEUR_PJ' => $this->joinFile,
'DATE_CONSO' => sprintf(
'EMETTEUR_PJ' => $this->joinFile,
'DATE_CONSO' => sprintf(
'%s/%s/%s',
$this->consumptionDateDay ?? '00',
$this->consumptionDateMonth ?? '00',
$this->consumptionDateYear ?? '0000'
),
'LIEU_ACHAT' => $this->buyPlace,
// * FUCK passerelle et leur DTD qui n'existe pas cf: resources/documents
// * Recla conso ?
'EMETTEUR_OBJETDEMANDE' => 3,
// * doit être vide ?
'EMETTEUR_OPT_IN' => '',
// * c'est quoi ça ?
'REPONSE_ETAT' => 0,
// * ok
'TYPE_REPONSE' => 'mail'
'LIEU_ACHAT' => $this->buyPlace,
'EMETTEUR_OBJETDEMANDE' => 3,
'EMETTEUR_OPT_IN' => '',
'REPONSE_ETAT' => 0,
'TYPE_REPONSE' => 'mail'
];
}
}

View file

@ -177,7 +177,7 @@ class MainSlide extends Model
}
/**
* Adjusts mainSlide status using current status and publish dates
* Adjusts mainSlide status using current status and publish dates.
*
* @param self $mainSlide
* @return void
@ -201,7 +201,7 @@ class MainSlide extends Model
}
/**
* Getter the current status following planification dates planificated_status
* Getter the current status following planification dates planificated_status.
*
* @return boolean
*/
@ -239,7 +239,7 @@ class MainSlide extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('publishedMainSlidesOrderedByOrderWithApproaches');
self::getPublishedOrderedWithApproaches();

View file

@ -127,14 +127,14 @@ class Meat extends Model
}
/**
* Asserts using validation that the label is unique
* Asserts using validation that the label is unique.
*
* @param string|null $label
* @param integer|null $id
* @return void
* @throws \Illuminate\Validation\ValidationException If a meat label already exists.
*/
private static function assertLabelIsUnique(string|null $label, ?int $id = null)
private static function assertLabelIsUnique(string|null $label, ?int $id = null): void
{
$table = (new self())->getTable();
ToolboxHelper::assertFieldIsUnique($table, 'label', $label, $id);
@ -157,7 +157,7 @@ class Meat extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('publishedMeatsOrderedByOrder');
self::getPublishedOrdered();

View file

@ -116,7 +116,7 @@ class MenuNodeData extends Model
// * METHODS
/**
* Deny Handling some of the MenuNodeData
* Deny Handling some of the MenuNodeData.
*
* @param self $model
* @return void

View file

@ -32,7 +32,7 @@ class Message extends Model implements INotifiable
// * RELATIONSHIPS
/**
* BelongsTo customer relation
* BelongsTo customer relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@ -42,7 +42,7 @@ class Message extends Model implements INotifiable
}
/**
* BelongsTo customer relation
* BelongsTo customer relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@ -52,7 +52,7 @@ class Message extends Model implements INotifiable
}
/**
* MorphOne notification relation
* MorphOne notification relation.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphOne
*/
@ -64,19 +64,19 @@ class Message extends Model implements INotifiable
// * METHODS
/**
* created_at_nice_date attribute
* Created at nice date.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
public function createdAtNiceDate(): \Illuminate\Database\Eloquent\Casts\Attribute
{
return Attribute::make(
get: fn () => (new NiceDate())->get(null, '', $this->created_at, [])
get: fn() => (new NiceDate())->get(null, '', $this->created_at, [])
);
}
/**
* Get MessagesOlderThan attribute
* Get older messages.
*
* @param integer $days
* @return \Illuminate\Contracts\Database\Eloquent\Builder

View file

@ -222,7 +222,7 @@ class News extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('publishedNewsWithCategories');
self::getPublishedWithNewsCategory();

View file

@ -121,7 +121,7 @@ class NewsBreeding extends Model
}
/**
* Adjusts breedingNews status using current status and publish dates
* Adjusts breedingNews status using current status and publish dates.
*
* @param self $model
* @return void
@ -145,7 +145,7 @@ class NewsBreeding extends Model
}
/**
* Asserts using validation that the title is unique
* Asserts using validation that the title is unique.
*
* @param string|null $title
* @param integer|null $id
@ -161,7 +161,7 @@ class NewsBreeding extends Model
/**
* Getter the current status following planification dates planificated_status
* Getter the current status following planification dates planificated_status.
*
* @return boolean
*/
@ -189,7 +189,7 @@ class NewsBreeding extends Model
* @param \App\Enums\StaticPageType $type
* @return void
*/
private static function resetCache(StaticPageType $type)
private static function resetCache(StaticPageType $type): void
{
Cache::forget(sprintf('%sPublishedNewsBreedingOrderedByOrder', $type->name));
self::getPublishedOrderedForType($type);

View file

@ -101,7 +101,7 @@ class NewsCategory extends Model
}
/**
* Asserts using validation that the title is unique
* Asserts using validation that the title is unique.
*
* @param string|null $title
* @param integer|null $id
@ -120,7 +120,7 @@ class NewsCategory extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('publishedNewsCategoriesOrderedByOrder');
self::getPublishedOrdered();

View file

@ -2,7 +2,7 @@
namespace App\Models;
use App\Enums\Club\NewsClubTypeEnum;
use App\Enums\News\NewsClubTypeEnum;
use App\Lib\Helpers\FileStorageHelper;
use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@ -11,7 +11,7 @@ use Illuminate\Support\Str;
use App\Lib\Helpers\ToolboxHelper;
/**
* @property \App\Enums\Club\NewsClubTypeEnum $type News club type.
* @property \App\Enums\News\NewsClubTypeEnum $type News club type.
* @property string $title News club title.
* @property string $slug News club title slug.
* @property string|null $content News club content.
@ -96,7 +96,7 @@ class NewsClub extends Model
}
/**
* Asserts using validation that the title is unique
* Asserts using validation that the title is unique.
*
* @param string|null $title
* @param integer|null $id

View file

@ -85,7 +85,7 @@ class NewsCorporate extends Model
// * METHODS
/**
* Adjusts newsCorporate status using current status and publish dates
* Adjusts newsCorporate status using current status and publish dates.
*
* @param self $newsCorporate
* @return void
@ -109,7 +109,7 @@ class NewsCorporate extends Model
}
/**
* Getter the current status following planification dates planificated_status
* Getter the current status following planification dates planificated_status.
*
* @return boolean
*/
@ -136,7 +136,7 @@ class NewsCorporate extends Model
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('9publishedNewsCorporateOrderedByUpdatedAt');
self::get9PublishedOrderedByUpdatedAt();
@ -150,11 +150,7 @@ class NewsCorporate extends Model
public static function get9PublishedOrderedByUpdatedAt(): \Illuminate\Database\Eloquent\Collection
{
return Cache::rememberForever('9publishedNewsCorporateOrderedByUpdatedAt', function () {
return self::query()
->where('published', true)
->orderByDesc('updated_at')
->limit(9)
->get();
return self::query()->where('published', true)->orderByDesc('updated_at')->limit(9)->get();
});
}
}

View file

@ -6,6 +6,8 @@ use App\Casts\NiceDate;
use App\Enums\NotificationType;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View;
/**
* @property \App\Enums\NotificationType $type Notification type.
@ -38,10 +40,41 @@ class Notification extends Model
'type' => NotificationType::class
];
// * METHODS
/**
* Created at nice date.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
public function createdAtNiceDate(): \Illuminate\Database\Eloquent\Casts\Attribute
{
return Attribute::make(
get: fn() => (new NiceDate())->get(null, '', $this->created_at, [])
);
}
/**
* Get notifications.
*
* @return void
*/
public static function getNotifications(): void
{
if (!Auth::guard('club')->check()) {
return;
}
/** @var \App\Models\Customer $customerModel */
$customerModel = Auth::guard('club')->user();
$notifications = $customerModel->getAllNotifications();
View::share('notifications', count($notifications) - $customerModel->readNotifications()->count());
View::share('notificationsList', $notifications);
}
// * RELATIONSHIPS
/**
* Get the customer that owns the Notifications
* Get the customer that owns the Notifications.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@ -51,7 +84,7 @@ class Notification extends Model
}
/**
* Polymorphic relation : Get the parent model
* Polymorphic relation : Get the parent model.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
@ -59,18 +92,4 @@ class Notification extends Model
{
return $this->morphTo();
}
// * METHODS
/**
* created_at_nice_date attribute
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
public function createdAtNiceDate(): \Illuminate\Database\Eloquent\Casts\Attribute
{
return Attribute::make(
get: fn () => (new NiceDate())->get(null, '', $this->created_at, [])
);
}
}

117
app/Models/Order.php Normal file
View file

@ -0,0 +1,117 @@
<?php
namespace App\Models;
use App\Enums\Shop\ContactFormCivility;
use App\Enums\Shop\OrderStatus;
use App\Enums\Shop\OrderType;
use Illuminate\Database\Eloquent\Model;
/**
* @property string $ref
* @property string $firstname
* @property string $lastname
* @property string $address
* @property string $postcode
* @property string|null $phone
* @property string $email
* @property string $city
* @property \App\Enums\Shop\ContactFormCivility $civility
* @property \App\Enums\Shop\OrderStatus $status
* @property \App\Enums\Shop\OrderType $payementType
* @property boolean $confirmMailSent
* @property \App\Models\Customer $customer_id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
*/
class Order extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'firstname',
'lastname',
'address',
'postcode',
'phone',
'email',
'city',
'civility',
'status',
'payementType',
'customer_id',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'civility' => ContactFormCivility::class,
'status' => OrderStatus::class,
'payementType' => OrderType::class
];
// * METHODS
/**
* Export the model data to a Formatted Arcadia Data array.
*
* @return array<string,string|integer|float|array<string,integer>>
*/
public function exportToOrderMailData(): array
{
return [
'ref' => $this->ref,
'civility' => $this->civility->value(),
'lastname' => $this->lastname,
'firstname' => $this->firstname,
'address' => $this->address,
'postcode' => $this->postcode,
'city' => $this->city,
'email' => $this->email,
'phone' => $this->phone ?? '',
'items' => $this->sellItems()->withPivot('quantity')->get()->map(function (SellItem $item) {
// @phpstan-ignore-next-line
$item->typeCustom = $item->type->toArray()[$item->type->name()];
return $item;
})->toArray()
];
}
// * RELATIONSHIPS
/**
* Get all of the items that are assigned this order.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function sellItems(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->belongsToMany(SellItem::class)->withPivot('quantity');
}
/**
* Get the customer that are assigned this order.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function customer(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Customer::class);
}
/**
* Get the delivery address that are assigned this order.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function deliveryAddress(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(DeliveryAddress::class);
}
}

View file

@ -0,0 +1,9 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\Pivot;
class OrderSellItem extends Pivot
{
}

View file

@ -150,7 +150,7 @@ class Product extends Model implements SeoInterface
* @return void
* @throws \Illuminate\Validation\ValidationException If a range label already exists.
*/
private static function assertLabelIsUnique(string|null $label, ?int $id = null)
private static function assertLabelIsUnique(string|null $label, ?int $id = null): void
{
$table = (new self())->getTable();
ToolboxHelper::assertFieldIsUnique($table, 'label', $label, $id);
@ -200,7 +200,7 @@ class Product extends Model implements SeoInterface
*
* @return void
*/
private static function resetCache()
private static function resetCache(): void
{
Cache::forget('publishedDiscoveredProducts');
self::getPublishedDiscovered();

Some files were not shown because too many files have changed in this diff Show more