Merge branch 'trunk'

This commit is contained in:
Noah Lancien 2025-06-04 15:18:47 +02:00
commit 43ae1cb818
359 changed files with 33299 additions and 33200 deletions

View file

@ -11,5 +11,8 @@ trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.yml]
[*.yml,yaml]
indent_size = 2
[docker-compose.yml]
indent_size = 4

View file

@ -6,6 +6,8 @@ APP_URL=http://localhost
PROJECT_UUID=
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
@ -16,13 +18,20 @@ DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MEMCACHED_HOST=127.0.0.1
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
@ -39,6 +48,16 @@ LDAP_USERNAME="cn=admin,dc=example,dc=org"
LDAP_PASSWORD=adminpassword
LDAP_USE_SSL=false
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
ELASTICSEARCH_HOSTS=
MAIL_LIST_SERVICEWEB=
PROJECT_UUID=
## MAIL ADDRESSES
MAIL_LIST_SERVICEWEB=digital@ldc.fr

60
.env.testing Normal file
View file

@ -0,0 +1,60 @@
APP_NAME=Dam
APP_ENV=local
APP_KEY=base64:2fKdUeMKBwyKzJeOcIaRXC0yujSMKkQJ98XLhC2uqf0=
APP_DEBUG=true
APP_URL=https://dam.s-web.test
PROJECT_UUID=
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=dev-mariadb
DB_PORT=3306
DB_DATABASE=testing_dam
DB_USERNAME=root
DB_PASSWORD=secret
ELASTICSEARCH_HOSTS=dev-elasticsearch:9200
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=dev-mailhog
MAIL_PORT=1025
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=no-reply@dam.lesidc.com
MAIL_FROM_NAME="${APP_NAME}"
MAIL_ADMIN=digital@ldc.fr
LDAP_ACCOUNT_PREFIX="cn="
LDAP_ACCOUNT_SUFFIX=",ou=users,dc=example,dc=org"
LDAP_HOSTS=dev-openldap
LDAP_PORT=1389
LDAP_BASE_DN="dc=example,dc=org"
LDAP_USERNAME="cn=admin,dc=example,dc=org"
LDAP_PASSWORD=adminpassword
LDAP_USE_SSL=false
PROJECT_UUID=
## MAIL ADDRESSES
MAIL_LIST_SERVICEWEB=digital@ldc.fr
LDC_STATUS_CHECKER_API_KEY=CE8S52Qq7stf5k8frF4T
LDC_STATUS_CHECKER_UUID=4d8b2c20-107a-4682-b591-dc6c685126df

60
.env.testing.example Normal file
View file

@ -0,0 +1,60 @@
APP_NAME=Dam
APP_ENV=local
APP_KEY=base64:2fKdUeMKBwyKzJeOcIaRXC0yujSMKkQJ98XLhC2uqf0=
APP_DEBUG=true
APP_URL=https://dam.s-web.test
PROJECT_UUID=
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=dev-mariadb
DB_PORT=3306
DB_DATABASE=testing_dam
DB_USERNAME=root
DB_PASSWORD=
ELASTICSEARCH_HOSTS=dev-elasticsearch:9200
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=dev-mailhog
MAIL_PORT=1025
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=no-reply@dam.lesidc.com
MAIL_FROM_NAME="${APP_NAME}"
MAIL_ADMIN=digital@ldc.fr
LDAP_ACCOUNT_PREFIX=
LDAP_ACCOUNT_SUFFIX=
LDAP_HOSTS=
LDAP_PORT=
LDAP_BASE_DN=
LDAP_USERNAME=
LDAP_PASSWORD=
LDAP_USE_SSL=
PROJECT_UUID=
## MAIL ADDRESSES
MAIL_LIST_SERVICEWEB=digital@ldc.fr
LDC_STATUS_CHECKER_API_KEY=
LDC_STATUS_CHECKER_UUID=

11
.gitattributes vendored
View file

@ -1,5 +1,10 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore

7
.gitignore vendored
View file

