-
Notifications
You must be signed in to change notification settings - Fork 1
Add ApplicationSettings bounded context for issue #67 #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mesilov
merged 38 commits into
dev
from
claude/fix-bitrix24-issue-67-01Pg2AJibYNoBKmUVijCYFhU
Nov 24, 2025
+4,812
−47
Merged
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
ba89b89
Add ApplicationSettings bounded context for issue #67
claude 73d9662
Refactor ApplicationSettings for multi-scope support (issue #67)
claude 52211f9
Refactor ApplicationSettings: Add tracking fields and event system (i…
claude e76e82c
Add soft-delete support and OnApplicationDelete UseCase (issue #67)
claude 4cf3494
Fix: Add backward compatibility methods to Repository
claude 704c22d
Add getEvents() method to AggregateRoot for testing
claude ea01d31
Align event handling with existing patterns
claude 4f25ed8
Fix linter errors and move documentation
claude c656e51
Refactor ApplicationSettings: cleanup and improve architecture
claude 4969132
Final refactoring: simplify Delete UseCase and add comprehensive tests
claude 02e878e
Apply Rector and PHP-CS-Fixer code improvements
claude fc72254
Fix PHPStan errors in InstallSettingsTest
claude 93bf656
Remove redundant repository methods and simplify API
claude f855474
Refactor ApplicationSettings: simplify API and add SettingsFetcher se…
claude 20cffda
Refactor SettingsFetcher: rename getSetting to getItem and add except…
claude 6450f18
Add findAllForInstallationByKey method to optimize SettingsFetcher
claude b85a052
Refactor ApplicationSettings: rename entity, separate Create/Update, …
claude 92d8b1d
Enhance SettingsFetcher: add logger, rename method, add deserializati…
claude 09ff03d
Apply Rector automatic code improvements
claude 88ea683
Improve exception handling and serialization in ApplicationSettings
claude 9e6ae22
Refactor ApplicationSettingsItem to generate UUID internally
claude b858438
Update Makefile to use Docker for composer license checker
mesilov 35e7f52
Add TODO comments for SDK interface gaps and refactor Bitrix24 accoun…
mesilov df4a879
Refactor test variable names for clarity and update lambda typing in …
mesilov c665594
Refactor TODO comment formatting and lambda syntax in account filtering
mesilov 2399fde
Update license-check workflow to use `composer-license-checker` directly
mesilov 38bbbc3
Translate ApplicationSettings documentation to English, update code e…
mesilov 8d3c5e6
Refactor repository tests: add contract tests for consistency, move i…
mesilov 4e7521f
Update README.md: adjust formatting, add new ApplicationSettings sect…
mesilov a06a148
Merge remote-tracking branch 'origin/dev' into claude/fix-bitrix24-is…
mesilov ce211c1
Add PHP 8.4 support in composer requirements and GitHub workflows
mesilov f187837
Remove outdated TODO comment and redundant PHPStan ignore directive i…
mesilov 6346c29
Refactor ApplicationSettings tests: introduce `flushChanges` method f…
mesilov 50f36ab
Refactor repository methods: add `#[\Override]` annotations and remov…
mesilov 1e7a1e1
Update CLAUDE.md: add steps for running linters and tests after each …
mesilov 218b3f8
Refactor ApplicationSettingsItemRepository: remove EntityRepository i…
mesilov 8ba250e
Replace custom exceptions with SDK standard exceptions for consistenc…
mesilov aa39517
Rename `InstallSettings` to `DefaultSettingsInstaller` for improved s…
mesilov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
28 changes: 28 additions & 0 deletions
28
config/xml/Bitrix24.Lib.ApplicationSettings.Entity.ApplicationSetting.dcm.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | ||
| xmlns:xs="https://www.w3.org/2001/XMLSchema" | ||
| xmlns:orm="https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | ||
| <entity name="Bitrix24\Lib\ApplicationSettings\Entity\ApplicationSetting" | ||
| table="application_setting"> | ||
| <id name="id" type="uuid" column="id"> | ||
|
|
||
| </id> | ||
|
|
||
| <field name="applicationInstallationId" type="uuid" column="application_installation_id" nullable="false"/> | ||
|
|
||
| <field name="key" type="string" column="key" length="255" nullable="false"/> | ||
|
|
||
| <field name="value" type="text" column="value" nullable="false"/> | ||
|
|
||
| <field name="createdAt" type="carbon_immutable" column="created_at_utc" precision="3" nullable="false"/> | ||
|
|
||
| <field name="updatedAt" type="carbon_immutable" column="updated_at_utc" precision="3" nullable="false"/> | ||
|
|
||
| <unique-constraints> | ||
| <unique-constraint columns="application_installation_id,key" name="unique_app_installation_key"/> | ||
| </unique-constraints> | ||
|
|
||
| <indexes> | ||
| <index name="idx_application_installation_id" columns="application_installation_id"/> | ||
| </indexes> | ||
| </entity> | ||
| </doctrine-mapping> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Bitrix24\Lib\ApplicationSettings\Entity; | ||
|
|
||
| use Bitrix24\Lib\AggregateRoot; | ||
| use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; | ||
| use Carbon\CarbonImmutable; | ||
| use Symfony\Component\Uid\Uuid; | ||
|
|
||
| /** | ||
| * Application setting entity | ||
| * | ||
| * Stores key-value settings for application installations. | ||
| * Each ApplicationInstallation can have multiple settings identified by unique keys. | ||
| */ | ||
| class ApplicationSetting extends AggregateRoot | ||
| { | ||
| private readonly CarbonImmutable $createdAt; | ||
| private CarbonImmutable $updatedAt; | ||
| private string $value; | ||
|
|
||
| public function __construct( | ||
| private readonly Uuid $id, | ||
| private readonly Uuid $applicationInstallationId, | ||
| private readonly string $key, | ||
| string $value | ||
| ) { | ||
| $this->validateKey($key); | ||
| $this->validateValue($value); | ||
|
|
||
| $this->value = $value; | ||
| $this->createdAt = new CarbonImmutable(); | ||
| $this->updatedAt = new CarbonImmutable(); | ||
| } | ||
|
|
||
| public function getId(): Uuid | ||
| { | ||
| return $this->id; | ||
| } | ||
|
|
||
| public function getApplicationInstallationId(): Uuid | ||
| { | ||
| return $this->applicationInstallationId; | ||
| } | ||
|
|
||
| public function getKey(): string | ||
| { | ||
| return $this->key; | ||
| } | ||
|
|
||
| public function getValue(): string | ||
| { | ||
| return $this->value; | ||
| } | ||
|
|
||
| public function getCreatedAt(): CarbonImmutable | ||
| { | ||
| return $this->createdAt; | ||
| } | ||
|
|
||
| public function getUpdatedAt(): CarbonImmutable | ||
| { | ||
| return $this->updatedAt; | ||
| } | ||
|
|
||
| /** | ||
| * Update setting value | ||
| */ | ||
| public function updateValue(string $value): void | ||
| { | ||
| $this->validateValue($value); | ||
|
|
||
| if ($this->value !== $value) { | ||
| $this->value = $value; | ||
| $this->updatedAt = new CarbonImmutable(); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Validate setting key | ||
| */ | ||
| private function validateKey(string $key): void | ||
| { | ||
| if ('' === trim($key)) { | ||
| throw new InvalidArgumentException('Setting key cannot be empty'); | ||
| } | ||
|
|
||
| if (strlen($key) > 255) { | ||
| throw new InvalidArgumentException('Setting key cannot exceed 255 characters'); | ||
| } | ||
|
|
||
| // Key should contain only alphanumeric characters, underscores, dots, and hyphens | ||
| if (!preg_match('/^[a-zA-Z0-9_.-]+$/', $key)) { | ||
| throw new InvalidArgumentException( | ||
| 'Setting key can only contain alphanumeric characters, underscores, dots, and hyphens' | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Validate setting value | ||
| */ | ||
| private function validateValue(string $value): void | ||
| { | ||
| // Value can be empty but not null (handled by type hint) | ||
| // We store value as string, could be JSON or plain text | ||
| // No specific validation needed here, can be extended if needed | ||
| } | ||
| } |
102 changes: 102 additions & 0 deletions
102
src/ApplicationSettings/Infrastructure/Doctrine/ApplicationSettingRepository.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Bitrix24\Lib\ApplicationSettings\Infrastructure\Doctrine; | ||
|
|
||
| use Bitrix24\Lib\ApplicationSettings\Entity\ApplicationSetting; | ||
| use Doctrine\ORM\EntityManagerInterface; | ||
| use Doctrine\ORM\EntityRepository; | ||
| use Symfony\Component\Uid\Uuid; | ||
|
|
||
| /** | ||
| * Repository for ApplicationSetting entity | ||
| * | ||
| * @extends EntityRepository<ApplicationSetting> | ||
| */ | ||
| class ApplicationSettingRepository extends EntityRepository | ||
| { | ||
| public function __construct(EntityManagerInterface $entityManager) | ||
| { | ||
| parent::__construct($entityManager, $entityManager->getClassMetadata(ApplicationSetting::class)); | ||
| } | ||
|
|
||
| /** | ||
| * Save application setting | ||
| */ | ||
| public function save(ApplicationSetting $applicationSetting): void | ||
| { | ||
| $this->getEntityManager()->persist($applicationSetting); | ||
| } | ||
|
|
||
| /** | ||
| * Delete application setting | ||
| */ | ||
| public function delete(ApplicationSetting $applicationSetting): void | ||
| { | ||
| $this->getEntityManager()->remove($applicationSetting); | ||
| } | ||
|
|
||
| /** | ||
| * Find setting by ID | ||
| */ | ||
| public function findById(Uuid $id): ?ApplicationSetting | ||
| { | ||
| return $this->getEntityManager() | ||
| ->getRepository(ApplicationSetting::class) | ||
| ->createQueryBuilder('s') | ||
| ->where('s.id = :id') | ||
| ->setParameter('id', $id) | ||
| ->getQuery() | ||
| ->getOneOrNullResult(); | ||
| } | ||
|
|
||
| /** | ||
| * Find setting by application installation ID and key | ||
| */ | ||
| public function findByApplicationInstallationIdAndKey( | ||
| Uuid $applicationInstallationId, | ||
| string $key | ||
| ): ?ApplicationSetting { | ||
| return $this->getEntityManager() | ||
| ->getRepository(ApplicationSetting::class) | ||
| ->createQueryBuilder('s') | ||
| ->where('s.applicationInstallationId = :applicationInstallationId') | ||
| ->andWhere('s.key = :key') | ||
| ->setParameter('applicationInstallationId', $applicationInstallationId) | ||
| ->setParameter('key', $key) | ||
| ->getQuery() | ||
| ->getOneOrNullResult(); | ||
| } | ||
|
|
||
| /** | ||
| * Find all settings for application installation | ||
| * | ||
| * @return ApplicationSetting[] | ||
| */ | ||
| public function findByApplicationInstallationId(Uuid $applicationInstallationId): array | ||
| { | ||
| return $this->getEntityManager() | ||
| ->getRepository(ApplicationSetting::class) | ||
| ->createQueryBuilder('s') | ||
| ->where('s.applicationInstallationId = :applicationInstallationId') | ||
| ->setParameter('applicationInstallationId', $applicationInstallationId) | ||
| ->orderBy('s.key', 'ASC') | ||
| ->getQuery() | ||
| ->getResult(); | ||
| } | ||
|
|
||
| /** | ||
| * Delete all settings for application installation | ||
| */ | ||
| public function deleteByApplicationInstallationId(Uuid $applicationInstallationId): void | ||
| { | ||
| $this->getEntityManager() | ||
| ->createQueryBuilder() | ||
| ->delete(ApplicationSetting::class, 's') | ||
| ->where('s.applicationInstallationId = :applicationInstallationId') | ||
| ->setParameter('applicationInstallationId', $applicationInstallationId) | ||
| ->getQuery() | ||
| ->execute(); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Bitrix24\Lib\ApplicationSettings\UseCase\Delete; | ||
|
|
||
| use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; | ||
| use Symfony\Component\Uid\Uuid; | ||
|
|
||
| /** | ||
| * Command to delete application setting | ||
| */ | ||
| readonly class Command | ||
| { | ||
| public function __construct( | ||
| public Uuid $applicationInstallationId, | ||
| public string $key | ||
| ) { | ||
| $this->validate(); | ||
| } | ||
|
|
||
| private function validate(): void | ||
| { | ||
| if ('' === trim($this->key)) { | ||
| throw new InvalidArgumentException('Setting key cannot be empty'); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Bitrix24\Lib\ApplicationSettings\UseCase\Delete; | ||
|
|
||
| use Bitrix24\Lib\ApplicationSettings\Infrastructure\Doctrine\ApplicationSettingRepository; | ||
| use Bitrix24\Lib\Services\Flusher; | ||
| use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; | ||
| use Psr\Log\LoggerInterface; | ||
|
|
||
| /** | ||
| * Handler for Delete command | ||
| */ | ||
| readonly class Handler | ||
| { | ||
| public function __construct( | ||
| private ApplicationSettingRepository $applicationSettingRepository, | ||
| private Flusher $flusher, | ||
| private LoggerInterface $logger | ||
| ) { | ||
| } | ||
|
|
||
| public function handle(Command $command): void | ||
| { | ||
| $this->logger->info('ApplicationSettings.Delete.start', [ | ||
| 'applicationInstallationId' => $command->applicationInstallationId->toRfc4122(), | ||
| 'key' => $command->key, | ||
| ]); | ||
|
|
||
| $setting = $this->applicationSettingRepository->findByApplicationInstallationIdAndKey( | ||
| $command->applicationInstallationId, | ||
| $command->key | ||
| ); | ||
|
|
||
| if (null === $setting) { | ||
| throw new InvalidArgumentException( | ||
| sprintf( | ||
| 'Setting with key "%s" not found for application installation "%s"', | ||
| $command->key, | ||
| $command->applicationInstallationId->toRfc4122() | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| $settingId = $setting->getId()->toRfc4122(); | ||
| $this->applicationSettingRepository->delete($setting); | ||
| $this->flusher->flush(); | ||
|
|
||
| $this->logger->info('ApplicationSettings.Delete.finish', [ | ||
| 'settingId' => $settingId, | ||
| ]); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Bitrix24\Lib\ApplicationSettings\UseCase\Get; | ||
|
|
||
| use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; | ||
| use Symfony\Component\Uid\Uuid; | ||
|
|
||
| /** | ||
| * Command to get application setting | ||
| */ | ||
| readonly class Command | ||
| { | ||
| public function __construct( | ||
| public Uuid $applicationInstallationId, | ||
| public string $key | ||
| ) { | ||
| $this->validate(); | ||
| } | ||
|
|
||
| private function validate(): void | ||
| { | ||
| if ('' === trim($this->key)) { | ||
| throw new InvalidArgumentException('Setting key cannot be empty'); | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.