diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index c3f7398..627d67b 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -8,6 +8,7 @@ jobs: with: botName: "sitepark-bot" botEmail: "opensource@sitepark.com" + phpVersion: "8.4" secrets: # Sitepark-BOT personal access token BOT_PAT: ${{ secrets.BOT_PAT }} diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index b70c764..e876bef 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -12,6 +12,8 @@ on: jobs: verify: uses: sitepark/github-project-workflow/.github/workflows/composer-verify.yml@release/1.x + with: + phpVersions: '["8.2","8.3","8.4"]' secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index ba1f0c7..87d776e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /vendor /vendor.orig +composer.lock .idea /var/cache/* !var/cache/.gitkeep @@ -8,3 +9,4 @@ /tools .phpactor.json *.swp +.claude/ diff --git a/.phive/phars.xml b/.phive/phars.xml index 6ca4cd9..787253f 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,8 +1,8 @@ - - - - - + + + + + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..833d987 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,344 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +**Atoolo Form Bundle** is a Symfony bundle providing an HTTP interface for displaying and processing forms using [JSON Forms](https://jsonforms.io/). It integrates with the Atoolo Resource Bundle to load form definitions from resources and processes submissions through a configurable processor pipeline. + +- **Language**: PHP 8.1+ (tested on 8.2, 8.3, 8.4) +- **Framework**: Symfony 6.3+ / 7.0+ +- **License**: MIT +- **Documentation**: https://sitepark.github.io/atoolo-docs/develop/bundles/form/ + +## Development Commands + +### Setup +```bash +# Install dependencies +composer install + +# Install PHAR tools via Phive (runs automatically post-install) +phive install --force-accept-unsigned --trust-gpg-keys C00543248C87FB13,4AA394086372C20A,CF1A108D0E7AE720,51C67305FFC2E5C0,E82B2FB314E9906E +``` + +### Testing +```bash +# Run all tests with coverage +composer test +./tools/phpunit.phar -c phpunit.xml --coverage-text + +# Run specific test file +./tools/phpunit.phar test/Service/FormDefinitionLoaderTest.php + +# Run specific test method +./tools/phpunit.phar --filter testMethodName test/Path/To/TestFile.php + +# Mutation testing (8 threads, covered code only) +composer test:infection +vendor/bin/infection --threads=8 --no-progress --only-covered -s +``` + +### Code Quality +```bash +# Run all analysis checks +composer analyse + +# Individual checks +composer analyse:phplint # PHP syntax linting +composer analyse:phpstan # Static analysis (Level 9) +composer analyse:phpcsfixer # Code style checking (PER-CS) +composer analyse:compatibilitycheck # PHP compatibility check + +# Fix code style issues +composer cs-fix +./vendor/bin/phpcbf +./tools/php-cs-fixer fix + +# Generate PHPStan report (XML) +composer report:phpstan +``` + +### Build Outputs +- PHPUnit coverage: `var/log/clover/` (HTML + XML) +- PHPUnit results: `var/log/surefire-reports/surefire-report.xml` +- PHPStan report: `var/log/phpstan-report.xml` +- Cache directories: `var/cache/` + +## Architecture + +### Layered Architecture + +``` +┌─────────────────────────────────────────────────────────┐ +│ HTTP/Controller Layer │ +│ FormController (REST API) │ +└──────────────────────────┬──────────────────────────────┘ + │ +┌──────────────────────────┴──────────────────────────────┐ +│ Service/Application Layer │ +│ FormDefinitionLoader SubmitHandler FormReader │ +│ Email Services JsonSchemaValidator │ +└──────────────────┬──────────────────────────────────────┘ + │ +┌──────────────────┴──────────────────────────────────────┐ +│ Processor Pipeline Layer │ +│ IpAllower → IpBlocker → IpLimiter → SubmitLimiter │ +│ → SpamDetector → JsonSchemaValidator → EmailSender │ +└──────────────────┬──────────────────────────────────────┘ + │ +┌──────────────────┴──────────────────────────────────────┐ +│ Data Transfer Objects │ +│ FormDefinition FormSubmission UISchema Elements │ +└──────────────────────────────────────────────────────────┘ +``` + +### Key Components + +#### Controllers (`src/Controller/`) +- **FormController** - REST API with two endpoints: + - `GET /api/form/{locale}/{location}/{component}` - Load form definition + - `POST /api/form/{locale}/{location}/{component}` - Submit form data + - Handles multilocale support via Atoolo Resource Bundle + +#### DTOs (`src/Dto/`) +- **Core DTOs**: FormDefinition, FormSubmission, UploadFile +- **UISchema DTOs** (`Dto/UISchema/`): Element, Layout, Control, Annotation, Type, Role + - Polymorphic deserialization using Symfony Serializer discriminator mapping +- **Email DTOs** (`Dto/Email/`): EmailHtmlMessageRendererResult + +#### Services (`src/Service/`) +- **FormDefinitionLoader** - Loads and transforms form configurations from Atoolo resources (FormEditor model → JSON Forms format) +- **SubmitHandler** - Orchestrates processor pipeline execution +- **FormDataModelFactory** - Converts submissions to email message models +- **FormReader** - Traverses form structure to extract field data +- **JsonSchemaValidator** - Extended JSON Schema Draft 2020-12 validation with custom format constraints +- **LabelTranslator** - Handles i18n for form labels + +**Email Services** (`src/Service/Email/`): +- **EmailMessageModelFactory** - Builds email data model from form submissions +- **EmailHtmlMessageRenderer** (abstract) - Base email rendering interface +- **EmailHtmlMessageTwigRenderer** - Twig-based email rendering +- **EmailHtmlMessageTwigMjmlRenderer** - MJML-based responsive email rendering +- **CsvGenerator** - Creates CSV attachments from form data +- **MjmlRenderer** - MJML compilation wrapper + +**Validation Services** (`src/Service/JsonSchemaValidator/`): +- **FormatConstraint** interface - Custom JSON Schema format validators +- **PhoneConstraint**, **HtmlConstraint**, **DataUrlConstraint** - Format validators +- **Draft202012Extended** - Extended JSON Schema validator + +#### Processor Pipeline (`src/Processor/`) + +All processors implement `SubmitProcessor` interface: +```php +interface SubmitProcessor { + public function process(FormSubmission $submission, array $options): FormSubmission; +} +``` + +**Available Processors** (execution order by priority): +1. **IpLimiter** (80) - Rate limits by IP address (Symfony RateLimiter) +2. **SubmitLimiter** (70) - Global submission rate limiting +3. **SpamDetector** - Spam detection logic +4. **IpAllower** - IP whitelist validation +5. **IpBlocker** - IP blacklist validation +6. **JsonSchemaValidator** - Schema validation +7. **EmailSender** - Email delivery via Symfony Mailer + +Processors can set `$submission->approved = true` to skip subsequent processors. + +### Data Flow Patterns + +**Form Load Flow:** +1. Request → FormController::definition() +2. FormDefinitionLoader loads from Atoolo Resource +3. Deserializes UISchema to typed objects (discriminator mapping) +4. LabelTranslator applies i18n +5. Returns FormDefinition JSON response + +**Form Submit Flow:** +1. Request → FormController::submit() +2. Creates FormSubmission with client IP +3. SubmitHandler chains processors (IP checks → rate limits → validation → email) +4. Each processor can approve or reject submission +5. Returns 200 on success, API Problem on failure + +**Email Generation:** +1. FormDataModelFactory extracts data from submission +2. EmailMessageModelFactory creates structured email model +3. Renderer (Twig/MJML) generates HTML body +4. CsvGenerator creates optional attachments +5. Symfony Mailer sends email + +## Code Quality Standards + +### PHPStan Configuration (Level 9) +- Configuration: `phpstan.neon.dist` +- Custom type aliases for complex email model structures +- Cache: `var/cache/phpstan` +- Analyzes: `src/` directory only + +### PHP-CS-Fixer (PER-CS Standard) +- Configuration: `.php-cs-fixer.dist.php` +- Rules: `@PER-CS` (PSR-12 compatible modern standard) +- Scans: `src/` and `test/` directories +- Cache: `var/cache/php-cs-fixer` + +### PHPUnit Configuration +- Configuration: `phpunit.xml` +- Framework: PHPUnit 10.4+ +- Execution: Random order for test independence +- Coverage: Clover XML + HTML reports +- Logging: JUnit XML format +- Memory limit: 512M + +### Testing Standards +- **One assertion per test** - Each test method must contain exactly one assertion +- **MANDATORY assertion messages** - Every assertion must include a descriptive message explaining what is being tested +- **Test complete objects** - Use object comparison, not field-by-field assertions +- **Static imports** - All assertion methods must use static imports +- **Test structure**: arrange-act-assert pattern + +Example test structure: +```php +use PHPUnit\Framework\TestCase; +use function PHPUnit\Framework\assertEquals; + +class ExampleTest extends TestCase { + #[Test] + public function loadsFormDefinitionWithAllProperties(): void { + // arrange + $loader = new FormDefinitionLoader(/* deps */); + $location = ResourceLocation::of(/* ... */); + + // act + $definition = $loader->load($location); + + // assert + assertEquals( + $expectedDefinition, + $definition, + "Form definition should be loaded with all properties intact including schema, UISchema, and processors" + ); + } +} +``` + +## Project-Specific Patterns + +### UISchema Polymorphic Deserialization +UISchema elements use Symfony Serializer discriminator mapping: +```php +#[DiscriminatorMap(typeProperty: 'type', mapping: [ + 'HorizontalLayout' => HorizontalLayout::class, + 'VerticalLayout' => VerticalLayout::class, + // ... +])] +abstract class Element { /* ... */ } +``` + +### Processor Configuration +Default processors are configured in `config/services.yaml`: +```yaml +Atoolo\Form\Service\SubmitHandler: + arguments: + $defaultProcessors: + - '@Atoolo\Form\Processor\IpLimiter' + - '@Atoolo\Form\Processor\SubmitLimiter' + - '@Atoolo\Form\Processor\JsonSchemaValidator' +``` + +Individual forms can override via `FormDefinition::$processors`. + +### Immutable DTOs +All DTOs use `readonly` properties with constructor injection: +```php +readonly class FormDefinition { + public function __construct( + public JsonSchema $schema, + public Element $uiSchema, + public FormMessages $messages, + // ... + ) {} +} +``` + +### Exception to API Problem Transformation +Custom exceptions are transformed to RFC 9457 API Problems via `ExceptionTransformer`: +- `FormNotFoundException` → 404 Not Found +- `AccessDeniedException` → 403 Forbidden +- `LimitExceededException` → 429 Too Many Requests +- `SpamDetectedException` → 422 Unprocessable Entity + +### Custom JSON Schema Format Constraints +Extend `FormatConstraint` interface for custom format validators: +```php +class PhoneConstraint implements FormatConstraint { + public function validate(mixed $value): ?ValidationError { + // Phone number validation logic + } +} +``` + +Register in service configuration with tag: +```yaml +Atoolo\Form\Service\JsonSchemaValidator\FormatConstraint\PhoneConstraint: + tags: + - { name: 'atoolo_form.format_constraint', format: 'phone' } +``` + +## Important File Locations + +| Path | Purpose | +|------|---------| +| `src/AtooloFormBundle.php` | Bundle entry point | +| `src/Controller/FormController.php` | REST API endpoints | +| `src/Service/FormDefinitionLoader.php` | Form configuration loading | +| `src/Service/SubmitHandler.php` | Processor pipeline orchestration | +| `src/Processor/SubmitProcessor.php` | Processor interface | +| `config/services.yaml` | Service registration & default processors | +| `config/routes.yaml` | API route definitions | +| `templates/email.text.twig` | Email body template | +| `templates/email.text.summary.twig` | Email summary template | + +## Dependencies + +**Core Symfony Bundles:** +- symfony/framework-bundle ^7.1 +- symfony/mailer ^7.1 +- symfony/rate-limiter ^7.1 +- symfony/serializer ^7.1 +- symfony/validator ^7.1 + +**Domain-Specific:** +- atoolo/resource-bundle ^1.3 - Atoolo resource loading +- opis/json-schema ^2.3 - JSON Schema validation +- phpro/api-problem-bundle ^1.7 - RFC 9457 API Problems + +**Email/Document:** +- twig/markdown-extra ^3.21 - Markdown support +- league/csv ^9.16 - CSV generation +- league/html-to-markdown ^5.1 - HTML to Markdown conversion + +## Configuration Files + +- `composer.json` - Dependencies, scripts, autoloading +- `phpunit.xml` - PHPUnit configuration +- `phpstan.neon.dist` - PHPStan Level 9 configuration with custom type aliases +- `.php-cs-fixer.dist.php` - PER-CS code style rules +- `phpcs.compatibilitycheck.xml` - PHP compatibility checking (8.1-8.4) +- `config/services.yaml` - Symfony service container configuration +- `config/routes.yaml` - API route definitions +- `config/rate_limiter.yaml` - Rate limiter configuration + +## Tools (Managed via Phive) + +PHAR tools are symlinked in `tools/` directory: +- `tools/phpunit.phar` - PHPUnit test runner (included directly) +- `tools/phpstan` → `~/.phive/phars/phpstan-*.phar` +- `tools/php-cs-fixer` → `~/.phive/phars/php-cs-fixer-*.phar` +- `tools/phplint` → `~/.phive/phars/overtrue/phplint-*.phar` +- `tools/composer-normalize` → `~/.phive/phars/composer-normalize-*.phar` + +All tools are version-locked and installed via Phive (PHP Version Manager) for reproducible builds. diff --git a/README.md b/README.md index fe7e0a7..bcb3d9c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,14 @@ +[![codecov](https://codecov.io/gh/sitepark/atoolo-form-bundle/graph/badge.svg?token=bPXRMUE4tn)](https://codecov.io/gh/sitepark/atoolo-form-bundle) +![phpstan](https://img.shields.io/badge/PHPStan-level%209-brightgreen) +[![php](https://img.shields.io/badge/PHP-8.1-yellow)](## "is no longer checked automatically") +![php](https://img.shields.io/badge/PHP-8.2-blue) +![php](https://img.shields.io/badge/PHP-8.3-blue) +![php](https://img.shields.io/badge/PHP-8.4-blue) +[![E2E Test](https://github.com/sitepark/atoolo-e2e-test/actions/workflows/e2e-test.yml/badge.svg)](https://github.com/sitepark/atoolo-e2e-test/actions/workflows/e2e-test.yml) + # Atoolo Form bundle This bundle provides an HTTP interface via which forms can be displayed and processed with the help of [JSON Forms](https://jsonforms.io/). -[Documentation](https://sitepark.github.io/atoolo-docs/develop/bundles/form/) +- [Bundle Documentation](https://sitepark.github.io/atoolo-docs/develop/bundles/form/) +- [API Documentation](https://sitepark.github.io/atoolo-docs/develop/form/) diff --git a/composer.json b/composer.json index cfbf8e6..fa4d17e 100644 --- a/composer.json +++ b/composer.json @@ -10,11 +10,30 @@ } ], "require": { - "php": ">=8.1 <8.4.0", + "php": ">=8.1 <8.5.0", + "ext-fileinfo": "*", + "atoolo/resource-bundle": "^1.3", + "league/csv": "^9.16.0", + "league/html-to-markdown": "^5.1", + "opis/json-schema": "^2.3", + "phpdocumentor/reflection-docblock": "^5.4", + "phpro/api-problem": "^1.7", + "phpro/api-problem-bundle": "^1.7", "symfony/config": "^6.3 || ^7.0", "symfony/dependency-injection": "^6.3 || ^7.0", + "symfony/framework-bundle": "^7.1", "symfony/http-kernel": "^6.3 || ^7.0", - "symfony/yaml": "^6.3 || ^7.0" + "symfony/mailer": "^7.1", + "symfony/property-access": "^7.1", + "symfony/property-info": "^7.1", + "symfony/rate-limiter": "^7.1", + "symfony/serializer": "^7.1", + "symfony/translation": "^7.1", + "symfony/twig-bundle": "^7.1", + "symfony/validator": "^7.1", + "symfony/yaml": "^6.3 || ^7.0", + "twig/extra-bundle": "^3.21", + "twig/markdown-extra": "^3.21" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", @@ -22,7 +41,9 @@ "phpcompatibility/php-compatibility": "^9.3", "phpunit/phpunit": "^10.4", "roave/security-advisories": "dev-latest", - "squizlabs/php_codesniffer": "^3.7" + "squizlabs/php_codesniffer": "^3.7", + "symfony/css-selector": "^7.1", + "symfony/dom-crawler": "^7.1" }, "repositories": {}, "minimum-stability": "dev", @@ -71,7 +92,7 @@ "@analyse:compatibilitycheck" ], "analyse:compatibilitycheck": "./vendor/bin/phpcs --standard=./phpcs.compatibilitycheck.xml", - "analyse:phpcsfixer": "./tools/php-cs-fixer check --diff --show-progress=dots", + "analyse:phpcsfixer": "./tools/php-cs-fixer check --diff --show-progress=dots", "analyse:phplint": "./tools/phplint", "analyse:phpstan": "./tools/phpstan analyse", "cs-fix": [ diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 020437b..0000000 --- a/composer.lock +++ /dev/null @@ -1,5660 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "e5962bd3bdae18db25e2d91c984601d1", - "packages": [ - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - }, - { - "name": "symfony/config", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "bcd3c4adf0144dee5011bb35454728c38adec055" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/bcd3c4adf0144dee5011bb35454728c38adec055", - "reference": "bcd3c4adf0144dee5011bb35454728c38adec055", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^7.1", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/finder": "<6.4", - "symfony/service-contracts": "<2.5" - }, - "require-dev": { - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/config/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-04T11:36:24+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "a475747af1a1c98272a5471abc35f3da81197c5d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a475747af1a1c98272a5471abc35f3da81197c5d", - "reference": "a475747af1a1c98272a5471abc35f3da81197c5d", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^3.5", - "symfony/var-exporter": "^6.4|^7.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<6.4", - "symfony/finder": "<6.4", - "symfony/yaml": "<6.4" - }, - "provide": { - "psr/container-implementation": "1.1|2.0", - "symfony/service-implementation": "1.1|2.0|3.0" - }, - "require-dev": { - "symfony/config": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows you to standardize and centralize the way objects are constructed in your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-25T15:45:00+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.5.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:20:29+00:00" - }, - { - "name": "symfony/error-handler", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/error-handler.git", - "reference": "672b3dd1ef8b87119b446d67c58c106c43f965fe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/672b3dd1ef8b87119b446d67c58c106c43f965fe", - "reference": "672b3dd1ef8b87119b446d67c58c106c43f965fe", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" - }, - "conflict": { - "symfony/deprecation-contracts": "<2.5", - "symfony/http-kernel": "<6.4" - }, - "require-dev": { - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" - }, - "bin": [ - "Resources/bin/patch-type-declarations" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\ErrorHandler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to manage errors and ease debugging PHP code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-05T15:35:02+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/event-dispatcher-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/service-contracts": "<2.5" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/event-dispatcher": "^1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:20:29+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", - "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-10-25T15:15:23+00:00" - }, - { - "name": "symfony/http-foundation", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "e88a66c3997859532bc2ddd6dd8f35aba2711744" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e88a66c3997859532bc2ddd6dd8f35aba2711744", - "reference": "e88a66c3997859532bc2ddd6dd8f35aba2711744", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" - }, - "conflict": { - "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4.12|>=7.0,<7.1.5" - }, - "require-dev": { - "doctrine/dbal": "^3.6|^4", - "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Defines an object-oriented layer for the HTTP specification", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-13T18:58:46+00:00" - }, - { - "name": "symfony/http-kernel", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "6b4722a25e0aed1ccb4914b9bcbd493cc4676b4d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6b4722a25e0aed1ccb4914b9bcbd493cc4676b4d", - "reference": "6b4722a25e0aed1ccb4914b9bcbd493cc4676b4d", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/browser-kit": "<6.4", - "symfony/cache": "<6.4", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<6.4", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", - "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/translation": "<6.4", - "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.4", - "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.4", - "twig/twig": "<3.12" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", - "twig/twig": "^3.12" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a structured process for converting a Request into a Response", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-29T08:42:40+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.31.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-php83", - "version": "v1.31.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.5.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:20:29+00:00" - }, - { - "name": "symfony/var-dumper", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-dumper.git", - "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6a22929407dec8765d6e2b6ff85b800b245879c", - "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/console": "<6.4" - }, - "require-dev": { - "ext-iconv": "*", - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", - "twig/twig": "^3.12" - }, - "bin": [ - "Resources/bin/var-dump-server" - ], - "type": "library", - "autoload": { - "files": [ - "Resources/functions/dump.php" - ], - "psr-4": { - "Symfony\\Component\\VarDumper\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides mechanisms for walking through any arbitrary PHP variable", - "homepage": "https://symfony.com", - "keywords": [ - "debug", - "dump" - ], - "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-08T15:48:14+00:00" - }, - { - "name": "symfony/var-exporter", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-exporter.git", - "reference": "1a6a89f95a46af0f142874c9d650a6358d13070d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1a6a89f95a46af0f142874c9d650a6358d13070d", - "reference": "1a6a89f95a46af0f142874c9d650a6358d13070d", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "symfony/property-access": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\VarExporter\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows exporting any serializable PHP data structure to plain PHP code", - "homepage": "https://symfony.com", - "keywords": [ - "clone", - "construct", - "export", - "hydrate", - "instantiate", - "lazy-loading", - "proxy", - "serialize" - ], - "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-10-18T07:58:17+00:00" - }, - { - "name": "symfony/yaml", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "099581e99f557e9f16b43c5916c26380b54abb22" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/099581e99f557e9f16b43c5916c26380b54abb22", - "reference": "099581e99f557e9f16b43c5916c26380b54abb22", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/console": "<6.4" - }, - "require-dev": { - "symfony/console": "^6.4|^7.0" - }, - "bin": [ - "Resources/bin/yaml-lint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Loads and dumps YAML files", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/yaml/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-10-23T06:56:12+00:00" - } - ], - "packages-dev": [ - { - "name": "colinodell/json5", - "version": "v2.3.0", - "source": { - "type": "git", - "url": "https://github.com/colinodell/json5.git", - "reference": "15b063f8cb5e6deb15f0cd39123264ec0d19c710" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/colinodell/json5/zipball/15b063f8cb5e6deb15f0cd39123264ec0d19c710", - "reference": "15b063f8cb5e6deb15f0cd39123264ec0d19c710", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-mbstring": "*", - "php": "^7.1.3|^8.0" - }, - "conflict": { - "scrutinizer/ocular": "1.7.*" - }, - "require-dev": { - "mikehaertl/php-shellcommand": "^1.2.5", - "phpstan/phpstan": "^1.4", - "scrutinizer/ocular": "^1.6", - "squizlabs/php_codesniffer": "^2.3 || ^3.0", - "symfony/finder": "^4.4|^5.4|^6.0", - "symfony/phpunit-bridge": "^5.4|^6.0" - }, - "bin": [ - "bin/json5" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "files": [ - "src/global.php" - ], - "psr-4": { - "ColinODell\\Json5\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "https://www.colinodell.com", - "role": "Developer" - } - ], - "description": "UTF-8 compatible JSON5 parser for PHP", - "homepage": "https://github.com/colinodell/json5", - "keywords": [ - "JSON5", - "json", - "json5_decode", - "json_decode" - ], - "support": { - "issues": "https://github.com/colinodell/json5/issues", - "source": "https://github.com/colinodell/json5/tree/v2.3.0" - }, - "funding": [ - { - "url": "https://www.colinodell.com/sponsor", - "type": "custom" - }, - { - "url": "https://www.paypal.me/colinpodell/10.00", - "type": "custom" - }, - { - "url": "https://github.com/colinodell", - "type": "github" - }, - { - "url": "https://www.patreon.com/colinodell", - "type": "patreon" - } - ], - "time": "2022-12-27T16:44:40+00:00" - }, - { - "name": "composer/pcre", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<1.11.10" - }, - "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - }, - "phpstan": { - "includes": [ - "extension.neon" - ] - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-11-12T16:29:46+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-05-06T16:37:16+00:00" - }, - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "*", - "ext-json": "*", - "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", - "yoast/phpunit-polyfills": "^1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "source": "https://github.com/PHPCSStandards/composer-installer" - }, - "time": "2023-01-05T11:28:13+00:00" - }, - { - "name": "fidry/cpu-core-counter", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "8520451a140d3f46ac33042715115e290cf5785f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", - "reference": "8520451a140d3f46ac33042715115e290cf5785f", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^8.5.31 || ^9.5.26", - "webmozarts/strict-phpunit": "^7.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Fidry\\CpuCoreCounter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com" - } - ], - "description": "Tiny utility to get the number of CPU cores.", - "keywords": [ - "CPU", - "core" - ], - "support": { - "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" - }, - "funding": [ - { - "url": "https://github.com/theofidry", - "type": "github" - } - ], - "time": "2024-08-06T10:04:20+00:00" - }, - { - "name": "infection/abstract-testframework-adapter", - "version": "0.5.0", - "source": { - "type": "git", - "url": "https://github.com/infection/abstract-testframework-adapter.git", - "reference": "18925e20d15d1a5995bb85c9dc09e8751e1e069b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/infection/abstract-testframework-adapter/zipball/18925e20d15d1a5995bb85c9dc09e8751e1e069b", - "reference": "18925e20d15d1a5995bb85c9dc09e8751e1e069b", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.8", - "friendsofphp/php-cs-fixer": "^2.17", - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Infection\\AbstractTestFramework\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Maks Rafalko", - "email": "maks.rafalko@gmail.com" - } - ], - "description": "Abstract Test Framework Adapter for Infection", - "support": { - "issues": "https://github.com/infection/abstract-testframework-adapter/issues", - "source": "https://github.com/infection/abstract-testframework-adapter/tree/0.5.0" - }, - "funding": [ - { - "url": "https://github.com/infection", - "type": "github" - }, - { - "url": "https://opencollective.com/infection", - "type": "open_collective" - } - ], - "time": "2021-08-17T18:49:12+00:00" - }, - { - "name": "infection/extension-installer", - "version": "0.1.2", - "source": { - "type": "git", - "url": "https://github.com/infection/extension-installer.git", - "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/infection/extension-installer/zipball/9b351d2910b9a23ab4815542e93d541e0ca0cdcf", - "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1 || ^2.0" - }, - "require-dev": { - "composer/composer": "^1.9 || ^2.0", - "friendsofphp/php-cs-fixer": "^2.18, <2.19", - "infection/infection": "^0.15.2", - "php-coveralls/php-coveralls": "^2.4", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.10", - "phpstan/phpstan-phpunit": "^0.12.6", - "phpstan/phpstan-strict-rules": "^0.12.2", - "phpstan/phpstan-webmozart-assert": "^0.12.2", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4.8" - }, - "type": "composer-plugin", - "extra": { - "class": "Infection\\ExtensionInstaller\\Plugin" - }, - "autoload": { - "psr-4": { - "Infection\\ExtensionInstaller\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Maks Rafalko", - "email": "maks.rafalko@gmail.com" - } - ], - "description": "Infection Extension Installer", - "support": { - "issues": "https://github.com/infection/extension-installer/issues", - "source": "https://github.com/infection/extension-installer/tree/0.1.2" - }, - "funding": [ - { - "url": "https://github.com/infection", - "type": "github" - }, - { - "url": "https://opencollective.com/infection", - "type": "open_collective" - } - ], - "time": "2021-10-20T22:08:34+00:00" - }, - { - "name": "infection/include-interceptor", - "version": "0.2.5", - "source": { - "type": "git", - "url": "https://github.com/infection/include-interceptor.git", - "reference": "0cc76d95a79d9832d74e74492b0a30139904bdf7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/infection/include-interceptor/zipball/0cc76d95a79d9832d74e74492b0a30139904bdf7", - "reference": "0cc76d95a79d9832d74e74492b0a30139904bdf7", - "shasum": "" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", - "infection/infection": "^0.15.0", - "phan/phan": "^2.4 || ^3", - "php-coveralls/php-coveralls": "^2.2", - "phpstan/phpstan": "^0.12.8", - "phpunit/phpunit": "^8.5", - "vimeo/psalm": "^3.8" - }, - "type": "library", - "autoload": { - "psr-4": { - "Infection\\StreamWrapper\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Maks Rafalko", - "email": "maks.rafalko@gmail.com" - } - ], - "description": "Stream Wrapper: Include Interceptor. Allows to replace included (autoloaded) file with another one.", - "support": { - "issues": "https://github.com/infection/include-interceptor/issues", - "source": "https://github.com/infection/include-interceptor/tree/0.2.5" - }, - "funding": [ - { - "url": "https://github.com/infection", - "type": "github" - }, - { - "url": "https://opencollective.com/infection", - "type": "open_collective" - } - ], - "time": "2021-08-09T10:03:57+00:00" - }, - { - "name": "infection/infection", - "version": "0.27.11", - "source": { - "type": "git", - "url": "https://github.com/infection/infection.git", - "reference": "6d55979c457eef2a5d0d80446c67ca533f201961" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/infection/infection/zipball/6d55979c457eef2a5d0d80446c67ca533f201961", - "reference": "6d55979c457eef2a5d0d80446c67ca533f201961", - "shasum": "" - }, - "require": { - "colinodell/json5": "^2.2", - "composer-runtime-api": "^2.0", - "composer/xdebug-handler": "^2.0 || ^3.0", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "fidry/cpu-core-counter": "^0.4.0 || ^0.5.0 || ^1.0", - "infection/abstract-testframework-adapter": "^0.5.0", - "infection/extension-installer": "^0.1.0", - "infection/include-interceptor": "^0.2.5", - "justinrainbow/json-schema": "^5.2.10", - "nikic/php-parser": "^4.15.1", - "ondram/ci-detector": "^4.1.0", - "php": "^8.1", - "sanmai/later": "^0.1.1", - "sanmai/pipeline": "^5.1 || ^6", - "sebastian/diff": "^3.0.2 || ^4.0 || ^5.0 || ^6.0", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", - "symfony/finder": "^5.4 || ^6.0 || ^7.0", - "symfony/process": "^5.4 || ^6.0 || ^7.0", - "thecodingmachine/safe": "^2.1.2", - "webmozart/assert": "^1.11" - }, - "conflict": { - "antecedent/patchwork": "<2.1.25", - "dg/bypass-finals": "<1.4.1", - "phpunit/php-code-coverage": ">9,<9.1.4 || >9.2.17,<9.2.21" - }, - "require-dev": { - "brianium/paratest": "^6.11", - "ext-simplexml": "*", - "fidry/makefile": "^1.0", - "helmich/phpunit-json-assert": "^3.0", - "phpspec/prophecy": "^1.15", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1.1.0", - "phpstan/phpstan": "^1.10.15", - "phpstan/phpstan-phpunit": "^1.0.0", - "phpstan/phpstan-strict-rules": "^1.1.0", - "phpstan/phpstan-webmozart-assert": "^1.0.2", - "phpunit/phpunit": "^9.6", - "rector/rector": "^0.16.0", - "sidz/phpstan-rules": "^0.4.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0", - "thecodingmachine/phpstan-safe-rule": "^1.2.0" - }, - "bin": [ - "bin/infection" - ], - "type": "library", - "autoload": { - "psr-4": { - "Infection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Maks Rafalko", - "email": "maks.rafalko@gmail.com", - "homepage": "https://twitter.com/maks_rafalko" - }, - { - "name": "Oleg Zhulnev", - "homepage": "https://github.com/sidz" - }, - { - "name": "Gert de Pagter", - "homepage": "https://github.com/BackEndTea" - }, - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com", - "homepage": "https://twitter.com/tfidry" - }, - { - "name": "Alexey Kopytko", - "email": "alexey@kopytko.com", - "homepage": "https://www.alexeykopytko.com" - }, - { - "name": "Andreas Möller", - "email": "am@localheinz.com", - "homepage": "https://localheinz.com" - } - ], - "description": "Infection is a Mutation Testing framework for PHP. The mutation adequacy score can be used to measure the effectiveness of a test set in terms of its ability to detect faults.", - "keywords": [ - "coverage", - "mutant", - "mutation framework", - "mutation testing", - "testing", - "unit testing" - ], - "support": { - "issues": "https://github.com/infection/infection/issues", - "source": "https://github.com/infection/infection/tree/0.27.11" - }, - "funding": [ - { - "url": "https://github.com/infection", - "type": "github" - }, - { - "url": "https://opencollective.com/infection", - "type": "open_collective" - } - ], - "time": "2024-03-20T07:48:57+00:00" - }, - { - "name": "justinrainbow/json-schema", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", - "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", - "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.35" - }, - "bin": [ - "bin/validate-json" - ], - "type": "library", - "autoload": { - "psr-4": { - "JsonSchema\\": "src/JsonSchema/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bruno Prieto Reis", - "email": "bruno.p.reis@gmail.com" - }, - { - "name": "Justin Rainbow", - "email": "justin.rainbow@gmail.com" - }, - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - }, - { - "name": "Robert Schönthal", - "email": "seroscho@googlemail.com" - } - ], - "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", - "keywords": [ - "json", - "schema" - ], - "support": { - "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0" - }, - "time": "2024-07-06T21:00:26+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.12.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2024-11-08T17:47:46+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.19.4", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "715f4d25e225bc47b293a8b997fe6ce99bf987d2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/715f4d25e225bc47b293a8b997fe6ce99bf987d2", - "reference": "715f4d25e225bc47b293a8b997fe6ce99bf987d2", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.1" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.4" - }, - "time": "2024-09-29T15:01:53+00:00" - }, - { - "name": "ondram/ci-detector", - "version": "4.2.0", - "source": { - "type": "git", - "url": "https://github.com/OndraM/ci-detector.git", - "reference": "8b0223b5ed235fd377c75fdd1bfcad05c0f168b8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/OndraM/ci-detector/zipball/8b0223b5ed235fd377c75fdd1bfcad05c0f168b8", - "reference": "8b0223b5ed235fd377c75fdd1bfcad05c0f168b8", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.13.2", - "lmc/coding-standard": "^3.0.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.1.0", - "phpstan/phpstan": "^1.2.0", - "phpstan/phpstan-phpunit": "^1.0.0", - "phpunit/phpunit": "^9.6.13" - }, - "type": "library", - "autoload": { - "psr-4": { - "OndraM\\CiDetector\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ondřej Machulda", - "email": "ondrej.machulda@gmail.com" - } - ], - "description": "Detect continuous integration environment and provide unified access to properties of current build", - "keywords": [ - "CircleCI", - "Codeship", - "Wercker", - "adapter", - "appveyor", - "aws", - "aws codebuild", - "azure", - "azure devops", - "azure pipelines", - "bamboo", - "bitbucket", - "buddy", - "ci-info", - "codebuild", - "continuous integration", - "continuousphp", - "devops", - "drone", - "github", - "gitlab", - "interface", - "jenkins", - "pipelines", - "sourcehut", - "teamcity", - "travis" - ], - "support": { - "issues": "https://github.com/OndraM/ci-detector/issues", - "source": "https://github.com/OndraM/ci-detector/tree/4.2.0" - }, - "time": "2024-03-12T13:22:30+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpcompatibility/php-compatibility", - "version": "9.3.5", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", - "shasum": "" - }, - "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" - }, - "conflict": { - "squizlabs/php_codesniffer": "2.6.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Wim Godden", - "homepage": "https://github.com/wimg", - "role": "lead" - }, - { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", - "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" - } - ], - "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", - "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", - "keywords": [ - "compatibility", - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", - "source": "https://github.com/PHPCompatibility/PHPCompatibility" - }, - "time": "2019-12-27T09:44:58+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "10.1.16", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", - "theseer/tokenizer": "^1.2.3" - }, - "require-dev": { - "phpunit/phpunit": "^10.1" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-08-22T04:31:57+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "4.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T06:24:48+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:56:09+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T14:07:24+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:57:52+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "10.5.38", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a86773b9e887a67bc53efa9da9ad6e3f2498c132" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a86773b9e887a67bc53efa9da9ad6e3f2498c132", - "reference": "a86773b9e887a67bc53efa9da9ad6e3f2498c132", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.3", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.2", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.0", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.38" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2024-10-28T13:06:21+00:00" - }, - { - "name": "roave/security-advisories", - "version": "dev-latest", - "source": { - "type": "git", - "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "fff26f7a91a7458bf6eea5afdd71b4aba1f1d3ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/fff26f7a91a7458bf6eea5afdd71b4aba1f1d3ea", - "reference": "fff26f7a91a7458bf6eea5afdd71b4aba1f1d3ea", - "shasum": "" - }, - "conflict": { - "3f/pygmentize": "<1.2", - "admidio/admidio": "<4.3.12", - "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", - "aheinze/cockpit": "<2.2", - "aimeos/ai-admin-graphql": ">=2022.04.1,<2022.10.10|>=2023.04.1,<2023.10.6|>=2024.04.1,<2024.07.2", - "aimeos/ai-admin-jsonadm": "<2020.10.13|>=2021.04.1,<2021.10.6|>=2022.04.1,<2022.10.3|>=2023.04.1,<2023.10.4|==2024.04.1", - "aimeos/ai-client-html": ">=2020.04.1,<2020.10.27|>=2021.04.1,<2021.10.22|>=2022.04.1,<2022.10.13|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.04.7", - "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9|==2024.04.1", - "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", - "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", - "airesvsg/acf-to-rest-api": "<=3.1", - "akaunting/akaunting": "<2.1.13", - "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", - "alextselegidis/easyappointments": "<1.5", - "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", - "amazing/media2click": ">=1,<1.3.3", - "ameos/ameos_tarteaucitron": "<1.2.23", - "amphp/artax": "<1.0.6|>=2,<2.0.6", - "amphp/http": "<=1.7.2|>=2,<=2.1", - "amphp/http-client": ">=4,<4.4", - "anchorcms/anchor-cms": "<=0.12.7", - "andreapollastri/cipi": "<=3.1.15", - "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<1.0.2|>=2,<2.2.5", - "apache-solr-for-typo3/solr": "<2.8.3", - "apereo/phpcas": "<1.6", - "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6|>=2.6,<2.7.10|>=3,<3.0.12|>=3.1,<3.1.3", - "appwrite/server-ce": "<=1.2.1", - "arc/web": "<3", - "area17/twill": "<1.2.5|>=2,<2.5.3", - "artesaos/seotools": "<0.17.2", - "asymmetricrypt/asymmetricrypt": "<9.9.99", - "athlon1600/php-proxy": "<=5.1", - "athlon1600/php-proxy-app": "<=3", - "austintoddj/canvas": "<=3.4.2", - "auth0/wordpress": "<=4.6", - "automad/automad": "<2.0.0.0-alpha5", - "automattic/jetpack": "<9.8", - "awesome-support/awesome-support": "<=6.0.7", - "aws/aws-sdk-php": "<3.288.1", - "azuracast/azuracast": "<0.18.3", - "backdrop/backdrop": "<1.27.3|>=1.28,<1.28.2", - "backpack/crud": "<3.4.9", - "backpack/filemanager": "<2.0.2|>=3,<3.0.9", - "bacula-web/bacula-web": "<8.0.0.0-RC2-dev", - "badaso/core": "<2.7", - "bagisto/bagisto": "<2.1", - "barrelstrength/sprout-base-email": "<1.2.7", - "barrelstrength/sprout-forms": "<3.9", - "barryvdh/laravel-translation-manager": "<0.6.2", - "barzahlen/barzahlen-php": "<2.0.1", - "baserproject/basercms": "<=5.1.1", - "bassjobsen/bootstrap-3-typeahead": ">4.0.2", - "bbpress/bbpress": "<2.6.5", - "bcosca/fatfree": "<3.7.2", - "bedita/bedita": "<4", - "bigfork/silverstripe-form-capture": ">=3,<3.1.1", - "billz/raspap-webgui": "<=3.1.4", - "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", - "blueimp/jquery-file-upload": "==6.4.4", - "bmarshall511/wordpress_zero_spam": "<5.2.13", - "bolt/bolt": "<3.7.2", - "bolt/core": "<=4.2", - "born05/craft-twofactorauthentication": "<3.3.4", - "bottelet/flarepoint": "<2.2.1", - "bref/bref": "<2.1.17", - "brightlocal/phpwhois": "<=4.2.5", - "brotkrueml/codehighlight": "<2.7", - "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", - "brotkrueml/typo3-matomo-integration": "<1.3.2", - "buddypress/buddypress": "<7.2.1", - "bugsnag/bugsnag-laravel": ">=2,<2.0.2", - "bytefury/crater": "<6.0.2", - "cachethq/cachet": "<2.5.1", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", - "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", - "cardgate/magento2": "<2.0.33", - "cardgate/woocommerce": "<=3.1.15", - "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", - "cart2quote/module-quotation-encoded": ">=4.1.6,<=4.4.5|>=5,<5.4.4", - "cartalyst/sentry": "<=2.1.6", - "catfan/medoo": "<1.7.5", - "causal/oidc": "<2.1", - "cecil/cecil": "<7.47.1", - "centreon/centreon": "<22.10.15", - "cesnet/simplesamlphp-module-proxystatistics": "<3.1", - "chriskacerguis/codeigniter-restserver": "<=2.7.1", - "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", - "ckeditor/ckeditor": "<4.24", - "cockpit-hq/cockpit": "<2.7|==2.7", - "codeception/codeception": "<3.1.3|>=4,<4.1.22", - "codeigniter/framework": "<3.1.9", - "codeigniter4/framework": "<4.4.7", - "codeigniter4/shield": "<1.0.0.0-beta8", - "codiad/codiad": "<=2.8.4", - "composer/composer": "<1.10.27|>=2,<2.2.24|>=2.3,<2.7.7", - "concrete5/concrete5": "<9.3.4", - "concrete5/core": "<8.5.8|>=9,<9.1", - "contao-components/mediaelement": ">=2.14.2,<2.21.1", - "contao/comments-bundle": ">=2,<4.13.40|>=5.0.0.0-RC1-dev,<5.3.4", - "contao/contao": "<=5.4.1", - "contao/core": "<3.5.39", - "contao/core-bundle": "<4.13.49|>=5,<5.3.15|>=5.4,<5.4.3", - "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", - "contao/managed-edition": "<=1.5", - "corveda/phpsandbox": "<1.3.5", - "cosenary/instagram": "<=2.3", - "craftcms/cms": "<=4.12.6.1|>=5,<=5.4.7.1", - "croogo/croogo": "<4", - "cuyz/valinor": "<0.12", - "czim/file-handling": "<1.5|>=2,<2.3", - "czproject/git-php": "<4.0.3", - "damienharper/auditor-bundle": "<5.2.6", - "dapphp/securimage": "<3.6.6", - "darylldoyle/safe-svg": "<1.9.10", - "datadog/dd-trace": ">=0.30,<0.30.2", - "datatables/datatables": "<1.10.10", - "david-garcia/phpwhois": "<=4.3.1", - "dbrisinajumi/d2files": "<1", - "dcat/laravel-admin": "<=2.1.3", - "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", - "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", - "desperado/xml-bundle": "<=0.1.7", - "dev-lancer/minecraft-motd-parser": "<=1.0.5", - "devgroup/dotplant": "<2020.09.14-dev", - "directmailteam/direct-mail": "<6.0.3|>=7,<7.0.3|>=8,<9.5.2", - "doctrine/annotations": "<1.2.7", - "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", - "doctrine/common": "<2.4.3|>=2.5,<2.5.1", - "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", - "doctrine/doctrine-bundle": "<1.5.2", - "doctrine/doctrine-module": "<0.7.2", - "doctrine/mongodb-odm": "<1.0.2", - "doctrine/mongodb-odm-bundle": "<3.0.1", - "doctrine/orm": ">=1,<1.2.4|>=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<19.0.2", - "dompdf/dompdf": "<2.0.4", - "doublethreedigital/guest-entries": "<3.1.2", - "drupal/core": ">=6,<6.38|>=7,<7.96|>=8,<10.2.9|>=10.3,<10.3.6|>=11,<11.0.5", - "drupal/core-recommended": ">=8,<10.2.9|>=10.3,<10.3.6|>=11,<11.0.5", - "drupal/drupal": ">=5,<5.11|>=6,<6.38|>=7,<7.80|>=8,<10.2.9|>=10.3,<10.3.6|>=11,<11.0.5", - "duncanmcclean/guest-entries": "<3.1.2", - "dweeves/magmi": "<=0.7.24", - "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.1.2", - "ecodev/newsletter": "<=4", - "ectouch/ectouch": "<=2.7.2", - "egroupware/egroupware": "<23.1.20240624", - "elefant/cms": "<2.0.7", - "elgg/elgg": "<3.3.24|>=4,<4.0.5", - "elijaa/phpmemcacheadmin": "<=1.3", - "encore/laravel-admin": "<=1.8.19", - "endroid/qr-code-bundle": "<3.4.2", - "enhavo/enhavo-app": "<=0.13.1", - "enshrined/svg-sanitize": "<0.15", - "erusev/parsedown": "<1.7.2", - "ether/logs": "<3.0.4", - "evolutioncms/evolution": "<=3.2.3", - "exceedone/exment": "<4.4.3|>=5,<5.0.3", - "exceedone/laravel-admin": "<2.2.3|==3", - "ezsystems/demobundle": ">=5.4,<5.4.6.1-dev", - "ezsystems/ez-support-tools": ">=2.2,<2.2.3", - "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1-dev", - "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1-dev|>=5.4,<5.4.11.1-dev|>=2017.12,<2017.12.0.1-dev", - "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", - "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.26|>=3.3,<3.3.39", - "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", - "ezsystems/ezplatform-graphql": ">=1.0.0.0-RC1-dev,<1.0.13|>=2.0.0.0-beta1,<2.3.12", - "ezsystems/ezplatform-kernel": "<1.2.5.1-dev|>=1.3,<1.3.35", - "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", - "ezsystems/ezplatform-richtext": ">=2.3,<2.3.7.1-dev|>=3.3,<3.3.40", - "ezsystems/ezplatform-solr-search-engine": ">=1.7,<1.7.12|>=2,<2.0.2|>=3.3,<3.3.15", - "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": "<6.13.8.2-dev|>=7,<7.5.31", - "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.03.5.1", - "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", - "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", - "ezyang/htmlpurifier": "<=4.2", - "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", - "facturascripts/facturascripts": "<=2022.08", - "fastly/magento2": "<1.2.26", - "feehi/cms": "<=2.1.1", - "feehi/feehicms": "<=2.1.1", - "fenom/fenom": "<=2.12.1", - "filament/actions": ">=3.2,<3.2.123", - "filament/infolists": ">=3,<3.2.115", - "filament/tables": ">=3,<3.2.115", - "filegator/filegator": "<7.8", - "filp/whoops": "<2.1.13", - "fineuploader/php-traditional-server": "<=1.2.2", - "firebase/php-jwt": "<6", - "fisharebest/webtrees": "<=2.1.18", - "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", - "fixpunkt/fp-newsletter": "<1.1.1|>=2,<2.1.2|>=2.2,<3.2.6", - "flarum/core": "<1.8.5", - "flarum/flarum": "<0.1.0.0-beta8", - "flarum/framework": "<1.8.5", - "flarum/mentions": "<1.6.3", - "flarum/sticky": ">=0.1.0.0-beta14,<=0.1.0.0-beta15", - "flarum/tags": "<=0.1.0.0-beta13", - "floriangaerber/magnesium": "<0.3.1", - "fluidtypo3/vhs": "<5.1.1", - "fof/byobu": ">=0.3.0.0-beta2,<1.1.7", - "fof/upload": "<1.2.3", - "foodcoopshop/foodcoopshop": ">=3.2,<3.6.1", - "fooman/tcpdf": "<6.2.22", - "forkcms/forkcms": "<5.11.1", - "fossar/tcpdf-parser": "<6.2.22", - "francoisjacquet/rosariosis": "<=11.5.1", - "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", - "friendsofsymfony/oauth2-php": "<1.3", - "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", - "friendsofsymfony/user-bundle": ">=1,<1.3.5", - "friendsofsymfony1/swiftmailer": ">=4,<5.4.13|>=6,<6.2.5", - "friendsofsymfony1/symfony1": ">=1.1,<1.5.19", - "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", - "friendsoftypo3/openid": ">=4.5,<4.5.31|>=4.7,<4.7.16|>=6,<6.0.11|>=6.1,<6.1.6", - "froala/wysiwyg-editor": "<3.2.7|>=4.0.1,<=4.1.3", - "froxlor/froxlor": "<=2.2.0.0-RC3", - "frozennode/administrator": "<=5.0.12", - "fuel/core": "<1.8.1", - "funadmin/funadmin": "<=5.0.2", - "gaoming13/wechat-php-sdk": "<=1.10.2", - "genix/cms": "<=1.1.11", - "getformwork/formwork": "<1.13.1|==2.0.0.0-beta1", - "getgrav/grav": "<1.7.46", - "getkirby/cms": "<=3.6.6.5|>=3.7,<=3.7.5.4|>=3.8,<=3.8.4.3|>=3.9,<=3.9.8.1|>=3.10,<=3.10.1|>=4,<=4.3", - "getkirby/kirby": "<=2.5.12", - "getkirby/panel": "<2.5.14", - "getkirby/starterkit": "<=3.7.0.2", - "gilacms/gila": "<=1.15.4", - "gleez/cms": "<=1.3|==2", - "globalpayments/php-sdk": "<2", - "gogentooss/samlbase": "<1.2.7", - "google/protobuf": "<3.15", - "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", - "gree/jose": "<2.2.1", - "gregwar/rst": "<1.0.3", - "grumpydictator/firefly-iii": "<6.1.17", - "gugoan/economizzer": "<=0.9.0.0-beta1", - "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", - "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", - "haffner/jh_captcha": "<=2.1.3|>=3,<=3.0.2", - "harvesthq/chosen": "<1.8.7", - "helloxz/imgurl": "<=2.31", - "hhxsv5/laravel-s": "<3.7.36", - "hillelcoren/invoice-ninja": "<5.3.35", - "himiklab/yii2-jqgrid-widget": "<1.0.8", - "hjue/justwriting": "<=1", - "hov/jobfair": "<1.0.13|>=2,<2.0.2", - "httpsoft/http-message": "<1.0.12", - "hyn/multi-tenant": ">=5.6,<5.7.2", - "ibexa/admin-ui": ">=4.2,<4.2.3|>=4.6.0.0-beta1,<4.6.9", - "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3|>=4.5,<4.5.6|>=4.6,<4.6.2", - "ibexa/fieldtype-richtext": ">=4.6,<4.6.10", - "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", - "ibexa/post-install": "<=1.0.4", - "ibexa/solr": ">=4.5,<4.5.4", - "ibexa/user": ">=4,<4.4.3", - "icecoder/icecoder": "<=8.1", - "idno/known": "<=1.3.1", - "ilicmiljan/secure-props": ">=1.2,<1.2.2", - "illuminate/auth": "<5.5.10", - "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<6.18.31|>=7,<7.22.4", - "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", - "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", - "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", - "imdbphp/imdbphp": "<=5.1.1", - "impresscms/impresscms": "<=1.4.5", - "impresspages/impresspages": "<=1.0.12", - "in2code/femanager": "<5.5.3|>=6,<6.3.4|>=7,<7.2.3", - "in2code/ipandlanguageredirect": "<5.1.2", - "in2code/lux": "<17.6.1|>=18,<24.0.2", - "in2code/powermail": "<7.5.1|>=8,<8.5.1|>=9,<10.9.1|>=11,<12.4.1", - "innologi/typo3-appointments": "<2.0.6", - "intelliants/subrion": "<4.2.2", - "inter-mediator/inter-mediator": "==5.5", - "ipl/web": "<0.10.1", - "islandora/islandora": ">=2,<2.4.1", - "ivankristianto/phpwhois": "<=4.3", - "jackalope/jackalope-doctrine-dbal": "<1.7.4", - "james-heinrich/getid3": "<1.9.21", - "james-heinrich/phpthumb": "<1.7.12", - "jasig/phpcas": "<1.3.3", - "jcbrand/converse.js": "<3.3.3", - "johnbillion/wp-crontrol": "<1.16.2", - "joomla/application": "<1.0.13", - "joomla/archive": "<1.1.12|>=2,<2.0.1", - "joomla/filesystem": "<1.6.2|>=2,<2.0.1", - "joomla/filter": "<1.4.4|>=2,<2.0.1", - "joomla/framework": "<1.5.7|>=2.5.4,<=3.8.12", - "joomla/input": ">=2,<2.0.2", - "joomla/joomla-cms": ">=2.5,<3.9.12", - "joomla/session": "<1.3.1", - "joyqi/hyper-down": "<=2.4.27", - "jsdecena/laracom": "<2.0.9", - "jsmitty12/phpwhois": "<5.1", - "juzaweb/cms": "<=3.4", - "jweiland/events2": "<8.3.8|>=9,<9.0.6", - "kazist/phpwhois": "<=4.2.6", - "kelvinmo/simplexrd": "<3.1.1", - "kevinpapst/kimai2": "<1.16.7", - "khodakhah/nodcms": "<=3", - "kimai/kimai": "<=2.20.1", - "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", - "klaviyo/magento2-extension": ">=1,<3", - "knplabs/knp-snappy": "<=1.4.2", - "kohana/core": "<3.3.3", - "krayin/laravel-crm": "<=1.3", - "kreait/firebase-php": ">=3.2,<3.8.1", - "kumbiaphp/kumbiapp": "<=1.1.1", - "la-haute-societe/tcpdf": "<6.2.22", - "laminas/laminas-diactoros": "<2.18.1|==2.19|==2.20|==2.21|==2.22|==2.23|>=2.24,<2.24.2|>=2.25,<2.25.2", - "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", - "laminas/laminas-http": "<2.14.2", - "lara-zeus/artemis": ">=1,<=1.0.6", - "lara-zeus/dynamic-dashboard": ">=3,<=3.0.1", - "laravel/fortify": "<1.11.1", - "laravel/framework": "<6.20.45|>=7,<7.30.7|>=8,<8.83.28|>=9,<9.52.17|>=10,<10.48.23|>=11,<11.31", - "laravel/laravel": ">=5.4,<5.4.22", - "laravel/reverb": "<1.4", - "laravel/socialite": ">=1,<2.0.10", - "latte/latte": "<2.10.8", - "lavalite/cms": "<=9|==10.1", - "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", - "league/commonmark": "<0.18.3", - "league/flysystem": "<1.1.4|>=2,<2.1.1", - "league/oauth2-server": ">=8.3.2,<8.4.2|>=8.5,<8.5.3", - "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", - "libreform/libreform": ">=2,<=2.0.8", - "librenms/librenms": "<2017.08.18", - "liftkit/database": "<2.13.2", - "lightsaml/lightsaml": "<1.3.5", - "limesurvey/limesurvey": "<6.5.12", - "livehelperchat/livehelperchat": "<=3.91", - "livewire/livewire": "<2.12.7|>=3.0.0.0-beta1,<3.5.2", - "lms/routes": "<2.1.1", - "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", - "luyadev/yii-helpers": "<1.2.1", - "maestroerror/php-heic-to-jpg": "<1.0.5", - "magento/community-edition": "<2.4.5|==2.4.5|>=2.4.5.0-patch1,<2.4.5.0-patch10|==2.4.6|>=2.4.6.0-patch1,<2.4.6.0-patch8|>=2.4.7.0-beta1,<2.4.7.0-patch3", - "magento/core": "<=1.9.4.5", - "magento/magento1ce": "<1.9.4.3-dev", - "magento/magento1ee": ">=1,<1.14.4.3-dev", - "magento/product-community-edition": "<2.4.4.0-patch9|>=2.4.5,<2.4.5.0-patch8|>=2.4.6,<2.4.6.0-patch6|>=2.4.7,<2.4.7.0-patch1", - "magneto/core": "<1.9.4.4-dev", - "maikuolan/phpmussel": ">=1,<1.6", - "mainwp/mainwp": "<=4.4.3.3", - "mantisbt/mantisbt": "<=2.26.3", - "marcwillmann/turn": "<0.3.3", - "matyhtf/framework": "<3.0.6", - "mautic/core": "<4.4.13|>=5,<5.1.1", - "mautic/core-lib": ">=1.0.0.0-beta,<4.4.13|>=5.0.0.0-alpha,<5.1.1", - "maximebf/debugbar": "<1.19", - "mdanter/ecc": "<2", - "mediawiki/cargo": "<3.6.1", - "mediawiki/core": "<1.39.5|==1.40", - "mediawiki/matomo": "<2.4.3", - "mediawiki/semantic-media-wiki": "<4.0.2", - "melisplatform/melis-asset-manager": "<5.0.1", - "melisplatform/melis-cms": "<5.0.1", - "melisplatform/melis-front": "<5.0.1", - "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", - "mgallegos/laravel-jqgrid": "<=1.3", - "microsoft/microsoft-graph": ">=1.16,<1.109.1|>=2,<2.0.1", - "microsoft/microsoft-graph-beta": "<2.0.1", - "microsoft/microsoft-graph-core": "<2.0.2", - "microweber/microweber": "<=2.0.16", - "mikehaertl/php-shellcommand": "<1.6.1", - "miniorange/miniorange-saml": "<1.4.3", - "mittwald/typo3_forum": "<1.2.1", - "mobiledetect/mobiledetectlib": "<2.8.32", - "modx/revolution": "<=2.8.3.0-patch", - "mojo42/jirafeau": "<4.4", - "mongodb/mongodb": ">=1,<1.9.2", - "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.3.8|>=4.4,<4.4.4", - "mos/cimage": "<0.7.19", - "movim/moxl": ">=0.8,<=0.10", - "movingbytes/social-network": "<=1.2.1", - "mpdf/mpdf": "<=7.1.7", - "munkireport/comment": "<4.1", - "munkireport/managedinstalls": "<2.6", - "munkireport/munki_facts": "<1.5", - "munkireport/munkireport": ">=2.5.3,<5.6.3", - "munkireport/reportdata": "<3.5", - "munkireport/softwareupdate": "<1.6", - "mustache/mustache": ">=2,<2.14.1", - "namshi/jose": "<2.2", - "nategood/httpful": "<1", - "neoan3-apps/template": "<1.1.1", - "neorazorx/facturascripts": "<2022.04", - "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", - "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", - "neos/media-browser": "<7.3.19|>=8,<8.0.16|>=8.1,<8.1.11|>=8.2,<8.2.11|>=8.3,<8.3.9", - "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", - "neos/swiftmailer": "<5.4.5", - "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", - "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", - "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", - "nilsteampassnet/teampass": "<3.0.10", - "nonfiction/nterchange": "<4.1.1", - "notrinos/notrinos-erp": "<=0.7", - "noumo/easyii": "<=0.9", - "novaksolutions/infusionsoft-php-sdk": "<1", - "nukeviet/nukeviet": "<4.5.02", - "nyholm/psr7": "<1.6.1", - "nystudio107/craft-seomatic": "<3.4.12", - "nzedb/nzedb": "<0.8", - "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", - "october/backend": "<1.1.2", - "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", - "october/october": "<=3.6.4", - "october/rain": "<1.0.472|>=1.1,<1.1.2", - "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.34|>=3,<3.5.15", - "omeka/omeka-s": "<4.0.3", - "onelogin/php-saml": "<2.10.4", - "oneup/uploader-bundle": ">=1,<1.9.3|>=2,<2.1.5", - "open-web-analytics/open-web-analytics": "<1.7.4", - "opencart/opencart": ">=0", - "openid/php-openid": "<2.3", - "openmage/magento-lts": "<20.10.1", - "opensolutions/vimbadmin": "<=3.0.15", - "opensource-workshop/connect-cms": "<1.7.2|>=2,<2.3.2", - "orchid/platform": ">=8,<14.43", - "oro/calendar-bundle": ">=4.2,<=4.2.6|>=5,<=5.0.6|>=5.1,<5.1.1", - "oro/commerce": ">=4.1,<5.0.11|>=5.1,<5.1.1", - "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", - "oro/crm-call-bundle": ">=4.2,<=4.2.5|>=5,<5.0.4|>=5.1,<5.1.1", - "oro/customer-portal": ">=4.1,<=4.1.13|>=4.2,<=4.2.10|>=5,<=5.0.11|>=5.1,<=5.1.3", - "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<=4.2.10|>=5,<=5.0.12|>=5.1,<=5.1.3", - "oveleon/contao-cookiebar": "<1.16.3|>=2,<2.1.3", - "oxid-esales/oxideshop-ce": "<4.5", - "oxid-esales/paymorrow-module": ">=1,<1.0.2|>=2,<2.0.1", - "packbackbooks/lti-1-3-php-library": "<5", - "padraic/humbug_get_contents": "<1.1.2", - "pagarme/pagarme-php": "<3", - "pagekit/pagekit": "<=1.0.18", - "paragonie/ecc": "<2.0.1", - "paragonie/random_compat": "<2", - "passbolt/passbolt_api": "<4.6.2", - "paypal/adaptivepayments-sdk-php": "<=3.9.2", - "paypal/invoice-sdk-php": "<=3.9", - "paypal/merchant-sdk-php": "<3.12", - "paypal/permissions-sdk-php": "<=3.9.1", - "pear/archive_tar": "<1.4.14", - "pear/auth": "<1.2.4", - "pear/crypt_gpg": "<1.6.7", - "pear/pear": "<=1.10.1", - "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", - "personnummer/personnummer": "<3.0.2", - "phanan/koel": "<5.1.4", - "phenx/php-svg-lib": "<0.5.2", - "php-censor/php-censor": "<2.0.13|>=2.1,<2.1.5", - "php-mod/curl": "<2.3.2", - "phpbb/phpbb": "<3.3.11", - "phpems/phpems": ">=6,<=6.1.3", - "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", - "phpmailer/phpmailer": "<6.5", - "phpmussel/phpmussel": ">=1,<1.6", - "phpmyadmin/phpmyadmin": "<5.2.1", - "phpmyfaq/phpmyfaq": "<3.2.5|==3.2.5", - "phpoffice/common": "<0.2.9", - "phpoffice/phpexcel": "<1.8.1", - "phpoffice/phpspreadsheet": "<1.29.4|>=2,<2.1.3|>=2.2,<2.3.2|>=3.3,<3.4", - "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", - "phpservermon/phpservermon": "<3.6", - "phpsysinfo/phpsysinfo": "<3.4.3", - "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", - "phpwhois/phpwhois": "<=4.2.5", - "phpxmlrpc/extras": "<0.6.1", - "phpxmlrpc/phpxmlrpc": "<4.9.2", - "pi/pi": "<=2.5", - "pimcore/admin-ui-classic-bundle": "<1.5.4", - "pimcore/customer-management-framework-bundle": "<4.0.6", - "pimcore/data-hub": "<1.2.4", - "pimcore/data-importer": "<1.8.9|>=1.9,<1.9.3", - "pimcore/demo": "<10.3", - "pimcore/ecommerce-framework-bundle": "<1.0.10", - "pimcore/perspective-editor": "<1.5.1", - "pimcore/pimcore": "<11.2.4", - "pixelfed/pixelfed": "<0.11.11", - "plotly/plotly.js": "<2.25.2", - "pocketmine/bedrock-protocol": "<8.0.2", - "pocketmine/pocketmine-mp": "<5.11.2", - "pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1", - "pressbooks/pressbooks": "<5.18", - "prestashop/autoupgrade": ">=4,<4.10.1", - "prestashop/blockreassurance": "<=5.1.3", - "prestashop/blockwishlist": ">=2,<2.1.1", - "prestashop/contactform": ">=1.0.1,<4.3", - "prestashop/gamification": "<2.3.2", - "prestashop/prestashop": "<8.1.6", - "prestashop/productcomments": "<5.0.2", - "prestashop/ps_emailsubscription": "<2.6.1", - "prestashop/ps_facetedsearch": "<3.4.1", - "prestashop/ps_linklist": "<3.1", - "privatebin/privatebin": "<1.4|>=1.5,<1.7.4", - "processwire/processwire": "<=3.0.229", - "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", - "propel/propel1": ">=1,<=1.7.1", - "pterodactyl/panel": "<1.11.8", - "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", - "ptrofimov/beanstalk_console": "<1.7.14", - "pubnub/pubnub": "<6.1", - "pusher/pusher-php-server": "<2.2.1", - "pwweb/laravel-core": "<=0.3.6.0-beta", - "pxlrbt/filament-excel": "<1.1.14|>=2.0.0.0-alpha,<2.3.3", - "pyrocms/pyrocms": "<=3.9.1", - "qcubed/qcubed": "<=3.1.1", - "quickapps/cms": "<=2.0.0.0-beta2", - "rainlab/blog-plugin": "<1.4.1", - "rainlab/debugbar-plugin": "<3.1", - "rainlab/user-plugin": "<=1.4.5", - "rankmath/seo-by-rank-math": "<=1.0.95", - "rap2hpoutre/laravel-log-viewer": "<0.13", - "react/http": ">=0.7,<1.9", - "really-simple-plugins/complianz-gdpr": "<6.4.2", - "redaxo/source": "<5.18", - "remdex/livehelperchat": "<4.29", - "reportico-web/reportico": "<=8.1", - "rhukster/dom-sanitizer": "<1.0.7", - "rmccue/requests": ">=1.6,<1.8", - "robrichards/xmlseclibs": ">=1,<3.0.4", - "roots/soil": "<4.1", - "rudloff/alltube": "<3.0.3", - "s-cart/core": "<6.9", - "s-cart/s-cart": "<6.9", - "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", - "sabre/dav": ">=1.6,<1.7.11|>=1.8,<1.8.9", - "scheb/two-factor-bundle": "<3.26|>=4,<4.11", - "sensiolabs/connect": "<4.2.3", - "serluck/phpwhois": "<=4.2.6", - "sfroemken/url_redirect": "<=1.2.1", - "sheng/yiicms": "<=1.2", - "shopware/core": "<=6.5.8.12|>=6.6,<=6.6.5", - "shopware/platform": "<=6.5.8.12|>=6.6,<=6.6.5", - "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<=5.7.17", - "shopware/storefront": "<=6.4.8.1|>=6.5.8,<6.5.8.7-dev", - "shopxo/shopxo": "<=6.1", - "showdoc/showdoc": "<2.10.4", - "silverstripe-australia/advancedreports": ">=1,<=2", - "silverstripe/admin": "<1.13.19|>=2,<2.1.8", - "silverstripe/assets": ">=1,<1.11.1", - "silverstripe/cms": "<4.11.3", - "silverstripe/comments": ">=1.3,<3.1.1", - "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<5.2.16", - "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.8.2|>=4,<4.3.7|>=5,<5.1.3", - "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", - "silverstripe/recipe-cms": ">=4.5,<4.5.3", - "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", - "silverstripe/reports": "<5.2.3", - "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4|>=2.1,<2.1.2", - "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", - "silverstripe/subsites": ">=2,<2.6.1", - "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", - "silverstripe/userforms": "<3|>=5,<5.4.2", - "silverstripe/versioned-admin": ">=1,<1.11.1", - "simple-updates/phpwhois": "<=1", - "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4|==5.0.0.0-alpha12", - "simplesamlphp/simplesamlphp": "<1.18.6", - "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", - "simplesamlphp/simplesamlphp-module-openid": "<1", - "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", - "simplesamlphp/xml-security": "==1.6.11", - "simplito/elliptic-php": "<1.0.6", - "sitegeist/fluid-components": "<3.5", - "sjbr/sr-freecap": "<2.4.6|>=2.5,<2.5.3", - "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", - "slim/slim": "<2.6", - "slub/slub-events": "<3.0.3", - "smarty/smarty": "<4.5.3|>=5,<5.1.1", - "snipe/snipe-it": "<=7.0.13", - "socalnick/scn-social-auth": "<1.15.2", - "socialiteproviders/steam": "<1.1", - "spatie/browsershot": "<3.57.4", - "spatie/image-optimizer": "<1.7.3", - "spencer14420/sp-php-email-handler": "<1", - "spipu/html2pdf": "<5.2.8", - "spoon/library": "<1.4.1", - "spoonity/tcpdf": "<6.2.22", - "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", - "ssddanbrown/bookstack": "<24.05.1", - "starcitizentools/citizen-skin": ">=2.6.3,<2.31", - "statamic/cms": "<=5.16", - "stormpath/sdk": "<9.9.99", - "studio-42/elfinder": "<=2.1.64", - "studiomitte/friendlycaptcha": "<0.1.4", - "subhh/libconnect": "<7.0.8|>=8,<8.1", - "sukohi/surpass": "<1", - "sulu/form-bundle": ">=2,<2.5.3", - "sulu/sulu": "<1.6.44|>=2,<2.5.21|>=2.6,<2.6.5", - "sumocoders/framework-user-bundle": "<1.4", - "superbig/craft-audit": "<3.0.2", - "swag/paypal": "<5.4.4", - "swiftmailer/swiftmailer": "<6.2.5", - "swiftyedit/swiftyedit": "<1.2", - "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", - "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", - "sylius/grid-bundle": "<1.10.1", - "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", - "sylius/resource-bundle": ">=1,<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", - "sylius/sylius": "<1.12.19|>=1.13.0.0-alpha1,<1.13.4", - "symbiote/silverstripe-multivaluefield": ">=3,<3.1", - "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", - "symbiote/silverstripe-seed": "<6.0.3", - "symbiote/silverstripe-versionedfiles": "<=2.0.3", - "symfont/process": ">=0", - "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", - "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", - "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", - "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<5.3.15|>=5.4.3,<5.4.4|>=6.0.3,<6.0.4", - "symfony/http-client": ">=4.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", - "symfony/http-foundation": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", - "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", - "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", - "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", - "symfony/mime": ">=4.3,<4.3.8", - "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/polyfill": ">=1,<1.10", - "symfony/polyfill-php55": ">=1,<1.10", - "symfony/process": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", - "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/routing": ">=2,<2.0.19", - "symfony/runtime": ">=5.3,<5.4.46|>=6,<6.4.14|>=7,<7.1.7", - "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", - "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.4.10|>=7,<7.0.10|>=7.1,<7.1.3", - "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", - "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", - "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", - "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", - "symfony/symfony": "<5.4.47|>=6,<6.4.15|>=7,<7.1.8", - "symfony/translation": ">=2,<2.0.17", - "symfony/twig-bridge": ">=2,<4.4.51|>=5,<5.4.31|>=6,<6.3.8", - "symfony/ux-autocomplete": "<2.11.2", - "symfony/validator": "<5.4.43|>=6,<6.4.11|>=7,<7.1.4", - "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", - "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", - "symfony/webhook": ">=6.3,<6.3.8", - "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7|>=2.2.0.0-beta1,<2.2.0.0-beta2", - "symphonycms/symphony-2": "<2.6.4", - "t3/dce": "<0.11.5|>=2.2,<2.6.2", - "t3g/svg-sanitizer": "<1.0.3", - "t3s/content-consent": "<1.0.3|>=2,<2.0.2", - "tastyigniter/tastyigniter": "<3.3", - "tcg/voyager": "<=1.4", - "tecnickcom/tcpdf": "<=6.7.5", - "terminal42/contao-tablelookupwizard": "<3.3.5", - "thelia/backoffice-default-template": ">=2.1,<2.1.2", - "thelia/thelia": ">=2.1,<2.1.3", - "theonedemon/phpwhois": "<=4.2.5", - "thinkcmf/thinkcmf": "<6.0.8", - "thorsten/phpmyfaq": "<3.2.2", - "tikiwiki/tiki-manager": "<=17.1", - "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", - "tinymce/tinymce": "<7.2", - "tinymighty/wiki-seo": "<1.2.2", - "titon/framework": "<9.9.99", - "tobiasbg/tablepress": "<=2.0.0.0-RC1", - "topthink/framework": "<6.0.17|>=6.1,<=8.0.4", - "topthink/think": "<=6.1.1", - "topthink/thinkphp": "<=3.2.3|>=6.1.3,<=8.0.4", - "torrentpier/torrentpier": "<=2.4.3", - "tpwd/ke_search": "<4.0.3|>=4.1,<4.6.6|>=5,<5.0.2", - "tribalsystems/zenario": "<=9.7.61188", - "truckersmp/phpwhois": "<=4.3.1", - "ttskch/pagination-service-provider": "<1", - "twbs/bootstrap": "<=3.4.1|>=4,<=4.6.2", - "twig/twig": "<3.11.2|>=3.12,<3.14.1", - "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", - "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<10.4.46|>=11,<11.5.40|>=12,<12.4.21|>=13,<13.3.1", - "typo3/cms-core": "<=8.7.56|>=9,<=9.5.47|>=10,<=10.4.44|>=11,<=11.5.36|>=12,<=12.4.14|>=13,<=13.1", - "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", - "typo3/cms-fluid": "<4.3.4|>=4.4,<4.4.1", - "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", - "typo3/cms-frontend": "<4.3.9|>=4.4,<4.4.5", - "typo3/cms-install": "<4.1.14|>=4.2,<4.2.16|>=4.3,<4.3.9|>=4.4,<4.4.5|>=12.2,<12.4.8", - "typo3/cms-rte-ckeditor": ">=9.5,<9.5.42|>=10,<10.4.39|>=11,<11.5.30", - "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", - "typo3/html-sanitizer": ">=1,<=1.5.2|>=2,<=2.1.3", - "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", - "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", - "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", - "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", - "ua-parser/uap-php": "<3.8", - "uasoft-indonesia/badaso": "<=2.9.7", - "unisharp/laravel-filemanager": "<2.6.4", - "unopim/unopim": "<0.1.5", - "userfrosting/userfrosting": ">=0.3.1,<4.6.3", - "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", - "uvdesk/community-skeleton": "<=1.1.1", - "uvdesk/core-framework": "<=1.1.1", - "vanilla/safecurl": "<0.9.2", - "verbb/comments": "<1.5.5", - "verbb/formie": "<2.1.6", - "verbb/image-resizer": "<2.0.9", - "verbb/knock-knock": "<1.2.8", - "verot/class.upload.php": "<=2.1.6", - "villagedefrance/opencart-overclocked": "<=1.11.1", - "vova07/yii2-fileapi-widget": "<0.1.9", - "vrana/adminer": "<4.8.1", - "vufind/vufind": ">=2,<9.1.1", - "waldhacker/hcaptcha": "<2.1.2", - "wallabag/tcpdf": "<6.2.22", - "wallabag/wallabag": "<2.6.7", - "wanglelecc/laracms": "<=1.0.3", - "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9", - "web-auth/webauthn-lib": ">=4.5,<4.9", - "web-feet/coastercms": "==5.5", - "webbuilders-group/silverstripe-kapost-bridge": "<0.4", - "webcoast/deferred-image-processing": "<1.0.2", - "webklex/laravel-imap": "<5.3", - "webklex/php-imap": "<5.3", - "webpa/webpa": "<3.1.2", - "wikibase/wikibase": "<=1.39.3", - "wikimedia/parsoid": "<0.12.2", - "willdurand/js-translation-bundle": "<2.1.1", - "winter/wn-backend-module": "<1.2.4", - "winter/wn-dusk-plugin": "<2.1", - "winter/wn-system-module": "<1.2.4", - "wintercms/winter": "<=1.2.3", - "wireui/wireui": "<1.19.3|>=2,<2.1.3", - "woocommerce/woocommerce": "<6.6|>=8.8,<8.8.5|>=8.9,<8.9.3", - "wp-cli/wp-cli": ">=0.12,<2.5", - "wp-graphql/wp-graphql": "<=1.14.5", - "wp-premium/gravityforms": "<2.4.21", - "wpanel/wpanel4-cms": "<=4.3.1", - "wpcloud/wp-stateless": "<3.2", - "wpglobus/wpglobus": "<=1.9.6", - "wwbn/avideo": "<14.3", - "xataface/xataface": "<3", - "xpressengine/xpressengine": "<3.0.15", - "yab/quarx": "<2.4.5", - "yeswiki/yeswiki": "<=4.4.4", - "yetiforce/yetiforce-crm": "<=6.4", - "yidashi/yii2cmf": "<=2", - "yii2mod/yii2-cms": "<1.9.2", - "yiisoft/yii": "<1.1.29", - "yiisoft/yii2": "<2.0.49.4-dev", - "yiisoft/yii2-authclient": "<2.2.15", - "yiisoft/yii2-bootstrap": "<2.0.4", - "yiisoft/yii2-dev": "<2.0.43", - "yiisoft/yii2-elasticsearch": "<2.0.5", - "yiisoft/yii2-gii": "<=2.2.4", - "yiisoft/yii2-jui": "<2.0.4", - "yiisoft/yii2-redis": "<2.0.8", - "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", - "yoast-seo-for-typo3/yoast_seo": "<7.2.3", - "yourls/yourls": "<=1.8.2", - "yuan1994/tpadmin": "<=1.3.12", - "zencart/zencart": "<=1.5.7.0-beta", - "zendesk/zendesk_api_client_php": "<2.2.11", - "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", - "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", - "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", - "zendframework/zend-db": "<2.2.10|>=2.3,<2.3.5", - "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", - "zendframework/zend-diactoros": "<1.8.4", - "zendframework/zend-feed": "<2.10.3", - "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-http": "<2.8.1", - "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", - "zendframework/zend-mail": "<2.4.11|>=2.5,<2.7.2", - "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-session": ">=2,<2.2.9|>=2.3,<2.3.4", - "zendframework/zend-validator": ">=2.3,<2.3.6", - "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zendframework": "<=3", - "zendframework/zendframework1": "<1.12.20", - "zendframework/zendopenid": "<2.0.2", - "zendframework/zendrest": "<2.0.2", - "zendframework/zendservice-amazon": "<2.0.3", - "zendframework/zendservice-api": "<1", - "zendframework/zendservice-audioscrobbler": "<2.0.2", - "zendframework/zendservice-nirvanix": "<2.0.2", - "zendframework/zendservice-slideshare": "<2.0.2", - "zendframework/zendservice-technorati": "<2.0.2", - "zendframework/zendservice-windowsazure": "<2.0.2", - "zendframework/zendxml": ">=1,<1.0.1", - "zenstruck/collection": "<0.2.1", - "zetacomponents/mail": "<1.8.2", - "zf-commons/zfc-user": "<1.2.2", - "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", - "zfr/zfr-oauth2-server-module": "<0.1.2", - "zoujingli/thinkadmin": "<=6.1.53" - }, - "default-branch": true, - "type": "metapackage", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "role": "maintainer" - }, - { - "name": "Ilya Tribusean", - "email": "slash3b@gmail.com", - "role": "maintainer" - } - ], - "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "keywords": [ - "dev" - ], - "support": { - "issues": "https://github.com/Roave/SecurityAdvisories/issues", - "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" - }, - "funding": [ - { - "url": "https://github.com/Ocramius", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", - "type": "tidelift" - } - ], - "time": "2024-11-27T22:05:07+00:00" - }, - { - "name": "sanmai/later", - "version": "0.1.4", - "source": { - "type": "git", - "url": "https://github.com/sanmai/later.git", - "reference": "e24c4304a4b1349c2a83151a692cec0c10579f60" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sanmai/later/zipball/e24c4304a4b1349c2a83151a692cec0c10579f60", - "reference": "e24c4304a4b1349c2a83151a692cec0c10579f60", - "shasum": "" - }, - "require": { - "php": ">=7.4" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.8", - "friendsofphp/php-cs-fixer": "^3.35.1", - "infection/infection": ">=0.27.6", - "phan/phan": ">=2", - "php-coveralls/php-coveralls": "^2.0", - "phpstan/phpstan": ">=1.4.5", - "phpunit/phpunit": ">=9.5 <10", - "vimeo/psalm": ">=2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "0.1.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Later\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Alexey Kopytko", - "email": "alexey@kopytko.com" - } - ], - "description": "Later: deferred wrapper object", - "support": { - "issues": "https://github.com/sanmai/later/issues", - "source": "https://github.com/sanmai/later/tree/0.1.4" - }, - "funding": [ - { - "url": "https://github.com/sanmai", - "type": "github" - } - ], - "time": "2023-10-24T00:25:28+00:00" - }, - { - "name": "sanmai/pipeline", - "version": "6.12", - "source": { - "type": "git", - "url": "https://github.com/sanmai/pipeline.git", - "reference": "ad7dbc3f773eeafb90d5459522fbd8f188532e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sanmai/pipeline/zipball/ad7dbc3f773eeafb90d5459522fbd8f188532e25", - "reference": "ad7dbc3f773eeafb90d5459522fbd8f188532e25", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.8", - "friendsofphp/php-cs-fixer": "^3.17", - "infection/infection": ">=0.10.5", - "league/pipeline": "^0.3 || ^1.0", - "phan/phan": ">=1.1", - "php-coveralls/php-coveralls": "^2.4.1", - "phpstan/phpstan": ">=0.10", - "phpunit/phpunit": ">=9.4", - "vimeo/psalm": ">=2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "v6.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Pipeline\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Alexey Kopytko", - "email": "alexey@kopytko.com" - } - ], - "description": "General-purpose collections pipeline", - "support": { - "issues": "https://github.com/sanmai/pipeline/issues", - "source": "https://github.com/sanmai/pipeline/tree/6.12" - }, - "funding": [ - { - "url": "https://github.com/sanmai", - "type": "github" - } - ], - "time": "2024-10-17T02:22:57+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:12:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:58:43+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:59:15+00:00" - }, - { - "name": "sebastian/comparator", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", - "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-10-18T14:56:07+00:00" - }, - { - "name": "sebastian/complexity", - "version": "3.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-21T08:37:17+00:00" - }, - { - "name": "sebastian/diff", - "version": "5.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:15:17+00:00" - }, - { - "name": "sebastian/environment", - "version": "6.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-23T08:47:14+00:00" - }, - { - "name": "sebastian/exporter", - "version": "5.1.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:17:12+00:00" - }, - { - "name": "sebastian/global-state", - "version": "6.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T07:19:19+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-21T08:38:20+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:08:32+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:06:18+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:05:40+00:00" - }, - { - "name": "sebastian/type", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:10:45+00:00" - }, - { - "name": "sebastian/version", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-07T11:34:05+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.11.1", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "19473c30efe4f7b3cd42522d0b2e6e7f243c6f87" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/19473c30efe4f7b3cd42522d0b2e6e7f243c6f87", - "reference": "19473c30efe4f7b3cd42522d0b2e6e7f243c6f87", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" - }, - "bin": [ - "bin/phpcbf", - "bin/phpcs" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "Former lead" - }, - { - "name": "Juliette Reinders Folmer", - "role": "Current lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", - "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", - "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" - }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - } - ], - "time": "2024-11-16T12:02:36+00:00" - }, - { - "name": "symfony/console", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", - "reference": "23c8aae6d764e2bae02d2a99f7532a7f6ed619cf", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.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": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-06T14:24:19+00:00" - }, - { - "name": "symfony/finder", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", - "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "symfony/filesystem": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-10-23T06:56:12+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/process", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", - "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-06T14:24:19+00:00" - }, - { - "name": "symfony/string", - "version": "v7.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" - }, - "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v7.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-13T13:31:26+00:00" - }, - { - "name": "thecodingmachine/safe", - "version": "v2.5.0", - "source": { - "type": "git", - "url": "https://github.com/thecodingmachine/safe.git", - "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/3115ecd6b4391662b4931daac4eba6b07a2ac1f0", - "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0", - "shasum": "" - }, - "require": { - "php": "^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": "^9.5", - "squizlabs/php_codesniffer": "^3.2", - "thecodingmachine/phpstan-strict-rules": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "files": [ - "deprecated/apc.php", - "deprecated/array.php", - "deprecated/datetime.php", - "deprecated/libevent.php", - "deprecated/misc.php", - "deprecated/password.php", - "deprecated/mssql.php", - "deprecated/stats.php", - "deprecated/strings.php", - "lib/special_cases.php", - "deprecated/mysqli.php", - "generated/apache.php", - "generated/apcu.php", - "generated/array.php", - "generated/bzip2.php", - "generated/calendar.php", - "generated/classobj.php", - "generated/com.php", - "generated/cubrid.php", - "generated/curl.php", - "generated/datetime.php", - "generated/dir.php", - "generated/eio.php", - "generated/errorfunc.php", - "generated/exec.php", - "generated/fileinfo.php", - "generated/filesystem.php", - "generated/filter.php", - "generated/fpm.php", - "generated/ftp.php", - "generated/funchand.php", - "generated/gettext.php", - "generated/gmp.php", - "generated/gnupg.php", - "generated/hash.php", - "generated/ibase.php", - "generated/ibmDb2.php", - "generated/iconv.php", - "generated/image.php", - "generated/imap.php", - "generated/info.php", - "generated/inotify.php", - "generated/json.php", - "generated/ldap.php", - "generated/libxml.php", - "generated/lzf.php", - "generated/mailparse.php", - "generated/mbstring.php", - "generated/misc.php", - "generated/mysql.php", - "generated/network.php", - "generated/oci8.php", - "generated/opcache.php", - "generated/openssl.php", - "generated/outcontrol.php", - "generated/pcntl.php", - "generated/pcre.php", - "generated/pgsql.php", - "generated/posix.php", - "generated/ps.php", - "generated/pspell.php", - "generated/readline.php", - "generated/rpminfo.php", - "generated/rrd.php", - "generated/sem.php", - "generated/session.php", - "generated/shmop.php", - "generated/sockets.php", - "generated/sodium.php", - "generated/solr.php", - "generated/spl.php", - "generated/sqlsrv.php", - "generated/ssdeep.php", - "generated/ssh2.php", - "generated/stream.php", - "generated/strings.php", - "generated/swoole.php", - "generated/uodbc.php", - "generated/uopz.php", - "generated/url.php", - "generated/var.php", - "generated/xdiff.php", - "generated/xml.php", - "generated/xmlrpc.php", - "generated/yaml.php", - "generated/yaz.php", - "generated/zip.php", - "generated/zlib.php" - ], - "classmap": [ - "lib/DateTime.php", - "lib/DateTimeImmutable.php", - "lib/Exceptions/", - "deprecated/Exceptions/", - "generated/Exceptions/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHP core functions that throw exceptions instead of returning FALSE on error", - "support": { - "issues": "https://github.com/thecodingmachine/safe/issues", - "source": "https://github.com/thecodingmachine/safe/tree/v2.5.0" - }, - "time": "2023-04-05T11:54:14+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:36:25+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" - } - ], - "aliases": [], - "minimum-stability": "dev", - "stability-flags": { - "roave/security-advisories": 20 - }, - "prefer-stable": true, - "prefer-lowest": false, - "platform": { - "php": ">=8.1 <8.4.0" - }, - "platform-dev": [], - "plugin-api-version": "2.6.0" -} diff --git a/config/rate_limiter.yaml b/config/rate_limiter.yaml new file mode 100644 index 0000000..e71ffb0 --- /dev/null +++ b/config/rate_limiter.yaml @@ -0,0 +1,12 @@ +framework: + rate_limiter: + form_submit_by_ip: + # https://symfony.com/doc/current/rate_limiter.html#token-bucket-rate-limiter + policy: 'token_bucket' + limit: 20 + rate: { interval: '15 minutes', amount: 5 } + form_submit_total: + # https://symfony.com/doc/current/rate_limiter.html#token-bucket-rate-limiter + policy: 'token_bucket' + limit: 1000 + rate: { interval: '15 minutes', amount: 100 } diff --git a/config/routes.yaml b/config/routes.yaml new file mode 100644 index 0000000..7ff4a08 --- /dev/null +++ b/config/routes.yaml @@ -0,0 +1,3 @@ +controller: + resource: "@AtooloFormBundle/Controller/" + type: attribute diff --git a/config/services.yaml b/config/services.yaml index 5d2d4be..d048efb 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -1,4 +1,28 @@ +parameters: + atoolo_form.default_processors: + 'ip-limiter': ~ + 'submit-limiter': ~ + 'json-schema-validator': ~ + atoolo_form.processor.ip_allower.allowed_ips: [] + atoolo_form.processor.ip_blocker.blocked_ips: [] + services: - Atoolo\CityCall\Service\Indexer\Enricher\SiteKitSchema2x\NewsDocumentEnricher: - tags: - - { name: 'atoolo_search.indexer.document_enricher.schema2x', priority: 10 } + + # default configuration for services in *this* file + _defaults: + autowire: true # Automatically injects dependencies in your services. + autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + + Atoolo\Form\Controller\: + resource: '../src/Controller' + + Atoolo\Form\Service\: + resource: '../src/Service' + + Atoolo\Form\Processor\: + resource: '../src/Processor' + + Atoolo\Form\Processor\EmailSender: + arguments: + - '@Atoolo\Form\Service\Email\EmailMessageModelFactory' + - '@Atoolo\Form\Service\Email\EmailMessageTwigRenderer' diff --git a/phpcs.compatibilitycheck.xml b/phpcs.compatibilitycheck.xml index b9fc4df..f4c9d97 100644 --- a/phpcs.compatibilitycheck.xml +++ b/phpcs.compatibilitycheck.xml @@ -2,7 +2,7 @@ - + diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 0a889e0..40eba4c 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -3,3 +3,59 @@ parameters: tmpDir: var/cache/phpstan paths: - src + typeAliases: + EmailMessageModelItem: ''' + array{ + type?: string, + layout?: boolean, + } + ''' + EmailMessageModelLayoutItem: ''' + array{ + type: string, + layout: boolean, + label?: string, + items?: array, + } + ''' + EmailMessageModelControlItem: ''' + array{ + type: string, + name: string, + label?: string, + htmlLabel?: string, + value: string|int|bool|array|EmailMessageModelFileUpload|null, + options?: array, + } + ''' + EmailMessageModelFileUpload: ''' + array{ + filename: string, + contentType: string, + data: string, + size: int, + } + ''' + EmailMessageModel: ''' + array{ + url: string, + tenant: array{name: string}, + host: string, + date: \DateTime, + items: array, + } + ''' + JsonSchema: ''' + array{ + type?: string, + format?: string, + oneOf?: array, + items?: array{ + oneOf?: array, + }, + } + ''' \ No newline at end of file diff --git a/src/AtooloFormBundle.php b/src/AtooloFormBundle.php index 606136a..418d569 100644 --- a/src/AtooloFormBundle.php +++ b/src/AtooloFormBundle.php @@ -9,12 +9,12 @@ use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; -use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\HttpKernel\Bundle\AbstractBundle; /** * @codeCoverageIgnore */ -class AtooloFormBundle extends Bundle +class AtooloFormBundle extends AbstractBundle { public function build(ContainerBuilder $container): void { @@ -30,5 +30,14 @@ public function build(ContainerBuilder $container): void ); $loader->load('services.yaml'); + $loader->load('rate_limiter.yaml'); } + + /* TODO actually, it shouldn't work at all without it + * https://symfony.com/doc/current/bundles.html + public function getPath(): string + { + return __DIR__; + } + */ } diff --git a/src/Controller/FormController.php b/src/Controller/FormController.php new file mode 100644 index 0000000..247ee9a --- /dev/null +++ b/src/Controller/FormController.php @@ -0,0 +1,152 @@ +serializer = new Serializer($normalizers, $encoders); + } + + #[Route("/api/form/{_locale}/{location}/{component}", name: "atoolo_form_definition", requirements: ['location' => '.+'], methods: ['GET'], format: 'json')] + public function definition(string $_locale, string $location, string $component): Response + { + $lang = $_locale; + $definition = $this->loadDefinition($lang, $location, $component); + + $json = $this->serializer->serialize($definition, 'json', [ + 'json_encode_options' => JSON_THROW_ON_ERROR, + AbstractObjectNormalizer::SKIP_NULL_VALUES => true, + AbstractNormalizer::IGNORED_ATTRIBUTES => ['processors'], // ignore-attribute not jet working + ]); + + return new JsonResponse(data: $json, json: true); + } + + #[Route("/api/form/{_locale}/{location}/{component}", name: "atoolo_form_submit", requirements: ['location' => '.+'], methods: ['POST'], format: 'json')] + public function submit( + string $_locale, + string $location, + string $component, + Request $request, + ): Response { + + $lang = $_locale; + $data = $this->requestBodyToObject($request); + + $formDefinition = $this->loadDefinition($lang, $location, $component); + + $submission = new FormSubmission( + $request->getClientIp() ?? '', + $formDefinition, + $data, + ); + + $this->submitHandler->handle($submission); + + return $this->json(['status' => 200]); + } + + private function requestBodyToObject(Request $request): stdClass + { + if ($request->getContentTypeFormat() !== 'json') { + throw new UnsupportedMediaTypeHttpException('Unsupported Media Type'); + } + + if ('' === $content = $request->getContent()) { + throw new JsonException('Request body is empty.'); + } + + try { + $data = json_decode($content, false, 512, JSON_BIGINT_AS_STRING | JSON_THROW_ON_ERROR); + if (!($data instanceof stdClass)) { + throw new JsonException('Request body is not an object: ' . $content); + } + return $data; + } catch (\JsonException $e) { + throw new JsonException('Could not decode request body: ' . $e->getMessage(), $e->getCode(), $e); + } + } + + private function loadDefinition(string $lang, string $path, string $component): FormDefinition + { + $location = $this->toResourceLocation($lang, $path); + try { + return $this->formDefinitionLoader->loadFromResource($location, $component); + } catch (ResourceNotFoundException) { + throw new NotFoundHttpException('Resource \'' . $location . '\' not found'); + } catch (FormNotFoundException $e) { + throw new NotFoundHttpException($e->getMessage()); + } + } + + private function toResourceLocation(string $lang, string $path): ResourceLocation + { + if ($this->isSupportedTranslation($lang)) { + $this->localeSwitcher->setLocale($lang); + return ResourceLocation::of('/' . $path . '.php', ResourceLanguage::of($lang)); + } + + if (str_starts_with($this->channel->locale, $lang . '_')) { + return ResourceLocation::of('/' . $path . '.php'); + } + + // lang is not a language but part of the path, if not empty + $location = ( + empty($lang) + ? '/' . $path + : '/' . $lang . '/' . $path + ) . '.php'; + + return ResourceLocation::of($location); + } + + private function isSupportedTranslation(string $lang): bool + { + foreach ($this->channel->translationLocales as $locale) { + if (str_starts_with($locale, $lang . '_')) { + return true; + } + } + return false; + } +} diff --git a/src/Dto/Email/EmailHtmlMessageRendererResult.php b/src/Dto/Email/EmailHtmlMessageRendererResult.php new file mode 100644 index 0000000..4f62f82 --- /dev/null +++ b/src/Dto/Email/EmailHtmlMessageRendererResult.php @@ -0,0 +1,19 @@ + $attachments + */ + public function __construct( + public readonly string $message, + public readonly array $attachments, + ) {} +} diff --git a/src/Dto/FormData/UploadFile.php b/src/Dto/FormData/UploadFile.php new file mode 100644 index 0000000..e4e6b3f --- /dev/null +++ b/src/Dto/FormData/UploadFile.php @@ -0,0 +1,18 @@ + $data Default values of form fields that should be prefilled + * @param array{ + * submit?: string, + * } $buttons + * @param array|null $messages + * @param array>|null $processors + */ + public function __construct( + public readonly array $schema, + public readonly Element $uischema, + public readonly ?array $data, + public readonly array $buttons, + public readonly ?array $messages, + public readonly string $lang, + public readonly string $component, + #[Ignore] + public readonly ?array $processors, + ) {} +} diff --git a/src/Dto/FormSubmission.php b/src/Dto/FormSubmission.php new file mode 100644 index 0000000..6264fdd --- /dev/null +++ b/src/Dto/FormSubmission.php @@ -0,0 +1,21 @@ + $htmlLabel + * @param array $options + */ + public function __construct( + public array $htmlLabel = [], + public readonly array $options = [], + ) { + parent::__construct(Type::ANNOTATION); + } +} diff --git a/src/Dto/UISchema/Control.php b/src/Dto/UISchema/Control.php new file mode 100644 index 0000000..974a0fc --- /dev/null +++ b/src/Dto/UISchema/Control.php @@ -0,0 +1,28 @@ +|null $htmlLabel CMS specific property + * @param array $options https://jsonforms.io/docs/uischema/controls#options + */ + public function __construct( + public string $scope, + public string|bool|null $label = null, + public ?array $htmlLabel = null, // custom property + public readonly array $options = [], + ) { + parent::__construct(Type::CONTROL); + if ( + !preg_match('/^#(?:\/[^\/"]+)+$/', $this->scope) + ) { + throw new \InvalidArgumentException('Invalid scope: ' . $this->scope); + } + } +} diff --git a/src/Dto/UISchema/Element.php b/src/Dto/UISchema/Element.php new file mode 100644 index 0000000..cdb9b6d --- /dev/null +++ b/src/Dto/UISchema/Element.php @@ -0,0 +1,27 @@ + Annotation::class, + 'Control' => Control::class, + 'Group' => Layout::class, + 'HorizontalLayout' => Layout::class, + 'VerticalLayout' => Layout::class, + 'Categorization' => Layout::class, + 'Category' => Layout::class, +])] +abstract class Element +{ + public function __construct( + public readonly Type $type, + public ?Role $rule = null, + ) {} +} diff --git a/src/Dto/UISchema/Layout.php b/src/Dto/UISchema/Layout.php new file mode 100644 index 0000000..efbf9da --- /dev/null +++ b/src/Dto/UISchema/Layout.php @@ -0,0 +1,30 @@ + */ + public array $elements; + + /** + * @param Type $type + * @param array $elements + * @param string|bool|null $label + * @param array $options + */ + public function __construct( + Type $type, + array $elements = [], + public string|bool|null $label = null, + public array $options = [], + ) { + parent::__construct($type); + $this->elements = $elements; + } +} diff --git a/src/Dto/UISchema/Role.php b/src/Dto/UISchema/Role.php new file mode 100644 index 0000000..7af00e4 --- /dev/null +++ b/src/Dto/UISchema/Role.php @@ -0,0 +1,11 @@ +, + * to: non-empty-array, + * cc?: array, + * bcc?: array, + * subject?: string, + * format?: 'html'|'text', + * showEmpty?: bool, + * attachCsv?: bool, + * } $options + * @throws TransportExceptionInterface + * @throws Exception + */ + public function process(FormSubmission $submission, array $options): FormSubmission + { + $rendererModel = $this->modelFactory->create($submission, $options['showEmpty'] ?? false); + $htmlResult = $this->htmlMessageRenderer->render('html', $rendererModel); + $html = $htmlResult->message; + + $textResult = $this->htmlMessageRenderer->render('text', $rendererModel); + $text = $textResult->message; + + $selectionKey = $this->findDelivererSelectionKey($rendererModel); + if ($selectionKey !== null && isset($options['selectable'][$selectionKey]['to'])) { + $options['to'] = $options['selectable'][$selectionKey]['to']; + } + + $email = new Email(); + foreach ($options['from'] as $from) { + $email->addFrom(new Address($from['address'], $from['name'] ?? '')); + } + foreach ($options['to'] as $to) { + $email->addTo(new Address($to['address'], $to['name'] ?? '')); + } + foreach ($options['cc'] ?? [] as $cc) { + $email->addCc(new Address($cc['address'], $cc['name'] ?? '')); + } + foreach ($options['bcc'] ?? [] as $bcc) { + $email->addBcc(new Address($bcc['address'], $bcc['name'] ?? '')); + } + + $email->subject($options['subject'] ?? $htmlResult->subject ?? ''); + + if (($options['format'] ?? 'html') === 'html') { + $email ->html($html); + } + $email->text($text); + + foreach ($htmlResult->attachments as $attachment) { + $email->attach($attachment['data'], $attachment['filename'], $attachment['contentType']); + } + + if ($options['attachCsv'] ?? false) { + $csvModel = $this->modelFactory->create($submission, true); + $csv = $this->csvGenerator->generate($csvModel); + $email->attach($csv, 'data.csv', 'text/csv'); + } + + $this->mailer->send($email); + + return $submission; + } + + private function findDelivererSelectionKey(array $model): ?string + { + foreach ($model as $item) { + if (!is_array($item)) { + continue; + } + if (isset($item['deliverer'])) { + return $item['deliverer']; + } + if (isset($item['items']) && is_array($item['items'])) { + $result = $this->findDelivererSelectionKey($item['items']); + if ($result !== null) { + return $result; + } + } else { + $result = $this->findDelivererSelectionKey($item); + if ($result !== null) { + return $result; + } + } + } + + return null; + } +} diff --git a/src/Processor/IpAllower.php b/src/Processor/IpAllower.php new file mode 100644 index 0000000..c5f646d --- /dev/null +++ b/src/Processor/IpAllower.php @@ -0,0 +1,32 @@ + $allowedIps + */ + public function __construct( + #[Autowire(param: 'atoolo_form.processor.ip_allower.allowed_ips')] + private readonly array $allowedIps, + ) {} + + /** + * @param array $options + */ + public function process(FormSubmission $submission, array $options): FormSubmission + { + if (in_array($submission->remoteAddress, $this->allowedIps, true)) { + $submission->approved = true; + } + return $submission; + } +} diff --git a/src/Processor/IpBlocker.php b/src/Processor/IpBlocker.php new file mode 100644 index 0000000..54aa772 --- /dev/null +++ b/src/Processor/IpBlocker.php @@ -0,0 +1,38 @@ + $blockedIps + */ + public function __construct( + #[Autowire(param: 'atoolo_form.processor.ip_blocker.blocked_ips')] + private readonly array $blockedIps, + ) {} + + /** + * @param array $options + */ + public function process(FormSubmission $submission, array $options): FormSubmission + { + if ($submission->approved) { + return $submission; + } + + if (in_array($submission->remoteAddress, $this->blockedIps, true)) { + throw new AccessDeniedException(); + } + + return $submission; + } +} diff --git a/src/Processor/IpLimiter.php b/src/Processor/IpLimiter.php new file mode 100644 index 0000000..d613fb0 --- /dev/null +++ b/src/Processor/IpLimiter.php @@ -0,0 +1,33 @@ + $options + */ + public function process(FormSubmission $submission, array $options): FormSubmission + { + if ($submission->approved) { + return $submission; + } + + $limiter = $this->formSubmitByIpLimiter->create($submission->remoteAddress); + if (false === $limiter->consume(1)->isAccepted()) { + throw new LimitExceededException(); + } + + return $submission; + } +} diff --git a/src/Processor/JsonSchemaValidator.php b/src/Processor/JsonSchemaValidator.php new file mode 100644 index 0000000..2c3d07b --- /dev/null +++ b/src/Processor/JsonSchemaValidator.php @@ -0,0 +1,27 @@ + $options + * @throws ValidationFailedException + * @throws JsonException + */ + public function process(FormSubmission $submission, array $options): FormSubmission + { + $this->validator->validate($submission->formDefinition->schema, $submission->data); + return $submission; + } +} diff --git a/src/Processor/SpamDetector.php b/src/Processor/SpamDetector.php new file mode 100644 index 0000000..a3b8a73 --- /dev/null +++ b/src/Processor/SpamDetector.php @@ -0,0 +1,27 @@ + $options + */ + public function process(FormSubmission $submission, array $options): FormSubmission + { + if ($submission->approved) { + return $submission; + } + + return $submission; + } +} diff --git a/src/Processor/SubmitLimiter.php b/src/Processor/SubmitLimiter.php new file mode 100644 index 0000000..82c9ef4 --- /dev/null +++ b/src/Processor/SubmitLimiter.php @@ -0,0 +1,33 @@ + $options + */ + public function process(FormSubmission $submission, array $options): FormSubmission + { + if ($submission->approved) { + return $submission; + } + + $limiter = $this->formSubmitTotalLimiter->create(); + if (false === $limiter->consume(1)->isAccepted()) { + throw new LimitExceededException(); + } + + return $submission; + } +} diff --git a/src/Processor/SubmitProcessor.php b/src/Processor/SubmitProcessor.php new file mode 100644 index 0000000..077cb9a --- /dev/null +++ b/src/Processor/SubmitProcessor.php @@ -0,0 +1,17 @@ + $options + */ + public function process(FormSubmission $submission, array $options): FormSubmission; +} diff --git a/src/Service/DataUrlParser.php b/src/Service/DataUrlParser.php new file mode 100644 index 0000000..8fa69d8 --- /dev/null +++ b/src/Service/DataUrlParser.php @@ -0,0 +1,45 @@ +, + * } $model + * @throws CannotInsertRecord + * @throws Exception + */ + public function generate(array $model): string + { + $csv = Writer::createFromString(); + $csv->insertOne($this->collect($model['items'] ?? [], 'label')); + $csv->insertOne($this->collect($model['items'] ?? [], 'value')); + return $csv->toString(); + } + + /** + * @param array $items + * @return array + */ + private function collect(array $items, string $field): array + { + $data = []; + foreach ($items as $item) { + if ($item['layout'] ?? false) { + /** @var EmailMessageModelLayoutItem $item */ + $data[] = $this->collect($item['items'] ?? [], $field); + continue; + } + /** @var array> $item */ + $value = $item[$field] ?? ''; + if (is_array($value)) { + $value = implode(', ', $value); + } + $data[] = [$value]; + } + + return array_merge([], ...$data); + } +} diff --git a/src/Service/Email/EmailMessageModelFactory.php b/src/Service/Email/EmailMessageModelFactory.php new file mode 100644 index 0000000..29cc597 --- /dev/null +++ b/src/Service/Email/EmailMessageModelFactory.php @@ -0,0 +1,44 @@ +formDataModelFactory->create( + $submission->formDefinition, + $this->platform->objectToArrayRecursive((array) $submission->data), + $includeEmptyFields, + ); + $dateTime = $this->platform->datetime(); + return [ + 'lang' => $submission->formDefinition->lang, + 'url' => 'https://' . $this->channel->serverName, + 'tenant' => [ 'name' => $this->channel->tenant->name ], + 'host' => $this->channel->serverName, + 'date' => $dateTime, + 'items' => $items, + ]; + } +} diff --git a/src/Service/Email/EmailMessageRenderer.php b/src/Service/Email/EmailMessageRenderer.php new file mode 100644 index 0000000..730d572 --- /dev/null +++ b/src/Service/Email/EmailMessageRenderer.php @@ -0,0 +1,41 @@ + $model + * @return array + */ + protected function findAttachments(array $model): array + { + return array_map(static function ($element) { + return $element['value']; + }, $this->findByType($model, 'file')); + } + + protected function findByType(array $model, string $type): array + { + $results = []; + foreach ($model as $item) { + if (($item['type'] ?? '') === $type) { + $results[] = [$item]; + } elseif (isset($item['items']) && is_array($item['items'])) { + $results[] = $this->findByType($item['items'], $type); + } + } + + return array_merge(...$results); + } +} diff --git a/src/Service/Email/EmailMessageTwigMjmlRenderer.php b/src/Service/Email/EmailMessageTwigMjmlRenderer.php new file mode 100644 index 0000000..7631283 --- /dev/null +++ b/src/Service/Email/EmailMessageTwigMjmlRenderer.php @@ -0,0 +1,34 @@ +twig->render('@AtooloForm/email.mjml.' . $format . '.twig', $model); + return new EmailHtmlMessageRendererResult( + message: $this->mjmlRenderer->render($mjml), + attachments: $this->findAttachments($model['items']), + ); + } +} diff --git a/src/Service/Email/EmailMessageTwigRenderer.php b/src/Service/Email/EmailMessageTwigRenderer.php new file mode 100644 index 0000000..59e5280 --- /dev/null +++ b/src/Service/Email/EmailMessageTwigRenderer.php @@ -0,0 +1,34 @@ +twig->render('@AtooloForm/email.' . $format . '.twig', $model); + + return new EmailHtmlMessageRendererResult( + message: $html, + attachments: $this->findAttachments($model['items']), + ); + } +} diff --git a/src/Service/Email/MjmlRenderer.php b/src/Service/Email/MjmlRenderer.php new file mode 100644 index 0000000..1dd7cd2 --- /dev/null +++ b/src/Service/Email/MjmlRenderer.php @@ -0,0 +1,18 @@ + + */ +#[AutoconfigureTag('phpro.api_problem.exception_transformer')] +class ExceptionTransformer implements ExceptionTransformerInterface +{ + public function transform(Throwable $exception): ApiProblemInterface + { + if ($exception instanceof ValidationFailedException) { + return new ValidationApiProblem($exception->getViolations()); + } + + if ($exception instanceof LimitExceededException) { + return new HttpApiProblem(Response::HTTP_TOO_MANY_REQUESTS, [ + 'detail' => 'The limit has been reached. The request can be repeated at a later time', + ]); + } + + if ($exception instanceof AccessDeniedException) { + return new HttpApiProblem(Response::HTTP_FORBIDDEN, [ + 'detail' => 'Access was denied', + ]); + } + + if ($exception instanceof SpamDetectedException) { + return new HttpApiProblem(Response::HTTP_UNPROCESSABLE_ENTITY, [ + 'detail' => 'Spam detected', + ]); + } + + + throw new \LogicException('Unaccepted exception ' . get_class($exception)); + } + + public function accepts(Throwable $exception): bool + { + return $exception instanceof ValidationFailedException + || $exception instanceof LimitExceededException + || $exception instanceof AccessDeniedException + || $exception instanceof SpamDetectedException; + } +} diff --git a/src/Service/FormDataModelFactory.php b/src/Service/FormDataModelFactory.php new file mode 100644 index 0000000..6f371fe --- /dev/null +++ b/src/Service/FormDataModelFactory.php @@ -0,0 +1,199 @@ + + */ + private array $items = []; + + /** + * @var array> + */ + private array $stack = []; + + private bool $includeEmptyFields = false; + + public function __construct( + private readonly DataUrlParser $dataUrlParser, + ) {} + + /** + * @param array $data + * @return array + */ + public function create(FormDefinition $definition, array $data, bool $includeEmptyFields): array + { + $this->stack = []; + $this->items = []; + $this->includeEmptyFields = $includeEmptyFields; + $reader = new FormReader($definition, $data, $this); + $reader->read(); + + return $this->items; + } + + public function startLayout(Layout $layout): void + { + $data = [ + 'type' => strtolower($layout->type->name), + 'layout' => true, + ]; + if (!empty($layout->label) && ($layout->options['hideLabel'] ?? false) === false) { + $data['label'] = $layout->label; + } + + $this->stack[] = $this->items; + $this->stack[] = $data; + $this->items = []; + } + + public function endLayout(Layout $layout): void + { + /** @var EmailMessageModelItem $data */ + $data = array_pop($this->stack); + $data['items'] = $this->items; + /** @var array $item */ + $item = array_pop($this->stack); + $this->items = $item; + $this->items[] = $data; + } + + public function control( + Control $control, + array $schema, + string $name, + mixed $value, + ): void { + if ($this->isEmptyValue($value)) { + if (!$this->includeEmptyFields) { + return; + } + } + + $type = $this->identifyType($control, $schema); + if ($type === 'file' && !empty($value)) { + /** @var string $value */ + $uploadFile = $this->dataUrlParser->parse($value); + /** @var EmailMessageModelFileUpload $value */ + $value = get_object_vars($uploadFile); + } + + $options = null; + $deliverer = null; + + $optionsFromSchema = $schema['items']['oneOf'] ?? $schema['oneOf'] ?? null; + if ($optionsFromSchema !== null) { + $selected = is_array($value) ? $value : [$value]; + $value = []; + $options = []; + foreach ($optionsFromSchema as $option) { + $isSelected = in_array($option['const'], $selected, true); + $label = $option['title']; + $options[] = [ + 'label' => $label, + 'value' => $option['const'], + 'selected' => $isSelected, + ]; + if ($isSelected) { + $value[] = $label; + if (($schema['deliverer'] ?? false) === true) { + $deliverer = $option['const']; + } + } + } + if (($schema['type'] ?? '') === 'string') { + $value = $value[0] ?? ''; + } + } + + $item = [ + 'type' => $type, + 'name' => $name, + ]; + if (!empty($control->label)) { + $item['label'] = $control->label; + } + if (!empty($control->htmlLabel)) { + $item['htmlLabel'] = $control->htmlLabel; + } + if (!$this->isEmptyValue($value)) { + $item['value'] = $value; + } + if (!empty($options)) { + $item['options'] = $options; + } + if (!empty($deliverer)) { + $item['deliverer'] = $deliverer; + } + + $this->items[] = $item; + } + + private function isEmptyValue(mixed $value): bool + { + if ($value === null) { + return true; + } + if ($value === '') { + return true; + } + if (is_array($value) && empty($value)) { + return true; + } + return false; + } + + /** + * @param JsonSchema $schema + * @see https://sitepark.github.io/atoolo-docs/develop/form/controls/#json-schema + */ + private function identifyType(Control $control, array $schema): string + { + + $type = $schema['type'] ?? ''; + $format = $schema['format'] ?? ''; + + if ($type === 'string' && $format === 'data-url') { + return 'file'; + } + + if ($type === 'string' && $format === 'html') { + return 'html'; + } + + if ($type === 'string' && ($format === 'date' || $format === 'time' || $format === 'date-time')) { + return $format; + } + + if ($type === 'boolean') { + return 'checkbox'; + } + + if ($type === 'array' && isset($schema['items']['oneOf'])) { + return 'checkbox-group'; + } + + if ( + $type === 'string' + && isset($schema['oneOf']) + && ($control->options['format'] ?? '') === 'radio') { + return 'radio-buttons'; + } + + if ($type === 'string' && isset($schema['oneOf']) + ) { + return 'select'; + } + + return 'text'; + } +} diff --git a/src/Service/FormDefinitionLoader.php b/src/Service/FormDefinitionLoader.php new file mode 100644 index 0000000..7864587 --- /dev/null +++ b/src/Service/FormDefinitionLoader.php @@ -0,0 +1,260 @@ +, + * to?: array, + * cc?: array, + * bcc?: array, + * selectable?: array{ + * to?: array + * }, + * subject?: string, + * format?: string, + * attachCsv?: bool, + * showEmpty?: bool + * } + * @phpstan-type FormEditorModel = array{ + * jsonForms?: array{ + * schema?: JsonSchema, + * uischema?: array + * }, + * bottomBar?: array{ + * items?: array, + * }, + * messages?: array, + * deliverer?: DelivererModel, + * } + * @phpstan-type FormEditorComponent = array{ + * id: string, + * type: string, + * model?: FormEditorModel, + * items?: array, + * } + * @phpstan-type DelivererConfig = array{ + * from: array, + * to: array, + * cc: array, + * bcc: array, + * subject: string, + * format: string, + * attachCsv: bool, + * showEmpty: bool + * selectable: array, + * } + */ +class FormDefinitionLoader +{ + public function __construct( + #[Autowire(service: 'atoolo_resource.resource_loader')] + private readonly ResourceLoader $resourceLoader, + private readonly LabelTranslator $translator, + ) {} + + public function loadFromResource(ResourceLocation $location, string $component): FormDefinition + { + $resource = $this->resourceLoader->load($location); + + /** @var array $items */ + $items = $resource->data->getArray('content.items'); + $componentConfig = $this->findFormEditorComponent($items, $component); + + if (empty($componentConfig)) { + throw new FormNotFoundException('Component \'' . $component . '\' not found'); + } + + /** @var FormEditorModel $model */ + $model = $componentConfig['model'] ?? []; + return $this->loadFromModel($resource->lang->code, $component, $model); + } + + /** + * @param string $component + * @param FormEditorModel $model + * @return FormDefinition + */ + public function loadFromModel(string $lang, string $component, array $model): FormDefinition + { + if (!isset($model['jsonForms'])) { + throw new InvalidFormConfiguration('Missing jsonForms definition in component \'' . $component . '\''); + } + + $jsonForms = $model['jsonForms']; + + if (!isset($jsonForms['schema'])) { + throw new InvalidFormConfiguration('Missing jsonForms.schema definition in component \'' . $component . '\''); + } + if (!isset($jsonForms['uischema'])) { + throw new InvalidFormConfiguration('Missing jsonForms.uischema definition in component \'' . $component . '\''); + } + + /** @var array{submit:string} $buttons */ + $buttons = []; + foreach ($model['bottomBar']['items'] ?? [] as $button) { + $buttons[$button['value']] = $button['label']; + } + + $messages = $model['messages'] ?? []; + + if (!isset($model['deliverer']['modelType'])) { + throw new InvalidFormConfiguration('Missing deliverer definition in component \'' . $component . '\''); + } + + if ($model['deliverer']['modelType'] !== 'content.form.deliverer.email') { + throw new InvalidFormConfiguration('Unsupported deliverer \'' . $model['deliverer']['modelType'] . '\' in component \'' . $component . '\''); + } + + $deliverer = $model['deliverer']; + $processor = [ + 'email-sender' => $this->transformProcessorConfig($deliverer), + ]; + + /** @var JsonSchema $schema */ + $schema = $this->translator->translate($jsonForms['schema']); + $uiSchema = $this->translator->translate($jsonForms['uischema']); + + return new FormDefinition( + schema: $schema, + uischema: $this->deserializeUiSchema($uiSchema), + data: null, + buttons: $buttons, + messages: $messages, + lang: $lang, + component: $component, + processors: $processor, + ); + } + + /** + * @param DelivererModel $deliverer + * @return DelivererConfig + */ + private function transformProcessorConfig(array $deliverer): array + { + $from = []; + foreach ($deliverer['from'] ?? [] as $address => $name) { + $from[] = ['address' => $address, 'name' => $name]; + } + + $to = []; + foreach ($deliverer['to'] ?? [] as $address => $name) { + $to[] = ['address' => $address, 'name' => $name]; + } + + $cc = []; + foreach ($deliverer['cc'] ?? [] as $address => $name) { + $cc[] = ['address' => $address, 'name' => $name]; + } + + $bcc = []; + foreach ($deliverer['bcc'] ?? [] as $address => $name) { + $bcc[] = ['address' => $address, 'name' => $name]; + } + + $selectable = []; + foreach ($deliverer['selectable'] ?? [] as $key => $config) { + foreach ($config['to'] as $address => $name) { + $selectable[$key]['to'][] = ['address' => $address, 'name' => $name]; + } + } + + return [ + 'from' => $from, + 'to' => $to, + 'cc' => $cc, + 'bcc' => $bcc, + 'subject' => $deliverer['subject'] ?? '', + 'format' => $deliverer['format'] ?? 'html', + 'attachCsv' => $deliverer['attachCsv'] ?? false, + 'showEmpty' => $deliverer['showEmpty'] ?? false, + 'selectable' => $selectable, + ]; + } + + + /** + * @param array $data + * @return Layout + */ + private function deserializeUiSchema(array $data): Layout + { + $classMetadataFactory = new ClassMetadataFactory(new AttributeLoader()); + $discriminator = new ClassDiscriminatorFromClassMetadata($classMetadataFactory); + + $encoders = [new JsonEncoder()]; + $normalizers = [ new ArrayDenormalizer(), new BackedEnumNormalizer(), new ObjectNormalizer( + classMetadataFactory: $classMetadataFactory, + propertyTypeExtractor: new PhpDocExtractor(), + classDiscriminatorResolver: $discriminator, + )]; + /** @var Layout $layout */ + $layout = (new Serializer($normalizers, $encoders))->denormalize($data, Layout::class); + return $layout; + } + + /** + * @param array $items + * @param string $component + * @return FormEditorComponent|array + */ + private function findFormEditorComponent(array $items, string $component): array + { + foreach ($items as $item) { + if ($item['type'] === 'formContainer' && $item['id'] === $component) { + return $item; + } + /** @var array $children */ + $children = $item['items'] ?? []; + $result = $this->findFormEditorComponent($children, $component); + if ($result) { + return $result; + } + } + return []; + } +} diff --git a/src/Service/FormReader.php b/src/Service/FormReader.php new file mode 100644 index 0000000..1adac13 --- /dev/null +++ b/src/Service/FormReader.php @@ -0,0 +1,100 @@ + $data + */ + public function __construct( + public readonly FormDefinition $formDefinition, + public readonly array $data, + public readonly FromReaderHandler $handler, + ) {} + + public function read(): void + { + $this->readElement($this->formDefinition->uischema); + } + + private function readElement(Element $element): void + { + if ($element instanceof Control) { + $this->readControl($element); + } elseif ($element instanceof Layout) { + $this->readLayout($element); + } + } + + private function readControl(Control $control): void + { + /** + * @var JsonSchema|null $schema + * @var string $name + * @var array $data + */ + [$schema, $name, $data] = $this->getValue($control->scope); + if ($schema === null) { + return; + } + $this->handler->control($control, $schema, $name, $data); + } + + private function readLayout(Layout $layout): void + { + $this->handler->startLayout($layout); + foreach ($layout->elements as $element) { + $this->readElement($element); + } + $this->handler->endLayout($layout); + } + + /** + * @return array|null> + */ + private function getValue(string $scope): array + { + $keys = explode('/', ltrim($scope, '#')); + $name = end($keys); + + /** @var array $data */ + $data = $this->data; + + /** @var JsonSchema $schema */ + $schema = $this->formDefinition->schema; + + foreach ($keys as $key) { + + if (empty($key)) { + continue; + } + + if ($schema !== null && isset($schema[$key])) { + $schema = $schema[$key]; + } else { + $schema = null; + } + + if ($key === 'properties') { + continue; + } + if (isset($data[$key])) { + /** @var array $data */ + $data = $data[$key]; + } else { + $data = null; + break; + } + } + + return [$schema, $name, $data]; + } +} diff --git a/src/Service/FromReaderHandler.php b/src/Service/FromReaderHandler.php new file mode 100644 index 0000000..a75d890 --- /dev/null +++ b/src/Service/FromReaderHandler.php @@ -0,0 +1,20 @@ + $constraints + */ + public function __construct( + #[Autowire('@' . ValidatorExtended::class)] + private readonly Validator $validator, + #[AutowireIterator('atoolo_form.jsonSchemaConstraint')] + iterable $constraints, + private readonly Platform $platform, + ) { + foreach ($constraints as $constraint) { + $this->registerConstraint($constraint); + } + } + + private function registerConstraint(Constraint $constraint): void + { + if ($constraint instanceof FormatConstraint) { + $this->registerFormatConstraint($constraint); + } else { + throw new InvalidArgumentException('Unknown constraint type ' . get_class($constraint)); + } + } + + private function registerFormatConstraint(FormatConstraint $constraint): void + { + $formatResolver = $this->validator->parser()->getFormatResolver(); + if ($formatResolver === null) { + throw new LogicException('No format resolver found'); + } + + $type = $constraint->getType(); + $name = $constraint->getName(); + + $formatResolver->registerCallable( + $type, + $name, + function ($data, $schema) use ($constraint) { + return $constraint->check($data, $schema); + }, + ); + } + + + /** + * @param JsonSchema $schema + * @throws JsonException + */ + public function validate(array $schema, object $data): void + { + $schemaJson = $this->platform->arrayToObjectRecursive($schema); + + $result = $this->validator->validate($data, $schemaJson); + + if (!$result->isValid() && $result->error() !== null) { + throw $this->errorsToValidationFailedException($data, $result->error()); + } + } + + private function errorsToValidationFailedException(object $data, ValidationError $validationError): ValidationFailedException + { + $list = new ConstraintViolationList(); + $formatter = new ErrorFormatter(); + $errors = $formatter->format($validationError, false, function (ValidationError $error) use ($formatter) { + $schema = $error->schema()->info(); + + $path = $schema->path(); + $args = $error->args(); + if (isset($args['missing'][0])) { + $path[] = $args['missing'][0]; + } + + return [ + 'message' => $formatter->formatErrorMessage($error), + 'path' => implode('/', $path), + 'args' => $error->args(), + 'constraint' => $error->keyword(), + ]; + }); + foreach ($errors as $error) { + $v = new ConstraintViolation( + $error['message'], + null, + $error['args'], + null, + $error['path'], + '', + null, + null, + $error['constraint'] === 'require' ? new NotBlank() : null, + ); + $list->add($v); + } + throw new ValidationFailedException($data, $list); + } +} diff --git a/src/Service/JsonSchemaValidator/Constraint.php b/src/Service/JsonSchemaValidator/Constraint.php new file mode 100644 index 0000000..299e9b4 --- /dev/null +++ b/src/Service/JsonSchemaValidator/Constraint.php @@ -0,0 +1,10 @@ +dataUrlParser->parse($value); + + if (isset($schema->maxFileSize) && $uploadFile->size > $schema->maxFileSize) { + throw new CustomError( + 'File size (' . $uploadFile->size . ' bytes) exceeds maximum allowed size (' . $schema->maxFileSize . ' bytes)', + ['maxFileSize' => $schema->maxFileSize], + ); + } + if (isset($schema->minFileSize) && $uploadFile->size < $schema->minFileSize) { + throw new CustomError( + 'File size (' . $uploadFile->size . ' bytes) is less than minimum allowed size (' . $schema->minFileSize . ' bytes)', + ['minFileSize' => $schema->minFileSize], + ); + } + if (isset($schema->acceptedContentTypes)) { + $fileInfo = new finfo(FILEINFO_MIME_TYPE); + $mimeType = $fileInfo->buffer($uploadFile->data) ?: 'application/octet-stream'; + if (!$this->match($schema->acceptedContentTypes, $mimeType)) { + throw new CustomError( + 'File content type (' . $mimeType . ') is not in the list of accepted content types (' . implode(', ', $schema->acceptedContentTypes) . ')', + ['acceptedContentTypes' => $schema->acceptedContentTypes], + ); + } + } + if (isset($schema->acceptedFileNames)) { + if (!$this->match($schema->acceptedFileNames, $uploadFile->filename)) { + throw new CustomError( + 'Filename (' . $uploadFile->filename . ') is not in the list of accepted file names (' . implode(', ', $schema->acceptedFileNames) . ')', + ['acceptedFileNames' => $schema->acceptedFileNames], + ); + } + } + + return true; + } + + /** + * @param array $patterns Array of strings that may also contain wildcards such as * and ? + * @param string $subject + * @return bool + */ + private function match(array $patterns, string $subject): bool + { + foreach ($patterns as $pattern) { + if (fnmatch($pattern, $subject)) { + return true; + } + } + return false; + } + +} diff --git a/src/Service/JsonSchemaValidator/Extended/Draft202012Extended.php b/src/Service/JsonSchemaValidator/Extended/Draft202012Extended.php new file mode 100644 index 0000000..f3c1161 --- /dev/null +++ b/src/Service/JsonSchemaValidator/Extended/Draft202012Extended.php @@ -0,0 +1,32 @@ +name = $name; + $this->types = $types; + } + + /** + * @inheritDoc + */ + public function validate(ValidationContext $context, Schema $schema): ?ValidationError + { + $type = $context->currentDataType(); + + if (!isset($this->types[$type])) { + return null; + } + + $format = $this->types[$type]; + + try { + if ($format instanceof Format) { + $ok = $format->validate($context->currentData()); + } else { + // modified line + $ok = $format($context->currentData(), $schema->info()->data()); + } + } catch (CustomError $error) { + return $this->error($schema, $context, 'format', $error->getMessage(), $error->getArgs() + [ + 'format' => $this->name, + 'type' => $type, + ]); + } + + if ($ok) { + return null; + } + + return $this->error($schema, $context, 'format', "The data must match the '{format}' format", [ + 'format' => $this->name, + 'type' => $type, + ]); + } +} diff --git a/src/Service/JsonSchemaValidator/Extended/FormatKeywordParserExtended.php b/src/Service/JsonSchemaValidator/Extended/FormatKeywordParserExtended.php new file mode 100644 index 0000000..242c941 --- /dev/null +++ b/src/Service/JsonSchemaValidator/Extended/FormatKeywordParserExtended.php @@ -0,0 +1,67 @@ +data(); + + $resolver = $parser->getFormatResolver(); + + if (!$resolver || !$parser->option('allowFormats') || !$this->keywordExists($schema)) { + return null; + } + + $value = $this->keywordValue($schema); + + if ($this->isDataKeywordAllowed($parser, $this->keyword)) { + if ($pointer = $this->getDataKeywordPointer($value)) { + return new FormatDataKeyword($pointer, $resolver); + } + } + + if (!is_string($value)) { + throw $this->keywordException("{keyword} must be a string", $info); + } + + $list = $resolver->resolveAll($value); + + if (!$list) { + return null; + } + + // modified line + return new FormatKeywordExtended($value, $this->resolveSubTypes($list)); + } +} diff --git a/src/Service/JsonSchemaValidator/Extended/ValidatorExtended.php b/src/Service/JsonSchemaValidator/Extended/ValidatorExtended.php new file mode 100644 index 0000000..1488b2a --- /dev/null +++ b/src/Service/JsonSchemaValidator/Extended/ValidatorExtended.php @@ -0,0 +1,22 @@ +parser()->addDraft($draft); + $this->parser()->setDefaultDraftVersion($draft->version()); + } +} diff --git a/src/Service/JsonSchemaValidator/FormatConstraint.php b/src/Service/JsonSchemaValidator/FormatConstraint.php new file mode 100644 index 0000000..3c6ce65 --- /dev/null +++ b/src/Service/JsonSchemaValidator/FormatConstraint.php @@ -0,0 +1,29 @@ +allowedElements)) { + $stripped = strip_tags($value, $schema->allowedElements); + if ($stripped !== $value) { + throw new CustomError( + 'HTML contains disallowed elements (allowedElemnets: ' . implode(',', $schema->allowedElements) . ')', + ['allowedElements' => $schema->allowedElements], + ); + } + } + return true; + } + +} diff --git a/src/Service/JsonSchemaValidator/PhoneConstraint.php b/src/Service/JsonSchemaValidator/PhoneConstraint.php new file mode 100644 index 0000000..a96c0d2 --- /dev/null +++ b/src/Service/JsonSchemaValidator/PhoneConstraint.php @@ -0,0 +1,26 @@ + $data + * @return array + */ + public function translate(array &$data): array + { + foreach ($data as $key => $value) { + if (is_array($value)) { + $this->translate($data[$key]); + } elseif (is_string($value)) { + $data[$key] = $this->translateLabel($value); + } + } + return $data; + } + + public function translateLabel(?string $label): ?string + { + if ($label === null) { + return null; + } + + preg_match('/\$\{([^}]+)}/', $label, $matches); + if ($matches) { + $key = $matches[1] ?? ''; + $translated = $this->translator->trans($key, domain: 'form'); + return $translated === '' ? $label : $translated; + } + + return $label; + } +} diff --git a/src/Service/Platform.php b/src/Service/Platform.php new file mode 100644 index 0000000..f7da1a6 --- /dev/null +++ b/src/Service/Platform.php @@ -0,0 +1,50 @@ +|object $array + * @return array|array $array + */ + public function objectToArrayRecursive(mixed $array): array + { + if (is_array($array)) { + foreach ($array as $key => $value) { + if (is_array($value)) { + $array[$key] = $this->objectToArrayRecursive($value); + } + if ($value instanceof stdClass) { + $array[$key] = $this->objectToArrayRecursive((array) $value); + } + } + } + if ($array instanceof stdClass) { + return $this->objectToArrayRecursive((array) $array); + } + /** @var array|array $array */ + return $array; + } + + /** + * @param array|array $array + * @throws \JsonException + */ + public function arrayToObjectRecursive(array $array): object + { + $json = json_encode($array, JSON_THROW_ON_ERROR); + return (object) json_decode($json, false, 512, JSON_THROW_ON_ERROR); + } + +} diff --git a/src/Service/SubmitHandler.php b/src/Service/SubmitHandler.php new file mode 100644 index 0000000..4348dec --- /dev/null +++ b/src/Service/SubmitHandler.php @@ -0,0 +1,68 @@ + + */ + private readonly array $processors; + + + /** + * @param iterable $processors + * @param array> $defaultProcessorKeys + */ + public function __construct( + #[AutowireIterator('atoolo_form.processor', indexAttribute: 'key')] + iterable $processors, + #[Autowire(param: 'atoolo_form.default_processors')] + private readonly array $defaultProcessorKeys, + ) { + $this->processors = $processors instanceof \Traversable ? + iterator_to_array($processors) : + $processors; + } + + public function handle(FormSubmission $submit): void + { + $processorsOptions = $this->getResultingOptions($submit->formDefinition->processors ?? []); + + foreach ($this->processors as $key => $processor) { + + if (!isset($processorsOptions[$key])) { + continue; + } + + $options = $processorsOptions[$key]; + + $submit = $processor->process($submit, $options); + } + } + + /** + * @param array> $processors + * @return array> + */ + private function getResultingOptions(array $processors): array + { + $resultingProcessors = []; + + foreach ($this->defaultProcessorKeys as $key => $options) { + $resultingProcessors[$key] = $options ?? []; + } + foreach ($processors as $key => $options) { + $resultingProcessors[$key] = array_merge($resultingProcessors[$key] ?? [], $options); + } + + return $resultingProcessors; + } +} diff --git a/templates/email.html.styles.css b/templates/email.html.styles.css new file mode 100644 index 0000000..82563cc --- /dev/null +++ b/templates/email.html.styles.css @@ -0,0 +1,74 @@ +body { + font-family: Arial, sans-serif; + color: #333; + margin: 0; + padding: 0; + background-color: #f9f9f9; +} +.container { + width: 100%; + max-width: 600px; + margin: 20px auto; + background-color: #ffffff; + border: 1px solid #ddd; + border-radius: 4px; + overflow: hidden; +} +.header, .footer { + background-color: #f3f3f3; + padding: 15px 20px; + text-align: center; + color: #666; +} +.header a { + color: #0066cc; + text-decoration: none; +} +.content { + padding: 20px; +} +.header .title { + font-size: 16px; + font-weight: bold; +} +.section { + margin-bottom: 15px; + padding-left: 15px; + border-left: 2px solid #eee; +} +.section .section { + margin-top: 10px; + border-left: 2px solid #ddd; +} +.field { + margin-bottom: 5px; +} +.field-label { + display: block; + font-weight: bold; + color: #333; +} +.field-value { + margin-left: 10px; + color: #666; +} +.checkbox-group { + margin-top: 5px; + margin-left: 10px; +} +.checkbox-item { + display: flex; + align-items: center; + margin-bottom: 5px; +} +.checkbox-item input[type="checkbox"] { + margin-right: 10px; +} +.checkbox-field { + display: flex; + align-items: center; + margin-bottom: 5px; +} +.checkbox-field input[type="checkbox"] { + margin-right: 10px; +} \ No newline at end of file diff --git a/templates/email.html.summary.twig b/templates/email.html.summary.twig new file mode 100644 index 0000000..839e480 --- /dev/null +++ b/templates/email.html.summary.twig @@ -0,0 +1,89 @@ +
+{% for item in items %} + {% if item.type == 'horizontal_layout' %} + {% if item.items|length > 0 %} + {% if item.label is defined and item.label is not empty %} +
{{ item.label|escape }}
+ {% endif %} + {{ include('@AtooloForm/email.html.summary.twig', {items: item.items}) }} + {% endif %} + {% elseif item.type == 'vertical_layout' %} + {% if item.items|length > 0 %} + {% if item.label is defined and item.label is not empty %} +
{{ item.label|escape }}
+ {% endif %} + {{ include('@AtooloForm/email.html.summary.twig', {items: item.items}) }} + {% endif %} + {% elseif item.type == 'group' %} + {% if item.items|length > 0 %} + {% if item.label is defined and item.label is not empty %} +
{{ item.label|escape }}
+ {% endif %} + {{ include('@AtooloForm/email.html.summary.twig', {items: item.items}) }} + {% endif %} + {% elseif item.type == 'categorization' %} + {% if item.items|length > 0 %} + {% if item.label is defined and item.label is not empty %} +
{{ item.label|escape }}
+ {% endif %} + {{ include('@AtooloForm/email.html.summary.twig', {items: []}) }} + {% endif %} + {% elseif item.type == 'category' %} + {% if item.label is defined and item.label is not empty %} +
{{ item.label|escape }}
+ {% endif %} + {{ include('@AtooloForm/email.html.summary.twig', {items: item.items}) }} + {% elseif item.type == 'file' %} +
+ {% if item.label is defined and item.label is not empty %} + {{ item.label|escape }} + {% endif %} + {{ item.value.filename|escape }} +
+ {% elseif item.options is defined and item.options is iterable %} +
+ {% if item.label is defined and item.label is not empty %} + {{ item.label|escape }} + {% endif %} +
+ {% for options in item.options %} +
+ +
{{ options.label|escape }}
+
+ {% endfor %} +
+
+ {% elseif item.type == 'checkbox' %} +
+ + {% if item.label is defined and item.label is not empty %} + {{ item.label|escape }} + {% endif %} + {% if item.htmlLabel.text is defined and item.htmlLabel.text is not empty %} + {{ item.htmlLabel.text|raw }} + {% endif %} +
+ {% elseif item.value is defined %} + {% if item.type == 'date' %} + {% set value = item.value|date("m.d.Y") %} + {% elseif item.type == 'time' %} + {% set value = item.value|date("H:i") %} + {% elseif item.type == 'date-time' %} + {% set value = item.value|date("m.d.Y H:i") %} + {% else %} + {% set value = item.value %} + {% endif %} + +
+ {% if item.label is defined and item.label is not empty %} + {{ item.label|escape }} + {% endif %} + {% if item.htmlLabel.text is defined and item.htmlLabel.text is not empty %} + {{ item.htmlLabel.text|raw }} + {% endif %} + {{ value|escape }} +
+ {% endif %} +{% endfor %} +
\ No newline at end of file diff --git a/templates/email.html.twig b/templates/email.html.twig new file mode 100644 index 0000000..f90d314 --- /dev/null +++ b/templates/email.html.twig @@ -0,0 +1,28 @@ + + + + + {{ tenant.name }} – Webform + + + + + +
+
+ {{ 'email.header'|trans({'{url}': url}, 'form')|raw }} +
+ +
+

{{ 'email.headline'|trans({}, 'form') }}

+ {{ include('@AtooloForm/email.html.summary.twig') }} +
+ + +
+ + \ No newline at end of file diff --git a/templates/email.text.summary.twig b/templates/email.text.summary.twig new file mode 100644 index 0000000..b24c33b --- /dev/null +++ b/templates/email.text.summary.twig @@ -0,0 +1,82 @@ +{% for item in items %} +{% if item.type == 'horizontal_layout' %} +{% if item.items|length > 0 %} +{% if item.label is defined and item.label is not empty %} + +{{ item.label }} +{% endif %} +{{ include('@AtooloForm/email.text.summary.twig', {items: item.items}) }} +{% endif %} +{% elseif item.type == 'vertical_layout' %} +{% if item.items|length > 0 %} +{% if item.label is defined and item.label is not empty %} + +{{ item.label }} +{% endif %} +{{ include('@AtooloForm/email.text.summary.twig', {items: item.items}) }} +{% endif %} +{% elseif item.type == 'group' %} +{% if item.items|length > 0 %} +{% if item.label is defined and item.label is not empty %} + +{{ item.label }} +{% endif %} +{{ include('@AtooloForm/email.text.summary.twig', {items: item.items}) }} +{% endif %} +{% elseif item.type == 'categorization' %} +{% if item.items|length > 0 %} +{% if item.label is defined and item.label is not empty %} + +{{ item.label }} +{% endif %} +{{ include('@AtooloForm/email.text.summary.twig', {items: []}) }} +{% endif %} +{% elseif item.type == 'category' %} +{% if item.label is defined and item.label is not empty %} + +{{ item.label }} +{% endif %} +{{ include('@AtooloForm/email.text.summary.twig', {items: item.items}) }} +{% elseif item.type == 'file' %} +{% if item.label is defined and item.label is not empty %} + +{{ item.label }}: +{{ item.value.filename }} +{% endif %} +{% elseif item.options is defined and item.options is iterable %} + +{% if item.label is defined and item.label is not empty %} +{{ item.label }}: +{% endif %} +{% for options in item.options %} +{{ options.selected ? '[x]' : '[ ]' }} {{ options.label }} +{% endfor %} +{% elseif item.type == 'checkbox' %} +{% if item.label is defined and item.label is not empty %} +{{ item.value ? '[x]' : '[ ]' }} {{ item.label }} +{% endif %} +{% if item.htmlLabel.text is defined and item.htmlLabel.text is not empty %} +{{ item.value ? '[x]' : '[ ]' }} {{ item.htmlLabel.text|raw }} +{% endif %} +{% elseif item.value is defined %} +{% if item.type == 'date' %} +{% set value = item.value|date("m.d.Y") %} +{% elseif item.type == 'time' %} +{% set value = item.value|date("H:i") %} +{% elseif item.type == 'date-time' %} +{% set value = item.value|date("m.d.Y H:i") %} +{% else %} +{% set value = item.value %} +{% endif %} +{% if item.label is defined and item.label is not empty %} + +{{ item.label }}: +{{ value }} +{% endif %} +{% if item.htmlLabel.text is defined and item.htmlLabel.text is not empty %} + +{{ item.htmlLabel.text|raw }}: +{{ value }} +{% endif %} +{% endif %} +{% endfor %} \ No newline at end of file diff --git a/templates/email.text.twig b/templates/email.text.twig new file mode 100644 index 0000000..52c2a06 --- /dev/null +++ b/templates/email.text.twig @@ -0,0 +1,8 @@ +{{ 'email.header'|trans({'{url}': url}, 'form')|html_to_markdown }} + +{{ 'email.headline'|trans({}, 'form') }} + +{{ include('@AtooloForm/email.text.summary.twig')|trim }} + +-- +{{ 'email.footer'|trans({'{host}': host, '{date}': date|date('d.m.Y'), '{time}': date|date('H:i:s')}, 'form')|raw }} diff --git a/test/Controller/FormControllerTest.php b/test/Controller/FormControllerTest.php new file mode 100644 index 0000000..604a08f --- /dev/null +++ b/test/Controller/FormControllerTest.php @@ -0,0 +1,303 @@ +channel = $this->createResourceChannel('de_DE', []); + $this->formDefinitionLoader = $this->createMock(FormDefinitionLoader::class); + $this->submitHandler = $this->createMock(SubmitHandler::class); + $this->localeSwitcher = $this->createMock(LocaleSwitcher::class); + + } + + /** + * @throws Exception + */ + private function createController(): FormController + { + $controller = new FormController( + $this->channel, + $this->formDefinitionLoader, + $this->submitHandler, + $this->localeSwitcher, + ); + $controller->setContainer($this->createStub(ContainerInterface::class)); + return $controller; + } + + /** + * @throws Exception + */ + #[DataProvider('resourceLocationOfDefinitionProvider')] + public function testResourceLocationOfDefinitionWithEmptyLang( + string $defaultLang, + array $translationLocales, + string $requestLang, + string $locationLang, + string $locationPath, + ): void { + $this->channel = $this->createResourceChannel($defaultLang, $translationLocales); + $this->formDefinitionLoader->expects($this->once()) + ->method('loadFromResource') + ->with( + ResourceLocation::of( + $locationPath, + ResourceLanguage::of($locationLang), + ), + 'form-1', + ); + $controller = $this->createController(); + $controller->definition($requestLang, 'location', 'form-1'); + } + + + /** + * @throws Exception + */ + public function testDefinitionWithResourceNotFoundException(): void + { + $this->formDefinitionLoader + ->method('loadFromResource') + ->willThrowException(new ResourceNotFoundException(ResourceLocation::of('test'))); + + $controller = $this->createController(); + + $this->expectException(NotFoundHttpException::class); + $controller->definition('', 'location', 'form-1'); + } + /** + * @throws Exception + */ + public function testDefinitionWithFormNotFoundException(): void + { + $this->formDefinitionLoader + ->method('loadFromResource') + ->willThrowException(new FormNotFoundException()); + + $controller = $this->createController(); + + $this->expectException(NotFoundHttpException::class); + $controller->definition('', 'location', 'form-1'); + } + + /** + * @throws Exception + * @throws JsonException + */ + public function testGetDefinition(): void + { + $this->formDefinitionLoader->method('loadFromResource')->willReturn(new FormDefinition( + schema: [], + uischema: new Layout(Type::VERTICAL_LAYOUT, []), + data: null, + buttons: [], + messages: null, + lang: 'en', + component: 'form-1', + processors: [ + 'processora' => ['options' => 'value'], + ], + )); + $controller = $this->createController(); + + $response = $controller->definition('en', 'location', 'form-1'); + $json = [ + "schema" => [], + "uischema" => [ + "elements" => [], + "options" => [], + "type" => "VerticalLayout", + ], + "buttons" => [], + "lang" => "en", + "component" => "form-1", + ]; + $this->assertEquals( + $json, + json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR), + "unexpected response", + ); + } + + /** + * @throws Exception + */ + public function testSubmit(): void + { + $controller = $this->createController(); + + $request = $this->createStub(Request::class); + $request->method('getContentTypeFormat')->willReturn('json'); + $request->method('getContent')->willReturn('{"field-1":"value"}'); + $request->method('getClientIp')->willReturn('127.0.0.1'); + + $response = $controller->submit( + '', + 'location', + 'form-1', + $request, + ); + $this->assertEquals( + '{"status":200}', + $response->getContent(), + "unexpected response", + ); + } + + /** + * @throws Exception + */ + public function testSubmitWithUnsupportedMediaType(): void + { + $controller = $this->createController(); + + $request = $this->createStub(Request::class); + $request->method('getContentTypeFormat')->willReturn('other'); + + $this->expectException(UnsupportedMediaTypeHttpException::class); + $controller->submit( + '', + 'location', + 'form-1', + $request, + ); + } + + /** + * @throws Exception + */ + public function testSubmitWithEmptyRequest(): void + { + + $controller = $this->createController(); + + $request = $this->createStub(Request::class); + $request->method('getContentTypeFormat')->willReturn('json'); + $request->method('getContent')->willReturn(''); + + $this->expectException(\Symfony\Component\HttpFoundation\Exception\JsonException::class); + $controller->submit( + '', + 'location', + 'form-1', + $request, + ); + } + + /** + * @throws Exception + */ + public function testSubmitWithJsonArrayRequestBody(): void + { + + $controller = $this->createController(); + + $request = $this->createStub(Request::class); + $request->method('getContentTypeFormat')->willReturn('json'); + $request->method('getContent')->willReturn('["test"]'); + + $this->expectException(\Symfony\Component\HttpFoundation\Exception\JsonException::class); + $controller->submit( + '', + 'location', + 'form-1', + $request, + ); + } + + /** + * @throws Exception + */ + public function testSubmitWithInvalidJson(): void + { + + $controller = $this->createController(); + + $request = $this->createStub(Request::class); + $request->method('getContentTypeFormat')->willReturn('json'); + $request->method('getContent')->willReturn('test'); + + $this->expectException(\Symfony\Component\HttpFoundation\Exception\JsonException::class); + $controller->submit( + '', + 'location', + 'form-1', + $request, + ); + } + + /** + * @throws Exception + */ + private function createResourceChannel(string $locale, array $translationLocales): ResourceChannel + { + return new ResourceChannel( + '', + '', + '', + '', + false, + '', + $locale, + '', + '', + '', + '', + $translationLocales, + new DataBag([]), + $this->createStub(ResourceTenant::class), + ); + } +} diff --git a/test/Dto/UISchema/ControlTest.php b/test/Dto/UISchema/ControlTest.php new file mode 100644 index 0000000..41c7505 --- /dev/null +++ b/test/Dto/UISchema/ControlTest.php @@ -0,0 +1,33 @@ +assertEquals('#/properties/field-1', $control->scope); + } + + public function testScopeStartsWithSlash(): void + { + $this->expectException(InvalidArgumentException::class); + new Control('/properties/field-1'); + } + + public function testScopeStartsWithLetter(): void + { + $this->expectException(InvalidArgumentException::class); + new Control('properties/field-1'); + } + +} diff --git a/test/Processor/EmailSenderTest.php b/test/Processor/EmailSenderTest.php new file mode 100644 index 0000000..6ff7ce6 --- /dev/null +++ b/test/Processor/EmailSenderTest.php @@ -0,0 +1,110 @@ +createStub(EmailMessageModelFactory::class); + $htmlResult = new EmailHtmlMessageRendererResult( + message: '

test

', + attachments: [ + [ + 'filename' => 'text.txt', + 'contentType' => 'text/plain', + 'data' => 'text', + ], + ], + ); + $textResult = new EmailHtmlMessageRendererResult( + message: 'test', + attachments: [], + ); + + $htmlMessageRenderer = $this->createStub(EmailMessageRenderer::class); + $htmlMessageRenderer->method('render') + ->willReturn($htmlResult, $textResult); + + $csvGenerator = $this->createStub(CsvGenerator::class); + $csvGenerator->method('generate') + ->willReturn('csv'); + $mailer = $this->createMock(MailerInterface::class); + + $emailSender = new EmailSender( + $modelFactory, + $htmlMessageRenderer, + $csvGenerator, + $mailer, + ); + + $submission = new FormSubmission( + '12.34.56.78', + $this->createStub(FormDefinition::class), + new stdClass(), + ); + + $expected = (new Email()) + ->subject('test') + ->html('

test

') + ->text('test') + ->from(new Address('from@example.com', 'From')) + ->to(new Address('to@example.com', 'To')) + ->cc(new Address('cc@example.com', 'Cc')) + ->bcc(new Address('bcc@example.com', 'Bcc')) + ->attach('text', 'text.txt', 'text/plain') + ->attach('csv', 'data.csv', 'text/csv') + ; + + $mailer->expects($this->once()) + ->method('send') + ->with($expected); + + $emailSender->process($submission, [ + 'attachCsv' => true, + 'subject' => 'test', + 'from' => [[ + 'address' => 'from@example.com', + 'name' => 'From', + ]], + 'to' => [[ + 'address' => 'to@example.com', + 'name' => 'To', + ]], + 'cc' => [[ + 'address' => 'cc@example.com', + 'name' => 'Cc', + ]], + 'bcc' => [[ + 'address' => 'bcc@example.com', + 'name' => 'Bcc', + ]], + ]); + } +} diff --git a/test/Processor/IpAllowerTest.php b/test/Processor/IpAllowerTest.php new file mode 100644 index 0000000..88a9407 --- /dev/null +++ b/test/Processor/IpAllowerTest.php @@ -0,0 +1,33 @@ +createStub(FormDefinition::class), + new stdClass(), + ); + + $resultSubmission = $processor->process($submission, []); + $this->assertTrue($resultSubmission->approved, 'should be approved'); + } +} diff --git a/test/Processor/IpBlockerTest.php b/test/Processor/IpBlockerTest.php new file mode 100644 index 0000000..6ae956d --- /dev/null +++ b/test/Processor/IpBlockerTest.php @@ -0,0 +1,68 @@ +createStub(FormDefinition::class), + new stdClass(), + ); + + $submission->approved = true; + $resultSubmission = $processor->process($submission, []); + $this->assertTrue($resultSubmission->approved, 'should be approved'); + } + + /** + * @throws Exception + */ + public function testProcessWithBlockedIp(): void + { + $processor = new IpBlocker(['12.34.56.78']); + $submission = new FormSubmission( + '12.34.56.78', + $this->createStub(FormDefinition::class), + new stdClass(), + ); + + $this->expectException(AccessDeniedException::class); + $processor->process($submission, []); + } + + /** + * @throws Exception + */ + public function testProcessNonBlockedIp(): void + { + $processor = new IpBlocker(['12.34.56.78']); + $submission = new FormSubmission( + '127.0.0.1', + $this->createStub(FormDefinition::class), + new stdClass(), + ); + + $this->expectNotToPerformAssertions(); + $processor->process($submission, []); + } + +} diff --git a/test/Processor/IpLimiterTest.php b/test/Processor/IpLimiterTest.php new file mode 100644 index 0000000..daaf23a --- /dev/null +++ b/test/Processor/IpLimiterTest.php @@ -0,0 +1,68 @@ + 'formSubmitByIp', + 'policy' => 'fixed_window', + 'limit' => 1, + 'interval' => '1 minute', + ], new InMemoryStorage()); + $this->processor = new IpLimiter($formSubmitByIpLimiter); + + $this->submission = new FormSubmission( + '127.0.0.1', + $this->createStub(FormDefinition::class), + new stdClass(), + ); + } + + public function testProcess(): void + { + $this->expectNotToPerformAssertions(); + $this->processor->process($this->submission, []); + } + + public function testProcessLimit(): void + { + $this->processor->process($this->submission, []); + + $this->expectException(LimitExceededException::class); + $this->processor->process($this->submission, []); + } + + public function testProcessWishApprove(): void + { + $this->submission->approved = true; + + $this->expectNotToPerformAssertions(); + $this->processor->process($this->submission, []); + $this->processor->process($this->submission, []); + } +} diff --git a/test/Processor/JsonSchemaValidatorTest.php b/test/Processor/JsonSchemaValidatorTest.php new file mode 100644 index 0000000..3a5318f --- /dev/null +++ b/test/Processor/JsonSchemaValidatorTest.php @@ -0,0 +1,59 @@ +service = $this->createMock(\Atoolo\Form\Service\JsonSchemaValidator::class); + $this->processor = new JsonSchemaValidator($this->service); + + $formDefinition = new FormDefinition( + schema: [], + uischema: new Layout(Type::VERTICAL_LAYOUT), + data: [], + buttons: [], + messages: [], + lang: 'en', + component: 'test', + processors: [], + ); + $this->submission = new FormSubmission( + '127.0.0.1', + $formDefinition, + new stdClass(), + ); + + } + + public function testProcess(): void + { + $this->service->expects($this->once()) + ->method('validate'); + $this->processor->process($this->submission, []); + } +} diff --git a/test/Processor/SpamDetectorTest.php b/test/Processor/SpamDetectorTest.php new file mode 100644 index 0000000..1f9b7cb --- /dev/null +++ b/test/Processor/SpamDetectorTest.php @@ -0,0 +1,53 @@ +processor = new SpamDetector(); + $this->submission = new FormSubmission( + '127.0.0.1', + $this->createStub(FormDefinition::class), + new stdClass(), + ); + } + + /** + * @throws Exception + */ + public function testProcessWithApproved(): void + { + $this->submission->approved = true; + $this->expectNotToPerformAssertions(); + $this->processor->process($this->submission, []); + } + + /** + * @throws Exception + */ + public function testProcess(): void + { + $this->expectNotToPerformAssertions(); + $this->processor->process($this->submission, []); + } +} diff --git a/test/Processor/SubmitLimiterTest.php b/test/Processor/SubmitLimiterTest.php new file mode 100644 index 0000000..b7d2d82 --- /dev/null +++ b/test/Processor/SubmitLimiterTest.php @@ -0,0 +1,68 @@ + 'formSubmitByIp', + 'policy' => 'fixed_window', + 'limit' => 1, + 'interval' => '1 minute', + ], new InMemoryStorage()); + $this->processor = new SubmitLimiter($formSubmitByIpLimiter); + + $this->submission = new FormSubmission( + '127.0.0.1', + $this->createStub(FormDefinition::class), + new stdClass(), + ); + } + + public function testProcess(): void + { + $this->expectNotToPerformAssertions(); + $this->processor->process($this->submission, []); + } + + public function testProcessLimit(): void + { + $this->processor->process($this->submission, []); + + $this->expectException(LimitExceededException::class); + $this->processor->process($this->submission, []); + } + + public function testProcessWishApprove(): void + { + $this->submission->approved = true; + + $this->expectNotToPerformAssertions(); + $this->processor->process($this->submission, []); + $this->processor->process($this->submission, []); + } +} diff --git a/test/Service/DataUrlParserTest.php b/test/Service/DataUrlParserTest.php new file mode 100644 index 0000000..821f352 --- /dev/null +++ b/test/Service/DataUrlParserTest.php @@ -0,0 +1,55 @@ +parser = new DataUrlParser(); + } + + public function testParseWithInvalidUrl(): void + { + $this->expectException(DataUrlException::class); + $this->parser->parse('x'); + } + + public function testParse(): void + { + $base64Data = base64_encode('text'); + $dataUrl = 'data:text/plain;name=text.txt;base64,' . $base64Data; + + $expected = new UploadFile( + filename: 'text.txt', + contentType: 'text/plain', + data: 'text', + size: 4, + ); + $this->assertEquals( + $expected, + $this->parser->parse($dataUrl), + 'unexpected value', + ); + } + + public function testParseWithInvalidBase64Data(): void + { + $invalidBase64 = "#"; + $dataUrl = 'data:text/plain;name=text.txt;base64,' . $invalidBase64; + + $this->expectException(DataUrlException::class); + $this->parser->parse($dataUrl); + } +} diff --git a/test/Service/Email/CsvGeneratorTest.php b/test/Service/Email/CsvGeneratorTest.php new file mode 100644 index 0000000..de17084 --- /dev/null +++ b/test/Service/Email/CsvGeneratorTest.php @@ -0,0 +1,53 @@ + [ + [ + 'layout' => true, + 'items' => [ + [ + 'label' => 'Name', + 'value' => 'John Doe', + ], + [ + 'label' => 'Email', + 'value' => 'test@example.com', + ], + [ + 'label' => 'Values', + 'value' => ['a', 'b'], + ], + ], + ], + ], + ]; + + $csv = $csvGenerator->generate($model); + $expectedCsv = <<assertEquals($expectedCsv, $csv, 'unexpected csv'); + } +} diff --git a/test/Service/Email/EmailMessageModelFactoryTest.php b/test/Service/Email/EmailMessageModelFactoryTest.php new file mode 100644 index 0000000..c25aab0 --- /dev/null +++ b/test/Service/Email/EmailMessageModelFactoryTest.php @@ -0,0 +1,92 @@ +createStub(FormDataModelFactory::class); + $formDataModelFactory->method('create') + ->willReturn([ + 'dummy' => true, + ]); + $platform = $this->createStub(Platform::class); + $dateTime = new DateTime(); + $dateTime->setDate(23, 9, 2024); + $dateTime->setTime(9, 38, 20); + $platform->method('datetime')->willReturn($dateTime); + $factory = new EmailMessageModelFactory($channel, $formDataModelFactory, $platform); + + $formDefinition = new FormDefinition( + schema: [], + uischema: new Layout(Type::VERTICAL_LAYOUT), + data: [], + buttons: [], + messages: [], + lang: 'en', + component: 'test', + processors: [], + ); + + $data = new stdClass(); + $submission = new FormSubmission('127.0.0.1', $formDefinition, $data); + + $expected = [ + 'lang' => 'en', + 'url' => 'https://test.example.com', + 'tenant' => ['name' => 'Test Tenant'], + 'host' => 'test.example.com', + 'date' => $dateTime, + 'items' => ['dummy' => true], + ]; + + $this->assertEquals($expected, $factory->create($submission, true), 'unexpected model'); + } +} diff --git a/test/Service/Email/EmailMessageRendererTest.php b/test/Service/Email/EmailMessageRendererTest.php new file mode 100644 index 0000000..09e5c4e --- /dev/null +++ b/test/Service/Email/EmailMessageRendererTest.php @@ -0,0 +1,61 @@ + 'file', + 'value' => [ + 'filename' => 'file1', + 'contentType' => 'application/pdf', + 'data' => 'date', + 'size' => 4, + ], + ], + [ + 'type' => 'text', + 'value' => 'text1', + ], + ]; + + $renderer = new class extends EmailMessageRenderer { + /** + * @param array $model + * @return array + */ + public function render(string $format, array $model): EmailHtmlMessageRendererResult + { + return new EmailHtmlMessageRendererResult( + message: 'html', + attachments: $this->findAttachments($model), + ); + } + }; + + $expected = new EmailHtmlMessageRendererResult( + message: 'html', + attachments: [ + [ + 'filename' => 'file1', + 'contentType' => 'application/pdf', + 'data' => 'date', + 'size' => 4, + ], + ], + ); + + $this->assertEquals($expected, $renderer->render('html', $model), 'unexpected result'); + } +} diff --git a/test/Service/Email/EmailMessageTwigMjmlRendererTest.php b/test/Service/Email/EmailMessageTwigMjmlRendererTest.php new file mode 100644 index 0000000..10ebb96 --- /dev/null +++ b/test/Service/Email/EmailMessageTwigMjmlRendererTest.php @@ -0,0 +1,37 @@ +createStub(Environment::class); + $twig->method('render') + ->willReturn('mjml'); + $mjml = $this->createStub(MjmlRenderer::class); + $mjml->method('render') + ->willReturn('html'); + + $renderer = new EmailMessageTwigMjmlRenderer($twig, $mjml); + $expected = new EmailHtmlMessageRendererResult( + message: 'html', + attachments: [], + ); + $this->assertEquals($expected, $renderer->render('html', ['items' => []]), 'unexpected result'); + } +} diff --git a/test/Service/Email/EmailMessageTwigRendererTest.php b/test/Service/Email/EmailMessageTwigRendererTest.php new file mode 100644 index 0000000..9c8b3d2 --- /dev/null +++ b/test/Service/Email/EmailMessageTwigRendererTest.php @@ -0,0 +1,44 @@ +createStub(Environment::class); + $twig->method('render') + ->willReturn('html'); + + $renderer = new EmailMessageTwigRenderer($twig); + + $model = [ + 'items' => [ + [ + 'type' => 'file', + 'value' => 'file1', + ], + ], + ]; + + $expected = new EmailHtmlMessageRendererResult( + message: 'html', + attachments: ['file1'], + ); + + $this->assertEquals($expected, $renderer->render('html', $model), 'unexpected result'); + } +} diff --git a/test/Service/Email/EmailTemplateTest.php b/test/Service/Email/EmailTemplateTest.php new file mode 100644 index 0000000..9c35506 --- /dev/null +++ b/test/Service/Email/EmailTemplateTest.php @@ -0,0 +1,156 @@ +addLoader('array', new ArrayLoader()); + $translator->addResource('array', [ + 'email.header' => 'Email header', + 'email.headline' => 'Email headline', + 'email.footer' => 'Email footer', + ], 'en', 'form'); + + $projectDir = __DIR__ . '/../../../'; + $loader = new FilesystemLoader(); + $loader->addPath($projectDir . '/templates', 'AtooloForm'); + $twig = new Environment($loader, [ + 'strict_variables' => true, + ]); + $twig->addExtension(new TranslationExtension($translator)); + + $context = [ + 'lang' => 'en', + 'tenant' => [ + 'name' => 'Test Tenant', + ], + 'url' => 'https://test.example.com', + 'host' => 'test.example.com', + 'date' => '25.09.2024', + 'time' => '12:09', + 'items' => [ + ['type' => 'text', 'label' => 'Text', 'value' => 'Test content'], + ], + ]; + + + $html = $twig->render('@AtooloForm/email.html.twig', $context); + + $crawler = new Crawler($html); + $this->assertEquals( + 'Email header', + $crawler->filter('.title')->first()->text(), + 'Email header does not match', + ); + $this->assertEquals( + 'Email headline', + $crawler->filter('h1.header')->first()->text(), + 'Email header does not match', + ); + $this->assertEquals( + 'Email footer', + $crawler->filter('.footer')->first()->text(), + 'Email header does not match', + ); + $this->assertEquals( + 'Text', + $crawler->filter('.field .field-label')->first()->text(), + 'Field text does not match', + ); + $this->assertEquals( + 'Test content', + $crawler->filter('.field .field-value')->first()->text(), + 'Field label does not match', + ); + } + + public function testTextTemplate(): void + { + + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', [ + 'email.header' => 'Email header', + 'email.headline' => 'Email headline', + 'email.footer' => 'Email footer', + ], 'en', 'form'); + + $projectDir = __DIR__ . '/../../../'; + $loader = new FilesystemLoader(); + $loader->addPath($projectDir . '/templates', 'AtooloForm'); + $twig = new Environment($loader, [ + 'strict_variables' => true, + ]); + $twig->addExtension(new TranslationExtension($translator)); + $twig->addExtension(new MarkdownExtension()); + + $context = [ + 'lang' => 'en', + 'tenant' => [ + 'name' => 'Test Tenant', + ], + 'url' => 'https://test.example.com', + 'host' => 'test.example.com', + 'date' => '25.09.2024', + 'time' => '12:09', + 'items' => [ + [ + 'type' => 'horizontal_layout', + 'label' => 'Layout', + 'items' => [ + ['type' => 'text', 'label' => 'Text', 'value' => 'Test content'], + [ + 'type' => 'checkbox_group', + 'label' => 'Checkbox-Group', + 'options' => [ + ['value' => 'option1', 'label' => 'Option 1', 'selected' => true], + ['value' => 'option2', 'label' => 'Option 2', 'selected' => false], + ['value' => 'option3', 'label' => 'Option 3', 'selected' => true], + ], + ], + ], + ], + ], + ]; + + + $text = $twig->render('@AtooloForm/email.text.twig', $context); + + $expected = <<assertEquals($expected, $text, 'Text email does not match'); + } +} diff --git a/test/Service/ExceptionTransformerTest.php b/test/Service/ExceptionTransformerTest.php new file mode 100644 index 0000000..01e8a26 --- /dev/null +++ b/test/Service/ExceptionTransformerTest.php @@ -0,0 +1,88 @@ +transformer = new ExceptionTransformer(); + } + + public static function transformTestData(): array + { + return [ + [ ValidationFailedException::class, ValidationApiProblem::class ], + [ LimitExceededException::class, HttpApiProblem::class ], + [ AccessDeniedException::class, HttpApiProblem::class ], + [ SpamDetectedException::class, HttpApiProblem::class ], + [ Exception::class, LogicException::class, false ], + ]; + } + + /** + * @throws \PHPUnit\Framework\MockObject\Exception + */ + #[DataProvider('transformTestData')] + public function testAccepts( + string $exceptionClass, + string $transformedClass, + bool $accepted = true, + ): void { + /** @var Throwable $exception */ + $exception = $this->createStub($exceptionClass); + + $this->assertEquals( + $accepted, + $this->transformer->accepts($exception), + 'unexpected accepts result', + ); + } + + /** + * @throws \PHPUnit\Framework\MockObject\Exception + */ + #[DataProvider('transformTestData')] + public function testTransform( + string $exceptionClass, + string $transformedClass, + bool $validException = true, + ): void { + + /** @var Throwable $exception */ + $exception = $this->createStub($exceptionClass); + + if (!$validException) { + $this->expectException(LogicException::class); + } + + $transformed = $this->transformer->transform($exception); + + if ($validException) { + $this->assertEquals( + $transformedClass, + get_class($transformed), + 'unexpected class: ' . get_class($transformed), + ); + } + } +} diff --git a/test/Service/FormDataModelFactoryTest.php b/test/Service/FormDataModelFactoryTest.php new file mode 100644 index 0000000..6144b9f --- /dev/null +++ b/test/Service/FormDataModelFactoryTest.php @@ -0,0 +1,107 @@ +dataUrlParser = $this->createStub(DataUrlParser::class); + $this->dataUrlParser->method('parse') + ->willReturn(new UploadFile( + 'text.txt', + 'text/plain', + 'text', + 4, + )); + $this->formDataModelFactory = new FormDataModelFactory($this->dataUrlParser); + } + + public static function loadTextures(): array + { + $textures = []; + $files = glob(self::$RESOURCE_PATH . '/*.php'); + foreach ($files as $file) { + $textures[basename($file)] = [require $file]; + } + + return $textures; + } + + #[DataProvider('loadTextures')] + public function testCreate(array $texture): void + { + + $schema = $texture['schema']; + $uischema = $texture['uischema']; + $data = $texture['data']; + $includeEmptyFields = $texture['includeEmptyFields'] ?? false; + $expected = $texture['expected']; + + $model = $this->createModel($schema, $uischema, $data, $includeEmptyFields); + $this->assertEquals($expected, $model, 'unexpected model'); + } + + private function createModel( + array $schema, + array $uischema, + array $data, + bool $includeEmptyFields = false, + ): array { + $formDefinition = new FormDefinition( + schema : $schema, + uischema: $this->deserializeUiSchema($uischema), + data: $data, + buttons: [], + messages: null, + lang: '', + component: '', + processors: null, + ); + return $this->formDataModelFactory->create($formDefinition, $data, $includeEmptyFields); + } + + private function deserializeUiSchema(array $data): Layout + { + $classMetadataFactory = new ClassMetadataFactory(new AttributeLoader()); + $discriminator = new ClassDiscriminatorFromClassMetadata($classMetadataFactory); + + $encoders = [new JsonEncoder()]; + $normalizers = [ new ArrayDenormalizer(), new BackedEnumNormalizer(), new ObjectNormalizer( + classMetadataFactory: $classMetadataFactory, + propertyTypeExtractor: new PhpDocExtractor(), + classDiscriminatorResolver: $discriminator, + )]; + return (new Serializer($normalizers, $encoders))->denormalize($data, Layout::class); + } + +} diff --git a/test/Service/FormDefinitionLoaderTest.php b/test/Service/FormDefinitionLoaderTest.php new file mode 100644 index 0000000..3b1e250 --- /dev/null +++ b/test/Service/FormDefinitionLoaderTest.php @@ -0,0 +1,315 @@ +resourceLoader = $this->createStub(ResourceLoader::class); + $translator = $this->createStub(LabelTranslator::class); + $translator->method('translate') + ->willReturnCallback(function (array $schema) { + return $schema; + }); + $this->loader = new FormDefinitionLoader( + $this->resourceLoader, + $translator, + ); + } + + public function testFormNotFound(): void + { + $this->setContentForResourceLoaderStub([]); + + $this->expectException(FormNotFoundException::class); + $this->loader->loadFromResource(ResourceLocation::of('/test.php'), 'formEditor-1'); + } + + public function testMissingJsonForm(): void + { + $this->setContentForResourceLoaderStub([ + "items" => [[ + "type" => "formContainer", + "id" => "formEditor-1", + "model" => [ + ], + ]], + ]); + $this->expectException(InvalidFormConfiguration::class); + $this->loader->loadFromResource(ResourceLocation::of('/test.php'), 'formEditor-1'); + } + + public function testMissingSchema(): void + { + $this->setContentForResourceLoaderStub([ + "items" => [[ + "type" => "formContainer", + "id" => "formEditor-1", + "model" => [ + "jsonForms" => [ + "uischema" => [], + ], + ], + ]], + ]); + $this->expectException(InvalidFormConfiguration::class); + $this->loader->loadFromResource(ResourceLocation::of('/test.php'), 'formEditor-1'); + } + + public function testMissingUiSchema(): void + { + $this->setContentForResourceLoaderStub([ + "items" => [[ + "type" => "formContainer", + "id" => "formEditor-1", + "model" => [ + "jsonForms" => [ + "schema" => [], + ], + ], + ]], + ]); + $this->expectException(InvalidFormConfiguration::class); + $this->loader->loadFromResource(ResourceLocation::of('/test.php'), 'formEditor-1'); + } + + public function testMissingDeliverer(): void + { + $this->setContentForResourceLoaderStub([ + "items" => [[ + "type" => "formContainer", + "id" => "formEditor-1", + "model" => [ + "jsonForms" => [ + "schema" => [], + "uischema" => [], + ], + ], + ]], + ]); + $this->expectException(InvalidFormConfiguration::class); + $this->loader->loadFromResource(ResourceLocation::of('/test.php'), 'formEditor-1'); + } + + public function testUnsupportedDeliverer(): void + { + $this->setContentForResourceLoaderStub([ + "items" => [[ + "type" => "formContainer", + "id" => "formEditor-1", + "model" => [ + "jsonForms" => [ + "schema" => [], + "uischema" => [], + ], + "deliverer" => [ + 'modelType' => 'unsupported', + ], + ], + ]], + ]); + $this->expectException(InvalidFormConfiguration::class); + $this->loader->loadFromResource(ResourceLocation::of('/test.php'), 'formEditor-1'); + } + + public function testLoad(): void + { + $this->setContentForResourceLoaderStub([ + "type" => "ROOT", + "id" => "ROOT", + "items" => [[ + "type" => "main", + "id" => "main", + "items" => [[ + "type" => "implicitSection", + "model" => [ + "implicit" => true, + ], + "id" => "implicitSection-1", + "items" => [[ + "type" => "formContainer", + "id" => "formEditor-1", + "model" => [ + "headline" => "Form heading", + "https" => true, + "consent" => false, + "jsonForms" => [ + "schema" => [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Single-line text field", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Single-line text field", + "options" => [ + "autocomplete" => "name", + "spaceAfter" => true, + ], + ], + ], + ], + ], + "bottomBar" => [ + "items" => [[ + "type" => "button.submit", + "id" => "button-1", + "label" => "submit", + "value" => "submit", + "action" => "submit", + ]], + ], + "deliverer" => [ + "modelType" => "content.form.deliverer.email", + "from" => [ + "test@email.com" => "Sender", + ], + "to" => [ + "test@email.com" => "to address", + ], + "cc" => [ + "test@email.com" => "cc address", + ], + "bcc" => [ + "test@email.com" => "bcc address", + ], + "subject" => "Subject of E-Mail", + "type" => "email", + "format" => "plain", + "attachCsv" => false, + "showEmpty" => false, + ], + "messages" => [ + "success" => [ + "headline" => "Confirmation", + "text" => "Text", + ], + ], + ], + ]], + ]], + ]], + ]); + + $definition = $this->loader->loadFromResource(ResourceLocation::of('/test.php'), 'formEditor-1'); + + $uischema = new Layout( + type: Type::VERTICAL_LAYOUT, + elements: [(new Control( + scope: '#/properties/field', + label: 'Single-line text field', + options: [ + 'autocomplete' => 'name', + 'spaceAfter' => true, + ], + ))], + ); + $expected = new FormDefinition( + schema: [ + 'type' => 'object', + 'properties' => [ + "field" => [ + "type" => "string", + "title" => "Single-line text field", + ], + ], + ], + uischema: $uischema, + data: null, + buttons: [ + 'submit' => 'submit', + ], + messages: [ + 'success' => [ + 'headline' => 'Confirmation', + 'text' => 'Text', + ], + ], + lang: 'en', + component: 'formEditor-1', + processors: [ + 'email-sender' => [ + 'from' => [ + [ + 'address' => 'test@email.com', + 'name' => 'Sender', + ], + ], + 'to' => [ + [ + 'address' => 'test@email.com', + 'name' => 'to address', + ], + ], + 'cc' => [ + [ + 'address' => 'test@email.com', + 'name' => 'cc address', + ], + ], + 'bcc' => [ + [ + 'address' => 'test@email.com', + 'name' => 'bcc address', + ], + ], + 'subject' => 'Subject of E-Mail', + 'format' => 'plain', + 'attachCsv' => false, + 'showEmpty' => false, + 'selectable' => [], + ], + ], + ); + + $this->assertEquals($expected, $definition, 'FormDefinition does not match'); + } + + private function setContentForResourceLoaderStub(array $content): void + { + $this->resourceLoader->method('load')->willReturn(new Resource( + '/test', + '', + '', + '', + ResourceLanguage::of('en'), + new DataBag(['content' => $content]), + )); + } +} diff --git a/test/Service/FormReaderTest.php b/test/Service/FormReaderTest.php new file mode 100644 index 0000000..d288cfc --- /dev/null +++ b/test/Service/FormReaderTest.php @@ -0,0 +1,118 @@ + 'object', + 'properties' => [ + 'field-1' => [ + 'type' => 'string', + ], + ], + ]; + + $formDefinition = $this->createDefinition($schema, $uischema); + $data = [ + 'field-1' => 'value', + ]; + + $handler = $this->createMock(FromReaderHandler::class); + $handler->expects($this->once()) + ->method('startLayout') + ->with($uischema); + $handler->expects($this->never()) + ->method('control'); + $handler->expects($this->once()) + ->method('endLayout') + ->with($uischema); + + $reader = new FormReader($formDefinition, $data, $handler); + $reader->read(); + } + + /** + * @throws Exception + */ + public function testLoad(): void + { + $control = new Control('#/properties/field-1'); + $uischema = new Layout( + Type::GROUP, + [ $control ], + ); + $schema = [ + 'type' => 'object', + 'properties' => [ + 'field-1' => [ + 'type' => 'string', + ], + ], + ]; + + $formDefinition = $this->createDefinition($schema, $uischema); + + $data = [ + 'field-1' => 'value', + ]; + + $handler = $this->createMock(FromReaderHandler::class); + $handler->expects($this->once()) + ->method('startLayout') + ->with($uischema); + $handler->expects($this->once()) + ->method('control') + ->with($control, ['type' => 'string'], 'field-1', 'value'); + $handler->expects($this->once()) + ->method('endLayout') + ->with($uischema); + + $reader = new FormReader($formDefinition, $data, $handler); + $reader->read(); + } + + private function createDefinition( + array $schema, + Layout $uischema, + ): FormDefinition { + return new FormDefinition( + schema: $schema, + uischema: $uischema, + data: null, + buttons: [], + messages: [], + lang: 'en', + component: 'form-1', + processors: [], + ); + } +} diff --git a/test/Service/JsonSchemaValidator/DataUrlConstraintTest.php b/test/Service/JsonSchemaValidator/DataUrlConstraintTest.php new file mode 100644 index 0000000..5dc0021 --- /dev/null +++ b/test/Service/JsonSchemaValidator/DataUrlConstraintTest.php @@ -0,0 +1,103 @@ +dataUrlParser = $this->createStub(DataUrlParser::class); + $this->constraint = new DataUrlConstraint($this->dataUrlParser); + } + + public function testGetType(): void + { + $this->assertEquals( + 'string', + $this->constraint->getType(), + 'unexpected type', + ); + } + + public function testGetName(): void + { + $this->assertEquals( + 'data-url', + $this->constraint->getName(), + 'unexpected name', + ); + } + + public function testCheckWithNonString(): void + { + $this->expectException(CustomError::class); + $this->constraint->check(0, (object) []); + } + + public static function dataToCheck(): array + { + $pngData = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'); + return [ + [ ['size' => 5], ['maxFileSize' => 10], true ], + [ ['size' => 10], ['maxFileSize' => 10], true ], + [ ['size' => 20], ['maxFileSize' => 10], false ], + [ ['size' => 5], ['minFileSize' => 10], false ], + [ ['size' => 10], ['minFileSize' => 10], true ], + [ ['size' => 20], ['minFileSize' => 10], true ], + [ ['data' => $pngData], ['acceptedContentTypes' => ['image/png']], true ], + [ ['data' => $pngData], ['acceptedContentTypes' => ['image/*']], true ], + [ ['data' => $pngData], ['acceptedContentTypes' => ['image/jpg']], false ], + [ ['data' => $pngData], ['acceptedContentTypes' => ['text/plain']], false ], + [ ['data' => $pngData], ['acceptedContentTypes' => ['text/plain', 'image/png']], true ], + [ ['filename' => 'test.txt'], ['acceptedFileNames' => ['test.txt']], true ], + [ ['filename' => 'test.txt'], ['acceptedFileNames' => ['test.*']], true ], + [ ['filename' => 'test.txt'], ['acceptedFileNames' => ['*.txt']], true ], + [ ['filename' => 'test.txt'], ['acceptedFileNames' => ['*.png']], false ], + [ ['filename' => 'test.txt'], ['acceptedFileNames' => ['*.txt', 'image.png']], true ], + ]; + } + + #[DataProvider('dataToCheck')] + public function testCheck( + array $uploadFileFields, + array $schema, + bool $shouldValid, + ): void { + + $uploadFile = new UploadFile( + $uploadFileFields['filename'] ?? '', + $uploadFileFields['mimeType'] ?? '', + $uploadFileFields['data'] ?? '', + $uploadFileFields['size'] ?? 0, + ); + + $this->dataUrlParser->method('parse')->willReturn($uploadFile); + + if (!$shouldValid) { + $this->expectException(CustomError::class); + } + + $result = $this->constraint->check('data-url', (object) $schema); + if ($shouldValid) { + $this->assertTrue($result, 'should be valid'); + } + } +} diff --git a/test/Service/JsonSchemaValidator/Extended/ValidatorExtendedTest.php b/test/Service/JsonSchemaValidator/Extended/ValidatorExtendedTest.php new file mode 100644 index 0000000..7cf29bf --- /dev/null +++ b/test/Service/JsonSchemaValidator/Extended/ValidatorExtendedTest.php @@ -0,0 +1,49 @@ +type = 'string'; + $expectedSchema->format = 'test'; + + $formatResolver = $validator->parser()->getFormatResolver(); + $formatResolver->registerCallable('string', 'test', function ($data, $schema) use ($expectedSchema) { + $this->assertEquals('abc', $data, "unexpected data"); + $this->assertEquals($expectedSchema, $schema, "unexpected schema"); + return true; + }); + + $schema = json_encode([ + "type" => "object", + "properties" => [ + "test" => [ + "type" => "string", + "format" => "test", + ], + ], + ], JSON_THROW_ON_ERROR); + $json = json_encode([ + 'test' => 'abc', + ], JSON_THROW_ON_ERROR); + + $validator->validate( + json_decode($json, false, 512, JSON_THROW_ON_ERROR), + $schema, + ); + } +} diff --git a/test/Service/JsonSchemaValidator/HtmlConstraintTest.php b/test/Service/JsonSchemaValidator/HtmlConstraintTest.php new file mode 100644 index 0000000..001d564 --- /dev/null +++ b/test/Service/JsonSchemaValidator/HtmlConstraintTest.php @@ -0,0 +1,79 @@ +constraint = new HtmlConstraint(); + } + + public function testGetType(): void + { + $this->assertEquals( + 'string', + $this->constraint->getType(), + 'unexpected type', + ); + } + + public function testGetName(): void + { + $this->assertEquals( + 'html', + $this->constraint->getName(), + 'unexpected name', + ); + } + + public function testCheckWithNonString(): void + { + $this->expectException(CustomError::class); + $this->constraint->check(0, (object) []); + } + + public static function dataToCheck(): array + { + return [ + [ 'abc', [], true ], + [ 'abc', ['p', 'strong'], true ], + [ '

abc test

', ['p', 'strong'], true ], + [ '

abc test

', ['p', 'strong'], false ], + ]; + } + + #[DataProvider('dataToCheck')] + public function testCheck( + string $value, + array $allowedElements, + bool $shouldValid, + ): void { + + $schema = (object) ['allowedElements' => $allowedElements]; + + if (!$shouldValid) { + $this->expectException(CustomError::class); + } + + $result = $this->constraint->check($value, $schema); + if ($shouldValid) { + $this->assertTrue($result, 'should be valid'); + } + } +} diff --git a/test/Service/JsonSchemaValidator/PhoneConstraintTest.php b/test/Service/JsonSchemaValidator/PhoneConstraintTest.php new file mode 100644 index 0000000..c0f7e89 --- /dev/null +++ b/test/Service/JsonSchemaValidator/PhoneConstraintTest.php @@ -0,0 +1,69 @@ +constraint = new PhoneConstraint(); + } + + public function testGetType(): void + { + $this->assertEquals( + 'string', + $this->constraint->getType(), + 'unexpected type', + ); + } + + public function testGetName(): void + { + $this->assertEquals( + 'phone', + $this->constraint->getName(), + 'unexpected name', + ); + } + + public static function dataToCheck(): array + { + return [ + [ 'abc', true ], + ]; + } + + #[DataProvider('dataToCheck')] + public function testCheck( + string $value, + bool $shouldValid, + ): void { + + $schema = (object) []; + + if (!$shouldValid) { + $this->expectException(CustomError::class); + } + + $result = $this->constraint->check($value, $schema); + if ($shouldValid) { + $this->assertTrue($result, 'should be valid'); + } + } +} diff --git a/test/Service/JsonSchemaValidatorTest.php b/test/Service/JsonSchemaValidatorTest.php new file mode 100644 index 0000000..c7c58f4 --- /dev/null +++ b/test/Service/JsonSchemaValidatorTest.php @@ -0,0 +1,194 @@ +validator = $this->createStub(Validator::class); + $this->formatResolver = $this->createMock(FormatResolver::class); + $schemaParser = $this->createStub(SchemaParser::class); + $schemaParser->method('getFormatResolver')->willReturn($this->formatResolver); + $this->validator->method('parser')->willReturn($schemaParser); + $this->formatConstraint = $this->createStub(FormatConstraint::class); + $this->jsonSchemaValidator = new JsonSchemaValidator( + $this->validator, + [$this->formatConstraint], + new Platform(), + ); + } + + /** + * @throws Exception + */ + public function testWithInvalidConstrains(): void + { + $this->expectException(InvalidArgumentException::class); + new JsonSchemaValidator( + $this->validator, + [$this->createStub(Constraint::class)], + new Platform(), + ); + } + + /** + * @throws Exception + */ + public function testWithMissingFormatResolver(): void + { + $this->expectException(LogicException::class); + + $validator = $this->createStub(Validator::class); + + new JsonSchemaValidator( + $validator, + [$this->createStub(FormatConstraint::class)], + new Platform(), + ); + } + + /** + * @throws Exception + */ + public function testRegisterFormatConstraint(): void + { + $formatConstraint = $this->createStub(FormatConstraint::class); + $formatConstraint->method('getType')->willReturn('string'); + $formatConstraint->method('getName')->willReturn('test'); + + $this->formatResolver->expects($this->once()) + ->method('registerCallable') + ->with( + 'string', + 'test', + $this->callback( + static function ($callback) { + return is_callable($callback); + }, + ), + ); + + new JsonSchemaValidator( + $this->validator, + [$formatConstraint], + new Platform(), + ); + } + + /** + * @throws Exception + */ + public function testFormatConstraintCheckCallback(): void + { + $formatConstraint = $this->createStub(FormatConstraint::class); + $formatConstraint->method('getType')->willReturn('string'); + $formatConstraint->method('getName')->willReturn('test'); + $formatConstraint->method('check')->willReturn(true); + + $validator = $this->createStub(Validator::class); + $formatResolver = new FormatResolver(); + $schemaParser = $this->createStub(SchemaParser::class); + $schemaParser->method('getFormatResolver')->willReturn($formatResolver); + $validator->method('parser')->willReturn($schemaParser); + + new JsonSchemaValidator( + $validator, + [$formatConstraint], + new Platform(), + ); + + $callback = $formatResolver->resolve('test', 'string'); + $this->assertTrue($callback('data', new stdClass()), 'Callback should return true'); + } + + + /** + * @throws Exception + * @throws \JsonException + */ + public function testValidate(): void + { + $schema = [ + 'type' => 'object', + 'properties' => [ + 'text' => [ + 'type' => 'string', + ], + ], + 'required' => ['text'], + ]; + + $data = new stdClass(); + + $result = $this->createValidationResult( + path: ['test'], + message: 'Field missing', + constraint: 'require', + args: ['missing' => ['text']], + ); + $this->validator->method('validate')->willReturn($result); + + try { + $this->jsonSchemaValidator->validate($schema, $data); + } catch (ValidationFailedException $e) { + $violation = $e->getViolations()->get(0); + $this->assertEquals('test/text', $violation->getPropertyPath()); + } + } + + /** + * @throws Exception + */ + private function createValidationResult( + array $path, + string $message, + string $constraint, + array $args, + ): ValidationResult { + $schemaInfo = $this->createStub(SchemaInfo::class); + $schemaInfo->method('path')->willReturn($path); + $schema = $this->createStub(Schema::class); + $schema->method('info')->willReturn($schemaInfo); + + $validationError = $this->createStub(ValidationError::class); + $validationError->method('keyword')->willReturn($constraint); + $validationError->method('schema')->willReturn($schema); + $validationError->method('args')->willReturn($args); + $validationError->method('message')->willReturn($message); + return new ValidationResult($validationError); + } +} diff --git a/test/Service/LabelTranslatorTest.php b/test/Service/LabelTranslatorTest.php new file mode 100644 index 0000000..d243238 --- /dev/null +++ b/test/Service/LabelTranslatorTest.php @@ -0,0 +1,96 @@ +translator = $this->createStub( + TranslatorInterface::class, + ); + $this->labelTranslator = new LabelTranslator($this->translator); + } + + public function testTranslateLabelWithNull(): void + { + $translated = $this->labelTranslator->translateLabel(null); + $this->assertNull( + $translated, + 'unexpected value', + ); + } + + public function testTranslateLabelWithoutPlaceholder(): void + { + $translated = $this->labelTranslator->translateLabel('test'); + $this->assertEquals( + 'test', + $translated, + 'unexpected value', + ); + } + + public function testTranslateLabelWithPlaceholder(): void + { + $this->translator->method('trans') + ->willReturn('translated'); + $translated = $this->labelTranslator->translateLabel('${test}'); + + $this->assertEquals( + 'translated', + $translated, + 'unexpected value', + ); + } + + public function testTranslateFieldsOfArray(): void + { + + $this->translator->method('trans') + ->willReturn('translated'); + + $fields = ['field']; + $data = ['field' => '${key}']; + $translated = $this->labelTranslator->translate($data, $fields); + + $this->assertEquals( + ['field' => 'translated'], + $translated, + 'unexpected value', + ); + } + + public function testTranslateFieldsOfArrayRecursive(): void + { + + $this->translator->method('trans') + ->willReturn('translated'); + + $fields = ['field']; + $data = ['object' => [ 'field' => '${key}' ]]; + $translated = $this->labelTranslator->translate($data, $fields); + + $this->assertEquals( + ['object' => [ 'field' => 'translated' ]], + $translated, + 'unexpected value', + ); + } + +} diff --git a/test/Service/PlatformTest.php b/test/Service/PlatformTest.php new file mode 100644 index 0000000..92c15b5 --- /dev/null +++ b/test/Service/PlatformTest.php @@ -0,0 +1,55 @@ +expectNotToPerformAssertions(); + $platform->datetime(); + } + + public function testObjectToArrayRecursive(): void + { + $platform = new Platform(); + $this->assertEquals( + ['a' => + [ + 'b' => ['c' => 'd'], + 'e' => [ + [ 'f' => 'g' ], + ], + ], + ], + $platform->objectToArrayRecursive((object) [ + 'a' => (object) [ + 'b' => (object) ['c' => 'd'], + 'e' => [ + (object) ['f' => 'g'], + ], + ], + ]), + 'unexpected value', + ); + } + + public function testArrayToObjectRecursive(): void + { + $platform = new Platform(); + $this->assertEquals( + (object) ['a' => (object) ['b' => (object) ['c' => 'd']]], + $platform->arrayToObjectRecursive(['a' => ['b' => ['c' => 'd']]]), + 'unexpected value', + ); + } +} diff --git a/test/Service/SubmitHandlerTest.php b/test/Service/SubmitHandlerTest.php new file mode 100644 index 0000000..7ede6c6 --- /dev/null +++ b/test/Service/SubmitHandlerTest.php @@ -0,0 +1,102 @@ +createMock(SubmitProcessor::class); + $submitHandler = new SubmitHandler( + [ 'test' => $processor ], + [ 'test' => ['a' => 'b'] ], + ); + + $submit = $this->createSubmission([ + 'test' => ['c' => 'd'], + ]); + + $processor->expects($this->once()) + ->method('process') + ->with($submit, ['a' => 'b', 'c' => 'd']); + $submitHandler->handle($submit); + } + + /** + * @throws Exception + */ + public function testHandleWithMissingProcessorKey(): void + { + $processor = $this->createMock(SubmitProcessor::class); + $submitHandler = new SubmitHandler( + [ 'test' => $processor, ], + [ ], + ); + + $submit = $this->createSubmission([ + 'x' => ['c' => 'd'], + ]); + + $processor->expects($this->never()) + ->method('process'); + $submitHandler->handle($submit); + } + + public function testConstructorWithTraversable(): void + { + + $processor = $this->createMock(SubmitProcessor::class); + $processors = (new \ArrayObject(['test' => $processor]))->getIterator(); + $submitHandler = new SubmitHandler( + $processors, + [ ], + ); + + $submit = $this->createSubmission([ + 'test' => ['c' => 'd'], + ]); + + $processor->expects($this->once()) + ->method('process') + ->with($submit, ['c' => 'd']); + $submitHandler->handle($submit); + + } + + private function createSubmission(array $processors): FormSubmission + { + $uischema = new Layout(Type::VERTICAL_LAYOUT); + $formDefinition = new FormDefinition( + schema: [], + uischema: $uischema, + data: [], + buttons: [], + messages: [], + lang: 'en', + component: 'test', + processors: $processors, + ); + return new FormSubmission( + '127.0.0.1', + $formDefinition, + new stdClass(), + ); + } +} diff --git a/test/resources/Service/FormDataModelFactoryTest/annotation.php b/test/resources/Service/FormDataModelFactoryTest/annotation.php new file mode 100644 index 0000000..d4b874e --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/annotation.php @@ -0,0 +1,29 @@ + [ + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Annotation", + "htmlLabel" => [ + "text" => "Note with html and link.", + ], + ], + ], + ], + "data" => [ + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/checkboxfield.php b/test/resources/Service/FormDataModelFactoryTest/checkboxfield.php new file mode 100644 index 0000000..28e6327 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/checkboxfield.php @@ -0,0 +1,45 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "boolean", + "title" => "Checkbox", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Checkbox", + "options" => [ + "label" => "Checkbox", + ], + ], + ], + ], + "data" => [ + 'field' => true, + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'checkbox', + 'name' => 'field', + 'label' => 'Checkbox', + 'value' => true, + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/checkboxgroupfield.php b/test/resources/Service/FormDataModelFactoryTest/checkboxgroupfield.php new file mode 100644 index 0000000..35f4bcb --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/checkboxgroupfield.php @@ -0,0 +1,76 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "array", + "title" => "Checkbox group", + "items" => [ + "oneOf" => [ + [ + "const" => "Dog", + "title" => "dog", + ], + [ + "const" => "cat", + "title" => "Cat", + ], + [ + "const" => "mouse", + "title" => "Mouse", + ], + ], + ], + "uniqueItems" => true, + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Checkbox group", + ], + ], + ], + "data" => [ + 'field' => ['cat', 'mouse'], + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'checkbox-group', + 'name' => 'field', + 'label' => 'Checkbox group', + 'options' => [ + [ + 'label' => 'dog', + 'value' => 'Dog', + 'selected' => false, + ], + [ + 'label' => 'Cat', + 'value' => 'cat', + 'selected' => true, + ], + [ + 'label' => 'Mouse', + 'value' => 'mouse', + 'selected' => true, + ], + ], + 'value' => ['Cat', 'Mouse'], + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/checkboxhtmllabelfield.php b/test/resources/Service/FormDataModelFactoryTest/checkboxhtmllabelfield.php new file mode 100644 index 0000000..4f4d58d --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/checkboxhtmllabelfield.php @@ -0,0 +1,47 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "boolean", + "title" => "Checkbox with Html Label", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "options" => [], + "htmlLabel" => [ + "text" => "An html label with link.", + ], + ], + ], + ], + "data" => [ + 'field' => true, + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'checkbox', + 'name' => 'field', + 'value' => true, + 'htmlLabel' => [ + 'text' => 'An html label with link.', + ], + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/contactgroup.php b/test/resources/Service/FormDataModelFactoryTest/contactgroup.php new file mode 100644 index 0000000..cae3fa6 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/contactgroup.php @@ -0,0 +1,283 @@ + [ + "type" => "object", + "properties" => [ + "contact" => [ + "type" => "object", + "properties" => [ + "salutation" => [ + "type" => "string", + "enum" => [ + "salutationFemale", + "salutationMale", + "salutationDiverse", + "salutationNotSpecified", + ], + ], + "firstname" => [ + "type" => "string", + ], + "lastname" => [ + "type" => "string", + ], + "street" => [ + "type" => "string", + ], + "housenumber" => [ + "type" => "string", + ], + "postalcode" => [ + "type" => "string", + ], + "city" => [ + "type" => "string", + ], + "phone" => [ + "type" => "string", + "format" => "phone", + ], + "mobile" => [ + "type" => "string", + "format" => "phone", + ], + "email" => [ + "type" => "string", + "format" => "email", + ], + ], + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "label" => "Field group Legend", + "type" => "Group", + "options" => [ + "hideLabel" => true, + ], + "elements" => [ + [ + "type" => "Group", + "options" => [], + "elements" => [ + [ + "type" => "Control", + "label" => "Salutation", + "scope" => "#/properties/contact/properties/salutation", + "options" => [ + "format" => "radio", + ], + ], + [ + "type" => "HorizontalLayout", + "elements" => [ + [ + "type" => "Control", + "label" => "Firstname", + "scope" => "#/properties/contact/properties/firstname", + "options" => [ + "autocomplete" => "given-name", + ], + ], + [ + "type" => "Control", + "label" => "Lastname", + "scope" => "#/properties/contact/properties/lastname", + "options" => [ + "autocomplete" => "family-name", + ], + ], + ], + ], + [ + "type" => "HorizontalLayout", + "elements" => [ + [ + "type" => "Control", + "label" => "Street", + "scope" => "#/properties/contact/properties/street", + "options" => [ + "autocomplete" => "address-line1", + ], + ], + [ + "type" => "Control", + "label" => "Housenumber", + "scope" => "#/properties/contact/properties/housenumber", + "options" => [ + "autocomplete" => "on", + ], + ], + ], + ], + [ + "type" => "HorizontalLayout", + "elements" => [ + [ + "type" => "Control", + "label" => "Postalcode", + "scope" => "#/properties/contact/properties/postalcode", + "options" => [ + "autocomplete" => "postal-code", + ], + ], + [ + "type" => "Control", + "label" => "City", + "scope" => "#/properties/contact/properties/city", + "options" => [ + "autocomplete" => "address-level2", + ], + ], + ], + ], + [ + "type" => "Control", + "label" => "Phone", + "scope" => "#/properties/contact/properties/phone", + "options" => [ + "autocomplete" => "tel-national", + ], + ], + [ + "type" => "Control", + "label" => "Mobile", + "scope" => "#/properties/contact/properties/mobile", + "options" => [ + "autocomplete" => "on", + ], + ], + [ + "type" => "Control", + "label" => "Email", + "scope" => "#/properties/contact/properties/email", + "options" => [ + "autocomplete" => "email", + ], + ], + ], + ], + ], + ], + ], + ], + "data" => [ + 'contact' => [ + 'salutation' => 'salutationMale', + 'firstname' => 'Peter', + 'lastname' => 'Pan', + 'street' => 'Dreamstreet', + 'housenumber' => '1', + 'postalcode' => '12345', + 'city' => 'Neverland', + 'phone' => '12345', + 'mobile' => '67890', + 'email' => 'pan@neverland.com', + ], + ], + "includeEmtpyFields" => true, + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'group', + 'layout' => true, + 'items' => [ + [ + 'type' => 'group', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'salutation', + 'label' => 'Salutation', + 'value' => 'salutationMale', + ], + [ + 'type' => 'horizontal_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'firstname', + 'label' => 'Firstname', + 'value' => 'Peter', + ], + [ + 'type' => 'text', + 'name' => 'lastname', + 'label' => 'Lastname', + 'value' => 'Pan', + ], + ], + ], + [ + 'type' => 'horizontal_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'street', + 'label' => 'Street', + 'value' => 'Dreamstreet', + ], + [ + 'type' => 'text', + 'name' => 'housenumber', + 'label' => 'Housenumber', + 'value' => '1', + ], + ], + ], + [ + 'type' => 'horizontal_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'postalcode', + 'label' => 'Postalcode', + 'value' => '12345', + ], + [ + 'type' => 'text', + 'name' => 'city', + 'label' => 'City', + 'value' => 'Neverland', + ], + ], + ], + [ + 'type' => 'text', + 'name' => 'phone', + 'label' => 'Phone', + 'value' => '12345', + ], + [ + 'type' => 'text', + 'name' => 'mobile', + 'label' => 'Mobile', + 'value' => '67890', + ], + [ + 'type' => 'text', + 'name' => 'email', + 'label' => 'Email', + 'value' => 'pan@neverland.com', + ], + ], + ], + ], + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/datefield.php b/test/resources/Service/FormDataModelFactoryTest/datefield.php new file mode 100644 index 0000000..a203f75 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/datefield.php @@ -0,0 +1,43 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Date", + "format" => "date", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Date", + ], + ], + ], + "data" => [ + 'field' => '2024-09-23', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'date', + 'name' => 'field', + 'label' => 'Date', + 'value' => '2024-09-23', + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/emailfield.php b/test/resources/Service/FormDataModelFactoryTest/emailfield.php new file mode 100644 index 0000000..d17d417 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/emailfield.php @@ -0,0 +1,47 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "email", + "format" => "email", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Email", + "options" => [ + "autocomplete" => "email", + "asReplyTo" => true, + ], + ], + ], + ], + "data" => [ + 'field' => 'test@example.com', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field', + 'label' => 'Email', + 'value' => 'test@example.com', + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/emptycheckboxgroupfield.php b/test/resources/Service/FormDataModelFactoryTest/emptycheckboxgroupfield.php new file mode 100644 index 0000000..76ea0f5 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/emptycheckboxgroupfield.php @@ -0,0 +1,53 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "array", + "title" => "Checkbox group", + "items" => [ + "oneOf" => [ + [ + "const" => "Dog", + "title" => "dog", + ], + [ + "const" => "cat", + "title" => "Cat", + ], + [ + "const" => "mouse", + "title" => "Mouse", + ], + ], + ], + "uniqueItems" => true, + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Checkbox group", + ], + ], + ], + "data" => [ + 'field' => [], + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/emptytextfield.php b/test/resources/Service/FormDataModelFactoryTest/emptytextfield.php new file mode 100644 index 0000000..392df5f --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/emptytextfield.php @@ -0,0 +1,40 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Single-line text field", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Single-line text field", + "options" => [ + "autocomplete" => "name", + "spaceAfter" => true, + ], + ], + ], + ], + "data" => [ + 'field' => '', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/fieldInGroup.php b/test/resources/Service/FormDataModelFactoryTest/fieldInGroup.php new file mode 100644 index 0000000..ef80dbc --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/fieldInGroup.php @@ -0,0 +1,59 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Single-line text field", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "label" => "Field group Legend", + "type" => "Group", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Single-line text field", + "options" => [ + "autocomplete" => "name", + "spaceAfter" => true, + ], + ], + ], + ], + ], + ], + "data" => [ + 'field' => 'text', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'group', + 'layout' => true, + 'label' => 'Field group Legend', + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field', + 'label' => 'Single-line text field', + 'value' => 'text', + ], + ], + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/fieldInGroupHideLabel.php b/test/resources/Service/FormDataModelFactoryTest/fieldInGroupHideLabel.php new file mode 100644 index 0000000..fdd1511 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/fieldInGroupHideLabel.php @@ -0,0 +1,61 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Single-line text field", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "label" => "Field group Legend", + "type" => "Group", + "options" => [ + "hideLabel" => true, + ], + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Single-line text field", + "options" => [ + "autocomplete" => "name", + "spaceAfter" => true, + ], + ], + ], + ], + ], + ], + "data" => [ + 'field' => 'text', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'group', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field', + 'label' => 'Single-line text field', + 'value' => 'text', + ], + ], + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/includeemptyfield.php b/test/resources/Service/FormDataModelFactoryTest/includeemptyfield.php new file mode 100644 index 0000000..5311a0f --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/includeemptyfield.php @@ -0,0 +1,57 @@ + [ + "type" => "object", + "properties" => [ + "field-1" => [ + "type" => "string", + "title" => "Field 1", + ], + "field-2" => [ + "type" => "string", + "title" => "Field 2", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field-1", + "label" => "Field 1", + ], + [ + "type" => "Control", + "scope" => "#/properties/field-2", + "label" => "Field 2", + ], + ], + ], + "data" => [ + 'field-1' => 'text', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field-1', + 'label' => 'Field 1', + 'value' => 'text', + ], + [ + 'type' => 'text', + 'name' => 'field-2', + 'label' => 'Field 2', + ], + ], + ], + ], + 'includeEmptyFields' => true, +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/multilinefield.php b/test/resources/Service/FormDataModelFactoryTest/multilinefield.php new file mode 100644 index 0000000..c17a4e6 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/multilinefield.php @@ -0,0 +1,46 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Multiline text field", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Multiline text field", + "options" => [ + "autocomplete" => "off", + "multi" => true, + ], + ], + ], + ], + "data" => [ + 'field' => "line1\nline2\n", + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field', + 'label' => 'Multiline text field', + 'value' => "line1\nline2\n", + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/numberfield.php b/test/resources/Service/FormDataModelFactoryTest/numberfield.php new file mode 100644 index 0000000..4923785 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/numberfield.php @@ -0,0 +1,45 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "integer", + "title" => "Number", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Number", + "options" => [ + "autocomplete" => "off", + ], + ], + ], + ], + "data" => [ + 'field' => 123, + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field', + 'label' => 'Number', + 'value' => 123, + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/phonefield.php b/test/resources/Service/FormDataModelFactoryTest/phonefield.php new file mode 100644 index 0000000..984b965 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/phonefield.php @@ -0,0 +1,46 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Phone number", + "format" => "phone", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Phone number", + "options" => [ + "autocomplete" => "tel", + ], + ], + ], + ], + "data" => [ + 'field' => "123", + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field', + 'label' => 'Phone number', + 'value' => '123', + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/radiobuttonsfield.php b/test/resources/Service/FormDataModelFactoryTest/radiobuttonsfield.php new file mode 100644 index 0000000..6fb3a4c --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/radiobuttonsfield.php @@ -0,0 +1,76 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Radio buttons", + "oneOf" => [ + [ + "const" => "Dog", + "title" => "dog", + ], + [ + "const" => "cat", + "title" => "Cat", + ], + [ + "const" => "mouse", + "title" => "Mouse", + ], + ], + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Radio buttons", + "options" => [ + "format" => "radio", + ], + ], + ], + ], + "data" => [ + 'field' => 'cat', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'radio-buttons', + 'name' => 'field', + 'label' => 'Radio buttons', + 'options' => [ + [ + 'label' => 'dog', + 'value' => 'Dog', + 'selected' => false, + ], + [ + 'label' => 'Cat', + 'value' => 'cat', + 'selected' => true, + ], + [ + 'label' => 'Mouse', + 'value' => 'mouse', + 'selected' => false, + ], + ], + 'value' => 'Cat', + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/richttextfield.php b/test/resources/Service/FormDataModelFactoryTest/richttextfield.php new file mode 100644 index 0000000..7bf2878 --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/richttextfield.php @@ -0,0 +1,55 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Rich text input field", + "format" => "html", + "allowedElements" => [ + "p", + "strong", + "em", + "li", + "ul", + "ol", + ], + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Rich text input field", + "options" => [ + "multi" => true, + "html" => true, + ], + ], + ], + ], + "data" => [ + 'field' => '

text abc

', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'html', + 'name' => 'field', + 'label' => 'Rich text input field', + 'value' => '

text abc

', + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/selectfield.php b/test/resources/Service/FormDataModelFactoryTest/selectfield.php new file mode 100644 index 0000000..37295dc --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/selectfield.php @@ -0,0 +1,73 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Selection list", + "oneOf" => [ + [ + "const" => "Dog", + "title" => "dog", + ], + [ + "const" => "cat", + "title" => "Cat", + ], + [ + "const" => "mouse", + "title" => "Mouse", + ], + ], + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Selection list", + ], + ], + ], + "data" => [ + 'field' => 'cat', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'select', + 'name' => 'field', + 'label' => 'Selection list', + 'options' => [ + [ + 'label' => 'dog', + 'value' => 'Dog', + 'selected' => false, + ], + [ + 'label' => 'Cat', + 'value' => 'cat', + 'selected' => true, + ], + [ + 'label' => 'Mouse', + 'value' => 'mouse', + 'selected' => false, + ], + ], + 'value' => 'Cat', + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/textfield.php b/test/resources/Service/FormDataModelFactoryTest/textfield.php new file mode 100644 index 0000000..cb4e5ef --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/textfield.php @@ -0,0 +1,46 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "Single-line text field", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "Single-line text field", + "options" => [ + "autocomplete" => "name", + "spaceAfter" => true, + ], + ], + ], + ], + "data" => [ + 'field' => 'text', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field', + 'label' => 'Single-line text field', + 'value' => 'text', + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/uploadfield.php b/test/resources/Service/FormDataModelFactoryTest/uploadfield.php new file mode 100644 index 0000000..39fd95f --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/uploadfield.php @@ -0,0 +1,57 @@ + [ + "type" => "object", + "properties" => [ + "field" => [ + "type" => "string", + "title" => "File upload", + "acceptedFileNames" => [ + "*.png", + "*.jpg", + ], + "maxFileSize" => 2000000, + "acceptedContentTypes" => ["image/*"], + "format" => "data-url", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field", + "label" => "File upload", + "options" => [ + "spaceAfter" => true, + ], + ], + ], + ], + "data" => [ + 'field' => 'data:text/plain;name=text.txt;base64,dGV4dAo=', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'file', + 'name' => 'field', + 'label' => 'File upload', + 'value' => [ + 'filename' => 'text.txt', + 'data' => 'text', + 'size' => 4, + 'contentType' => 'text/plain', + ], + ], + ], + ], + ], +]; diff --git a/test/resources/Service/FormDataModelFactoryTest/withemptyfield.php b/test/resources/Service/FormDataModelFactoryTest/withemptyfield.php new file mode 100644 index 0000000..4ac251c --- /dev/null +++ b/test/resources/Service/FormDataModelFactoryTest/withemptyfield.php @@ -0,0 +1,51 @@ + [ + "type" => "object", + "properties" => [ + "field-1" => [ + "type" => "string", + "title" => "Field 1", + ], + "field-2" => [ + "type" => "string", + "title" => "Field 2", + ], + ], + ], + "uischema" => [ + "type" => "VerticalLayout", + "elements" => [ + [ + "type" => "Control", + "scope" => "#/properties/field-1", + "label" => "Field 1", + ], + [ + "type" => "Control", + "scope" => "#/properties/field-2", + "label" => "Field 2", + ], + ], + ], + "data" => [ + 'field-1' => 'text', + ], + "expected" => [ + [ + 'type' => 'vertical_layout', + 'layout' => true, + 'items' => [ + [ + 'type' => 'text', + 'name' => 'field-1', + 'label' => 'Field 1', + 'value' => 'text', + ], + ], + ], + ], +]; diff --git a/translations/.translation-cache/ar b/translations/.translation-cache/ar new file mode 100644 index 0000000..bc72f56 --- /dev/null +++ b/translations/.translation-cache/ar @@ -0,0 +1 @@ +{"2198048":"السيدة","-1786052594":"تم إرسال الرسالة بواسطة: {مضيف} في {التاريخ} في {الوقت}","97548":"حتى","-498793269":"رقم المنزل","79569":"الموقع","116949":"من","1417991068":"يرجى الاختيار","2047368021":"متفرقات","79326":"الرمز البريدي","-1537606010":"كلمة السر، التكرار","-788578976":"فترة حرة","65804367":"التاريخ","1219549716":"بيانات النموذج","-1861260825":"أوافق على جمع البيانات المطلوبة للخدمات المقدمة هنا واستخدامها.","-1442260191":"عنوان البريد الإلكتروني","-446991822":"حذف الملف","-1315720328":"الهاتف المحمول","1125300473":"اختر","-1808122922":"الشارع","1965978561":"التحية","1281629899":"كلمة السر","-191589980":"غير محدد","-866113391":"تكرار عنوان البريد الإلكتروني","-836852440":"يُرجى تأكيد إقرار الموافقة.","1622469635":"اللقب","-868531965":"حماية البيانات","1804339638":"Websiteتم إرسال الرسالة التالية من .","1583329189":"فئات فرعية أخرى إلى","235292859":"الهاتف","499381181":"الفترة","-1992571196":"الاسم الأول","2245661":"السيد"} \ No newline at end of file diff --git a/translations/.translation-cache/bg b/translations/.translation-cache/bg new file mode 100644 index 0000000..9afbdbe --- /dev/null +++ b/translations/.translation-cache/bg @@ -0,0 +1 @@ +{"2198048":"Г-жа","-1786052594":"Message sent by: {хост} на {дата} в {време}","97548":"до","-498793269":"Номер на къщата","1417991068":"моля, изберете","-788578976":"свободен период","65804367":"дата","1219549716":"Данни от формуляра","-1442260191":"Адрес на електронна поща","1281629899":"парола","-191589980":"Не е посочено","-836852440":"Моля, потвърдете декларацията за съгласие.","1622469635":"Фамилно име","-868531965":"Защита на данните","1804339638":"WebsiteСледното съобщение беше изпратено от вашия .","235292859":"Телефон","2245661":"Г-н","79569":"Местоположение","116949":"от","2047368021":"Различни","79326":"ПОЩЕНСКИ КОД","-1537606010":"Парола, повторение","-1861260825":"Съгласен съм данните, необходими за предлаганите тук услуги, да бъдат събирани и използвани.","-446991822":"Изтриване на файла","-1315720328":"Мобилен телефон","1125300473":"изберете","-1808122922":"Улица","1965978561":"Поздрав","-866113391":"Повтаряне на имейл адреса","1583329189":"допълнителни подкатегории към","499381181":"Период","-1992571196":"Първо име"} \ No newline at end of file diff --git a/translations/.translation-cache/cs b/translations/.translation-cache/cs new file mode 100644 index 0000000..8cca916 --- /dev/null +++ b/translations/.translation-cache/cs @@ -0,0 +1 @@ +{"2198048":"Paní","-1786052594":"Zprávu odeslal: {host} dne {datum} v {čas}.","97548":"do","-498793269":"Číslo domu","1417991068":"vyberte si prosím","-788578976":"volné období","65804367":"datum","1219549716":"Formulářové údaje","-1442260191":"E-mailová adresa","1281629899":"heslo","-191589980":"Není specifikováno","-836852440":"Potvrďte prosím prohlášení o souhlasu.","1622469635":"Příjmení","-868531965":"Ochrana údajů","1804339638":"WebsiteNásledující zpráva byla odeslána z vašeho .","235292859":"Telefon","2245661":"Pan","79569":"Místo","116949":"z","2047368021":"Různé","79326":"POSTCODE","-1537606010":"Heslo, opakování","-1861260825":"Souhlasím s tím, že údaje potřebné pro zde nabízené služby mohou být shromažďovány a používány.","-446991822":"Smazat soubor","-1315720328":"Mobilní telefon","1125300473":"vybrat","-1808122922":"Ulice","1965978561":"Pozdrav","-866113391":"Opakování e-mailové adresy","1583329189":"další podkategorie na","499381181":"Období","-1992571196":"Křestní jméno"} \ No newline at end of file diff --git a/translations/.translation-cache/da b/translations/.translation-cache/da new file mode 100644 index 0000000..765d725 --- /dev/null +++ b/translations/.translation-cache/da @@ -0,0 +1 @@ +{"2198048":"Fru","-1786052594":"Besked sendt af: {host} den {dato} kl. {tidspunkt}.","97548":"indtil","-498793269":"Husnummer","1417991068":"Vælg venligst","-788578976":"fri periode","65804367":"dato","1219549716":"Formular-data","-1442260191":"E-mail-adresse","1281629899":"adgangskode","-191589980":"Ikke specificeret","-836852440":"Bekræft venligst samtykkeerklæringen.","1622469635":"Efternavn","-868531965":"Beskyttelse af data","1804339638":"WebsiteFølgende besked blev sendt fra din .","235292859":"Telefon","2245661":"Hr.","79569":"Sted","116949":"fra","2047368021":"Diverse","79326":"POSTKODE","-1537606010":"Adgangskode, gentagelse","-1861260825":"Jeg accepterer, at de data, der er nødvendige for de tjenester, der tilbydes her, kan indsamles og bruges.","-446991822":"Slet filen","-1315720328":"Mobiltelefon","1125300473":"Vælg","-1808122922":"Gade","1965978561":"Hilsen","-866113391":"Gentag e-mail-adresse","1583329189":"yderligere underkategorier til","499381181":"Periode","-1992571196":"Fornavn"} \ No newline at end of file diff --git a/translations/.translation-cache/el b/translations/.translation-cache/el new file mode 100644 index 0000000..986ddad --- /dev/null +++ b/translations/.translation-cache/el @@ -0,0 +1 @@ +{"2198048":"Κυρία","-1786052594":"Μήνυμα εστάλη από: {host} στις {ημερομηνία} στις {ώρα}","97548":"μέχρι το","-498793269":"Αριθμός σπιτιού","1417991068":"παρακαλώ επιλέξτε","-788578976":"ελεύθερη περίοδος","65804367":"ημερομηνία","1219549716":"Δεδομένα φόρμας","-1442260191":"Διεύθυνση ηλεκτρονικού ταχυδρομείου","1281629899":"κωδικός πρόσβασης","-191589980":"Δεν προσδιορίζεται","-836852440":"Παρακαλούμε επιβεβαιώστε τη δήλωση συγκατάθεσης.","1622469635":"Επώνυμο","-868531965":"Προστασία δεδομένων","1804339638":"WebsiteΤο ακόλουθο μήνυμα εστάλη από το .","235292859":"Τηλέφωνο","2245661":"Κύριε","79569":"Τόπος","116949":"από το","2047368021":"Διάφορα","79326":"ΤΑΧΥΔΡΟΜΙΚΟΣ ΚΩΔΙΚΟΣ","-1537606010":"Κωδικός πρόσβασης, επανάληψη","-1861260825":"Συμφωνώ ότι τα δεδομένα που απαιτούνται για τις υπηρεσίες που προσφέρονται εδώ μπορούν να συλλεχθούν και να χρησιμοποιηθούν.","-446991822":"Διαγραφή αρχείου","-1315720328":"Κινητό τηλέφωνο","1125300473":"επιλέξτε","-1808122922":"Οδός","1965978561":"Χαιρετισμός","-866113391":"Επανάληψη της διεύθυνσης ηλεκτρονικού ταχυδρομείου","1583329189":"περαιτέρω υποκατηγορίες για να","499381181":"Περίοδος","-1992571196":"Όνομα"} \ No newline at end of file diff --git a/translations/.translation-cache/en-gb b/translations/.translation-cache/en-gb new file mode 100644 index 0000000..d819562 --- /dev/null +++ b/translations/.translation-cache/en-gb @@ -0,0 +1 @@ +{"2198048":"Mrs","-1786052594":"Message sent by: {host} on {date} at {time}","97548":"until","-498793269":"House number","1417991068":"please choose","-788578976":"free period","65804367":"date","1219549716":"Form data","-1442260191":"E-mail address","1281629899":"password","-191589980":"Not specified","-836852440":"Please confirm the declaration of consent.","1622469635":"Surname","-868531965":"Data protection","1804339638":"The following message was sent from your Website.","235292859":"Telephone","2245661":"Mr","79569":"Place","116949":"from","2047368021":"Miscellaneous","79326":"POSTCODE","-1537606010":"Password, repetition","-1861260825":"I agree that the data required for the services offered here may be collected and used.","-446991822":"Delete file","-1315720328":"Mobile phone","1125300473":"select","-1808122922":"Street","1965978561":"Salutation","-866113391":"Repeat e-mail address","1583329189":"further subcategories to","499381181":"Period","-1992571196":"First name"} \ No newline at end of file diff --git a/translations/.translation-cache/en-us b/translations/.translation-cache/en-us new file mode 100644 index 0000000..9017f3c --- /dev/null +++ b/translations/.translation-cache/en-us @@ -0,0 +1 @@ +{"2198048":"Woman","-1786052594":"Message sent by: {host} on {date} at {time}","97548":"to","-498793269":"House number","1417991068":"please choose","-788578976":"free period","65804367":"Date","1219549716":"Form data","-1442260191":"E-mail address","1281629899":"password","-191589980":"Not specified","-836852440":"Please confirm the declaration of consent.","1622469635":"Surname","-868531965":"Data protection","1804339638":"The following message was sent from your Website.","235292859":"Telephone","2245661":"Mr.","79569":"Location","116949":"from","2047368021":"Miscellaneous","79326":"ZIP CODE","-1537606010":"Password, repetition","-1861260825":"I agree that the data required for the services offered here may be collected and used.","-446991822":"Delete file","-1315720328":"Cell phone","1125300473":"select","-1808122922":"Street","1965978561":"Salutation","-866113391":"Repeat e-mail address","1583329189":"further subcategories to","499381181":"Period","-1992571196":"First name"} \ No newline at end of file diff --git a/translations/.translation-cache/es b/translations/.translation-cache/es new file mode 100644 index 0000000..815501a --- /dev/null +++ b/translations/.translation-cache/es @@ -0,0 +1 @@ +{"2198048":"Sra.","-1786052594":"Mensaje enviado por: {host} el {date} a las {time}","97548":"hasta","-498793269":"Número de casa","1417991068":"elija","-788578976":"período libre","65804367":"fecha","1219549716":"Datos del formulario","-1442260191":"Correo electrónico","1281629899":"contraseña","-191589980":"No especificado","-836852440":"Por favor, confirme la declaración de consentimiento.","1622469635":"Apellido","-868531965":"Protección de datos","1804339638":"WebsiteEl siguiente mensaje fue enviado desde su .","235292859":"Teléfono","2245661":"Sr.","79569":"Lugar","116949":"de","2047368021":"Varios","79326":"CÓDIGO POSTAL","-1537606010":"Contraseña, repetición","-1861260825":"Acepto que se recojan y utilicen los datos necesarios para los servicios aquí ofrecidos.","-446991822":"Eliminar archivo","-1315720328":"Teléfono móvil","1125300473":"seleccione","-1808122922":"Calle","1965978561":"Saludo","-866113391":"Repita la dirección de correo electrónico","1583329189":"otras subcategorías para","499381181":"Periodo","-1992571196":"Nombre"} \ No newline at end of file diff --git a/translations/.translation-cache/et b/translations/.translation-cache/et new file mode 100644 index 0000000..b1dff27 --- /dev/null +++ b/translations/.translation-cache/et @@ -0,0 +1 @@ +{"2198048":"Proua","-1786052594":"Sõnum saatis: {host} {kuupäev} kell {kellaaeg}","97548":"kuni","-498793269":"Maja number","1417991068":"palun valige","-788578976":"vaba periood","65804367":"kuupäev","1219549716":"Vormi andmed","-1442260191":"E-posti aadress","1281629899":"parool","-191589980":"Ei ole täpsustatud","-836852440":"Palun kinnitage nõusoleku deklaratsioon.","1622469635":"Perekonnanimi","-868531965":"Andmekaitse","1804339638":"WebsiteJärgmine sõnum saadeti teie .","235292859":"Telefon","2245661":"Härra","79569":"Koht","116949":"aadressilt","2047368021":"Mitmesugused","79326":"POSTIINFO","-1537606010":"Salasõna, kordus","-1861260825":"Olen nõus, et siin pakutavate teenuste jaoks vajalikke andmeid võib koguda ja kasutada.","-446991822":"Kustuta fail","-1315720328":"Mobiiltelefon","1125300473":"valige","-1808122922":"Street","1965978561":"Tervitus","-866113391":"E-posti aadressi kordamine","1583329189":"täiendavad alamkategooriad, et","499381181":"Ajavahemik","-1992571196":"Eesnimi"} \ No newline at end of file diff --git a/translations/.translation-cache/fi b/translations/.translation-cache/fi new file mode 100644 index 0000000..beee82c --- /dev/null +++ b/translations/.translation-cache/fi @@ -0,0 +1 @@ +{"2198048":"Rouva","-1786052594":"Viestin lähetti: {host} {päivänä} klo {aika}","97548":"kunnes","-498793269":"Talon numero","1417991068":"valitse","-788578976":"vapaa-aika","65804367":"päivämäärä","1219549716":"Lomakkeen tiedot","-1442260191":"Sähköpostiosoite","1281629899":"salasana","-191589980":"Ei määritelty","-836852440":"Vahvistakaa suostumusilmoitus.","1622469635":"Sukunimi","-868531965":"Tietosuoja","1804339638":"WebsiteSeuraava viesti lähetettiin sinun .","235292859":"Puhelin","2245661":"Herra","79569":"Paikka","116949":"osoitteesta","2047368021":"Sekalaiset","79326":"POSTINUMERO","-1537606010":"Salasana, toisto","-1861260825":"Hyväksyn, että täällä tarjottujen palvelujen edellyttämiä tietoja voidaan kerätä ja käyttää.","-446991822":"Poista tiedosto","-1315720328":"Matkapuhelin","1125300473":"valitse","-1808122922":"Street","1965978561":"Tervehdys","-866113391":"Toista sähköpostiosoite","1583329189":"muita alaluokkia","499381181":"Jakso","-1992571196":"Etunimi"} \ No newline at end of file diff --git a/translations/.translation-cache/fr b/translations/.translation-cache/fr new file mode 100644 index 0000000..d8191a7 --- /dev/null +++ b/translations/.translation-cache/fr @@ -0,0 +1 @@ +{"2198048":"Mme","-1786052594":"Message envoyé par : {host} le {date} à {time} heures","97548":"jusqu'à","-498793269":"Numéro de maison","1417991068":"choisir svp","-788578976":"période libre","65804367":"Date","1219549716":"Données du formulaire","-1442260191":"Adresse électronique","1281629899":"Mot de passe","-191589980":"Aucune indication","-836852440":"Veuillez confirmer le consentement.","1622469635":"Nom de famille","-868531965":"Protection des données","1804339638":"Le message suivant a été envoyé par votre Website.","235292859":"Téléphone","2245661":"Monsieur","79569":"Lieu","116949":"de","2047368021":"Divers","79326":"CODE POSTAL","-1537606010":"Mot de passe, répétition","-1861260825":"J'accepte que les données nécessaires soient collectées et utilisées pour les services proposés ici.","-446991822":"Supprimer un fichier","-1315720328":"Téléphone portable","1125300473":"sélectionner","-1808122922":"Rue","1965978561":"Titre de civilité","-866113391":"Répéter l'adresse e-mail","1583329189":"autres sous-catégories de","499381181":"Période","-1992571196":"Prénom"} \ No newline at end of file diff --git a/translations/.translation-cache/hu b/translations/.translation-cache/hu new file mode 100644 index 0000000..617432a --- /dev/null +++ b/translations/.translation-cache/hu @@ -0,0 +1 @@ +{"2198048":"Mrs","-1786052594":"Üzenetet küldött:: {host} a {dátum} {időpontban}","97548":"amíg","-498793269":"Házszám","1417991068":"Kérjük, válasszon","-788578976":"szabadidő","65804367":"dátum","1219549716":"Formanyomtatvány adatok","-1442260191":"E-mail cím","1281629899":"jelszó","-191589980":"Nincs megadva","-836852440":"Kérjük, erősítse meg a hozzájáruló nyilatkozatot.","1622469635":"Vezetéknév","-868531965":"Adatvédelem","1804339638":"WebsiteA következő üzenetet küldte az Ön .","235292859":"Telefon","2245661":"Mr","79569":"Helyszín","116949":"a címről","2047368021":"Egyéb","79326":"POSTACÍM","-1537606010":"Jelszó, ismétlés","-1861260825":"Hozzájárulok, hogy az itt kínált szolgáltatásokhoz szükséges adatokat összegyűjtsék és felhasználják.","-446991822":"Fájl törlése","-1315720328":"Mobiltelefon","1125300473":"válassza ki a címet.","-1808122922":"Street","1965978561":"Üdvözlés","-866113391":"E-mail cím megismétlése","1583329189":"további alkategóriák","499381181":"Időszak","-1992571196":"Keresztnév"} \ No newline at end of file diff --git a/translations/.translation-cache/id b/translations/.translation-cache/id new file mode 100644 index 0000000..5b9b1c6 --- /dev/null +++ b/translations/.translation-cache/id @@ -0,0 +1 @@ +{"2198048":"Nyonya","-1786052594":"Pesan dikirim oleh: {host} pada {tanggal} di {waktu}","97548":"sampai","-498793269":"Nomor rumah","1417991068":"silakan pilih","-788578976":"periode bebas","65804367":"tanggal","1219549716":"Formulir data","-1442260191":"Alamat email","1281629899":"kata sandi","-191589980":"Tidak ditentukan","-836852440":"Mohon konfirmasikan pernyataan persetujuan.","1622469635":"Nama keluarga","-868531965":"Perlindungan data","1804339638":"WebsitePesan berikut ini dikirim dari .","235292859":"Telepon","2245661":"Mr.","79569":"Tempat","116949":"dari","2047368021":"Lain-lain","79326":"KODE POS","-1537606010":"Kata sandi, pengulangan","-1861260825":"Saya setuju bahwa data yang diperlukan untuk layanan yang ditawarkan di sini dapat dikumpulkan dan digunakan.","-446991822":"Menghapus file","-1315720328":"Ponsel","1125300473":"pilih","-1808122922":"Jalan","1965978561":"Salam","-866113391":"Ulangi alamat email","1583329189":"subkategori lebih lanjut ke","499381181":"Periode","-1992571196":"Nama depan"} \ No newline at end of file diff --git a/translations/.translation-cache/it b/translations/.translation-cache/it new file mode 100644 index 0000000..6a02938 --- /dev/null +++ b/translations/.translation-cache/it @@ -0,0 +1 @@ +{"2198048":"Signora","-1786052594":"Messaggio inviato da: {host} il {data} all' {ora}","97548":"fino a quando","-498793269":"Numero civico","1417991068":"scegliere","-788578976":"periodo libero","65804367":"data","1219549716":"Dati del modulo","-1442260191":"Indirizzo e-mail","1281629899":"password","-191589980":"Non specificato","-836852440":"Confermare la dichiarazione di consenso.","1622469635":"Cognome","-868531965":"Protezione dei dati","1804339638":"WebsiteIl seguente messaggio è stato inviato dal vostro .","235292859":"Telefono","2245661":"Il Sig.","79569":"Luogo","116949":"da","2047368021":"Varie","79326":"CAP","-1537606010":"Password, ripetizione","-1861260825":"Acconsento alla raccolta e all'utilizzo dei dati necessari per i servizi offerti.","-446991822":"Cancellare il file","-1315720328":"Telefono cellulare","1125300473":"selezionare","-1808122922":"Via","1965978561":"Saluto","-866113391":"Ripetere l'indirizzo e-mail","1583329189":"ulteriori sottocategorie per","499381181":"Periodo","-1992571196":"Nome"} \ No newline at end of file diff --git a/translations/.translation-cache/ja b/translations/.translation-cache/ja new file mode 100644 index 0000000..95daea6 --- /dev/null +++ b/translations/.translation-cache/ja @@ -0,0 +1 @@ +{"2198048":"夫人","-1786052594":"メッセージ送信者{ホスト} on {日付} at {時刻}.","97548":"まで","-498793269":"家屋番号","1417991068":"選択してください","-788578976":"休み時間","65804367":"日付","1219549716":"フォームデータ","-1442260191":"Eメールアドレス","1281629899":"パスワード","-191589980":"特になし","-836852440":"同意宣言をご確認ください。","1622469635":"苗字","-868531965":"データ保護","1804339638":".NETから以下のメッセージが送信されました。","235292859":"電話","2245661":"ミスター","79569":"場所","116949":"より","2047368021":"その他","79326":"郵便番号","-1537606010":"パスワード、繰り返し","-1861260825":"私は、ここで提供されるサービスに必要なデータが収集され使用されることに同意します。","-446991822":"ファイルの削除","-1315720328":"携帯電話","1125300473":"選ぶ","-1808122922":"ストリート","1965978561":"挨拶","-866113391":"リピートEメールアドレス","1583329189":"にはさらにサブカテゴリーがある。","499381181":"期間","-1992571196":"名前"} \ No newline at end of file diff --git a/translations/.translation-cache/ko b/translations/.translation-cache/ko new file mode 100644 index 0000000..2af336e --- /dev/null +++ b/translations/.translation-cache/ko @@ -0,0 +1 @@ +{"2198048":"부인","-1786052594":"보낸 메시지입니다: {호스트}가 {날짜}에 {시간}에 보낸 메시지입니다.","97548":"까지","-498793269":"집 번호","1417991068":"선택해 주세요","-788578976":"무료 기간","65804367":"날짜","1219549716":"양식 데이터","-1442260191":"이메일 주소","1281629899":"비밀번호","-191589980":"지정되지 않음","-836852440":"동의 선언을 확인해 주세요.","1622469635":"성","-868531965":"데이터 보호","1804339638":"Website에서 다음 메시지가 전송되었습니다.","235292859":"전화","2245661":"Mr","79569":"위치","116949":"에서","2047368021":"기타","79326":"포스트코드","-1537606010":"비밀번호, 반복","-1861260825":"본인은 여기에서 제공하는 서비스에 필요한 데이터를 수집하고 사용할 수 있음에 동의합니다.","-446991822":"파일 삭제","-1315720328":"휴대폰","1125300473":"선택","-1808122922":"거리","1965978561":"인사말","-866113391":"이메일 주소 반복","1583329189":"추가 하위 카테고리","499381181":"기간","-1992571196":"이름"} \ No newline at end of file diff --git a/translations/.translation-cache/lt b/translations/.translation-cache/lt new file mode 100644 index 0000000..0bc3e81 --- /dev/null +++ b/translations/.translation-cache/lt @@ -0,0 +1 @@ +{"2198048":"Ponia","-1786052594":"Pranešimą atsiuntė: {host}, {data}, {laikas}.","97548":"iki","-498793269":"Namo numeris","1417991068":"pasirinkite","-788578976":"laisvas laikotarpis","65804367":"data","1219549716":"Formos duomenys","-1442260191":"el. pašto adresas","1281629899":"slaptažodis","-191589980":"Nenurodyta","-836852440":"Patvirtinkite sutikimo deklaraciją.","1622469635":"Pavardė","-868531965":"Duomenų apsauga","1804339638":"WebsiteŠis pranešimas buvo išsiųstas iš jūsų .","235292859":"Telefonas","2245661":"Ponas","79569":"Vieta","116949":"iš","2047368021":"Įvairūs","79326":"POSTCODE","-1537606010":"Slaptažodis, kartojimas","-1861260825":"Sutinku, kad čia siūlomoms paslaugoms reikalingi duomenys gali būti renkami ir naudojami.","-446991822":"Ištrinti failą","-1315720328":"Mobilusis telefonas","1125300473":"pasirinkite","-1808122922":"Gatvė","1965978561":"Pasveikinimas","-866113391":"Pakartokite el. pašto adresą","1583329189":"kitos subkategorijos","499381181":"Laikotarpis","-1992571196":"Vardas ir pavardė"} \ No newline at end of file diff --git a/translations/.translation-cache/lv b/translations/.translation-cache/lv new file mode 100644 index 0000000..323f5c7 --- /dev/null +++ b/translations/.translation-cache/lv @@ -0,0 +1 @@ +{"2198048":"kundze","-1786052594":"Ziņu nosūtīja: {host} {datos} plkst. {laikā}","97548":"līdz","-498793269":"Mājas numurs","1417991068":"lūdzu, izvēlieties","-788578976":"bezmaksas periods","65804367":"datums","1219549716":"Veidlapu dati","-1442260191":"E-pasta adrese","1281629899":"parole","-191589980":"Nav norādīts","-836852440":"Lūdzu, apstipriniet piekrišanas deklarāciju.","1622469635":"Uzvārds","-868531965":"Datu aizsardzība","1804339638":"WebsiteŠāds ziņojums tika nosūtīts no jūsu .","235292859":"Tālrunis","2245661":"kungs","79569":"Vieta","116949":"no","2047368021":"Dažādi","79326":"POSTCODE","-1537606010":"Parole, atkārtošana","-1861260825":"Es piekrītu, ka šeit piedāvātajiem pakalpojumiem nepieciešamie dati var tikt vākti un izmantoti.","-446991822":"Dzēst failu","-1315720328":"Mobilais tālrunis","1125300473":"atlasīt","-1808122922":"Ielas","1965978561":"Sveiciens","-866113391":"Atkārtota e-pasta adrese","1583329189":"papildu apakškategorijas, lai","499381181":"Periods","-1992571196":"Vārds"} \ No newline at end of file diff --git a/translations/.translation-cache/nb b/translations/.translation-cache/nb new file mode 100644 index 0000000..1c19f96 --- /dev/null +++ b/translations/.translation-cache/nb @@ -0,0 +1 @@ +{"2198048":"Fru","-1786052594":"Melding sendt av: {host} den {dato} kl {klokkeslett}","97548":"inntil","-498793269":"Husnummer","1417991068":"vennligst velg","-788578976":"fri periode","65804367":"dato","1219549716":"Skjemadata","-1442260191":"E-postadresse","1281629899":"passord","-191589980":"Ikke spesifisert","-836852440":"Vennligst bekreft samtykkeerklæringen.","1622469635":"Etternavn","-868531965":"Beskyttelse av personopplysninger","1804339638":"WebsiteFølgende melding ble sendt fra din .","235292859":"Telefon","2245661":"Mr.","79569":"Sted","116949":"fra","2047368021":"Diverse","79326":"POSTCODE","-1537606010":"Passord, repetisjon","-1861260825":"Jeg samtykker i at opplysningene som kreves for tjenestene som tilbys her, kan samles inn og brukes.","-446991822":"Slett fil","-1315720328":"Mobiltelefon","1125300473":"velg","-1808122922":"Gate","1965978561":"Hilsen","-866113391":"Gjenta e-postadressen","1583329189":"ytterligere underkategorier til","499381181":"Periode","-1992571196":"Fornavn"} \ No newline at end of file diff --git a/translations/.translation-cache/nl b/translations/.translation-cache/nl new file mode 100644 index 0000000..b407ae6 --- /dev/null +++ b/translations/.translation-cache/nl @@ -0,0 +1 @@ +{"2198048":"Mevrouw","-1786052594":"Bericht verzonden door: {host} op {datum} om {tijd}","97548":"tot","-498793269":"Huisnummer","1417991068":"kies","-788578976":"vrije periode","65804367":"datum","1219549716":"Formuliergegevens","-1442260191":"E-mailadres","1281629899":"wachtwoord","-191589980":"Niet gespecificeerd","-836852440":"Bevestig de toestemmingsverklaring.","1622469635":"Achternaam","-868531965":"Gegevensbescherming","1804339638":"WebsiteHet volgende bericht is verzonden vanuit uw .","235292859":"Telefoon","2245661":"De heer","79569":"Locatie","116949":"van","2047368021":"Diverse","79326":"POSTCODE","-1537606010":"Wachtwoord, herhaling","-1861260825":"Ik ga ermee akkoord dat de gegevens die nodig zijn voor de hier aangeboden diensten worden verzameld en gebruikt.","-446991822":"Bestand verwijderen","-1315720328":"Mobiele telefoon","1125300473":"selecteer","-1808122922":"Straat","1965978561":"Begroeting","-866113391":"E-mailadres herhalen","1583329189":"verdere subcategorieën naar","499381181":"Periode","-1992571196":"Voornaam"} \ No newline at end of file diff --git a/translations/.translation-cache/pl b/translations/.translation-cache/pl new file mode 100644 index 0000000..091bc3b --- /dev/null +++ b/translations/.translation-cache/pl @@ -0,0 +1 @@ +{"2198048":"Pani","-1786052594":"Wiadomość wysłana przez: {host} w dniu {data} o godzinie {godzina}","97548":"do","-498793269":"Numer domu","1417991068":"wybierz","-788578976":"okres wolny","65804367":"data","1219549716":"Dane formularza","-1442260191":"Adres e-mail","1281629899":"hasło","-191589980":"Nie określono","-836852440":"Prosimy o potwierdzenie deklaracji zgody.","1622469635":"Nazwisko","-868531965":"Ochrona danych","1804339638":"WebsiteNastępująca wiadomość została wysłana z Twojego .","235292859":"Telefon","2245661":"Pan","79569":"Lokalizacja","116949":"z","2047368021":"Różne","79326":"KOD POCZTOWY","-1537606010":"Hasło, powtórzenie","-1861260825":"Wyrażam zgodę na gromadzenie i wykorzystywanie danych wymaganych do korzystania z oferowanych tutaj usług.","-446991822":"Usuń plik","-1315720328":"Telefon komórkowy","1125300473":"wybór","-1808122922":"ul.","1965978561":"Pozdrowienie","-866113391":"Powtórzony adres e-mail","1583329189":"dalsze podkategorie do","499381181":"Okres","-1992571196":"Imię"} \ No newline at end of file diff --git a/translations/.translation-cache/pt-br b/translations/.translation-cache/pt-br new file mode 100644 index 0000000..1910177 --- /dev/null +++ b/translations/.translation-cache/pt-br @@ -0,0 +1 @@ +{"2198048":"Senhora","-1786052594":"Mensagem enviada por: {host} em {date} às {time}","97548":"até que","-498793269":"Número da casa","1417991068":"escolha","-788578976":"período livre","65804367":"data","1219549716":"Dados do formulário","-1442260191":"Endereço de e-mail","1281629899":"senha","-191589980":"Não especificado","-836852440":"Por favor, confirme a declaração de consentimento.","1622469635":"Sobrenome","-868531965":"Proteção de dados","1804339638":"WebsiteA seguinte mensagem foi enviada de seu .","235292859":"Telefone","2245661":"Senhor","79569":"Local","116949":"de","2047368021":"Diversos","79326":"CÓDIGO POSTAL","-1537606010":"Senha, repetição","-1861260825":"Concordo que os dados necessários para os serviços oferecidos aqui podem ser coletados e usados.","-446991822":"Excluir arquivo","-1315720328":"Telefone celular","1125300473":"selecionar","-1808122922":"Rua","1965978561":"Saudação","-866113391":"Repetir endereço de e-mail","1583329189":"outras subcategorias para","499381181":"Período","-1992571196":"Primeiro nome"} \ No newline at end of file diff --git a/translations/.translation-cache/pt-pt b/translations/.translation-cache/pt-pt new file mode 100644 index 0000000..938c587 --- /dev/null +++ b/translations/.translation-cache/pt-pt @@ -0,0 +1 @@ +{"2198048":"Senhora","-1786052594":"Mensagem enviada por: {host} em {date} às {time}","97548":"até","-498793269":"Número da casa","1417991068":"escolha","-788578976":"período livre","65804367":"data","1219549716":"Dados do formulário","-1442260191":"endereço eletrónico","1281629899":"palavra-passe","-191589980":"Não especificado","-836852440":"Por favor, confirme a declaração de consentimento.","1622469635":"Apelido","-868531965":"Proteção de dados","1804339638":"WebsiteA seguinte mensagem foi enviada do seu .","235292859":"Telefone","2245661":"Senhor","79569":"Local","116949":"de","2047368021":"Diversos","79326":"CÓDIGO POSTAL","-1537606010":"Palavra-passe, repetição","-1861260825":"Aceito que os dados necessários para os serviços aqui oferecidos possam ser recolhidos e utilizados.","-446991822":"Eliminar ficheiro","-1315720328":"Telemóvel","1125300473":"selecionar","-1808122922":"Rua","1965978561":"Saudação","-866113391":"Repetir o endereço de correio eletrónico","1583329189":"outras subcategorias para","499381181":"Período","-1992571196":"Nome próprio"} \ No newline at end of file diff --git a/translations/.translation-cache/ro b/translations/.translation-cache/ro new file mode 100644 index 0000000..0fac276 --- /dev/null +++ b/translations/.translation-cache/ro @@ -0,0 +1 @@ +{"2198048":"Doamnă","-1786052594":"Mesaj trimis de: {host} pe {data} la {ora}","97548":"până când","-498793269":"Numărul casei","79569":"Loc","116949":"de la","1417991068":"vă rugăm să alegeți","2047368021":"Diverse","79326":"COD POȘTAL","-1537606010":"Parolă, repetiție","-788578976":"perioadă liberă","65804367":"data","1219549716":"Datele formularului","-1861260825":"Sunt de acord că datele necesare pentru serviciile oferite aici pot fi colectate și utilizate.","-1442260191":"Adresa de e-mail","-446991822":"Ștergeți fișierul","-1315720328":"Telefon mobil","1125300473":"selectați","-1808122922":"Strada","1965978561":"Salutul","1281629899":"parolă","-191589980":"Nu este specificat","-866113391":"Repetați adresa de e-mail","-836852440":"Vă rugăm să confirmați declarația de consimțământ.","1622469635":"Numele de familie","-868531965":"Protecția datelor","1804339638":"WebsiteUrmătorul mesaj a fost trimis din .","1583329189":"subcategorii suplimentare pentru","235292859":"Telefon","499381181":"Perioada","-1992571196":"Numele și prenumele","2245661":"Dl"} \ No newline at end of file diff --git a/translations/.translation-cache/ru b/translations/.translation-cache/ru new file mode 100644 index 0000000..c963f41 --- /dev/null +++ b/translations/.translation-cache/ru @@ -0,0 +1 @@ +{"2198048":"Миссис","-1786052594":"Сообщение отправлено: {host} в {дата} в {время}","97548":"до","-498793269":"Номер дома","79569":"Расположение","116949":"с сайта","1417991068":"пожалуйста, выберите","2047368021":"Разное","79326":"ПОЧТОВЫЙ ИНДЕКС","-1537606010":"Пароль, повторение","-788578976":"свободный период","65804367":"дата","1219549716":"Данные формы","-1861260825":"Я согласен с тем, что данные, необходимые для предлагаемых здесь услуг, могут быть собраны и использованы.","-1442260191":"Адрес электронной почты","-446991822":"Удалить файл","-1315720328":"Мобильный телефон","1125300473":"выберите","-1808122922":"Улица","1965978561":"Приветствие","1281629899":"пароль","-191589980":"Не указано","-866113391":"Повторите адрес электронной почты","-836852440":"Пожалуйста, подтвердите заявление о согласии.","1622469635":"Фамилия","-868531965":"Защита данных","1804339638":"WebsiteСледующее сообщение было отправлено с вашего .","1583329189":"дополнительные подкатегории к","235292859":"Телефон","499381181":"Период","-1992571196":"Имя","2245661":"Мистер"} \ No newline at end of file diff --git a/translations/.translation-cache/sk b/translations/.translation-cache/sk new file mode 100644 index 0000000..1ea1d50 --- /dev/null +++ b/translations/.translation-cache/sk @@ -0,0 +1 @@ +{"2198048":"Pani","-1786052594":"Správu poslal: {hostiteľ} dňa {dátum} v {čas}","97548":"do","-498793269":"Číslo domu","79569":"Miesto","116949":"z adresy","1417991068":"vyberte si, prosím,","2047368021":"Rôzne","79326":"POSTCODE","-1537606010":"Heslo, opakovanie","-788578976":"voľné obdobie","65804367":"dátum","1219549716":"Údaje vo formulári","-1861260825":"Súhlasím so zhromažďovaním a používaním údajov potrebných pre tu ponúkané služby.","-1442260191":"e-mailová adresa","-446991822":"Odstrániť súbor","-1315720328":"Mobilný telefón","1125300473":"vybrať","-1808122922":"Ulica","1965978561":"Pozdrav","1281629899":"heslo","-191589980":"Nie je špecifikované","-866113391":"Opakovanie e-mailovej adresy","-836852440":"Potvrďte, prosím, vyhlásenie o súhlase.","1622469635":"Priezvisko","-868531965":"Ochrana údajov","1804339638":"WebsiteNasledujúca správa bola odoslaná z vášho .","1583329189":"ďalšie podkategórie","235292859":"Telefón","499381181":"Obdobie","-1992571196":"Krstné meno","2245661":"Pán"} \ No newline at end of file diff --git a/translations/.translation-cache/sl b/translations/.translation-cache/sl new file mode 100644 index 0000000..93d9231 --- /dev/null +++ b/translations/.translation-cache/sl @@ -0,0 +1 @@ +{"2198048":"Gospa","-1786052594":"Sporočilo je poslal: {host} na {datum} ob {času}","97548":"do .","-498793269":"Številka hiše","79569":"Kraj","116949":"s spletne strani","1417991068":"izberite","2047368021":"Različni","79326":"POŠTNA KODA","-1537606010":"Geslo, ponavljanje","-788578976":"brezplačno obdobje","65804367":"datum","1219549716":"Podatki v obrazcu","-1861260825":"Strinjam se z zbiranjem in uporabo podatkov, ki so potrebni za opravljanje tukaj ponujenih storitev.","-1442260191":"e-poštni naslov","-446991822":"Izbriši datoteko","-1315720328":"Mobilni telefon","1125300473":"izberite","-1808122922":"Ulica","1965978561":"Pozdrav","1281629899":"geslo","-191589980":"Ni določeno","-866113391":"Ponovite e-poštni naslov","-836852440":"Potrdite izjavo o privolitvi.","1622469635":"Priimek","-868531965":"Varstvo podatkov","1804339638":"WebsiteNaslednje sporočilo je bilo poslano iz vašega .","1583329189":"dodatne podkategorije za","235292859":"Telefon","499381181":"Obdobje","-1992571196":"Ime in priimek","2245661":"Gospod"} \ No newline at end of file diff --git a/translations/.translation-cache/sv b/translations/.translation-cache/sv new file mode 100644 index 0000000..5374568 --- /dev/null +++ b/translations/.translation-cache/sv @@ -0,0 +1 @@ +{"2198048":"Fru","-1786052594":"Meddelande skickat av: {host} den {datum} kl {tid}","97548":"tills","-498793269":"Husnummer","79569":"Plats","116949":"från","1417991068":"Vänligen välj","2047368021":"Övrigt","79326":"POSTKODE","-1537606010":"Lösenord, repetition","-788578976":"fri period","65804367":"datum","1219549716":"Formulärdata","-1861260825":"Jag samtycker till att de uppgifter som krävs för de tjänster som erbjuds här får samlas in och användas.","-1442260191":"E-postadress","-446991822":"Ta bort fil","-1315720328":"Mobiltelefon","1125300473":"Välj","-1808122922":"Gata","1965978561":"Hälsning","1281629899":"Lösenord","-191589980":"Ej specificerat","-866113391":"Upprepa e-postadressen","-836852440":"Vänligen bekräfta samtyckesförklaringen.","1622469635":"Efternamn","-868531965":"Skydd av personuppgifter","1804339638":"WebsiteFöljande meddelande skickades från din .","1583329189":"ytterligare underkategorier till","235292859":"Telefon","499381181":"Period","-1992571196":"Förnamn","2245661":"Herr"} \ No newline at end of file diff --git a/translations/.translation-cache/tr b/translations/.translation-cache/tr new file mode 100644 index 0000000..cffa5bd --- /dev/null +++ b/translations/.translation-cache/tr @@ -0,0 +1 @@ +{"2198048":"Bayan","-1786052594":"Mesaj şu kişi tarafından gönderildi: {ana bilgisayar} tarafından {tarih} tarihinde {saat}","97548":"kadar","-498793269":"Ev numarası","79569":"Konum","116949":"gelen","1417991068":"lütfen seçin","2047368021":"Çeşitli","79326":"POSTA KODU","-1537606010":"Şifre, tekrarlama","-788578976":"serbest dönem","65804367":"Tarih","1219549716":"Form verileri","-1861260825":"Burada sunulan hizmetler için gerekli verilerin toplanabileceğini ve kullanılabileceğini kabul ediyorum.","-1442260191":"e-posta adresi","-446991822":"Dosya silme","-1315720328":"Cep telefonu","1125300473":"seçin","-1808122922":"Sokak","1965978561":"Selamlama","1281629899":"şifre","-191589980":"Belirtilmemiş","-866113391":"E-posta adresini tekrarla","-836852440":"Lütfen onay beyanını onaylayın.","1622469635":"Soyadı","-868531965":"Veri koruma","1804339638":"WebsiteAşağıdaki mesaj tarafınızdan gönderilmiştir.","1583329189":"daha fazla alt kategori","235292859":"Telefon","499381181":"Dönem","-1992571196":"İlk isim","2245661":"Bay"} \ No newline at end of file diff --git a/translations/.translation-cache/uk b/translations/.translation-cache/uk new file mode 100644 index 0000000..b6f3937 --- /dev/null +++ b/translations/.translation-cache/uk @@ -0,0 +1 @@ +{"2198048":"Пані","-1786052594":"Повідомлення відправлено {хост} на {дата} о {час}","97548":"до тих пір, поки","-498793269":"Номер будинку","79569":"Місце","116949":"від","1417991068":"будь ласка, оберіть","2047368021":"Різне","79326":"ПОШТОВИЙ КОД","-1537606010":"Пароль, повторення","-788578976":"безкоштовний період","65804367":"дата","1219549716":"Дані форми","-1861260825":"Я погоджуюся, що дані, необхідні для надання послуг, пропонованих тут, можуть бути зібрані та використані.","-1442260191":"Адреса електронної пошти","-446991822":"Видалити файл","-1315720328":"Мобільний телефон","1125300473":"вибрати","-1808122922":"Вулиця","1965978561":"Привітання","1281629899":"пароль","-191589980":"Не вказано","-866113391":"Повторити адресу електронної пошти","-836852440":"Будь ласка, підтвердіть декларацію про згоду.","1622469635":"Прізвище","-868531965":"Захист даних","1804339638":"WebsiteНаступне повідомлення було надіслано з вашого .","1583329189":"інші підкатегорії до","235292859":"Телефон","499381181":"Крапка","-1992571196":"Ім'я та прізвище","2245661":"Пане"} \ No newline at end of file diff --git a/translations/.translation-cache/zh b/translations/.translation-cache/zh new file mode 100644 index 0000000..aa21e76 --- /dev/null +++ b/translations/.translation-cache/zh @@ -0,0 +1 @@ +{"2198048":"夫人","-1786052594":"信息由{主机}于{日期}在{时间}发送","97548":"直到","-498793269":"门牌号","79569":"地点","116949":"从","1417991068":"请选择","2047368021":"杂项","79326":"邮政编码","-1537606010":"密码,重复","-788578976":"自由活动期","65804367":"日期","1219549716":"表格数据","-1861260825":"我同意收集和使用此处提供的服务所需的数据。","-1442260191":"电子邮件地址","-446991822":"删除文件","-1315720328":"移动电话","1125300473":"遴选","-1808122922":"街道","1965978561":"致辞","1281629899":"暗号","-191589980":"未说明","-866113391":"重复电子邮件地址","-836852440":"请确认同意声明。","1622469635":"姓氏","-868531965":"数据保护","1804339638":"Website以下信息是从您的 .NET 账户发送的","1583329189":"进一步细分为","235292859":"电话","499381181":"期间","-1992571196":"姓名","2245661":"先生"} \ No newline at end of file diff --git a/translations/.translation-cache/zh-hans b/translations/.translation-cache/zh-hans new file mode 100644 index 0000000..41f1225 --- /dev/null +++ b/translations/.translation-cache/zh-hans @@ -0,0 +1 @@ +{"2198048":"夫人","-1786052594":"信息发送者{主机}于{日期}在{时间}发送","97548":"直到","-498793269":"门牌号","79569":"地点","116949":"从","1417991068":"请选择","2047368021":"杂项","79326":"邮政编码","-1537606010":"密码,重复","-788578976":"自由活动期","65804367":"日期","1219549716":"表格数据","-1861260825":"我同意收集和使用此处提供的服务所需的数据。","-1442260191":"电子邮件地址","-446991822":"删除文件","-1315720328":"移动电话","1125300473":"遴选","-1808122922":"街道","1965978561":"致辞","1281629899":"暗号","-191589980":"未说明","-866113391":"重复电子邮件地址","-836852440":"请确认同意声明。","1622469635":"姓氏","-868531965":"数据保护","1804339638":"Website以下信息是从您的 .NET 账户发送的","1583329189":"进一步细分为","235292859":"电话","499381181":"期间","-1992571196":"姓名","2245661":"先生"} \ No newline at end of file diff --git a/translations/form.ar.json b/translations/form.ar.json new file mode 100644 index 0000000..e187cc8 --- /dev/null +++ b/translations/form.ar.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "Websiteتم إرسال الرسالة التالية من .", + "footer" : "تم إرسال الرسالة بواسطة: {مضيف} في {التاريخ} في {الوقت}", + "headline" : "بيانات النموذج" + }, + "field" : { + "webAccount" : { + "salutation.label" : "التحية", + "salutation.salutationMale.label" : "السيد", + "salutation.salutationFemale.label" : "السيدة", + "salutation.salutationDiverse.label" : "متفرقات", + "salutation.salutationNotSpecified.label" : "غير محدد", + "lastname.label" : "اللقب", + "firstname.label" : "الاسم الأول", + "street.label" : "الشارع", + "housenumber.label" : "رقم المنزل", + "postalCode.label" : "الرمز البريدي", + "city.label" : "الموقع", + "tel.label" : "الهاتف", + "mobile.label" : "الهاتف المحمول", + "email.label" : "عنوان البريد الإلكتروني", + "emailCompare.label" : "تكرار عنوان البريد الإلكتروني", + "password.label" : "كلمة السر", + "passwordRepetition.label" : "كلمة السر، التكرار" + }, + "dateFilter" : { + "empty.label" : "فترة حرة" + }, + "dateSelectorComposition.label" : "الفترة", + "date.label" : "التاريخ", + "dateFrom.label" : "من", + "dateTo.label" : "حتى", + "file.deleteFile.label" : "حذف الملف", + "salutation.label" : "التحية", + "salutation.salutationMale.label" : "السيد", + "salutation.salutationFemale.label" : "السيدة", + "salutation.salutationDiverse.label" : "متفرقات", + "salutation.salutationNotSpecified.label" : "غير محدد", + "firstname.label" : "الاسم الأول", + "lastname.label" : "اللقب", + "street.label" : "الشارع", + "housenumber.label" : "رقم المنزل", + "postalCode.label" : "الرمز البريدي", + "city.label" : "الموقع", + "tel.label" : "الهاتف", + "mobile.label" : "الهاتف المحمول", + "email.label" : "عنوان البريد الإلكتروني", + "select.pleaseSelect.label" : "يرجى الاختيار", + "consent" : { + "legend" : "حماية البيانات", + "label" : "أوافق على جمع البيانات المطلوبة للخدمات المقدمة هنا واستخدامها.", + "validator" : { + "required" : { + "message" : "يُرجى تأكيد إقرار الموافقة." + } + } + }, + "file.button.label" : "اختر", + "checkboxTree.furtherSubCategoriesFor.label" : "فئات فرعية أخرى إلى" + } +} \ No newline at end of file diff --git a/translations/form.bg.json b/translations/form.bg.json new file mode 100644 index 0000000..287caef --- /dev/null +++ b/translations/form.bg.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteСледното съобщение беше изпратено от вашия .", + "footer" : "Message sent by: {хост} на {дата} в {време}", + "headline" : "Данни от формуляра" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Поздрав", + "salutation.salutationMale.label" : "Г-н", + "salutation.salutationFemale.label" : "Г-жа", + "salutation.salutationDiverse.label" : "Различни", + "salutation.salutationNotSpecified.label" : "Не е посочено", + "lastname.label" : "Фамилно име", + "firstname.label" : "Първо име", + "street.label" : "Улица", + "housenumber.label" : "Номер на къщата", + "postalCode.label" : "ПОЩЕНСКИ КОД", + "city.label" : "Местоположение", + "tel.label" : "Телефон", + "mobile.label" : "Мобилен телефон", + "email.label" : "Адрес на електронна поща", + "emailCompare.label" : "Повтаряне на имейл адреса", + "password.label" : "парола", + "passwordRepetition.label" : "Парола, повторение" + }, + "dateFilter" : { + "empty.label" : "свободен период" + }, + "dateSelectorComposition.label" : "Период", + "date.label" : "дата", + "dateFrom.label" : "от", + "dateTo.label" : "до", + "file.deleteFile.label" : "Изтриване на файла", + "salutation.label" : "Поздрав", + "salutation.salutationMale.label" : "Г-н", + "salutation.salutationFemale.label" : "Г-жа", + "salutation.salutationDiverse.label" : "Различни", + "salutation.salutationNotSpecified.label" : "Не е посочено", + "firstname.label" : "Първо име", + "lastname.label" : "Фамилно име", + "street.label" : "Улица", + "housenumber.label" : "Номер на къщата", + "postalCode.label" : "ПОЩЕНСКИ КОД", + "city.label" : "Местоположение", + "tel.label" : "Телефон", + "mobile.label" : "Мобилен телефон", + "email.label" : "Адрес на електронна поща", + "select.pleaseSelect.label" : "моля, изберете", + "consent" : { + "legend" : "Защита на данните", + "label" : "Съгласен съм данните, необходими за предлаганите тук услуги, да бъдат събирани и използвани.", + "validator" : { + "required" : { + "message" : "Моля, потвърдете декларацията за съгласие." + } + } + }, + "file.button.label" : "изберете", + "checkboxTree.furtherSubCategoriesFor.label" : "допълнителни подкатегории към" + } +} \ No newline at end of file diff --git a/translations/form.cs.json b/translations/form.cs.json new file mode 100644 index 0000000..67893b3 --- /dev/null +++ b/translations/form.cs.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteNásledující zpráva byla odeslána z vašeho .", + "footer" : "Zprávu odeslal: {host} dne {datum} v {čas}.", + "headline" : "Formulářové údaje" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Pozdrav", + "salutation.salutationMale.label" : "Pan", + "salutation.salutationFemale.label" : "Paní", + "salutation.salutationDiverse.label" : "Různé", + "salutation.salutationNotSpecified.label" : "Není specifikováno", + "lastname.label" : "Příjmení", + "firstname.label" : "Křestní jméno", + "street.label" : "Ulice", + "housenumber.label" : "Číslo domu", + "postalCode.label" : "POSTCODE", + "city.label" : "Místo", + "tel.label" : "Telefon", + "mobile.label" : "Mobilní telefon", + "email.label" : "E-mailová adresa", + "emailCompare.label" : "Opakování e-mailové adresy", + "password.label" : "heslo", + "passwordRepetition.label" : "Heslo, opakování" + }, + "dateFilter" : { + "empty.label" : "volné období" + }, + "dateSelectorComposition.label" : "Období", + "date.label" : "datum", + "dateFrom.label" : "z", + "dateTo.label" : "do", + "file.deleteFile.label" : "Smazat soubor", + "salutation.label" : "Pozdrav", + "salutation.salutationMale.label" : "Pan", + "salutation.salutationFemale.label" : "Paní", + "salutation.salutationDiverse.label" : "Různé", + "salutation.salutationNotSpecified.label" : "Není specifikováno", + "firstname.label" : "Křestní jméno", + "lastname.label" : "Příjmení", + "street.label" : "Ulice", + "housenumber.label" : "Číslo domu", + "postalCode.label" : "POSTCODE", + "city.label" : "Místo", + "tel.label" : "Telefon", + "mobile.label" : "Mobilní telefon", + "email.label" : "E-mailová adresa", + "select.pleaseSelect.label" : "vyberte si prosím", + "consent" : { + "legend" : "Ochrana údajů", + "label" : "Souhlasím s tím, že údaje potřebné pro zde nabízené služby mohou být shromažďovány a používány.", + "validator" : { + "required" : { + "message" : "Potvrďte prosím prohlášení o souhlasu." + } + } + }, + "file.button.label" : "vybrat", + "checkboxTree.furtherSubCategoriesFor.label" : "další podkategorie na" + } +} \ No newline at end of file diff --git a/translations/form.da.json b/translations/form.da.json new file mode 100644 index 0000000..ceef9f7 --- /dev/null +++ b/translations/form.da.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteFølgende besked blev sendt fra din .", + "footer" : "Besked sendt af: {host} den {dato} kl. {tidspunkt}.", + "headline" : "Formular-data" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Hilsen", + "salutation.salutationMale.label" : "Hr.", + "salutation.salutationFemale.label" : "Fru", + "salutation.salutationDiverse.label" : "Diverse", + "salutation.salutationNotSpecified.label" : "Ikke specificeret", + "lastname.label" : "Efternavn", + "firstname.label" : "Fornavn", + "street.label" : "Gade", + "housenumber.label" : "Husnummer", + "postalCode.label" : "POSTKODE", + "city.label" : "Sted", + "tel.label" : "Telefon", + "mobile.label" : "Mobiltelefon", + "email.label" : "E-mail-adresse", + "emailCompare.label" : "Gentag e-mail-adresse", + "password.label" : "adgangskode", + "passwordRepetition.label" : "Adgangskode, gentagelse" + }, + "dateFilter" : { + "empty.label" : "fri periode" + }, + "dateSelectorComposition.label" : "Periode", + "date.label" : "dato", + "dateFrom.label" : "fra", + "dateTo.label" : "indtil", + "file.deleteFile.label" : "Slet filen", + "salutation.label" : "Hilsen", + "salutation.salutationMale.label" : "Hr.", + "salutation.salutationFemale.label" : "Fru", + "salutation.salutationDiverse.label" : "Diverse", + "salutation.salutationNotSpecified.label" : "Ikke specificeret", + "firstname.label" : "Fornavn", + "lastname.label" : "Efternavn", + "street.label" : "Gade", + "housenumber.label" : "Husnummer", + "postalCode.label" : "POSTKODE", + "city.label" : "Sted", + "tel.label" : "Telefon", + "mobile.label" : "Mobiltelefon", + "email.label" : "E-mail-adresse", + "select.pleaseSelect.label" : "Vælg venligst", + "consent" : { + "legend" : "Beskyttelse af data", + "label" : "Jeg accepterer, at de data, der er nødvendige for de tjenester, der tilbydes her, kan indsamles og bruges.", + "validator" : { + "required" : { + "message" : "Bekræft venligst samtykkeerklæringen." + } + } + }, + "file.button.label" : "Vælg", + "checkboxTree.furtherSubCategoriesFor.label" : "yderligere underkategorier til" + } +} \ No newline at end of file diff --git a/translations/form.de.json b/translations/form.de.json new file mode 100644 index 0000000..9927cc3 --- /dev/null +++ b/translations/form.de.json @@ -0,0 +1,63 @@ +{ + + "email" : { + "header": "Die folgende Nachricht wurde gesendet von Ihrer Website.", + "footer": "Nachricht gesendet von: {host} am {date} um {time} Uhr", + "headline": "Formulardaten" + }, + "field" : { + "webAccount": { + "salutation.label": "Anrede", + "salutation.salutationMale.label": "Herr", + "salutation.salutationFemale.label": "Frau", + "salutation.salutationDiverse.label": "Divers", + "salutation.salutationNotSpecified.label": "Keine Angabe", + "lastname.label": "Nachname", + "firstname.label": "Vorname", + "street.label": "Stra\u00dfe", + "housenumber.label": "Hausnummer", + "postalCode.label": "PLZ", + "city.label": "Ort", + "tel.label": "Telefon", + "mobile.label": "Mobiltelefon", + "email.label": "E-Mail-Adresse", + "emailCompare.label": "E-Mail-Adresse wiederholen", + "password.label": "Passwort", + "passwordRepetition.label": "Passwort, Wiederholung" + }, + "dateFilter": { + "empty.label": "freier Zeitraum" + }, + "dateSelectorComposition.label": "Zeitraum", + "date.label": "Datum", + "dateFrom.label": "von", + "dateTo.label": "bis", + "file.deleteFile.label": "Datei löschen", + "salutation.label": "Anrede", + "salutation.salutationMale.label": "Herr", + "salutation.salutationFemale.label": "Frau", + "salutation.salutationDiverse.label": "Divers", + "salutation.salutationNotSpecified.label": "Keine Angabe", + "firstname.label": "Vorname", + "lastname.label": "Nachname", + "street.label": "Stra\u00dfe", + "housenumber.label": "Hausnummer", + "postalCode.label": "PLZ", + "city.label": "Ort", + "tel.label": "Telefon", + "mobile.label": "Mobiltelefon", + "email.label": "E-Mail-Adresse", + "select.pleaseSelect.label": "bitte wählen", + "consent": { + "legend": "Datenschutz", + "label": "Ich erkläre mich damit einverstanden, dass die erforderlichen Daten für die hier angebotenen Leistungen erhoben und verwendet werden.", + "validator": { + "required": { + "message": "Bitte bestätigen Sie die Einverständniserklärung." + } + } + }, + "file.button.label": "auswählen", + "checkboxTree.furtherSubCategoriesFor.label": "weitere Unterkategorien zu x" + } +} \ No newline at end of file diff --git a/translations/form.el.json b/translations/form.el.json new file mode 100644 index 0000000..d31e311 --- /dev/null +++ b/translations/form.el.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteΤο ακόλουθο μήνυμα εστάλη από το .", + "footer" : "Μήνυμα εστάλη από: {host} στις {ημερομηνία} στις {ώρα}", + "headline" : "Δεδομένα φόρμας" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Χαιρετισμός", + "salutation.salutationMale.label" : "Κύριε", + "salutation.salutationFemale.label" : "Κυρία", + "salutation.salutationDiverse.label" : "Διάφορα", + "salutation.salutationNotSpecified.label" : "Δεν προσδιορίζεται", + "lastname.label" : "Επώνυμο", + "firstname.label" : "Όνομα", + "street.label" : "Οδός", + "housenumber.label" : "Αριθμός σπιτιού", + "postalCode.label" : "ΤΑΧΥΔΡΟΜΙΚΟΣ ΚΩΔΙΚΟΣ", + "city.label" : "Τόπος", + "tel.label" : "Τηλέφωνο", + "mobile.label" : "Κινητό τηλέφωνο", + "email.label" : "Διεύθυνση ηλεκτρονικού ταχυδρομείου", + "emailCompare.label" : "Επανάληψη της διεύθυνσης ηλεκτρονικού ταχυδρομείου", + "password.label" : "κωδικός πρόσβασης", + "passwordRepetition.label" : "Κωδικός πρόσβασης, επανάληψη" + }, + "dateFilter" : { + "empty.label" : "ελεύθερη περίοδος" + }, + "dateSelectorComposition.label" : "Περίοδος", + "date.label" : "ημερομηνία", + "dateFrom.label" : "από το", + "dateTo.label" : "μέχρι το", + "file.deleteFile.label" : "Διαγραφή αρχείου", + "salutation.label" : "Χαιρετισμός", + "salutation.salutationMale.label" : "Κύριε", + "salutation.salutationFemale.label" : "Κυρία", + "salutation.salutationDiverse.label" : "Διάφορα", + "salutation.salutationNotSpecified.label" : "Δεν προσδιορίζεται", + "firstname.label" : "Όνομα", + "lastname.label" : "Επώνυμο", + "street.label" : "Οδός", + "housenumber.label" : "Αριθμός σπιτιού", + "postalCode.label" : "ΤΑΧΥΔΡΟΜΙΚΟΣ ΚΩΔΙΚΟΣ", + "city.label" : "Τόπος", + "tel.label" : "Τηλέφωνο", + "mobile.label" : "Κινητό τηλέφωνο", + "email.label" : "Διεύθυνση ηλεκτρονικού ταχυδρομείου", + "select.pleaseSelect.label" : "παρακαλώ επιλέξτε", + "consent" : { + "legend" : "Προστασία δεδομένων", + "label" : "Συμφωνώ ότι τα δεδομένα που απαιτούνται για τις υπηρεσίες που προσφέρονται εδώ μπορούν να συλλεχθούν και να χρησιμοποιηθούν.", + "validator" : { + "required" : { + "message" : "Παρακαλούμε επιβεβαιώστε τη δήλωση συγκατάθεσης." + } + } + }, + "file.button.label" : "επιλέξτε", + "checkboxTree.furtherSubCategoriesFor.label" : "περαιτέρω υποκατηγορίες για να" + } +} \ No newline at end of file diff --git a/translations/form.en-gb.json b/translations/form.en-gb.json new file mode 100644 index 0000000..069c416 --- /dev/null +++ b/translations/form.en-gb.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "The following message was sent from your Website.", + "footer" : "Message sent by: {host} on {date} at {time}", + "headline" : "Form data" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Salutation", + "salutation.salutationMale.label" : "Mr", + "salutation.salutationFemale.label" : "Mrs", + "salutation.salutationDiverse.label" : "Miscellaneous", + "salutation.salutationNotSpecified.label" : "Not specified", + "lastname.label" : "Surname", + "firstname.label" : "First name", + "street.label" : "Street", + "housenumber.label" : "House number", + "postalCode.label" : "POSTCODE", + "city.label" : "Place", + "tel.label" : "Telephone", + "mobile.label" : "Mobile phone", + "email.label" : "E-mail address", + "emailCompare.label" : "Repeat e-mail address", + "password.label" : "password", + "passwordRepetition.label" : "Password, repetition" + }, + "dateFilter" : { + "empty.label" : "free period" + }, + "dateSelectorComposition.label" : "Period", + "date.label" : "date", + "dateFrom.label" : "from", + "dateTo.label" : "until", + "file.deleteFile.label" : "Delete file", + "salutation.label" : "Salutation", + "salutation.salutationMale.label" : "Mr", + "salutation.salutationFemale.label" : "Mrs", + "salutation.salutationDiverse.label" : "Miscellaneous", + "salutation.salutationNotSpecified.label" : "Not specified", + "firstname.label" : "First name", + "lastname.label" : "Surname", + "street.label" : "Street", + "housenumber.label" : "House number", + "postalCode.label" : "POSTCODE", + "city.label" : "Place", + "tel.label" : "Telephone", + "mobile.label" : "Mobile phone", + "email.label" : "E-mail address", + "select.pleaseSelect.label" : "please choose", + "consent" : { + "legend" : "Data protection", + "label" : "I agree that the data required for the services offered here may be collected and used.", + "validator" : { + "required" : { + "message" : "Please confirm the declaration of consent." + } + } + }, + "file.button.label" : "select", + "checkboxTree.furtherSubCategoriesFor.label" : "further subcategories to" + } +} \ No newline at end of file diff --git a/translations/form.en-us.json b/translations/form.en-us.json new file mode 100644 index 0000000..5e40048 --- /dev/null +++ b/translations/form.en-us.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "The following message was sent from your Website.", + "footer" : "Message sent by: {host} on {date} at {time}", + "headline" : "Form data" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Salutation", + "salutation.salutationMale.label" : "Mr.", + "salutation.salutationFemale.label" : "Woman", + "salutation.salutationDiverse.label" : "Miscellaneous", + "salutation.salutationNotSpecified.label" : "Not specified", + "lastname.label" : "Surname", + "firstname.label" : "First name", + "street.label" : "Street", + "housenumber.label" : "House number", + "postalCode.label" : "ZIP CODE", + "city.label" : "Location", + "tel.label" : "Telephone", + "mobile.label" : "Cell phone", + "email.label" : "E-mail address", + "emailCompare.label" : "Repeat e-mail address", + "password.label" : "password", + "passwordRepetition.label" : "Password, repetition" + }, + "dateFilter" : { + "empty.label" : "free period" + }, + "dateSelectorComposition.label" : "Period", + "date.label" : "Date", + "dateFrom.label" : "from", + "dateTo.label" : "to", + "file.deleteFile.label" : "Delete file", + "salutation.label" : "Salutation", + "salutation.salutationMale.label" : "Mr.", + "salutation.salutationFemale.label" : "Woman", + "salutation.salutationDiverse.label" : "Miscellaneous", + "salutation.salutationNotSpecified.label" : "Not specified", + "firstname.label" : "First name", + "lastname.label" : "Surname", + "street.label" : "Street", + "housenumber.label" : "House number", + "postalCode.label" : "ZIP CODE", + "city.label" : "Location", + "tel.label" : "Telephone", + "mobile.label" : "Cell phone", + "email.label" : "E-mail address", + "select.pleaseSelect.label" : "please choose", + "consent" : { + "legend" : "Data protection", + "label" : "I agree that the data required for the services offered here may be collected and used.", + "validator" : { + "required" : { + "message" : "Please confirm the declaration of consent." + } + } + }, + "file.button.label" : "select", + "checkboxTree.furtherSubCategoriesFor.label" : "further subcategories to" + } +} \ No newline at end of file diff --git a/translations/form.en.json b/translations/form.en.json new file mode 100644 index 0000000..0081dae --- /dev/null +++ b/translations/form.en.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "The following message was sent from your Website.", + "footer" : "Message sent by: {host} on {date} at {time}", + "headline" : "Form data" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Salutation", + "salutation.salutationMale.label" : "Mr.", + "salutation.salutationFemale.label" : "Woman", + "salutation.salutationDiverse.label" : "Miscellaneous", + "salutation.salutationNotSpecified.label" : "Not specified", + "lastname.label" : "Surname", + "firstname.label" : "First name", + "street.label" : "Street", + "housenumber.label" : "House number", + "postalCode.label" : "ZIP CODE", + "city.label" : "Location", + "tel.label" : "Telephone", + "mobile.label" : "Cell phone", + "email.label" : "E-mail address", + "emailCompare.label" : "Repeat e-mail address", + "password.label" : "password", + "passwordRepetition.label" : "Password, repetition" + }, + "dateFilter" : { + "empty.label" : "free period" + }, + "dateSelectorComposition.label" : "Period", + "date.label" : "Date", + "dateFrom.label" : "from", + "dateTo.label" : "to", + "file.deleteFile.label" : "Delete file", + "salutation.label" : "Salutation", + "salutation.salutationMale.label" : "Mr.", + "salutation.salutationFemale.label" : "Woman", + "salutation.salutationDiverse.label" : "Miscellaneous", + "salutation.salutationNotSpecified.label" : "Not specified", + "firstname.label" : "First name", + "lastname.label" : "Surname", + "street.label" : "Street", + "housenumber.label" : "House number", + "postalCode.label" : "ZIP CODE", + "city.label" : "Location", + "tel.label" : "Telephone", + "mobile.label" : "Cell phone", + "email.label" : "E-mail address", + "select.pleaseSelect.label" : "please choose", + "consent" : { + "legend" : "Data protection", + "label" : "I agree that the data required for the services offered here may be collected and used.", + "validator" : { + "required" : { + "message" : "Please confirm the declaration of consent." + } + } + }, + "file.button.label" : "select", + "checkboxTree.furtherSubCategoriesFor.label" : "further subcategories to" + } +} diff --git a/translations/form.es.json b/translations/form.es.json new file mode 100644 index 0000000..cfed7fe --- /dev/null +++ b/translations/form.es.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteEl siguiente mensaje fue enviado desde su .", + "footer" : "Mensaje enviado por: {host} el {date} a las {time}", + "headline" : "Datos del formulario" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Saludo", + "salutation.salutationMale.label" : "Sr.", + "salutation.salutationFemale.label" : "Sra.", + "salutation.salutationDiverse.label" : "Varios", + "salutation.salutationNotSpecified.label" : "No especificado", + "lastname.label" : "Apellido", + "firstname.label" : "Nombre", + "street.label" : "Calle", + "housenumber.label" : "Número de casa", + "postalCode.label" : "CÓDIGO POSTAL", + "city.label" : "Lugar", + "tel.label" : "Teléfono", + "mobile.label" : "Teléfono móvil", + "email.label" : "Correo electrónico", + "emailCompare.label" : "Repita la dirección de correo electrónico", + "password.label" : "contraseña", + "passwordRepetition.label" : "Contraseña, repetición" + }, + "dateFilter" : { + "empty.label" : "período libre" + }, + "dateSelectorComposition.label" : "Periodo", + "date.label" : "fecha", + "dateFrom.label" : "de", + "dateTo.label" : "hasta", + "file.deleteFile.label" : "Eliminar archivo", + "salutation.label" : "Saludo", + "salutation.salutationMale.label" : "Sr.", + "salutation.salutationFemale.label" : "Sra.", + "salutation.salutationDiverse.label" : "Varios", + "salutation.salutationNotSpecified.label" : "No especificado", + "firstname.label" : "Nombre", + "lastname.label" : "Apellido", + "street.label" : "Calle", + "housenumber.label" : "Número de casa", + "postalCode.label" : "CÓDIGO POSTAL", + "city.label" : "Lugar", + "tel.label" : "Teléfono", + "mobile.label" : "Teléfono móvil", + "email.label" : "Correo electrónico", + "select.pleaseSelect.label" : "elija", + "consent" : { + "legend" : "Protección de datos", + "label" : "Acepto que se recojan y utilicen los datos necesarios para los servicios aquí ofrecidos.", + "validator" : { + "required" : { + "message" : "Por favor, confirme la declaración de consentimiento." + } + } + }, + "file.button.label" : "seleccione", + "checkboxTree.furtherSubCategoriesFor.label" : "otras subcategorías para" + } +} \ No newline at end of file diff --git a/translations/form.et.json b/translations/form.et.json new file mode 100644 index 0000000..b4630c4 --- /dev/null +++ b/translations/form.et.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteJärgmine sõnum saadeti teie .", + "footer" : "Sõnum saatis: {host} {kuupäev} kell {kellaaeg}", + "headline" : "Vormi andmed" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Tervitus", + "salutation.salutationMale.label" : "Härra", + "salutation.salutationFemale.label" : "Proua", + "salutation.salutationDiverse.label" : "Mitmesugused", + "salutation.salutationNotSpecified.label" : "Ei ole täpsustatud", + "lastname.label" : "Perekonnanimi", + "firstname.label" : "Eesnimi", + "street.label" : "Street", + "housenumber.label" : "Maja number", + "postalCode.label" : "POSTIINFO", + "city.label" : "Koht", + "tel.label" : "Telefon", + "mobile.label" : "Mobiiltelefon", + "email.label" : "E-posti aadress", + "emailCompare.label" : "E-posti aadressi kordamine", + "password.label" : "parool", + "passwordRepetition.label" : "Salasõna, kordus" + }, + "dateFilter" : { + "empty.label" : "vaba periood" + }, + "dateSelectorComposition.label" : "Ajavahemik", + "date.label" : "kuupäev", + "dateFrom.label" : "aadressilt", + "dateTo.label" : "kuni", + "file.deleteFile.label" : "Kustuta fail", + "salutation.label" : "Tervitus", + "salutation.salutationMale.label" : "Härra", + "salutation.salutationFemale.label" : "Proua", + "salutation.salutationDiverse.label" : "Mitmesugused", + "salutation.salutationNotSpecified.label" : "Ei ole täpsustatud", + "firstname.label" : "Eesnimi", + "lastname.label" : "Perekonnanimi", + "street.label" : "Street", + "housenumber.label" : "Maja number", + "postalCode.label" : "POSTIINFO", + "city.label" : "Koht", + "tel.label" : "Telefon", + "mobile.label" : "Mobiiltelefon", + "email.label" : "E-posti aadress", + "select.pleaseSelect.label" : "palun valige", + "consent" : { + "legend" : "Andmekaitse", + "label" : "Olen nõus, et siin pakutavate teenuste jaoks vajalikke andmeid võib koguda ja kasutada.", + "validator" : { + "required" : { + "message" : "Palun kinnitage nõusoleku deklaratsioon." + } + } + }, + "file.button.label" : "valige", + "checkboxTree.furtherSubCategoriesFor.label" : "täiendavad alamkategooriad, et" + } +} \ No newline at end of file diff --git a/translations/form.fi.json b/translations/form.fi.json new file mode 100644 index 0000000..fdbb21f --- /dev/null +++ b/translations/form.fi.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteSeuraava viesti lähetettiin sinun .", + "footer" : "Viestin lähetti: {host} {päivänä} klo {aika}", + "headline" : "Lomakkeen tiedot" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Tervehdys", + "salutation.salutationMale.label" : "Herra", + "salutation.salutationFemale.label" : "Rouva", + "salutation.salutationDiverse.label" : "Sekalaiset", + "salutation.salutationNotSpecified.label" : "Ei määritelty", + "lastname.label" : "Sukunimi", + "firstname.label" : "Etunimi", + "street.label" : "Street", + "housenumber.label" : "Talon numero", + "postalCode.label" : "POSTINUMERO", + "city.label" : "Paikka", + "tel.label" : "Puhelin", + "mobile.label" : "Matkapuhelin", + "email.label" : "Sähköpostiosoite", + "emailCompare.label" : "Toista sähköpostiosoite", + "password.label" : "salasana", + "passwordRepetition.label" : "Salasana, toisto" + }, + "dateFilter" : { + "empty.label" : "vapaa-aika" + }, + "dateSelectorComposition.label" : "Jakso", + "date.label" : "päivämäärä", + "dateFrom.label" : "osoitteesta", + "dateTo.label" : "kunnes", + "file.deleteFile.label" : "Poista tiedosto", + "salutation.label" : "Tervehdys", + "salutation.salutationMale.label" : "Herra", + "salutation.salutationFemale.label" : "Rouva", + "salutation.salutationDiverse.label" : "Sekalaiset", + "salutation.salutationNotSpecified.label" : "Ei määritelty", + "firstname.label" : "Etunimi", + "lastname.label" : "Sukunimi", + "street.label" : "Street", + "housenumber.label" : "Talon numero", + "postalCode.label" : "POSTINUMERO", + "city.label" : "Paikka", + "tel.label" : "Puhelin", + "mobile.label" : "Matkapuhelin", + "email.label" : "Sähköpostiosoite", + "select.pleaseSelect.label" : "valitse", + "consent" : { + "legend" : "Tietosuoja", + "label" : "Hyväksyn, että täällä tarjottujen palvelujen edellyttämiä tietoja voidaan kerätä ja käyttää.", + "validator" : { + "required" : { + "message" : "Vahvistakaa suostumusilmoitus." + } + } + }, + "file.button.label" : "valitse", + "checkboxTree.furtherSubCategoriesFor.label" : "muita alaluokkia" + } +} \ No newline at end of file diff --git a/translations/form.fr.json b/translations/form.fr.json new file mode 100644 index 0000000..7747cd8 --- /dev/null +++ b/translations/form.fr.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "Le message suivant a été envoyé par votre Website.", + "footer" : "Message envoyé par : {host} le {date} à {time} heures", + "headline" : "Données du formulaire" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Titre de civilité", + "salutation.salutationMale.label" : "Monsieur", + "salutation.salutationFemale.label" : "Mme", + "salutation.salutationDiverse.label" : "Divers", + "salutation.salutationNotSpecified.label" : "Aucune indication", + "lastname.label" : "Nom de famille", + "firstname.label" : "Prénom", + "street.label" : "Rue", + "housenumber.label" : "Numéro de maison", + "postalCode.label" : "CODE POSTAL", + "city.label" : "Lieu", + "tel.label" : "Téléphone", + "mobile.label" : "Téléphone portable", + "email.label" : "Adresse électronique", + "emailCompare.label" : "Répéter l'adresse e-mail", + "password.label" : "Mot de passe", + "passwordRepetition.label" : "Mot de passe, répétition" + }, + "dateFilter" : { + "empty.label" : "période libre" + }, + "dateSelectorComposition.label" : "Période", + "date.label" : "Date", + "dateFrom.label" : "de", + "dateTo.label" : "jusqu'à", + "file.deleteFile.label" : "Supprimer un fichier", + "salutation.label" : "Titre de civilité", + "salutation.salutationMale.label" : "Monsieur", + "salutation.salutationFemale.label" : "Mme", + "salutation.salutationDiverse.label" : "Divers", + "salutation.salutationNotSpecified.label" : "Aucune indication", + "firstname.label" : "Prénom", + "lastname.label" : "Nom de famille", + "street.label" : "Rue", + "housenumber.label" : "Numéro de maison", + "postalCode.label" : "CODE POSTAL", + "city.label" : "Lieu", + "tel.label" : "Téléphone", + "mobile.label" : "Téléphone portable", + "email.label" : "Adresse électronique", + "select.pleaseSelect.label" : "choisir svp", + "consent" : { + "legend" : "Protection des données", + "label" : "J'accepte que les données nécessaires soient collectées et utilisées pour les services proposés ici.", + "validator" : { + "required" : { + "message" : "Veuillez confirmer le consentement." + } + } + }, + "file.button.label" : "sélectionner", + "checkboxTree.furtherSubCategoriesFor.label" : "autres sous-catégories de" + } +} \ No newline at end of file diff --git a/translations/form.hu.json b/translations/form.hu.json new file mode 100644 index 0000000..17f9c25 --- /dev/null +++ b/translations/form.hu.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteA következő üzenetet küldte az Ön .", + "footer" : "Üzenetet küldött:: {host} a {dátum} {időpontban}", + "headline" : "Formanyomtatvány adatok" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Üdvözlés", + "salutation.salutationMale.label" : "Mr", + "salutation.salutationFemale.label" : "Mrs", + "salutation.salutationDiverse.label" : "Egyéb", + "salutation.salutationNotSpecified.label" : "Nincs megadva", + "lastname.label" : "Vezetéknév", + "firstname.label" : "Keresztnév", + "street.label" : "Street", + "housenumber.label" : "Házszám", + "postalCode.label" : "POSTACÍM", + "city.label" : "Helyszín", + "tel.label" : "Telefon", + "mobile.label" : "Mobiltelefon", + "email.label" : "E-mail cím", + "emailCompare.label" : "E-mail cím megismétlése", + "password.label" : "jelszó", + "passwordRepetition.label" : "Jelszó, ismétlés" + }, + "dateFilter" : { + "empty.label" : "szabadidő" + }, + "dateSelectorComposition.label" : "Időszak", + "date.label" : "dátum", + "dateFrom.label" : "a címről", + "dateTo.label" : "amíg", + "file.deleteFile.label" : "Fájl törlése", + "salutation.label" : "Üdvözlés", + "salutation.salutationMale.label" : "Mr", + "salutation.salutationFemale.label" : "Mrs", + "salutation.salutationDiverse.label" : "Egyéb", + "salutation.salutationNotSpecified.label" : "Nincs megadva", + "firstname.label" : "Keresztnév", + "lastname.label" : "Vezetéknév", + "street.label" : "Street", + "housenumber.label" : "Házszám", + "postalCode.label" : "POSTACÍM", + "city.label" : "Helyszín", + "tel.label" : "Telefon", + "mobile.label" : "Mobiltelefon", + "email.label" : "E-mail cím", + "select.pleaseSelect.label" : "Kérjük, válasszon", + "consent" : { + "legend" : "Adatvédelem", + "label" : "Hozzájárulok, hogy az itt kínált szolgáltatásokhoz szükséges adatokat összegyűjtsék és felhasználják.", + "validator" : { + "required" : { + "message" : "Kérjük, erősítse meg a hozzájáruló nyilatkozatot." + } + } + }, + "file.button.label" : "válassza ki a címet.", + "checkboxTree.furtherSubCategoriesFor.label" : "további alkategóriák" + } +} \ No newline at end of file diff --git a/translations/form.id.json b/translations/form.id.json new file mode 100644 index 0000000..8d557fc --- /dev/null +++ b/translations/form.id.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsitePesan berikut ini dikirim dari .", + "footer" : "Pesan dikirim oleh: {host} pada {tanggal} di {waktu}", + "headline" : "Formulir data" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Salam", + "salutation.salutationMale.label" : "Mr.", + "salutation.salutationFemale.label" : "Nyonya", + "salutation.salutationDiverse.label" : "Lain-lain", + "salutation.salutationNotSpecified.label" : "Tidak ditentukan", + "lastname.label" : "Nama keluarga", + "firstname.label" : "Nama depan", + "street.label" : "Jalan", + "housenumber.label" : "Nomor rumah", + "postalCode.label" : "KODE POS", + "city.label" : "Tempat", + "tel.label" : "Telepon", + "mobile.label" : "Ponsel", + "email.label" : "Alamat email", + "emailCompare.label" : "Ulangi alamat email", + "password.label" : "kata sandi", + "passwordRepetition.label" : "Kata sandi, pengulangan" + }, + "dateFilter" : { + "empty.label" : "periode bebas" + }, + "dateSelectorComposition.label" : "Periode", + "date.label" : "tanggal", + "dateFrom.label" : "dari", + "dateTo.label" : "sampai", + "file.deleteFile.label" : "Menghapus file", + "salutation.label" : "Salam", + "salutation.salutationMale.label" : "Mr.", + "salutation.salutationFemale.label" : "Nyonya", + "salutation.salutationDiverse.label" : "Lain-lain", + "salutation.salutationNotSpecified.label" : "Tidak ditentukan", + "firstname.label" : "Nama depan", + "lastname.label" : "Nama keluarga", + "street.label" : "Jalan", + "housenumber.label" : "Nomor rumah", + "postalCode.label" : "KODE POS", + "city.label" : "Tempat", + "tel.label" : "Telepon", + "mobile.label" : "Ponsel", + "email.label" : "Alamat email", + "select.pleaseSelect.label" : "silakan pilih", + "consent" : { + "legend" : "Perlindungan data", + "label" : "Saya setuju bahwa data yang diperlukan untuk layanan yang ditawarkan di sini dapat dikumpulkan dan digunakan.", + "validator" : { + "required" : { + "message" : "Mohon konfirmasikan pernyataan persetujuan." + } + } + }, + "file.button.label" : "pilih", + "checkboxTree.furtherSubCategoriesFor.label" : "subkategori lebih lanjut ke" + } +} \ No newline at end of file diff --git a/translations/form.it.json b/translations/form.it.json new file mode 100644 index 0000000..284d028 --- /dev/null +++ b/translations/form.it.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteIl seguente messaggio è stato inviato dal vostro .", + "footer" : "Messaggio inviato da: {host} il {data} all' {ora}", + "headline" : "Dati del modulo" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Saluto", + "salutation.salutationMale.label" : "Il Sig.", + "salutation.salutationFemale.label" : "Signora", + "salutation.salutationDiverse.label" : "Varie", + "salutation.salutationNotSpecified.label" : "Non specificato", + "lastname.label" : "Cognome", + "firstname.label" : "Nome", + "street.label" : "Via", + "housenumber.label" : "Numero civico", + "postalCode.label" : "CAP", + "city.label" : "Luogo", + "tel.label" : "Telefono", + "mobile.label" : "Telefono cellulare", + "email.label" : "Indirizzo e-mail", + "emailCompare.label" : "Ripetere l'indirizzo e-mail", + "password.label" : "password", + "passwordRepetition.label" : "Password, ripetizione" + }, + "dateFilter" : { + "empty.label" : "periodo libero" + }, + "dateSelectorComposition.label" : "Periodo", + "date.label" : "data", + "dateFrom.label" : "da", + "dateTo.label" : "fino a quando", + "file.deleteFile.label" : "Cancellare il file", + "salutation.label" : "Saluto", + "salutation.salutationMale.label" : "Il Sig.", + "salutation.salutationFemale.label" : "Signora", + "salutation.salutationDiverse.label" : "Varie", + "salutation.salutationNotSpecified.label" : "Non specificato", + "firstname.label" : "Nome", + "lastname.label" : "Cognome", + "street.label" : "Via", + "housenumber.label" : "Numero civico", + "postalCode.label" : "CAP", + "city.label" : "Luogo", + "tel.label" : "Telefono", + "mobile.label" : "Telefono cellulare", + "email.label" : "Indirizzo e-mail", + "select.pleaseSelect.label" : "scegliere", + "consent" : { + "legend" : "Protezione dei dati", + "label" : "Acconsento alla raccolta e all'utilizzo dei dati necessari per i servizi offerti.", + "validator" : { + "required" : { + "message" : "Confermare la dichiarazione di consenso." + } + } + }, + "file.button.label" : "selezionare", + "checkboxTree.furtherSubCategoriesFor.label" : "ulteriori sottocategorie per" + } +} \ No newline at end of file diff --git a/translations/form.ja.json b/translations/form.ja.json new file mode 100644 index 0000000..2d0fbb8 --- /dev/null +++ b/translations/form.ja.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : ".NETから以下のメッセージが送信されました。", + "footer" : "メッセージ送信者{ホスト} on {日付} at {時刻}.", + "headline" : "フォームデータ" + }, + "field" : { + "webAccount" : { + "salutation.label" : "挨拶", + "salutation.salutationMale.label" : "ミスター", + "salutation.salutationFemale.label" : "夫人", + "salutation.salutationDiverse.label" : "その他", + "salutation.salutationNotSpecified.label" : "特になし", + "lastname.label" : "苗字", + "firstname.label" : "名前", + "street.label" : "ストリート", + "housenumber.label" : "家屋番号", + "postalCode.label" : "郵便番号", + "city.label" : "場所", + "tel.label" : "電話", + "mobile.label" : "携帯電話", + "email.label" : "Eメールアドレス", + "emailCompare.label" : "リピートEメールアドレス", + "password.label" : "パスワード", + "passwordRepetition.label" : "パスワード、繰り返し" + }, + "dateFilter" : { + "empty.label" : "休み時間" + }, + "dateSelectorComposition.label" : "期間", + "date.label" : "日付", + "dateFrom.label" : "より", + "dateTo.label" : "まで", + "file.deleteFile.label" : "ファイルの削除", + "salutation.label" : "挨拶", + "salutation.salutationMale.label" : "ミスター", + "salutation.salutationFemale.label" : "夫人", + "salutation.salutationDiverse.label" : "その他", + "salutation.salutationNotSpecified.label" : "特になし", + "firstname.label" : "名前", + "lastname.label" : "苗字", + "street.label" : "ストリート", + "housenumber.label" : "家屋番号", + "postalCode.label" : "郵便番号", + "city.label" : "場所", + "tel.label" : "電話", + "mobile.label" : "携帯電話", + "email.label" : "Eメールアドレス", + "select.pleaseSelect.label" : "選択してください", + "consent" : { + "legend" : "データ保護", + "label" : "私は、ここで提供されるサービスに必要なデータが収集され使用されることに同意します。", + "validator" : { + "required" : { + "message" : "同意宣言をご確認ください。" + } + } + }, + "file.button.label" : "選ぶ", + "checkboxTree.furtherSubCategoriesFor.label" : "にはさらにサブカテゴリーがある。" + } +} \ No newline at end of file diff --git a/translations/form.ko.json b/translations/form.ko.json new file mode 100644 index 0000000..ee4a590 --- /dev/null +++ b/translations/form.ko.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "Website에서 다음 메시지가 전송되었습니다.", + "footer" : "보낸 메시지입니다: {호스트}가 {날짜}에 {시간}에 보낸 메시지입니다.", + "headline" : "양식 데이터" + }, + "field" : { + "webAccount" : { + "salutation.label" : "인사말", + "salutation.salutationMale.label" : "Mr", + "salutation.salutationFemale.label" : "부인", + "salutation.salutationDiverse.label" : "기타", + "salutation.salutationNotSpecified.label" : "지정되지 않음", + "lastname.label" : "성", + "firstname.label" : "이름", + "street.label" : "거리", + "housenumber.label" : "집 번호", + "postalCode.label" : "포스트코드", + "city.label" : "위치", + "tel.label" : "전화", + "mobile.label" : "휴대폰", + "email.label" : "이메일 주소", + "emailCompare.label" : "이메일 주소 반복", + "password.label" : "비밀번호", + "passwordRepetition.label" : "비밀번호, 반복" + }, + "dateFilter" : { + "empty.label" : "무료 기간" + }, + "dateSelectorComposition.label" : "기간", + "date.label" : "날짜", + "dateFrom.label" : "에서", + "dateTo.label" : "까지", + "file.deleteFile.label" : "파일 삭제", + "salutation.label" : "인사말", + "salutation.salutationMale.label" : "Mr", + "salutation.salutationFemale.label" : "부인", + "salutation.salutationDiverse.label" : "기타", + "salutation.salutationNotSpecified.label" : "지정되지 않음", + "firstname.label" : "이름", + "lastname.label" : "성", + "street.label" : "거리", + "housenumber.label" : "집 번호", + "postalCode.label" : "포스트코드", + "city.label" : "위치", + "tel.label" : "전화", + "mobile.label" : "휴대폰", + "email.label" : "이메일 주소", + "select.pleaseSelect.label" : "선택해 주세요", + "consent" : { + "legend" : "데이터 보호", + "label" : "본인은 여기에서 제공하는 서비스에 필요한 데이터를 수집하고 사용할 수 있음에 동의합니다.", + "validator" : { + "required" : { + "message" : "동의 선언을 확인해 주세요." + } + } + }, + "file.button.label" : "선택", + "checkboxTree.furtherSubCategoriesFor.label" : "추가 하위 카테고리" + } +} \ No newline at end of file diff --git a/translations/form.lt.json b/translations/form.lt.json new file mode 100644 index 0000000..69aaadd --- /dev/null +++ b/translations/form.lt.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteŠis pranešimas buvo išsiųstas iš jūsų .", + "footer" : "Pranešimą atsiuntė: {host}, {data}, {laikas}.", + "headline" : "Formos duomenys" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Pasveikinimas", + "salutation.salutationMale.label" : "Ponas", + "salutation.salutationFemale.label" : "Ponia", + "salutation.salutationDiverse.label" : "Įvairūs", + "salutation.salutationNotSpecified.label" : "Nenurodyta", + "lastname.label" : "Pavardė", + "firstname.label" : "Vardas ir pavardė", + "street.label" : "Gatvė", + "housenumber.label" : "Namo numeris", + "postalCode.label" : "POSTCODE", + "city.label" : "Vieta", + "tel.label" : "Telefonas", + "mobile.label" : "Mobilusis telefonas", + "email.label" : "el. pašto adresas", + "emailCompare.label" : "Pakartokite el. pašto adresą", + "password.label" : "slaptažodis", + "passwordRepetition.label" : "Slaptažodis, kartojimas" + }, + "dateFilter" : { + "empty.label" : "laisvas laikotarpis" + }, + "dateSelectorComposition.label" : "Laikotarpis", + "date.label" : "data", + "dateFrom.label" : "iš", + "dateTo.label" : "iki", + "file.deleteFile.label" : "Ištrinti failą", + "salutation.label" : "Pasveikinimas", + "salutation.salutationMale.label" : "Ponas", + "salutation.salutationFemale.label" : "Ponia", + "salutation.salutationDiverse.label" : "Įvairūs", + "salutation.salutationNotSpecified.label" : "Nenurodyta", + "firstname.label" : "Vardas ir pavardė", + "lastname.label" : "Pavardė", + "street.label" : "Gatvė", + "housenumber.label" : "Namo numeris", + "postalCode.label" : "POSTCODE", + "city.label" : "Vieta", + "tel.label" : "Telefonas", + "mobile.label" : "Mobilusis telefonas", + "email.label" : "el. pašto adresas", + "select.pleaseSelect.label" : "pasirinkite", + "consent" : { + "legend" : "Duomenų apsauga", + "label" : "Sutinku, kad čia siūlomoms paslaugoms reikalingi duomenys gali būti renkami ir naudojami.", + "validator" : { + "required" : { + "message" : "Patvirtinkite sutikimo deklaraciją." + } + } + }, + "file.button.label" : "pasirinkite", + "checkboxTree.furtherSubCategoriesFor.label" : "kitos subkategorijos" + } +} \ No newline at end of file diff --git a/translations/form.lv.json b/translations/form.lv.json new file mode 100644 index 0000000..80ac14b --- /dev/null +++ b/translations/form.lv.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteŠāds ziņojums tika nosūtīts no jūsu .", + "footer" : "Ziņu nosūtīja: {host} {datos} plkst. {laikā}", + "headline" : "Veidlapu dati" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Sveiciens", + "salutation.salutationMale.label" : "kungs", + "salutation.salutationFemale.label" : "kundze", + "salutation.salutationDiverse.label" : "Dažādi", + "salutation.salutationNotSpecified.label" : "Nav norādīts", + "lastname.label" : "Uzvārds", + "firstname.label" : "Vārds", + "street.label" : "Ielas", + "housenumber.label" : "Mājas numurs", + "postalCode.label" : "POSTCODE", + "city.label" : "Vieta", + "tel.label" : "Tālrunis", + "mobile.label" : "Mobilais tālrunis", + "email.label" : "E-pasta adrese", + "emailCompare.label" : "Atkārtota e-pasta adrese", + "password.label" : "parole", + "passwordRepetition.label" : "Parole, atkārtošana" + }, + "dateFilter" : { + "empty.label" : "bezmaksas periods" + }, + "dateSelectorComposition.label" : "Periods", + "date.label" : "datums", + "dateFrom.label" : "no", + "dateTo.label" : "līdz", + "file.deleteFile.label" : "Dzēst failu", + "salutation.label" : "Sveiciens", + "salutation.salutationMale.label" : "kungs", + "salutation.salutationFemale.label" : "kundze", + "salutation.salutationDiverse.label" : "Dažādi", + "salutation.salutationNotSpecified.label" : "Nav norādīts", + "firstname.label" : "Vārds", + "lastname.label" : "Uzvārds", + "street.label" : "Ielas", + "housenumber.label" : "Mājas numurs", + "postalCode.label" : "POSTCODE", + "city.label" : "Vieta", + "tel.label" : "Tālrunis", + "mobile.label" : "Mobilais tālrunis", + "email.label" : "E-pasta adrese", + "select.pleaseSelect.label" : "lūdzu, izvēlieties", + "consent" : { + "legend" : "Datu aizsardzība", + "label" : "Es piekrītu, ka šeit piedāvātajiem pakalpojumiem nepieciešamie dati var tikt vākti un izmantoti.", + "validator" : { + "required" : { + "message" : "Lūdzu, apstipriniet piekrišanas deklarāciju." + } + } + }, + "file.button.label" : "atlasīt", + "checkboxTree.furtherSubCategoriesFor.label" : "papildu apakškategorijas, lai" + } +} \ No newline at end of file diff --git a/translations/form.nb.json b/translations/form.nb.json new file mode 100644 index 0000000..d7abaf4 --- /dev/null +++ b/translations/form.nb.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteFølgende melding ble sendt fra din .", + "footer" : "Melding sendt av: {host} den {dato} kl {klokkeslett}", + "headline" : "Skjemadata" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Hilsen", + "salutation.salutationMale.label" : "Mr.", + "salutation.salutationFemale.label" : "Fru", + "salutation.salutationDiverse.label" : "Diverse", + "salutation.salutationNotSpecified.label" : "Ikke spesifisert", + "lastname.label" : "Etternavn", + "firstname.label" : "Fornavn", + "street.label" : "Gate", + "housenumber.label" : "Husnummer", + "postalCode.label" : "POSTCODE", + "city.label" : "Sted", + "tel.label" : "Telefon", + "mobile.label" : "Mobiltelefon", + "email.label" : "E-postadresse", + "emailCompare.label" : "Gjenta e-postadressen", + "password.label" : "passord", + "passwordRepetition.label" : "Passord, repetisjon" + }, + "dateFilter" : { + "empty.label" : "fri periode" + }, + "dateSelectorComposition.label" : "Periode", + "date.label" : "dato", + "dateFrom.label" : "fra", + "dateTo.label" : "inntil", + "file.deleteFile.label" : "Slett fil", + "salutation.label" : "Hilsen", + "salutation.salutationMale.label" : "Mr.", + "salutation.salutationFemale.label" : "Fru", + "salutation.salutationDiverse.label" : "Diverse", + "salutation.salutationNotSpecified.label" : "Ikke spesifisert", + "firstname.label" : "Fornavn", + "lastname.label" : "Etternavn", + "street.label" : "Gate", + "housenumber.label" : "Husnummer", + "postalCode.label" : "POSTCODE", + "city.label" : "Sted", + "tel.label" : "Telefon", + "mobile.label" : "Mobiltelefon", + "email.label" : "E-postadresse", + "select.pleaseSelect.label" : "vennligst velg", + "consent" : { + "legend" : "Beskyttelse av personopplysninger", + "label" : "Jeg samtykker i at opplysningene som kreves for tjenestene som tilbys her, kan samles inn og brukes.", + "validator" : { + "required" : { + "message" : "Vennligst bekreft samtykkeerklæringen." + } + } + }, + "file.button.label" : "velg", + "checkboxTree.furtherSubCategoriesFor.label" : "ytterligere underkategorier til" + } +} \ No newline at end of file diff --git a/translations/form.nl.json b/translations/form.nl.json new file mode 100644 index 0000000..1b194e5 --- /dev/null +++ b/translations/form.nl.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteHet volgende bericht is verzonden vanuit uw .", + "footer" : "Bericht verzonden door: {host} op {datum} om {tijd}", + "headline" : "Formuliergegevens" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Begroeting", + "salutation.salutationMale.label" : "De heer", + "salutation.salutationFemale.label" : "Mevrouw", + "salutation.salutationDiverse.label" : "Diverse", + "salutation.salutationNotSpecified.label" : "Niet gespecificeerd", + "lastname.label" : "Achternaam", + "firstname.label" : "Voornaam", + "street.label" : "Straat", + "housenumber.label" : "Huisnummer", + "postalCode.label" : "POSTCODE", + "city.label" : "Locatie", + "tel.label" : "Telefoon", + "mobile.label" : "Mobiele telefoon", + "email.label" : "E-mailadres", + "emailCompare.label" : "E-mailadres herhalen", + "password.label" : "wachtwoord", + "passwordRepetition.label" : "Wachtwoord, herhaling" + }, + "dateFilter" : { + "empty.label" : "vrije periode" + }, + "dateSelectorComposition.label" : "Periode", + "date.label" : "datum", + "dateFrom.label" : "van", + "dateTo.label" : "tot", + "file.deleteFile.label" : "Bestand verwijderen", + "salutation.label" : "Begroeting", + "salutation.salutationMale.label" : "De heer", + "salutation.salutationFemale.label" : "Mevrouw", + "salutation.salutationDiverse.label" : "Diverse", + "salutation.salutationNotSpecified.label" : "Niet gespecificeerd", + "firstname.label" : "Voornaam", + "lastname.label" : "Achternaam", + "street.label" : "Straat", + "housenumber.label" : "Huisnummer", + "postalCode.label" : "POSTCODE", + "city.label" : "Locatie", + "tel.label" : "Telefoon", + "mobile.label" : "Mobiele telefoon", + "email.label" : "E-mailadres", + "select.pleaseSelect.label" : "kies", + "consent" : { + "legend" : "Gegevensbescherming", + "label" : "Ik ga ermee akkoord dat de gegevens die nodig zijn voor de hier aangeboden diensten worden verzameld en gebruikt.", + "validator" : { + "required" : { + "message" : "Bevestig de toestemmingsverklaring." + } + } + }, + "file.button.label" : "selecteer", + "checkboxTree.furtherSubCategoriesFor.label" : "verdere subcategorieën naar" + } +} \ No newline at end of file diff --git a/translations/form.pl.json b/translations/form.pl.json new file mode 100644 index 0000000..3cc2680 --- /dev/null +++ b/translations/form.pl.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteNastępująca wiadomość została wysłana z Twojego .", + "footer" : "Wiadomość wysłana przez: {host} w dniu {data} o godzinie {godzina}", + "headline" : "Dane formularza" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Pozdrowienie", + "salutation.salutationMale.label" : "Pan", + "salutation.salutationFemale.label" : "Pani", + "salutation.salutationDiverse.label" : "Różne", + "salutation.salutationNotSpecified.label" : "Nie określono", + "lastname.label" : "Nazwisko", + "firstname.label" : "Imię", + "street.label" : "ul.", + "housenumber.label" : "Numer domu", + "postalCode.label" : "KOD POCZTOWY", + "city.label" : "Lokalizacja", + "tel.label" : "Telefon", + "mobile.label" : "Telefon komórkowy", + "email.label" : "Adres e-mail", + "emailCompare.label" : "Powtórzony adres e-mail", + "password.label" : "hasło", + "passwordRepetition.label" : "Hasło, powtórzenie" + }, + "dateFilter" : { + "empty.label" : "okres wolny" + }, + "dateSelectorComposition.label" : "Okres", + "date.label" : "data", + "dateFrom.label" : "z", + "dateTo.label" : "do", + "file.deleteFile.label" : "Usuń plik", + "salutation.label" : "Pozdrowienie", + "salutation.salutationMale.label" : "Pan", + "salutation.salutationFemale.label" : "Pani", + "salutation.salutationDiverse.label" : "Różne", + "salutation.salutationNotSpecified.label" : "Nie określono", + "firstname.label" : "Imię", + "lastname.label" : "Nazwisko", + "street.label" : "ul.", + "housenumber.label" : "Numer domu", + "postalCode.label" : "KOD POCZTOWY", + "city.label" : "Lokalizacja", + "tel.label" : "Telefon", + "mobile.label" : "Telefon komórkowy", + "email.label" : "Adres e-mail", + "select.pleaseSelect.label" : "wybierz", + "consent" : { + "legend" : "Ochrona danych", + "label" : "Wyrażam zgodę na gromadzenie i wykorzystywanie danych wymaganych do korzystania z oferowanych tutaj usług.", + "validator" : { + "required" : { + "message" : "Prosimy o potwierdzenie deklaracji zgody." + } + } + }, + "file.button.label" : "wybór", + "checkboxTree.furtherSubCategoriesFor.label" : "dalsze podkategorie do" + } +} \ No newline at end of file diff --git a/translations/form.pt-br.json b/translations/form.pt-br.json new file mode 100644 index 0000000..dfc11fc --- /dev/null +++ b/translations/form.pt-br.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteA seguinte mensagem foi enviada de seu .", + "footer" : "Mensagem enviada por: {host} em {date} às {time}", + "headline" : "Dados do formulário" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Saudação", + "salutation.salutationMale.label" : "Senhor", + "salutation.salutationFemale.label" : "Senhora", + "salutation.salutationDiverse.label" : "Diversos", + "salutation.salutationNotSpecified.label" : "Não especificado", + "lastname.label" : "Sobrenome", + "firstname.label" : "Primeiro nome", + "street.label" : "Rua", + "housenumber.label" : "Número da casa", + "postalCode.label" : "CÓDIGO POSTAL", + "city.label" : "Local", + "tel.label" : "Telefone", + "mobile.label" : "Telefone celular", + "email.label" : "Endereço de e-mail", + "emailCompare.label" : "Repetir endereço de e-mail", + "password.label" : "senha", + "passwordRepetition.label" : "Senha, repetição" + }, + "dateFilter" : { + "empty.label" : "período livre" + }, + "dateSelectorComposition.label" : "Período", + "date.label" : "data", + "dateFrom.label" : "de", + "dateTo.label" : "até que", + "file.deleteFile.label" : "Excluir arquivo", + "salutation.label" : "Saudação", + "salutation.salutationMale.label" : "Senhor", + "salutation.salutationFemale.label" : "Senhora", + "salutation.salutationDiverse.label" : "Diversos", + "salutation.salutationNotSpecified.label" : "Não especificado", + "firstname.label" : "Primeiro nome", + "lastname.label" : "Sobrenome", + "street.label" : "Rua", + "housenumber.label" : "Número da casa", + "postalCode.label" : "CÓDIGO POSTAL", + "city.label" : "Local", + "tel.label" : "Telefone", + "mobile.label" : "Telefone celular", + "email.label" : "Endereço de e-mail", + "select.pleaseSelect.label" : "escolha", + "consent" : { + "legend" : "Proteção de dados", + "label" : "Concordo que os dados necessários para os serviços oferecidos aqui podem ser coletados e usados.", + "validator" : { + "required" : { + "message" : "Por favor, confirme a declaração de consentimento." + } + } + }, + "file.button.label" : "selecionar", + "checkboxTree.furtherSubCategoriesFor.label" : "outras subcategorias para" + } +} \ No newline at end of file diff --git a/translations/form.pt-pt.json b/translations/form.pt-pt.json new file mode 100644 index 0000000..824b8cd --- /dev/null +++ b/translations/form.pt-pt.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteA seguinte mensagem foi enviada do seu .", + "footer" : "Mensagem enviada por: {host} em {date} às {time}", + "headline" : "Dados do formulário" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Saudação", + "salutation.salutationMale.label" : "Senhor", + "salutation.salutationFemale.label" : "Senhora", + "salutation.salutationDiverse.label" : "Diversos", + "salutation.salutationNotSpecified.label" : "Não especificado", + "lastname.label" : "Apelido", + "firstname.label" : "Nome próprio", + "street.label" : "Rua", + "housenumber.label" : "Número da casa", + "postalCode.label" : "CÓDIGO POSTAL", + "city.label" : "Local", + "tel.label" : "Telefone", + "mobile.label" : "Telemóvel", + "email.label" : "endereço eletrónico", + "emailCompare.label" : "Repetir o endereço de correio eletrónico", + "password.label" : "palavra-passe", + "passwordRepetition.label" : "Palavra-passe, repetição" + }, + "dateFilter" : { + "empty.label" : "período livre" + }, + "dateSelectorComposition.label" : "Período", + "date.label" : "data", + "dateFrom.label" : "de", + "dateTo.label" : "até", + "file.deleteFile.label" : "Eliminar ficheiro", + "salutation.label" : "Saudação", + "salutation.salutationMale.label" : "Senhor", + "salutation.salutationFemale.label" : "Senhora", + "salutation.salutationDiverse.label" : "Diversos", + "salutation.salutationNotSpecified.label" : "Não especificado", + "firstname.label" : "Nome próprio", + "lastname.label" : "Apelido", + "street.label" : "Rua", + "housenumber.label" : "Número da casa", + "postalCode.label" : "CÓDIGO POSTAL", + "city.label" : "Local", + "tel.label" : "Telefone", + "mobile.label" : "Telemóvel", + "email.label" : "endereço eletrónico", + "select.pleaseSelect.label" : "escolha", + "consent" : { + "legend" : "Proteção de dados", + "label" : "Aceito que os dados necessários para os serviços aqui oferecidos possam ser recolhidos e utilizados.", + "validator" : { + "required" : { + "message" : "Por favor, confirme a declaração de consentimento." + } + } + }, + "file.button.label" : "selecionar", + "checkboxTree.furtherSubCategoriesFor.label" : "outras subcategorias para" + } +} \ No newline at end of file diff --git a/translations/form.ro.json b/translations/form.ro.json new file mode 100644 index 0000000..f637657 --- /dev/null +++ b/translations/form.ro.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteUrmătorul mesaj a fost trimis din .", + "footer" : "Mesaj trimis de: {host} pe {data} la {ora}", + "headline" : "Datele formularului" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Salutul", + "salutation.salutationMale.label" : "Dl", + "salutation.salutationFemale.label" : "Doamnă", + "salutation.salutationDiverse.label" : "Diverse", + "salutation.salutationNotSpecified.label" : "Nu este specificat", + "lastname.label" : "Numele de familie", + "firstname.label" : "Numele și prenumele", + "street.label" : "Strada", + "housenumber.label" : "Numărul casei", + "postalCode.label" : "COD POȘTAL", + "city.label" : "Loc", + "tel.label" : "Telefon", + "mobile.label" : "Telefon mobil", + "email.label" : "Adresa de e-mail", + "emailCompare.label" : "Repetați adresa de e-mail", + "password.label" : "parolă", + "passwordRepetition.label" : "Parolă, repetiție" + }, + "dateFilter" : { + "empty.label" : "perioadă liberă" + }, + "dateSelectorComposition.label" : "Perioada", + "date.label" : "data", + "dateFrom.label" : "de la", + "dateTo.label" : "până când", + "file.deleteFile.label" : "Ștergeți fișierul", + "salutation.label" : "Salutul", + "salutation.salutationMale.label" : "Dl", + "salutation.salutationFemale.label" : "Doamnă", + "salutation.salutationDiverse.label" : "Diverse", + "salutation.salutationNotSpecified.label" : "Nu este specificat", + "firstname.label" : "Numele și prenumele", + "lastname.label" : "Numele de familie", + "street.label" : "Strada", + "housenumber.label" : "Numărul casei", + "postalCode.label" : "COD POȘTAL", + "city.label" : "Loc", + "tel.label" : "Telefon", + "mobile.label" : "Telefon mobil", + "email.label" : "Adresa de e-mail", + "select.pleaseSelect.label" : "vă rugăm să alegeți", + "consent" : { + "legend" : "Protecția datelor", + "label" : "Sunt de acord că datele necesare pentru serviciile oferite aici pot fi colectate și utilizate.", + "validator" : { + "required" : { + "message" : "Vă rugăm să confirmați declarația de consimțământ." + } + } + }, + "file.button.label" : "selectați", + "checkboxTree.furtherSubCategoriesFor.label" : "subcategorii suplimentare pentru" + } +} \ No newline at end of file diff --git a/translations/form.ru.json b/translations/form.ru.json new file mode 100644 index 0000000..cff3ce4 --- /dev/null +++ b/translations/form.ru.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteСледующее сообщение было отправлено с вашего .", + "footer" : "Сообщение отправлено: {host} в {дата} в {время}", + "headline" : "Данные формы" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Приветствие", + "salutation.salutationMale.label" : "Мистер", + "salutation.salutationFemale.label" : "Миссис", + "salutation.salutationDiverse.label" : "Разное", + "salutation.salutationNotSpecified.label" : "Не указано", + "lastname.label" : "Фамилия", + "firstname.label" : "Имя", + "street.label" : "Улица", + "housenumber.label" : "Номер дома", + "postalCode.label" : "ПОЧТОВЫЙ ИНДЕКС", + "city.label" : "Расположение", + "tel.label" : "Телефон", + "mobile.label" : "Мобильный телефон", + "email.label" : "Адрес электронной почты", + "emailCompare.label" : "Повторите адрес электронной почты", + "password.label" : "пароль", + "passwordRepetition.label" : "Пароль, повторение" + }, + "dateFilter" : { + "empty.label" : "свободный период" + }, + "dateSelectorComposition.label" : "Период", + "date.label" : "дата", + "dateFrom.label" : "с сайта", + "dateTo.label" : "до", + "file.deleteFile.label" : "Удалить файл", + "salutation.label" : "Приветствие", + "salutation.salutationMale.label" : "Мистер", + "salutation.salutationFemale.label" : "Миссис", + "salutation.salutationDiverse.label" : "Разное", + "salutation.salutationNotSpecified.label" : "Не указано", + "firstname.label" : "Имя", + "lastname.label" : "Фамилия", + "street.label" : "Улица", + "housenumber.label" : "Номер дома", + "postalCode.label" : "ПОЧТОВЫЙ ИНДЕКС", + "city.label" : "Расположение", + "tel.label" : "Телефон", + "mobile.label" : "Мобильный телефон", + "email.label" : "Адрес электронной почты", + "select.pleaseSelect.label" : "пожалуйста, выберите", + "consent" : { + "legend" : "Защита данных", + "label" : "Я согласен с тем, что данные, необходимые для предлагаемых здесь услуг, могут быть собраны и использованы.", + "validator" : { + "required" : { + "message" : "Пожалуйста, подтвердите заявление о согласии." + } + } + }, + "file.button.label" : "выберите", + "checkboxTree.furtherSubCategoriesFor.label" : "дополнительные подкатегории к" + } +} \ No newline at end of file diff --git a/translations/form.sk.json b/translations/form.sk.json new file mode 100644 index 0000000..f39beab --- /dev/null +++ b/translations/form.sk.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteNasledujúca správa bola odoslaná z vášho .", + "footer" : "Správu poslal: {hostiteľ} dňa {dátum} v {čas}", + "headline" : "Údaje vo formulári" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Pozdrav", + "salutation.salutationMale.label" : "Pán", + "salutation.salutationFemale.label" : "Pani", + "salutation.salutationDiverse.label" : "Rôzne", + "salutation.salutationNotSpecified.label" : "Nie je špecifikované", + "lastname.label" : "Priezvisko", + "firstname.label" : "Krstné meno", + "street.label" : "Ulica", + "housenumber.label" : "Číslo domu", + "postalCode.label" : "POSTCODE", + "city.label" : "Miesto", + "tel.label" : "Telefón", + "mobile.label" : "Mobilný telefón", + "email.label" : "e-mailová adresa", + "emailCompare.label" : "Opakovanie e-mailovej adresy", + "password.label" : "heslo", + "passwordRepetition.label" : "Heslo, opakovanie" + }, + "dateFilter" : { + "empty.label" : "voľné obdobie" + }, + "dateSelectorComposition.label" : "Obdobie", + "date.label" : "dátum", + "dateFrom.label" : "z adresy", + "dateTo.label" : "do", + "file.deleteFile.label" : "Odstrániť súbor", + "salutation.label" : "Pozdrav", + "salutation.salutationMale.label" : "Pán", + "salutation.salutationFemale.label" : "Pani", + "salutation.salutationDiverse.label" : "Rôzne", + "salutation.salutationNotSpecified.label" : "Nie je špecifikované", + "firstname.label" : "Krstné meno", + "lastname.label" : "Priezvisko", + "street.label" : "Ulica", + "housenumber.label" : "Číslo domu", + "postalCode.label" : "POSTCODE", + "city.label" : "Miesto", + "tel.label" : "Telefón", + "mobile.label" : "Mobilný telefón", + "email.label" : "e-mailová adresa", + "select.pleaseSelect.label" : "vyberte si, prosím,", + "consent" : { + "legend" : "Ochrana údajov", + "label" : "Súhlasím so zhromažďovaním a používaním údajov potrebných pre tu ponúkané služby.", + "validator" : { + "required" : { + "message" : "Potvrďte, prosím, vyhlásenie o súhlase." + } + } + }, + "file.button.label" : "vybrať", + "checkboxTree.furtherSubCategoriesFor.label" : "ďalšie podkategórie" + } +} \ No newline at end of file diff --git a/translations/form.sl.json b/translations/form.sl.json new file mode 100644 index 0000000..94c4f2d --- /dev/null +++ b/translations/form.sl.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteNaslednje sporočilo je bilo poslano iz vašega .", + "footer" : "Sporočilo je poslal: {host} na {datum} ob {času}", + "headline" : "Podatki v obrazcu" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Pozdrav", + "salutation.salutationMale.label" : "Gospod", + "salutation.salutationFemale.label" : "Gospa", + "salutation.salutationDiverse.label" : "Različni", + "salutation.salutationNotSpecified.label" : "Ni določeno", + "lastname.label" : "Priimek", + "firstname.label" : "Ime in priimek", + "street.label" : "Ulica", + "housenumber.label" : "Številka hiše", + "postalCode.label" : "POŠTNA KODA", + "city.label" : "Kraj", + "tel.label" : "Telefon", + "mobile.label" : "Mobilni telefon", + "email.label" : "e-poštni naslov", + "emailCompare.label" : "Ponovite e-poštni naslov", + "password.label" : "geslo", + "passwordRepetition.label" : "Geslo, ponavljanje" + }, + "dateFilter" : { + "empty.label" : "brezplačno obdobje" + }, + "dateSelectorComposition.label" : "Obdobje", + "date.label" : "datum", + "dateFrom.label" : "s spletne strani", + "dateTo.label" : "do .", + "file.deleteFile.label" : "Izbriši datoteko", + "salutation.label" : "Pozdrav", + "salutation.salutationMale.label" : "Gospod", + "salutation.salutationFemale.label" : "Gospa", + "salutation.salutationDiverse.label" : "Različni", + "salutation.salutationNotSpecified.label" : "Ni določeno", + "firstname.label" : "Ime in priimek", + "lastname.label" : "Priimek", + "street.label" : "Ulica", + "housenumber.label" : "Številka hiše", + "postalCode.label" : "POŠTNA KODA", + "city.label" : "Kraj", + "tel.label" : "Telefon", + "mobile.label" : "Mobilni telefon", + "email.label" : "e-poštni naslov", + "select.pleaseSelect.label" : "izberite", + "consent" : { + "legend" : "Varstvo podatkov", + "label" : "Strinjam se z zbiranjem in uporabo podatkov, ki so potrebni za opravljanje tukaj ponujenih storitev.", + "validator" : { + "required" : { + "message" : "Potrdite izjavo o privolitvi." + } + } + }, + "file.button.label" : "izberite", + "checkboxTree.furtherSubCategoriesFor.label" : "dodatne podkategorije za" + } +} \ No newline at end of file diff --git a/translations/form.sv.json b/translations/form.sv.json new file mode 100644 index 0000000..d405aa4 --- /dev/null +++ b/translations/form.sv.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteFöljande meddelande skickades från din .", + "footer" : "Meddelande skickat av: {host} den {datum} kl {tid}", + "headline" : "Formulärdata" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Hälsning", + "salutation.salutationMale.label" : "Herr", + "salutation.salutationFemale.label" : "Fru", + "salutation.salutationDiverse.label" : "Övrigt", + "salutation.salutationNotSpecified.label" : "Ej specificerat", + "lastname.label" : "Efternamn", + "firstname.label" : "Förnamn", + "street.label" : "Gata", + "housenumber.label" : "Husnummer", + "postalCode.label" : "POSTKODE", + "city.label" : "Plats", + "tel.label" : "Telefon", + "mobile.label" : "Mobiltelefon", + "email.label" : "E-postadress", + "emailCompare.label" : "Upprepa e-postadressen", + "password.label" : "Lösenord", + "passwordRepetition.label" : "Lösenord, repetition" + }, + "dateFilter" : { + "empty.label" : "fri period" + }, + "dateSelectorComposition.label" : "Period", + "date.label" : "datum", + "dateFrom.label" : "från", + "dateTo.label" : "tills", + "file.deleteFile.label" : "Ta bort fil", + "salutation.label" : "Hälsning", + "salutation.salutationMale.label" : "Herr", + "salutation.salutationFemale.label" : "Fru", + "salutation.salutationDiverse.label" : "Övrigt", + "salutation.salutationNotSpecified.label" : "Ej specificerat", + "firstname.label" : "Förnamn", + "lastname.label" : "Efternamn", + "street.label" : "Gata", + "housenumber.label" : "Husnummer", + "postalCode.label" : "POSTKODE", + "city.label" : "Plats", + "tel.label" : "Telefon", + "mobile.label" : "Mobiltelefon", + "email.label" : "E-postadress", + "select.pleaseSelect.label" : "Vänligen välj", + "consent" : { + "legend" : "Skydd av personuppgifter", + "label" : "Jag samtycker till att de uppgifter som krävs för de tjänster som erbjuds här får samlas in och användas.", + "validator" : { + "required" : { + "message" : "Vänligen bekräfta samtyckesförklaringen." + } + } + }, + "file.button.label" : "Välj", + "checkboxTree.furtherSubCategoriesFor.label" : "ytterligare underkategorier till" + } +} \ No newline at end of file diff --git a/translations/form.tr.json b/translations/form.tr.json new file mode 100644 index 0000000..3a712dc --- /dev/null +++ b/translations/form.tr.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteAşağıdaki mesaj tarafınızdan gönderilmiştir.", + "footer" : "Mesaj şu kişi tarafından gönderildi: {ana bilgisayar} tarafından {tarih} tarihinde {saat}", + "headline" : "Form verileri" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Selamlama", + "salutation.salutationMale.label" : "Bay", + "salutation.salutationFemale.label" : "Bayan", + "salutation.salutationDiverse.label" : "Çeşitli", + "salutation.salutationNotSpecified.label" : "Belirtilmemiş", + "lastname.label" : "Soyadı", + "firstname.label" : "İlk isim", + "street.label" : "Sokak", + "housenumber.label" : "Ev numarası", + "postalCode.label" : "POSTA KODU", + "city.label" : "Konum", + "tel.label" : "Telefon", + "mobile.label" : "Cep telefonu", + "email.label" : "e-posta adresi", + "emailCompare.label" : "E-posta adresini tekrarla", + "password.label" : "şifre", + "passwordRepetition.label" : "Şifre, tekrarlama" + }, + "dateFilter" : { + "empty.label" : "serbest dönem" + }, + "dateSelectorComposition.label" : "Dönem", + "date.label" : "Tarih", + "dateFrom.label" : "gelen", + "dateTo.label" : "kadar", + "file.deleteFile.label" : "Dosya silme", + "salutation.label" : "Selamlama", + "salutation.salutationMale.label" : "Bay", + "salutation.salutationFemale.label" : "Bayan", + "salutation.salutationDiverse.label" : "Çeşitli", + "salutation.salutationNotSpecified.label" : "Belirtilmemiş", + "firstname.label" : "İlk isim", + "lastname.label" : "Soyadı", + "street.label" : "Sokak", + "housenumber.label" : "Ev numarası", + "postalCode.label" : "POSTA KODU", + "city.label" : "Konum", + "tel.label" : "Telefon", + "mobile.label" : "Cep telefonu", + "email.label" : "e-posta adresi", + "select.pleaseSelect.label" : "lütfen seçin", + "consent" : { + "legend" : "Veri koruma", + "label" : "Burada sunulan hizmetler için gerekli verilerin toplanabileceğini ve kullanılabileceğini kabul ediyorum.", + "validator" : { + "required" : { + "message" : "Lütfen onay beyanını onaylayın." + } + } + }, + "file.button.label" : "seçin", + "checkboxTree.furtherSubCategoriesFor.label" : "daha fazla alt kategori" + } +} \ No newline at end of file diff --git a/translations/form.uk.json b/translations/form.uk.json new file mode 100644 index 0000000..da0512a --- /dev/null +++ b/translations/form.uk.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "WebsiteНаступне повідомлення було надіслано з вашого .", + "footer" : "Повідомлення відправлено {хост} на {дата} о {час}", + "headline" : "Дані форми" + }, + "field" : { + "webAccount" : { + "salutation.label" : "Привітання", + "salutation.salutationMale.label" : "Пане", + "salutation.salutationFemale.label" : "Пані", + "salutation.salutationDiverse.label" : "Різне", + "salutation.salutationNotSpecified.label" : "Не вказано", + "lastname.label" : "Прізвище", + "firstname.label" : "Ім'я та прізвище", + "street.label" : "Вулиця", + "housenumber.label" : "Номер будинку", + "postalCode.label" : "ПОШТОВИЙ КОД", + "city.label" : "Місце", + "tel.label" : "Телефон", + "mobile.label" : "Мобільний телефон", + "email.label" : "Адреса електронної пошти", + "emailCompare.label" : "Повторити адресу електронної пошти", + "password.label" : "пароль", + "passwordRepetition.label" : "Пароль, повторення" + }, + "dateFilter" : { + "empty.label" : "безкоштовний період" + }, + "dateSelectorComposition.label" : "Крапка", + "date.label" : "дата", + "dateFrom.label" : "від", + "dateTo.label" : "до тих пір, поки", + "file.deleteFile.label" : "Видалити файл", + "salutation.label" : "Привітання", + "salutation.salutationMale.label" : "Пане", + "salutation.salutationFemale.label" : "Пані", + "salutation.salutationDiverse.label" : "Різне", + "salutation.salutationNotSpecified.label" : "Не вказано", + "firstname.label" : "Ім'я та прізвище", + "lastname.label" : "Прізвище", + "street.label" : "Вулиця", + "housenumber.label" : "Номер будинку", + "postalCode.label" : "ПОШТОВИЙ КОД", + "city.label" : "Місце", + "tel.label" : "Телефон", + "mobile.label" : "Мобільний телефон", + "email.label" : "Адреса електронної пошти", + "select.pleaseSelect.label" : "будь ласка, оберіть", + "consent" : { + "legend" : "Захист даних", + "label" : "Я погоджуюся, що дані, необхідні для надання послуг, пропонованих тут, можуть бути зібрані та використані.", + "validator" : { + "required" : { + "message" : "Будь ласка, підтвердіть декларацію про згоду." + } + } + }, + "file.button.label" : "вибрати", + "checkboxTree.furtherSubCategoriesFor.label" : "інші підкатегорії до" + } +} \ No newline at end of file diff --git a/translations/form.zh-hans.json b/translations/form.zh-hans.json new file mode 100644 index 0000000..d71ab2c --- /dev/null +++ b/translations/form.zh-hans.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "Website以下信息是从您的 .NET 账户发送的", + "footer" : "信息发送者{主机}于{日期}在{时间}发送", + "headline" : "表格数据" + }, + "field" : { + "webAccount" : { + "salutation.label" : "致辞", + "salutation.salutationMale.label" : "先生", + "salutation.salutationFemale.label" : "夫人", + "salutation.salutationDiverse.label" : "杂项", + "salutation.salutationNotSpecified.label" : "未说明", + "lastname.label" : "姓氏", + "firstname.label" : "姓名", + "street.label" : "街道", + "housenumber.label" : "门牌号", + "postalCode.label" : "邮政编码", + "city.label" : "地点", + "tel.label" : "电话", + "mobile.label" : "移动电话", + "email.label" : "电子邮件地址", + "emailCompare.label" : "重复电子邮件地址", + "password.label" : "暗号", + "passwordRepetition.label" : "密码,重复" + }, + "dateFilter" : { + "empty.label" : "自由活动期" + }, + "dateSelectorComposition.label" : "期间", + "date.label" : "日期", + "dateFrom.label" : "从", + "dateTo.label" : "直到", + "file.deleteFile.label" : "删除文件", + "salutation.label" : "致辞", + "salutation.salutationMale.label" : "先生", + "salutation.salutationFemale.label" : "夫人", + "salutation.salutationDiverse.label" : "杂项", + "salutation.salutationNotSpecified.label" : "未说明", + "firstname.label" : "姓名", + "lastname.label" : "姓氏", + "street.label" : "街道", + "housenumber.label" : "门牌号", + "postalCode.label" : "邮政编码", + "city.label" : "地点", + "tel.label" : "电话", + "mobile.label" : "移动电话", + "email.label" : "电子邮件地址", + "select.pleaseSelect.label" : "请选择", + "consent" : { + "legend" : "数据保护", + "label" : "我同意收集和使用此处提供的服务所需的数据。", + "validator" : { + "required" : { + "message" : "请确认同意声明。" + } + } + }, + "file.button.label" : "遴选", + "checkboxTree.furtherSubCategoriesFor.label" : "进一步细分为" + } +} \ No newline at end of file diff --git a/translations/form.zh.json b/translations/form.zh.json new file mode 100644 index 0000000..3b9f046 --- /dev/null +++ b/translations/form.zh.json @@ -0,0 +1,62 @@ +{ + "email" : { + "header" : "Website以下信息是从您的 .NET 账户发送的", + "footer" : "信息由{主机}于{日期}在{时间}发送", + "headline" : "表格数据" + }, + "field" : { + "webAccount" : { + "salutation.label" : "致辞", + "salutation.salutationMale.label" : "先生", + "salutation.salutationFemale.label" : "夫人", + "salutation.salutationDiverse.label" : "杂项", + "salutation.salutationNotSpecified.label" : "未说明", + "lastname.label" : "姓氏", + "firstname.label" : "姓名", + "street.label" : "街道", + "housenumber.label" : "门牌号", + "postalCode.label" : "邮政编码", + "city.label" : "地点", + "tel.label" : "电话", + "mobile.label" : "移动电话", + "email.label" : "电子邮件地址", + "emailCompare.label" : "重复电子邮件地址", + "password.label" : "暗号", + "passwordRepetition.label" : "密码,重复" + }, + "dateFilter" : { + "empty.label" : "自由活动期" + }, + "dateSelectorComposition.label" : "期间", + "date.label" : "日期", + "dateFrom.label" : "从", + "dateTo.label" : "直到", + "file.deleteFile.label" : "删除文件", + "salutation.label" : "致辞", + "salutation.salutationMale.label" : "先生", + "salutation.salutationFemale.label" : "夫人", + "salutation.salutationDiverse.label" : "杂项", + "salutation.salutationNotSpecified.label" : "未说明", + "firstname.label" : "姓名", + "lastname.label" : "姓氏", + "street.label" : "街道", + "housenumber.label" : "门牌号", + "postalCode.label" : "邮政编码", + "city.label" : "地点", + "tel.label" : "电话", + "mobile.label" : "移动电话", + "email.label" : "电子邮件地址", + "select.pleaseSelect.label" : "请选择", + "consent" : { + "legend" : "数据保护", + "label" : "我同意收集和使用此处提供的服务所需的数据。", + "validator" : { + "required" : { + "message" : "请确认同意声明。" + } + } + }, + "file.button.label" : "遴选", + "checkboxTree.furtherSubCategoriesFor.label" : "进一步细分为" + } +} \ No newline at end of file