Merge branch 'develop' into trunk

This commit is contained in:
Vincent BRIDIER 2022-03-28 10:54:30 +02:00
commit 99df59ce23
No known key found for this signature in database
GPG key ID: 8571BFA20420D512
173 changed files with 17029 additions and 85013 deletions

View file

@ -1,4 +1,4 @@
APP_NAME=Laravel
APP_NAME=DAM
APP_ENV=local
APP_KEY=
APP_DEBUG=true
@ -20,26 +20,25 @@ QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=no-reply@dam.lesidc.com
MAIL_FROM_NAME="${APP_NAME}"
MAIL_ADMIN=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
LDAP_ACCOUNT_PREFIX="cn="
LDAP_ACCOUNT_SUFFIX=",ou=users,dc=example,dc=org"
LDAP_HOSTS=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
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
ELASTICSEARCH_HOSTS=
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
MAIL_LIST_SERVICEWEB=

12
.gitignore vendored
View file

@ -1,6 +1,15 @@
/node_modules
/public/hot
/public/storage
/public/css
/public/js
/public/images
/public/fonts
/public/medias
/public/uploads
/public/assets
/public/mix-manifest.json
.vscode
public/uploads/*
!public/uploads/.gitkeep
@ -11,6 +20,9 @@ public/uploads/*
/storage/export_arcadia/*
!storage/export_arcadia/.gitkeep
/storage/arcadia_link/*
!storage/arcadia_link/.gitkeep
/storage/*.key
/vendor
.env

26
README.md Normal file
View file

@ -0,0 +1,26 @@
# DAM
## Installation
### - Default
```
npm install && npm run prod
composer install
cp .env.example .env
php artisan key:generate
```
### - Stack en attendant le bump 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
```

View file

@ -1,80 +0,0 @@
<?php
namespace App\Console\Commands;
use App\Models\Media;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
class ArcadiaLink extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'arcadialink:process';
/**
* 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('Démarrage du traitement');
$files = Storage::disk('arcadia_link_r')->files();
$bar = $this->output->createProgressBar(count($files)-1);
$bar->start();
foreach ($files as $filename) {
if($filename == ".gitignore" || $filename == ".gitkeep") continue;
// ---- Récupération du contenu
$files = Storage::disk('arcadia_link_r')->get($filename);
$fileContent = simplexml_load_string($files, null, LIBXML_NOCDATA);
$media = Media::withTrashed()->find($fileContent->code_DAM);
$media->arcadia_id = $fileContent->codeArcadia;
$media->version = $fileContent->version;
$media->isLocked = 0;
$media->save();
// Suppression dans la supervision Arcadia Link
$a = \App\Models\ArcadiaLink::where('media_id', $fileContent->code_DAM)->first();
if ($a)
$a->delete();
// ---- Index dans Elasticsearch
$media = Media::withTrashed()->find($media->id);
$esExist = Media::searchByQuery(array('match' => array('arcadia_id' => "$media->arcadia_id")));
if ($esExist->totalHits() > 0)
$media->removeFromIndex();
$media->addToIndex();
Storage::disk('arcadia_link_r')->delete($filename);
$bar->advance();
}
$bar->finish();
$this->line("");
$this->info('Fin du traitement');
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace App\Console\Commands;
use App\Jobs\Arcadia\XmlArcadiaMediasIn;
use Illuminate\Console\Command;
class ArcadiaLinkCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'arcadialink:process';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Lecture du flux Arcadia entrant (medias). Run the XmlArcadiaMediasIn manually';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Running the Job, this could take some time.');
$job = new XmlArcadiaMediasIn();
$job->console = $this;
$job->handle();
$this->line("");
$this->info('Fin du traitement');
}
}

View file

@ -143,7 +143,7 @@ class ImportMedia extends Command
} else {
// on applique une image par défaut
$record->extension = "jpg";
Storage::disk('local')->copy("images/default.jpg", $destinationPath . $record->uid . '.' . $record->extension);
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));

View file

@ -0,0 +1,67 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Media;
class ReindexElasticMedia extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:reindex';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Reindex la base médias dans Elasticsearch';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Reindexation de la base médias dans Elasticsearch...');
$this->info('Test Présence...');
if (Media::indexExists()) {
$this->info('Suppression index...');
Media::deleteIndex();
}
$this->info('Création...');
Media::createIndex();
$pageNumber = 0;
$perPage = 200;
/** @var \Illuminate\Pagination\LengthAwarePaginator $medias */
$medias = Media::paginate($perPage);
$bar = $this->output->createProgressBar(count($medias));
$bar->start($medias->total());
// * LOOP
do {
if ($pageNumber > 0) {
/** @var \Illuminate\Pagination\LengthAwarePaginator $medias */
$medias = Media::paginate($perPage, ['*'], 'page', $pageNumber);
}
foreach ($medias as $media) {
$media->addToIndex();
$bar->advance();
}
++$pageNumber;
} while ($medias->hasMorePages());
$bar->finish();
$this->line('');
$this->info('Fin du traitement');
}
}

View file

@ -1,81 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Media;
class reindexElasticMedia extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'medias:reindex {injectfrom?}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Reindex la base médias dans Elasticsearch';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Reindexation de la base médias dans Elasticsearch...');
$bReprise = false;
$startFrom = $this->argument('injectfrom');
if($startFrom != "") {
$bReprise = true;
} else {
$startFrom = 1;
}
$this->info('Test Présence...');
if (Media::indexExists() && !$bReprise) {
$this->info('Suppression index...');
Media::deleteIndex();
}
if(!$bReprise) {
$this->info('Création...');
Media::createIndex();
}
$medias = Media::all();
$bar = $this->output->createProgressBar(count($medias));
$bar->start();
if($bReprise)
$bar->advance($startFrom);
$i=1;
foreach ($medias as $media) {
if($i >= $startFrom) {
// ---- index le media dans Elasticsearch
$media->addToIndex();
$bar->advance();
}
unset($media);
$i++;
}
$bar->finish();
$this->line("");
$this->info('Fin du traitement');
}
}

View file

@ -2,6 +2,8 @@
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;
@ -13,19 +15,19 @@ class Kernel extends ConsoleKernel
* @var array
*/
protected $commands = [
//
ArcadiaLinkCommand::class
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
$schedule->job(XmlArcadiaMediasIn::class)->name('arcadia_medias_in')
->onOneServer()->cron('*/2 * * * *');
}
/**
@ -35,7 +37,7 @@ class Kernel extends ConsoleKernel
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}

17
app/Enums/LogType.php Normal file
View file

@ -0,0 +1,17 @@
<?php
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
{
}

View file

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

View file

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

View file

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

View file

@ -93,11 +93,14 @@ class MediaController extends Controller
]);
}
public function show(Request $request) {
$uid = $request->uid;
$media = Media::where('uid', $uid)->first();
if (!$media)
abort(404);
/**
* Show media
*
* @param Media $media
* @return \Illuminate\Http\RedirectResponse
*/
public function show(Media $media)
{
return redirect()->route('media_manager')->with('autoOpen', $media);
}
@ -214,42 +217,44 @@ class MediaController extends Controller
]
]
]);
$esFilters = array_merge($esFilters, array(
[
'bool' => [
'should' => [
[
'bool' => [
'must_not' => [
[
'term' => [
'statut' => [
'value' => config('services.statut.brouillon'),
'boost' => 1.0
/** @var \App\Models\User $user */
$user = auth()->user();
if (!$user->hasRole(config('roles.const.ADMIN'))) {
$esFilters = array_merge($esFilters, array(
[
'bool' => [
'should' => [
[
'bool' => [
'must_not' => [
[
'term' => [
'statut' => [
'value' => config('services.statut.brouillon'),
'boost' => 1.0
]
]
]
]
],
'adjust_pure_negative' => true,
'boost' => 1.0
]
],
[
'term' => [
'created_by' => [
'value' => $userId,
],
'adjust_pure_negative' => true,
'boost' => 1.0
]
],
[
'term' => [
'created_by' => [
'value' => $userId,
'boost' => 1.0
]
]
]
]
],
'adjust_pure_negative' => true,
'boost' => 1.0
],
'adjust_pure_negative' => true,
'boost' => 1.0
]
]
]
));
));
}//end if
} else { // dossier dépôt
$isDepot = 1;
$esMust = array_merge($esMust, [
@ -896,7 +901,7 @@ class MediaController extends Controller
$destinationPath = $this->get_mediaFolder() . "/";
$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));
$filename = $uid . ".jpg";
Storage::copy("images/default.jpg", $destinationPath . $filename);
Storage::copy("assets/images/default.jpg", $destinationPath . $filename);
$n->arcadia_id = NULL;
$n->libelle = (strlen($n->libelle) + 5) >= 50 ? substr($n->libelle, 0, -((strlen($n->libelle) - 50) + 5)) . '_copy' : $n->libelle . '_copy';

View file

@ -0,0 +1,284 @@
<?php
namespace App\Jobs\Arcadia;
use App\Enums\LogType;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
abstract class XArcadiaFlux implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
/**
* The Laravel disk name
*
* @var string
*/
protected $disk = null;
/**
* This is for Laravel Console usage
* @var \Illuminate\Console\Command|null
*/
public $console = null;
/**
* This is for Laravel Console usage
* @var \Symfony\Component\Console\Helper\ProgressBar|null
*/
public $progressBar = null;
/**
* The relative folder where to archive data
*
* @var string
*/
private $archiveFolderName = 'archives';
/**
* The files to ignore
*
* @var array
*/
protected $ignoreFiles = [
'.gitignore', '.gitkeep'
];
/**
* Check if the file extension
*
* @param string $filename
* @param string $extension
* @return boolean
*/
protected function checkExtension(string $filename, string $extension): bool
{
$isExtension = strtolower(pathinfo($filename, \PATHINFO_EXTENSION)) === $extension;
if (!$isExtension) {
Log::warning(sprintf(
'%s : unwanted file type in %s wanted %s',
get_class($this),
$filename,
$extension
));
}
return $isExtension;
}
/**
* Move the file to archives
*
* @param string $filename
* @return void
*/
protected function moveToArchives(string $filename): void
{
$newFileName = $filename;
if (!$this->getDisk()->exists($filename)) {
$this->log(
sprintf(
'File %s could not be moved to archives (not found)',
$filename
),
LogType::warning()
);
return;
}
if ($this->getDisk()->exists(sprintf('%s/%s', $this->archiveFolderName, $filename))) {
$ext = \pathinfo($filename, \PATHINFO_EXTENSION);
$newFileName = \sprintf(
'%s_%d.%s',
\substr($filename, 0, 0 - (strlen($ext) + 1)),
\time(),
$ext
);
}
try {
if (!$this->getDisk()->move($filename, sprintf('%s/%s', $this->archiveFolderName, $newFileName))) {
$this->log(
sprintf(
'File %s could not be moved to archives',
$filename
),
LogType::warning()
);
}
} catch (\Exception $e) {
$this->log(
sprintf(
'File %s could not be moved to archives',
$filename
),
LogType::warning()
);
}
}
/**
* Suppression des fichiers dans
* archives qui ont plus de 2j
*
* @return void
*/
protected function clearOldArchives(): void
{
$disk = $this->getDisk();
$archives = $disk->files($this->archiveFolderName);
// /** @var File */
foreach ($archives as $archive) {
$pi = \pathinfo($archive, \PATHINFO_BASENAME);
if (in_array($pi, $this->ignoreFiles)) {
continue;
}
if ($disk->lastModified($archive) < strtotime(Carbon::now()->subDays(2))) {
if (!$disk->delete($archive)) {
Log::critical(sprintf('%s : Could not delete file %s', get_class($this), $archive));
};
}
}
}
/**
* Get the concerned disk
*
* @return Filesystem
*/
protected function getDisk(): Filesystem
{
return Storage::disk($this->disk);
}
/**
* Logs data
*
* @param string $message
* @param LogType $logtype
* @return void
* @throws \ErrorException If logtype is not handled.
*/
protected function log(string $message, LogType $logtype = null): void
{
if (!$logtype) {
$logtype = LogType::debug();
}
$message = sprintf('%s : %s', get_class($this), $message);
switch ($logtype->value) {
case LogType::debug()->value:
Log::debug($message);
break;
case LogType::info()->value:
Log::info($message);
break;
case LogType::log()->value:
Log::log($message);
break;
case LogType::warning()->value:
Log::warning($message);
break;
case LogType::error()->value:
Log::error($message);
break;
case LogType::critical()->value:
Log::critical($message);
break;
default:
throw new \ErrorException(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label));
} //end switch
$this->consolePrint($message, $logtype);
}
/**
* Prints to the console
*
* @param string $message
* @param LogType $logtype
* @return void
* @throws \ErrorException If logtype is not handled.
*/
protected function consolePrint(string $message, LogType $logtype): void
{
$this->clearProgressBarFromLine();
if ($this->console) {
switch ($logtype->value) {
case LogType::debug()->value:
case LogType::info()->value:
case LogType::log()->value:
$this->console->info($message);
break;
case LogType::warning()->value:
$this->console->comment($message);
break;
case LogType::error()->value:
case LogType::critical()->value:
$this->console->error($message);
break;
default:
throw new \ErrorException(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label));
}
}
}
/**
* Start ProgressBar
*
* @param integer $total
* @return void
*/
protected function startProgressBar(int $total)
{
if ($this->console) {
$this->progressBar = $this->console->getOutput()
->createProgressBar($total - 1);
$this->progressBar->start();
}
}
/**
* Clear the line to write someting
*
* @return void
*/
protected function clearProgressBarFromLine()
{
if ($this->progressBar) {
$this->progressBar->clear();
}
}
/**
* Increment 1 on progress bar
*
* @return void
*/
protected function incrementProgressBar()
{
if ($this->progressBar) {
$this->progressBar->advance();
}
}
/**
* End the progress bar
*
* @return void
*/
protected function endProgressBar()
{
if ($this->progressBar) {
$this->progressBar->finish();
}
}
}

View file

@ -0,0 +1,145 @@
<?php
namespace App\Jobs\Arcadia;
use App\Exceptions\AbortXmlImportException;
use App\Exceptions\ElasticSearchException;
use App\Lib\Utils;
use App\Models\ArcadiaLink;
use App\Models\Media;
use Illuminate\Database\Eloquent\ModelNotFoundException;
class XmlArcadiaMediasIn extends XmlJobs
{
/**
* The xsd file path used to validate files
*
* @var string|null
*/
protected $xsdSchemaPath = 'resources/documents/arcadia/incoming_medias.xsd';
/**
* Disk name from config/filesystems.php
*
* @var string
*/
protected $disk = 'arcadia_link_r';
/**
* The columns to take from the XML subcolumns can be added with a dot
*
* @var array
*/
protected $takeColumns = [
'code_DAM' => 'id',
'codeArcadia' => 'arcadia_id',
'version' => 'version'
];
/**
* The columns allowed to be null
*
* @var array
*/
protected $nullableFields = [];
/**
* Fields that are unique
*
* @var array
*/
protected $uniqueKeyField = [
'id'
];
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
$this->parseData('MEDIA_VISUEL', Media::class, function (\SimpleXMLElement $xmlData, array &$line) {
// * After XML parse Callback.
// * Unlock media
$line['isLocked'] = 0;
}, function (array $uniqueColumnsKey, $line) {
// * DO the DB save yourself callback
try {
/** @var \App\Models\Media $media */
$media = Media::withTrashed()->where($uniqueColumnsKey)->firstOrFail();
$media->arcadia_id = $line['arcadia_id'];
$media->version = $line['version'];
$media->isLocked = 0;
$media->saveOrFail();
} catch (ModelNotFoundException $e) {
$e = new AbortXmlImportException(
sprintf('La fiche media \'%s\' ne peut être trouvé', \json_encode($uniqueColumnsKey)),
0,
1,
__FILE__,
__LINE__,
$e
);
throw $e;
}//end try
//phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
}, function (\SimpleXMLElement $xmlData, array &$line) {
// * After DB save Callback.
$media = null;
try {
/** @var \App\Models\Media $media */
$media = Media::withTrashed()->findOrFail($line['id']);
} catch (ModelNotFoundException $e) {
$e = new AbortXmlImportException(
"La fiche media '%s' ne peut être trouvé",
0,
1,
__FILE__,
__LINE__,
$e
);
throw $e;
}
try {
// * Suppression dans la supervision Arcadia Link
$arcadiaLink = ArcadiaLink::whereHas('media', function ($q) use ($media) {
$q->whereId($media->id);
})->first();
if ($arcadiaLink) {
$arcadiaLink->delete();
}
// * Index ElasticSearch
$esExist = Media::searchByQuery([
'match' => ['arcadia_id' => $media->arcadia_id ?? '']
]);
// * Remove all from elastic if any duplicates
if ($esExist->totalHits() > 0) {
$media->removeFromIndex();
}
// * Save into elastic
$media->addToIndex();
} catch (\Exception $e) {
$report = new ElasticSearchException(
'Something went wrong when updating media into elastic search',
0,
__FILE__,
__LINE__,
$e
);
// ! Someting went wrong
report($report);
// ! TODO: Remove this after adding kwaadpepper/exception-handler.
Utils::sendEmailErrorManually($report);
throw new AbortXmlImportException($report->getMessage());
} //end try
});
}
}

View file

@ -0,0 +1,467 @@
<?php
namespace App\Jobs\Arcadia;
use App\Enums\LogType;
use App\Exceptions\AbortXmlImportException;
use App\Exceptions\InvalidXmlException;
use App\Lib\Utils;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
abstract class XmlJobs extends XArcadiaFlux
{
/**
* The xsd file path used to validate files
*
* @var string|null
*/
protected $xsdSchemaPath = null;
/**
* The xsd file content used to validate files
*
* @var string|null
*/
protected $xsdSchema = null;
/**
* invalid xml folder
*
* @var string
*/
protected $invalidFolderName = 'invalid';
/**
* The columns to take from the XML
* subcolumns can be added with a dot
*
* @var array
*/
protected $takeColumns = [];
/**
* The columns allowed to be null
*
* @var array
*/
protected $nullableFields = [];
/**
* Need to encapsulate the freeking XML
* Because provided one is dirty
*
* @var boolean
*/
protected $encapsulate = false;
/**
* Parse Data from the XML and gives it to the callback
*
* @param string $entityName
* @param string $modelClass
* @param callable $afterParseCallback After parse is done.
* @param callable $saveCallback Instead of updateOrCreate, execute $saveCallback.
* @param callable $afterSaveCallback After save is done.
* @return void
* @throws InvalidXmlException If xml file is not valid.
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded
*/
protected function parseData(
string $entityName,
string $modelClass,
callable $afterParseCallback = null,
callable $saveCallback = null,
callable $afterSaveCallback = null
): void {
/** @var Filesystem */
$disk = $this->getDisk();
$this->log('Démarrage du traitement');
$this->assertXsdIsHereIfAny();
$files = $disk->files();
$total = count(array_filter($files, function ($filename) {
if ($this->fileHasToBeIgnored($filename)) {
return false;
}
return true;
}));
$this->startProgressBar($total);
foreach ($files as $filename) {
if ($this->fileHasToBeIgnored($filename)) {
continue;
}
$this->incrementProgressBar();
try {
/** @var string $data */
$data = $disk->get($filename);
$this->validateXmlFile($filename, $data);
try {
if ($this->encapsulate) {
$data = sprintf('<Root>%s</Root>', $data);
/** @var \SimpleXMLElement|false */
$xmlContent = $data;
} else {
/** @var \SimpleXMLElement|false */
$xmlContent = simplexml_load_string($data, null, LIBXML_NOCDATA | LIBXML_PARSEHUGE);
}
if ($xmlContent === false) {
throw new InvalidXmlException('XML is Invalid (simplexml_load_string returned false)');
}
} catch (\ErrorException $e) {
throw new InvalidXmlException('XML is Invalid', 0, $e);
}
$data = $this->extract($xmlContent);
$lines = [];
// * Multiple Entities within file
if (isset($data[$entityName])) {
foreach ($data[$entityName] as $traca) {
$line = $this->processFields($traca);
if ($afterParseCallback) {
$afterParseCallback($xmlContent, $line);
}
$lines[] = $line;
}
} else {
// * Only one entity within file
$line = $this->processFields($data);
if ($afterParseCallback) {
$afterParseCallback($xmlContent, $line);
}
$lines[] = $line;
}
// * Mise en base des données
foreach ($lines as $line) {
/** @var array Unique Key columns */
$uniqueColumnsKey = [];
foreach ($this->uniqueKeyField as $uField) {
$uniqueColumnsKey[$uField] = $line[$uField];
}
if (count($uniqueColumnsKey)) {
if ($saveCallback) {
$saveCallback($uniqueColumnsKey, $line);
} else {
forward_static_call_array(
[$modelClass, 'updateOrCreate'],
[$uniqueColumnsKey, $line]
);
}
if ($afterSaveCallback) {
$afterSaveCallback($xmlContent, $line);
}
}
} //end foreach
} catch (InvalidXmlException $e) {
$message = $e->getMessage();
$this->log(
sprintf(
'File %s could not be parsed => %s on line %d',
$filename,
$message,
$e->getLine()
),
LogType::critical()
);
$this->sendInvalidXmlEmail($filename, $e);
$this->moveToInvalid($filename);
continue;
} catch (AbortXmlImportException $e) {
$this->log(
sprintf(
'ERROR: File %s could not be parsed => %s on line %d',
$filename,
$e->getMessage(),
$e->getLine()
),
LogType::error()
);
report($e);
// ! TODO: Remove this after adding kwaadpepper/exception-handler.
Utils::sendEmailErrorManually($e);
continue;
// * ignore the file
} catch (QueryException $e) {
$this->log(implode(' ', $e->errorInfo), LogType::critical());
report($e);
// ! TODO: Remove this after adding kwaadpepper/exception-handler.
Utils::sendEmailErrorManually($e);
continue;
} catch (FileNotFoundException $e) {
// This happens because of concurent xml jobs read.
$message = $e->getMessage();
$this->log(
sprintf(
'ERROR: File %s could not be read (not found) => %s on line %d',
$filename,
$message,
$e->getLine()
),
LogType::debug()
);
continue;
// * ignore the file
} catch (\Exception | \ErrorException | \TypeError $e) {
$this->log(
sprintf(
'File %s could not be parsed => %s on line %d',
$filename,
$e->getMessage(),
$e->getLine()
),
LogType::critical()
);
report($e);
// ! TODO: Remove this after adding kwaadpepper/exception-handler.
Utils::sendEmailErrorManually($e);
continue;
// * ignore the file
} //end try
$this->moveToArchives($filename);
} //end foreach
// Clear old archives.
$this->clearOldArchives();
$this->endProgressBar();
}
/**
* Recursive extract to array
*
* @param \SimpleXMLElement|false $sxe
* @return array
*/
protected function extract($sxe = null): array
{
if (!$sxe instanceof \SimpleXMLElement) {
return array();
}
$extract = array();
foreach ($sxe->children() as $key => $value) {
if ($value->count()) {
$extract[$key][] = $this->extract($value);
continue;
}
$value = strval($value);
if (array_key_exists($key, $extract) and is_array($extract[$key])) {
$extract[$key][] = strlen($value) ? $value : null;
} else {
$extract[$key] = strlen($value) ? $value : null;
}
}
return $extract;
}
/**
* Process fields to gather data
*
* @param array $fields
* @return array
* @throws AbortXmlImportException If a field could not be validated.
*/
protected function processFields(array $fields): array
{
$result = [];
foreach ($fields as $key => $field) {
if (!($key = $this->shouldFieldBeConsidered($key))) {
continue;
}
if (!$this->isFieldNullable($key) && is_null($field)) {
throw new AbortXmlImportException(sprintf('The field %s is not allowed to be null', $key));
}
if (is_array($field)) {
// * Flatten data
$it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($field));
foreach ($it as $k => $f) {
$ko = strtolower(sprintf('%s.%s', $key, $k));
if (!$this->isFieldNullable($ko) && is_null($f)) {
throw new AbortXmlImportException(sprintf(
'%s : The field %s is not allowed to be null',
get_class($this),
$ko
));
}
if (!($k = $this->shouldFieldBeConsidered($ko))) {
continue;
}
$result[$k] = $f;
}
} else {
$result[$key] = $field;
}
} //end foreach
return $result;
}
/**
* Is the filed nullable
*
* @param string $key
* @return boolean
*/
private function isFieldNullable(string $key): bool
{
if (in_array($key, $this->nullableFields)) {
return true;
}
return false;
}
/**
* - replace key name with the corresponding alias
* - strtolower the key
* - snake_case the key
*
* @param string $key
* @return string|false
*/
private function shouldFieldBeConsidered(string $key)
{
$key = strtolower($key);
foreach ($this->takeColumns as $k => $alias) {
if (strtolower($k) === $key) {
return Str::snake(strtolower($alias));
}
}
return false;
}
/**
* Is the file to be ignored
*
* @param string $filename
* @return boolean
*/
protected function fileHasToBeIgnored(string $filename): bool
{
return in_array($filename, $this->ignoreFiles) or !$this->checkExtension($filename, 'xml');
}
/**
* Check if the file is an xml file
*
* @param string $filename
* @return boolean
*/
protected function isFileXml(string $filename): bool
{
$isXml = strtolower(pathinfo($filename, \PATHINFO_EXTENSION)) === 'xml';
if (!$isXml) {
Log::warning(sprintf('%s : unwanted file type in %s', get_class($this), $filename));
}
return $isXml;
}
/**
* Send invalid XML email
*
* @param string $filename
* @param \Throwable $e
* @return void
*/
protected function sendInvalidXmlEmail(string $filename, \Throwable $e)
{
$message = $e->getPrevious()->getMessage();
Mail::send('mails.invalidxml', [
'strError' => sprintf(
'File %s could not be parsed => %s on line %d',
$filename,
$message,
$e->getLine()
),
'filename' => $filename,
'exception' => $e->getPrevious()
], function ($m) {
$m->to(
config('mail.contactsList.invalidXml'),
'XML Exception Handler'
)->subject('You sent me an invalid XML file, please check its validity before resend ASAP.');
});
}
/**
* Move the file to invalid folder
*
* @param string $filename
* @return void
*/
protected function moveToInvalid(string $filename): void
{
if (!$this->getDisk()->move($filename, sprintf('%s/%s', $this->invalidFolderName, $filename))) {
$this->log(
sprintf(
'File %s could not be moved to invalid folder name',
$filename
),
LogType::warning()
);
}
}
/**
* Assert XSD is readable if configured
*
* @return void
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException If xsd file cant be read.
*/
private function assertXsdIsHereIfAny()
{
if ($this->xsdSchemaPath) {
$this->xsdSchema = File::get($this->xsdSchemaPath);
}
}
/**
* Validate Xml file against XSD if loaded
*
* @param string $fileName
* @param string $fileContent
* @return void
* @throws InvalidXmlException If XML could not be parsed or validated against XSD.
* @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
*/
private function validateXmlFile(string $fileName, string $fileContent)
{
if ($this->xsdSchema) {
$domDocument = new \DOMDocument('1.0', 'UTF-8');
try {
if (!$domDocument->loadXML($fileContent)) {
throw new InvalidXmlException("XML Validation $fileName content could not be loaded to validate.");
}
if (!$domDocument->schemaValidateSource($this->xsdSchema, LIBXML_SCHEMA_CREATE)) {
throw new InvalidXmlException(
"XML Validation $fileName content could not be validated against xsd."
);
}
} catch (\Exception $e) {
if (\get_class($e) === InvalidXmlException::class) {
throw $e;
}
throw new InvalidXmlException(
"XML Validation $fileName content could not be validated against xsd.",
0,
1,
__FILE__,
__LINE__,
$e
);
} //end try
}//end if
}
}

