Files
esun3d/app/code/Esun/Catalog/Model/SpecificationMedia.php
T
2026-09-15 10:35:56 +08:00

167 lines
5.6 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\Catalog\Model;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\MediaStorage\Model\File\UploaderFactory;
class SpecificationMedia
{
public const LOGO_PATH = 'esun/catalog/specifications/brand-logo';
public const ARCHIVE_PATH = 'esun/catalog/specifications/archive';
public const FILE_PATH = 'esun/catalog/specifications/file';
public function __construct(
private readonly UploaderFactory $uploaderFactory,
private readonly Filesystem $filesystem,
private readonly Http $request
) {
}
public function saveLogo(string $field): ?string
{
return $this->saveUpload($field, self::LOGO_PATH, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg']);
}
public function saveArchive(string $field, int $brandId): ?string
{
return $this->saveUpload($field, self::ARCHIVE_PATH . '/' . $brandId, ['zip']);
}
public function hasUpload(string $field): bool
{
$file = $this->request->getFiles($field);
return is_array($file)
&& !empty($file['tmp_name'])
&& (int)($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_NO_FILE;
}
public function writeSpecificationFile(int $brandId, string $modelName, string $fileName, string $contents): string
{
$relativeDirectory = self::FILE_PATH . '/' . $brandId . '/' . $this->sanitizePathSegment($modelName);
$relativePath = $relativeDirectory . '/' . $this->sanitizeFilename($fileName);
$media = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$media->create($relativeDirectory);
$media->writeFile($relativePath, $contents);
return $relativePath;
}
public function deleteBrandFiles(int $brandId): void
{
$media = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
foreach ([self::ARCHIVE_PATH . '/' . $brandId, self::FILE_PATH . '/' . $brandId] as $path) {
if ($media->isExist($path)) {
$media->delete($path);
}
}
}
public function deleteBrandParsedFiles(int $brandId): void
{
$path = self::FILE_PATH . '/' . $brandId;
$media = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
if ($media->isExist($path)) {
$media->delete($path);
}
}
public function deleteBrandArchiveFiles(int $brandId): void
{
$path = self::ARCHIVE_PATH . '/' . $brandId;
$media = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
if ($media->isExist($path)) {
$media->delete($path);
}
}
public function delete(string $path): void
{
$path = ltrim($path, '/');
if ($path === '' || !str_starts_with($path, 'esun/catalog/specifications/')) {
return;
}
$media = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
if ($media->isExist($path)) {
$media->delete($path);
}
}
public function getAbsolutePath(string $path): string
{
return $this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath(ltrim($path, '/'));
}
public function exists(string $path): bool
{
$path = ltrim($path, '/');
return $path !== ''
&& $this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->isExist($path);
}
public function getFileSize(string $path): int
{
$path = ltrim($path, '/');
if ($path === '' || !$this->exists($path)) {
return 0;
}
$stat = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->stat($path);
return is_array($stat) ? (int)($stat['size'] ?? 0) : 0;
}
public function sanitizePathSegment(string $value): string
{
$value = trim($value);
$value = preg_replace('/[^A-Za-z0-9._-]+/', '_', $value) ?: '';
$value = trim($value, '._-');
return $value !== '' ? $value : 'model';
}
private function saveUpload(string $field, string $relativeDirectory, array $extensions): ?string
{
$file = $this->request->getFiles($field);
if (!is_array($file)
|| empty($file['tmp_name'])
|| (int)($file['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE
) {
return null;
}
if ((int)($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
throw new LocalizedException(__('The %1 file could not be uploaded.', $field));
}
$media = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$media->create($relativeDirectory);
$uploader = $this->uploaderFactory->create(['fileId' => $field]);
$uploader->setAllowedExtensions($extensions);
$uploader->setAllowRenameFiles(true);
$uploader->setFilesDispersion(false);
$saved = $uploader->save($media->getAbsolutePath($relativeDirectory));
if (!is_array($saved) || empty($saved['file'])) {
throw new LocalizedException(__('Unable to save the %1 file.', $field));
}
return trim($relativeDirectory . '/' . ltrim((string)$saved['file'], '/'), '/');
}
private function sanitizeFilename(string $value): string
{
$value = strtolower(trim($value));
$value = preg_replace('/[^a-z0-9._+ -]+/', '_', $value) ?: '';
$value = preg_replace('/\\s+/', ' ', $value) ?: '';
$value = trim($value, ' ._-');
return $value !== '' ? $value : 'specification';
}
}