15 Commits

Author SHA1 Message Date
358f1af52c fix(deps): update vue monorepo to v3.5.34
Some checks failed
renovate/artifacts Artifact file update failure
Build Test / build (pull_request) Failing after 10s
JS Unit Tests / test (pull_request) Failing after 9s
PHP Unit Tests / test (pull_request) Successful in 38s
2026-05-15 03:09:53 +00:00
858e9fddf0 Merge pull request 'refactor: mail interfaces' (#79) from refactor/mail-interfaces into main
Some checks are pending
Renovate / renovate (push) Has started running
Reviewed-on: #79
2026-05-15 02:56:07 +00:00
f3c882454d refactor: mail interfaces
All checks were successful
Build Test / build (pull_request) Successful in 12s
JS Unit Tests / test (pull_request) Successful in 11s
PHP Unit Tests / test (pull_request) Successful in 39s
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-05-14 22:54:51 -04:00
d6005246dc Merge pull request 'refactor: service interfaces' (#78) from refactor/service-interfaces into main
Some checks are pending
Renovate / renovate (push) Waiting to run
Reviewed-on: #78
2026-05-09 21:00:33 +00:00
b8cda71c17 refactor: service interfaces
All checks were successful
Build Test / build (pull_request) Successful in 14s
JS Unit Tests / test (pull_request) Successful in 14s
PHP Unit Tests / test (pull_request) Successful in 48s
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-05-09 17:00:00 -04:00
4e7260ad86 Merge pull request 'refactor: entity move and delete' (#77) from refactor/entity-move-and-delete into main
Some checks failed
Renovate / renovate (push) Failing after 1m56s
Reviewed-on: #77
2026-05-08 03:58:54 +00:00
69d6c7fd1a refactor: entity move and delete
All checks were successful
Build Test / build (pull_request) Successful in 18s
JS Unit Tests / test (pull_request) Successful in 16s
PHP Unit Tests / test (pull_request) Successful in 41s
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-05-07 23:58:36 -04:00
6d71bb49d5 Merge pull request 'chore: downgrade console and mongodb' (#76) from chore/downgrade-mongodb into main
Some checks failed
Renovate / renovate (push) Failing after 1m46s
Reviewed-on: #76
2026-05-07 03:35:06 +00:00
19e49379f4 chore: downgrade console and mongodb
All checks were successful
Build Test / build (pull_request) Successful in 24s
JS Unit Tests / test (pull_request) Successful in 23s
PHP Unit Tests / test (pull_request) Successful in 46s
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-05-06 23:34:51 -04:00
cce65c3e62 Merge pull request 'chore(deps): update dependency typescript to v6' (#73) from renovate/typescript-6.x into main
Reviewed-on: #73
2026-05-07 03:17:33 +00:00
757d69b803 Merge pull request 'chore(deps): update dependency mongodb/mongodb to v2.3.0' (#69) from renovate/mongodb-mongodb-2.x-lockfile into main
Reviewed-on: #69
2026-05-07 03:17:23 +00:00
745c2947c3 Merge pull request 'chore(deps): update eslint monorepo to v10 (major)' (#74) from renovate/major-eslint-monorepo into main
Reviewed-on: #74
2026-05-07 03:17:13 +00:00
2b05cd39ef chore(deps): update eslint monorepo to v10
All checks were successful
Build Test / build (pull_request) Successful in 19s
JS Unit Tests / test (pull_request) Successful in 19s
PHP Unit Tests / test (pull_request) Successful in 36s
2026-05-07 03:15:20 +00:00
bb10f48ded chore(deps): update dependency typescript to v6
All checks were successful
Build Test / build (pull_request) Successful in 30s
JS Unit Tests / test (pull_request) Successful in 14s
PHP Unit Tests / test (pull_request) Successful in 1m16s
2026-05-07 03:15:17 +00:00
aec0abaca6 chore(deps): update dependency mongodb/mongodb to v2.3.0
All checks were successful
JS Unit Tests / test (pull_request) Successful in 31s
Build Test / build (pull_request) Successful in 35s
PHP Unit Tests / test (pull_request) Successful in 1m11s
2026-05-07 03:15:10 +00:00
36 changed files with 784 additions and 1297 deletions

View File

@@ -11,7 +11,7 @@
"mongodb/mongodb": "^2.1",
"php-di/php-di": "*",
"phpseclib/phpseclib": "^3.0",
"symfony/console": "^8.0"
"symfony/console": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "^11.0"

54
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "451b6afae1bbd5c2285e55037e138890",
"content-hash": "b14b010c422e222aeb1e33104e2a09ec",
"packages": [
{
"name": "laravel/serializable-closure",
@@ -606,39 +606,47 @@
},
{
"name": "symfony/console",
"version": "v8.0.9",
"version": "v7.4.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d"
"reference": "d7d2b64a45a89d607865927b176fa51c33ddbb58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/7113778e2e91f4709cb3194a75dfa9c0d028d94d",
"reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d",
"url": "https://api.github.com/repos/symfony/console/zipball/d7d2b64a45a89d607865927b176fa51c33ddbb58",
"reference": "d7d2b64a45a89d607865927b176fa51c33ddbb58",
"shasum": ""
},
"require": {
"php": ">=8.4",
"symfony/polyfill-mbstring": "^1.0",
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
"symfony/string": "^7.4|^8.0"
"symfony/string": "^7.2|^8.0"
},
"conflict": {
"symfony/dependency-injection": "<6.4",
"symfony/dotenv": "<6.4",
"symfony/event-dispatcher": "<6.4",
"symfony/lock": "<6.4",
"symfony/process": "<6.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^7.4|^8.0",
"symfony/dependency-injection": "^7.4|^8.0",
"symfony/event-dispatcher": "^7.4|^8.0",
"symfony/http-foundation": "^7.4|^8.0",
"symfony/http-kernel": "^7.4|^8.0",
"symfony/lock": "^7.4|^8.0",
"symfony/messenger": "^7.4|^8.0",
"symfony/process": "^7.4|^8.0",
"symfony/stopwatch": "^7.4|^8.0",
"symfony/var-dumper": "^7.4|^8.0"
"symfony/config": "^6.4|^7.0|^8.0",
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
"symfony/http-foundation": "^6.4|^7.0|^8.0",
"symfony/http-kernel": "^6.4|^7.0|^8.0",
"symfony/lock": "^6.4|^7.0|^8.0",
"symfony/messenger": "^6.4|^7.0|^8.0",
"symfony/process": "^6.4|^7.0|^8.0",
"symfony/stopwatch": "^6.4|^7.0|^8.0",
"symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -672,7 +680,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v8.0.9"
"source": "https://github.com/symfony/console/tree/v7.4.9"
},
"funding": [
{
@@ -692,7 +700,7 @@
"type": "tidelift"
}
],
"time": "2026-04-29T15:02:55+00:00"
"time": "2026-04-22T15:21:55+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -3140,7 +3148,7 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"stability-flags": [],
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
@@ -3148,6 +3156,6 @@
"ext-ctype": "*",
"ext-iconv": "*"
},
"platform-dev": {},
"plugin-api-version": "2.9.0"
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

367
package-lock.json generated
View File

@@ -27,7 +27,7 @@
"vuetify": "4.0.6"
},
"devDependencies": {
"@eslint/js": "^9.18.0",
"@eslint/js": "^10.0.0",
"@types/dompurify": "^3.2.0",
"@types/node": "25.6.0",
"@vitejs/plugin-vue": "6.0.6",
@@ -36,13 +36,13 @@
"@vue/eslint-config-prettier": "10.2.0",
"@vue/test-utils": "^2.4.8",
"@vue/tsconfig": "0.9.1",
"eslint": "^9.39.4",
"eslint": "^10.0.0",
"eslint-plugin-vue": "10.9.1",
"jsdom": "^29.0.0",
"prettier": "3.8.3",
"sass": "1.99.0",
"sass-loader": "16.0.7",
"typescript": "5.9.3",
"typescript": "6.0.3",
"typescript-eslint": "^8.59.0",
"vite": "8.0.10",
"vite-plugin-static-copy": "^4.0.0",
@@ -398,154 +398,84 @@
}
},
"node_modules/@eslint/config-array": {
"version": "0.21.2",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
"integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
"version": "0.23.5",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz",
"integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==",
"license": "Apache-2.0",
"dependencies": {
"@eslint/object-schema": "^2.1.7",
"@eslint/object-schema": "^3.0.5",
"debug": "^4.3.1",
"minimatch": "^3.1.5"
"minimatch": "^10.2.4"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/config-array/node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"license": "MIT"
},
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/@eslint/config-array/node_modules/minimatch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/config-helpers": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
"integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz",
"integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==",
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.17.0"
"@eslint/core": "^1.2.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/core": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz",
"integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/eslintrc": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
"integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
"license": "MIT",
"dependencies": {
"ajv": "^6.14.0",
"debug": "^4.3.2",
"espree": "^10.0.1",
"globals": "^14.0.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.1",
"minimatch": "^3.1.5",
"strip-json-comments": "^3.1.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@eslint/eslintrc/node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"license": "MIT"
},
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/@eslint/eslintrc/node_modules/minimatch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/js": {
"version": "9.39.4",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
"integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz",
"integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
"url": "https://eslint.org/donate"
},
"peerDependencies": {
"eslint": "^10.0.0"
},
"peerDependenciesMeta": {
"eslint": {
"optional": true
}
}
},
"node_modules/@eslint/object-schema": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz",
"integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==",
"license": "Apache-2.0",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/plugin-kit": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
"integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz",
"integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==",
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.17.0",
"@eslint/core": "^1.2.1",
"levn": "^0.4.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@exodus/bytes": {
@@ -1430,6 +1360,12 @@
"@types/estree": "*"
}
},
"node_modules/@types/esrecurse": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
"integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
"license": "MIT"
},
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
@@ -2537,6 +2473,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -2575,12 +2512,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0"
},
"node_modules/assertion-error": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
@@ -2785,15 +2716,6 @@
"license": "MIT",
"peer": true
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001790",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz",
@@ -2826,22 +2748,6 @@
"node": ">=18"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
@@ -2873,6 +2779,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -2885,6 +2792,7 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"license": "MIT"
},
"node_modules/commander": {
@@ -2901,6 +2809,7 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true,
"license": "MIT"
},
"node_modules/confbox": {
@@ -3203,32 +3112,29 @@
}
},
"node_modules/eslint": {
"version": "9.39.4",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-10.3.0.tgz",
"integrity": "sha512-XbEXaRva5cF0ZQB8w6MluHA0kZZfV2DuCMJ3ozyEOHLwDpZX2Lmm/7Pp0xdJmI0GL1W05VH5VwIFHEm1Vcw2gw==",
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.21.2",
"@eslint/config-helpers": "^0.4.2",
"@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.5",
"@eslint/js": "9.39.4",
"@eslint/plugin-kit": "^0.4.1",
"@eslint-community/regexpp": "^4.12.2",
"@eslint/config-array": "^0.23.5",
"@eslint/config-helpers": "^0.5.5",
"@eslint/core": "^1.2.1",
"@eslint/plugin-kit": "^0.7.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
"ajv": "^6.14.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
"eslint-scope": "^8.4.0",
"eslint-visitor-keys": "^4.2.1",
"espree": "^10.4.0",
"esquery": "^1.5.0",
"eslint-scope": "^9.1.2",
"eslint-visitor-keys": "^5.0.1",
"espree": "^11.2.0",
"esquery": "^1.7.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
"file-entry-cache": "^8.0.0",
@@ -3238,8 +3144,7 @@
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.5",
"minimatch": "^10.2.4",
"natural-compare": "^1.4.0",
"optionator": "^0.9.3"
},
@@ -3247,7 +3152,7 @@
"eslint": "bin/eslint.js"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
"url": "https://eslint.org/donate"
@@ -3341,16 +3246,18 @@
}
},
"node_modules/eslint-scope": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
"integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
"license": "BSD-2-Clause",
"dependencies": {
"@types/esrecurse": "^4.3.1",
"@types/estree": "^1.0.8",
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
"url": "https://opencollective.com/eslint"
@@ -3368,51 +3275,30 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint/node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"license": "MIT"
},
"node_modules/eslint/node_modules/brace-expansion": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"license": "MIT",
"node_modules/eslint/node_modules/espree": {
"version": "11.2.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
"integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
"license": "BSD-2-Clause",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/eslint/node_modules/eslint-visitor-keys": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"license": "Apache-2.0",
"acorn": "^8.16.0",
"acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^5.0.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint/node_modules/minimatch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/espree": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
"license": "BSD-2-Clause",
"peer": true,
"dependencies": {
"acorn": "^8.15.0",
"acorn-jsx": "^5.3.2",
@@ -3429,7 +3315,9 @@
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
@@ -3762,18 +3650,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/globals": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -3786,6 +3662,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -3846,22 +3723,6 @@
"devOptional": true,
"license": "MIT"
},
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -4129,18 +3990,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/jsdom": {
"version": "29.1.1",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz",
@@ -4567,12 +4416,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"license": "MIT"
},
"node_modules/lru-cache": {
"version": "11.3.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
@@ -4937,18 +4780,6 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/parse5": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
@@ -5279,15 +5110,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
@@ -5731,18 +5553,6 @@
"node": ">=8"
}
},
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/superjson": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz",
@@ -5759,6 +5569,7 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
@@ -6098,9 +5909,9 @@
}
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",

View File

@@ -39,7 +39,7 @@
"vuetify": "4.0.6"
},
"devDependencies": {
"@eslint/js": "^9.18.0",
"@eslint/js": "^10.0.0",
"@types/dompurify": "^3.2.0",
"@types/node": "25.6.0",
"@vitejs/plugin-vue": "6.0.6",
@@ -48,13 +48,13 @@
"@vue/eslint-config-prettier": "10.2.0",
"@vue/test-utils": "^2.4.8",
"@vue/tsconfig": "0.9.1",
"eslint": "^9.39.4",
"eslint": "^10.0.0",
"eslint-plugin-vue": "10.9.1",
"jsdom": "^29.0.0",
"prettier": "3.8.3",
"sass": "1.99.0",
"sass-loader": "16.0.7",
"typescript": "5.9.3",
"typescript": "6.0.3",
"typescript-eslint": "^8.59.0",
"vite": "8.0.10",
"vite-plugin-static-copy": "^4.0.0",

View File

@@ -9,6 +9,7 @@ declare(strict_types=1);
namespace KTXF\Mail\Collection;
use KTXF\Resource\Identifier\CollectionIdentifier;
use KTXF\Resource\Provider\Node\NodeBaseAbstract;
/**
@@ -20,8 +21,13 @@ use KTXF\Resource\Provider\Node\NodeBaseAbstract;
*/
abstract class CollectionBase extends NodeBaseAbstract implements CollectionBaseInterface {
protected string $type = 'mail.collection';
protected CollectionPropertiesBaseAbstract $properties;
protected function nodeIdentifier(): CollectionIdentifier {
return new CollectionIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], (string) $this->data[static::PROPERTY_IDENTIFIER]);
}
/**
* @inheritDoc
*/

View File

@@ -9,6 +9,7 @@ declare(strict_types=1);
namespace KTXF\Mail\Collection;
use KTXF\Resource\Identifier\CollectionIdentifier;
use KTXF\Resource\Provider\Node\NodeMutableAbstract;
use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface;
@@ -23,6 +24,10 @@ abstract class CollectionMutableAbstract extends NodeMutableAbstract implements
protected CollectionPropertiesMutableAbstract $properties;
protected function nodeIdentifier(): CollectionIdentifier {
return new CollectionIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], $this->data[static::PROPERTY_IDENTIFIER]);
}
/**
* @inheritDoc
*/

View File

@@ -20,49 +20,47 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseAbstract;
*/
abstract class CollectionPropertiesBaseAbstract extends NodePropertiesBaseAbstract implements CollectionPropertiesBaseInterface {
public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE;
/**
* @inheritDoc
*/
public function total(): int {
return $this->data['total'] ?? 0;
return $this->data[static::PROPERTY_TOTAL] ?? 0;
}
/**
* @inheritDoc
*/
public function unread(): int {
return $this->data['unread'] ?? 0;
return $this->data[static::PROPERTY_UNREAD] ?? 0;
}
/**
* @inheritDoc
*/
public function getLabel(): string {
return $this->data['label'] ?? '';
return $this->data[static::PROPERTY_LABEL] ?? '';
}
/**
* @inheritDoc
*/
public function getRole(): CollectionRoles {
return isset($this->data['role'])
? ($this->data['role'] instanceof CollectionRoles ? $this->data['role'] : CollectionRoles::from($this->data['role']))
: CollectionRoles::Custom;
return isset($this->data[static::PROPERTY_ROLE])
? ($this->data[static::PROPERTY_ROLE] instanceof CollectionRoles ? $this->data[static::PROPERTY_ROLE] : CollectionRoles::from($this->data[static::PROPERTY_ROLE]))
: CollectionRoles::None;
}
/**
* @inheritDoc
*/
public function getRank(): int {
return $this->data['rank'] ?? 0;
return $this->data[static::PROPERTY_RANK] ?? 0;
}
/**
* @inheritDoc
*/
public function getSubscription(): bool {
return $this->data['subscribed'] ?? false;
return $this->data[static::PROPERTY_SUBSCRIPTION] ?? false;
}
}

View File

@@ -13,13 +13,12 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseInterface;
interface CollectionPropertiesBaseInterface extends NodePropertiesBaseInterface {
public const JSON_TYPE = 'mail.collection';
public const JSON_PROPERTY_TOTAL = 'total';
public const JSON_PROPERTY_UNREAD = 'unread';
public const JSON_PROPERTY_LABEL = 'label';
public const JSON_PROPERTY_ROLE = 'role';
public const JSON_PROPERTY_RANK = 'rank';
public const JSON_PROPERTY_SUBSCRIPTION = 'subscription';
public const PROPERTY_TOTAL = 'total';
public const PROPERTY_UNREAD = 'unread';
public const PROPERTY_LABEL = 'label';
public const PROPERTY_ROLE = 'role';
public const PROPERTY_RANK = 'rank';
public const PROPERTY_SUBSCRIPTION = 'subscription';
public function total(): int;

View File

@@ -16,8 +16,6 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableAbstract;
*/
abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesBaseAbstract implements CollectionPropertiesMutableInterface {
public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE;
/**
* @inheritDoc
*/
@@ -35,7 +33,7 @@ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesB
* @inheritDoc
*/
public function setLabel(string $value): static {
$this->data['label'] = $value;
$this->data[self::PROPERTY_LABEL] = $value;
return $this;
}
@@ -43,7 +41,7 @@ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesB
* @inheritDoc
*/
public function setRole(CollectionRoles $value): static {
$this->data['role'] = $value;
$this->data[self::PROPERTY_ROLE] = $value;
return $this;
}
@@ -51,7 +49,7 @@ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesB
* @inheritDoc
*/
public function setRank(int $value): static {
$this->data['rank'] = $value;
$this->data[self::PROPERTY_RANK] = $value;
return $this;
}
@@ -59,7 +57,7 @@ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesB
* @inheritDoc
*/
public function setSubscription(bool $value): static {
$this->data['subscription'] = $value;
$this->data[self::PROPERTY_SUBSCRIPTION] = $value;
return $this;
}
}

View File

@@ -13,8 +13,6 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface;
interface CollectionPropertiesMutableInterface extends CollectionPropertiesBaseInterface, NodePropertiesMutableInterface {
public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE;
public function setLabel(string $value);
public function setRole(CollectionRoles $value): static;

View File

@@ -10,6 +10,7 @@ declare(strict_types=1);
namespace KTXF\Mail\Entity;
use KTXF\Mail\Object\MessagePropertiesBaseInterface;
use KTXF\Resource\Identifier\EntityIdentifier;
use KTXF\Resource\Provider\Node\NodeBaseAbstract;
/**
@@ -21,8 +22,13 @@ use KTXF\Resource\Provider\Node\NodeBaseAbstract;
*/
abstract class EntityBaseAbstract extends NodeBaseAbstract implements EntityBaseInterface {
protected string $type = 'mail.entity';
protected MessagePropertiesBaseInterface $properties;
protected function nodeIdentifier(): EntityIdentifier {
return new EntityIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], $this->data[static::PROPERTY_COLLECTION], $this->data[static::PROPERTY_IDENTIFIER]);
}
/**
* @inheritDoc
*/

View File

@@ -15,8 +15,6 @@ use KTXF\Resource\Provider\Node\NodeBaseInterface;
interface EntityBaseInterface extends NodeBaseInterface {
public const JSON_TYPE = 'mail.entity';
/**
* Gets the entity properties
*

View File

@@ -10,6 +10,7 @@ declare(strict_types=1);
namespace KTXF\Mail\Entity;
use KTXF\Mail\Object\MessagePropertiesMutableInterface;
use KTXF\Resource\Identifier\EntityIdentifier;
use KTXF\Resource\Provider\Node\NodeMutableAbstract;
use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface;
@@ -22,10 +23,13 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface;
*/
abstract class EntityMutableAbstract extends NodeMutableAbstract implements EntityMutableInterface {
public const JSON_TYPE = EntityMutableInterface::JSON_TYPE;
protected string $type = 'mail.entity';
protected MessagePropertiesMutableInterface $properties;
protected function nodeIdentifier(): EntityIdentifier {
return new EntityIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], (string) $this->data[static::PROPERTY_COLLECTION], (string) $this->data[static::PROPERTY_IDENTIFIER]);
}
/**
* @inheritDoc
*/

View File

@@ -17,8 +17,6 @@ use KTXF\Resource\Provider\Node\NodeMutableInterface;
*/
interface EntityMutableInterface extends EntityBaseInterface, NodeMutableInterface {
public const JSON_TYPE = EntityBaseInterface::JSON_TYPE;
/**
* Gets the entity properties (mutable)
*

View File

@@ -21,188 +21,161 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseAbstract;
*/
abstract class MessagePropertiesBaseAbstract extends NodePropertiesBaseAbstract implements MessagePropertiesBaseInterface {
public const JSON_TYPE = MessagePropertiesBaseInterface::JSON_TYPE;
protected string $type = 'mail.message';
/**
* @inheritDoc
*/
public function getHeaders(): array {
return $this->data['headers'] ?? [];
}
/**
* @inheritDoc
*/
public function getHeader(string $name): string|array|null {
return $this->data['headers'][$name] ?? null;
}
/**
* @inheritDoc
*/
public function getUrid(): ?string {
return $this->data['urid'] ?? null;
}
/**
* @inheritDoc
*/
public function getCreated(): ?DateTimeImmutable {
return $this->data['created'] ?? null;
}
/**
* @inheritDoc
*/
public function getModified(): ?DateTimeImmutable {
return $this->data['modified'] ?? null;
}
/**
* @inheritDoc
*/
public function getDate(): ?DateTimeImmutable {
return $this->data['date'] ?? null;
}
/**
* @inheritDoc
*/
public function getReceived(): ?DateTimeImmutable {
return $this->data['received'] ?? null;
public function jsonSerialize(): array {
return $this->data;
}
/**
* @inheritDoc
*/
public function getSize(): ?int {
return $this->data['size'] ?? null;
return $this->data[static::PROPERTY_SIZE] ?? null;
}
/**
* @inheritDoc
*/
public function getSender(): ?AddressInterface {
return $this->data['sender'] ?? null;
public function getHeaders(): array {
return $this->data[static::PROPERTY_HEADERS] ?? [];
}
/**
* @inheritDoc
*/
public function getFrom(): ?AddressInterface {
return $this->data['from'] ?? null;
public function getHeader(string $name): string|array|null {
return $this->data[static::PROPERTY_HEADERS][$name] ?? null;
}
/**
* @inheritDoc
*/
public function getReplyTo(): array {
return $this->data['replyTo'] ?? [];
}
/**
* @inheritDoc
*/
public function getTo(): array {
return $this->data['to'] ?? [];
}
/**
* @inheritDoc
*/
public function getCc(): array {
return $this->data['cc'] ?? [];
}
/**
* @inheritDoc
*/
public function getBcc(): array {
return $this->data['bcc'] ?? [];
public function getUrid(): ?string {
return $this->data[static::PROPERTY_URID] ?? null;
}
/**
* @inheritDoc
*/
public function getInReplyTo(): ?string {
return $this->data['inReplyTo'] ?? null;
return $this->data[static::PROPERTY_IN_REPLY_TO] ?? null;
}
/**
* @inheritDoc
*/
public function getReferences(): array {
return $this->data['references'] ?? [];
return $this->data[static::PROPERTY_REFERENCES] ?? [];
}
/**
* @inheritDoc
*/
public function getReceived(): ?DateTimeImmutable {
return $this->data[static::PROPERTY_RECEIVED] ?? null;
}
/**
* @inheritDoc
*/
public function getSent(): ?DateTimeImmutable {
return $this->data[static::PROPERTY_SENT] ?? null;
}
/**
* @inheritDoc
*/
public function getSender(): ?AddressInterface {
return $this->data[static::PROPERTY_SENDER] ?? null;
}
/**
* @inheritDoc
*/
public function getFrom(): ?AddressInterface {
return $this->data[static::PROPERTY_FROM] ?? null;
}
/**
* @inheritDoc
*/
public function getReplyTo(): array {
return $this->data[static::PROPERTY_REPLY_TO] ?? [];
}
/**
* @inheritDoc
*/
public function getTo(): array {
return $this->data[static::PROPERTY_TO] ?? [];
}
/**
* @inheritDoc
*/
public function getCc(): array {
return $this->data[static::PROPERTY_CC] ?? [];
}
/**
* @inheritDoc
*/
public function getBcc(): array {
return $this->data[static::PROPERTY_BCC] ?? [];
}
/**
* @inheritDoc
*/
public function getSubject(): string {
return $this->data['subject'] ?? '';
return $this->data[static::PROPERTY_SUBJECT] ?? '';
}
/**
* @inheritDoc
*/
public function getSnippet(): ?string {
return $this->data['snippet'] ?? null;
public function getBody(): ?MessagePartInterface {
return $this->data[static::PROPERTY_BODY] ?? null;
}
/**
* @inheritDoc
*/
public function getBodyText(): ?string {
return $this->data['bodyText'] ?? null;
public function hasBody(): bool {
return ($this->data[static::PROPERTY_BODY_TEXT_PLAIN] !== null && $this->data[static::PROPERTY_BODY_TEXT_PLAIN] !== '')
|| ($this->data[static::PROPERTY_BODY_TEXT_HTML] !== null && $this->data[static::PROPERTY_BODY_TEXT_HTML] !== '');
}
/**
* @inheritDoc
*/
public function getBodyTextCharset(): ?string {
return $this->data['bodyTextCharset'] ?? null;
public function getBodyTextPlain(): ?string {
return $this->data[static::PROPERTY_BODY_TEXT_PLAIN] ?? null;
}
/**
* @inheritDoc
*/
public function getBodyTextSize(): ?int {
return $this->data['bodyTextSize'] ?? null;
}
/**
* @inheritDoc
*/
public function getBodyHtml(): ?string {
return $this->data['bodyHtml'] ?? null;
}
/**
* @inheritDoc
*/
public function getBodyHtmlCharset(): ?string {
return $this->data['bodyHtmlCharset'] ?? null;
}
/**
* @inheritDoc
*/
public function getBodyHtmlSize(): ?int {
return $this->data['bodyHtmlSize'] ?? null;
public function getBodyTextHtml(): ?string {
return $this->data[static::PROPERTY_BODY_TEXT_HTML] ?? null;
}
/**
* @inheritDoc
*/
public function getAttachments(): array {
return $this->data['attachments'] ?? [];
return $this->data[static::PROPERTY_ATTACHMENTS] ?? [];
}
/**
* @inheritDoc
*/
public function getFlags(): array {
return $this->data['flags'] ?? [
return $this->data[static::PROPERTY_FLAGS] ?? [
'read' => false,
'starred' => false,
'important' => false,
@@ -218,179 +191,7 @@ abstract class MessagePropertiesBaseAbstract extends NodePropertiesBaseAbstract
* @inheritDoc
*/
public function getFlag(string $name): bool {
return $this->data['flags'][$name] ?? false;
return $this->data[static::PROPERTY_FLAGS][$name] ?? false;
}
/**
* Gets message labels
*
* @since 2025.05.01
*
* @return array<int, string>
*/
public function getLabels(): array {
return $this->data['labels'] ?? [];
}
/**
* Gets message tags
*
* @since 2025.05.01
*
* @return array<int, string>
*/
public function getTags(): array {
return $this->data['tags'] ?? [];
}
/**
* Gets message priority
*
* @since 2025.05.01
*
* @return string
*/
public function getPriority(): string {
return $this->data['priority'] ?? 'normal';
}
/**
* Gets message sensitivity
*
* @since 2025.05.01
*
* @return string
*/
public function getSensitivity(): string {
return $this->data['sensitivity'] ?? 'normal';
}
/**
* Gets encryption information
*
* @since 2025.05.01
*
* @return array{method: string|null, signed: bool, encrypted: bool}
*/
public function getEncryption(): array {
return $this->data['encryption'] ?? [
'method' => null,
'signed' => false,
'encrypted' => false,
];
}
/**
* Checks if delivery receipt is requested
*
* @since 2025.05.01
*
* @return bool
*/
public function isDeliveryReceipt(): bool {
return $this->data['deliveryReceipt'] ?? false;
}
/**
* Checks if read receipt is requested
*
* @since 2025.05.01
*
* @return bool
*/
public function isReadReceipt(): bool {
return $this->data['readReceipt'] ?? false;
}
/**
* @inheritDoc
*/
public function hasRecipients(): bool {
return !empty($this->data['to']) || !empty($this->data['cc']) || !empty($this->data['bcc']);
}
/**
* @inheritDoc
*/
public function hasBody(): bool {
return ($this->data['bodyText'] !== null && $this->data['bodyText'] !== '')
|| ($this->data['bodyHtml'] !== null && $this->data['bodyHtml'] !== '');
}
/**
* @inheritDoc
*/
public function getBody(): ?MessagePartInterface {
return $this->data['body'] ?? null;
}
/**
* @inheritDoc
*/
public function jsonSerialize(): array {
$data = [
self::JSON_PROPERTY_TYPE => self::JSON_TYPE,
self::JSON_PROPERTY_SCHEMA => $this->data['schema'] ?? 1,
];
if (!empty($this->data['headers'])) {
$data[self::JSON_PROPERTY_HEADERS] = $this->data['headers'];
}
if (isset($this->data['urid']) && $this->data['urid'] !== null) {
$data[self::JSON_PROPERTY_URID] = $this->data['urid'];
}
if (isset($this->data['date']) && $this->data['date'] !== null) {
$data[self::JSON_PROPERTY_DATE] = $this->data['date'] instanceof DateTimeImmutable
? $this->data['date']->format('c')
: $this->data['date'];
}
if (isset($this->data['received']) && $this->data['received'] !== null) {
$data[self::JSON_PROPERTY_RECEIVED] = $this->data['received'] instanceof DateTimeImmutable
? $this->data['received']->format('c')
: $this->data['received'];
}
if (isset($this->data['size']) && $this->data['size'] !== null) {
$data[self::JSON_PROPERTY_SIZE] = $this->data['size'];
}
if (isset($this->data['sender']) && $this->data['sender'] !== null) {
$data[self::JSON_PROPERTY_SENDER] = $this->data['sender'];
}
if (isset($this->data['from']) && $this->data['from'] !== null) {
$data[self::JSON_PROPERTY_FROM] = $this->data['from'];
}
if (!empty($this->data['replyTo'])) {
$data[self::JSON_PROPERTY_REPLY_TO] = $this->data['replyTo'];
}
if (!empty($this->data['to'])) {
$data[self::JSON_PROPERTY_TO] = $this->data['to'];
}
if (!empty($this->data['cc'])) {
$data[self::JSON_PROPERTY_CC] = $this->data['cc'];
}
if (!empty($this->data['bcc'])) {
$data[self::JSON_PROPERTY_BCC] = $this->data['bcc'];
}
if (isset($this->data['inReplyTo']) && $this->data['inReplyTo'] !== null) {
$data[self::JSON_PROPERTY_IN_REPLY_TO] = $this->data['inReplyTo'];
}
if (!empty($this->data['references'])) {
$data[self::JSON_PROPERTY_REFERENCES] = $this->data['references'];
}
if (isset($this->data['snippet']) && $this->data['snippet'] !== null) {
$data[self::JSON_PROPERTY_SNIPPET] = $this->data['snippet'];
}
if (!empty($this->data['attachments'])) {
$data[self::JSON_PROPERTY_ATTACHMENTS] = $this->data['attachments'];
}
if (!empty($this->data['flags'])) {
$data[self::JSON_PROPERTY_FLAGS] = $this->data['flags'];
}
$data[self::JSON_PROPERTY_SUBJECT] = $this->data['subject'] ?? null;
$data[self::JSON_PROPERTY_BODY] = $this->data['body'] ?? null;
return $data;
}
}

View File

@@ -19,26 +19,35 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseInterface;
*/
interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface {
public const JSON_TYPE = 'mail.message';
public const JSON_PROPERTY_HEADERS = 'headers';
public const JSON_PROPERTY_URID = 'urid';
public const JSON_PROPERTY_DATE = 'date';
public const JSON_PROPERTY_RECEIVED = 'received';
public const JSON_PROPERTY_SIZE = 'size';
public const JSON_PROPERTY_SENDER = 'sender';
public const JSON_PROPERTY_FROM = 'from';
public const JSON_PROPERTY_REPLY_TO = 'replyTo';
public const JSON_PROPERTY_TO = 'to';
public const JSON_PROPERTY_CC = 'cc';
public const JSON_PROPERTY_BCC = 'bcc';
public const JSON_PROPERTY_IN_REPLY_TO = 'inReplyTo';
public const JSON_PROPERTY_REFERENCES = 'references';
public const JSON_PROPERTY_SUBJECT = 'subject';
public const JSON_PROPERTY_SNIPPET = 'snippet';
public const JSON_PROPERTY_BODY = 'body';
public const JSON_PROPERTY_ATTACHMENTS = 'attachments';
public const JSON_PROPERTY_FLAGS = 'flags';
public const JSON_PROPERTY_TAGS = 'tags';
public const PROPERTY_SIZE = 'size';
public const PROPERTY_HEADERS = 'headers';
public const PROPERTY_URID = 'urid'; // mime message ID or similar unique identifier
public const PROPERTY_IN_REPLY_TO = 'inReplyTo';
public const PROPERTY_REFERENCES = 'references';
public const PROPERTY_RECEIVED = 'received';
public const PROPERTY_SENT = 'sent';
public const PROPERTY_SENDER = 'sender';
public const PROPERTY_REPLY_TO = 'replyTo';
public const PROPERTY_FROM = 'from';
public const PROPERTY_TO = 'to';
public const PROPERTY_CC = 'cc';
public const PROPERTY_BCC = 'bcc';
public const PROPERTY_SUBJECT = 'subject';
public const PROPERTY_BODY = 'body';
public const PROPERTY_BODY_TEXT_PLAIN = 'bodyTextPlain';
public const PROPERTY_BODY_TEXT_HTML = 'bodyTextHtml';
public const PROPERTY_ATTACHMENTS = 'attachments';
public const PROPERTY_FLAGS = 'flags';
public const PROPERTY_TAGS = 'tags';
/**
* Gets the message size in bytes
*
* @since 2025.05.01
*
* @return int|null
*/
public function getSize(): ?int;
/**
* Gets custom headers
@@ -70,13 +79,22 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface {
public function getUrid(): ?string;
/**
* Gets the message date
* Gets the message ID this is replying to
*
* @since 2025.05.01
*
* @return DateTimeImmutable|null
* @return string|null
*/
public function getDate(): ?DateTimeImmutable;
public function getInReplyTo(): ?string;
/**
* Gets the references (message IDs in thread)
*
* @since 2025.05.01
*
* @return array<int,string>
*/
public function getReferences(): array;
/**
* Gets the received date
@@ -88,13 +106,13 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface {
public function getReceived(): ?DateTimeImmutable;
/**
* Gets the message size in bytes
* Gets the sent date
*
* @since 2025.05.01
*
* @return int|null
* @return DateTimeImmutable|null
*/
public function getSize(): ?int;
public function getSent(): ?DateTimeImmutable;
/**
* Gets the sender address (actual sender, may differ from From)
@@ -149,24 +167,6 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface {
*/
public function getBcc(): array;
/**
* Gets the message ID this is replying to
*
* @since 2025.05.01
*
* @return string|null
*/
public function getInReplyTo(): ?string;
/**
* Gets the references (message IDs in thread)
*
* @since 2025.05.01
*
* @return array<int,string>
*/
public function getReferences(): array;
/**
* Gets the message subject
*
@@ -176,24 +176,6 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface {
*/
public function getSubject(): string;
/**
* Gets the message snippet/preview
*
* @since 2025.05.01
*
* @return string|null
*/
public function getSnippet(): ?string;
/**
* Checks if the message has any body content
*
* @since 2025.05.01
*
* @return bool True if text or HTML body is set
*/
public function hasBody(): bool;
/**
* Gets the message body structure
*
@@ -203,6 +185,15 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface {
*/
public function getBody(): ?MessagePartInterface;
/**
* Checks if the message has any body content
*
* @since 2025.05.01
*
* @return bool True if text or HTML body is set
*/
public function hasBody(): bool;
/**
* Gets the plain text body content
*
@@ -210,7 +201,7 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface {
*
* @return string|null
*/
public function getBodyText(): ?string;
public function getBodyTextPlain(): ?string;
/**
* Gets the HTML body content
@@ -219,7 +210,7 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface {
*
* @return string|null
*/
public function getBodyHtml(): ?string;
public function getBodyTextHtml(): ?string;
/**
* Gets the attachments

View File

@@ -19,422 +19,9 @@ use DateTimeImmutable;
* @since 2025.05.01
*/
abstract class MessagePropertiesMutableAbstract extends MessagePropertiesBaseAbstract implements MessagePropertiesMutableInterface {
public const JSON_TYPE = MessagePropertiesBaseInterface::JSON_TYPE;
/**
* @inheritDoc
*/
public function setHeaders(array $value): static {
$this->data['headers'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setHeader(string $name, string|array $value): static {
$this->data['headers'][$name] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setUrid(?string $value): static {
$this->data['urid'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setCreated(DateTimeImmutable $value): static {
$this->data['created'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setModified(DateTimeImmutable $value): static {
$this->data['modified'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setDate(DateTimeImmutable $value): static {
$this->data['date'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setReceived(?DateTimeImmutable $value): static {
$this->data['received'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setSize(?int $value): static {
$this->data['size'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setSender(?AddressInterface $value): static {
$this->data['sender'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setFrom(AddressInterface $value): static {
$this->data['from'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setReplyTo(AddressInterface ...$value): static {
$this->data['replyTo'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setTo(AddressInterface ...$value): static {
$this->data['to'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setCc(AddressInterface ...$value): static {
$this->data['cc'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setBcc(AddressInterface ...$value): static {
$this->data['bcc'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setInReplyTo(?string $value): static {
$this->data['inReplyTo'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setReferences(string ...$value): static {
$this->data['references'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setSubject(string $value): static {
$this->data['subject'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setSnippet(?string $value): static {
$this->data['snippet'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setBodyText(?string $value): static {
$this->data['bodyText'] = $value;
return $this;
}
/**
* Sets the plain text body charset
*
* @since 2025.05.01
*
* @param string $value
*
* @return static
*/
public function setBodyTextCharset(string $value): static {
$this->data['bodyTextCharset'] = $value;
return $this;
}
/**
* Sets the plain text body size
*
* @since 2025.05.01
*
* @param int $value
*
* @return static
*/
public function setBodyTextSize(int $value): static {
$this->data['bodyTextSize'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setBodyHtml(?string $value): static {
$this->data['bodyHtml'] = $value;
return $this;
}
/**
* Sets the HTML body charset
*
* @since 2025.05.01
*
* @param string $value
*
* @return static
*/
public function setBodyHtmlCharset(string $value): static {
$this->data['bodyHtmlCharset'] = $value;
return $this;
}
/**
* Sets the HTML body size
*
* @since 2025.05.01
*
* @param int $value
*
* @return static
*/
public function setBodyHtmlSize(int $value): static {
$this->data['bodyHtmlSize'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setAttachments(AttachmentInterface ...$value): static {
$this->data['attachments'] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function addAttachment(AttachmentInterface $value): static {
$this->data['attachments'][] = $value;
return $this;
}
/**
* Sets message flags
*
* @since 2025.05.01
*
* @param array $value
*
* @return static
*/
public function setFlags(array $value): static {
if (!isset($this->data['flags'])) {
$this->data['flags'] = [
'read' => false,
'starred' => false,
'important' => false,
'answered' => false,
'forwarded' => false,
'draft' => false,
'deleted' => false,
'flagged' => false,
];
}
$this->data['flags'] = array_merge($this->data['flags'], $value);
return $this;
}
/**
* @inheritDoc
*/
public function setFlag(string $name, bool $value): static {
if (!isset($this->data['flags'])) {
$this->data['flags'] = [
'read' => false,
'starred' => false,
'important' => false,
'answered' => false,
'forwarded' => false,
'draft' => false,
'deleted' => false,
'flagged' => false,
];
}
if (array_key_exists($name, $this->data['flags'])) {
$this->data['flags'][$name] = $value;
}
return $this;
}
/**
* Sets message labels
*
* @since 2025.05.01
*
* @param string ...$value
*
* @return static
*/
public function setLabels(string ...$value): static {
$this->data['labels'] = $value;
return $this;
}
/**
* Adds a message label
*
* @since 2025.05.01
*
* @param string $value
*
* @return static
*/
public function addLabel(string $value): static {
$this->data['labels'][] = $value;
return $this;
}
/**
* Sets message tags
*
* @since 2025.05.01
*
* @param string ...$value
*
* @return static
*/
public function setTags(string ...$value): static {
$this->data['tags'] = $value;
return $this;
}
/**
* Adds a message tag
*
* @since 2025.05.01
*
* @param string $value
*
* @return static
*/
public function addTag(string $value): static {
$this->data['tags'][] = $value;
return $this;
}
/**
* Sets message priority
*
* @since 2025.05.01
*
* @param string $value
*
* @return static
*/
public function setPriority(string $value): static {
$this->data['priority'] = $value;
return $this;
}
/**
* Sets message sensitivity
*
* @since 2025.05.01
*
* @param string $value
*
* @return static
*/
public function setSensitivity(string $value): static {
$this->data['sensitivity'] = $value;
return $this;
}
/**
* Sets encryption information
*
* @since 2025.05.01
*
* @param array $value
*
* @return static
*/
public function setEncryption(array $value): static {
if (!isset($this->data['encryption'])) {
$this->data['encryption'] = [
'method' => null,
'signed' => false,
'encrypted' => false,
];
}
$this->data['encryption'] = array_merge($this->data['encryption'], $value);
return $this;
}
/**
* Sets delivery receipt flag
*
* @since 2025.05.01
*
* @param bool $value
*
* @return static
*/
public function setDeliveryReceipt(bool $value): static {
$this->data['deliveryReceipt'] = $value;
return $this;
}
/**
* Sets read receipt flag
*
* @since 2025.05.01
*
* @param bool $value
*
* @return static
*/
public function setReadReceipt(bool $value): static {
$this->data['readReceipt'] = $value;
return $this;
}
protected string $type = 'mail.message';
/**
* @inheritDoc
*/
@@ -452,4 +39,213 @@ abstract class MessagePropertiesMutableAbstract extends MessagePropertiesBaseAbs
return $this;
}
/**
* @inheritDoc
*/
public function setSize(?int $value): static {
$this->data[static::PROPERTY_SIZE] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setHeaders(array $value): static {
$this->data[static::PROPERTY_HEADERS] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setHeader(string $name, string|array $value): static {
$this->data[static::PROPERTY_HEADERS][$name] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setUrid(?string $value): static {
$this->data[static::PROPERTY_URID] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setInReplyTo(?string $value): static {
$this->data[static::PROPERTY_IN_REPLY_TO] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setReferences(string ...$value): static {
$this->data[static::PROPERTY_REFERENCES] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setReceived(?DateTimeImmutable $value): static {
$this->data[static::PROPERTY_RECEIVED] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setSent(DateTimeImmutable $value): static {
$this->data[static::PROPERTY_SENT] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setSender(?AddressInterface $value): static {
$this->data[static::PROPERTY_SENDER] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setFrom(AddressInterface $value): static {
$this->data[static::PROPERTY_FROM] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setReplyTo(AddressInterface ...$value): static {
$this->data[static::PROPERTY_REPLY_TO] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setTo(AddressInterface ...$value): static {
$this->data[static::PROPERTY_TO] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setCc(AddressInterface ...$value): static {
$this->data[static::PROPERTY_CC] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setBcc(AddressInterface ...$value): static {
$this->data[static::PROPERTY_BCC] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setSubject(string $value): static {
$this->data[static::PROPERTY_SUBJECT] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setBody(?MessagePartInterface $value): static {
$this->data[static::PROPERTY_BODY] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setBodyTextPlain(?string $value): static {
$this->data[static::PROPERTY_BODY_TEXT_PLAIN] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setBodyTextHtml(?string $value): static {
$this->data[static::PROPERTY_BODY_TEXT_HTML] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function setAttachments(AttachmentInterface ...$value): static {
$this->data[static::PROPERTY_ATTACHMENTS] = $value;
return $this;
}
/**
* @inheritDoc
*/
public function addAttachment(AttachmentInterface $value): static {
$this->data[static::PROPERTY_ATTACHMENTS][] = $value;
return $this;
}
/**
* Sets message flags
*
* @since 2025.05.01
*
* @param array $value
*
* @return static
*/
public function setFlags(array $value): static {
if (!isset($this->data[static::PROPERTY_FLAGS])) {
$this->data[static::PROPERTY_FLAGS] = [
'read' => false,
'starred' => false,
'important' => false,
'answered' => false,
'forwarded' => false,
'draft' => false,
'deleted' => false,
'flagged' => false,
];
}
$this->data[static::PROPERTY_FLAGS] = array_merge($this->data[static::PROPERTY_FLAGS], $value);
return $this;
}
/**
* @inheritDoc
*/
public function setFlag(string $name, bool $value): static {
if (!isset($this->data[static::PROPERTY_FLAGS])) {
$this->data[static::PROPERTY_FLAGS] = [
'read' => false,
'starred' => false,
'important' => false,
'answered' => false,
'forwarded' => false,
'draft' => false,
'deleted' => false,
'flagged' => false,
];
}
if (array_key_exists($name, $this->data[static::PROPERTY_FLAGS])) {
$this->data[static::PROPERTY_FLAGS][$name] = $value;
}
return $this;
}
}

View File

@@ -18,9 +18,18 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface;
* @since 2025.05.01
*/
interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterface, NodePropertiesMutableInterface {
public const JSON_TYPE = MessagePropertiesBaseInterface::JSON_TYPE;
/**
* Sets the message size in bytes
*
* @since 2025.05.01
*
* @param int|null $value
*
* @return self
*/
public function setSize(?int $value): static;
/**
* Sets custom headers
*
@@ -56,15 +65,26 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa
public function setUrid(?string $value): static;
/**
* Sets the message date
* Sets the message ID this is replying to
*
* @since 2025.05.01
*
* @param DateTimeImmutable $value
* @param string|null $value
*
* @return self
*/
public function setDate(DateTimeImmutable $value): static;
public function setInReplyTo(?string $value): static;
/**
* Sets the references (message IDs in thread)
*
* @since 2025.05.01
*
* @param string ...$value
*
* @return self
*/
public function setReferences(string ...$value): static;
/**
* Sets the received date
@@ -77,16 +97,16 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa
*/
public function setReceived(?DateTimeImmutable $value): static;
/**
* Sets the message size in bytes
/**
* Sets the message date
*
* @since 2025.05.01
*
* @param int|null $value
* @param DateTimeImmutable $value
*
* @return self
*/
public function setSize(?int $value): static;
public function setSent(DateTimeImmutable $value): static;
/**
* Sets the sender address (actual sender, may differ from From)
@@ -154,28 +174,6 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa
*/
public function setBcc(AddressInterface ...$value): static;
/**
* Sets the message ID this is replying to
*
* @since 2025.05.01
*
* @param string|null $value
*
* @return self
*/
public function setInReplyTo(?string $value): static;
/**
* Sets the references (message IDs in thread)
*
* @since 2025.05.01
*
* @param string ...$value
*
* @return self
*/
public function setReferences(string ...$value): static;
/**
* Sets the message subject
*
@@ -188,15 +186,15 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa
public function setSubject(string $value): static;
/**
* Sets the message snippet/preview
* Sets the message body
*
* @since 2025.05.01
*
* @param string|null $value
* @param MessagePartInterface|null $value
*
* @return self
*/
public function setSnippet(?string $value): static;
public function setBody(?MessagePartInterface $value): static;
/**
* Sets the plain text body content
@@ -207,7 +205,7 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa
*
* @return self
*/
public function setBodyText(?string $value): static;
public function setBodyTextPlain(?string $value): static;
/**
* Sets the HTML body content
@@ -218,7 +216,7 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa
*
* @return self
*/
public function setBodyHtml(?string $value): static;
public function setBodyTextHtml(?string $value): static;
/**
* Sets the attachments
@@ -241,15 +239,28 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa
* @return self
*/
public function addAttachment(AttachmentInterface $value): static;
/**
* Sets message tags
* Sets message flags
*
* @since 2025.05.01
*
* @param array{read: bool, starred: bool, important: bool, answered: bool, forwarded: bool, draft: bool, deleted: bool, flagged: bool} $value
* @param array $value
*
* @return self
*/
public function setFlags(array $value): static;
/**
* Sets message flags
*
* @since 2025.05.01
*
* @param string $label
* @param bool $value
*
* @return self
*/
public function setFlag(string $label, bool $value): static;
}

View File

@@ -26,7 +26,7 @@ use KTXF\Resource\Provider\ResourceServiceLocationInterface;
*
* @since 2025.05.01
*/
interface ProviderServiceDiscoverInterface extends ProviderBaseInterface {
interface ProviderServiceDiscoverInterface {
/**
* Attempts to discover service configuration using provider-specific methods.

View File

@@ -25,9 +25,7 @@ use KTXF\Resource\Provider\ResourceProviderServiceMutateInterface;
* @method string serviceModify(string $tenantId, ?string $userId, ServiceMutableInterface $service) Modify a mail service configuration
* @method bool serviceDestroy(string $tenantId, ?string $userId, ServiceMutableInterface $service) Delete a mail service configuration
*/
interface ProviderServiceMutateInterface extends ProviderBaseInterface, ResourceProviderServiceMutateInterface {
public const JSON_TYPE = ProviderBaseInterface::JSON_TYPE;
interface ProviderServiceMutateInterface extends ResourceProviderServiceMutateInterface {
// Methods inherited from ResourceProviderServiceMutateInterface
// Implementations should return/accept ServiceMutableInterface instances

View File

@@ -10,6 +10,7 @@ declare(strict_types=1);
namespace KTXF\Mail\Provider;
use KTXF\Mail\Service\ServiceBaseInterface;
use KTXF\Mail\Service\ServiceMutableInterface;
/**
* Mail Provider Service Test Interface
@@ -25,7 +26,7 @@ use KTXF\Mail\Service\ServiceBaseInterface;
*
* @since 2025.05.01
*/
interface ProviderServiceTestInterface extends ProviderBaseInterface {
interface ProviderServiceTestInterface {
/**
* Test a service connection
@@ -39,7 +40,7 @@ interface ProviderServiceTestInterface extends ProviderBaseInterface {
*
* @since 2025.05.01
*
* @param ServiceBaseInterface $service Service to test (can be fresh/unsaved or existing)
* @param ServiceBaseInterface|ServiceMutableInterface $service Service to test (can be fresh/unsaved or existing)
* @param array $options Provider-specific test options:
* - 'timeout' => int (seconds, default: 10)
* - 'verify_ssl' => bool (default: true)
@@ -72,6 +73,6 @@ interface ProviderServiceTestInterface extends ProviderBaseInterface {
* ]
* ]
*/
public function serviceTest(ServiceBaseInterface $service, array $options = []): array;
public function serviceTest(ServiceBaseInterface|ServiceMutableInterface $service, array $options = []): array;
}

View File

@@ -11,6 +11,8 @@ namespace KTXF\Mail\Service;
use KTXF\Mail\Collection\CollectionBaseInterface;
use KTXF\Mail\Collection\CollectionMutableInterface;
use KTXF\Mail\Collection\CollectionPropertiesBaseInterface;
use KTXF\Resource\Identifier\CollectionIdentifier;
/**
* Mail Service Collection Mutable Interface
@@ -20,7 +22,7 @@ use KTXF\Mail\Collection\CollectionMutableInterface;
*
* @since 2025.05.01
*/
interface ServiceCollectionMutableInterface extends ServiceBaseInterface {
interface ServiceCollectionMutableInterface {
public const CAPABILITY_COLLECTION_CREATE = 'CollectionCreate';
public const CAPABILITY_COLLECTION_UPDATE = 'CollectionUpdate';
@@ -41,48 +43,48 @@ interface ServiceCollectionMutableInterface extends ServiceBaseInterface {
*
* @since 2025.05.01
*
* @param string|int|null $location Parent collection ID (null for root)
* @param CollectionMutableInterface $collection Collection to create
* @param CollectionIdentifier $target Target collection identifier (parent)
* @param CollectionPropertiesBaseInterface $properties Collection properties
* @param array $options Protocol-specific options
*
* @return CollectionBaseInterface Created collection with assigned ID
*/
public function collectionCreate(string|int|null $location, CollectionMutableInterface $collection, array $options = []): CollectionBaseInterface;
public function collectionCreate(CollectionIdentifier|null $target, CollectionPropertiesBaseInterface $properties, array $options = []): CollectionBaseInterface;
/**
* Updates an existing collection
*
* @since 2025.05.01
*
* @param string|int $identifier Collection ID
* @param CollectionMutableInterface $collection Updated collection data
* @param CollectionIdentifier $target Target collection identifier
* @param CollectionPropertiesBaseInterface $properties Updated collection data
*
* @return CollectionBaseInterface Updated collection
*/
public function collectionUpdate(string|int $identifier, CollectionMutableInterface $collection): CollectionBaseInterface;
public function collectionUpdate(CollectionIdentifier $target, CollectionPropertiesBaseInterface $properties): CollectionBaseInterface;
/**
* Deletes a collection
*
* @since 2025.05.01
*
* @param string|int $identifier Collection ID
* @param CollectionIdentifier $target Target collection identifier
* @param bool $force Force deletion even if not empty
*
* @return CollectionBaseInterface|true Collection object on soft delete, true on hard delete
*/
public function collectionDelete(string|int $identifier, bool $force = false): CollectionBaseInterface | true;
public function collectionDelete(CollectionIdentifier $target, bool $force = false): CollectionBaseInterface | true;
/**
* Moves a collection to a new parent
*
* @since 2025.05.01
*
* @param string|int $identifier Collection ID
* @param string|int|null $targetLocation New parent ID (null for root)
* @param CollectionIdentifier $source Source collection identifier
* @param CollectionIdentifier $target Target collection identifier
*
* @return CollectionBaseInterface Moved collection
*/
public function collectionMove(string|int $identifier, string|int|null $targetLocation): CollectionBaseInterface;
public function collectionMove(CollectionIdentifier $target, CollectionIdentifier $source): CollectionBaseInterface;
}

View File

@@ -12,15 +12,12 @@ namespace KTXF\Mail\Service;
use KTXF\Resource\Provider\ResourceServiceConfigureInterface;
/**
* Mail Service Mutable Interface
* Mail Service Configurable Interface
*
* Extends base service interface with setter methods for mutable properties.
* Used for service configuration and updates.
*
* @since 2025.05.01
*/
interface ServiceConfigurableInterface extends ServiceMutableInterface, ResourceServiceConfigureInterface {
public const JSON_TYPE = ServiceBaseInterface::JSON_TYPE;
interface ServiceConfigurableInterface extends ResourceServiceConfigureInterface {
}

View File

@@ -11,6 +11,9 @@ namespace KTXF\Mail\Service;
use KTXF\Mail\Entity\EntityBaseInterface;
use KTXF\Mail\Entity\EntityMutableInterface;
use KTXF\Mail\Object\MessagePropertiesMutableInterface;
use KTXF\Resource\Identifier\CollectionIdentifier;
use KTXF\Resource\Identifier\EntityIdentifier;
/**
* Mail Service Entity Mutable Interface
@@ -20,11 +23,12 @@ use KTXF\Mail\Entity\EntityMutableInterface;
*
* @since 2025.05.01
*/
interface ServiceEntityMutableInterface extends ServiceBaseInterface {
interface ServiceEntityMutableInterface {
public const CAPABILITY_ENTITY_CREATE = 'EntityCreate';
public const CAPABILITY_ENTITY_MODIFY = 'EntityModify';
public const CAPABILITY_ENTITY_DELETE = 'EntityDelete';
public const CAPABILITY_ENTITY_PATCH = 'EntityPatch';
public const CAPABILITY_ENTITY_COPY = 'EntityCopy';
public const CAPABILITY_ENTITY_MOVE = 'EntityMove';
@@ -42,49 +46,54 @@ interface ServiceEntityMutableInterface extends ServiceBaseInterface {
*
* @since 2025.05.01
*
* @param string|int $collection collection identifier
* @param EntityMutableInterface $entity Entity data
* @param array $options additional options
* @param CollectionIdentifier $target Target collection identifier
* @param MessagePropertiesMutableInterface $properties Entity properties
* @param array $options Additional options
*
* @return EntityBaseInterface Created entity
*/
public function entityCreate(string|int $collection, EntityMutableInterface $entity, array $options = []): EntityBaseInterface;
public function entityCreate(CollectionIdentifier $target, MessagePropertiesMutableInterface $properties, array $options = []): EntityBaseInterface;
/**
* Modifies an existing entity
*
* @since 2025.05.01
*
* @param string|int $collection Collection identifier
* @param string|int $identifier Entity identifier
* @param EntityMutableInterface $entity Entity data
* @param EntityIdentifier $target Target entity identifier
* @param MessagePropertiesMutableInterface $properties Entity properties to update
*
* @return EntityBaseInterface Modified entity
*/
public function entityModify(string|int $collection, string|int $identifier, EntityMutableInterface $entity): EntityBaseInterface;
public function entityModify(EntityIdentifier $target, MessagePropertiesMutableInterface $properties): EntityBaseInterface;
/**
* Deletes entities
*
* @since 2026.04.01
*
* @param EntityIdentifier ...$identifiers Source entities to delete
* @param EntityIdentifier ...$targets Source entities to delete
*
* @return array<string|int,bool|string> Results keyed by entity identifier (true on success, error string on failure)
* @return array<string, array{
* disposition: 'moved'|'deleted'|'error',
* destination: ?CollectionIdentifier,
* mutation: EntityIdentifier
* }> Results keyed by source entity identifier
*/
public function entityDelete(EntityIdentifier ...$identifiers): array;
public function entityDelete(EntityIdentifier ...$targets): array;
/**
* Copies entities to another collection
* Patches an existing entity(ies) with partial data
*
* @since 2025.05.01
*
* @param CollectionIdentifier $target Target collection identifier
* @param EntityIdentifier ...$identifiers Source entities to copy
* @param MessagePropertiesMutableInterface $properties Partial entity properties
* @param EntityIdentifier ...$targets Source entities to patch
*
* @return array<string|int,bool> List of copied entity identifiers
* @return array<string, array{
* disposition: 'patched'|'error'
* }> Results keyed by source entity identifier
*/
public function entityCopy(CollectionIdentifier $target, EntityIdentifier ...$identifiers): array;
public function entityPatch(MessagePropertiesMutableInterface $properties, EntityIdentifier ...$targets): array;
/**
* Moves entities to another collection
@@ -92,10 +101,30 @@ interface ServiceEntityMutableInterface extends ServiceBaseInterface {
* @since 2025.05.01
*
* @param CollectionIdentifier $target Target collection identifier
* @param EntityIdentifier ...$identifiers Source entities to move
* @param EntityIdentifier ...$sources Source entities to move
*
* @return array<string|int,bool> List of moved entity identifiers
* @return array<string, array{
* disposition: 'moved'|'error',
* destination: ?CollectionIdentifier,
* mutation: EntityIdentifier
* }> Results keyed by source entity identifier
*/
public function entityMove(CollectionIdentifier $target, EntityIdentifier ...$identifiers): array;
public function entityMove(CollectionIdentifier $target, EntityIdentifier ...$sources): array;
/**
* Copies entities to another collection
*
* @since 2025.05.01
*
* @param CollectionIdentifier $target Target collection identifier
* @param EntityIdentifier ...$sources Source entities to copy
*
* @return array<string, array{
* disposition: 'copied'|'error',
* destination: ?CollectionIdentifier,
* mutation: EntityIdentifier
* }> Results keyed by source entity identifier
*/
public function entityCopy(CollectionIdentifier $target, EntityIdentifier ...$sources): array;
}

View File

@@ -19,7 +19,7 @@ use KTXF\Mail\Exception\SendException;
*
* @since 2025.05.01
*/
interface ServiceEntityTransmitInterface extends ServiceBaseInterface {
interface ServiceEntityTransmitInterface {
public const CAPABILITY_ENTITY_TRANSMIT = 'EntityTransmit';

View File

@@ -20,7 +20,7 @@ use KTXF\Resource\Provider\ResourceServiceMutateInterface;
*
* @since 2025.05.01
*/
interface ServiceMutableInterface extends ServiceBaseInterface, ResourceServiceMutateInterface {
interface ServiceMutableInterface extends ResourceServiceMutateInterface {
/**
* Sets the primary mailing address for this service

View File

@@ -35,6 +35,10 @@ class ResourceIdentifier implements ResourceIdentifierInterface {
return $this->provider;
}
public function jsonSerialize(): string {
return (string) $this;
}
/**
* Parse a colon-separated identifier string and return the appropriate level class
*

View File

@@ -9,10 +9,12 @@ declare(strict_types=1);
namespace KTXF\Resource\Identifier;
use KTXF\Json\JsonSerializable;
/**
* Top-level identifier for resources (provider level)
*/
interface ResourceIdentifierInterface extends \Stringable {
interface ResourceIdentifierInterface extends JsonSerializable, \Stringable {
/** The provider segment (e.g. "imap") */
public function provider(): string;
@@ -23,4 +25,7 @@ interface ResourceIdentifierInterface extends \Stringable {
/** Canonical string form: provider[:service[:collection[:entity]]] */
public function __toString(): string;
/** Canonical JSON form: provider[:service[:collection[:entity]]] */
public function jsonSerialize(): string;
}

View File

@@ -151,4 +151,11 @@ class ResourceIdentifiers implements ResourceIdentifiersInterface {
return count($this->identifiers) === 0;
}
public function jsonSerialize(): array {
return array_map(
static fn (ResourceIdentifierInterface $identifier): string => $identifier->jsonSerialize(),
$this->identifiers,
);
}
}

View File

@@ -9,10 +9,12 @@ declare(strict_types=1);
namespace KTXF\Resource\Identifier;
use KTXF\Json\JsonSerializable;
/**
* A typed collection of resource identifiers with search and filter capabilities
*/
interface ResourceIdentifiersInterface extends \Countable, \IteratorAggregate {
interface ResourceIdentifiersInterface extends JsonSerializable, \Countable, \IteratorAggregate {
/** Add an identifier to the collection */
public function add(ResourceIdentifierInterface $identifier): void;
@@ -47,4 +49,7 @@ interface ResourceIdentifiersInterface extends \Countable, \IteratorAggregate {
/** Get unique entity names */
public function entities(): array;
/** Serialize as an array of canonical identifier strings */
public function jsonSerialize(): array;
}

View File

@@ -10,6 +10,11 @@ declare(strict_types=1);
namespace KTXF\Resource\Provider\Node;
use DateTimeImmutable;
use KTXF\Resource\Identifier\CollectionIdentifier;
use KTXF\Resource\Identifier\CollectionIdentifierInterface;
use KTXF\Resource\Identifier\EntityIdentifierInterface;
use KTXF\Resource\Identifier\ResourceIdentifier;
use KTXF\Resource\Identifier\ServiceIdentifier;
/**
* Abstract Node Base Class
@@ -23,6 +28,7 @@ abstract class NodeBaseAbstract implements NodeBaseInterface {
/**
* Internal data storage
*/
protected string $type = 'resource.node';
protected array $data = [];
public function __construct(
@@ -30,87 +36,96 @@ abstract class NodeBaseAbstract implements NodeBaseInterface {
protected readonly string|int $service,
) {
$this->data = [
static::JSON_PROPERTY_PROVIDER => $this->provider,
static::JSON_PROPERTY_SERVICE => $this->service,
static::JSON_PROPERTY_COLLECTION => null,
static::JSON_PROPERTY_IDENTIFIER => null,
static::JSON_PROPERTY_SIGNATURE => null,
static::JSON_PROPERTY_CREATED => null,
static::JSON_PROPERTY_MODIFIED => null,
static::PROPERTY_TYPE => $this->type,
static::PROPERTY_PROVIDER => $this->provider,
static::PROPERTY_SERVICE => $this->service,
static::PROPERTY_COLLECTION => null,
static::PROPERTY_IDENTIFIER => null,
static::PROPERTY_SIGNATURE => null,
static::PROPERTY_CREATED => null,
static::PROPERTY_MODIFIED => null,
];
}
/**
* @inheritDoc
*/
public function type(): string {
return static::RESOURCE_TYPE;
}
/**
* @inheritDoc
*/
public function provider(): string {
return $this->data[static::JSON_PROPERTY_PROVIDER];
}
/**
* @inheritDoc
*/
public function service(): string|int {
return $this->data[static::JSON_PROPERTY_SERVICE];
}
/**
* @inheritDoc
*/
public function collection(): string|int|null {
return $this->data[static::JSON_PROPERTY_COLLECTION] ?? null;
}
/**
* @inheritDoc
*/
public function identifier(): string|int|null {
return $this->data[static::JSON_PROPERTY_IDENTIFIER] ?? null;
}
/**
* @inheritDoc
*/
public function signature(): string|null {
return isset($this->data[static::JSON_PROPERTY_SIGNATURE])
? (string)$this->data[static::JSON_PROPERTY_SIGNATURE]
: null;
}
/**
* @inheritDoc
*/
public function created(): DateTimeImmutable|null {
return isset($this->data[static::JSON_PROPERTY_CREATED])
? new DateTimeImmutable($this->data[static::JSON_PROPERTY_CREATED])
: null;
}
/**
* @inheritDoc
*/
public function modified(): DateTimeImmutable|null {
return isset($this->data[static::JSON_PROPERTY_MODIFIED])
? new DateTimeImmutable($this->data[static::JSON_PROPERTY_MODIFIED])
: null;
}
/**
* @inheritDoc
*/
public function jsonSerialize(): array {
$data = $this->data;
$data[static::JSON_PROPERTY_PROPERTIES] = $this->getProperties()->jsonSerialize();
$data['provider'] = new ResourceIdentifier($this->data[static::PROPERTY_PROVIDER]);
$data['service'] = new ServiceIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE]);
$data['collection'] = isset($this->data[static::PROPERTY_COLLECTION])
? new CollectionIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], $this->data[static::PROPERTY_COLLECTION])
: null;
$data['identifier'] = $this->nodeIdentifier();
$data[static::PROPERTY_PROPERTIES] = $this->getProperties()->jsonSerialize();
return $data;
}
abstract protected function nodeIdentifier(): CollectionIdentifierInterface|EntityIdentifierInterface|null;
/**
* @inheritDoc
*/
public function type(): string {
return $this->data[static::PROPERTY_TYPE];
}
/**
* @inheritDoc
*/
public function provider(): string {
return $this->data[static::PROPERTY_PROVIDER];
}
/**
* @inheritDoc
*/
public function service(): string|int {
return $this->data[static::PROPERTY_SERVICE];
}
/**
* @inheritDoc
*/
public function collection(): string|int|null {
return $this->data[static::PROPERTY_COLLECTION] ?? null;
}
/**
* @inheritDoc
*/
public function identifier(): string|int|null {
return $this->data[static::PROPERTY_IDENTIFIER] ?? null;
}
/**
* @inheritDoc
*/
public function signature(): string|null {
return isset($this->data[static::PROPERTY_SIGNATURE])
? (string)$this->data[static::PROPERTY_SIGNATURE]
: null;
}
/**
* @inheritDoc
*/
public function created(): DateTimeImmutable|null {
return isset($this->data[static::PROPERTY_CREATED])
? new DateTimeImmutable($this->data[static::PROPERTY_CREATED])
: null;
}
/**
* @inheritDoc
*/
public function modified(): DateTimeImmutable|null {
return isset($this->data[static::PROPERTY_MODIFIED])
? new DateTimeImmutable($this->data[static::PROPERTY_MODIFIED])
: null;
}
/**
* @inheritDoc
*/

View File

@@ -19,15 +19,15 @@ use KTXF\Json\JsonSerializable;
*/
interface NodeBaseInterface extends JsonSerializable {
public const RESOURCE_TYPE = 'resource.node';
public const JSON_PROPERTY_PROVIDER = 'provider';
public const JSON_PROPERTY_SERVICE = 'service';
public const JSON_PROPERTY_COLLECTION = 'collection';
public const JSON_PROPERTY_IDENTIFIER = 'identifier';
public const JSON_PROPERTY_SIGNATURE = 'signature';
public const JSON_PROPERTY_CREATED = 'created';
public const JSON_PROPERTY_MODIFIED = 'modified';
public const JSON_PROPERTY_PROPERTIES = 'properties';
public const PROPERTY_TYPE = 'resource.node';
public const PROPERTY_PROVIDER = 'provider';
public const PROPERTY_SERVICE = 'service';
public const PROPERTY_COLLECTION = 'collection';
public const PROPERTY_IDENTIFIER = 'identifier';
public const PROPERTY_SIGNATURE = 'signature';
public const PROPERTY_CREATED = 'created';
public const PROPERTY_MODIFIED = 'modified';
public const PROPERTY_PROPERTIES = 'properties';
/**
* Node type

View File

@@ -28,56 +28,56 @@ abstract class NodeMutableAbstract extends NodeBaseAbstract implements NodeMutab
$this->data = [];
if (isset($data[static::JSON_PROPERTY_COLLECTION])) {
if (!is_string($data[static::JSON_PROPERTY_COLLECTION]) && !is_int($data[static::JSON_PROPERTY_COLLECTION])) {
if (isset($data[static::PROPERTY_COLLECTION])) {
if (!is_string($data[static::PROPERTY_COLLECTION]) && !is_int($data[static::PROPERTY_COLLECTION])) {
throw new \InvalidArgumentException("Collection must be a string or integer");
}
$this->data[static::JSON_PROPERTY_COLLECTION] = $data[static::JSON_PROPERTY_COLLECTION];
$this->data[static::PROPERTY_COLLECTION] = $data[static::PROPERTY_COLLECTION];
} else {
$this->data[static::JSON_PROPERTY_COLLECTION] = null;
$this->data[static::PROPERTY_COLLECTION] = null;
}
if (isset($data[static::JSON_PROPERTY_IDENTIFIER])) {
if (!is_string($data[static::JSON_PROPERTY_IDENTIFIER]) && !is_int($data[static::JSON_PROPERTY_IDENTIFIER])) {
if (isset($data[static::PROPERTY_IDENTIFIER])) {
if (!is_string($data[static::PROPERTY_IDENTIFIER]) && !is_int($data[static::PROPERTY_IDENTIFIER])) {
throw new \InvalidArgumentException("Identifier must be a string or integer");
}
$this->data[static::JSON_PROPERTY_IDENTIFIER] = $data[static::JSON_PROPERTY_IDENTIFIER];
$this->data[static::PROPERTY_IDENTIFIER] = $data[static::PROPERTY_IDENTIFIER];
} else {
$this->data[static::JSON_PROPERTY_IDENTIFIER] = null;
$this->data[static::PROPERTY_IDENTIFIER] = null;
}
if (isset($data[static::JSON_PROPERTY_SIGNATURE])) {
if (!is_string($data[static::JSON_PROPERTY_SIGNATURE]) && !is_int($data[static::JSON_PROPERTY_SIGNATURE])) {
if (isset($data[static::PROPERTY_SIGNATURE])) {
if (!is_string($data[static::PROPERTY_SIGNATURE]) && !is_int($data[static::PROPERTY_SIGNATURE])) {
throw new \InvalidArgumentException("Signature must be a string or integer");
}
$this->data[static::JSON_PROPERTY_SIGNATURE] = $data[static::JSON_PROPERTY_SIGNATURE];
$this->data[static::PROPERTY_SIGNATURE] = $data[static::PROPERTY_SIGNATURE];
} else {
$this->data[static::JSON_PROPERTY_SIGNATURE] = null;
$this->data[static::PROPERTY_SIGNATURE] = null;
}
if (isset($data[static::JSON_PROPERTY_CREATED])) {
if (!is_string($data[static::JSON_PROPERTY_CREATED])) {
if (isset($data[static::PROPERTY_CREATED])) {
if (!is_string($data[static::PROPERTY_CREATED])) {
throw new \InvalidArgumentException("Created date must be a string in ISO 8601 format");
}
$this->data[static::JSON_PROPERTY_CREATED] = $data[static::JSON_PROPERTY_CREATED];
$this->data[static::PROPERTY_CREATED] = $data[static::PROPERTY_CREATED];
} else {
$this->data[static::JSON_PROPERTY_CREATED] = null;
$this->data[static::PROPERTY_CREATED] = null;
}
if (isset($data[static::JSON_PROPERTY_MODIFIED])) {
if (!is_string($data[static::JSON_PROPERTY_MODIFIED])) {
if (isset($data[static::PROPERTY_MODIFIED])) {
if (!is_string($data[static::PROPERTY_MODIFIED])) {
throw new \InvalidArgumentException("Modified date must be a string in ISO 8601 format");
}
$this->data[static::JSON_PROPERTY_MODIFIED] = $data[static::JSON_PROPERTY_MODIFIED];
$this->data[static::PROPERTY_MODIFIED] = $data[static::PROPERTY_MODIFIED];
} else {
$this->data[static::JSON_PROPERTY_MODIFIED] = null;
$this->data[static::PROPERTY_MODIFIED] = null;
}
if (isset($data[static::JSON_PROPERTY_PROPERTIES])) {
if (!is_array($data[static::JSON_PROPERTY_PROPERTIES])) {
if (isset($data[static::PROPERTY_PROPERTIES])) {
if (!is_array($data[static::PROPERTY_PROPERTIES])) {
throw new \InvalidArgumentException("Properties must be an array");
}
$this->getProperties()->jsonDeserialize($data[static::JSON_PROPERTY_PROPERTIES]);
$this->getProperties()->jsonDeserialize($data[static::PROPERTY_PROPERTIES]);
}
return $this;

View File

@@ -18,16 +18,17 @@ namespace KTXF\Resource\Provider\Node;
*/
abstract class NodePropertiesBaseAbstract implements NodePropertiesBaseInterface {
protected string $type = 'resource.data';
protected array $data = [];
public function __construct(array $data) {
if (!isset($data[static::JSON_PROPERTY_TYPE])) {
$data[static::JSON_PROPERTY_TYPE] = static::JSON_TYPE;
if (!isset($data[static::PROPERTY_TYPE])) {
$data[static::PROPERTY_TYPE] = $this->type;
}
if (!isset($data[static::JSON_PROPERTY_SCHEMA])) {
$data[static::JSON_PROPERTY_SCHEMA] = 1;
if (!isset($data[static::PROPERTY_SCHEMA])) {
$data[static::PROPERTY_SCHEMA] = 1;
}
$this->data = $data;
@@ -44,14 +45,14 @@ abstract class NodePropertiesBaseAbstract implements NodePropertiesBaseInterface
* @inheritDoc
*/
public function type(): string {
return $this->data[static::JSON_PROPERTY_TYPE];
return $this->data[static::PROPERTY_TYPE];
}
/**
* @inheritDoc
*/
public function schema(): int {
return $this->data[static::JSON_PROPERTY_SCHEMA];
return $this->data[static::PROPERTY_SCHEMA];
}
}

View File

@@ -18,11 +18,8 @@ use JsonSerializable;
*/
interface NodePropertiesBaseInterface extends JsonSerializable {
public const RESOURCE_TYPE = 'resource.data';
public const JSON_TYPE = 'resource.data';
public const JSON_PROPERTY_TYPE = '@type';
public const JSON_PROPERTY_SCHEMA = 'schema';
public const PROPERTY_TYPE = '@type';
public const PROPERTY_SCHEMA = 'schema';
/**
* Get resource node properties type

View File

@@ -16,6 +16,4 @@ use KTXF\Json\JsonDeserializable;
*
* @since 2025.05.01
*/
interface NodePropertiesMutableInterface extends NodePropertiesBaseInterface, JsonDeserializable {
}
interface NodePropertiesMutableInterface extends NodePropertiesBaseInterface, JsonDeserializable {}