From cf789f281ab745b37a60fc6e89af8c303c4eda43 Mon Sep 17 00:00:00 2001 From: kirill Date: Sun, 8 Feb 2026 12:30:34 +0300 Subject: [PATCH 1/6] Remove unused repository methods `deleteByApplicationInstallationId` and `countByApplicationInstallationId` --- .../DoctrineDbalJournalItemRepository.php | 53 ++++++------------- .../JournalItemRepositoryInterface.php | 10 ---- .../InMemoryJournalItemRepository.php | 20 ------- .../InMemoryJournalItemRepositoryTest.php | 47 ---------------- 4 files changed, 15 insertions(+), 115 deletions(-) diff --git a/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php b/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php index a9bccc7..e3dcd3b 100644 --- a/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php +++ b/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php @@ -22,24 +22,26 @@ use Doctrine\ORM\EntityRepository; use Symfony\Component\Uid\Uuid; -class DoctrineDbalJournalItemRepository extends EntityRepository implements JournalItemRepositoryInterface +class DoctrineDbalJournalItemRepository implements JournalItemRepositoryInterface { + private readonly EntityRepository $repository; + public function __construct( - EntityManagerInterface $entityManager + private readonly EntityManagerInterface $entityManager ) { - parent::__construct($entityManager, $entityManager->getClassMetadata(JournalItem::class)); + $this->repository = $this->entityManager->getRepository(JournalItem::class); } #[\Override] public function save(JournalItemInterface $journalItem): void { - $this->getEntityManager()->persist($journalItem); + $this->entityManager->persist($journalItem); } #[\Override] public function findById(Uuid $id): ?JournalItemInterface { - return $this->getEntityManager()->getRepository(JournalItem::class)->find($id); + return $this->repository->find($id); } /** @@ -52,15 +54,17 @@ public function findByApplicationInstallationId( ?int $limit = null, ?int $offset = null ): array { - $qb = $this->getEntityManager()->getRepository(JournalItem::class) + $qb = $this->repository ->createQueryBuilder('j') ->where('j.applicationInstallationId = :appId') ->setParameter('appId', $applicationInstallationId) - ->orderBy('j.createdAt', 'DESC'); + ->orderBy('j.createdAt', 'DESC') + ; if (null !== $level) { $qb->andWhere('j.level = :level') - ->setParameter('level', $level); + ->setParameter('level', $level) + ; } if (null !== $limit) { @@ -74,42 +78,15 @@ public function findByApplicationInstallationId( return $qb->getQuery()->getResult(); } - #[\Override] - public function deleteByApplicationInstallationId(Uuid $applicationInstallationId): int - { - return $this->getEntityManager()->createQueryBuilder() - ->delete(JournalItem::class, 'j') - ->where('j.applicationInstallationId = :appId') - ->setParameter('appId', $applicationInstallationId) - ->getQuery() - ->execute(); - } - #[\Override] public function deleteOlderThan(CarbonImmutable $date): int { - return $this->getEntityManager()->createQueryBuilder() + return $this->entityManager->createQueryBuilder() ->delete(JournalItem::class, 'j') ->where('j.createdAt < :date') ->setParameter('date', $date) ->getQuery() - ->execute(); - } - - #[\Override] - public function countByApplicationInstallationId(Uuid $applicationInstallationId, ?LogLevel $level = null): int - { - $qb = $this->getEntityManager()->getRepository(JournalItem::class) - ->createQueryBuilder('j') - ->select('COUNT(j.id)') - ->where('j.applicationInstallationId = :appId') - ->setParameter('appId', $applicationInstallationId); - - if (null !== $level) { - $qb->andWhere('j.level = :level') - ->setParameter('level', $level); - } - - return (int) $qb->getQuery()->getSingleScalarResult(); + ->execute() + ; } } diff --git a/src/Journal/Infrastructure/JournalItemRepositoryInterface.php b/src/Journal/Infrastructure/JournalItemRepositoryInterface.php index eb1fe4d..a7019d9 100644 --- a/src/Journal/Infrastructure/JournalItemRepositoryInterface.php +++ b/src/Journal/Infrastructure/JournalItemRepositoryInterface.php @@ -45,18 +45,8 @@ public function findByApplicationInstallationId( ?int $offset = null ): array; - /** - * Delete all journal items by application installation ID - */ - public function deleteByApplicationInstallationId(Uuid $applicationInstallationId): int; - /** * Delete journal items older than specified date */ public function deleteOlderThan(CarbonImmutable $date): int; - - /** - * Count journal items by application installation ID - */ - public function countByApplicationInstallationId(Uuid $applicationInstallationId, ?LogLevel $level = null): int; } diff --git a/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php b/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php index 5b8789b..a5fe835 100644 --- a/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php +++ b/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php @@ -82,20 +82,6 @@ static function (JournalItemInterface $item) use ($applicationInstallationId, $l return $filtered; } - #[\Override] - public function deleteByApplicationInstallationId(Uuid $applicationInstallationId): int - { - $count = 0; - foreach ($this->items as $key => $item) { - if ($item->getApplicationInstallationId()->equals($applicationInstallationId)) { - unset($this->items[$key]); - ++$count; - } - } - - return $count; - } - #[\Override] public function deleteOlderThan(CarbonImmutable $date): int { @@ -110,12 +96,6 @@ public function deleteOlderThan(CarbonImmutable $date): int return $count; } - #[\Override] - public function countByApplicationInstallationId(Uuid $applicationInstallationId, ?LogLevel $level = null): int - { - return count($this->findByApplicationInstallationId($applicationInstallationId, $level)); - } - /** * Get all items (for testing purposes) * diff --git a/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php b/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php index 19c3d52..7386ec4 100644 --- a/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php +++ b/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php @@ -141,25 +141,6 @@ public function testFindByApplicationInstallationIdWithLimitAndOffset(): void $this->assertCount(3, $items); } - public function testDeleteByApplicationInstallationId(): void - { - $context = new JournalContext('test.label'); - $item1 = JournalItem::info($this->applicationInstallationId, 'Message 1', $context); - $item2 = JournalItem::info($this->applicationInstallationId, 'Message 2', $context); - $otherInstallationId = Uuid::v7(); - $item3 = JournalItem::info($otherInstallationId, 'Message 3', $context); - - $this->repository->save($item1); - $this->repository->save($item2); - $this->repository->save($item3); - - $deleted = $this->repository->deleteByApplicationInstallationId($this->applicationInstallationId); - - $this->assertSame(2, $deleted); - $this->assertEmpty($this->repository->findByApplicationInstallationId($this->applicationInstallationId)); - $this->assertCount(1, $this->repository->findByApplicationInstallationId($otherInstallationId)); - } - public function testDeleteOlderThan(): void { $context = new JournalContext('test.label'); @@ -173,34 +154,6 @@ public function testDeleteOlderThan(): void $this->assertSame(1, $deleted); } - public function testCountByApplicationInstallationId(): void - { - $context = new JournalContext('test.label'); - for ($i = 1; $i <= 5; ++$i) { - $item = JournalItem::info($this->applicationInstallationId, "Message {$i}", $context); - $this->repository->save($item); - } - - $count = $this->repository->countByApplicationInstallationId($this->applicationInstallationId); - - $this->assertSame(5, $count); - } - - public function testCountByApplicationInstallationIdWithLevelFilter(): void - { - $context = new JournalContext('test.label'); - $this->repository->save(JournalItem::info($this->applicationInstallationId, 'Info 1', $context)); - $this->repository->save(JournalItem::info($this->applicationInstallationId, 'Info 2', $context)); - $this->repository->save(JournalItem::error($this->applicationInstallationId, 'Error 1', $context)); - - $count = $this->repository->countByApplicationInstallationId( - $this->applicationInstallationId, - LogLevel::info - ); - - $this->assertSame(2, $count); - } - public function testClear(): void { $context = new JournalContext('test.label'); From e04d8b3be3b26e2945efc503974998a6a77be48a Mon Sep 17 00:00:00 2001 From: kirill Date: Fri, 13 Feb 2026 00:03:32 +0300 Subject: [PATCH 2/6] Refactor: normalize parameter naming, add missing doc punctuation, and implement minor code quality updates --- ...ournal.ValueObjects.JournalContext.dcm.xml | 2 +- rector.php | 4 +- .../Controller/JournalAdminController.php | 13 +-- src/Journal/Entity/JournalItem.php | 46 ++++---- src/Journal/Entity/JournalItemInterface.php | 2 +- src/Journal/Entity/LogLevel.php | 4 +- .../DoctrineDbalJournalItemRepository.php | 24 ++-- .../JournalItemRepositoryInterface.php | 16 +-- .../ReadModel/JournalItemReadRepository.php | 87 +++++++------- src/Journal/Services/JournalLogger.php | 14 +-- src/Journal/Services/JournalLoggerFactory.php | 7 +- src/Journal/ValueObjects/JournalContext.php | 7 +- tests/EntityManagerFactory.php | 5 + tests/Unit/Journal/Entity/JournalItemTest.php | 107 +++++++++--------- tests/Unit/Journal/Entity/LogLevelTest.php | 34 +++--- .../InMemoryJournalItemRepository.php | 20 ++-- .../InMemoryJournalItemRepositoryTest.php | 65 +++++------ .../Journal/Services/JournalLoggerTest.php | 1 + 18 files changed, 234 insertions(+), 224 deletions(-) diff --git a/config/xml/Bitrix24.Lib.Journal.ValueObjects.JournalContext.dcm.xml b/config/xml/Bitrix24.Lib.Journal.ValueObjects.JournalContext.dcm.xml index 97fdee3..8291328 100644 --- a/config/xml/Bitrix24.Lib.Journal.ValueObjects.JournalContext.dcm.xml +++ b/config/xml/Bitrix24.Lib.Journal.ValueObjects.JournalContext.dcm.xml @@ -8,6 +8,6 @@ - + diff --git a/rector.php b/rector.php index 3ce8e42..59026b6 100644 --- a/rector.php +++ b/rector.php @@ -15,6 +15,7 @@ use Rector\Naming\Rector\Class_\RenamePropertyToMatchTypeRector; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\DowngradeLevelSetList; +use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector; return RectorConfig::configure() ->withPaths([ @@ -48,5 +49,6 @@ strictBooleans: true ) ->withSkip([ - RenamePropertyToMatchTypeRector::class + RenamePropertyToMatchTypeRector::class, + FlipTypeControlToUseExclusiveTypeRector::class, ]); \ No newline at end of file diff --git a/src/Journal/Controller/JournalAdminController.php b/src/Journal/Controller/JournalAdminController.php index 0aab3bb..e2a73f5 100644 --- a/src/Journal/Controller/JournalAdminController.php +++ b/src/Journal/Controller/JournalAdminController.php @@ -22,17 +22,16 @@ /** * Admin controller for journal management - * Developer should configure routes in their application + * Developer should configure routes in their application. */ class JournalAdminController extends AbstractController { public function __construct( private readonly JournalItemReadRepository $journalReadRepository - ) { - } + ) {} /** - * List journal items with filters and pagination + * List journal items with filters and pagination. */ public function list(Request $request): Response { @@ -48,7 +47,7 @@ public function list(Request $request): Response $pagination = $this->journalReadRepository->findWithFilters( domainUrl: $domainUrl ?: null, - level: $level, + logLevel: $level, label: $label ?: null, page: $page, limit: 50 @@ -71,7 +70,7 @@ public function list(Request $request): Response } /** - * Show journal item details + * Show journal item details. */ public function show(string $id): Response { @@ -83,7 +82,7 @@ public function show(string $id): Response $journalItem = $this->journalReadRepository->findById($uuid); - if (!$journalItem) { + if (null === $journalItem) { throw $this->createNotFoundException('Journal item not found'); } diff --git a/src/Journal/Entity/JournalItem.php b/src/Journal/Entity/JournalItem.php index 36a1011..b45a58d 100644 --- a/src/Journal/Entity/JournalItem.php +++ b/src/Journal/Entity/JournalItem.php @@ -21,7 +21,7 @@ /** * Journal item entity - * Each journal record contains domain business events for technical support staff + * Each journal record contains domain business events for technical support staff. */ class JournalItem extends AggregateRoot implements JournalItemInterface { @@ -30,10 +30,10 @@ class JournalItem extends AggregateRoot implements JournalItemInterface private readonly CarbonImmutable $createdAt; public function __construct( - private Uuid $applicationInstallationId, - private LogLevel $level, - private string $message, - private JournalContext $context + private readonly Uuid $applicationInstallationId, + private readonly LogLevel $level, + private readonly string $message, + private readonly JournalContext $context ) { if ('' === trim($this->message)) { throw new InvalidArgumentException('Journal message cannot be empty'); @@ -80,7 +80,7 @@ public function getContext(): JournalContext } /** - * Create journal item with custom log level + * Create journal item with custom log level. */ public static function create( Uuid $applicationInstallationId, @@ -97,45 +97,45 @@ public static function create( } /** - * PSR-3 compatible factory methods + * PSR-3 compatible factory methods. */ - public static function emergency(Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function emergency(Uuid $uuid, string $message, JournalContext $journalContext): self { - return self::create($applicationInstallationId, LogLevel::emergency, $message, $context); + return self::create($uuid, LogLevel::emergency, $message, $journalContext); } - public static function alert(Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function alert(Uuid $uuid, string $message, JournalContext $journalContext): self { - return self::create($applicationInstallationId, LogLevel::alert, $message, $context); + return self::create($uuid, LogLevel::alert, $message, $journalContext); } - public static function critical(Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function critical(Uuid $uuid, string $message, JournalContext $journalContext): self { - return self::create($applicationInstallationId, LogLevel::critical, $message, $context); + return self::create($uuid, LogLevel::critical, $message, $journalContext); } - public static function error(Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function error(Uuid $uuid, string $message, JournalContext $journalContext): self { - return self::create($applicationInstallationId, LogLevel::error, $message, $context); + return self::create($uuid, LogLevel::error, $message, $journalContext); } - public static function warning(Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function warning(Uuid $uuid, string $message, JournalContext $journalContext): self { - return self::create($applicationInstallationId, LogLevel::warning, $message, $context); + return self::create($uuid, LogLevel::warning, $message, $journalContext); } - public static function notice(Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function notice(Uuid $uuid, string $message, JournalContext $journalContext): self { - return self::create($applicationInstallationId, LogLevel::notice, $message, $context); + return self::create($uuid, LogLevel::notice, $message, $journalContext); } - public static function info(Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function info(Uuid $uuid, string $message, JournalContext $journalContext): self { - return self::create($applicationInstallationId, LogLevel::info, $message, $context); + return self::create($uuid, LogLevel::info, $message, $journalContext); } - public static function debug(Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function debug(Uuid $uuid, string $message, JournalContext $journalContext): self { - return self::create($applicationInstallationId, LogLevel::debug, $message, $context); + return self::create($uuid, LogLevel::debug, $message, $journalContext); } } diff --git a/src/Journal/Entity/JournalItemInterface.php b/src/Journal/Entity/JournalItemInterface.php index bccbddb..74e2cf8 100644 --- a/src/Journal/Entity/JournalItemInterface.php +++ b/src/Journal/Entity/JournalItemInterface.php @@ -18,7 +18,7 @@ use Symfony\Component\Uid\Uuid; /** - * Journal item interface for SDK contract extraction + * Journal item interface for SDK contract extraction. */ interface JournalItemInterface { diff --git a/src/Journal/Entity/LogLevel.php b/src/Journal/Entity/LogLevel.php index bc4dfbb..1f8c891 100644 --- a/src/Journal/Entity/LogLevel.php +++ b/src/Journal/Entity/LogLevel.php @@ -14,7 +14,7 @@ namespace Bitrix24\Lib\Journal\Entity; /** - * PSR-3 compatible log level enum + * PSR-3 compatible log level enum. */ enum LogLevel: string { @@ -28,7 +28,7 @@ enum LogLevel: string case debug = 'debug'; /** - * Creates LogLevel from PSR-3 log level string + * Creates LogLevel from PSR-3 log level string. */ public static function fromPsr3Level(string $level): self { diff --git a/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php b/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php index e3dcd3b..4f4e4af 100644 --- a/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php +++ b/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php @@ -39,9 +39,9 @@ public function save(JournalItemInterface $journalItem): void } #[\Override] - public function findById(Uuid $id): ?JournalItemInterface + public function findById(Uuid $uuid): ?JournalItemInterface { - return $this->repository->find($id); + return $this->repository->find($uuid); } /** @@ -49,33 +49,33 @@ public function findById(Uuid $id): ?JournalItemInterface */ #[\Override] public function findByApplicationInstallationId( - Uuid $applicationInstallationId, - ?LogLevel $level = null, + Uuid $uuid, + ?LogLevel $logLevel = null, ?int $limit = null, ?int $offset = null ): array { - $qb = $this->repository + $queryBuilder = $this->repository ->createQueryBuilder('j') ->where('j.applicationInstallationId = :appId') - ->setParameter('appId', $applicationInstallationId) + ->setParameter('appId', $uuid) ->orderBy('j.createdAt', 'DESC') ; - if (null !== $level) { - $qb->andWhere('j.level = :level') - ->setParameter('level', $level) + if (null !== $logLevel) { + $queryBuilder->andWhere('j.level = :level') + ->setParameter('level', $logLevel) ; } if (null !== $limit) { - $qb->setMaxResults($limit); + $queryBuilder->setMaxResults($limit); } if (null !== $offset) { - $qb->setFirstResult($offset); + $queryBuilder->setFirstResult($offset); } - return $qb->getQuery()->getResult(); + return $queryBuilder->getQuery()->getResult(); } #[\Override] diff --git a/src/Journal/Infrastructure/JournalItemRepositoryInterface.php b/src/Journal/Infrastructure/JournalItemRepositoryInterface.php index a7019d9..2039ee3 100644 --- a/src/Journal/Infrastructure/JournalItemRepositoryInterface.php +++ b/src/Journal/Infrastructure/JournalItemRepositoryInterface.php @@ -19,34 +19,34 @@ use Symfony\Component\Uid\Uuid; /** - * Journal item repository interface for SDK contract extraction + * Journal item repository interface for SDK contract extraction. */ interface JournalItemRepositoryInterface { /** - * Save journal item + * Save journal item. */ public function save(JournalItemInterface $journalItem): void; /** - * Find journal item by ID + * Find journal item by ID. */ - public function findById(Uuid $id): ?JournalItemInterface; + public function findById(Uuid $uuid): ?JournalItemInterface; /** - * Find journal items by application installation ID + * Find journal items by application installation ID. * * @return JournalItemInterface[] */ public function findByApplicationInstallationId( - Uuid $applicationInstallationId, - ?LogLevel $level = null, + Uuid $uuid, + ?LogLevel $logLevel = null, ?int $limit = null, ?int $offset = null ): array; /** - * Delete journal items older than specified date + * Delete journal items older than specified date. */ public function deleteOlderThan(CarbonImmutable $date): int; } diff --git a/src/Journal/ReadModel/JournalItemReadRepository.php b/src/Journal/ReadModel/JournalItemReadRepository.php index 6faa9be..7e08fa4 100644 --- a/src/Journal/ReadModel/JournalItemReadRepository.php +++ b/src/Journal/ReadModel/JournalItemReadRepository.php @@ -13,42 +13,43 @@ namespace Bitrix24\Lib\Journal\ReadModel; +use Bitrix24\Lib\ApplicationInstallations\Entity\ApplicationInstallation; +use Bitrix24\Lib\Bitrix24Accounts\Entity\Bitrix24Account; use Bitrix24\Lib\Journal\Entity\JournalItem; use Bitrix24\Lib\Journal\Entity\JournalItemInterface; use Bitrix24\Lib\Journal\Entity\LogLevel; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; -use Knp\Component\Pager\PaginatorInterface; use Knp\Component\Pager\Pagination\PaginationInterface; +use Knp\Component\Pager\PaginatorInterface; use Symfony\Component\Uid\Uuid; /** - * Read model repository for journal items with filtering and pagination + * Read model repository for journal items with filtering and pagination. */ readonly class JournalItemReadRepository { public function __construct( private EntityManagerInterface $entityManager, private PaginatorInterface $paginator - ) { - } + ) {} /** - * Find journal items with filters and pagination + * Find journal items with filters and pagination. * * @return PaginationInterface */ public function findWithFilters( ?string $domainUrl = null, - ?LogLevel $level = null, + ?LogLevel $logLevel = null, ?string $label = null, int $page = 1, int $limit = 50 ): PaginationInterface { - $qb = $this->createFilteredQueryBuilder($domainUrl, $level, $label); + $queryBuilder = $this->createFilteredQueryBuilder($domainUrl, $logLevel, $label); return $this->paginator->paginate( - $qb, + $queryBuilder, $page, $limit, [ @@ -59,82 +60,88 @@ public function findWithFilters( } /** - * Find journal item by ID + * Find journal item by ID. */ - public function findById(Uuid $id): ?JournalItemInterface + public function findById(Uuid $uuid): ?JournalItemInterface { - return $this->entityManager->getRepository(JournalItem::class)->find($id); + return $this->entityManager->getRepository(JournalItem::class)->find($uuid); } /** - * Get available domain URLs from journal + * Get available domain URLs from journal. * * @return string[] */ public function getAvailableDomains(): array { // Join with ApplicationInstallation and then Bitrix24Account to get domain URLs - $qb = $this->entityManager->createQueryBuilder(); - $qb->select('DISTINCT b24.domainUrl') + $queryBuilder = $this->entityManager->createQueryBuilder(); + $queryBuilder->select('DISTINCT b24.domainUrl') ->from(JournalItem::class, 'j') - ->innerJoin('Bitrix24\Lib\ApplicationInstallations\Entity\ApplicationInstallation', 'ai', 'WITH', 'ai.id = j.applicationInstallationId') - ->innerJoin('Bitrix24\Lib\Bitrix24Accounts\Entity\Bitrix24Account', 'b24', 'WITH', 'b24.id = ai.bitrix24AccountId') - ->orderBy('b24.domainUrl', 'ASC'); + ->innerJoin(ApplicationInstallation::class, 'ai', 'WITH', 'ai.id = j.applicationInstallationId') + ->innerJoin(Bitrix24Account::class, 'b24', 'WITH', 'b24.id = ai.bitrix24AccountId') + ->orderBy('b24.domainUrl', 'ASC') + ; - $results = $qb->getQuery()->getScalarResult(); + $results = $queryBuilder->getQuery()->getScalarResult(); return array_column($results, 'domainUrl'); } /** - * Get available labels from journal + * Get available labels from journal. * * @return string[] */ public function getAvailableLabels(): array { - $qb = $this->entityManager->createQueryBuilder(); - $qb->select('DISTINCT j.context.label') + $queryBuilder = $this->entityManager->createQueryBuilder(); + $queryBuilder->select('DISTINCT j.context.label') ->from(JournalItem::class, 'j') ->where('j.context.label IS NOT NULL') - ->orderBy('j.context.label', 'ASC'); + ->orderBy('j.context.label', 'ASC') + ; - $results = $qb->getQuery()->getScalarResult(); + $results = $queryBuilder->getQuery()->getScalarResult(); return array_filter(array_column($results, 'label')); } /** - * Create query builder with filters + * Create query builder with filters. */ private function createFilteredQueryBuilder( ?string $domainUrl = null, - ?LogLevel $level = null, + ?LogLevel $logLevel = null, ?string $label = null ): QueryBuilder { - $qb = $this->entityManager->createQueryBuilder(); - $qb->select('j') - ->from(JournalItem::class, 'j'); + $queryBuilder = $this->entityManager->createQueryBuilder(); + $queryBuilder->select('j') + ->from(JournalItem::class, 'j') + ; - if ($domainUrl) { - $qb->innerJoin('Bitrix24\Lib\ApplicationInstallations\Entity\ApplicationInstallation', 'ai', 'WITH', 'ai.id = j.applicationInstallationId') - ->innerJoin('Bitrix24\Lib\Bitrix24Accounts\Entity\Bitrix24Account', 'b24', 'WITH', 'b24.id = ai.bitrix24AccountId') + if (null !== $domainUrl && '' !== $domainUrl && '0' !== $domainUrl) { + $queryBuilder->innerJoin(ApplicationInstallation::class, 'ai', 'WITH', 'ai.id = j.applicationInstallationId') + ->innerJoin(Bitrix24Account::class, 'b24', 'WITH', 'b24.id = ai.bitrix24AccountId') ->andWhere('b24.domainUrl = :domainUrl') - ->setParameter('domainUrl', $domainUrl); + ->setParameter('domainUrl', $domainUrl) + ; } - if ($level) { - $qb->andWhere('j.level = :level') - ->setParameter('level', $level); + if (null !== $logLevel) { + $queryBuilder->andWhere('j.level = :level') + ->setParameter('level', $logLevel) + ; } - if ($label) { - $qb->andWhere('j.context.label = :label') - ->setParameter('label', $label); + if (null !== $label && '' !== $label && '0' !== $label) { + $queryBuilder->andWhere('j.context.label = :label') + ->setParameter('label', $label) + ; } - $qb->orderBy('j.createdAt', 'DESC'); + $queryBuilder->orderBy('j.createdAt', 'DESC'); - return $qb; + return $queryBuilder; } } diff --git a/src/Journal/Services/JournalLogger.php b/src/Journal/Services/JournalLogger.php index 1af06ac..0402dd0 100644 --- a/src/Journal/Services/JournalLogger.php +++ b/src/Journal/Services/JournalLogger.php @@ -25,7 +25,7 @@ /** * PSR-3 compatible journal logger - * Writes log entries to the journal repository + * Writes log entries to the journal repository. */ class JournalLogger implements LoggerInterface { @@ -35,14 +35,12 @@ public function __construct( private readonly Uuid $applicationInstallationId, private readonly JournalItemRepositoryInterface $repository, private readonly EntityManagerInterface $entityManager - ) { - } + ) {} /** - * Logs with an arbitrary level + * Logs with an arbitrary level. * - * @param mixed $level - * @param string|\Stringable $message + * @param mixed $level * @param array $context */ #[\Override] @@ -63,7 +61,7 @@ public function log($level, string|\Stringable $message, array $context = []): v } /** - * Convert PSR-3 log level to LogLevel enum + * Convert PSR-3 log level to LogLevel enum. */ private function convertLevel(mixed $level): LogLevel { @@ -81,7 +79,7 @@ private function convertLevel(mixed $level): LogLevel } /** - * Create JournalContext from PSR-3 context array + * Create JournalContext from PSR-3 context array. */ private function createContext(array $context): JournalContext { diff --git a/src/Journal/Services/JournalLoggerFactory.php b/src/Journal/Services/JournalLoggerFactory.php index 3b09d5e..fb46b06 100644 --- a/src/Journal/Services/JournalLoggerFactory.php +++ b/src/Journal/Services/JournalLoggerFactory.php @@ -19,18 +19,17 @@ use Symfony\Component\Uid\Uuid; /** - * Factory for creating JournalLogger instances + * Factory for creating JournalLogger instances. */ readonly class JournalLoggerFactory { public function __construct( private JournalItemRepositoryInterface $repository, private EntityManagerInterface $entityManager - ) { - } + ) {} /** - * Create logger for specific application installation + * Create logger for specific application installation. */ public function createLogger(Uuid $applicationInstallationId): LoggerInterface { diff --git a/src/Journal/ValueObjects/JournalContext.php b/src/Journal/ValueObjects/JournalContext.php index 627e5cd..fe13a5c 100644 --- a/src/Journal/ValueObjects/JournalContext.php +++ b/src/Journal/ValueObjects/JournalContext.php @@ -16,7 +16,7 @@ use Darsyn\IP\Version\Multi as IP; /** - * Journal context value object + * Journal context value object. */ readonly class JournalContext { @@ -25,8 +25,7 @@ public function __construct( private ?array $payload = null, private ?int $bitrix24UserId = null, private ?IP $ipAddress = null - ) { - } + ) {} public function getLabel(): string { @@ -49,7 +48,7 @@ public function getIpAddress(): ?IP } /** - * Convert to array + * Convert to array. */ public function toArray(): array { diff --git a/tests/EntityManagerFactory.php b/tests/EntityManagerFactory.php index e3935cf..621244e 100644 --- a/tests/EntityManagerFactory.php +++ b/tests/EntityManagerFactory.php @@ -7,6 +7,7 @@ use Bitrix24\SDK\Core\Exceptions\WrongConfigurationException; use Carbon\Doctrine\CarbonImmutableType; use Doctrine\DBAL\DriverManager; +use Darsyn\IP\Doctrine\MultiType; use Doctrine\DBAL\Exception; use Doctrine\DBAL\Types\Type; use Doctrine\ORM\EntityManager; @@ -66,6 +67,10 @@ public static function get(): EntityManagerInterface Type::addType('carbon_immutable', CarbonImmutableType::class); } + if (!Type::hasType('ip_address')) { + Type::addType('ip_address', MultiType::class); + } + $configuration = ORMSetup::createXMLMetadataConfiguration($paths, $isDevMode); $connection = DriverManager::getConnection($connectionParams, $configuration); diff --git a/tests/Unit/Journal/Entity/JournalItemTest.php b/tests/Unit/Journal/Entity/JournalItemTest.php index 0aeef62..abb7def 100644 --- a/tests/Unit/Journal/Entity/JournalItemTest.php +++ b/tests/Unit/Journal/Entity/JournalItemTest.php @@ -24,6 +24,7 @@ class JournalItemTest extends TestCase { private Uuid $applicationInstallationId; + #[\Override] protected function setUp(): void { $this->applicationInstallationId = Uuid::v7(); @@ -32,96 +33,96 @@ protected function setUp(): void public function testCreateJournalItemWithInfoLevel(): void { $message = 'Test info message'; - $context = new JournalContext( + $journalContext = new JournalContext( label: 'test.label', payload: ['key' => 'value'], bitrix24UserId: 123 ); - $item = JournalItem::info($this->applicationInstallationId, $message, $context); + $journalItem = JournalItem::info($this->applicationInstallationId, $message, $journalContext); - $this->assertInstanceOf(JournalItem::class, $item); - $this->assertSame(LogLevel::info, $item->getLevel()); - $this->assertSame($message, $item->getMessage()); - $this->assertTrue($item->getApplicationInstallationId()->equals($this->applicationInstallationId)); - $this->assertSame('test.label', $item->getContext()->getLabel()); - $this->assertSame(['key' => 'value'], $item->getContext()->getPayload()); - $this->assertSame(123, $item->getContext()->getBitrix24UserId()); + $this->assertInstanceOf(JournalItem::class, $journalItem); + $this->assertSame(LogLevel::info, $journalItem->getLevel()); + $this->assertSame($message, $journalItem->getMessage()); + $this->assertTrue($journalItem->getApplicationInstallationId()->equals($this->applicationInstallationId)); + $this->assertSame('test.label', $journalItem->getContext()->getLabel()); + $this->assertSame(['key' => 'value'], $journalItem->getContext()->getPayload()); + $this->assertSame(123, $journalItem->getContext()->getBitrix24UserId()); } public function testCreateJournalItemWithEmergencyLevel(): void { - $context = new JournalContext('emergency.label'); - $item = JournalItem::emergency($this->applicationInstallationId, 'Emergency message', $context); + $journalContext = new JournalContext('emergency.label'); + $journalItem = JournalItem::emergency($this->applicationInstallationId, 'Emergency message', $journalContext); - $this->assertSame(LogLevel::emergency, $item->getLevel()); - $this->assertSame('Emergency message', $item->getMessage()); + $this->assertSame(LogLevel::emergency, $journalItem->getLevel()); + $this->assertSame('Emergency message', $journalItem->getMessage()); } public function testCreateJournalItemWithAlertLevel(): void { - $context = new JournalContext('alert.label'); - $item = JournalItem::alert($this->applicationInstallationId, 'Alert message', $context); + $journalContext = new JournalContext('alert.label'); + $journalItem = JournalItem::alert($this->applicationInstallationId, 'Alert message', $journalContext); - $this->assertSame(LogLevel::alert, $item->getLevel()); + $this->assertSame(LogLevel::alert, $journalItem->getLevel()); } public function testCreateJournalItemWithCriticalLevel(): void { - $context = new JournalContext('critical.label'); - $item = JournalItem::critical($this->applicationInstallationId, 'Critical message', $context); + $journalContext = new JournalContext('critical.label'); + $journalItem = JournalItem::critical($this->applicationInstallationId, 'Critical message', $journalContext); - $this->assertSame(LogLevel::critical, $item->getLevel()); + $this->assertSame(LogLevel::critical, $journalItem->getLevel()); } public function testCreateJournalItemWithErrorLevel(): void { - $context = new JournalContext('error.label'); - $item = JournalItem::error($this->applicationInstallationId, 'Error message', $context); + $journalContext = new JournalContext('error.label'); + $journalItem = JournalItem::error($this->applicationInstallationId, 'Error message', $journalContext); - $this->assertSame(LogLevel::error, $item->getLevel()); + $this->assertSame(LogLevel::error, $journalItem->getLevel()); } public function testCreateJournalItemWithWarningLevel(): void { - $context = new JournalContext('warning.label'); - $item = JournalItem::warning($this->applicationInstallationId, 'Warning message', $context); + $journalContext = new JournalContext('warning.label'); + $journalItem = JournalItem::warning($this->applicationInstallationId, 'Warning message', $journalContext); - $this->assertSame(LogLevel::warning, $item->getLevel()); + $this->assertSame(LogLevel::warning, $journalItem->getLevel()); } public function testCreateJournalItemWithNoticeLevel(): void { - $context = new JournalContext('notice.label'); - $item = JournalItem::notice($this->applicationInstallationId, 'Notice message', $context); + $journalContext = new JournalContext('notice.label'); + $journalItem = JournalItem::notice($this->applicationInstallationId, 'Notice message', $journalContext); - $this->assertSame(LogLevel::notice, $item->getLevel()); + $this->assertSame(LogLevel::notice, $journalItem->getLevel()); } public function testCreateJournalItemWithDebugLevel(): void { - $context = new JournalContext('debug.label'); - $item = JournalItem::debug($this->applicationInstallationId, 'Debug message', $context); + $journalContext = new JournalContext('debug.label'); + $journalItem = JournalItem::debug($this->applicationInstallationId, 'Debug message', $journalContext); - $this->assertSame(LogLevel::debug, $item->getLevel()); + $this->assertSame(LogLevel::debug, $journalItem->getLevel()); } public function testJournalItemHasUniqueId(): void { - $context = new JournalContext('test.label'); - $item1 = JournalItem::info($this->applicationInstallationId, 'Message 1', $context); - $item2 = JournalItem::info($this->applicationInstallationId, 'Message 2', $context); + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::info($this->applicationInstallationId, 'Message 2', $journalContext); - $this->assertNotEquals($item1->getId()->toRfc4122(), $item2->getId()->toRfc4122()); + $this->assertNotEquals($journalItem->getId()->toRfc4122(), $item2->getId()->toRfc4122()); } public function testJournalItemHasCreatedAt(): void { - $context = new JournalContext('test.label'); - $item = JournalItem::info($this->applicationInstallationId, 'Test message', $context); + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Test message', $journalContext); - $this->assertNotNull($item->getCreatedAt()); - $this->assertInstanceOf(\Carbon\CarbonImmutable::class, $item->getCreatedAt()); + $this->assertNotNull($journalItem->getCreatedAt()); + $this->assertInstanceOf(\Carbon\CarbonImmutable::class, $journalItem->getCreatedAt()); } public function testCreateJournalItemWithEmptyMessageThrowsException(): void @@ -129,8 +130,8 @@ public function testCreateJournalItemWithEmptyMessageThrowsException(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Journal message cannot be empty'); - $context = new JournalContext('test.label'); - JournalItem::info($this->applicationInstallationId, '', $context); + $journalContext = new JournalContext('test.label'); + JournalItem::info($this->applicationInstallationId, '', $journalContext); } public function testCreateJournalItemWithWhitespaceMessageThrowsException(): void @@ -138,19 +139,19 @@ public function testCreateJournalItemWithWhitespaceMessageThrowsException(): voi $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Journal message cannot be empty'); - $context = new JournalContext('test.label'); - JournalItem::info($this->applicationInstallationId, ' ', $context); + $journalContext = new JournalContext('test.label'); + JournalItem::info($this->applicationInstallationId, ' ', $journalContext); } public function testJournalItemContextWithOnlyLabel(): void { - $context = new JournalContext('test.label'); - $item = JournalItem::info($this->applicationInstallationId, 'Test message', $context); + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Test message', $journalContext); - $this->assertSame('test.label', $item->getContext()->getLabel()); - $this->assertNull($item->getContext()->getPayload()); - $this->assertNull($item->getContext()->getBitrix24UserId()); - $this->assertNull($item->getContext()->getIpAddress()); + $this->assertSame('test.label', $journalItem->getContext()->getLabel()); + $this->assertNull($journalItem->getContext()->getPayload()); + $this->assertNull($journalItem->getContext()->getBitrix24UserId()); + $this->assertNull($journalItem->getContext()->getIpAddress()); } public function testJournalItemWithComplexPayload(): void @@ -164,13 +165,13 @@ public function testJournalItemWithComplexPayload(): void ], ]; - $context = new JournalContext('sync.label', $payload); - $item = JournalItem::info( + $journalContext = new JournalContext('sync.label', $payload); + $journalItem = JournalItem::info( $this->applicationInstallationId, 'Sync completed', - $context + $journalContext ); - $this->assertSame($payload, $item->getContext()->getPayload()); + $this->assertSame($payload, $journalItem->getContext()->getPayload()); } } diff --git a/tests/Unit/Journal/Entity/LogLevelTest.php b/tests/Unit/Journal/Entity/LogLevelTest.php index 0b20b42..76e7715 100644 --- a/tests/Unit/Journal/Entity/LogLevelTest.php +++ b/tests/Unit/Journal/Entity/LogLevelTest.php @@ -20,50 +20,50 @@ class LogLevelTest extends TestCase { public function testFromPsr3LevelEmergency(): void { - $level = LogLevel::fromPsr3Level('emergency'); - $this->assertSame(LogLevel::emergency, $level); + $logLevel = LogLevel::fromPsr3Level('emergency'); + $this->assertSame(LogLevel::emergency, $logLevel); } public function testFromPsr3LevelAlert(): void { - $level = LogLevel::fromPsr3Level('alert'); - $this->assertSame(LogLevel::alert, $level); + $logLevel = LogLevel::fromPsr3Level('alert'); + $this->assertSame(LogLevel::alert, $logLevel); } public function testFromPsr3LevelCritical(): void { - $level = LogLevel::fromPsr3Level('critical'); - $this->assertSame(LogLevel::critical, $level); + $logLevel = LogLevel::fromPsr3Level('critical'); + $this->assertSame(LogLevel::critical, $logLevel); } public function testFromPsr3LevelError(): void { - $level = LogLevel::fromPsr3Level('error'); - $this->assertSame(LogLevel::error, $level); + $logLevel = LogLevel::fromPsr3Level('error'); + $this->assertSame(LogLevel::error, $logLevel); } public function testFromPsr3LevelWarning(): void { - $level = LogLevel::fromPsr3Level('warning'); - $this->assertSame(LogLevel::warning, $level); + $logLevel = LogLevel::fromPsr3Level('warning'); + $this->assertSame(LogLevel::warning, $logLevel); } public function testFromPsr3LevelNotice(): void { - $level = LogLevel::fromPsr3Level('notice'); - $this->assertSame(LogLevel::notice, $level); + $logLevel = LogLevel::fromPsr3Level('notice'); + $this->assertSame(LogLevel::notice, $logLevel); } public function testFromPsr3LevelInfo(): void { - $level = LogLevel::fromPsr3Level('info'); - $this->assertSame(LogLevel::info, $level); + $logLevel = LogLevel::fromPsr3Level('info'); + $this->assertSame(LogLevel::info, $logLevel); } public function testFromPsr3LevelDebug(): void { - $level = LogLevel::fromPsr3Level('debug'); - $this->assertSame(LogLevel::debug, $level); + $logLevel = LogLevel::fromPsr3Level('debug'); + $this->assertSame(LogLevel::debug, $logLevel); } public function testFromPsr3LevelCaseInsensitive(): void @@ -98,7 +98,7 @@ public function testAllLogLevelsExist(): void $cases = LogLevel::cases(); $this->assertCount(8, $cases); - $values = array_map(static fn (LogLevel $level): string => $level->value, $cases); + $values = array_map(static fn (LogLevel $logLevel): string => $logLevel->value, $cases); $this->assertContains('emergency', $values); $this->assertContains('alert', $values); diff --git a/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php b/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php index a5fe835..a2ee94f 100644 --- a/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php +++ b/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php @@ -36,9 +36,9 @@ public function save(JournalItemInterface $journalItem): void } #[\Override] - public function findById(Uuid $id): ?JournalItemInterface + public function findById(Uuid $uuid): ?JournalItemInterface { - return $this->items[$id->toRfc4122()] ?? null; + return $this->items[$uuid->toRfc4122()] ?? null; } /** @@ -46,19 +46,19 @@ public function findById(Uuid $id): ?JournalItemInterface */ #[\Override] public function findByApplicationInstallationId( - Uuid $applicationInstallationId, - ?LogLevel $level = null, + Uuid $uuid, + ?LogLevel $logLevel = null, ?int $limit = null, ?int $offset = null ): array { $filtered = array_filter( $this->items, - static function (JournalItemInterface $item) use ($applicationInstallationId, $level): bool { - if (!$item->getApplicationInstallationId()->equals($applicationInstallationId)) { + static function (JournalItemInterface $journalItem) use ($uuid, $logLevel): bool { + if (!$journalItem->getApplicationInstallationId()->equals($uuid)) { return false; } - if ($level !== null && $item->getLevel() !== $level) { + if ($logLevel !== null && $journalItem->getLevel() !== $logLevel) { return false; } @@ -67,16 +67,14 @@ static function (JournalItemInterface $item) use ($applicationInstallationId, $l ); // Sort by created date descending - usort($filtered, static function (JournalItemInterface $a, JournalItemInterface $b): int { - return $b->getCreatedAt()->getTimestamp() <=> $a->getCreatedAt()->getTimestamp(); - }); + usort($filtered, static fn(JournalItemInterface $a, JournalItemInterface $b): int => $b->getCreatedAt()->getTimestamp() <=> $a->getCreatedAt()->getTimestamp()); if ($offset !== null) { $filtered = array_slice($filtered, $offset); } if ($limit !== null) { - $filtered = array_slice($filtered, 0, $limit); + return array_slice($filtered, 0, $limit); } return $filtered; diff --git a/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php b/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php index 7386ec4..684e63a 100644 --- a/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php +++ b/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php @@ -27,6 +27,7 @@ class InMemoryJournalItemRepositoryTest extends TestCase private Uuid $applicationInstallationId; + #[\Override] protected function setUp(): void { $this->repository = new InMemoryJournalItemRepository(); @@ -35,16 +36,16 @@ protected function setUp(): void public function testSaveAndFindById(): void { - $context = new JournalContext('test.label'); - $item = JournalItem::info($this->applicationInstallationId, 'Test message', $context); + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Test message', $journalContext); - $this->repository->save($item); + $this->repository->save($journalItem); - $found = $this->repository->findById($item->getId()); + $found = $this->repository->findById($journalItem->getId()); $this->assertNotNull($found); - $this->assertSame($item->getId()->toRfc4122(), $found->getId()->toRfc4122()); - $this->assertSame($item->getMessage(), $found->getMessage()); + $this->assertSame($journalItem->getId()->toRfc4122(), $found->getId()->toRfc4122()); + $this->assertSame($journalItem->getMessage(), $found->getMessage()); } public function testFindByIdReturnsNullForNonexistent(): void @@ -56,12 +57,12 @@ public function testFindByIdReturnsNullForNonexistent(): void public function testFindByApplicationInstallationId(): void { - $context = new JournalContext('test.label'); - $item1 = JournalItem::info($this->applicationInstallationId, 'Message 1', $context); - $item2 = JournalItem::error($this->applicationInstallationId, 'Message 2', $context); - $item3 = JournalItem::info(Uuid::v7(), 'Message 3', $context); // Different installation + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::error($this->applicationInstallationId, 'Message 2', $journalContext); + $item3 = JournalItem::info(Uuid::v7(), 'Message 3', $journalContext); // Different installation - $this->repository->save($item1); + $this->repository->save($journalItem); $this->repository->save($item2); $this->repository->save($item3); @@ -72,12 +73,12 @@ public function testFindByApplicationInstallationId(): void public function testFindByApplicationInstallationIdWithLevelFilter(): void { - $context = new JournalContext('test.label'); - $item1 = JournalItem::info($this->applicationInstallationId, 'Message 1', $context); - $item2 = JournalItem::error($this->applicationInstallationId, 'Message 2', $context); - $item3 = JournalItem::info($this->applicationInstallationId, 'Message 3', $context); + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::error($this->applicationInstallationId, 'Message 2', $journalContext); + $item3 = JournalItem::info($this->applicationInstallationId, 'Message 3', $journalContext); - $this->repository->save($item1); + $this->repository->save($journalItem); $this->repository->save($item2); $this->repository->save($item3); @@ -94,9 +95,9 @@ public function testFindByApplicationInstallationIdWithLevelFilter(): void public function testFindByApplicationInstallationIdWithLimit(): void { - $context = new JournalContext('test.label'); + $journalContext = new JournalContext('test.label'); for ($i = 1; $i <= 5; ++$i) { - $item = JournalItem::info($this->applicationInstallationId, "Message {$i}", $context); + $item = JournalItem::info($this->applicationInstallationId, 'Message ' . $i, $journalContext); $this->repository->save($item); } @@ -110,9 +111,9 @@ public function testFindByApplicationInstallationIdWithLimit(): void public function testFindByApplicationInstallationIdWithOffset(): void { - $context = new JournalContext('test.label'); + $journalContext = new JournalContext('test.label'); for ($i = 1; $i <= 5; ++$i) { - $item = JournalItem::info($this->applicationInstallationId, "Message {$i}", $context); + $item = JournalItem::info($this->applicationInstallationId, 'Message ' . $i, $journalContext); $this->repository->save($item); } @@ -126,9 +127,9 @@ public function testFindByApplicationInstallationIdWithOffset(): void public function testFindByApplicationInstallationIdWithLimitAndOffset(): void { - $context = new JournalContext('test.label'); + $journalContext = new JournalContext('test.label'); for ($i = 1; $i <= 10; ++$i) { - $item = JournalItem::info($this->applicationInstallationId, "Message {$i}", $context); + $item = JournalItem::info($this->applicationInstallationId, 'Message ' . $i, $journalContext); $this->repository->save($item); } @@ -143,9 +144,9 @@ public function testFindByApplicationInstallationIdWithLimitAndOffset(): void public function testDeleteOlderThan(): void { - $context = new JournalContext('test.label'); - $item = JournalItem::info($this->applicationInstallationId, 'Message', $context); - $this->repository->save($item); + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Message', $journalContext); + $this->repository->save($journalItem); $futureDate = new CarbonImmutable('+1 day'); $deleted = $this->repository->deleteOlderThan($futureDate); @@ -156,9 +157,9 @@ public function testDeleteOlderThan(): void public function testClear(): void { - $context = new JournalContext('test.label'); - $item = JournalItem::info($this->applicationInstallationId, 'Message', $context); - $this->repository->save($item); + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Message', $journalContext); + $this->repository->save($journalItem); $this->assertNotEmpty($this->repository->findAll()); @@ -169,11 +170,11 @@ public function testClear(): void public function testFindAll(): void { - $context = new JournalContext('test.label'); - $item1 = JournalItem::info($this->applicationInstallationId, 'Message 1', $context); - $item2 = JournalItem::error(Uuid::v7(), 'Message 2', $context); + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::error(Uuid::v7(), 'Message 2', $journalContext); - $this->repository->save($item1); + $this->repository->save($journalItem); $this->repository->save($item2); $all = $this->repository->findAll(); diff --git a/tests/Unit/Journal/Services/JournalLoggerTest.php b/tests/Unit/Journal/Services/JournalLoggerTest.php index 66ad4ea..44755d7 100644 --- a/tests/Unit/Journal/Services/JournalLoggerTest.php +++ b/tests/Unit/Journal/Services/JournalLoggerTest.php @@ -30,6 +30,7 @@ class JournalLoggerTest extends TestCase private JournalLogger $logger; + #[\Override] protected function setUp(): void { $this->repository = new InMemoryJournalItemRepository(); From 91f2c325e396bd7929971cbdc19f22f7e4b90f68 Mon Sep 17 00:00:00 2001 From: kirill Date: Tue, 17 Feb 2026 23:12:50 +0300 Subject: [PATCH 3/6] add memberId --- ...x24.Lib.Journal.Entity.JournalItem.dcm.xml | 5 +- rector.php | 3 +- .../Controller/JournalAdminController.php | 5 +- src/Journal/Docs/README.md | 18 ++++-- src/Journal/Entity/JournalItem.php | 45 +++++++++----- src/Journal/Entity/JournalItemInterface.php | 2 + .../DoctrineDbalJournalItemRepository.php | 43 +++++++++++++- .../Doctrine}/JournalItemReadRepository.php | 18 ++++-- .../JournalItemRepositoryInterface.php | 15 ++++- src/Journal/Services/JournalLogger.php | 2 + src/Journal/Services/JournalLoggerFactory.php | 3 +- tests/Unit/Journal/Entity/JournalItemTest.php | 42 +++++++++----- .../InMemoryJournalItemRepository.php | 46 ++++++++++++++- .../InMemoryJournalItemRepositoryTest.php | 58 ++++++++++++++----- .../Journal/Services/JournalLoggerTest.php | 5 ++ 15 files changed, 244 insertions(+), 66 deletions(-) rename src/Journal/{ReadModel => Infrastructure/Doctrine}/JournalItemReadRepository.php (88%) diff --git a/config/xml/Bitrix24.Lib.Journal.Entity.JournalItem.dcm.xml b/config/xml/Bitrix24.Lib.Journal.Entity.JournalItem.dcm.xml index fd2ac06..c9130cf 100644 --- a/config/xml/Bitrix24.Lib.Journal.Entity.JournalItem.dcm.xml +++ b/config/xml/Bitrix24.Lib.Journal.Entity.JournalItem.dcm.xml @@ -6,6 +6,8 @@ + + @@ -17,8 +19,9 @@ - + + diff --git a/rector.php b/rector.php index 59026b6..c957618 100644 --- a/rector.php +++ b/rector.php @@ -14,8 +14,8 @@ use Rector\Config\RectorConfig; use Rector\Naming\Rector\Class_\RenamePropertyToMatchTypeRector; use Rector\PHPUnit\Set\PHPUnitSetList; -use Rector\Set\ValueObject\DowngradeLevelSetList; use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector; +use Rector\Naming\Rector\ClassMethod\RenameParamToMatchTypeRector; return RectorConfig::configure() ->withPaths([ @@ -50,5 +50,6 @@ ) ->withSkip([ RenamePropertyToMatchTypeRector::class, + RenameParamToMatchTypeRector::class, FlipTypeControlToUseExclusiveTypeRector::class, ]); \ No newline at end of file diff --git a/src/Journal/Controller/JournalAdminController.php b/src/Journal/Controller/JournalAdminController.php index e2a73f5..65448bc 100644 --- a/src/Journal/Controller/JournalAdminController.php +++ b/src/Journal/Controller/JournalAdminController.php @@ -14,7 +14,7 @@ namespace Bitrix24\Lib\Journal\Controller; use Bitrix24\Lib\Journal\Entity\LogLevel; -use Bitrix24\Lib\Journal\ReadModel\JournalItemReadRepository; +use Bitrix24\Lib\Journal\Infrastructure\Doctrine\JournalItemReadRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -37,6 +37,7 @@ public function list(Request $request): Response { $page = max(1, $request->query->getInt('page', 1)); $domainUrl = $request->query->get('domain'); + $memberId = $request->query->get('member_id'); $levelValue = $request->query->get('level'); $label = $request->query->get('label'); @@ -46,6 +47,7 @@ public function list(Request $request): Response } $pagination = $this->journalReadRepository->findWithFilters( + memberId: $memberId ?: null, domainUrl: $domainUrl ?: null, logLevel: $level, label: $label ?: null, @@ -60,6 +62,7 @@ public function list(Request $request): Response 'pagination' => $pagination, 'currentFilters' => [ 'domain' => $domainUrl, + 'member_id' => $memberId, 'level' => $levelValue, 'label' => $label, ], diff --git a/src/Journal/Docs/README.md b/src/Journal/Docs/README.md index d30442c..4f7f519 100644 --- a/src/Journal/Docs/README.md +++ b/src/Journal/Docs/README.md @@ -20,7 +20,8 @@ $factory = $container->get(JournalLoggerFactory::class); // Создаем логгер для конкретной установки приложения $installationId = Uuid::fromString('...'); -$logger = $factory->createLogger($installationId); +$memberId = '...'; +$logger = $factory->createLogger($memberId, $installationId); // Используем как обычный PSR-3 логгер $logger->info('Синхронизация завершена', [ @@ -50,6 +51,7 @@ use Bitrix24\Lib\Journal\Services\JournalLogger; use Bitrix24\Lib\Journal\Infrastructure\Doctrine\DoctrineDbalJournalItemRepository; $logger = new JournalLogger( + memberId: $memberId, applicationInstallationId: $installationId, repository: $repository, entityManager: $entityManager @@ -74,13 +76,14 @@ $logger->debug('Отладочная информация'); use Bitrix24\Lib\Journal\Entity\JournalItem; // Создание через статические методы -$item = JournalItem::info($installationId, 'Сообщение', [ +$item = JournalItem::info($memberId, $installationId, 'Сообщение', [ 'label' => 'custom.label', 'payload' => ['key' => 'value'] ]); // Или через create с явным указанием уровня $item = JournalItem::create( + memberId: $memberId, applicationInstallationId: $installationId, level: LogLevel::error, message: 'Сообщение об ошибке', @@ -103,10 +106,9 @@ $entityManager->flush(); // Поиск $item = $repository->findById($uuid); -$items = $repository->findByApplicationInstallationId($installationId, LogLevel::error, 50, 0); +$items = $repository->findByApplicationInstallationId($memberId, $installationId, LogLevel::error, 50, 0); // Очистка -$deleted = $repository->deleteByApplicationInstallationId($installationId); $deleted = $repository->deleteOlderThan(new CarbonImmutable('-30 days')); ``` @@ -126,12 +128,13 @@ $repository->clear(); ### 4. Admin UI (ReadModel) ```php -use Bitrix24\Lib\Journal\ReadModel\JournalItemReadRepository; +use Bitrix24\Lib\Journal\Infrastructure\Doctrine\JournalItemReadRepository; $readRepo = new JournalItemReadRepository($entityManager, $paginator); // Получение с фильтрами и пагинацией $pagination = $readRepo->findWithFilters( + memberId: '66c9893d5f30e6.45265697', domainUrl: 'example.bitrix24.ru', level: LogLevel::error, label: 'b24.api.error', @@ -185,6 +188,7 @@ class MyTest extends TestCase $entityManager = $this->createMock(EntityManagerInterface::class); $this->logger = new JournalLogger( + '66c9893d5f30e6.45265697', Uuid::v7(), $this->repository, $entityManager @@ -215,6 +219,7 @@ class MyTest extends TestCase Таблица `journal_item` с полями: - `id` (UUID) - PK +- `member_id` (string) - ID портала Bitrix24 - `application_installation_id` (UUID) - FK к установке приложения - `created_at_utc` (timestamp) - время создания - `level` (string) - уровень логирования @@ -222,6 +227,7 @@ class MyTest extends TestCase - `label`, `payload`, `bitrix24_user_id`, `ip_address` - поля контекста Индексы: -- `application_installation_id` +- `member_id, application_installation_id, level, created_at_utc` (composite) +- `member_id` - `created_at_utc` - `level` diff --git a/src/Journal/Entity/JournalItem.php b/src/Journal/Entity/JournalItem.php index b45a58d..2d80314 100644 --- a/src/Journal/Entity/JournalItem.php +++ b/src/Journal/Entity/JournalItem.php @@ -30,11 +30,16 @@ class JournalItem extends AggregateRoot implements JournalItemInterface private readonly CarbonImmutable $createdAt; public function __construct( + private readonly string $memberId, private readonly Uuid $applicationInstallationId, private readonly LogLevel $level, private readonly string $message, private readonly JournalContext $context ) { + if ('' === trim($this->memberId)) { + throw new InvalidArgumentException('memberId cannot be empty'); + } + if ('' === trim($this->message)) { throw new InvalidArgumentException('Journal message cannot be empty'); } @@ -55,6 +60,12 @@ public function getApplicationInstallationId(): Uuid return $this->applicationInstallationId; } + #[\Override] + public function getMemberId(): string + { + return $this->memberId; + } + #[\Override] public function getCreatedAt(): CarbonImmutable { @@ -83,12 +94,14 @@ public function getContext(): JournalContext * Create journal item with custom log level. */ public static function create( + string $memberId, Uuid $applicationInstallationId, LogLevel $level, string $message, JournalContext $context ): self { return new self( + memberId: $memberId, applicationInstallationId: $applicationInstallationId, level: $level, message: $message, @@ -99,43 +112,43 @@ public static function create( /** * PSR-3 compatible factory methods. */ - public static function emergency(Uuid $uuid, string $message, JournalContext $journalContext): self + public static function emergency(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self { - return self::create($uuid, LogLevel::emergency, $message, $journalContext); + return self::create($memberId, $applicationInstallationId, LogLevel::emergency, $message, $context); } - public static function alert(Uuid $uuid, string $message, JournalContext $journalContext): self + public static function alert(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self { - return self::create($uuid, LogLevel::alert, $message, $journalContext); + return self::create($memberId, $applicationInstallationId, LogLevel::alert, $message, $context); } - public static function critical(Uuid $uuid, string $message, JournalContext $journalContext): self + public static function critical(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self { - return self::create($uuid, LogLevel::critical, $message, $journalContext); + return self::create($memberId, $applicationInstallationId, LogLevel::critical, $message, $context); } - public static function error(Uuid $uuid, string $message, JournalContext $journalContext): self + public static function error(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self { - return self::create($uuid, LogLevel::error, $message, $journalContext); + return self::create($memberId, $applicationInstallationId, LogLevel::error, $message, $context); } - public static function warning(Uuid $uuid, string $message, JournalContext $journalContext): self + public static function warning(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self { - return self::create($uuid, LogLevel::warning, $message, $journalContext); + return self::create($memberId, $applicationInstallationId, LogLevel::warning, $message, $context); } - public static function notice(Uuid $uuid, string $message, JournalContext $journalContext): self + public static function notice(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self { - return self::create($uuid, LogLevel::notice, $message, $journalContext); + return self::create($memberId, $applicationInstallationId, LogLevel::notice, $message, $context); } - public static function info(Uuid $uuid, string $message, JournalContext $journalContext): self + public static function info(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self { - return self::create($uuid, LogLevel::info, $message, $journalContext); + return self::create($memberId, $applicationInstallationId, LogLevel::info, $message, $context); } - public static function debug(Uuid $uuid, string $message, JournalContext $journalContext): self + public static function debug(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self { - return self::create($uuid, LogLevel::debug, $message, $journalContext); + return self::create($memberId, $applicationInstallationId, LogLevel::debug, $message, $context); } } diff --git a/src/Journal/Entity/JournalItemInterface.php b/src/Journal/Entity/JournalItemInterface.php index 74e2cf8..9ee8dbf 100644 --- a/src/Journal/Entity/JournalItemInterface.php +++ b/src/Journal/Entity/JournalItemInterface.php @@ -26,6 +26,8 @@ public function getId(): Uuid; public function getApplicationInstallationId(): Uuid; + public function getMemberId(): string; + public function getCreatedAt(): CarbonImmutable; public function getLevel(): LogLevel; diff --git a/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php b/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php index 4f4e4af..a48333d 100644 --- a/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php +++ b/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php @@ -49,15 +49,52 @@ public function findById(Uuid $uuid): ?JournalItemInterface */ #[\Override] public function findByApplicationInstallationId( - Uuid $uuid, + string $memberId, + Uuid $applicationInstallationId, ?LogLevel $logLevel = null, ?int $limit = null, ?int $offset = null ): array { $queryBuilder = $this->repository ->createQueryBuilder('j') - ->where('j.applicationInstallationId = :appId') - ->setParameter('appId', $uuid) + ->where('j.memberId = :memberId') + ->setParameter('memberId', $memberId) + ->andWhere('j.applicationInstallationId = :appId') + ->setParameter('appId', $applicationInstallationId) + ->orderBy('j.createdAt', 'DESC') + ; + + if (null !== $logLevel) { + $queryBuilder->andWhere('j.level = :level') + ->setParameter('level', $logLevel) + ; + } + + if (null !== $limit) { + $queryBuilder->setMaxResults($limit); + } + + if (null !== $offset) { + $queryBuilder->setFirstResult($offset); + } + + return $queryBuilder->getQuery()->getResult(); + } + + /** + * @return JournalItemInterface[] + */ + #[\Override] + public function findByMemberId( + string $memberId, + ?LogLevel $logLevel = null, + ?int $limit = null, + ?int $offset = null + ): array { + $queryBuilder = $this->repository + ->createQueryBuilder('j') + ->where('j.memberId = :memberId') + ->setParameter('memberId', $memberId) ->orderBy('j.createdAt', 'DESC') ; diff --git a/src/Journal/ReadModel/JournalItemReadRepository.php b/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php similarity index 88% rename from src/Journal/ReadModel/JournalItemReadRepository.php rename to src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php index 7e08fa4..a3dfbdc 100644 --- a/src/Journal/ReadModel/JournalItemReadRepository.php +++ b/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace Bitrix24\Lib\Journal\ReadModel; +namespace Bitrix24\Lib\Journal\Infrastructure\Doctrine; use Bitrix24\Lib\ApplicationInstallations\Entity\ApplicationInstallation; use Bitrix24\Lib\Bitrix24Accounts\Entity\Bitrix24Account; @@ -25,7 +25,7 @@ use Symfony\Component\Uid\Uuid; /** - * Read model repository for journal items with filtering and pagination. + * Read the model repository for journal items with filtering and pagination. */ readonly class JournalItemReadRepository { @@ -40,13 +40,14 @@ public function __construct( * @return PaginationInterface */ public function findWithFilters( + ?string $memberId = null, ?string $domainUrl = null, ?LogLevel $logLevel = null, ?string $label = null, int $page = 1, int $limit = 50 ): PaginationInterface { - $queryBuilder = $this->createFilteredQueryBuilder($domainUrl, $logLevel, $label); + $queryBuilder = $this->createFilteredQueryBuilder($memberId, $domainUrl, $logLevel, $label); return $this->paginator->paginate( $queryBuilder, @@ -111,6 +112,7 @@ public function getAvailableLabels(): array * Create query builder with filters. */ private function createFilteredQueryBuilder( + ?string $memberId = null, ?string $domainUrl = null, ?LogLevel $logLevel = null, ?string $label = null @@ -120,7 +122,13 @@ private function createFilteredQueryBuilder( ->from(JournalItem::class, 'j') ; - if (null !== $domainUrl && '' !== $domainUrl && '0' !== $domainUrl) { + if (null !== $memberId) { + $queryBuilder->andWhere('j.memberId = :memberId') + ->setParameter('memberId', $memberId) + ; + } + + if (null !== $domainUrl) { $queryBuilder->innerJoin(ApplicationInstallation::class, 'ai', 'WITH', 'ai.id = j.applicationInstallationId') ->innerJoin(Bitrix24Account::class, 'b24', 'WITH', 'b24.id = ai.bitrix24AccountId') ->andWhere('b24.domainUrl = :domainUrl') @@ -134,7 +142,7 @@ private function createFilteredQueryBuilder( ; } - if (null !== $label && '' !== $label && '0' !== $label) { + if (null !== $label) { $queryBuilder->andWhere('j.context.label = :label') ->setParameter('label', $label) ; diff --git a/src/Journal/Infrastructure/JournalItemRepositoryInterface.php b/src/Journal/Infrastructure/JournalItemRepositoryInterface.php index 2039ee3..57cdf7a 100644 --- a/src/Journal/Infrastructure/JournalItemRepositoryInterface.php +++ b/src/Journal/Infrastructure/JournalItemRepositoryInterface.php @@ -39,7 +39,20 @@ public function findById(Uuid $uuid): ?JournalItemInterface; * @return JournalItemInterface[] */ public function findByApplicationInstallationId( - Uuid $uuid, + string $memberId, + Uuid $applicationInstallationId, + ?LogLevel $logLevel = null, + ?int $limit = null, + ?int $offset = null + ): array; + + /** + * Find journal items by member ID. + * + * @return JournalItemInterface[] + */ + public function findByMemberId( + string $memberId, ?LogLevel $logLevel = null, ?int $limit = null, ?int $offset = null diff --git a/src/Journal/Services/JournalLogger.php b/src/Journal/Services/JournalLogger.php index 0402dd0..dec6012 100644 --- a/src/Journal/Services/JournalLogger.php +++ b/src/Journal/Services/JournalLogger.php @@ -32,6 +32,7 @@ class JournalLogger implements LoggerInterface use LoggerTrait; public function __construct( + private readonly string $memberId, private readonly Uuid $applicationInstallationId, private readonly JournalItemRepositoryInterface $repository, private readonly EntityManagerInterface $entityManager @@ -50,6 +51,7 @@ public function log($level, string|\Stringable $message, array $context = []): v $journalContext = $this->createContext($context); $journalItem = JournalItem::create( + memberId: $this->memberId, applicationInstallationId: $this->applicationInstallationId, level: $logLevel, message: (string) $message, diff --git a/src/Journal/Services/JournalLoggerFactory.php b/src/Journal/Services/JournalLoggerFactory.php index fb46b06..eb4f1e8 100644 --- a/src/Journal/Services/JournalLoggerFactory.php +++ b/src/Journal/Services/JournalLoggerFactory.php @@ -31,9 +31,10 @@ public function __construct( /** * Create logger for specific application installation. */ - public function createLogger(Uuid $applicationInstallationId): LoggerInterface + public function createLogger(string $memberId, Uuid $applicationInstallationId): LoggerInterface { return new JournalLogger( + memberId: $memberId, applicationInstallationId: $applicationInstallationId, repository: $this->repository, entityManager: $this->entityManager diff --git a/tests/Unit/Journal/Entity/JournalItemTest.php b/tests/Unit/Journal/Entity/JournalItemTest.php index abb7def..06ccad7 100644 --- a/tests/Unit/Journal/Entity/JournalItemTest.php +++ b/tests/Unit/Journal/Entity/JournalItemTest.php @@ -24,10 +24,13 @@ class JournalItemTest extends TestCase { private Uuid $applicationInstallationId; + private string $memberId; + #[\Override] protected function setUp(): void { $this->applicationInstallationId = Uuid::v7(); + $this->memberId = 'test-member-id'; } public function testCreateJournalItemWithInfoLevel(): void @@ -39,10 +42,11 @@ public function testCreateJournalItemWithInfoLevel(): void bitrix24UserId: 123 ); - $journalItem = JournalItem::info($this->applicationInstallationId, $message, $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, $message, $journalContext); $this->assertInstanceOf(JournalItem::class, $journalItem); $this->assertSame(LogLevel::info, $journalItem->getLevel()); + $this->assertSame($this->memberId, $journalItem->getMemberId()); $this->assertSame($message, $journalItem->getMessage()); $this->assertTrue($journalItem->getApplicationInstallationId()->equals($this->applicationInstallationId)); $this->assertSame('test.label', $journalItem->getContext()->getLabel()); @@ -53,7 +57,7 @@ public function testCreateJournalItemWithInfoLevel(): void public function testCreateJournalItemWithEmergencyLevel(): void { $journalContext = new JournalContext('emergency.label'); - $journalItem = JournalItem::emergency($this->applicationInstallationId, 'Emergency message', $journalContext); + $journalItem = JournalItem::emergency($this->memberId, $this->applicationInstallationId, 'Emergency message', $journalContext); $this->assertSame(LogLevel::emergency, $journalItem->getLevel()); $this->assertSame('Emergency message', $journalItem->getMessage()); @@ -62,7 +66,7 @@ public function testCreateJournalItemWithEmergencyLevel(): void public function testCreateJournalItemWithAlertLevel(): void { $journalContext = new JournalContext('alert.label'); - $journalItem = JournalItem::alert($this->applicationInstallationId, 'Alert message', $journalContext); + $journalItem = JournalItem::alert($this->memberId, $this->applicationInstallationId, 'Alert message', $journalContext); $this->assertSame(LogLevel::alert, $journalItem->getLevel()); } @@ -70,7 +74,7 @@ public function testCreateJournalItemWithAlertLevel(): void public function testCreateJournalItemWithCriticalLevel(): void { $journalContext = new JournalContext('critical.label'); - $journalItem = JournalItem::critical($this->applicationInstallationId, 'Critical message', $journalContext); + $journalItem = JournalItem::critical($this->memberId, $this->applicationInstallationId, 'Critical message', $journalContext); $this->assertSame(LogLevel::critical, $journalItem->getLevel()); } @@ -78,7 +82,7 @@ public function testCreateJournalItemWithCriticalLevel(): void public function testCreateJournalItemWithErrorLevel(): void { $journalContext = new JournalContext('error.label'); - $journalItem = JournalItem::error($this->applicationInstallationId, 'Error message', $journalContext); + $journalItem = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Error message', $journalContext); $this->assertSame(LogLevel::error, $journalItem->getLevel()); } @@ -86,7 +90,7 @@ public function testCreateJournalItemWithErrorLevel(): void public function testCreateJournalItemWithWarningLevel(): void { $journalContext = new JournalContext('warning.label'); - $journalItem = JournalItem::warning($this->applicationInstallationId, 'Warning message', $journalContext); + $journalItem = JournalItem::warning($this->memberId, $this->applicationInstallationId, 'Warning message', $journalContext); $this->assertSame(LogLevel::warning, $journalItem->getLevel()); } @@ -94,7 +98,7 @@ public function testCreateJournalItemWithWarningLevel(): void public function testCreateJournalItemWithNoticeLevel(): void { $journalContext = new JournalContext('notice.label'); - $journalItem = JournalItem::notice($this->applicationInstallationId, 'Notice message', $journalContext); + $journalItem = JournalItem::notice($this->memberId, $this->applicationInstallationId, 'Notice message', $journalContext); $this->assertSame(LogLevel::notice, $journalItem->getLevel()); } @@ -102,7 +106,7 @@ public function testCreateJournalItemWithNoticeLevel(): void public function testCreateJournalItemWithDebugLevel(): void { $journalContext = new JournalContext('debug.label'); - $journalItem = JournalItem::debug($this->applicationInstallationId, 'Debug message', $journalContext); + $journalItem = JournalItem::debug($this->memberId, $this->applicationInstallationId, 'Debug message', $journalContext); $this->assertSame(LogLevel::debug, $journalItem->getLevel()); } @@ -110,8 +114,8 @@ public function testCreateJournalItemWithDebugLevel(): void public function testJournalItemHasUniqueId(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::info($this->applicationInstallationId, 'Message 2', $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 2', $journalContext); $this->assertNotEquals($journalItem->getId()->toRfc4122(), $item2->getId()->toRfc4122()); } @@ -119,7 +123,7 @@ public function testJournalItemHasUniqueId(): void public function testJournalItemHasCreatedAt(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Test message', $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', $journalContext); $this->assertNotNull($journalItem->getCreatedAt()); $this->assertInstanceOf(\Carbon\CarbonImmutable::class, $journalItem->getCreatedAt()); @@ -131,7 +135,7 @@ public function testCreateJournalItemWithEmptyMessageThrowsException(): void $this->expectExceptionMessage('Journal message cannot be empty'); $journalContext = new JournalContext('test.label'); - JournalItem::info($this->applicationInstallationId, '', $journalContext); + JournalItem::info($this->memberId, $this->applicationInstallationId, '', $journalContext); } public function testCreateJournalItemWithWhitespaceMessageThrowsException(): void @@ -140,13 +144,22 @@ public function testCreateJournalItemWithWhitespaceMessageThrowsException(): voi $this->expectExceptionMessage('Journal message cannot be empty'); $journalContext = new JournalContext('test.label'); - JournalItem::info($this->applicationInstallationId, ' ', $journalContext); + JournalItem::info($this->memberId, $this->applicationInstallationId, ' ', $journalContext); + } + + public function testCreateJournalItemWithEmptyMemberIdThrowsException(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('memberId cannot be empty'); + + $journalContext = new JournalContext('test.label'); + JournalItem::info('', $this->applicationInstallationId, 'Message', $journalContext); } public function testJournalItemContextWithOnlyLabel(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Test message', $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', $journalContext); $this->assertSame('test.label', $journalItem->getContext()->getLabel()); $this->assertNull($journalItem->getContext()->getPayload()); @@ -167,6 +180,7 @@ public function testJournalItemWithComplexPayload(): void $journalContext = new JournalContext('sync.label', $payload); $journalItem = JournalItem::info( + $this->memberId, $this->applicationInstallationId, 'Sync completed', $journalContext diff --git a/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php b/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php index a2ee94f..74738d1 100644 --- a/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php +++ b/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php @@ -46,6 +46,7 @@ public function findById(Uuid $uuid): ?JournalItemInterface */ #[\Override] public function findByApplicationInstallationId( + string $memberId, Uuid $uuid, ?LogLevel $logLevel = null, ?int $limit = null, @@ -53,7 +54,11 @@ public function findByApplicationInstallationId( ): array { $filtered = array_filter( $this->items, - static function (JournalItemInterface $journalItem) use ($uuid, $logLevel): bool { + static function (JournalItemInterface $journalItem) use ($uuid, $memberId, $logLevel): bool { + if ($journalItem->getMemberId() !== $memberId) { + return false; + } + if (!$journalItem->getApplicationInstallationId()->equals($uuid)) { return false; } @@ -80,6 +85,45 @@ static function (JournalItemInterface $journalItem) use ($uuid, $logLevel): bool return $filtered; } + /** + * @return JournalItemInterface[] + */ + #[\Override] + public function findByMemberId( + string $memberId, + ?LogLevel $logLevel = null, + ?int $limit = null, + ?int $offset = null + ): array { + $filtered = array_filter( + $this->items, + static function (JournalItemInterface $journalItem) use ($memberId, $logLevel): bool { + if ($journalItem->getMemberId() !== $memberId) { + return false; + } + + if ($logLevel !== null && $journalItem->getLevel() !== $logLevel) { + return false; + } + + return true; + } + ); + + // Sort by created date descending + usort($filtered, static fn(JournalItemInterface $a, JournalItemInterface $b): int => $b->getCreatedAt()->getTimestamp() <=> $a->getCreatedAt()->getTimestamp()); + + if ($offset !== null) { + $filtered = array_slice($filtered, $offset); + } + + if ($limit !== null) { + return array_slice($filtered, 0, $limit); + } + + return $filtered; + } + #[\Override] public function deleteOlderThan(CarbonImmutable $date): int { diff --git a/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php b/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php index 684e63a..ad53906 100644 --- a/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php +++ b/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php @@ -27,17 +27,20 @@ class InMemoryJournalItemRepositoryTest extends TestCase private Uuid $applicationInstallationId; + private string $memberId; + #[\Override] protected function setUp(): void { $this->repository = new InMemoryJournalItemRepository(); $this->applicationInstallationId = Uuid::v7(); + $this->memberId = 'test-member-id'; } public function testSaveAndFindById(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Test message', $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', $journalContext); $this->repository->save($journalItem); @@ -58,15 +61,15 @@ public function testFindByIdReturnsNullForNonexistent(): void public function testFindByApplicationInstallationId(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::error($this->applicationInstallationId, 'Message 2', $journalContext); - $item3 = JournalItem::info(Uuid::v7(), 'Message 3', $journalContext); // Different installation + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', $journalContext); + $item3 = JournalItem::info('other-member', Uuid::v7(), 'Message 3', $journalContext); // Different installation $this->repository->save($journalItem); $this->repository->save($item2); $this->repository->save($item3); - $items = $this->repository->findByApplicationInstallationId($this->applicationInstallationId); + $items = $this->repository->findByApplicationInstallationId($this->memberId, $this->applicationInstallationId); $this->assertCount(2, $items); } @@ -74,17 +77,18 @@ public function testFindByApplicationInstallationId(): void public function testFindByApplicationInstallationIdWithLevelFilter(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::error($this->applicationInstallationId, 'Message 2', $journalContext); - $item3 = JournalItem::info($this->applicationInstallationId, 'Message 3', $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', $journalContext); + $item3 = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 3', $journalContext); $this->repository->save($journalItem); $this->repository->save($item2); $this->repository->save($item3); $items = $this->repository->findByApplicationInstallationId( + $this->memberId, $this->applicationInstallationId, - LogLevel::info + logLevel: LogLevel::info ); $this->assertCount(2, $items); @@ -93,15 +97,35 @@ public function testFindByApplicationInstallationIdWithLevelFilter(): void } } + public function testFindByMemberId(): void + { + $journalContext = new JournalContext('test.label'); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', $journalContext); + $item3 = JournalItem::info('other-member', Uuid::v7(), 'Message 3', $journalContext); + + $this->repository->save($journalItem); + $this->repository->save($item2); + $this->repository->save($item3); + + $items = $this->repository->findByMemberId($this->memberId); + + $this->assertCount(2, $items); + foreach ($items as $item) { + $this->assertSame($this->memberId, $item->getMemberId()); + } + } + public function testFindByApplicationInstallationIdWithLimit(): void { $journalContext = new JournalContext('test.label'); for ($i = 1; $i <= 5; ++$i) { - $item = JournalItem::info($this->applicationInstallationId, 'Message ' . $i, $journalContext); + $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message ' . $i, $journalContext); $this->repository->save($item); } $items = $this->repository->findByApplicationInstallationId( + $this->memberId, $this->applicationInstallationId, limit: 3 ); @@ -113,11 +137,12 @@ public function testFindByApplicationInstallationIdWithOffset(): void { $journalContext = new JournalContext('test.label'); for ($i = 1; $i <= 5; ++$i) { - $item = JournalItem::info($this->applicationInstallationId, 'Message ' . $i, $journalContext); + $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message ' . $i, $journalContext); $this->repository->save($item); } $items = $this->repository->findByApplicationInstallationId( + $this->memberId, $this->applicationInstallationId, offset: 2 ); @@ -129,11 +154,12 @@ public function testFindByApplicationInstallationIdWithLimitAndOffset(): void { $journalContext = new JournalContext('test.label'); for ($i = 1; $i <= 10; ++$i) { - $item = JournalItem::info($this->applicationInstallationId, 'Message ' . $i, $journalContext); + $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message ' . $i, $journalContext); $this->repository->save($item); } $items = $this->repository->findByApplicationInstallationId( + $this->memberId, $this->applicationInstallationId, limit: 3, offset: 2 @@ -145,7 +171,7 @@ public function testFindByApplicationInstallationIdWithLimitAndOffset(): void public function testDeleteOlderThan(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Message', $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message', $journalContext); $this->repository->save($journalItem); $futureDate = new CarbonImmutable('+1 day'); @@ -158,7 +184,7 @@ public function testDeleteOlderThan(): void public function testClear(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Message', $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message', $journalContext); $this->repository->save($journalItem); $this->assertNotEmpty($this->repository->findAll()); @@ -171,8 +197,8 @@ public function testClear(): void public function testFindAll(): void { $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::error(Uuid::v7(), 'Message 2', $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); + $item2 = JournalItem::error('other-member', Uuid::v7(), 'Message 2', $journalContext); $this->repository->save($journalItem); $this->repository->save($item2); diff --git a/tests/Unit/Journal/Services/JournalLoggerTest.php b/tests/Unit/Journal/Services/JournalLoggerTest.php index 44755d7..28b8d5f 100644 --- a/tests/Unit/Journal/Services/JournalLoggerTest.php +++ b/tests/Unit/Journal/Services/JournalLoggerTest.php @@ -28,6 +28,8 @@ class JournalLoggerTest extends TestCase private Uuid $applicationInstallationId; + private string $memberId; + private JournalLogger $logger; #[\Override] @@ -36,8 +38,10 @@ protected function setUp(): void $this->repository = new InMemoryJournalItemRepository(); $this->entityManager = $this->createMock(EntityManagerInterface::class); $this->applicationInstallationId = Uuid::v7(); + $this->memberId = 'test-member-id'; $this->logger = new JournalLogger( + $this->memberId, $this->applicationInstallationId, $this->repository, $this->entityManager @@ -53,6 +57,7 @@ public function testLogInfoMessage(): void $items = $this->repository->findAll(); $this->assertCount(1, $items); $this->assertSame(LogLevel::info, $items[0]->getLevel()); + $this->assertSame($this->memberId, $items[0]->getMemberId()); $this->assertSame('Test info message', $items[0]->getMessage()); $this->assertSame('test.label', $items[0]->getContext()->getLabel()); } From 9a8fa6801bf7891570b7e9eec15b1741a8ae5266 Mon Sep 17 00:00:00 2001 From: kirill Date: Thu, 19 Feb 2026 23:41:31 +0300 Subject: [PATCH 4/6] Refactor: rename `JournalContext` to `Context`, update related tests and repository logic, and add `label` and `userId` to `JournalItem` --- ...x24.Lib.Journal.Entity.JournalItem.dcm.xml | 6 +- ...urnal.Entity.ValueObjects.Context.dcm.xml} | 4 +- .../Controller/JournalAdminController.php | 2 +- src/Journal/Entity/JournalItem.php | 62 +++++++++++----- src/Journal/Entity/JournalItemInterface.php | 8 +- .../ValueObjects/Context.php} | 11 +-- .../DoctrineDbalJournalItemRepository.php | 13 +++- .../Doctrine/JournalItemReadRepository.php | 8 +- .../JournalItemRepositoryInterface.php | 6 +- src/Journal/Services/JournalLogger.php | 15 ++-- tests/Unit/Journal/Entity/JournalItemTest.php | 74 ++++++++++--------- .../InMemoryJournalItemRepository.php | 40 +++++----- .../InMemoryJournalItemRepositoryTest.php | 63 ++++++++-------- .../Journal/Services/JournalLoggerTest.php | 11 +-- 14 files changed, 186 insertions(+), 137 deletions(-) rename config/xml/{Bitrix24.Lib.Journal.ValueObjects.JournalContext.dcm.xml => Bitrix24.Lib.Journal.Entity.ValueObjects.Context.dcm.xml} (79%) rename src/Journal/{ValueObjects/JournalContext.php => Entity/ValueObjects/Context.php} (82%) diff --git a/config/xml/Bitrix24.Lib.Journal.Entity.JournalItem.dcm.xml b/config/xml/Bitrix24.Lib.Journal.Entity.JournalItem.dcm.xml index c9130cf..99fb5c3 100644 --- a/config/xml/Bitrix24.Lib.Journal.Entity.JournalItem.dcm.xml +++ b/config/xml/Bitrix24.Lib.Journal.Entity.JournalItem.dcm.xml @@ -15,8 +15,12 @@ + + - + + + diff --git a/config/xml/Bitrix24.Lib.Journal.ValueObjects.JournalContext.dcm.xml b/config/xml/Bitrix24.Lib.Journal.Entity.ValueObjects.Context.dcm.xml similarity index 79% rename from config/xml/Bitrix24.Lib.Journal.ValueObjects.JournalContext.dcm.xml rename to config/xml/Bitrix24.Lib.Journal.Entity.ValueObjects.Context.dcm.xml index 8291328..fff5a50 100644 --- a/config/xml/Bitrix24.Lib.Journal.ValueObjects.JournalContext.dcm.xml +++ b/config/xml/Bitrix24.Lib.Journal.Entity.ValueObjects.Context.dcm.xml @@ -1,9 +1,7 @@ - - - + diff --git a/src/Journal/Controller/JournalAdminController.php b/src/Journal/Controller/JournalAdminController.php index 65448bc..5e69be5 100644 --- a/src/Journal/Controller/JournalAdminController.php +++ b/src/Journal/Controller/JournalAdminController.php @@ -35,7 +35,7 @@ public function __construct( */ public function list(Request $request): Response { - $page = max(1, $request->query->getInt('page', 1)); + $page = max(1 , $request->query->getInt('page', 1)); $domainUrl = $request->query->get('domain'); $memberId = $request->query->get('member_id'); $levelValue = $request->query->get('level'); diff --git a/src/Journal/Entity/JournalItem.php b/src/Journal/Entity/JournalItem.php index 2d80314..327b8e6 100644 --- a/src/Journal/Entity/JournalItem.php +++ b/src/Journal/Entity/JournalItem.php @@ -14,7 +14,7 @@ namespace Bitrix24\Lib\Journal\Entity; use Bitrix24\Lib\AggregateRoot; -use Bitrix24\Lib\Journal\ValueObjects\JournalContext; +use Bitrix24\Lib\Journal\Entity\ValueObjects\Context; use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; use Carbon\CarbonImmutable; use Symfony\Component\Uid\Uuid; @@ -34,7 +34,9 @@ public function __construct( private readonly Uuid $applicationInstallationId, private readonly LogLevel $level, private readonly string $message, - private readonly JournalContext $context + private readonly string $label, + private readonly ?string $userId, + private readonly Context $context ) { if ('' === trim($this->memberId)) { throw new InvalidArgumentException('memberId cannot be empty'); @@ -44,6 +46,10 @@ public function __construct( throw new InvalidArgumentException('Journal message cannot be empty'); } + if ('' === trim($this->label)) { + throw new InvalidArgumentException('Journal label cannot be empty'); + } + $this->id = Uuid::v7(); $this->createdAt = new CarbonImmutable(); } @@ -85,7 +91,19 @@ public function getMessage(): string } #[\Override] - public function getContext(): JournalContext + public function getLabel(): string + { + return $this->label; + } + + #[\Override] + public function getUserId(): ?string + { + return $this->userId; + } + + #[\Override] + public function getContext(): Context { return $this->context; } @@ -98,13 +116,17 @@ public static function create( Uuid $applicationInstallationId, LogLevel $level, string $message, - JournalContext $context + string $label, + ?string $userId, + Context $context ): self { return new self( memberId: $memberId, applicationInstallationId: $applicationInstallationId, level: $level, message: $message, + label: $label, + userId: $userId, context: $context ); } @@ -112,43 +134,43 @@ public static function create( /** * PSR-3 compatible factory methods. */ - public static function emergency(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function emergency(string $memberId, Uuid $applicationInstallationId, string $message, string $label, ?string $userId, Context $context): self { - return self::create($memberId, $applicationInstallationId, LogLevel::emergency, $message, $context); + return self::create($memberId, $applicationInstallationId, LogLevel::emergency, $message, $label, $userId, $context); } - public static function alert(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function alert(string $memberId, Uuid $applicationInstallationId, string $message, string $label, ?string $userId, Context $context): self { - return self::create($memberId, $applicationInstallationId, LogLevel::alert, $message, $context); + return self::create($memberId, $applicationInstallationId, LogLevel::alert, $message, $label, $userId, $context); } - public static function critical(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function critical(string $memberId, Uuid $applicationInstallationId, string $message, string $label, ?string $userId, Context $context): self { - return self::create($memberId, $applicationInstallationId, LogLevel::critical, $message, $context); + return self::create($memberId, $applicationInstallationId, LogLevel::critical, $message, $label, $userId, $context); } - public static function error(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function error(string $memberId, Uuid $applicationInstallationId, string $message, string $label, ?string $userId, Context $context): self { - return self::create($memberId, $applicationInstallationId, LogLevel::error, $message, $context); + return self::create($memberId, $applicationInstallationId, LogLevel::error, $message, $label, $userId, $context); } - public static function warning(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function warning(string $memberId, Uuid $applicationInstallationId, string $message, string $label, ?string $userId, Context $context): self { - return self::create($memberId, $applicationInstallationId, LogLevel::warning, $message, $context); + return self::create($memberId, $applicationInstallationId, LogLevel::warning, $message, $label, $userId, $context); } - public static function notice(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function notice(string $memberId, Uuid $applicationInstallationId, string $message, string $label, ?string $userId, Context $context): self { - return self::create($memberId, $applicationInstallationId, LogLevel::notice, $message, $context); + return self::create($memberId, $applicationInstallationId, LogLevel::notice, $message, $label, $userId, $context); } - public static function info(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function info(string $memberId, Uuid $applicationInstallationId, string $message, string $label, ?string $userId, Context $context): self { - return self::create($memberId, $applicationInstallationId, LogLevel::info, $message, $context); + return self::create($memberId, $applicationInstallationId, LogLevel::info, $message, $label, $userId, $context); } - public static function debug(string $memberId, Uuid $applicationInstallationId, string $message, JournalContext $context): self + public static function debug(string $memberId, Uuid $applicationInstallationId, string $message, string $label, ?string $userId, Context $context): self { - return self::create($memberId, $applicationInstallationId, LogLevel::debug, $message, $context); + return self::create($memberId, $applicationInstallationId, LogLevel::debug, $message, $label, $userId, $context); } } diff --git a/src/Journal/Entity/JournalItemInterface.php b/src/Journal/Entity/JournalItemInterface.php index 9ee8dbf..a1b8723 100644 --- a/src/Journal/Entity/JournalItemInterface.php +++ b/src/Journal/Entity/JournalItemInterface.php @@ -13,7 +13,7 @@ namespace Bitrix24\Lib\Journal\Entity; -use Bitrix24\Lib\Journal\ValueObjects\JournalContext; +use Bitrix24\Lib\Journal\Entity\ValueObjects\Context; use Carbon\CarbonImmutable; use Symfony\Component\Uid\Uuid; @@ -33,6 +33,10 @@ public function getCreatedAt(): CarbonImmutable; public function getLevel(): LogLevel; public function getMessage(): string; + + public function getUserId(): ?string; - public function getContext(): JournalContext; + public function getLabel(): string; + + public function getContext(): Context; } diff --git a/src/Journal/ValueObjects/JournalContext.php b/src/Journal/Entity/ValueObjects/Context.php similarity index 82% rename from src/Journal/ValueObjects/JournalContext.php rename to src/Journal/Entity/ValueObjects/Context.php index fe13a5c..046e987 100644 --- a/src/Journal/ValueObjects/JournalContext.php +++ b/src/Journal/Entity/ValueObjects/Context.php @@ -11,27 +11,21 @@ declare(strict_types=1); -namespace Bitrix24\Lib\Journal\ValueObjects; +namespace Bitrix24\Lib\Journal\Entity\ValueObjects; use Darsyn\IP\Version\Multi as IP; /** * Journal context value object. */ -readonly class JournalContext +readonly class Context { public function __construct( - private string $label, private ?array $payload = null, private ?int $bitrix24UserId = null, private ?IP $ipAddress = null ) {} - public function getLabel(): string - { - return $this->label; - } - public function getPayload(): ?array { return $this->payload; @@ -53,7 +47,6 @@ public function getIpAddress(): ?IP public function toArray(): array { return [ - 'label' => $this->label, 'payload' => $this->payload, 'bitrix24UserId' => $this->bitrix24UserId, 'ipAddress' => $this->ipAddress?->getCompactedAddress(), diff --git a/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php b/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php index a48333d..927856e 100644 --- a/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php +++ b/src/Journal/Infrastructure/Doctrine/DoctrineDbalJournalItemRepository.php @@ -116,11 +116,18 @@ public function findByMemberId( } #[\Override] - public function deleteOlderThan(CarbonImmutable $date): int - { + public function deleteOlderThan( + string $memberId, + Uuid $applicationInstallationId, + CarbonImmutable $date + ): int { return $this->entityManager->createQueryBuilder() ->delete(JournalItem::class, 'j') - ->where('j.createdAt < :date') + ->where('j.memberId = :memberId') + ->andWhere('j.applicationInstallationId = :appId') + ->andWhere('j.createdAt < :date') + ->setParameter('memberId', $memberId) + ->setParameter('appId', $applicationInstallationId) ->setParameter('date', $date) ->getQuery() ->execute() diff --git a/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php b/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php index a3dfbdc..a3b02f5 100644 --- a/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php +++ b/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php @@ -97,10 +97,10 @@ public function getAvailableDomains(): array public function getAvailableLabels(): array { $queryBuilder = $this->entityManager->createQueryBuilder(); - $queryBuilder->select('DISTINCT j.context.label') + $queryBuilder->select('DISTINCT j.label') ->from(JournalItem::class, 'j') - ->where('j.context.label IS NOT NULL') - ->orderBy('j.context.label', 'ASC') + ->where('j.label IS NOT NULL') + ->orderBy('j.label', 'ASC') ; $results = $queryBuilder->getQuery()->getScalarResult(); @@ -143,7 +143,7 @@ private function createFilteredQueryBuilder( } if (null !== $label) { - $queryBuilder->andWhere('j.context.label = :label') + $queryBuilder->andWhere('j.label = :label') ->setParameter('label', $label) ; } diff --git a/src/Journal/Infrastructure/JournalItemRepositoryInterface.php b/src/Journal/Infrastructure/JournalItemRepositoryInterface.php index 57cdf7a..099c2cd 100644 --- a/src/Journal/Infrastructure/JournalItemRepositoryInterface.php +++ b/src/Journal/Infrastructure/JournalItemRepositoryInterface.php @@ -61,5 +61,9 @@ public function findByMemberId( /** * Delete journal items older than specified date. */ - public function deleteOlderThan(CarbonImmutable $date): int; + public function deleteOlderThan( + string $memberId, + Uuid $applicationInstallationId, + CarbonImmutable $date + ): int; } diff --git a/src/Journal/Services/JournalLogger.php b/src/Journal/Services/JournalLogger.php index dec6012..63f6df9 100644 --- a/src/Journal/Services/JournalLogger.php +++ b/src/Journal/Services/JournalLogger.php @@ -16,7 +16,7 @@ use Bitrix24\Lib\Journal\Entity\JournalItem; use Bitrix24\Lib\Journal\Entity\LogLevel; use Bitrix24\Lib\Journal\Infrastructure\JournalItemRepositoryInterface; -use Bitrix24\Lib\Journal\ValueObjects\JournalContext; +use Bitrix24\Lib\Journal\Entity\ValueObjects\Context; use Darsyn\IP\Version\Multi as IP; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; @@ -48,6 +48,8 @@ public function __construct( public function log($level, string|\Stringable $message, array $context = []): void { $logLevel = $this->convertLevel($level); + $label = $context['label'] ?? 'application.log'; + $userId = $context['userId'] ?? null; $journalContext = $this->createContext($context); $journalItem = JournalItem::create( @@ -55,6 +57,8 @@ public function log($level, string|\Stringable $message, array $context = []): v applicationInstallationId: $this->applicationInstallationId, level: $logLevel, message: (string) $message, + label: (string) $label, + userId: $userId, context: $journalContext ); @@ -81,12 +85,10 @@ private function convertLevel(mixed $level): LogLevel } /** - * Create JournalContext from PSR-3 context array. + * Create Context from PSR-3 context array. */ - private function createContext(array $context): JournalContext + private function createContext(array $context): Context { - $label = $context['label'] ?? 'application.log'; - $ipAddress = null; if (isset($context['ipAddress']) && is_string($context['ipAddress'])) { try { @@ -96,8 +98,7 @@ private function createContext(array $context): JournalContext } } - return new JournalContext( - label: $label, + return new Context( payload: $context['payload'] ?? null, bitrix24UserId: isset($context['bitrix24UserId']) ? (int) $context['bitrix24UserId'] : null, ipAddress: $ipAddress diff --git a/tests/Unit/Journal/Entity/JournalItemTest.php b/tests/Unit/Journal/Entity/JournalItemTest.php index 06ccad7..352caac 100644 --- a/tests/Unit/Journal/Entity/JournalItemTest.php +++ b/tests/Unit/Journal/Entity/JournalItemTest.php @@ -15,7 +15,7 @@ use Bitrix24\Lib\Journal\Entity\JournalItem; use Bitrix24\Lib\Journal\Entity\LogLevel; -use Bitrix24\Lib\Journal\ValueObjects\JournalContext; +use Bitrix24\Lib\Journal\Entity\ValueObjects\Context; use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; use PHPUnit\Framework\TestCase; use Symfony\Component\Uid\Uuid; @@ -36,28 +36,30 @@ protected function setUp(): void public function testCreateJournalItemWithInfoLevel(): void { $message = 'Test info message'; - $journalContext = new JournalContext( - label: 'test.label', + $label = 'test.label'; + $userName = 'test-user'; + $journalContext = new Context( payload: ['key' => 'value'], bitrix24UserId: 123 ); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, $message, $journalContext); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, $message, $label, $userName, $journalContext); $this->assertInstanceOf(JournalItem::class, $journalItem); $this->assertSame(LogLevel::info, $journalItem->getLevel()); $this->assertSame($this->memberId, $journalItem->getMemberId()); $this->assertSame($message, $journalItem->getMessage()); + $this->assertSame($label, $journalItem->getLabel()); + $this->assertSame($userName, $journalItem->getUserId()); $this->assertTrue($journalItem->getApplicationInstallationId()->equals($this->applicationInstallationId)); - $this->assertSame('test.label', $journalItem->getContext()->getLabel()); $this->assertSame(['key' => 'value'], $journalItem->getContext()->getPayload()); $this->assertSame(123, $journalItem->getContext()->getBitrix24UserId()); } public function testCreateJournalItemWithEmergencyLevel(): void { - $journalContext = new JournalContext('emergency.label'); - $journalItem = JournalItem::emergency($this->memberId, $this->applicationInstallationId, 'Emergency message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::emergency($this->memberId, $this->applicationInstallationId, 'Emergency message', 'emergency.label', null, $journalContext); $this->assertSame(LogLevel::emergency, $journalItem->getLevel()); $this->assertSame('Emergency message', $journalItem->getMessage()); @@ -65,65 +67,65 @@ public function testCreateJournalItemWithEmergencyLevel(): void public function testCreateJournalItemWithAlertLevel(): void { - $journalContext = new JournalContext('alert.label'); - $journalItem = JournalItem::alert($this->memberId, $this->applicationInstallationId, 'Alert message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::alert($this->memberId, $this->applicationInstallationId, 'Alert message', 'alert.label', null, $journalContext); $this->assertSame(LogLevel::alert, $journalItem->getLevel()); } public function testCreateJournalItemWithCriticalLevel(): void { - $journalContext = new JournalContext('critical.label'); - $journalItem = JournalItem::critical($this->memberId, $this->applicationInstallationId, 'Critical message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::critical($this->memberId, $this->applicationInstallationId, 'Critical message', 'critical.label', null, $journalContext); $this->assertSame(LogLevel::critical, $journalItem->getLevel()); } public function testCreateJournalItemWithErrorLevel(): void { - $journalContext = new JournalContext('error.label'); - $journalItem = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Error message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Error message', 'error.label', null, $journalContext); $this->assertSame(LogLevel::error, $journalItem->getLevel()); } public function testCreateJournalItemWithWarningLevel(): void { - $journalContext = new JournalContext('warning.label'); - $journalItem = JournalItem::warning($this->memberId, $this->applicationInstallationId, 'Warning message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::warning($this->memberId, $this->applicationInstallationId, 'Warning message', 'warning.label', null, $journalContext); $this->assertSame(LogLevel::warning, $journalItem->getLevel()); } public function testCreateJournalItemWithNoticeLevel(): void { - $journalContext = new JournalContext('notice.label'); - $journalItem = JournalItem::notice($this->memberId, $this->applicationInstallationId, 'Notice message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::notice($this->memberId, $this->applicationInstallationId, 'Notice message', 'notice.label', null, $journalContext); $this->assertSame(LogLevel::notice, $journalItem->getLevel()); } public function testCreateJournalItemWithDebugLevel(): void { - $journalContext = new JournalContext('debug.label'); - $journalItem = JournalItem::debug($this->memberId, $this->applicationInstallationId, 'Debug message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::debug($this->memberId, $this->applicationInstallationId, 'Debug message', 'debug.label', null, $journalContext); $this->assertSame(LogLevel::debug, $journalItem->getLevel()); } public function testJournalItemHasUniqueId(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 2', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', 'test.label', null, $journalContext); + $item2 = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 2', 'test.label', null, $journalContext); $this->assertNotEquals($journalItem->getId()->toRfc4122(), $item2->getId()->toRfc4122()); } public function testJournalItemHasCreatedAt(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', 'test.label', null, $journalContext); $this->assertNotNull($journalItem->getCreatedAt()); $this->assertInstanceOf(\Carbon\CarbonImmutable::class, $journalItem->getCreatedAt()); @@ -134,8 +136,8 @@ public function testCreateJournalItemWithEmptyMessageThrowsException(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Journal message cannot be empty'); - $journalContext = new JournalContext('test.label'); - JournalItem::info($this->memberId, $this->applicationInstallationId, '', $journalContext); + $journalContext = new Context(); + JournalItem::info($this->memberId, $this->applicationInstallationId, '', 'test.label', null, $journalContext); } public function testCreateJournalItemWithWhitespaceMessageThrowsException(): void @@ -143,8 +145,8 @@ public function testCreateJournalItemWithWhitespaceMessageThrowsException(): voi $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Journal message cannot be empty'); - $journalContext = new JournalContext('test.label'); - JournalItem::info($this->memberId, $this->applicationInstallationId, ' ', $journalContext); + $journalContext = new Context(); + JournalItem::info($this->memberId, $this->applicationInstallationId, ' ', 'test.label', null, $journalContext); } public function testCreateJournalItemWithEmptyMemberIdThrowsException(): void @@ -152,16 +154,16 @@ public function testCreateJournalItemWithEmptyMemberIdThrowsException(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('memberId cannot be empty'); - $journalContext = new JournalContext('test.label'); - JournalItem::info('', $this->applicationInstallationId, 'Message', $journalContext); + $journalContext = new Context(); + JournalItem::info('', $this->applicationInstallationId, 'Message', 'test.label', null, $journalContext); } - public function testJournalItemContextWithOnlyLabel(): void + public function testJournalItemContextWithoutLabel(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', $journalContext); + $journalContext = new Context(); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', 'test.label', null, $journalContext); - $this->assertSame('test.label', $journalItem->getContext()->getLabel()); + $this->assertSame('test.label', $journalItem->getLabel()); $this->assertNull($journalItem->getContext()->getPayload()); $this->assertNull($journalItem->getContext()->getBitrix24UserId()); $this->assertNull($journalItem->getContext()->getIpAddress()); @@ -178,11 +180,13 @@ public function testJournalItemWithComplexPayload(): void ], ]; - $journalContext = new JournalContext('sync.label', $payload); + $journalContext = new Context(payload: $payload); $journalItem = JournalItem::info( $this->memberId, $this->applicationInstallationId, 'Sync completed', + 'sync.label', + null, $journalContext ); diff --git a/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php b/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php index 74738d1..cdaf183 100644 --- a/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php +++ b/tests/Unit/Journal/Infrastructure/InMemory/InMemoryJournalItemRepository.php @@ -20,7 +20,7 @@ use Symfony\Component\Uid\Uuid; /** - * In-memory implementation of JournalItemRepository for testing + * In-memory implementation of JournalItemRepository for testing. */ class InMemoryJournalItemRepository implements JournalItemRepositoryInterface { @@ -47,23 +47,23 @@ public function findById(Uuid $uuid): ?JournalItemInterface #[\Override] public function findByApplicationInstallationId( string $memberId, - Uuid $uuid, + Uuid $applicationInstallationId, ?LogLevel $logLevel = null, ?int $limit = null, ?int $offset = null ): array { $filtered = array_filter( $this->items, - static function (JournalItemInterface $journalItem) use ($uuid, $memberId, $logLevel): bool { + static function (JournalItemInterface $journalItem) use ($applicationInstallationId, $memberId, $logLevel): bool { if ($journalItem->getMemberId() !== $memberId) { return false; } - if (!$journalItem->getApplicationInstallationId()->equals($uuid)) { + if (!$journalItem->getApplicationInstallationId()->equals($applicationInstallationId)) { return false; } - if ($logLevel !== null && $journalItem->getLevel() !== $logLevel) { + if (null !== $logLevel && $journalItem->getLevel() !== $logLevel) { return false; } @@ -72,13 +72,13 @@ static function (JournalItemInterface $journalItem) use ($uuid, $memberId, $logL ); // Sort by created date descending - usort($filtered, static fn(JournalItemInterface $a, JournalItemInterface $b): int => $b->getCreatedAt()->getTimestamp() <=> $a->getCreatedAt()->getTimestamp()); + usort($filtered, static fn (JournalItemInterface $a, JournalItemInterface $b): int => $b->getCreatedAt()->getTimestamp() <=> $a->getCreatedAt()->getTimestamp()); - if ($offset !== null) { + if (null !== $offset) { $filtered = array_slice($filtered, $offset); } - if ($limit !== null) { + if (null !== $limit) { return array_slice($filtered, 0, $limit); } @@ -102,7 +102,7 @@ static function (JournalItemInterface $journalItem) use ($memberId, $logLevel): return false; } - if ($logLevel !== null && $journalItem->getLevel() !== $logLevel) { + if (null !== $logLevel && $journalItem->getLevel() !== $logLevel) { return false; } @@ -111,13 +111,13 @@ static function (JournalItemInterface $journalItem) use ($memberId, $logLevel): ); // Sort by created date descending - usort($filtered, static fn(JournalItemInterface $a, JournalItemInterface $b): int => $b->getCreatedAt()->getTimestamp() <=> $a->getCreatedAt()->getTimestamp()); + usort($filtered, static fn (JournalItemInterface $a, JournalItemInterface $b): int => $b->getCreatedAt()->getTimestamp() <=> $a->getCreatedAt()->getTimestamp()); - if ($offset !== null) { + if (null !== $offset) { $filtered = array_slice($filtered, $offset); } - if ($limit !== null) { + if (null !== $limit) { return array_slice($filtered, 0, $limit); } @@ -125,11 +125,17 @@ static function (JournalItemInterface $journalItem) use ($memberId, $logLevel): } #[\Override] - public function deleteOlderThan(CarbonImmutable $date): int - { + public function deleteOlderThan( + string $memberId, + Uuid $applicationInstallationId, + CarbonImmutable $date + ): int { $count = 0; foreach ($this->items as $key => $item) { - if ($item->getCreatedAt()->isBefore($date)) { + if ($item->getMemberId() === $memberId + && $item->getApplicationInstallationId()->equals($applicationInstallationId) + && $item->getCreatedAt()->isBefore($date) + ) { unset($this->items[$key]); ++$count; } @@ -139,7 +145,7 @@ public function deleteOlderThan(CarbonImmutable $date): int } /** - * Get all items (for testing purposes) + * Get all items (for testing purposes). * * @return JournalItemInterface[] */ @@ -149,7 +155,7 @@ public function findAll(): array } /** - * Clear all items (for testing purposes) + * Clear all items (for testing purposes). */ public function clear(): void { diff --git a/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php b/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php index ad53906..86c3b21 100644 --- a/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php +++ b/tests/Unit/Journal/Infrastructure/InMemoryJournalItemRepositoryTest.php @@ -15,12 +15,17 @@ use Bitrix24\Lib\Journal\Entity\JournalItem; use Bitrix24\Lib\Journal\Entity\LogLevel; -use Bitrix24\Lib\Journal\ValueObjects\JournalContext; +use Bitrix24\Lib\Journal\Entity\ValueObjects\Context; use Bitrix24\Lib\Tests\Unit\Journal\Infrastructure\InMemory\InMemoryJournalItemRepository; use Carbon\CarbonImmutable; use PHPUnit\Framework\TestCase; use Symfony\Component\Uid\Uuid; +/** + * @internal + * + * @coversNothing + */ class InMemoryJournalItemRepositoryTest extends TestCase { private InMemoryJournalItemRepository $repository; @@ -39,8 +44,8 @@ protected function setUp(): void public function testSaveAndFindById(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', $journalContext); + $journalContext = new Context(['key' => 'value']); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Test message', 'test.label', null, $journalContext); $this->repository->save($journalItem); @@ -60,10 +65,10 @@ public function testFindByIdReturnsNullForNonexistent(): void public function testFindByApplicationInstallationId(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', $journalContext); - $item3 = JournalItem::info('other-member', Uuid::v7(), 'Message 3', $journalContext); // Different installation + $journalContext = new Context(['key' => 'value']); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', 'test.label', null, $journalContext); + $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', 'test.label', null, $journalContext); + $item3 = JournalItem::info('other-member', Uuid::v7(), 'Message 3', 'test.label', null, $journalContext); // Different installation $this->repository->save($journalItem); $this->repository->save($item2); @@ -76,10 +81,10 @@ public function testFindByApplicationInstallationId(): void public function testFindByApplicationInstallationIdWithLevelFilter(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', $journalContext); - $item3 = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 3', $journalContext); + $journalContext = new Context(['key' => 'value']); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', 'test.label', null, $journalContext); + $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', 'test.label', null, $journalContext); + $item3 = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 3', 'test.label', null, $journalContext); $this->repository->save($journalItem); $this->repository->save($item2); @@ -99,10 +104,10 @@ public function testFindByApplicationInstallationIdWithLevelFilter(): void public function testFindByMemberId(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', $journalContext); - $item3 = JournalItem::info('other-member', Uuid::v7(), 'Message 3', $journalContext); + $journalContext = new Context(['key' => 'value']); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', 'test.label', null, $journalContext); + $item2 = JournalItem::error($this->memberId, $this->applicationInstallationId, 'Message 2', 'test.label', null, $journalContext); + $item3 = JournalItem::info('other-member', Uuid::v7(), 'Message 3', 'test.label', null, $journalContext); $this->repository->save($journalItem); $this->repository->save($item2); @@ -118,9 +123,9 @@ public function testFindByMemberId(): void public function testFindByApplicationInstallationIdWithLimit(): void { - $journalContext = new JournalContext('test.label'); + $journalContext = new Context(['key' => 'value']); for ($i = 1; $i <= 5; ++$i) { - $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message ' . $i, $journalContext); + $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message '.$i, 'test.label', null, $journalContext); $this->repository->save($item); } @@ -135,9 +140,9 @@ public function testFindByApplicationInstallationIdWithLimit(): void public function testFindByApplicationInstallationIdWithOffset(): void { - $journalContext = new JournalContext('test.label'); + $journalContext = new Context(['key' => 'value']); for ($i = 1; $i <= 5; ++$i) { - $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message ' . $i, $journalContext); + $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message '.$i, 'test.label', null, $journalContext); $this->repository->save($item); } @@ -152,9 +157,9 @@ public function testFindByApplicationInstallationIdWithOffset(): void public function testFindByApplicationInstallationIdWithLimitAndOffset(): void { - $journalContext = new JournalContext('test.label'); + $journalContext = new Context(['key' => 'value']); for ($i = 1; $i <= 10; ++$i) { - $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message ' . $i, $journalContext); + $item = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message '.$i, 'test.label', null, $journalContext); $this->repository->save($item); } @@ -170,12 +175,12 @@ public function testFindByApplicationInstallationIdWithLimitAndOffset(): void public function testDeleteOlderThan(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message', $journalContext); + $journalContext = new Context(['key' => 'value']); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message', 'test.label', null, $journalContext); $this->repository->save($journalItem); $futureDate = new CarbonImmutable('+1 day'); - $deleted = $this->repository->deleteOlderThan($futureDate); + $deleted = $this->repository->deleteOlderThan($this->memberId, $this->applicationInstallationId, $futureDate); // Item should be deleted as it's older than future date $this->assertSame(1, $deleted); @@ -183,8 +188,8 @@ public function testDeleteOlderThan(): void public function testClear(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message', $journalContext); + $journalContext = new Context(['key' => 'value']); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message', 'test.label', null, $journalContext); $this->repository->save($journalItem); $this->assertNotEmpty($this->repository->findAll()); @@ -196,9 +201,9 @@ public function testClear(): void public function testFindAll(): void { - $journalContext = new JournalContext('test.label'); - $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', $journalContext); - $item2 = JournalItem::error('other-member', Uuid::v7(), 'Message 2', $journalContext); + $journalContext = new Context(['key' => 'value']); + $journalItem = JournalItem::info($this->memberId, $this->applicationInstallationId, 'Message 1', 'test.label', null, $journalContext); + $item2 = JournalItem::error('other-member', Uuid::v7(), 'Message 2', 'test.label', null, $journalContext); $this->repository->save($journalItem); $this->repository->save($item2); diff --git a/tests/Unit/Journal/Services/JournalLoggerTest.php b/tests/Unit/Journal/Services/JournalLoggerTest.php index 28b8d5f..98b207e 100644 --- a/tests/Unit/Journal/Services/JournalLoggerTest.php +++ b/tests/Unit/Journal/Services/JournalLoggerTest.php @@ -52,14 +52,15 @@ public function testLogInfoMessage(): void { $this->entityManager->expects($this->once())->method('flush'); - $this->logger->info('Test info message', ['label' => 'test.label']); + $this->logger->info('Test info message', ['label' => 'test.label', 'userId' => 'test-user']); $items = $this->repository->findAll(); $this->assertCount(1, $items); $this->assertSame(LogLevel::info, $items[0]->getLevel()); $this->assertSame($this->memberId, $items[0]->getMemberId()); $this->assertSame('Test info message', $items[0]->getMessage()); - $this->assertSame('test.label', $items[0]->getContext()->getLabel()); + $this->assertSame('test.label', $items[0]->getLabel()); + $this->assertSame('test-user', $items[0]->getUserId()); } public function testLogErrorMessage(): void @@ -71,7 +72,7 @@ public function testLogErrorMessage(): void $items = $this->repository->findAll(); $this->assertCount(1, $items); $this->assertSame(LogLevel::error, $items[0]->getLevel()); - $this->assertSame('error.label', $items[0]->getContext()->getLabel()); + $this->assertSame('error.label', $items[0]->getLabel()); } public function testLogWarningMessage(): void @@ -150,7 +151,7 @@ public function testLogWithContext(): void $items = $this->repository->findAll(); $item = $items[0]; - $this->assertSame('test.label', $item->getContext()->getLabel()); + $this->assertSame('test.label', $item->getLabel()); $this->assertSame(['key' => 'value'], $item->getContext()->getPayload()); $this->assertSame(123, $item->getContext()->getBitrix24UserId()); $this->assertNotNull($item->getContext()->getIpAddress()); @@ -163,7 +164,7 @@ public function testLogWithoutLabelUsesDefault(): void $this->logger->info('Test message without label'); $items = $this->repository->findAll(); - $this->assertSame('application.log', $items[0]->getContext()->getLabel()); + $this->assertSame('application.log', $items[0]->getLabel()); } public function testLogMultipleMessages(): void From a574defa283e60338278bedf57f96bfde7b1995d Mon Sep 17 00:00:00 2001 From: kirill Date: Wed, 25 Feb 2026 23:05:28 +0300 Subject: [PATCH 5/6] Refactor: move `Domain` value object to `Kernel` namespace, update references across codebase and tests --- .../UseCase/Install/Command.php | 2 +- .../UseCase/OnAppInstall/Command.php | 2 +- .../UseCase/Uninstall/Command.php | 2 +- .../UseCase/ChangeDomainUrl/Command.php | 2 +- .../UseCase/InstallFinish/Command.php | 2 +- src/Bitrix24Accounts/UseCase/InstallStart/Command.php | 2 +- src/Journal/Controller/JournalAdminController.php | 3 ++- src/Journal/Docs/README.md | 4 ++-- .../Doctrine/JournalItemReadRepository.php | 11 ++++++----- .../ValueObjects/Domain.php | 2 +- .../UseCase/Install/HandlerTest.php | 2 +- .../UseCase/OnAppInstall/HandlerTest.php | 2 +- .../UseCase/Uninstall/HandlerTest.php | 2 +- .../UseCase/ChangeDomainUrl/HandlerTest.php | 2 +- .../UseCase/InstallFinish/HandlerTest.php | 2 +- .../UseCase/InstallStart/HandlerTest.php | 2 +- .../UseCase/Install/CommandTest.php | 2 +- .../UseCase/OnAppInstall/CommandTest.php | 2 +- .../UseCase/Uninstall/CommandTest.php | 2 +- .../UseCase/ChangeDomainUrl/CommandTest.php | 2 +- .../UseCase/InstallFinish/CommandTest.php | 2 +- .../UseCase/InstallStart/CommandTest.php | 2 +- 22 files changed, 29 insertions(+), 27 deletions(-) rename src/{Bitrix24Accounts => Kernel}/ValueObjects/Domain.php (97%) diff --git a/src/ApplicationInstallations/UseCase/Install/Command.php b/src/ApplicationInstallations/UseCase/Install/Command.php index 224f9ba..8e5e191 100644 --- a/src/ApplicationInstallations/UseCase/Install/Command.php +++ b/src/ApplicationInstallations/UseCase/Install/Command.php @@ -4,7 +4,7 @@ namespace Bitrix24\Lib\ApplicationInstallations\UseCase\Install; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Bitrix24\SDK\Application\ApplicationStatus; use Bitrix24\SDK\Application\PortalLicenseFamily; use Bitrix24\SDK\Core\Credentials\AuthToken; diff --git a/src/ApplicationInstallations/UseCase/OnAppInstall/Command.php b/src/ApplicationInstallations/UseCase/OnAppInstall/Command.php index 5ce5b06..a0a88fc 100644 --- a/src/ApplicationInstallations/UseCase/OnAppInstall/Command.php +++ b/src/ApplicationInstallations/UseCase/OnAppInstall/Command.php @@ -4,7 +4,7 @@ namespace Bitrix24\Lib\ApplicationInstallations\UseCase\OnAppInstall; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; /** * Command is called when installation occurs through UI. diff --git a/src/ApplicationInstallations/UseCase/Uninstall/Command.php b/src/ApplicationInstallations/UseCase/Uninstall/Command.php index 84debaa..a3a0ee8 100644 --- a/src/ApplicationInstallations/UseCase/Uninstall/Command.php +++ b/src/ApplicationInstallations/UseCase/Uninstall/Command.php @@ -4,7 +4,7 @@ namespace Bitrix24\Lib\ApplicationInstallations\UseCase\Uninstall; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; readonly class Command { diff --git a/src/Bitrix24Accounts/UseCase/ChangeDomainUrl/Command.php b/src/Bitrix24Accounts/UseCase/ChangeDomainUrl/Command.php index 0d640a8..8ceb9e6 100644 --- a/src/Bitrix24Accounts/UseCase/ChangeDomainUrl/Command.php +++ b/src/Bitrix24Accounts/UseCase/ChangeDomainUrl/Command.php @@ -4,7 +4,7 @@ namespace Bitrix24\Lib\Bitrix24Accounts\UseCase\ChangeDomainUrl; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; readonly class Command { diff --git a/src/Bitrix24Accounts/UseCase/InstallFinish/Command.php b/src/Bitrix24Accounts/UseCase/InstallFinish/Command.php index 979b0e1..30de5e0 100644 --- a/src/Bitrix24Accounts/UseCase/InstallFinish/Command.php +++ b/src/Bitrix24Accounts/UseCase/InstallFinish/Command.php @@ -4,7 +4,7 @@ namespace Bitrix24\Lib\Bitrix24Accounts\UseCase\InstallFinish; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; readonly class Command { diff --git a/src/Bitrix24Accounts/UseCase/InstallStart/Command.php b/src/Bitrix24Accounts/UseCase/InstallStart/Command.php index e480182..10f989e 100644 --- a/src/Bitrix24Accounts/UseCase/InstallStart/Command.php +++ b/src/Bitrix24Accounts/UseCase/InstallStart/Command.php @@ -4,7 +4,7 @@ namespace Bitrix24\Lib\Bitrix24Accounts\UseCase\InstallStart; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Bitrix24\SDK\Core\Credentials\AuthToken; use Bitrix24\SDK\Core\Credentials\Scope; diff --git a/src/Journal/Controller/JournalAdminController.php b/src/Journal/Controller/JournalAdminController.php index 5e69be5..d25d7d2 100644 --- a/src/Journal/Controller/JournalAdminController.php +++ b/src/Journal/Controller/JournalAdminController.php @@ -15,6 +15,7 @@ use Bitrix24\Lib\Journal\Entity\LogLevel; use Bitrix24\Lib\Journal\Infrastructure\Doctrine\JournalItemReadRepository; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -48,7 +49,7 @@ public function list(Request $request): Response $pagination = $this->journalReadRepository->findWithFilters( memberId: $memberId ?: null, - domainUrl: $domainUrl ?: null, + domain: $domainUrl ? new Domain($domainUrl) : null, logLevel: $level, label: $label ?: null, page: $page, diff --git a/src/Journal/Docs/README.md b/src/Journal/Docs/README.md index 4f7f519..7e8b9a5 100644 --- a/src/Journal/Docs/README.md +++ b/src/Journal/Docs/README.md @@ -135,8 +135,8 @@ $readRepo = new JournalItemReadRepository($entityManager, $paginator); // Получение с фильтрами и пагинацией $pagination = $readRepo->findWithFilters( memberId: '66c9893d5f30e6.45265697', - domainUrl: 'example.bitrix24.ru', - level: LogLevel::error, + domain: new Domain('example.bitrix24.ru'), + logLevel: LogLevel::error, label: 'b24.api.error', page: 1, limit: 50 diff --git a/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php b/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php index a3b02f5..404cd8e 100644 --- a/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php +++ b/src/Journal/Infrastructure/Doctrine/JournalItemReadRepository.php @@ -18,6 +18,7 @@ use Bitrix24\Lib\Journal\Entity\JournalItem; use Bitrix24\Lib\Journal\Entity\JournalItemInterface; use Bitrix24\Lib\Journal\Entity\LogLevel; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; use Knp\Component\Pager\Pagination\PaginationInterface; @@ -41,13 +42,13 @@ public function __construct( */ public function findWithFilters( ?string $memberId = null, - ?string $domainUrl = null, + ?Domain $domain = null, ?LogLevel $logLevel = null, ?string $label = null, int $page = 1, int $limit = 50 ): PaginationInterface { - $queryBuilder = $this->createFilteredQueryBuilder($memberId, $domainUrl, $logLevel, $label); + $queryBuilder = $this->createFilteredQueryBuilder($memberId, $domain, $logLevel, $label); return $this->paginator->paginate( $queryBuilder, @@ -113,7 +114,7 @@ public function getAvailableLabels(): array */ private function createFilteredQueryBuilder( ?string $memberId = null, - ?string $domainUrl = null, + ?Domain $domain = null, ?LogLevel $logLevel = null, ?string $label = null ): QueryBuilder { @@ -128,11 +129,11 @@ private function createFilteredQueryBuilder( ; } - if (null !== $domainUrl) { + if (null !== $domain) { $queryBuilder->innerJoin(ApplicationInstallation::class, 'ai', 'WITH', 'ai.id = j.applicationInstallationId') ->innerJoin(Bitrix24Account::class, 'b24', 'WITH', 'b24.id = ai.bitrix24AccountId') ->andWhere('b24.domainUrl = :domainUrl') - ->setParameter('domainUrl', $domainUrl) + ->setParameter('domainUrl', $domain->value) ; } diff --git a/src/Bitrix24Accounts/ValueObjects/Domain.php b/src/Kernel/ValueObjects/Domain.php similarity index 97% rename from src/Bitrix24Accounts/ValueObjects/Domain.php rename to src/Kernel/ValueObjects/Domain.php index e172b22..d53fcf3 100644 --- a/src/Bitrix24Accounts/ValueObjects/Domain.php +++ b/src/Kernel/ValueObjects/Domain.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Bitrix24\Lib\Bitrix24Accounts\ValueObjects; +namespace Bitrix24\Lib\Kernel\ValueObjects; readonly class Domain { diff --git a/tests/Functional/ApplicationInstallations/UseCase/Install/HandlerTest.php b/tests/Functional/ApplicationInstallations/UseCase/Install/HandlerTest.php index 45846d3..d1a8876 100644 --- a/tests/Functional/ApplicationInstallations/UseCase/Install/HandlerTest.php +++ b/tests/Functional/ApplicationInstallations/UseCase/Install/HandlerTest.php @@ -16,7 +16,7 @@ use Bitrix24\Lib\Bitrix24Accounts; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Bitrix24\Lib\Services\Flusher; use Bitrix24\Lib\ApplicationInstallations; use Bitrix24\Lib\Tests\EntityManagerFactory; diff --git a/tests/Functional/ApplicationInstallations/UseCase/OnAppInstall/HandlerTest.php b/tests/Functional/ApplicationInstallations/UseCase/OnAppInstall/HandlerTest.php index ea179a5..9ed7384 100644 --- a/tests/Functional/ApplicationInstallations/UseCase/OnAppInstall/HandlerTest.php +++ b/tests/Functional/ApplicationInstallations/UseCase/OnAppInstall/HandlerTest.php @@ -16,7 +16,7 @@ use Bitrix24\Lib\Bitrix24Accounts; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Bitrix24\Lib\Services\Flusher; use Bitrix24\Lib\ApplicationInstallations; use Bitrix24\Lib\Tests\EntityManagerFactory; diff --git a/tests/Functional/ApplicationInstallations/UseCase/Uninstall/HandlerTest.php b/tests/Functional/ApplicationInstallations/UseCase/Uninstall/HandlerTest.php index 2728053..c3ecbfa 100644 --- a/tests/Functional/ApplicationInstallations/UseCase/Uninstall/HandlerTest.php +++ b/tests/Functional/ApplicationInstallations/UseCase/Uninstall/HandlerTest.php @@ -16,7 +16,7 @@ use Bitrix24\Lib\Bitrix24Accounts; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Bitrix24\Lib\Services\Flusher; use Bitrix24\Lib\ApplicationInstallations; use Bitrix24\Lib\Tests\EntityManagerFactory; diff --git a/tests/Functional/Bitrix24Accounts/UseCase/ChangeDomainUrl/HandlerTest.php b/tests/Functional/Bitrix24Accounts/UseCase/ChangeDomainUrl/HandlerTest.php index 01e2d5a..e9c70e5 100644 --- a/tests/Functional/Bitrix24Accounts/UseCase/ChangeDomainUrl/HandlerTest.php +++ b/tests/Functional/Bitrix24Accounts/UseCase/ChangeDomainUrl/HandlerTest.php @@ -29,7 +29,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Uid\Uuid; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; /** * @internal diff --git a/tests/Functional/Bitrix24Accounts/UseCase/InstallFinish/HandlerTest.php b/tests/Functional/Bitrix24Accounts/UseCase/InstallFinish/HandlerTest.php index 5d84d7e..66e22a8 100644 --- a/tests/Functional/Bitrix24Accounts/UseCase/InstallFinish/HandlerTest.php +++ b/tests/Functional/Bitrix24Accounts/UseCase/InstallFinish/HandlerTest.php @@ -30,7 +30,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Uid\Uuid; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; /** * @internal diff --git a/tests/Functional/Bitrix24Accounts/UseCase/InstallStart/HandlerTest.php b/tests/Functional/Bitrix24Accounts/UseCase/InstallStart/HandlerTest.php index d179e46..578c497 100644 --- a/tests/Functional/Bitrix24Accounts/UseCase/InstallStart/HandlerTest.php +++ b/tests/Functional/Bitrix24Accounts/UseCase/InstallStart/HandlerTest.php @@ -33,7 +33,7 @@ use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Stopwatch\Stopwatch; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; /** * @internal diff --git a/tests/Unit/ApplicationInstallations/UseCase/Install/CommandTest.php b/tests/Unit/ApplicationInstallations/UseCase/Install/CommandTest.php index 0afee06..03c3182 100644 --- a/tests/Unit/ApplicationInstallations/UseCase/Install/CommandTest.php +++ b/tests/Unit/ApplicationInstallations/UseCase/Install/CommandTest.php @@ -5,7 +5,7 @@ namespace Bitrix24\Lib\Tests\Unit\ApplicationInstallations\UseCase\Install; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Bitrix24\Lib\Tests\Functional\Bitrix24Accounts\Builders\Bitrix24AccountBuilder; use Bitrix24\SDK\Application\ApplicationStatus; use Bitrix24\SDK\Application\PortalLicenseFamily; diff --git a/tests/Unit/ApplicationInstallations/UseCase/OnAppInstall/CommandTest.php b/tests/Unit/ApplicationInstallations/UseCase/OnAppInstall/CommandTest.php index d530274..c9b3d26 100644 --- a/tests/Unit/ApplicationInstallations/UseCase/OnAppInstall/CommandTest.php +++ b/tests/Unit/ApplicationInstallations/UseCase/OnAppInstall/CommandTest.php @@ -5,7 +5,7 @@ namespace Bitrix24\Lib\Tests\Unit\ApplicationInstallations\UseCase\OnAppInstall; use Bitrix24\Lib\ApplicationInstallations\UseCase\OnAppInstall\Command; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Bitrix24\Lib\Tests\Functional\ApplicationInstallations\Builders\ApplicationInstallationBuilder; use Bitrix24\Lib\Tests\Functional\Bitrix24Accounts\Builders\Bitrix24AccountBuilder; use Bitrix24\SDK\Application\ApplicationStatus; diff --git a/tests/Unit/ApplicationInstallations/UseCase/Uninstall/CommandTest.php b/tests/Unit/ApplicationInstallations/UseCase/Uninstall/CommandTest.php index 75cc13f..51b7d6a 100644 --- a/tests/Unit/ApplicationInstallations/UseCase/Uninstall/CommandTest.php +++ b/tests/Unit/ApplicationInstallations/UseCase/Uninstall/CommandTest.php @@ -5,7 +5,7 @@ namespace Bitrix24\Lib\Tests\Unit\ApplicationInstallations\UseCase\Uninstall; use Bitrix24\Lib\ApplicationInstallations\UseCase\Uninstall\Command; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use Bitrix24\Lib\Tests\Functional\Bitrix24Accounts\Builders\Bitrix24AccountBuilder; use Bitrix24\SDK\Application\Contracts\Bitrix24Accounts\Entity\Bitrix24AccountStatus; use Bitrix24\SDK\Core\Credentials\Scope; diff --git a/tests/Unit/Bitrix24Accounts/UseCase/ChangeDomainUrl/CommandTest.php b/tests/Unit/Bitrix24Accounts/UseCase/ChangeDomainUrl/CommandTest.php index f8deb49..8dc5c47 100644 --- a/tests/Unit/Bitrix24Accounts/UseCase/ChangeDomainUrl/CommandTest.php +++ b/tests/Unit/Bitrix24Accounts/UseCase/ChangeDomainUrl/CommandTest.php @@ -5,7 +5,7 @@ namespace Bitrix24\Lib\Tests\Unit\Bitrix24Accounts\UseCase\ChangeDomainUrl; use Bitrix24\Lib\Bitrix24Accounts\UseCase\ChangeDomainUrl\Command; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; diff --git a/tests/Unit/Bitrix24Accounts/UseCase/InstallFinish/CommandTest.php b/tests/Unit/Bitrix24Accounts/UseCase/InstallFinish/CommandTest.php index 44559ef..dfc1200 100644 --- a/tests/Unit/Bitrix24Accounts/UseCase/InstallFinish/CommandTest.php +++ b/tests/Unit/Bitrix24Accounts/UseCase/InstallFinish/CommandTest.php @@ -12,7 +12,7 @@ use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Symfony\Component\Uid\Uuid; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; /** diff --git a/tests/Unit/Bitrix24Accounts/UseCase/InstallStart/CommandTest.php b/tests/Unit/Bitrix24Accounts/UseCase/InstallStart/CommandTest.php index 27a39a4..bf4de15 100644 --- a/tests/Unit/Bitrix24Accounts/UseCase/InstallStart/CommandTest.php +++ b/tests/Unit/Bitrix24Accounts/UseCase/InstallStart/CommandTest.php @@ -14,7 +14,7 @@ use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Symfony\Component\Uid\Uuid; -use Bitrix24\Lib\Bitrix24Accounts\ValueObjects\Domain; +use Bitrix24\Lib\Kernel\ValueObjects\Domain; /** From d4a44a8358e7ef70514be31c42011ca6cb5856c5 Mon Sep 17 00:00:00 2001 From: kirill Date: Wed, 25 Feb 2026 23:06:55 +0300 Subject: [PATCH 6/6] Refactor: fix spacing issues, optimize imports, and improve code formatting in `JournalAdminController`, `JournalLogger`, and `JournalItemInterface` --- src/Journal/Controller/JournalAdminController.php | 2 +- src/Journal/Entity/JournalItemInterface.php | 2 +- src/Journal/Services/JournalLogger.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Journal/Controller/JournalAdminController.php b/src/Journal/Controller/JournalAdminController.php index d25d7d2..8dd1560 100644 --- a/src/Journal/Controller/JournalAdminController.php +++ b/src/Journal/Controller/JournalAdminController.php @@ -36,7 +36,7 @@ public function __construct( */ public function list(Request $request): Response { - $page = max(1 , $request->query->getInt('page', 1)); + $page = max(1, $request->query->getInt('page', 1)); $domainUrl = $request->query->get('domain'); $memberId = $request->query->get('member_id'); $levelValue = $request->query->get('level'); diff --git a/src/Journal/Entity/JournalItemInterface.php b/src/Journal/Entity/JournalItemInterface.php index a1b8723..b87edd6 100644 --- a/src/Journal/Entity/JournalItemInterface.php +++ b/src/Journal/Entity/JournalItemInterface.php @@ -33,7 +33,7 @@ public function getCreatedAt(): CarbonImmutable; public function getLevel(): LogLevel; public function getMessage(): string; - + public function getUserId(): ?string; public function getLabel(): string; diff --git a/src/Journal/Services/JournalLogger.php b/src/Journal/Services/JournalLogger.php index 63f6df9..3a6c024 100644 --- a/src/Journal/Services/JournalLogger.php +++ b/src/Journal/Services/JournalLogger.php @@ -15,8 +15,8 @@ use Bitrix24\Lib\Journal\Entity\JournalItem; use Bitrix24\Lib\Journal\Entity\LogLevel; -use Bitrix24\Lib\Journal\Infrastructure\JournalItemRepositoryInterface; use Bitrix24\Lib\Journal\Entity\ValueObjects\Context; +use Bitrix24\Lib\Journal\Infrastructure\JournalItemRepositoryInterface; use Darsyn\IP\Version\Multi as IP; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface;