Fixes #24 XmlInco Full process of pictures
This commit is contained in:
parent
97361f7a56
commit
33d2f4e573
11 changed files with 153 additions and 83 deletions
|
|
@ -313,8 +313,8 @@ class ProductController extends Controller
|
|||
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$storagePublicDisk = Storage::disk('public');
|
||||
$pictureBaseName = $picture['filename'];
|
||||
$pictureExtension = \pathinfo($picture['filename'], \PATHINFO_EXTENSION);
|
||||
$pictureBaseName = $picture['file_name'];
|
||||
$pictureExtension = \pathinfo($picture['file_name'], \PATHINFO_EXTENSION);
|
||||
|
||||
/**
|
||||
* We create one file in tmp to be resized
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class XmlIncoController extends Controller
|
|||
$stream = $disk->readStream($picturePath);
|
||||
\fpassthru($stream);
|
||||
\fclose($stream);
|
||||
}, $inco_picture, [
|
||||
}, \pathinfo($inco_picture, \PATHINFO_BASENAME), [
|
||||
'Content-Type' => $disk->mimeType($picturePath),
|
||||
'Content-Length' => $disk->size($picturePath),
|
||||
'Content-Disposition' => 'inline',
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
namespace App\Jobs;
|
||||
|
||||
use App\Exceptions\AbortXmlImportException;
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Models\XmlInco;
|
||||
use SimpleXMLElement;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class XmlIncoReader extends XmlJobs
|
||||
{
|
||||
|
|
@ -419,7 +421,7 @@ class XmlIncoReader extends XmlJobs
|
|||
public function handle()
|
||||
{
|
||||
|
||||
$this->parseData('INCO', XmlInco::class, function (SimpleXMLElement $xmlData, array &$line) {
|
||||
$this->parseData('INCO', XmlInco::class, function (\SimpleXMLElement $xmlData, array &$line) {
|
||||
|
||||
// Merge columns.
|
||||
foreach ($this->mergeColumns as $key => $values) {
|
||||
|
|
@ -442,70 +444,83 @@ class XmlIncoReader extends XmlJobs
|
|||
(strtolower($line['prod_saison']) == 'non' ? false : true) : false;
|
||||
|
||||
$arImgPaths = $this->parseImage($xmlData);
|
||||
$line['picturse'] = $arImgPaths;
|
||||
$line['pictures'] = $arImgPaths;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract Image form XML file
|
||||
*
|
||||
* @param SimpleXMLElement $xmlData
|
||||
* @param \SimpleXMLElement $xmlData
|
||||
* @return array
|
||||
* @throws AbortXmlImportException When media tag does not contain an image.
|
||||
*/
|
||||
private function parseImage(SimpleXMLElement $xmlData)
|
||||
private function parseImage(\SimpleXMLElement $xmlData)
|
||||
{
|
||||
$list_media = $xmlData->INCO->MEDIA_VISUEL_EAI->MEDIA_VISUEL_EAI;
|
||||
$arImgPaths = array();
|
||||
$index = 1;
|
||||
/** @var \Illuminate\Support\Collection<\SimpleXMLElement> */
|
||||
$list_media = collect($xmlData->INCO->MEDIA_VISUEL_EAI->MEDIA_VISUEL_EAI);
|
||||
$arImgPaths = \collect();
|
||||
|
||||
foreach ($list_media as $media) {
|
||||
$i = -1;
|
||||
|
||||
$list_media->each(function ($media) use ($xmlData, $arImgPaths, &$i) {
|
||||
$i++;
|
||||
|
||||
/** @var \SimpleXMLElement|null */
|
||||
$image = $media->img;
|
||||
$imageData = trim((string)$image);
|
||||
if (strlen($imageData)) {
|
||||
$imageData = base64_decode($imageData);
|
||||
$imgName = strval($xmlData->INCO->INCO_COMPO->TBL_INCO_COMPO->ID_INCO);
|
||||
if (empty($imgName)) {
|
||||
$imgName = strval($xmlData->INCO->NO_ART);
|
||||
}
|
||||
// * Store only picture name.
|
||||
$imgNamePath = $imgName . "_" . $index;
|
||||
|
||||
$disk = $this->getDisk();
|
||||
if (!strlen($imageData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$info = getimagesizefromstring($imageData);
|
||||
if ($info !== false) {
|
||||
$mime = $info['mime'];
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
$imgExtension = 'jpg';
|
||||
break;
|
||||
case 'image/png':
|
||||
$imgExtension = 'png';
|
||||
break;
|
||||
case 'image/gif':
|
||||
$imgExtension = 'gif';
|
||||
break;
|
||||
default:
|
||||
throw new AbortXmlImportException(sprintf('Unknown image type %s', $imgName));
|
||||
}
|
||||
$imageData = \strval(base64_decode($imageData));
|
||||
$imgName = strval($xmlData->INCO->INCO_COMPO->TBL_INCO_COMPO->ID_INCO ?? $xmlData->INCO->NO_ART);
|
||||
$imgNamePath = "{$imgName}_" . \uniqid();
|
||||
|
||||
$imgNamePath = sprintf('%s.%s', $imgNamePath, $imgExtension);
|
||||
$info = getimagesizefromstring($imageData);
|
||||
if ($info === false) {
|
||||
Log::debug("Skipping file {$imgNamePath} on index {$i} as could not determine picture info.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$disk->put($imgNamePath, $imageData)) {
|
||||
throw new AbortXmlImportException(sprintf('The image %s could not be saved', $imgNamePath));
|
||||
}
|
||||
$mime = $info['mime'];
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
$imgExtension = 'jpg';
|
||||
break;
|
||||
case 'image/png':
|
||||
$imgExtension = 'png';
|
||||
break;
|
||||
case 'image/gif':
|
||||
$imgExtension = 'gif';
|
||||
break;
|
||||
default:
|
||||
throw new AbortXmlImportException(sprintf('Unknown image type %s', $imgName));
|
||||
}
|
||||
|
||||
$arImgPaths[$index] = sprintf('%s/%s', $this->disk, $imgNamePath);
|
||||
$index++;
|
||||
}//end if
|
||||
}//end if
|
||||
}//end foreach
|
||||
$imgNamePath = FileStorageHelper::sanitizeFileName("{$imgNamePath}-{$i}.{$imgExtension}");
|
||||
|
||||
return $arImgPaths;
|
||||
if (!($file = tempnam(sys_get_temp_dir(), $imgNamePath))) {
|
||||
throw new \RuntimeException('Could not initiate a php temp file');
|
||||
}
|
||||
|
||||
if (!File::put($file, $imageData)) {
|
||||
throw new \RuntimeException('Could not write to the php temp file');
|
||||
}
|
||||
|
||||
$arImgPaths->push(FileStorageHelper::storeFile(
|
||||
new XmlInco(),
|
||||
new \SplFileInfo($file),
|
||||
true,
|
||||
$imgNamePath,
|
||||
true
|
||||
));
|
||||
});
|
||||
|
||||
return $arImgPaths->all();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursive extract to array
|
||||
* introduce sort of Hook to transform
|
||||
|
|
@ -530,7 +545,7 @@ class XmlIncoReader extends XmlJobs
|
|||
protected function extract($sxe = null): array
|
||||
{
|
||||
|
||||
if (!$sxe instanceof SimpleXMLElement) {
|
||||
if (!$sxe instanceof \SimpleXMLElement) {
|
||||
return array();
|
||||
}
|
||||
$extract = array();
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
*/
|
||||
protected function sendErrorParseEmailToServiceWeb(Throwable $e)
|
||||
{
|
||||
Mail::send('emails.exception', [
|
||||
Mail::send('back::emails.exception', [
|
||||
'exception' => $e,
|
||||
'appName' => config('app.name'),
|
||||
], function ($m) {
|
||||
|
|
@ -351,7 +351,7 @@ abstract class XmlJobs extends XArcadiaFlux
|
|||
protected function sendInvalidXmlEmail(string $filename, Throwable $e)
|
||||
{
|
||||
$message = $e->getPrevious()->getMessage();
|
||||
Mail::send('emails.invalidxml', [
|
||||
Mail::send('back::emails.invalidxml', [
|
||||
'strError' => sprintf(
|
||||
'File %s could not be parsed => %s on line %d',
|
||||
$filename,
|
||||
|
|
|
|||
|
|
@ -82,13 +82,22 @@ class FileStorageHelper
|
|||
* @param \Illuminate\Http\UploadedFile|\SplFileInfo|string $file The file, will just return itself is string.
|
||||
* @param boolean $slugify Force filename slugification.
|
||||
* @param string|null $filename This string may be used to store the file.
|
||||
* @param boolean $private To store the file in a private space.
|
||||
* @return string
|
||||
* @throws \RuntimeException If file copy fails.
|
||||
*/
|
||||
public static function storeFile(Model $model, $file, bool $slugify = false, string $filename = null): string
|
||||
{
|
||||
public static function storeFile(
|
||||
Model $model,
|
||||
$file,
|
||||
bool $slugify = false,
|
||||
string $filename = null,
|
||||
bool $private = false
|
||||
): string {
|
||||
$tableName = $model->getTable();
|
||||
if (\is_object($file) and $file instanceof \Illuminate\Http\UploadedFile) {
|
||||
if ($private) {
|
||||
throw new \RuntimeException('Private storage for uploaded files is unhandled');
|
||||
}
|
||||
/** @var \Illuminate\Http\UploadedFile $file */
|
||||
$filename = $filename ?: $file->getClientOriginalName();
|
||||
$filename = $slugify ? self::slugifyFileName($filename) : $filename;
|
||||
|
|
@ -104,7 +113,7 @@ class FileStorageHelper
|
|||
/** @var \SplFileInfo $file */
|
||||
$filename = $filename ?: $file->getBaseName();
|
||||
$filename = $slugify ? self::slugifyFileName($filename) : $filename;
|
||||
$newPath = self::prepareMoveFile($tableName, $filename);
|
||||
$newPath = self::prepareMoveFile($tableName, $filename, $private);
|
||||
if (!File::copy($file->getRealPath(), $newPath)) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Failed to copy file %s to %s',
|
||||
|
|
@ -112,7 +121,9 @@ class FileStorageHelper
|
|||
$newPath
|
||||
));
|
||||
}
|
||||
return \ltrim(str_replace(\storage_path('app/public'), '/storage', $newPath), '/');
|
||||
return $private ?
|
||||
\ltrim(str_replace(\storage_path('app/private'), '/storage/app/private', $newPath), '/') :
|
||||
\ltrim(str_replace(\storage_path('app/public'), '/storage', $newPath), '/');
|
||||
}
|
||||
return strval($file);
|
||||
}
|
||||
|
|
@ -268,11 +279,12 @@ class FileStorageHelper
|
|||
* Prepare storage path and return
|
||||
* the file full path
|
||||
*
|
||||
* @param string $tableName Model table name.
|
||||
* @param string $filename The basename for the file.
|
||||
* @param string $tableName Model table name.
|
||||
* @param string $filename The basename for the file.
|
||||
* @param boolean $private May the file be stored in a private dir.
|
||||
* @return string
|
||||
*/
|
||||
private static function prepareMoveFile(string $tableName, string $filename): string
|
||||
private static function prepareMoveFile(string $tableName, string $filename, bool $private = false): string
|
||||
{
|
||||
// * Security filter + beautifier
|
||||
$filename = self::sanitizeFileName($filename);
|
||||
|
|
@ -283,7 +295,12 @@ class FileStorageHelper
|
|||
$filename = Str::slug(\pathinfo($filename, \PATHINFO_FILENAME)) .
|
||||
(\strlen($ext) ? ".{$ext}" : '');
|
||||
|
||||
$folderPath = self::getStoragePath($tableName, $filename);
|
||||
$folderPath = self::getStoragePath(
|
||||
$private ? 'app/private/modelfiles' : 'app/public/modelfiles',
|
||||
$tableName,
|
||||
$filename,
|
||||
$private
|
||||
);
|
||||
$filename = self::getFileUniqueName($folderPath, $filename);
|
||||
return "{$folderPath}/{$filename}";
|
||||
}
|
||||
|
|
@ -293,15 +310,17 @@ class FileStorageHelper
|
|||
* storage/modelfiles/posts/10/04/19/5f
|
||||
* year/month/day/md5 first 2 letters
|
||||
*
|
||||
* @param string $storage_dir
|
||||
* @param string $table
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
private static function getStoragePath(string $table, string $filename): string
|
||||
private static function getStoragePath(string $storage_dir, string $table, string $filename): string
|
||||
{
|
||||
$filenameHash = \md5($filename);
|
||||
$pathFolder = \storage_path(sprintf(
|
||||
'app/public/modelfiles/%s/%s/%s/%s/%s',
|
||||
'%s/%s/%s/%s/%s/%s',
|
||||
$storage_dir,
|
||||
$table,
|
||||
gmdate('y'),
|
||||
gmdate('m'),
|
||||
|
|
|
|||
|
|
@ -53,29 +53,22 @@ class XmlInco extends Model
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $disk = 'inco';
|
||||
|
||||
/**
|
||||
* Storage path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $imagesPath = 'images';
|
||||
protected static $disk = 'private';
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Get xml inco picture path
|
||||
*
|
||||
* @param string $pictureName
|
||||
* @param string $inco_picture
|
||||
* @return null|string
|
||||
*/
|
||||
public static function getXmlIncoPicturePath(string $pictureName): ?string
|
||||
public static function getXmlIncoPicturePath(string $inco_picture): ?string
|
||||
{
|
||||
$disk = static::getDisk();
|
||||
$picturePath = static::$imagesPath . "/{$pictureName}";
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$disk = static::getDisk();
|
||||
|
||||
return $disk->exists($picturePath) ? $picturePath : null;
|
||||
return $disk->exists($inco_picture) ? $inco_picture : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -85,16 +78,15 @@ class XmlInco extends Model
|
|||
*/
|
||||
public function getMediaListAttribute(): Collection
|
||||
{
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$disk = static::getDisk();
|
||||
|
||||
/** @var \Illuminate\Support\Collection<array<string,string> */
|
||||
$collFiles = new Collection();
|
||||
foreach ($this->pictures as $pictureName) {
|
||||
$collFiles->add([
|
||||
'filename' => $pictureName,
|
||||
'imgdata' => base64_encode($disk->get(
|
||||
static::$imagesPath . "/{$pictureName}"
|
||||
))
|
||||
$collFiles = \collect();
|
||||
foreach ($this->pictures as $picture_path) {
|
||||
$collFiles->add(['file_name' => \pathinfo($picture_path, \PATHINFO_BASENAME),
|
||||
'file_path' => $picture_path,
|
||||
'imgdata' => base64_encode($disk->get($picture_path))
|
||||
]);
|
||||
}
|
||||
return $collFiles;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,12 @@ return [
|
|||
'endpoint' => env('AWS_ENDPOINT'),
|
||||
],
|
||||
|
||||
'private' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/private'),
|
||||
'url' => env('APP_URL') . '/storage'
|
||||
],
|
||||
|
||||
'inco' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('inco')
|
||||
|
|
|
|||
38
database/migrations/2023_02_24_103044_move_info_files.php
Normal file
38
database/migrations/2023_02_24_103044_move_info_files.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class MoveInfoFiles extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$private_disk = Storage::disk('private');
|
||||
collect(File::glob(storage_path('inco/images/*')))->each(function ($file_path) use ($private_disk) {
|
||||
if (
|
||||
!$private_disk->put(
|
||||
pathinfo($file_path, PATHINFO_BASENAME),
|
||||
File::get($file_path)
|
||||
)
|
||||
) {
|
||||
throw new \RuntimeException('Failed to move inco file');
|
||||
}
|
||||
});
|
||||
File::deleteDirectory(storage_path('inco/images'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
</button>
|
||||
<div class="form-control alert-info">
|
||||
<img class="img-fluid" src="{{ route('bo.xml_incos.getXmlIncoPicture', [
|
||||
'inco_picture' => $picture['filename'],
|
||||
'inco_picture' => $picture['file_path'],
|
||||
'resize' => true
|
||||
]) }}" alt="visuel Inco">
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ Route::prefix('bo')->name('bo.')->group(function () {
|
|||
// * XML INCO
|
||||
Route::get('/xml_incos/search', [XmlIncoController::class, 'getXmlIncos'])->name('xml_incos.getXmlIncos');
|
||||
Route::get('/xml_incos/picture/{inco_picture}', [XmlIncoController::class, 'getXmlIncoPicture'])
|
||||
->where('inco_picture', '[a-zA-Z0-9_-]+\.(png|jpg|jpeg)')
|
||||
->where('inco_picture', '.+[a-zA-Z0-9_-]+\.(png|jpg|jpeg)')
|
||||
->name('xml_incos.getXmlIncoPicture');
|
||||
|
||||
// * Tags
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue