Compare commits
2 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
656120f042 | ||
|
|
e3318d652c |
109 changed files with 21748 additions and 1708 deletions
|
|
@ -1,8 +1,8 @@
|
|||
APP_NAME=Laravel
|
||||
APP_NAME=Incollector
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
APP_URL=https://incollector.s-web.test
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
|
|
|
|||
47
.env.testing.example
Normal file
47
.env.testing.example
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
APP_NAME=Incollector
|
||||
APP_ENV=testing
|
||||
APP_KEY=base64:oRXNjgvWgIcboJN2O0NgaBt3kMUUfgyQ1Wv0S9/7sAA=
|
||||
APP_DEBUG=true
|
||||
APP_URL="http://127.0.0.1:8888"
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=dev-mariadb
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=testing-incollector
|
||||
DB_USERNAME=
|
||||
DB_PASSWORD=
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
QUEUE_CONNECTION=database
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailhog
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS=incollector@ldc.fr
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
13
.gitignore
vendored
13
.gitignore
vendored
|
|
@ -1,9 +1,22 @@
|
|||
/node_modules
|
||||
/public/hot
|
||||
/public/storage
|
||||
/public/css
|
||||
/public/js
|
||||
/public/images
|
||||
/public/fonts
|
||||
/public/medias
|
||||
/public/uploads
|
||||
/public/assets
|
||||
/public/mix-manifest.json
|
||||
.vscode
|
||||
|
||||
/storage/*.key
|
||||
/storage/inco/*
|
||||
/storage/marque/*
|
||||
/vendor
|
||||
.env
|
||||
.env.testing
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
docker-compose.override.yml
|
||||
|
|
|
|||
24
.vscode/settings.json
vendored
24
.vscode/settings.json
vendored
|
|
@ -1,23 +1,23 @@
|
|||
{
|
||||
"phpcs.executablePath": "vendor/bin/phpcs",
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.activeBackground": "#a714ac",
|
||||
"activityBar.activeBorder": "#eb549a",
|
||||
"activityBar.background": "#a714ac",
|
||||
"activityBar.activeBackground": "#834329",
|
||||
"activityBar.activeBorder": "#08180c",
|
||||
"activityBar.background": "#834329",
|
||||
"activityBar.foreground": "#e7e7e7",
|
||||
"activityBar.inactiveForeground": "#e7e7e799",
|
||||
"activityBarBadge.background": "#eb549a",
|
||||
"activityBarBadge.foreground": "#15202b",
|
||||
"sash.hoverBorder": "#a714ac",
|
||||
"statusBar.background": "#0f437e",
|
||||
"activityBarBadge.background": "#08180c",
|
||||
"activityBarBadge.foreground": "#e7e7e7",
|
||||
"sash.hoverBorder": "#834329",
|
||||
"statusBar.background": "#5c2f1d",
|
||||
"statusBar.foreground": "#e7e7e7",
|
||||
"statusBarItem.hoverBackground": "#a714ac",
|
||||
"statusBarItem.remoteBackground": "#0f437e",
|
||||
"statusBarItem.hoverBackground": "#834329",
|
||||
"statusBarItem.remoteBackground": "#5c2f1d",
|
||||
"statusBarItem.remoteForeground": "#e7e7e7",
|
||||
"titleBar.activeBackground": "#0f437e",
|
||||
"titleBar.activeBackground": "#5c2f1d",
|
||||
"titleBar.activeForeground": "#e7e7e7",
|
||||
"titleBar.inactiveBackground": "#0f437e99",
|
||||
"titleBar.inactiveBackground": "#5c2f1d99",
|
||||
"titleBar.inactiveForeground": "#e7e7e799"
|
||||
},
|
||||
"peacock.remoteColor": "#0f437e"
|
||||
"peacock.remoteColor": "#5c2f1d"
|
||||
}
|
||||
|
|
|
|||
78
app/Console/Commands/LdcWebStatusChecker.php
Normal file
78
app/Console/Commands/LdcWebStatusChecker.php
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Command Name: LDC Web Status Checker
|
||||
* Description: Envoi des infos Serveur/Laravel vers LDC Web
|
||||
* Version: 1.1
|
||||
* Author: Vincent BRIDIER
|
||||
* Author URI: vincent.bridier@ldc.fr
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class LdcWebStatusChecker extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ldcweb:statuschecker';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Envoi des infos Serveur/Laravel vers LDC Web';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$data = [];
|
||||
$data['uuid'] = config('ldcweb.project_uuid');
|
||||
|
||||
// Sitemap.xml ?
|
||||
if (file_exists(public_path() . '/sitemap.xml')) {
|
||||
$data['sitemap'] = 'true';
|
||||
} else {
|
||||
$data['sitemap'] = 'false';
|
||||
}
|
||||
|
||||
// Robots.txt ?
|
||||
if (file_exists(public_path() . '/robots.txt')) {
|
||||
$data['robots'] = 'true';
|
||||
} else {
|
||||
$data['robots'] = 'false';
|
||||
}
|
||||
|
||||
// Check logs.
|
||||
$data['logs'] = 0;
|
||||
$patherror = storage_path('/logs');
|
||||
$files = glob($patherror . '/*.log');
|
||||
if (count($files) > 0) {
|
||||
foreach ($files as $file) {
|
||||
$data['logs'] = $data['logs'] + filesize($file);
|
||||
}
|
||||
}
|
||||
|
||||
$data['code']['version'] = app()->version();
|
||||
|
||||
// Send by cURL.
|
||||
$url = 'https://ldc-web.ldc.fr/api/status-checker';
|
||||
$ch = curl_init($url);
|
||||
$payload = ['token' => 'CE8S52Qq7stf5k8frF4T', 'datas' => json_encode($data)];
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
49
app/Console/Commands/UserCreate.php
Normal file
49
app/Console/Commands/UserCreate.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UserCreate extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'user:create';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$firstname = $this->ask('What is the firstname?');
|
||||
$lastname = $this->ask('What is the lastname?');
|
||||
$email = $this->ask('What is the email?');
|
||||
$pwd = $this->secret('What is the password?');
|
||||
|
||||
$user = new User();
|
||||
$user->firstname = $firstname;
|
||||
$user->lastname = $lastname;
|
||||
$user->email = $email;
|
||||
$user->password = $pwd;
|
||||
$user->saveOrFail();
|
||||
|
||||
$this->info('User created.');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
37
app/Console/Commands/XmlBrandReader.php
Normal file
37
app/Console/Commands/XmlBrandReader.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\Arcadia\XmlBrandReaderJob;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class XmlBrandReader extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'xml:brand';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Run the XmlBrandReaderJob manually';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('Running the Job, this could take some time.');
|
||||
$job = new XmlBrandReaderJob();
|
||||
$job->console = $this;
|
||||
$job->handle();
|
||||
$this->info('Job completed');
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\XmlIncoReader as JobsXmlIncoReader;
|
||||
use App\Jobs\Arcadia\XmlIncoReaderJob;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class XmlIncoReader extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
|
|
@ -30,7 +29,7 @@ class XmlIncoReader extends Command
|
|||
public function handle()
|
||||
{
|
||||
$this->info('Running the Job, this could take some time.');
|
||||
$job = new JobsXmlIncoReader();
|
||||
$job = new XmlIncoReaderJob();
|
||||
$job->console = $this;
|
||||
$job->handle();
|
||||
$this->info('Job completed');
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Console\Commands\LdcWebStatusChecker;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
|
|
@ -12,20 +13,17 @@ class Kernel extends ConsoleKernel
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
//
|
||||
];
|
||||
protected $commands = [];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// $schedule->command('inspire')->hourly();
|
||||
//$schedule->job(new XmlIncoReader)->weeklyOn(1, '8:00');
|
||||
$schedule->command(LdcWebStatusChecker::class)->everyFifteenMinutes();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -35,8 +33,6 @@ class Kernel extends ConsoleKernel
|
|||
*/
|
||||
protected function commands()
|
||||
{
|
||||
$this->load(__DIR__.'/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
$this->load(__DIR__ . '/Commands');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
84
app/Enums/ApiError.php
Normal file
84
app/Enums/ApiError.php
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* This describes an API error.
|
||||
*
|
||||
* @method static self modelNotFound()
|
||||
* The request model was not found (typically the customer)
|
||||
*
|
||||
* @method static self validationFailed()
|
||||
* This means some data could not be validated,
|
||||
* you may have to look into message to get the details
|
||||
*
|
||||
* @method static self apiAuthFailed()
|
||||
* The authentification to the api failed. You may have to
|
||||
* check into config or .env file for your service credentials
|
||||
*
|
||||
* @method static self methodNotAllowed()
|
||||
* This http method is not allowed
|
||||
*
|
||||
* @method static self wrongTimeStamp()
|
||||
* The timestamp given is wrong. This would happen in case if
|
||||
* a replay attack scenario. Timestamps are provided in headers
|
||||
* and in the http body
|
||||
*
|
||||
* @method static self missingParameter()
|
||||
* The request is missing some parameters
|
||||
*
|
||||
* @method static self throttleRequestsException()
|
||||
* Too many requests have been attempted. The is a throttle security.
|
||||
* Normally you should not trigger this.
|
||||
* If this happens fill a ticket on https://supportweb.ldc.fr
|
||||
* with some technical details
|
||||
*
|
||||
* @method static self authorizationException()
|
||||
* You are maybe trying to access data that is out of your range.
|
||||
* This should not happen normally, it is here to allow you to handle this case.
|
||||
* If this happens fill a ticket on https://supportweb.ldc.fr
|
||||
* with some technical details
|
||||
*
|
||||
*/
|
||||
class ApiError extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Valeurs des possibilités de cet énumération (value)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function values(): array
|
||||
{
|
||||
return [
|
||||
'modelNotFound' => 101,
|
||||
'validationFailed' => 102,
|
||||
'apiAuthFailed' => 119,
|
||||
'methodNotAllowed' => 150,
|
||||
'wrongTimeStamp' => 151,
|
||||
'missingParameter' => 400,
|
||||
'authorizationException' => 403,
|
||||
'throttleRequestsException' => 429
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Libellés des possibilités de cet énumération (label)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function labels(): array
|
||||
{
|
||||
return [
|
||||
'modelNotFound' => '%s introuvable.',
|
||||
'validationFailed' => 'Impossible de valider les données',
|
||||
'apiAuthFailed' => 'Echec de l\'authentification client à l\'Api LDC-CRM pour ce service',
|
||||
'methodNotAllowed' => 'This method is not allowed for this request',
|
||||
'wrongTimeStamp' => 'Your request is malformed, please check timestamp header and parameter',
|
||||
'missingParameter' => 'The request is missing some parameters',
|
||||
'authorizationException' => 'You are not autorized to access this',
|
||||
'throttleRequestsException' => 'Throttle: too many request have been attempted, please retry later'
|
||||
];
|
||||
}
|
||||
}
|
||||
16
app/Enums/ApiStatus.php
Normal file
16
app/Enums/ApiStatus.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self OK()
|
||||
* @method static self KO()
|
||||
*
|
||||
* @package LDCCrmClient
|
||||
* @subpackage enums
|
||||
*/
|
||||
class ApiStatus extends BaseEnumRoutable
|
||||
{
|
||||
}
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use ErrorException;
|
||||
|
||||
class AbortXmlImportException extends Exception
|
||||
class AbortXmlImportException extends ErrorException
|
||||
{
|
||||
}
|
||||
|
|
|
|||
101
app/Exceptions/Api/ApiErrorException.php
Normal file
101
app/Exceptions/Api/ApiErrorException.php
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exceptions\Api;
|
||||
|
||||
use App\Enums\ApiError;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* This would be thrown if any of the case
|
||||
* referenced in \App\Enums\ApiError would
|
||||
* occur within the crm
|
||||
*
|
||||
* On the client an ApiErrorException would
|
||||
* also be throw with the ApiError corresponding to
|
||||
* the situation
|
||||
*/
|
||||
class ApiErrorException extends Exception
|
||||
{
|
||||
/**
|
||||
* Api Error
|
||||
* This value makes the error more explicit.
|
||||
* Handling these errors are normal as inputs or
|
||||
* request may be undesired or refused by the crm.
|
||||
*
|
||||
* @var \App\Enums\ApiError
|
||||
*/
|
||||
protected $error;
|
||||
|
||||
/**
|
||||
* This is an explicit error message,
|
||||
* ou may print this to the front or not depending
|
||||
* on $error value
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $message;
|
||||
|
||||
/**
|
||||
* This is the http code returned by the crm.
|
||||
* This value could be used to handle errors.
|
||||
* But please take in consideration $error first
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $httpCode;
|
||||
|
||||
/**
|
||||
* Create a new exception base on ApiError enum.
|
||||
*
|
||||
* @param ApiError $error
|
||||
* @param integer $httpCode
|
||||
* @param string $message
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct(ApiError $error, int $httpCode = 400, string $message = '', Throwable $previous = null)
|
||||
{
|
||||
$this->error = $error;
|
||||
$this->message = $message;
|
||||
$this->httpCode = $httpCode;
|
||||
parent::__construct(
|
||||
strlen($this->message) ? $this->message : $error->label,
|
||||
$error->value,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Api Error
|
||||
*
|
||||
* @return ApiError
|
||||
*/
|
||||
public function getApiError(): ApiError
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the http code
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getStatusCode(): int
|
||||
{
|
||||
return $this->httpCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used by laravel only.
|
||||
* It uses Log class to print the error.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function report()
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
Log::debug(sprintf('CRM API: %s', $this->getMessage()));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
25
app/Exceptions/Api/ApplicationException.php
Normal file
25
app/Exceptions/Api/ApplicationException.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exceptions\Api;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* This is a critical error.
|
||||
* The request could not be handled. You may dump any value you can
|
||||
* get before submitting a ticket to https://supportweb.ldc.fr
|
||||
*/
|
||||
class ApplicationException extends Exception
|
||||
{
|
||||
/**
|
||||
* This is used by laravel only.
|
||||
* It uses Log class to print the error.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function report()
|
||||
{
|
||||
Log::critical(sprintf('API: %s', $this->getMessage()));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,20 @@
|
|||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use App\Enums\ApiError;
|
||||
use App\Enums\ApiStatus;
|
||||
use App\Exceptions\Api\ApiErrorException;
|
||||
use App\Http\Resources\Api\V1\ApiResponseResource;
|
||||
use App\Lib\Helper;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\Exceptions\ThrottleRequestsException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
|
|
@ -10,19 +23,18 @@ class Handler extends ExceptionHandler
|
|||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var string[]
|
||||
* @var array
|
||||
*/
|
||||
protected $dontReport = [
|
||||
//
|
||||
ApiErrorException::class
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed for validation exceptions.
|
||||
*
|
||||
* @var string[]
|
||||
* @var array
|
||||
*/
|
||||
protected $dontFlash = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
|
@ -34,8 +46,125 @@ class Handler extends ExceptionHandler
|
|||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->reportable(function (Throwable $e) {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an exception into an HTTP response.
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param \Throwable $e
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function render($request, Throwable $e)
|
||||
{
|
||||
if (Helper::isRequestForApiV1($request) and $request->isJson()) {
|
||||
return $this->handleApiV1Exception($request, $e);
|
||||
} //end if
|
||||
// @codeCoverageIgnoreStart
|
||||
return parent::render($request, $e);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a json response for any apiV2 error case
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Throwable $e
|
||||
* @return JsonResponse
|
||||
*/
|
||||
private function handleApiV1Exception(Request $request, \Throwable $e): JsonResponse
|
||||
{
|
||||
switch (get_class($e)) {
|
||||
case AuthenticationException::class:
|
||||
/** @var AuthenticationException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
401,
|
||||
ApiError::apiAuthFailed()->value,
|
||||
sprintf('%s, %s', ApiError::apiAuthFailed()->label, $e->getMessage())
|
||||
);
|
||||
case MethodNotAllowedHttpException::class:
|
||||
/** @var MethodNotAllowedHttpException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
$e->getStatusCode(),
|
||||
ApiError::methodNotAllowed()->value,
|
||||
sprintf('%s, %s', ApiError::methodNotAllowed()->label, $e->getMessage())
|
||||
);
|
||||
case ValidationException::class:
|
||||
/** @var ValidationException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
$e->status,
|
||||
ApiError::validationFailed()->value,
|
||||
sprintf(ApiError::validationFailed()->label, $e->getMessage()),
|
||||
['errors' => $e->errors()]
|
||||
);
|
||||
case ModelNotFoundException::class:
|
||||
/** @var ModelNotFoundException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
404,
|
||||
ApiError::modelNotFound()->value,
|
||||
sprintf(
|
||||
ApiError::modelNotFound()->label,
|
||||
\array_slice(explode('\\', $e->getModel()), -1)[0]
|
||||
)
|
||||
);
|
||||
case ApiErrorException::class:
|
||||
/** @var ApiErrorException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
$e->getStatusCode(),
|
||||
$e->getCode(),
|
||||
$e->getMessage()
|
||||
);
|
||||
case ThrottleRequestsException::class:
|
||||
/** @var ThrottleRequestsException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
429,
|
||||
ApiError::throttleRequestsException()->value,
|
||||
ApiError::throttleRequestsException()->label
|
||||
);
|
||||
case AuthorizationException::class:
|
||||
/** @var AuthorizationException $e */
|
||||
return $this->getReponse(
|
||||
$request,
|
||||
403,
|
||||
ApiError::authorizationException()->value,
|
||||
ApiError::authorizationException()->label
|
||||
);
|
||||
} //end switch
|
||||
// @codeCoverageIgnoreStart
|
||||
if (config('app.env') === 'testing') {
|
||||
// phpcs:ignore Squiz.PHP.DiscouragedFunctions.Found
|
||||
print_r((string)$e);
|
||||
}
|
||||
return $this->getReponse($request, 500, $e->getCode(), $e->getMessage());
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an ApiV2 json response
|
||||
*
|
||||
* @param Request $request
|
||||
* @param integer $httpCode
|
||||
* @param integer $apiCode
|
||||
* @param string $message
|
||||
* @param array $data
|
||||
* @return JsonResponse
|
||||
*/
|
||||
private static function getReponse(
|
||||
Request $request,
|
||||
int $httpCode,
|
||||
int $apiCode,
|
||||
string $message,
|
||||
array $data = []
|
||||
): JsonResponse {
|
||||
return (new ApiResponseResource(
|
||||
(object)array_merge($data, ['message' => $message, 'code' => $apiCode]),
|
||||
ApiStatus::KO()
|
||||
))->toResponse($request)->setStatusCode($httpCode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use ErrorException;
|
||||
|
||||
class InvalidXmlException extends Exception
|
||||
class InvalidXmlException extends ErrorException
|
||||
{
|
||||
}
|
||||
|
|
|
|||
19
app/Http/Controllers/Api/V1/ApiController.php
Normal file
19
app/Http/Controllers/Api/V1/ApiController.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class ApiController extends Controller
|
||||
{
|
||||
/**
|
||||
* Just returns HTTP 200 response
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function ping(): JsonResponse
|
||||
{
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
58
app/Http/Controllers/Api/V1/XmlIncoController.php
Normal file
58
app/Http/Controllers/Api/V1/XmlIncoController.php
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Api\V1\XmlIncosIndexRequest;
|
||||
use App\Http\Resources\Api\V1\XmlIncoResource;
|
||||
use App\Models\XmlInco;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class XmlIncoController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns xmlIncos.
|
||||
*
|
||||
* @param XmlIncosIndexRequest $request
|
||||
* - autorised is 'brand' with id
|
||||
* @return JsonResource
|
||||
*/
|
||||
public function index(XmlIncosIndexRequest $request): ResourceCollection
|
||||
{
|
||||
/** @var \App\Models\ArcadiaBrand|null $arcadiaBrand */
|
||||
$arcadiaBrand = $request->arcadiaBrand;
|
||||
|
||||
$xmlIncos = XmlInco::query();
|
||||
|
||||
if ($arcadiaBrand) {
|
||||
// * Make sure we are accessing xmlIncos that belongs to our service.
|
||||
$this->authorize('arcadiaBrandBelongsToService', $arcadiaBrand);
|
||||
|
||||
$xmlIncos->whereHas('arcadiaBrands', function ($q) use ($arcadiaBrand) {
|
||||
$q->whereId($arcadiaBrand->id);
|
||||
});
|
||||
}
|
||||
|
||||
return XmlIncoResource::collection($xmlIncos->simplePaginate(
|
||||
$request->per_page,
|
||||
['*'],
|
||||
'page',
|
||||
$request->page
|
||||
)->items());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a specific xmlInco.
|
||||
*
|
||||
* @param XmlInco $xmlInco
|
||||
* @return JsonResource
|
||||
*/
|
||||
public function show(XmlInco $xmlInco): JsonResource
|
||||
{
|
||||
// * Make sure we are accessing a xmlInco that belongs to our service.
|
||||
$this->authorize('arcadiaBrandBelongsToService', $xmlInco->arcadiaBrand);
|
||||
|
||||
return new XmlIncoResource($xmlInco);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,5 +9,7 @@ use Illuminate\Routing\Controller as BaseController;
|
|||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
use AuthorizesRequests;
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ class Kernel extends HttpKernel
|
|||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
// \App\Http\Middleware\TrustHosts::class,
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\Fruitcake\Cors\HandleCors::class,
|
||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\App\Http\Middleware\XssSanitizer::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
];
|
||||
|
||||
|
|
@ -33,16 +33,18 @@ class Kernel extends HttpKernel
|
|||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
// \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
|
||||
'throttle:api',
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\App\Http\Middleware\JsonOnly::class,
|
||||
\App\Http\Middleware\ApiResponse::class,
|
||||
\App\Http\Middleware\ApiCheckTimeStamps::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class
|
||||
],
|
||||
];
|
||||
|
||||
|
|
|
|||
38
app/Http/Middleware/ApiCheckTimeStamps.php
Normal file
38
app/Http/Middleware/ApiCheckTimeStamps.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Enums\ApiError;
|
||||
use App\Exceptions\Api\ApiErrorException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
/**
|
||||
* Check Http Header Timestamp with request timestamp
|
||||
* to prevent replay attacks
|
||||
* https://restfulapi.net/security-essentials/
|
||||
*/
|
||||
class ApiCheckTimeStamps
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
* @throws ApiErrorException With ApiError::wrongTimeStamp if timestamp has an incorrect format or is timed out.
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next)
|
||||
{
|
||||
if (!\is_string($request->timestamp) or !Carbon::hasFormat($request->timestamp, 'Y-m-d H:i:s')) {
|
||||
throw new ApiErrorException(ApiError::wrongTimeStamp());
|
||||
}
|
||||
if (
|
||||
Carbon::parse($request->timestamp, 'utc')
|
||||
->isBefore(Carbon::now('UTC')->subSeconds(config('api.timestampTimeout', 10)))
|
||||
) {
|
||||
throw new ApiErrorException(ApiError::wrongTimeStamp());
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
57
app/Http/Middleware/ApiResponse.php
Normal file
57
app/Http/Middleware/ApiResponse.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Enums\ApiStatus;
|
||||
use App\Http\Resources\Api\V1\ApiResponseResource;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ApiResponse
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
* @throws \ErrorException If the received response is not a JsonResponse.
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next)
|
||||
{
|
||||
/** @var \Illuminate\Http\JsonResponse $response */
|
||||
$response = $next($request);
|
||||
|
||||
if (\get_class($response) !== JsonResponse::class) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \ErrorException('All api responses should be json.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
// Set no cache header.
|
||||
$response->header('Cache-Control', 'No-Store');
|
||||
|
||||
/** @var \App\Models\Service|null */
|
||||
if (\optional($service = app(Service::class))->id) {
|
||||
$service->incrementStat();
|
||||
}
|
||||
|
||||
/** @var object $data */
|
||||
$data = $response->getData();
|
||||
|
||||
// If reponse is already a V2ApiResponse then just return it. This happens if error handler comes to action.
|
||||
if (
|
||||
isset($data->status) and
|
||||
isset($data->data) and
|
||||
isset($data->version) and
|
||||
in_array($data->status, [ApiStatus::OK()->value, ApiStatus::KO()->value])
|
||||
) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
/** @var \App\Enums\ApiStatus $status */
|
||||
$status = intval($response->getStatusCode() / 100) == 2 ? ApiStatus::OK() : ApiStatus::KO();
|
||||
return $response->setData(new ApiResponseResource((object)$response->getData(), $status));
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ class Authenticate extends Middleware
|
|||
/**
|
||||
* Get the path the user should be redirected to when they are not authenticated.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
protected function redirectTo($request)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,5 @@ class EncryptCookies extends Middleware
|
|||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
];
|
||||
}
|
||||
|
|
|
|||
24
app/Http/Middleware/JsonOnly.php
Normal file
24
app/Http/Middleware/JsonOnly.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class JsonOnly
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next)
|
||||
{
|
||||
if (!$request->isJson() or !$request->expectsJson() or is_null(json_decode($request->getContent()))) {
|
||||
abort(400, 'Invalid JSON');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,5 @@ class PreventRequestsDuringMaintenance extends Middleware
|
|||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ class RedirectIfAuthenticated
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null ...$guards
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null ...$guards
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, ...$guards)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class TrustProxies extends Middleware
|
|||
/**
|
||||
* The headers that should be used to detect proxies.
|
||||
*
|
||||
* @var int
|
||||
* @var integer
|
||||
*/
|
||||
protected $headers =
|
||||
Request::HEADER_X_FORWARDED_FOR |
|
||||
|
|
|
|||
|
|
@ -12,6 +12,5 @@ class VerifyCsrfToken extends Middleware
|
|||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
];
|
||||
}
|
||||
|
|
|
|||
25
app/Http/Middleware/XssSanitizer.php
Normal file
25
app/Http/Middleware/XssSanitizer.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class XssSanitizer
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$input = $request->all();
|
||||
array_walk_recursive($input, function (&$input) {
|
||||
$input = strip_tags($input);
|
||||
});
|
||||
$request->merge($input);
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
31
app/Http/Requests/Api/V1/PaginatorRequest.php
Normal file
31
app/Http/Requests/Api/V1/PaginatorRequest.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Api\V1;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class PaginatorRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'page' => 'sometimes|numeric|min:1',
|
||||
'per_page' => 'sometimes|numeric|min:1|max:100',
|
||||
];
|
||||
}
|
||||
}
|
||||
36
app/Http/Requests/Api/V1/XmlIncosIndexRequest.php
Normal file
36
app/Http/Requests/Api/V1/XmlIncosIndexRequest.php
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Api\V1;
|
||||
|
||||
use App\Models\ArcadiaBrand;
|
||||
|
||||
class XmlIncosIndexRequest extends PaginatorRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
$this->merge([
|
||||
'brand' => $this->brand ? ArcadiaBrand::whereId($this->brand)->firstOrFail() : null
|
||||
]);
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return \array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
'brand' => 'nullable'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
42
app/Http/Resources/Api/V1/ApiResponseResource.php
Normal file
42
app/Http/Resources/Api/V1/ApiResponseResource.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources\Api\V1;
|
||||
|
||||
use App\Enums\ApiStatus;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use stdClass;
|
||||
|
||||
class ApiResponseResource extends JsonResource
|
||||
{
|
||||
/** @var stdClass */
|
||||
protected $data;
|
||||
|
||||
/** @var \App\Enums\ApiStatus */
|
||||
protected $status;
|
||||
|
||||
/**
|
||||
* @param stdClass $data
|
||||
* @param ApiStatus $status
|
||||
*/
|
||||
public function __construct(stdClass $data = null, ApiStatus $status)
|
||||
{
|
||||
$this->status = $status;
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param mixed $request
|
||||
* @return array
|
||||
*/
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass, Squiz.Commenting.FunctionComment.Missing
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'status' => $this->status->value,
|
||||
'data' => (array)$this->data,
|
||||
'version' => config('api.version')
|
||||
];
|
||||
}
|
||||
}
|
||||
66
app/Http/Resources/Api/V1/XmlIncoResource.php
Normal file
66
app/Http/Resources/Api/V1/XmlIncoResource.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources\Api\V1;
|
||||
|
||||
use App\Models\XmlInco;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class XmlIncoResource extends JsonResource
|
||||
{
|
||||
/** @var array */
|
||||
private static $skeleton = [
|
||||
'id' => '',
|
||||
'no_art' => '',
|
||||
'prod_saison' => '',
|
||||
'allegations' => '',
|
||||
'conseil_prepa' => '',
|
||||
'astuces' => '',
|
||||
'descriptif' => '',
|
||||
'arg_vente' => '',
|
||||
'nb_portion' => '',
|
||||
'typ_portion' => '',
|
||||
'pds_moy_theo' => '',
|
||||
'lib_conso' => '',
|
||||
'lst_ing' => '',
|
||||
'lib_allergene' => '',
|
||||
'nutritional_values' => '',
|
||||
'pictures' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* XmlIncoResource
|
||||
*
|
||||
* @param XmlInco $xmlInco
|
||||
*/
|
||||
public function __construct(XmlInco $xmlInco)
|
||||
{
|
||||
$this->xmlInco = $xmlInco;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request|null $request
|
||||
* @return array
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
public function toArray($request = null)
|
||||
{
|
||||
$data = array_intersect_key(
|
||||
$this->xmlInco->toArray(),
|
||||
$this->getSkeleton()
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource skeletton
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getSkeleton(): array
|
||||
{
|
||||
return self::$skeleton;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
namespace App\Jobs\Arcadia;
|
||||
|
||||
use App\Enums\LogType;
|
||||
use Exception;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Filesystem\Filesystem;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
|
@ -30,9 +29,23 @@ abstract class XArcadiaFlux implements ShouldQueue
|
|||
|
||||
/**
|
||||
* This is for Laravel Console usage
|
||||
* @var \Illuminate\Console\Command|null
|
||||
*/
|
||||
public $console = null;
|
||||
|
||||
/**
|
||||
* This is for Laravel Console usage
|
||||
* @var \Symfony\Component\Console\Helper\ProgressBar|null
|
||||
*/
|
||||
public $progressBar = null;
|
||||
|
||||
/**
|
||||
* invalid xml folder
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $invalidFolderName = 'invalid';
|
||||
|
||||
/**
|
||||
* The relative folder where to archive data
|
||||
*
|
||||
|
|
@ -53,6 +66,7 @@ abstract class XArcadiaFlux implements ShouldQueue
|
|||
* Check if the file extension
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $extension
|
||||
* @return boolean
|
||||
*/
|
||||
protected function checkExtension(string $filename, string $extension): bool
|
||||
|
|
@ -69,6 +83,81 @@ abstract class XArcadiaFlux implements ShouldQueue
|
|||
return $isExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the file to invalid folder
|
||||
*
|
||||
* @param string $filename
|
||||
* @return void
|
||||
*/
|
||||
protected function moveToInvalid(string $filename): void
|
||||
{
|
||||
$newFileName = $filename;
|
||||
if (!$this->getDisk()->exists($filename)) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be moved to invalid (not found)',
|
||||
$filename
|
||||
),
|
||||
LogType::warning()
|
||||
);
|
||||
return;
|
||||
}
|
||||
if ($this->getDisk()->exists(sprintf('%s/%s', $this->invalidFolderName, $filename))) {
|
||||
$ext = \pathinfo($filename, \PATHINFO_EXTENSION);
|
||||
$newFileName = \sprintf(
|
||||
'%s_%d.%s',
|
||||
\substr($filename, 0, 0 - (strlen($ext) + 1)),
|
||||
\time(),
|
||||
$ext
|
||||
);
|
||||
}
|
||||
try {
|
||||
if (!$this->getDisk()->move($filename, sprintf('%s/%s', $this->invalidFolderName, $newFileName))) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be moved to invalid',
|
||||
$filename
|
||||
),
|
||||
LogType::warning()
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be moved to invalid',
|
||||
$filename
|
||||
),
|
||||
LogType::warning()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppression des fichiers dans
|
||||
* invalid qui ont plus de 6 mois
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function clearOldInvalids(): void
|
||||
{
|
||||
$disk = $this->getDisk();
|
||||
$invalids = $disk->files($this->invalidFolderName);
|
||||
|
||||
// /** @var File */
|
||||
foreach ($invalids as $invalid) {
|
||||
$pi = \pathinfo($invalid, \PATHINFO_BASENAME);
|
||||
if (in_array($pi, $this->ignoreFiles)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($disk->lastModified($invalid) < strtotime(Carbon::now()->subMonth(6))) {
|
||||
if (!$disk->delete($invalid)) {
|
||||
Log::critical(sprintf('%s : Could not delete file %s', get_class($this), $invalid));
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the file to archives
|
||||
*
|
||||
|
|
@ -107,7 +196,7 @@ abstract class XArcadiaFlux implements ShouldQueue
|
|||
LogType::warning()
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be moved to archives',
|
||||
|
|
@ -160,6 +249,7 @@ abstract class XArcadiaFlux implements ShouldQueue
|
|||
* @param string $message
|
||||
* @param LogType $logtype
|
||||
* @return void
|
||||
* @throws \ErrorException If logtype is not handled.
|
||||
*/
|
||||
protected function log(string $message, LogType $logtype = null): void
|
||||
{
|
||||
|
|
@ -187,8 +277,8 @@ abstract class XArcadiaFlux implements ShouldQueue
|
|||
Log::critical($message);
|
||||
break;
|
||||
default:
|
||||
throw new Exception(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label));
|
||||
}//end switch
|
||||
throw new \ErrorException(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label));
|
||||
} //end switch
|
||||
$this->consolePrint($message, $logtype);
|
||||
}
|
||||
|
||||
|
|
@ -198,9 +288,11 @@ abstract class XArcadiaFlux implements ShouldQueue
|
|||
* @param string $message
|
||||
* @param LogType $logtype
|
||||
* @return void
|
||||
* @throws \ErrorException If logtype is not handled.
|
||||
*/
|
||||
protected function consolePrint(string $message, LogType $logtype): void
|
||||
{
|
||||
$this->clearProgressBarFromLine();
|
||||
if ($this->console) {
|
||||
switch ($logtype->value) {
|
||||
case LogType::debug()->value:
|
||||
|
|
@ -216,8 +308,59 @@ abstract class XArcadiaFlux implements ShouldQueue
|
|||
$this->console->error($message);
|
||||
break;
|
||||
default:
|
||||
throw new Exception(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label));
|
||||
throw new \ErrorException(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start ProgressBar
|
||||
*
|
||||
* @param integer $total
|
||||
* @return void
|
||||
*/
|
||||
protected function startProgressBar(int $total)
|
||||
{
|
||||
if ($this->console) {
|
||||
$this->progressBar = $this->console->getOutput()
|
||||
->createProgressBar($total - 1);
|
||||
$this->progressBar->start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the line to write someting
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function clearProgressBarFromLine()
|
||||
{
|
||||
if ($this->progressBar) {
|
||||
$this->progressBar->clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment 1 on progress bar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function incrementProgressBar()
|
||||
{
|
||||
if ($this->progressBar) {
|
||||
$this->progressBar->advance();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End the progress bar
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function endProgressBar()
|
||||
{
|
||||
if ($this->progressBar) {
|
||||
$this->progressBar->finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
55
app/Jobs/Arcadia/XmlBrandReaderJob.php
Normal file
55
app/Jobs/Arcadia/XmlBrandReaderJob.php
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs\Arcadia;
|
||||
|
||||
use App\Models\ArcadiaBrand;
|
||||
|
||||
class XmlBrandReaderJob extends XmlJobs
|
||||
{
|
||||
/**
|
||||
* The xsd file path used to validate files
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $xsdSchemaPath = 'resources/documents/arcadia/marque.xsd';
|
||||
|
||||
/**
|
||||
* Disk name from config/filesystems.php
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $disk = 'arcadia_brand';
|
||||
|
||||
/**
|
||||
* @var array Columns to take from the xml.
|
||||
*/
|
||||
protected $takeColumns = [
|
||||
'codMarq' => 'arcadia_id',
|
||||
'libMarq' => 'libelle',
|
||||
];
|
||||
|
||||
/**
|
||||
* Fields that are allowed to be null
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nullableFields = [];
|
||||
|
||||
/**
|
||||
* Unique keys for updating rows
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $uniqueKeyField = ['arcadia_id'];
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$this->parseData('dam', ArcadiaBrand::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
namespace App\Jobs\Arcadia;
|
||||
|
||||
use App\Exceptions\AbortXmlImportException;
|
||||
use App\Models\XmlInco;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use SimpleXMLElement;
|
||||
|
||||
class XmlIncoReader extends XmlJobs
|
||||
class XmlIncoReaderJob extends XmlJobs
|
||||
{
|
||||
/**
|
||||
* The xsd file path used to validate files
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $xsdSchemaPath = 'resources/documents/inco/incollector.xsd';
|
||||
|
||||
/**
|
||||
* Disk name from config/filesystems.php
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $disk = 'inco';
|
||||
|
||||
/**
|
||||
* Storage path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $imagesPath = 'images';
|
||||
|
||||
protected $xsdFile = 'xsd/incollector.xsd';
|
||||
|
||||
/**
|
||||
* éléments à la racine : nom du noeud
|
||||
* sous éléments d'un noeud PARENT :
|
||||
|
|
@ -29,31 +45,35 @@ class XmlIncoReader extends XmlJobs
|
|||
* 'EXPLOITANT' => 'exploitant', // Consider this sub array
|
||||
* 'EXPLOITANT.ID_SOCIETE' => 'id_societe',
|
||||
* 'EXPLOITANT.NOM_SOCIETE' => 'nom_societe',
|
||||
* @var array Columns to take from the xml.
|
||||
*/
|
||||
protected $takeColumns = [
|
||||
'NO_ART' => 'id', // primary key on model
|
||||
|
||||
//this wil not return anything cf doc above
|
||||
'NO_ART' => 'id',
|
||||
// primary key on model
|
||||
// this wil not return anything cf doc above
|
||||
'ID_SOCIETE' => 'id_societe',
|
||||
'NOM_SOCIETE' => 'nom_societe',
|
||||
|
||||
'PROD_SAISON' => 'prod_saison',
|
||||
'NOM' => 'nom',
|
||||
'NUMERO' => 'numero',
|
||||
'TAILLE_REF' => 'taille_ref', //$poidsRef censé être dans INCO_COMPO (et généralement 100g)
|
||||
'TAILLE_REF' => 'taille_ref',
|
||||
// $poidsRef censé être dans INCO_COMPO (et généralement 100g)
|
||||
'ALLEGATIONS' => 'allegations',
|
||||
'CONSEIL_PREPA' => 'conseil_prepa',
|
||||
'ASTUCES' => 'astuces',
|
||||
'DESCRIPTIF' => 'descriptif', //$descriptif
|
||||
'DESCRIPTIF' => 'descriptif',
|
||||
// $descriptif
|
||||
'ARG_VENTE' => 'arg_vente',
|
||||
'NB_PORTION' => 'nb_portion',
|
||||
'TYP_PORTION' => 'typ_portion',
|
||||
'PDS_MOY_THEO' => 'pds_moy_theo',
|
||||
'LIB_CONSO' => 'lib_conso',
|
||||
'LST_ING' => 'lst_ing', //$ingredients
|
||||
|
||||
'LST_ING' => 'lst_ing',
|
||||
// $ingredients
|
||||
// list alergene
|
||||
'LST_ALLERGENE' => 'lst_allergene', // Consider this sub array
|
||||
'LST_ALLERGENE' => 'lst_allergene',
|
||||
// Consider this sub array
|
||||
'LST_ALLERGENE.LIB_ALLERGENE' => 'lib_allergene',
|
||||
|
||||
// Allegations
|
||||
|
|
@ -62,11 +82,13 @@ class XmlIncoReader extends XmlJobs
|
|||
'ALLEGAT_AUTRE' => 'allegat_autre',
|
||||
|
||||
|
||||
'INCO_COMPO' => 'inco_compo', // Consider this sub array
|
||||
'INCO_COMPO' => 'inco_compo',
|
||||
// Consider this sub array
|
||||
'INCO_COMPO.NOM' => 'nom',
|
||||
'INCO_COMPO.TAILLE_REF' => 'taille_ref',
|
||||
'INCO_COMPO.VAL_ENERG_KJ_NUT' => 'val_energ_kj_nut',
|
||||
'INCO_COMPO.VAL_ENERG_KJ_R' => 'val_energ_kj_r', //_R apports de la taille_ref
|
||||
'INCO_COMPO.VAL_ENERG_KJ_R' => 'val_energ_kj_r',
|
||||
// _R apports de la taille_ref
|
||||
'INCO_COMPO.VAL_ENERG_KCAL_R' => 'val_energ_kcal_r',
|
||||
'INCO_COMPO.VAL_ENERG_KCAL_NUT' => 'val_energ_kcal_nut',
|
||||
'INCO_COMPO.MAT_GRASS_R' => 'mat_grass_r',
|
||||
|
|
@ -87,7 +109,8 @@ class XmlIncoReader extends XmlJobs
|
|||
'INCO_COMPO.ENER_E14_R' => 'ener_e14_r',
|
||||
'INCO_COMPO.FRUITS_R' => 'fruits_r',
|
||||
'INCO_COMPO.FRUITS_COQUE_SECH_R' => 'fruits_coque_sech_r',
|
||||
'INCO_COMPO.POURCENT_APPORT_REF_E14_R' => 'pourcent_apport_ref_e14_r', //POURCENT_*_P apports journaliers par portion
|
||||
'INCO_COMPO.POURCENT_APPORT_REF_E14_R' => 'pourcent_apport_ref_e14_r',
|
||||
// POURCENT_*_P apports journaliers par portion
|
||||
'INCO_COMPO.ENER_KJO_R' => 'ener_kjo_r',
|
||||
'INCO_COMPO.POURCENT_APPORT_REF_KJO_R' => 'pourcent_apport_ref_kjo_r',
|
||||
'INCO_COMPO.POURCENT_APPORT_REF_FAT_R' => 'pourcent_apport_ref_fat_r',
|
||||
|
|
@ -104,8 +127,10 @@ class XmlIncoReader extends XmlJobs
|
|||
'INCO_COMPO.SALTEQ_R' => 'salteq_r',
|
||||
'INCO_COMPO.POURCENT_APPORT_REF_SALTEQ_R' => 'pourcent_apport_ref_salteq_r',
|
||||
'INCO_COMPO.APPORT_REF' => 'apport_ref',
|
||||
'INCO_COMPO.TAILLE_PORT' => 'taille_port', //$poidsPortion
|
||||
'INCO_COMPO.VAL_ENERG_KJ_P' => 'val_energ_kj_p', //_P apports par portion
|
||||
'INCO_COMPO.TAILLE_PORT' => 'taille_port',
|
||||
// $poidsPortion
|
||||
'INCO_COMPO.VAL_ENERG_KJ_P' => 'val_energ_kj_p',
|
||||
// _P apports par portion
|
||||
'INCO_COMPO.VAL_ENERG_KCAL_P' => 'val_energ_kcal_p',
|
||||
'INCO_COMPO.MAT_GRASS_P' => 'mat_grass_p',
|
||||
'INCO_COMPO.AGS_P' => 'ags_p',
|
||||
|
|
@ -147,8 +172,10 @@ class XmlIncoReader extends XmlJobs
|
|||
'INCO_COMPO.COMPOSANTE_N' => 'composante_n',
|
||||
'INCO_COMPO.COMPOSANTE_P' => 'composante_p',
|
||||
'INCO_COMPO.POURCENT_FRUITS' => 'pourcent_fruits',
|
||||
'INCO_COMPO.SCORE_NUTRI' => 'score_nutri', //du coup nutriscore ?
|
||||
'INCO_COMPO.CLASSEMENT' => 'classement', //$nutriscore mais pas censé être dans INCO_COMPO
|
||||
'INCO_COMPO.SCORE_NUTRI' => 'score_nutri',
|
||||
// du coup nutriscore ?
|
||||
'INCO_COMPO.CLASSEMENT' => 'classement',
|
||||
// $nutriscore mais pas censé être dans INCO_COMPO
|
||||
'INCO_COMPO.MAT_GRASS_R_PREC' => 'mat_grass_r_prec',
|
||||
'INCO_COMPO.AGS_R_PREC' => 'ags_r_prec',
|
||||
'INCO_COMPO.GLUCIDES_R_PREC' => 'glucides_r_prec',
|
||||
|
|
@ -161,6 +188,11 @@ class XmlIncoReader extends XmlJobs
|
|||
'INCO_COMPO.FRUITS_COQUE_SECH_R_PREC' => 'fruits_coque_sech_r_prec',
|
||||
];
|
||||
|
||||
/**
|
||||
* Fields that are allowed to be null
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $nullableFields = [
|
||||
'taille_ref',
|
||||
'conseil_prepa',
|
||||
|
|
@ -274,8 +306,18 @@ class XmlIncoReader extends XmlJobs
|
|||
'inco_compo.fruits_coque_sech_r_prec'
|
||||
];
|
||||
|
||||
/**
|
||||
* Unique keys for updating rows
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $uniqueKeyField = ['id'];
|
||||
|
||||
/**
|
||||
* Columns to merge in
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mergeColumns = [
|
||||
'allegations' => [
|
||||
'allegat_sante',
|
||||
|
|
@ -381,15 +423,20 @@ class XmlIncoReader extends XmlJobs
|
|||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$this->parseData('INCO', XmlInco::class, function (SimpleXMLElement $xmlData, array &$line) {
|
||||
|
||||
// merge columns
|
||||
// * merge columns
|
||||
foreach ($this->mergeColumns as $key => $values) {
|
||||
$line[$key] = [];
|
||||
// merge columns and remove merged columns from line
|
||||
// * merge columns and remove merged columns from line
|
||||
array_map(function ($kValue) use (&$line, $key) {
|
||||
if (array_key_exists($kValue, $line)) {
|
||||
$line[$key][$kValue] = $line[$kValue];
|
||||
|
|
@ -400,22 +447,33 @@ class XmlIncoReader extends XmlJobs
|
|||
$line[$key] = implode(',', array_filter($line[$key]));
|
||||
$line[$key] = strlen($line[$key]) ? $line[$key] : null;
|
||||
}
|
||||
//json column cast into array in model => no need for encode
|
||||
// json column cast into array in model => no need for encode
|
||||
// if ($key == 'nutritional_values') {
|
||||
// $line[$key] = json_encode($line[$key], \JSON_FORCE_OBJECT);
|
||||
// $line[$key] = json_encode($line[$key], \JSON_FORCE_OBJECT);
|
||||
// }
|
||||
}
|
||||
|
||||
// Boolean cast prod_saison
|
||||
// * Boolean cast prod_saison
|
||||
$line['prod_saison'] = isset($line['prod_saison']) ?
|
||||
(strtolower($line['prod_saison']) == 'non' ? false : true) : false;
|
||||
(strtolower($line['prod_saison']) == 'non' ? false : true) : false;
|
||||
|
||||
$arImgPaths = $this->parseImage($xmlData);
|
||||
$line['picture'] = $arImgPaths;
|
||||
/** @var \Illuminate\Database\Eloquent\Model|null $model */
|
||||
$model = XmlInco::where($this->getUniqueValues($line))->first();
|
||||
|
||||
$line['pictures'] = $this->updateOrCreateImagesFiles(
|
||||
$this->parseImages($xmlData),
|
||||
$model
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private function parseImage(SimpleXMLElement $xmlData)
|
||||
/**
|
||||
* Parse images
|
||||
*
|
||||
* @param SimpleXMLElement $xmlData
|
||||
* @return array List of arrays [imgNamePath, imageData]
|
||||
*/
|
||||
private function parseImages(SimpleXMLElement $xmlData): array
|
||||
{
|
||||
$images = $xmlData->INCO->MEDIA_VISUEL_EAI->MEDIA_VISUEL_EAI;
|
||||
$arImgPaths = array();
|
||||
|
|
@ -423,51 +481,138 @@ class XmlIncoReader extends XmlJobs
|
|||
|
||||
foreach ($images as $image) {
|
||||
$imageData = trim((string)$image);
|
||||
if (strlen($imageData)) {
|
||||
$imageData = base64_decode($imageData);
|
||||
if (strlen($imageData) and $imageData = base64_decode($imageData)) {
|
||||
$imgName = strval($xmlData->INCO->INCO_COMPO->TBL_INCO_COMPO->ID_INCO);
|
||||
if(empty($imgName)) {
|
||||
if (empty($imgName)) {
|
||||
$imgName = strval($xmlData->INCO->NO_ART);
|
||||
}
|
||||
$imgName = $imgName."_".$index;
|
||||
$imgName = $imgName . "_" . $index;
|
||||
$imgNamePath = sprintf('%s/%s', rtrim($this->imagesPath, '/'), $imgName);
|
||||
|
||||
$disk = $this->getDisk();
|
||||
|
||||
$info = getimagesizefromstring($imageData);
|
||||
if($info !== false) {
|
||||
$mime = $info['mime'];
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
$imgExtension = 'jpg';
|
||||
break;
|
||||
case 'image/png':
|
||||
$imgExtension = 'png';
|
||||
break;
|
||||
case 'image/gif':
|
||||
$imgExtension = 'gif';
|
||||
break;
|
||||
default:
|
||||
throw new AbortXmlImportException(sprintf('Unknown image type %s', $imgName));
|
||||
}
|
||||
|
||||
$imgNamePath = sprintf('%s.%s', $imgNamePath, $imgExtension);
|
||||
|
||||
if (!$disk->put($imgNamePath, $imageData)) {
|
||||
throw new AbortXmlImportException(sprintf('The image %s could not be saved', $imgNamePath));
|
||||
}
|
||||
|
||||
$arImgPaths[$index] = sprintf('%s/%s', $this->disk, $imgNamePath);
|
||||
$index++;
|
||||
} else {
|
||||
//probably not an image could be a PDF, PPT, AI anything is possible
|
||||
if ($info === false) {
|
||||
Log::debug("Could not get file info from $imgName");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch ($info['mime'] ?? '') {
|
||||
case 'image/jpeg':
|
||||
$imgExtension = 'jpg';
|
||||
break;
|
||||
case 'image/png':
|
||||
$imgExtension = 'png';
|
||||
break;
|
||||
case 'image/gif':
|
||||
$imgExtension = 'gif';
|
||||
break;
|
||||
default:
|
||||
Log::debug("Unknown image type from $imgName");
|
||||
}
|
||||
|
||||
$imgNamePath = sprintf('%s.%s', $imgNamePath, $imgExtension);
|
||||
|
||||
$arImgPaths[$index] = compact('imgNamePath', 'imageData');
|
||||
$index++;
|
||||
} //end if
|
||||
} //end foreach
|
||||
|
||||
return $arImgPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update or create images
|
||||
*
|
||||
* @param array $images
|
||||
* @param \Illuminate\Database\Eloquent\Model|null $model
|
||||
* @return array Pictures pathes with checksums as keys that will be save into model.
|
||||
*/
|
||||
private function updateOrCreateImagesFiles(array $images, Model $model = null): array
|
||||
{
|
||||
$disk = $this->getDisk();
|
||||
|
||||
$oldChecksums = [];
|
||||
$oldPicturesPaths = [];
|
||||
|
||||
if ($model) {
|
||||
/** @var array $oldChecksums */
|
||||
$oldChecksums = \array_keys($model->pictures ?? []);
|
||||
/** @var array $oldPicturesPaths */
|
||||
$oldPicturesPaths = $model->pictures ?? [];
|
||||
}
|
||||
|
||||
/** @var array $oldPictures old pictures pathes with checksums as keys */
|
||||
$oldPictures = \array_combine($oldChecksums, $oldPicturesPaths);
|
||||
|
||||
/** @var array $newPictures new pictures pathes with checksums as keys */
|
||||
$newPictures = collect($images)->mapWithKeys(function (array $imageProps) {
|
||||
/** @var string $imgNamePath */
|
||||
/** @var string $imageData */
|
||||
extract($imageProps);
|
||||
|
||||
$imageFinalPath = sprintf('%s/%s', $this->disk, $imgNamePath);
|
||||
|
||||
// ? Sucessfully calculate checksum ?
|
||||
if (!($newFileChk = hash('crc32b', $imageFinalPath . $imageData))) {
|
||||
throw new \ErrorException('crc32b doesnt seems to be supported.');
|
||||
}
|
||||
return [$newFileChk => $imageFinalPath];
|
||||
});
|
||||
|
||||
/** @var array $modelPictures pictures that wont change */
|
||||
$modelPictures = \array_intersect_key($oldPictures, $newPictures);
|
||||
|
||||
/** @var \Illuminate\Support\Collection $removePictures pictures that we will remove (delete from disk) */
|
||||
$removePictures = collect(\array_diff_key($oldPictures, $newPictures));
|
||||
|
||||
/** @var \Illuminate\Support\Collection $addPictures pictures that we will create (save on disk) */
|
||||
$addPictures = collect(\array_diff_key($newPictures, $oldPictures));
|
||||
|
||||
// * Save or remove pictures from storage as needed
|
||||
collect($images)->mapWithKeys(function (
|
||||
array $imageProps,
|
||||
string $checksum
|
||||
) use (
|
||||
$disk,
|
||||
$removePictures,
|
||||
$addPictures
|
||||
) {
|
||||
/** @var string $imgNamePath */
|
||||
/** @var string $imageData */
|
||||
extract($imageProps);
|
||||
|
||||
if ($addPictures->has($checksum)) {
|
||||
// * Save new picture
|
||||
if (!$disk->put($imgNamePath, $imageData)) {
|
||||
throw new AbortXmlImportException(sprintf('The image %s could not be saved', $imgNamePath));
|
||||
}
|
||||
}
|
||||
|
||||
if ($removePictures->has($checksum)) {
|
||||
// * Remove old picture (if exists)
|
||||
if ($disk->exists($imgNamePath) and !$disk->delete($imgNamePath)) {
|
||||
throw new AbortXmlImportException(sprintf('The image %s could not be delete', $imgNamePath));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return $newPictures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Unique Values for a specific file
|
||||
*
|
||||
* @param array $line
|
||||
* @return array
|
||||
*/
|
||||
private function getUniqueValues(array $line): array
|
||||
{
|
||||
/** @var array Unique Key columns */
|
||||
$uniqueColumnsKey = [];
|
||||
foreach ($this->uniqueKeyField as $uField) {
|
||||
$uniqueColumnsKey[$uField] = $line[$uField];
|
||||
}
|
||||
return $uniqueColumnsKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive extract to array
|
||||
* introduce sort of Hook to transform
|
||||
|
|
@ -500,15 +645,18 @@ class XmlIncoReader extends XmlJobs
|
|||
if ($value->count()) {
|
||||
$extraction = $this->extract($value);
|
||||
|
||||
if(count($extraction)
|
||||
&& array_key_exists("code",$extraction)
|
||||
&& array_key_exists("libelle",$extraction)) {
|
||||
$val = strval($extraction['libelle']);
|
||||
if (
|
||||
count($extraction)
|
||||
&& array_key_exists("code", $extraction)
|
||||
&& array_key_exists("libelle", $extraction)
|
||||
) {
|
||||
$val = strval($extraction['libelle']);
|
||||
$extract[$key] = strlen($val) ? $val : null;
|
||||
continue;
|
||||
}
|
||||
|
||||
$extract[$key][] = $extraction; //$this->extract($value);
|
||||
$extract[$key][] = $extraction;
|
||||
// $this->extract($value);
|
||||
continue;
|
||||
}
|
||||
$value = strval($value);
|
||||
|
|
@ -517,7 +665,7 @@ class XmlIncoReader extends XmlJobs
|
|||
} else {
|
||||
$extract[$key] = strlen($value) ? $value : null;
|
||||
}
|
||||
}
|
||||
} //end foreach
|
||||
return $extract;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
namespace App\Jobs\Arcadia;
|
||||
|
||||
use App\Enums\LogType;
|
||||
use App\Exceptions\AbortXmlImportException;
|
||||
use App\Exceptions\InvalidXmlException;
|
||||
use App\Lib\Utils;
|
||||
use ErrorException;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Str;
|
||||
use RecursiveArrayIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use SimpleXMLElement;
|
||||
use Throwable;
|
||||
use TypeError;
|
||||
|
||||
abstract class XmlJobs extends XArcadiaFlux
|
||||
{
|
||||
/**
|
||||
* invalid xml folder
|
||||
* The xsd file path used to validate files
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
protected $invalidFolderName = 'invalid';
|
||||
protected $xsdSchemaPath = null;
|
||||
|
||||
/**
|
||||
* xsd file location
|
||||
* The xsd file content used to validate files
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
protected $xsdFile = '';
|
||||
protected $xsdSchema = null;
|
||||
|
||||
/**
|
||||
* The columns to take from the XML
|
||||
|
|
@ -60,80 +54,113 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
/**
|
||||
* Parse Data from the XML and gives it to the callback
|
||||
*
|
||||
* @param string $entityName
|
||||
* @param string $modelClass
|
||||
* @param string $entityName
|
||||
* @param string $modelClass
|
||||
* @param callable $afterParseCallback After parse is done.
|
||||
* @param callable $saveCallback Instead of updateOrCreate, execute $saveCallback.
|
||||
* @param callable $afterSaveCallback After save is done.
|
||||
* @return void
|
||||
* @throws InvalidXmlException If xml file is not valid.
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded
|
||||
*/
|
||||
// phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
protected function parseData(string $entityName, string $modelClass, callable $callback = null): void
|
||||
{
|
||||
protected function parseData(
|
||||
string $entityName,
|
||||
string $modelClass,
|
||||
callable $afterParseCallback = null,
|
||||
callable $saveCallback = null,
|
||||
callable $afterSaveCallback = null
|
||||
): void {
|
||||
/** @var Filesystem */
|
||||
$disk = $this->getDisk();
|
||||
$this->log('Démarrage du traitement');
|
||||
|
||||
$this->assertXsdIsHereIfAny();
|
||||
|
||||
$files = $disk->files();
|
||||
|
||||
$progress = 1;
|
||||
$total = count(array_filter($files, function ($filename) {
|
||||
$total = count(array_filter($files, function ($filename) {
|
||||
if ($this->fileHasToBeIgnored($filename)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
|
||||
$this->startProgressBar($total);
|
||||
|
||||
foreach ($files as $filename) {
|
||||
if ($this->fileHasToBeIgnored($filename)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->log(sprintf(' traitement %d sur %s ', $progress++, $total));
|
||||
$this->incrementProgressBar();
|
||||
|
||||
try {
|
||||
/** @var string $data */
|
||||
$data = $disk->get($filename);
|
||||
|
||||
$this->validateXmlFile($filename, $data);
|
||||
|
||||
try {
|
||||
$this->validateSchema($data);
|
||||
if ($this->encapsulate) {
|
||||
$data = sprintf('<Root>%s</Root>', $data);
|
||||
/** @var SimpleXMLElement|false */
|
||||
/** @var \SimpleXMLElement|false */
|
||||
$xmlContent = simplexml_load_string($data);
|
||||
} else {
|
||||
/** @var SimpleXMLElement|false */
|
||||
/** @var \SimpleXMLElement|false */
|
||||
$xmlContent = simplexml_load_string($data, null, LIBXML_NOCDATA | LIBXML_PARSEHUGE);
|
||||
}
|
||||
if ($xmlContent === false) {
|
||||
throw new InvalidXmlException('XML is Invalid (simplexml_load_string returned false)');
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
} catch (\ErrorException $e) {
|
||||
throw new InvalidXmlException('XML is Invalid', 0, $e);
|
||||
}
|
||||
|
||||
$data = $this->extract($xmlContent);
|
||||
|
||||
$data = $this->extract($xmlContent);
|
||||
$lines = [];
|
||||
foreach ($data[$entityName] as $traca) {
|
||||
$line = $this->processFields($traca);
|
||||
if ($callback) {
|
||||
$callback($xmlContent, $line);
|
||||
|
||||
// * Multiple Entities within file
|
||||
if (isset($data[$entityName])) {
|
||||
foreach ($data[$entityName] as $traca) {
|
||||
$line = $this->processFields($traca);
|
||||
if ($afterParseCallback) {
|
||||
$afterParseCallback($xmlContent, $line);
|
||||
}
|
||||
$lines[] = $line;
|
||||
}
|
||||
} else {
|
||||
// * Only one entity within file
|
||||
$line = $this->processFields($data);
|
||||
if ($afterParseCallback) {
|
||||
$afterParseCallback($xmlContent, $line);
|
||||
}
|
||||
$lines[] = $line;
|
||||
}
|
||||
|
||||
// Mise en base des données
|
||||
|
||||
// * Mise en base des données
|
||||
foreach ($lines as $line) {
|
||||
/** @var array Unique Key columns */
|
||||
$uniqueColumnsKey = [];
|
||||
foreach ($this->uniqueKeyField as $uField) {
|
||||
$uniqueColumnsKey[$uField] = $line[$uField];
|
||||
}
|
||||
forward_static_call_array(
|
||||
[$modelClass, 'updateOrCreate'],
|
||||
[$uniqueColumnsKey, $line]
|
||||
);
|
||||
}
|
||||
if (count($uniqueColumnsKey)) {
|
||||
if ($saveCallback) {
|
||||
$saveCallback($uniqueColumnsKey, $line);
|
||||
} else {
|
||||
forward_static_call_array(
|
||||
[$modelClass, 'updateOrCreate'],
|
||||
[$uniqueColumnsKey, $line]
|
||||
);
|
||||
}
|
||||
if ($afterSaveCallback) {
|
||||
$afterSaveCallback($xmlContent, $line);
|
||||
}
|
||||
}
|
||||
} //end foreach
|
||||
} catch (InvalidXmlException $e) {
|
||||
$message = $e->getMessage();
|
||||
if (get_class($e) === QueryException::class) {
|
||||
$message = implode(' ', $e->errorInfo);
|
||||
}
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be parsed => %s on line %d',
|
||||
|
|
@ -146,19 +173,6 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
$this->sendInvalidXmlEmail($filename, $e);
|
||||
$this->moveToInvalid($filename);
|
||||
continue;
|
||||
} catch (ErrorException | TypeError $e) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'CRITICAL: File %s could not be parsed => %s on line %d',
|
||||
$filename,
|
||||
$e->getMessage(),
|
||||
$e->getLine()
|
||||
),
|
||||
LogType::critical()
|
||||
);
|
||||
$this->sendErrorParseEmailToServiceWeb($e);
|
||||
continue;
|
||||
// ignore the file
|
||||
} catch (AbortXmlImportException $e) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
|
|
@ -169,15 +183,16 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
),
|
||||
LogType::error()
|
||||
);
|
||||
$this->sendErrorParseEmailToServiceWeb($e);
|
||||
report($e);
|
||||
continue;
|
||||
// ignore the file
|
||||
} catch (FileNotFoundException | QueryException $e) {
|
||||
// This happens because of concurent xml jobs read
|
||||
// * ignore the file
|
||||
} catch (QueryException $e) {
|
||||
$this->log(implode(' ', $e->errorInfo), LogType::critical());
|
||||
report($e);
|
||||
continue;
|
||||
} catch (FileNotFoundException $e) {
|
||||
// This happens because of concurent xml jobs read.
|
||||
$message = $e->getMessage();
|
||||
if (get_class($e) === QueryException::class) {
|
||||
$message = implode(' ', $e->errorInfo);
|
||||
}
|
||||
$this->log(
|
||||
sprintf(
|
||||
'ERROR: File %s could not be read (not found) => %s on line %d',
|
||||
|
|
@ -188,13 +203,31 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
LogType::debug()
|
||||
);
|
||||
continue;
|
||||
// ignore the file
|
||||
}//end try
|
||||
// * ignore the file
|
||||
} catch (\Exception | \ErrorException | \TypeError $e) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be parsed => %s on line %d',
|
||||
$filename,
|
||||
$e->getMessage(),
|
||||
$e->getLine()
|
||||
),
|
||||
LogType::critical()
|
||||
);
|
||||
report($e);
|
||||
continue;
|
||||
// * ignore the file
|
||||
} //end try
|
||||
$this->moveToArchives($filename);
|
||||
}//end foreach
|
||||
} //end foreach
|
||||
|
||||
// Clear old archives
|
||||
// Clear old invalids.
|
||||
$this->clearOldInvalids();
|
||||
|
||||
// Clear old archives.
|
||||
$this->clearOldArchives();
|
||||
|
||||
$this->endProgressBar();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -205,7 +238,7 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
*/
|
||||
protected function extract($sxe = null): array
|
||||
{
|
||||
if (!$sxe instanceof SimpleXMLElement) {
|
||||
if (!$sxe instanceof \SimpleXMLElement) {
|
||||
return array();
|
||||
}
|
||||
$extract = array();
|
||||
|
|
@ -229,7 +262,7 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
*
|
||||
* @param array $fields
|
||||
* @return array
|
||||
* @throws AbortXmlImportException
|
||||
* @throws AbortXmlImportException If a field could not be validated.
|
||||
*/
|
||||
protected function processFields(array $fields): array
|
||||
{
|
||||
|
|
@ -242,8 +275,8 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
throw new AbortXmlImportException(sprintf('The field %s is not allowed to be null', $key));
|
||||
}
|
||||
if (is_array($field)) {
|
||||
// Flatten data
|
||||
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($field));
|
||||
// * Flatten data
|
||||
$it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($field));
|
||||
foreach ($it as $k => $f) {
|
||||
$ko = strtolower(sprintf('%s.%s', $key, $k));
|
||||
if (!$this->isFieldNullable($ko) && is_null($f)) {
|
||||
|
|
@ -261,7 +294,7 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
} else {
|
||||
$result[$key] = $field;
|
||||
}
|
||||
}//end foreach
|
||||
} //end foreach
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
@ -309,23 +342,6 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
return in_array($filename, $this->ignoreFiles) or !$this->checkExtension($filename, 'xml');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate xml data against xsd file if provided
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function validateSchema($data) {
|
||||
if($this->xsdFile) {
|
||||
//check against XSD
|
||||
$xsd = storage_path($this->disk."/".$this->xsdFile);
|
||||
$domDocument= new \DOMDocument();
|
||||
$domDocument->loadXML($data);
|
||||
//free some memroy to avoid overload
|
||||
unset($data);
|
||||
$domDocument->schemaValidate($xsd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the file is an xml file
|
||||
*
|
||||
|
|
@ -341,78 +357,81 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
return $isXml;
|
||||
}
|
||||
|
||||
protected function sendErrorParseEmailToServiceWeb(Throwable $e)
|
||||
{
|
||||
Utils::sendEmailErrorManually($e);
|
||||
}
|
||||
|
||||
protected function sendInvalidXmlEmail(string $filename, Throwable $e)
|
||||
/**
|
||||
* Send invalid XML email
|
||||
*
|
||||
* @param string $filename
|
||||
* @param \Throwable $e
|
||||
* @return void
|
||||
*/
|
||||
protected function sendInvalidXmlEmail(string $filename, \Throwable $e)
|
||||
{
|
||||
$message = $e->getPrevious()->getMessage();
|
||||
Mail::send('emails.invalidxml', [
|
||||
Mail::send('mails.invalidxml', [
|
||||
'strError' => sprintf(
|
||||
'File %s could not be parsed => %s on line %d',
|
||||
$filename,
|
||||
$message,
|
||||
$e->getLine()
|
||||
),
|
||||
'appName' => config('app.name'),
|
||||
'filename' => $filename,
|
||||
'exception' => $e->getPrevious()
|
||||
], function ($m) {
|
||||
$m->to(
|
||||
config('mail.contactsList.invalidInco'),
|
||||
sprintf('%s Exception Handler', config('app.name'))
|
||||
sprintf('%s XML Exception Handler', config('app.name'))
|
||||
)->subject('You sent me an invalid XML file, please check its validity before resend ASAP.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the file to invalid folder
|
||||
* Assert XSD is readable if configured
|
||||
*
|
||||
* @param string $filename
|
||||
* @return void
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException If xsd file cant be read.
|
||||
*/
|
||||
protected function moveToInvalid(string $filename): void
|
||||
private function assertXsdIsHereIfAny()
|
||||
{
|
||||
$newFileName = $filename;
|
||||
if (!$this->getDisk()->exists($filename)) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be moved to invalid (not found)',
|
||||
$filename
|
||||
),
|
||||
LogType::warning()
|
||||
);
|
||||
return;
|
||||
}
|
||||
if ($this->getDisk()->exists(sprintf('%s/%s', $this->invalidFolderName, $filename))) {
|
||||
$ext = \pathinfo($filename, \PATHINFO_EXTENSION);
|
||||
$newFileName = \sprintf(
|
||||
'%s_%d.%s',
|
||||
\substr($filename, 0, 0 - (strlen($ext) + 1)),
|
||||
\time(),
|
||||
$ext
|
||||
);
|
||||
}
|
||||
try {
|
||||
if (!$this->getDisk()->move($filename, sprintf('%s/%s', $this->invalidFolderName, $newFileName))) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be moved to invalid',
|
||||
$filename
|
||||
),
|
||||
LogType::warning()
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->log(
|
||||
sprintf(
|
||||
'File %s could not be moved to invalid',
|
||||
$filename
|
||||
),
|
||||
LogType::warning()
|
||||
);
|
||||
if ($this->xsdSchemaPath) {
|
||||
$this->xsdSchema = File::get($this->xsdSchemaPath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Xml file against XSD if loaded
|
||||
*
|
||||
* @param string $fileName
|
||||
* @param string $fileContent
|
||||
* @return void
|
||||
* @throws InvalidXmlException If XML could not be parsed or validated against XSD.
|
||||
* @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
||||
*/
|
||||
private function validateXmlFile(string $fileName, string $fileContent)
|
||||
{
|
||||
if ($this->xsdSchema) {
|
||||
$domDocument = new \DOMDocument('1.0', 'UTF-8');
|
||||
try {
|
||||
if (!$domDocument->loadXML($fileContent)) {
|
||||
throw new InvalidXmlException("XML Validation $fileName content could not be loaded to validate.");
|
||||
}
|
||||
if (!$domDocument->schemaValidateSource($this->xsdSchema, LIBXML_SCHEMA_CREATE)) {
|
||||
throw new InvalidXmlException(
|
||||
"XML Validation $fileName content could not be validated against xsd."
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if (\get_class($e) === InvalidXmlException::class) {
|
||||
throw $e;
|
||||
}
|
||||
throw new InvalidXmlException(
|
||||
"XML Validation $fileName content could not be validated against xsd.",
|
||||
0,
|
||||
1,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
$e
|
||||
);
|
||||
} //end try
|
||||
} //end if
|
||||
}
|
||||
}
|
||||
81
app/Jobs/SetServiceStats.php
Normal file
81
app/Jobs/SetServiceStats.php
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceStat;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class SetServiceStats implements ShouldQueue
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithQueue;
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
private const KEY = '2202020';
|
||||
|
||||
/** @var \App\Models\Service */
|
||||
protected $service;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param Service $service
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Service $service)
|
||||
{
|
||||
$this->service = $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
/** @var \App\Models\ServiceStat */
|
||||
$serviceStat = ServiceStat::firstOrNew([
|
||||
'date' => date('Y-m-d'),
|
||||
'service_id' => $this->service->id,
|
||||
]);
|
||||
if (!$serviceStat->exists) {
|
||||
$serviceStat->service()->associate($this->service);
|
||||
}
|
||||
$serviceStat->nb_calls += 1;
|
||||
$serviceStat->saveOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the time at which the job should timeout.
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function retryUntil()
|
||||
{
|
||||
return now()->addMinutes(rand(0, 360));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the middleware the job should pass through.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function middleware()
|
||||
{
|
||||
return [
|
||||
(new WithoutOverlapping(self::KEY))
|
||||
->releaseAfter(rand(90, 180))
|
||||
];
|
||||
}
|
||||
}
|
||||
180
app/Lib/Helper.php
Normal file
180
app/Lib/Helper.php
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
<?php
|
||||
|
||||
namespace App\Lib;
|
||||
|
||||
use App\Exceptions\Api\ApplicationException;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Helper Class
|
||||
*/
|
||||
class Helper
|
||||
{
|
||||
/**
|
||||
* Package infos
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $packageInfos;
|
||||
|
||||
/**
|
||||
* Tells if the request is within apiV1 routes
|
||||
*
|
||||
* @param Request $request
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isRequestForApiV1(Request $request): bool
|
||||
{
|
||||
// * Small hack to ensure to know if route is From APIv1.
|
||||
$routePrefix = (strpos(static::getRoutePrefix($request), 'api/v1') ? 'v1' : null) ??
|
||||
(strpos($request->path(), 'api/v1') === 0 ? 'v1' : null) ?? 'none';
|
||||
return strpos($routePrefix, 'v1') === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get current route name
|
||||
*
|
||||
* @param Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getRouteName(Request $request)
|
||||
{
|
||||
return Route::currentRouteName() ?? ($request->route() ? $request->route()->getName() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bearer token from request
|
||||
*
|
||||
* @param Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getBearerTokenFromRequest(Request $request): ?string
|
||||
{
|
||||
$header = $request->header('Authorization', '');
|
||||
|
||||
if (Str::contains($header, 'Bearer ')) {
|
||||
$auths = \explode(',', $header);
|
||||
foreach ($auths as $auth) {
|
||||
if (Str::contains($auth, 'Bearer ')) {
|
||||
return Str::substr($auth, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get current route prefix
|
||||
*
|
||||
* @param Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getRoutePrefix(Request $request)
|
||||
{
|
||||
return (Route::getCurrentRoute() ? Route::getCurrentRoute()->getPrefix() : null) ??
|
||||
($request->route() ? $request->route()->getPrefix() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get route from request
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Routing\Route|null
|
||||
*/
|
||||
public static function getRoute(Request $request)
|
||||
{
|
||||
return Route::getRoutes()->getByName(static::getRouteName($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get composer.json infos
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getPackageInfo(): array
|
||||
{
|
||||
if (!static::$packageInfos) {
|
||||
static::$packageInfos = \json_decode(\file_get_contents(__DIR__ . '/../../composer.json'), true);
|
||||
}
|
||||
return static::$packageInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the request signature
|
||||
*
|
||||
* @param string $secret
|
||||
* @param string $uri
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return string request signature
|
||||
* @throws ApplicationException If an error occurs.
|
||||
*/
|
||||
public static function signRequest(string $secret, string $uri, string $method, array $parameters): string
|
||||
{
|
||||
try {
|
||||
$uri = collect(\parse_url($uri));
|
||||
$method = \strtolower($method);
|
||||
|
||||
// * Remove signature from parameters to calculate the hashmac.
|
||||
$signature = collect([
|
||||
'uri' => sprintf(
|
||||
'%s://%s%s',
|
||||
$uri->get('scheme'),
|
||||
$uri->get('host'),
|
||||
$uri->get('path')
|
||||
),
|
||||
'method' => $method
|
||||
]);
|
||||
|
||||
$flattenRequestArray = function (array $array) use (&$flattenRequestArray) {
|
||||
$out = [];
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$subArray = $flattenRequestArray($value);
|
||||
foreach ($subArray as $subKey => $subValue) {
|
||||
$out["$key.$subKey"] = $subValue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$out[$key] = $value;
|
||||
}
|
||||
return $out;
|
||||
};
|
||||
|
||||
$parameters = $flattenRequestArray($parameters);
|
||||
$parameters = collect($parameters);
|
||||
|
||||
// * Remove signature from parameters.
|
||||
$parameters->pull('signature');
|
||||
|
||||
// * Natural sort all parameters.
|
||||
$parameters = $parameters->sortKeys(\SORT_NATURAL)
|
||||
->map(function ($value, $key) {
|
||||
return sprintf('%s=%s', \rawurlencode($key), \rawurlencode($value));
|
||||
});
|
||||
|
||||
$signature->push($parameters->implode('&'));
|
||||
|
||||
$calculatedHash = base64_encode(hash_hmac(
|
||||
'sha256',
|
||||
$signature->implode('\n'),
|
||||
Crypt::decryptString($secret),
|
||||
true
|
||||
));
|
||||
|
||||
if (!$calculatedHash) {
|
||||
throw new ApplicationException('Failed to calculate requests hash');
|
||||
}
|
||||
|
||||
return $calculatedHash;
|
||||
} catch (DecryptException $e) {
|
||||
throw new ApplicationException('Failed to decrypt service credentials', 0, $e);
|
||||
} catch (\Exception $e) {
|
||||
throw new ApplicationException('An error occured when authenticating service', 0, $e);
|
||||
} //end try
|
||||
}
|
||||
}
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Lib;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Some utilities methods
|
||||
*
|
||||
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
|
||||
*/
|
||||
// phpcs:disable Generic.Files.LineLength.TooLong
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* Replace stange accents
|
||||
*
|
||||
* https://stackoverflow.com/questions/3371697/replacing-accented-characters-php
|
||||
* @author Jérémy Munsch <jeremy.munsch@jeremydev.ovh>
|
||||
* @param string $subject
|
||||
* @return string
|
||||
*/
|
||||
public static function replaceSpecChar(string $subject): string
|
||||
{
|
||||
$char_map = array(
|
||||
"ъ" => "-", "ь" => "-", "Ъ" => "-", "Ь" => "-",
|
||||
"А" => "A", "Ă" => "A", "Ǎ" => "A", "Ą" => "A", "À" => "A", "Ã" => "A", "Á" => "A", "Æ" => "A", "Â" => "A", "Å" => "A", "Ǻ" => "A", "Ā" => "A", "א" => "A",
|
||||
"Б" => "B", "ב" => "B", "Þ" => "B",
|
||||
"Ĉ" => "C", "Ć" => "C", "Ç" => "C", "Ц" => "C", "צ" => "C", "Ċ" => "C", "Č" => "C", "©" => "C", "ץ" => "C",
|
||||
"Д" => "D", "Ď" => "D", "Đ" => "D", "ד" => "D", "Ð" => "D",
|
||||
"È" => "E", "Ę" => "E", "É" => "E", "Ë" => "E", "Ê" => "E", "Е" => "E", "Ē" => "E", "Ė" => "E", "Ě" => "E", "Ĕ" => "E", "Є" => "E", "Ə" => "E", "ע" => "E",
|
||||
"Ф" => "F", "Ƒ" => "F",
|
||||
"Ğ" => "G", "Ġ" => "G", "Ģ" => "G", "Ĝ" => "G", "Г" => "G", "ג" => "G", "Ґ" => "G",
|
||||
"ח" => "H", "Ħ" => "H", "Х" => "H", "Ĥ" => "H", "ה" => "H",
|
||||
"I" => "I", "Ï" => "I", "Î" => "I", "Í" => "I", "Ì" => "I", "Į" => "I", "Ĭ" => "I", "I" => "I", "И" => "I", "Ĩ" => "I", "Ǐ" => "I", "י" => "I", "Ї" => "I", "Ī" => "I", "І" => "I",
|
||||
"Й" => "J", "Ĵ" => "J",
|
||||
"ĸ" => "K", "כ" => "K", "Ķ" => "K", "К" => "K", "ך" => "K",
|
||||
"Ł" => "L", "Ŀ" => "L", "Л" => "L", "Ļ" => "L", "Ĺ" => "L", "Ľ" => "L", "ל" => "L",
|
||||
"מ" => "M", "М" => "M", "ם" => "M",
|
||||
"Ñ" => "N", "Ń" => "N", "Н" => "N", "Ņ" => "N", "ן" => "N", "Ŋ" => "N", "נ" => "N", "ʼn" => "N", "Ň" => "N",
|
||||
"Ø" => "O", "Ó" => "O", "Ò" => "O", "Ô" => "O", "Õ" => "O", "О" => "O", "Ő" => "O", "Ŏ" => "O", "Ō" => "O", "Ǿ" => "O", "Ǒ" => "O", "Ơ" => "O",
|
||||
"פ" => "P", "ף" => "P", "П" => "P",
|
||||
"ק" => "Q",
|
||||
"Ŕ" => "R", "Ř" => "R", "Ŗ" => "R", "ר" => "R", "Р" => "R", "®" => "R",
|
||||
"Ş" => "S", "Ś" => "S", "Ș" => "S", "Š" => "S", "С" => "S", "Ŝ" => "S", "ס" => "S",
|
||||
"Т" => "T", "Ț" => "T", "ט" => "T", "Ŧ" => "T", "ת" => "T", "Ť" => "T", "Ţ" => "T",
|
||||
"Ù" => "U", "Û" => "U", "Ú" => "U", "Ū" => "U", "У" => "U", "Ũ" => "U", "Ư" => "U", "Ǔ" => "U", "Ų" => "U", "Ŭ" => "U", "Ů" => "U", "Ű" => "U", "Ǖ" => "U", "Ǜ" => "U", "Ǚ" => "U", "Ǘ" => "U",
|
||||
"В" => "V", "ו" => "V",
|
||||
"Ý" => "Y", "Ы" => "Y", "Ŷ" => "Y", "Ÿ" => "Y",
|
||||
"Ź" => "Z", "Ž" => "Z", "Ż" => "Z", "З" => "Z", "ז" => "Z",
|
||||
"а" => "a", "ă" => "a", "ǎ" => "a", "ą" => "a", "à" => "a", "ã" => "a", "á" => "a", "æ" => "a", "â" => "a", "å" => "a", "ǻ" => "a", "ā" => "a", "א" => "a",
|
||||
"б" => "b", "ב" => "b", "þ" => "b",
|
||||
"ĉ" => "c", "ć" => "c", "ç" => "c", "ц" => "c", "צ" => "c", "ċ" => "c", "č" => "c", "©" => "c", "ץ" => "c",
|
||||
"Ч" => "ch", "ч" => "ch",
|
||||
"д" => "d", "ď" => "d", "đ" => "d", "ד" => "d", "ð" => "d",
|
||||
"è" => "e", "ę" => "e", "é" => "e", "ë" => "e", "ê" => "e", "е" => "e", "ē" => "e", "ė" => "e", "ě" => "e", "ĕ" => "e", "є" => "e", "ə" => "e", "ע" => "e",
|
||||
"ф" => "f", "ƒ" => "f",
|
||||
"ğ" => "g", "ġ" => "g", "ģ" => "g", "ĝ" => "g", "г" => "g", "ג" => "g", "ґ" => "g",
|
||||
"ח" => "h", "ħ" => "h", "х" => "h", "ĥ" => "h", "ה" => "h",
|
||||
"i" => "i", "ï" => "i", "î" => "i", "í" => "i", "ì" => "i", "į" => "i", "ĭ" => "i", "ı" => "i", "и" => "i", "ĩ" => "i", "ǐ" => "i", "י" => "i", "ї" => "i", "ī" => "i", "і" => "i",
|
||||
"й" => "j", "Й" => "j", "Ĵ" => "j", "ĵ" => "j",
|
||||
"ĸ" => "k", "כ" => "k", "ķ" => "k", "к" => "k", "ך" => "k",
|
||||
"ł" => "l", "ŀ" => "l", "л" => "l", "ļ" => "l", "ĺ" => "l", "ľ" => "l", "ל" => "l",
|
||||
"מ" => "m", "м" => "m", "ם" => "m",
|
||||
"ñ" => "n", "ń" => "n", "н" => "n", "ņ" => "n", "ן" => "n", "ŋ" => "n", "נ" => "n", "ʼn" => "n", "ň" => "n",
|
||||
"ø" => "o", "ó" => "o", "ò" => "o", "ô" => "o", "õ" => "o", "о" => "o", "ő" => "o", "ŏ" => "o", "ō" => "o", "ǿ" => "o", "ǒ" => "o", "ơ" => "o",
|
||||
"פ" => "p", "ף" => "p", "п" => "p",
|
||||
"ק" => "q",
|
||||
"ŕ" => "r", "ř" => "r", "ŗ" => "r", "ר" => "r", "р" => "r", "®" => "r",
|
||||
"ş" => "s", "ś" => "s", "ș" => "s", "š" => "s", "с" => "s", "ŝ" => "s", "ס" => "s",
|
||||
"т" => "t", "ț" => "t", "ט" => "t", "ŧ" => "t", "ת" => "t", "ť" => "t", "ţ" => "t",
|
||||
"ù" => "u", "û" => "u", "ú" => "u", "ū" => "u", "у" => "u", "ũ" => "u", "ư" => "u", "ǔ" => "u", "ų" => "u", "ŭ" => "u", "ů" => "u", "ű" => "u", "ǖ" => "u", "ǜ" => "u", "ǚ" => "u", "ǘ" => "u",
|
||||
"в" => "v", "ו" => "v",
|
||||
"ý" => "y", "ы" => "y", "ŷ" => "y", "ÿ" => "y",
|
||||
"ź" => "z", "ž" => "z", "ż" => "z", "з" => "z", "ז" => "z", "ſ" => "z",
|
||||
"™" => "tm",
|
||||
"@" => "at",
|
||||
"Ä" => "ae", "Ǽ" => "ae", "ä" => "ae", "æ" => "ae", "ǽ" => "ae",
|
||||
"ij" => "ij", "IJ" => "ij",
|
||||
"я" => "ja", "Я" => "ja",
|
||||
"Э" => "je", "э" => "je",
|
||||
"ё" => "jo", "Ё" => "jo",
|
||||
"ю" => "ju", "Ю" => "ju",
|
||||
"œ" => "oe", "Œ" => "oe", "ö" => "oe", "Ö" => "oe",
|
||||
"щ" => "sch", "Щ" => "sch",
|
||||
"ш" => "sh", "Ш" => "sh",
|
||||
"ß" => "ss",
|
||||
"Ü" => "ue",
|
||||
"Ж" => "zh", "ж" => "zh",
|
||||
);
|
||||
return self::mbStrtr($subject, $char_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multibyte strtr
|
||||
*
|
||||
* @param string $str
|
||||
* @param string|array $from
|
||||
* @param string|null $to
|
||||
* @return string
|
||||
*/
|
||||
public static function mbStrtr($str, $from, $to = null): string
|
||||
{
|
||||
if (is_array($from)) {
|
||||
$from = array_map('utf8_decode', $from);
|
||||
$from = array_map('utf8_decode', array_flip($from));
|
||||
return utf8_encode(strtr(utf8_decode($str), array_flip($from)));
|
||||
}
|
||||
return utf8_encode(strtr(utf8_decode($str), utf8_decode($from), utf8_decode($to)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually send an exception to team instead of going trough the error handler
|
||||
* (requires package kwaadpepper/exception-handler)
|
||||
*
|
||||
* @param Throwable $e
|
||||
* @return void
|
||||
*/
|
||||
public static function sendEmailErrorManually(Throwable $e)
|
||||
{
|
||||
Mail::send([
|
||||
'html' => 'exception-handler::emails.exception',
|
||||
'text' => 'exception-handler::emails.exception-plain'
|
||||
], [
|
||||
'appName' => config('app.name'),
|
||||
'code' => $e->getCode(),
|
||||
'line' => $e->getLine(),
|
||||
'ename' => \get_class($e),
|
||||
'emessage' => self::getAnonymizedMessage($e->getMessage()),
|
||||
'file' => str_replace(\realpath(\sprintf('%s/../', \app_path())), '', $e->getFile()),
|
||||
'stackTrace' => self::getAnonymizedStackTrace($e),
|
||||
'uri' => app()->runningInConsole() ?
|
||||
'CONSOLE' : (
|
||||
(request() and request()->fullUrl()) ?
|
||||
request()->fullUrl() : 'none')
|
||||
], function ($m) {
|
||||
/** @var \Illuminate\Mail\Message $m */
|
||||
$m->to(
|
||||
config('mail.contactsList.serviceweb'),
|
||||
sprintf('%s Exception Handler', config('app.name'))
|
||||
)->subject('Need help !, an error occured in your application, please check Logs ASAP');
|
||||
});
|
||||
Log::alert(sprintf('Envoie d\'une erreur par mail : %s', json_encode($e)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymize at least Sql queries
|
||||
*
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
private static function getAnonymizedMessage(string $message): string
|
||||
{
|
||||
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymize stack trace
|
||||
*
|
||||
* @param \Exception $e
|
||||
* @return string
|
||||
*/
|
||||
private static function getAnonymizedStackTrace(Throwable $e): string
|
||||
{
|
||||
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
|
||||
$traceStack = $e->getTrace();
|
||||
$traceStr = '';
|
||||
$maxStackStage = 0;
|
||||
foreach ($traceStack as $stackStage => $stack) {
|
||||
$maxStackStage = $stackStage;
|
||||
$traceStr .= \sprintf(
|
||||
'#%s %s(%d): ',
|
||||
$stackStage,
|
||||
str_replace($projectPath, '', $stack['file']),
|
||||
$stack['line']
|
||||
);
|
||||
$traceStr .= "{$stack['class']}->{$stack['function']}(";
|
||||
$traceArgs = '';
|
||||
if (isset($stack['args'])) {
|
||||
$argsCount = count($stack['args']);
|
||||
for ($i = 0; $i < $argsCount; $i++) {
|
||||
$type = \gettype($stack['args'][$i]);
|
||||
switch ($type) {
|
||||
case 'object':
|
||||
$traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i]));
|
||||
break;
|
||||
case 'array':
|
||||
$traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i]));
|
||||
break;
|
||||
case 'string':
|
||||
$traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i]));
|
||||
break;
|
||||
default:
|
||||
$traceArgs .= \gettype($stack['args'][$i]);
|
||||
}
|
||||
$traceArgs .= ($i !== ($argsCount - 1) ? ',' : '');
|
||||
}
|
||||
$traceStr .= $traceArgs;
|
||||
}//end if
|
||||
$traceStr .= ")\n";
|
||||
}//end foreach
|
||||
$maxStackStage++;
|
||||
$traceStr .= "#$maxStackStage {main}";
|
||||
return $traceStr;
|
||||
}
|
||||
}
|
||||
90
app/Models/ArcadiaBrand.php
Normal file
90
app/Models/ArcadiaBrand.php
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Rennokki\QueryCache\Traits\QueryCacheable;
|
||||
|
||||
class ArcadiaBrand extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use QueryCacheable;
|
||||
|
||||
/**
|
||||
* The timeout cache for this model
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $cacheFor = 0;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'arcadia_id',
|
||||
'libelle'
|
||||
];
|
||||
|
||||
/**
|
||||
* ArcadiaBrand
|
||||
*
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
$this->cacheFor = config('api.arcadiaBrandsDBCache') * 60;
|
||||
|
||||
parent::__construct($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base cache tags that will be present
|
||||
* on all queries.
|
||||
*
|
||||
* ! This is used to flush caching
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getCacheBaseTags(): array
|
||||
{
|
||||
return [
|
||||
'incollector_arcadia_brands',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::created(function () {
|
||||
// * Flush Eloquent cache.
|
||||
self::flushQueryCache();
|
||||
});
|
||||
static::updated(function () {
|
||||
// * Flush Eloquent cache.
|
||||
self::flushQueryCache();
|
||||
});
|
||||
static::deleted(function () {
|
||||
// * Flush Eloquent cache.
|
||||
self::flushQueryCache();
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* Service belongsToMany relation
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\belongsToMany
|
||||
*/
|
||||
public function services()
|
||||
{
|
||||
return $this->belongsToMany(Service::class);
|
||||
}
|
||||
}
|
||||
224
app/Models/Service.php
Normal file
224
app/Models/Service.php
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Jobs\SetServiceStats;
|
||||
use App\Lib\Helper;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Str;
|
||||
use Rennokki\QueryCache\Traits\QueryCacheable;
|
||||
|
||||
class Service extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use QueryCacheable;
|
||||
|
||||
/**
|
||||
* The timeout cache for this model
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $cacheFor = 0;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name'
|
||||
];
|
||||
|
||||
/**
|
||||
* Service
|
||||
*
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
$this->cacheFor = config('api.servicesDBCache') * 60;
|
||||
|
||||
parent::__construct($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base cache tags that will be present
|
||||
* on all queries.
|
||||
*
|
||||
* ! This is used to flush caching
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getCacheBaseTags(): array
|
||||
{
|
||||
return [
|
||||
'incollector_services',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $service) {
|
||||
$service->generateBearerToken();
|
||||
$service->generateBearerPassword();
|
||||
});
|
||||
static::created(function () {
|
||||
// * Flush Eloquent cache.
|
||||
self::flushQueryCache();
|
||||
});
|
||||
static::updated(function () {
|
||||
// * Flush Eloquent cache.
|
||||
self::flushQueryCache();
|
||||
});
|
||||
static::deleted(function () {
|
||||
// * Flush Eloquent cache.
|
||||
self::flushQueryCache();
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* ArcadiaBrand belongsToMany relation
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\belongsToMany
|
||||
*/
|
||||
public function arcadiaBrands()
|
||||
{
|
||||
return $this->belongsToMany(ArcadiaBrand::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* ServiceStat hasMany relation
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function servicesStats()
|
||||
{
|
||||
return $this->hasMany(ServiceStat::class);
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Increment API CRM Stat
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function incrementStat(): void
|
||||
{
|
||||
SetServiceStats::dispatch($this)->afterResponse()
|
||||
->onConnection('database')->onQueue('stats');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates new bearer token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateBearerToken(): string
|
||||
{
|
||||
$this->bearer_token = hash('ripemd160', Str::uuid());
|
||||
$this->bearer_token_date = now();
|
||||
return $this->bearer_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates new bearer password
|
||||
* It store the crypted password in model
|
||||
* and returns the plain password
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateBearerPassword(): string
|
||||
{
|
||||
$pwd = hash('sha256', Str::uuid());
|
||||
$this->bearer_pwd = Crypt::encryptString($pwd);
|
||||
return $pwd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Service from bearerToken with its brand
|
||||
*
|
||||
* @param string $bearerToken
|
||||
* @return \App\Models\Service
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException If the token matches no known service.
|
||||
*/
|
||||
public static function getFromBearerToken(string $bearerToken): self
|
||||
{
|
||||
$services = static::all();
|
||||
/** @var \App\Models\Service $service */
|
||||
foreach ($services as $service) {
|
||||
if ($service->bearer_token and $bearerToken === $service->bearer_token) {
|
||||
return $service->load([
|
||||
'arcadiaBrands' => function ($query) use ($service) {
|
||||
return $query->cacheTags(["service:{$service->id}:arcadiaBrands"]);
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
throw new ModelNotFoundException('Could not find service from Service Token');
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the request for this service
|
||||
*
|
||||
* This will check hash-mac and that the request is wellformed
|
||||
*
|
||||
* The request should have the minimum following parameters
|
||||
* - timestamp using format Y-m-d H:i:s, and must be UTC (Greenwich Mean Time)
|
||||
* - bearerToken the public token generated by the crm
|
||||
* - signature the hashmac signature of the request
|
||||
*
|
||||
* ! Signature must be calculated with every parameter urlencode once only
|
||||
* ! All parameters to calculate the signature must be sorted (natural sort asc)
|
||||
*
|
||||
* ! Signature should look like
|
||||
* * httpVerb\n
|
||||
* * uri\n
|
||||
* * queryString
|
||||
*
|
||||
* ! httpVerb as well as uri must be lower case
|
||||
* ! uri should include scheme, host and path and nothing else, if path is empty a trailing slash should be added
|
||||
* ! eg: https://ldc-crm.fr/customer/1 or https://ldc-crm.fr/
|
||||
* ! The query string shall be separated with '&', eg param1=value1¶m2=value2
|
||||
* ! Key names and values of the query string must be url encoded using RFC 3986
|
||||
* ! http://www.faqs.org/rfcs/rfc3986.html
|
||||
* ! Signature must be hmac sha256 using the private key generatedby the crm
|
||||
*
|
||||
* * ! They should then be concat in a string separated by \n
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return boolean
|
||||
* @throws \App\Exceptions\Api\V2\CrmException If an error occurs.
|
||||
*/
|
||||
public function authenticateApi(Request $request): bool
|
||||
{
|
||||
// ! Hack to prevent Laravel to cast empty strings to null or the opposite.
|
||||
// ! If cannot decode json user legacy all() method.
|
||||
$data = \json_decode($request->getContent(), true);
|
||||
$data = (\is_array($data) and \json_last_error() === \JSON_ERROR_NONE) ?
|
||||
array_replace_recursive($request->all(), $data) : $request->all();
|
||||
|
||||
$calculatedHash = Helper::signRequest(
|
||||
$this->bearer_pwd,
|
||||
$request->getUri(),
|
||||
$request->getMethod(),
|
||||
$data
|
||||
);
|
||||
|
||||
// ! Très important hash_equals https://fr.wikipedia.org/wiki/Attaque_temporelle
|
||||
return \hash_equals($calculatedHash, $request->signature);
|
||||
}
|
||||
}
|
||||
39
app/Models/ServiceStat.php
Normal file
39
app/Models/ServiceStat.php
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ServiceStat extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = ['date'];
|
||||
|
||||
/**
|
||||
* The model's attributes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attributes = [
|
||||
'nb_calls' => 0
|
||||
];
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* Service BelongsTo relation
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function service()
|
||||
{
|
||||
return $this->belongsTo(Service::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,15 +2,17 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
use HasApiTokens;
|
||||
use HasFactory;
|
||||
use Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -41,4 +43,21 @@ class User extends Authenticatable
|
|||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $user) {
|
||||
$user->password = Hash::make($user->password);
|
||||
});
|
||||
static::updating(function (self $user) {
|
||||
if (Hash::needsRehash($user->password)) {
|
||||
$user->password = Hash::make($user->password);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,26 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Contracts\Filesystem\Filesystem;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* XmlInco
|
||||
*
|
||||
* pictures attribute is organized as following
|
||||
* [
|
||||
* 'checksum' => 'storageFilePath'
|
||||
* ]
|
||||
*
|
||||
* ! checksum includes fullfilepath + data
|
||||
*/
|
||||
class XmlInco extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'id',
|
||||
'no_art',
|
||||
|
|
@ -29,72 +40,40 @@ class XmlInco extends Model
|
|||
'lst_ing',
|
||||
'lib_allergene',
|
||||
'nutritional_values',
|
||||
'picture',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'picture' => 'array',
|
||||
'nutritional_values' => 'array',
|
||||
'pictures',
|
||||
];
|
||||
|
||||
/**
|
||||
* The Laravel disk name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $disk = 'inco';
|
||||
|
||||
protected $imagesPath = 'images';
|
||||
|
||||
/**
|
||||
* The files to ignore
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $ignoreFiles = [
|
||||
'.gitignore', '.gitkeep'
|
||||
protected $casts = [
|
||||
'pictures' => 'array',
|
||||
'nutritional_values' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* retrieve a collection of medias
|
||||
*/
|
||||
public function getMediasAttribute() {
|
||||
/** @var Filesystem */
|
||||
$disk = $this->getDisk();
|
||||
$files = $disk->files($this->imagesPath);
|
||||
|
||||
$collFiles = new Collection();
|
||||
// /** @var File */
|
||||
foreach ($files as $file) {
|
||||
$pi = \pathinfo($file, \PATHINFO_BASENAME);
|
||||
if (in_array($pi, $this->ignoreFiles)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($pi, array($this->id))) {
|
||||
continue;
|
||||
}
|
||||
$image = base64_encode($disk->get($file));
|
||||
$element = array(
|
||||
"filename" => $pi,
|
||||
"imgdata" => $image
|
||||
);
|
||||
$collFiles->add($element);
|
||||
}
|
||||
return $collFiles;
|
||||
}
|
||||
// * GETTERS
|
||||
|
||||
/**
|
||||
* Get the concerned disk
|
||||
* Get niceString attribute
|
||||
*
|
||||
* @return Filesystem
|
||||
* @return string
|
||||
*/
|
||||
protected function getDisk(): Filesystem
|
||||
{
|
||||
return Storage::disk($this->disk);
|
||||
}
|
||||
|
||||
public function getNiceStringAttribute()
|
||||
public function getNiceStringAttribute(): string
|
||||
{
|
||||
return sprintf('%s - %s', $this->id, $this->descriptif);
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* ArcadiaBrand belongsTo relation
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\belongsTo
|
||||
*/
|
||||
public function arcadiaBrand()
|
||||
{
|
||||
return $this->belongsTo(ArcadiaBrand::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
52
app/Policies/ArcadiaBrandPolicy.php
Normal file
52
app/Policies/ArcadiaBrandPolicy.php
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\ArcadiaBrand;
|
||||
use App\Models\Service;
|
||||
use App\Policies\Rules\UserStaticRules as USR;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ArcadiaBrandPolicy extends RootPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Init policies on call
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPolicies()
|
||||
{
|
||||
/**
|
||||
* This first rule to return true in a policy action authorises the action
|
||||
*/
|
||||
$this->policies = [
|
||||
'arcadia_brand' => [
|
||||
'viewAny' => USR::make('everyOne'),
|
||||
'view' => USR::make('everyOne'),
|
||||
'create' => USR::make('noOne'),
|
||||
'update' => USR::make('noOne'),
|
||||
'delete' => USR::make('noOne')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the customer belongs to the service
|
||||
*
|
||||
* @param Service $service
|
||||
* @param ArcadiaBrand $arcadiaBrand
|
||||
* @return boolean
|
||||
*/
|
||||
public function arcadiaBrandBelongsToService(Service $service, ArcadiaBrand $arcadiaBrand)
|
||||
{
|
||||
return $service->arcadiaBrands()->whereHas('services', function ($q) use ($arcadiaBrand) {
|
||||
$q->whereId($arcadiaBrand->id);
|
||||
})->exists();
|
||||
}
|
||||
}
|
||||
32
app/Policies/Rules/UserStaticRules.php
Normal file
32
app/Policies/Rules/UserStaticRules.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Policies\Rules;
|
||||
|
||||
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
|
||||
|
||||
/**
|
||||
* Userlevel Policiy Static Rules
|
||||
* ! Rules has to return boolean value
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class UserStaticRules extends StaticRules
|
||||
{
|
||||
/**
|
||||
* Allow everyone
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function everyOne(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Allow no one
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function noOne(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,14 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
|
|
@ -13,7 +21,6 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -23,6 +30,54 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
// ! Important pourra etre retiré quand la V1 sera supprimé
|
||||
// Empeche l'encapsulation dans data .
|
||||
JsonResource::withoutWrapping();
|
||||
|
||||
// * LOCAL HTTPS FIX.
|
||||
if (!in_array(config('app.env'), ['local', 'testing'])) {
|
||||
URL::forceScheme('https');
|
||||
}
|
||||
|
||||
// * HA PROXY FIX.
|
||||
App::singleton('clientIp', function () {
|
||||
if (
|
||||
config('app.env') === 'local'
|
||||
) {
|
||||
return request()->getClientIp();
|
||||
} else {
|
||||
return request()->server('HTTP_X_FORWARDED_FOR') ??
|
||||
request()->getClientIp();
|
||||
}
|
||||
});
|
||||
|
||||
// * LOCAL FORCE eg: for Carbon
|
||||
// * Remove numeric to prevent float seperator to breaking numeric transactions
|
||||
\collect([\LC_TIME, \LC_MESSAGES, \LC_COLLATE, \LC_CTYPE, \LC_MONETARY])
|
||||
->map(function ($contant) {
|
||||
setlocale(
|
||||
$contant,
|
||||
\sprintf(
|
||||
'%s_%s.UTF-8',
|
||||
config('app.locale'),
|
||||
\strtoupper(config('app.locale'))
|
||||
)
|
||||
);
|
||||
});
|
||||
Carbon::setLocale(config('app.locale'));
|
||||
|
||||
// * Force bootstrap paginator
|
||||
Paginator::useBootstrap();
|
||||
|
||||
$appInfos = Cache::remember(
|
||||
'composer',
|
||||
360,
|
||||
function () {
|
||||
return json_decode(File::get(\app_path('../composer.json')));
|
||||
}
|
||||
);
|
||||
View::share('name', $appInfos->name);
|
||||
View::share('version', $appInfos->version);
|
||||
View::share('license', $appInfos->license);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Lib\Helper;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -12,9 +16,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $policies = [
|
||||
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
||||
];
|
||||
protected $policies = [];
|
||||
|
||||
/**
|
||||
* Register any authentication / authorization services.
|
||||
|
|
@ -25,6 +27,50 @@ class AuthServiceProvider extends ServiceProvider
|
|||
{
|
||||
$this->registerPolicies();
|
||||
|
||||
//
|
||||
Auth::viaRequest('api-hmac', function (Request $request) {
|
||||
|
||||
/**
|
||||
* Un token devrais être fourni pour chaque requete
|
||||
*/
|
||||
if (is_null($request->bearer_token)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// * Si la route actuelle n'as pas de nom alors on refuse de la traiter.
|
||||
if (!(Helper::getRoute($request))) {
|
||||
// @codeCoverageIgnoreStart
|
||||
return null;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
$service = null;
|
||||
|
||||
try {
|
||||
// * On récupère le service actuel correspondant au token fourni.
|
||||
$service = Service::getFromBearerToken($request->bearer_token ?? '');
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// * Preload the arcadiaBrands as we will access it often later.
|
||||
$service = $service->load('arcadiaBrands');
|
||||
|
||||
/**
|
||||
** All Api routes must pass ArcadiaBrand model to controller action since a ArcadiaBrand owns
|
||||
** a service token, otherwise the api cannot be called.
|
||||
** This hack is a custom binder instead of passing
|
||||
** this to route as a parameter
|
||||
*/
|
||||
app()->bind(Service::class, function () use ($service) {
|
||||
return $service;
|
||||
});
|
||||
|
||||
// * On authenticate la request en vérifiant sa signature.
|
||||
if ($service->authenticateApi($request)) {
|
||||
return $service;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ namespace App\Providers;
|
|||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -27,6 +26,5 @@ class EventServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,6 @@ class RouteServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public const HOME = '/home';
|
||||
|
||||
/**
|
||||
* The controller namespace for the application.
|
||||
*
|
||||
* When present, controller route declarations will automatically be prefixed with this namespace.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
// protected $namespace = 'App\\Http\\Controllers';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, etc.
|
||||
*
|
||||
|
|
@ -56,8 +47,16 @@ class RouteServiceProvider extends ServiceProvider
|
|||
*/
|
||||
protected function configureRateLimiting()
|
||||
{
|
||||
RateLimiter::for('web', function (Request $request) {
|
||||
// @codeCoverageIgnoreStart
|
||||
return Limit::perMinute(25)
|
||||
->by(optional($request->user())->id ?: app('clientIp'));
|
||||
// @codeCoverageIgnoreEnd
|
||||
});
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
|
||||
return Limit::perMinute(config('api.apiRequestRatePerMinute', 100))
|
||||
->by(app('clientIp'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,31 @@
|
|||
{
|
||||
"name": "laravel/laravel",
|
||||
"name": "ldc/incollector",
|
||||
"type": "project",
|
||||
"description": "The Laravel Framework.",
|
||||
"keywords": ["framework", "laravel"],
|
||||
"version": "1.0.0",
|
||||
"description": "LDC Incollector - A workaround of Arcadia",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Olivier Legat",
|
||||
"email": "olivier.legat@ldc.fr"
|
||||
},
|
||||
{
|
||||
"name": "Jérémy Munsch",
|
||||
"email": "jeremy.munsch@ldc.fr",
|
||||
"homepage": "https://jeremydev.ovh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"kwaadpepper/crud-policies": "^0.3.5",
|
||||
"kwaadpepper/enum": "^2.1",
|
||||
"kwaadpepper/exception-handler": "^0.0.5",
|
||||
"laravel/framework": "^8.65",
|
||||
"laravel/sanctum": "^2.11",
|
||||
"laravel/tinker": "^2.5",
|
||||
"squizlabs/php_codesniffer": "^3.6"
|
||||
"rennokki/laravel-eloquent-query-cache": "^3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"facade/ignition": "^2.5",
|
||||
|
|
@ -21,7 +33,9 @@
|
|||
"laravel/sail": "^1.0.1",
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"nunomaduro/collision": "^5.10",
|
||||
"phpunit/phpunit": "^9.5.10"
|
||||
"phpunit/phpunit": "^9.5.10",
|
||||
"slevomat/coding-standard": "^7.1",
|
||||
"squizlabs/php_codesniffer": "^3.6"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -36,6 +50,16 @@
|
|||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": [
|
||||
"@configclear",
|
||||
"./test.sh"
|
||||
],
|
||||
"configclear": "@php artisan config:clear",
|
||||
"runtestmigration": "@php artisan migrate:fresh --env=testing --seed",
|
||||
"runtest": "@php artisan test --no-coverage --testsuite Api",
|
||||
"runtestWithCoverage": "@php artisan test --testsuite Api",
|
||||
"runserve": "@php artisan serve --host=127.0.0.1 --port=8888 --env=testing&",
|
||||
"killserve": "kill $(ps -f | grep '[1]27.0.0.1:8888' | awk '{print $2}')",
|
||||
"post-autoload-dump": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||
"@php artisan package:discover --ansi"
|
||||
|
|
@ -58,7 +82,10 @@
|
|||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
|
|
|
|||
1140
composer.lock
generated
1140
composer.lock
generated
File diff suppressed because it is too large
Load diff
30
config/api.php
Normal file
30
config/api.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use App\Lib\Helper;
|
||||
|
||||
return [
|
||||
/**
|
||||
* Api versions
|
||||
** this value is sent in response
|
||||
*/
|
||||
'version' => Helper::getPackageInfo()['version'],
|
||||
|
||||
/**
|
||||
* Timestamp timeout in seconds
|
||||
* Request with timestamp older than 30sec
|
||||
* will be rejected
|
||||
*/
|
||||
'timestampTimeout' => 30,
|
||||
|
||||
/**
|
||||
* The number of request
|
||||
* per user or ip per minutes
|
||||
*/
|
||||
'apiRequestRatePerMinute' => 256,
|
||||
|
||||
/**
|
||||
* Service requests cache
|
||||
* time in minutes
|
||||
*/
|
||||
'servicesDBCache' => 10
|
||||
];
|
||||
188
config/app.php
188
config/app.php
|
|
@ -3,53 +3,53 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value is the name of your application. This value is used when the
|
||||
| framework needs to place the application's name in a notification or
|
||||
| any other location as required by the application or its packages.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value is the name of your application. This value is used when the
|
||||
| framework needs to place the application's name in a notification or
|
||||
| any other location as required by the application or its packages.
|
||||
|
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Laravel'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Environment
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the "environment" your application is currently
|
||||
| running in. This may determine how you prefer to configure various
|
||||
| services the application utilizes. Set this in your ".env" file.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Environment
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the "environment" your application is currently
|
||||
| running in. This may determine how you prefer to configure various
|
||||
| services the application utilizes. Set this in your ".env" file.
|
||||
|
|
||||
*/
|
||||
|
||||
'env' => env('APP_ENV', 'production'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Debug Mode
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When your application is in debug mode, detailed error messages with
|
||||
| stack traces will be shown on every error that occurs within your
|
||||
| application. If disabled, a simple generic error page is shown.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Debug Mode
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When your application is in debug mode, detailed error messages with
|
||||
| stack traces will be shown on every error that occurs within your
|
||||
| application. If disabled, a simple generic error page is shown.
|
||||
|
|
||||
*/
|
||||
|
||||
'debug' => (bool) env('APP_DEBUG', false),
|
||||
'debug' => (bool)env('APP_DEBUG', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This URL is used by the console to properly generate URLs when using
|
||||
| the Artisan command line tool. You should set this to the root of
|
||||
| your application so that it is used when running Artisan tasks.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Application URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This URL is used by the console to properly generate URLs when using
|
||||
| the Artisan command line tool. You should set this to the root of
|
||||
| your application so that it is used when running Artisan tasks.
|
||||
|
|
||||
*/
|
||||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
|
@ -57,66 +57,66 @@ return [
|
|||
'asset_url' => env('ASSET_URL', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default timezone for your application, which
|
||||
| will be used by the PHP date and date-time functions. We have gone
|
||||
| ahead and set this to a sensible default for you out of the box.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default timezone for your application, which
|
||||
| will be used by the PHP date and date-time functions. We have gone
|
||||
| ahead and set this to a sensible default for you out of the box.
|
||||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'UTC',
|
||||
'timezone' => 'Europe/Paris',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Locale Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The application locale determines the default locale that will be used
|
||||
| by the translation service provider. You are free to set this value
|
||||
| to any of the locales which will be supported by the application.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Locale Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The application locale determines the default locale that will be used
|
||||
| by the translation service provider. You are free to set this value
|
||||
| to any of the locales which will be supported by the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'locale' => 'en',
|
||||
'locale' => 'fr',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Fallback Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The fallback locale determines the locale to use when the current one
|
||||
| is not available. You may change the value to correspond to any of
|
||||
| the language folders that are provided through your application.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Fallback Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The fallback locale determines the locale to use when the current one
|
||||
| is not available. You may change the value to correspond to any of
|
||||
| the language folders that are provided through your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'fallback_locale' => 'en',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Faker Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This locale will be used by the Faker PHP library when generating fake
|
||||
| data for your database seeds. For example, this will be used to get
|
||||
| localized telephone numbers, street address information and more.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Faker Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This locale will be used by the Faker PHP library when generating fake
|
||||
| data for your database seeds. For example, this will be used to get
|
||||
| localized telephone numbers, street address information and more.
|
||||
|
|
||||
*/
|
||||
|
||||
'faker_locale' => 'en_US',
|
||||
'faker_locale' => 'fr_FR',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This key is used by the Illuminate encrypter service and should be set
|
||||
| to a random, 32 character string, otherwise these encrypted strings
|
||||
| will not be safe. Please do this before deploying an application!
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This key is used by the Illuminate encrypter service and should be set
|
||||
| to a random, 32 character string, otherwise these encrypted strings
|
||||
| will not be safe. Please do this before deploying an application!
|
||||
|
|
||||
*/
|
||||
|
||||
'key' => env('APP_KEY'),
|
||||
|
|
@ -124,14 +124,14 @@ return [
|
|||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Autoloaded Service Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The service providers listed here will be automatically loaded on the
|
||||
| request to your application. Feel free to add your own services to
|
||||
| this array to grant expanded functionality to your applications.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Autoloaded Service Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The service providers listed here will be automatically loaded on the
|
||||
| request to your application. Feel free to add your own services to
|
||||
| this array to grant expanded functionality to your applications.
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
|
|
@ -139,6 +139,7 @@ return [
|
|||
/*
|
||||
* Laravel Framework Service Providers...
|
||||
*/
|
||||
|
||||
Illuminate\Auth\AuthServiceProvider::class,
|
||||
Illuminate\Broadcasting\BroadcastServiceProvider::class,
|
||||
Illuminate\Bus\BusServiceProvider::class,
|
||||
|
|
@ -169,23 +170,23 @@ return [
|
|||
/*
|
||||
* Application Service Providers...
|
||||
*/
|
||||
|
||||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\AuthServiceProvider::class,
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Class Aliases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array of class aliases will be registered when this application
|
||||
| is started. However, feel free to register as many as you wish as
|
||||
| the aliases are "lazy" loaded so they don't hinder performance.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Class Aliases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array of class aliases will be registered when this application
|
||||
| is started. However, feel free to register as many as you wish as
|
||||
| the aliases are "lazy" loaded so they don't hinder performance.
|
||||
|
|
||||
*/
|
||||
|
||||
'aliases' => [
|
||||
|
|
@ -218,7 +219,6 @@ return [
|
|||
'Queue' => Illuminate\Support\Facades\Queue::class,
|
||||
'RateLimiter' => Illuminate\Support\Facades\RateLimiter::class,
|
||||
'Redirect' => Illuminate\Support\Facades\Redirect::class,
|
||||
// 'Redis' => Illuminate\Support\Facades\Redis::class,
|
||||
'Request' => Illuminate\Support\Facades\Request::class,
|
||||
'Response' => Illuminate\Support\Facades\Response::class,
|
||||
'Route' => Illuminate\Support\Facades\Route::class,
|
||||
|
|
|
|||
122
config/auth.php
122
config/auth.php
|
|
@ -3,14 +3,14 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Defaults
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default authentication "guard" and password
|
||||
| reset options for your application. You may change these defaults
|
||||
| as required, but they're a perfect start for most applications.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Defaults
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default authentication "guard" and password
|
||||
| reset options for your application. You may change these defaults
|
||||
| as required, but they're a perfect start for most applications.
|
||||
|
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
|
|
@ -19,20 +19,20 @@ return [
|
|||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, you may define every authentication guard for your application.
|
||||
| Of course, a great default configuration has been defined for you
|
||||
| here which uses session storage and the Eloquent user provider.
|
||||
|
|
||||
| All authentication drivers have a user provider. This defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| mechanisms used by this application to persist your user's data.
|
||||
|
|
||||
| Supported: "session"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, you may define every authentication guard for your application.
|
||||
| Of course, a great default configuration has been defined for you
|
||||
| here which uses session storage and the Eloquent user provider.
|
||||
|
|
||||
| All authentication drivers have a user provider. This defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| mechanisms used by this application to persist your user's data.
|
||||
|
|
||||
| Supported: "session"
|
||||
|
|
||||
*/
|
||||
|
||||
'guards' => [
|
||||
|
|
@ -40,50 +40,48 @@ return [
|
|||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
'api' => [
|
||||
'driver' => 'api-hmac'
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| User Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| All authentication drivers have a user provider. This defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| mechanisms used by this application to persist your user's data.
|
||||
|
|
||||
| If you have multiple user tables or models you may configure multiple
|
||||
| sources which represent each model / table. These sources may then
|
||||
| be assigned to any extra authentication guards you have defined.
|
||||
|
|
||||
| Supported: "database", "eloquent"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| User Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| All authentication drivers have a user provider. This defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| mechanisms used by this application to persist your user's data.
|
||||
|
|
||||
| If you have multiple user tables or models you may configure multiple
|
||||
| sources which represent each model / table. These sources may then
|
||||
| be assigned to any extra authentication guards you have defined.
|
||||
|
|
||||
| Supported: "database", "eloquent"
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
'users' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => App\Models\User::class,
|
||||
],
|
||||
|
||||
// 'users' => [
|
||||
// 'driver' => 'database',
|
||||
// 'table' => 'users',
|
||||
// ],
|
||||
]
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Resetting Passwords
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may specify multiple password reset configurations if you have more
|
||||
| than one user table or model in the application and you want to have
|
||||
| separate password reset settings based on the specific user types.
|
||||
|
|
||||
| The expire time is the number of minutes that the reset token should be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Resetting Passwords
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may specify multiple password reset configurations if you have more
|
||||
| than one user table or model in the application and you want to have
|
||||
| separate password reset settings based on the specific user types.
|
||||
|
|
||||
| The expire time is the number of minutes that the reset token should be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'passwords' => [
|
||||
|
|
@ -96,14 +94,14 @@ return [
|
|||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Confirmation Timeout
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define the amount of seconds before a password confirmation
|
||||
| times out and the user is prompted to re-enter their password via the
|
||||
| confirmation screen. By default, the timeout lasts for three hours.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Confirmation Timeout
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define the amount of seconds before a password confirmation
|
||||
| times out and the user is prompted to re-enter their password via the
|
||||
| confirmation screen. By default, the timeout lasts for three hours.
|
||||
|
|
||||
*/
|
||||
|
||||
'password_timeout' => 10800,
|
||||
|
|
|
|||
|
|
@ -3,29 +3,29 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Broadcaster
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default broadcaster that will be used by the
|
||||
| framework when an event needs to be broadcast. You may set this to
|
||||
| any of the connections defined in the "connections" array below.
|
||||
|
|
||||
| Supported: "pusher", "ably", "redis", "log", "null"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Broadcaster
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default broadcaster that will be used by the
|
||||
| framework when an event needs to be broadcast. You may set this to
|
||||
| any of the connections defined in the "connections" array below.
|
||||
|
|
||||
| Supported: "pusher", "ably", "redis", "log", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('BROADCAST_DRIVER', 'null'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Broadcast Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the broadcast connections that will be used
|
||||
| to broadcast events to other systems or over websockets. Samples of
|
||||
| each available type of connection are provided inside this array.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Broadcast Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the broadcast connections that will be used
|
||||
| to broadcast events to other systems or over websockets. Samples of
|
||||
| each available type of connection are provided inside this array.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
|
|
|||
|
|
@ -5,30 +5,30 @@ use Illuminate\Support\Str;
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache connection that gets used while
|
||||
| using this caching library. This connection is used when another is
|
||||
| not explicitly specified when executing a given caching function.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache connection that gets used while
|
||||
| using this caching library. This connection is used when another is
|
||||
| not explicitly specified when executing a given caching function.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('CACHE_DRIVER', 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Stores
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the cache "stores" for your application as
|
||||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
| Supported drivers: "apc", "array", "database", "file",
|
||||
| "memcached", "redis", "dynamodb", "octane", "null"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Stores
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the cache "stores" for your application as
|
||||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
| Supported drivers: "apc", "array", "database", "file",
|
||||
| "memcached", "redis", "dynamodb", "octane", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'stores' => [
|
||||
|
|
@ -95,16 +95,16 @@ return [
|
|||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing a RAM based store such as APC or Memcached, there might
|
||||
| be other applications utilizing the same cache. So, we'll specify a
|
||||
| value to get prefixed to all our keys so we can avoid collisions.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing a RAM based store such as APC or Memcached, there might
|
||||
| be other applications utilizing the same cache. So, we'll specify a
|
||||
| value to get prefixed to all our keys so we can avoid collisions.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache'),
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure your settings for cross-origin resource sharing
|
||||
| or "CORS". This determines what cross-origin operations may execute
|
||||
| in web browsers. You are free to adjust these settings as needed.
|
||||
|
|
||||
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure your settings for cross-origin resource sharing
|
||||
| or "CORS". This determines what cross-origin operations may execute
|
||||
| in web browsers. You are free to adjust these settings as needed.
|
||||
|
|
||||
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
|
|
||||
*/
|
||||
|
||||
'paths' => ['api/*', 'sanctum/csrf-cookie'],
|
||||
|
|
|
|||
|
|
@ -5,32 +5,32 @@ use Illuminate\Support\Str;
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which of the database connections below you wish
|
||||
| to use as your default connection for all database work. Of course
|
||||
| you may use many connections at once using the Database library.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which of the database connections below you wish
|
||||
| to use as your default connection for all database work. Of course
|
||||
| you may use many connections at once using the Database library.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('DB_CONNECTION', 'mysql'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here are each of the database connections setup for your application.
|
||||
| Of course, examples of configuring each database platform that is
|
||||
| supported by Laravel is shown below to make development simple.
|
||||
|
|
||||
|
|
||||
| All database work in Laravel is done through the PHP PDO facilities
|
||||
| so make sure you have the driver for your particular database of
|
||||
| choice installed on your machine before you begin development.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here are each of the database connections setup for your application.
|
||||
| Of course, examples of configuring each database platform that is
|
||||
| supported by Laravel is shown below to make development simple.
|
||||
|
|
||||
|
|
||||
| All database work in Laravel is done through the PHP PDO facilities
|
||||
| so make sure you have the driver for your particular database of
|
||||
| choice installed on your machine before you begin development.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
|
@ -94,27 +94,27 @@ return [
|
|||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Migration Repository Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This table keeps track of all the migrations that have already run for
|
||||
| your application. Using this information, we can determine which of
|
||||
| the migrations on disk haven't actually been run in the database.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Migration Repository Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This table keeps track of all the migrations that have already run for
|
||||
| your application. Using this information, we can determine which of
|
||||
| the migrations on disk haven't actually been run in the database.
|
||||
|
|
||||
*/
|
||||
|
||||
'migrations' => 'migrations',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis Databases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Redis is an open source, fast, and advanced key-value store that also
|
||||
| provides a richer body of commands than a typical key-value system
|
||||
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis Databases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Redis is an open source, fast, and advanced key-value store that also
|
||||
| provides a richer body of commands than a typical key-value system
|
||||
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
||||
|
|
||||
*/
|
||||
|
||||
'redis' => [
|
||||
|
|
@ -123,7 +123,7 @@ return [
|
|||
|
||||
'options' => [
|
||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'),
|
||||
],
|
||||
|
||||
'default' => [
|
||||
|
|
|
|||
|
|
@ -11,5 +11,7 @@ return [
|
|||
* Put a developper secured mailbox in here
|
||||
* so you can receive email if things go mad
|
||||
*/
|
||||
'contactsList' => []
|
||||
'contactsList' => [
|
||||
env('MAIL_LIST_SERVICEWEB', 'equipe.web@ldc.fr')
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -3,29 +3,29 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. The "local" disk, as well as a variety of cloud
|
||||
| based disks are available to your application. Just store away!
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. The "local" disk, as well as a variety of cloud
|
||||
| based disks are available to your application. Just store away!
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('FILESYSTEM_DRIVER', 'local'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure as many filesystem "disks" as you wish, and you
|
||||
| may even configure multiple disks of the same driver. Defaults have
|
||||
| been setup for each driver as an example of the required options.
|
||||
|
|
||||
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure as many filesystem "disks" as you wish, and you
|
||||
| may even configure multiple disks of the same driver. Defaults have
|
||||
| been setup for each driver as an example of the required options.
|
||||
|
|
||||
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
||||
|
|
||||
*/
|
||||
|
||||
'disks' => [
|
||||
|
|
@ -38,7 +38,7 @@ return [
|
|||
'public' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/public'),
|
||||
'url' => env('APP_URL').'/storage',
|
||||
'url' => env('APP_URL') . '/storage',
|
||||
'visibility' => 'public',
|
||||
],
|
||||
|
||||
|
|
@ -57,17 +57,21 @@ return [
|
|||
'driver' => 'local',
|
||||
'root' => storage_path('inco'),
|
||||
],
|
||||
'arcadia_brand' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('marque'),
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Symbolic Links
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the symbolic links that will be created when the
|
||||
| `storage:link` Artisan command is executed. The array keys should be
|
||||
| the locations of the links and the values should be their targets.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Symbolic Links
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the symbolic links that will be created when the
|
||||
| `storage:link` Artisan command is executed. The array keys should be
|
||||
| the locations of the links and the values should be their targets.
|
||||
|
|
||||
*/
|
||||
|
||||
'links' => [
|
||||
|
|
|
|||
|
|
@ -3,29 +3,29 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Hash Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default hash driver that will be used to hash
|
||||
| passwords for your application. By default, the bcrypt algorithm is
|
||||
| used; however, you remain free to modify this option if you wish.
|
||||
|
|
||||
| Supported: "bcrypt", "argon", "argon2id"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Hash Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default hash driver that will be used to hash
|
||||
| passwords for your application. By default, the bcrypt algorithm is
|
||||
| used; however, you remain free to modify this option if you wish.
|
||||
|
|
||||
| Supported: "bcrypt", "argon", "argon2id"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => 'bcrypt',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bcrypt Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Bcrypt algorithm. This will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Bcrypt Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Bcrypt algorithm. This will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
*/
|
||||
|
||||
'bcrypt' => [
|
||||
|
|
@ -33,14 +33,14 @@ return [
|
|||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Argon Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Argon algorithm. These will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Argon Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Argon algorithm. These will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
*/
|
||||
|
||||
'argon' => [
|
||||
|
|
|
|||
5
config/ldcweb.php
Normal file
5
config/ldcweb.php
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'project_uuid' => env('PROJECT_UUID')
|
||||
];
|
||||
|
|
@ -7,44 +7,44 @@ use Monolog\Handler\SyslogUdpHandler;
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default log channel that gets used when writing
|
||||
| messages to the logs. The name specified in this option should match
|
||||
| one of the channels defined in the "channels" configuration array.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default log channel that gets used when writing
|
||||
| messages to the logs. The name specified in this option should match
|
||||
| one of the channels defined in the "channels" configuration array.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('LOG_CHANNEL', 'stack'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Deprecations Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the log channel that should be used to log warnings
|
||||
| regarding deprecated PHP and library features. This allows you to get
|
||||
| your application ready for upcoming major versions of dependencies.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Deprecations Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the log channel that should be used to log warnings
|
||||
| regarding deprecated PHP and library features. This allows you to get
|
||||
| your application ready for upcoming major versions of dependencies.
|
||||
|
|
||||
*/
|
||||
|
||||
'deprecations' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Channels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log channels for your application. Out of
|
||||
| the box, Laravel uses the Monolog PHP logging library. This gives
|
||||
| you a variety of powerful log handlers / formatters to utilize.
|
||||
|
|
||||
| Available Drivers: "single", "daily", "slack", "syslog",
|
||||
| "errorlog", "monolog",
|
||||
| "custom", "stack"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Channels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log channels for your application. Out of
|
||||
| the box, Laravel uses the Monolog PHP logging library. This gives
|
||||
| you a variety of powerful log handlers / formatters to utilize.
|
||||
|
|
||||
| Available Drivers: "single", "daily", "slack", "syslog",
|
||||
| "errorlog", "monolog",
|
||||
| "custom", "stack"
|
||||
|
|
||||
*/
|
||||
|
||||
'channels' => [
|
||||
|
|
|
|||
|
|
@ -3,34 +3,34 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Mailer
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default mailer that is used to send any email
|
||||
| messages sent by your application. Alternative mailers may be setup
|
||||
| and used as needed; however, this mailer will be used by default.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Mailer
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default mailer that is used to send any email
|
||||
| messages sent by your application. Alternative mailers may be setup
|
||||
| and used as needed; however, this mailer will be used by default.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('MAIL_MAILER', 'smtp'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mailer Configurations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure all of the mailers used by your application plus
|
||||
| their respective settings. Several examples have been configured for
|
||||
| you and you are free to add your own as your application requires.
|
||||
|
|
||||
| Laravel supports a variety of mail "transport" drivers to be used while
|
||||
| sending an e-mail. You will specify which one you are using for your
|
||||
| mailers below. You are free to add additional mailers as required.
|
||||
|
|
||||
| Supported: "smtp", "sendmail", "mailgun", "ses",
|
||||
| "postmark", "log", "array", "failover"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Mailer Configurations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure all of the mailers used by your application plus
|
||||
| their respective settings. Several examples have been configured for
|
||||
| you and you are free to add your own as your application requires.
|
||||
|
|
||||
| Laravel supports a variety of mail "transport" drivers to be used while
|
||||
| sending an e-mail. You will specify which one you are using for your
|
||||
| mailers below. You are free to add additional mailers as required.
|
||||
|
|
||||
| Supported: "smtp", "sendmail", "mailgun", "ses",
|
||||
| "postmark", "log", "array", "failover"
|
||||
|
|
||||
*/
|
||||
|
||||
'mailers' => [
|
||||
|
|
@ -81,14 +81,14 @@ return [
|
|||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global "From" Address
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may wish for all e-mails sent by your application to be sent from
|
||||
| the same address. Here, you may specify a name and address that is
|
||||
| used globally for all e-mails that are sent by your application.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Global "From" Address
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may wish for all e-mails sent by your application to be sent from
|
||||
| the same address. Here, you may specify a name and address that is
|
||||
| used globally for all e-mails that are sent by your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'from' => [
|
||||
|
|
@ -97,19 +97,20 @@ return [
|
|||
],
|
||||
|
||||
'contactsList' => [
|
||||
'serviceweb' => explode(",", env('MAIL_LIST_SERVICEWEB', 'equipe.web@ldc.fr')),
|
||||
'invalidInco' => explode(",", env('MAIL_LIST_INVALIDINCO', 'equipe.web@ldc.fr')),
|
||||
'serviceweb' => explode(',', env('MAIL_LIST_SERVICEWEB', 'equipe.web@ldc.fr')),
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'invalidInco' => explode(',', env('MAIL_LIST_INVALIDINCO', 'equipe.web@ldc.fr,vincent.pierre@ldc.fr,christelle.manceau@ldc.fr')),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Markdown Mail Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you are using Markdown based email rendering, you may configure your
|
||||
| theme and component paths here, allowing you to customize the design
|
||||
| of the emails. Or, you may simply stick with the Laravel defaults!
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Markdown Mail Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you are using Markdown based email rendering, you may configure your
|
||||
| theme and component paths here, allowing you to customize the design
|
||||
| of the emails. Or, you may simply stick with the Laravel defaults!
|
||||
|
|
||||
*/
|
||||
|
||||
'markdown' => [
|
||||
|
|
|
|||
|
|
@ -3,29 +3,29 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Queue Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Laravel's queue API supports an assortment of back-ends via a single
|
||||
| API, giving you convenient access to each back-end using the same
|
||||
| syntax for every one. Here you may define a default connection.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Queue Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Laravel's queue API supports an assortment of back-ends via a single
|
||||
| API, giving you convenient access to each back-end using the same
|
||||
| syntax for every one. Here you may define a default connection.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('QUEUE_CONNECTION', 'sync'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the connection information for each server that
|
||||
| is used by your application. A default configuration has been added
|
||||
| for each back-end shipped with Laravel. You are free to add more.
|
||||
|
|
||||
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the connection information for each server that
|
||||
| is used by your application. A default configuration has been added
|
||||
| for each back-end shipped with Laravel. You are free to add more.
|
||||
|
|
||||
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
|
@ -74,14 +74,14 @@ return [
|
|||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Failed Queue Jobs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These options configure the behavior of failed queue job logging so you
|
||||
| can control which database and table are used to store the jobs that
|
||||
| have failed. You may change them to any database / table you wish.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Failed Queue Jobs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These options configure the behavior of failed queue job logging so you
|
||||
| can control which database and table are used to store the jobs that
|
||||
| have failed. You may change them to any database / table you wish.
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => [
|
||||
|
|
|
|||
|
|
@ -3,58 +3,58 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stateful Domains
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Requests from the following domains / hosts will receive stateful API
|
||||
| authentication cookies. Typically, these should include your local
|
||||
| and production domains which access your API via a frontend SPA.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Stateful Domains
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Requests from the following domains / hosts will receive stateful API
|
||||
| authentication cookies. Typically, these should include your local
|
||||
| and production domains which access your API via a frontend SPA.
|
||||
|
|
||||
*/
|
||||
|
||||
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
|
||||
'%s%s',
|
||||
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
|
||||
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
|
||||
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
|
||||
))),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sanctum Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array contains the authentication guards that will be checked when
|
||||
| Sanctum is trying to authenticate a request. If none of these guards
|
||||
| are able to authenticate the request, Sanctum will use the bearer
|
||||
| token that's present on an incoming request for authentication.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Sanctum Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array contains the authentication guards that will be checked when
|
||||
| Sanctum is trying to authenticate a request. If none of these guards
|
||||
| are able to authenticate the request, Sanctum will use the bearer
|
||||
| token that's present on an incoming request for authentication.
|
||||
|
|
||||
*/
|
||||
|
||||
'guard' => ['web'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Expiration Minutes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value controls the number of minutes until an issued token will be
|
||||
| considered expired. If this value is null, personal access tokens do
|
||||
| not expire. This won't tweak the lifetime of first-party sessions.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Expiration Minutes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value controls the number of minutes until an issued token will be
|
||||
| considered expired. If this value is null, personal access tokens do
|
||||
| not expire. This won't tweak the lifetime of first-party sessions.
|
||||
|
|
||||
*/
|
||||
|
||||
'expiration' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sanctum Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When authenticating your first-party SPA with Sanctum you may need to
|
||||
| customize some of the middleware Sanctum uses while processing the
|
||||
| request. You may change the middleware listed below as required.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Sanctum Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When authenticating your first-party SPA with Sanctum you may need to
|
||||
| customize some of the middleware Sanctum uses while processing the
|
||||
| request. You may change the middleware listed below as required.
|
||||
|
|
||||
*/
|
||||
|
||||
'middleware' => [
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Third Party Services
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is for storing the credentials for third party services such
|
||||
| as Mailgun, Postmark, AWS and more. This file provides the de facto
|
||||
| location for this type of information, allowing packages to have
|
||||
| a conventional file to locate the various service credentials.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Third Party Services
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is for storing the credentials for third party services such
|
||||
| as Mailgun, Postmark, AWS and more. This file provides the de facto
|
||||
| location for this type of information, allowing packages to have
|
||||
| a conventional file to locate the various service credentials.
|
||||
|
|
||||
*/
|
||||
|
||||
'mailgun' => [
|
||||
|
|
|
|||
|
|
@ -5,30 +5,30 @@ use Illuminate\Support\Str;
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Session Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default session "driver" that will be used on
|
||||
| requests. By default, we will use the lightweight native driver but
|
||||
| you may specify any of the other wonderful drivers provided here.
|
||||
|
|
||||
| Supported: "file", "cookie", "database", "apc",
|
||||
| "memcached", "redis", "dynamodb", "array"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Session Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default session "driver" that will be used on
|
||||
| requests. By default, we will use the lightweight native driver but
|
||||
| you may specify any of the other wonderful drivers provided here.
|
||||
|
|
||||
| Supported: "file", "cookie", "database", "apc",
|
||||
| "memcached", "redis", "dynamodb", "array"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Lifetime
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the number of minutes that you wish the session
|
||||
| to be allowed to remain idle before it expires. If you want them
|
||||
| to immediately expire on the browser closing, set that option.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Lifetime
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the number of minutes that you wish the session
|
||||
| to be allowed to remain idle before it expires. If you want them
|
||||
| to immediately expire on the browser closing, set that option.
|
||||
|
|
||||
*/
|
||||
|
||||
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||
|
|
@ -36,164 +36,164 @@ return [
|
|||
'expire_on_close' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to easily specify that all of your session data
|
||||
| should be encrypted before it is stored. All encryption will be run
|
||||
| automatically by Laravel and you can use the Session like normal.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to easily specify that all of your session data
|
||||
| should be encrypted before it is stored. All encryption will be run
|
||||
| automatically by Laravel and you can use the Session like normal.
|
||||
|
|
||||
*/
|
||||
|
||||
'encrypt' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session File Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the native session driver, we need a location where session
|
||||
| files may be stored. A default has been set for you but a different
|
||||
| location may be specified. This is only needed for file sessions.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session File Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the native session driver, we need a location where session
|
||||
| files may be stored. A default has been set for you but a different
|
||||
| location may be specified. This is only needed for file sessions.
|
||||
|
|
||||
*/
|
||||
|
||||
'files' => storage_path('framework/sessions'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" or "redis" session drivers, you may specify a
|
||||
| connection that should be used to manage these sessions. This should
|
||||
| correspond to a connection in your database configuration options.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" or "redis" session drivers, you may specify a
|
||||
| connection that should be used to manage these sessions. This should
|
||||
| correspond to a connection in your database configuration options.
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => env('SESSION_CONNECTION', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" session driver, you may specify the table we
|
||||
| should use to manage the sessions. Of course, a sensible default is
|
||||
| provided for you; however, you are free to change this as needed.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" session driver, you may specify the table we
|
||||
| should use to manage the sessions. Of course, a sensible default is
|
||||
| provided for you; however, you are free to change this as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'table' => 'sessions',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| While using one of the framework's cache driven session backends you may
|
||||
| list a cache store that should be used for these sessions. This value
|
||||
| must match with one of the application's configured cache "stores".
|
||||
|
|
||||
| Affects: "apc", "dynamodb", "memcached", "redis"
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| While using one of the framework's cache driven session backends you may
|
||||
| list a cache store that should be used for these sessions. This value
|
||||
| must match with one of the application's configured cache "stores".
|
||||
|
|
||||
| Affects: "apc", "dynamodb", "memcached", "redis"
|
||||
|
|
||||
*/
|
||||
|
||||
'store' => env('SESSION_STORE', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Sweeping Lottery
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some session drivers must manually sweep their storage location to get
|
||||
| rid of old sessions from storage. Here are the chances that it will
|
||||
| happen on a given request. By default, the odds are 2 out of 100.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Sweeping Lottery
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some session drivers must manually sweep their storage location to get
|
||||
| rid of old sessions from storage. Here are the chances that it will
|
||||
| happen on a given request. By default, the odds are 2 out of 100.
|
||||
|
|
||||
*/
|
||||
|
||||
'lottery' => [2, 100],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the name of the cookie used to identify a session
|
||||
| instance by ID. The name specified here will get used every time a
|
||||
| new session cookie is created by the framework for every driver.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the name of the cookie used to identify a session
|
||||
| instance by ID. The name specified here will get used every time a
|
||||
| new session cookie is created by the framework for every driver.
|
||||
|
|
||||
*/
|
||||
|
||||
'cookie' => env(
|
||||
'SESSION_COOKIE',
|
||||
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
|
||||
Str::slug(env('APP_NAME', 'laravel'), '_') . '_session'
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session cookie path determines the path for which the cookie will
|
||||
| be regarded as available. Typically, this will be the root path of
|
||||
| your application but you are free to change this when necessary.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session cookie path determines the path for which the cookie will
|
||||
| be regarded as available. Typically, this will be the root path of
|
||||
| your application but you are free to change this when necessary.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => '/',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the domain of the cookie used to identify a session
|
||||
| in your application. This will determine which domains the cookie is
|
||||
| available to in your application. A sensible default has been set.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the domain of the cookie used to identify a session
|
||||
| in your application. This will determine which domains the cookie is
|
||||
| available to in your application. A sensible default has been set.
|
||||
|
|
||||
*/
|
||||
|
||||
'domain' => env('SESSION_DOMAIN', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTPS Only Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By setting this option to true, session cookies will only be sent back
|
||||
| to the server if the browser has a HTTPS connection. This will keep
|
||||
| the cookie from being sent to you when it can't be done securely.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTPS Only Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By setting this option to true, session cookies will only be sent back
|
||||
| to the server if the browser has a HTTPS connection. This will keep
|
||||
| the cookie from being sent to you when it can't be done securely.
|
||||
|
|
||||
*/
|
||||
|
||||
'secure' => env('SESSION_SECURE_COOKIE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTP Access Only
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to true will prevent JavaScript from accessing the
|
||||
| value of the cookie and the cookie will only be accessible through
|
||||
| the HTTP protocol. You are free to modify this option if needed.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTP Access Only
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to true will prevent JavaScript from accessing the
|
||||
| value of the cookie and the cookie will only be accessible through
|
||||
| the HTTP protocol. You are free to modify this option if needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'http_only' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Same-Site Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines how your cookies behave when cross-site requests
|
||||
| take place, and can be used to mitigate CSRF attacks. By default, we
|
||||
| will set this value to "lax" since this is a secure default value.
|
||||
|
|
||||
| Supported: "lax", "strict", "none", null
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Same-Site Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines how your cookies behave when cross-site requests
|
||||
| take place, and can be used to mitigate CSRF attacks. By default, we
|
||||
| will set this value to "lax" since this is a secure default value.
|
||||
|
|
||||
| Supported: "lax", "strict", "none", null
|
||||
|
|
||||
*/
|
||||
|
||||
'same_site' => 'lax',
|
||||
|
|
|
|||
58
config/trustedproxy.php
Normal file
58
config/trustedproxy.php
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
* Set trusted proxy IP addresses.
|
||||
*
|
||||
* Both IPv4 and IPv6 addresses are
|
||||
* supported, along with CIDR notation.
|
||||
*
|
||||
* The "*" character is syntactic sugar
|
||||
* within TrustedProxy to trust any proxy
|
||||
* that connects directly to your server,
|
||||
* a requirement when you cannot know the address
|
||||
* of your proxy (e.g. if using ELB or similar).
|
||||
*
|
||||
*/
|
||||
|
||||
'proxies' => [
|
||||
// * HA PROXY prod "Virtual IP".
|
||||
'192.168.31.9',
|
||||
// * HA PROXY prod "Virtual IP" redondance.
|
||||
'192.168.31.10',
|
||||
// * HA PROXY dev "Virtual IP".
|
||||
'192.168.34.15'
|
||||
],
|
||||
|
||||
/*
|
||||
* To trust one or more specific proxies that connect
|
||||
* directly to your server, use an array or a string separated by comma of IP addresses:
|
||||
*/
|
||||
|
||||
/*
|
||||
* Or, to trust all proxies that connect
|
||||
* directly to your server, use a "*"
|
||||
*/
|
||||
|
||||
/*
|
||||
* Which headers to use to detect proxy related data (For, Host, Proto, Port)
|
||||
*
|
||||
* Options include:
|
||||
*
|
||||
* - Illuminate\Http\Request::HEADER_X_FORWARDED_ALL (use all x-forwarded-* headers to establish trust)
|
||||
* - Illuminate\Http\Request::HEADER_FORWARDED (use the FORWARDED header to establish trust)
|
||||
* - Illuminate\Http\Request::HEADER_X_FORWARDED_AWS_ELB (If you are using AWS Elastic Load Balancer)
|
||||
*
|
||||
* - 'HEADER_X_FORWARDED_ALL' (use all x-forwarded-* headers to establish trust)
|
||||
* - 'HEADER_FORWARDED' (use the FORWARDED header to establish trust)
|
||||
* - 'HEADER_X_FORWARDED_AWS_ELB' (If you are using AWS Elastic Load Balancer)
|
||||
*
|
||||
* @link https://symfony.com/doc/current/deployment/proxies.html
|
||||
*/
|
||||
|
||||
'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_FOR |
|
||||
Illuminate\Http\Request::HEADER_X_FORWARDED_HOST |
|
||||
Illuminate\Http\Request::HEADER_X_FORWARDED_PORT |
|
||||
Illuminate\Http\Request::HEADER_X_FORWARDED_PROTO,
|
||||
];
|
||||
|
|
@ -3,14 +3,14 @@
|
|||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| View Storage Paths
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Most templating systems load templates from disk. Here you may specify
|
||||
| an array of paths that should be checked for your views. Of course
|
||||
| the usual Laravel view path has already been registered for you.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| View Storage Paths
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Most templating systems load templates from disk. Here you may specify
|
||||
| an array of paths that should be checked for your views. Of course
|
||||
| the usual Laravel view path has already been registered for you.
|
||||
|
|
||||
*/
|
||||
|
||||
'paths' => [
|
||||
|
|
@ -18,14 +18,14 @@ return [
|
|||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Compiled View Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines where all the compiled Blade templates will be
|
||||
| stored for your application. Typically, this is within the storage
|
||||
| directory. However, as usual, you are free to change this value.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Compiled View Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines where all the compiled Blade templates will be
|
||||
| stored for your application. Typically, this is within the storage
|
||||
| directory. However, as usual, you are free to change this value.
|
||||
|
|
||||
*/
|
||||
|
||||
'compiled' => env(
|
||||
|
|
|
|||
21
database/factories/ArcadiaBrandFactory.php
Normal file
21
database/factories/ArcadiaBrandFactory.php
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class ArcadiaBrandFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'arcadia_id' => $this->faker->unique()->numberBetween(1, 999),
|
||||
'libelle' => $this->faker->unique()->company()
|
||||
];
|
||||
}
|
||||
}
|
||||
20
database/factories/ServiceFactory.php
Normal file
20
database/factories/ServiceFactory.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class ServiceFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->unique()->name() . ' Service'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ class UserFactory extends Factory
|
|||
'name' => $this->faker->name(),
|
||||
'email' => $this->faker->unique()->safeEmail(),
|
||||
'email_verified_at' => now(),
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
'password' => 'password',
|
||||
'remember_token' => Str::random(10),
|
||||
];
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ class UserFactory extends Factory
|
|||
*/
|
||||
public function unverified()
|
||||
{
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
return $this->state(function (array $attributes) {
|
||||
return [
|
||||
'email_verified_at' => null,
|
||||
|
|
|
|||
105
database/factories/XmlIncoFactory.php
Normal file
105
database/factories/XmlIncoFactory.php
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class XmlIncoFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'nom' => $this->faker->unique()->words(rand(2, 3), true),
|
||||
'prod_saison' => $this->faker->boolean(),
|
||||
'allegations' => $this->faker->boolean(75) ? $this->faker->sentence(7) : null,
|
||||
'descriptif' => $this->faker->boolean(75) ? 'descriptif ' . $this->faker->text(150) : null,
|
||||
'pictures' => [],
|
||||
'astuces' => $this->faker->boolean(75) ? 'astuces ' . $this->faker->text(150) : null,
|
||||
'lib_conso' => $this->faker->boolean(75) ? $this->faker->sentence(7) : null,
|
||||
'nb_portion' => $this->faker->boolean(75) ? $this->faker->text(20) : null,
|
||||
'typ_portion' => $this->faker->boolean(75) ? 'typ_portion ' . $this->faker->text(150) : null,
|
||||
'pds_moy_theo' => $this->faker->boolean(75) ? $this->faker->numberBetween(0, 250) : null,
|
||||
|
||||
'conseil_prepa' => $this->faker->boolean(75) ? 'conseil_prepa ' . $this->faker->text(150) : null,
|
||||
'arg_vente' => $this->faker->boolean(75) ? 'arg_vente ' . $this->faker->text(150) : null,
|
||||
'lst_ing' => $this->faker->boolean(75) ? 'lst_ing ' . $this->faker->text(150) : null,
|
||||
'lib_allergene' => $this->faker->boolean(75) ? 'lib_allergene ' . $this->faker->text(150) : null,
|
||||
|
||||
'nutritional_values' => [
|
||||
'val_energ_kj_r' => $this->faker->numberBetween(250, 1200),
|
||||
'val_energ_kcal_r' => $this->faker->numberBetween(50, 400),
|
||||
'mat_grass_r' => $this->faker->numberBetween(6, 30),
|
||||
'ags_r' => '5.3',
|
||||
'glucides_r' => '2',
|
||||
'sucre_r' => '1.4',
|
||||
'fib_alim_r' => '0.8',
|
||||
'proteine_r' => '17',
|
||||
'sel_r' => '0.47',
|
||||
'sodium_r' => '188',
|
||||
'fruits_r' => '0',
|
||||
'fruits_coque_sech_r' => '0',
|
||||
'pourcent_apport_ref_e14_r' => '11.4',
|
||||
'pourcent_apport_ref_kjo_r' => '11.5',
|
||||
'pourcent_apport_ref_fat_r' => '24.7',
|
||||
'pourcent_apport_ref_fatsat_r' => '29.8',
|
||||
'pourcent_apport_ref_choval_r' => '0.6',
|
||||
'pourcent_apport_ref_sugar_r' => '1.7',
|
||||
'pourcent_apport_ref_fibtg_r' => null,
|
||||
'pourcent_apport_ref_pro_r' => '33',
|
||||
'pourcent_apport_ref_salteq_r' => '6.7',
|
||||
'taille_port' => null,
|
||||
'val_energ_kj_p' => null,
|
||||
'val_energ_kcal_p' => null,
|
||||
'mat_grass_p' => null,
|
||||
'ags_p' => null,
|
||||
'glucides_p' => null,
|
||||
'sucre_p' => null,
|
||||
'fib_alim_p' => null,
|
||||
'proteine_p' => null,
|
||||
'sodium_p' => null,
|
||||
'fruits_p' => null,
|
||||
'sel_p' => null,
|
||||
'fruits_coque_sech_p' => null,
|
||||
'pourcent_apport_ref_e14_p' => null,
|
||||
'pourcent_apport_ref_kjo_p' => null,
|
||||
'pourcent_apport_ref_fat_p' => null,
|
||||
'pourcent_apport_ref_fatsat_p' => null,
|
||||
'pourcent_apport_ref_choval_p' => null,
|
||||
'pourcent_apport_ref_sugar_p' => null,
|
||||
'pourcent_apport_ref_fibtg_p' => null,
|
||||
'pourcent_apport_ref_pro_p' => null,
|
||||
'pourcent_apport_ref_salteq_p' => null,
|
||||
'apport_port' => 'Apport de r\u00e9f\u00e9rence pour un adulte type (8400Kj-2000Kcal)',
|
||||
'part_p' => '32',
|
||||
'part_g' => '4',
|
||||
'part_l' => '63',
|
||||
'p_sur_l' => '1.13',
|
||||
'pourcent_ags' => '35',
|
||||
'pourcent_agi' => '65',
|
||||
'pourcent_ss' => '70',
|
||||
'pourcent_amidon' => '30',
|
||||
'composante_n' => '9',
|
||||
'composante_p' => '5',
|
||||
'pourcent_fruits' => '0',
|
||||
'score_nutri' => '4',
|
||||
'classement' => 'C',
|
||||
'mat_grass_r_prec' => '=',
|
||||
'ags_r_prec' => '=',
|
||||
'glucides_r_prec' => '=',
|
||||
'sucre_r_prec' => '=',
|
||||
'fib_alim_r_prec' => '=',
|
||||
'proteine_r_prec' => '=',
|
||||
'sel_r_prec' => '=',
|
||||
'sodium_r_prec' => null,
|
||||
'fruits_r_prec' => null,
|
||||
'fruits_coque_sech_r_prec' => null
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateArcadiaBrandsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('arcadia_brands', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->unsignedBigInteger('arcadia_id')->unique();
|
||||
$table->string('libelle');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('arcadia_brands');
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
|
|||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreatePersonalAccessTokensTable extends Migration
|
||||
class CreateServicesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
|
|
@ -13,13 +13,14 @@ class CreatePersonalAccessTokensTable extends Migration
|
|||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||
Schema::create('services', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->morphs('tokenable');
|
||||
|
||||
$table->string('name');
|
||||
$table->string('token', 64)->unique();
|
||||
$table->text('abilities')->nullable();
|
||||
$table->timestamp('last_used_at')->nullable();
|
||||
$table->string('bearer_token')->unique();
|
||||
$table->string('bearer_pwd', 312);
|
||||
$table->timestamp('bearer_token_date');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
@ -31,6 +32,6 @@ class CreatePersonalAccessTokensTable extends Migration
|
|||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('personal_access_tokens');
|
||||
Schema::dropIfExists('services');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateArcadiaBrandServiceTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('arcadia_brand_service', function (Blueprint $table) {
|
||||
$table->foreignId('service_id')->constrained('services');
|
||||
$table->foreignId('arcadia_brand_id')->constrained('arcadia_brands');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('arcadia_brand_service');
|
||||
}
|
||||
}
|
||||
|
|
@ -15,13 +15,13 @@ class CreateXmlIncosTable extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('xml_incos', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->id()->comment('Inco ID (NO_ART)');
|
||||
$table->string('nom')->nullable();
|
||||
$table->boolean('prod_saison');
|
||||
|
||||
$table->string('allegations')->nullable();
|
||||
$table->text('descriptif')->nullable();
|
||||
$table->json('picture');
|
||||
$table->json('pictures');
|
||||
$table->text('astuces')->nullable();
|
||||
$table->string('lib_conso')->nullable();
|
||||
$table->string('nb_portion', 20)->nullable();
|
||||
|
|
@ -35,6 +35,8 @@ class CreateXmlIncosTable extends Migration
|
|||
|
||||
$table->json('nutritional_values');
|
||||
|
||||
$table->foreignId('arcadia_brand_id')->constrained('arcadia_brands');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
// phpcs:ignore PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
class CreateServiceStats extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('service_stats', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->foreignId('service_id')->constrained('services');
|
||||
$table->date('date');
|
||||
$table->unsignedBigInteger('nb_calls')->default(0);
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('service_stats');
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,13 @@
|
|||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\ArcadiaBrand;
|
||||
use App\Models\Service;
|
||||
use App\Models\XmlInco;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use SplFileInfo;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
|
|
@ -13,6 +19,35 @@ class DatabaseSeeder extends Seeder
|
|||
*/
|
||||
public function run()
|
||||
{
|
||||
// \App\Models\User::factory(10)->create();
|
||||
/** @var \Illuminate\Database\Eloquent\Collection $services */
|
||||
$services = Service::factory(5)->create();
|
||||
/** @var \Illuminate\Database\Eloquent\Collection $brands */
|
||||
$brands = ArcadiaBrand::factory(10)->create();
|
||||
|
||||
// * Associate brands to services
|
||||
$services->map(function (Service $service) use (&$brands) {
|
||||
$pullBrands = $brands->random(rand(1, 2));
|
||||
$service->arcadiaBrands()->sync($pullBrands);
|
||||
$brands = $brands->diff($pullBrands);
|
||||
});
|
||||
|
||||
$disk = Storage::disk('inco');
|
||||
|
||||
$brands->map(function (ArcadiaBrand $brand) use ($disk) {
|
||||
XmlInco::factory(rand(150, 355))->make()
|
||||
->each(function (XmlInco $xmlInco) use ($disk, $brand) {
|
||||
$xmlInco->pictures = collect([
|
||||
new SplFileInfo(resource_path('seeders/xml_inco/fakeimage1.png')),
|
||||
new SplFileInfo(resource_path('seeders/xml_inco/fakeimage2.png'))
|
||||
])->random(rand(0, 2))->map(function (SplFileInfo $image) use ($disk) {
|
||||
$imgNamePath = $image->getFilename();
|
||||
$imageFinalPath = "images/inco/$imgNamePath";
|
||||
$disk->put($imgNamePath, File::get($image->getPathname()));
|
||||
return $imageFinalPath;
|
||||
})->all();
|
||||
$xmlInco->arcadiaBrand()->associate($brand);
|
||||
$xmlInco->saveOrFail();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16468
package-lock.json
generated
Normal file
16468
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -11,7 +11,9 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.21",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"laravel-mix": "^6.0.6",
|
||||
"laravel-mix-polyfill": "^3.0.1",
|
||||
"lodash": "^4.17.19",
|
||||
"postcss": "^8.1.14"
|
||||
}
|
||||
|
|
|
|||
48
phpunit.xml
48
phpunit.xml
|
|
@ -1,31 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/schema/9.2.xsd" bootstrap="vendor/autoload.php" colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory suffix="Test.php">./tests/Unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Feature">
|
||||
<directory suffix="Test.php">./tests/Feature</directory>
|
||||
<testsuite name="Api">
|
||||
<directory suffix="Test.php">./tests/Api</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">./app</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory>./app</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-html" target="tests/coverage" />
|
||||
</logging>
|
||||
<php>
|
||||
<server name="APP_ENV" value="testing"/>
|
||||
<server name="BCRYPT_ROUNDS" value="4"/>
|
||||
<server name="CACHE_DRIVER" value="array"/>
|
||||
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
|
||||
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
|
||||
<server name="MAIL_MAILER" value="array"/>
|
||||
<server name="QUEUE_CONNECTION" value="sync"/>
|
||||
<server name="SESSION_DRIVER" value="array"/>
|
||||
<server name="TELESCOPE_ENABLED" value="false"/>
|
||||
<server name="APP_ENV" value="testing" />
|
||||
<server name="APP_URL" value="http://127.0.0.1:8888" />
|
||||
|
||||
<server name="BCRYPT_ROUNDS" value="4" />
|
||||
<server name="CACHE_DRIVER" value="array" />
|
||||
|
||||
<server name="MAIL_MAILER" value="array" />
|
||||
<env name="QUEUE_DRIVER" value="database" />
|
||||
<server name="QUEUE_CONNECTION" value="database" />
|
||||
|
||||
<server name="SESSION_DRIVER" value="array" />
|
||||
<server name="TELESCOPE_ENABLED" value="false" />
|
||||
|
||||
</php>
|
||||
</phpunit>
|
||||
|
|
|
|||
0
resources/documents/arcadia/marque.xsd
Normal file
0
resources/documents/arcadia/marque.xsd
Normal file
270
resources/documents/inco/incollector.xsd
Normal file
270
resources/documents/inco/incollector.xsd
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Created with Liquid Technologies Online Tools 1.0 (https://www.liquid-technologies.com) -->
|
||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="INCO">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="typemouvementinformatique" type="xs:string" />
|
||||
<xs:element name="NO_ART" type="xs:string" />
|
||||
<xs:element name="INCO_COMPO">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="TBL_INCO_COMPO">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string" />
|
||||
<xs:element name="ID_INCO" type="xs:string" />
|
||||
<xs:element name="NOM" type="xs:string" />
|
||||
<xs:element name="NUMERO" type="xs:string" />
|
||||
<xs:element name="TAILLE_REF" type="xs:string" />
|
||||
<xs:element name="VAL_ENERG_KJ_R" type="xs:string" />
|
||||
<xs:element name="VAL_ENERG_KCAL_R" type="xs:string" />
|
||||
<xs:element name="MAT_GRASS_R" type="xs:string" />
|
||||
<xs:element name="AGS_R" type="xs:string" />
|
||||
<xs:element name="GLUCIDES_R" type="xs:string" />
|
||||
<xs:element name="SUCRE_R" type="xs:string" />
|
||||
<xs:element name="FIB_ALIM_R" type="xs:string" />
|
||||
<xs:element name="PROTEINE_R" type="xs:string" />
|
||||
<xs:element name="SEL_R" type="xs:string" />
|
||||
<xs:element name="SODIUM_R" type="xs:string" />
|
||||
<xs:element name="FRUITS_R" type="xs:string" />
|
||||
<xs:element name="FRUITS_COQUE_SECH_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_E14_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_KJO_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FAT_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FATSAT_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_CHOVAL_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_SUGAR_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FIBTG_R" />
|
||||
<xs:element name="POURCENT_APPORT_REF_PRO_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_SALTEQ_R" type="xs:string" />
|
||||
<xs:element name="TAILLE_PORT" type="xs:string" />
|
||||
<xs:element name="VAL_ENERG_KJ_P" type="xs:string" />
|
||||
<xs:element name="VAL_ENERG_KCAL_P" type="xs:string" />
|
||||
<xs:element name="MAT_GRASS_P" type="xs:string" />
|
||||
<xs:element name="AGS_P" type="xs:string" />
|
||||
<xs:element name="GLUCIDES_P" type="xs:string" />
|
||||
<xs:element name="SUCRE_P" type="xs:string" />
|
||||
<xs:element name="FIB_ALIM_P" type="xs:string" />
|
||||
<xs:element name="PROTEINE_P" type="xs:string" />
|
||||
<xs:element name="SEL_P" type="xs:string" />
|
||||
<xs:element name="SODIUM_P" type="xs:string" />
|
||||
<xs:element name="FRUITS_P" type="xs:string" />
|
||||
<xs:element name="FRUITS_COQUE_SECH_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_E14_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_KJO_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FAT_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FATSAT_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_CHOVAL_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_SUGAR_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FIBTG_P" />
|
||||
<xs:element name="POURCENT_APPORT_REF_PRO_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_SALTEQ_P" type="xs:string" />
|
||||
<xs:element name="APPORT_PORT" type="xs:string" />
|
||||
<xs:element name="PART_P" type="xs:string" />
|
||||
<xs:element name="PART_G" type="xs:string" />
|
||||
<xs:element name="PART_L" type="xs:string" />
|
||||
<xs:element name="P_SUR_L" type="xs:string" />
|
||||
<xs:element name="POURCENT_AGS" type="xs:string" />
|
||||
<xs:element name="POURCENT_AGI" type="xs:string" />
|
||||
<xs:element name="POURCENT_SS" type="xs:string" />
|
||||
<xs:element name="POURCENT_AMIDON" type="xs:string" />
|
||||
<xs:element name="COMPOSANTE_N" type="xs:string" />
|
||||
<xs:element name="COMPOSANTE_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_FRUITS" type="xs:string" />
|
||||
<xs:element name="SCORE_NUTRI" type="xs:string" />
|
||||
<xs:element name="CLASSEMENT" type="xs:string" />
|
||||
<xs:element name="MAT_GRASS_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="AGS_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="GLUCIDES_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SUCRE_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="FIB_ALIM_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="PROTEINE_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SEL_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SODIUM_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" />
|
||||
<xs:element name="libelle" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="FRUITS_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" />
|
||||
<xs:element name="libelle" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="FRUITS_COQUE_SECH_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" />
|
||||
<xs:element name="libelle" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="PROD_SAISON">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="CONSEIL_PREPA" type="xs:string" />
|
||||
<xs:element name="ALLEGATIONS" />
|
||||
<xs:element name="ASTUCES" />
|
||||
<xs:element name="DESCRIPTIF" type="xs:string" />
|
||||
<xs:element name="ARG_VENTE" type="xs:string" />
|
||||
<xs:element name="NB_PORTION" type="xs:string" />
|
||||
<xs:element name="TYP_PORTION">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="FAMILLE_VTE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="COD_FAMVTE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="FAM_VENTE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="COD_FAMVTE" type="xs:string" />
|
||||
<xs:element name="LIB_FAMVTE" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="DATE_STATUT_CHEF_PRODUIT" type="xs:string" />
|
||||
<xs:element name="EXPLOITANT">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="SOCIETE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID_SOCIETE" type="xs:string" />
|
||||
<xs:element name="NOM_SOCIETE" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="PDS_MOY_THEO" />
|
||||
<xs:element name="LIB_CONSO" />
|
||||
<xs:element name="LST_ING" />
|
||||
<xs:element name="LST_ALLERGENE" />
|
||||
<xs:element name="ALLEGAT_SANTE" />
|
||||
<xs:element name="ALLEGAT_NUTRIT" />
|
||||
<xs:element name="ALLEGAT_AUTRE" />
|
||||
<xs:element name="MEDIA_VISUEL_EAI">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="MEDIA_VISUEL_EAI">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="NumeroArticle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="version" type="xs:string" />
|
||||
<xs:element name="DATEVERSION" type="xs:string" />
|
||||
<xs:element name="STATUT_CHEF_PRODUIT">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="CHEF_PRODUIT">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="UTILISATEURS">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
|
||||
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
BIN
resources/seeders/xml_inco/fakeimage1.png
Normal file
BIN
resources/seeders/xml_inco/fakeimage1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3 MiB |
BIN
resources/seeders/xml_inco/fakeimage2.png
Normal file
BIN
resources/seeders/xml_inco/fakeimage2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 MiB |
|
|
@ -1,11 +1,11 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>{{ $appName }} Exception Handler: Unvalid XML</title>
|
||||
<title>XML Exception Handler: Invalid XML</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{ $appName }} à reçu un fichier xml non valide !!</h1>
|
||||
<h1>{{ config('app.name') }} à reçu un fichier xml non valide</h1>
|
||||
<h3>{{ $strError }}</h3>
|
||||
<h4>FICHIER: `{{ $filename }}`</h4>
|
||||
<p>{{ $exception->getMessage() }}</p>
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
<b>file</b> : {{$exception->getFile() }}<br>
|
||||
<b>line</b> : {{$exception->getLine() }}<br>
|
||||
<p>
|
||||
<b>Merci de corriger le flux, puis de renvoyer le fichier en provoquant un mouvement EAI.</b><br><br>
|
||||
<b>Merci de corriger les données, puis de renvoyer le fichier en provoquant un mouvement EAI.</b><br><br>
|
||||
<b>Pour rappel</b> : Il est recommandé de valider un fichier XML à l'aide d'un <b>DTD</b><br>
|
||||
<a href="https://www.w3schools.com/xml/xml_dtd.asp">https://www.w3schools.com/xml/xml_dtd.asp</a><br>
|
||||
ou bien <b>XSD</b> <a href="https://www.w3schools.com/xml/schema_intro.asp">https://www.w3schools.com/xml/schema_intro.asp</a><br><br>
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\Api\V1\ApiController as V1ApiController;
|
||||
use App\Http\Controllers\Api\V1\XmlIncoController as V1XmlIncoController;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register API routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider within a group which
|
||||
| is assigned the "api" middleware group. Enjoy building your API!
|
||||
|
|
||||
*/
|
||||
Route::prefix('v1')->name('apiV1.')->group(function () {
|
||||
|
||||
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
// * PUBLIC
|
||||
Route::get('/ping', [V1ApiController::class, 'ping'])->name('ping');
|
||||
|
||||
// * PRIVATE
|
||||
Route::middleware('auth:api')->group(function () {
|
||||
Route::prefix('inco')->name('incos.')->group(function () {
|
||||
Route::get('/', [V1XmlIncoController::class, 'index'])->name('index');
|
||||
Route::get('/{xmlinco}', [V1XmlIncoController::class, 'show'])->name('show');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Broadcast;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Broadcast Channels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may register all of the event broadcasting channels that your
|
||||
| application supports. The given channel authorization callbacks are
|
||||
| used to check if an authenticated user can listen to the channel.
|
||||
|
|
||||
*/
|
||||
|
||||
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
|
||||
return (int) $user->id === (int) $id;
|
||||
});
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Console Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is where you may define all of your Closure based console
|
||||
| commands. Each Closure is bound to a command instance allowing a
|
||||
| simple approach to interacting with each command's IO methods.
|
||||
|
|
||||
*/
|
||||
|
||||
Artisan::command('inspire', function () {
|
||||
$this->comment(Inspiring::quote());
|
||||
})->purpose('Display an inspiring quote');
|
||||
|
|
@ -3,14 +3,14 @@
|
|||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register web routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider within a group which
|
||||
| contains the "web" middleware group. Now create something great!
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register web routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider within a group which
|
||||
| contains the "web" middleware group. Now create something great!
|
||||
|
|
||||
*/
|
||||
|
||||
Route::get('/', function () {
|
||||
|
|
|
|||
1
storage/.gitignore
vendored
1
storage/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
inco/*
|
||||
|
|
@ -1,273 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Created with Liquid Technologies Online Tools 1.0 (https://www.liquid-technologies.com) -->
|
||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="LIST">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="INCO">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="typemouvementinformatique" type="xs:string" />
|
||||
<xs:element name="NO_ART" type="xs:string" />
|
||||
<xs:element name="INCO_COMPO">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="TBL_INCO_COMPO">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string" />
|
||||
<xs:element name="ID_INCO" type="xs:string" />
|
||||
<xs:element name="NOM" type="xs:string" />
|
||||
<xs:element name="NUMERO" type="xs:string" />
|
||||
<xs:element name="TAILLE_REF" type="xs:string" />
|
||||
<xs:element name="VAL_ENERG_KJ_R" type="xs:string" />
|
||||
<xs:element name="VAL_ENERG_KCAL_R" type="xs:string" />
|
||||
<xs:element name="MAT_GRASS_R" type="xs:string" />
|
||||
<xs:element name="AGS_R" type="xs:string" />
|
||||
<xs:element name="GLUCIDES_R" type="xs:string" />
|
||||
<xs:element name="SUCRE_R" type="xs:string" />
|
||||
<xs:element name="FIB_ALIM_R" type="xs:string" />
|
||||
<xs:element name="PROTEINE_R" type="xs:string" />
|
||||
<xs:element name="SEL_R" type="xs:string" />
|
||||
<xs:element name="SODIUM_R" type="xs:string" />
|
||||
<xs:element name="FRUITS_R" type="xs:string" />
|
||||
<xs:element name="FRUITS_COQUE_SECH_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_E14_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_KJO_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FAT_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FATSAT_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_CHOVAL_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_SUGAR_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FIBTG_R" />
|
||||
<xs:element name="POURCENT_APPORT_REF_PRO_R" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_SALTEQ_R" type="xs:string" />
|
||||
<xs:element name="TAILLE_PORT" type="xs:string" />
|
||||
<xs:element name="VAL_ENERG_KJ_P" type="xs:string" />
|
||||
<xs:element name="VAL_ENERG_KCAL_P" type="xs:string" />
|
||||
<xs:element name="MAT_GRASS_P" type="xs:string" />
|
||||
<xs:element name="AGS_P" type="xs:string" />
|
||||
<xs:element name="GLUCIDES_P" type="xs:string" />
|
||||
<xs:element name="SUCRE_P" type="xs:string" />
|
||||
<xs:element name="FIB_ALIM_P" type="xs:string" />
|
||||
<xs:element name="PROTEINE_P" type="xs:string" />
|
||||
<xs:element name="SEL_P" type="xs:string" />
|
||||
<xs:element name="SODIUM_P" type="xs:string" />
|
||||
<xs:element name="FRUITS_P" type="xs:string" />
|
||||
<xs:element name="FRUITS_COQUE_SECH_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_E14_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_KJO_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FAT_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FATSAT_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_CHOVAL_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_SUGAR_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_FIBTG_P" />
|
||||
<xs:element name="POURCENT_APPORT_REF_PRO_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_APPORT_REF_SALTEQ_P" type="xs:string" />
|
||||
<xs:element name="APPORT_PORT" type="xs:string" />
|
||||
<xs:element name="PART_P" type="xs:string" />
|
||||
<xs:element name="PART_G" type="xs:string" />
|
||||
<xs:element name="PART_L" type="xs:string" />
|
||||
<xs:element name="P_SUR_L" type="xs:string" />
|
||||
<xs:element name="POURCENT_AGS" type="xs:string" />
|
||||
<xs:element name="POURCENT_AGI" type="xs:string" />
|
||||
<xs:element name="POURCENT_SS" type="xs:string" />
|
||||
<xs:element name="POURCENT_AMIDON" type="xs:string" />
|
||||
<xs:element name="COMPOSANTE_N" type="xs:string" />
|
||||
<xs:element name="COMPOSANTE_P" type="xs:string" />
|
||||
<xs:element name="POURCENT_FRUITS" type="xs:string" />
|
||||
<xs:element name="SCORE_NUTRI" type="xs:string" />
|
||||
<xs:element name="CLASSEMENT" type="xs:string" />
|
||||
<xs:element name="MAT_GRASS_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="AGS_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="GLUCIDES_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SUCRE_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="FIB_ALIM_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="PROTEINE_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SEL_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SODIUM_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" />
|
||||
<xs:element name="libelle" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="FRUITS_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" />
|
||||
<xs:element name="libelle" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="FRUITS_COQUE_SECH_R_PREC">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" />
|
||||
<xs:element name="libelle" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="PROD_SAISON">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="CONSEIL_PREPA" type="xs:string" />
|
||||
<xs:element name="ALLEGATIONS" />
|
||||
<xs:element name="ASTUCES" />
|
||||
<xs:element name="DESCRIPTIF" type="xs:string" />
|
||||
<xs:element name="ARG_VENTE" type="xs:string" />
|
||||
<xs:element name="NB_PORTION" type="xs:string" />
|
||||
<xs:element name="TYP_PORTION">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="FAMILLE_VTE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="COD_FAMVTE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="FAM_VENTE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="COD_FAMVTE" type="xs:string" />
|
||||
<xs:element name="LIB_FAMVTE" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="DATE_STATUT_CHEF_PRODUIT" type="xs:string" />
|
||||
<xs:element name="EXPLOITANT">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="SOCIETE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID_SOCIETE" type="xs:string" />
|
||||
<xs:element name="NOM_SOCIETE" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="PDS_MOY_THEO" />
|
||||
<xs:element name="LIB_CONSO" />
|
||||
<xs:element name="LST_ING" />
|
||||
<xs:element name="LST_ALLERGENE" />
|
||||
<xs:element name="ALLEGAT_SANTE" />
|
||||
<xs:element name="ALLEGAT_NUTRIT" />
|
||||
<xs:element name="ALLEGAT_AUTRE" />
|
||||
<xs:element name="MEDIA_VISUEL_EAI">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="MEDIA_VISUEL_EAI">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="NumeroArticle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="version" type="xs:string" />
|
||||
<xs:element name="DATEVERSION" type="xs:string" />
|
||||
<xs:element name="STATUT_CHEF_PRODUIT">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="CHEF_PRODUIT">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="UTILISATEURS">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" />
|
||||
<xs:element name="libelle" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
0
storage/marque/archives/.gitkeep
Normal file
0
storage/marque/archives/.gitkeep
Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue