diff --git a/app/modules/web/Controllers/ConfigImport/ImportController.php b/app/modules/web/Controllers/ConfigImport/ImportController.php index 48bb1ee5..0c629184 100644 --- a/app/modules/web/Controllers/ConfigImport/ImportController.php +++ b/app/modules/web/Controllers/ConfigImport/ImportController.php @@ -24,106 +24,85 @@ namespace SP\Modules\Web\Controllers\ConfigImport; -use Exception; -use JsonException; use SP\Core\Application; use SP\Core\Context\Session; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; +use SP\Domain\Common\Attributes\Action; +use SP\Domain\Common\Dtos\ActionResponse; +use SP\Domain\Common\Enums\ResponseType; use SP\Domain\Core\Acl\AclActionsInterface; -use SP\Domain\Core\Acl\UnauthorizedPageException; use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\Core\Exceptions\SPException; -use SP\Domain\Http\Dtos\JsonMessage; use SP\Domain\Import\Dtos\ImportParamsDto; -use SP\Domain\Import\Ports\ItemsImportService; +use SP\Domain\Import\Ports\ImportService; use SP\Infrastructure\File\FileException; use SP\Infrastructure\File\FileHandler; use SP\Modules\Web\Controllers\SimpleControllerBase; -use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Mvc\Controller\SimpleControllerHelper; use function SP\__u; -use function SP\processException; /** * Class ImportController - * - * @package SP\Modules\Web\Controllers */ final class ImportController extends SimpleControllerBase { - use JsonTrait; - - private ItemsImportService $importService; public function __construct( - Application $application, - SimpleControllerHelper $simpleControllerHelper, - ItemsImportService $importService + Application $application, + SimpleControllerHelper $simpleControllerHelper, + private readonly ImportService $importService ) { parent::__construct($application, $simpleControllerHelper); - - $this->importService = $importService; } /** - * @throws JsonException * @throws SPException */ - public function importAction(): bool + #[Action(ResponseType::JSON)] + public function importAction(): ActionResponse { if ($this->config->getConfigData()->isDemoEnabled()) { - return $this->returnJsonResponse(JsonMessage::JSON_WARNING, __u('Ey, this is a DEMO!!')); + return ActionResponse::warning(__u('Ey, this is a DEMO!!')); } - try { - $this->eventDispatcher->notify('run.import.start', new Event($this)); + $this->eventDispatcher->notify('run.import.start', new Event($this)); - Session::close(); + Session::close(); - $counter = $this->importService->doImport($this->getImportParams())->getCounter(); + $counter = $this->importService->doImport($this->getImportParams())->getCounter(); - $this->eventDispatcher->notify( - 'run.import.end', - new Event( - $this, - EventMessage::build()->addDetail(__u('Accounts imported'), $counter) - ) + $this->eventDispatcher->notify( + 'run.import.end', + new Event( + $this, + EventMessage::build(__u('Accounts imported'))->addDetail(__u('Accounts imported'), $counter) + ) + ); + + if ($counter > 0) { + return ActionResponse::ok( + __u('Import finished'), + __u('Please check out the event log for more details') ); - - if ($counter > 0) { - return $this->returnJsonResponse( - JsonMessage::JSON_SUCCESS, - __u('Import finished'), - [__u('Please check out the event log for more details')] - ); - } - - return $this->returnJsonResponse( - JsonMessage::JSON_WARNING, - __u('No accounts were imported'), - [__u('Please check out the event log for more details')] - ); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notify('exception', new Event($e)); - - return $this->returnJsonResponseException($e); } + + return ActionResponse::warning( + __u('No accounts were imported'), + __u('Please check out the event log for more details') + ); } /** - * @return ImportParamsDto * @throws FileException */ private function getImportParams(): ImportParamsDto { return new ImportParamsDto( - $this->getFileFromRequest('inFile'), - $this->request->analyzeInt('import_defaultuser', $this->session->getUserData()->getId()), - $this->request->analyzeInt('import_defaultgroup', $this->session->getUserData()->getUserGroupId()), + $this->getFileFromRequest(), + $this->request->analyzeInt('import_defaultuser', $this->session->getUserData()->id), + $this->request->analyzeInt('import_defaultgroup', $this->session->getUserData()->userGroupId), $this->request->analyzeEncrypted('importPwd'), $this->request->analyzeEncrypted('importMasterPwd'), $this->request->analyzeString('csvDelimiter') @@ -131,13 +110,12 @@ final class ImportController extends SimpleControllerBase } /** - * @param string $filename * @return FileHandler * @throws FileException */ - public function getFileFromRequest(string $filename): FileHandler + private function getFileFromRequest(): FileHandler { - $file = $this->request->getFile($filename); + $file = $this->request->getFile('inFile'); if (!is_array($file)) { throw FileException::error( @@ -150,19 +128,12 @@ final class ImportController extends SimpleControllerBase } /** - * @return void * @throws SPException * @throws SessionTimeout */ protected function initialize(): void { - try { - $this->checks(); - $this->checkAccess(AclActionsInterface::CONFIG_IMPORT); - } catch (UnauthorizedPageException $e) { - $this->eventDispatcher->notify('exception', new Event($e)); - - $this->returnJsonResponseException($e); - } + $this->checks(); + $this->checkAccess(AclActionsInterface::CONFIG_IMPORT); } } diff --git a/lib/SP/Core/Definitions/DomainDefinitions.php b/lib/SP/Core/Definitions/DomainDefinitions.php index 4a49fa9f..f06f7b80 100644 --- a/lib/SP/Core/Definitions/DomainDefinitions.php +++ b/lib/SP/Core/Definitions/DomainDefinitions.php @@ -33,6 +33,8 @@ use SP\Domain\Common\Providers\Image; use SP\Domain\Export\Ports\XmlVerifyService; use SP\Domain\Export\Services\XmlVerify; use SP\Domain\Image\Ports\ImageService; +use SP\Domain\Import\Ports\ImportHelperInterface; +use SP\Domain\Import\Services\ImportHelper; use SP\Infrastructure\Common\Repositories\SimpleRepository; use SP\Infrastructure\File\FileSystem; @@ -94,7 +96,8 @@ final class DomainDefinitions XmlVerifyService::class => autowire(XmlVerify::class)->constructorParameter( 'schema', factory(static fn(PathsContext $p) => $p[Path::XML_SCHEMA]) - ) + ), + ImportHelperInterface::class => autowire(ImportHelper::class) ]; foreach (self::DOMAINS as $domain) { diff --git a/lib/SP/Domain/Import/Services/CsvImport.php b/lib/SP/Domain/Import/Services/CsvImport.php index 8513d553..df0b27af 100644 --- a/lib/SP/Domain/Import/Services/CsvImport.php +++ b/lib/SP/Domain/Import/Services/CsvImport.php @@ -1,4 +1,5 @@ getOrSetCache( self::ITEM_CATEGORY, $key, - fn(): int => $this->categoryService->getByName($category->getName())?->getId() - ?? $this->categoryService->create($category) + function () use ($category): int { + try { + return $this->categoryService->getByName($category->getName())?->getId(); + } catch (NoSuchItemException) { + return $this->categoryService->create($category); + } + } ); } /** + * @throws ConstraintException * @throws DuplicatedItemException * @throws SPException + * @throws QueryException */ protected function addClient(Client $client): int { @@ -209,13 +218,20 @@ abstract class ImportBase extends Service implements ImportService return $this->getOrSetCache( self::ITEM_CLIENT, $key, - fn(): int => $this->clientService->getByName($client->getName())?->getId() - ?? $this->clientService->create($client) + function () use ($client): int { + try { + return $this->clientService->getByName($client->getName())?->getId(); + } catch (NoSuchItemException) { + return $this->clientService->create($client); + } + } ); } /** - * @throws SPException + * @throws ConstraintException + * @throws DuplicatedItemException + * @throws QueryException */ protected function addTag(Tag $tag): int { @@ -224,8 +240,13 @@ abstract class ImportBase extends Service implements ImportService return $this->getOrSetCache( self::ITEM_TAG, $key, - fn(): int => $this->tagService->getByName($tag->getName())?->getId() - ?? $this->tagService->create($tag) + function () use ($tag): int { + try { + return $this->tagService->getByName($tag->getName())?->getId(); + } catch (NoSuchItemException) { + return $this->tagService->create($tag); + } + } ); } } diff --git a/tests/SP/Modules/Web/Controllers/ConfigAccount/ConfigAccountControllerTest.php b/tests/SP/Modules/Web/Controllers/ConfigAccount/ConfigAccountTest.php similarity index 97% rename from tests/SP/Modules/Web/Controllers/ConfigAccount/ConfigAccountControllerTest.php rename to tests/SP/Modules/Web/Controllers/ConfigAccount/ConfigAccountTest.php index 49a57f51..49479772 100644 --- a/tests/SP/Modules/Web/Controllers/ConfigAccount/ConfigAccountControllerTest.php +++ b/tests/SP/Modules/Web/Controllers/ConfigAccount/ConfigAccountTest.php @@ -37,7 +37,7 @@ use SP\Tests\IntegrationTestCase; * Class ConfigAccountControllerTest */ #[Group('integration')] -class ConfigAccountControllerTest extends IntegrationTestCase +class ConfigAccountTest extends IntegrationTestCase { /** diff --git a/tests/SP/Modules/Web/Controllers/ConfigBackup/ConfigBackupControllerTest.php b/tests/SP/Modules/Web/Controllers/ConfigBackup/ConfigBackupTest.php similarity index 98% rename from tests/SP/Modules/Web/Controllers/ConfigBackup/ConfigBackupControllerTest.php rename to tests/SP/Modules/Web/Controllers/ConfigBackup/ConfigBackupTest.php index feb0836e..37ad7394 100644 --- a/tests/SP/Modules/Web/Controllers/ConfigBackup/ConfigBackupControllerTest.php +++ b/tests/SP/Modules/Web/Controllers/ConfigBackup/ConfigBackupTest.php @@ -37,7 +37,7 @@ use SP\Tests\IntegrationTestCase; * Class ConfigBackupControllerTest */ #[Group('integration')] -class ConfigBackupControllerTest extends IntegrationTestCase +class ConfigBackupTest extends IntegrationTestCase { /** * @throws ContainerExceptionInterface diff --git a/tests/SP/Modules/Web/Controllers/ConfigEncryption/ConfigEncryptionControllerTest.php b/tests/SP/Modules/Web/Controllers/ConfigEncryption/ConfigEncryptionTest.php similarity index 98% rename from tests/SP/Modules/Web/Controllers/ConfigEncryption/ConfigEncryptionControllerTest.php rename to tests/SP/Modules/Web/Controllers/ConfigEncryption/ConfigEncryptionTest.php index c2760616..2dba6c44 100644 --- a/tests/SP/Modules/Web/Controllers/ConfigEncryption/ConfigEncryptionControllerTest.php +++ b/tests/SP/Modules/Web/Controllers/ConfigEncryption/ConfigEncryptionTest.php @@ -45,7 +45,7 @@ use SP\Tests\IntegrationTestCase; */ #[Group('integration')] #[InjectVault] -class ConfigEncryptionControllerTest extends IntegrationTestCase +class ConfigEncryptionTest extends IntegrationTestCase { /** diff --git a/tests/SP/Modules/Web/Controllers/ConfigImport/ConfigImportTest.php b/tests/SP/Modules/Web/Controllers/ConfigImport/ConfigImportTest.php new file mode 100644 index 00000000..392e62df --- /dev/null +++ b/tests/SP/Modules/Web/Controllers/ConfigImport/ConfigImportTest.php @@ -0,0 +1,85 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Tests\Modules\Web\Controllers\ConfigImport; + +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\MockObject\Exception; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use SP\Tests\InjectVault; +use SP\Tests\IntegrationTestCase; + +use function SP\Tests\getResource; + +/** + * Class ConfigImportTest + */ +#[Group('integration')] +#[InjectVault] +class ConfigImportTest extends IntegrationTestCase +{ + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws Exception + */ + #[Test] + public function import() + { + $file = sprintf('%s.csv', self::$faker->filePath()); + + file_put_contents($file, getResource('import', 'data.csv')); + + $files = [ + 'inFile' => [ + 'name' => self::$faker->name(), + 'tmp_name' => $file, + 'size' => filesize($file), + 'type' => 'text/plain' + ] + ]; + + $data = [ + 'import_defaultuser' => self::$faker->randomNumber(3), + 'import_defaultgroup' => self::$faker->randomNumber(3), + 'importPwd' => self::$faker->password(), + 'importMasterPwd' => self::$faker->password(), + 'csvDelimiter' => ';', + ]; + + $container = $this->buildContainer( + IntegrationTestCase::buildRequest('post', 'index.php', ['r' => 'configImport/import'], $data, $files) + ); + + $this->expectOutputString( + '{"status":"OK","description":"Import finished","data":"Please check out the event log for more details"}' + ); + + IntegrationTestCase::runApp($container); + } +}