@ -25,10 +25,13 @@ public/uploads/*
/storage/*.key
/vendor
.env
.env*
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
.idea/
/.idea
/.vscode
*.sqlite*
auth.json

View file

@ -0,0 +1,11 @@
## Comportement constaté
## Comportement attendu
## Solution envisagée
## Étapes pour la reproduction du bug
*

View file

@ -0,0 +1,7 @@
## Présentation du besoin
## Implémentation
## Maquettes, documentations...

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "clients/Api"]
path = clients/Api
url = ../dam-client.git

13
.styleci.yml Normal file
View file

@ -0,0 +1,13 @@
php:
preset: laravel
disabled:
- unused_use
- no_unused_imports
finder:
not-name:
- index.php
js:
finder:
not-name:
- webpack.mix.js
css: true

View file

@ -16,7 +16,9 @@
"titleBar.activeBackground": "#514403",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#51440399",
"titleBar.inactiveForeground": "#e7e7e799"
"titleBar.inactiveForeground": "#e7e7e799",
"commandCenter.border": "#e7e7e799"
},
"peacock.remoteColor": "#514403"
"peacock.remoteColor": "#514403",
"intelephense.environment.phpVersion": "8.1"
}

View file

@ -1,4 +1,10 @@
# DAM
# TODO:
- Remplace par VUE 3 + Runtime Only
- Typescript
- Faut-il exporter les stats Api avant de supprimer un ApiToken ?
## Installation
### - Default
```
@ -7,20 +13,24 @@ composer install
cp .env.example .env
php artisan key:generate
```
### - Stack en attendant le bump Laravel
### - Stack Laravel
```
npm install && npm run prod
composer install
```
Dans vendor/laravel/framework/src/Illuminate/Foundation/PackageManifest.php, ligne 116
```
//$packages = json_decode($this->files->get($path), true);
$installed = json_decode($this->files->get($path), true);
$packages = $installed['packages'] ?? $installed;
```
Puis
```
composer install
cp .env.example .env
php artisan key:generate
```
# BUMP LARAVEL MEP
.env => remplacer MAIL_DRIVER par MAIL_MAILER
.env => remplacer FILESYSTEM_DRIVER par FILESYSTEM_DISK
.env rajouter PROJECT_UUID=
.env rajouter MAIL_LIST_SERVICEWEB=digital@ldc.fr
# SUPERVISOR
jobs Api stats sur queue `database`
## Dans les LABs
```
MAIL_VERIFY_PEER=false
```

View file

@ -0,0 +1,225 @@
<?php
namespace App\Console\Commands\Api;
use App\Enums\Legacy\ApiError;
use App\Enums\Legacy\ApiStatus;
use App\Enums\MediaExtension;
use App\Exceptions\Api\ApiErrorException;
use App\Exceptions\Api\DamException;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Route;
use Symfony\Component\Process\Process;
/**
* @codeCoverageIgnore
*/
class GenerateApiClient extends Command
{
private const TARGET = 'clients/Api/src';
private const CLIENTNAMESPACE = 'LDC\\DAM\\Client';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'api:generate-client';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate the dam client in clients/Api folder';
/**
* Execute the console command.
*
* @return integer
*/
public function handle()
{
$this->copyEnums();
$this->copyExceptions();
$this->copyRoutesList();
$this->copyApiConfigInfo();
return 0;
}
/**
* Copy config files
*
* @return void
*/
private function copyApiConfigInfo()
{
$this->info('Copy Api Config');
$rootTarget = app_path('../' . self::TARGET);
if (File::exists("$rootTarget/../apiConfig.readonly.json")) {
File::delete("$rootTarget/../apiConfig.readonly.json");
}
File::put(
"$rootTarget/../apiConfig.readonly.json",
\json_encode(config('api'), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
);
$this->phpcbfFile("$rootTarget/../apiConfig.readonly.json");
}
/**
* Copy routes into a json file
*
* @return void
*/
private function copyRoutesList()
{
$this->info('Copy Routes');
$routes = [];
/** @var \Illuminate\Routing\Route */
foreach (Route::getRoutes() as $route) {
if (\strpos($route->getPrefix(), 'api') !== false) {
$routes[$route->getName()] = [
'uri' => $route->uri(),
'methods' => $route->methods()
];
}
}
$rootTarget = app_path('../' . self::TARGET);
if (File::exists("$rootTarget/routes.json")) {
File::delete("$rootTarget/routes.json");
}
File::put(
"$rootTarget/routes.json",
\json_encode($routes, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
);
$this->phpcbfFile("$rootTarget/routes.json");
}
/**
* Copy Exeption classes
*
* @return void
*/
private function copyExceptions(): void
{
$this->info('Copy Exceptions');
$rootTarget = app_path('../' . self::TARGET);
$this->copyToFolder([
DamException::class,
ApiErrorException::class
], 'Exceptions');
$this->replaceInPhpFile(
"$rootTarget/Exceptions/ApiErrorException.php",
ApiError::class,
self::CLIENTNAMESPACE . '\\Enums\\ApiError'
);
$this->replaceInPhpFile(
"$rootTarget/Exceptions/DamException.php",
DamException::class,
self::CLIENTNAMESPACE . '\\Exceptions\\DamException'
);
$this->replaceInPhpFile(
"$rootTarget/Exceptions/DamException.php",
ApiErrorException::class,
self::CLIENTNAMESPACE . '\\Exceptions\\ApiErrorException'
);
$this->phpcbfFile("$rootTarget/Exceptions/DamException.php");
$this->phpcbfFile("$rootTarget/Exceptions/ApiErrorException.php");
}
/**
* Copy enums classes
*
* @return void
*/
private function copyEnums(): void
{
$this->info('Copy Enums');
$classes = [
ApiError::class,
ApiStatus::class
];
$this->copyToFolder($classes, 'Enums');
$rootTarget = app_path('../' . self::TARGET);
foreach ($classes as $class) {
$classBasename = class_basename($class);
$dest = "$rootTarget/Enums/$classBasename.php";
$this->replaceInPhpFile($dest, 'BaseEnumRoutable', 'BaseEnum');
$this->replaceInPhpFile($dest, '\\Legacy', '');
$this->phpcbfFile($dest);
}
$mediaExtensionEnum = "<?php\n\nnamespace LDC\DAM\Client\Enums;\n\nuse Kwaadpepper\Enum\BaseEnum;\n\n/**\n";
foreach (MediaExtension::cases() as $strType) {
$mediaExtensionEnum .= " * @method static self {$strType->name}()\n";
}
// phpcs:ignore Generic.Files.LineLength.TooLong
$mediaExtensionEnum .= " *\n * @package DAMclient\n * @subpackage enums\n */\nclass MediaExtension extends BaseEnum\n{\n}\n";
File::put("$rootTarget/Enums/MediaExtension.php", $mediaExtensionEnum);
$this->phpcbfFile("$rootTarget/Enums/MediaExtensio.php");
}
/**
* Copy Classes to specified folder
*
* @param array $classes
* @param string $folder
* @return void
*/
private function copyToFolder(array $classes, string $folder): void
{
$rootTarget = app_path('../' . self::TARGET);
foreach ($classes as $class) {
$classFileName = \str_replace("App\\$folder\\", '', sprintf('%s.php', $class));
$classFileName = \str_replace('\\', '/', $classFileName);
$classBasename = class_basename($class);
$source = \app_path("$folder/$classFileName");
$dest = "$rootTarget/$folder/$classBasename.php";
if (File::exists($dest)) {
File::delete($dest);
}
File::copy($source, $dest);
$this->replaceInPhpFile($dest, 'namespace App', 'namespace ' . self::CLIENTNAMESPACE);
}
}
/**
* Replaces a specific string with another on a file
*
* @param string $source
* @param string $search
* @param string $replace
* @return void
*/
private function replaceInPhpFile(string $source, string $search, string $replace): void
{
$fContent = File::get($source);
// Remove trailing \Api .
$regex = '/namespace ([a-zA-Z0-9\\\\]+)\\\\Api;/m';
$fContent = preg_replace($regex, 'namespace $1;', $fContent);
// Replace namespace top level.
$pos = strpos($fContent, $search);
if ($pos !== false) {
File::put($source, \str_replace($search, $replace, $fContent));
}
}
/**
* Lint the file
*
* @param string $path
* @return void
* @throws \Symfony\Component\Process\Exception\RuntimeException If anything goes wrong.
* @throws \Symfony\Component\Process\Exception\ProcessTimedOutException If anything goes wrong.
* @throws \Symfony\Component\Process\Exception\ProcessSignaledException If anything goes wrong.
* @throws \Symfony\Component\Process\Exception\LogicException If anything goes wrong.
*/
private function phpcbfFile(string $path): void
{
$process = new Process(['./vendor/bin/phpcbf', $path]);
$process->run();
}
}

View file

@ -0,0 +1,184 @@
<?php
namespace App\Console\Commands\Api;
use App\Mail\Api\ApiTokenCreated;
use App\Mail\Api\ApiTokenRegenerated;
use App\Mail\Api\ApiTokenRemoved;
use App\Models\Api\ApiToken;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
class TokenCrud extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'api:token
{action? : Can be list, add, remove, regen, default is list}
{api_token? : Only if action is remove, pass the ID to remove}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Manage api tokens';
/**
* Execute the console command.
*
* @return inteager
*/
public function handle(): int
{
switch ($this->argument('action')) {
case null:
case 'list':
$this->table(['id', 'name', 'token_date'], ApiToken::all()->map(function (ApiToken $apiToken) {
return [
'id' => $apiToken->id,
'name' => $apiToken->name,
'token_date' => $apiToken->token_date,
];
}));
return 0;
case 'add':
return $this->createApiToken();
case 'remove':
return $this->removeApiToken();
case 'regen':
return $this->regenApiToken();
default:
$this->error(\sprintf(
'action \'%s\' is not availaible, use --help to see usage.',
$this->argument('action')
));
return -1;
} //end switch
}
/**
* Create api Token
*
* @return integer
*/
private function createApiToken(): int
{
return DB::transaction(function () {
$apiToken = new ApiToken();
do {
if (!($apiToken->name = $this->ask('Give your token a name'))) {
$this->warn('Please provide a valid name.');
}
} while (!$apiToken->name);
$publicToken = $apiToken->generatePublicToken();
$privateToken = $apiToken->generatePrivateToken();
if (
!$this->confirm(
"Are you should you want to create the following '{$apiToken->name}'"
)
) {
$this->info('Nothing was created.');
return 0;
}
$apiToken->saveOrFail();
Mail::send(new ApiTokenCreated($apiToken));
$this->alert("
Your new api Token for '{$apiToken->id}' named '{$apiToken->name}'
public: {$publicToken}
private: {$privateToken}
Please take note as it wont be available to display anymore !
");
return 0;
});
}
/**
* Remove Api token
*
* @return integer
*/
private function removeApiToken(): int
{
return DB::transaction(function () {
if (!\is_numeric($apiTokenId = $this->argument('api_token'))) {
$this->error('remove command needs an id, use `list` to see all.');
return -1;
}
/** @var \App\Models\Api\ApiToken|null */
if (!($apiToken = ApiToken::where('id', $apiTokenId)->first())) {
$this->error("api_token '{$apiTokenId}' was not found");
return -1;
}
if (
!$this->confirm(
"Are you sur you want to remove apiToken '{$apiToken->id}' '{$apiToken->name}' ?"
)
) {
$this->info('Nothing was deleted.');
return 0;
}
if (!$apiToken->deleteOrFail()) {
$this->error('removing apiToken failed');
}
Mail::send(new ApiTokenRemoved($apiToken));
$this->alert("apiToken '{$apiToken->id}' '{$apiToken->name}' has been removed !");
return 0;
});
}
/**
* Regenerate Api token
*
* @return integer
*/
private function regenApiToken(): int
{
return DB::transaction(function () {
if (!\is_numeric($apiTokenId = $this->argument('api_token'))) {
$this->error('remove command needs an id, use `list` to see all.');
return -1;
}
/** @var \App\Models\Api\ApiToken|null */
if (!($apiToken = ApiToken::where('id', $apiTokenId)->first())) {
$this->error("api_token '{$apiTokenId}' was not found");
return -1;
}
$publicToken = $apiToken->generatePublicToken();
$privateToken = $apiToken->generatePrivateToken();
if (
!$this->confirm(
"Are you sur you want to regen apiToken '{$apiToken->id}' '{$apiToken->name}' ?"
)
) {
$this->info('Nothing was done.');
return 0;
}
$apiToken->saveOrFail();
Mail::send(new ApiTokenRegenerated($apiToken));
$this->alert("
Your new api Token for '{$apiToken->id}' named '{$apiToken->name}'
public: {$publicToken}
private: {$privateToken}
Please take note as it wont be available to display anymore !
");
return 0;
});
}
}

View file

@ -19,7 +19,7 @@ class ArcadiaLinkCommand extends Command
*
* @var string
*/
protected $description = 'Lecture du flux Arcadia entrant (medias). Run the XmlArcadiaMediasIn manually';
protected $description = 'Lecture du flux Arcadia entrant (media). Run the XmlArcadiaMediasIn manually';
/**
* Execute the console command.
@ -34,7 +34,7 @@ class ArcadiaLinkCommand extends Command
$job->console = $this;
$job->handle();
$this->line("");
$this->newLine();
$this->info('Fin du traitement');
}
}

View file

@ -2,10 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use App\Models\Sujet;
use App\Models\Media;
use App\Models\Sujet;
use Illuminate\Console\Command;
class DeleteMediaArchive extends Command
{
@ -14,25 +13,16 @@ class DeleteMediaArchive extends Command
*
* @var string
*/
protected $signature = 'medias:deletearchive';
protected $signature = 'media:deletearchive';
/**
* The console command description.
*
* @var string
* @phpcs:disable Generic.Files.LineLength.TooLong
*/
protected $description = 'Suppression définitive de tous les médias (et leurs fichiers) qui ont été supprimés (en soft delete)';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
@ -40,60 +30,62 @@ class DeleteMediaArchive extends Command
*/
public function handle()
{
$this->info('Vous allez supprimer définitivement tous les médias (et leurs fichiers) qui ont été supprimés (en soft delete).');
//phpcs:ignore Generic.Files.LineLength.TooLong
$this->info('Vous allez supprimer définitivement tous les médias (et leurs fichiers) qui ont été supprimés (en soft delete).');
$choice = $this->choice('Etes-vous sûr de vouloir lancer ce traitement ?' , ['y', 'n'], 'y');
if (!$this->confirm('Etes-vous sûr de vouloir lancer ce traitement ?')) {
return 0;
}
if($choice != "y"){
$this->error('Choix incorrect');
die();
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$subjects = Sujet::where('sujet_dam', true)->get();
$sujets = Sujet::where('sujet_dam', 1)->get();
$this->newLine();
$this->line('Liste des sujets disponibles');
$this->line('----------------------------');
$this->line('[0] Tous les sujets');
foreach ($subjects as $subject) {
$this->line("[{$subject->codeSujet}] {$subject->libelle}");
}
$this->line("");
$this->line("Liste des sujets disponibles");
$this->line("----------------------------");
foreach ($sujets as $key => $sujet) {
$this->line("[".$sujet->codeSujet."] ". $sujet->libelle);
}
$this->line("[0] Tous les sujets");
$sujetId = $this->askWithCompletion(
'Pour quel sujet de média souhaitez vous executer le traitement ?',
$subjects->pluck('codeSujet')->toArray(),
0
);
$sujetId = $this->ask('Pour quel sujet de média souhaitez vous executer le traitement ?' );
$this->newLine();
if($sujetId == ""){
$this->error('Id de sujet incorrect');
die();
}
if ($sujetId != 0 and !$subjects->pluck('codeSujet')->contains(\intval($sujetId))) {
$this->error('Id de sujet incorrect');
return -1;
}
if($sujetId == 0){
$medias = Media::onlyTrashed()->with('Sujet.formats')->get();
}else{
$medias = Media::onlyTrashed()->where('sujet_id', $sujetId)->with('Sujet.formats')->get();
}
$sujetId = intval($sujetId);
if($medias->count() == 0){
$this->error('Aucun média a supprimer');
die();
}
$mediaCollection = Media::onlyTrashed()->with('sujet.formats');
if ($sujetId !== 0) {
$mediaCollection->where('sujet_id', $sujetId);
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
$mediaCollection = $mediaCollection->get();
$this->info($medias->count().' média(s) trouvé(s) - Début du traitement');
$bar = $this->output->createProgressBar(count($medias));
$bar->start();
if (!$mediaCollection->count()) {
$this->error('Aucun média a supprimer');
return -1;
}
foreach ($medias as $media) {
// supprime les fichiers médias stockés sur disque
$files = Storage::files($media->folder."/");
$filepath = preg_quote($media->folder.$media->uid, '/');
$matchingFiles = preg_grep('/^'.$filepath.'/', $files);
Storage::delete($matchingFiles);
// supprime le media en bdd
$media->forceDelete();
$bar->advance();
}
$this->info($mediaCollection->count() . ' média(s) trouvé(s) - Début du traitement');
$bar = $this->output->createProgressBar($mediaCollection->count());
$bar->start();
$bar->finish();
$this->line("");
$this->info('Fin du traitement');
foreach ($mediaCollection as $media) {
$media->prune();
$bar->advance();
}
$bar->finish();
$this->newLine();
$this->info('Fin du traitement');
}
}

View file

@ -1,233 +0,0 @@
<?php
namespace App\Console\Commands;
use App\Models\Societe;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;
use App\Models\Article;
use App\Models\Marque;
use App\Models\Sujet;
use App\Models\Typemedia;
use App\Models\Typevue;
use App\Models\Site;
use App\Models\Variante;
use App\Models\Media;
use App\Http\Traits\MediaTools;
class ImportArcadiaFiles extends Command
{
use MediaTools;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'arcadia:import';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import des fichiers xml Arcadia';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Démarrage du traitement');
$files = Storage::disk('arcadia')->files();
$bar = $this->output->createProgressBar(count($files)-1);
$bar->start();
// ---- Pour chaque fichier
foreach ($files as $filename) {
if($filename == ".gitignore") continue;
// ---- Récupération du contenu
$files = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($files);
// ---- traitement du fichier
if(substr($filename, 0, 11) == "DAM_ARTICLE"){
foreach ($fileContent->dam as $row) {
$record = Article::where('noArt', $row->noArt)->first();
if($record){ // Update record
$record->libCcial = $row->libCcial;
$record->codMarq = $row->codMarq;
$record->libMarq = $row->libMarq;
$record->codFamVte = $row->codFamVte;
$record->libFamVte = $row->libFamVte;
$record->codGencodAdm = $row->codGencodAdm;
$record->codGencodSymb = $row->codGencodSymb;
$record->codGencodPds = $row->codGencodPds;
$record->utilisableGroupe = $row->utilisableGroupe;
$record->save();
}else{ // Insert new record
$record = new Article();
$record->noArt = $row->noArt;
$record->libCcial = $row->libCcial;
$record->codMarq = $row->codMarq;
$record->libMarq = $row->libMarq;
$record->codFamVte = $row->codFamVte;
$record->libFamVte = $row->libFamVte;
$record->codGencodAdm = $row->codGencodAdm;
$record->codGencodSymb = $row->codGencodSymb;
$record->codGencodPds = $row->codGencodPds;
$record->utilisableGroupe = $row->utilisableGroupe;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 10) == "DAM_MARQUE") {
foreach ($fileContent->dam as $row) {
$record = Marque::where('codMarq', $row->codMarq)->first();
if($record){ // Update record
$record->libMarq = $row->libMarq;
$record->save();
}else{ // Insert new record
$record = new Marque();
$record->codMarq = $row->codMarq;
$record->libMarq = $row->libMarq;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 15) == "DAM_MEDIA_SUJET") {
foreach ($fileContent->mediaSujet as $row) {
$record = Sujet::where('codeSujet', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->save();
}else{ // Insert new record
$record = new Sujet();
$record->codeSujet = $row->code;
$record->libelle = $row->libelle;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 20) == "DAM_MEDIA_TYPE_MEDIA") {
foreach ($fileContent->mediatypemedia as $row) {
$record = Typemedia::where('codeTypemedia', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->save();
}else{ // Insert new record
$record = new Typemedia();
$record->codeTypemedia = $row->code;
$record->libelle = $row->libelle;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 17) == "DAM_MEDIA_TYPEVUE") {
foreach ($fileContent->mediatypesvue as $row) {
$record = Typevue::where('codeTypevue', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->mediasujet->code;
$record->save();
}else{ // Insert new record
$record = new Typevue();
$record->codeTypevue = $row->code;
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->mediasujet->code;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 18) == "DAM_MEDIA_VARIANTE") {
foreach ($fileContent->mediavariante as $row) {
$record = Variante::where('codeVariante', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->children()[0]->code;
$record->typevue_id = $row->CodeTypeVue->mediatypesvue->code;
$record->save();
}else{ // Insert new record
$record = new Variante();
$record->codeVariante = $row->code;
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->children()[0]->code;
$record->typevue_id = $row->CodeTypeVue->mediatypesvue->code;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 20) == "DAM_SITE_PROD_GROUPE") {
foreach ($fileContent->SITE_PROD_GRP as $row) {
$record = Site::where('id', $row->code)->first();
if($record){ // Update record
$record->libelle = $row->libelle;
$record->save();
}else{ // Insert new record
$record = new Site();
$record->id = $row->code;
$record->libelle = $row->libelle;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}elseif (substr($filename, 0, 11) == "DAM_SOCIETE") {
foreach ($fileContent->dam as $row) {
$record = Societe::where('id', $row->codSociete)->first();
if($record){ // Update record
$record->libelle = $row->nomSociete;
$record->save();
}else{ // Insert new record
$record = new Societe();
$record->id = $row->codSociete;
$record->libelle = $row->nomSociete;
$record->save();
}
}
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
$bar->advance();
}
$bar->finish();
$this->line("");
$this->info('Fin du traitement');
}
}

View file

@ -0,0 +1,317 @@
<?php
namespace App\Console\Commands;
use App\Traits\Http\HandlesMedia;
use App\Models\Article;
use App\Models\Marque;
use App\Models\Site;
use App\Models\Societe;
use App\Models\Sujet;
use App\Models\TypeMedia;
use App\Models\TypeVue;
use App\Models\Variante;
use Illuminate\Console\Command;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class ImportArcadiaModelFiles extends Command
{
use HandlesMedia;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'arcadia:import';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import des modèles xml Arcadia';
/**
* Execute the console command.
*
* @return mixed
* @throws \League\Flysystem\FileNotFoundException If a file could not be read.
* @throws \ErrorException If a xml file could not be parsed.
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function handle()
{
/** @var \Illuminate\Support\Collection<string> */
$files = collect(Storage::disk('arcadia')->files())
->filter(function (string $fileName) {
return !\in_array($fileName, ['.gitignore']);
});
if (!$files->count()) {
$this->info('Pas de nouveau fichiers');
return 0;
}
$this->info('Démarrage du traitement');
$bar = $this->output->createProgressBar($files->count() - 1);
$bar->start();
// ---- Pour chaque fichier
foreach ($files as $filename) {
// ---- Récupération du contenu
if (!($fileContent = Storage::disk('arcadia')->get($filename))) {
throw new FileNotFoundException($filename);
}
if (!($fileContent = simplexml_load_string($fileContent))) {
throw new \ErrorException("Could not parse $filename from arcadia storage.");
}
// ---- traitement du fichier
switch (true) {
case substr($filename, 0, 11) == 'DAM_ARTICLE':
$this->insertDamArticle($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 10) == 'DAM_MARQUE':
$this->insertDamMarque($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 15) == 'DAM_MEDIA_SUJET':
$this->insertDamMediaSujet($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 20) == 'DAM_MEDIA_TYPE_MEDIA':
$this->insertDamMediaTypeMedia($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 17) == 'DAM_MEDIA_TYPEVUE':
$this->insertDamMediaTypeVue($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 18) == 'DAM_MEDIA_VARIANTE':
$this->insertDamMediaVariante($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 20) == 'DAM_SITE_PROD_GROUPE':
$this->insertDamSiteProdGroupe($fileContent);
$this->deleteFile($filename);
break;
case substr($filename, 0, 11) == 'DAM_SOCIETE':
$this->insertDamSociete($fileContent);
$this->deleteFile($filename);
break;
default:
throw new \ErrorException("Unhandled file $filename");
} //end switch
$bar->advance();
} //end foreach
$bar->finish();
$this->newLine();
$this->info('Fin du traitement');
}
/**
* Update or Create Dam Article
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamArticle(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->dam as $row) {
/** @var \App\Models\Article|null $record */
$record = Article::where('noArt', $row->noArt)->first();
if (!$record) {
$record = new Article();
$record->noArt = $row->noArt;
}
$record->libCcial = $row->libCcial;
$record->codMarq = $row->codMarq;
$record->libMarq = $row->libMarq;
$record->codFamVte = $row->codFamVte;
$record->libFamVte = $row->libFamVte;
$record->codGencodAdm = $row->codGencodAdm;
$record->codGencodSymb = $row->codGencodSymb;
$record->codGencodPds = $row->codGencodPds;
$record->utilisableGroupe = $row->utilisableGroupe;
$record->saveOrFail();
} //end foreach
}
/**
* Update or Create Dam Marque
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMarque(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->dam as $row) {
/** @var \App\Models\Marque|null $record */
$record = Marque::where('codMarq', $row->codMarq)->first();
if (!$record) {
$record = new Marque();
$record->codMarq = $row->codMarq;
}
$record->libMarq = $row->libMarq;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Media Sujet
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMediaSujet(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->mediaSujet as $row) {
/** @var \App\Models\Sujet|null $record */
$record = Sujet::where('codeSujet', $row->code)->first();
if (!$record) {
$record = new Sujet();
$record->codeSujet = $row->code;
}
$record->libelle = $row->libelle;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Media Type Media
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMediaTypeMedia(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->mediatypemedia as $row) {
/** @var \App\Models\TypeMedia|null $record */
$record = TypeMedia::where('codeTypemedia', $row->code)->first();
if (!$record) {
$record = new TypeMedia();
$record->codeTypemedia = $row->code;
}
$record->libelle = $row->libelle;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Media Type Vue
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMediaTypeVue(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->mediatypesvue as $row) {
/** @var \App\Models\TypeVue|null $record */
$record = TypeVue::where('codeTypevue', $row->code)->first();
if (!$record) {
$record = new TypeVue();
$record->codeTypevue = $row->code;
}
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->mediasujet->code;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Media Variante
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamMediaVariante(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->mediavariante as $row) {
/** @var \App\Models\TypeVue|null $record */
$record = Variante::where('codeVariante', $row->code)->first();
if (!$record) {
$record = new Variante();
$record->codeVariante = $row->code;
}
$record->libelle = $row->libelle;
$record->sujet_id = $row->sujet_id->children()[0]->code;
$record->type_vue_id = $row->CodeTypeVue->mediatypesvue->code;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Site Prod Groupe
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamSiteProdGroupe(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->SITE_PROD_GRP as $row) {
/** @var \App\Models\TypeVue|null $record */
$record = Site::where('id', $row->code)->first();
if (!$record) {
$record = new Site();
$record->id = $row->code;
}
$record->libelle = $row->libelle;
$record->saveOrFail();
}
}
/**
* Update or Create Dam Societe
*
* @param \SimpleXMLElement $fileContent
* @return void
* @throws \Throwable On save failure.
*/
private function insertDamSociete(\SimpleXMLElement $fileContent)
{
/** @var \SimpleXMLElement $row */
foreach ($fileContent->dam as $row) {
/** @var \App\Models\TypeVue|null $record */
$record = Societe::where('id', $row->codSociete)->first();
if (!$record) {
$record = new Societe();
$record->id = $row->codSociete;
}
$record->libelle = $row->nomSociete;
$record->saveOrFail();
}
}
/**
* Delete file
*
* @param string $filename
* @return void
*/
private function deleteFile(string $filename)
{
if (!Storage::disk('arcadia')->delete($filename)) {
Log::warning("Could not delete $filename from arcadia storage.");
}
}
}

View file

@ -1,299 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;
use App\Http\Traits\MediaTools;
use App\Models\Article;
use App\Models\Marque;
use App\Models\Media;
use App\Models\Dossier;
class ImportMedia extends Command
{
use MediaTools;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:import';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import des fichiers xml Média Visuel Arcadia';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Démarrage du traitement');
$files = File::glob(storage_path('export_arcadia') . "/DAM_MEDIA_VISUEL_*.*");
$this->line("-> Import du fichier DAM_MEDIA_VISUEL");
// ---- Traitement de l'import des XML Visuel
foreach ($files as $filename) {
$path = explode("/", $filename);
$filename = $path[count($path) - 1];
// ---- Récupération du contenu
$oneFile = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($oneFile);
// ---- traitement du fichier
$bar = $this->output->createProgressBar(count($fileContent->MEDIA_VISUEL)-1);
$bar->start();
foreach ($fileContent->MEDIA_VISUEL as $row) {
$record = Media::where('arcadia_id', $row->code)->first();
if (!$record) { // Insert new record
$record = new Media();
$record->arcadia_id = $row->code;
if ($row->extension != "") {
$record->extension = $row->extension->typeFichier->libExtension;
}
$record->libelle = $row->libelle;
$record->largeur = $row->nbPxLargeur;
$record->largeur_mm = $row->largeurMm;
$record->hauteur = $row->nbPxHauteur;
$record->hauteur_mm = $row->hauteurMm;
$record->resolution = $row->pppLargeur;
if ($row->version != "") {
$record->version = $row->version;
} else {
$record->version = 1;
}
if ($row->codeTypeMedia != "") {
$record->typemedia_id = $row->codeTypeMedia;
} else {
$record->typemedia_id = 1;
}
if ($row->codeTypeVue != "") {
$record->typevue_id = $row->codeTypeVue;
}
$record->commentaire = $row->commentaire;
$record->sujet_id = $row->codeSujet;
if ($row->langue != "") {
$record->langue_id = $row->langue;
}
if ($row->copyright != "") {
$record->copyright_id = $row->copyright;
}else{
$record->copyright_id = 3;
}
if ($row->codeVariante != "") {
$record->variante_id = $row->codeVariante;
}
if ($row->dateCreation != "") {
$row->dateCreation = substr($row->dateCreation, 0, 10);
$date = explode("/", $row->dateCreation);
$record->created_at = $date[2] . '-' . $date[1] . '-' . $date[0];
}
if ($row->dateModification != "") {
$row->dateModification = substr($row->dateModification, 0, 10);
$date = explode("/", $row->dateModification);
$record->updated_at = $date[2] . '-' . $date[1] . '-' . $date[0];
}
if ($row->datePublication != "") {
$row->datePublication = substr($row->datePublication, 0, 10);
$date = explode("/", $row->datePublication);
$record->published_at = $date[2] . '-' . $date[1] . '-' . $date[0];
}
$record->statut = config('services.statut.public_etendu');
// Affectation d'un dossier et d'un uid
$destinationPath = $this->get_mediaFolder() . "/";
$record->folder = $destinationPath;
$record->uid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$mediaFile = "/images/" . $record->arcadia_id . "." . $record->extension;
$fileExists = Storage::disk('arcadia')->exists($mediaFile);
if ($fileExists) {
// déplacement du média et renommage du fichier
$file = Storage::disk('arcadia')->get($mediaFile);
$full_path_source = Storage::disk('arcadia')->getDriver()->getAdapter()->applyPathPrefix($mediaFile);
$full_path_dest = Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix($destinationPath . $record->uid . '.' . $record->extension);
File::move($full_path_source, $full_path_dest);
// calcul de la taille du média
$record->taille = $this->formatBytes($this->get_file_size($full_path_dest));
} else {
// on applique une image par défaut
$record->extension = "jpg";
Storage::disk('local')->copy("assets/images/default.jpg", $destinationPath . $record->uid . '.' . $record->extension);
// calcul de la taille du média
$record->taille = $this->formatBytes($this->get_file_size("public/" . $destinationPath . $record->uid . '.' . $record->extension));
}
$record->save();
// ---- Creation des vignettes de base
$this->create_sys_thumb($record);
// ---- Creation des vignettes en lien avec le sujet du média
$this->create_thumb($record);
} else {
$this->line("\nDAM_MEDIA_VISUEL : le media n°" . $row->code . " existe déjà en base");
}
$bar->advance();
}
$bar->finish();
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
// ---- Traitement de l'association media <-> article
$files = File::glob(storage_path('export_arcadia') . "/DAM_ASSO_ARTICLE_*.*");
$this->line("-> Import du fichier DAM_ASSO_ARTICLE");
foreach ($files as $filename) {
$path = explode("/", $filename);
$filename = $path[count($path) - 1];
// ---- Récupération du contenu
$oneFile = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($oneFile);
// ---- traitement du fichier
$bar = $this->output->createProgressBar(count($fileContent->mediaassoarticle)-1);
$bar->start();
foreach ($fileContent->mediaassoarticle as $row) {
$record = Media::where('arcadia_id', $row->codeVisuel)->first();
if ($record) {
$article = Article::where('noArt', $row->noArt)->first();
if ($article) {
// attache l'article au média
$record->articles()->syncWithoutDetaching($article->id);
// recherche un dossier lié à la marque de l'article
$marque_id = $article->codMarq;
$dossier = Dossier::whereHas("marques", function ($query) use ($marque_id) {
$query->where("codMarq", $marque_id);
})->first();
if ($dossier) {
// attache le dossier marque au Média
$record->dossier_id = $dossier->id;
$record->save();
$this->line("Liason media n°" . $row->codeVisuel . " à la marque n°" . $article->libMarq);
} else {
$marque = Marque::where('codMarq', '=', $marque_id)->first();
// On cree le dossier
$dossier = new Dossier();
$dossier->libelle = $marque->libMarq;
$dossier->sujet_id = 1;
$dossier->system = 0;
$dossier->save();
$dossier->marques()->syncWithoutDetaching($marque_id);
$dossier->save();
$record->dossier_id = $dossier->id;
$record->save();
//$this->line("Liason media n°" . $row->codeVisuel . " à la marque n°" . $article->libMarq);
}
} else {
$this->line("\nDAM_ASSO_ARTICLE : le media n°" . $row->codeVisuel . " ne peut être lié à l'article n°" . $row->noArt);
}
} else {
$this->line("\nDAM_ASSO_ARTICLE : le media n°" . $row->codeVisuel . " n'existe pas");
}
$bar->advance();
}
$bar->finish();
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
// ---- Traitement de l'association media <-> marque
$files = File::glob(storage_path('export_arcadia') . "/DAM_ASSO_MARQUE_*.*");
$this->line("-> Import du fichier DAM_ASSO_MARQUE");
foreach ($files as $filename) {
$path = explode("/", $filename);
$filename = $path[count($path) - 1];
// ---- Récupération du contenu
$oneFile = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($oneFile);
// ---- traitement du fichier
$bar = $this->output->createProgressBar(count($fileContent->mediaassomarque)-1);
$bar->start();
foreach ($fileContent->mediaassomarque as $row) {
$record = Media::where('arcadia_id', $row->codeVisuel)->first();
if ($record) {
if ($record->marques->contains($row->codMarq)){
$this->line("\nDAM_ASSO_MARQUE : le media n°" . $row->codeVisuel . " est déjà associé à cette marque.");
}else{
// attache la marque au média
$record->marques()->attach($row->codMarq);
}
} else {
$this->line("\nDAM_ASSO_MARQUE : le media n°" . $row->codeVisuel . " n'existe pas");
}
$bar->advance();
}
$bar->finish();
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
// ---- Traitement de l'association media <-> societe
$files = File::glob(storage_path('export_arcadia') . "/DAM_ASSO_SOCIETE_*.*");
$this->line("-> Import du fichier DAM_ASSO_SOCIETE");
foreach ($files as $filename) {
$path = explode("/", $filename);
$filename = $path[count($path) - 1];
// ---- Récupération du contenu
$oneFile = Storage::disk('arcadia')->get($filename);
$fileContent = simplexml_load_string($oneFile);
// ---- traitement du fichier
$bar = $this->output->createProgressBar(count($fileContent->mediaassosociete)-1);
$bar->start();
foreach ($fileContent->mediaassosociete as $row) {
$record = Media::where('arcadia_id', $row->codeVisuel)->first();
if ($record) {
// attache la societe au média
$record->societes()->attach($row->codSociete);
} else {
$this->line("\nDAM_ASSO_SOCIETE : le media n°" . $row->codeVisuel . " n'existe pas");
}
$bar->advance();
}
$bar->finish();
// ---- Suppression du fichier
Storage::disk('arcadia')->delete($filename);
}
$this->line("");
$this->info('Fin du traitement');
}
}

View file

@ -1,85 +0,0 @@
<?php
/*
* Command Name: LDC Web Status Checker
* Description: Envoi des infos Serveur/Laravel vers LDC Web
* Version: 1.0
* Author: Vincent BRIDIER
* Author URI: vincent.bridier@ldc.fr
*/
namespace App\Console\Commands;
use Illuminate\Console\Command;
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';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$data = [];
$data['uuid'] = env('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);
$result = curl_exec($ch);
curl_close($ch);
}
}

View file

@ -2,24 +2,18 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use App\Models\Sujet;
use App\Models\Format;
use App\Models\Media;
use App\Http\Traits\MediaTools;
use App\Models\Sujet;
use Illuminate\Console\Command;
class RegenerateThumbnails extends Command
{
use MediaTools;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:regenerate';
protected $signature = 'media:regenerate';
/**
* The console command description.
@ -28,16 +22,6 @@ class RegenerateThumbnails extends Command
*/
protected $description = 'Regénération de toutes les vignettes des médias';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
@ -45,50 +29,63 @@ class RegenerateThumbnails extends Command
*/
public function handle()
{
$this->info('Vous allez regénérer toutes les miniatures des médias.');
$this->info('Vous allez regénérer toutes les miniatures des médias.');
$sujets = Sujet::where('sujet_dam', 1)->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$subjects = Sujet::where('sujet_dam', true)->get();
$this->line("");
$this->line("Liste des sujets disponibles");
$this->line("----------------------------");
foreach ($sujets as $key => $sujet) {
$this->line("[".$sujet->codeSujet."] ". $sujet->libelle);
}
$this->line("[0] Tous les sujets");
$this->newLine();
$this->line('Liste des sujets disponibles');
$this->line('----------------------------');
$this->line('[0] Tous les sujets');
foreach ($subjects as $subject) {
$this->line("[{$subject->codeSujet}] {$subject->libelle}");
}
$sujetId = $this->ask('Pour quel sujet de média souhaitez vous executer le traitement ?' );
$sujetId = $this->askWithCompletion(
'Pour quel sujet de média souhaitez vous executer le traitement ?',
$subjects->pluck('codeSujet')->toArray(),
0
);
if($sujetId == ""){
$this->error('Id de sujet incorrect');
die();
}
if ($sujetId != 0 and !$subjects->pluck('codeSujet')->contains(\intval($sujetId))) {
$this->error('Id de sujet incorrect');
return -1;
}
if($sujetId == 0){
$medias = Media::where('typemedia_id', 1)->with('Sujet.formats')->get();
}else{
$medias = Media::where('sujet_id', $sujetId)->where('typemedia_id', 1)->with('Sujet.formats')->get();
}
$sujetId = intval($sujetId);
if($medias->count() == 0){
$this->error('Aucun média n\'a été trouvé');
die();
}
$mediaCollection = Media::onlyTrashed()->with('sujet.formats');
if ($sujetId !== 0) {
$mediaCollection->where('sujet_id', $sujetId);
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
$mediaCollection = $mediaCollection->get();
$this->info($medias->count().' média(s) trouvé(s) - Début du traitement');
$bar = $this->output->createProgressBar(count($medias));
$bar->start();
if (!$mediaCollection->count()) {
$this->error('Aucun média n\'a été trouvé');
return -1;
}
foreach ($medias as $media) {
// ---- Creation des vignettes de base
$this->create_sys_thumb($media);
// ---- Creation des vignettes en lien avec le sujet du média
$this->create_thumb($media);
$bar->advance();
}
$this->info($mediaCollection->count() . ' média(s) trouvé(s) - Début du traitement');
$bar = $this->output->createProgressBar($mediaCollection->count());
$bar->start();
$bar->finish();
$this->line("");
$this->info('Fin du traitement');
/** @var \App\Models\Media $media */
foreach ($mediaCollection as $media) {
try {
// ---- Creation des vignettes de base
$media->createThumbnail();
// ---- Creation des vignettes en lien avec le sujet du média
$media->createSubjectThumbnails();
} catch (\ImagickException | \RuntimeException $e) {
report($e);
}
$bar->advance();
}
$bar->finish();
$this->newLine();
$this->info('Fin du traitement');
}
}

View file

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Media;
use Illuminate\Console\Command;
class ReindexElasticMedia extends Command
{
@ -12,7 +12,7 @@ class ReindexElasticMedia extends Command
*
* @var string
*/
protected $signature = 'medias:reindex';
protected $signature = 'media:reindex';
/**
* The console command description.
@ -29,39 +29,48 @@ class ReindexElasticMedia extends Command
public function handle()
{
$this->info('Reindexation de la base médias dans Elasticsearch...');
$this->info('Test Présence...');
$this->info('ES: Test présence index...');
if (Media::indexExists()) {
$this->info('Suppression index...');
$this->info('ES: Suppression index...');
Media::deleteIndex();
}
$this->info('Création...');
$this->info('ES: Création index...');
Media::createIndex();
$pageNumber = 0;
$perPage = 200;
/** @var \Illuminate\Pagination\LengthAwarePaginator $medias */
$medias = Media::paginate($perPage);
$bar = $this->output->createProgressBar(count($medias));
/** @var \Illuminate\Pagination\LengthAwarePaginator $mediaCollection */
$mediaCollection = Media::paginate($perPage);
$bar->start($medias->total());
if (!$mediaCollection->total()) {
$this->info('Pas de medias');
}
$bar = $this->output->createProgressBar(count($mediaCollection));
$bar->start($mediaCollection->total());
// * LOOP
do {
if ($pageNumber > 0) {
/** @var \Illuminate\Pagination\LengthAwarePaginator $medias */
$medias = Media::paginate($perPage, ['*'], 'page', $pageNumber);
/** @var \Illuminate\Pagination\LengthAwarePaginator $mediaCollection */
$mediaCollection = Media::paginate($perPage, ['*'], 'page', $pageNumber);
}
foreach ($medias as $media) {
$media->addToIndex();
/** @var \App\Models\Media $media */
foreach ($mediaCollection->getCollection() as $media) {
/** @throws \RuntimeException */
$media->addToElasticSearch();
$bar->advance();
}
++$pageNumber;
} while ($medias->hasMorePages());
} while ($mediaCollection->hasMorePages());
$bar->finish();
$this->line('');
$this->newLine();
$this->info('Fin du traitement');
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace App\Console\Commands;
use App\Models\Media;
use Illuminate\Console\Command;
class ReindexElasticOneMedia extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'media:reindexone {media_id}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$mediaID = \strval($this->argument('media_id'));
$this->info("Reindexation du media $mediaID dans Elasticsearch...");
/** @var \App\Models\Media */
if (!($media = Media::withTrashed()->find($this->argument('media_id')))) {
$this->info("Pas de media $mediaID");
}
/** @throws \RuntimeException */
$media->addToElasticSearch();
$this->info("Media ID '$mediaID' Ajouté");
}
}

View file

@ -12,7 +12,7 @@ class SendMediasModificationsReport extends Command
*
* @var string
*/
protected $signature = 'medias:sendreport';
protected $signature = 'media:sendreport';
/**
* The console command description.
@ -21,16 +21,6 @@ class SendMediasModificationsReport extends Command
*/
protected $description = 'Run the SendMediasModificationsReport Manually';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
@ -39,7 +29,7 @@ class SendMediasModificationsReport extends Command
public function handle()
{
$this->info('Running the Job, this could take some time.');
$job = new JobsSendMediasModificationsReport();
$job = new JobsSendMediasModificationsReport();
$job->console = $this;
$job->handle();
$this->info('Job completed');

View file

@ -1,49 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Media;
class reindexElasticOneMedia extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:reindexone {media_id}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Reindexation du media '.$this->argument('media_id').' dans Elasticsearch...');
$media = Media::withTrashed()->find($this->argument('media_id'));
$esExist = Media::searchByQuery(array('match' => array('arcadia_id' => "$media->arcadia_id")));
if ($esExist->totalHits() > 0) {
$media->removeFromIndex();
}
$media->addToIndex();
}
}

View file

@ -2,22 +2,12 @@
namespace App\Console;
use App\Console\Commands\ArcadiaLinkCommand;
use App\Jobs\Arcadia\XmlArcadiaMediasIn;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
ArcadiaLinkCommand::class
];
/**
* Define the application's command schedule.
*
@ -26,8 +16,10 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
$schedule->job(XmlArcadiaMediasIn::class)->name('arcadia_medias_in')
$schedule->job(XmlArcadiaMediasIn::class)->name('Import Arcadia Media Files')
->onOneServer()->cron('*/2 * * * *');
$schedule->command('arcadia:import')->name('Import Arcadia XML Models')
->onOneServer()->cron('*/30 * * * *');
}
/**

23
app/Enums/ContactType.php Normal file
View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums;
enum ContactType: int
{
case bug = 1;
case evolution = 2;
/**
* Get num label
*
* @return string
*/
public function label(): string
{
return match ($this) {
static::bug => trans('Signaler un bug'),
static::evolution => trans('Proposer une amélioration'),
default => trans('MISSING LABEL')
};
}
}

View file

@ -0,0 +1,11 @@
<?php
namespace App\Enums;
enum EdiMouvementType: string
{
case create = 'C';
case update = 'M';
case delete = 'S';
case reactivate = 'R';
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\Enums;
enum EventHistoryType: int
{
case created = 0;
case moved = 1;
case changed = 2;
case destroyed = 3;
case labelled = 4;
/**
* Get num label
*
* @return string
*/
public function label(): string
{
return match ($this) {
static::created => trans('Création'),
static::moved => trans('Déplacement'),
static::changed => trans('Modification'),
static::destroyed => trans('Suppression'),
static::labelled => trans('Etiquette'),
default => trans('MISSING LABEL')
};
}
}

View file

@ -0,0 +1,93 @@
<?php
namespace App\Enums\Legacy;
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 authFailed()
* The authentification for this customer failed because of wrong 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
*
* @package DAMclient
* @subpackage enums
*
* TODO: pass this as php8 enum, when support of 7 will be dropped.
*/
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,
'authFailed' => 117,
'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',
'authFailed' => 'Echec de l\'authentification du compte',
'apiAuthFailed' => 'Echec de l\'authentification client à l\'Api DAM',
'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'
];
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace App\Enums\Legacy;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self OK()
* @method static self KO()
*
* @package DAMclient
* @subpackage enums
*
* TODO: pass this as php8 enum, when support of 7 will be dropped.
*/
class ApiStatus extends BaseEnumRoutable
{
}

View file

@ -2,16 +2,12 @@
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self debug()
* @method static self log()
* @method static self warning()
* @method static self info()
* @method static self error()
* @method static self critical()
*/
final class LogType extends BaseEnumRoutable
enum LogType: int
{
case debug = 0;
case log = 1;
case warning = 2;
case info = 3;
case error = 4;
case critical = 5;
}

View file

@ -0,0 +1,17 @@
<?php
namespace App\Enums;
enum MediaExtension: string
{
case ai = 'ai';
case gif = 'gif';
case jpeg = 'jpeg';
case jpg = 'jpg';
case mp4 = 'mp4';
case mp3 = 'mp3';
case pdf = 'pdf';
case png = 'png';
case psd = 'psd';
case svg = 'svg';
}

10
app/Enums/MediaStatut.php Normal file
View file

@ -0,0 +1,10 @@
<?php
namespace App\Enums;
enum MediaStatut: int
{
case brouillon = 0;
case public = 1;
case public_etendu = 2;
}

View file

@ -0,0 +1,103 @@
<?php
namespace App\Events;
use App\Models\Etiquette;
use App\Models\Media;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MediaChangedLabel extends MediaCreated
{
use Dispatchable;
use SerializesModels;
/**
* The user who created the media
*
* @var \App\Models\User
*/
private $user;
/**
* The media
*
* @var \App\Models\Media
*/
private $media;
/**
* The oldLabel
*
* @var \App\Models\Etiquette|null
*/
private $oldLabel;
/**
* The newLabel
*
* @var \App\Models\Etiquette|null
*/
private $newLabel;
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @param \App\Models\Media $media
* @param \App\Models\Etiquette|null $oldLabel
* @param \App\Models\Etiquette|null $newLabel
*/
public function __construct(
User $user,
Media $media,
Etiquette $oldLabel,
Etiquette $newLabel,
) {
$this->user = $user;
$this->media = $media;
$this->oldLabel = $oldLabel;
$this->newLabel = $newLabel;
}
/**
* Get User who triggered the event
*
* @return \App\Models\User
*/
public function getUser(): User
{
return $this->user;
}
/**
* Get the media
*
* @return \App\Models\Media
*/
public function getMedia(): Media
{
return $this->media;
}
/**
* Get the oldLabel
*
* @return \App\Models\Etiquette|null
*/
public function getOldLabel(): Etiquette|null
{
return $this->oldLabel;
}
/**
* Get the newLabel
*
* @return \App\Models\Etiquette|null
*/
public function getNewLabel(): Etiquette|null
{
return $this->newLabel;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Events;
use App\Models\Media;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MediaCreated
{
use Dispatchable;
use SerializesModels;
/**
* The user who created the media
*
* @var \App\Models\User
*/
private $user;
/**
* The media
*
* @var \App\Models\Media
*/
private $media;
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @param \App\Models\Media $media
*/
public function __construct(User $user, Media $media)
{
$this->user = $user;
$this->media = $media;
}
/**
* Get User who triggered the event
*
* @return \App\Models\User
*/
public function getUser(): User
{
return $this->user;
}
/**
* Get the media
*
* @return \App\Models\Media
*/
public function getMedia(): Media
{
return $this->media;
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Events;
class MediaDestroyed extends MediaCreated
{
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Events;
use App\Models\Media;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MediaLinkWithArcadia
{
use Dispatchable;
use SerializesModels;
/**
* The user who created the media
*
* @var \App\Models\User
*/
private $user;
/**
* The media
*
* @var \App\Models\Media
*/
private $media;
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @param \App\Models\Media $media
*/
public function __construct(User $user, Media $media)
{
$this->user = $user;
$this->media = $media;
}
/**
* Get User who triggered the event
*
* @return \App\Models\User
*/
public function getUser(): User
{
return $this->user;
}
/**
* Get the media
*
* @return \App\Models\Media
*/
public function getMedia(): Media
{
return $this->media;
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Events;
class MediaMoved extends MediaCreated
{
}

View file

@ -0,0 +1,122 @@
<?php
namespace App\Events;
use App\Models\Sujet;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MediaSearched
{
use Dispatchable;
use SerializesModels;
/**
* The user who created the media
*
* @var \App\Models\User
*/
private $user;
/**
* The sujet
*
* @var \App\Models\Sujet
*/
private $sujet;
/**
* The searchString
*
* @var string
*/
private $searchString;
/**
* The filters
*
* @var object
*/
private $filters;
/**
* The dossier_id
*
* @var integer
*/
private $dossier_id;
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @param \App\Models\Sujet $sujet
* @param string $searchString
* @param object $filters
* @param integer $dossier_id
*/
public function __construct(
User $user,
Sujet $sujet,
string $searchString,
object $filters,
int $dossier_id
) {
$this->user = $user;
$this->sujet = $sujet;
$this->searchString = $searchString;
$this->filters = $filters;
$this->dossier_id = $dossier_id;
}
/**
* Get User who triggered the event
*
* @return \App\Models\User
*/
public function getUser(): User
{
return $this->user;
}
/**
* Get the sujet
*
* @return \App\Models\Sujet
*/
public function getSujet(): Sujet
{
return $this->sujet;
}
/**
* Get the searchString
*
* @return string
*/
public function getSearchString(): string
{
return $this->searchString;
}
/**
* Get the filters
*
* @return string
*/
public function getFilters(): object
{
return $this->filters;
}
/**
* Get the dossier_id
*
* @return integer
*/
public function getDossierId(): int
{
return $this->dossier_id;
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Events;
class MediaUpdated extends MediaCreated
{
}

View file

@ -2,8 +2,6 @@
namespace App\Exceptions;
use ErrorException;
class AbortXmlImportException extends ErrorException
class AbortXmlImportException extends \RuntimeException
{
}

View file

@ -0,0 +1,102 @@
<?php
namespace App\Exceptions\Api;
use App\Enums\Legacy\ApiError;
use Illuminate\Support\Facades\Log;
/**
* This would be thrown if any of the case
* referenced in \App\Enums\ApiError would
* occur within the dam
*
* On the client an ApiErrorException would
* also be throw with the ApiError corresponding to
* the situation
*
* @package DAMclient
* @subpackage exceptions
*/
class ApiErrorException extends \RuntimeException
{
/**
* 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 dam.
*
* @var \App\Enums\Legacy\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 dam.
* 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 \App\Enums\Legacy\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 \App\Enums\Legacy\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('DAM API: %s', $this->getMessage()));
// @codeCoverageIgnoreEnd
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace App\Exceptions\Api;
/**
* Unhandled error that occus within DAM.
*/
class DamException extends \RuntimeException
{
}

View file

@ -2,8 +2,6 @@
namespace App\Exceptions;
use ErrorException;
class ElasticSearchException extends ErrorException
class ElasticSearchException extends \RuntimeException
{
}

View file

@ -2,50 +2,183 @@
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use App\Enums\Legacy\ApiError;
use App\Enums\Legacy\ApiStatus;
use App\Exceptions\Api\ApiErrorException;
use App\Http\Resources\Api\ApiResponse as 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
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [
ApiErrorException::class => \Psr\Log\LogLevel::WARNING
];
/**
* A list of the exception types that are not reported.
*
* @var array
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
//
ApiErrorException::class,
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Report or log an exception.
* Register the exception handling callbacks for the application.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
public function register()
{
parent::report($exception);
$this->reportable(function (Throwable $e) {
});
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
* @param mixed $request
* @param \Throwable $e
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Throwable If needed.
*/
public function render($request, Exception $exception)
public function render(mixed $request, Throwable $e)
{
return parent::render($request, $exception);
if (Helper::isRequestForApi($request) and $request->isJson()) {
return $this->handleApiException($request, $e);
} //end if
// @codeCoverageIgnoreStart
return parent::render($request, $e);
// @codeCoverageIgnoreEnd
}
/**
* Generate a json response for any api error case
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $e
* @return \Illuminate\Http\JsonResponse
*/
private function handleApiException(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('\\', (string)$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, intval($e->getCode()), $e->getMessage());
// @codeCoverageIgnoreEnd
}
/**
* Generate an Api json response
*
* @param \Illuminate\Http\Request $request
* @param integer $httpCode
* @param integer $apiCode
* @param string $message
* @param array $data
* @return \Illuminate\Http\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);
}
}

View file

@ -2,8 +2,6 @@
namespace App\Exceptions;
use ErrorException;
class InvalidXmlException extends ErrorException
class InvalidXmlException extends \ErrorException
{
}

View file

@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers\Api;
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();
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace App\Http\Controllers\Api;
use App\Enums\MediaStatut;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\MediaListResource;
use App\Http\Resources\Api\MediaPictureResource;
use App\Http\Resources\Api\MediaResource;
use App\Models\Article;
use App\Models\Media;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection as JsonResourceCollection;
use Illuminate\Support\Facades\DB;
class MediaController extends Controller
{
/**
* Show specific media
*
* @param \App\Models\Media $media
* @return \Illuminate\Http\Resources\Json\JsonResource
*/
public function show(Media $media): JsonResource
{
return new MediaResource($media);
}
/**
* Get Media list of the latest version for each vue type and variant
* of media that is linked with an article.
*
* Working example
* SELECT `mediaList`.`id`,`mediaList`.`arcadia_id`,`mediaList`.`libelle`,`mediaList`.`uid`,
* `mediaList`.`version`,`mediaList`.`type_vue_id`,`mediaList`.`variante_id`,`mediaList`.`created_at`,`mediaList`.`updated_at`
* FROM (
* SELECT `media`.*
* from `media`
* JOIN `media_article` ON `media_article`.`media_id` =`media`.`id`
* JOIN `articles` ON `articles`.`id` =`media_article`.`article_id` AND `articles`.`noArt` = 2842
* WHERE
* `media`.type_media_id IN (1,5) AND
* `media`.isLocked = 0 AND
* `media`.statut != 0
* ORDER BY `version` DESC
* LIMIT 18446744073709551615
* ) AS mediaList
* GROUP BY `type_vue_id`,`variante_id`
*
* @param \App\Models\Article $article
* @return \Illuminate\Http\Resources\Json\ResourceCollection
*/
public function getMediaListByArticle(Article $article): JsonResourceCollection
{
// ! Hack to allow group by (may have side effects)
DB::statement("SET SQL_MODE=''");
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
$mediaList = Media::cacheForever()->withTrashed()->fromSub(
Media::query()->whereHas('articles', function ($q) use ($article) {
$q->where('noArt', $article->noArt);
})->whereHas('typeMedia', function ($q) {
$q->whereIn('libelle', ['Photo', 'jpeg']);
})->where('isLocked', false)
->where('statut', '!=', MediaStatut::brouillon)
->orderBy('version', 'DESC')
// ! Maria Hack: use limit to preserve order.
->limit(\PHP_INT_MAX),
'mediaList'
)->groupBy(['mediaList.type_vue_id', 'mediaList.variante_id'])
->paginate();
return new MediaListResource($mediaList, true);
}
/**
* Get Media picture resource
*
* @param \App\Models\Media $media
* @return \Illuminate\Http\Resources\Json\JsonResource
*/
public function getMediaPicture(Media $media): JsonResource
{
return new MediaPictureResource($media);
}
}

View file

@ -3,25 +3,46 @@
namespace App\Http\Controllers;
use App\Models\ArcadiaLink;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Contracts\Database\Eloquent\Builder;
class ArcadiaLinkController extends Controller
{
public function index(Request $request)
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$dt = Carbon::now('Europe/Paris')->subMinutes(15)->toDateTimeString();
$ano = ArcadiaLink::where('created_at', '<', $dt)->orderBy('id', 'DESC')->get();
return view('arcadialink.index', ['ano' => $ano]);
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
// * ArcadiaLink->Media is nullable
$arcadiaLinkList = ArcadiaLink::query()
->with('media', fn (Builder $q) => $q->withTrashed())
->where('created_at', '<', now()->subMinutes(15))
->orderBy('id', 'DESC')->get();
return view('arcadialinks.index', compact('arcadiaLinkList'));
}
public function delete(Request $request)
/**
* Remove the specified resource from storage.
*
* @param \App\Models\ArcadiaLink $arcadia_link
* @return \Illuminate\Http\Response
*/
public function delete(ArcadiaLink $arcadia_link)
{
$id = $request->id;
$a = ArcadiaLink::find($id);
$a->delete();
return redirect()->route('arcadialink.index');
if ($arcadia_link->deleteOrFail()) {
return redirect()
->route('arcadialinks.index')
->with('warning', trans(
':model a bien été supprimé',
['model' => trans('ArcadiaLink')]
));
}
return back();
}
}

View file

@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\Bo\Ajax\GetArticleRequest;
use App\Models\Article;
use Illuminate\Http\JsonResponse;
class ArticleController
{
/**
* Renvoie un article par ID Arcadia
* @param \App\Http\Requests\Bo\Ajax\GetArticleRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function getArticle(GetArticleRequest $request): JsonResponse
{
return \response()->json([
'article' => Article::where('noArt', $request->arcadia_id)->firstOrFail()
]);
}
}

View file

@ -1,32 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
}

View file

@ -3,21 +3,11 @@
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
@ -25,7 +15,7 @@ class LoginController extends Controller
*
* @var string
*/
protected $redirectTo = '/';
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
@ -37,8 +27,13 @@ class LoginController extends Controller
$this->middleware('guest')->except('logout');
}
public function username()
{
return 'matricule';
}
/**
* Get the login username to be used by the controller.
*
* @return string
*/
public function username()
{
return 'matricule';
}
}

View file

@ -1,72 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}

View file

@ -1,39 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
}

View file

@ -1,41 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\VerifiesEmails;
class VerificationController extends Controller
{
/*
|--------------------------------------------------------------------------
| Email Verification Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling email verification for any
| user that recently registered with the application. Emails may also
| be re-sent if the user didn't receive the original email message.
|
*/
use VerifiesEmails;
/**
* Where to redirect users after verification.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
}

View file

@ -0,0 +1,85 @@
<?php
namespace App\Http\Controllers;
use App\Enums\ContactType;
use App\Http\Requests\Bo\Ajax\SendContactMessageRequest;
use App\Mail\ContactMail;
use App\Models\Dossier;
use App\Models\Format;
use App\Models\Recherche;
use App\Models\Sujet;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Mail;
class CommonController extends Controller
{
/**
* Show main interface
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function showInterface()
{
/** @var \App\Models\User */
$user = auth()->user();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$sujets = $user->sujets;
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Recherche> */
$recherches = Recherche::query()->whereHas('user', function (Builder $q) use ($user) {
$q->where('id', $user->id);
})->with('sujet')
->limit(10)
->orderBy('created_at', 'desc')
->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> */
$dossiers = Dossier::whereHas('users', function ($q) use ($user) {
$q->where('user_id', $user->id);
})->with('sujet')->get();
return view('home')->with([
'sujets' => $sujets,
'recherches' => $recherches,
'dossiers' => $dossiers
]);
}
/**
* Envoi d'un message
*
* @param \App\Http\Requests\Bo\Ajax\SendContactMessageRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function sendMessage(SendContactMessageRequest $request): JsonResponse
{
/** @var \App\Models\User $user */
$user = auth()->user();
foreach (config('mail.contactsList.admin') as $mail) {
Mail::to($mail)
->send(new ContactMail(ContactType::from($request->type), $request->url, $request->message, $user));
}
return response()->json(['status' => 'OK']);
}
/**
* Get data by sujet
*
* @param \App\Models\Sujet $sujet
* @return \Illuminate\Http\JsonResponse
*/
public function getDatasBySujet(Sujet $sujet): JsonResponse
{
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Format> */
$formats = Format::withoutGlobalScope('App\Scopes\SystemScope')
->where('system', 1)->get();
$formats = $formats->merge($sujet->formats);
return response()->json([
'typesvue' => $sujet->typeVues,
'typesvariantes' => $sujet->variantes,
'formats' => $formats
]);
}
}

View file

@ -1,71 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Format;
use App\Models\Typevue;
use App\Models\Variante;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use App\Models\Sujet;
use App\Models\Recherche;
use App\User;
use App\Models\Dossier;
use App\Mail\contact;
use Illuminate\Http\Request;
class CommunController extends Controller
{
/**
* page d'accueil
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$user = Auth::user();
$sujets = $user->sujets;
$paniers = Auth::user()->paniersFavoris;
$recherches = Recherche::where('user_id', $user->id)
->with("sujet")
->limit(10)
->orderBy("created_at", "desc")
->get();
$dossiers = Dossier::whereHas("users", function($query) use ($user){
$query->where('user_id', $user->id);
})
->with("sujet")
->get();
return view('home')->with(['sujets'=> $sujets, 'recherches'=> $recherches, 'dossiers'=> $dossiers, 'paniers'=> $paniers]);
}
/**
* Envoi d'un message
*
*/
public function sendMessage(Request $request)
{
$type = $request->input('type');
$url = $request->input('url');
$message = $request->input('message');
if (Auth::check()) {
$user = auth()->user();
Mail::to(env('MAIL_ADMIN_ADDRESS', "informatique.internet@ldc.fr"))->send(new contact($type, $url, $message, $user));
}
return json_encode(array('status' => "OK"));
}
public function getDatasBySujet(Request $request) {
$sujet_id = $request->sujet_id;
$sujet = Sujet::findOrFail($sujet_id);
$response['typesvue'] = $sujet->typeVues;
$response['typesvariantes'] = $sujet->variantes;
$response['formats'] = array_merge(Format::withoutGlobalScope('App\Scopes\SystemScope')->where('system', 1)->get()->toArray(), $sujet->formats->toArray());
return response()->json($response);
}
}

View file

@ -2,12 +2,14 @@
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
use AuthorizesRequests;
use DispatchesJobs;
use ValidatesRequests;
}

View file

@ -2,18 +2,141 @@
namespace App\Http\Controllers;
use App\Enums\MediaStatut;
use App\Http\Requests\Bo\Ajax\FetchFoldersRequest;
use App\Http\Requests\Bo\Ajax\LoadFoldersRequest;
use App\Http\Requests\Bo\Folders\StoreDepotFolderRequest;
use App\Http\Requests\Bo\Folders\StoreFolderRequest;
use App\Http\Requests\Bo\Folders\UpdateFolderRequest;
use App\Http\Resources\NestedDossiersListResource;
use App\Models\Dossier;
use App\Models\Sujet;
use App\Models\Marque;
use App\Models\Media;
use App\Models\Typevue;
use App\Models\Variante;
use App\Models\Format;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class DossierController extends Controller
{
/**
* Ajax Load folders
*
* @param \App\Http\Requests\Bo\Ajax\LoadFoldersRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function loadFolders(LoadFoldersRequest $request): JsonResponse
{
/** @var \App\Models\User */
$user = Auth::user();
$folders = [];
$select = ['id', 'libelle', 'system'];
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> Dossiers publiques */
$publicFolders = Dossier::query()
->whereHas('sujet', fn (Builder $q) => $q->where('codeSujet', $request->input('sujet_id')))
->where('is_private', false)
->whereDoesntHave('dossierParent')
->select($select)->get();
// * On récupère les dossiers privés.
/** @var \Illuminate\Database\Eloquent\Builder */
$privateQuery = Dossier::query()
->whereHas('sujet', fn (Builder $q) => $q->where('codeSujet', $request->input('sujet_id')))
->where('is_private', true)
->select($select);
// ? Is admin ?
if (!$user->hasRole(config('roles.const.ADMIN'))) {
// * If not admin, get using brands.
/** @var \Illuminate\Database\Eloquent\Collection<integer> Codes marques */
$marques = $user->marques()->pluck('codMarq');
$privateQuery->whereHas('marques', fn (Builder $q) => $q->whereIn('codMarq', $marques));
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> Dossiers privés */
$privateFolders = $privateQuery->get();
$foldersCollection = $publicFolders->merge($privateFolders);
$foldersCollection = $foldersCollection
->sortBy('libelle', SORT_NATURAL | SORT_FLAG_CASE)
->sortBy('favoris')->values();
// ? Is admin ?
if ($user->hasRole(config('roles.const.ADMIN'))) {
// * Ajout du dépôt de fichier pour les admin.
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> Dossiers depots */
$depotQuery = Dossier::query()
->whereDoesntHave('dossierParent')
->where('system', true)
->orderBy('libelle', 'ASC')
->get();
$foldersCollection = $foldersCollection->merge($depotQuery);
}
Arr::set($folders, 'data', new NestedDossiersListResource($foldersCollection));
// * Racine Count
$racineCountQuery = Media::query()
->whereHas('sujet', fn (Builder $q) => $q->where('codeSujet', $request->input('sujet_id')))
->whereDoesntHave('dossier');
// ? Is not admin ?
if (!$user->hasRole(config('roles.const.ADMIN'))) {
$racineCountQuery->where(
fn (Builder $q) =>
$q->where('statut', MediaStatut::public_etendu)
->orWhere('statut', MediaStatut::public)
->orWhere('created_by', $user->id)
);
}
Arr::set($folders, 'racineCount', $racineCountQuery->count());
return response()->json($folders);
}
/**
* Chargement des dossiers
*
* @param \App\Http\Requests\Bo\Ajax\FetchFoldersRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function loadFolder(FetchFoldersRequest $request): JsonResponse
{
/** @var \App\Models\User */
$user = auth()->user();
$response = [];
$response['variantes'] = Variante::query()
->whereHas('sujet', fn (Builder $q) => $q->where('codeSujet', $request->input('sujetId')))
->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Format> */
$FormatsSujet = Format::query()
->whereHas('sujets', fn (Builder $q) => $q->where('sujet_id', $request->input('sujetId')))
->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Format> */
$FormatsSystem = Format::query()
->withoutGlobalScope('App\Scopes\SystemScope')
->where('system', true)->get();
$response['formats'] = $FormatsSujet->merge($FormatsSystem);
$response['draggable'] = $user->hasRole([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
// Envoi du role .
$response['role'] = $user->role;
return \response()->json($response);
}
// * CRUD
/**
* Display a listing of the resource.
*
@ -21,11 +144,20 @@ class DossierController extends Controller
*/
public function index()
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$dossiers = Dossier::whereNull('parent_id')->where('system', 0)->orderBy('libelle', 'asc')->get();
$sujets = Sujet::where('sujet_dam', 1)->get();
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
return view('dossiers.index')->with([
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> */
$dossiers = Dossier::query()
->whereDoesntHave('dossierParent')
->where('system', false)
->orderBy('libelle', 'asc')
->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$sujets = Sujet::query()->where('sujet_dam', true)->get();
return view('dossiers.index', [
'dossiers' => $dossiers,
'sujets' => $sujets,
]);
@ -34,463 +166,164 @@ class DossierController extends Controller
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function create()
public function create(Request $request)
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$marques = Marque::all();
$sujets = Sujet::where('sujet_dam', 1)->get();
return view('dossiers.create')->with(['marques' => $marques, 'sujets' => $sujets]);
}
if ($request->sub) {
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Dossier> */
$dossiers = Dossier::query()
->whereDoesntHave('dossierParent')
->where('system', false)
->orderBy('libelle', 'asc')->get();
return view('dossiers.create-sub', [
'dossiers' => $dossiers
]);
}
public function createSub()
{
$dossiers = Dossier::whereNull('parent_id')->where('system', 0)->orderBy('libelle', 'asc')->get();
return view('dossiers.create-sub')->with(['dossiers' => $dossiers]);
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
$marques = Marque::all();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$sujets = Sujet::query()->where('sujet_dam', true)->get();
return view('dossiers.create')->with([
'marques' => $marques,
'sujets' => $sujets
]);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Http\Requests\Bo\Folders\StoreFolderRequest $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(StoreFolderRequest $request)
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$validatedData = $request->validate([
'libelle' => 'required',
'sujet' => 'required',
'status' => 'required'
]);
DB::transaction(function () use ($request) {
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
$dossierExist = Dossier::where('libelle', $request->libelle)->where('sujet_id', $request->sujet)->first();
if ($dossierExist) {
session()->flash('error', "Ce nom de dossier est déjà présent dans l'application pour ce sujet. Ajout impossible.");
return redirect()->route('dossier.create');
} else {
// ---- Le dossier
$dossier = new Dossier();
$dossier->libelle = $request->libelle;
$dossier->description = $request->description;
$dossier->is_private = $request->status;
$dossier->sujet()->associate($request->sujet);
$dossier->fill($request->validated());
if ($dossier->save()) {
if ($request->sub) {
/** @var \App\Models\Dossier */
$parent_dossier = Dossier::query()->findOrFail($request->input('parent_id'));
$dossier->sujet()->associate($parent_dossier->sujet);
} else {
$dossier->sujet()->associate($request->input('sujet'));
}
if ($dossier->saveOrFail()) {
// ---- Les marques
$sMarques = $request->marques;
if ($sMarques != "") {
$marques = explode(",", $sMarques);
foreach ($marques as $marqueId) {
$dossier->marques()->attach($marqueId);
}
if ($request->input('marques')) {
$dossier->marques()->sync($request->input('marques'));
}
session()->flash('message', "Le dossier a été enregistré");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
session()->flash('error', "Une erreur s'est produite, ajout impossible");
return redirect()->route('dossier.create');
return redirect()->route('dossier.edit', ['dossier' => $dossier])
->with('success', 'Le dossier a été enregistré');
}
}
}
public function storeSub(Request $request)
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$validatedData = $request->validate([
'libelle' => 'required',
'parent_id' => 'required',
]);
$dossierExist = Dossier::where('libelle', $request->libelle)->first();
$parent_dossier = Dossier::findOrFail($request->parent_id);
if ($dossierExist) {
session()->flash('error', "Ce nom de dossier est déjà présent dans l'application pour ce sujet. Ajout impossible.");
return redirect()->route('dossier.create');
} else {
// ---- Le dossier
$dossier = new Dossier();
$dossier->libelle = $request->libelle;
$dossier->description = $request->description;
$dossier->is_private = 0;
$dossier->parent_id = $request->parent_id;
$dossier->sujet_id = $parent_dossier->sujet_id;
if ($dossier->save()) {
session()->flash('message', "Le dossier a été enregistré");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
session()->flash('error', "Une erreur s'est produite, ajout impossible");
return redirect()->route('dossier.create');
}
}
}
/**
* Display the specified resource.
*
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\Response
*/
public function show(Dossier $dossier)
{
//
});
return back();
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\Response
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function edit(Dossier $dossier)
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
$dossierMarques = $dossier->marques;
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
$marques = Marque::all();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Marque> */
$dossierMarques = $dossier->marques;
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$dossierSujets = $dossier->sujets;
$sujets = Sujet::where('sujet_dam', 1)->get();
return view('dossiers.edit')->with(['dossier' => $dossier, 'dossierMarques' => $dossierMarques, 'marques' => $marques, 'sujets' => $sujets]);
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
$sujets = Sujet::query()->where('sujet_dam', true)->get();
return view('dossiers.edit', [
'dossier' => $dossier,
'dossierMarques' => $dossierMarques,
'marques' => $marques,
'sujets' => $sujets
]);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\Response
* @param \App\Http\Requests\Bo\Folders\UpdateFolderRequest $request
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request, Dossier $dossier)
public function update(UpdateFolderRequest $request, Dossier $dossier): RedirectResponse
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
DB::transaction(function () use ($request, $dossier) {
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
if ($dossier->parent_id === null) {
// ---- Le dossier
$dossier->fill($request->validated());
$validatedData = $request->validate([
'libelle' => 'required',
'sujet' => 'required',
'status' => 'required'
]);
$dossierExist = Dossier::where('libelle', $request->libelle)->where('sujet_id', $request->sujet)->where('id', '<>', $dossier->id)->first();
if ($dossierExist) {
session()->flash('error', "Ce nom de dossier est déjà présent dans l'application pour ce sujet. Ajout impossible.");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
// ---- Le dossier
$dossier->libelle = $request->libelle;
$dossier->description = $request->description;
$dossier->is_private = $request->status;
$dossier->sujet()->dissociate();
$dossier->sujet()->associate($request->sujet);
if ($dossier->save()) {
// ---- Les marques
$dossier->marques()->detach();
$sMarques = $request->marques;
if ($sMarques != "") {
$marques = explode(",", $sMarques);
foreach ($marques as $marqueId) {
$dossier->marques()->attach($marqueId);
}
}
session()->flash('message', "Le dossier a été mis à jour");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
session()->flash('error', "Une erreur s'est produite, enregistrement impossible");
return redirect()->route('dossier.edit');
if ($dossier->saveOrFail()) {
// ---- Les marques
if ($request->marques) {
$dossier->marques()->sync($request->marques);
}
return redirect()->route('dossier.edit', ['dossier' => $dossier])
->with('success', trans('Le dossier a été mis à jour'));
}
}else{
$validatedData = $request->validate([
'libelle' => 'required',
]);
$dossierExist = Dossier::where('libelle', $request->libelle)->where('sujet_id', $request->sujet)->where('id', '<>', $dossier->id)->first();
if ($dossierExist) {
session()->flash('error', "Ce nom de dossier est déjà présent dans l'application pour ce sujet. Ajout impossible.");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
// ---- Le dossier
$dossier->libelle = $request->libelle;
$dossier->description = $request->description;
if ($dossier->save()) {
session()->flash('message', "Le dossier a été mis à jour");
return redirect()->route('dossier.edit', ['dossier' => $dossier]);
} else {
session()->flash('error', "Une erreur s'est produite, enregistrement impossible");
return redirect()->route('dossier.edit');
}
}
}
});
return back();
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Dossier $dossier)
public function destroy(Dossier $dossier): RedirectResponse
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
if ($dossier->delete()) {
return redirect(route('dossier.index'));
} else {
session()->flash('error', 'Erreur lors de la suppression');
return redirect()->route('dossier.edit', ['user' => $dossier]);
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
if ($dossier->deleteOrFail()) {
return \response()->redirectToRoute('dossier.index')
->with('warning', trans('Le dossier à été supprimé'));
}
}
/**
* Chargement des dossiers
*
*/
public function loadFolder(Request $request)
{
$response = array();
$sujetId = $request->input('sujetId');
$response['variantes'] = Variante::where('sujet_id', $sujetId)->get();
$FormatsSujet = Format::whereHas('sujets', function ($query) use ($sujetId) {
$query->where('sujet_id', $sujetId);
})->get();
$FormatsSystem = Format::withoutGlobalScope('App\Scopes\SystemScope')->where('system', 1)->get();
$response['formats'] = $FormatsSujet->merge($FormatsSystem);
if (Auth::user()->hasRole([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')])) {
$response['draggable'] = true;
} else {
$response['draggable'] = false;
}
// Envoi du role
$response['role'] = Auth::user()->role;
return json_encode($response);
}
/**
* Ajouter un dossier
*
*/
public function addFolder(Request $request)
{
$response = array();
Auth::user()->authorizeRoles([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
$parent_id = $request->input('parent_id');
$libelle = $request->input('libelle');
$description = $request->input('description');
// ---- Le dossier
$dossier = new Dossier();
$dossier->libelle = htmlspecialchars($libelle);
$dossier->description = $description;
$dossier->parent_id = $parent_id;
$dossierParent = Dossier::where('id', $parent_id)->first();
if ($parent_id == 1 || $dossierParent->system == 1) { // dossier de dépôt
$dossier->system = 1;
} else {
$dossier->system = 0;
}
$dossier->sujet_id = $dossierParent->sujet_id;
$dossier->save();
$response['folder_id'] = $dossier->id;
$response['system'] = $dossier->system;
return json_encode($response);
return back();
}
/**
* Ajouter un dossier de dépôt
*
* @param \App\Http\Requests\Bo\Folders\StoreDepotFolderRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function addDepotFolder(Request $request)
public function addDepotFolder(StoreDepotFolderRequest $request): JsonResponse
{
$response = array();
$parent_id = $request->input('parent_id');
$libelle = $request->input('libelle');
$description = $request->input('description');
// ---- Le dossier
$dossier = new Dossier();
$dossier->libelle = htmlspecialchars($libelle);
$dossier->description = $description;
$dossier = new Dossier($request->validated());
$dossier->parent_id = 1;
$dossier->system = 1;
$dossier->save();
$response['folder_id'] = $dossier->id;
return json_encode($response);
$dossier->system = true;
$dossier->saveOrFail();
return \response()->json([
'folder_id' => $dossier->id
]);
}
/**
* supprimer un dossier
*
*/
public function removeFolder(Request $request)
{
Auth::user()->authorizeRoles([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
$dossier_id = $request->input('dossier_id');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier && !is_null($dossier->parent_id)) {
if ($dossier->delete()) {
return json_encode($dossier->parent_id);
}
}
return json_encode(false);
}
/**
* déplacer un dossier
*
*/
public function moveFolder(Request $request)
{
Auth::user()->authorizeRoles([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
$dossier_id = $request->input('dossier_id');
$parent_id = $request->input('parent_id');
$sujet_id = $request->input('sujet_id');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier && !is_null($dossier->parent_id)) {
$dossier->parent_id = $parent_id;
if ($dossier->save()) {
Media::where('dossier_id', $dossier_id)->update(['sujet_id' => $sujet_id]);
return json_encode(true);
}
}
return json_encode(false);
}
/**
* renommer un dossier
*
*/
public function renameFolder(Request $request)
{
Auth::user()->authorizeRoles([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
$dossier_id = $request->input('dossier_id');
$libelle = $request->input('libelle');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier && !is_null($dossier->parent_id)) {
$dossier->libelle = $libelle;
if ($dossier->save()) {
return json_encode(true);
}
}
return json_encode(false);
}
/**
* get propriétés d'un dossier
*
*/
public function getFolderProperty(Request $request)
{
$response = array();
$dossier_id = $request->input('dossier_id');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier) {
$response["data"] = $dossier;
}
return json_encode($response);
}
/**
* enregistre les propriétés d'un dossier
*
*/
public function saveFolderProperty(Request $request)
{
$dossier_id = $request->input('dossier_id');
$libelle = $request->input('libelle');
$description = $request->input('description');
// ---- Le dossier
$dossier = Dossier::where('id', $dossier_id)->first();
if ($dossier && !is_null($dossier->parent_id) && strlen($libelle) > 3) {
$dossier->libelle = $libelle;
$dossier->description = $description;
$dossier->save();
}
return json_encode(true);
}
public function loadFolders(Request $request)
{
$folders = array();
$user = Auth::user();
$sujet_id = $request->sujet_id;
$dossierQuery = Dossier::where([
['sujet_id', $sujet_id],
['is_private', 0]
])
->whereNull('parent_id');
$dossierQuery = $dossierQuery->get();
// On récupère les dossiers privés
if ($user->hasRole(config('roles.const.ADMIN'))) {
$privateQuery = Dossier::where([
['is_private', '=', 1],
['sujet_id', '=', $sujet_id],
])->get();
} else {
$marques = $user->marques()->pluck("marque_id");
$privateQuery = Dossier::where([
['is_private', '=', 1],
['sujet_id', '=', $sujet_id],
])->whereHas("marques", function ($query) use ($marques) {
$query->whereIn("marque_id", $marques);
})->get();
}
$dossierQuery = $dossierQuery->merge($privateQuery);
$dossierQuery = $dossierQuery->sortBy('libelle', SORT_NATURAL | SORT_FLAG_CASE)->values();
// Ajout du dépôt de fichier pour les admin
if ($user->hasRole(config('roles.const.ADMIN'))) {
$depotQuery = Dossier::whereNull('parent_id')
->where('system', 1)
->orderBy('libelle', 'ASC')
->get();
$folders['data'] = $dossierQuery->merge($depotQuery);
} else {
$folders['data'] = $dossierQuery;
}
$folders['racineCount'] = Media::where('sujet_id', $sujet_id)
->whereNull('dossier_id')
->where(function ($query) use ($user) {
$query->where('statut', config('services.statut.public_etendu'))
->orWhere('statut', config('services.statut.public'))
->orWhere('created_by', $user->id);
})
->count();
return response()->json($folders);
}
}

File diff suppressed because it is too large Load diff

View file

@ -2,15 +2,17 @@
namespace App\Http\Controllers;
use App\Http\Requests\Bo\AjaxAddMediasBasketRequest;
use App\Http\Requests\Bo\AjaxCreateBasketRequest;
use App\Http\Requests\Bo\AjaxDestroyBasketRequest;
use App\Http\Requests\Bo\AjaxRemoveMediasBasketRequest;
use App\Http\Requests\Bo\AjaxSaveBasketPropsRequest;
use App\Http\Requests\Bo\Ajax\AddMediasBasketRequest;
use App\Http\Requests\Bo\Ajax\CreateBasketRequest;
use App\Http\Requests\Bo\Ajax\DestroyBasketRequest;
use App\Http\Requests\Bo\Ajax\RemoveMediasBasketRequest;
use App\Http\Requests\Bo\Ajax\SaveBasketPropsRequest;
use Illuminate\Support\Str;
use App\Models\Panier;
use App\Models\Format;
use App\Models\Media;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
class PanierController extends Controller
{
@ -19,15 +21,16 @@ class PanierController extends Controller
/**
* Page principale des paniers
*
* @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
* @return \Illuminate\Contracts\View\View
*/
public function index()
public function index(): View
{
/** @var \App\User $user */
/** @var \App\Models\User $user */
$user = \auth()->user();
/** @var \Illuminate\Database\Eloquent\Collection $paniers */
// ! Has to flush Media cache before querying basket with media list
Media::flushQueryCache();
$paniers = $user->paniersOwner;
return view('panier.index')->with([
'paniers' => $paniers,
]);
@ -39,12 +42,12 @@ class PanierController extends Controller
*
* @return \Illuminate\Http\JsonResponse
*/
public function getBaskets()
public function getBaskets(): JsonResponse
{
/** @var \App\User $user */
/** @var \App\Models\User $user */
$user = \auth()->user();
/** @var \Illuminate\Database\Eloquent\Collection $paniers */
// ! Has to flush Media cache before querying basket with media list
Media::flushQueryCache();
$paniers = $user->paniersOwner;
return response()->json($paniers);
@ -53,41 +56,48 @@ class PanierController extends Controller
/**
* Ajout de média à un panier
*
* @param AjaxAddMediasBasketRequest $request
* @param \App\Http\Requests\Bo\Ajax\AddMediasBasketRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function addMediasBasket(AjaxAddMediasBasketRequest $request)
public function addMediasBasket(AddMediasBasketRequest $request): JsonResponse
{
/** @var \App\Models\Panier $panier */
$panier = Panier::whereId($request->panier_id)
->with('medias')->firstOrFail();
$panier = Panier::query()
->where('id', $request->input('panier_id'))
->with('mediaList')
->firstOrFail();
// * Sync every media to basket
$panier->medias()->sync(array_merge(
$panier->medias()->pluck('id')->all(),
$request->medias
$panier->mediaList()->sync(array_merge(
$panier->mediaList()->pluck('id')->all(),
$request->input('mediaList')
));
Media::flushQueryCache();
return response()->json();
}
/**
* Suppression de média à un panier
*
* @param AjaxRemoveMediasBasketRequest $request
* @param \App\Http\Requests\Bo\Ajax\RemoveMediasBasketRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function removeMediasBasket(AjaxRemoveMediasBasketRequest $request)
public function removeMediasBasket(RemoveMediasBasketRequest $request): JsonResponse
{
/** @var \App\Models\Panier $panier */
$panier = Panier::whereId($request->panier_id)
->with('medias')->firstOrFail();
$panier = Panier::query()
->where('id', $request->input('panier_id'))
->with('mediaList')
->firstOrFail();
/** @var \App\Models\Media $media */
$media = Media::whereId($request->media_id)->firstOrFail();
$media = Media::query()
->where('id', $request->input('media_id'))
->firstOrFail();
$panier->medias()->detach($media);
$panier->mediaList()->detach($media);
return response()->json(true);
}
@ -95,16 +105,16 @@ class PanierController extends Controller
/**
* Ajoute un panier
*
* @param AjaxCreateBasketRequest $request
* @param \App\Http\Requests\Bo\Ajax\CreateBasketRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function createBasket(AjaxCreateBasketRequest $request)
public function createBasket(CreateBasketRequest $request): JsonResponse
{
/** @var \App\Models\User $user */
$user = auth()->user();
$panier = new Panier();
$panier->libelle = $request->title;
$panier->libelle = $request->input('title');
$panier->uid = Str::uuid();
$panier->owner()->associate($user);
$panier->saveOrFail();
@ -115,16 +125,17 @@ class PanierController extends Controller
/**
* Supprimer un panier
*
* @param AjaxDestroyBasketRequest $request
* @param \App\Http\Requests\Bo\Ajax\DestroyBasketRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroyBasket(AjaxDestroyBasketRequest $request)
public function destroyBasket(DestroyBasketRequest $request): JsonResponse
{
/** @var \App\Models\Panier $basket */
$basket = Panier::whereId($request->basket_id)->firstOrFail();
$basket = Panier::query()
->where('id', $request->input('basket_id'))
->firstOrFail();
// TODO: Replace this with deleteOrFail after laravel bump.
$basket->delete();
$basket->deleteOrFail();
return response()->json();
}
@ -134,12 +145,12 @@ class PanierController extends Controller
/**
* Page publique d'un panier
*
* @param Panier $panier
* @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
* @param \App\Models\Panier $panier
* @return \Illuminate\Contracts\View\View
*/
public function showBasket(Panier $panier)
public function showBasket(Panier $panier): View
{
/** @var \App\User|null $user */
/** @var \App\Models\User|null $user */
$user = auth()->user();
// * Ne pas afficher le panier si il n'est pas pas publié et
@ -150,10 +161,13 @@ class PanierController extends Controller
}
}
/** @var \Illuminate\Database\Eloquent\Collection $formats */
$formats = Format::withoutGlobalScope('App\Scopes\SystemScope')
->where('system', 1)->get();
return view('panier.show')->with([
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Format> $formats */
$formats = Format::query()
->withoutGlobalScope('App\Scopes\SystemScope')
->where('system', true)
->get();
return view('panier.show', [
'panier' => $panier,
'formats' => $formats,
]);
@ -162,13 +176,15 @@ class PanierController extends Controller
/**
* Enregistre les propriétés d'un panier
*
* @param AjaxSaveBasketPropsRequest $request
* @param \App\Http\Requests\Bo\Ajax\SaveBasketPropsRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function saveBasketProperty(AjaxSaveBasketPropsRequest $request)
public function saveBasketProperty(SaveBasketPropsRequest $request): JsonResponse
{
/** @var \App\Models\Panier $panier */
$panier = Panier::whereId($request->basket_id)->firstOrFail();
$panier = Panier::query()
->where('id', $request->input('basket_id'))
->firstOrFail();
$panier->fill($request->validated());
$panier->saveOrFail();

View file

@ -4,24 +4,33 @@ namespace App\Http\Controllers;
use App\Models\Media;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RecoveryController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
Auth::user()->authorizeRoles(config('roles.const.ADMIN'));
/** @var \App\Models\User */
$user = auth()->user();
$user->authorizeRoles(config('roles.const.ADMIN'));
return view('recovery.index');
}
/**
* Check if ArcadiaId exists.
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function checkArcadiaId(Request $request)
{
$response = false;
$arcadia_id = $request->id;
$media = Media::onlyTrashed()->where('arcadia_id', '=', $arcadia_id)->first();
if ($media)
$response = true;
return json_encode($response);
return \response()->json(
Media::onlyTrashed()->where('arcadia_id', '=', \intval($request->id))->exists()
);
}
}

View file

@ -1,516 +1,350 @@
<?php
namespace App\Http\Controllers;
use App\Http\Traits\ArcadiaLink;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
use App\Enums\MediaExtension;
use App\Http\Requests\Bo\Ajax\UploadMediaFileRequest;
use App\Lib\ToolboxHelper;
use App\Models\Copyright;
use App\Models\Dossier;
use App\Models\Etiquette;
use App\Models\Langue;
use App\Models\Media;
use App\Models\Site;
use App\Models\Historique;
use App\Http\Traits\MediaTools;
use App\Models\Sujet;
use App\Models\TypeMedia;
use App\Models\User;
use App\Traits\Http\HandlesMedia;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException;
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;
use Symfony\Component\Mime\MimeTypes;
class UploadController extends Controller
{
use HandlesMedia;
use MediaTools;
public function index(Request $request)
/**
* Show upload form
*
* @param Request $request
* @return \Illuminate\Contracts\Validation\Validator|\Illuminate\Contracts\Validation\Factory
*/
public function showUploadForm(Request $request)
{
// ---- Vérification du token de sécurité
// TODO: Quand le DAM sera ouvert au public, Enforce security with dynamic tokens.
// ---- Vérification du token de sécurité .
$token = $request->get('token');
if($token != env('TOKEN_DEPOT', "c8c4613a-236c-4b06-95f6-a9c9c6c18861")) { return abort(404);
if ($token != env('TOKEN_DEPOT', "c8c4613a-236c-4b06-95f6-a9c9c6c18861")) {
return abort(404);
}
$sites = Site::orderBy('libelle')->get();
return view('upload.show')->with(
[
'sites'=> $sites,
]
);
return view('upload.show')->with([
'sites' => $sites,
]);
}
public function storeMedia(Request $request)
{
$uid = $request->input('uid');
$sujet_id = $request->input('sujet_id');
$dossier_id = $request->input('dossier_id');
$replaceMediaId = $request->input('replaceMediaId');
if($dossier_id == 0) { $dossier_id = null;
/**
* Asynchronous chunked upload file.
*
* @param \App\Http\Requests\Bo\Ajax\UploadMediaFileRequest $request
* @param \Pion\Laravel\ChunkUpload\Receiver\FileReceiver $receiver
* @return \Illuminate\Http\JsonResponse
* @throws \Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException If failed upload.
*/
public function uploadMediaFileIntoDepot(
UploadMediaFileRequest $request,
FileReceiver $receiver,
): JsonResponse {
/** @var \App\Models\Dossier */
$dossier = Dossier::where('id', intval($request->dossier_id))->firstOrFail();
// Check if the upload is success, throw exception or return response you need.
if ($receiver->isUploaded() === false) {
throw new UploadMissingFileException();
}
// Receive the file.
$save = $receiver->receive();
$headers = $request->headers->all();
$acceptFileTypes = array('gif','jpeg', 'jpg','png','mp4','mp3','psd','ai','svg','pdf');
// Check if the upload has finished (in chunk mode it will send smaller files).
if ($save->isFinished()) {
/** @var \App\Models\User */
$user = auth()->user();
if ($request->hasFile('files')) {
$filesa = [];
$file = $request->file('files');
$uplodedFile = $save->getFile();
foreach($file as $files){
$is_last_chunk = false;
$is_chunked_upload = !empty($headers['content-range']);
if ($is_chunked_upload) {
if (preg_match('|(\d+)/(\d+)|', $headers['content-range'][0], $range)) {
if ($range[1] == $range[2] - 1) {
$is_last_chunk = true;
}
}
}
try {
/** @throws \Illuminate\Validation\ValidationException */
$this->validateUploadedFile($uplodedFile);
$extension = strtolower($files->getClientOriginalExtension());
$originalName = str_replace(".".$extension, "", $files->getClientOriginalName());
if (!in_array($extension, $acceptFileTypes)) { return array("false");
}
/** @var \App\Models\Media */
$media = Media::whereId($request->media_id)
->whereHas('dossier', function ($q) use ($dossier) {
$q->whereId($dossier->id);
})->firstOrNew();
if($is_chunked_upload) {
$filename = $uid."_".$range[1].".".$extension;
}else{
$filename = $uid.'.'.$extension;
}
$uploadPath = public_path() . '/uploads/';
$files->move($uploadPath, $filename);
// si c'est le dernier morceux d'un fichier
if($is_last_chunk) {
if($dossier = opendir($uploadPath)) {
$dirFiles = array();
// on compile tous les chunk du fichier
while(false !== ($fichier = readdir($dossier))){
if($fichier != '.' && $fichier != '..' ) {
if(strpos($fichier, $uid) !== false) {
$dirFiles[$fichier] = str_replace(".".$extension, "", str_replace($uid."_", "", $fichier));
}
}
}
closedir($dossier);
// on les trie pour les assembler dans le bon ordre
asort($dirFiles, SORT_NUMERIC);
// on les assemble dans un fichier final
$filename = $uid . '.' . $extension;
foreach($dirFiles as $key => $fichier) {
$file = fopen($uploadPath.$key, 'rb');
$buff = fread($file, filesize($uploadPath.$key));
fclose($file);
$final = fopen($uploadPath.$filename, 'a');
$write = fwrite($final, $buff);
fclose($final);
unlink($uploadPath.$key);
}
}
}
// si c'est le dernier morceau d'un fichier ou que c'est un envoi simple
if($is_last_chunk || !$is_chunked_upload ) {
$destinationPath = $this->get_mediaFolder()."/";
// si on upload un média pour remplacer un fichier par un autre
if($replaceMediaId != 0) {
// on récupère le média à modifier
$media= Media::where('id', $replaceMediaId)->first();
// On déplace le fichier dans le répertoire des médias
Storage::move("uploads/".$filename, $destinationPath.$filename);
// supprime les fichiers médias stockés sur disque
$filesfF= Storage::files($media->folder."/");
$filepath = preg_quote($media->folder.$media->uid, '/');
$matchingFiles = preg_grep('/^'.$filepath.'/', $filesfF);
Storage::delete($matchingFiles);
$media->isDefault = 0;
$media->save();
}else{
// On déplace le fichier dans le répertoire des médias
Storage::move("uploads/".$filename, $destinationPath.$filename);
// on créé un média en bdd
$media = new Media();
$media->dossier_id = $dossier_id;
$media->sujet_id = $sujet_id;
// Par défaut FR
$media->langue_id = 1;
// Par défaut propriété de la marque
$media->copyright_id = 3;
}
$media->extension = $extension;
$media->folder = $destinationPath;
if($replaceMediaId == 0) {
$media->libelle = mb_substr($originalName, 0, 50, "UTF-8");
$media->created_by= Auth::user()->id;
}
$media->uid = $uid;
$media->taille = $this->formatBytes($this->get_file_size($destinationPath.$filename));
switch ($extension) {
// Photo (1)
case 'gif':
case 'jpeg':
case 'jpg':
case 'png':
case 'ai':
case 'pdf':
case 'psd':
$media->typemedia_id = 1;
$im = new \imagick($destinationPath.$filename);
if(in_array($extension, array("pdf", "ai", "psd", "gif")) ) {
$im->setIteratorIndex(0);
}
$resolutions = $im->getImageResolution();
$media->resolution = round($resolutions['x'] * 2.54);
$imageprops = $im->getImageGeometry();
$media->largeur = $imageprops['width'];
$media->hauteur = $imageprops['height'];
if($media->resolution != 0) {
$media->largeur_mm = ceil(($media->largeur * 2.54 / $media->resolution)*10);
$media->hauteur_mm = ceil(($media->hauteur * 2.54 / $media->resolution)*10);
}else{
$media->largeur_mm = "";
$media->hauteur_mm = "";
}
$media->save();
$im->destroy();
// ---- Creation des vignettes de base
$this->create_sys_thumb($media);
// ---- Creation des vignettes en lien avec le sujet du média
if(isset($sujet_id) ) {
$this->create_thumb($media);
}
break;
// Illustration/Vectorielle (2)
case 'svg':
$media->typemedia_id = 2;
$media->save();
break;
// Vidéo (3)
case 'mp4':
$media->typemedia_id =3 ;
$getID3 = new \getID3;
if($fileInfo = $getID3->analyze($destinationPath.$filename)) {
$media->largeur = $fileInfo['video']['resolution_x'];
$media->hauteur = $fileInfo['video']['resolution_y'];
$media->duree = $fileInfo['playtime_string'];
}
$media->save();
break;
// Audio (4)
case 'mp3':
$media->typemedia_id = 4;
$getID3 = new \getID3;
if($fileInfo = $getID3->analyze($destinationPath.$filename)) {
$media->duree= $fileInfo['playtime_string'];
}
$media->save();
break;
}
$id = $media->id;
$media = Media::find($id);
// ---- Index dans Elasticsearch
$media = Media::where('id', $media->id)->first();
$media->addToIndex();
// ---- Historique des actions
$historique = new historique();
if($user = Auth::user()) {
$historique->user_id = $user->id;
}
$historique->media_id = $media->id;
if($replaceMediaId == 0) {
$historique->type = "Création";
$historique->description = "Média ajouté";
}else{
$historique->type = "Modification";
$historique->description = "Le média a été remplacé";
}
$historique->save();
$filest = array();
$filest['name'] = $filename;
$filest['uid'] = $uid;
$filest['libelle'] = $media->libelle;
$filest['id'] = $media->id;
$filest['folder'] = $media->folder;
$filest['extension'] = $media->extension;
$filest['typemedia_id'] = $media->typemedia_id;
$filesa['files'][]=$filest;
}
// Save the file and return any response you need.
return $this->createOrUpdateMedia($user, $uplodedFile, $media, $dossier);
} catch (ValidationException $e) {
// 400 instead of 422 is for resumablejs to handle properly.
return \response()->json($e->errors(), 400);
}
return $filesa;
}
} //end if
// We are in chunk mode, lets send the current progress.
/** @var AbstractHandler $handler */
$handler = $save->handler();
return response()->json([
'done' => $handler->getPercentageDone()
]);
}
public function storeMediaV2(Request $request)
/**
* Asynchronous chunked upload file.
*
* @param \App\Http\Requests\Bo\Ajax\UploadMediaFileRequest $request
* @param \Pion\Laravel\ChunkUpload\Receiver\FileReceiver $receiver
* @param \App\Models\Sujet $sujet
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\JsonResponse
* @throws \Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException If failed upload.
*/
public function uploadMediaFile(
UploadMediaFileRequest $request,
FileReceiver $receiver,
Sujet $sujet,
Dossier $dossier
): JsonResponse {
// Check if the upload is success, throw exception or return response you need.
if ($receiver->isUploaded() === false) {
throw new UploadMissingFileException();
}
// Receive the file.
$save = $receiver->receive();
// Check if the upload has finished (in chunk mode it will send smaller files).
if ($save->isFinished()) {
/** @var \App\Models\User */
$user = auth()->user();
$uplodedFile = $save->getFile();
try {
/** @throws \Illuminate\Validation\ValidationException */
$this->validateUploadedFile($uplodedFile);
/** @var \App\Models\Media */
$media = Media::query()
->where('id', $request->input('media_id'))
->whereHas('sujet', fn(Builder $q) => $q->where('codeSujet', $sujet->codeSujet))
->whereHas('dossier', fn(Builder $q) => $q->where('id', $dossier->id))
->firstOrNew();
// Save the file and return any response you need.
return $this->createOrUpdateMedia($user, $uplodedFile, $media, $dossier, $sujet);
} catch (ValidationException $e) {
// 400 instead of 422 is for resumablejs to handle properly.
return \response()->json($e->errors(), 400);
}
} //end if
// We are in chunk mode, lets send the current progress.
/** @var AbstractHandler $handler */
$handler = $save->handler();
return response()->json([
'done' => $handler->getPercentageDone()
]);
}
/**
* Validate uploaded file
*
* @param \Illuminate\Http\UploadedFile $file
* @return void
* @throws \Illuminate\Validation\ValidationException If uploaded file is not valid.
*/
private function validateUploadedFile(UploadedFile $file)
{
$uid = $request->input('uid');
$sujet_id = $request->input('sujet_id');
$dossier_id = $request->input('dossier_id');
$replaceMediaId = $request->input('replaceMediaId');
if($dossier_id == 0) { $dossier_id = null;
Validator::make([
'file' => $file
], [
'file' => 'required|file|mimes:gif,jpeg,jpg,png,mp4,mp3,psd,ai,svg,pdf'
], [
'files.mimes' => trans('Ce type de fichier n\'est pas accepté.')
])->validate();
$this->validateExtension($file);
}
/**
* Validate file extension matches allowed extensions enum
*
* @param \Illuminate\Http\UploadedFile $file
* @return void
* @throws \Illuminate\Validation\ValidationException If file extension could not be confirmed.
*/
private function validateExtension(UploadedFile $file)
{
if (\is_null(MediaExtension::tryFrom($file->getClientOriginalExtension()))) {
throw ValidationException::withMessages([
'file' => trans('Ce type de fichier n\'est pas accepté.')
]);
}
$filesa = [];
$acceptFileTypes = array('gif','jpeg', 'jpg','png','mp4','mp3','psd','ai','svg','pdf');
/** @throws \ValueError If value is not defined in enum */
$mediaExtension = MediaExtension::from($file->getClientOriginalExtension());
if (!$uid) {
$uid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
}
if ($file->guessExtension()) {
$mt = new MimeTypes();
$guessedExts = $mt->getExtensions($mt->guessMimeType($file->path()));
$file = $request->file('files');
if (!empty($file)) {
$extension = strtolower($file->getClientOriginalExtension());
$originalName = str_replace(".".$extension, "", $file->getClientOriginalName());
if (!in_array($extension, $acceptFileTypes)) { return array("false");
}
if (!in_array($extension, $acceptFileTypes)) { return array("error" => "Ce type de fichier n'est pas accepté.");
}
// check the error status
if ($file->getError() != 0) {
Log::error('error ' . $file->getError() . ' in file ' . $request->resumableFilename);
}
// init the destination file (format <filename.ext>.part<#chunk>
// the file is stored in a temporary directory
if(isset($request->resumableIdentifier) && trim($request->resumableIdentifier)!='') {
$temp_dir = 'uploads/' . $request->resumableIdentifier;
}
$dest_file = $temp_dir . '/' . $request->resumableFilename . '.part' . $request->resumableChunkNumber;
// create the temporary directory
if (!is_dir($temp_dir)) {
mkdir($temp_dir, 0777, true);
}
// move the temporary file
if (!move_uploaded_file($file->getPathname(), $dest_file)) {
Log::error('Error saving (move_uploaded_file) chunk ' . $request->resumableChunkNumber.' for file ' . $request->resumableFilename);
} else {
$filename = $uid . '.' . $extension;
// check if all the parts present, and create the final destination file
$isLast = $this->createFileFromChunks($temp_dir, $request->resumableFilename, $request->resumableChunkSize, $request->resumableTotalSize, $request->resumableTotalChunks, $filename);
if ($isLast) {
$destinationPath = $this->get_mediaFolder()."/";
// si on upload un média pour remplacer un fichier par un autre
if($replaceMediaId != 0) {
// on récupère le média à modifier
$media= Media::where('id', $replaceMediaId)->first();
// On déplace le fichier dans le répertoire des médias
Storage::move("uploads/".$filename, $destinationPath.$filename);
// supprime les fichiers médias stockés sur disque
$filesfF= Storage::files($media->folder."/");
$filepath = preg_quote($media->folder.$media->uid, '/');
$matchingFiles = preg_grep('/^'.$filepath.'/', $filesfF);
Storage::delete($matchingFiles);
$media->isDefault = 0;
$media->save();
}else{
// On déplace le fichier dans le répertoire des médias
Storage::move("uploads/".$filename, $destinationPath.$filename);
// on créé un média en bdd
$media = new Media();
$media->dossier_id = $dossier_id;
$media->sujet_id = $sujet_id;
// Par défaut FR
$media->langue_id = 1;
// Par défaut propriété de la marque
$media->copyright_id = 3;
}
$media->extension = $extension;
$media->folder = $destinationPath;
if($replaceMediaId == 0) {
$media->libelle = mb_substr($originalName, 0, 50, "UTF-8");
$media->created_by= Auth::user()->id;
}
$media->uid = $uid;
$media->taille = $this->formatBytes($this->get_file_size($destinationPath.$filename));
switch ($extension) {
// Photo (1)
case 'gif':
case 'jpeg':
case 'jpg':
case 'png':
case 'ai':
case 'pdf':
case 'psd':
$media->typemedia_id = 1;
$im = new \imagick($destinationPath . $filename);
//$im = new \imagick(realpath($destinationPath.$filename));
if(in_array($extension, array("pdf", "ai", "psd", "gif")) ) {
$im->setIteratorIndex(0);
}
$resolutions = $im->getImageResolution();
$media->resolution = round($resolutions['x'] * 2.54);
$imageprops = $im->getImageGeometry();
$media->largeur = $imageprops['width'];
$media->hauteur = $imageprops['height'];
if($media->resolution != 0) {
$media->largeur_mm = ceil(($media->largeur * 2.54 / $media->resolution)*10);
$media->hauteur_mm = ceil(($media->hauteur * 2.54 / $media->resolution)*10);
}else{
$media->largeur_mm = "";
$media->hauteur_mm = "";
}
$media->save();
$im->destroy();
// ---- Creation des vignettes de base
$this->create_sys_thumb($media);
// ---- Creation des vignettes en lien avec le sujet du média
if(isset($sujet_id) ) {
$this->create_thumb($media);
}
break;
// Illustration/Vectorielle (2)
case 'svg':
$media->typemedia_id = 2;
$media->save();
break;
// Vidéo (3)
case 'mp4':
$media->typemedia_id =3 ;
$getID3 = new \getID3;
if($fileInfo = $getID3->analyze($destinationPath.$filename)) {
$media->largeur = $fileInfo['video']['resolution_x'];
$media->hauteur = $fileInfo['video']['resolution_y'];
$media->duree = $fileInfo['playtime_string'];
}
$media->save();
break;
// Audio (4)
case 'mp3':
$media->typemedia_id = 4;
$getID3 = new \getID3;
if($fileInfo = $getID3->analyze($destinationPath.$filename)) {
$media->duree= $fileInfo['playtime_string'];
}
$media->save();
break;
}
$id = $media->id;
$media = Media::find($id);
// ---- Index dans Elasticsearch
$media = Media::where('id', $media->id)->first();
$media->addToIndex();
// ---- Historique des actions
$historique = new historique();
if($user = Auth::user()) {
$historique->user_id = $user->id;
}
$historique->media_id = $media->id;
if($replaceMediaId == 0) {
$historique->type = "Création";
$historique->description = "Média ajouté";
}else{
$historique->type = "Modification";
$historique->description = "Le média a été remplacé";
}
$historique->save();
return response()->json($media);
}
if (!\in_array($mediaExtension->value, $guessedExts)) {
$guessedExts = \implode(',', $guessedExts);
throw ValidationException::withMessages([
'file' => trans(
'File guessed extensions :guessedExts does not match file name extension :extension',
[
'guessedExt' => $guessedExts,
'extension' => $mediaExtension,
]
)
]);
}
}
}
/**
* Check if all the parts exist, and
* gather all the parts of the file together
* Create or update media
*
* @param string $temp_dir - the temporary directory holding all the parts of the file
* @param string $fileName - the original file name
* @param string $chunkSize - each chunk size (in bytes)
* @param string $totalSize - original file size (in bytes)
* @return bool
* @param \App\Models\User $user
* @param \Illuminate\Http\UploadedFile $file
* @param \App\Models\Media $media
* @param \App\Models\Dossier $dossier
* @param \App\Models\Sujet|null $sujet
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException If $subject is missing and folder
* is not a system folder (Dossier dépot).
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
* (switch) .
*/
private function createFileFromChunks($temp_dir, $fileName, $chunkSize, $totalSize, $total_files, $finalName)
{
// count all the parts of this file
$total_files_on_server_size = 0;
$temp_total = 0;
foreach(scandir($temp_dir) as $file) {
$temp_total = $total_files_on_server_size;
$tempfilesize = filesize($temp_dir.'/'.$file);
$total_files_on_server_size = $temp_total + $tempfilesize;
}
// check that all the parts are present
// If the Size of all the chunks on the server is equal to the size of the file uploaded.
if ($total_files_on_server_size >= $totalSize) {
// create the final destination file
if (($fp = fopen('uploads/'.$finalName, 'w')) !== false) {
for ($i=1; $i<=$total_files; $i++) {
fwrite($fp, file_get_contents($temp_dir.'/'.$fileName.'.part'.$i));
//Log::info('writing chunk '.$i);
}
fclose($fp);
} else {
Log::error('cannot create the destination file');
return false;
private function createOrUpdateMedia(
User $user,
UploadedFile $file,
Media $media,
Dossier $dossier,
Sujet|null $sujet = null
): JsonResponse {
// phpcs:enable
return DB::transaction(function () use ($user, $file, $media, $dossier, $sujet) {
if (!$dossier->system and !$sujet) {
throw ValidationException::withMessages([
'file' => 'Cannot put media inside a non system folder (depot) without a subject'
]);
}
// rename the temporary directory (to avoid access from other
// concurrent chunks uploads) and than delete it
if (rename($temp_dir, $temp_dir.'_UNUSED')) {
$this->rrmdir($temp_dir.'_UNUSED');
} else {
$this->rrmdir($temp_dir);
}
return true;
}
return false;
}
/** @var \Illuminate\Filesystem\FilesystemAdapter */
$storage = Storage::disk('media');
/**
* Delete a directory RECURSIVELY
*
* @param string $dir - directory path
* @link http://php.net/manual/en/function.rmdir.php
*/
private function rrmdir($dir)
{
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir . "/" . $object) == "dir") {
$this->rrmdir($dir . "/" . $object);
} else {
unlink($dir . "/" . $object);
$isNewMedia = !$media->exists;
$mediaFolderName = $this->getCurentMediaFolderName();
// * File size
$fileSize = $file->getSize();
$sanitizedFileName = ToolboxHelper::sanitizeFileName($file->getClientOriginalName());
/** @var string */
$sanitizedFileBasename = \pathinfo($sanitizedFileName, \PATHINFO_BASENAME);
/** @var string */
$sanitizedFileExtension = \pathinfo($sanitizedFileName, \PATHINFO_EXTENSION);
/** @throws \ValueError If value is not defined in enum */
$mediaExtension = MediaExtension::from($sanitizedFileExtension);
if (!$isNewMedia) {
// Supprimer les vielles images.
$media->deleteFilesOnAllPath();
}
// * New folder attribution
$media->folder = $mediaFolderName;
// * New Image, New uuid.
$media->uid = Str::uuid();
// * New Image extension
$media->extension = $mediaExtension;
// * New Image size
$media->taille = $fileSize ? $fileSize : 0;
// * Le media n'est pas une image par défaut.
$media->isDefault = false;
// * On déplace le fichier dans le répertoire des médias.
/** @throws \FileException */
$file->move($storage->path($media->folder), $media->basename);
// * Si on upload un média pour remplacer un fichier par un autre
if ($isNewMedia) {
$media->libelle = Str::limit($sanitizedFileBasename, 50, '');
$media->owner()->associate($user);
$media->dossier()->associate($dossier);
$media->sujet()->associate($sujet);
// * Par défaut FR
$media->langue()->associate(Langue::getDefaultLang());
// * Par défaut propriété de la marque
$media->copyright()->associate(Copyright::getBrandCopyright());
$media->etiquette()->associate(Etiquette::getDefaultEtiquette());
}
switch ($media->extension) {
case MediaExtension::gif:
case MediaExtension::jpeg:
case MediaExtension::jpg:
case MediaExtension::png:
case MediaExtension::ai:
case MediaExtension::pdf:
case MediaExtension::psd:
$dimensions = ToolboxHelper::getImageDimensions($media->full_path);
if ($dimensions) {
$media->resolution = $dimensions['resolutionX'];
$media->largeur = $dimensions['width'];
$media->hauteur = $dimensions['height'];
$media->largeur_mm = !empty($media->resolution) ? ceil($media->largeur * 10) : 0;
$media->hauteur_mm = !empty($media->resolution) ? ceil($media->hauteur * 10) : 0;
}
}
}
reset($objects);
rmdir($dir);
}
// ---- Creation des vignettes de base
$media->createThumbnail();
// ---- Creation des vignettes en lien avec le sujet du média
$media->createSubjectThumbnails();
break;
case MediaExtension::mp4:
if ($dimensions = ToolboxHelper::getId3VideoDimensions($media->full_path)) {
$media->largeur = $dimensions['width'];
$media->hauteur = $dimensions['height'];
}
// Fall-through .
case MediaExtension::mp3:
$media->duree = ToolboxHelper::getId3Playtime($media->full_path);
break;
} //end switch
$media->typeMedia()->associate(TypeMedia::getMediaType($media->extension));
$media->saveOrFail();
Media::flushQueryCache();
// * Get props inserted by DB.
return response()->json($media->refresh());
});
}
}

View file

@ -2,12 +2,13 @@
namespace App\Http\Controllers;
use App\User;
use App\Models\User;
use App\Models\Marque;
use App\Models\Sujet;
use Illuminate\Http\Request;
use Adldap\Laravel\Facades\Adldap;
use App\Http\Requests\DestroyUserRequest;
use App\Models\Dossier;
use App\Models\Media;
use Illuminate\Support\Facades\DB;
@ -20,7 +21,7 @@ class UserController extends Controller
*/
public function index()
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$users = User::all();
@ -36,12 +37,12 @@ class UserController extends Controller
*/
public function create()
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$roles = config('roles.label');
$marques = Marque::orderBy('libMarq', 'asc')->get();
$sujets = Sujet::where('sujet_dam', 1)->orderBy('libelle', 'asc')->get();
$sujets = Sujet::where('sujet_dam', true)->orderBy('libelle', 'asc')->get();
return view('users.create')->with([
'roles' => $roles, 'marques' => $marques,
'sujets' => $sujets
@ -56,7 +57,7 @@ class UserController extends Controller
*/
public function store(Request $request)
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$validatedData = $request->validate([
@ -122,7 +123,7 @@ class UserController extends Controller
*/
public function checkMatricule(Request $request)
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$response = [];
@ -157,7 +158,7 @@ class UserController extends Controller
/**
* Display the specified resource.
*
* @param \App\User $user
* @param \App\Models\User $user
* @return \Illuminate\Http\Response
*/
public function show(User $user)
@ -175,12 +176,12 @@ class UserController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param \App\User $user
* @param \App\Models\User $user
* @return \Illuminate\Http\Response
*/
public function edit(User $user)
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
@ -188,7 +189,7 @@ class UserController extends Controller
$userMarques = $user->marques;
$marques = Marque::orderBy('libMarq', 'asc')->get();
$userSujets = $user->sujets;
$sujets = Sujet::where('sujet_dam', 1)->orderBy('libelle', 'asc')->get();
$sujets = Sujet::where('sujet_dam', true)->orderBy('libelle', 'asc')->get();
$users = User::select(['id', 'email'])->whereIn('role', [
config('roles.const.ADMIN'), config('roles.const.CONTRIBUTEUR'),
config('roles.const.REDACTEUR')
@ -204,12 +205,12 @@ class UserController extends Controller
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\User $user
* @param \App\Models\User $user
* @return \Illuminate\Http\Response
*/
public function update(Request $request, User $user)
{
/** @var \App\User $localUser */
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
$validatedData = $request->validate([
@ -257,7 +258,7 @@ class UserController extends Controller
* Remove the specified resource from storage.
*
* @param \App\Http\Requests\DestroyUserRequest $request
* @param \App\User $user
* @param \App\Models\User $user
* @return \Illuminate\Http\Response
*/
public function destroy(DestroyUserRequest $request, User $user)
@ -266,7 +267,7 @@ class UserController extends Controller
$localUser = auth()->user();
$localUser->authorizeRoles(config('roles.const.ADMIN'));
/** @var \App\User */
/** @var \App\Models\User */
$userPourRemplacer = User::whereId($request->created_by)->firstOrFail();
try {
@ -276,8 +277,7 @@ class UserController extends Controller
$media->owner()->associate($userPourRemplacer);
$media->saveOrFail();
});
// TODO: use deleteOrFail after upgrate to laravel 8.
if ($user->delete()) {
if ($user->deleteOrFail()) {
session()->flash('success', trans('L\'utilisateur à été supprimé'));
return redirect(route('user.index'));
}
@ -294,23 +294,22 @@ class UserController extends Controller
/**
* Ajouter un dossier en favoris
*
* @param Request $request
* @param \Illuminate\Http\Request $request
* @param \App\Models\Dossier $dossier
* @return \Illuminate\Http\JsonResponse
*/
public function favorisFolder(Request $request)
public function favorisFolder(Request $request, Dossier $dossier)
{
/** @var \App\Models\User $localUser */
$localUser = auth()->user();
$dossier_id = $request->input('dossier_id');
$favoris = $request->input('favoris');
$dossierFavExists = $localUser->dossiers()
->where('id', $dossier->id)->exists();
$dossierFav = $localUser->dossiers()->where('id', $dossier_id)->first();
if ($favoris === false && $dossierFav) {
$localUser->dossiers()->detach($dossier_id);
} elseif ($favoris === true && !$dossierFav) {
$localUser->dossiers()->attach($dossier_id);
if (!$request->boolean('favoris') and $dossierFavExists) {
$localUser->dossiers()->detach($dossier->id);
} elseif ($request->boolean('favoris') and !$dossierFavExists) {
$localUser->dossiers()->attach($dossier->id);
}
return response()->json();
}

View file

@ -11,10 +11,13 @@ class Kernel extends HttpKernel
*
* These middleware are run during every request to your application.
*
* @var array
* @var array<int, class-string|string>
*/
protected $middleware = [
\App\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
@ -24,22 +27,25 @@ class Kernel extends HttpKernel
/**
* The application's route middleware groups.
*
* @var array
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
'htmlsanitize',
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
'throttle:api',
\App\Http\Middleware\JsonOnly::class,
\App\Http\Middleware\ApiResponse::class,
\App\Http\Middleware\ApiCheckTimeStamps::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class
],
];
@ -48,33 +54,19 @@ class Kernel extends HttpKernel
*
* These middleware may be assigned to groups or used individually.
*
* @var array
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
];
}

View file

@ -0,0 +1,41 @@
<?php
namespace App\Http\Middleware;
use App\Enums\Legacy\ApiError;
use App\Exceptions\Api\ApiErrorException;
use App\Lib\Helper;
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 (Helper::isRequestForApi($request)) {
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);
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace App\Http\Middleware;
use App\Enums\Legacy\ApiStatus;
use App\Http\Resources\Api\ApiResponse as ApiResponseResource;
use App\Models\Api\ApiToken;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
/**
* Make sur the response is an ApiResource resource.
*/
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\Api\ApiToken|null */
if (\optional($apiToken = app(ApiToken::class))->id) {
$apiToken->incrementStat();
}
/** @var object $data */
$data = (object)$response->getData();
// If reponse is already a ApiResponse then just return it. This happens if error handler comes into action.
if (
isset($data->status) and
isset($data->version) and
in_array($data->status, [ApiStatus::OK()->value, ApiStatus::KO()->value])
) {
return $response;
}
/** @var \App\Enums\Legacy\ApiStatus $status */
$status = intval($response->getStatusCode() / 100) == 2 ? ApiStatus::OK() : ApiStatus::KO();
return $response->setData(new ApiResponseResource((object)\optional($data)->data ?? $data, $status));
}
}

View file

@ -9,11 +9,13 @@ class Authenticate extends Middleware
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string
* @param \Illuminate\Http\Request $request
* @return string|null
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
*/
protected function redirectTo($request)
{
// phpcs:enable
if (! $request->expectsJson()) {
return route('login');
}

View file

@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
class CheckForMaintenanceMode extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
//
];
}

View file

@ -9,9 +9,7 @@ class EncryptCookies extends Middleware
/**
* The names of the cookies that should not be encrypted.
*
* @var array
* @var array<int, string>
*/
protected $except = [
//
];
protected $except = [];
}

View file

@ -0,0 +1,43 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
class HtmlSanitizer
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$params
* @return mixed
*/
public function handle(Request $request, \Closure $next, mixed ...$params)
{
$inputs = $request->all();
array_walk_recursive($inputs, function (&$input, $name) use ($params) {
if (!is_string($input)) {
return;
}
if (in_array($name, $params)) {
// ? Is a json input ?
if ($isJson = \json_decode($input, true) and is_array($isJson)) {
// ! Decode each json field recursive.
\array_walk_recursive($isJson, function (&$item) {
if (\is_string($item)) {
$item = clean($item);
}
});
} else {
$input = clean($input);
}
} else {
$input = strip_tags($input);
}
});
$request->merge($inputs);
return $next($request);
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
/**
* Allow ony json requests
*/
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);
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [];
}

View file

@ -2,7 +2,8 @@
namespace App\Http\Middleware;
use Closure;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
@ -10,15 +11,20 @@ class RedirectIfAuthenticated
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null ...$guards
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle($request, Closure $next, $guard = null)
public function handle(Request $request, \Closure $next, ...$guards)
{
if (Auth::guard($guard)->check()) {
return redirect('/');
/** @var array<string|null> */
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);

View file

@ -9,9 +9,10 @@ class TrimStrings extends Middleware
/**
* The names of the attributes that should not be trimmed.
*
* @var array
* @var array<int, string>
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];

View file

@ -0,0 +1,20 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array<int, string|null>
*/
public function hosts()
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View file

@ -2,22 +2,26 @@
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array
* @var array<int, string>|string|null
*/
protected $proxies = '*';
/**
* The headers that should be used to detect proxies.
*
* @var int
* @var integer
*/
protected $headers = Request::HEADER_X_FORWARDED_ALL;
protected $headers = Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View file

@ -6,19 +6,10 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
* @var array<int, string>
*/
protected $except = [
//
];
protected $except = [];
}

View file

@ -1,10 +1,10 @@
<?php
namespace App\Http\Requests\Bo;
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class AjaxAddMediasBasketRequest extends FormRequest
class AddMediasBasketRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
@ -13,7 +13,7 @@ class AjaxAddMediasBasketRequest extends FormRequest
*/
public function authorize()
{
return auth()->check();
return auth()->check() and $this->ajax();
}
/**
@ -25,8 +25,8 @@ class AjaxAddMediasBasketRequest extends FormRequest
{
return [
'panier_id' => 'required|exists:paniers,id,deleted_at,NULL',
'medias' => 'required|array',
'medias.*' => 'required|exists:medias,id,deleted_at,NULL'
'mediaList' => 'required|array',
'mediaList.*' => 'required|exists:media,id,deleted_at,NULL'
];
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class ApplyStickerRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'etiquette_id' => 'required|exists:etiquettes,etiquette_id',
'mediaList' => 'required|array',
'mediaList.*' => 'array|min:0',
'mediaList.*.id' => 'required|exists:media,id',
];
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use App\Models\Media;
use Illuminate\Foundation\Http\FormRequest;
class CheckRefKeyRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return \auth()->check() and $this->ajax();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'media' => Media::where('id', $this->media_id)->first()
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'media_id' => 'required|exists:media,id,deleted_at,NULL'
];
}
}

View file

@ -1,11 +1,11 @@
<?php
namespace App\Http\Requests\Bo;
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Carbon;
class AjaxCreateBasketRequest extends FormRequest
class CreateBasketRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
@ -18,7 +18,7 @@ class AjaxCreateBasketRequest extends FormRequest
'title' => $this->title ??
sprintf('Panier du %s', Carbon::now()->format('d/m/Y'))
]);
return auth()->check();
return auth()->check() and $this->ajax();
}
/**

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class DeleteMediaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'mediaList' => 'required|array',
'mediaList.*' => 'required|exists:media,id,deleted_at,NULL'
];
}
}

View file

@ -1,10 +1,10 @@
<?php
namespace App\Http\Requests\Bo;
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class AjaxDestroyBasketRequest extends FormRequest
class DestroyBasketRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
@ -13,7 +13,7 @@ class AjaxDestroyBasketRequest extends FormRequest
*/
public function authorize()
{
return auth()->check();
return auth()->check() and $this->ajax();
}
/**

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class FetchFoldersRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'sujetId' => 'required|exists:sujets,codeSujet'
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class GetArticleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return \auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'arcadia_id' => 'required|exists:articles,noArt'
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class LoadFoldersRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return \auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'sujet_id' => 'required|exists:sujets,codeSujet'
];
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class MoveMediaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'dossier_id' => 'required|numeric',
'mediaList' => 'required|array',
'mediaList.*' => 'required|array',
'mediaList.*.id' => 'required|exists:media,id',
];
}
}

View file

@ -1,10 +1,10 @@
<?php
namespace App\Http\Requests\Bo;
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class AjaxRemoveMediasBasketRequest extends FormRequest
class RemoveMediasBasketRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
@ -13,7 +13,7 @@ class AjaxRemoveMediasBasketRequest extends FormRequest
*/
public function authorize()
{
return auth()->check();
return auth()->check() and $this->ajax();
}
/**
@ -25,7 +25,7 @@ class AjaxRemoveMediasBasketRequest extends FormRequest
{
return [
'panier_id' => 'required|exists:paniers,id,deleted_at,NULL',
'media_id' => 'required|exists:medias,id,deleted_at,NULL'
'media_id' => 'required|exists:media,id,deleted_at,NULL'
];
}
}

View file

@ -1,10 +1,10 @@
<?php
namespace App\Http\Requests\Bo;
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class AjaxSaveBasketPropsRequest extends FormRequest
class SaveBasketPropsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
@ -16,7 +16,7 @@ class AjaxSaveBasketPropsRequest extends FormRequest
$this->merge([
'statut' => $this->statut ? true : false
]);
return \auth()->check();
return auth()->check() and $this->ajax();
}
/**

View file

@ -0,0 +1,47 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use App\Enums\ContactType;
use App\Rules\EnumIsValidRule;
use Illuminate\Foundation\Http\FormRequest;
class SendContactMessageRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'url' => strval($this->url),
'type' => intval($this->type)
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'type' => ['required', new EnumIsValidRule(ContactType::class)],
'url' => 'nullable|url',
'message' => 'required|string|min:20'
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class StoreMediaFileRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'media_id' => 'nullable|exists:media,id'
];
}
}

View file

@ -0,0 +1,118 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use App\Enums\MediaStatut;
use Illuminate\Foundation\Http\FormRequest;
class UpdateMediaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check() and $this->ajax();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'tags' => $this->tags ?? [],
'articles' => $this->articles ?? [],
'marques' => $this->marques ?? [],
'societes' => $this->societes ?? []
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
$rules = [
'statut' => 'required|numeric|in:' . \implode(',', collect(MediaStatut::cases())->pluck('value')->all()),
'version' => 'required|numeric|min:1',
'type_vue_id' => 'required|exists:type_vues,codeTypevue',
'variante_id' => 'required|exists:variantes,codeVariante',
'langue_id' => 'required|exists:langues,langue_id',
];
// ? Est lié à arcadia ?
if ($this->media->arcadia_id) {
// Ne pas autoriser brouillon .
$rules['statut'] = 'required|numeric|in:' . \implode(',', [
MediaStatut::public->value, MediaStatut::public_etendu->value
]);
unset($rules['version']);
unset($rules['type_vue_id']);
unset($rules['variante_id']);
unset($rules['langue_id']);
}
// Article.
if ($this->sujet_id == 1) {
$rules['articles'] = 'present|array|min:0';
$rules['articles.*'] = 'array';
$rules['articles.*.id'] = 'exists:articles,id';
}
// Marque.
if ($this->sujet_id == 2) {
$rules['marques'] = 'present|array|min:0';
$rules['marques.*'] = 'array';
$rules['marques.*.codMarq'] = 'exists:marques,codMarq';
}
// Sociétés.
if ($this->sujet_id == 4) {
$rules['societes'] = 'present|array|min:0';
$rules['societes.*'] = 'array';
$rules['societes.*.id'] = 'exists:societes,id';
}
return \array_merge($rules, [
'libelle' => 'required|string|min:2|max:50',
'commentaire' => 'nullable|string|min:2',
'copyright_id' => 'required|exists:copyrights,copyright_id',
// Tags.
'tags' => 'present|array|min:0',
'tags.*.libelle' => 'min:2|max:50',
'etiquette_id' => 'required|exists:etiquettes,etiquette_id',
]);
}
/**
* Get custom attributes for validator errors.
*
* @return array<string,string>
*/
public function attributes(): array
{
return [
'libelle' => trans('libelle'),
'commentaire' => trans('commentaire'),
'societes' => trans('societes'),
'societes.*' => trans('societes'),
'societes.*.id' => trans('societes'),
'marques' => trans('marques'),
'marques.*' => trans('marques'),
'marques.*.codMarq' => trans('marques'),
'copyright_id' => trans('copyright'),
'etiquette_id' => trans('etiquette'),
'type_vue_id' => trans('type de vue'),
'variante_id' => trans('type de variante'),
'tags' => trans('nuage de tags'),
'tags.*.libelle' => trans('libellé dans le nuage de tags'),
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Bo\Ajax;
use Illuminate\Foundation\Http\FormRequest;
class UploadMediaFileRequest 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<string, mixed>
*/
public function rules()
{
return [
'media_id' => 'nullable|exists:media,id',
'dossier_id' => 'sometimes|exists:dossiers,id'
];
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace App\Http\Requests\Bo;
class DownloadMediaPublicRequest extends DownloadMediaRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return true;
}
}

View file

@ -4,14 +4,14 @@ namespace App\Http\Requests\Bo;
use Illuminate\Foundation\Http\FormRequest;
class AjaxDeleteMediaRequest extends FormRequest
class DownloadMediaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return auth()->check();
}
@ -19,13 +19,13 @@ class AjaxDeleteMediaRequest extends FormRequest
/**
* Get the validation rules that apply to the request.
*
* @return array
* @return array<string, mixed>
*/
public function rules()
{
return [
'medias' => 'required|array',
'medias.*' => 'exists:medias,id,deleted_at,NULL'
'mediaList' => 'required|array',
'mediaList.*' => 'required|exists:media,id',
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Bo\Folders;
use Illuminate\Foundation\Http\FormRequest;
class StoreDepotFolderRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'libelle' => 'required|string|min:4|max:255|unique:dossiers,libelle',
'description' => 'nullable|string|min:4'
];
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace App\Http\Requests\Bo\Folders;
use Illuminate\Foundation\Http\FormRequest;
class StoreFolderRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth()->check();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'sub' => $this->sub ? true : false,
'is_private' => $this->status ? true : false,
'marques' => !$this->marques ? null : \explode(',', \strval($this->marques))
]);
if ($this->sub) {
$this->merge([
'is_private' => false
]);
}
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'parent_id' => 'sometimes|exists:dossiers,id',
'libelle' => 'required|string|min:4|max:255|unique:dossiers,libelle',
'description' => 'nullable|string|min:4',
'sujet' => 'required_unless:sub,true|exists:sujets,codeSujet',
'is_private' => 'required|boolean',
'marques' => 'nullable|array',
'marques.*' => 'required|exists:marques,codMarq',
'sub' => 'required|boolean'
];
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Http\Requests\Bo\Folders;
class UpdateFolderRequest extends StoreFolderRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
$rules = \array_merge(parent::rules(), [
'libelle' => 'required|string|min:4|max:255|unique:dossiers,libelle,' . $this->dossier->id,
]);
unset($rules['parent_id']);
return $rules;
}
}

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