diff --git a/application/Espo/Binding.php b/application/Espo/Binding.php index 473e27ca80..536ba732d5 100644 --- a/application/Espo/Binding.php +++ b/application/Espo/Binding.php @@ -143,11 +143,6 @@ class Binding implements BindingProcessor 'recordServiceContainer' ); - $binder->bindService( - 'Espo\\Core\\Record\\HookManager', - 'recordHookManager' - ); - $binder->bindService( 'Espo\\Core\\HookManager', 'hookManager' diff --git a/application/Espo/Core/Di/RecordHookManagerAware.php b/application/Espo/Core/Di/RecordHookManagerAware.php deleted file mode 100644 index 8c9bb38de9..0000000000 --- a/application/Espo/Core/Di/RecordHookManagerAware.php +++ /dev/null @@ -1,37 +0,0 @@ -. - * - * The interactive user interfaces in modified source and object code versions - * of this program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU Affero General Public License version 3. - * - * In accordance with Section 7(b) of the GNU Affero General Public License version 3, - * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. - ************************************************************************/ - -namespace Espo\Core\Di; - -use Espo\Core\Record\HookManager as RecordHookManager; - -interface RecordHookManagerAware -{ - public function setRecordHookManager(RecordHookManager $recordHookManager): void; -} diff --git a/application/Espo/Core/Di/RecordHookManagerSetter.php b/application/Espo/Core/Di/RecordHookManagerSetter.php deleted file mode 100644 index 574641348d..0000000000 --- a/application/Espo/Core/Di/RecordHookManagerSetter.php +++ /dev/null @@ -1,45 +0,0 @@ -. - * - * The interactive user interfaces in modified source and object code versions - * of this program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU Affero General Public License version 3. - * - * In accordance with Section 7(b) of the GNU Affero General Public License version 3, - * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. - ************************************************************************/ - -namespace Espo\Core\Di; - -use Espo\Core\Record\HookManager as RecordHookManager; - -trait RecordHookManagerSetter -{ - /** - * @var RecordHookManager - */ - protected $recordHookManager; - - public function setRecordHookManager(RecordHookManager $recordHookManager): void - { - $this->recordHookManager = $recordHookManager; - } -} diff --git a/application/Espo/Core/Record/Defaults/PopulatorFactory.php b/application/Espo/Core/Record/Defaults/PopulatorFactory.php index b383b9b713..6978cd8568 100644 --- a/application/Espo/Core/Record/Defaults/PopulatorFactory.php +++ b/application/Espo/Core/Record/Defaults/PopulatorFactory.php @@ -29,8 +29,11 @@ namespace Espo\Core\Record\Defaults; +use Espo\Core\Acl; +use Espo\Core\Binding\BindingContainerBuilder; use Espo\Core\InjectableFactory; use Espo\Core\Utils\Metadata; +use Espo\Entities\User; use Espo\ORM\Entity; class PopulatorFactory @@ -40,7 +43,9 @@ class PopulatorFactory public function __construct( private InjectableFactory $injectableFactory, - private Metadata $metadata + private Metadata $metadata, + private User $user, + private Acl $acl ) {} /** @@ -48,7 +53,12 @@ class PopulatorFactory */ public function create(string $entityType): Populator { - return $this->injectableFactory->create($this->getClassName($entityType)); + $binding = BindingContainerBuilder::create() + ->bindInstance(User::class, $this->user) + ->bindInstance(Acl::class, $this->acl) + ->build(); + + return $this->injectableFactory->createWithBinding($this->getClassName($entityType), $binding); } /** diff --git a/application/Espo/Core/Record/Hook/Provider.php b/application/Espo/Core/Record/Hook/Provider.php index 8b4d113f15..2c78551801 100644 --- a/application/Espo/Core/Record/Hook/Provider.php +++ b/application/Espo/Core/Record/Hook/Provider.php @@ -29,9 +29,13 @@ namespace Espo\Core\Record\Hook; +use Espo\Core\Acl; +use Espo\Core\Binding\BindingContainer; +use Espo\Core\Binding\BindingContainerBuilder; use Espo\Core\Utils\Metadata; use Espo\Core\InjectableFactory; +use Espo\Entities\User; use ReflectionClass; use RuntimeException; @@ -53,10 +57,19 @@ class Provider Type::BEFORE_UNLINK => [UnlinkHook::class], ]; + private BindingContainer $bindingContainer; + public function __construct( private Metadata $metadata, - private InjectableFactory $injectableFactory - ) {} + private InjectableFactory $injectableFactory, + private Acl $acl, + private User $user + ) { + $this->bindingContainer = BindingContainerBuilder::create() + ->bindInstance(User::class, $this->user) + ->bindInstance(Acl::class, $this->acl) + ->build(); + } /** * @return object[] @@ -107,7 +120,7 @@ class Provider throw new RuntimeException("Hook '$className' does not implement any required interface."); } - $list[] = $this->injectableFactory->create($className); + $list[] = $this->injectableFactory->createWithBinding($className, $this->bindingContainer); } return $list; diff --git a/application/Espo/Core/Record/Service.php b/application/Espo/Core/Record/Service.php index 7604889a45..e9c5485fd2 100644 --- a/application/Espo/Core/Record/Service.php +++ b/application/Espo/Core/Record/Service.php @@ -29,6 +29,7 @@ namespace Espo\Core\Record; +use Espo\Core\Binding\BindingContainer; use Espo\Core\Binding\BindingContainerBuilder; use Espo\Core\Binding\ContextualBinder; use Espo\Core\Exceptions\Conflict; @@ -98,8 +99,7 @@ class Service implements Crud, Di\FieldValidationManagerAware, Di\RecordServiceContainerAware, Di\SelectBuilderFactoryAware, - Di\AssignmentCheckerManagerAware, - Di\RecordHookManagerAware + Di\AssignmentCheckerManagerAware { use Di\ConfigSetter; use Di\ServiceFactorySetter; @@ -113,7 +113,6 @@ class Service implements Crud, use Di\RecordServiceContainerSetter; use Di\SelectBuilderFactorySetter; use Di\AssignmentCheckerManagerSetter; - use Di\RecordHookManagerSetter; protected string $entityType; protected bool $getEntityBeforeUpdate = false; @@ -268,6 +267,7 @@ class Service implements Crud, private ?ActionLogger $actionLogger = null; /** @var ?DefaultsPopulator */ private ?DefaultsPopulator $defaultsPopulator = null; + private ?HookManager $recordHookManager = null; /** @var ?Filter[] */ private ?array $createFilterList = null; /** @var ?Filter[] */ @@ -342,7 +342,7 @@ class Service implements Crud, throw new NotFoundSilent("Record $id does not exist."); } - $this->recordHookManager->processBeforeRead($entity, $params); + $this->getRecordHookManager()->processBeforeRead($entity, $params); $this->processActionHistoryRecord(Action::READ, $entity); return $entity; @@ -623,13 +623,7 @@ class Service implements Crud, private function createFilterProvider(): FilterProvider { - return $this->injectableFactory->createWithBinding( - FilterProvider::class, - BindingContainerBuilder::create() - ->bindInstance(User::class, $this->user) - ->bindInstance(Acl::class, $this->acl) - ->build() - ); + return $this->injectableFactory->createWithBinding(FilterProvider::class, $this->createBinding()); } /** @@ -822,13 +816,13 @@ class Service implements Crud, } $this->processApiBeforeCreateApiScript($entity, $params); - $this->recordHookManager->processBeforeCreate($entity, $params); + $this->getRecordHookManager()->processBeforeCreate($entity, $params); /** @noinspection PhpDeprecationInspection */ $this->beforeCreateEntity($entity, $data); $this->entityManager->saveEntity($entity, [SaveOption::API => true]); - $this->recordHookManager->processAfterCreate($entity, $params); + $this->getRecordHookManager()->processAfterCreate($entity, $params); /** @noinspection PhpDeprecationInspection */ $this->afterCreateEntity($entity, $data); /** @noinspection PhpDeprecationInspection */ @@ -901,7 +895,7 @@ class Service implements Crud, } $this->processApiBeforeUpdateApiScript($entity, $params); - $this->recordHookManager->processBeforeUpdate($entity, $params); + $this->getRecordHookManager()->processBeforeUpdate($entity, $params); /** @noinspection PhpDeprecationInspection */ $this->beforeUpdateEntity($entity, $data); @@ -910,7 +904,7 @@ class Service implements Crud, SaveOption::KEEP_DIRTY => true, ]); - $this->recordHookManager->processAfterUpdate($entity, $params); + $this->getRecordHookManager()->processAfterUpdate($entity, $params); $entity->updateFetchedValues(); /** @noinspection PhpDeprecationInspection */ @@ -954,7 +948,7 @@ class Service implements Crud, throw new ForbiddenSilent("No delete access."); } - $this->recordHookManager->processBeforeDelete($entity, $params); + $this->getRecordHookManager()->processBeforeDelete($entity, $params); /** @noinspection PhpDeprecationInspection */ $this->beforeDeleteEntity($entity); @@ -962,7 +956,7 @@ class Service implements Crud, /** @noinspection PhpDeprecationInspection */ $this->afterDeleteEntity($entity); - $this->recordHookManager->processAfterDelete($entity, $params); + $this->getRecordHookManager()->processAfterDelete($entity, $params); $this->processActionHistoryRecord(Action::DELETE, $entity); } @@ -1275,7 +1269,7 @@ class Service implements Crud, $this->getLinkCheck()->processLinkForeign($entity, $link, $foreignEntity); - $this->recordHookManager->processBeforeLink($entity, $link, $foreignEntity); + $this->getRecordHookManager()->processBeforeLink($entity, $link, $foreignEntity); $this->getRepository() ->getRelation($entity, $link) @@ -1331,7 +1325,7 @@ class Service implements Crud, $this->getLinkCheck()->processUnlinkForeign($entity, $link, $foreignEntity); - $this->recordHookManager->processBeforeUnlink($entity, $link, $foreignEntity); + $this->getRecordHookManager()->processBeforeUnlink($entity, $link, $foreignEntity); $this->getRepository() ->getRelation($entity, $link) @@ -1998,4 +1992,22 @@ class Service implements Crud, */ protected function afterDeleteEntity(Entity $entity) {} + + private function createBinding(): BindingContainer + { + return BindingContainerBuilder::create() + ->bindInstance(User::class, $this->user) + ->bindInstance(Acl::class, $this->acl) + ->build(); + } + + private function getRecordHookManager(): HookManager + { + if (!$this->recordHookManager) { + $this->recordHookManager = + $this->injectableFactory->createWithBinding(HookManager::class, $this->createBinding()); + } + + return $this->recordHookManager; + } } diff --git a/application/Espo/Resources/metadata/app/containerServices.json b/application/Espo/Resources/metadata/app/containerServices.json index e8cbad9e1b..6748616b5c 100644 --- a/application/Espo/Resources/metadata/app/containerServices.json +++ b/application/Espo/Resources/metadata/app/containerServices.json @@ -38,9 +38,6 @@ "recordServiceContainer": { "className": "Espo\\Core\\Record\\ServiceContainer" }, - "recordHookManager": { - "className": "Espo\\Core\\Record\\HookManager" - }, "templateFileManager": { "className": "Espo\\Core\\Utils\\TemplateFileManager" }, diff --git a/tests/unit/Espo/Core/Record/HookManagerTest.php b/tests/unit/Espo/Core/Record/HookManagerTest.php index c3dd12f8cb..5918e78b6d 100644 --- a/tests/unit/Espo/Core/Record/HookManagerTest.php +++ b/tests/unit/Espo/Core/Record/HookManagerTest.php @@ -30,6 +30,9 @@ namespace tests\unit\Espo\Core\Record; use Espo\Core\{ + Acl, + Binding\BindingContainer, + Binding\BindingContainerBuilder, Record\HookManager, Record\Hook\Provider, Record\Hook\Type, @@ -38,9 +41,9 @@ use Espo\Core\{ Record\UpdateParams, Record\DeleteParams, InjectableFactory, - Utils\Metadata, -}; + Utils\Metadata}; +use Espo\Entities\User; use Espo\ORM\Entity; use tests\unit\testClasses\Core\Record\Hooks\{ @@ -64,11 +67,6 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase */ private $metadata; - /** - * @var Provider - */ - private $provider; - /** * @var HookManager */ @@ -81,14 +79,24 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase private $entityType = 'Test'; + private ?BindingContainer $bindingContainer; + protected function setUp(): void { $this->injectableFactory = $this->createMock(InjectableFactory::class); $this->metadata = $this->createMock(Metadata::class); - $this->provider = new Provider($this->metadata, $this->injectableFactory); + $acl = $this->createMock(Acl::class); + $user = $this->createMock(User::class); - $this->manager = new HookManager($this->provider); + $this->bindingContainer = BindingContainerBuilder::create() + ->bindInstance(User::class, $user) + ->bindInstance(Acl::class, $acl) + ->build(); + + $provider = new Provider($this->metadata, $this->injectableFactory, $acl, $user); + + $this->manager = new HookManager($provider); $this->entity = $this->createEntity($this->entityType); } @@ -212,8 +220,8 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase foreach ($hookClassNameList as $i => $className) { $this->injectableFactory ->expects($this->any()) - ->method('create') - ->with($className) + ->method('createWithBinding') + ->with($className, $this->bindingContainer) ->willReturn($hookList[$i]); } }