diff --git a/CHANGELOG.md b/CHANGELOG.md index ff6e1fe0a..d58ccfd9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## CHANGELOG FOR 0.5.0 + - feature [#115](https://github.com/ergonode/backend/issues/115) Product segment functionality (rprzedzik) + - feature [#118](https://github.com/ergonode/backend/issues/118) Event store history (BastekBielawski) + - feature [#124](https://github.com/ergonode/backend/issues/124) Register events in database (BastekBielawski) + ## CHANGELOG FOR 0.4.0 - feature [#104](https://github.com/ergonode/backend/issues/104) Multiple category trees (wiewiurdp) diff --git a/README.md b/README.md index 84480ee4e..1e7c7a388 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@
-
+
@@ -96,7 +96,7 @@ On the front side we've used headless approach with Vue.js application. Thanks t
#### Backend Technologies
- PHP 7.2
-- Symfony 4.2
+- Symfony 4.3
- Postgres 9.6 (uuid-ossp, ltree)
- RabbitMQ (optional)
- Redis (optional)
diff --git a/composer.json b/composer.json
index aebfbede7..31712680a 100644
--- a/composer.json
+++ b/composer.json
@@ -99,6 +99,7 @@
"Ergonode\\AttributeUnit\\": "module/attribute-unit/src",
"Ergonode\\AttributeDate\\": "module/attribute-date/src",
"Ergonode\\AttributeImage\\": "module/attribute-image/src",
+ "Ergonode\\Condition\\": "module/condition/src",
"Ergonode\\Segment\\": "module/segment/src",
"Ergonode\\Grid\\": "module/grid/src",
"Ergonode\\Channel\\": "module/channel/src",
@@ -136,6 +137,7 @@
"Ergonode\\AttributeUnit\\Tests\\": "module/attribute-unit/tests",
"Ergonode\\AttributeDate\\Tests\\": "module/attribute-date/tests",
"Ergonode\\AttributeImage\\Tests\\": "module/attribute-image/tests",
+ "Ergonode\\Condition\\Tests\\": "module/condition/tests",
"Ergonode\\Segment\\Tests\\": "module/segment/tests",
"Ergonode\\Grid\\Tests\\": "module/grid/tests",
"Ergonode\\Channel\\Tests\\": "module/channel/tests",
diff --git a/config/bundles.php b/config/bundles.php
index b877aa6b7..5ef63ed0d 100644
--- a/config/bundles.php
+++ b/config/bundles.php
@@ -25,6 +25,8 @@
Ergonode\Importer\ErgonodeImporterBundle::class => ['all' => true],
Ergonode\Reader\ErgonodeReaderBundle::class => ['all' => true],
Ergonode\Transformer\ErgonodeTransformerBundle::class => ['all' => true],
+ Ergonode\Condition\ErgonodeConditionBundle::class => ['all' => true],
+ Ergonode\Segment\ErgonodeSegmentBundle::class => ['all' => true],
Ergonode\Category\ErgonodeCategoryBundle::class => ['all' => true],
Ergonode\CategoryTree\ErgonodeCategoryTreeBundle::class => ['all' => true],
Ergonode\Product\ErgonodeProductBundle::class => ['all' => true],
@@ -43,6 +45,6 @@
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
Vich\UploaderBundle\VichUploaderBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
- Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
+ Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
];
diff --git a/config/packages/nelmio_api_doc.yaml b/config/packages/nelmio_api_doc.yaml
index bfa6e20a0..6871b2ffb 100644
--- a/config/packages/nelmio_api_doc.yaml
+++ b/config/packages/nelmio_api_doc.yaml
@@ -98,6 +98,40 @@ nelmio_api_doc:
type: boolean
required: true
example: true
+ account_upd:
+ type: object
+ properties:
+ firstName:
+ type: string
+ required: true
+ description: User first name
+ example: Jon
+ lastName:
+ type: string
+ required: true
+ description: User last name
+ example: Dove
+ language:
+ type: string
+ required: true
+ description: User language
+ example: EN
+ password:
+ type: string
+ required: true
+ example: 12345678
+ passwordRepeat:
+ type: string
+ equired: true
+ example: 12345678
+ roleId:
+ type: string
+ required: true
+ example: 86800536-0f2a-4920-9291-f35fdcea3839
+ isActive:
+ type: boolean
+ required: true
+ example: true
status:
type: object
properties:
@@ -210,6 +244,15 @@ nelmio_api_doc:
example:
DE: Name DE
EN: Name EN
+ category_upd:
+ type: object
+ properties:
+ name:
+ type: object
+ description: category name
+ example:
+ DE: Name DE
+ EN: Name EN
product:
type: object
properties:
@@ -228,6 +271,15 @@ nelmio_api_doc:
type: string
required: false
description: Lista id kategorii
+ product_upd:
+ type: object
+ properties:
+ categortyIds:
+ type: array
+ items:
+ type: string
+ required: false
+ description: Lista id kategorii
template:
type: object
properties:
@@ -269,7 +321,7 @@ nelmio_api_doc:
$ref: "#/definitions/translation"
example:
key: key_1
- translation:
+ value:
PL: Option PL 1
EN: Option EN 1
attribute_parameters:
@@ -281,13 +333,29 @@ nelmio_api_doc:
description: Additional format information (If used by attribute)
example: YYYY-MM-DDDD
segment:
- type: object
+ type: 'object'
properties:
- name:
- type: string
+ condition_set_id:
+ type: 'string'
required: true
- description: segment name
- example: segment name
+ description: 'Condition set ID'
+ code:
+ type: 'string'
+ required: true
+ description: 'Segment unique code'
+ name:
+ $ref: "#/definitions/translation"
+ description:
+ $ref: "#/definitions/translation"
+ example:
+ condition_set_id: 'd1b9b64a-fef6-440c-9560-cf73daa4b4d6'
+ code: 'code'
+ name:
+ PL: 'Nazwa'
+ EN: 'Name'
+ description:
+ PL: 'Opis'
+ EN: 'Description'
languages_req:
type: object
properties:
@@ -416,7 +484,6 @@ nelmio_api_doc:
items:
type: 'string'
example: 'Error message'
-
credentials:
type: object
properties:
@@ -451,6 +518,28 @@ nelmio_api_doc:
description: List of role privileges
example:
[ ATTRIBUTE_CREATE, ATTRIBUTE_READ, ATTRIBUTE_UPDATE, ATTRIBUTE_DELETE]
+ conditionset_create:
+ type: 'object'
+ properties:
+ code:
+ type: 'string'
+ required: true
+ description: 'Condition code'
+ example: 'CONDITION_CODE'
+ name:
+ $ref: '#/definitions/translation'
+ description:
+ $ref: '#/definitions/translation'
+ conditionset_update:
+ type: 'object'
+ properties:
+ name:
+ $ref: '#/definitions/translation'
+ description:
+ $ref: '#/definitions/translation'
+ conditions:
+ type: 'array'
+ example: []
authentication:
type: object
properties:
diff --git a/features/account.feature b/features/account.feature
index 734937480..24a75ee59 100644
--- a/features/account.feature
+++ b/features/account.feature
@@ -27,6 +27,107 @@ Feature: Account module
Given I request "/api/v1/EN/roles" using HTTP POST
Then unauthorized response is received
+ Scenario: Create role (without name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "description": "Test role",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create role (without description)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create role (without privileges)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "description": "Test role"
+ }
+ """
+ When I request "/api/v1/EN/roles" using HTTP POST
+ Then created response is received
+
+ Scenario: Create role (wrong parameter - name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "test": "Test role (@@random_uuid@@)",
+ "description": "Test role",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create role (empty name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "",
+ "description": "Test role",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create role (empty description)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "description": "",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create role (empty privilages)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "description": "Test role",
+ "privileges": []
+ }
+ """
+ When I request "/api/v1/EN/roles" using HTTP POST
+ Then created response is received
+
+ Scenario: Create role (no existing privilages)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "description": "Test role",
+ "privileges": ["test", "test2"]
+ }
+ """
+ When I request "/api/v1/EN/roles" using HTTP POST
+ Then validation error response is received
+
Scenario: Create role for delete
Given current authentication token
Given the request body is:
@@ -56,134 +157,722 @@ Feature: Account module
When I request "/api/v1/EN/roles/@@static_uuid@@" using HTTP DELETE
Then not found response is received
- Scenario: Update role
+ Scenario: Update role
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role 2 (@@random_uuid@@)",
+ "description": "Test role 2",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update role (not authorized)
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then unauthorized response is received
+
+ Scenario: Update role (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/roles/@@static_uuid@@" using HTTP PUT
+ Then not found response is received
+
+ Scenario: Update role (without name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "description": "Test role",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update role (without description)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update role (without privileges)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "description": "Test role"
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update role (wrong parameter - name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "test": "Test role (@@random_uuid@@)",
+ "description": "Test role",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update role (empty name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "",
+ "description": "Test role",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update role (empty description)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "description": "",
+ "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_UPDATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update role (empty privilages)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "description": "Test role",
+ "privileges": []
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update role (no existing privilages)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "Test role (@@random_uuid@@)",
+ "description": "Test role",
+ "privileges": ["test", "test2"]
+ }
+ """
+ When I request "/api/v1/EN/roles/@role@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Get role
+ Given current authentication token
+ When I request "/api/v1/EN/roles/@role@" using HTTP GET
+ Then the response code is 200
+ And the JSON object contains keys "id"
+
+ Scenario: Get role (not authorized)
+ When I request "/api/v1/EN/roles/@role@" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get role (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/roles/@@static_uuid@@" using HTTP GET
+ Then not found response is received
+
+ Scenario: Get roles
+ Given current authentication token
+ When I request "/api/v1/EN/roles" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get roles (not authorized)
+ When I request "/api/v1/EN/roles" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get roles (order by name)
+ Given current authentication token
+ When I request "/api/v1/EN/roles?field=name" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get roles (order by description)
+ Given current authentication token
+ When I request "/api/v1/EN/roles?field=description" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get roles (order by users_count)
+ Given current authentication token
+ When I request "/api/v1/EN/roles?field=users_count" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get roles (filter by name)
+ Given current authentication token
+ When I request "/api/v1/EN/roles?limit=25&offset=0&filter=name%3Dsuper" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get roles (filter by description)
+ Given current authentication token
+ When I request "/api/v1/EN/roles?limit=25&offset=0&filter=description%3DManage" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get roles (filter by user_count)
+ Given current authentication token
+ When I request "/api/v1/EN/roles?limit=25&offset=0&filter=users_count%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get roles (not authorized)
+ When I request "/api/v1/EN/roles" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Create user
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then created response is received
+ And remember response param "id" as "user"
+
+ Scenario: Create user (not authorized)
+ Given I request "/api/v1/EN/accounts" using HTTP POST
+ Then unauthorized response is received
+
+ Scenario: Create user (no email)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (empty email)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (no firsName)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (empty firsName)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (no lastName)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (empty lastName)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (no language)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (empty language)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (no password)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (empty password)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": "",
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (no passwordRepeat)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (empty passwordRepeat)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": "",
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (no roleId)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (empty roleId)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": ""
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (not UUID roleID)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "test"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create user (random UUID roleID)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "email": "@@random_uuid@@@ergonode.com",
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@@random_uuid@@"
+ }
+ """
+ When I request "/api/v1/EN/accounts" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Delete role (with conflict)
+ Given current authentication token
+ When I request "/api/v1/EN/roles/@role@" using HTTP DELETE
+ Then the response code is 409
+ And the JSON object contains keys "code,message"
+
+ Scenario: Update user
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "firstName": "Test (changed)",
+ "lastName": "Test (changed)",
+ "language": "EN",
+ "password": 123456789,
+ "passwordRepeat": 123456789,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update user (not authorized)
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then unauthorized response is received
+
+ Scenario: Update user (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts/@@static_uuid@@" using HTTP PUT
+ Then not found response is received
+
+ Scenario: Update user (no firsName)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update user (empty firsName)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "firstName": "",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update user (no lastName)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update user (empty lastName)
Given current authentication token
Given the request body is:
"""
{
- "name": "Test role 2 (@@random_uuid@@)",
- "description": "Test role 2",
- "privileges": ["ATTRIBUTE_CREATE","ATTRIBUTE_READ","ATTRIBUTE_DELETE"]
+ "firstName": "Test",
+ "lastName": "",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
}
"""
- When I request "/api/v1/EN/roles/@role@" using HTTP PUT
- Then empty response is received
-
- Scenario: Update role (not authorized)
- When I request "/api/v1/EN/roles/@role@" using HTTP PUT
- Then unauthorized response is received
-
- Scenario: Update role (not found)
- Given current authentication token
- When I request "/api/v1/EN/roles/@@static_uuid@@" using HTTP PUT
- Then not found response is received
-
- Scenario: Get role
- Given current authentication token
- When I request "/api/v1/EN/roles/@role@" using HTTP GET
- Then the response code is 200
- And the JSON object contains keys "id"
-
- Scenario: Get role (not authorized)
- When I request "/api/v1/EN/roles/@role@" using HTTP GET
- Then unauthorized response is received
-
- Scenario: Get role (not found)
- Given current authentication token
- When I request "/api/v1/EN/roles/@@static_uuid@@" using HTTP GET
- Then not found response is received
-
- Scenario: Get roles
- Given current authentication token
- When I request "/api/v1/EN/roles" using HTTP GET
- Then grid response is received
-
- Scenario: Get roles (order by name)
- Given current authentication token
- When I request "/api/v1/EN/roles?field=name" using HTTP GET
- Then grid response is received
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
- Scenario: Get roles (order by description)
+ Scenario: Update user (no language)
Given current authentication token
- When I request "/api/v1/EN/roles?field=description" using HTTP GET
- Then grid response is received
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
- Scenario: Get roles (order by users_count)
+ Scenario: Update user (empty language)
Given current authentication token
- When I request "/api/v1/EN/roles?field=users_count" using HTTP GET
- Then grid response is received
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
- Scenario: Get roles (filter by name)
+ Scenario: Update user (no password)
Given current authentication token
- When I request "/api/v1/EN/roles?limit=25&offset=0&filter=name%3Dsuper" using HTTP GET
- Then grid response is received
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
- Scenario: Get roles (filter by description)
+ Scenario: Update user (empty password)
Given current authentication token
- When I request "/api/v1/EN/roles?limit=25&offset=0&filter=description%3DManage" using HTTP GET
- Then grid response is received
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": "",
+ "passwordRepeat": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
- Scenario: Get roles (filter by user_count)
+ Scenario: Update user (no passwordRepeat)
Given current authentication token
- When I request "/api/v1/EN/roles?limit=25&offset=0&filter=users_count%3D1" using HTTP GET
- Then grid response is received
-
- Scenario: Get roles (not authorized)
- When I request "/api/v1/EN/roles" using HTTP GET
- Then unauthorized response is received
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "roleId": "@role@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
- Scenario: Create user
+ Scenario: Update user (empty passwordRepeat)
Given current authentication token
Given the request body is:
"""
{
- "email": "@@random_uuid@@@ergonode.com",
"firstName": "Test",
"lastName": "Test",
"language": "EN",
"password": 12345678,
- "passwordRepeat": 12345678,
+ "passwordRepeat": "",
"roleId": "@role@"
}
"""
- When I request "/api/v1/EN/accounts" using HTTP POST
- Then created response is received
- And remember response param "id" as "user"
-
- Scenario: Create user (not authorized)
- Given I request "/api/v1/EN/accounts" using HTTP POST
- Then unauthorized response is received
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
- Scenario: Delete role (with conflict)
+ Scenario: Update user (no roleId)
Given current authentication token
- When I request "/api/v1/EN/roles/@role@" using HTTP DELETE
- Then the response code is 409
- And the JSON object contains keys "code,message"
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
- Scenario: Update user
+ Scenario: Update user (empty roleId)
Given current authentication token
Given the request body is:
"""
{
- "firstName": "Test (changed)",
- "lastName": "Test (changed)",
+ "firstName": "Test",
+ "lastName": "Test",
"language": "EN",
- "password": 123456789,
- "passwordRepeat": 123456789,
- "roleId": "@role@"
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": ""
}
"""
When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
- Then empty response is received
+ Then validation error response is received
- Scenario: Update user (not authorized)
+ Scenario: Update user (not UUID roleID)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "test"
+ }
+ """
When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
- Then unauthorized response is received
+ Then validation error response is received
- Scenario: Update user (not found)
+ Scenario: Update user (random UUID roleID)
Given current authentication token
- When I request "/api/v1/EN/accounts/@@static_uuid@@" using HTTP PUT
- Then not found response is received
+ Given the request body is:
+ """
+ {
+ "firstName": "Test",
+ "lastName": "Test",
+ "language": "EN",
+ "password": 12345678,
+ "passwordRepeat": 12345678,
+ "roleId": "@@random_uuid@@"
+ }
+ """
+ When I request "/api/v1/EN/accounts/@user@" using HTTP PUT
+ Then validation error response is received
Scenario: Get user
Given current authentication token
@@ -382,8 +1071,88 @@ Feature: Account module
When I request "/api/v1/EN/accounts/log" using HTTP GET
Then unauthorized response is received
- # TODO Check role create action with all incorrect possibilities
- # TODO Check role update action with all incorrect possibilities
- # TODO Check user create action with all incorrect possibilities
- # TODO Check user update action with all incorrect possibilities
+ Scenario: Get accounts (order by id)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=id" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (order by email)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=email" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (order by first_name)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=first_name" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (order by last_name)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=last_name" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (order by language)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=language" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (order by role_id)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=role_id" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (order by is_active)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=is_active" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (order ASC)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=email&order=ASC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (order DESC)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?field=email&order=DESC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (filter by id)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?limit=25&offset=0&filter=id%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (filter by email)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?limit=25&offset=0&filter=email%3Dasd" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (filter by first_name)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?limit=25&offset=0&filter=first_name%3DCAT" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (filter by last_name)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?limit=25&offset=0&filter=last_name%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (filter by language)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?limit=25&offset=0&filter=language%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (filter by role_id)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?limit=25&offset=0&filter=role_id%3Dasd1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (filter by is_active)
+ Given current authentication token
+ When I request "/api/v1/EN/accounts?limit=25&offset=0&filter=last_name%3Dasd1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get accounts (not authorized)
+ When I request "/api/v1/EN/accounts" using HTTP GET
+ Then unauthorized response is received
+
# TODO Check user avatar change action with correct and incorrect file
diff --git a/features/bootstrap/AttributeContext.php b/features/bootstrap/AttributeContext.php
index 69e6bdedd..aaef6dd4d 100644
--- a/features/bootstrap/AttributeContext.php
+++ b/features/bootstrap/AttributeContext.php
@@ -38,11 +38,13 @@ public function gatherContexts(BeforeScenarioScope $scope): void
}
/**
- * @Then remember first attribute group as "attribute_group"
+ * @param string $key
+ *
+ * @Then remember first attribute group as :key
*/
- public function rememberFirstAttributeGroup(): void
+ public function rememberFirstAttributeGroup(string $key): void
{
$response = $this->apiContext->getLastResponseBody();
- $this->storageContext->add('attribute_group', $response[count($response)-1]->id);
+ $this->storageContext->add($key, $response[key($response)]->id);
}
}
diff --git a/features/category-tree.feature b/features/category-tree.feature
index 14ad73a46..6917de759 100644
--- a/features/category-tree.feature
+++ b/features/category-tree.feature
@@ -5,7 +5,7 @@ Feature: Category tree module
Given the request body is:
"""
{
- "code": "TREE_CAT_@@random_code@@",
+ "code": "TREE_@@random_code@@",
"name": {
"DE": "Test DE",
"EN": "Test EN"
@@ -20,7 +20,7 @@ Feature: Category tree module
When I request "/api/v1/EN/trees" using HTTP POST
Then unauthorized response is received
- Scenario: Create category for update
+ Scenario: Create category for update 1
Given current authentication token
Given the request body is:
"""
@@ -34,20 +34,105 @@ Feature: Category tree module
"""
When I request "/api/v1/EN/categories" using HTTP POST
Then created response is received
- And remember response param "id" as "tree_category"
+ And remember response param "id" as "category_1"
- Scenario: Update category tree
+ Scenario: Create category for update 2
Given current authentication token
Given the request body is:
- """
+ """
{
+ "code": "TREE_CAT_@@random_code@@",
"name": {
"DE": "Test DE",
"EN": "Test EN"
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories" using HTTP POST
+ Then created response is received
+ And remember response param "id" as "category_2"
+
+ Scenario: Create category tree (no Name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@"
+ }
+ """
+ When I request "/api/v1/EN/trees" using HTTP POST
+ Then created response is received
+
+ Scenario: Create category tree (empty Name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@",
+ "name": {
+ }
+ }
+ """
+ When I request "/api/v1/EN/trees" using HTTP POST
+ Then created response is received
+
+ Scenario: Create category tree (name with language with empty string value)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@",
+ "name": {
+ "DE": "",
+ "EN": "Test EN"
+ }
+ }
+ """
+ When I request "/api/v1/EN/trees" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create category tree (name with wrong language code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@",
+ "name": {
+ "test": "Test DE",
+ "EN": "Test EN"
+ }
+ }
+ """
+ When I request "/api/v1/EN/trees" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create category tree (name with no existing language code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@",
+ "name": {
+ "ZZ": "Test DE",
+ "EN": "Test EN"
+ }
+ }
+ """
+ When I request "/api/v1/EN/trees" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Update category tree
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
},
"categories": [
{
- "category_id": "@tree_category@",
+ "category_id": "@category_1@",
"childrens": []
}
]
@@ -65,6 +150,271 @@ Feature: Category tree module
When I request "/api/v1/EN/trees/@@static_uuid@@" using HTTP PUT
Then not found response is received
+ Scenario: Update category tree (no name field)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update category tree (empty name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update category tree (wrong parameter)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "test": {
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (wrong language code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "test": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (incorrect language code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "ZZ": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (no categories)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ }
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (incorrect category Id)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "test",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (empty categotry id)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (wrong categories key)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "test": "@category_1@",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (with childrens)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": [{"category_id":"@category_2@"}]
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update category tree (no childrens)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@"
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update category tree (with empty childrens category Id)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": [{"category_id":""}]
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (with empty childrens wrong key)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": [{"test":"@category_2@"}]
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category tree (empty translation)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "",
+ "EN": "Test EN (changed)"
+ },
+ "categories": [
+ {
+ "category_id": "@category_1@",
+ "childrens": []
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP PUT
+ Then validation error response is received
+
Scenario: Get category tree
Given current authentication token
When I request "/api/v1/EN/trees/@category_tree@" using HTTP GET
@@ -79,6 +429,20 @@ Feature: Category tree module
When I request "/api/v1/EN/trees/@@static_uuid@@" using HTTP GET
Then not found response is received
+ Scenario: Delete category tree (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/trees/@@static_uuid@@" using HTTP DELETE
+ Then not found response is received
+
+ Scenario: Delete category tree (not authorized)
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP DELETE
+ Then unauthorized response is received
+
+ Scenario: Delete category tree
+ Given current authentication token
+ When I request "/api/v1/EN/trees/@category_tree@" using HTTP DELETE
+ Then empty response is received
+
Scenario: Get category trees (order by name)
Given current authentication token
When I request "/api/v1/EN/trees?field=name" using HTTP GET
@@ -88,6 +452,47 @@ Feature: Category tree module
When I request "/api/v1/EN/trees" using HTTP GET
Then unauthorized response is received
- # TODO Check add category to category tree action
- # TODO Check create category tree action with all incorrect possibilities
- # TODO Check update category tree action with all incorrect possibilities
+ Scenario: Get category trees
+ Given current authentication token
+ When I request "/api/v1/EN/trees" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get category trees (order by id)
+ Given current authentication token
+ When I request "/api/v1/EN/trees?field=id" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get category trees (order by code)
+ Given current authentication token
+ When I request "/api/v1/EN/trees?field=code" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get category trees (order by name)
+ Given current authentication token
+ When I request "/api/v1/EN/trees?field=name" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get category trees (order ASC)
+ Given current authentication token
+ When I request "/api/v1/EN/trees?field=name&order=ASC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get category trees (order DESC)
+ Given current authentication token
+ When I request "/api/v1/EN/trees?field=name&order=DESC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get category trees (filter by name)
+ Given current authentication token
+ When I request "/api/v1/EN/trees?limit=25&offset=0&filter=name%3Dasd" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get category trees (filter by code)
+ Given current authentication token
+ When I request "/api/v1/EN/trees?limit=25&offset=0&filter=code%3DCAT" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get category trees (filter by name)
+ Given current authentication token
+ When I request "/api/v1/EN/trees?limit=25&offset=0&filter=name%3D1" using HTTP GET
+ Then grid response is received
diff --git a/features/category.feature b/features/category.feature
index 084b0065c..951ce3e1d 100644
--- a/features/category.feature
+++ b/features/category.feature
@@ -20,6 +20,75 @@ Feature: Category module
When I request "/api/v1/EN/categories" using HTTP POST
Then unauthorized response is received
+ Scenario: Create category (no Name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@"
+ }
+ """
+ When I request "/api/v1/EN/categories" using HTTP POST
+ Then created response is received
+
+ Scenario: Create category (empty Name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@",
+ "name": {
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories" using HTTP POST
+ Then created response is received
+
+ Scenario: Create category (name with language with empty string value)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@",
+ "name": {
+ "DE": "",
+ "EN": "Test EN"
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create category (name with wrong language code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@",
+ "name": {
+ "test": "Test DE",
+ "EN": "Test EN"
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create category (name with no existing language code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "TREE_CAT_@@random_code@@",
+ "name": {
+ "ZZ": "Test DE",
+ "EN": "Test EN"
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories" using HTTP POST
+ Then validation error response is received
+
Scenario: Update category
Given current authentication token
Given the request body is:
@@ -43,6 +112,72 @@ Feature: Category module
When I request "/api/v1/EN/categories/@@static_uuid@@" using HTTP PUT
Then not found response is received
+ Scenario: Update category (empty name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories/@category@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update category (wrong parameter)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "test": {
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories/@category@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category (wrong language code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "test": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories/@category@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category (incorrect language code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "ZZ": "Test DE (changed)",
+ "EN": "Test EN (changed)"
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories/@category@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update category (empty translation)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "DE": "",
+ "EN": "Test EN (changed)"
+ }
+ }
+ """
+ When I request "/api/v1/EN/categories/@category@" using HTTP PUT
+ Then validation error response is received
+
Scenario: Get category
Given current authentication token
When I request "/api/v1/EN/categories/@category@" using HTTP GET
@@ -77,6 +212,16 @@ Feature: Category module
When I request "/api/v1/EN/categories?field=sequence" using HTTP GET
Then grid response is received
+ Scenario: Get categories (order ASC)
+ Given current authentication token
+ When I request "/api/v1/EN/categories?field=name&order=ASC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get categories (order DESC)
+ Given current authentication token
+ When I request "/api/v1/EN/categories?field=name&order=DESC" using HTTP GET
+ Then grid response is received
+
Scenario: Get categories (filter by sequence)
Given current authentication token
When I request "/api/v1/EN/categories?limit=25&offset=0&filter=sequence%3D1" using HTTP GET
@@ -100,6 +245,3 @@ Feature: Category module
Scenario: Get categories (not authorized)
When I request "/api/v1/EN/categories" using HTTP GET
Then unauthorized response is received
-
- # TODO Check create category action with all incorrect possibilities
- # TODO Check update category action with all incorrect possibilities
diff --git a/features/condition.feature b/features/condition.feature
new file mode 100644
index 000000000..a019f4c27
--- /dev/null
+++ b/features/condition.feature
@@ -0,0 +1,733 @@
+Feature: Condition
+
+ Scenario: Get conditions dicitionary (not authorized)
+ When I request "/api/v1/EN/dictionary/conditions" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get conditions dicitionary
+ Given current authentication token
+ When I request "/api/v1/EN/dictionary/conditions" using HTTP GET
+ Then the response code is 200
+
+ Scenario: Get condition (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/conditions/asd" using HTTP GET
+ Then not found response is received
+
+ Scenario: Get numeric condition (not authorized)
+ When I request "/api/v1/EN/conditions/NUMERIC_ATTRIBUTE_VALUE_CONDITION" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get numeric condition
+ Given current authentication token
+ When I request "/api/v1/EN/conditions/NUMERIC_ATTRIBUTE_VALUE_CONDITION" using HTTP GET
+ Then the response code is 200
+
+ Scenario: Get option condition (not authorized)
+ When I request "/api/v1/EN/conditions/OPTION_ATTRIBUTE_VALUE_CONDITION" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get option condition
+ Given current authentication token
+ When I request "/api/v1/EN/conditions/OPTION_ATTRIBUTE_VALUE_CONDITION" using HTTP GET
+ Then the response code is 200
+
+ Scenario: Get attribute exists condition (not authorized)
+ When I request "/api/v1/EN/conditions/ATTRIBUTE_EXISTS_CONDITION" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get attribute exists condition
+ Given current authentication token
+ When I request "/api/v1/EN/conditions/ATTRIBUTE_EXISTS_CONDITION" using HTTP GET
+ Then the response code is 200
+
+ Scenario: Get text condition (not authorized)
+ When I request "/api/v1/EN/conditions/TEXT_ATTRIBUTE_VALUE_CONDITION" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get text condition
+ Given current authentication token
+ When I request "/api/v1/EN/conditions/TEXT_ATTRIBUTE_VALUE_CONDITION" using HTTP GET
+ Then the response code is 200
+
+ Scenario: Get attribute groups dictionary
+ Given current authentication token
+ When I request "/api/v1/EN/dictionary/attributes/groups" using HTTP GET
+ Then the response code is 200
+ And remember first attribute group as "condition_attribute_group"
+
+ Scenario: Create text attribute
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "CONDITION_@@random_code@@",
+ "type": "TEXT",
+ "label": {"PL": "Atrybut tekstowy", "EN": "Text attribute"},
+ "groups": ["@condition_attribute_group@"],
+ "parameters": []
+ }
+ """
+ When I request "/api/v1/EN/attributes" using HTTP POST
+ Then created response is received
+ And remember response param "id" as "condition_text_attribute"
+
+ Scenario: Create condition set (not authorized)
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then unauthorized response is received
+
+ Scenario: Create condition set
+ Given current authentication token
+ Given remember param "condition_set_code" with value "CONDITION_@@random_uuid@@"
+ Given the request body is:
+ """
+ {
+ "code": "@condition_set_code@",
+ "name": {
+ "PL": "Zbiór warunków",
+ "EN": "Condition set"
+ },
+ "description": {
+ "PL": "Opis do zbioru warunków",
+ "EN": "Condition set description"
+ }
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then created response is received
+ And remember response param "id" as "conditionset"
+
+ Scenario: Create condition set (not unique code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "@condition_set_code@"
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create condition set (without description)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "CONDITION_2_@@random_uuid@@",
+ "name": {
+ "PL": "Zbiór warunków",
+ "EN": "Condition set"
+ }
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then created response is received
+
+ Scenario: Create condition set (only code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "CONDITION_3_@@random_uuid@@"
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then created response is received
+
+ Scenario: Create condition set (without code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "PL": "Zbiór warunków",
+ "EN": "Condition set"
+ }
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create condition set (short name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "CONDITION_@@random_uuid@@",
+ "name": {
+ "PL": "Z",
+ "EN": "C"
+ }
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create condition set (long name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "CONDITION_@@random_uuid@@",
+ "name": {
+ "PL": "ceqvqEO1AsN92sTa0yn6vtYKc4Wkegfw7P5IQO34hhmtNWPYUKZXF8npJg55qGTUG4unmQPlaqRRvAzuaQLST2RP030V9gbqx5gekGPRnRqwVi03Cs0SDvmZe0jmMNm4lOm2w02kyHA1wtMapqgv3GGtQFTsXBegVFFu3aGlpZyfyWRl4TLSm4rTWMSRC89u2A3mxEAWv1AXn64ouBL4AoqwRGomgeU58ewRWiEwPv55BMmMfa0SxQOfiplqksmQ",
+ "EN": "Condition set"
+ }
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create condition set (long description)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "CONDITION_@@random_uuid@@",
+ "description": {
+ "PL": "Opis do zbioru warunków",
+ "EN": "ceqvqEO1AsN92sTa0yn6vtYKc4Wkegfw7P5IQO34hhmtNWPYUKZXF8npJg55qGTUG4unmQPlaqRRvAzuaQLST2RP030V9gbqx5gekGPRnRqwVi03Cs0SDvmZe0jmMNm4lOm2w02kyHA1wtMapqgv3GGtQFTsXBegVFFu3aGlpZyfyWRl4TLSm4rTWMSRC89u2A3mxEAWv1AXn64ouBL4AoqwRGomgeU58ewRWiEwPv55BMmMfa0SxQOfiplqksmQ"
+ }
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Update condition set
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "PL": "Zbiór warunków (changed)",
+ "EN": "Condition set (changed)"
+ },
+ "description": {
+ "PL": "Opis do zbioru warunków (changed)",
+ "EN": "Condition set description (changed)"
+ },
+ "conditions": [
+ {
+ "type": "ATTRIBUTE_EXISTS_CONDITION",
+ "attribute": "@condition_text_attribute@"
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update condition set (without conditions)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "PL": "Zbiór warunków (changed)",
+ "EN": "Condition set (changed)"
+ },
+ "description": {
+ "PL": "Opis do zbioru warunków (changed)",
+ "EN": "Condition set description (changed)"
+ }
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (without name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "description": {
+ "PL": "Opis do zbioru warunków (changed)",
+ "EN": "Condition set description (changed)"
+ },
+ "conditions": [
+ {
+ "type": "ATTRIBUTE_EXISTS_CONDITION",
+ "attribute": "@condition_text_attribute@"
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update condition set (without description)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "PL": "Zbiór warunków (changed)",
+ "EN": "Condition set (changed)"
+ },
+ "conditions": [
+ {
+ "type": "ATTRIBUTE_EXISTS_CONDITION",
+ "attribute": "@condition_text_attribute@"
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update condition set (attribute not exists)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "ATTRIBUTE_EXISTS_CONDITION",
+ "attribute": "@@static_uuid@@"
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (attribute not uuid)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "ATTRIBUTE_EXISTS_CONDITION",
+ "attribute": "abc"
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (numeric attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "operator": "=",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update condition set (numeric attribute with not uuid attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "abc",
+ "operator": "=",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (numeric attribute without value)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "operator": "="
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (numeric attribute without operator)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (numeric attribute invalid operator)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "operator": "123",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (numeric attribute without attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "operator": "=",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (numeric attribute with not existing attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@@static_uuid@@",
+ "operator": "=",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (option attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "OPTION_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update condition set (option attribute with not uuid attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "OPTION_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "abc",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (option attribute without value)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "OPTION_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@"
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (option attribute without attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (option attribute with not existing attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "NUMERIC_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@@static_uuid@@",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (text attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "TEXT_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "operator": "=",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update condition set (text attribute with not uuid attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "TEXT_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "abc",
+ "operator": "=",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (text attribute without value)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "TEXT_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "operator": "="
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (text attribute without operator)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "TEXT_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (text attribute invalid operator)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "TEXT_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@condition_text_attribute@",
+ "operator": "123",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (text attribute without attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "TEXT_ATTRIBUTE_VALUE_CONDITION",
+ "operator": "=",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update condition set (text attribute with not existing attribute)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "conditions": [
+ {
+ "type": "TEXT_ATTRIBUTE_VALUE_CONDITION",
+ "attribute": "@@static_uuid@@",
+ "operator": "=",
+ "value": 123
+ }
+ ]
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Get condition set (not authorized)
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get condition set (not found)
+ Given current authentication token
+ Given I request "/api/v1/EN/conditionsets/@@static_uuid@@" using HTTP GET
+ Then not found response is received
+
+ Scenario: Get condition set
+ Given current authentication token
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP GET
+ Then the response code is 200
+
+ Scenario: Delete condition set (not authorized)
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP DELETE
+ Then unauthorized response is received
+
+ Scenario: Delete condition set (not found)
+ Given current authentication token
+ Given I request "/api/v1/EN/conditionsets/@@static_uuid@@" using HTTP DELETE
+ Then not found response is received
+
+ Scenario: Delete condition set
+ Given current authentication token
+ Given I request "/api/v1/EN/conditionsets/@conditionset@" using HTTP DELETE
+ Then empty response is received
+
+ Scenario: Get condition sets
+ Given current authentication token
+ When I request "/api/v1/EN/conditionsets" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get condition sets (not authorized)
+ When I request "/api/v1/EN/conditionsets" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get condition sets (order by code)
+ Given current authentication token
+ When I request "/api/v1/EN/conditionsets?field=code" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get condition sets (order by name)
+ Given current authentication token
+ When I request "/api/v1/EN/conditionsets?field=name" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get condition sets (order by description)
+ Given current authentication token
+ When I request "/api/v1/EN/conditionsets?field=description" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get condition sets (filter by code)
+ Given current authentication token
+ When I request "/api/v1/EN/conditionsets?limit=25&offset=0&filter=code%3Dsuper" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get condition sets (filter by name)
+ Given current authentication token
+ When I request "/api/v1/EN/conditionsets?limit=25&offset=0&filter=name%3Dsuper" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get condition sets (filter by description)
+ Given current authentication token
+ When I request "/api/v1/EN/conditionsets?limit=25&offset=0&filter=description%3Dsuper" using HTTP GET
+ Then grid response is received
+
+ Scenario: Create condition set (for conflict delete)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "CONDITION_DELETE_@@random_uuid@@"
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then created response is received
+ And remember response param "id" as "conditionset_delete"
+
+ Scenario: Create segment (for relation to condition set conflict delete)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "SEG_REL_@@random_code@@",
+ "condition_set_id": "@conditionset_delete@"
+ }
+ """
+ When I request "/api/v1/EN/segments" using HTTP POST
+ Then created response is received
+
+ Scenario: Delete condition set (with conflict)
+ Given current authentication token
+ Given I request "/api/v1/EN/conditionsets/@conditionset_delete@" using HTTP DELETE
+ Then conflict response is received
diff --git a/features/core.feature b/features/core.feature
index c7d47736d..57affe647 100644
--- a/features/core.feature
+++ b/features/core.feature
@@ -8,3 +8,81 @@ Feature: Core module
Scenario: Get languages (not authorized)
When I request "/api/v1/EN/dictionary/languages" using HTTP GET
Then unauthorized response is received
+
+ Scenario: Get translation language (not authorized)
+ When I request "/api/v1/EN/languages/EN" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get translation language
+ Given current authentication token
+ When I request "/api/v1/EN/languages/EN" using HTTP GET
+ Then the response code is 200
+
+ Scenario: Get translation language (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/languages/ZZ" using HTTP GET
+ Then not found response is received
+
+ Scenario: Update language (not authorized)
+ When I request "/api/v1/EN/languages" using HTTP PUT
+ Then unauthorized response is received
+
+ Scenario: Update language
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "collection":[
+ {
+ "code":"EN",
+ "active":true
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/languages" using HTTP PUT
+ Then the response code is 204
+
+ Scenario: Update language (wrong active - bad request)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "collection":[
+ {
+ "code":"EN",
+ "active":"test"
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/languages" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update language (wrong code - bad request)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "collection":[
+ {
+ "code":"ZZ",
+ "active":true
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/languages" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update language (wrong structure)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "ZZ",
+ "active": true
+ }
+ """
+ When I request "/api/v1/EN/languages" using HTTP PUT
+ Then validation error response is received
diff --git a/features/designer.feature b/features/designer.feature
index 99f4e84af..a777dcd59 100644
--- a/features/designer.feature
+++ b/features/designer.feature
@@ -66,6 +66,126 @@ Feature: Designer module
When I request "/api/v1/EN/templates" using HTTP POST
Then unauthorized response is received
+ Scenario: Create template (wrong image)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "test",
+ "elements": [
+ {
+ "position": {"x": 0, "y": 0},
+ "size": {"width": 2, "height": 1},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "@template_text_attribute@",
+ "required": true
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create template (wrong position)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "@template_image_attribute@",
+ "elements": [
+ {
+ "position": {"x": "test", "y": 0},
+ "size": {"width": 2, "height": 1},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "@template_text_attribute@",
+ "required": true
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create template (wrong size)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "@template_image_attribute@",
+ "elements": [
+ {
+ "position": {"x": 0, "y": 0},
+ "size": {"width": "test", "height": 1},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "@template_text_attribute@",
+ "required": true
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create template (wrong attribute_id)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "@template_image_attribute@",
+ "elements": [
+ {
+ "position": {"x": 0, "y": 0},
+ "size": {"width": "test", "height": 1},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "test",
+ "required": true
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create template (wrong required)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "@template_image_attribute@",
+ "elements": [
+ {
+ "position": {"x": 0, "y": 0},
+ "size": {"width": 2, "height": 1},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "@template_text_attribute@",
+ "required": "test"
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates" using HTTP POST
+ Then validation error response is received
+
Scenario: Update template
Given current authentication token
Given the request body is:
@@ -99,6 +219,126 @@ Feature: Designer module
When I request "/api/v1/EN/templates/@@static_uuid@@" using HTTP PUT
Then not found response is received
+ Scenario: Update template (wrong image)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "test",
+ "elements": [
+ {
+ "position": {"x": 10, "y": 10},
+ "size": {"width": 2, "height": 2},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "@template_text_attribute@",
+ "required": true
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates/@template@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update template (wrong position)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "@template_image_attribute@",
+ "elements": [
+ {
+ "position": {"x": "test", "y": 10},
+ "size": {"width": 2, "height": 2},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "@template_text_attribute@",
+ "required": true
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates/@template@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update template (wrong size)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "@template_image_attribute@",
+ "elements": [
+ {
+ "position": {"x": 10, "y": 10},
+ "size": {"width": "test", "height": 2},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "@template_text_attribute@",
+ "required": true
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates/@template@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update template (wrong attribute_id)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "@template_image_attribute@",
+ "elements": [
+ {
+ "position": {"x": 10, "y": 10},
+ "size": {"width": 2, "height": 2},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "test",
+ "required": true
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates/@template@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update template (wrong required)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": "@@random_md5@@",
+ "image": "@template_image_attribute@",
+ "elements": [
+ {
+ "position": {"x": 10, "y": 10},
+ "size": {"width": "test", "height": 2},
+ "variant": "attribute",
+ "type": "text",
+ "properties": {
+ "attribute_id": "@template_text_attribute@",
+ "required": "test"
+ }
+ }
+ ]
+ }
+ """
+ When I request "/api/v1/EN/templates/@template@" using HTTP PUT
+ Then validation error response is received
+
Scenario: Delete template
Given current authentication token
When I request "/api/v1/EN/templates/@template@" using HTTP DELETE
@@ -127,6 +367,65 @@ Feature: Designer module
When I request "/api/v1/EN/templates/@@static_uuid@@" using HTTP GET
Then not found response is received
+ Scenario: Get templates
+ Given current authentication token
+ When I request "/api/v1/EN/templates" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (not authorized)
+ When I request "/api/v1/EN/templates" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get templates (order by id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?field=id" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (order by name)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?field=name" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (order by image_id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?field=image_id" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (order by group_id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?field=group_id" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (order ASC)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?field=name&order=ASC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (order DESC)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?field=name&order=DESC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (filter by id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?limit=25&offset=0&filter=id%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (filter by name)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?limit=25&offset=0&filter=name%3Dasd" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (filter by image_id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?limit=25&offset=0&filter=image_id%3Dasd" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates (filter by group_id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates?limit=25&offset=0&filter=group_id%3D4fbba5a0-61c7-5dc8-ba1b-3314f398bfa2" using HTTP GET
+ Then grid response is received
+
Scenario: Get template groups
Given current authentication token
When I request "/api/v1/EN/templates/groups" using HTTP GET
@@ -136,6 +435,46 @@ Feature: Designer module
When I request "/api/v1/EN/templates/groups" using HTTP GET
Then unauthorized response is received
+ Scenario: Get templates groups (order by id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/groups?field=id" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates groups (order by name)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/groups?field=name" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates groups (order by custom)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/groups?field=custom" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates groups (order ASC)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/groups?field=name&order=ASC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates groups (order DESC)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/groups?field=name&order=DESC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates groups (filter by id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/groups?limit=25&offset=0&filter=id%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates groups (filter by name)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/groups?limit=25&offset=0&filter=name%3Dasd" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates groups (filter by custom)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/groups?limit=25&offset=0&filter=custom%3Dasd" using HTTP GET
+ Then grid response is received
+
Scenario: Get template types
Given current authentication token
When I request "/api/v1/EN/templates/types" using HTTP GET
@@ -145,17 +484,89 @@ Feature: Designer module
When I request "/api/v1/EN/templates/types" using HTTP GET
Then unauthorized response is received
- Scenario: Get templates
+
+ Scenario: Get templates types (order by type)
Given current authentication token
- When I request "/api/v1/EN/templates" using HTTP GET
- Then the response code is 200
+ When I request "/api/v1/EN/templates/types?field=type" using HTTP GET
+ Then grid response is received
- Scenario: Get templates (not authorized)
- When I request "/api/v1/EN/templates" using HTTP GET
- Then unauthorized response is received
+ Scenario: Get templates types (order by variant)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?field=variant" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (order by label)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?field=label" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (order by min_width)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?field=min_width" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (order by min_height)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?field=min_height" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (order by max_width)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?field=max_width" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (order by max_height)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?field=max_height" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (order ASC)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?field=type&order=ASC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (order DESC)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?field=type&order=DESC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (filter by id)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?limit=25&offset=0&filter=id%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (filter by type)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?limit=25&offset=0&filter=type%3Dasd" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (filter by variant)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?limit=25&offset=0&filter=variant%3Dasd" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (filter by label)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?limit=25&offset=0&filter=label%3D4fbba5a0-61c7-5dc8-ba1b-3314f398bfa2" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (filter by min_width)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?limit=25&offset=0&filter=min_width%3D4fbba5a0-61c7-5dc8-ba1b-3314f398bfa2" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (filter by max_width)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?limit=25&offset=0&filter=max_width%3D4fbba5a0-61c7-5dc8-ba1b-3314f398bfa2" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (filter by max_height)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?limit=25&offset=0&filter=max_height%3D4fbba5a0-61c7-5dc8-ba1b-3314f398bfa2" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get templates types (filter by min_height)
+ Given current authentication token
+ When I request "/api/v1/EN/templates/types?limit=25&offset=0&filter=min_height%3D4fbba5a0-61c7-5dc8-ba1b-3314f398bfa2" using HTTP GET
+ Then grid response is received
- # TODO Check template grid
- # TODO Check template group grid
- # TODO Check template type grid
- # TODO Check create template action with all incorrect possibilities
- # TODO Check update template action with all incorrect possibilities
diff --git a/features/product.feature b/features/product.feature
index 5ddb61bdc..82ac3754c 100644
--- a/features/product.feature
+++ b/features/product.feature
@@ -94,6 +94,94 @@ Feature: Product module
When I request "/api/v1/EN/products" using HTTP POST
Then unauthorized response is received
+ Scenario: Create product (wrong product_template no UUID)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "sku": "SKU_@@random_code@@",
+ "templateId": "test",
+ "categoryIds": ["@product_category@"]
+ }
+ """
+ When I request "/api/v1/EN/products" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create product (wrong product_template wrong UUID)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "sku": "SKU_@@random_code@@",
+ "templateId": "@@random_uuid@@",
+ "categoryIds": ["@product_category@"]
+ }
+ """
+ When I request "/api/v1/EN/products" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create product (no templateId)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "sku": "SKU_@@random_code@@",
+ "categoryIds": ["@product_category@"]
+ }
+ """
+ When I request "/api/v1/EN/products" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create product (empty categoryIds)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "sku": "SKU_@@random_code@@",
+ "templateId": "@product_template@",
+ "categoryIds": []
+ }
+ """
+ When I request "/api/v1/EN/products" using HTTP POST
+ Then created response is received
+
+ Scenario: Create product (no categoryIds)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "sku": "SKU_@@random_code@@",
+ "templateId": "@product_template@"
+ }
+ """
+ When I request "/api/v1/EN/products" using HTTP POST
+ Then created response is received
+
+ Scenario: Create product (categoryIds not UUID)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "sku": "SKU_@@random_code@@",
+ "templateId": "@product_template@",
+ "categoryIds": ["test"]
+ }
+ """
+ When I request "/api/v1/EN/products" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create product (no categoryIds)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "sku": "SKU_@@random_code@@",
+ "templateId": "@product_template@"
+ }
+ """
+ When I request "/api/v1/EN/products" using HTTP POST
+ Then created response is received
+
Scenario: Update product
Given current authentication token
Given the request body is:
@@ -114,6 +202,38 @@ Feature: Product module
When I request "/api/v1/EN/products/@@static_uuid@@" using HTTP PUT
Then not found response is received
+ Scenario: Update product (no content)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ }
+ """
+ When I request "/api/v1/EN/products/@product@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update product (categoryID not UUID)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "categoryIds": ["@@random_md5@@"]
+ }
+ """
+ When I request "/api/v1/EN/products/@product@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Update product (categoryID wrong UUID)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "categoryIds": ["@@random_uuid@@"]
+ }
+ """
+ When I request "/api/v1/EN/products/@product@" using HTTP PUT
+ Then validation error response is received
+
Scenario: Get product
Given current authentication token
When I request "/api/v1/EN/products/@product@" using HTTP GET
@@ -128,6 +248,70 @@ Feature: Product module
When I request "/api/v1/EN/products/@@static_uuid@@" using HTTP GET
Then not found response is received
- # TODO Check product grid
- # TODO Check create product action with all incorrect possibilities
- # TODO Check update product action with all incorrect possibilities
+ Scenario: Delete product (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/products/@@static_uuid@@" using HTTP DELETE
+ Then not found response is received
+
+ Scenario: Delete product (not authorized)
+ When I request "/api/v1/EN/products/@product@" using HTTP DELETE
+ Then unauthorized response is received
+
+ Scenario: Delete product
+ Given current authentication token
+ When I request "/api/v1/EN/products/@product@" using HTTP DELETE
+ Then empty response is received
+
+ Scenario: Get products (order by id)
+ Given current authentication token
+ When I request "/api/v1/EN/products?field=id" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (order by index)
+ Given current authentication token
+ When I request "/api/v1/EN/products?field=index" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (order by sku)
+ Given current authentication token
+ When I request "/api/v1/EN/products?field=sku" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (order by template)
+ Given current authentication token
+ When I request "/api/v1/EN/products?field=template" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (order ASC)
+ Given current authentication token
+ When I request "/api/v1/EN/products?field=index&order=ASC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (order DESC)
+ Given current authentication token
+ When I request "/api/v1/EN/products?field=index&order=DESC" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (filter by template)
+ Given current authentication token
+ When I request "/api/v1/EN/products?limit=25&offset=0&filter=template%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (filter by index)
+ Given current authentication token
+ When I request "/api/v1/EN/products?limit=25&offset=0&filter=index%3Dasd" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (filter by id)
+ Given current authentication token
+ When I request "/api/v1/EN/products?limit=25&offset=0&filter=id%3DCAT" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (filter by sku)
+ Given current authentication token
+ When I request "/api/v1/EN/products?limit=25&offset=0&filter=sku%3D1" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get products (not authorized)
+ When I request "/api/v1/EN/products" using HTTP GET
+ Then unauthorized response is received
diff --git a/features/segment.feature b/features/segment.feature
new file mode 100644
index 000000000..5decc307b
--- /dev/null
+++ b/features/segment.feature
@@ -0,0 +1,252 @@
+Feature: Segment
+
+ Scenario: Create condition set
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "SEGMENT_CONDITION_@@random_uuid@@"
+ }
+ """
+ Given I request "/api/v1/EN/conditionsets" using HTTP POST
+ Then created response is received
+ And remember response param "id" as "segment_conditionset"
+
+ Scenario: Create segment (not authorized)
+ When I request "/api/v1/EN/segments" using HTTP POST
+ Then unauthorized response is received
+
+ Scenario: Create segment
+ Given remember param "segment_code" with value "SEG_1_@@random_code@@"
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "@segment_code@",
+ "condition_set_id": "@segment_conditionset@",
+ "name": {
+ "PL": "Segment",
+ "EN": "Segment"
+ },
+ "description": {
+ "PL": "Opis segmentu",
+ "EN": "Segment description"
+ }
+ }
+ """
+ When I request "/api/v1/EN/segments" using HTTP POST
+ Then created response is received
+ And remember response param "id" as "segment"
+
+ Scenario: Create segment (not unique code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "@segment_code@",
+ "condition_set_id": "@segment_conditionset@",
+ "description": {
+ "PL": "Opis segmentu",
+ "EN": "Segment description"
+ }
+ }
+ """
+ When I request "/api/v1/EN/segments" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create segment (without name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "SEG_2_@@random_code@@",
+ "condition_set_id": "@segment_conditionset@",
+ "description": {
+ "PL": "Opis segmentu",
+ "EN": "Segment description"
+ }
+ }
+ """
+ When I request "/api/v1/EN/segments" using HTTP POST
+ Then created response is received
+
+ Scenario: Create segment (without description and name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "SEG_2_@@random_code@@",
+ "condition_set_id": "@segment_conditionset@"
+ }
+ """
+ When I request "/api/v1/EN/segments" using HTTP POST
+ Then created response is received
+
+ Scenario: Create segment (without code)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "condition_set_id": "@segment_conditionset@",
+ "name": {
+ "PL": "Segment",
+ "EN": "Segment"
+ },
+ "description": {
+ "PL": "Opis segmentu",
+ "EN": "Segment description"
+ }
+ }
+ """
+ When I request "/api/v1/EN/segments" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Create segment (without condition set)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "SEG_2_@@random_code@@"
+ }
+ """
+ When I request "/api/v1/EN/segments" using HTTP POST
+ Then validation error response is received
+
+ Scenario: Update segment (not authorized)
+ When I request "/api/v1/EN/segments/@segment@" using HTTP PUT
+ Then unauthorized response is received
+
+ Scenario: Update segment (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/segments/@@static_uuid@@" using HTTP PUT
+ Then not found response is received
+
+ Scenario: Update segment
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "condition_set_id": "@segment_conditionset@",
+ "name": {
+ "PL": "Segment (changed)",
+ "EN": "Segment (changed)"
+ },
+ "description": {
+ "PL": "Opis segmentu (changed)",
+ "EN": "Segment description (changed)"
+ }
+ }
+ """
+ When I request "/api/v1/EN/segments/@segment@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update segment (without name)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "condition_set_id": "@segment_conditionset@",
+ "description": {
+ "PL": "Opis segmentu (changed)",
+ "EN": "Segment description (changed)"
+ }
+ }
+ """
+ When I request "/api/v1/EN/segments/@segment@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update segment (without name and description)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "condition_set_id": "@segment_conditionset@"
+ }
+ """
+ When I request "/api/v1/EN/segments/@segment@" using HTTP PUT
+ Then empty response is received
+
+ Scenario: Update segment (without condition set)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "name": {
+ "PL": "Segment (changed)",
+ "EN": "Segment (changed)"
+ },
+ "description": {
+ "PL": "Opis segmentu (changed)",
+ "EN": "Segment description (changed)"
+ }
+ }
+ """
+ When I request "/api/v1/EN/segments/@segment@" using HTTP PUT
+ Then validation error response is received
+
+ Scenario: Get segment (not authorized)
+ When I request "/api/v1/EN/segments/@segment@" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get segment (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/segments/@@static_uuid@@" using HTTP GET
+ Then not found response is received
+
+ Scenario: Get segment
+ Given current authentication token
+ When I request "/api/v1/EN/segments/@segment@" using HTTP GET
+ Then the response code is 200
+
+ Scenario: Get segments
+ Given current authentication token
+ When I request "/api/v1/EN/segments" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get segments (not authorized)
+ When I request "/api/v1/EN/segments" using HTTP GET
+ Then unauthorized response is received
+
+ Scenario: Get segments (order by code)
+ Given current authentication token
+ When I request "/api/v1/EN/segments?field=code" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get segments (order by name)
+ Given current authentication token
+ When I request "/api/v1/EN/segments?field=name" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get segments (order by description)
+ Given current authentication token
+ When I request "/api/v1/EN/segments?field=description" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get segments (filter by code)
+ Given current authentication token
+ When I request "/api/v1/EN/segments?limit=25&offset=0&filter=code%3Dsuper" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get segments (filter by name)
+ Given current authentication token
+ When I request "/api/v1/EN/segments?limit=25&offset=0&filter=name%3Dsuper" using HTTP GET
+ Then grid response is received
+
+ Scenario: Get segments (filter by description)
+ Given current authentication token
+ When I request "/api/v1/EN/segments?limit=25&offset=0&filter=description%3Dsuper" using HTTP GET
+ Then grid response is received
+
+ Scenario: Delete segment (not authorized)
+ When I request "/api/v1/EN/segments/@segment@" using HTTP DELETE
+ Then unauthorized response is received
+
+ Scenario: Delete segment (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/segments/@@static_uuid@@" using HTTP DELETE
+ Then not found response is received
+
+ Scenario: Delete segment
+ Given current authentication token
+ When I request "/api/v1/EN/segments/@segment@" using HTTP DELETE
+ Then empty response is received
diff --git a/features/workflow.feature b/features/workflow.feature
index 740c12766..ccb9e90b7 100644
--- a/features/workflow.feature
+++ b/features/workflow.feature
@@ -81,19 +81,18 @@ Feature: Workflow
When I request "/api/v1/EN/workflow/default" using HTTP PUT
Then empty response is received
- Scenario: Delete default status
+ Scenario: Update default workflow (wrong status)
Given current authentication token
- When I request "/api/v1/EN/status/@workflow_status@" using HTTP DELETE
- Then empty response is received
-
- Scenario: Delete default status (not authorized)
- When I request "/api/v1/EN/status/@workflow_status@" using HTTP DELETE
- Then unauthorized response is received
-
- Scenario: Delete default status (not found)
- Given current authentication token
- When I request "/api/v1/EN/status/@@static_uuid@@" using HTTP DELETE
- Then not found response is received
+ Given the request body is:
+ """
+ {
+ "code": "TEST_@@random_code@@",
+ "statuses": ["test"],
+ "transitions": []
+ }
+ """
+ When I request "/api/v1/EN/workflow/default" using HTTP PUT
+ Then validation error response is received
Scenario: Get default statuses
Given current authentication token
@@ -118,6 +117,19 @@ Feature: Workflow
Then created response is received
And remember response param "id" as "workflow"
+ Scenario: Create workflow (wrong statuses)
+ Given current authentication token
+ Given the request body is:
+ """
+ {
+ "code": "WRK_@@random_code@@",
+ "statuses": ["test"],
+ "transitions": []
+ }
+ """
+ When I request "/api/v1/EN/workflow" using HTTP POST
+ Then validation error response is received
+
Scenario: Create workflow (not authorized)
When I request "/api/v1/EN/workflow" using HTTP POST
Then unauthorized response is received
@@ -135,5 +147,30 @@ Feature: Workflow
When I request "/api/v1/EN/workflow/default" using HTTP GET
Then unauthorized response is received
- # TODO Check create workflow action with all incorrect possibilities
- # TODO Check update workflow action with all incorrect possibilities
+ Scenario: Delete workflow (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/workflow/@static_uuid@" using HTTP DELETE
+ Then not found response is received
+
+ Scenario: Delete workflow (not authorized)
+ When I request "/api/v1/EN/workflow/@workflow@" using HTTP DELETE
+ Then unauthorized response is received
+
+ Scenario: Delete workflow
+ Given current authentication token
+ When I request "/api/v1/EN/workflow/@workflow@" using HTTP DELETE
+ Then empty response is received
+
+ Scenario: Delete default status
+ Given current authentication token
+ When I request "/api/v1/EN/status/@workflow_status@" using HTTP DELETE
+ Then empty response is received
+
+ Scenario: Delete default status (not authorized)
+ When I request "/api/v1/EN/status/@workflow_status@" using HTTP DELETE
+ Then unauthorized response is received
+
+ Scenario: Delete default status (not found)
+ Given current authentication token
+ When I request "/api/v1/EN/status/@@static_uuid@@" using HTTP DELETE
+ Then not found response is received
diff --git a/module/account/README.md b/module/account/README.md
index a3da860f2..8af4522fe 100644
--- a/module/account/README.md
+++ b/module/account/README.md
@@ -1,4 +1,4 @@
-# Ergonode -Aaccount
+# Ergonode - Account
## Documentation
diff --git a/module/account/composer.json b/module/account/composer.json
index 4446e74f0..b9d5045df 100644
--- a/module/account/composer.json
+++ b/module/account/composer.json
@@ -7,13 +7,12 @@
"require": {
"php": "^7.2",
"doctrine/dbal": "^2.9",
- "ergonode/api": "^0.4.0",
- "ergonode/core": "^0.4.0",
- "ergonode/es": "^0.4.0",
- "ergonode/grid": "^0.4.0",
- "ergonode/migration": "^0.4.0",
- "ergonode/multimedia": "^0.4.0",
- "friendsofsymfony/rest-bundle": "^2.5",
+ "ergonode/api": "^0.5.0",
+ "ergonode/core": "^0.5.0",
+ "ergonode/es": "^0.5.0",
+ "ergonode/grid": "^0.5.0",
+ "ergonode/migration": "^0.5.0",
+ "ergonode/multimedia": "^0.5.0",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
"ramsey/uuid": "^3.8",
diff --git a/module/account/migrations/Version20180610062601.php b/module/account/migrations/Version20180610062601.php
index a6d98a2a1..3d5ed87b3 100644
--- a/module/account/migrations/Version20180610062601.php
+++ b/module/account/migrations/Version20180610062601.php
@@ -8,7 +8,6 @@
use Ramsey\Uuid\Uuid;
/**
- * Auto-generated Ergonode Migration Class:
*/
final class Version20180610062601 extends AbstractErgonodeMigration
{
@@ -19,7 +18,8 @@ final class Version20180610062601 extends AbstractErgonodeMigration
*/
public function up(Schema $schema): void
{
- $this->addSql('CREATE TABLE users (
+ $this->addSql('
+ CREATE TABLE users (
id UUID NOT NULL,
first_name VARCHAR(128) NOT NULL,
last_name VARCHAR(128) NOT NULL,
@@ -28,24 +28,29 @@ public function up(Schema $schema): void
password VARCHAR(41) NOT NULL,
role_id UUID NOT NULL,
language VARCHAR(2) NOT NULL,
- PRIMARY KEY(id))');
-
+ PRIMARY KEY(id)
+ )
+ ');
$this->addSql('CREATE UNIQUE INDEX users_username_key ON users (username)');
- $this->addSql('CREATE TABLE privileges (
+ $this->addSql('
+ CREATE TABLE privileges (
id UUID NOT NULL,
code VARCHAR(128) NOT NULL,
area VARCHAR(128) NOT NULL,
- PRIMARY KEY(id))');
-
+ PRIMARY KEY(id)
+ )
+ ');
$this->addSql('CREATE UNIQUE INDEX privileges_name_key ON privileges (code)');
- $this->addSql('CREATE TABLE roles (
+ $this->addSql('
+ CREATE TABLE roles (
id UUID NOT NULL,
name VARCHAR(100) NOT NULL,
description VARCHAR(500) NOT NULL,
- PRIMARY KEY(id))');
-
+ PRIMARY KEY(id)
+ )
+ ');
$this->addSql('CREATE UNIQUE INDEX role_name_key ON roles (name)');
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'USER_ROLE_CREATE', 'Role']);
@@ -61,5 +66,40 @@ public function up(Schema $schema): void
$this->addSql('ALTER TABLE roles ADD privileges json DEFAULT NULL');
$this->addSql('ALTER TABLE users ADD is_active BOOLEAN DEFAULT TRUE NOT NULL');
+
+ $this->createEventStoreEvents([
+ 'Ergonode\Account\Domain\Event\User\UserAvatarChangedEvent' => 'User avatar changed',
+ 'Ergonode\Account\Domain\Event\User\UserCreatedEvent' => 'User created',
+ 'Ergonode\Account\Domain\Event\User\UserFirstNameChangedEvent' => 'User first name changed',
+ 'Ergonode\Account\Domain\Event\User\UserLanguageChangedEvent' => 'User language changed',
+ 'Ergonode\Account\Domain\Event\User\UserLastNameChangedEvent' => 'User last name changed',
+ 'Ergonode\Account\Domain\Event\User\UserPasswordChangedEvent' => 'User password changed',
+ 'Ergonode\Account\Domain\Event\User\UserRoleChangedEvent' => 'User role changed',
+ 'Ergonode\Account\Domain\Event\User\UserActivatedEvent' => 'User activated',
+ 'Ergonode\Account\Domain\Event\User\UserDeactivatedEvent' => 'User disabled',
+ 'Ergonode\Account\Domain\Event\Role\AddPrivilegeToRoleEvent' => 'Privilege added',
+ 'Ergonode\Account\Domain\Event\Role\RemovePrivilegeFromRoleEvent' => 'Privilege removed',
+ 'Ergonode\Account\Domain\Event\Role\RoleCreatedEvent' => 'Role created',
+ 'Ergonode\Account\Domain\Event\Role\RoleNameChangedEvent' => 'Role name changed',
+ 'Ergonode\Account\Domain\Event\Role\RoleDescriptionChangedEvent' => 'Role description changed',
+ 'Ergonode\Account\Domain\Event\Role\RolePrivilegesChangedEvent' => 'List of privileges changed',
+ 'Ergonode\Account\Domain\Event\Role\RoleDeletedEvent' => 'Role deleted',
+ ]);
+ }
+
+ /**
+ * @param array $collection
+ *
+ * @throws \Doctrine\DBAL\DBALException
+ */
+ private function createEventStoreEvents(array $collection): void
+ {
+ foreach ($collection as $class => $translation) {
+ $this->connection->insert('event_store_event', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'event_class' => $class,
+ 'translation_key' => $translation,
+ ]);
+ }
}
}
diff --git a/module/account/src/Application/Controller/Api/AccountController.php b/module/account/src/Application/Controller/Api/AccountController.php
index 813dac628..e462e5568 100644
--- a/module/account/src/Application/Controller/Api/AccountController.php
+++ b/module/account/src/Application/Controller/Api/AccountController.php
@@ -305,7 +305,7 @@ public function createUser(Request $request): Response
* in="body",
* description="Add attribute",
* required=true,
- * @SWG\Schema(ref="#/definitions/account")
+ * @SWG\Schema(ref="#/definitions/account_upd")
* )
* @SWG\Parameter(
* name="language",
diff --git a/module/account/src/Application/Form/Model/UpdateUserFormModel.php b/module/account/src/Application/Form/Model/UpdateUserFormModel.php
index e82e866c2..b6b739efc 100644
--- a/module/account/src/Application/Form/Model/UpdateUserFormModel.php
+++ b/module/account/src/Application/Form/Model/UpdateUserFormModel.php
@@ -44,6 +44,7 @@ class UpdateUserFormModel
/**
* @var Password|null
*
+ * @Assert\NotBlank(message="User password repeat is required")
* @Assert\EqualTo(propertyPath="password", message="This value should be same as password")
*/
public $passwordRepeat;
diff --git a/module/account/src/Domain/Entity/Role.php b/module/account/src/Domain/Entity/Role.php
index 06b2c246c..7f416cf5f 100644
--- a/module/account/src/Domain/Entity/Role.php
+++ b/module/account/src/Domain/Entity/Role.php
@@ -15,10 +15,8 @@
use Ergonode\Account\Domain\Event\Role\RoleDescriptionChangedEvent;
use Ergonode\Account\Domain\Event\Role\RoleNameChangedEvent;
use Ergonode\Account\Domain\Event\Role\RolePrivilegesChangedEvent;
-use Ergonode\Account\Domain\Event\Role\RoleRemovedEvent;
use Ergonode\Account\Domain\ValueObject\Privilege;
use Ergonode\Core\Domain\Entity\AbstractId;
-use Ergonode\Core\Domain\ValueObject\State;
use Ergonode\EventSourcing\Domain\AbstractAggregateRoot;
use JMS\Serializer\Annotation as JMS;
use Webmozart\Assert\Assert;
@@ -55,13 +53,6 @@ class Role extends AbstractAggregateRoot
*/
private $privileges;
- /**
- * @var State
- *
- * @JMS\Exclude()
- */
- private $state;
-
/**
* @param RoleId $id
* @param string $name
@@ -77,15 +68,6 @@ public function __construct(RoleId $id, string $name, string $description, array
$this->apply(new RoleCreatedEvent($id, $name, $description, $privileges));
}
- /**
- */
- public function remove(): void
- {
- if ($this->state->getValue() !== State::STATE_DELETED) {
- $this->apply(new RoleRemovedEvent());
- }
- }
-
/**
* @return RoleId|AbstractId
*/
@@ -188,14 +170,6 @@ public function removePrivilege(Privilege $privilege): void
$this->apply(new RemovePrivilegeFromRoleEvent($privilege));
}
- /**
- * @return bool
- */
- public function isDeleted(): bool
- {
- return $this->state->getValue() === State::STATE_DELETED;
- }
-
/**
* @param RoleCreatedEvent $event
*/
@@ -205,15 +179,6 @@ protected function applyRoleCreatedEvent(RoleCreatedEvent $event): void
$this->name = $event->getName();
$this->description = $event->getDescription();
$this->privileges = $event->getPrivileges();
- $this->state = new State();
- }
-
- /**
- * @param RoleRemovedEvent $event
- */
- protected function applyRoleRemovedEvent(RoleRemovedEvent $event): void
- {
- $this->state = new State(State::STATE_DELETED);
}
/**
diff --git a/module/account/src/Domain/Event/Role/RoleRemovedEvent.php b/module/account/src/Domain/Event/Role/RoleDeletedEvent.php
similarity index 64%
rename from module/account/src/Domain/Event/Role/RoleRemovedEvent.php
rename to module/account/src/Domain/Event/Role/RoleDeletedEvent.php
index dbc60514c..a2cbd0a24 100644
--- a/module/account/src/Domain/Event/Role/RoleRemovedEvent.php
+++ b/module/account/src/Domain/Event/Role/RoleDeletedEvent.php
@@ -9,10 +9,10 @@
namespace Ergonode\Account\Domain\Event\Role;
-use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
+use Ergonode\EventSourcing\Infrastructure\AbstractDeleteEvent;
/**
*/
-class RoleRemovedEvent implements DomainEventInterface
+class RoleDeletedEvent extends AbstractDeleteEvent
{
}
diff --git a/module/account/src/Domain/Repository/RoleRepositoryInterface.php b/module/account/src/Domain/Repository/RoleRepositoryInterface.php
index 68e3790f6..da4627120 100644
--- a/module/account/src/Domain/Repository/RoleRepositoryInterface.php
+++ b/module/account/src/Domain/Repository/RoleRepositoryInterface.php
@@ -28,4 +28,9 @@ public function load(RoleId $id): ?AbstractAggregateRoot;
* @param AbstractAggregateRoot $aggregateRoot
*/
public function save(AbstractAggregateRoot $aggregateRoot): void;
+
+ /**
+ * @param AbstractAggregateRoot $aggregateRoot
+ */
+ public function delete(AbstractAggregateRoot $aggregateRoot): void;
}
diff --git a/module/account/src/Infrastructure/Handler/Role/DeleteRoleCommandHandler.php b/module/account/src/Infrastructure/Handler/Role/DeleteRoleCommandHandler.php
index 776df8a4f..4baf41f2d 100644
--- a/module/account/src/Infrastructure/Handler/Role/DeleteRoleCommandHandler.php
+++ b/module/account/src/Infrastructure/Handler/Role/DeleteRoleCommandHandler.php
@@ -40,8 +40,7 @@ public function __invoke(DeleteRoleCommand $command)
{
$role = $this->repository->load($command->getId());
Assert::isInstanceOf($role, Role::class, sprintf('Can\'t find Role with id %s', $command->getId()));
- $role->remove();
- $this->repository->save($role);
+ $this->repository->delete($role);
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/Role/RoleCreatedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/Role/RoleCreatedEventProjector.php
index d187b84b5..11bd0b231 100644
--- a/module/account/src/Persistence/Dbal/Projector/Role/RoleCreatedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/Role/RoleCreatedEventProjector.php
@@ -15,6 +15,7 @@
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
+use JMS\Serializer\SerializerInterface;
/**
*/
@@ -28,17 +29,22 @@ class RoleCreatedEventProjector implements DomainEventProjectorInterface
private $connection;
/**
- * @param Connection $connection
+ * @var SerializerInterface
*/
- public function __construct(Connection $connection)
+ private $serializer;
+
+ /**
+ * @param Connection $connection
+ * @param SerializerInterface $serializer
+ */
+ public function __construct(Connection $connection, SerializerInterface $serializer)
{
$this->connection = $connection;
+ $this->serializer = $serializer;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +52,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws UnsupportedEventException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,16 +60,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, RoleCreatedEvent::class);
}
- $this->connection->transactional(function () use ($event) {
- $this->connection->insert(
- self::TABLE,
- [
- 'id' => $event->getId()->getValue(),
- 'name' => $event->getName(),
- 'description' => $event->getDescription(),
- 'privileges' => json_encode($event->getPrivileges()),
- ]
- );
- });
+ $this->connection->insert(
+ self::TABLE,
+ [
+ 'id' => $event->getId()->getValue(),
+ 'name' => $event->getName(),
+ 'description' => $event->getDescription(),
+ 'privileges' => $this->serializer->serialize($event->getPrivileges(), 'json'),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/Role/RoleRemovedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/Role/RoleDeletedEventProjector.php
similarity index 51%
rename from module/account/src/Persistence/Dbal/Projector/Role/RoleRemovedEventProjector.php
rename to module/account/src/Persistence/Dbal/Projector/Role/RoleDeletedEventProjector.php
index ea1ec04c1..713c4b6a1 100644
--- a/module/account/src/Persistence/Dbal/Projector/Role/RoleRemovedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/Role/RoleDeletedEventProjector.php
@@ -10,7 +10,7 @@
namespace Ergonode\Account\Persistence\Dbal\Projector\Role;
use Doctrine\DBAL\Connection;
-use Ergonode\Account\Domain\Event\Role\RoleRemovedEvent;
+use Ergonode\Account\Domain\Event\Role\RoleDeletedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
@@ -18,7 +18,7 @@
/**
*/
-class RoleRemovedEventProjector implements DomainEventProjectorInterface
+class RoleDeletedEventProjector implements DomainEventProjectorInterface
{
private const TABLE = 'roles';
@@ -36,40 +36,27 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
- return $event instanceof RoleRemovedEvent;
+ return $event instanceof RoleDeletedEvent;
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
- if (!$event instanceof RoleRemovedEvent) {
- throw new UnsupportedEventException($event, RoleRemovedEvent::class);
+ if (!$event instanceof RoleDeletedEvent) {
+ throw new UnsupportedEventException($event, RoleDeletedEvent::class);
}
- $this->connection->beginTransaction();
- try {
- $this->connection->delete(
- self::TABLE,
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw $exception;
- }
+ $this->connection->delete(
+ self::TABLE,
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/Role/RoleDescriptionChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/Role/RoleDescriptionChangedEventProjector.php
index 0641556d5..b82ddb348 100644
--- a/module/account/src/Persistence/Dbal/Projector/Role/RoleDescriptionChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/Role/RoleDescriptionChangedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,21 +52,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, RoleDescriptionChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
- $this->connection->update(
- self::TABLE,
- [
- 'description' => $event->getTo(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw $exception;
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'description' => $event->getTo(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/Role/RoleNameChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/Role/RoleNameChangedEventProjector.php
index 86456a7aa..b154ca213 100644
--- a/module/account/src/Persistence/Dbal/Projector/Role/RoleNameChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/Role/RoleNameChangedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,21 +52,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, RoleNameChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
- $this->connection->update(
- self::TABLE,
- [
- 'name' => $event->getTo(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw $exception;
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'name' => $event->getTo(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/Role/RolePrivilegesChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/Role/RolePrivilegesChangedEventProjector.php
index 847ebd878..0579f3fe5 100644
--- a/module/account/src/Persistence/Dbal/Projector/Role/RolePrivilegesChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/Role/RolePrivilegesChangedEventProjector.php
@@ -15,6 +15,7 @@
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
+use JMS\Serializer\SerializerInterface;
/**
*/
@@ -28,17 +29,22 @@ class RolePrivilegesChangedEventProjector implements DomainEventProjectorInterfa
private $connection;
/**
- * @param Connection $connection
+ * @var SerializerInterface
*/
- public function __construct(Connection $connection)
+ private $serializer;
+
+ /**
+ * @param Connection $connection
+ * @param SerializerInterface $serializer
+ */
+ public function __construct(Connection $connection, SerializerInterface $serializer)
{
$this->connection = $connection;
+ $this->serializer = $serializer;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +52,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws UnsupportedEventException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,16 +60,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, RolePrivilegesChangedEvent::class);
}
- $this->connection->transactional(function () use ($event, $aggregateId) {
- $this->connection->update(
- self::TABLE,
- [
- 'privileges' => json_encode($event->getTo()),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- });
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'privileges' => $this->serializer->serialize($event->getTo(), 'json'),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserActivatedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserActivatedEventProjector.php
index 8fcdff9f9..06038cf08 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserActivatedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserActivatedEventProjector.php
@@ -44,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws UnsupportedEventException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -56,19 +52,17 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserActivatedEvent::class);
}
- $this->connection->transactional(function () use ($aggregateId, $event) {
- $this->connection->update(
- self::TABLE,
- [
- 'is_active' => $event->isActive(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ],
- [
- 'is_active' => \PDO::PARAM_BOOL,
- ]
- );
- });
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'is_active' => $event->isActive(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ],
+ [
+ 'is_active' => \PDO::PARAM_BOOL,
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserAvatarChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserAvatarChangedEventProjector.php
index 0941fd124..d8f0428bc 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserAvatarChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserAvatarChangedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,21 +52,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserAvatarChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
- $this->connection->update(
- self::TABLE,
- [
- 'avatar_id' => $event->getAvatarId() ? $event->getAvatarId()->getValue() : null,
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw $exception;
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'avatar_id' => $event->getAvatarId() ? $event->getAvatarId()->getValue() : null,
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserCreatedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserCreatedEventProjector.php
index 220721c9a..48302e30f 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserCreatedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserCreatedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws UnsupportedEventException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,23 +52,21 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserCreatedEvent::class);
}
- $this->connection->transactional(function () use ($event) {
- $this->connection->insert(
- self::TABLE,
- [
- 'id' => $event->getId()->getValue(),
- 'first_name' => $event->getFirstName(),
- 'last_name' => $event->getLastName(),
- 'username' => $event->getEmail(),
- 'role_id' => $event->getRoleId()->getValue(),
- 'language' => $event->getLanguage()->getCode(),
- 'password' => $event->getPassword()->getValue(),
- 'is_active' => $event->isActive(),
- ],
- [
- 'is_active' => \PDO::PARAM_BOOL,
- ]
- );
- });
+ $this->connection->insert(
+ self::TABLE,
+ [
+ 'id' => $event->getId()->getValue(),
+ 'first_name' => $event->getFirstName(),
+ 'last_name' => $event->getLastName(),
+ 'username' => $event->getEmail(),
+ 'role_id' => $event->getRoleId()->getValue(),
+ 'language' => $event->getLanguage()->getCode(),
+ 'password' => $event->getPassword()->getValue(),
+ 'is_active' => $event->isActive(),
+ ],
+ [
+ 'is_active' => \PDO::PARAM_BOOL,
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserDeactivatedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserDeactivatedEventProjector.php
index a859b2b16..d08140f13 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserDeactivatedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserDeactivatedEventProjector.php
@@ -44,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws UnsupportedEventException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -56,19 +52,17 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserDeactivatedEvent::class);
}
- $this->connection->transactional(function () use ($aggregateId, $event) {
- $this->connection->update(
- self::TABLE,
- [
- 'is_active' => $event->isActive(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ],
- [
- 'is_active' => \PDO::PARAM_BOOL,
- ]
- );
- });
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'is_active' => $event->isActive(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ],
+ [
+ 'is_active' => \PDO::PARAM_BOOL,
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserFirstNameChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserFirstNameChangedEventProjector.php
index f24cb1ac7..c65e0a596 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserFirstNameChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserFirstNameChangedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,21 +52,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserFirstNameChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
- $this->connection->update(
- self::TABLE,
- [
- 'first_name' => $event->getTo(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw $exception;
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'first_name' => $event->getTo(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserLanguageChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserLanguageChangedEventProjector.php
index c27bbcf48..5d341e630 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserLanguageChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserLanguageChangedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,21 +52,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserLanguageChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
- $this->connection->update(
- self::TABLE,
- [
- 'language' => $event->getTo()->getCode(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw $exception;
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'language' => $event->getTo()->getCode(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserLastNameChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserLastNameChangedEventProjector.php
index 10c3ef72c..31f180be4 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserLastNameChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserLastNameChangedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,21 +52,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserLastNameChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
- $this->connection->update(
- self::TABLE,
- [
- 'last_name' => $event->getTo(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw $exception;
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'last_name' => $event->getTo(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserPasswordChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserPasswordChangedEventProjector.php
index db60ef6c4..c5e158b4a 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserPasswordChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserPasswordChangedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,11 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -58,21 +52,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserPasswordChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
- $this->connection->update(
- self::TABLE,
- [
- 'password' => $event->getPassword(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw $exception;
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'password' => $event->getPassword(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Projector/User/UserRoleChangedEventProjector.php b/module/account/src/Persistence/Dbal/Projector/User/UserRoleChangedEventProjector.php
index a6e5fcfe3..7444d8ff7 100644
--- a/module/account/src/Persistence/Dbal/Projector/User/UserRoleChangedEventProjector.php
+++ b/module/account/src/Persistence/Dbal/Projector/User/UserRoleChangedEventProjector.php
@@ -11,12 +11,10 @@
use Doctrine\DBAL\Connection;
use Ergonode\Account\Domain\Event\User\UserRoleChangedEvent;
-use Ergonode\Account\Domain\Repository\RoleRepositoryInterface;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
-use Webmozart\Assert\Assert;
/**
*/
@@ -30,24 +28,15 @@ class UserRoleChangedEventProjector implements DomainEventProjectorInterface
private $connection;
/**
- * @var RoleRepositoryInterface
+ * @param Connection $connection
*/
- private $repository;
-
- /**
- * @param Connection $connection
- * @param RoleRepositoryInterface $repository
- */
- public function __construct(Connection $connection, RoleRepositoryInterface $repository)
+ public function __construct(Connection $connection)
{
$this->connection = $connection;
- $this->repository = $repository;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -55,12 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
- * @throws \Throwable
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -68,20 +52,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, UserRoleChangedEvent::class);
}
- $role = $this->repository->load($event->getTo());
-
- Assert::notNull($role);
-
- $this->connection->transactional(function () use ($event, $aggregateId) {
- $this->connection->update(
- self::TABLE,
- [
- 'role_id' => $event->getTo()->getValue(),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- });
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'role_id' => $event->getTo()->getValue(),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/account/src/Persistence/Dbal/Query/DbalLogQuery.php b/module/account/src/Persistence/Dbal/Query/DbalLogQuery.php
index 5a295435d..96b42e25a 100644
--- a/module/account/src/Persistence/Dbal/Query/DbalLogQuery.php
+++ b/module/account/src/Persistence/Dbal/Query/DbalLogQuery.php
@@ -59,9 +59,26 @@ public function getDataSet(?UserId $id = null): DataSetInterface
*/
private function getQuery(): QueryBuilder
{
+ $publicEventStoreBuilder = $this->connection->createQueryBuilder()
+ ->select('*')
+ ->from('public.event_store');
+
+ $importerEventStoreBuilder = $this->connection->createQueryBuilder()
+ ->select('*')
+ ->from('importer.event_store');
+
+ $union = sprintf(
+ '(%s UNION %s)',
+ $publicEventStoreBuilder->getSQL(),
+ $importerEventStoreBuilder->getSQL()
+ );
+
return $this->connection->createQueryBuilder()
- ->select('es.id, event, payload, recorded_at, recorded_by AS author_id, coalesce(u.first_name || \' \' || u.last_name, \'System\') AS author')
- ->leftJoin('es', 'users', 'u', 'u.id = es.recorded_by')
- ->from('event_store', 'es');
+ ->select('es.id, es.payload, es.recorded_at, es.recorded_by AS author_id')
+ ->addSelect('coalesce(u.first_name || \' \' || u.last_name, \'System\') AS author')
+ ->addSelect('ese.translation_key as event')
+ ->from($union, 'es')
+ ->join('es', 'public.event_store_event', 'ese', 'es.event_id = ese.id')
+ ->leftJoin('es', 'public.users', 'u', 'u.id = es.recorded_by');
}
}
diff --git a/module/account/src/Persistence/Dbal/Repository/DbalRoleRepository.php b/module/account/src/Persistence/Dbal/Repository/DbalRoleRepository.php
index f9e5dc60a..5a0010fc9 100644
--- a/module/account/src/Persistence/Dbal/Repository/DbalRoleRepository.php
+++ b/module/account/src/Persistence/Dbal/Repository/DbalRoleRepository.php
@@ -9,6 +9,7 @@
use Ergonode\Account\Domain\Entity\Role;
use Ergonode\Account\Domain\Entity\RoleId;
+use Ergonode\Account\Domain\Event\Role\RoleDeletedEvent;
use Ergonode\Account\Domain\Repository\RoleRepositoryInterface;
use Ergonode\EventSourcing\Domain\AbstractAggregateRoot;
use Ergonode\EventSourcing\Infrastructure\DomainEventDispatcherInterface;
@@ -32,8 +33,10 @@ class DbalRoleRepository implements RoleRepositoryInterface
* @param DomainEventStoreInterface $eventStore
* @param DomainEventDispatcherInterface $eventDispatcher
*/
- public function __construct(DomainEventStoreInterface $eventStore, DomainEventDispatcherInterface $eventDispatcher)
- {
+ public function __construct(
+ DomainEventStoreInterface $eventStore,
+ DomainEventDispatcherInterface $eventDispatcher
+ ) {
$this->eventStore = $eventStore;
$this->eventDispatcher = $eventDispatcher;
}
@@ -59,9 +62,7 @@ public function load(RoleId $id): ?AbstractAggregateRoot
$aggregate->initialize($eventStream);
- if (!$aggregate->isDeleted()) {
- return $aggregate;
- }
+ return $aggregate;
}
return null;
@@ -79,4 +80,17 @@ public function save(AbstractAggregateRoot $aggregateRoot): void
$this->eventDispatcher->dispatch($envelope);
}
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws \Exception
+ */
+ public function delete(AbstractAggregateRoot $aggregateRoot): void
+ {
+ $aggregateRoot->apply(new RoleDeletedEvent());
+ $this->save($aggregateRoot);
+
+ $this->eventStore->delete($aggregateRoot->getId());
+ }
}
diff --git a/module/account/src/Resources/translations/log.en.yaml b/module/account/src/Resources/translations/log.en.yaml
index 17a742bad..421a10af0 100644
--- a/module/account/src/Resources/translations/log.en.yaml
+++ b/module/account/src/Resources/translations/log.en.yaml
@@ -1,19 +1,16 @@
-"Ergonode\\Account\\Domain\\Event\\User\\UserAvatarChangedEvent": User avatar changed
-"Ergonode\\Account\\Domain\\Event\\User\\UserCreatedEvent": User "%first_name% %last_name%" created
-"Ergonode\\Account\\Domain\\Event\\User\\UserFirstNameChangedEvent": User first name changed from "%from% to "%to%"
-"Ergonode\\Account\\Domain\\Event\\User\\UserLanguageChangedEvent": User language changed from "%from% to %to%"
-"Ergonode\\Account\\Domain\\Event\\User\\UserLastNameChangedEvent": User last name changed from "%from% to "%to%"
-"Ergonode\\Account\\Domain\\Event\\User\\UserPasswordChangedEvent": User password changed
-"Ergonode\\Account\\Domain\\Event\\User\\UserRoleChangedEvent": User role changed from "%from%" to "%to%"
-"Ergonode\\Account\\Domain\\Event\\User\\UserActivatedEvent": User activated
-"Ergonode\\Account\\Domain\\Event\\User\\UserDeactivatedEvent": User disabled
-"Ergonode\\Account\\Domain\\Event\\Role\\AddPrivilegeToRoleEvent": Provilege "%privilege%" added
-"Ergonode\\Account\\Domain\\Event\\Role\\RemovePrivilegeFromRoleEvent": privilege "%privilege%" removed
-"Ergonode\\Account\\Domain\\Event\\Role\\RoleCreatedEvent": Role "%name%" created
-"Ergonode\\Account\\Domain\\Event\\Role\\RoleNameChangedEvent": Role name changed from "%from%" to "%to%"
-"Ergonode\\Account\\Domain\\Event\\Role\\RoleDescriptionChangedEvent": Role description changed from "%from%" to "%to%"
-"Ergonode\\Account\\Domain\\Event\\Role\\RolePrivilegesChangedEvent": List of pirivileges changed
-"Ergonode\\Account\\Domain\\Event\\Role\\RoleRemovedEvent": Role removed
-
-
-
+'User avatar changed': 'User avatar changed'
+'User created': 'User "%first_name% %last_name%" created'
+'User first name changed': 'User first name changed from "%from% to "%to%"'
+'User language changed': 'User language changed from "%from% to %to%"'
+'User last name changed': 'User last name changed from "%from% to "%to%"'
+'User password changed': 'User password changed'
+'User role changed': 'User role changed'
+'User activated': 'User activated'
+'User disabled': 'User disabled'
+'Privilege added': 'Provilege "%privilege%" added'
+'Privilege removed': 'Privilege "%privilege%" removed'
+'Role created': 'Role "%name%" created'
+'Role name changed': 'Role name changed from "%from%" to "%to%"'
+'Role description changed': 'Role description changed from "%from%" to "%to%"'
+'List of privileges changed': 'List of privileges changed'
+'Role deleted': 'Role deleted'
diff --git a/module/account/src/Resources/translations/log.pl.yaml b/module/account/src/Resources/translations/log.pl.yaml
index 93a70ea15..6360adb94 100644
--- a/module/account/src/Resources/translations/log.pl.yaml
+++ b/module/account/src/Resources/translations/log.pl.yaml
@@ -1,16 +1,16 @@
-"Ergonode\\Account\\Domain\\Event\\User\\UserAvatarChangedEvent": Awatar użytkownika został zmieniony
-"Ergonode\\Account\\Domain\\Event\\User\\UserCreatedEvent": Użytkownik "%first_name% %last_name%" został utworzony
-"Ergonode\\Account\\Domain\\Event\\User\\UserFirstNameChangedEvent": Imię użytkownika zostało zmienione z "%from% na "%to%"
-"Ergonode\\Account\\Domain\\Event\\User\\UserLanguageChangedEvent": Język użytkownika został zmieniony z "%from% na %to%"
-"Ergonode\\Account\\Domain\\Event\\User\\UserLastNameChangedEvent": Nazwisko użytkownika zostało zmienione z "%from% na "%to%"
-"Ergonode\\Account\\Domain\\Event\\User\\UserPasswordChangedEvent": Hasło użytkownika zostało zmienione
-"Ergonode\\Account\\Domain\\Event\\User\\UserRoleChangedEvent": Rola użytkonika została zmieniona z "%from%" na "%to%"
-"Ergonode\\Account\\Domain\\Event\\User\\UserActivatedEvent": Użytkownik aktywowany
-"Ergonode\\Account\\Domain\\Event\\User\\UserDeactivatedEvent": Użytkownik zablokowany
-"Ergonode\\Account\\Domain\\Event\\Role\\AddPrivilegeToRoleEvent": Uprawnienie "%privilege%" zostało dodane
-"Ergonode\\Account\\Domain\\Event\\Role\\RemovePrivilegeFromRoleEvent": Uprawnienie "%privilege%" zostało usunięte
-"Ergonode\\Account\\Domain\\Event\\Role\\RoleCreatedEvent": Rola "%name%" została utworzona
-"Ergonode\\Account\\Domain\\Event\\Role\\RoleDescriptionChangedEvent": Opis roli została zmieniona z "%from%" na "%to%"
-"Ergonode\\Account\\Domain\\Event\\Role\\RoleNameChangedEvent": Nazwa roli została zmieniona z "%from%" na "%to%"
-"Ergonode\\Account\\Domain\\Event\\Role\\RolePrivilegesChangedEvent": List uprawnień została zmieniona
-"Ergonode\\Account\\Domain\\Event\\Role\\RoleRemovedEvent": Rola została usunięta
+'User avatar changed': 'Awatar użytkownika został zmieniony'
+'User created': 'Użytkownik "%first_name% %last_name%" został utworzony'
+'User first name changed': 'Imię użytkownika zostało zmienione z "%from% na "%to%"'
+'User language changed': 'Język użytkownika został zmieniony z "%from% na %to%"'
+'User last name changed': 'Nazwisko użytkownika zostało zmienione z "%from% na "%to%"'
+'User password changed': 'Hasło użytkownika zostało zmienione'
+'User role changed': 'Rola użytkownika została zmieniona z "%from%" na "%to%"'
+'User activated': 'Użytkownik aktywowany'
+'User disabled': 'Użytkownik zablokowany'
+'Privilege added': 'Uprawnienie "%privilege%" zostało dodane'
+'Privilege removed': 'Uprawnienie "%privilege%" zostało usunięte'
+'Role created': 'Rola "%name%" została utworzona'
+'Role name changed': 'Opis roli został zmieniony z "%from%" na "%to%"'
+'Role description changed': 'Nazwa roli została zmieniona z "%from%" na "%to%"'
+'List of privileges changed': 'Lista uprawnień została zmieniona'
+'Role deleted': 'Rola została usunięta'
diff --git a/module/account/tests/Domain/Entity/RoleTest.php b/module/account/tests/Domain/Entity/RoleTest.php
index 0cceb94fb..b51c9387e 100644
--- a/module/account/tests/Domain/Entity/RoleTest.php
+++ b/module/account/tests/Domain/Entity/RoleTest.php
@@ -130,13 +130,4 @@ public function testChangePrivilegesWithIncorrectType(): void
$role = new Role($this->roleId, $this->name, $this->description);
$role->changesPrivileges([$privileges]);
}
-
- /**
- */
- public function testDelete(): void
- {
- $role = new Role($this->roleId, $this->name, $this->description);
- $role->remove();
- $this->assertTrue($role->isDeleted());
- }
}
diff --git a/module/api/composer.json b/module/api/composer.json
index f1d12f7e6..5b0763394 100644
--- a/module/api/composer.json
+++ b/module/api/composer.json
@@ -7,7 +7,7 @@
"require": {
"php": "^7.2",
"doctrine/dbal": "^2.9",
- "ergonode/core": "^0.4.0",
+ "ergonode/core": "^0.5.0",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
"ramsey/uuid": "^3.8",
diff --git a/module/api/src/Infrastructure/JMS/Serializer/Handler/ViolationsExceptionHandler.php b/module/api/src/Infrastructure/JMS/Serializer/Handler/ViolationsExceptionHandler.php
index 4715f180a..12716b89a 100644
--- a/module/api/src/Infrastructure/JMS/Serializer/Handler/ViolationsExceptionHandler.php
+++ b/module/api/src/Infrastructure/JMS/Serializer/Handler/ViolationsExceptionHandler.php
@@ -86,13 +86,23 @@ private function mapViolations(ConstraintViolationListInterface $violations): ar
$errors = [];
/** @var ConstraintViolationInterface $violation */
foreach ($violations as $violation) {
- $field = substr($violation->getPropertyPath(), 1, -1);
+ $field = ltrim(str_replace(['[', ']'], ['.', ''], $violation->getPropertyPath()), '.');
+ $path = explode('.', $field);
- if (!array_key_exists($field, $errors)) {
- $errors[$field] = [];
+ $pointer = &$errors;
+ foreach ($path as $key) {
+ if (ctype_digit($key)) {
+ $key = 'element-'.$key;
+ }
+
+ if (!array_key_exists($key, $pointer)) {
+ $pointer[$key] = [];
+ }
+
+ $pointer = &$pointer[$key];
}
- $errors[$field][] = $violation->getMessage();
+ $pointer[] = $violation->getMessage();
}
return $errors;
diff --git a/module/attribute-date/composer.json b/module/attribute-date/composer.json
index 9c133ce0a..20ee6cd51 100644
--- a/module/attribute-date/composer.json
+++ b/module/attribute-date/composer.json
@@ -6,8 +6,8 @@
"license": "OSL-3.0",
"require": {
"php": "^7.2",
- "ergonode/api": "^0.4.0",
- "ergonode/attribute": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/attribute": "^0.5.0",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
"symfony/form": "^4.3",
diff --git a/module/attribute-date/src/Domain/ValueObject/DateFormat.php b/module/attribute-date/src/Domain/ValueObject/DateFormat.php
index f3db75ece..c53c07d3a 100644
--- a/module/attribute-date/src/Domain/ValueObject/DateFormat.php
+++ b/module/attribute-date/src/Domain/ValueObject/DateFormat.php
@@ -13,15 +13,15 @@
*/
class DateFormat
{
- public const YYYY_MM_DD = 'YYYY-MM-DD';
- public const YY_MM_DD = 'YY-MM-DD';
- public const DD_MM_YY = 'DD.MM.YY';
- public const DD_MM_YYYY = 'DD.MM.YYYY';
- public const MM_DD_YY = 'MM/DD/YY';
- public const MM_DD_YYYY = 'MM/DD/YYYY';
- public const MMMM_DD_YYYY = 'MMMM DD, YYYY';
- public const DD_MMMM_YYYY = 'DD MMMM YYYY';
- public const DD_MMM_YYYY = 'DD MMM YYYY';
+ public const YYYY_MM_DD = 'yyyy-MM-dd';
+ public const YY_MM_DD = 'yy-MM-dd';
+ public const DD_MM_YY = 'dd.MM.yy';
+ public const DD_MM_YYYY = 'dd.MM.yyyy';
+ public const MM_DD_YY = 'MM/dd/yy';
+ public const MM_DD_YYYY = 'MM/dd/yyyy';
+ public const MMMM_DD_YYYY = 'MMMM dd, yyyy';
+ public const DD_MMMM_YYYY = 'dd MMMM yyyy';
+ public const DD_MMM_YYYY = 'dd MMM yyyy';
public const AVAILABLE = [
self::YYYY_MM_DD,
diff --git a/module/attribute-image/composer.json b/module/attribute-image/composer.json
index add4f831a..50e4484e9 100644
--- a/module/attribute-image/composer.json
+++ b/module/attribute-image/composer.json
@@ -7,8 +7,8 @@
"require": {
"php": "^7.2",
"doctrine/collections": "^1.6",
- "ergonode/api": "^0.4.0",
- "ergonode/attribute": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/attribute": "^0.5.0",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
"symfony/http-foundation": "^4.3"
diff --git a/module/attribute-image/migrations/Version20180610062602.php b/module/attribute-image/migrations/Version20180610062602.php
new file mode 100644
index 000000000..d21222044
--- /dev/null
+++ b/module/attribute-image/migrations/Version20180610062602.php
@@ -0,0 +1,41 @@
+createEventStoreEvents([
+ 'Ergonode\AttributeImage\Domain\Event\AttributeImageFormatAddedEvent' => 'Added format to image attribute',
+ ]);
+ }
+
+ /**
+ * @param array $collection
+ *
+ * @throws \Doctrine\DBAL\DBALException
+ */
+ private function createEventStoreEvents(array $collection): void
+ {
+ foreach ($collection as $class => $translation) {
+ $this->connection->insert('event_store_event', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'event_class' => $class,
+ 'translation_key' => $translation,
+ ]);
+ }
+ }
+}
diff --git a/module/attribute-image/src/Resources/translations/log.en.yaml b/module/attribute-image/src/Resources/translations/log.en.yaml
new file mode 100644
index 000000000..d3a1d6108
--- /dev/null
+++ b/module/attribute-image/src/Resources/translations/log.en.yaml
@@ -0,0 +1 @@
+'Added format to image attribute': 'Added format to image attribute'
diff --git a/module/attribute-image/src/Resources/translations/log.pl.yaml b/module/attribute-image/src/Resources/translations/log.pl.yaml
new file mode 100644
index 000000000..303411fcd
--- /dev/null
+++ b/module/attribute-image/src/Resources/translations/log.pl.yaml
@@ -0,0 +1 @@
+'Added format to image attribute': 'Dodano nowy format do atrybutu obrazka'
diff --git a/module/attribute-price/composer.json b/module/attribute-price/composer.json
index 8d5d7d7e4..01eb26d63 100644
--- a/module/attribute-price/composer.json
+++ b/module/attribute-price/composer.json
@@ -7,10 +7,10 @@
"require": {
"php": "^7.2",
"doctrine/dbal": "^2.9",
- "ergonode/api": "^0.4.0",
- "ergonode/attribute": "^0.4.0",
- "ergonode/core": "^0.4.0",
- "ergonode/es": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/attribute": "^0.5.0",
+ "ergonode/core": "^0.5.0",
+ "ergonode/es": "^0.5.0",
"jms/serializer": "^3.1",
"moneyphp/money": "^3.2",
"nelmio/api-doc-bundle": "^3.4",
diff --git a/module/attribute-unit/composer.json b/module/attribute-unit/composer.json
index 7ee8cc537..53e58453e 100644
--- a/module/attribute-unit/composer.json
+++ b/module/attribute-unit/composer.json
@@ -8,8 +8,8 @@
"php": "^7.2",
"doctrine/collections": "^1.6",
"doctrine/dbal": "^2.9",
- "ergonode/api": "^0.4.0",
- "ergonode/attribute": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/attribute": "^0.5.0",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
"symfony/form": "^4.3",
diff --git a/module/attribute/composer.json b/module/attribute/composer.json
index 3dc20a84d..896c64c31 100644
--- a/module/attribute/composer.json
+++ b/module/attribute/composer.json
@@ -6,12 +6,12 @@
"license": "OSL-3.0",
"require": {
"php": "^7.2",
- "ergonode/api": "^0.4.0",
- "ergonode/core": "^0.4.0",
- "ergonode/es": "^0.4.0",
- "ergonode/grid": "^0.4.0",
- "ergonode/importer": "^0.4.0",
- "ergonode/value": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/core": "^0.5.0",
+ "ergonode/es": "^0.5.0",
+ "ergonode/grid": "^0.5.0",
+ "ergonode/importer": "^0.5.0",
+ "ergonode/value": "^0.5.0",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
"ramsey/uuid": "^3.8",
diff --git a/module/attribute/migrations/Version20180625083834.php b/module/attribute/migrations/Version20180625083834.php
index 1197303fc..b846fe8ed 100644
--- a/module/attribute/migrations/Version20180625083834.php
+++ b/module/attribute/migrations/Version20180625083834.php
@@ -125,6 +125,20 @@ public function up(Schema $schema): void
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'ATTRIBUTE_GROUP_READ', 'Attribute group']);
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'ATTRIBUTE_GROUP_UPDATE', 'Attribute group']);
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'ATTRIBUTE_GROUP_DELETE', 'Attribute group']);
+
+ $this->createEventStoreEvents([
+ 'Ergonode\Attribute\Domain\Event\Attribute\AttributeCreatedEvent' => 'Attribute added',
+ 'Ergonode\Attribute\Domain\Event\Attribute\AttributeHintChangedEvent' => 'Attribute hint changed',
+ 'Ergonode\Attribute\Domain\Event\Attribute\AttributeLabelChangedEvent' => 'Attribute label changed',
+ 'Ergonode\Attribute\Domain\Event\Attribute\AttributePlaceholderChangedEvent' => 'Attribute placeholder changed',
+ 'Ergonode\Attribute\Domain\Event\Attribute\AttributeArrayParameterChangeEvent' => 'Attribute parameters changed',
+ 'Ergonode\Attribute\Domain\Event\Attribute\AttributeParameterChangeEvent' => 'Attribute parameter changed',
+ 'Ergonode\Attribute\Domain\Event\AttributeGroupAddedEvent' => 'Attribute added to group',
+ 'Ergonode\Attribute\Domain\Event\AttributeGroupDeletedEvent' => 'Attribute removed from group',
+ 'Ergonode\Attribute\Domain\Event\AttributeOptionAddedEvent' => 'Attribute option added',
+ 'Ergonode\Attribute\Domain\Event\AttributeOptionRemovedEvent' => 'Attribute option removed',
+ 'Ergonode\Attribute\Domain\Event\AttributeOptionChangedEvent' => 'Attribute option changed',
+ ]);
}
/**
@@ -138,4 +152,20 @@ private function addGroup(string $label, bool $default = false): void
$id = AttributeGroupId::generate();
$this->addSql('INSERT INTO attribute_group (id, label, "default") VALUES (?, ?, ?)', [$id, $label, (int) $default], ['default' => \PDO::PARAM_BOOL]);
}
+
+ /**
+ * @param array $collection
+ *
+ * @throws \Doctrine\DBAL\DBALException
+ */
+ private function createEventStoreEvents(array $collection): void
+ {
+ foreach ($collection as $class => $translation) {
+ $this->connection->insert('event_store_event', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'event_class' => $class,
+ 'translation_key' => $translation,
+ ]);
+ }
+ }
}
diff --git a/module/attribute/src/Application/Form/Model/AttributeOptionModel.php b/module/attribute/src/Application/Form/Model/AttributeOptionModel.php
index c81e0d040..35b2ec36a 100644
--- a/module/attribute/src/Application/Form/Model/AttributeOptionModel.php
+++ b/module/attribute/src/Application/Form/Model/AttributeOptionModel.php
@@ -19,7 +19,7 @@ class AttributeOptionModel
* @var string
*
* @Assert\NotBlank(message="Option code is required")
- * @Assert\Length(max=128, maxMessage="Option code is to long,. It should have {{ limit }} character or less.")
+ * @Assert\Length(max=128, maxMessage="Option code is to long. It should have {{ limit }} character or less.")
*/
public $key;
diff --git a/module/attribute/src/Application/Form/Model/AttributeParametersModel.php b/module/attribute/src/Application/Form/Model/AttributeParametersModel.php
index 7b67345cc..f36a36917 100644
--- a/module/attribute/src/Application/Form/Model/AttributeParametersModel.php
+++ b/module/attribute/src/Application/Form/Model/AttributeParametersModel.php
@@ -10,7 +10,6 @@
namespace Ergonode\Attribute\Application\Form\Model;
/**
- * Class AttributeParametersModel
*/
class AttributeParametersModel
{
diff --git a/module/attribute/src/Application/Form/Model/CreateAttributeFormModel.php b/module/attribute/src/Application/Form/Model/CreateAttributeFormModel.php
index edbf43dd1..292e43913 100644
--- a/module/attribute/src/Application/Form/Model/CreateAttributeFormModel.php
+++ b/module/attribute/src/Application/Form/Model/CreateAttributeFormModel.php
@@ -55,7 +55,7 @@ class CreateAttributeFormModel
*
* @Assert\All({
* @Assert\NotBlank(),
- * @Assert\Length(max=4000, maxMessage="Attribute placeholder is to long, It should have {{ limit }} character or less.")
+ * @Assert\Length(max=4000, maxMessage="Attribute placeholder is to long. It should have {{ limit }} character or less.")
* })
*/
public $placeholder;
@@ -65,7 +65,7 @@ class CreateAttributeFormModel
*
* @Assert\All({
* @Assert\NotBlank(),
- * @Assert\Length(max=4000, maxMessage="Attribute hint is to long,. It should have {{ limit }} character or less.")
+ * @Assert\Length(max=4000, maxMessage="Attribute hint is to long. It should have {{ limit }} character or less.")
* })
*/
public $hint;
diff --git a/module/attribute/src/Application/Form/Model/UpdateAttributeFormModel.php b/module/attribute/src/Application/Form/Model/UpdateAttributeFormModel.php
index 14389e87d..da4d551b3 100644
--- a/module/attribute/src/Application/Form/Model/UpdateAttributeFormModel.php
+++ b/module/attribute/src/Application/Form/Model/UpdateAttributeFormModel.php
@@ -32,7 +32,7 @@ class UpdateAttributeFormModel
*
* @Assert\All({
* @Assert\NotBlank(),
- * @Assert\Length(max=32, maxMessage="Attribute name is to long, It should have {{ limit }} character or less.")
+ * @Assert\Length(max=32, maxMessage="Attribute name is to long. It should have {{ limit }} character or less.")
* })
*/
public $label;
@@ -42,7 +42,7 @@ class UpdateAttributeFormModel
*
* @Assert\All({
* @Assert\NotBlank(),
- * @Assert\Length(max=4000, maxMessage="Attribute placeholder is to long, It should have {{ limit }} character or less.")
+ * @Assert\Length(max=4000, maxMessage="Attribute placeholder is to long. It should have {{ limit }} character or less.")
* })
*/
public $placeholder;
@@ -52,7 +52,7 @@ class UpdateAttributeFormModel
*
* @Assert\All({
* @Assert\NotBlank(),
- * @Assert\Length(max=4000, maxMessage="Attribute hint is to long,. It should have {{ limit }} character or less.")
+ * @Assert\Length(max=4000, maxMessage="Attribute hint is to long. It should have {{ limit }} character or less.")
* })
*/
public $hint;
diff --git a/module/attribute/src/Domain/Command/DeleteAttributeCommand.php b/module/attribute/src/Domain/Command/DeleteAttributeCommand.php
index b5eb61d75..976b0621e 100644
--- a/module/attribute/src/Domain/Command/DeleteAttributeCommand.php
+++ b/module/attribute/src/Domain/Command/DeleteAttributeCommand.php
@@ -12,7 +12,6 @@
use Ergonode\Attribute\Domain\Entity\AttributeId;
/**
- * Class DeleteAttributeCommand
*/
class DeleteAttributeCommand
{
diff --git a/module/attribute/src/Domain/Entity/AbstractAttribute.php b/module/attribute/src/Domain/Entity/AbstractAttribute.php
index 5c61c04fe..b2d6e7617 100644
--- a/module/attribute/src/Domain/Entity/AbstractAttribute.php
+++ b/module/attribute/src/Domain/Entity/AbstractAttribute.php
@@ -18,7 +18,7 @@
use Ergonode\Attribute\Domain\Event\Attribute\AttributePlaceholderChangedEvent;
use Ergonode\Attribute\Domain\Event\Attribute\AttributeSystemChangedEvent;
use Ergonode\Attribute\Domain\Event\AttributeGroupAddedEvent;
-use Ergonode\Attribute\Domain\Event\AttributeGroupRemovedEvent;
+use Ergonode\Attribute\Domain\Event\AttributeGroupDeletedEvent;
use Ergonode\Attribute\Domain\ValueObject\AttributeCode;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\Core\Domain\ValueObject\TranslatableString;
@@ -256,7 +256,7 @@ public function addGroup(AttributeGroupId $groupId): void
public function removeGroup(AttributeGroupId $groupId): void
{
if ($this->inGroup($groupId)) {
- $this->apply(new AttributeGroupRemovedEvent($groupId));
+ $this->apply(new AttributeGroupDeletedEvent($groupId));
}
}
@@ -322,9 +322,9 @@ protected function applyAttributeGroupAddedEvent(AttributeGroupAddedEvent $event
}
/**
- * @param AttributeGroupRemovedEvent $event
+ * @param AttributeGroupDeletedEvent $event
*/
- protected function applyAttributeGroupRemovedEvent(AttributeGroupRemovedEvent $event): void
+ protected function applyAttributeGroupDeletedEvent(AttributeGroupDeletedEvent $event): void
{
unset($this->groups[$event->getGroupId()->getValue()]);
}
diff --git a/module/attribute/src/Domain/Event/AttributeGroupRemovedEvent.php b/module/attribute/src/Domain/Event/AttributeGroupDeletedEvent.php
similarity index 92%
rename from module/attribute/src/Domain/Event/AttributeGroupRemovedEvent.php
rename to module/attribute/src/Domain/Event/AttributeGroupDeletedEvent.php
index 7096d875f..46de60f91 100644
--- a/module/attribute/src/Domain/Event/AttributeGroupRemovedEvent.php
+++ b/module/attribute/src/Domain/Event/AttributeGroupDeletedEvent.php
@@ -15,7 +15,7 @@
/**
*/
-class AttributeGroupRemovedEvent implements DomainEventInterface
+class AttributeGroupDeletedEvent implements DomainEventInterface
{
/**
* @var AttributeGroupId
diff --git a/module/attribute/src/Domain/Factory/MultiSelectAttributeFactory.php b/module/attribute/src/Domain/Factory/MultiSelectAttributeFactory.php
index 6d36914dd..0706426d7 100644
--- a/module/attribute/src/Domain/Factory/MultiSelectAttributeFactory.php
+++ b/module/attribute/src/Domain/Factory/MultiSelectAttributeFactory.php
@@ -56,7 +56,8 @@ public function create(CreateAttributeCommand $command): AbstractAttribute
$option = new StringOption('');
}
}
- $attribute->addOption(new OptionKey($key), $option);
+
+ $attribute->addOption(new OptionKey((string) $key), $option);
}
return $attribute;
diff --git a/module/attribute/src/Domain/Factory/SelectAttributeFactory.php b/module/attribute/src/Domain/Factory/SelectAttributeFactory.php
index 4245135e6..06d255c81 100644
--- a/module/attribute/src/Domain/Factory/SelectAttributeFactory.php
+++ b/module/attribute/src/Domain/Factory/SelectAttributeFactory.php
@@ -56,7 +56,8 @@ public function create(CreateAttributeCommand $command): AbstractAttribute
$option = new StringOption('');
}
}
- $attribute->addOption(new OptionKey($key), $option);
+
+ $attribute->addOption(new OptionKey((string) $key), $option);
}
return $attribute;
diff --git a/module/attribute/src/Domain/Query/AttributeQueryInterface.php b/module/attribute/src/Domain/Query/AttributeQueryInterface.php
index 9e868046d..4f7f84986 100644
--- a/module/attribute/src/Domain/Query/AttributeQueryInterface.php
+++ b/module/attribute/src/Domain/Query/AttributeQueryInterface.php
@@ -51,6 +51,20 @@ public function getAttribute(AttributeId $attributeId): ?array;
*/
public function getAllAttributeCodes(): array;
+ /**
+ * @param array $types
+ *
+ * @return string[]
+ */
+ public function getDictionary(array $types = []): array;
+
+ /**
+ * @param array $types
+ *
+ * @return array
+ */
+ public function getAttributeCodes(array $types = []): array;
+
/**
* @param AttributeId $attributeId
*
diff --git a/module/attribute/src/Infrastructure/Validator/AttributeExistsValidator.php b/module/attribute/src/Infrastructure/Validator/AttributeExistsValidator.php
index b870685f5..30a1fbddc 100644
--- a/module/attribute/src/Infrastructure/Validator/AttributeExistsValidator.php
+++ b/module/attribute/src/Infrastructure/Validator/AttributeExistsValidator.php
@@ -54,7 +54,10 @@ public function validate($value, Constraint $constraint): void
$value = (string) $value;
- $attribute = $this->attributeRepository->load(new AttributeId($value));
+ $attribute = false;
+ if (AttributeId::isValid($value)) {
+ $attribute = $this->attributeRepository->load(new AttributeId($value));
+ }
if (!$attribute) {
$this->context->buildViolation($constraint->message)
diff --git a/module/attribute/src/Persistence/Dbal/Projector/AttributeArrayParameterChangeEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/AttributeArrayParameterChangeEventProjector.php
index bafc4d86c..f31c0dc4c 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/AttributeArrayParameterChangeEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/AttributeArrayParameterChangeEventProjector.php
@@ -13,9 +13,9 @@
use Ergonode\Attribute\Domain\Event\Attribute\AttributeArrayParameterChangeEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
+use JMS\Serializer\SerializerInterface;
/**
*/
@@ -29,17 +29,22 @@ class AttributeArrayParameterChangeEventProjector implements DomainEventProjecto
private $connection;
/**
- * @param Connection $connection
+ * @var SerializerInterface
*/
- public function __construct(Connection $connection)
+ private $serializer;
+
+ /**
+ * @param Connection $connection
+ * @param SerializerInterface $serializer
+ */
+ public function __construct(Connection $connection, SerializerInterface $serializer)
{
$this->connection = $connection;
+ $this->serializer = $serializer;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -47,12 +52,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -60,24 +60,17 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributeArrayParameterChangeEvent::class);
}
- try {
- $this->connection->beginTransaction();
- if (!empty($event->getTo())) {
- $this->connection->update(
- self::TABLE_PARAMETER,
- [
- 'value' => \json_encode($event->getTo()),
- ],
- [
- 'attribute_id' => $aggregateId->getValue(),
- 'type' => $event->getName(),
- ]
- );
- }
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
+ if (!empty($event->getTo())) {
+ $this->connection->update(
+ self::TABLE_PARAMETER,
+ [
+ 'value' => $this->serializer->serialize($event->getTo(), 'json'),
+ ],
+ [
+ 'attribute_id' => $aggregateId->getValue(),
+ 'type' => $event->getName(),
+ ]
+ );
}
}
}
diff --git a/module/attribute/src/Persistence/Dbal/Projector/AttributeCreatedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/AttributeCreatedEventProjector.php
index d575f5c97..f0017068a 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/AttributeCreatedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/AttributeCreatedEventProjector.php
@@ -13,9 +13,9 @@
use Ergonode\Attribute\Domain\Event\Attribute\AttributeCreatedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
+use JMS\Serializer\SerializerInterface;
use Ramsey\Uuid\Uuid;
/**
@@ -33,17 +33,22 @@ class AttributeCreatedEventProjector implements DomainEventProjectorInterface
private $connection;
/**
- * @param Connection $connection
+ * @var SerializerInterface
*/
- public function __construct(Connection $connection)
+ private $serializer;
+
+ /**
+ * @param Connection $connection
+ * @param SerializerInterface $serializer
+ */
+ public function __construct(Connection $connection, SerializerInterface $serializer)
{
$this->connection = $connection;
+ $this->serializer = $serializer;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -51,12 +56,9 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
+ * {@inheritDoc}
*
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * @throws \Throwable
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -64,8 +66,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributeCreatedEvent::class);
}
- try {
- $this->connection->beginTransaction();
+ $this->connection->transactional(function () use ($aggregateId, $event) {
$labelUuid = Uuid::uuid4();
$placeholderUuid = Uuid::uuid4();
$hintUuid = Uuid::uuid4();
@@ -152,15 +153,11 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
[
'attribute_id' => $aggregateId->getValue(),
'type' => $name,
- 'value' => \json_encode($value),
+ 'value' => $this->serializer->serialize($value, 'json'),
]
);
}
}
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ });
}
}
diff --git a/module/attribute/src/Persistence/Dbal/Projector/AttributeHintChangedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/AttributeHintChangedEventProjector.php
index 1ab535c81..792983352 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/AttributeHintChangedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/AttributeHintChangedEventProjector.php
@@ -13,7 +13,6 @@
use Ergonode\Attribute\Domain\Event\Attribute\AttributeHintChangedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
use Ramsey\Uuid\Uuid;
@@ -38,9 +37,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -48,12 +45,9 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
+ * {@inheritDoc}
*
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * @throws \Throwable
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -61,8 +55,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributeHintChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
+ $this->connection->transactional(function () use ($aggregateId, $event) {
$from = $event->getFrom()->getTranslations();
$to = $event->getTo()->getTranslations();
@@ -102,11 +95,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
);
}
}
- $this->connection->commit();
- } catch (\Exception $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ });
}
/**
diff --git a/module/attribute/src/Persistence/Dbal/Projector/AttributeLabelChangedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/AttributeLabelChangedEventProjector.php
index 5bf051356..a4f6c4a5b 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/AttributeLabelChangedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/AttributeLabelChangedEventProjector.php
@@ -13,7 +13,6 @@
use Ergonode\Attribute\Domain\Event\Attribute\AttributeLabelChangedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
use Ramsey\Uuid\Uuid;
@@ -38,9 +37,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -48,12 +45,9 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
+ * {@inheritDoc}
*
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * @throws \Throwable
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -64,8 +58,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
$from = $event->getFrom()->getTranslations();
$to = $event->getTo()->getTranslations();
- try {
- $this->connection->beginTransaction();
+ $this->connection->transactional(function () use ($aggregateId, $to, $from) {
foreach ($to as $language => $value) {
$result = $this->connection->update(
self::TABLE,
@@ -102,11 +95,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
);
}
}
- $this->connection->commit();
- } catch (\Exception $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ });
}
/**
diff --git a/module/attribute/src/Persistence/Dbal/Projector/AttributeParameterChangeEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/AttributeParameterChangeEventProjector.php
index 296124ecb..7f2eaaec4 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/AttributeParameterChangeEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/AttributeParameterChangeEventProjector.php
@@ -13,9 +13,9 @@
use Ergonode\Attribute\Domain\Event\Attribute\AttributeParameterChangeEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
+use JMS\Serializer\SerializerInterface;
/**
*/
@@ -29,17 +29,22 @@ class AttributeParameterChangeEventProjector implements DomainEventProjectorInte
private $connection;
/**
- * @param Connection $connection
+ * @var SerializerInterface
*/
- public function __construct(Connection $connection)
+ private $serializer;
+
+ /**
+ * @param Connection $connection
+ * @param SerializerInterface $serializer
+ */
+ public function __construct(Connection $connection, SerializerInterface $serializer)
{
$this->connection = $connection;
+ $this->serializer = $serializer;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -47,12 +52,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -60,24 +60,17 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributeParameterChangeEvent::class);
}
- try {
- $this->connection->beginTransaction();
- if (!empty($event->getTo())) {
- $this->connection->update(
- self::TABLE_PARAMETER,
- [
- 'value' => \json_encode($event->getTo()),
- ],
- [
- 'attribute_id' => $aggregateId->getValue(),
- 'type' => $event->getName(),
- ]
- );
- }
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
+ if (!empty($event->getTo())) {
+ $this->connection->update(
+ self::TABLE_PARAMETER,
+ [
+ 'value' => $this->serializer->serialize($event->getTo(), 'json'),
+ ],
+ [
+ 'attribute_id' => $aggregateId->getValue(),
+ 'type' => $event->getName(),
+ ]
+ );
}
}
}
diff --git a/module/attribute/src/Persistence/Dbal/Projector/AttributePlaceholderChangedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/AttributePlaceholderChangedEventProjector.php
index fce823842..5a1408c9b 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/AttributePlaceholderChangedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/AttributePlaceholderChangedEventProjector.php
@@ -13,7 +13,6 @@
use Ergonode\Attribute\Domain\Event\Attribute\AttributePlaceholderChangedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
use Ramsey\Uuid\Uuid;
@@ -38,9 +37,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -48,12 +45,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -61,12 +53,10 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributePlaceholderChangedEvent::class);
}
-
$from = $event->getFrom()->getTranslations();
$to = $event->getTo()->getTranslations();
- try {
- $this->connection->beginTransaction();
+ $this->connection->transactional(function () use ($aggregateId, $from, $to) {
foreach ($to as $language => $value) {
$result = $this->connection->update(
self::TABLE,
@@ -103,11 +93,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
);
}
}
- $this->connection->commit();
- } catch (\Exception $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ });
}
/**
diff --git a/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupAddedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupAddedEventProjector.php
index a9efd5c43..87f015525 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupAddedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupAddedEventProjector.php
@@ -13,7 +13,6 @@
use Ergonode\Attribute\Domain\Event\AttributeGroupAddedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
@@ -37,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -47,12 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -60,19 +52,12 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributeGroupAddedEvent::class);
}
- try {
- $this->connection->beginTransaction();
- $this->connection->insert(
- self::TABLE,
- [
- 'attribute_id' => $aggregateId->getValue(),
- 'attribute_group_id' => $event->getGroupId()->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ $this->connection->insert(
+ self::TABLE,
+ [
+ 'attribute_id' => $aggregateId->getValue(),
+ 'attribute_group_id' => $event->getGroupId()->getValue(),
+ ]
+ );
}
}
diff --git a/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupCreatedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupCreatedEventProjector.php
index 9c32f6234..f7d16eef8 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupCreatedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupCreatedEventProjector.php
@@ -36,9 +36,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -46,10 +44,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws \Exception
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -57,21 +52,13 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributeGroupCreatedEvent::class);
}
- try {
- $this->connection->beginTransaction();
- $this->connection->insert(
- self::TABLE,
- [
- 'id' => $aggregateId->getValue(),
- 'label' => $event->getLabel(),
+ $this->connection->insert(
+ self::TABLE,
+ [
+ 'id' => $aggregateId->getValue(),
+ 'label' => $event->getLabel(),
- ]
- );
- $this->connection->commit();
- } catch (\Exception $exception) {
- $this->connection->rollBack();
-
- throw $exception;
- }
+ ]
+ );
}
}
diff --git a/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupRemovedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupRemovedEventProjector.php
index b102ae270..c271488c5 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupRemovedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/Group/AttributeGroupRemovedEventProjector.php
@@ -10,10 +10,9 @@
namespace Ergonode\Attribute\Persistence\Dbal\Projector\Group;
use Doctrine\DBAL\Connection;
-use Ergonode\Attribute\Domain\Event\AttributeGroupRemovedEvent;
+use Ergonode\Attribute\Domain\Event\AttributeGroupDeletedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
@@ -37,42 +36,28 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
- return $event instanceof AttributeGroupRemovedEvent;
+ return $event instanceof AttributeGroupDeletedEvent;
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
- if (!$event instanceof AttributeGroupRemovedEvent) {
- throw new UnsupportedEventException($event, AttributeGroupRemovedEvent::class);
+ if (!$event instanceof AttributeGroupDeletedEvent) {
+ throw new UnsupportedEventException($event, AttributeGroupDeletedEvent::class);
}
- try {
- $this->connection->beginTransaction();
- $this->connection->delete(
- self::TABLE,
- [
- 'attribute_id' => $aggregateId->getValue(),
- 'attribute_group_id' => $event->getGroupId()->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ $this->connection->delete(
+ self::TABLE,
+ [
+ 'attribute_id' => $aggregateId->getValue(),
+ 'attribute_group_id' => $event->getGroupId()->getValue(),
+ ]
+ );
}
}
diff --git a/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionAddedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionAddedEventProjector.php
index 43b48b0ba..31388780e 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionAddedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionAddedEventProjector.php
@@ -17,7 +17,6 @@
use Ergonode\Attribute\Domain\ValueObject\OptionValue\StringOption;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
use Ramsey\Uuid\Uuid;
@@ -43,9 +42,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -53,12 +50,9 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
+ * {@inheritDoc}
*
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * @throws \Throwable
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -66,8 +60,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributeOptionAddedEvent::class);
}
- try {
- $this->connection->beginTransaction();
+ $this->connection->transactional(function () use ($aggregateId, $event) {
$valueId = Uuid::uuid4()->toString();
$this->connection->insert(
@@ -80,11 +73,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
);
$this->insertOption($valueId, $event->getOption());
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ });
}
/**
diff --git a/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionChangedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionChangedEventProjector.php
index e1ceaee4e..73c2a66c5 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionChangedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionChangedEventProjector.php
@@ -17,7 +17,6 @@
use Ergonode\Attribute\Domain\ValueObject\OptionValue\StringOption;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
use Ramsey\Uuid\Uuid;
@@ -52,6 +51,8 @@ public function support(DomainEventInterface $event): bool
/**
* {@inheritDoc}
+ *
+ * @throws \Throwable
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -59,8 +60,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, AttributeOptionChangedEvent::class);
}
- $this->connection->beginTransaction();
- try {
+ $this->connection->transactional(function () use ($aggregateId, $event) {
$valueId = Uuid::uuid4()->toString();
$attributeId = $aggregateId->getValue();
@@ -76,12 +76,7 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
);
$this->insertOption($valueId, $event->getTo());
-
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ });
}
/**
diff --git a/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionRemovedEventProjector.php b/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionRemovedEventProjector.php
index 088541bb4..520ccf27e 100644
--- a/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionRemovedEventProjector.php
+++ b/module/attribute/src/Persistence/Dbal/Projector/Option/AttributeOptionRemovedEventProjector.php
@@ -37,9 +37,7 @@ public function __construct(Connection $connection)
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -47,12 +45,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws DBALException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\Exception\InvalidArgumentException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
diff --git a/module/attribute/src/Persistence/Dbal/Query/DbalAttributeGroupQuery.php b/module/attribute/src/Persistence/Dbal/Query/DbalAttributeGroupQuery.php
index f21d11844..fa9524ca3 100644
--- a/module/attribute/src/Persistence/Dbal/Query/DbalAttributeGroupQuery.php
+++ b/module/attribute/src/Persistence/Dbal/Query/DbalAttributeGroupQuery.php
@@ -54,7 +54,8 @@ public function getAttributeGroups(): array
public function getDataSet(Language $language): DataSetInterface
{
$query = $this->connection->createQueryBuilder();
- $query->select('*')
+ $query
+ ->select('*')
->from(sprintf('(%s)', $this->getSQL()), 't');
return new DbalDataSet($query);
diff --git a/module/attribute/src/Persistence/Dbal/Query/DbalAttributeQuery.php b/module/attribute/src/Persistence/Dbal/Query/DbalAttributeQuery.php
index cd5f5f427..fcae2fb47 100644
--- a/module/attribute/src/Persistence/Dbal/Query/DbalAttributeQuery.php
+++ b/module/attribute/src/Persistence/Dbal/Query/DbalAttributeQuery.php
@@ -198,12 +198,49 @@ public function checkAttributeExistsByCode(AttributeCode $code): bool
*/
public function getAllAttributeCodes(): array
{
- return $this->getQuery()
- ->select('code')
+ return $this->getAttributeCodes();
+ }
+
+ /**
+ * @param array $types
+ *
+ * @return string[]
+ */
+ public function getAttributeCodes(array $types = []): array
+ {
+ $qb = $this->getQuery()
+ ->select('code');
+
+ if ($types) {
+ $qb->andWhere($qb->expr()->in('type', ':types'))
+ ->setParameter(':types', $types, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
+ }
+
+ return $qb
->execute()
->fetchAll(\PDO::FETCH_COLUMN);
}
+ /**
+ * @param array $types
+ *
+ * @return string[]
+ */
+ public function getDictionary(array $types = []): array
+ {
+ $qb = $this->getQuery()
+ ->select('id, code');
+
+ if ($types) {
+ $qb->andWhere($qb->expr()->in('type', ':types'))
+ ->setParameter(':types', $types, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
+ }
+
+ return $qb
+ ->execute()
+ ->fetchAll(\PDO::FETCH_KEY_PAIR);
+ }
+
/**
* @param AttributeId $attributeId
*
diff --git a/module/attribute/src/Persistence/Dbal/Query/Decorator/CacheAttributeQueryDecorator.php b/module/attribute/src/Persistence/Dbal/Query/Decorator/CacheAttributeQueryDecorator.php
index f8fbe4e63..cdfaf6d66 100644
--- a/module/attribute/src/Persistence/Dbal/Query/Decorator/CacheAttributeQueryDecorator.php
+++ b/module/attribute/src/Persistence/Dbal/Query/Decorator/CacheAttributeQueryDecorator.php
@@ -113,6 +113,16 @@ public function getAllAttributeCodes(): array
return $this->attributeQuery->getAllAttributeCodes();
}
+ /**
+ * @param array $types
+ *
+ * @return array
+ */
+ public function getAttributeCodes(array $types = []): array
+ {
+ return $this->attributeQuery->getAttributeCodes($types);
+ }
+
/**
* @param AttributeId $id
* @param OptionKey $key
@@ -123,4 +133,14 @@ public function findAttributeOption(AttributeId $id, OptionKey $key): ?OptionInt
{
return $this->attributeQuery->findAttributeOption($id, $key);
}
+
+ /**
+ * @param array $types
+ *
+ * @return array
+ */
+ public function getDictionary(array $types = []): array
+ {
+ return $this->attributeQuery->getDictionary($types);
+ }
}
diff --git a/module/attribute/src/Resources/translations/log.en.yaml b/module/attribute/src/Resources/translations/log.en.yaml
index b4a911951..e78982de6 100644
--- a/module/attribute/src/Resources/translations/log.en.yaml
+++ b/module/attribute/src/Resources/translations/log.en.yaml
@@ -1,12 +1,12 @@
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeCreatedEvent": Attribute "%code%" added
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeHintChangedEvent": Attribute hint changed
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeLabelChangedEvent": Attribute label changed
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributePlaceholderChangedEvent": Attribute placeholder changed
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeArrayParameterChangeEvent": Attribute parameters changed
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeParameterChangeEvent": Attribute parameter changed
-"Ergonode\\Attribute\\Domain\\Event\\AttributeGroupAddedEvent": Attribute added to group
-"Ergonode\\Attribute\\Domain\\Event\\AttributeGroupRemovedEvent": Attribute removed from group
-"Ergonode\\Attribute\\Domain\\Event\\AttributeOptionAddedEvent": Attribute option "%key%" added
-"Ergonode\\Attribute\\Domain\\Event\\AttributeOptionRemovedEvent": Attribute option "%key%" removed
-"Ergonode\\Attribute\\Domain\\Event\\AttributeOptionChangedEvent": Attribute option "%key%" changed
+'Attribute added': 'Attribute "%code%" added'
+'Attribute hint changed': 'Attribute hint changed'
+'Attribute label changed': 'Attribute label changed'
+'Attribute placeholder changed': 'Attribute placeholder changed'
+'Attribute parameters changed': 'Attribute parameters changed'
+'Attribute parameter changed': 'Attribute parameter changed'
+'Attribute added to group': 'Attribute added to group'
+'Attribute removed from group': 'Attribute removed from group'
+'Attribute option added': 'Attribute option "%key%" added'
+'Attribute option removed': 'Attribute option "%key%" removed'
+'Attribute option changed': 'Attribute option "%key%" changed'
diff --git a/module/attribute/src/Resources/translations/log.pl.yaml b/module/attribute/src/Resources/translations/log.pl.yaml
index 1327bca5c..a3549da52 100644
--- a/module/attribute/src/Resources/translations/log.pl.yaml
+++ b/module/attribute/src/Resources/translations/log.pl.yaml
@@ -1,12 +1,12 @@
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeCreatedEvent": Atrybut "%code%" został dodany
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeHintChangedEvent": Wartość podpowiedzi dla atrybutu została zmieniona
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeLabelChangedEvent": Nazwa atrybutu została zmieniona
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributePlaceholderChangedEvent": Wartość wskazówki dla atrybutu została zmieniona
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeArrayParameterChangeEvent": Ustawienia atrybutu zostały zmienione
-"Ergonode\\Attribute\\Domain\\Event\\Attribute\\AttributeParameterChangeEvent": Ustawienia atrybutu zostały zmieniona
-"Ergonode\\Attribute\\Domain\\Event\\AttributeGroupAddedEvent": Atrybut dodany do grupy
-"Ergonode\\Attribute\\Domain\\Event\\AttributeGroupRemovedEvent": Atrybut usunięty z grupy
-"Ergonode\\Attribute\\Domain\\Event\\AttributeOptionAddedEvent": Opcja atrybutu "%key%" została dodana
-"Ergonode\\Attribute\\Domain\\Event\\AttributeOptionRemovedEvent": Opcja atrybutu "%key%" została zmieniona
-"Ergonode\\Attribute\\Domain\\Event\\AttributeOptionChangedEvent": Opcja atrybutu "%key%" została usunięta
+'Attribute added': 'Atrybut "%code%" został dodany'
+'Attribute hint changed': 'Wartość podpowiedzi dla atrybutu została zmieniona'
+'Attribute label changed': 'Nazwa atrybutu została zmieniona'
+'Attribute placeholder changed': 'Wartość wskazówki dla atrybutu została zmieniona'
+'Attribute parameters changed': 'Ustawienia atrybutu zostały zmienione'
+'Attribute parameter changed': 'Ustawienia atrybutu zostały zmieniona'
+'Attribute added to group': 'Atrybut dodany do grupy'
+'Attribute removed from group': 'Atrybut usunięty z grupy'
+'Attribute option added': 'Opcja atrybutu "%key%" została dodana'
+'Attribute option removed': 'Opcja atrybutu "%key%" została zmieniona'
+'Attribute option changed': 'Opcja atrybutu "%key%" została usunięta'
diff --git a/module/attribute/tests/Domain/Event/AttributeGroupRemovedEventTest.php b/module/attribute/tests/Domain/Event/AttributeGroupDeletedEventTest.php
similarity index 75%
rename from module/attribute/tests/Domain/Event/AttributeGroupRemovedEventTest.php
rename to module/attribute/tests/Domain/Event/AttributeGroupDeletedEventTest.php
index 6fe8915a7..3b224c2ef 100644
--- a/module/attribute/tests/Domain/Event/AttributeGroupRemovedEventTest.php
+++ b/module/attribute/tests/Domain/Event/AttributeGroupDeletedEventTest.php
@@ -10,12 +10,12 @@
namespace Ergonode\Attribute\Tests\Domain\Event;
use Ergonode\Attribute\Domain\Entity\AttributeGroupId;
-use Ergonode\Attribute\Domain\Event\AttributeGroupRemovedEvent;
+use Ergonode\Attribute\Domain\Event\AttributeGroupDeletedEvent;
use PHPUnit\Framework\TestCase;
/**
*/
-class AttributeGroupRemovedEventTest extends TestCase
+class AttributeGroupDeletedEventTest extends TestCase
{
/**
*/
@@ -23,7 +23,7 @@ public function testEventCreation(): void
{
/** @var AttributeGroupId $groupId */
$groupId = $this->createMock(AttributeGroupId::class);
- $event = new AttributeGroupRemovedEvent($groupId);
+ $event = new AttributeGroupDeletedEvent($groupId);
$this->assertEquals($groupId, $event->getGroupId());
}
}
diff --git a/module/authentication/composer.json b/module/authentication/composer.json
index b4b93bc9f..d513eed49 100644
--- a/module/authentication/composer.json
+++ b/module/authentication/composer.json
@@ -8,8 +8,8 @@
"php": "^7.2",
"doctrine/dbal": "^2.9",
"doctrine/orm": "^2.6",
- "ergonode/api": "^0.4.0",
- "ergonode/core": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/core": "^0.5.0",
"friendsofsymfony/rest-bundle": "^2.5",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
diff --git a/module/category-tree/composer.json b/module/category-tree/composer.json
index d925afa33..79898791c 100644
--- a/module/category-tree/composer.json
+++ b/module/category-tree/composer.json
@@ -7,10 +7,10 @@
"require": {
"php": "^7.2",
"doctrine/dbal": "^2.9",
- "ergonode/api": "^0.4.0",
- "ergonode/category": "^0.4.0",
- "ergonode/es": "^0.4.0",
- "ergonode/migration": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/category": "^0.5.0",
+ "ergonode/es": "^0.5.0",
+ "ergonode/migration": "^0.5.0",
"friendsofsymfony/rest-bundle": "^2.5",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
diff --git a/module/category-tree/migrations/Version20180619083700.php b/module/category-tree/migrations/Version20180619083700.php
index bbe705848..81801b82d 100644
--- a/module/category-tree/migrations/Version20180619083700.php
+++ b/module/category-tree/migrations/Version20180619083700.php
@@ -18,17 +18,43 @@ final class Version20180619083700 extends AbstractErgonodeMigration
*/
public function up(Schema $schema): void
{
- $this->addSql(
- 'CREATE TABLE IF NOT EXISTS tree (
- id UUID NOT NULL,
- code VARCHAR(64) NOT NULL,
- name JSONB NOT NULL,
- PRIMARY KEY(id))'
- );
+ $this->addSql('
+ CREATE TABLE IF NOT EXISTS tree (
+ id UUID NOT NULL,
+ code VARCHAR(64) NOT NULL,
+ name JSONB NOT NULL,
+ PRIMARY KEY(id)
+ )
+ ');
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'CATEGORY_TREE_CREATE', 'Category tree']);
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'CATEGORY_TREE_READ', 'Category tree']);
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'CATEGORY_TREE_UPDATE', 'Category tree']);
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'CATEGORY_TREE_DELETE', 'Category tree']);
+
+ $this->createEventStoreEvents([
+ 'Ergonode\CategoryTree\Domain\Event\CategoryTreeCategoriesChangedEvent' => 'Categories changed on category tree',
+ 'Ergonode\CategoryTree\Domain\Event\CategoryTreeCategoryAddedEvent' => 'Category added to category tree',
+ 'Ergonode\CategoryTree\Domain\Event\CategoryTreeCategoryRemovedEvent' => 'Category removed from category tree',
+ 'Ergonode\CategoryTree\Domain\Event\CategoryTreeCreatedEvent' => 'Category tree created',
+ 'Ergonode\CategoryTree\Domain\Event\CategoryTreeNameChangedEvent' => 'Category tree name changed',
+ 'Ergonode\CategoryTree\Domain\Event\CategoryTreeDeletedEvent' => 'Category tree deleted',
+ ]);
+ }
+
+ /**
+ * @param array $collection
+ *
+ * @throws \Doctrine\DBAL\DBALException
+ */
+ private function createEventStoreEvents(array $collection): void
+ {
+ foreach ($collection as $class => $translation) {
+ $this->connection->insert('event_store_event', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'event_class' => $class,
+ 'translation_key' => $translation,
+ ]);
+ }
}
}
diff --git a/module/category-tree/src/Application/Controller/Api/CategoryTreeController.php b/module/category-tree/src/Application/Controller/Api/CategoryTreeController.php
index 500dcd21f..ddfd64492 100644
--- a/module/category-tree/src/Application/Controller/Api/CategoryTreeController.php
+++ b/module/category-tree/src/Application/Controller/Api/CategoryTreeController.php
@@ -13,13 +13,12 @@
use Ergonode\Api\Application\Response\CreatedResponse;
use Ergonode\Api\Application\Response\EmptyResponse;
use Ergonode\Api\Application\Response\SuccessResponse;
-use Ergonode\Category\Domain\Entity\CategoryId;
use Ergonode\CategoryTree\Application\Form\CategoryTreeCreateForm;
use Ergonode\CategoryTree\Application\Form\CategoryTreeUpdateForm;
use Ergonode\CategoryTree\Application\Model\CategoryTreeCreateFormModel;
use Ergonode\CategoryTree\Application\Model\CategoryTreeUpdateFormModel;
-use Ergonode\CategoryTree\Domain\Command\AddCategoryCommand;
use Ergonode\CategoryTree\Domain\Command\CreateTreeCommand;
+use Ergonode\CategoryTree\Domain\Command\DeleteTreeCommand;
use Ergonode\CategoryTree\Domain\Command\UpdateTreeCommand;
use Ergonode\CategoryTree\Domain\Entity\CategoryTree;
use Ergonode\CategoryTree\Domain\Entity\CategoryTreeId;
@@ -155,9 +154,9 @@ public function getCategories(Language $language, RequestGridConfiguration $conf
}
/**
- * @Route("/trees", methods={"POST"})
+ * @Route("/trees/{tree}", methods={"GET"})
*
- * @IsGranted("CATEGORY_TREE_CREATE")
+ * @IsGranted("CATEGORY_TREE_READ")
*
* @SWG\Tag(name="Tree")
* @SWG\Parameter(
@@ -168,58 +167,46 @@ public function getCategories(Language $language, RequestGridConfiguration $conf
* default="EN",
* description="Language Code",
* )
+ *
* @SWG\Parameter(
- * name="body",
- * in="body",
- * description="Category tree body",
+ * name="tree",
+ * in="path",
+ * type="string",
* required=true,
- * @SWG\Schema(ref="#/definitions/tree_req")
+ * description="tree ID",
+ * )
+ * @SWG\Parameter(
+ * name="language",
+ * in="path",
+ * type="string",
+ * required=true,
+ * description="Language",
* )
* @SWG\Response(
- * response=201,
- * description="Create category tree",
+ * response=200,
+ * description="Returns category tree",
* )
* @SWG\Response(
- * response=400,
- * description="Validation error",
- * @SWG\Schema(ref="#/definitions/error_response")
+ * response=404,
+ * description="Not found",
* )
*
- * @param Request $request
+ * @ParamConverter(class="Ergonode\CategoryTree\Domain\Entity\CategoryTree")
*
- * @return Response
- * @throws \Exception
+ * @param CategoryTree $tree
+ * @param Language $language
*
- * @todo Validation required
+ * @return Response
*/
- public function createTree(Request $request): Response
+ public function getTree(CategoryTree $tree, Language $language): Response
{
- $model = new CategoryTreeCreateFormModel();
- $form = $this->createForm(CategoryTreeCreateForm::class, $model);
-
- $form->handleRequest($request);
-
- if ($form->isSubmitted() && $form->isValid()) {
- $data = $form->getData();
- $tree = $this->treeRepository->exists(CategoryTreeId::fromKey($data->code));
-
- if (!$tree) {
- $command = new CreateTreeCommand(new TranslatableString($data->name), $data->code);
- $this->messageBus->dispatch($command);
-
- return new CreatedResponse($command->getId());
- }
-
- throw new BadRequestHttpException('Tree already exists');
- }
-
- throw new FormValidationHttpException($form);
+ return new SuccessResponse($tree);
}
/**
- * @Route("/trees/{tree}/category/{category}/child", methods={"POST"})
+ * @Route("/trees", methods={"POST"})
*
- * @IsGranted("CATEGORY_CREATE")
+ * @IsGranted("CATEGORY_TREE_CREATE")
*
* @SWG\Tag(name="Tree")
* @SWG\Parameter(
@@ -231,29 +218,15 @@ public function createTree(Request $request): Response
* description="Language Code",
* )
* @SWG\Parameter(
- * name="tree",
- * in="path",
- * type="string",
- * required=true,
- * description="Id of category tree",
- * )
- * @SWG\Parameter(
- * name="category",
- * in="path",
- * type="string",
- * required=true,
- * description="Id of category in tree",
- * )
- * @SWG\Parameter(
- * name="child",
- * in="formData",
- * type="string",
+ * name="body",
+ * in="body",
+ * description="Category tree body",
* required=true,
- * description="Id of added child category",
+ * @SWG\Schema(ref="#/definitions/tree_req")
* )
* @SWG\Response(
- * response=202,
- * description="Action accepted",
+ * response=201,
+ * description="Create category tree",
* )
* @SWG\Response(
* response=400,
@@ -261,29 +234,37 @@ public function createTree(Request $request): Response
* @SWG\Schema(ref="#/definitions/error_response")
* )
*
- * @param string $tree
- * @param string $category
* @param Request $request
*
* @return Response
* @throws \Exception
+ *
+ * @todo Validation required
*/
- public function addCategory(string $tree, string $category, Request $request): Response
+ public function createTree(Request $request): Response
{
- $child = $request->request->get('child');
+ $model = new CategoryTreeCreateFormModel();
+ $form = $this->createForm(CategoryTreeCreateForm::class, $model);
+ $form->handleRequest($request);
- if ($child) {
- $command = new AddCategoryCommand(new CategoryTreeId($tree), new CategoryId($category), new CategoryId($child));
- $this->messageBus->dispatch($command);
+ if ($form->isSubmitted() && $form->isValid()) {
+ $data = $form->getData();
+ $tree = $this->treeRepository->exists(CategoryTreeId::fromKey($data->code));
- return new CreatedResponse($command->getCategoryId());
+ if (!$tree) {
+ $command = new CreateTreeCommand(new TranslatableString($data->name), $data->code);
+ $this->messageBus->dispatch($command);
+
+ return new CreatedResponse($command->getId());
+ }
+
+ throw new BadRequestHttpException('Tree already exists');
}
- throw new BadRequestHttpException();
+ throw new FormValidationHttpException($form);
}
-
/**
- * @Route("/trees/{tree}", methods={"PUT"})
+ * @Route("/trees/{tree}", methods={"PUT"}, requirements={"tree"="[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"})
*
* @IsGranted("CATEGORY_TREE_UPDATE")
*
@@ -350,9 +331,9 @@ public function updateTree(CategoryTree $tree, Request $request): Response
}
/**
- * @Route("/trees/{tree}", methods={"GET"})
+ * @Route("/trees/{tree}", methods={"DELETE"}, requirements={"tree"="[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"})
*
- * @IsGranted("CATEGORY_TREE_READ")
+ * @IsGranted("CATEGORY_TREE_DELETE")
*
* @SWG\Tag(name="Tree")
* @SWG\Parameter(
@@ -363,39 +344,33 @@ public function updateTree(CategoryTree $tree, Request $request): Response
* default="EN",
* description="Language Code",
* )
- *
* @SWG\Parameter(
* name="tree",
* in="path",
- * type="string",
* required=true,
- * description="tree ID",
- * )
- * @SWG\Parameter(
- * name="language",
- * in="path",
* type="string",
- * required=true,
- * description="Language",
+ * description="Tree ID",
* )
* @SWG\Response(
- * response=200,
- * description="Returns import",
+ * response=204,
+ * description="Success"
* )
* @SWG\Response(
* response=404,
- * description="Not found",
+ * description="Not found"
* )
*
* @ParamConverter(class="Ergonode\CategoryTree\Domain\Entity\CategoryTree")
*
* @param CategoryTree $tree
- * @param Language $language
*
* @return Response
*/
- public function getTree(CategoryTree $tree, Language $language): Response
+ public function deleteTree(CategoryTree $tree): Response
{
- return new SuccessResponse($tree);
+ $command = new DeleteTreeCommand($tree->getId());
+ $this->messageBus->dispatch($command);
+
+ return new EmptyResponse();
}
}
diff --git a/module/category-tree/src/Application/Model/CategoryTreeUpdateFormModel.php b/module/category-tree/src/Application/Model/CategoryTreeUpdateFormModel.php
index ea335bfc9..8a6741a41 100644
--- a/module/category-tree/src/Application/Model/CategoryTreeUpdateFormModel.php
+++ b/module/category-tree/src/Application/Model/CategoryTreeUpdateFormModel.php
@@ -28,6 +28,7 @@ class CategoryTreeUpdateFormModel
/**
* @var TreeNodeFormModel[]
*
+ * @Assert\NotBlank()
* @Assert\Valid()
*/
public $categories;
diff --git a/module/category-tree/src/Domain/Command/AddCategoryCommand.php b/module/category-tree/src/Domain/Command/AddCategoryCommand.php
deleted file mode 100644
index 25b5c279f..000000000
--- a/module/category-tree/src/Domain/Command/AddCategoryCommand.php
+++ /dev/null
@@ -1,78 +0,0 @@
-treeId = $treeId;
- $this->categoryId = $categoryId;
- $this->parentId = $parentId;
- }
-
- /**
- * @return CategoryTreeId
- */
- public function getTreeId(): CategoryTreeId
- {
- return $this->treeId;
- }
-
- /**
- * @return CategoryId
- */
- public function getCategoryId(): CategoryId
- {
- return $this->categoryId;
- }
-
- /**
- * @return CategoryId
- */
- public function getParentId(): CategoryId
- {
- return $this->parentId;
- }
-}
diff --git a/module/category-tree/src/Domain/Command/DeleteTreeCommand.php b/module/category-tree/src/Domain/Command/DeleteTreeCommand.php
new file mode 100644
index 000000000..a8236a0b9
--- /dev/null
+++ b/module/category-tree/src/Domain/Command/DeleteTreeCommand.php
@@ -0,0 +1,41 @@
+id = $id;
+ }
+
+ /**
+ * @return CategoryTreeId
+ */
+ public function getId(): CategoryTreeId
+ {
+ return $this->id;
+ }
+}
diff --git a/module/category-tree/src/Domain/Event/CategoryTreeDeletedEvent.php b/module/category-tree/src/Domain/Event/CategoryTreeDeletedEvent.php
new file mode 100644
index 000000000..cac665864
--- /dev/null
+++ b/module/category-tree/src/Domain/Event/CategoryTreeDeletedEvent.php
@@ -0,0 +1,18 @@
+repository->load($command->getTreeId());
+ $categoryTree = $this->repository->load($command->getId());
+ Assert::isInstanceOf($categoryTree, CategoryTree::class, sprintf('Can\'t find category tree with id "%s"', $command->getId()));
- Assert::notNull($tree);
- $tree->addCategory($command->getCategoryId(), $command->getParentId());
-
- $this->repository->save($tree);
+ $this->repository->delete($categoryTree);
}
}
diff --git a/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeCreatedEventProjector.php b/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeCreatedEventProjector.php
index 03c1de2f0..c390e584a 100644
--- a/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeCreatedEventProjector.php
+++ b/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeCreatedEventProjector.php
@@ -13,9 +13,9 @@
use Ergonode\CategoryTree\Domain\Event\CategoryTreeCreatedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
+use JMS\Serializer\SerializerInterface;
/**
*/
@@ -29,17 +29,22 @@ class CategoryTreeCreatedEventProjector implements DomainEventProjectorInterface
protected $connection;
/**
- * @param Connection $connection
+ * @var SerializerInterface
*/
- public function __construct(Connection $connection)
+ private $serializer;
+
+ /**
+ * @param Connection $connection
+ * @param SerializerInterface $serializer
+ */
+ public function __construct(Connection $connection, SerializerInterface $serializer)
{
$this->connection = $connection;
+ $this->serializer = $serializer;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -47,12 +52,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -60,20 +60,13 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, CategoryTreeCreatedEvent::class);
}
- try {
- $this->connection->beginTransaction();
- $this->connection->insert(
- self::TABLE,
- [
- 'id' => $event->getId(),
- 'code' => $event->getCode(),
- 'name' => json_encode($event->getName()->getTranslations()),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ $this->connection->insert(
+ self::TABLE,
+ [
+ 'id' => $event->getId(),
+ 'code' => $event->getCode(),
+ 'name' => $this->serializer->serialize($event->getName()->getTranslations(), 'json'),
+ ]
+ );
}
}
diff --git a/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeDeletedEventProjector.php b/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeDeletedEventProjector.php
new file mode 100644
index 000000000..b920013a9
--- /dev/null
+++ b/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeDeletedEventProjector.php
@@ -0,0 +1,62 @@
+connection = $connection;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function support(DomainEventInterface $event): bool
+ {
+ return $event instanceof CategoryTreeDeletedEvent;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
+ {
+ if (!$event instanceof CategoryTreeDeletedEvent) {
+ throw new UnsupportedEventException($event, CategoryTreeDeletedEvent::class);
+ }
+
+ $this->connection->delete(
+ self::TABLE,
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
+ }
+}
diff --git a/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeNameChangedEventProjector.php b/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeNameChangedEventProjector.php
index 7dfcdc3a8..373663744 100644
--- a/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeNameChangedEventProjector.php
+++ b/module/category-tree/src/Persistence/Dbal/Projector/CategoryTreeNameChangedEventProjector.php
@@ -13,9 +13,9 @@
use Ergonode\CategoryTree\Domain\Event\CategoryTreeNameChangedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
+use JMS\Serializer\SerializerInterface;
/**
*/
@@ -29,17 +29,22 @@ class CategoryTreeNameChangedEventProjector implements DomainEventProjectorInter
private $connection;
/**
- * @param Connection $connection
+ * @var SerializerInterface
*/
- public function __construct(Connection $connection)
+ private $serializer;
+
+ /**
+ * @param Connection $connection
+ * @param SerializerInterface $serializer
+ */
+ public function __construct(Connection $connection, SerializerInterface $serializer)
{
$this->connection = $connection;
+ $this->serializer = $serializer;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -47,12 +52,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -60,21 +60,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, CategoryTreeNameChangedEvent::class);
}
- try {
- $this->connection->beginTransaction();
- $this->connection->update(
- self::TABLE,
- [
- 'name' => json_encode($event->getTo()->getTranslations()),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'name' => $this->serializer->serialize($event->getTo()->getTranslations(), 'json'),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/category-tree/src/Persistence/Dbal/Repository/DbalTreeRepository.php b/module/category-tree/src/Persistence/Dbal/Repository/DbalTreeRepository.php
index eebc0104d..1a1b45bd3 100644
--- a/module/category-tree/src/Persistence/Dbal/Repository/DbalTreeRepository.php
+++ b/module/category-tree/src/Persistence/Dbal/Repository/DbalTreeRepository.php
@@ -11,6 +11,7 @@
use Ergonode\CategoryTree\Domain\Entity\CategoryTree;
use Ergonode\CategoryTree\Domain\Entity\CategoryTreeId;
+use Ergonode\CategoryTree\Domain\Event\CategoryTreeDeletedEvent;
use Ergonode\CategoryTree\Domain\Repository\TreeRepositoryInterface;
use Ergonode\EventSourcing\Domain\AbstractAggregateRoot;
use Ergonode\EventSourcing\Infrastructure\DomainEventDispatcherInterface;
@@ -41,9 +42,7 @@ public function __construct(DomainEventStoreInterface $eventStore, DomainEventDi
}
/**
- * @param CategoryTreeId $id
- *
- * @return CategoryTree|null
+ * {@inheritDoc}
*
* @throws \ReflectionException
*/
@@ -68,9 +67,7 @@ public function load(CategoryTreeId $id): ?AbstractAggregateRoot
}
/**
- * @param CategoryTreeId $id
- *
- * @return bool
+ * {@inheritDoc}
*/
public function exists(CategoryTreeId $id) : bool
{
@@ -80,7 +77,7 @@ public function exists(CategoryTreeId $id) : bool
}
/**
- * @param AbstractAggregateRoot $aggregateRoot
+ * {@inheritDoc}
*/
public function save(AbstractAggregateRoot $aggregateRoot): void
{
@@ -91,4 +88,17 @@ public function save(AbstractAggregateRoot $aggregateRoot): void
$this->eventDispatcher->dispatch($envelope);
}
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws \Exception
+ */
+ public function delete(AbstractAggregateRoot $aggregateRoot): void
+ {
+ $aggregateRoot->apply(new CategoryTreeDeletedEvent());
+ $this->save($aggregateRoot);
+
+ $this->eventStore->delete($aggregateRoot->getId());
+ }
}
diff --git a/module/category-tree/src/Resources/translations/log.en.yaml b/module/category-tree/src/Resources/translations/log.en.yaml
index 86d4a3ef5..9bccc0439 100644
--- a/module/category-tree/src/Resources/translations/log.en.yaml
+++ b/module/category-tree/src/Resources/translations/log.en.yaml
@@ -1,4 +1,6 @@
-"Ergonode\\CategoryTree\\Domain\\Event\\CategoryTreeCategoriesChangedEvent": Categories changed
-"Ergonode\\CategoryTree\\Domain\\Event\\CategoryTreeCategoryAddedEvent": Category added
-"Ergonode\\CategoryTree\\Domain\\Event\\CategoryTreeCategoryRemovedEvent": Category removed
-"Ergonode\\CategoryTree\\Domain\\Event\\CategoryTreeCreatedEvent": Category Tree "%name%" created
+'Categories changed on category tree': 'Categories changed on category tree'
+'Category added to category tree': 'Category added to category tree'
+'Category removed from category tree': 'Category removed from category tree'
+'Category tree created': 'Category tree created'
+'Category tree name changed': 'Category tree name changed'
+'Category tree deleted': 'Category tree "%id%" deleted'
diff --git a/module/category-tree/src/Resources/translations/log.pl.yaml b/module/category-tree/src/Resources/translations/log.pl.yaml
index 2824e0efe..976dea321 100644
--- a/module/category-tree/src/Resources/translations/log.pl.yaml
+++ b/module/category-tree/src/Resources/translations/log.pl.yaml
@@ -1,4 +1,6 @@
-"Ergonode\\CategoryTree\\Domain\\Event\\CategoryTreeCategoriesChangedEvent": Zamiana wielu kategorii
-"Ergonode\\CategoryTree\\Domain\\Event\\CategoryTreeCategoryAddedEvent": Dodanie kategorii
-"Ergonode\\CategoryTree\\Domain\\Event\\CategoryTreeCategoryRemovedEvent": Usunięcie kategorii
-"Ergonode\\CategoryTree\\Domain\\Event\\CategoryTreeCreatedEvent": Stworzenie drzewa kategorii
+'Categories changed on category tree': 'Zamiana wielu kategorii na drzewie kategorii'
+'Category added to category tree': 'Dodanie kategorii do drzewa kategorii'
+'Category removed from category tree': 'Usunięcie kategorii z drzewa kategorii'
+'Category tree created': 'Stworzenie drzewa kategorii'
+'Category tree name changed': 'Zmieniono nazwę drzewa kategorii'
+'Category tree deleted': 'Drzewo kategorii "%id%" zostało usunięte'
diff --git a/module/category/composer.json b/module/category/composer.json
index 91bd8dbce..3ba439d6f 100644
--- a/module/category/composer.json
+++ b/module/category/composer.json
@@ -7,12 +7,12 @@
"require": {
"php": "^7.2",
"doctrine/dbal": "^2.9",
- "ergonode/api": "^0.4.0",
- "ergonode/attribute": "^0.4.0",
- "ergonode/core": "^0.4.0",
- "ergonode/es": "^0.4.0",
- "ergonode/grid": "^0.4.0",
- "ergonode/value": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/attribute": "^0.5.0",
+ "ergonode/core": "^0.5.0",
+ "ergonode/es": "^0.5.0",
+ "ergonode/grid": "^0.5.0",
+ "ergonode/value": "^0.5.0",
"friendsofsymfony/rest-bundle": "^2.5",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
diff --git a/module/category/migrations/Version20180619083800.php b/module/category/migrations/Version20180619083800.php
index 915035e59..1e59bc377 100644
--- a/module/category/migrations/Version20180619083800.php
+++ b/module/category/migrations/Version20180619083800.php
@@ -18,19 +18,40 @@ final class Version20180619083800 extends AbstractErgonodeMigration
*/
public function up(Schema $schema): void
{
- $this->addSql(
- 'CREATE TABLE IF NOT EXISTS category (
- id UUID NOT NULL,
- name JSONB NOT NULL,
- code VARCHAR(255) DEFAULT NULL,
- sequence SERIAL,
- PRIMARY KEY(id)
- )'
- );
+ $this->addSql('
+ CREATE TABLE IF NOT EXISTS category (
+ id UUID NOT NULL,
+ name JSONB NOT NULL,
+ code VARCHAR(255) DEFAULT NULL,
+ sequence SERIAL,
+ PRIMARY KEY(id)
+ )
+ ');
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'CATEGORY_CREATE', 'Category']);
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'CATEGORY_READ', 'Category']);
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'CATEGORY_UPDATE', 'Category']);
$this->addSql('INSERT INTO privileges (id, code, area) VALUES (?, ?, ?)', [Uuid::uuid4()->toString(), 'CATEGORY_DELETE', 'Category']);
+
+ $this->createEventStoreEvents([
+ 'Ergonode\Category\Domain\Event\CategoryCreatedEvent' => 'Category created',
+ 'Ergonode\Category\Domain\Event\CategoryNameChangedEvent' => 'Category name changed',
+ ]);
+ }
+
+ /**
+ * @param array $collection
+ *
+ * @throws \Doctrine\DBAL\DBALException
+ */
+ private function createEventStoreEvents(array $collection): void
+ {
+ foreach ($collection as $class => $translation) {
+ $this->connection->insert('event_store_event', [
+ 'id' => Uuid::uuid4()->toString(),
+ 'event_class' => $class,
+ 'translation_key' => $translation,
+ ]);
+ }
}
}
diff --git a/module/category/src/Application/Controller/Api/CategoryController.php b/module/category/src/Application/Controller/Api/CategoryController.php
index 26e32dc3f..4eb6d19f1 100644
--- a/module/category/src/Application/Controller/Api/CategoryController.php
+++ b/module/category/src/Application/Controller/Api/CategoryController.php
@@ -270,7 +270,7 @@ public function createCategory(Request $request): Response
* in="body",
* description="Category body",
* required=true,
- * @SWG\Schema(ref="#/definitions/category")
+ * @SWG\Schema(ref="#/definitions/category_upd")
* )
* @SWG\Response(
* response=204,
diff --git a/module/category/src/Persistence/Dbal/Projector/CategoryCreatedEventProjector.php b/module/category/src/Persistence/Dbal/Projector/CategoryCreatedEventProjector.php
index d12ddcff3..878fd0008 100644
--- a/module/category/src/Persistence/Dbal/Projector/CategoryCreatedEventProjector.php
+++ b/module/category/src/Persistence/Dbal/Projector/CategoryCreatedEventProjector.php
@@ -15,7 +15,6 @@
use Ergonode\Category\Domain\Event\CategoryCreatedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
use JMS\Serializer\SerializerInterface;
@@ -51,9 +50,7 @@ public function __construct(Connection $connection, SerializerInterface $seriali
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -61,12 +58,9 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
+ * {@inheritDoc}
*
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * @throws \Throwable
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -74,13 +68,12 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, CategoryCreatedEvent::class);
}
- try {
- $this->connection->beginTransaction();
+ $this->connection->transactional(function () use ($aggregateId, $event) {
$this->connection->insert(
self::TABLE,
[
'id' => $aggregateId->getValue(),
- 'name' => json_encode($event->getName()->getTranslations()),
+ 'name' => $this->serializer->serialize($event->getName()->getTranslations(), 'json'),
'code' => $event->getCode()->getValue(),
]
);
@@ -116,10 +109,6 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
]
);
}
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ });
}
}
diff --git a/module/category/src/Persistence/Dbal/Projector/CategoryNameChangedEventProjector.php b/module/category/src/Persistence/Dbal/Projector/CategoryNameChangedEventProjector.php
index 76067415f..b6e429b10 100644
--- a/module/category/src/Persistence/Dbal/Projector/CategoryNameChangedEventProjector.php
+++ b/module/category/src/Persistence/Dbal/Projector/CategoryNameChangedEventProjector.php
@@ -13,9 +13,9 @@
use Ergonode\Category\Domain\Event\CategoryNameChangedEvent;
use Ergonode\Core\Domain\Entity\AbstractId;
use Ergonode\EventSourcing\Infrastructure\DomainEventInterface;
-use Ergonode\EventSourcing\Infrastructure\Exception\ProjectorException;
use Ergonode\EventSourcing\Infrastructure\Exception\UnsupportedEventException;
use Ergonode\EventSourcing\Infrastructure\Projector\DomainEventProjectorInterface;
+use JMS\Serializer\SerializerInterface;
/**
*/
@@ -29,17 +29,22 @@ class CategoryNameChangedEventProjector implements DomainEventProjectorInterface
private $connection;
/**
- * @param Connection $connection
+ * @var SerializerInterface
*/
- public function __construct(Connection $connection)
+ private $serializer;
+
+ /**
+ * @param Connection $connection
+ * @param SerializerInterface $serializer
+ */
+ public function __construct(Connection $connection, SerializerInterface $serializer)
{
$this->connection = $connection;
+ $this->serializer = $serializer;
}
/**
- * @param DomainEventInterface $event
- *
- * @return bool
+ * {@inheritDoc}
*/
public function support(DomainEventInterface $event): bool
{
@@ -47,12 +52,7 @@ public function support(DomainEventInterface $event): bool
}
/**
- * @param AbstractId $aggregateId
- * @param DomainEventInterface $event
- *
- * @throws ProjectorException
- * @throws UnsupportedEventException
- * @throws \Doctrine\DBAL\ConnectionException
+ * {@inheritDoc}
*/
public function projection(AbstractId $aggregateId, DomainEventInterface $event): void
{
@@ -60,21 +60,14 @@ public function projection(AbstractId $aggregateId, DomainEventInterface $event)
throw new UnsupportedEventException($event, CategoryNameChangedEvent::class);
}
- try {
- $this->connection->beginTransaction();
- $this->connection->update(
- self::TABLE,
- [
- 'name' => json_encode($event->getTo()->getTranslations()),
- ],
- [
- 'id' => $aggregateId->getValue(),
- ]
- );
- $this->connection->commit();
- } catch (\Throwable $exception) {
- $this->connection->rollBack();
- throw new ProjectorException($event, $exception);
- }
+ $this->connection->update(
+ self::TABLE,
+ [
+ 'name' => $this->serializer->serialize($event->getTo()->getTranslations(), 'json'),
+ ],
+ [
+ 'id' => $aggregateId->getValue(),
+ ]
+ );
}
}
diff --git a/module/category/src/Resources/translations/log.en.yaml b/module/category/src/Resources/translations/log.en.yaml
index f60cec2e8..0cf9f891f 100644
--- a/module/category/src/Resources/translations/log.en.yaml
+++ b/module/category/src/Resources/translations/log.en.yaml
@@ -1,2 +1,2 @@
-"Ergonode\\Category\\Domain\\Event\\CategoryCreatedEvent": Category "%code%" created
-"Ergonode\\Category\\Domain\\Event\\CategoryNameChangedEvent": Category name changed
+'Category created': 'Category "%code%" created'
+'Category name changed': 'Category name changed'
diff --git a/module/category/src/Resources/translations/log.pl.yaml b/module/category/src/Resources/translations/log.pl.yaml
index 8bb9dc04a..6961c8a64 100644
--- a/module/category/src/Resources/translations/log.pl.yaml
+++ b/module/category/src/Resources/translations/log.pl.yaml
@@ -1,2 +1,2 @@
-"Ergonode\\Category\\Domain\\Event\\CategoryCreatedEvent": Stworzono kategorię "%code%"
-"Ergonode\\Category\\Domain\\Event\\CategoryNameChangedEvent": Nazwa kategori została zmieniona
+'Category created': 'Stworzono kategorię "%code%"'
+'Category name changed': 'Nazwa kategori została zmieniona'
diff --git a/module/completeness/composer.json b/module/completeness/composer.json
index 43c70657c..af6c05a8f 100644
--- a/module/completeness/composer.json
+++ b/module/completeness/composer.json
@@ -7,10 +7,10 @@
"require": {
"php": "^7.2",
"doctrine/dbal": "^2.9",
- "ergonode/api": "^0.4.0",
- "ergonode/attribute": "^0.4.0",
- "ergonode/core": "^0.4.0",
- "ergonode/editor": "^0.4.0",
+ "ergonode/api": "^0.5.0",
+ "ergonode/attribute": "^0.5.0",
+ "ergonode/core": "^0.5.0",
+ "ergonode/editor": "^0.5.0",
"friendsofsymfony/rest-bundle": "^2.5",
"jms/serializer": "^3.1",
"nelmio/api-doc-bundle": "^3.4",
diff --git a/module/condition/LICENSE.txt b/module/condition/LICENSE.txt
new file mode 100644
index 000000000..996dcc641
--- /dev/null
+++ b/module/condition/LICENSE.txt
@@ -0,0 +1,26 @@
+Open Software License ("OSL") v. 3.0
+
+This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work:
+Licensed under the Open Software License version 3.0
+
+ 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following:
+ a) to reproduce the Original Work in copies, either alone or as part of a collective work;
+ b) to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work;
+ c) to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License;
+ d) to perform the Original Work publicly; and
+ e) to display the Original Work publicly.
+ 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works.
+ 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work.
+ 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license.
+ 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c).
+ 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
+ 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer.
+ 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation.
+ 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c).
+ 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
+ 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License.
+ 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
+ 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
+ 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+ 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
+ 16. Modification of This License. This License is Copyright (C) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under