Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ba89b89
Add ApplicationSettings bounded context for issue #67
claude Nov 21, 2025
73d9662
Refactor ApplicationSettings for multi-scope support (issue #67)
claude Nov 21, 2025
52211f9
Refactor ApplicationSettings: Add tracking fields and event system (i…
claude Nov 21, 2025
e76e82c
Add soft-delete support and OnApplicationDelete UseCase (issue #67)
claude Nov 21, 2025
4cf3494
Fix: Add backward compatibility methods to Repository
claude Nov 21, 2025
704c22d
Add getEvents() method to AggregateRoot for testing
claude Nov 21, 2025
ea01d31
Align event handling with existing patterns
claude Nov 21, 2025
4f25ed8
Fix linter errors and move documentation
claude Nov 21, 2025
c656e51
Refactor ApplicationSettings: cleanup and improve architecture
claude Nov 21, 2025
4969132
Final refactoring: simplify Delete UseCase and add comprehensive tests
claude Nov 21, 2025
02e878e
Apply Rector and PHP-CS-Fixer code improvements
claude Nov 21, 2025
fc72254
Fix PHPStan errors in InstallSettingsTest
claude Nov 21, 2025
93bf656
Remove redundant repository methods and simplify API
claude Nov 21, 2025
f855474
Refactor ApplicationSettings: simplify API and add SettingsFetcher se…
claude Nov 21, 2025
20cffda
Refactor SettingsFetcher: rename getSetting to getItem and add except…
claude Nov 21, 2025
6450f18
Add findAllForInstallationByKey method to optimize SettingsFetcher
claude Nov 21, 2025
b85a052
Refactor ApplicationSettings: rename entity, separate Create/Update, …
claude Nov 21, 2025
92d8b1d
Enhance SettingsFetcher: add logger, rename method, add deserializati…
claude Nov 21, 2025
09ff03d
Apply Rector automatic code improvements
claude Nov 21, 2025
88ea683
Improve exception handling and serialization in ApplicationSettings
claude Nov 21, 2025
9e6ae22
Refactor ApplicationSettingsItem to generate UUID internally
claude Nov 21, 2025
b858438
Update Makefile to use Docker for composer license checker
mesilov Nov 23, 2025
35e7f52
Add TODO comments for SDK interface gaps and refactor Bitrix24 accoun…
mesilov Nov 23, 2025
df4a879
Refactor test variable names for clarity and update lambda typing in …
mesilov Nov 23, 2025
c665594
Refactor TODO comment formatting and lambda syntax in account filtering
mesilov Nov 23, 2025
2399fde
Update license-check workflow to use `composer-license-checker` directly
mesilov Nov 23, 2025
38bbbc3
Translate ApplicationSettings documentation to English, update code e…
mesilov Nov 23, 2025
8d3c5e6
Refactor repository tests: add contract tests for consistency, move i…
mesilov Nov 23, 2025
4e7521f
Update README.md: adjust formatting, add new ApplicationSettings sect…
mesilov Nov 23, 2025
a06a148
Merge remote-tracking branch 'origin/dev' into claude/fix-bitrix24-is…
mesilov Nov 23, 2025
ce211c1
Add PHP 8.4 support in composer requirements and GitHub workflows
mesilov Nov 23, 2025
f187837
Remove outdated TODO comment and redundant PHPStan ignore directive i…
mesilov Nov 23, 2025
6346c29
Refactor ApplicationSettings tests: introduce `flushChanges` method f…
mesilov Nov 23, 2025
50f36ab
Refactor repository methods: add `#[\Override]` annotations and remov…
mesilov Nov 23, 2025
1e7a1e1
Update CLAUDE.md: add steps for running linters and tests after each …
mesilov Nov 23, 2025
218b3f8
Refactor ApplicationSettingsItemRepository: remove EntityRepository i…
mesilov Nov 23, 2025
8ba250e
Replace custom exceptions with SDK standard exceptions for consistenc…
mesilov Nov 24, 2025
aa39517
Rename `InstallSettings` to `DefaultSettingsInstaller` for improved s…
mesilov Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/license-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
fail-fast: false
matrix:
php-version:
- "8.3"
- "8.4"
dependencies: [ highest ]
operating-system: [ ubuntu-latest]

Expand All @@ -37,7 +37,7 @@ jobs:
run: "composer update --no-interaction --no-progress --no-suggest"

- name: "composer-license-checker"
run: "make lint-allowed-licenses"
run: "php vendor/bin/composer-license-checker"

- name: "is allowed licenses check succeeded"
if: ${{ success() }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-cs-fixer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
fail-fast: false
matrix:
php-version:
- "8.3"
- "8.4"
dependencies: [ highest ]
operating-system: [ ubuntu-latest]

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
fail-fast: false
matrix:
php-version:
- "8.3"
- "8.4"
dependencies: [ highest ]
operating-system: [ ubuntu-latest]

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-rector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
fail-fast: false
matrix:
php-version:
- "8.3"
- "8.4"
dependencies: [ highest ]
operating-system: [ ubuntu-latest]

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tests-functional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
matrix:
php-version:
- "8.3"
- "8.4"
dependencies: [ highest ]
operating-system: [ ubuntu-latest ]
services:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tests-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
matrix:
php-version:
- "8.3"
- "8.4"
dependencies: [ highest ]
operating-system: [ ubuntu-latest]

Expand Down
108 changes: 108 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,111 @@



## 0.1.2
### Added
- **ApplicationSettings bounded context** for application configuration management — [#67](https://github.com/mesilov/bitrix24-php-lib/issues/67)
- Full CRUD functionality with CQRS pattern (Create, Update, Delete use cases)
- Multi-scope support: Global, Departmental, and Personal settings with cascading resolution
- **SettingsFetcher service** with automatic deserialization support
- Cascading resolution logic (Personal → Departmental → Global)
- JSON deserialization to objects using Symfony Serializer
- Comprehensive logging with LoggerInterface
- **DefaultSettingsInstaller service** for bulk creation of default settings
- Soft-delete support with `ApplicationSettingStatus` enum (Active/Deleted)
- Event system with `ApplicationSettingsItemChangedEvent` for change tracking
- CLI command `app:settings:list` for viewing settings with scope filtering
- InMemory repository implementation for fast unit testing
- Unique constraint on (installation_id, key, user_id, department_id)
- Tracking fields: `changedByBitrix24UserId`, `isRequired`
- Database schema updates
- Table `application_settings` with UUID v7 IDs
- Scope fields: `b24_user_id`, `b24_department_id`
- Status field with index for query optimization
- Timestamp tracking: `created_at_utc`, `updated_at_utc`
- Comprehensive test coverage
- Unit tests for entity validation and business logic
- Functional tests for repository operations and use case handlers
- Tests for all scope types and soft-delete behavior

### Changed
- **Refactored ApplicationSettings entity naming**
- Renamed `ApplicationSetting` → `ApplicationSettingsItem`
- Renamed all interfaces and events accordingly
- Updated table name from `application_setting` → `application_settings`
- **Renamed service class for clarity** — [#67](https://github.com/mesilov/bitrix24-php-lib/issues/67)
- Renamed `InstallSettings` → `DefaultSettingsInstaller` for better semantic clarity
- Updated all references in documentation and tests
- Updated log message prefixes to use new class name
- **Separated Create/Update use cases**
- Create UseCase now only creates new settings (throws exception if exists)
- Update UseCase for modifying existing settings (throws exception if not found)
- Update automatically emits `ApplicationSettingsItemChangedEvent`
- **Simplified repository API**
- Removed 6 redundant methods, kept only `findAllForInstallation()`
- Renamed `findAll()` → `findAllForInstallationByKey()` to avoid conflicts
- All find methods now filter by `status=Active` by default
- Added optimized `findAllForInstallationByKey()` method
- **Enhanced SettingsFetcher**
- Renamed `getSetting()` → `getItem()`
- Renamed `getSettingValue()` → `getValue()`
- Added automatic deserialization with type-safe generics
- Non-nullable return types with exception throwing
- **ApplicationSettingsItem improvements**
- UUID v7 generation moved inside entity constructor
- Key validation: only lowercase latin letters and dots
- Scope methods: `isGlobal()`, `isPersonal()`, `isDepartmental()`
- `updateValue()` method emits change events
- **Makefile improvements**
- Updated to use Docker for `composer-license-checker`
- Aligns with other linting and analysis workflows
- **Code quality improvements**
- Applied Rector automatic refactoring (arrow functions, type hints, naming)
- Added `#[\Override]` attributes to overridden methods
- Applied PHP-CS-Fixer formatting consistently
- Added symfony/property-access dependency for ObjectNormalizer
- **Documentation improvements**
- Translated ApplicationSettings documentation to English
- Updated all code examples to reflect current codebase
- Updated exception references to use SDK standard exceptions
- Improved best practices and security sections
- **Test infrastructure improvements**
- Created contract tests for ApplicationSettingsItemRepositoryInterface
- Moved ApplicationSettingsItemInMemoryRepository from src to tests/Helpers
- Added contract test implementations for both InMemory and Doctrine repositories
- Refactored existing repository tests to focus on implementation-specific behavior

### Fixed
- **PHPStan level 5 errors related to SDK interface compatibility** — [#67](https://github.com/mesilov/bitrix24-php-lib/issues/67)
- Removed invalid `#[\Override]` attributes from extension methods in `ApplicationInstallationRepository`
- Fixed `findByMemberId()` call with incorrect parameter count in `OnAppInstall\Handler`
- Added `@phpstan-ignore-next-line` comments for methods not yet available in SDK interface
- Added TODO comments to track SDK interface extension requirements
- **Doctrine XML mapping**
- Fixed `enumType` → `enum-type` syntax for Doctrine ORM 3 compatibility
- **Repository method naming conflicts**
- Renamed methods to avoid conflicts with EntityRepository base class
- **Exception handling standardization** — [#67](https://github.com/mesilov/bitrix24-php-lib/issues/67)
- Replaced custom exceptions with SDK standard exceptions for consistency
- Removed `SettingsItemAlreadyExistsException` → using `Bitrix24\SDK\Core\Exceptions\InvalidArgumentException`
- Removed `SettingsItemNotFoundException` → using `Bitrix24\SDK\Core\Exceptions\ItemNotFoundException`
- Created `BaseException` class in `src/Exceptions/` for future custom exceptions
- Updated all tests to expect correct SDK exception types
- Fixed PHPDoc annotations to reference correct exception types

### Removed
- **Get UseCase** - replaced with `SettingsFetcher` service (UseCases now only for data modification)
- **Redundant repository methods**
- `findGlobalByKey()`, `findPersonalByKey()`, `findDepartmentalByKey()`
- `findAllGlobal()`, `findAllPersonal()`, `findAllDepartmental()`
- `deleteByApplicationInstallationId()`
- `softDeleteByApplicationInstallationId()`
- **Hard delete from Delete UseCase** - replaced with soft-delete pattern
- **Entity getStatus() method** - use `isActive()` instead for better encapsulation
- **Static getRecommendedDefaults()** - developers should define their own defaults
- **Custom exception classes** — [#67](https://github.com/mesilov/bitrix24-php-lib/issues/67)
- `ApplicationSettings\Services\Exception\SettingsItemNotFoundException`
- `ApplicationSettings\UseCase\Create\Exception\SettingsItemAlreadyExistsException`

## 0.1.1
### Added
- Change php version requirements — [#44](https://github.com/mesilov/bitrix24-php-lib/pull/44)
Expand Down
11 changes: 9 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,17 @@ src/
3. Follow DDD principles
4. Use CQRS for write operations
5. Validate all inputs in command constructors
6. **After each refactoring task, automatically run linters and tests:**
- Run all linters: `make lint-phpstan && make lint-cs-fixer && make lint-rector`
- Run unit tests: `make test-run-unit`
- Run functional tests: `make test-run-functional`
- Fix any errors before proceeding to the next task
7. After refactoring, summarize changes in `changelog.md`
8. Check and actualize documentation in related files and README

## Git Workflow
- Main branch: `main`
- Feature branches: `feature/issue-number-description`
- Current branch: `feature/46-fix-errors`

## Docker Setup
- PHP CLI container for development
Expand All @@ -121,4 +127,5 @@ The `.env` file contains default values that work out-of-the-box with Docker Com
- `DATABASE_NAME=b24phpLibTest`
- `POSTGRES_VERSION=16`

These defaults allow running functional tests immediately after `make up` without additional configuration.
These defaults allow running functional tests immediately after `make up` without additional configuration.
- Always update changelog.md
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ composer:

# check allowed licenses
lint-allowed-licenses:
vendor/bin/composer-license-checker
docker-compose run --rm php-cli php vendor/bin/composer-license-checker
# linters
lint-phpstan:
docker-compose run --rm php-cli php vendor/bin/phpstan analyse --memory-limit 2G
Expand Down
34 changes: 23 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ PHP lib for Bitrix24 application development

## Build status

| CI\CD [status](https://github.com/mesilov/bitrix24-php-lib/actions) on `master` |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [![allowed licenses check](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/license-check.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/license-check.yml) |
| [![php-cs-fixer check](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-cs-fixer.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-cs-fixer.yml) |
| [![phpstan check](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-phpstan.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-phpstan.yml) |
| [![rector check](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-rector.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-rector.yml) |
| [![unit-tests status](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/tests-unit.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/tests-unit.yml) |
| CI\CD [status](https://github.com/mesilov/bitrix24-php-lib/actions) on `master` |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [![allowed licenses check](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/license-check.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/license-check.yml) |
| [![php-cs-fixer check](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-cs-fixer.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-cs-fixer.yml) |
| [![phpstan check](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-phpstan.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-phpstan.yml) |
| [![rector check](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-rector.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/lint-rector.yml) |
| [![unit-tests status](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/tests-unit.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/tests-unit.yml) |
| [![functional-tests status](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/tests-functional.yml/badge.svg)](https://github.com/mesilov/bitrix24-php-lib/actions/workflows/tests-functional.yml) |


## Application Domain

The library is designed for rapid development of Bitrix24 applications. Provides data storage layer in
Expand Down Expand Up @@ -45,11 +44,19 @@ who performed application installation
### Bitrix24Partners — ⏳ work in progress

Responsible for
storing [Bitrix24 partners](https://github.com/bitrix24/b24phpsdk/tree/main/src/Application/Contracts/Bitrix24Partners) who performed installation or service the portal
storing [Bitrix24 partners](https://github.com/bitrix24/b24phpsdk/tree/main/src/Application/Contracts/Bitrix24Partners) who performed installation or service
the portal

### ApplicationSettings — ✅

Responsible for
storing [application settings](https://github.com/bitrix24/b24phpsdk/tree/main/src/Application/Contracts/ApplicationSettings)
for specific Bitrix24 portal

## Architecture

### Layers and Abstraction Levels

```
bitrix24-app-laravel-skeleton – Laravel application template
bitrix24-app-symfony-skeleton – Symfony application template
Expand All @@ -58,6 +65,7 @@ bitrix24-php-sdk – transport layer + transport events (expired token, portal r
```

### Bounded Context Folder Structure

```
src/
Bitrix24Accounts
Expand All @@ -77,14 +85,15 @@ src/
Tests
```


## Quick Start

### Prerequisites

- Docker and Docker Compose
- Make

### Running Tests

```bash
# Initialize and start services
make up
Expand All @@ -99,7 +108,9 @@ make lint-rector
```

### Database Configuration

Default database credentials are pre-configured in `.env`:

- Host: `database` (Docker service)
- Database: `b24phpLibTest`
- User: `b24phpLibTest`
Expand All @@ -108,10 +119,11 @@ Default database credentials are pre-configured in `.env`:
No additional configuration needed for running tests.

## Infrastructure
- library is made cloud-agnostic

- library is made cloud-agnostic

## Development Rules

1. We use linters
2. Library is covered with tests
3. All work is organized through issues
Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
}
},
"require": {
"php": "^8.3",
"php": "8.3.* || 8.4.*",
"ext-json": "*",
"ext-curl": "*",
"ext-bcmath": "*",
Expand All @@ -59,17 +59,18 @@
"symfony/dotenv": "^7"
},
"require-dev": {
"lendable/composer-license-checker": "^1.2",
"doctrine/migrations": "^3",
"fakerphp/faker": "^1",
"friendsofphp/php-cs-fixer": "^3.64",
"lendable/composer-license-checker": "^1.2",
"monolog/monolog": "^3",
"fakerphp/faker": "^1",
"phpstan/phpstan": "^1",
"phpunit/phpunit": "^11",
"doctrine/migrations": "^3",
"psalm/phar": "^5",
"rector/rector": "^1",
"roave/security-advisories": "dev-master",
"symfony/debug-bundle": "^7",
"symfony/property-access": "^7.3",
"symfony/stopwatch": "^7"
},
"autoload": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<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\ApplicationSettingsItem"
table="application_settings">
<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="b24UserId" type="integer" column="b24_user_id" nullable="true"/>

<field name="b24DepartmentId" type="integer" column="b24_department_id" nullable="true"/>

<field name="changedByBitrix24UserId" type="integer" column="changed_by_b24_user_id" nullable="true"/>

<field name="isRequired" type="boolean" column="is_required" nullable="false"/>

<field name="status" enum-type="string" column="status" nullable="false"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Map status enum using enum class, not string literal

The XML mapping declares status with enum-type="string", but ApplicationSettingsItem::$status is a typed ApplicationSettingStatus enum (see src/ApplicationSettings/Entity/ApplicationSettingsItem.php:30‑39). Doctrine expects enum-type to point at the enum FQCN; using the literal string will hydrate database values as plain strings and will either raise a mapping/type error or fail assigning to the enum-typed property whenever settings are loaded from the database. Any read of application settings will break until the mapping references ApplicationSettingStatus (or a custom type) instead of string.

Useful? React with 👍 / 👎.


<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,b24_user_id,b24_department_id" name="unique_app_setting_scope"/>
</unique-constraints>
Comment on lines +30 to +32

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Soft-deleted settings still block re-create via unique key

The unique constraint on (application_installation_id,key,b24_user_id,b24_department_id) applies regardless of status, but the Delete handler only soft-deletes by setting status to Deleted (src/ApplicationSettings/UseCase/Delete/Handler.php:53‑55). After a setting is deleted, the row remains and the unique constraint still matches, so a subsequent Create for the same key/scope will hit a database unique-constraint violation even though code only checks active records. Include status in the unique key or hard-delete soft-deleted rows to allow recreating settings after deletion.

Useful? React with 👍 / 👎.


<indexes>
<index name="idx_application_installation_id" columns="application_installation_id"/>
<index name="idx_b24_user_id" columns="b24_user_id"/>
<index name="idx_b24_department_id" columns="b24_department_id"/>
<index name="idx_key" columns="key"/>
<index name="idx_status" columns="status"/>
</indexes>
</entity>
</doctrine-mapping>
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,13 @@ public function findByExternalId(string $externalId): array
/**
* Find application installation by application token.
*
* TODO: Create issue in b24-php-sdk to add this method to ApplicationInstallationRepositoryInterface
*
* @param non-empty-string $applicationToken
*
* @throws InvalidArgumentException
*/
#[\Override]
public function findByApplicationToken(string $applicationToken): ?ApplicationInstallationInterface
{
if ('' === trim($applicationToken)) {
Expand All @@ -131,6 +134,7 @@ public function findByApplicationToken(string $applicationToken): ?ApplicationIn
;
}

#[\Override]
public function findByBitrix24AccountMemberId(string $memberId): ?ApplicationInstallationInterface
{
if ('' === trim($memberId)) {
Expand Down
Loading