129 lines
4.3 KiB
PHP
129 lines
4.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\MultiLocaleTranslation\Model\Config\Backend;
|
|
|
|
use Magento\Config\Model\Config\Backend\File;
|
|
use Magento\Framework\App\Filesystem\DirectoryList;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\Filesystem;
|
|
use Magento\Framework\Filesystem\DriverInterface;
|
|
|
|
class ServiceAccountFile extends File
|
|
{
|
|
private const REQUIRED_FIELDS = ['type', 'project_id', 'private_key', 'client_email'];
|
|
|
|
private string $oldCredentialFile = '';
|
|
private string $credentialFileToDelete = '';
|
|
|
|
public function __construct(
|
|
\Magento\Framework\Model\Context $context,
|
|
\Magento\Framework\Registry $registry,
|
|
\Magento\Framework\App\Config\ScopeConfigInterface $config,
|
|
\Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
|
|
\Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
|
|
\Magento\Config\Model\Config\Backend\File\RequestData\RequestDataInterface $requestData,
|
|
Filesystem $filesystem,
|
|
private readonly DriverInterface $fileDriver,
|
|
?\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
|
|
?\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
|
|
array $data = []
|
|
) {
|
|
parent::__construct(
|
|
$context,
|
|
$registry,
|
|
$config,
|
|
$cacheTypeList,
|
|
$uploaderFactory,
|
|
$requestData,
|
|
$filesystem,
|
|
$resource,
|
|
$resourceCollection,
|
|
$data
|
|
);
|
|
$this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
|
|
$this->_maxFileSize = 64;
|
|
}
|
|
|
|
public function beforeSave(): static
|
|
{
|
|
$this->oldCredentialFile = basename((string)$this->getOldValue());
|
|
$file = $this->getFileData();
|
|
$deleteRequested = is_array($this->getValue()) && !empty($this->getValue()['delete']);
|
|
|
|
if ($file !== []) {
|
|
$this->validateServiceAccountFile((string)$file['tmp_name']);
|
|
}
|
|
|
|
parent::beforeSave();
|
|
|
|
$newFile = basename((string)$this->getValue());
|
|
if ($file !== [] && $newFile !== '') {
|
|
$this->fileDriver->changePermissions($this->getCredentialPath($newFile), 0600);
|
|
}
|
|
|
|
if ($this->oldCredentialFile !== ''
|
|
&& ($deleteRequested || ($newFile !== '' && $newFile !== $this->oldCredentialFile))
|
|
) {
|
|
$this->credentialFileToDelete = $this->oldCredentialFile;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function afterSave(): static
|
|
{
|
|
parent::afterSave();
|
|
|
|
if ($this->credentialFileToDelete !== '') {
|
|
$oldPath = $this->getCredentialPath($this->credentialFileToDelete);
|
|
if ($this->fileDriver->isExists($oldPath)) {
|
|
$this->fileDriver->deleteFile($oldPath);
|
|
}
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
protected function _getAllowedExtensions(): array
|
|
{
|
|
return ['json'];
|
|
}
|
|
|
|
private function validateServiceAccountFile(string $path): void
|
|
{
|
|
try {
|
|
$credentials = json_decode(
|
|
$this->fileDriver->fileGetContents($path),
|
|
true,
|
|
32,
|
|
JSON_THROW_ON_ERROR
|
|
);
|
|
} catch (\Throwable $exception) {
|
|
throw new LocalizedException(__('The service account JSON file is invalid.'));
|
|
}
|
|
|
|
if (!is_array($credentials) || ($credentials['type'] ?? '') !== 'service_account') {
|
|
throw new LocalizedException(__('The uploaded JSON is not a Google service account key.'));
|
|
}
|
|
foreach (self::REQUIRED_FIELDS as $field) {
|
|
if (!is_string($credentials[$field] ?? null) || trim($credentials[$field]) === '') {
|
|
throw new LocalizedException(__('The service account JSON is missing "%1".', $field));
|
|
}
|
|
}
|
|
|
|
$privateKey = openssl_pkey_get_private($credentials['private_key']);
|
|
if ($privateKey === false) {
|
|
throw new LocalizedException(__('The service account private key is invalid.'));
|
|
}
|
|
}
|
|
|
|
private function getCredentialPath(string $filename): string
|
|
{
|
|
return $this->_mediaDirectory->getAbsolutePath(
|
|
'esun/multilocale_translation/google/' . basename($filename)
|
|
);
|
|
}
|
|
}
|