diff --git a/application/Espo/Classes/Cleanup/Stars.php b/application/Espo/Classes/Cleanup/Stars.php new file mode 100644 index 0000000000..028b2190ee --- /dev/null +++ b/application/Espo/Classes/Cleanup/Stars.php @@ -0,0 +1,138 @@ +. + * + * 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\Classes\Cleanup; + +use Espo\Core\Cleanup\Cleanup; +use Espo\Core\Utils\Acl\UserAclManagerProvider; +use Espo\Entities\StarSubscription; +use Espo\Entities\User; +use Espo\ORM\EntityManager; +use Espo\ORM\Query\DeleteBuilder; +use Espo\Tools\Stars\StarService; + +/** + * @noinspection PhpUnused + */ +class Stars implements Cleanup +{ + public function __construct( + private EntityManager $entityManager, + private UserAclManagerProvider $userAclManagerProvider, + private StarService $service + ) {} + + public function process(): void + { + foreach ($this->getEntityTypeList() as $entityType) { + $this->processEntityType($entityType); + } + } + + /** + * @return string[] + */ + private function getEntityTypeList(): array + { + $groups = $this->entityManager->getRDBRepositoryByClass(StarSubscription::class) + ->group('entityType') + ->select('entityType') + ->find(); + + $list = []; + + foreach ($groups as $group) { + $list[] = $group->get('entityType'); + } + + return $list; + } + + private function processEntityType(string $entityType): void + { + if ( + !$this->service->isEnabled($entityType) || + !$this->entityManager->hasRepository($entityType) + ) { + $deleteQuery = DeleteBuilder::create() + ->from(StarSubscription::ENTITY_TYPE) + ->where(['entityType' => $entityType]) + ->build(); + + $this->entityManager->getQueryExecutor()->execute($deleteQuery); + + return; + } + + $stars = $this->entityManager + ->getRDBRepositoryByClass(StarSubscription::class) + ->where(['entityType' => $entityType]) + ->sth() + ->find(); + + foreach ($stars as $star) { + $entityId = $star->get('entityId'); + $userId = $star->get('userId'); + + if ($userId === null || $entityId === null) { + // @todo Cleanup. + continue; + } + + $entity = $this->entityManager->getEntityById($entityType, $entityId); + $user = $this->entityManager->getRDBRepositoryByClass(User::class)->getById($userId); + + if (!$entity || !$user) { + $this->unstar($userId, $entityType, $entityId); + + continue; + } + + $aclManager = $this->userAclManagerProvider->get($user); + + if (!$aclManager->checkEntityRead($user, $entity)) { + $this->unstar($userId, $entityType, $entityId); + } + } + } + + private function unstar(string $userId, string $entityType, string $entityId): void + { + $deleteQuery = DeleteBuilder::create() + ->from(StarSubscription::ENTITY_TYPE) + ->where([ + 'userId' => $userId, + 'entityType' => $entityType, + 'entityId' => $entityId, + ]) + ->build(); + + $this->entityManager->getQueryExecutor()->execute($deleteQuery); + } +} diff --git a/application/Espo/Resources/metadata/app/cleanup.json b/application/Espo/Resources/metadata/app/cleanup.json index 4508497fc6..ed90e1cc5c 100644 --- a/application/Espo/Resources/metadata/app/cleanup.json +++ b/application/Espo/Resources/metadata/app/cleanup.json @@ -24,5 +24,8 @@ }, "audit": { "className": "Espo\\Classes\\Cleanup\\Audit" + }, + "stars": { + "className": "Espo\\Classes\\Cleanup\\Stars" } }