129
app/Lib/Utils.php Normal file
View file

@ -0,0 +1,129 @@
<?php
namespace App\Lib;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
/**
* Some utilities methods
*
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
*/
class Utils
{
/**
* Manually send an exception to team instead of going trough the error handler
* (requires package kwaadpepper/exception-handler)
*
* @param \Throwable $e
* @return void
*/
public static function sendEmailErrorManually(\Throwable $e)
{
Mail::send([
'html' => 'exception-handler.exception',
'text' => 'exception-handler.exception-plain'
], [
'appName' => config('app.name'),
'code' => $e->getCode(),
'line' => $e->getLine(),
'ename' => \get_class($e),
'emessage' => self::getAnonymizedMessage($e->getMessage()),
'file' => str_replace(\realpath(\sprintf('%s/../', \app_path())), '', $e->getFile()),
'stackTrace' => self::getAnonymizedStackTrace($e),
'uri' => app()->runningInConsole() ?
'CONSOLE' : (
(request() and request()->fullUrl()) ?
request()->fullUrl() : 'none')
], function ($m) {
/** @var \Illuminate\Mail\Message $m */
$m->to(
config('mail.contactsList.serviceweb'),
sprintf('%s Exception Handler', config('app.name'))
)->subject('Need help !, an error occured in your application, please check Logs ASAP');
});
Log::alert(sprintf('Envoie d\'une erreur par mail : %s', json_encode($e)));
}
/**
* Anonymize at least Sql queries
*
* @param string $message
* @return string
*/
private static function getAnonymizedMessage(string $message): string
{
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
return $message;
}
/**
* Anonymize stack trace
*
* @param \Exception $e
* @return string
*/
private static function getAnonymizedStackTrace(\Throwable $e): string
{
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
$traceStack = $e->getTrace();
$traceStr = '';
$maxStackStage = 0;
foreach ($traceStack as $stackStage => $stack) {
$maxStackStage = $stackStage;
$traceStr .= \sprintf(
'#%s %s(%d): ',
$stackStage,
str_replace($projectPath, '', $stack['file'] ?? ''),
$stack['line'] ?? ''
);
if (isset($stack['class'])) {
$traceStr .= "{$stack['class']}->{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
} elseif (isset($stack['function'])) {
$traceStr .= "{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
}
}
$maxStackStage++;
$traceStr .= "#$maxStackStage {main}";
return $traceStr;
}
/**
* Handle Args
*
* @param array $stack
* @return string
*/
private static function handleArgs(array $stack): string
{
$traceArgs = '';
$argsCount = count($stack['args']);
for ($i = 0; $i < $argsCount; $i++) {
$type = \gettype($stack['args'][$i]);
switch ($type) {
case 'object':
$traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i]));
break;
case 'array':
$traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i]));
break;
case 'string':
$traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i]));
break;
default:
$traceArgs .= \gettype($stack['args'][$i]);
}
$traceArgs .= ($i !== ($argsCount - 1) ? ',' : '');
}
return $traceArgs;
}
}

