diff --git a/app/modules/web/Controllers/AccountManager/BulkEditController.php b/app/modules/web/Controllers/AccountManager/BulkEditController.php index 02d325bb..7c2aa769 100644 --- a/app/modules/web/Controllers/AccountManager/BulkEditController.php +++ b/app/modules/web/Controllers/AccountManager/BulkEditController.php @@ -25,28 +25,30 @@ namespace SP\Modules\Web\Controllers\AccountManager; use Exception; -use JsonException; -use SP\Core\Acl\Acl; use SP\Core\Application; use SP\Core\Events\Event; -use SP\Domain\Account\Ports\AccountHistoryService; -use SP\Domain\Account\Ports\AccountSearchService; -use SP\Domain\Account\Ports\AccountService; +use SP\Domain\Auth\Services\AuthException; use SP\Domain\Category\Ports\CategoryService; use SP\Domain\Client\Ports\ClientService; use SP\Domain\Core\Acl\AclActionsInterface; -use SP\Domain\CustomField\Ports\CustomFieldDataService; +use SP\Domain\Core\Exceptions\ConstraintException; +use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SessionTimeout; +use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Http\Dtos\JsonMessage; use SP\Domain\Tag\Ports\TagService; use SP\Domain\User\Ports\UserGroupService; use SP\Domain\User\Ports\UserService; use SP\Modules\Web\Controllers\ControllerBase; -use SP\Modules\Web\Controllers\Helpers\Grid\AccountGrid; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Mvc\Controller\ItemTrait; use SP\Mvc\Controller\WebControllerHelper; use SP\Mvc\View\Components\SelectItemAdapter; +use function SP\__; +use function SP\__u; +use function SP\processException; + /** * Class AccountManagerController * @@ -57,34 +59,21 @@ final class BulkEditController extends ControllerBase use ItemTrait; use JsonTrait; - private AccountService $accountService; - private AccountSearchService $accountSearchService; - private AccountHistoryService $accountHistoryService; - private AccountGrid $accountGrid; - private CustomFieldDataService $customFieldService; - private CategoryService $categoryService; - private ClientService $clientService; - private TagService $tagService; - private UserService $userService; - private UserGroupService $userGroupService; - + /** + * @throws AuthException + * @throws SessionTimeout + */ public function __construct( - Application $application, - WebControllerHelper $webControllerHelper, - CategoryService $categoryService, - ClientService $clientService, - TagService $tagService, - UserService $userService, - UserGroupService $userGroupService + Application $application, + WebControllerHelper $webControllerHelper, + private readonly CategoryService $categoryService, + private readonly ClientService $clientService, + private readonly TagService $tagService, + private readonly UserService $userService, + private readonly UserGroupService $userGroupService ) { parent::__construct($application, $webControllerHelper); - $this->categoryService = $categoryService; - $this->clientService = $clientService; - $this->tagService = $tagService; - $this->userService = $userService; - $this->userGroupService = $userGroupService; - $this->checkLoggedIn(); } @@ -92,7 +81,7 @@ final class BulkEditController extends ControllerBase * bulkEditAction * * @return bool - * @throws JsonException + * @throws SPException */ public function bulkEditAction(): bool { @@ -111,10 +100,7 @@ final class BulkEditController extends ControllerBase $this->setViewData(); - $this->eventDispatcher->notify( - 'show.account.bulkEdit', - new Event($this) - ); + $this->eventDispatcher->notify('show.account.bulkEdit', new Event($this)); return $this->returnJsonResponseData(['html' => $this->render()]); } catch (Exception $e) { @@ -125,33 +111,28 @@ final class BulkEditController extends ControllerBase } /** - * Sets view data + * @return void + * @throws ConstraintException + * @throws QueryException */ protected function setViewData(): void { $this->view->addTemplate('account_bulkedit', 'itemshow'); - $this->view->assign('nextAction', Acl::getActionRoute(AclActionsInterface::ITEMS_MANAGE)); + $this->view->assign('nextAction', $this->acl->getRouteFor(AclActionsInterface::ITEMS_MANAGE)); - $clients = SelectItemAdapter::factory($this->clientService->getAll())->getItemsFromModel(); - $categories = SelectItemAdapter::factory($this->categoryService->getAll())->getItemsFromModel(); - $tags = SelectItemAdapter::factory($this->tagService->getAll())->getItemsFromModel(); - $users = SelectItemAdapter::factory($this->userService->getAll())->getItemsFromModel(); - $userGroups = SelectItemAdapter::factory($this->userGroupService->getAll())->getItemsFromModel(); - - $this->view->assign('users', $users); - $this->view->assign('userGroups', $userGroups); - - $this->view->assign('clients', $clients); - $this->view->assign('categories', $categories); - $this->view->assign('tags', $tags); - - if ($this->view->isView === true) { - $this->view->assign('disabled', 'disabled'); - $this->view->assign('readonly', 'readonly'); - } else { - $this->view->assign('disabled', false); - $this->view->assign('readonly', false); - } + $this->view->assign('users', SelectItemAdapter::factory($this->userService->getAll())->getItemsFromModel()); + $this->view->assign( + 'userGroups', + SelectItemAdapter::factory($this->userGroupService->getAll())->getItemsFromModel() + ); + $this->view->assign('clients', SelectItemAdapter::factory($this->clientService->getAll())->getItemsFromModel()); + $this->view->assign( + 'categories', + SelectItemAdapter::factory($this->categoryService->getAll())->getItemsFromModel() + ); + $this->view->assign('tags', SelectItemAdapter::factory($this->tagService->getAll())->getItemsFromModel()); + $this->view->assign('disabled', ''); + $this->view->assign('readonly', ''); } } diff --git a/lib/SP/Domain/Client/Models/Client.php b/lib/SP/Domain/Client/Models/Client.php index 0e386e5e..6bb4bd38 100644 --- a/lib/SP/Domain/Client/Models/Client.php +++ b/lib/SP/Domain/Client/Models/Client.php @@ -1,4 +1,5 @@ constructorParameter('module', 'web') ->constructorParameter('name', 'material-blue'), AclInterface::class => $acl, - AccountAclService::class => $accountAcl + AccountAclService::class => $accountAcl, ]; + $outputChecker = $this->getOutputChecker(); + + if ($outputChecker !== null) { + $definitions[OutputHandlerInterface::class] = new OutputHandlerStub($outputChecker->bindTo($this)); + } if ($request) { $definitions += [Request::class => $request]; @@ -238,6 +247,21 @@ abstract class IntegrationTestCase extends TestCase return UserProfileDataGenerator::factory()->buildProfileData(); } + /** + * @throws ReflectionException + */ + private function getOutputChecker(): ?Closure + { + $reflection = new ReflectionObject($this); + foreach ($reflection->getMethods(ReflectionMethod::IS_PRIVATE) as $method) { + if (count($method->getAttributes(OutputChecker::class)) > 0) { + return $method->getClosure($this); + } + } + + return null; + } + final protected function addDatabaseMapperResolver(string $className, QueryResult $queryResult): void { $this->databaseMapperResolvers[$className] = $queryResult; diff --git a/tests/SP/Modules/Web/Controllers/AccountManager/AccountManagerTest.php b/tests/SP/Modules/Web/Controllers/AccountManager/AccountManagerTest.php new file mode 100644 index 00000000..f99ab711 --- /dev/null +++ b/tests/SP/Modules/Web/Controllers/AccountManager/AccountManagerTest.php @@ -0,0 +1,112 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Tests\Modules\Web\Controllers\AccountManager; + +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\Domain\Category\Models\Category; +use SP\Domain\Client\Models\Client; +use SP\Domain\Core\Exceptions\InvalidClassException; +use SP\Domain\Tag\Models\Tag; +use SP\Domain\User\Models\User; +use SP\Domain\User\Models\UserGroup; +use SP\Infrastructure\Database\QueryResult; +use SP\Infrastructure\File\FileException; +use SP\OutputChecker; +use SP\Tests\Generators\CategoryGenerator; +use SP\Tests\Generators\ClientGenerator; +use SP\Tests\Generators\TagGenerator; +use SP\Tests\Generators\UserDataGenerator; +use SP\Tests\Generators\UserGroupGenerator; +use SP\Tests\IntegrationTestCase; +use Symfony\Component\DomCrawler\Crawler; + +/** + * Class AccountManagerTest + */ +#[Group('integration')] +class AccountManagerTest extends IntegrationTestCase +{ + + /** + * @throws NotFoundExceptionInterface + * @throws Exception + * @throws FileException + * @throws InvalidClassException + * @throws ContainerExceptionInterface + */ + #[Test] + public function bulkEdit() + { + $this->addDatabaseMapperResolver( + User::class, + QueryResult::withTotalNumRows([UserDataGenerator::factory()->buildUserData()], 1) + ); + + $this->addDatabaseMapperResolver( + UserGroup::class, + QueryResult::withTotalNumRows([UserGroupGenerator::factory()->buildUserGroupData()], 1) + ); + + $this->addDatabaseMapperResolver( + Client::class, + QueryResult::withTotalNumRows([ClientGenerator::factory()->buildClient()], 1) + ); + + $this->addDatabaseMapperResolver( + Tag::class, + QueryResult::withTotalNumRows([TagGenerator::factory()->buildTag()], 1) + ); + + $this->addDatabaseMapperResolver( + Category::class, + QueryResult::withTotalNumRows([CategoryGenerator::factory()->buildCategory()], 1) + ); + + $container = $this->buildContainer( + $this->getModuleDefinitions(), + $this->buildRequest('post', 'index.php', ['r' => 'accountManager/bulkEdit'], ['items' => [100, 200, 300]]) + ); + + $this->runApp($container); + } + + #[OutputChecker] + private function outputChecker(string $output): void + { + $crawler = new Crawler($output); + $filter = $crawler->filterXPath( + '//div[@id="box-popup"]//form[@name="frmAccountBulkEdit"]//select|//input|//div[@class="action-in-box"]/button' + )->extract(['_name']); + + $this->assertNotEmpty($output); + $this->assertCount(19, $filter); + } +} diff --git a/tests/SP/OutputChecker.php b/tests/SP/OutputChecker.php new file mode 100644 index 00000000..0b57c7b8 --- /dev/null +++ b/tests/SP/OutputChecker.php @@ -0,0 +1,38 @@ +. + */ + +declare(strict_types=1); + +namespace SP; + +use Attribute; + +/** + * Class OutputChecker + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class OutputChecker +{ + +}