_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) ); } }