View file

@ -7,15 +7,46 @@ use Carbon\Carbon;
class ArcadiaLink extends Model
{
/**
* *The table associated with the model.
*
* @var string
*/
protected $table = 'arcadia_link';
public function getDateFAttribute() {
// * GETTERS
/**
* Get dateF attribute
*
* @return string
* @phpcs:disable Generic.NamingConventions.CamelCapsFunctionName.ScopeNotCamelCaps
*/
public function getDateFAttribute()
{
return Carbon::createFromFormat('Y-m-d H:i:s', $this->created_at)->format('d/m/Y H:i:s');
}
public function getMediaUuidAttribute() {
/**
* Get mediaUuid attribute
*
* @return string|null
*/
public function getMediaUuidAttribute()
{
$m = Media::find($this->media_id);
return $m->uid;
}
// * RELATIONSHIPS
/**
* BelongsTo media relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function media()
{
return $this->belongsTo(Media::class);
}
}

View file

@ -2,97 +2,150 @@
namespace App\Models;
use App\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
class Dossier extends Model
{
protected $with = ["sousdossiers"];
protected $appends = array('favoris', 'mediacount');
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $with = [
'sousdossiers'
];
/**
* Get user favoris
*/
public function getFavorisAttribute()
{
$userId = Auth::user()->id;
if($this->users()->where('id', $userId)->first()){
return true;
}else{
return false;
}
}
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = [
'favoris', 'mediacount'
];
/**
* Get media linked
*/
public function getMediacountAttribute()
{
$userId = Auth::user()->id;
// * GETTERS
if($this->parent_id != 1 && $this->id != 1){ // dossier classic
return $this->medias()
->where(function ($query) use ( $userId ) {
$query->where('statut', '<>', config('services.statut.brouillon'))
->orWhere('created_by', $userId);
})
->count();
}else{ // dossier dépôt
return $this->medias()->count();
}
}
/**
* Get user favoris
*
* @return boolean
*/
public function getFavorisAttribute(): bool
{
$userId = Auth::user()->id;
if ($this->users()->where('id', $userId)->first()) {
return true;
} else {
return false;
}
}
/**
* The marques that belong to the dossier.
*/
public function marques()
{
return $this->belongsToMany('App\Models\Marque', 'marques_dossiers', 'dossier_id', 'marque_id');
}
/**
* Get media linked
*
* @return integer
*/
public function getMediacountAttribute(): int
{
/** @var \App\Model\User $user */
$user = Auth::user();
/**
// * dossier classic
if ($this->parent_id != 1 && $this->id != 1) {
if ($user->hasRole(config('roles.const.ADMIN'))) {
return $this->medias()->count();
} else {
return $this->medias()
->where('statut', '<>', config('services.statut.brouillon'))
->orWhere('created_by', $user->id)->count();
}
} else {
// * dossier dépôt
return $this->medias()->count();
}
}
// * RELATIONSHIPS
/**
* BelongsToMany marque relation
* The marques that belong to the dossier.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function marques()
{
return $this->belongsToMany(Marque::class, 'marques_dossiers', 'dossier_id', 'marque_id');
}
/**
* BelongsTo sujet relation
* Get the sujet that owns the dossier.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function sujet()
{
return $this->belongsTo('App\Models\Sujet', 'sujet_id');
return $this->belongsTo(Sujet::class, 'sujet_id');
}
/**
* Get the dossier for the sujet.
*/
public function medias()
{
return $this->hasMany('App\Models\Media', 'dossier_id', 'id');
}
/**
* HasMany media relation
* Get the dossier for the sujet.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function medias()
{
return $this->hasMany(Media::class, 'dossier_id', 'id');
}
/**
/**
* HasMany dossier relation
* Get the dossiers for the parent.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function sousdossiers()
{
return $this->hasMany('App\Models\Dossier', 'parent_id');
return $this->hasMany(Dossier::class, 'parent_id');
}
/**
* Get the parent that owns the dossiers.
*/
public function dossierParent()
{
return $this->belongsTo('App\Models\Dossier', 'id', 'parent_id');
}
/**
* BelongsTo dossier relation
* Get the parent that owns the dossiers.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function dossierParent()
{
return $this->belongsTo(Dossier::class, 'id', 'parent_id');
}
/**
* BelongsToMany user relation
* The users that belong to the dossier.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users()
{
return $this->belongsToMany(User::class, 'dossiers_users', 'dossier_id', 'user_id');
}
/**
* The users that belong to the dossier.
*/
public function users()
{
return $this->belongsToMany('App\User', 'dossiers_users', 'dossier_id', 'user_id');
}
// * METHODS
public static function getDossierBySujetid($sujetId)
{
return Dossier::where('sujet_id', $sujetId)->whereNull('parent_id')->get();
}
/**
* Find Dossier by subject id
*
* @param integer $sujetId
* @return Dossier|null
*/
public static function getDossierBySujetid(int $sujetId)
{
return Dossier::where('sujet_id', $sujetId)->whereNull('parent_id')->get();
}
}

View file

@ -2,28 +2,51 @@
namespace App\Models;
use App\Http\Controllers\CommunController;
use App\Http\Controllers\MediaController;
use App\Http\Traits\ElasticTrait;
use App\User;
use Elasticquent\ElasticquentTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Elasticquent\ElasticquentTrait;
use Illuminate\Support\Facades\DB;
class Media extends Model
{
use ElasticquentTrait;
use ElasticquentTrait;
use ElasticTrait;
use SoftDeletes;
protected $with = ["owner", "tags", "etiquette", "articles", "sujet", "typemedia", "societes", "marques"];
protected $table = "medias";
use SoftDeletes;
/**
* The elasticsearch settings.
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'medias';
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $indexSettings = [
protected $with = [
'owner', 'tags', 'etiquette', 'articles', 'sujet',
'typemedia', 'societes', 'marques'
];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
// ! id est obligatoire ici pour Jobs/XmlArcadiaMediasIn
'id'
];
/**
* ES The elasticsearch settings.
*
* @var array
*/
protected $indexSettings = [
'analysis' => [
'char_filter' => [
'replace' => [
@ -70,173 +93,223 @@ class Media extends Model
]
],
];
/**
* ES Mapping Properties
*
* @var array
*/
protected $mappingProperties = array(
'libelle' => array(
'type' => 'text',
'analyzer' => 'default',
'fields' => array(
'keyword' => array(
'fields' => [
'keyword' => [
'type' => 'keyword',
'normalizer' => 'my_normalizer'
)
),
]
],
'fielddata' => true
),
'commentaire' => array(
'type' => 'text',
'analyzer' => 'default',
'fields' => array(
'keyword' => array(
'fields' => [
'keyword' => [
'type' => 'keyword',
'normalizer' => 'my_normalizer'
)
),
]
],
'fielddata' => true
),
'created_at' => array(
'created_at' => [
'type' => 'date',
"format" => "yyyy-MM-dd HH:mm:ss",
//'fielddata' => true
),
'updated_at' => array(
// 'fielddata' => true
],
'updated_at' => [
'type' => 'date',
"format" => "yyyy-MM-dd HH:mm:ss",
//'fielddata' => true
),
'version' => array(
// 'fielddata' => true
],
'version' => [
'type' => 'text',
'fielddata' => true
),
'arcadia_id' => array(
],
'arcadia_id' => [
'type' => 'text',
'analyzer' => 'standard'
),
'articles.noArt' => array(
],
'articles.noArt' => [
'type' => 'text',
'analyzer' => 'standard'
),
'articles.libCcial' => array(
],
'articles.libCcial' => [
'type' => 'text',
'analyzer' => 'default',
'fields' => array(
'keyword' => array(
'fields' => [
'keyword' => [
'type' => 'keyword',
'normalizer' => 'my_normalizer'
)
),
]
],
'fielddata' => true
)
]
);
/**
// * RELATIONSHIPS
/**
* BelongsTo dossier relation
* Get the dossier that owns the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function dossier()
{
return $this->belongsTo('App\Models\Dossier', 'dossier_id');
return $this->belongsTo(Dossier::class, 'dossier_id');
}
/**
* Get the sujet that owns the media.
*/
public function sujet()
{
return $this->belongsTo('App\Models\Sujet', 'sujet_id');
}
/**
* BelongsTo sujet relation
* Get the sujet that owns the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function sujet()
{
return $this->belongsTo(Sujet::class, 'sujet_id');
}
/**
* Get the typemedia that owns the media.
*/
public function typemedia()
{
return $this->belongsTo('App\Models\Typemedia', 'typemedia_id');
}
/**
* BelongsTo typemedia relation
* Get the typemedia that owns the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function typemedia()
{
return $this->belongsTo(Typemedia::class, 'typemedia_id');
}
/**
* Get the typevue that owns the media.
*/
public function typevue()
{
return $this->belongsTo('App\Models\Typevue', 'typevue_id');
}
/**
* BelongsTo typevue relation
* Get the typevue that owns the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function typevue()
{
return $this->belongsTo(Typevue::class, 'typevue_id');
}
/**
* Get the langue that owns the media.
*/
public function langue()
{
return $this->belongsTo('App\Models\Langue', 'typevue_id');
}
/**
* BelongsTo langue relation
* Get the langue that owns the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function langue()
{
return $this->belongsTo(Langue::class, 'typevue_id');
}
/**
* Get the copyright that owns the media.
*/
public function copyright()
{
return $this->belongsTo('App\Models\Copyright', 'copyright_id');
}
/**
* BelongsTo copyright relation
* Get the copyright that owns the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function copyright()
{
return $this->belongsTo(Copyright::class, 'copyright_id');
}
/**
* Get the etiquette that owns the media.
*/
public function etiquette()
{
return $this->belongsTo('App\Models\Etiquette', 'etiquette_id');
}
/**
* BelongsTo etiquette relation
* Get the etiquette that owns the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function etiquette()
{
return $this->belongsTo(Etiquette::class, 'etiquette_id');
}
/**
* The tag that belong to the media.
*/
public function tags()
{
return $this->belongsToMany('App\Models\Tag', 'medias_tags', 'media_id', 'tag_id');
}
/**
* BelongsToMany tags relation
* The tags that belong to the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany(Tag::class, 'medias_tags', 'media_id', 'tag_id');
}
/**
* The articles that belong to the media.
*/
public function articles()
{
return $this->belongsToMany('App\Models\Article', 'medias_articles', 'media_id', 'article_id');
}
/**
* BelongsToMany articles relation
* The articles that belong to the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function articles()
{
return $this->belongsToMany(Article::class, 'medias_articles', 'media_id', 'article_id');
}
/**
* The societes that belong to the media.
*/
public function societes()
{
return $this->belongsToMany('App\Models\Societe', 'medias_societes', 'media_id', 'societe_id');
}
/**
* BelongsToMany societes relation
* The societes that belong to the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function societes()
{
return $this->belongsToMany(Societe::class, 'medias_societes', 'media_id', 'societe_id');
}
/**
* The marques that belong to the media.
*/
public function marques()
{
return $this->belongsToMany('App\Models\Marque', 'medias_marques', 'media_id', 'marque_id');
}
/**
* BelongsToMany marques relation
* The marques that belong to the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function marques()
{
return $this->belongsToMany(Marque::class, 'medias_marques', 'media_id', 'marque_id');
}
/**
* Get the user that owns the media.
*/
public function owner()
{
return $this->belongsTo('App\User', 'created_by');
}
/**
* BelongsTo user relation
* Get the user that owns the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function owner()
{
return $this->belongsTo(User::class, 'created_by');
}
/**
* Get the historiques for the media.
*/
public function historiques()
{
return $this->hasMany('App\Models\Historique');
}
/**
* HasMany historiques relation
* Get the historiques for the media.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function historiques()
{
return $this->hasMany(Historique::class);
}
/**
* The paniers that belong to the media.
*/
public function paniers()
{
return $this->belongsToMany('App\Models\Panier', 'paniers_medias', 'media_id', 'panier_id');
}
/**
* BelongsToMany paniers relation
* The paniers that belong to the media.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function paniers()
{
return $this->belongsToMany(Panier::class, 'paniers_medias', 'media_id', 'panier_id');
}
}

View file

@ -2,6 +2,7 @@
namespace App\Providers;
use App\Models\Media;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
@ -23,7 +24,9 @@ class RouteServiceProvider extends ServiceProvider
*/
public function boot()
{
//
Route::bind('media', function ($value) {
return Media::whereUid($value)->firstOrFail();
});
parent::boot();
}
@ -36,10 +39,7 @@ class RouteServiceProvider extends ServiceProvider
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
//
}
/**

View file

@ -9,14 +9,16 @@
"license": "MIT",
"require": {
"php": "^7.1.3",
"ext-json": "*",
"adldap2/adldap2-laravel": "^6.0",
"elasticquent/elasticquent": "dev-master",
"fideloper/proxy": "^4.0",
"james-heinrich/getid3": "^1.9",
"kwaadpepper/enum": "^2.1",
"laravel/framework": "5.8.*",
"laravel/tinker": "^1.0",
"laravelcollective/html": "^5.8",
"elasticquent/elasticquent": "dev-master",
"ext-json": "*"
"slevomat/coding-standard": "^7.0"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.2",
@ -30,7 +32,10 @@
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"extra": {
"laravel": {

309
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9814a710aa897e03292972471ff75050",
"content-hash": "68a7a8d32fb9300acb3a4735c3bb1580",
"packages": [
{
"name": "adldap2/adldap2",
@ -117,6 +117,81 @@
],
"time": "2019-06-28T17:34:46+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "dnoegel/php-xdg-base-dir",
"version": "0.1",
@ -859,6 +934,66 @@
],
"time": "2019-02-07T17:30:03+00:00"
},
{
"name": "kwaadpepper/enum",
"version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/Kwaadpepper/enum.git",
"reference": "bbd08723895cad5a41bc0d57e565fe64fa13ca41"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Kwaadpepper/enum/zipball/bbd08723895cad5a41bc0d57e565fe64fa13ca41",
"reference": "bbd08723895cad5a41bc0d57e565fe64fa13ca41",
"shasum": ""
},
"require": {
"php": "^7.3"
},
"require-dev": {
"orchestra/testbench": "^5",
"phpunit/php-code-coverage": "^9.2",
"phpunit/phpunit": "~9.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Kwaadpepper\\Enum\\EnumServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Kwaadpepper\\Enum\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jérémy Munsch",
"email": "github@jeremydev.ovh",
"homepage": "https://jeremydev.ovh"
}
],
"description": "Enums to use for any project",
"homepage": "https://github.com/kwaadpepper/enum",
"keywords": [
"enum",
"laravel"
],
"support": {
"issues": "https://github.com/Kwaadpepper/enum/issues",
"source": "https://github.com/Kwaadpepper/enum/tree/2.1.2"
},
"time": "2021-11-18T16:52:08+00:00"
},
{
"name": "laravel/framework",
"version": "v5.8.30",
@ -1573,6 +1708,55 @@
],
"time": "2015-07-25T16:39:46+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "dbc093d7af60eff5cd575d2ed761b15ed40bd08e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/dbc093d7af60eff5cd575d2ed761b15ed40bd08e",
"reference": "dbc093d7af60eff5cd575d2ed761b15ed40bd08e",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.2.0"
},
"time": "2021-09-16T20:46:02+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
@ -1919,6 +2103,123 @@
],
"time": "2019-01-07T21:25:54+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.0.19",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "bef66a43815bbf9b5f49775e9ded3f7c6ba0cc37"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/bef66a43815bbf9b5f49775e9ded3f7c6ba0cc37",
"reference": "bef66a43815bbf9b5f49775e9ded3f7c6ba0cc37",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.1 || ^8.0",
"phpstan/phpdoc-parser": "^1.0.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.2",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.6",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0",
"phpstan/phpstan-strict-rules": "1.1.0",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.16"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.0.19"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-03-01T18:01:41+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.6.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2021-12-12T21:44:58+00:00"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v6.2.1",
@ -5343,7 +5644,9 @@
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": "^7.1.3"
"php": "^7.1.3",
"ext-json": "*"
},
"platform-dev": []
"platform-dev": [],
"plugin-api-version": "2.2.0"
}

View file

@ -14,7 +14,7 @@ return array(
*/
'config' => [
'hosts' => ['http://127.0.0.1:9200'],
'hosts' => explode(",", env('ELASTICSEARCH_HOSTS')),
'retries' => 1,
],

View file

@ -114,7 +114,7 @@ return [
|
*/
'account_prefix' => env('LDAP_ACCOUNT_PREFIX', 'uid='),
'account_prefix' => env('LDAP_ACCOUNT_PREFIX'),
/*
|--------------------------------------------------------------------------
@ -127,7 +127,7 @@ return [
|
*/
'account_suffix' => env('LDAP_ACCOUNT_SUFFIX', ',ou=Users,dc=Comptes,dc=com'),
'account_suffix' => env('LDAP_ACCOUNT_SUFFIX'),
/*
|--------------------------------------------------------------------------
@ -143,7 +143,7 @@ return [
|
*/
'hosts' => explode(' ', env('LDAP_HOSTS', 'dtys05403.svlidc.com')),
'hosts' => explode(' ', env('LDAP_HOSTS')),
/*
|--------------------------------------------------------------------------
@ -183,7 +183,7 @@ return [
|
*/
'base_dn' => env('LDAP_BASE_DN', 'ou=Users,dc=Comptes,dc=com'),
'base_dn' => env('LDAP_BASE_DN'),
/*
|--------------------------------------------------------------------------
@ -198,8 +198,8 @@ return [
|
*/
'username' => env('LDAP_USERNAME', 'uid=tp9900153,ou=Users,dc=Comptes,dc=com'),
'password' => env('LDAP_PASSWORD', 'EH3Un2ah2019'),
'username' => env('LDAP_USERNAME'),
'password' => env('LDAP_PASSWORD'),
/*
|--------------------------------------------------------------------------

View file

@ -3,56 +3,56 @@
return [
/*
|--------------------------------------------------------------------------
| Mail Driver
|--------------------------------------------------------------------------
|
| Laravel supports both SMTP and PHP's "mail" function as drivers for the
| sending of e-mail. You may specify which one you're using throughout
| your application here. By default, Laravel is setup for SMTP mail.
|
| Supported: "smtp", "sendmail", "mailgun", "mandrill", "ses",
| "sparkpost", "postmark", "log", "array"
|
|--------------------------------------------------------------------------
| Mail Driver
|--------------------------------------------------------------------------
|
| Laravel supports both SMTP and PHP's "mail" function as drivers for the
| sending of e-mail. You may specify which one you're using throughout
| your application here. By default, Laravel is setup for SMTP mail.
|
| Supported: "smtp", "sendmail", "mailgun", "ses",
| "postmark", "log", "array"
|
*/
'driver' => env('MAIL_DRIVER', 'smtp'),
'driver' => env('MAIL_MAILER', 'smtp'),
/*
|--------------------------------------------------------------------------
| SMTP Host Address
|--------------------------------------------------------------------------
|
| Here you may provide the host address of the SMTP server used by your
| applications. A default option is provided that is compatible with
| the Mailgun mail service which will provide reliable deliveries.
|
|--------------------------------------------------------------------------
| SMTP Host Address
|--------------------------------------------------------------------------
|
| Here you may provide the host address of the SMTP server used by your
| applications. A default option is provided that is compatible with
| the Mailgun mail service which will provide reliable deliveries.
|
*/
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
/*
|--------------------------------------------------------------------------
| SMTP Host Port
|--------------------------------------------------------------------------
|
| This is the SMTP port used by your application to deliver e-mails to
| users of the application. Like the host we have set this value to
| stay compatible with the Mailgun e-mail application by default.
|
|--------------------------------------------------------------------------
| SMTP Host Port
|--------------------------------------------------------------------------
|
| This is the SMTP port used by your application to deliver e-mails to
| users of the application. Like the host we have set this value to
| stay compatible with the Mailgun e-mail application by default.
|
*/
'port' => env('MAIL_PORT', 587),
/*
|--------------------------------------------------------------------------
| Global "From" Address
|--------------------------------------------------------------------------
|
| You may wish for all e-mails sent by your application to be sent from
| the same address. Here, you may specify a name and address that is
| used globally for all e-mails that are sent by your application.
|
|--------------------------------------------------------------------------
| Global "From" Address
|--------------------------------------------------------------------------
|
| You may wish for all e-mails sent by your application to be sent from
| the same address. Here, you may specify a name and address that is
| used globally for all e-mails that are sent by your application.
|
*/
'from' => [
@ -61,27 +61,27 @@ return [
],
/*
|--------------------------------------------------------------------------
| E-Mail Encryption Protocol
|--------------------------------------------------------------------------
|
| Here you may specify the encryption protocol that should be used when
| the application send e-mail messages. A sensible default using the
| transport layer security protocol should provide great security.
|
|--------------------------------------------------------------------------
| E-Mail Encryption Protocol
|--------------------------------------------------------------------------
|
| Here you may specify the encryption protocol that should be used when
| the application send e-mail messages. A sensible default using the
| transport layer security protocol should provide great security.
|
*/
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
/*
|--------------------------------------------------------------------------
| SMTP Server Username
|--------------------------------------------------------------------------
|
| If your SMTP server requires a username for authentication, you should
| set it here. This will get used to authenticate with your server on
| connection. You may also set the "password" value below this one.
|
|--------------------------------------------------------------------------
| SMTP Server Username
|--------------------------------------------------------------------------
|
| If your SMTP server requires a username for authentication, you should
| set it here. This will get used to authenticate with your server on
| connection. You may also set the "password" value below this one.
|
*/
'username' => env('MAIL_USERNAME'),
@ -89,27 +89,27 @@ return [
'password' => env('MAIL_PASSWORD'),
/*
|--------------------------------------------------------------------------
| Sendmail System Path
|--------------------------------------------------------------------------
|
| When using the "sendmail" driver to send e-mails, we will need to know
| the path to where Sendmail lives on this server. A default path has
| been provided here, which will work well on most of your systems.
|
|--------------------------------------------------------------------------
| Sendmail System Path
|--------------------------------------------------------------------------
|
| When using the "sendmail" driver to send e-mails, we will need to know
| the path to where Sendmail lives on this server. A default path has
| been provided here, which will work well on most of your systems.
|
*/
'sendmail' => '/usr/sbin/sendmail -bs',
/*
|--------------------------------------------------------------------------
| Markdown Mail Settings
|--------------------------------------------------------------------------
|
| If you are using Markdown based email rendering, you may configure your
| theme and component paths here, allowing you to customize the design
| of the emails. Or, you may simply stick with the Laravel defaults!
|
|--------------------------------------------------------------------------
| Markdown Mail Settings
|--------------------------------------------------------------------------
|
| If you are using Markdown based email rendering, you may configure your
| theme and component paths here, allowing you to customize the design
| of the emails. Or, you may simply stick with the Laravel defaults!
|
*/
'markdown' => [
@ -121,16 +121,22 @@ return [
],
/*
|--------------------------------------------------------------------------
| Log Channel
|--------------------------------------------------------------------------
|
| If you are using the "log" driver, you may specify the logging channel
| if you prefer to keep mail messages separate from other log entries
| for simpler reading. Otherwise, the default channel will be used.
|
|--------------------------------------------------------------------------
| Log Channel
|--------------------------------------------------------------------------
|
| If you are using the "log" driver, you may specify the logging channel
| if you prefer to keep mail messages separate from other log entries
| for simpler reading. Otherwise, the default channel will be used.
|
*/
'log_channel' => env('MAIL_LOG_CHANNEL'),
// * Contacts List
'contactsList' => [
'invalidXml' => env('MAIL_LIST_SERVICEWEB', 'equipe.web@ldc.fr'),
'serviceweb' => env('MAIL_LIST_SERVICEWEB', 'equipe.web@ldc.fr')
],
];

25002
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,35 +2,35 @@
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "npm run development -- --watch",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"wp": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
"production": "mix --production"
},
"devDependencies": {
"axios": "^0.18",
"bootstrap": "^4.0.0",
"cross-env": "^5.1",
"jquery": "^3.2",
"laravel-mix": "^4.0.7",
"lodash": "^4.17.5",
"@fortawesome/fontawesome-free": "^6.1.1",
"axios": "^0.26.1",
"bootstrap": "^4.6.1",
"clean-webpack-plugin": "^4.0.0",
"core-js": "^3.21.1",
"jquery": "^3.6",
"laravel-mix": "^6.0.43",
"laravel-mix-polyfill": "^3.0.1",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"popper.js": "^1.12",
"resolve-url-loader": "^2.3.1",
"sass": "^1.15.2",
"sass-loader": "^7.1.0",
"vue": "^2.5.17",
"vue-template-compiler": "^2.6.10"
},
"dependencies": {
"popper.js": "^1.16.1-lts",
"resolve-url-loader": "^5.0.0",
"resumablejs": "^1.1.0",
"sass": "^1.32.13",
"sass-loader": "^8.0.2",
"vue": "^2.6.14",
"vue-clipboards": "^1.3.0",
"vue-dialog-loading": "^0.5.3",
"vue-infinite-loading": "^2.4.4",
"vue-select": "^3.10.3",
"vuex": "^3.4.0"
"vue-dialog-loading": "^0.1.7",
"vue-infinite-loading": "^2.4.5",
"vue-select": "^3.18.3",
"vue-template-compiler": "^2.6.14",
"vuex": "^3.6.2"
}
}

129
phpcs.xml Normal file
View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="LDC Laravel"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
<description>Created with the PHP Coding Standard Generator. http://edorian.github.com/php-coding-standard-generator/</description>
<arg name="colors" />
<arg name="extensions" value="php" />
<file>app/</file>
<file>config/</file>
<file>database/factories</file>
<file>routes/</file>
<file>tests/</file>
<rule ref="PSR1" />
<rule ref="PSR12" />
<rule ref="Generic.Classes.DuplicateClassName"/>
<rule ref="Generic.CodeAnalysis.EmptyStatement"/>
<rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
<rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
<rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
<rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>
<rule ref="Generic.Commenting.Todo"/>
<rule ref="Generic.Commenting.Fixme"/>
<rule ref="Generic.ControlStructures.InlineControlStructure"/>
<rule ref="Generic.Files.ByteOrderMark"/>
<rule ref="Generic.Files.LineEndings"/>
<rule ref="Generic.Files.LineLength"/>
<rule ref="Generic.Formatting.DisallowMultipleStatements"/>
<rule ref="Generic.Formatting.MultipleStatementAlignment"/>
<rule ref="Generic.Formatting.NoSpaceAfterCast"/>
<rule ref="Generic.Functions.CallTimePassByReference"/>
<rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
<rule ref="Generic.Metrics.CyclomaticComplexity"/>
<rule ref="Generic.Metrics.NestingLevel"/>
<rule ref="Generic.NamingConventions.ConstructorName"/>
<rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
<rule ref="Generic.NamingConventions.CamelCapsFunctionName"/>
<rule ref="Generic.PHP.DeprecatedFunctions"/>
<rule ref="Generic.PHP.DisallowShortOpenTag"/>
<rule ref="Generic.PHP.ForbiddenFunctions"/>
<rule ref="Generic.PHP.NoSilencedErrors"/>
<rule ref="Generic.Strings.UnnecessaryStringConcat"/>
<rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
<rule ref="Generic.WhiteSpace.ScopeIndent"/>
<rule ref="MySource.PHP.EvalObjectFactory"/>
<rule ref="MySource.PHP.GetRequestData"/>
<rule ref="MySource.PHP.AjaxNullComparison"/>
<rule ref="PEAR.Classes.ClassDeclaration"/>
<rule ref="PEAR.Commenting.InlineComment"/>
<rule ref="PSR1.Classes.ClassDeclaration"/>
<rule ref="PSR1.Files.SideEffects"/>
<rule ref="PSR2.Classes.ClassDeclaration"/>
<rule ref="PSR2.Classes.PropertyDeclaration"/>
<rule ref="PSR2.ControlStructures.ElseIfDeclaration"/>
<rule ref="PSR2.ControlStructures.SwitchDeclaration"/>
<rule ref="PSR2.Files.EndFileNewline"/>
<rule ref="PSR2.Methods.MethodDeclaration"/>
<rule ref="PSR2.Namespaces.NamespaceDeclaration"/>
<rule ref="PSR2.Namespaces.UseDeclaration"/>
<rule ref="Squiz.PHP.CommentedOutCode"/>
<rule ref="Squiz.PHP.DisallowMultipleAssignments">
<exclude name="Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure" />
</rule>
<rule ref="Squiz.PHP.DisallowSizeFunctionsInLoops"/>
<rule ref="Squiz.PHP.DiscouragedFunctions">
<properties>
<property name="error" value="true"/>
</properties>
</rule>
<rule ref="Squiz.PHP.Eval"/>
<rule ref="Squiz.PHP.GlobalKeyword"/>
<rule ref="Squiz.PHP.Heredoc"/>
<rule ref="Squiz.PHP.InnerFunctions"/>
<rule ref="Squiz.PHP.LowercasePHPFunctions"/>
<rule ref="Squiz.PHP.NonExecutableCode"/>
<rule ref="Squiz.Scope.MemberVarScope"/>
<rule ref="Squiz.Scope.MethodScope"/>
<rule ref="Squiz.Scope.StaticThisUsage"/>
<rule ref="Squiz.WhiteSpace.LanguageConstructSpacing"/>
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>
<rule ref="Squiz.WhiteSpace.MemberVarSpacing">
<properties>
<property name="spacingBeforeFirst " value="false"/>
</properties>
</rule>
<rule ref="Squiz.WhiteSpace.OperatorSpacing">
<properties>
<property name="ignoreNewlines" value="true"/>
</properties>
</rule>
<rule ref="Squiz.WhiteSpace.ObjectOperatorSpacing">
<properties>
<property name="ignoreNewlines" value="true"/>
</properties>
</rule>
<rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing"/>
<rule ref="Squiz.WhiteSpace.SemicolonSpacing"/>
<rule ref="Squiz.Commenting.BlockComment">
<exclude name="Squiz.Commenting.BlockComment.WrongStart" />
</rule>
<rule ref="Squiz.Commenting.ClassComment">
<exclude name="Squiz.Commenting.ClassComment.Missing" />
<exclude name="Squiz.Commenting.ClassComment.TagNotAllowed" />
</rule>
<rule ref="Squiz.Commenting.DocCommentAlignment"/>
<rule ref="Squiz.Commenting.EmptyCatchComment"/>
<rule ref="Squiz.Commenting.FunctionComment">
<exclude name="Squiz.Commenting.FunctionComment.MissingParamComment" />
</rule>
<rule ref="Squiz.Commenting.FunctionCommentThrowTag"/>
<rule ref="Squiz.Commenting.InlineComment">
<exclude name="Squiz.Commenting.InlineComment.DocBlock" />
</rule>
<rule ref="Squiz.Commenting.LongConditionClosingComment">
<exclude name="Squiz.Commenting.LongConditionClosingComment.SpacingBefore" />
</rule>
<rule ref="Squiz.Commenting.PostStatementComment"/>
<rule ref="Squiz.Commenting.VariableComment"/>
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse" />
<!-- For Laravel migrations -->
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
<exclude-pattern>*/database/migrations/*</exclude-pattern>
</rule>
</ruleset>

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View file

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View file

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

34
public/css/app.css vendored

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 678 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
public/js/app.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +0,0 @@
{
"/js/app.js": "/js/app.js",
"/css/app.css": "/css/app.css"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<Image xmlns="http://schemas.microsoft.com/deepzoom/2008"
Format="png"
Overlap="2"
TileSize="256" >
<Size Height="9221"
Width="7026"/>
</Image>

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- < XSD deviné, basé sur la BDD et cette seule affirmation "les 3 champs sont obligatoires" @author Jérémy Munsch jeremy.munsch@ldc.fr > -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="MEDIA_VISUEL">
<xs:complexType>
<xs:sequence>
<xs:element name="codeArcadia" type="_positive_unsigned_integer_without_leading_zeros" />
<xs:element name="code_DAM" type="_positive_unsigned_integer_without_leading_zeros"/>
<xs:element name="version" type="_positive_unsigned_integer_without_leading_zeros"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="_positive_unsigned_integer_without_leading_zeros">
<xs:restriction base="xs:positiveInteger">
<xs:pattern value="[123456789]\d*"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

4
resources/js/app.js vendored
View file

@ -264,7 +264,7 @@ $.fancyConfirm = function( opts ) {
src :
'<div class="fc-content">' +
'<h3>' + opts.title + '</h3><hr/>' +
'<p class="tcenter"><i class="fal fa-question-circle"></i>' +
'<p class="tcenter"><i class="fa fa-question-circle"></i>' +
opts.message + '</p>' +
'<hr/><p class="button_bar">' +
'<a data-value="0" data-fancybox-close class="btn btn-black mr-10 btn-square" >' + opts.noButton + '</a>' +
@ -306,7 +306,7 @@ $.fancyMessage = function( opts ) {
src :
'<div class="fc-content '+opts.type+'">' +
'<h3>' + opts.title + '</h3><hr/>' +
'<p class="tcenter"><i class="fal fa-info-circle"></i></i><i class="fal fa-exclamation-triangle"></i>' +
'<p class="tcenter"><i class="fa fa-info-circle"></i></i><i class="fa fa-exclamation-triangle"></i>' +
opts.message + '</p>' +
'<hr/><p class="button_bar">' +
'<a data-value="0" data-fancybox-close class="btn btn-square '+

View file

@ -4,7 +4,7 @@
<a href="#" @click="download" class="action_download_media"><i class="fas fa-file-download"></i> Télécharger</a>
<!--<a v-if="storeRole === 1 || storeRole === 4" href="#" class="action_delete_media"><i class="fas fa-trash-alt"></i> Supprimer</a>-->
<a v-if="storeRole !== 2" @click="duplicateMedia" href="#" class="action_duplicate_media"><i
class="far fa-copy"></i> Dupliquer</a>
class="fa fa-copy"></i> Dupliquer</a>
<a v-if="storeRole !== 2" @click="applySticker" href="#" class="action_tag_media"><i class="fas fa-tags"></i>
Etiquette</a>
@ -48,7 +48,7 @@
<div v-for="(file, key) in files">
<div>
<span>{{file.fileName}}</span>
<button v-on:click="removeFile(file)" class="cancel"><i class="fal fa-times"></i></button>
<button v-on:click="removeFile(file)" class="cancel"><i class="fa fa-times"></i></button>
</div>
<div>
<span>{{FileConvertSize(file.size)}}</span>

View file

@ -5,7 +5,7 @@
<select id="panier_selector" v-model="selectedBasket">
<option v-for="item in storeBaskets" :value="item">{{item.libelle}}</option>
</select>
<a id="menu_panier" href="#" class="btn btn-square"><i class="far fa-bars"></i></a>
<a id="menu_panier" href="#" class="btn btn-square"><i class="fa fa-bars"></i></a>
<div class="panier_menu">
<ul class="menu-options">
<!--
@ -28,9 +28,9 @@
<div v-if="media.typemedia_id === 3" class="media video"></div>
<div v-if="media.typemedia_id === 4" class="media son"></div>
<div class="bar">
<a href="#" class="media_info" @click="openMedia(media)"><i class="far fa-info-circle"></i></a>
<a href="#" class="media_info" @click="openMedia(media)"><i class="fa fa-info-circle"></i></a>
<a href="#" class="media_remove_basket" @click="removeMedia(media.id)"><i
class="far fa-times-circle"></i></a>
class="fa fa-times-circle"></i></a>
</div>
</div>
</div>

View file

@ -1,10 +1,11 @@
<template>
<div>
<div v-show="scrollLoader" class="scrollLoader"><div class="animated slideInUp"><i class="fal fa-circle-notch fa-spin"></i> Chargements des médias</div></div>
<div v-show="scrollLoader" class="scrollLoader"><div class="animated slideInUp"><i class="fa fa-circle-notch fa-spin"></i> Chargements des médias</div></div>
<div class="media_container">
<div v-show="loader" class="loader"><i class="fal fa-circle-notch fa-spin"></i></div>
<div v-show="loader" class="loader"><i class="fa fa-circle-notch fa-spin"></i></div>
<div class="wrapper" v-if="medias.data">
<div v-if="showDateSeparators()" class="date-separator">{{formatDate(medias.data[0].updated_at)}}</div>
<div v-if="showDateSeparators() && medias.data.length" class="date-separator">{{formatDate(medias.data[0].updated_at)}}</div>
<div v-else class="noresult" >Aucun résultat</div>
<template v-for="media,index in medias.data">
<div v-if="showDateSeparators() && !isSameDay(media,medias.data[Math.max(index-1,0)])" class="date-separator">{{formatDate(media[dateSorted])}}</div>
<div @dragstart="dragStart(media, $event)" v-on:dblclick="edit(media)" @click="select(media)" :class=" isCAQuery && media.id !== lastVersion.id ? 'imageItem not-last-version' : 'imageItem'" :draggable="medias.draggable" :aria-grabbed="storeGrabbed.filter(e => e.id === media.id).length > 0">
@ -110,6 +111,11 @@
init() {
this.offset = 0;
this.resetInfiniteScroll();
// * Reset selected on component load
this.$store.commit({
type: 'updateGrabbed',
grabbed: []
});
this.loadMedias(this.$store.state);
//set dateSorted
this.dateSorted = false;
@ -131,10 +137,6 @@
}
},
loadMedias($state) {
this.$store.commit({
type: 'updateGrabbed',
grabbed: []
});
if (this.offset === 0){
this.medias = [];
this.loader = true;
@ -257,5 +259,8 @@
</script>
<style scoped>
.noresult {
padding: 5rem;
font-size: 2rem;
}
</style>

View file

@ -44,7 +44,7 @@
<div class="filter_wrapper">
<span>Filtres :</span>
<div class="search_filters_list">
<a v-for="(filter, index) in storeFilters" :id="filter.type" class="filter_item" href="#"><span class="libelle">{{ filter.legend }}</span><span class="value">{{ filter.libelle }}</span><i @click="deleteFilter(index)" class="delete_filter fal fa-times"></i></a>
<a v-for="(filter, index) in storeFilters" :id="filter.type" class="filter_item" href="#"><span class="libelle">{{ filter.legend }}</span><span class="value">{{ filter.libelle }}</span><i @click="deleteFilter(index)" class="delete_filter fa fa-times"></i></a>
</div>
<a v-if="storeFilters.length > 0" @click="reset" class="reinit_search_btn" href="#">Réinitialiser</a>
</div>

View file

@ -1,7 +1,7 @@
<template>
<div class="folder_container">
<div :style="isLoading === true ? 'display:block' : 'display:none;'" class="loader">
<i class="fal fa-circle-notch fa-spin"></i>
<i class="fa fa-circle-notch fa-spin"></i>
</div>
<a href="#" @click="selectFolder({id: 0, libelle: 'racine'})" ondragstart="return false;"
:class="storeFolder === 0 ? 'root_folder selected' : 'root_folder'" data-id="0">/racine <span class="count">{{racineCount}}</span></a>
@ -16,7 +16,7 @@
<input type="text" value="" class="input_rename" maxlength="100">
<span>{{item.libelle}}</span>
<div class="count">{{item.mediacount}}</div>
<i v-if="item.system === 0" :class="item.favoris === true ? 'fas fa-star' : 'fal fa-star'"
<i v-if="item.system === 0" :class="item.favoris === true ? 'fas fa-star' : 'fa fa-star'"
@click="toggleFav(item)"></i>
</div>
<ol v-if="item.sousdossiers.length > 0" class='dd-list' :parent-id="item.id">
@ -30,7 +30,7 @@
<span>{{item2.libelle}}</span>
<div class="count">{{item2.mediacount}}</div>
<i v-if="item2.system === 0"
:class="item2.favoris === true ? 'fas fa-star' : 'fal fa-star'"
:class="item2.favoris === true ? 'fas fa-star' : 'fa fa-star'"
@click="toggleFav(item2)"></i>
</div>
<ol v-if="item2.sousdossiers.length > 0" class='dd-list' :parent-id="item2.id">
@ -45,7 +45,7 @@
<span>{{item3.libelle}}</span>
<div class="count">{{item3.mediacount}}</div>
<i v-if="item3.system === 0"
:class="item3.favoris === true ? 'fas fa-star' : 'fal fa-star'"
:class="item3.favoris === true ? 'fas fa-star' : 'fa fa-star'"
@click="toggleFav(item3)"></i>
</div>
</li>
@ -89,12 +89,7 @@
watch: {
storeSujet() {
this.initFolders();
},
storeFolder() {
if (this.storeFolder === 0) {
this.selectFolder({id: 0, libelle: 'racine'});
}
},
}
},
methods: {
initFolders(toSelectFolder = false) {
@ -113,14 +108,17 @@
if (toSelectFolder !== false){
this.selectFolder(toSelectFolder);
} else {
// ! Reset Current folder to none selected
this.$store.state.folder = -1
}
}).catch(function (error) {
console.log(error);
});
},
renderItems() {
const favs = this.oFolders.filter(item => item.favoris === true);
const favs = this.oFolders.filter(item => item.favoris === true),
self = this
favs.forEach(item => {
this.folders.push(item);
@ -130,6 +128,14 @@
this.folders.push(item);
}
});
this.$nextTick(() => {
self.oFolders.forEach(item => {
if (item.favoris === false) {
self.folders.push(item);
self.toggle(item)
}
})
})
},
selectFolder(item) {
let filter = this.storeFilters.findIndex(e => e.type === 'dossier_id');
@ -224,7 +230,11 @@
}
},
toggle(item) {
$("[parent-id='"+ item.id +"']").toggle();
const self = this
$("[parent-id='"+ item.id +"']").toggle(300, () => {
// * Force rerender classes on folders
self.$forceUpdate()
})
}
}
}

View file

@ -8,11 +8,11 @@
<a href="#" @click="currentTab = 'links'" :class="currentTab === 'links' ? 'tabbtn form_media_links active' : 'tabbtn form_media_links'" data-tab="2">Vignettes</a>
<a href="#" @click="currentTab = 'history'" :class="currentTab === 'history' ? 'tabbtn form_media_history active' : 'tabbtn form_media_history'" data-tab="3">Historique</a>
<a @click="close" href="#" class="form_media_close"><i class="fal fa-times"></i></a>
<a @click="close" href="#" class="form_media_close"><i class="fa fa-times"></i></a>
<a href="#" class="float-right mr-10 copyclipboard" v-clipboard="'https://dam.lesidc.com/media/' + this.storeMedia.uid" title="Copier le lien"><i class="fas fa-link"></i></a>
<a v-show="currentTab === 'edit' && storeMedia.isLocked === 0" @click="$refs.newMedia.click()" href="#" class="form_media_replace" title="Chargez un autre média"><i class="fas fa-file-upload"></i></a>
</div>
<a v-show="this.storeMedia.dossier_id === 1" @click="close" href="#" class="form_media_close"><i class="fal fa-times"></i></a>
<a v-show="this.storeMedia.dossier_id === 1" @click="close" href="#" class="form_media_close"><i class="fa fa-times"></i></a>
</header>
<div class="main_content">
<mm-me-tab-preview :currentTab="currentTab"></mm-me-tab-preview>
@ -56,12 +56,12 @@
},
mounted() {
console.log('EditComponent Mounted.');
// if (this.open !== undefined) { TODO : REMOVE ?
// this.$store.commit({
// type: 'updateMedia',
// media: JSON.parse(this.open)
// });
// }
if (this.open !== undefined) {
this.$store.commit({
type: 'updateMedia',
media: JSON.parse(this.open)
});
}
},
computed: {
storeMedia () {
@ -143,7 +143,6 @@
});
},
close(){
console.log('close click')
this.$store.commit({
type: 'updateMedia',
media: { close: true, isModified: this.storeMedia.isModified }

View file

@ -10,14 +10,14 @@
<button @click="ArcadiaLink"
v-if="this.oMedia.arcadia_id === null && this.oMedia.isLocked === 0"
class="btn btn-square btn-arcadia-link" type="button" name="button"><i
class="far fa-link"></i> Lier avec Arcadia
class="fa fa-link"></i> Lier avec Arcadia
</button>
<span v-if="this.oMedia.isLocked === 1"
class="is-locked">En attente de liaison Arcadia</span>
</div>
</div>
<div class="row">
<label>Sujet <span>*</span> : {{this.oMedia.sujet.libelle}}</label>
<div class="row" v-if="oMedia.arcadia_id">
<label>Sujet <span>*</span> : {{this.oMedia.sujet ? this.oMedia.sujet.libelle : '' }}</label>
<label>Type de média <span>*</span> : {{this.oMedia.typemedia.libelle}}</label>
<label>Date de création : {{this.oMedia.created_at}}</label>
<label>Date de modification : {{this.oMedia.updated_at}}</label>
@ -109,7 +109,7 @@
<td class="col_gencodSymb">{{item.codGencodSymb}}</td>
<td class="col_gencodPds">{{item.codGencodPds}}</td>
<td><a @click="DeleteArticles(item.id)" href="#" class="remove_article"><i
class="far fa-times"></i></a></td>
class="fa fa-times"></i></a></td>
</tr>
</tbody>
<tfoot>
@ -120,7 +120,7 @@
</table>
<br/>
<button class="add_article btn btn-black btn-square floatr" type="button" name="button"
@click="AddArticles"><i class="far fa-plus"></i> Ajouter
@click="AddArticles"><i class="fa fa-plus"></i> Ajouter
</button>
</div>
</div>

View file

@ -45,7 +45,11 @@
},
watch: {
storeMedia() {
if (Object.keys(this.storeMedia).length > 0 && (this.storeMedia.history === undefined)){
if (
this.storeMedia.id &&
Object.keys(this.storeMedia).length > 0 &&
(this.storeMedia.history === undefined)
){
const _this2 = this;
axios.post('/ajax/get-media-others-infos', {
media_id: this.storeMedia.id

View file

@ -18,8 +18,8 @@
<input type="text" readonly :value="item.url">
</td>
<td class="ctas">
<i class="fal fa-copy" v-clipboard="item.url"></i>
<a :href="item.url" :download="storeMedia.libelle.replaceAll(' ', '_').replaceAll('.','') + '_' + item.largeur + 'x' + item.hauteur + 'px'"><i class="fas fa-arrow-circle-down"></i></a>
<i class="fa fa-copy" v-clipboard="item.url"></i>
<a v-if="storeMedia.libelle" :href="item.url" :download="storeMedia.libelle.replaceAll(' ', '_').replaceAll('.','') + '_' + item.largeur + 'x' + item.hauteur + 'px'"><i class="fas fa-arrow-circle-down"></i></a>
</td>
</tr>
</tbody>
@ -52,7 +52,11 @@
},
watch: {
storeMedia() {
if (Object.keys(this.storeMedia).length > 0 && (this.storeMedia.vignettes === undefined)){
if (
this.storeMedia.id &&
Object.keys(this.storeMedia).length > 0 &&
(this.storeMedia.vignettes === undefined)
){
const _this2 = this;
axios.post('/ajax/get-media-others-infos', {
media_id: this.storeMedia.id

View file

@ -15,7 +15,7 @@ $(document).ready(function() {
var dossier_id = 0;
var cancel_btn = $('<button/>')
.addClass('cancel')
.html('<i class="fal fa-times"></i>');
.html('<i class="fa fa-times"></i>');
var upload_btn = $('<button/>')
.addClass('upload')
.css('display', 'none');
@ -33,7 +33,7 @@ $(document).ready(function() {
return false;
}
$("#submit").html('<i class="fal fa-circle-notch fa-spin"></i> Transférer');
$("#submit").html('<i class="fa fa-circle-notch fa-spin"></i> Transférer');
$("#submit").css("pointer-events", "none");
var currentdate = new Date();

10
resources/lang/en.json Normal file
View file

@ -0,0 +1,10 @@
{
"error_occured_in_app_check_trace": "An error occured on :appName",
"check_trace": "Please check logs in order to fix this.",
"uri": "uri",
"date": "date",
"code": "code",
"file": "file",
"line": "line",
"anonymized_stack_trace": "anonymized stack trace"
}

10
resources/lang/fr.json Normal file
View file

@ -0,0 +1,10 @@
{
"error_occured_in_app": "Une erreur est survenue sur :appName",
"check_trace": "Veuillez vérifier les logs pour réparer ceci.",
"uri": "uri",
"date": "date",
"code": "code",
"file": "fichier",
"line": "ligne",
"anonymized_stack_trace": "pile d'appels anonymisée"
}

View file

@ -1,21 +1,16 @@
// Variables
@import "vue-select/src/scss/vue-select.scss";
@import 'partials/app_variables.scss',
'partials/reset.scss',
'partials/animate.scss',
'partials/nestable.scss',
'partials/fontawesome/fontawesome.scss',
'partials/fontawesome/solid.scss',
'partials/fontawesome/regular.scss',
'partials/fontawesome/light.scss',
'partials/fontawesome/brands.scss',
'partials/fileupload.scss',
'partials/darkroom.scss',
'partials/tag-editor.scss',
'partials/common.scss',
'partials/form.scss',
'partials/media.scss',
'partials/panier.scss',
'partials/user.scss',
'partials/vselect-custom.scss';
@import 'vue-select/src/scss/vue-select.scss';
@import 'partials/app_variables.scss';
@import 'partials/reset.scss';
@import 'partials/animate.scss';
@import 'partials/nestable.scss';
@import 'partials/fileupload.scss';
@import 'partials/darkroom.scss';
@import 'partials/tag-editor.scss';
@import 'partials/common.scss';
@import 'partials/form.scss';
@import 'partials/media.scss';
@import 'partials/panier.scss';
@import 'partials/user.scss';
@import 'partials/vselect-custom.scss';

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