diff --git a/.docker/nginx.conf b/.docker/nginx.conf index 05516e318b..08e7b64603 100644 --- a/.docker/nginx.conf +++ b/.docker/nginx.conf @@ -10,7 +10,10 @@ upstream php-pimcore11 { server { listen [::]:80 default_server; listen 80 default_server; - + + fastcgi_buffer_size 128k; + fastcgi_buffers 8 256k; + fastcgi_busy_buffers_size 256k; #server_name pimcore.localhost; root /var/www/html/public; @@ -50,6 +53,21 @@ server { # return 403; # } + # Mercure Hub Proxy fΓΌr SSE (Server-Sent Events) + # /hub/.well-known/mercure -> http://mercure/.well-known/mercure + location /hub/ { + rewrite ^/hub/(.*)$ /$1 break; + proxy_pass http://mercure; + proxy_read_timeout 24h; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_buffering off; + proxy_cache off; + } + # Pimcore Head-Link Cache-Busting rewrite ^/cache-buster-(?:\d+)/(.*) /$1 last; diff --git a/.github/workflows/frontend-build.yaml b/.github/workflows/frontend-build.yaml new file mode 100644 index 0000000000..6f4bd106ca --- /dev/null +++ b/.github/workflows/frontend-build.yaml @@ -0,0 +1,63 @@ +name: CoreShop Studio Frontend Build + +on: + push: + branches: [ '4.0', '4.1', '5.0', 'next', 'studiov2' ] + pull_request: + branches: [ '4.0', '4.1', '5.0', 'next', 'studiov2' ] + +jobs: + frontend-build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Lint and fix + run: npm run lint || true + + - name: Type check + run: npm run check-types + + - name: Build all bundles + run: npm run build + + - name: Force add built assets to git + run: | + git add -f src/CoreShop/Bundle/*/Resources/public/studio/*/ + git status --porcelain + + - name: Check for changes + id: verify-changed-files + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "changed=true" >> $GITHUB_OUTPUT + fi + + - name: Commit built assets + if: steps.verify-changed-files.outputs.changed == 'true' + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git commit -m "πŸš€ Build CoreShop Studio bundles + + πŸ€– Generated with [GitHub Actions](https://github.com/coreshop/CoreShop/actions) + + Co-Authored-By: GitHub Action " + + - name: Push changes + if: steps.verify-changed-files.outputs.changed == 'true' && github.event_name == 'push' + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: ${{ github.ref }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 08ee7386c6..52542222b9 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,8 @@ docs/.docusaurus node_modules cache/ docker-compose.override.yaml +settings.local.json +.rsbuild + +# CoreShop Studio Build Output +src/CoreShop/Bundle/*/Resources/public/studio/*/ \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..512e0dd44b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,39 @@ +# Repository Guidelines + +## Project Structure & Module Organization +- Source: `src/CoreShop/Bundle/*` (Symfony bundles) and `src/CoreShop/Component/*` (domain components). +- Config: `config/` (services, routes), app kernels in `src/*Kernel.php`. +- Public assets: `public/`. +- Studio UI plugins (TypeScript/React): `src/*/Resources/assets/pimcore-studio` (npm workspaces). +- Tests: Behat features in `features/`; perf script in `tests/k6.js`. +- Docs and templates: `docs/`, `templates/`. + +## Build, Test, and Development Commands +- PHP deps: `composer install` (or `docker compose run --rm php composer install`). +- App console: `bin/console` (Symfony/Pimcore CLI), e.g. `bin/console cache:clear`. +- Studio UI build: `npm run dev` (watch) or `npm run build` (prod) at repo root. Node β‰₯ 18. +- Static analysis: `vendor/bin/phpstan analyse -c phpstan.neon src` and `vendor/bin/psalm`. +- Coding standard: `vendor/bin/ecs check src --fix` (see `ecs.php`). +- Behat domain: `docker compose run --rm behat vendor/bin/behat -c behat.yml.dist -p default`. +- Behat UI: `docker compose run --rm behat` (requires a running instance). + +## Coding Style & Naming Conventions +- PHP: PSR-12 + project rules via ECS. 4-space indent; strict types where practical; services autowired/aliased in YAML. +- Namespaces: `CoreShop\Bundle\` and `CoreShop\Component\`; tests and features mirror package structure. +- TypeScript/React: follow workspace lint configs; prefer functional components and `camelCase` files; bundle names kebab-case. + +## Testing Guidelines +- Primary framework: Behat (`features/`), profiles in `behat.yml.dist`. +- Add domain scenarios under `features/domain/` and UI under `features/ui/`. +- Keep scenarios independent; use tags for slow/browser tests. +- For static checks, ensure PHPStan and Psalm pass before PR. + +## Commit & Pull Request Guidelines +- Commits: imperative mood with scope, e.g. `[Product] fix price rounding` or `[Studio] improve menu state]`. +- PRs: clear description, linked issues, steps to test; include screenshots/GIFs for Studio UI. +- Keep changes scoped; update docs/config when relevant. +- CLA required (see `CLA.md`). Security issues: email `info@coreshop.com`. + +## Security & Configuration Tips +- Use `.env.local` for secrets; don’t commit `var/`, `vendor/`, or `node_modules/`. +- PHP 8.3+, Pimcore 12+. Run via Docker (`docker compose build` then `docker compose run --rm php bin/install`) for a clean setup. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000..bdd78fb489 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,1065 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +CoreShop is a Symfony-based Pimcore eCommerce platform built with a modular bundle/component architecture. The codebase follows Domain-Driven Design principles and is structured as a monorepo containing multiple related packages. + +## Commands + +### Development Commands + +```bash +# Validate code syntax and configuration +bin/console lint:yaml src +bin/console lint:twig src +bin/console lint:container +bin/console doctrine:schema:validate --skip-sync + +# Static Analysis +vendor/bin/phpstan # PHPStan analysis (level 3) +vendor/bin/psalm # Psalm static analysis + +# Code Style +vendor/bin/ecs # Easy Coding Standard +vendor/bin/ecs --fix # Fix coding standard issues + +# Testing +vendor/bin/behat # Run Behat tests +vendor/bin/behat --profile=default # Run specific Behat profile + +# Validation +composer validate # Validate composer.json +``` + +### Database & Cache +```bash +bin/console cache:clear --env=dev +bin/console doctrine:migrations:migrate +bin/console pimcore:install +``` + +## Architecture + +### CRITICAL: Documentation Requirements +**⚠️ EVERY CODE CHANGE MUST UPDATE DOCUMENTATION!** +- When adding/modifying React components β†’ Update Studio React docs in `docs/03_Development/14_Studio/` +- When adding/modifying ExtJS components β†’ Update ExtJS docs in `docs/03_Development/` +- When adding Rules (Actions/Conditions) β†’ Update both ExtJS and React docs +- When creating new features β†’ Document architecture, API, and usage +- Documentation is NOT optional - it's part of the implementation + +### CRITICAL: Bundle Dependencies +**⚠️ NO BUNDLE HAS A DEPENDENCY TO COREBUNDLE!** +- Individual bundles (ProductBundle, OrderBundle, etc.) MUST NOT import from CoreBundle +- Bundles are independent and habe cross-bundle dependencies. check the composer.json to see which bundle has which dependencies +- CoreBundle acts as a glue layer, not as a shared dependency layer + +### Bundle-Component Pattern +CoreShop follows a strict Bundle-Component separation pattern: +- **Components** (`src/CoreShop/Component/`): Domain logic, business rules, interfaces +- **Bundles** (`src/CoreShop/Bundle/`): Symfony integration, DI configuration, controllers + +### Core Architecture Layers + +#### Components (Business Logic) +- `Core/`: Central business logic and models +- `Product/`: Product management and catalog functionality +- `Order/`: Order processing and cart management +- `Customer/`: Customer and user management +- `Payment/`: Payment processing abstractions +- `Shipping/`: Shipping calculation and management +- `Index/`: Search and indexing functionality +- `Currency/`: Multi-currency support +- `Address/`: Address management +- `Store/`: Multi-store functionality +- `Taxation/`: Tax calculation rules +- `Rule/`: Business rule engine + +#### Bundles (Symfony Integration) +- `CoreBundle/`: Main bundle providing core services +- `AdminBundle/`: Pimcore admin interface integration +- `FrontendBundle/`: Frontend controllers and templates +- `ResourceBundle/`: Generic CRUD operations +- Corresponding bundles for each Component (e.g., `ProductBundle/`, `OrderBundle/`) + +### Key Design Patterns +- **Factory Pattern**: Extensive use for object creation +- **Specification Pattern**: Business rules and validation +- **Event-Driven Architecture**: Symfony events for extensibility +- **Repository Pattern**: Data access layer +- **State Machine**: Order and payment workflows + +## Configuration + +### Environment Files +- `.env`: Base environment configuration +- `.env.local`: Local overrides (not committed) + +### Key Configuration Files +- `config/`: Symfony configuration +- `phpstan.neon`: Static analysis configuration (level 3) +- `psalm.xml`: Psalm configuration +- `ecs.php`: Coding standards configuration +- `behat.yml.dist`: BDD testing configuration + +## Localization + +### Translation Resources +- **CoreBundle**: `src/CoreShop/Bundle/CoreBundle/Resources/translations/studio.*.yaml` +- **StoreBundle**: `src/CoreShop/Bundle/StoreBundle/Resources/translations/studio.*.yaml` +- **CurrencyBundle**: `src/CoreShop/Bundle/CurrencyBundle/Resources/translations/studio.*.yaml` +- **Other Bundles**: Follow the pattern `src/CoreShop/Bundle/{BundleName}/Resources/translations/studio.*.yaml` + +You can also add new keys, but double check existing ones first. Use `studio.en.yml` as the source of truth for English keys. + +## Testing Strategy + +### Test Types +- **Behat**: BDD integration tests for business scenarios +- **PHPUnit**: Unit tests (configured via composer.json) +- **Static Analysis**: PHPStan (level 3) and Psalm + +### Test Environment +- Uses MySQL database for integration tests +- Pimcore test environment with specific kernel (`BehatKernel.php`) +- Environment variables required for Pimcore licensing + +## Development Workflow + +### Code Quality Standards +- PHP 8.3+ required +- Strict PSR-12 coding standards via ECS +- PHPStan level 3 analysis required +- All YAML, Twig, and container configuration must be valid +- Doctrine schema validation required + +### Branch Strategy +- Main branches: `4.0`, `4.1`, `5.0`, `next` +- Base branch for PRs: `master` + +### Before Committing +Always run the full validation suite: +```bash +composer validate +bin/console lint:yaml src +bin/console lint:twig src +bin/console lint:container +bin/console doctrine:schema:validate --skip-sync +vendor/bin/phpstan +vendor/bin/psalm +vendor/bin/ecs +``` + +## Pimcore Integration + +This is a Pimcore Bundle project requiring: +- Pimcore ^12.0 +- Specific Pimcore environment variables and licensing +- Integration with Pimcore's data objects and admin interface +- Pimcore-specific kernels for different environments + +## Key Dependencies + +- **Symfony**: 6.3+ or 7.0+ for framework components +- **Doctrine ORM**: 3.0+ for data persistence +- **Payum**: Payment processing integration +- **Sylius ThemeBundle**: Theme management +- **JMS Serializer**: API serialization +- **KnpMenuBundle**: Navigation management + +## Pimcore Studio v2 Architecture (React/TypeScript) + +### Separation of Concerns - CRITICALLY IMPORTANT + +**Each Bundle creates and owns its own Registries:** + +Each Rule Engine (Cart Price Rules, Product Price Rules, Shipping Rules, etc.) has **separate ConditionRegistry and ActionRegistry instances**. This is fundamental to the architecture. + +#### Pattern: Bundle Registry Ownership + +**RuleBundle provides generic registries:** +- `ConditionRegistry` - Generic class for condition registration +- `ActionRegistry` - Generic class for action registration +- Both classes are reusable with the same implementation (register, get, has, getAll) +- Type-safe through TypeScript generics + +**Each bundle creates separate instances:** + +1. **ProductBundle** creates and binds: + - New instance of `ConditionRegistry` as ProductPriceRule condition registry + - New instance of `ActionRegistry` as ProductPriceRule action registry + - Registers ONLY what ProductBundle knows about (based on its composer.json dependencies) + - Example: nested, timespan, weight conditions + discount/price actions + - Does NOT know about Countries, Currencies, Customers (no dependency) + +2. **OrderBundle** creates and binds: + - New instance of `ConditionRegistry` as CartPriceRule condition registry + - New instance of `ActionRegistry` as CartPriceRule action registry + - Also creates CartItem registries (separate instances for nested rules) + - Registers ONLY what OrderBundle knows about + - Example: amount, voucher conditions + surcharge actions + - Does NOT know about Countries, Currencies, Customers (no dependency) + +3. **CoreBundle** acts as the "Glue": + - Has dependencies on ALL bundles (see composer.json) + - Retrieves registries via `container.get()` from other bundles + - Registers shared conditions/actions into EACH registry + - Example: CategoriesCondition, ProductsCondition, CustomersCondition, etc. + - Registers bundle-specific extensions (e.g., QuantityCondition for Product Price Rules) + +#### Key Principles + +- **Each Bundle is independent**: Only depends on what's in its composer.json +- **No cross-bundle knowledge**: ProductBundle doesn't know CustomerBundle exists +- **CoreBundle orchestrates**: Has all dependencies, connects everything +- **Separate Registries**: Same action name (e.g., 'discountAmount') can exist in multiple registries with different implementations +- **Future-proof**: New rule engines follow the same pattern (ShippingRuleRegistry, etc.) + +#### Checking Dependencies + +When uncertain about which bundle should register a component: +```bash +# Check bundle dependencies +cat src/CoreShop/Bundle/{BundleName}/composer.json | grep require +``` + +If a condition/action needs CustomerBundle but ProductBundle doesn't depend on it β†’ CoreBundle must register it. + +### Studio v2 Structure Pattern + +``` +BundleX/Resources/assets/pimcore-studio/src/ +β”œβ”€β”€ modules/ +β”‚ β”œβ”€β”€ rule-type/ # e.g., product-price-rules/ +β”‚ β”‚ β”œβ”€β”€ actions/ +β”‚ β”‚ β”‚ β”œβ”€β”€ SpecificAction.tsx # Bundle-specific action +β”‚ β”‚ β”‚ └── index.ts +β”‚ β”‚ └── conditions/ +β”‚ β”‚ β”œβ”€β”€ SpecificCondition.tsx +β”‚ β”‚ └── index.ts +β”‚ └── icon-library/ +└── main.ts # Registry creation + registration +``` + +**main.ts pattern:** +```typescript +import { container } from '@pimcore/studio-ui-bundle' +import { ConditionRegistry, ActionRegistry } from '@coreshop/rule/src/rules/registry' + +// 1. Create and bind own registries (using generic RuleBundle classes) +container.bind(serviceIds.myConditionRegistry).to(ConditionRegistry).inSingletonScope() +container.bind(serviceIds.myActionRegistry).to(ActionRegistry).inSingletonScope() + +// 2. Get own registries +const conditionRegistry = container.get(serviceIds.myConditionRegistry) +const actionRegistry = container.get(serviceIds.myActionRegistry) + +// 3. Register ONLY what this bundle knows +conditionRegistry.register('myCondition', MyCondition) +actionRegistry.register('myAction', MyAction) +``` + +**CoreBundle extends all registries:** +```typescript +import type { ConditionRegistry, ActionRegistry } from '@coreshop/rule/src/rules/registry' + +// Get registries from other bundles (they're all ConditionRegistry/ActionRegistry instances) +const productConditionRegistry = container.get(productServiceIds.conditionRegistry) +const cartConditionRegistry = container.get(cartServiceIds.conditionRegistry) + +// Register shared components into BOTH +productConditionRegistry.register('categories', CategoriesCondition) +cartConditionRegistry.register('categories', CategoriesCondition) +``` + +### Select Components with Module-Level Caching + +**IMPORTANT:** When creating Select components that load data from APIs (e.g., TaxRuleGroupSelect, ShippingRuleSelect, StoreSelect), ALWAYS implement module-level caching to prevent multiple API calls when multiple select instances are rendered. + +#### ❌ **WRONG** - No Caching (API called for each Select instance): + +```typescript +export const ShippingRuleSelect: React.FC = (props) => { + const [options, setOptions] = React.useState>([]) + const [loading, setLoading] = React.useState(false) + + React.useEffect(() => { + const load = async () => { + setLoading(true) + const rules = await shippingRuleApi.list() + setOptions(rules.map(r => ({ value: r.id!, label: r.name ?? `#${r.id}` }))) + setLoading(false) + } + void load() + }, []) + + return + (option?.label ?? '').toLowerCase().includes(input.toLowerCase()) + } + /> + ) +} +``` + +**Benefits:** +- βœ… API called only ONCE even with multiple Select instances +- βœ… Loading state shows immediately for first render +- βœ… Subsequent Selects instantly show cached data +- βœ… Prevents race conditions with `loadPromise` check +- βœ… Optional `clearCache()` function for invalidation +- βœ… Uses EntityApi `.list()` method (not raw fetch) + +**Key Points:** +1. **Use EntityApi**: Import and use the Api class (e.g., `shippingRuleApi.list()`), NOT raw `fetch()` +2. **Module-level variables**: `cachedOptions` and `loadPromise` outside component +3. **Promise sharing**: Return same promise if already loading (prevents duplicate calls) +4. **Initial state from cache**: `useState(cachedOptions || [])` shows data immediately if cached +5. **Conditional loading**: Only show spinner if cache is empty + +## Extension System + +CoreShop Studio v2 provides a comprehensive extension system that allows bundles and projects to customize and extend ANY entity in the system. This system enables full customization without modifying core code. + +### Available Extension Types + +#### 1. **Form Extensions** - Add fields to entity forms + +Add custom fields to any entity form (Country, TaxRate, Product, etc.). + +**Use Cases:** +- Add custom fields from external bundles +- Integrate third-party services +- Add computed/derived fields + +**Example:** +```typescript +import { container } from '@pimcore/studio-ui-bundle' +import { entityFormExtensionsServiceId, type EntityFormExtensionRegistry } from '@coreshop/resource/src/entities' +import { Input, Form } from 'antd' + +const registry = container.get(entityFormExtensionsServiceId) + +registry.add('coreshop.address.country.form', ({ data, onChange, form }) => { + return ( + + onChange({ customField: e.target.value })} /> + + ) +}) +``` + +**Slot Naming Convention:** `{bundle}.{resource}.{component}` +- Example: `coreshop.address.country.form` +- Example: `coreshop.taxation.tax_rate.form` + +#### 2. **Table Column Extensions** - Add columns to nested tables + +Add custom columns to inline tables (e.g., tax rules table in TaxRuleGroup). + +**Use Cases:** +- Add relational data columns +- Add computed columns +- Integrate external data + +**Example:** +```typescript +import { entityTableColumnExtensionsServiceId, type EntityTableColumnExtensionRegistry } from '@coreshop/resource/src/entities' + +const registry = container.get(entityTableColumnExtensionsServiceId) + +registry.add('coreshop.taxation.tax_rule_group.tax_rules', ({ updateRecord }) => [ + { + title: 'Country', + dataIndex: 'country', + width: 150, + render: (value, record, index) => ( + updateRecord(index, 'country', newValue)} + /> + ) + } +]) +``` + +#### 3. **Save Decorator Extensions** - Transform save payloads + +Modify entity data before it's sent to the backend. + +**Use Cases:** +- Add computed fields +- Transform data formats +- Inject additional data +- Clean up temporary fields + +**Example:** +```typescript +import { entitySaveDecoratorsServiceId, type EntitySaveDecoratorRegistry } from '@coreshop/resource/src/entities' + +const registry = container.get(entitySaveDecoratorsServiceId) + +registry.add('coreshop.address.country', (payload, data) => { + return { + ...payload, + // Add timestamp + lastModified: new Date().toISOString(), + // Add computed field + displayName: `${data.name} (${data.isoCode})` + } +}) +``` + +#### 4. **Tab Extensions** - Add custom tabs to entity managers + +Add entire new tabs to entity detail views. + +**Use Cases:** +- Add settings/configuration tabs +- Add related data tabs +- Add integration tabs + +**Example:** +```typescript +import { entityTabExtensionsServiceId, type EntityTabExtensionRegistry } from '@coreshop/resource/src/entities' + +const registry = container.get(entityTabExtensionsServiceId) + +registry.add('coreshop.address.country', ({ data }) => ({ + key: 'custom-tab', + label: 'Custom Settings', + icon: 'settings', + render: (tabData, onChange, ctx) => ( +
+

Custom Tab Content

+
+ + onChange({ customSetting: e.target.value })} + /> + +
+
+ ) +})) +``` + +#### 5. **Action Extensions** - Add custom buttons/actions + +Add custom buttons to toolbars, context menus, or footers. + +**Use Cases:** +- Export/Import functions +- Duplicate/Clone operations +- External integrations +- Bulk operations + +**Example:** +```typescript +import { entityActionExtensionsServiceId, type EntityActionExtensionRegistry } from '@coreshop/resource/src/entities' + +const registry = container.get(entityActionExtensionsServiceId) + +registry.add('coreshop.address.country', ({ data, position }) => { + if (position !== 'toolbar') return null + + return { + key: 'export', + label: 'Export', + type: 'default', + onClick: async (entityData) => { + // Implement export logic + await exportToCSV(entityData) + } + } +}) +``` + +**Positions:** +- `toolbar` - Top toolbar buttons +- `context-menu` - Right-click context menu +- `footer` - Bottom footer actions + +#### 6. **Validation Extensions** - Add custom validation + +Add custom validation logic that runs before save. + +**Use Cases:** +- Business rule validation +- Cross-field validation +- Async validation (uniqueness checks, API validation) +- Complex validation logic + +**Example:** +```typescript +import { entityValidationExtensionsServiceId, type EntityValidationExtensionRegistry } from '@coreshop/resource/src/entities' + +const registry = container.get(entityValidationExtensionsServiceId) + +registry.add('coreshop.address.country', async (data, context) => { + const errors: Record = {} + + // Validate ISO code format + if (data.isoCode && !/^[A-Z]{2}$/.test(data.isoCode)) { + errors.isoCode = ['ISO code must be 2 uppercase letters'] + } + + // Async validation - check uniqueness + if (data.name) { + const exists = await checkNameExists(data.name, data.id) + if (exists) { + errors.name = ['Country name already exists'] + } + } + + return { + valid: Object.keys(errors).length === 0, + errors: Object.keys(errors).length > 0 ? errors : undefined + } +}) +``` + +#### 7. **Lifecycle Hook Extensions** - Hook into entity lifecycle + +Execute code at specific lifecycle events. + +**Use Cases:** +- Data enrichment +- Logging/auditing +- Cache invalidation +- Triggering side effects +- Data cleanup + +**Hook Types:** +- `beforeLoad` - Before entity is loaded from API +- `afterLoad` - After entity is loaded (enrich data) +- `beforeSave` - Before save payload is sent (final cleanup) +- `afterSave` - After successful save (side effects) +- `beforeDelete` - Before deletion (validation) +- `afterDelete` - After deletion (cleanup) + +**Example:** +```typescript +import { entityLifecycleHooksServiceId, type EntityLifecycleHookRegistry } from '@coreshop/resource/src/entities' + +const registry = container.get(entityLifecycleHooksServiceId) + +// Enrich data after loading +registry.add('coreshop.address.country', 'afterLoad', (data, context) => { + return { + ...data, + _loadedAt: new Date().toISOString() + } +}) + +// Clean up before save +registry.add('coreshop.address.country', 'beforeSave', (data, context) => { + return { + ...data, + // Remove temporary fields + _loadedAt: undefined + } +}) + +// Side effects after save +registry.add('coreshop.address.country', 'afterSave', (data, context) => { + // Invalidate cache + invalidateCountryCache() + + // Log audit event + logAuditEvent('country_saved', context?.id) + + return data +}) +``` + +### Extension Module Pattern + +All extensions should be registered in a dedicated AbstractModule: + +```typescript +import { type AbstractModule, container } from '@pimcore/studio-ui-bundle' +import { entityFormExtensionsServiceId } from '@coreshop/resource/src/entities' + +export const MyExtensionModule: AbstractModule = { + onInit(): void { + const formRegistry = container.get(entityFormExtensionsServiceId) + + formRegistry.add('coreshop.address.country.form', ({ data, onChange }) => { + // Your extension + }) + } +} +``` + +Then register the module in your bundle's `main.ts`: + +```typescript +const plugin: IAbstractPlugin = { + name: 'my-bundle', + + onInit() { + // Bundle initialization + }, + + onStartup({ moduleSystem }) { + moduleSystem.registerModule(MyExtensionModule) + } +} +``` + +### Complete Example + +See `CoreBundle/Resources/assets/pimcore-studio/src/modules/extension/comprehensive-example/index.tsx` for a complete working example demonstrating all 7 extension types. + +### Extension Slot Reference + +**Common Slot Patterns:** + +Forms: +- `coreshop.address.country.form` +- `coreshop.address.state.form` +- `coreshop.address.zone.form` +- `coreshop.taxation.tax_rate.form` +- `coreshop.taxation.tax_rule_group.form` +- `coreshop.currency.currency.form` + +Tables: +- `coreshop.taxation.tax_rule_group.tax_rules` (nested tax rules table) + +Entity Keys (for save, validation, lifecycle, tabs, actions): +- `coreshop.address.country` +- `coreshop.address.state` +- `coreshop.address.zone` +- `coreshop.taxation.tax_rate` +- `coreshop.taxation.tax_rule_group` +- `coreshop.currency.currency` + +### Best Practices + +1. **Always use descriptive slot names** following the convention +2. **Keep extensions focused** - one extension per concern +3. **Handle errors gracefully** - extensions should never break the UI +4. **Use TypeScript** for type safety +5. **Document your extensions** - others need to know what you added +6. **Test extensions** - verify they work with the core system +7. **Consider bundle dependencies** - only extend entities your bundle depends on +8. **Use proper service IDs** - always import from `@coreshop/resource/src/entities` + +## Form Builder Pattern (Decorator-Based) + +CoreShop Studio v2 implements a **Decorator Pattern** for building flexible, extensible entity forms. This pattern allows bundles to define base forms and other bundles to extend them without creating tight coupling. + +### Architecture + +**FormBuilder** uses decorators to compose form configurations: +- Base bundle creates a FormBuilder with core fields +- Extension bundles add decorators to extend functionality +- Decorators can add fields, sections, validation, or modify existing configuration +- Similar to Pimcore Studio's ListingBuilder pattern + +### Key Concepts + +#### 1. **FormBuilder Class** + +```typescript +export class FormBuilder { + private decorators: Array<{ name: string, decorator: FormDecorator }> = [] + private baseConfig: FormBuilderConfig + + constructor(baseConfig: FormBuilderConfig) { + this.baseConfig = baseConfig + } + + addDecorator(name: string, decorator: FormDecorator): this + overrideDecorator(name: string, decorator: FormDecorator): this + removeDecorator(name: string): this + build(data?: T): FormBuilderConfig + copy(): FormBuilder +} +``` + +#### 2. **FormDecorator Type** + +```typescript +export interface FormDecorator { + (config: FormBuilderConfig, data?: T): FormBuilderConfig +} +``` + +Decorators are pure functions that transform form configuration. + +### Bundle Architecture + +**AddressBundle** (Base): +```typescript +// CountryFormBuilder.ts +export const createCountryFormBuilder = (): FormBuilder => { + const builder = new FormBuilder({ + fields: [ + { name: 'name', label: 'Name', component: Input }, + { name: 'isoCode', label: 'ISO Code', component: Input }, + { name: 'active', label: 'Active', component: Switch }, + { name: 'zone', label: 'Zone', component: ZoneSelect } // βœ… AddressBundle dependency + ] + }) + + builder.addDecorator('section-general', addSectionDecorator({ + key: 'general', + title: 'General Settings', + order: 10 + })) + + return builder +} + +// main.ts +export const CountryFormBuilderModule: AbstractModule = { + onInit(): void { + const builder = createCountryFormBuilder() + container.bind('CoreShop/Address/Country/FormBuilder').toConstantValue(builder) + } +} +``` + +**CoreBundle** (Extension): +```typescript +// country-form-extension.ts +export const CountryFormExtensionModule: AbstractModule = { + onInit(): void { + const builder = container.get>( + 'CoreShop/Address/Country/FormBuilder' + ) + + // CoreBundle has dependency on CurrencyBundle + builder.addDecorator('currency-section', addSectionDecorator({ + key: 'currency', + title: 'Currency Settings', + order: 30 + })) + + builder.addDecorator('currency-field', addFieldDecorator({ + name: 'currency', + label: 'Default Currency', + component: CurrencySelect, // βœ… CoreBundle knows CurrencyBundle + section: 'currency' + })) + } +} +``` + +### Common Decorator Patterns + +#### Add Fields +```typescript +const addFieldDecorator = (field: FieldDefinition): FormDecorator => { + return (config) => ({ + ...config, + fields: [...config.fields, field] + }) +} +``` + +#### Add Sections +```typescript +const addSectionDecorator = (section: SectionDefinition): FormDecorator => { + return (config) => ({ + ...config, + sections: [...(config.sections ?? []), section] + }) +} +``` + +#### Conditional Fields +```typescript +const conditionalDecorator: FormDecorator = (config, data) => { + if (!data?.active) return config + + return { + ...config, + fields: [...config.fields, { name: 'activeOnlyField', ... }] + } +} +``` + +#### Add Validation +```typescript +const validationDecorator: FormDecorator = (config) => ({ + ...config, + validationRules: [ + ...(config.validationRules ?? []), + { field: 'isoCode', rules: [{ pattern: /^[A-Z]{2}$/ }] } + ] +}) +``` + +### Usage in Components + +```typescript +export const CountryForm: React.FC = ({ data, onChange }) => { + const builder = container.get>( + 'CoreShop/Address/Country/FormBuilder' + ) + + const config = React.useMemo(() => builder.build(data), [data]) + + return +} +``` + +### Key Principles + +1. βœ… **Bundle Independence**: Base bundle doesn't know about extensions +2. βœ… **Decorator Composition**: Multiple decorators can be combined +3. βœ… **Type Safety**: TypeScript ensures type-safe transformations +4. βœ… **Testability**: Decorators are pure functions +5. βœ… **Order Control**: Decorators execute in registration order +6. βœ… **Override Support**: `overrideDecorator()` for replacing decorators + +### Dependency Chain + +``` +AddressBundle + ↓ Creates base FormBuilder + ↓ Registers AddressBundle-specific fields (zone, addressFormat) + ↓ Binds to container: 'CoreShop/Address/Country/FormBuilder' + +CoreBundle + ↓ Has dependency on AddressBundle + ↓ Has dependency on CurrencyBundle + ↓ Gets FormBuilder from container + ↓ Adds decorators for cross-bundle fields (currency) +``` + +### Benefits + +- **Flexible**: Decorators can add, remove, or modify any part of form config +- **Composable**: Multiple bundles can extend the same form +- **Conditional**: Decorators can use data to make decisions +- **Testable**: Pure functions are easy to unit test +- **Similar to Pimcore**: Follows same pattern as Pimcore Studio's ListingBuilder + +### Example: Complete Form Structure + +After all decorators are applied: + +**Sections:** +1. **General Settings** (order: 10) - AddressBundle + - name, isoCode, active, zone +2. **Address Configuration** (order: 20) - AddressBundle + - addressFormat, salutations +3. **Currency Settings** (order: 30) - CoreBundle + - currency (cross-bundle extension) + +## Dynamic Types for Pimcore Data Objects + +CoreShop extends Pimcore's Data Object field types with custom dynamic types for eCommerce-specific data. These types allow selection of CoreShop entities (Countries, Currencies, Stores, etc.) directly in Pimcore Data Object class definitions. + +### Architecture + +**Pimcore Studio v2** uses a `DynamicTypeObjectDataRegistry` to manage custom field types: + +```typescript +import { container } from '@pimcore/studio-ui-bundle' +import { DynamicTypeObjectDataRegistry } from '@pimcore/studio-ui-bundle/modules/element' +import { serviceIds } from '@pimcore/studio-ui-bundle/app' + +const registry = container.get( + serviceIds['DynamicTypes/ObjectDataRegistry'] +) + +registry.registerDynamicType(new MyCustomType()) +``` + +### Available Abstract Classes + +From `@pimcore/studio-ui-bundle/modules/element`: + +- **`DynamicTypeObjectDataAbstract`** - Base class for all field types +- **`DynamicTypeObjectDataAbstractSelect`** - For single-select fields (extends Abstract) +- **`DynamicTypeObjectDataAbstractMultiSelect`** - For multi-select fields (extends Abstract) + +### Implementation Pattern + +**1. Create the Dynamic Type Class:** + +```typescript +// dynamic-types/DynamicTypeObjectDataCoreShopCountry.tsx +import { + DynamicTypeObjectDataAbstractSelect, + DynamicTypeFieldFilterMultiselect +} from '@pimcore/studio-ui-bundle/modules/element' + +export class DynamicTypeObjectDataCoreShopCountry extends DynamicTypeObjectDataAbstractSelect { + // The id MUST match the PHP CoreExtension type name + readonly id = 'coreShopCountry' + readonly dynamicTypeFieldFilterType = new DynamicTypeFieldFilterMultiselect() +} +``` + +**2. Register in main.ts (onInit lifecycle):** + +```typescript +import { container, IAbstractPlugin } from '@pimcore/studio-ui-bundle' +import { serviceIds } from '@pimcore/studio-ui-bundle/app' +import { DynamicTypeObjectDataRegistry } from '@pimcore/studio-ui-bundle/modules/element' +import { DynamicTypeObjectDataCoreShopCountry } from './dynamic-types' + +const plugin: IAbstractPlugin = { + name: 'my-plugin', + + onInit() { + const objectDataRegistry = container.get( + serviceIds['DynamicTypes/ObjectDataRegistry'] + ) + + objectDataRegistry.registerDynamicType(new DynamicTypeObjectDataCoreShopCountry()) + }, + + onStartup({ moduleSystem }) { + // Widget registration etc. + } +} +``` + +### Key Points + +1. **ID must match PHP type**: The `id` property must exactly match the PHP CoreExtension field type name (e.g., `coreShopCountry`) +2. **Options from backend**: The select options are provided by the PHP backend - the frontend just renders them +3. **Registration in onInit**: Dynamic types MUST be registered in `onInit()`, not `onStartup()` +4. **Abstract classes handle rendering**: `DynamicTypeObjectDataAbstractSelect` provides grid support, batch edit, and version handling + +### CoreShop Dynamic Types List + +#### Simple Select Types + +| Type | Bundle | Base Class | +|------|--------|------------| +| `coreShopCountry` | AddressBundle | AbstractSelect | +| `coreShopCountryMultiselect` | AddressBundle | AbstractMultiSelect | +| `coreShopState` | AddressBundle | AbstractSelect | +| `coreShopAddressIdentifier` | AddressBundle | AbstractSelect | +| `coreShopCurrency` | CurrencyBundle | AbstractSelect | +| `coreShopCurrencyMultiselect` | CurrencyBundle | AbstractMultiSelect | +| `coreShopStore` | StoreBundle | AbstractSelect | +| `coreShopStoreMultiselect` | StoreBundle | AbstractMultiSelect | +| `coreShopCarrier` | ShippingBundle | AbstractSelect | +| `coreShopCarrierMultiselect` | ShippingBundle | AbstractMultiSelect | +| `coreShopPaymentProvider` | PaymentBundle | AbstractSelect | +| `coreShopPaymentProviderMultiselect` | PaymentBundle | AbstractMultiSelect | +| `coreShopTaxRate` | TaxationBundle | AbstractSelect | +| `coreShopTaxRuleGroup` | TaxationBundle | AbstractSelect | +| `coreShopFilter` | IndexBundle | AbstractSelect | +| `coreShopCartPriceRule` | OrderBundle | AbstractSelect | +| `coreShopProductUnit` | ProductBundle | AbstractSelect | +| `coreShopProductUnitDefinition` | ProductBundle | AbstractSelect | +| `coreShopProductUnitDefinitions` | ProductBundle | AbstractMultiSelect | + +#### Complex Dynamic Types + +These types have custom rendering and editing logic beyond simple select fields: + +| Type | Bundle | Description | +|------|--------|-------------| +| `coreShopMoney` | MoneyBundle | Currency-aware money input with amount and currency | +| `coreShopMoneyCurrency` | CurrencyBundle | Money field with currency selection | +| `coreShopStoreValues` | CoreBundle | Store-specific values (prices per store) | +| `coreShopRelation` | ResourceBundle | Single CoreShop entity relation | +| `coreShopRelations` | ResourceBundle | Multiple CoreShop entity relations | +| `coreShopProductSpecificPriceRules` | ProductBundle | Inline product-specific price rules editor | +| `coreShopProductQuantityPriceRules` | ProductQuantityPriceRulesBundle | Inline quantity/volume price rules editor | + +### File Structure + +``` +BundleX/Resources/assets/pimcore-studio/src/ +β”œβ”€β”€ dynamic-types/ +β”‚ β”œβ”€β”€ DynamicTypeObjectDataCoreShopXxx.tsx +β”‚ β”œβ”€β”€ DynamicTypeObjectDataCoreShopXxxMultiselect.tsx +β”‚ └── index.ts +└── main.ts # Registration in onInit() +``` + +## Knowledge Graph +Use the knowledge-graph-mcp before and after every task you do. \ No newline at end of file diff --git a/composer.json b/composer.json index d5cb6e92d9..56891d5842 100644 --- a/composer.json +++ b/composer.json @@ -101,6 +101,7 @@ "php-http/guzzle7-adapter": "^1.0", "php-http/message-factory": "^1.1", "pimcore/admin-ui-classic-bundle": "^2.0", + "pimcore/generic-data-index-bundle": "2.x-dev", "pimcore/google-marketing-bundle": "^2.0", "pimcore/newsletter-bundle": "^2.0", "pimcore/pimcore": "^12.3", @@ -121,7 +122,10 @@ "webmozart/assert": "^1.12" }, "suggest": { - "pimcore/opensearch-client": "Allows to use OpenSearch as your index engine." + "pimcore/opensearch-client": "Allows to use OpenSearch as your index engine.", + "pimcore/elasticsearch-client": "Allows to use ElasticSearch as your index engine.", + "pimcore/admin-ui-classic-bundle": "^2.0 - Classic ExtJS-based admin interface for Pimcore (legacy)", + "pimcore/studio-ui-bundle": "^1.0 - Modern React-based Studio UI for Pimcore (recommended)" }, "conflict": { "ezimuel/ringphp": "<1.4" @@ -137,18 +141,20 @@ "friends-of-behat/symfony-extension": "^2.6", "gotenberg/gotenberg-php": "^2.6", "lendable/composer-license-checker": "^1.2", + "php-webdriver/webdriver": "^1.15", "phpstan/phpstan": "^2.1", "phpstan/phpstan-doctrine": "^2.0", "phpstan/phpstan-symfony": "^2.0", "phpstan/phpstan-webmozart-assert": "^2.0", "phpunit/phpunit": "^10.0", "pimcore/opensearch-client": "^2.1", + "pimcore/studio-backend-bundle": "^0.12.18", + "pimcore/studio-ui-bundle": "^0.12.18", "robertfausk/behat-panther-extension": "^1.2", - "symfony/panther": "^2.3", - "php-webdriver/webdriver": "^1.15", "symfony/browser-kit": "^6.3 || ^7.0", - "symfony/runtime": "^6.4 || ^7.0", "symfony/css-selector": "^6.4 || ^7.0", + "symfony/panther": "^2.3", + "symfony/runtime": "^6.4 || ^7.0", "symplify/easy-coding-standard": "^11.1", "vimeo/psalm": "^6.10" }, diff --git a/config/bundles.php b/config/bundles.php index 038f64d864..c6119a4f42 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -7,4 +7,9 @@ Pimcore\Bundle\StaticRoutesBundle\PimcoreStaticRoutesBundle::class => ['all' => true], Pimcore\Bundle\NewsletterBundle\PimcoreNewsletterBundle::class => ['all' => true], Pimcore\Bundle\OpenSearchClientBundle\PimcoreOpenSearchClientBundle::class => ['all' => true], + Pimcore\Bundle\StudioUiBundle\PimcoreStudioUiBundle::class => ['all' => true], + \Pimcore\Bundle\StudioBackendBundle\PimcoreStudioBackendBundle::class => ['all' => true], + Pimcore\Bundle\GenericDataIndexBundle\PimcoreGenericDataIndexBundle::class => ['all' => true], + Pimcore\Bundle\GenericExecutionEngineBundle\PimcoreGenericExecutionEngineBundle::class => ['all' => true], + \Pimcore\Bundle\AdminBundle\PimcoreAdminBundle::class => ['all' => true], ]; diff --git a/config/packages/pimcore_studio_backend.yaml b/config/packages/pimcore_studio_backend.yaml new file mode 100644 index 0000000000..70dd455a1d --- /dev/null +++ b/config/packages/pimcore_studio_backend.yaml @@ -0,0 +1,10 @@ +pimcore_studio_backend: + mercure_settings: + # Server-seitig: Docker-internes Netzwerk + hub_url_server: 'http://mercure/.well-known/mercure' + # Client-seitig: VollstΓ€ndige URL inkl. .well-known/mercure + hub_url_client: 'https://coreshop-5.localhost/hub/.well-known/mercure' + # Muss mit docker-compose.override.yaml ΓΌbereinstimmen + jwt_key: 'SECRET_MERCURE_KEY_SECRET_MERCURE_KEY' + # Cookie-Pfad muss /hub sein, damit es fΓΌr alle Mercure-Requests gilt + jwt_cookie_host: 'coreshop-5.localhost' diff --git a/config/packages/security.yaml b/config/packages/security.yaml index f057721291..634e861c30 100755 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,5 +1,5 @@ parameters: - coreshop.security.frontend_regex: "^/(?!admin)[^/]*" + coreshop.security.frontend_regex: "^/(?!admin|!pimcore-studio)[^/]*" pimcore: security: @@ -26,6 +26,8 @@ security: # Pimcore Admin Bundle firewall pimcore_admin: '%pimcore_admin_bundle.firewall_settings%' + pimcore_studio: '%pimcore_studio_backend.firewall_settings%' + coreshop_frontend: provider: coreshop_user @@ -61,6 +63,8 @@ security: - { path: ^/asset/webdav, roles: ROLE_PIMCORE_USER } - { path: "%coreshop.security.frontend_regex%/_partial", role: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1] } - { path: "%coreshop.security.frontend_regex%/_partial", role: ROLE_NO_ACCESS } + - { path: ^/pimcore-studio/api/(docs|docs/json|translations)$, roles: PUBLIC_ACCESS } + - { path: ^/pimcore-studio/api, roles: ROLE_PIMCORE_USER } role_hierarchy: # Pimcore admin // DO NOT CHANGE! diff --git a/config/reference.php b/config/reference.php new file mode 100644 index 0000000000..51d2119c18 --- /dev/null +++ b/config/reference.php @@ -0,0 +1,4810 @@ + [ + * 'App\\' => [ + * 'resource' => '../src/', + * ], + * ], + * ]); + * ``` + * + * @psalm-type ImportsConfig = list + * @psalm-type ParametersConfig = array|null>|null> + * @psalm-type ArgumentsType = list|array + * @psalm-type CallType = array|array{0:string, 1?:ArgumentsType, 2?:bool}|array{method:string, arguments?:ArgumentsType, returns_clone?:bool} + * @psalm-type TagsType = list>> // arrays inside the list must have only one element, with the tag name as the key + * @psalm-type CallbackType = string|array{0:string|ReferenceConfigurator,1:string}|\Closure|ReferenceConfigurator|ExpressionConfigurator + * @psalm-type DeprecationType = array{package: string, version: string, message?: string} + * @psalm-type DefaultsType = array{ + * public?: bool, + * tags?: TagsType, + * resource_tags?: TagsType, + * autowire?: bool, + * autoconfigure?: bool, + * bind?: array, + * } + * @psalm-type InstanceofType = array{ + * shared?: bool, + * lazy?: bool|string, + * public?: bool, + * properties?: array, + * configurator?: CallbackType, + * calls?: list, + * tags?: TagsType, + * resource_tags?: TagsType, + * autowire?: bool, + * bind?: array, + * constructor?: string, + * } + * @psalm-type DefinitionType = array{ + * class?: string, + * file?: string, + * parent?: string, + * shared?: bool, + * synthetic?: bool, + * lazy?: bool|string, + * public?: bool, + * abstract?: bool, + * deprecated?: DeprecationType, + * factory?: CallbackType, + * configurator?: CallbackType, + * arguments?: ArgumentsType, + * properties?: array, + * calls?: list, + * tags?: TagsType, + * resource_tags?: TagsType, + * decorates?: string, + * decoration_inner_name?: string, + * decoration_priority?: int, + * decoration_on_invalid?: 'exception'|'ignore'|null, + * autowire?: bool, + * autoconfigure?: bool, + * bind?: array, + * constructor?: string, + * from_callable?: CallbackType, + * } + * @psalm-type AliasType = string|array{ + * alias: string, + * public?: bool, + * deprecated?: DeprecationType, + * } + * @psalm-type PrototypeType = array{ + * resource: string, + * namespace?: string, + * exclude?: string|list, + * parent?: string, + * shared?: bool, + * lazy?: bool|string, + * public?: bool, + * abstract?: bool, + * deprecated?: DeprecationType, + * factory?: CallbackType, + * arguments?: ArgumentsType, + * properties?: array, + * configurator?: CallbackType, + * calls?: list, + * tags?: TagsType, + * resource_tags?: TagsType, + * autowire?: bool, + * autoconfigure?: bool, + * bind?: array, + * constructor?: string, + * } + * @psalm-type StackType = array{ + * stack: list>, + * public?: bool, + * deprecated?: DeprecationType, + * } + * @psalm-type ServicesConfig = array{ + * _defaults?: DefaultsType, + * _instanceof?: InstanceofType, + * ... + * } + * @psalm-type ExtensionType = array + * @psalm-type PimcoreSeoConfig = array{ + * sitemaps?: array{ + * generators?: array, + * }, + * redirects?: array{ + * status_codes?: list, + * auto_create_redirects?: bool|Param, // Auto create redirects on moving documents & changing pretty url, updating Url slugs in Data Objects. // Default: false + * }, + * } + * @psalm-type PimcoreStaticRoutesConfig = array{ + * definitions?: list, + * methods?: list, + * priority?: int|Param, + * creationDate?: int|Param, + * modificationDate?: int|Param, + * }>, + * config_location?: array{ + * staticroutes?: array{ + * write_target?: array{ + * type?: "symfony-config"|"settings-store"|"disabled"|Param, // Default: "symfony-config" + * options?: list, + * }, + * }, + * }, + * } + * @psalm-type PimcoreNewsletterConfig = array{ + * sender?: array{ + * name?: scalar|null|Param, + * email?: scalar|null|Param, + * }, + * return?: array{ + * name?: scalar|null|Param, + * email?: scalar|null|Param, + * }, + * method?: scalar|null|Param, // Default: null + * debug?: array{ + * email_addresses?: scalar|null|Param, // Default: "" + * }, + * use_specific?: bool|Param, // Default: false + * source_adapters?: array, + * default_url_prefix?: scalar|null|Param, // Default: null + * } + * @psalm-type PimcoreOpenSearchClientConfig = array{ + * clients?: array, + * logger_channel?: scalar|null|Param, // Logger channel to be used for opensearch client logs // Default: "pimcore.opensearch.default" + * log_404_errors?: bool|Param, // Enables logging of 404 errors (default: false) // Default: false + * username?: scalar|null|Param, // Username for opensearch authentication // Default: "admin" + * password?: scalar|null|Param, // Password for opensearch authentication // Default: "admin" + * ssl_key?: scalar|null|Param, // Path to private SSL key file (.key) + * ssl_cert?: scalar|null|Param, // Path to PEM formatted SSL cert file (.cert) + * ssl_password?: scalar|null|Param, // If private key and certificate require a password (default: null) + * ssl_verification?: bool|Param, // Enable or disable the SSL verification (default: true) + * aws_region?: scalar|null|Param, // Will set the setSigV4Region() + * aws_service?: scalar|null|Param, // Will set the setSigV4ServicesetSigV4Service() + * aws_key?: scalar|null|Param, // Will set the setSigV4CredentialProvider() key + * aws_secret?: scalar|null|Param, // Will set the setSigV4CredentialProvider() key + * }>, + * } + * @psalm-type PimcoreStudioUiConfig = array{ + * url_path?: scalar|null|Param, // Default: "/pimcore-studio" + * static_resources?: array{ + * css?: list, + * js?: list, + * editmode?: array{ + * css?: list, + * js?: list, + * }, + * }, + * wysiwyg?: array{ + * defaultEditorConfig?: array{ + * document?: mixed, // Default: [] + * dataObject?: mixed, // Default: [] + * }, + * }, + * csp_header?: bool|array{ // Can be used to enable or disable the Content Security Policy headers. + * enabled?: bool|Param, // Default: true + * exclude_paths?: list, + * additional_urls?: array{ + * default-src?: list, + * img-src?: list, + * script-src?: list, + * style-src?: list, + * connect-src?: list, + * font-src?: list, + * media-src?: list, + * frame-src?: list, + * }, + * }, + * } + * @psalm-type PimcoreStudioBackendConfig = array{ + * url_prefix?: scalar|null|Param, // Default: "/pimcore-studio/api" + * open_api_scan_paths?: list, + * api_token?: array{ + * lifetime?: int|Param, // Default: 3600 + * }, + * allowed_hosts_for_cors?: list, + * security_firewall?: mixed, + * asset_default_formats?: array, + * element_recycle_bin_threshold?: int|Param, // Default: 100 + * mercure_settings?: array{ + * hub_url_server?: scalar|null|Param, // The url to the mercure hub for the server.This can also be the docker container name (e.g., http://mercure/.well-known/mercure). If it is not set, default will be set to "http(s):///hub/.well-known/mercure". // Default: null + * hub_url_client?: scalar|null|Param, // The url to the mercure hub for the (frontend) client. If it is not set, the default will be set to "http(s):///hub". It is possible to use "" as a placeholder for the current schema and host if path to mercure should be different. // Default: null + * jwt_key: scalar|null|Param, // The key used to sign the JWT token. Must be longer than 256 bits. // Default: "some-secret-default" + * cookie_lifetime?: int|Param, // Lifetime of the mercure cookie in seconds. Default is one hour. // Default: 3600 + * jwt_cookie_host?: scalar|null|Param, // Domain where to set the Mercure auth cookie, e.g. ".example.com". // Default: null + * jwt_cookie_strictness?: bool|Param, // If true, use SameSite=Strict; if false, use SameSite=None. // Default: true + * }, + * asset_download_settings?: array{ + * size_limit?: int|Param, // The maximum size of all assets together that can be downloaded in bytes. // Default: 5368709120 + * amount_limit?: int|Param, // The maximum amount of assets that can be downloaded at once. // Default: 1000 + * }, + * csv_settings?: array{ + * default_delimiter?: scalar|null|Param, // Default delimiter to be used for csv operations. // Default: ";" + * }, + * grid?: array{ + * asset?: array{ + * predefined_columns?: list, + * }, + * data_object?: array{ + * predefined_columns?: list, + * skip_field_types?: list, + * }, + * }, + * search_grid?: array{ + * asset?: array{ + * predefined_columns?: list, + * }, + * data_object?: array{ + * predefined_columns?: list, + * }, + * }, + * notes?: array{ + * types?: array{ // List all note types for asset, document, and data-object. + * asset?: list, + * document?: list, + * data-object?: list, + * }, + * }, + * asset_metadata_adapter_mapping?: array>, + * data_object_data_adapter_mapping?: array>, + * document_type_adapter_mapping?: array>, + * user?: array{ + * default_key_bindings?: list, + * }, + * open_api_servers?: list, + * widget_types?: list, + * studio_perspectives?: array, + * widgetsRight?: array, + * widgetsBottom?: array, + * expandedLeft?: scalar|null|Param, // The id of the widget that should be expanded on the left side. // Default: null + * expandedRight?: scalar|null|Param, // The id of the widget that should be expanded on the right side. // Default: null + * contextPermissions?: array>, + * }>, + * element_tree_widgets?: array, + * pql?: scalar|null|Param, // Default: null + * contextPermissions?: list, + * }>, + * studio_from_default_email?: scalar|null|Param, // Default: "studio-admin@pimcore.com" + * twig?: array{ // Configure the Twig sandbox policy. + * sandbox_security_policy?: array{ + * tags?: list, + * filters?: list, + * functions?: list, + * }, + * }, + * config_location?: array{ + * element_tree_widgets?: array{ + * write_target?: array{ + * type?: "symfony-config"|"settings-store"|"disabled"|Param, // Default: "symfony-config" + * options?: list, + * }, + * read_target?: array{ + * type?: "symfony-config"|"settings-store"|Param, // Default: null + * options?: list, + * }, + * }, + * studio_perspectives?: array{ + * write_target?: array{ + * type?: "symfony-config"|"settings-store"|"disabled"|Param, // Default: "symfony-config" + * options?: list, + * }, + * read_target?: array{ + * type?: "symfony-config"|"settings-store"|Param, // Default: null + * options?: list, + * }, + * }, + * }, + * } + * @psalm-type PimcoreGenericDataIndexConfig = array{ + * index_service?: array{ + * client_params?: array{ + * client_name?: scalar|null|Param, // Name of search client from to be used. // Default: "default" + * client_type?: "openSearch"|"elasticsearch"|Param, // Type of search client to be used. // Default: "openSearch" + * index_prefix?: scalar|null|Param, // Default: "pimcore_" + * }, + * search_settings?: array{ + * list_page_size?: scalar|null|Param, // Default: 60 + * list_max_filter_options?: scalar|null|Param, // Default: 500 + * max_synchronous_children_rename_limit?: scalar|null|Param, // Maximum number of direct/synchronous children path updates if asset folders get renamed. If more then the given number of children need an path update the process will be done by the asynchronous index update command. This mechanismn is needed to be able to see directly the new paths in the folder navigation. // Default: 500 + * search_analyzer_attributes?: array, + * }, + * index_settings?: mixed, // Default: [] + * queue_settings?: array{ + * worker_count?: scalar|null|Param, // Default: 1 + * min_batch_size?: scalar|null|Param, // Default: 5 + * max_batch_size?: scalar|null|Param, // Default: 400 + * }, + * system_fields_settings?: array{ + * general?: array, + * document?: array, + * data_object?: array, + * asset?: array, + * }, + * }, + * } + * @psalm-type PimcoreGenericExecutionEngineConfig = array{ + * error_handling?: "continue_on_error"|"stop_on_first_error"|Param, // Specifies how errors should be handled for all job run executions. // Default: "continue_on_error" + * execution_context?: list, + * } + * @psalm-type PimcoreAdminConfig = array{ + * gdpr_data_extractor?: array{ + * dataObjects?: array{ // Settings for DataObjects DataProvider + * classes?: list, + * }>, + * }, + * assets?: array{ // Settings for Assets DataProvider + * types?: list, + * }, + * }, + * objects?: array{ + * notes_events?: array{ + * types?: list, + * }, + * }, + * assets?: array{ + * notes_events?: array{ + * types?: list, + * }, + * hide_edit_image?: bool|Param, // Default: false + * disable_tree_preview?: bool|Param, // Default: true + * }, + * documents?: array{ + * notes_events?: array{ + * types?: list, + * }, + * email_search?: list, + * }, + * notifications?: bool|array{ + * enabled?: bool|Param, // Default: true + * check_new_notification?: bool|array{ // Can be used to enable or disable the check of new notifications (url: /admin/notification/find-last-unread). + * enabled?: bool|Param, // Default: true + * interval?: int|Param, // Interval in seconds to check new notifications // Default: 30 + * }, + * }, + * user?: array{ + * default_key_bindings?: list, + * }, + * admin_languages?: list, + * csrf_protection?: array{ + * excluded_routes?: list, + * }, + * admin_csp_header?: bool|array{ // Can be used to enable or disable the Content Security Policy headers. + * enabled?: bool|Param, // Default: true + * exclude_paths?: list, + * additional_urls?: array{ + * default-src?: list, + * img-src?: list, + * script-src?: list, + * style-src?: list, + * connect-src?: list, + * font-src?: list, + * media-src?: list, + * frame-src?: list, + * }, + * }, + * custom_admin_path_identifier?: scalar|null|Param, // Default: null + * custom_admin_route_name?: scalar|null|Param, // Default: "my_custom_admin_entry_point" + * branding?: array{ + * login_screen_invert_colors?: bool|Param, // Default: false + * color_login_screen?: scalar|null|Param, // Default: null + * color_admin_interface?: scalar|null|Param, // Default: null + * color_admin_interface_background?: scalar|null|Param, // Default: null + * login_screen_custom_image?: scalar|null|Param, // Default: "" + * }, + * session?: array{ + * attribute_bags?: array, + * }, + * translations?: array{ + * path?: scalar|null|Param, // Default: null + * }, + * security_firewall?: mixed, + * config_location?: array{ + * admin_system_settings?: array{ + * write_target?: array{ + * type?: "symfony-config"|"settings-store"|"disabled"|Param, // Default: "symfony-config" + * options?: list, + * }, + * read_target?: array{ + * type?: "symfony-config"|"settings-store"|Param, // Default: null + * options?: list, + * }, + * }, + * }, + * } + * @psalm-type PimcoreCustomReportsConfig = array{ + * definitions?: list, + * columnConfiguration?: list, + * pagination?: bool|Param, + * }>, + * adapters?: array, + * config_location?: array{ + * custom_reports?: array{ + * write_target?: array{ + * type?: "symfony-config"|"settings-store"|"disabled"|Param, // Default: "symfony-config" + * options?: list, + * }, + * }, + * }, + * } + * @psalm-type CoreShopMenuConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * } + * @psalm-type JmsSerializerConfig = array{ + * twig_enabled?: scalar|null|Param, // Default: "default" + * profiler?: scalar|null|Param, // Default: true + * enum_support?: scalar|null|Param, // Default: false + * default_value_property_reader_support?: scalar|null|Param, // Default: false + * handlers?: array{ + * datetime?: array{ + * default_format?: scalar|null|Param, // Default: "Y-m-d\\TH:i:sP" + * default_deserialization_formats?: list, + * default_timezone?: scalar|null|Param, // Default: "Europe/Berlin" + * cdata?: scalar|null|Param, // Default: true + * }, + * array_collection?: array{ + * initialize_excluded?: bool|Param, // Default: false + * }, + * symfony_uid?: array{ + * default_format?: scalar|null|Param, // Default: "canonical" + * cdata?: scalar|null|Param, // Default: true + * }, + * }, + * subscribers?: array{ + * doctrine_proxy?: array{ + * initialize_excluded?: bool|Param, // Default: false + * initialize_virtual_types?: bool|Param, // Default: false + * }, + * }, + * object_constructors?: array{ + * doctrine?: bool|array{ + * enabled?: bool|Param, // Default: true + * fallback_strategy?: "null"|"exception"|"fallback"|Param, // Default: "null" + * }, + * }, + * property_naming?: string|array{ + * id?: scalar|null|Param, + * separator?: scalar|null|Param, // Default: "_" + * lower_case?: bool|Param, // Default: true + * }, + * expression_evaluator?: string|array{ + * id?: scalar|null|Param, // Default: "jms_serializer.expression_evaluator" + * }, + * metadata?: array{ + * warmup?: array{ + * paths?: array{ + * included?: list, + * excluded?: list, + * }, + * }, + * cache?: scalar|null|Param, // Default: "file" + * debug?: bool|Param, // Default: true + * file_cache?: array{ + * dir?: scalar|null|Param, // Default: null + * }, + * include_interfaces?: bool|Param, // Default: false + * auto_detection?: bool|Param, // Default: true + * infer_types_from_doc_block?: bool|Param, // Default: false + * infer_types_from_doctrine_metadata?: bool|Param, // Infers type information from Doctrine metadata if no explicit type has been defined for a property. // Default: true + * directories?: array, + * }, + * visitors?: array{ + * json_serialization?: array{ + * depth?: scalar|null|Param, + * options?: scalar|null|Param, // Default: 1024 + * }, + * json_deserialization?: array{ + * options?: scalar|null|Param, // Default: 0 + * strict?: bool|Param, // Default: false + * }, + * xml_serialization?: array{ + * version?: scalar|null|Param, + * encoding?: scalar|null|Param, + * format_output?: bool|Param, // Default: false + * default_root_name?: scalar|null|Param, + * default_root_ns?: scalar|null|Param, // Default: "" + * }, + * xml_deserialization?: array{ + * doctype_whitelist?: list, + * external_entities?: bool|Param, // Default: false + * options?: scalar|null|Param, // Default: 0 + * }, + * }, + * default_context?: array{ + * serialization?: string|array{ + * id?: scalar|null|Param, + * serialize_null?: scalar|null|Param, // Flag if null values should be serialized + * enable_max_depth_checks?: scalar|null|Param, // Flag to enable the max-depth exclusion strategy + * attributes?: array, + * groups?: list, + * version?: scalar|null|Param, // Application version to use in exclusion strategies + * }, + * deserialization?: string|array{ + * id?: scalar|null|Param, + * serialize_null?: scalar|null|Param, // Flag if null values should be serialized + * enable_max_depth_checks?: scalar|null|Param, // Flag to enable the max-depth exclusion strategy + * attributes?: array, + * groups?: list, + * version?: scalar|null|Param, // Application version to use in exclusion strategies + * }, + * }, + * instances?: array, + * default_timezone?: scalar|null|Param, // Default: "Europe/Berlin" + * cdata?: scalar|null|Param, // Default: true + * }, + * array_collection?: array{ + * initialize_excluded?: bool|Param, // Default: false + * }, + * symfony_uid?: array{ + * default_format?: scalar|null|Param, // Default: "canonical" + * cdata?: scalar|null|Param, // Default: true + * }, + * }, + * subscribers?: array{ + * doctrine_proxy?: array{ + * initialize_excluded?: bool|Param, // Default: false + * initialize_virtual_types?: bool|Param, // Default: false + * }, + * }, + * object_constructors?: array{ + * doctrine?: bool|array{ + * enabled?: bool|Param, // Default: true + * fallback_strategy?: "null"|"exception"|"fallback"|Param, // Default: "null" + * }, + * }, + * property_naming?: string|array{ + * id?: scalar|null|Param, + * separator?: scalar|null|Param, // Default: "_" + * lower_case?: bool|Param, // Default: true + * }, + * expression_evaluator?: string|array{ + * id?: scalar|null|Param, // Default: "jms_serializer.expression_evaluator" + * }, + * metadata?: array{ + * warmup?: array{ + * paths?: array{ + * included?: list, + * excluded?: list, + * }, + * }, + * cache?: scalar|null|Param, // Default: "file" + * debug?: bool|Param, // Default: true + * file_cache?: array{ + * dir?: scalar|null|Param, // Default: null + * }, + * include_interfaces?: bool|Param, // Default: false + * auto_detection?: bool|Param, // Default: true + * infer_types_from_doc_block?: bool|Param, // Default: false + * infer_types_from_doctrine_metadata?: bool|Param, // Infers type information from Doctrine metadata if no explicit type has been defined for a property. // Default: true + * directories?: array, + * }, + * visitors?: array{ + * json_serialization?: array{ + * depth?: scalar|null|Param, + * options?: scalar|null|Param, // Default: 1024 + * }, + * json_deserialization?: array{ + * options?: scalar|null|Param, // Default: 0 + * strict?: bool|Param, // Default: false + * }, + * xml_serialization?: array{ + * version?: scalar|null|Param, + * encoding?: scalar|null|Param, + * format_output?: bool|Param, // Default: false + * default_root_name?: scalar|null|Param, + * default_root_ns?: scalar|null|Param, // Default: "" + * }, + * xml_deserialization?: array{ + * doctype_whitelist?: list, + * external_entities?: bool|Param, // Default: false + * options?: scalar|null|Param, // Default: 0 + * }, + * }, + * default_context?: array{ + * serialization?: string|array{ + * id?: scalar|null|Param, + * serialize_null?: scalar|null|Param, // Flag if null values should be serialized + * enable_max_depth_checks?: scalar|null|Param, // Flag to enable the max-depth exclusion strategy + * attributes?: array, + * groups?: list, + * version?: scalar|null|Param, // Application version to use in exclusion strategies + * }, + * deserialization?: string|array{ + * id?: scalar|null|Param, + * serialize_null?: scalar|null|Param, // Flag if null values should be serialized + * enable_max_depth_checks?: scalar|null|Param, // Flag to enable the max-depth exclusion strategy + * attributes?: array, + * groups?: list, + * version?: scalar|null|Param, // Application version to use in exclusion strategies + * }, + * }, + * }>, + * } + * @psalm-type CoreShopPimcoreConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * }, + * } + * @psalm-type CoreShopLocaleConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * } + * @psalm-type CoreShopResourceConfig = array{ + * mapping?: array{ + * paths?: list, + * }, + * resources?: array, + * pimcore?: array, + * classes?: array{ + * model: scalar|null|Param, + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Pimcore\\PimcoreRepository" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * install_file?: scalar|null|Param, + * type?: scalar|null|Param, // Default: "object" + * pimcore_controller?: array, + * }, + * }>, + * translation?: bool|array{ + * enabled?: bool|Param, // Default: true + * locale_provider?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Translation\\Provider\\TranslationLocaleProviderInterface" + * }, + * drivers?: list<"doctrine/orm"|Param>, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * }, + * orm_cascade_merge_associations?: array, + * }>, + * } + * @psalm-type CoreShopSeoConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * } + * @psalm-type CoreShopMoneyConfig = array{ + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * }, + * } + * @psalm-type CoreShopWorkflowConfig = array{ + * state_machine?: array, + * transitions: array, + * to?: list, + * }>, + * place_colors?: array, + * transition_colors?: array, + * callbacks?: array{ + * guard?: array, + * }>, + * before?: array, + * }>, + * after?: array, + * }>, + * }, + * }>, + * } + * @psalm-type CoreShopMessengerConfig = array{ + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["messenger"] + * }, + * doctrine?: array{ + * table_name?: scalar|null|Param, // Default: null + * connection?: scalar|null|Param, // Default: null + * }, + * } + * @psalm-type CoreShopRuleConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * resources?: array{ + * rule_condition?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Rule\\Model\\Condition" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Rule\\Model\\ConditionInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * }, + * }, + * rule_action?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Rule\\Model\\Action" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Rule\\Model\\ActionInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * }, + * } + * @psalm-type CoreShopConfigurationConfig = array{ + * resources?: array{ + * configuration?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Configuration\\Model\\Configuration" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Configuration\\Model\\ConfigurationInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ConfigurationBundle\\Controller\\ConfigurationController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ConfigurationBundle\\Doctrine\\ORM\\ConfigurationRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ConfigurationBundle\\Form\\Type\\ConfigurationType" + * }, + * }, + * }, + * } + * @psalm-type CoreShopOrderConfig = array{ + * allow_order_edit?: bool|Param, // Default: false + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * resources?: array{ + * cart_price_rule?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "cart_price_rule" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\CartPriceRule" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\CartPriceRuleInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\CartPriceRuleController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Doctrine\\ORM\\CartPriceRuleRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Form\\Type\\CartPriceRuleType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\CartPriceRuleTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\CartPriceRuleTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Form\\Type\\CartPriceRuleTranslationType" + * }, + * }, + * }, + * cart_price_rule_voucher_code?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\CartPriceRuleVoucherCode" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\CartPriceRuleVoucherCodeInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Doctrine\\ORM\\CartPriceRuleVoucherRepository" + * }, + * }, + * cart_price_rule_voucher_code_customer?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\CartPriceRuleVoucherCodeCustomer" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\CartPriceRuleVoucherCodeCustomerInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Factory\\CartPriceRuleVoucherCodeCustomerFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Doctrine\\ORM\\CartPriceRuleVoucherCodeCustomerRepository" + * }, + * }, + * }, + * pimcore?: array{ + * order?: array{ + * options?: mixed, + * path?: array{ + * order?: scalar|null|Param, // Default: "orders" + * quote?: scalar|null|Param, // Default: "quotes" + * cart?: scalar|null|Param, // Default: "carts" + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopOrder" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Pimcore\\Repository\\OrderRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/classes/CoreShopOrder.json" + * type?: scalar|null|Param, // Default: "object" + * pimcore_controller?: array{ + * default?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\OrderController" + * creation?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\OrderCreationController" + * edit?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\OrderEditController" + * payment?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\OrderPaymentController" + * comment?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\OrderCommentController" + * customer_creation?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\CustomerCreationController" + * address_creation?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\AddressCreationController" + * }, + * }, + * }, + * order_item?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "items" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopOrderItem" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderItemInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Pimcore\\Repository\\OrderItemRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/classes/CoreShopOrderItem.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * order_invoice?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "invoices" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopOrderInvoice" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderInvoiceInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Pimcore\\Repository\\OrderInvoiceRepository" + * pimcore_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\OrderInvoiceController" + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/classes/CoreShopOrderInvoice.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * order_invoice_item?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "items" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopOrderInvoiceItem" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderInvoiceItemInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/classes/CoreShopOrderInvoiceItem.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * order_shipment?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "shipments" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopOrderShipment" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderShipmentInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Pimcore\\Repository\\OrderShipmentRepository" + * pimcore_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\OrderBundle\\Controller\\OrderShipmentController" + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/classes/CoreShopOrderShipment.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * order_shipment_item?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "items" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopOrderShipmentItem" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderShipmentItemInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/classes/CoreShopOrderShipmentItem.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * cart_price_rule_item?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\Fieldcollection\\Data\\CoreShopProposalCartPriceRuleItem" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\ProposalCartPriceRuleItemInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/fieldcollections/CoreShopProposalCartPriceRuleItem.json" + * type?: scalar|null|Param, // Default: "fieldcollection" + * }, + * }, + * price_rule_item?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\Fieldcollection\\Data\\CoreShopPriceRuleItem" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\PriceRuleItemInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/fieldcollections/CoreShopPriceRuleItem.json" + * type?: scalar|null|Param, // Default: "fieldcollection" + * }, + * }, + * adjustment?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\Fieldcollection\\Data\\CoreShopAdjustment" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\AdjustmentInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/fieldcollections/CoreShopAdjustment.json" + * type?: scalar|null|Param, // Default: "fieldcollection" + * }, + * }, + * order_item_attribute?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\Fieldcollection\\Data\\CoreShopOrderItemAttribute" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderItemAttributeInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopOrderBundle/Resources/install/pimcore/fieldcollections/CoreShopOrderItemAttribute.json" + * type?: scalar|null|Param, // Default: "fieldcollection" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["cart_price_rule","order_list","order_detail","order_create","quote_list","quote_detail","quote_create","cart_list","cart_detail","cart_create"] + * install?: array{ + * grid_config?: list, + * }, + * }, + * stack?: array{ + * purchasable?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\PurchasableInterface" + * order?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderInterface" + * order_item?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderItemInterface" + * order_invoice?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderInvoiceInterface" + * order_invoice_item?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderInvoiceItemInterface" + * order_shipment?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderShipmentInterface" + * order_shipment_item?: scalar|null|Param, // Default: "CoreShop\\Component\\Order\\Model\\OrderShipmentItemInterface" + * }, + * } + * @psalm-type CoreShopCustomerConfig = array{ + * login_identifier?: "email"|"username"|Param, // Default: "email" + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * stack?: array{ + * customer?: scalar|null|Param, // Default: "CoreShop\\Component\\Customer\\Model\\CustomerInterface" + * customer_group?: scalar|null|Param, // Default: "CoreShop\\Component\\Customer\\Model\\CustomerGroupInterface" + * company?: scalar|null|Param, // Default: "CoreShop\\Component\\Customer\\Model\\CompanyInterface" + * }, + * pimcore?: array{ + * company?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "companies" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopCompany" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Customer\\Model\\CompanyInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CustomerBundle\\Pimcore\\Repository\\CompanyRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopCustomerBundle/Resources/install/pimcore/classes/CoreShopCompany.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * customer?: array{ + * options?: mixed, + * path?: array{ + * customer?: scalar|null|Param, // Default: "customers" + * guest?: scalar|null|Param, // Default: "guests" + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopCustomer" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Customer\\Model\\CustomerInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CustomerBundle\\Pimcore\\Repository\\CustomerRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopCustomerBundle/Resources/install/pimcore/classes/CoreShopCustomer.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * customer_group?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "customer_groups" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopCustomerGroup" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Customer\\Model\\CustomerGroupInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopCustomerBundle/Resources/install/pimcore/classes/CoreShopCustomerGroup.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["customer_list","customer_group_list"] + * install?: array{ + * grid_config?: list, + * }, + * }, + * } + * @psalm-type CoreShopUserConfig = array{ + * driver?: scalar|null|Param, // Default: "doctrine/orm" + * stack?: array{ + * user?: scalar|null|Param, // Default: "CoreShop\\Component\\User\\Model\\UserInterface" + * }, + * pimcore?: array{ + * user?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "user" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopUser" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\User\\Model\\UserInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\UserBundle\\Pimcore\\Repository\\UserRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopUserBundle/Resources/install/pimcore/classes/CoreShopUser.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * }, + * } + * @psalm-type CoreShopInventoryConfig = array{ + * checker?: scalar|null|Param, // Default: "CoreShop\\Component\\Inventory\\Checker\\AvailabilityChecker" + * } + * @psalm-type CoreShopVariantConfig = array{ + * stack?: array{ + * attribute_group?: scalar|null|Param, // Default: "CoreShop\\Component\\Variant\\Model\\AttributeGroupInterface" + * attribute?: scalar|null|Param, // Default: "CoreShop\\Component\\Variant\\Model\\AttributeInterface" + * variant_aware?: scalar|null|Param, // Default: "CoreShop\\Component\\Variant\\Model\\ProductVariantAwareInterface" + * }, + * pimcore?: array{ + * attribute_group?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopAttributeGroup" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Variant\\Model\\AttributeGroupInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopVariantBundle/Resources/install/pimcore/classes/CoreShopAttributeGroup.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * attribute_value?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopAttributeValue" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Variant\\Model\\AttributeValueInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopVariantBundle/Resources/install/pimcore/classes/CoreShopAttributeValue.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * attribute_color?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopAttributeColor" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Variant\\Model\\AttributeColorInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopVariantBundle/Resources/install/pimcore/classes/CoreShopAttributeColor.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * }, + * redirect_to_main_variant?: scalar|null|Param, // Default: true + * } + * @psalm-type CoreShopProductConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * resources?: array{ + * product_price_rule?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "product_price_rule" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductPriceRule" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductPriceRuleInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Controller\\ProductPriceRuleController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\TranslatableFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Doctrine\\ORM\\ProductPriceRuleRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Form\\Type\\ProductPriceRuleType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductPriceRuleTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductPriceRuleTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Form\\Type\\ProductPriceRuleTranslationType" + * }, + * }, + * }, + * product_specific_price_rule?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductSpecificPriceRule" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductSpecificPriceRuleInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\TranslatableFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Doctrine\\ORM\\ProductSpecificPriceRuleRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Form\\Type\\ProductSpecificPriceRuleType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductSpecificPriceRuleTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductSpecificPriceRuleTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Form\\Type\\ProductSpecificPriceRuleTranslationType" + * }, + * }, + * }, + * product_unit?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "product_unit" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnit" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\TranslatableFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Doctrine\\ORM\\ProductUnitRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Form\\Type\\Unit\\ProductUnitType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Form\\Type\\Unit\\ProductUnitTranslationType" + * }, + * }, + * }, + * product_unit_definitions?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitDefinitions" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitDefinitionsInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Controller\\ProductUnitDefinitionsController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Doctrine\\ORM\\ProductUnitDefinitionsRepository" + * }, + * }, + * product_unit_definition?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitDefinition" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitDefinitionInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * }, + * }, + * product_unit_definition_price?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitDefinitionPrice" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductUnitDefinitionPriceInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * }, + * }, + * }, + * pimcore?: array{ + * product?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "products" + * slug?: bool|Param, // Default: true + * route?: array{ + * name?: scalar|null|Param, // Default: "coreshop_product_detail" + * id_param?: scalar|null|Param, // Default: "product" + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopProduct" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Pimcore\\Repository\\ProductRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopProductBundle/Resources/install/pimcore/classes/CoreShopProduct.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * category?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "categories" + * slug?: bool|Param, // Default: true + * route?: array{ + * name?: scalar|null|Param, // Default: "coreshop_category_list" + * id_param?: scalar|null|Param, // Default: "category" + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopCategory" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\CategoryInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductBundle\\Pimcore\\Repository\\CategoryRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopProductBundle/Resources/install/pimcore/classes/CoreShopCategory.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * manufacturer?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "manufacturers" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopManufacturer" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ManufacturerInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopProductBundle/Resources/install/pimcore/classes/CoreShopManufacturer.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["product_price_rule","product_unit"] + * }, + * stack?: array{ + * product?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ProductInterface" + * category?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\CategoryInterface" + * manufacturer?: scalar|null|Param, // Default: "CoreShop\\Component\\Product\\Model\\ManufacturerInterface" + * }, + * } + * @psalm-type CoreShopThemeConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * default_resolvers?: array{ + * pimcore_site?: bool|Param, // Default: false + * pimcore_document_property?: bool|Param, // Default: false + * }, + * } + * @psalm-type CoreShopAddressConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * stack?: array{ + * address?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\AddressInterface" + * }, + * resources?: array{ + * country?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "country" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\Country" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\CountryInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Controller\\CountryController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\TranslatableFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Doctrine\\ORM\\CountryRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Form\\Type\\CountryType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\CountryTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\CountryTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Form\\Type\\CountryTranslationType" + * }, + * }, + * }, + * zone?: array{ + * permission?: scalar|null|Param, // Default: "zone" + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\Zone" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\ZoneInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Form\\Type\\ZoneType" + * }, + * }, + * state?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "state" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\State" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\StateInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\TranslatableFactory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Form\\Type\\StateType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\StateTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\StateTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Form\\Type\\StateTranslationType" + * }, + * }, + * }, + * address_identifier?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "address_identifier" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\AddressIdentifier" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\AddressIdentifierInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Doctrine\\ORM\\AddressIdentifierRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\AddressBundle\\Form\\Type\\AddressIdentifierType" + * }, + * }, + * }, + * pimcore?: array{ + * address?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "addresses" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopAddress" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Address\\Model\\AddressInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopAddressBundle/Resources/install/pimcore/classes/CoreShopAddress.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["country","state","zone"] + * }, + * } + * @psalm-type CoreShopCurrencyConfig = array{ + * money_decimal_factor?: int|Param, // Default: 100 + * money_decimal_precision?: int|Param, // Default: 2 + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * resources?: array{ + * currency?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * permission?: scalar|null|Param, // Default: "currency" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Currency\\Model\\Currency" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Currency\\Model\\CurrencyInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CurrencyBundle\\Controller\\CurrencyController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CurrencyBundle\\Doctrine\\ORM\\CurrencyRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CurrencyBundle\\Form\\Type\\CurrencyType" + * }, + * }, + * exchange_rate?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "exchange_rate" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Currency\\Model\\ExchangeRate" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Currency\\Model\\ExchangeRateInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CurrencyBundle\\Controller\\ExchangeRateController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CurrencyBundle\\Doctrine\\ORM\\ExchangeRateRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CurrencyBundle\\Form\\Type\\ExchangeRateType" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["currency","exchange_rate"] + * }, + * } + * @psalm-type CoreShopTaxationConfig = array{ + * resources?: array{ + * tax_rate?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "tax_rate" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxRate" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxRateInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\TranslatableFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\TaxationBundle\\Doctrine\\ORM\\TaxRateRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\TaxationBundle\\Form\\Type\\TaxRateType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxRateTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxRateTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\TaxationBundle\\Form\\Type\\TaxRateTranslationType" + * }, + * }, + * }, + * tax_rule_group?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "tax_rule_group" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxRuleGroup" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxRuleGroupInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\TaxationBundle\\Controller\\TaxRuleGroupController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\TaxationBundle\\Form\\Type\\TaxRuleGroupType" + * }, + * }, + * tax_rule?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxRule" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxRuleInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\TaxationBundle\\Doctrine\\ORM\\TaxRuleRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\TaxationBundle\\Form\\Type\\TaxRuleType" + * }, + * }, + * }, + * pimcore?: array{ + * tax_item?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\Fieldcollection\\Data\\CoreShopTaxItem" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Taxation\\Model\\TaxItemInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, + * install_file?: scalar|null|Param, // Default: "@CoreShopTaxationBundle/Resources/install/pimcore/fieldcollections/CoreShopTaxItem.json" + * type?: scalar|null|Param, // Default: "fieldcollection" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["tax_rate","tax_rule_group"] + * }, + * } + * @psalm-type CoreShopStoreConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * resources?: array{ + * store?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "store" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Store\\Model\\Store" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Store\\Model\\StoreInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\StoreBundle\\Controller\\StoreController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\StoreBundle\\Doctrine\\ORM\\StoreRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\StoreBundle\\Form\\Type\\StoreType" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["store"] + * }, + * } + * @psalm-type CoreShopIndexConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * mysql_auto_generate_migrations?: scalar|null|Param, // Default: false + * resources?: array{ + * index?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "index" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Index\\Model\\Index" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Index\\Model\\IndexInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\IndexBundle\\Controller\\IndexController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\IndexBundle\\Form\\Type\\IndexType" + * }, + * }, + * index_column?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Index\\Model\\IndexColumn" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Index\\Model\\IndexColumnInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\IndexBundle\\Form\\Type\\IndexColumnType" + * }, + * }, + * filter?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "filter" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Index\\Model\\Filter" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Index\\Model\\FilterInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\IndexBundle\\Controller\\FilterController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\IndexBundle\\Form\\Type\\FilterType" + * }, + * }, + * filter_condition?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Index\\Model\\FilterCondition" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Index\\Model\\FilterConditionInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\IndexBundle\\Form\\Type\\FilterConditionType" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["index","filter"] + * }, + * mapping_types?: array, + * worker_mapping_types?: array>, + * } + * @psalm-type CoreShopShippingConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * default_resolver?: scalar|null|Param, + * resources?: array{ + * carrier?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "carrier" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Shipping\\Model\\Carrier" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Shipping\\Model\\CarrierInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ShippingBundle\\Controller\\CarrierController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ShippingBundle\\Form\\Type\\CarrierType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Shipping\\Model\\CarrierTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Shipping\\Model\\CarrierTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ShippingBundle\\Form\\Type\\CarrierTranslationType" + * }, + * }, + * }, + * shipping_rule?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "shipping_rule" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Shipping\\Model\\ShippingRule" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Shipping\\Model\\ShippingRuleInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ShippingBundle\\Controller\\ShippingRuleController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\RuleBundle\\Doctrine\\ORM\\RuleRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ShippingBundle\\Form\\Type\\ShippingRuleType" + * }, + * }, + * shipping_rule_group?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Shipping\\Model\\ShippingRuleGroup" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Shipping\\Model\\ShippingRuleGroupInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ShippingBundle\\Form\\Type\\ShippingRuleGroupType" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["carrier","shipping_rule"] + * }, + * } + * @psalm-type CoreShopPaymentConfig = array{ + * driver?: scalar|null|Param, // Default: "doctrine/orm" + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * resources?: array{ + * payment_provider?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "payment_provider" + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProvider" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\TranslatableFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PaymentBundle\\Doctrine\\ORM\\PaymentProviderRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PaymentBundle\\Form\\Type\\PaymentProviderType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PaymentBundle\\Form\\Type\\PaymentProviderTranslationType" + * }, + * }, + * }, + * payment?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\Payment" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PaymentBundle\\Doctrine\\ORM\\PaymentRepository" + * }, + * }, + * payment_provider_rule?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "payment_provider_rule" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderRule" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderRuleInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PaymentBundle\\Controller\\PaymentProviderRuleController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\RuleBundle\\Doctrine\\ORM\\RuleRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PaymentBundle\\Form\\Type\\PaymentProviderRuleType" + * }, + * translation?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderRuleTranslation" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderRuleTranslationInterface" + * repository?: scalar|null|Param, + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PaymentBundle\\Form\\Type\\PaymentProviderRuleTranslationType" + * }, + * }, + * }, + * payment_provider_rule_group?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderRuleGroup" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Payment\\Model\\PaymentProviderRuleGroupInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PaymentBundle\\Form\\Type\\PaymentProviderRuleGroupType" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["payment_provider","payment_provider_rule"] + * }, + * } + * @psalm-type CoreShopSequenceConfig = array{ + * resources?: array{ + * sequence?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Sequence\\Model\\Sequence" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Sequence\\Model\\SequenceInterface" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Sequence\\Factory\\SequenceFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\SequenceBundle\\Doctrine\\ORM\\SequenceRepository" + * }, + * }, + * }, + * } + * @psalm-type CoreShopPayumPaymentConfig = array{ + * driver?: scalar|null|Param, // Default: "doctrine/orm" + * resources?: array{ + * gateway_config?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\PayumPayment\\Model\\GatewayConfig" + * controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * }, + * }, + * payment_security_token?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\PayumPayment\\Model\\PaymentSecurityToken" + * controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ResourceBundle\\Controller\\ResourceController" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * }, + * }, + * }, + * } + * @psalm-type CoreShopNotificationConfig = array{ + * resources?: array{ + * notification_rule?: array{ + * options?: mixed, + * permission?: scalar|null|Param, // Default: "notification" + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Notification\\Model\\NotificationRule" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Notification\\Model\\NotificationRuleInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\NotificationBundle\\Doctrine\\ORM\\NotificationRuleRepository" + * admin_controller?: scalar|null|Param, // Default: "CoreShop\\Bundle\\NotificationBundle\\Controller\\NotificationRuleController" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\NotificationBundle\\Form\\Type\\NotificationRuleType" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["notification"] + * }, + * } + * @psalm-type CoreShopTrackingConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * trackers?: array, + * } + * @psalm-type CoreShopFrontendConfig = array{ + * view_suffix?: scalar|null|Param, // Default: "twig" + * view_bundle?: scalar|null|Param, // Deprecated: Use view_prefix instead // Default: "@CoreShopFrontend" + * view_prefix?: scalar|null|Param, // Default: "@CoreShopFrontend" + * category?: array{ + * valid_sort_options?: list, + * default_sort_name?: scalar|null|Param, // Default: "name" + * default_sort_direction?: scalar|null|Param, // Default: "asc" + * }, + * pimcore_admin?: array{ + * install?: array{ + * routes?: list, + * documents?: list, + * image_thumbnails?: list, + * }, + * }, + * controllers?: array{ + * index?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\IndexController" + * register?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\RegisterController" + * customer?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\CustomerController" + * currency?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\CurrencyController" + * search?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\SearchController" + * cart?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\CartController" + * checkout?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\CheckoutController" + * order?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\OrderController" + * category?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\CategoryController" + * product?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\ProductController" + * quote?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\QuoteController" + * security?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\SecurityController" + * payment?: scalar|null|Param, // Default: "CoreShop\\Bundle\\PayumBundle\\Controller\\PaymentController" + * mail?: scalar|null|Param, // Default: "CoreShop\\Bundle\\FrontendBundle\\Controller\\MailController" + * }, + * } + * @psalm-type CoreShopPayumConfig = array{ + * template?: array{ + * layout?: scalar|null|Param, // Default: "@CoreShopPayum/:layout.html.twig" + * obtain_credit_card?: scalar|null|Param, // Default: "@CoreShopPayum/Action/obtainCreditCard.html.twig" + * }, + * } + * @psalm-type CoreShopProductQuantityPriceRulesConfig = array{ + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * action_constraints?: list, + * }>, + * resources?: array{ + * product_quantity_price_rule_range?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\ProductQuantityPriceRules\\Model\\QuantityRange" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\ProductQuantityPriceRules\\Model\\QuantityRangeInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, + * }, + * }, + * product_quantity_price_rule?: array{ + * options?: mixed, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\ProductQuantityPriceRules\\Model\\ProductQuantityPriceRule" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\ProductQuantityPriceRules\\Model\\ProductQuantityPriceRuleInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductQuantityPriceRulesBundle\\Doctrine\\ORM\\ProductQuantityPriceRuleRepository" + * form?: scalar|null|Param, // Default: "CoreShop\\Bundle\\ProductQuantityPriceRulesBundle\\Form\\Type\\ProductQuantityPriceRuleType" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array, + * editmode_js?: array, + * editmode_css?: array, + * permissions?: scalar|null|Param, // Default: ["notification"] + * }, + * } + * @psalm-type CoreShopWishlistConfig = array{ + * pimcore?: array{ + * wishlist?: array{ + * options?: mixed, + * path?: array{ + * wishlist?: scalar|null|Param, // Default: "wishlists" + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopWishlist" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Wishlist\\Model\\WishlistInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\WishlistBundle\\Pimcore\\Repository\\WishlistRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopWishlistBundle/Resources/install/pimcore/classes/CoreShopWishlist.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * wishlist_item?: array{ + * options?: mixed, + * path?: scalar|null|Param, // Default: "items" + * classes?: array{ + * model?: scalar|null|Param, // Default: "Pimcore\\Model\\DataObject\\CoreShopWishlistItem" + * pimcore_class_name?: scalar|null|Param, + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Wishlist\\Model\\WishlistItemInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\PimcoreFactory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\WishlistBundle\\Pimcore\\Repository\\WishlistItemRepository" + * install_file?: scalar|null|Param, // Default: "@CoreShopWishlistBundle/Resources/install/pimcore/classes/CoreShopWishlistItem.json" + * type?: scalar|null|Param, // Default: "object" + * }, + * }, + * }, + * stack?: array{ + * wishlist?: scalar|null|Param, // Default: "CoreShop\\Component\\Wishlist\\Model\\WishlistInterface" + * wishlist_item?: scalar|null|Param, // Default: "CoreShop\\Component\\Wishlist\\Model\\WishlistItemInterface" + * wishlist_product?: scalar|null|Param, // Default: "CoreShop\\Component\\Wishlist\\Model\\WishlistProductInterface" + * }, + * } + * @psalm-type CoreShopClassDefinitionPatchConfig = array{ + * patches?: array, + * parent_class?: scalar|null|Param, + * group?: scalar|null|Param, + * description?: scalar|null|Param, + * listing_parent_class?: scalar|null|Param, + * use_traits?: list, + * listing_use_traits?: list, + * fields?: array, + * }>, + * } + * @psalm-type PayumConfig = array{ + * security: array{ + * token_storage: array, + * propel2?: array, + * }>, + * }, + * dynamic_gateways?: array{ + * sonata_admin?: bool|Param, // Default: false + * config_storage: array, + * propel2?: array, + * }>, + * encryption?: array{ + * defuse_secret_key?: scalar|null|Param, + * }, + * }, + * gateways?: array, + * storages?: array, + * factories?: array, + * }, + * filesystem?: array{ + * storage_dir: scalar|null|Param, + * id_property?: scalar|null|Param, // Default: null + * }, + * doctrine?: string|array{ + * driver: scalar|null|Param, + * }, + * custom?: string|array{ + * service: scalar|null|Param, + * }, + * propel1?: array, + * propel2?: array, + * }>, + * } + * @psalm-type StofDoctrineExtensionsConfig = array{ + * orm?: array, + * mongodb?: array, + * class?: array{ + * translatable?: scalar|null|Param, // Default: "Gedmo\\Translatable\\TranslatableListener" + * timestampable?: scalar|null|Param, // Default: "Gedmo\\Timestampable\\TimestampableListener" + * blameable?: scalar|null|Param, // Default: "Gedmo\\Blameable\\BlameableListener" + * sluggable?: scalar|null|Param, // Default: "Gedmo\\Sluggable\\SluggableListener" + * tree?: scalar|null|Param, // Default: "Gedmo\\Tree\\TreeListener" + * loggable?: scalar|null|Param, // Default: "Gedmo\\Loggable\\LoggableListener" + * sortable?: scalar|null|Param, // Default: "Gedmo\\Sortable\\SortableListener" + * softdeleteable?: scalar|null|Param, // Default: "Gedmo\\SoftDeleteable\\SoftDeleteableListener" + * uploadable?: scalar|null|Param, // Default: "Gedmo\\Uploadable\\UploadableListener" + * reference_integrity?: scalar|null|Param, // Default: "Gedmo\\ReferenceIntegrity\\ReferenceIntegrityListener" + * }, + * softdeleteable?: array{ + * handle_post_flush_event?: bool|Param, // Default: false + * }, + * uploadable?: array{ + * default_file_path?: scalar|null|Param, // Default: null + * mime_type_guesser_class?: scalar|null|Param, // Default: "Stof\\DoctrineExtensionsBundle\\Uploadable\\MimeTypeGuesserAdapter" + * default_file_info_class?: scalar|null|Param, // Default: "Stof\\DoctrineExtensionsBundle\\Uploadable\\UploadedFileInfo" + * validate_writable_directory?: bool|Param, // Default: true + * }, + * default_locale?: scalar|null|Param, // Default: "en" + * translation_fallback?: bool|Param, // Default: false + * persist_default_translation?: bool|Param, // Default: false + * skip_translation_on_load?: bool|Param, // Default: false + * metadata_cache_pool?: scalar|null|Param, // Default: null + * } + * @psalm-type SyliusThemeConfig = array{ + * sources?: array{ + * filesystem?: bool|array{ + * enabled?: bool|Param, // Default: false + * filename?: scalar|null|Param, // Default: "composer.json" + * scan_depth?: scalar|null|Param, // Restrict depth to scan for configuration file inside theme folder // Default: 1 + * directories?: list, + * }, + * test?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * }, + * assets?: bool|array{ + * enabled?: bool|Param, // Default: true + * }, + * templating?: bool|array{ + * enabled?: bool|Param, // Default: true + * }, + * translations?: bool|array{ + * enabled?: bool|Param, // Default: true + * }, + * context?: scalar|null|Param, // Default: "sylius.theme.context.settable" + * legacy_mode?: bool|Param, // Deprecated: "legacy_mode" at path "sylius_theme.legacy_mode" is deprecated since Sylius/ThemeBundle 2.0 and will be removed in 3.0. // Default: false + * } + * @psalm-type PimcoreGoogleMarketingConfig = array{ + * client_id?: scalar|null|Param, // This is required for the Google API integrations. Only use a `Service AccountΒ΄ from the Google Cloud Console. // Default: null + * email?: scalar|null|Param, // Email address of the Google service account // Default: null + * simple_api_key?: scalar|null|Param, // Server API key // Default: null + * browser_api_key?: scalar|null|Param, // Browser API key // Default: null + * } + * @psalm-type FrameworkConfig = array{ + * secret?: scalar|null|Param, + * http_method_override?: bool|Param, // Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. // Default: false + * allowed_http_method_override?: list|null, + * trust_x_sendfile_type_header?: scalar|null|Param, // Set true to enable support for xsendfile in binary file responses. // Default: "%env(bool:default::SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER)%" + * ide?: scalar|null|Param, // Default: "%env(default::SYMFONY_IDE)%" + * test?: bool|Param, + * default_locale?: scalar|null|Param, // Default: "en" + * set_locale_from_accept_language?: bool|Param, // Whether to use the Accept-Language HTTP header to set the Request locale (only when the "_locale" request attribute is not passed). // Default: false + * set_content_language_from_locale?: bool|Param, // Whether to set the Content-Language HTTP header on the Response using the Request locale. // Default: false + * enabled_locales?: list, + * trusted_hosts?: list, + * trusted_proxies?: mixed, // Default: ["%env(default::SYMFONY_TRUSTED_PROXIES)%"] + * trusted_headers?: list, + * error_controller?: scalar|null|Param, // Default: "error_controller" + * handle_all_throwables?: bool|Param, // HttpKernel will handle all kinds of \Throwable. // Default: true + * csrf_protection?: bool|array{ + * enabled?: scalar|null|Param, // Default: null + * stateless_token_ids?: list, + * check_header?: scalar|null|Param, // Whether to check the CSRF token in a header in addition to a cookie when using stateless protection. // Default: false + * cookie_name?: scalar|null|Param, // The name of the cookie to use when using stateless protection. // Default: "csrf-token" + * }, + * form?: bool|array{ // Form configuration + * enabled?: bool|Param, // Default: true + * csrf_protection?: array{ + * enabled?: scalar|null|Param, // Default: null + * token_id?: scalar|null|Param, // Default: null + * field_name?: scalar|null|Param, // Default: "_token" + * field_attr?: array, + * }, + * }, + * http_cache?: bool|array{ // HTTP cache configuration + * enabled?: bool|Param, // Default: false + * debug?: bool|Param, // Default: "%kernel.debug%" + * trace_level?: "none"|"short"|"full"|Param, + * trace_header?: scalar|null|Param, + * default_ttl?: int|Param, + * private_headers?: list, + * skip_response_headers?: list, + * allow_reload?: bool|Param, + * allow_revalidate?: bool|Param, + * stale_while_revalidate?: int|Param, + * stale_if_error?: int|Param, + * terminate_on_cache_hit?: bool|Param, + * }, + * esi?: bool|array{ // ESI configuration + * enabled?: bool|Param, // Default: false + * }, + * ssi?: bool|array{ // SSI configuration + * enabled?: bool|Param, // Default: false + * }, + * fragments?: bool|array{ // Fragments configuration + * enabled?: bool|Param, // Default: false + * hinclude_default_template?: scalar|null|Param, // Default: null + * path?: scalar|null|Param, // Default: "/_fragment" + * }, + * profiler?: bool|array{ // Profiler configuration + * enabled?: bool|Param, // Default: false + * collect?: bool|Param, // Default: true + * collect_parameter?: scalar|null|Param, // The name of the parameter to use to enable or disable collection on a per request basis. // Default: null + * only_exceptions?: bool|Param, // Default: false + * only_main_requests?: bool|Param, // Default: false + * dsn?: scalar|null|Param, // Default: "file:%kernel.cache_dir%/profiler" + * collect_serializer_data?: bool|Param, // Enables the serializer data collector and profiler panel. // Default: false + * }, + * workflows?: bool|array{ + * enabled?: bool|Param, // Default: false + * workflows?: array, + * definition_validators?: list, + * support_strategy?: scalar|null|Param, + * initial_marking?: list, + * events_to_dispatch?: list|null, + * places?: list, + * }>, + * transitions: list, + * to?: list, + * weight?: int|Param, // Default: 1 + * metadata?: list, + * }>, + * metadata?: list, + * }>, + * }, + * router?: bool|array{ // Router configuration + * enabled?: bool|Param, // Default: false + * resource: scalar|null|Param, + * type?: scalar|null|Param, + * cache_dir?: scalar|null|Param, // Deprecated: Setting the "framework.router.cache_dir.cache_dir" configuration option is deprecated. It will be removed in version 8.0. // Default: "%kernel.build_dir%" + * default_uri?: scalar|null|Param, // The default URI used to generate URLs in a non-HTTP context. // Default: null + * http_port?: scalar|null|Param, // Default: 80 + * https_port?: scalar|null|Param, // Default: 443 + * strict_requirements?: scalar|null|Param, // set to true to throw an exception when a parameter does not match the requirements set to false to disable exceptions when a parameter does not match the requirements (and return null instead) set to null to disable parameter checks against requirements 'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production // Default: true + * utf8?: bool|Param, // Default: true + * }, + * session?: bool|array{ // Session configuration + * enabled?: bool|Param, // Default: false + * storage_factory_id?: scalar|null|Param, // Default: "session.storage.factory.native" + * handler_id?: scalar|null|Param, // Defaults to using the native session handler, or to the native *file* session handler if "save_path" is not null. + * name?: scalar|null|Param, + * cookie_lifetime?: scalar|null|Param, + * cookie_path?: scalar|null|Param, + * cookie_domain?: scalar|null|Param, + * cookie_secure?: true|false|"auto"|Param, // Default: "auto" + * cookie_httponly?: bool|Param, // Default: true + * cookie_samesite?: null|"lax"|"strict"|"none"|Param, // Default: "lax" + * use_cookies?: bool|Param, + * gc_divisor?: scalar|null|Param, + * gc_probability?: scalar|null|Param, + * gc_maxlifetime?: scalar|null|Param, + * save_path?: scalar|null|Param, // Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null. + * metadata_update_threshold?: int|Param, // Seconds to wait between 2 session metadata updates. // Default: 0 + * sid_length?: int|Param, // Deprecated: Setting the "framework.session.sid_length.sid_length" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option. + * sid_bits_per_character?: int|Param, // Deprecated: Setting the "framework.session.sid_bits_per_character.sid_bits_per_character" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option. + * }, + * request?: bool|array{ // Request configuration + * enabled?: bool|Param, // Default: false + * formats?: array>, + * }, + * assets?: bool|array{ // Assets configuration + * enabled?: bool|Param, // Default: true + * strict_mode?: bool|Param, // Throw an exception if an entry is missing from the manifest.json. // Default: false + * version_strategy?: scalar|null|Param, // Default: null + * version?: scalar|null|Param, // Default: null + * version_format?: scalar|null|Param, // Default: "%%s?%%s" + * json_manifest_path?: scalar|null|Param, // Default: null + * base_path?: scalar|null|Param, // Default: "" + * base_urls?: list, + * packages?: array, + * }>, + * }, + * asset_mapper?: bool|array{ // Asset Mapper configuration + * enabled?: bool|Param, // Default: false + * paths?: array, + * excluded_patterns?: list, + * exclude_dotfiles?: bool|Param, // If true, any files starting with "." will be excluded from the asset mapper. // Default: true + * server?: bool|Param, // If true, a "dev server" will return the assets from the public directory (true in "debug" mode only by default). // Default: true + * public_prefix?: scalar|null|Param, // The public path where the assets will be written to (and served from when "server" is true). // Default: "/assets/" + * missing_import_mode?: "strict"|"warn"|"ignore"|Param, // Behavior if an asset cannot be found when imported from JavaScript or CSS files - e.g. "import './non-existent.js'". "strict" means an exception is thrown, "warn" means a warning is logged, "ignore" means the import is left as-is. // Default: "warn" + * extensions?: array, + * importmap_path?: scalar|null|Param, // The path of the importmap.php file. // Default: "%kernel.project_dir%/importmap.php" + * importmap_polyfill?: scalar|null|Param, // The importmap name that will be used to load the polyfill. Set to false to disable. // Default: "es-module-shims" + * importmap_script_attributes?: array, + * vendor_dir?: scalar|null|Param, // The directory to store JavaScript vendors. // Default: "%kernel.project_dir%/assets/vendor" + * precompress?: bool|array{ // Precompress assets with Brotli, Zstandard and gzip. + * enabled?: bool|Param, // Default: false + * formats?: list, + * extensions?: list, + * }, + * }, + * translator?: bool|array{ // Translator configuration + * enabled?: bool|Param, // Default: true + * fallbacks?: list, + * logging?: bool|Param, // Default: false + * formatter?: scalar|null|Param, // Default: "translator.formatter.default" + * cache_dir?: scalar|null|Param, // Default: "%kernel.cache_dir%/translations" + * default_path?: scalar|null|Param, // The default path used to load translations. // Default: "%kernel.project_dir%/translations" + * paths?: list, + * pseudo_localization?: bool|array{ + * enabled?: bool|Param, // Default: false + * accents?: bool|Param, // Default: true + * expansion_factor?: float|Param, // Default: 1.0 + * brackets?: bool|Param, // Default: true + * parse_html?: bool|Param, // Default: false + * localizable_html_attributes?: list, + * }, + * providers?: array, + * locales?: list, + * }>, + * globals?: array, + * domain?: string|Param, + * }>, + * }, + * validation?: bool|array{ // Validation configuration + * enabled?: bool|Param, // Default: true + * cache?: scalar|null|Param, // Deprecated: Setting the "framework.validation.cache.cache" configuration option is deprecated. It will be removed in version 8.0. + * enable_attributes?: bool|Param, // Default: true + * static_method?: list, + * translation_domain?: scalar|null|Param, // Default: "validators" + * email_validation_mode?: "html5"|"html5-allow-no-tld"|"strict"|"loose"|Param, // Default: "html5" + * mapping?: array{ + * paths?: list, + * }, + * not_compromised_password?: bool|array{ + * enabled?: bool|Param, // When disabled, compromised passwords will be accepted as valid. // Default: true + * endpoint?: scalar|null|Param, // API endpoint for the NotCompromisedPassword Validator. // Default: null + * }, + * disable_translation?: bool|Param, // Default: false + * auto_mapping?: array, + * }>, + * }, + * annotations?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * serializer?: bool|array{ // Serializer configuration + * enabled?: bool|Param, // Default: true + * enable_attributes?: bool|Param, // Default: true + * name_converter?: scalar|null|Param, + * circular_reference_handler?: scalar|null|Param, + * max_depth_handler?: scalar|null|Param, + * mapping?: array{ + * paths?: list, + * }, + * default_context?: list, + * named_serializers?: array, + * include_built_in_normalizers?: bool|Param, // Whether to include the built-in normalizers // Default: true + * include_built_in_encoders?: bool|Param, // Whether to include the built-in encoders // Default: true + * }>, + * }, + * property_access?: bool|array{ // Property access configuration + * enabled?: bool|Param, // Default: true + * magic_call?: bool|Param, // Default: false + * magic_get?: bool|Param, // Default: true + * magic_set?: bool|Param, // Default: true + * throw_exception_on_invalid_index?: bool|Param, // Default: false + * throw_exception_on_invalid_property_path?: bool|Param, // Default: true + * }, + * type_info?: bool|array{ // Type info configuration + * enabled?: bool|Param, // Default: true + * aliases?: array, + * }, + * property_info?: bool|array{ // Property info configuration + * enabled?: bool|Param, // Default: true + * with_constructor_extractor?: bool|Param, // Registers the constructor extractor. + * }, + * cache?: array{ // Cache configuration + * prefix_seed?: scalar|null|Param, // Used to namespace cache keys when using several apps with the same shared backend. // Default: "_%kernel.project_dir%.%kernel.container_class%" + * app?: scalar|null|Param, // App related cache pools configuration. // Default: "cache.adapter.filesystem" + * system?: scalar|null|Param, // System related cache pools configuration. // Default: "cache.adapter.system" + * directory?: scalar|null|Param, // Default: "%kernel.share_dir%/pools/app" + * default_psr6_provider?: scalar|null|Param, + * default_redis_provider?: scalar|null|Param, // Default: "redis://localhost" + * default_valkey_provider?: scalar|null|Param, // Default: "valkey://localhost" + * default_memcached_provider?: scalar|null|Param, // Default: "memcached://localhost" + * default_doctrine_dbal_provider?: scalar|null|Param, // Default: "database_connection" + * default_pdo_provider?: scalar|null|Param, // Default: null + * pools?: array, + * tags?: scalar|null|Param, // Default: null + * public?: bool|Param, // Default: false + * default_lifetime?: scalar|null|Param, // Default lifetime of the pool. + * provider?: scalar|null|Param, // Overwrite the setting from the default provider for this adapter. + * early_expiration_message_bus?: scalar|null|Param, + * clearer?: scalar|null|Param, + * }>, + * }, + * php_errors?: array{ // PHP errors handling configuration + * log?: mixed, // Use the application logger instead of the PHP logger for logging PHP errors. // Default: true + * throw?: bool|Param, // Throw PHP errors as \ErrorException instances. // Default: true + * }, + * exceptions?: array, + * web_link?: bool|array{ // Web links configuration + * enabled?: bool|Param, // Default: true + * }, + * lock?: bool|string|array{ // Lock configuration + * enabled?: bool|Param, // Default: true + * resources?: array>, + * }, + * semaphore?: bool|string|array{ // Semaphore configuration + * enabled?: bool|Param, // Default: false + * resources?: array, + * }, + * messenger?: bool|array{ // Messenger configuration + * enabled?: bool|Param, // Default: true + * routing?: array, + * }>, + * serializer?: array{ + * default_serializer?: scalar|null|Param, // Service id to use as the default serializer for the transports. // Default: "messenger.transport.native_php_serializer" + * symfony_serializer?: array{ + * format?: scalar|null|Param, // Serialization format for the messenger.transport.symfony_serializer service (which is not the serializer used by default). // Default: "json" + * context?: array, + * }, + * }, + * transports?: array, + * failure_transport?: scalar|null|Param, // Transport name to send failed messages to (after all retries have failed). // Default: null + * retry_strategy?: string|array{ + * service?: scalar|null|Param, // Service id to override the retry strategy entirely. // Default: null + * max_retries?: int|Param, // Default: 3 + * delay?: int|Param, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 + * multiplier?: float|Param, // If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries)). // Default: 2 + * max_delay?: int|Param, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 + * jitter?: float|Param, // Randomness to apply to the delay (between 0 and 1). // Default: 0.1 + * }, + * rate_limiter?: scalar|null|Param, // Rate limiter name to use when processing messages. // Default: null + * }>, + * failure_transport?: scalar|null|Param, // Transport name to send failed messages to (after all retries have failed). // Default: null + * stop_worker_on_signals?: list, + * default_bus?: scalar|null|Param, // Default: null + * buses?: array, + * }>, + * }>, + * }, + * scheduler?: bool|array{ // Scheduler configuration + * enabled?: bool|Param, // Default: true + * }, + * disallow_search_engine_index?: bool|Param, // Enabled by default when debug is enabled. // Default: true + * http_client?: bool|array{ // HTTP Client configuration + * enabled?: bool|Param, // Default: true + * max_host_connections?: int|Param, // The maximum number of connections to a single host. + * default_options?: array{ + * headers?: array, + * vars?: array, + * max_redirects?: int|Param, // The maximum number of redirects to follow. + * http_version?: scalar|null|Param, // The default HTTP version, typically 1.1 or 2.0, leave to null for the best version. + * resolve?: array, + * proxy?: scalar|null|Param, // The URL of the proxy to pass requests through or null for automatic detection. + * no_proxy?: scalar|null|Param, // A comma separated list of hosts that do not require a proxy to be reached. + * timeout?: float|Param, // The idle timeout, defaults to the "default_socket_timeout" ini parameter. + * max_duration?: float|Param, // The maximum execution time for the request+response as a whole. + * bindto?: scalar|null|Param, // A network interface name, IP address, a host name or a UNIX socket to bind to. + * verify_peer?: bool|Param, // Indicates if the peer should be verified in a TLS context. + * verify_host?: bool|Param, // Indicates if the host should exist as a certificate common name. + * cafile?: scalar|null|Param, // A certificate authority file. + * capath?: scalar|null|Param, // A directory that contains multiple certificate authority files. + * local_cert?: scalar|null|Param, // A PEM formatted certificate file. + * local_pk?: scalar|null|Param, // A private key file. + * passphrase?: scalar|null|Param, // The passphrase used to encrypt the "local_pk" file. + * ciphers?: scalar|null|Param, // A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...) + * peer_fingerprint?: array{ // Associative array: hashing algorithm => hash(es). + * sha1?: mixed, + * pin-sha256?: mixed, + * md5?: mixed, + * }, + * crypto_method?: scalar|null|Param, // The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants. + * extra?: array, + * rate_limiter?: scalar|null|Param, // Rate limiter name to use for throttling requests. // Default: null + * caching?: bool|array{ // Caching configuration. + * enabled?: bool|Param, // Default: false + * cache_pool?: string|Param, // The taggable cache pool to use for storing the responses. // Default: "cache.http_client" + * shared?: bool|Param, // Indicates whether the cache is shared (public) or private. // Default: true + * max_ttl?: int|Param, // The maximum TTL (in seconds) allowed for cached responses. Null means no cap. // Default: null + * }, + * retry_failed?: bool|array{ + * enabled?: bool|Param, // Default: false + * retry_strategy?: scalar|null|Param, // service id to override the retry strategy. // Default: null + * http_codes?: array, + * }>, + * max_retries?: int|Param, // Default: 3 + * delay?: int|Param, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 + * multiplier?: float|Param, // If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries). // Default: 2 + * max_delay?: int|Param, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 + * jitter?: float|Param, // Randomness in percent (between 0 and 1) to apply to the delay. // Default: 0.1 + * }, + * }, + * mock_response_factory?: scalar|null|Param, // The id of the service that should generate mock responses. It should be either an invokable or an iterable. + * scoped_clients?: array, + * headers?: array, + * max_redirects?: int|Param, // The maximum number of redirects to follow. + * http_version?: scalar|null|Param, // The default HTTP version, typically 1.1 or 2.0, leave to null for the best version. + * resolve?: array, + * proxy?: scalar|null|Param, // The URL of the proxy to pass requests through or null for automatic detection. + * no_proxy?: scalar|null|Param, // A comma separated list of hosts that do not require a proxy to be reached. + * timeout?: float|Param, // The idle timeout, defaults to the "default_socket_timeout" ini parameter. + * max_duration?: float|Param, // The maximum execution time for the request+response as a whole. + * bindto?: scalar|null|Param, // A network interface name, IP address, a host name or a UNIX socket to bind to. + * verify_peer?: bool|Param, // Indicates if the peer should be verified in a TLS context. + * verify_host?: bool|Param, // Indicates if the host should exist as a certificate common name. + * cafile?: scalar|null|Param, // A certificate authority file. + * capath?: scalar|null|Param, // A directory that contains multiple certificate authority files. + * local_cert?: scalar|null|Param, // A PEM formatted certificate file. + * local_pk?: scalar|null|Param, // A private key file. + * passphrase?: scalar|null|Param, // The passphrase used to encrypt the "local_pk" file. + * ciphers?: scalar|null|Param, // A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...). + * peer_fingerprint?: array{ // Associative array: hashing algorithm => hash(es). + * sha1?: mixed, + * pin-sha256?: mixed, + * md5?: mixed, + * }, + * crypto_method?: scalar|null|Param, // The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants. + * extra?: array, + * rate_limiter?: scalar|null|Param, // Rate limiter name to use for throttling requests. // Default: null + * caching?: bool|array{ // Caching configuration. + * enabled?: bool|Param, // Default: false + * cache_pool?: string|Param, // The taggable cache pool to use for storing the responses. // Default: "cache.http_client" + * shared?: bool|Param, // Indicates whether the cache is shared (public) or private. // Default: true + * max_ttl?: int|Param, // The maximum TTL (in seconds) allowed for cached responses. Null means no cap. // Default: null + * }, + * retry_failed?: bool|array{ + * enabled?: bool|Param, // Default: false + * retry_strategy?: scalar|null|Param, // service id to override the retry strategy. // Default: null + * http_codes?: array, + * }>, + * max_retries?: int|Param, // Default: 3 + * delay?: int|Param, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 + * multiplier?: float|Param, // If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries). // Default: 2 + * max_delay?: int|Param, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 + * jitter?: float|Param, // Randomness in percent (between 0 and 1) to apply to the delay. // Default: 0.1 + * }, + * }>, + * }, + * mailer?: bool|array{ // Mailer configuration + * enabled?: bool|Param, // Default: true + * message_bus?: scalar|null|Param, // The message bus to use. Defaults to the default bus if the Messenger component is installed. // Default: null + * dsn?: scalar|null|Param, // Default: null + * transports?: array, + * envelope?: array{ // Mailer Envelope configuration + * sender?: scalar|null|Param, + * recipients?: list, + * allowed_recipients?: list, + * }, + * headers?: array, + * dkim_signer?: bool|array{ // DKIM signer configuration + * enabled?: bool|Param, // Default: false + * key?: scalar|null|Param, // Key content, or path to key (in PEM format with the `file://` prefix) // Default: "" + * domain?: scalar|null|Param, // Default: "" + * select?: scalar|null|Param, // Default: "" + * passphrase?: scalar|null|Param, // The private key passphrase // Default: "" + * options?: array, + * }, + * smime_signer?: bool|array{ // S/MIME signer configuration + * enabled?: bool|Param, // Default: false + * key?: scalar|null|Param, // Path to key (in PEM format) // Default: "" + * certificate?: scalar|null|Param, // Path to certificate (in PEM format without the `file://` prefix) // Default: "" + * passphrase?: scalar|null|Param, // The private key passphrase // Default: null + * extra_certificates?: scalar|null|Param, // Default: null + * sign_options?: int|Param, // Default: null + * }, + * smime_encrypter?: bool|array{ // S/MIME encrypter configuration + * enabled?: bool|Param, // Default: false + * repository?: scalar|null|Param, // S/MIME certificate repository service. This service shall implement the `Symfony\Component\Mailer\EventListener\SmimeCertificateRepositoryInterface`. // Default: "" + * cipher?: int|Param, // A set of algorithms used to encrypt the message // Default: null + * }, + * }, + * secrets?: bool|array{ + * enabled?: bool|Param, // Default: true + * vault_directory?: scalar|null|Param, // Default: "%kernel.project_dir%/config/secrets/%kernel.runtime_environment%" + * local_dotenv_file?: scalar|null|Param, // Default: "%kernel.project_dir%/.env.%kernel.runtime_environment%.local" + * decryption_env_var?: scalar|null|Param, // Default: "base64:default::SYMFONY_DECRYPTION_SECRET" + * }, + * notifier?: bool|array{ // Notifier configuration + * enabled?: bool|Param, // Default: true + * message_bus?: scalar|null|Param, // The message bus to use. Defaults to the default bus if the Messenger component is installed. // Default: null + * chatter_transports?: array, + * texter_transports?: array, + * notification_on_failed_messages?: bool|Param, // Default: false + * channel_policy?: array>, + * admin_recipients?: list, + * }, + * rate_limiter?: bool|array{ // Rate limiter configuration + * enabled?: bool|Param, // Default: true + * limiters?: array, + * limit?: int|Param, // The maximum allowed hits in a fixed interval or burst. + * interval?: scalar|null|Param, // Configures the fixed interval if "policy" is set to "fixed_window" or "sliding_window". The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent). + * rate?: array{ // Configures the fill rate if "policy" is set to "token_bucket". + * interval?: scalar|null|Param, // Configures the rate interval. The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent). + * amount?: int|Param, // Amount of tokens to add each interval. // Default: 1 + * }, + * }>, + * }, + * uid?: bool|array{ // Uid configuration + * enabled?: bool|Param, // Default: true + * default_uuid_version?: 7|6|4|1|Param, // Default: 7 + * name_based_uuid_version?: 5|3|Param, // Default: 5 + * name_based_uuid_namespace?: scalar|null|Param, + * time_based_uuid_version?: 7|6|1|Param, // Default: 7 + * time_based_uuid_node?: scalar|null|Param, + * }, + * html_sanitizer?: bool|array{ // HtmlSanitizer configuration + * enabled?: bool|Param, // Default: true + * sanitizers?: array, + * block_elements?: list, + * drop_elements?: list, + * allow_attributes?: array, + * drop_attributes?: array, + * force_attributes?: array>, + * force_https_urls?: bool|Param, // Transforms URLs using the HTTP scheme to use the HTTPS scheme instead. // Default: false + * allowed_link_schemes?: list, + * allowed_link_hosts?: list|null, + * allow_relative_links?: bool|Param, // Allows relative URLs to be used in links href attributes. // Default: false + * allowed_media_schemes?: list, + * allowed_media_hosts?: list|null, + * allow_relative_medias?: bool|Param, // Allows relative URLs to be used in media source attributes (img, audio, video, ...). // Default: false + * with_attribute_sanitizers?: list, + * without_attribute_sanitizers?: list, + * max_input_length?: int|Param, // The maximum length allowed for the sanitized input. // Default: 0 + * }>, + * }, + * webhook?: bool|array{ // Webhook configuration + * enabled?: bool|Param, // Default: false + * message_bus?: scalar|null|Param, // The message bus to use. // Default: "messenger.default_bus" + * routing?: array, + * }, + * remote-event?: bool|array{ // RemoteEvent configuration + * enabled?: bool|Param, // Default: false + * }, + * json_streamer?: bool|array{ // JSON streamer configuration + * enabled?: bool|Param, // Default: false + * }, + * } + * @psalm-type SecurityConfig = array{ + * access_denied_url?: scalar|null|Param, // Default: null + * session_fixation_strategy?: "none"|"migrate"|"invalidate"|Param, // Default: "migrate" + * hide_user_not_found?: bool|Param, // Deprecated: The "hide_user_not_found" option is deprecated and will be removed in 8.0. Use the "expose_security_errors" option instead. + * expose_security_errors?: \Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::None|\Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::AccountStatus|\Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::All|Param, // Default: "none" + * erase_credentials?: bool|Param, // Default: true + * access_decision_manager?: array{ + * strategy?: "affirmative"|"consensus"|"unanimous"|"priority"|Param, + * service?: scalar|null|Param, + * strategy_service?: scalar|null|Param, + * allow_if_all_abstain?: bool|Param, // Default: false + * allow_if_equal_granted_denied?: bool|Param, // Default: true + * }, + * password_hashers?: array, + * hash_algorithm?: scalar|null|Param, // Name of hashing algorithm for PBKDF2 (i.e. sha256, sha512, etc..) See hash_algos() for a list of supported algorithms. // Default: "sha512" + * key_length?: scalar|null|Param, // Default: 40 + * ignore_case?: bool|Param, // Default: false + * encode_as_base64?: bool|Param, // Default: true + * iterations?: scalar|null|Param, // Default: 5000 + * cost?: int|Param, // Default: null + * memory_cost?: scalar|null|Param, // Default: null + * time_cost?: scalar|null|Param, // Default: null + * id?: scalar|null|Param, + * }>, + * providers?: array, + * }, + * memory?: array{ + * users?: array, + * }>, + * }, + * ldap?: array{ + * service: scalar|null|Param, + * base_dn: scalar|null|Param, + * search_dn?: scalar|null|Param, // Default: null + * search_password?: scalar|null|Param, // Default: null + * extra_fields?: list, + * default_roles?: list, + * role_fetcher?: scalar|null|Param, // Default: null + * uid_key?: scalar|null|Param, // Default: "sAMAccountName" + * filter?: scalar|null|Param, // Default: "({uid_key}={user_identifier})" + * password_attribute?: scalar|null|Param, // Default: null + * }, + * entity?: array{ + * class: scalar|null|Param, // The full entity class name of your user class. + * property?: scalar|null|Param, // Default: null + * manager_name?: scalar|null|Param, // Default: null + * }, + * }>, + * firewalls: array, + * security?: bool|Param, // Default: true + * user_checker?: scalar|null|Param, // The UserChecker to use when authenticating users in this firewall. // Default: "security.user_checker" + * request_matcher?: scalar|null|Param, + * access_denied_url?: scalar|null|Param, + * access_denied_handler?: scalar|null|Param, + * entry_point?: scalar|null|Param, // An enabled authenticator name or a service id that implements "Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface". + * provider?: scalar|null|Param, + * stateless?: bool|Param, // Default: false + * lazy?: bool|Param, // Default: false + * context?: scalar|null|Param, + * logout?: array{ + * enable_csrf?: bool|null|Param, // Default: null + * csrf_token_id?: scalar|null|Param, // Default: "logout" + * csrf_parameter?: scalar|null|Param, // Default: "_csrf_token" + * csrf_token_manager?: scalar|null|Param, + * path?: scalar|null|Param, // Default: "/logout" + * target?: scalar|null|Param, // Default: "/" + * invalidate_session?: bool|Param, // Default: true + * clear_site_data?: list<"*"|"cache"|"cookies"|"storage"|"executionContexts"|Param>, + * delete_cookies?: array, + * }, + * switch_user?: array{ + * provider?: scalar|null|Param, + * parameter?: scalar|null|Param, // Default: "_switch_user" + * role?: scalar|null|Param, // Default: "ROLE_ALLOWED_TO_SWITCH" + * target_route?: scalar|null|Param, // Default: null + * }, + * required_badges?: list, + * custom_authenticators?: list, + * login_throttling?: array{ + * limiter?: scalar|null|Param, // A service id implementing "Symfony\Component\HttpFoundation\RateLimiter\RequestRateLimiterInterface". + * max_attempts?: int|Param, // Default: 5 + * interval?: scalar|null|Param, // Default: "1 minute" + * lock_factory?: scalar|null|Param, // The service ID of the lock factory used by the login rate limiter (or null to disable locking). // Default: null + * cache_pool?: string|Param, // The cache pool to use for storing the limiter state // Default: "cache.rate_limiter" + * storage_service?: string|Param, // The service ID of a custom storage implementation, this precedes any configured "cache_pool" // Default: null + * }, + * two_factor?: array{ + * check_path?: scalar|null|Param, // Default: "/2fa_check" + * post_only?: bool|Param, // Default: true + * auth_form_path?: scalar|null|Param, // Default: "/2fa" + * always_use_default_target_path?: bool|Param, // Default: false + * default_target_path?: scalar|null|Param, // Default: "/" + * success_handler?: scalar|null|Param, // Default: null + * failure_handler?: scalar|null|Param, // Default: null + * authentication_required_handler?: scalar|null|Param, // Default: null + * auth_code_parameter_name?: scalar|null|Param, // Default: "_auth_code" + * trusted_parameter_name?: scalar|null|Param, // Default: "_trusted" + * remember_me_sets_trusted?: scalar|null|Param, // Default: false + * multi_factor?: bool|Param, // Default: false + * prepare_on_login?: bool|Param, // Default: false + * prepare_on_access_denied?: bool|Param, // Default: false + * enable_csrf?: scalar|null|Param, // Default: false + * csrf_parameter?: scalar|null|Param, // Default: "_csrf_token" + * csrf_token_id?: scalar|null|Param, // Default: "two_factor" + * csrf_header?: scalar|null|Param, // Default: null + * csrf_token_manager?: scalar|null|Param, // Default: "scheb_two_factor.csrf_token_manager" + * provider?: scalar|null|Param, // Default: null + * }, + * x509?: array{ + * provider?: scalar|null|Param, + * user?: scalar|null|Param, // Default: "SSL_CLIENT_S_DN_Email" + * credentials?: scalar|null|Param, // Default: "SSL_CLIENT_S_DN" + * user_identifier?: scalar|null|Param, // Default: "emailAddress" + * }, + * remote_user?: array{ + * provider?: scalar|null|Param, + * user?: scalar|null|Param, // Default: "REMOTE_USER" + * }, + * login_link?: array{ + * check_route: scalar|null|Param, // Route that will validate the login link - e.g. "app_login_link_verify". + * check_post_only?: scalar|null|Param, // If true, only HTTP POST requests to "check_route" will be handled by the authenticator. // Default: false + * signature_properties: list, + * lifetime?: int|Param, // The lifetime of the login link in seconds. // Default: 600 + * max_uses?: int|Param, // Max number of times a login link can be used - null means unlimited within lifetime. // Default: null + * used_link_cache?: scalar|null|Param, // Cache service id used to expired links of max_uses is set. + * success_handler?: scalar|null|Param, // A service id that implements Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface. + * failure_handler?: scalar|null|Param, // A service id that implements Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface. + * provider?: scalar|null|Param, // The user provider to load users from. + * secret?: scalar|null|Param, // Default: "%kernel.secret%" + * always_use_default_target_path?: bool|Param, // Default: false + * default_target_path?: scalar|null|Param, // Default: "/" + * login_path?: scalar|null|Param, // Default: "/login" + * target_path_parameter?: scalar|null|Param, // Default: "_target_path" + * use_referer?: bool|Param, // Default: false + * failure_path?: scalar|null|Param, // Default: null + * failure_forward?: bool|Param, // Default: false + * failure_path_parameter?: scalar|null|Param, // Default: "_failure_path" + * }, + * form_login?: array{ + * provider?: scalar|null|Param, + * remember_me?: bool|Param, // Default: true + * success_handler?: scalar|null|Param, + * failure_handler?: scalar|null|Param, + * check_path?: scalar|null|Param, // Default: "/login_check" + * use_forward?: bool|Param, // Default: false + * login_path?: scalar|null|Param, // Default: "/login" + * username_parameter?: scalar|null|Param, // Default: "_username" + * password_parameter?: scalar|null|Param, // Default: "_password" + * csrf_parameter?: scalar|null|Param, // Default: "_csrf_token" + * csrf_token_id?: scalar|null|Param, // Default: "authenticate" + * enable_csrf?: bool|Param, // Default: false + * post_only?: bool|Param, // Default: true + * form_only?: bool|Param, // Default: false + * always_use_default_target_path?: bool|Param, // Default: false + * default_target_path?: scalar|null|Param, // Default: "/" + * target_path_parameter?: scalar|null|Param, // Default: "_target_path" + * use_referer?: bool|Param, // Default: false + * failure_path?: scalar|null|Param, // Default: null + * failure_forward?: bool|Param, // Default: false + * failure_path_parameter?: scalar|null|Param, // Default: "_failure_path" + * }, + * form_login_ldap?: array{ + * provider?: scalar|null|Param, + * remember_me?: bool|Param, // Default: true + * success_handler?: scalar|null|Param, + * failure_handler?: scalar|null|Param, + * check_path?: scalar|null|Param, // Default: "/login_check" + * use_forward?: bool|Param, // Default: false + * login_path?: scalar|null|Param, // Default: "/login" + * username_parameter?: scalar|null|Param, // Default: "_username" + * password_parameter?: scalar|null|Param, // Default: "_password" + * csrf_parameter?: scalar|null|Param, // Default: "_csrf_token" + * csrf_token_id?: scalar|null|Param, // Default: "authenticate" + * enable_csrf?: bool|Param, // Default: false + * post_only?: bool|Param, // Default: true + * form_only?: bool|Param, // Default: false + * always_use_default_target_path?: bool|Param, // Default: false + * default_target_path?: scalar|null|Param, // Default: "/" + * target_path_parameter?: scalar|null|Param, // Default: "_target_path" + * use_referer?: bool|Param, // Default: false + * failure_path?: scalar|null|Param, // Default: null + * failure_forward?: bool|Param, // Default: false + * failure_path_parameter?: scalar|null|Param, // Default: "_failure_path" + * service?: scalar|null|Param, // Default: "ldap" + * dn_string?: scalar|null|Param, // Default: "{user_identifier}" + * query_string?: scalar|null|Param, + * search_dn?: scalar|null|Param, // Default: "" + * search_password?: scalar|null|Param, // Default: "" + * }, + * json_login?: array{ + * provider?: scalar|null|Param, + * remember_me?: bool|Param, // Default: true + * success_handler?: scalar|null|Param, + * failure_handler?: scalar|null|Param, + * check_path?: scalar|null|Param, // Default: "/login_check" + * use_forward?: bool|Param, // Default: false + * login_path?: scalar|null|Param, // Default: "/login" + * username_path?: scalar|null|Param, // Default: "username" + * password_path?: scalar|null|Param, // Default: "password" + * }, + * json_login_ldap?: array{ + * provider?: scalar|null|Param, + * remember_me?: bool|Param, // Default: true + * success_handler?: scalar|null|Param, + * failure_handler?: scalar|null|Param, + * check_path?: scalar|null|Param, // Default: "/login_check" + * use_forward?: bool|Param, // Default: false + * login_path?: scalar|null|Param, // Default: "/login" + * username_path?: scalar|null|Param, // Default: "username" + * password_path?: scalar|null|Param, // Default: "password" + * service?: scalar|null|Param, // Default: "ldap" + * dn_string?: scalar|null|Param, // Default: "{user_identifier}" + * query_string?: scalar|null|Param, + * search_dn?: scalar|null|Param, // Default: "" + * search_password?: scalar|null|Param, // Default: "" + * }, + * access_token?: array{ + * provider?: scalar|null|Param, + * remember_me?: bool|Param, // Default: true + * success_handler?: scalar|null|Param, + * failure_handler?: scalar|null|Param, + * realm?: scalar|null|Param, // Default: null + * token_extractors?: list, + * token_handler: string|array{ + * id?: scalar|null|Param, + * oidc_user_info?: string|array{ + * base_uri: scalar|null|Param, // Base URI of the userinfo endpoint on the OIDC server, or the OIDC server URI to use the discovery (require "discovery" to be configured). + * discovery?: array{ // Enable the OIDC discovery. + * cache?: array{ + * id: scalar|null|Param, // Cache service id to use to cache the OIDC discovery configuration. + * }, + * }, + * claim?: scalar|null|Param, // Claim which contains the user identifier (e.g. sub, email, etc.). // Default: "sub" + * client?: scalar|null|Param, // HttpClient service id to use to call the OIDC server. + * }, + * oidc?: array{ + * discovery?: array{ // Enable the OIDC discovery. + * base_uri: list, + * cache?: array{ + * id: scalar|null|Param, // Cache service id to use to cache the OIDC discovery configuration. + * }, + * }, + * claim?: scalar|null|Param, // Claim which contains the user identifier (e.g.: sub, email..). // Default: "sub" + * audience: scalar|null|Param, // Audience set in the token, for validation purpose. + * issuers: list, + * algorithm?: array, + * algorithms: list, + * key?: scalar|null|Param, // Deprecated: The "key" option is deprecated and will be removed in 8.0. Use the "keyset" option instead. // JSON-encoded JWK used to sign the token (must contain a "kty" key). + * keyset?: scalar|null|Param, // JSON-encoded JWKSet used to sign the token (must contain a list of valid public keys). + * encryption?: bool|array{ + * enabled?: bool|Param, // Default: false + * enforce?: bool|Param, // When enabled, the token shall be encrypted. // Default: false + * algorithms: list, + * keyset: scalar|null|Param, // JSON-encoded JWKSet used to decrypt the token (must contain a list of valid private keys). + * }, + * }, + * cas?: array{ + * validation_url: scalar|null|Param, // CAS server validation URL + * prefix?: scalar|null|Param, // CAS prefix // Default: "cas" + * http_client?: scalar|null|Param, // HTTP Client service // Default: null + * }, + * oauth2?: scalar|null|Param, + * }, + * }, + * http_basic?: array{ + * provider?: scalar|null|Param, + * realm?: scalar|null|Param, // Default: "Secured Area" + * }, + * http_basic_ldap?: array{ + * provider?: scalar|null|Param, + * realm?: scalar|null|Param, // Default: "Secured Area" + * service?: scalar|null|Param, // Default: "ldap" + * dn_string?: scalar|null|Param, // Default: "{user_identifier}" + * query_string?: scalar|null|Param, + * search_dn?: scalar|null|Param, // Default: "" + * search_password?: scalar|null|Param, // Default: "" + * }, + * remember_me?: array{ + * secret?: scalar|null|Param, // Default: "%kernel.secret%" + * service?: scalar|null|Param, + * user_providers?: list, + * catch_exceptions?: bool|Param, // Default: true + * signature_properties?: list, + * token_provider?: string|array{ + * service?: scalar|null|Param, // The service ID of a custom remember-me token provider. + * doctrine?: bool|array{ + * enabled?: bool|Param, // Default: false + * connection?: scalar|null|Param, // Default: null + * }, + * }, + * token_verifier?: scalar|null|Param, // The service ID of a custom rememberme token verifier. + * name?: scalar|null|Param, // Default: "REMEMBERME" + * lifetime?: int|Param, // Default: 31536000 + * path?: scalar|null|Param, // Default: "/" + * domain?: scalar|null|Param, // Default: null + * secure?: true|false|"auto"|Param, // Default: null + * httponly?: bool|Param, // Default: true + * samesite?: null|"lax"|"strict"|"none"|Param, // Default: "lax" + * always_remember_me?: bool|Param, // Default: false + * remember_me_parameter?: scalar|null|Param, // Default: "_remember_me" + * }, + * }>, + * access_control?: list, + * attributes?: array, + * route?: scalar|null|Param, // Default: null + * methods?: list, + * allow_if?: scalar|null|Param, // Default: null + * roles?: list, + * }>, + * role_hierarchy?: array>, + * } + * @psalm-type TwigConfig = array{ + * form_themes?: list, + * globals?: array, + * autoescape_service?: scalar|null|Param, // Default: null + * autoescape_service_method?: scalar|null|Param, // Default: null + * base_template_class?: scalar|null|Param, // Deprecated: The child node "base_template_class" at path "twig.base_template_class" is deprecated. + * cache?: scalar|null|Param, // Default: true + * charset?: scalar|null|Param, // Default: "%kernel.charset%" + * debug?: bool|Param, // Default: "%kernel.debug%" + * strict_variables?: bool|Param, // Default: "%kernel.debug%" + * auto_reload?: scalar|null|Param, + * optimizations?: int|Param, + * default_path?: scalar|null|Param, // The default path used to load templates. // Default: "%kernel.project_dir%/templates" + * file_name_pattern?: list, + * paths?: array, + * date?: array{ // The default format options used by the date filter. + * format?: scalar|null|Param, // Default: "F j, Y H:i" + * interval_format?: scalar|null|Param, // Default: "%d days" + * timezone?: scalar|null|Param, // The timezone used when formatting dates, when set to null, the timezone returned by date_default_timezone_get() is used. // Default: null + * }, + * number_format?: array{ // The default format options for the number_format filter. + * decimals?: int|Param, // Default: 0 + * decimal_point?: scalar|null|Param, // Default: "." + * thousands_separator?: scalar|null|Param, // Default: "," + * }, + * mailer?: array{ + * html_to_text_converter?: scalar|null|Param, // A service implementing the "Symfony\Component\Mime\HtmlToTextConverter\HtmlToTextConverterInterface". // Default: null + * }, + * } + * @psalm-type TwigExtraConfig = array{ + * cache?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * html?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * markdown?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * intl?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * cssinliner?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * inky?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * string?: bool|array{ + * enabled?: bool|Param, // Default: true + * }, + * commonmark?: array{ + * renderer?: array{ // Array of options for rendering HTML. + * block_separator?: scalar|null|Param, + * inner_separator?: scalar|null|Param, + * soft_break?: scalar|null|Param, + * }, + * html_input?: "strip"|"allow"|"escape"|Param, // How to handle HTML input. + * allow_unsafe_links?: bool|Param, // Remove risky link and image URLs by setting this to false. // Default: true + * max_nesting_level?: int|Param, // The maximum nesting level for blocks. // Default: 9223372036854775807 + * max_delimiters_per_line?: int|Param, // The maximum number of strong/emphasis delimiters per line. // Default: 9223372036854775807 + * slug_normalizer?: array{ // Array of options for configuring how URL-safe slugs are created. + * instance?: mixed, + * max_length?: int|Param, // Default: 255 + * unique?: mixed, + * }, + * commonmark?: array{ // Array of options for configuring the CommonMark core extension. + * enable_em?: bool|Param, // Default: true + * enable_strong?: bool|Param, // Default: true + * use_asterisk?: bool|Param, // Default: true + * use_underscore?: bool|Param, // Default: true + * unordered_list_markers?: list, + * }, + * ... + * }, + * } + * @psalm-type MonologConfig = array{ + * use_microseconds?: scalar|null|Param, // Default: true + * channels?: list, + * handlers?: array, + * excluded_http_codes?: list, + * }>, + * accepted_levels?: list, + * min_level?: scalar|null|Param, // Default: "DEBUG" + * max_level?: scalar|null|Param, // Default: "EMERGENCY" + * buffer_size?: scalar|null|Param, // Default: 0 + * flush_on_overflow?: bool|Param, // Default: false + * handler?: scalar|null|Param, + * url?: scalar|null|Param, + * exchange?: scalar|null|Param, + * exchange_name?: scalar|null|Param, // Default: "log" + * room?: scalar|null|Param, + * message_format?: scalar|null|Param, // Default: "text" + * api_version?: scalar|null|Param, // Default: null + * channel?: scalar|null|Param, // Default: null + * bot_name?: scalar|null|Param, // Default: "Monolog" + * use_attachment?: scalar|null|Param, // Default: true + * use_short_attachment?: scalar|null|Param, // Default: false + * include_extra?: scalar|null|Param, // Default: false + * icon_emoji?: scalar|null|Param, // Default: null + * webhook_url?: scalar|null|Param, + * exclude_fields?: list, + * team?: scalar|null|Param, + * notify?: scalar|null|Param, // Default: false + * nickname?: scalar|null|Param, // Default: "Monolog" + * token?: scalar|null|Param, + * region?: scalar|null|Param, + * source?: scalar|null|Param, + * use_ssl?: bool|Param, // Default: true + * user?: mixed, + * title?: scalar|null|Param, // Default: null + * host?: scalar|null|Param, // Default: null + * port?: scalar|null|Param, // Default: 514 + * config?: list, + * members?: list, + * connection_string?: scalar|null|Param, + * timeout?: scalar|null|Param, + * time?: scalar|null|Param, // Default: 60 + * deduplication_level?: scalar|null|Param, // Default: 400 + * store?: scalar|null|Param, // Default: null + * connection_timeout?: scalar|null|Param, + * persistent?: bool|Param, + * dsn?: scalar|null|Param, + * hub_id?: scalar|null|Param, // Default: null + * client_id?: scalar|null|Param, // Default: null + * auto_log_stacks?: scalar|null|Param, // Default: false + * release?: scalar|null|Param, // Default: null + * environment?: scalar|null|Param, // Default: null + * message_type?: scalar|null|Param, // Default: 0 + * parse_mode?: scalar|null|Param, // Default: null + * disable_webpage_preview?: bool|null|Param, // Default: null + * disable_notification?: bool|null|Param, // Default: null + * split_long_messages?: bool|Param, // Default: false + * delay_between_messages?: bool|Param, // Default: false + * topic?: int|Param, // Default: null + * factor?: int|Param, // Default: 1 + * tags?: list, + * console_formater_options?: mixed, // Deprecated: "monolog.handlers..console_formater_options.console_formater_options" is deprecated, use "monolog.handlers..console_formater_options.console_formatter_options" instead. + * console_formatter_options?: mixed, // Default: [] + * formatter?: scalar|null|Param, + * nested?: bool|Param, // Default: false + * publisher?: string|array{ + * id?: scalar|null|Param, + * hostname?: scalar|null|Param, + * port?: scalar|null|Param, // Default: 12201 + * chunk_size?: scalar|null|Param, // Default: 1420 + * encoder?: "json"|"compressed_json"|Param, + * }, + * mongo?: string|array{ + * id?: scalar|null|Param, + * host?: scalar|null|Param, + * port?: scalar|null|Param, // Default: 27017 + * user?: scalar|null|Param, + * pass?: scalar|null|Param, + * database?: scalar|null|Param, // Default: "monolog" + * collection?: scalar|null|Param, // Default: "logs" + * }, + * mongodb?: string|array{ + * id?: scalar|null|Param, // ID of a MongoDB\Client service + * uri?: scalar|null|Param, + * username?: scalar|null|Param, + * password?: scalar|null|Param, + * database?: scalar|null|Param, // Default: "monolog" + * collection?: scalar|null|Param, // Default: "logs" + * }, + * elasticsearch?: string|array{ + * id?: scalar|null|Param, + * hosts?: list, + * host?: scalar|null|Param, + * port?: scalar|null|Param, // Default: 9200 + * transport?: scalar|null|Param, // Default: "Http" + * user?: scalar|null|Param, // Default: null + * password?: scalar|null|Param, // Default: null + * }, + * index?: scalar|null|Param, // Default: "monolog" + * document_type?: scalar|null|Param, // Default: "logs" + * ignore_error?: scalar|null|Param, // Default: false + * redis?: string|array{ + * id?: scalar|null|Param, + * host?: scalar|null|Param, + * password?: scalar|null|Param, // Default: null + * port?: scalar|null|Param, // Default: 6379 + * database?: scalar|null|Param, // Default: 0 + * key_name?: scalar|null|Param, // Default: "monolog_redis" + * }, + * predis?: string|array{ + * id?: scalar|null|Param, + * host?: scalar|null|Param, + * }, + * from_email?: scalar|null|Param, + * to_email?: list, + * subject?: scalar|null|Param, + * content_type?: scalar|null|Param, // Default: null + * headers?: list, + * mailer?: scalar|null|Param, // Default: null + * email_prototype?: string|array{ + * id: scalar|null|Param, + * method?: scalar|null|Param, // Default: null + * }, + * lazy?: bool|Param, // Default: true + * verbosity_levels?: array{ + * VERBOSITY_QUIET?: scalar|null|Param, // Default: "ERROR" + * VERBOSITY_NORMAL?: scalar|null|Param, // Default: "WARNING" + * VERBOSITY_VERBOSE?: scalar|null|Param, // Default: "NOTICE" + * VERBOSITY_VERY_VERBOSE?: scalar|null|Param, // Default: "INFO" + * VERBOSITY_DEBUG?: scalar|null|Param, // Default: "DEBUG" + * }, + * channels?: string|array{ + * type?: scalar|null|Param, + * elements?: list, + * }, + * }>, + * } + * @psalm-type DoctrineConfig = array{ + * dbal?: array{ + * default_connection?: scalar|null|Param, + * types?: array, + * driver_schemes?: array, + * connections?: array, + * mapping_types?: array, + * default_table_options?: array, + * schema_manager_factory?: scalar|null|Param, // Default: "doctrine.dbal.default_schema_manager_factory" + * result_cache?: scalar|null|Param, + * slaves?: array, + * replicas?: array, + * }>, + * }, + * orm?: array{ + * default_entity_manager?: scalar|null|Param, + * auto_generate_proxy_classes?: scalar|null|Param, // Auto generate mode possible values are: "NEVER", "ALWAYS", "FILE_NOT_EXISTS", "EVAL", "FILE_NOT_EXISTS_OR_CHANGED", this option is ignored when the "enable_native_lazy_objects" option is true // Default: false + * enable_lazy_ghost_objects?: bool|Param, // Enables the new implementation of proxies based on lazy ghosts instead of using the legacy implementation // Default: true + * enable_native_lazy_objects?: bool|Param, // Enables the new native implementation of PHP lazy objects instead of generated proxies // Default: false + * proxy_dir?: scalar|null|Param, // Configures the path where generated proxy classes are saved when using non-native lazy objects, this option is ignored when the "enable_native_lazy_objects" option is true // Default: "%kernel.build_dir%/doctrine/orm/Proxies" + * proxy_namespace?: scalar|null|Param, // Defines the root namespace for generated proxy classes when using non-native lazy objects, this option is ignored when the "enable_native_lazy_objects" option is true // Default: "Proxies" + * controller_resolver?: bool|array{ + * enabled?: bool|Param, // Default: true + * auto_mapping?: bool|null|Param, // Set to false to disable using route placeholders as lookup criteria when the primary key doesn't match the argument name // Default: null + * evict_cache?: bool|Param, // Set to true to fetch the entity from the database instead of using the cache, if any // Default: false + * }, + * entity_managers?: array, + * }>, + * }>, + * }, + * connection?: scalar|null|Param, + * class_metadata_factory_name?: scalar|null|Param, // Default: "Doctrine\\ORM\\Mapping\\ClassMetadataFactory" + * default_repository_class?: scalar|null|Param, // Default: "Doctrine\\ORM\\EntityRepository" + * auto_mapping?: scalar|null|Param, // Default: false + * naming_strategy?: scalar|null|Param, // Default: "doctrine.orm.naming_strategy.default" + * quote_strategy?: scalar|null|Param, // Default: "doctrine.orm.quote_strategy.default" + * typed_field_mapper?: scalar|null|Param, // Default: "doctrine.orm.typed_field_mapper.default" + * entity_listener_resolver?: scalar|null|Param, // Default: null + * fetch_mode_subselect_batch_size?: scalar|null|Param, + * repository_factory?: scalar|null|Param, // Default: "doctrine.orm.container_repository_factory" + * schema_ignore_classes?: list, + * report_fields_where_declared?: bool|Param, // Set to "true" to opt-in to the new mapping driver mode that was added in Doctrine ORM 2.16 and will be mandatory in ORM 3.0. See https://github.com/doctrine/orm/pull/10455. // Default: true + * validate_xml_mapping?: bool|Param, // Set to "true" to opt-in to the new mapping driver mode that was added in Doctrine ORM 2.14. See https://github.com/doctrine/orm/pull/6728. // Default: false + * second_level_cache?: array{ + * region_cache_driver?: string|array{ + * type?: scalar|null|Param, // Default: null + * id?: scalar|null|Param, + * pool?: scalar|null|Param, + * }, + * region_lock_lifetime?: scalar|null|Param, // Default: 60 + * log_enabled?: bool|Param, // Default: true + * region_lifetime?: scalar|null|Param, // Default: 3600 + * enabled?: bool|Param, // Default: true + * factory?: scalar|null|Param, + * regions?: array, + * loggers?: array, + * }, + * hydrators?: array, + * mappings?: array, + * dql?: array{ + * string_functions?: array, + * numeric_functions?: array, + * datetime_functions?: array, + * }, + * filters?: array, + * }>, + * identity_generation_preferences?: array, + * }>, + * resolve_target_entities?: array, + * }, + * } + * @psalm-type DoctrineMigrationsConfig = array{ + * migrations_paths?: array, + * services?: array, + * factories?: array, + * storage?: array{ // Storage to use for migration status metadata. + * table_storage?: array{ // The default metadata storage, implemented as a table in the database. + * table_name?: scalar|null|Param, // Default: null + * version_column_name?: scalar|null|Param, // Default: null + * version_column_length?: scalar|null|Param, // Default: null + * executed_at_column_name?: scalar|null|Param, // Default: null + * execution_time_column_name?: scalar|null|Param, // Default: null + * }, + * }, + * migrations?: list, + * connection?: scalar|null|Param, // Connection name to use for the migrations database. // Default: null + * em?: scalar|null|Param, // Entity manager name to use for the migrations database (available when doctrine/orm is installed). // Default: null + * all_or_nothing?: scalar|null|Param, // Run all migrations in a transaction. // Default: false + * check_database_platform?: scalar|null|Param, // Adds an extra check in the generated migrations to allow execution only on the same platform as they were initially generated on. // Default: true + * custom_template?: scalar|null|Param, // Custom template path for generated migration classes. // Default: null + * organize_migrations?: scalar|null|Param, // Organize migrations mode. Possible values are: "BY_YEAR", "BY_YEAR_AND_MONTH", false // Default: false + * enable_profiler?: bool|Param, // Whether or not to enable the profiler collector to calculate and visualize migration status. This adds some queries overhead. // Default: false + * transactional?: bool|Param, // Whether or not to wrap migrations in a single transaction. // Default: true + * } + * @psalm-type CmfRoutingConfig = array{ + * chain?: array{ + * routers_by_id?: array, + * replace_symfony_router?: bool|Param, // Default: true + * }, + * dynamic?: bool|array{ + * enabled?: bool|Param, // Default: false + * route_collection_limit?: scalar|null|Param, // Default: 0 + * generic_controller?: scalar|null|Param, // Default: null + * default_controller?: scalar|null|Param, // Default: null + * controllers_by_type?: array, + * controllers_by_class?: array, + * templates_by_class?: array, + * persistence?: array{ + * phpcr?: bool|array{ + * enabled?: bool|Param, // Default: false + * manager_name?: scalar|null|Param, // Default: null + * route_basepaths?: list, + * enable_initializer?: bool|Param, // Default: true + * }, + * orm?: bool|array{ + * enabled?: bool|Param, // Default: false + * manager_name?: scalar|null|Param, // Default: null + * route_class?: scalar|null|Param, // Default: "Symfony\\Cmf\\Bundle\\RoutingBundle\\Doctrine\\Orm\\Route" + * }, + * }, + * uri_filter_regexp?: scalar|null|Param, // Default: "" + * route_provider_service_id?: scalar|null|Param, + * route_filters_by_id?: array, + * content_repository_service_id?: scalar|null|Param, + * locales?: list, + * limit_candidates?: int|Param, // Default: 20 + * match_implicit_locale?: bool|Param, // Default: true + * redirectable_url_matcher?: bool|Param, // Default: false + * auto_locale_pattern?: bool|Param, // Default: false + * url_generator?: scalar|null|Param, // URL generator service ID // Default: "cmf_routing.generator" + * }, + * } + * @psalm-type SchebTwoFactorConfig = array{ + * persister?: scalar|null|Param, // Default: "scheb_two_factor.persister.doctrine" + * model_manager_name?: scalar|null|Param, // Default: null + * security_tokens?: list, + * ip_whitelist?: list, + * ip_whitelist_provider?: scalar|null|Param, // Default: "scheb_two_factor.default_ip_whitelist_provider" + * two_factor_token_factory?: scalar|null|Param, // Default: "scheb_two_factor.default_token_factory" + * two_factor_provider_decider?: scalar|null|Param, // Default: "scheb_two_factor.default_provider_decider" + * two_factor_condition?: scalar|null|Param, // Default: null + * code_reuse_cache?: scalar|null|Param, // Default: null + * code_reuse_cache_duration?: int|Param, // Default: 60 + * code_reuse_default_handler?: scalar|null|Param, // Default: null + * google?: bool|array{ + * enabled?: scalar|null|Param, // Default: false + * form_renderer?: scalar|null|Param, // Default: null + * issuer?: scalar|null|Param, // Default: null + * server_name?: scalar|null|Param, // Default: null + * template?: scalar|null|Param, // Default: "@SchebTwoFactor/Authentication/form.html.twig" + * digits?: int|Param, // Default: 6 + * leeway?: int|Param, // Default: 0 + * }, + * } + * @psalm-type FosJsRoutingConfig = array{ + * serializer?: scalar|null|Param, + * routes_to_expose?: list, + * router?: scalar|null|Param, // Default: "router" + * request_context_base_url?: scalar|null|Param, // Default: null + * cache_control?: array{ + * public?: bool|Param, // Default: false + * expires?: scalar|null|Param, // Default: null + * maxage?: scalar|null|Param, // Default: null + * smaxage?: scalar|null|Param, // Default: null + * vary?: list, + * }, + * } + * @psalm-type FlysystemConfig = array{ + * storages?: array, + * visibility?: scalar|null|Param, // Default: null + * directory_visibility?: scalar|null|Param, // Default: null + * retain_visibility?: bool|null|Param, // Default: null + * case_sensitive?: bool|Param, // Default: true + * disable_asserts?: bool|Param, // Default: false + * public_url?: list, + * path_normalizer?: scalar|null|Param, // Default: null + * public_url_generator?: scalar|null|Param, // Default: null + * temporary_url_generator?: scalar|null|Param, // Default: null + * read_only?: bool|Param, // Default: false + * }>, + * } + * @psalm-type KnpPaginatorConfig = array{ + * default_options?: array{ + * sort_field_name?: scalar|null|Param, // Default: "sort" + * sort_direction_name?: scalar|null|Param, // Default: "direction" + * filter_field_name?: scalar|null|Param, // Default: "filterField" + * filter_value_name?: scalar|null|Param, // Default: "filterValue" + * page_name?: scalar|null|Param, // Default: "page" + * distinct?: bool|Param, // Default: true + * page_out_of_range?: scalar|null|Param, // Default: "ignore" + * default_limit?: scalar|null|Param, // Default: 10 + * }, + * template?: array{ + * pagination?: scalar|null|Param, // Default: "@KnpPaginator/Pagination/sliding.html.twig" + * rel_links?: scalar|null|Param, // Default: "@KnpPaginator/Pagination/rel_links.html.twig" + * filtration?: scalar|null|Param, // Default: "@KnpPaginator/Pagination/filtration.html.twig" + * sortable?: scalar|null|Param, // Default: "@KnpPaginator/Pagination/sortable_link.html.twig" + * }, + * page_range?: scalar|null|Param, // Default: 5 + * page_limit?: scalar|null|Param, // Default: null + * convert_exception?: bool|Param, // Default: false + * remove_first_page_param?: bool|Param, // Default: false + * } + * @psalm-type CoreShopCoreConfig = array{ + * send_usage_log?: scalar|null|Param, // Default: true + * checkout_manager_factory?: scalar|null|Param, + * after_logout_redirect_route?: scalar|null|Param, // Default: "coreshop_index" + * autoconfigure_with_attributes?: scalar|null|Param, // Default: false + * resources?: array{ + * product_store_values?: array{ + * options?: mixed, + * graphql?: array{ + * enabled?: bool|Param, // Default: true + * }, + * classes?: array{ + * model?: scalar|null|Param, // Default: "CoreShop\\Component\\Core\\Model\\ProductStoreValues" + * interface?: scalar|null|Param, // Default: "CoreShop\\Component\\Core\\Model\\ProductStoreValuesInterface" + * factory?: scalar|null|Param, // Default: "CoreShop\\Component\\Resource\\Factory\\Factory" + * repository?: scalar|null|Param, // Default: "CoreShop\\Bundle\\CoreBundle\\Doctrine\\ORM\\ProductStoreValuesRepository" + * }, + * }, + * }, + * pimcore_admin?: array{ + * js?: array, + * css?: array{ + * core?: scalar|null|Param, // Default: "/bundles/coreshopcore/pimcore/css/core.css" + * ... + * }, + * permissions?: scalar|null|Param, // Default: ["settings","ctc_assign_to_new","ctc_assign_to_existing"] + * editmode_js?: array, + * editmode_css?: array, + * }, + * checkout: array, + * }>, + * } + * @psalm-type CoreShopStorageListConfig = array{ + * list?: array, + * } + * @psalm-type DebugConfig = array{ + * max_items?: int|Param, // Max number of displayed items past the first level, -1 means no limit. // Default: 2500 + * min_depth?: int|Param, // Minimum tree depth to clone all the items, 1 is default. // Default: 1 + * max_string_length?: int|Param, // Max length of displayed strings, -1 means no limit. // Default: -1 + * dump_destination?: scalar|null|Param, // A stream URL where dumps should be written to. // Default: null + * theme?: "dark"|"light"|Param, // Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light". // Default: "dark" + * } + * @psalm-type WebProfilerConfig = array{ + * toolbar?: bool|array{ // Profiler toolbar configuration + * enabled?: bool|Param, // Default: false + * ajax_replace?: bool|Param, // Replace toolbar on AJAX requests // Default: false + * }, + * intercept_redirects?: bool|Param, // Default: false + * excluded_ajax_paths?: scalar|null|Param, // Default: "^/((index|app(_[\\w]+)?)\\.php/)?_wdt" + * } + * @psalm-type PrestaSitemapConfig = array{ + * generator?: scalar|null|Param, // Default: "presta_sitemap.generator_default" + * dumper?: scalar|null|Param, // Default: "presta_sitemap.dumper_default" + * timetolive?: int|Param, // Default: 3600 + * sitemap_file_prefix?: scalar|null|Param, // Sets sitemap filename prefix defaults to "sitemap" -> sitemap.xml (for index); sitemap.
.xml(.gz) (for sitemaps) // Default: "sitemap" + * items_by_set?: int|Param, // The maximum number of items allowed in single sitemap. // Default: 50000 + * route_annotation_listener?: scalar|null|Param, // Default: true + * dump_directory?: scalar|null|Param, // The directory to which the sitemap will be dumped. It can be either absolute, or relative (to the place where the command will be triggered). Default to Symfony's public dir. // Default: "%kernel.project_dir%/public" + * defaults?: array{ + * priority?: scalar|null|Param, // Default: 0.5 + * changefreq?: scalar|null|Param, // Default: "daily" + * lastmod?: scalar|null|Param, // Default: "now" + * }, + * default_section?: scalar|null|Param, // The default section in which static routes are registered. // Default: "default" + * alternate?: bool|array{ // Automatically generate alternate (hreflang) urls with static routes. Requires route_annotation_listener config to be enabled. + * enabled?: bool|Param, // Default: false + * default_locale?: scalar|null|Param, // The default locale of your routes. // Default: "en" + * locales?: list, + * i18n?: "symfony"|"jms"|Param, // Strategy used to create your i18n routes. // Default: "symfony" + * }, + * } + * @psalm-type PimcoreStaticResolverConfig = array + * @psalm-type PimcoreElasticsearchClientConfig = array{ + * es_clients?: array, + * logger_channel?: scalar|null|Param, // Logger channel to be used for elasticsearch client logs // Default: "pimcore.elasticsearch.default" + * username?: scalar|null|Param, // Username for elasticsearch authentication + * password?: scalar|null|Param, // Password for elasticsearch authentication + * ca_bundle?: scalar|null|Param, // Path to certificate authority file (.crt) + * ssl_key?: scalar|null|Param, // Path to private SSL key file (.key) + * ssl_cert?: scalar|null|Param, // Path to PEM formatted SSL cert file (.cert) + * ssl_password?: scalar|null|Param, // If private key and certificate require a password (default: null) + * ssl_verification?: bool|Param, // Enable or disable the SSL verification (default: true) + * http_options?: list, + * cloud_id?: scalar|null|Param, // Elastic Cloud Id for elasticsearch cloud authentication + * api_key?: scalar|null|Param, // Elastic Cloud API key for elasticsearch cloud authentication + * }>, + * } + * @psalm-type MercureConfig = array{ + * hubs?: array, + * subscribe?: list, + * secret?: scalar|null|Param, // The JWT Secret to use. + * passphrase?: scalar|null|Param, // The JWT secret passphrase. // Default: "" + * algorithm?: scalar|null|Param, // The algorithm to use to sign the JWT // Default: "hmac.sha256" + * }, + * jwt_provider?: scalar|null|Param, // Deprecated: The child node "jwt_provider" at path "mercure.hubs..jwt_provider" is deprecated, use "jwt.provider" instead. // The ID of a service to call to generate the JSON Web Token. + * bus?: scalar|null|Param, // Name of the Messenger bus where the handler for this hub must be registered. Default to the default bus if Messenger is enabled. + * }>, + * default_hub?: scalar|null|Param, + * default_cookie_lifetime?: int|Param, // Default lifetime of the cookie containing the JWT, in seconds. Defaults to the value of "framework.session.cookie_lifetime". // Default: null + * enable_profiler?: bool|Param, // Deprecated: The child node "enable_profiler" at path "mercure.enable_profiler" is deprecated. // Enable Symfony Web Profiler integration. + * } + * @psalm-type WebpackEncoreConfig = array{ + * output_path: scalar|null|Param, // The path where Encore is building the assets - i.e. Encore.setOutputPath() + * crossorigin?: false|"anonymous"|"use-credentials"|Param, // crossorigin value when Encore.enableIntegrityHashes() is used, can be false (default), anonymous or use-credentials // Default: false + * preload?: bool|Param, // preload all rendered script and link tags automatically via the http2 Link header. // Default: false + * cache?: bool|Param, // Enable caching of the entry point file(s) // Default: false + * strict_mode?: bool|Param, // Throw an exception if the entrypoints.json file is missing or an entry is missing from the data // Default: true + * builds?: array, + * script_attributes?: array, + * link_attributes?: array, + * } + * @psalm-type KnpMenuConfig = array{ + * providers?: array{ + * builder_alias?: bool|Param, // Default: true + * }, + * twig?: array{ + * template?: scalar|null|Param, // Default: "@KnpMenu/menu.html.twig" + * }, + * templating?: bool|Param, // Default: false + * default_renderer?: scalar|null|Param, // Default: "twig" + * } + * @psalm-type PimcoreConfig = array{ + * bundles?: array{ // Define parameters for Pimcore Bundle Locator + * search_paths?: list, + * handle_composer?: bool|Param, // Define whether it should be scanning bundles through composer /vendor folder or not // Default: true + * }, + * flags?: list, + * translations?: array{ + * domains?: list, + * admin_translation_mapping?: array, + * debugging?: bool|array{ // If debugging is enabled, the translator will return the plain translation key instead of the translated message. + * enabled?: bool|Param, // Default: true + * parameter?: scalar|null|Param, // Default: "pimcore_debug_translations" + * }, + * }, + * maps?: array{ + * tile_layer_url_template?: scalar|null|Param, // Default: "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png" + * geocoding_url_template?: scalar|null|Param, // Default: "https://nominatim.openstreetmap.org/search?q={q}&addressdetails=1&format=json&limit=1" + * reverse_geocoding_url_template?: scalar|null|Param, // Default: "https://nominatim.openstreetmap.org/reverse?format=json&lat={lat}&lon={lon}&addressdetails=1" + * }, + * general?: array{ + * timezone?: scalar|null|Param, // Default: "" + * path_variable?: scalar|null|Param, // Additional $PATH variable (: separated) (/x/y:/foo/bar): // Default: null + * domain?: scalar|null|Param, // Default: "" + * redirect_to_maindomain?: bool|Param, // Default: false + * language?: scalar|null|Param, // Deprecated: The child node "language" at path "pimcore.general.language" is deprecated. // Default: "en" + * valid_languages?: list, + * required_languages?: list, + * fallback_languages?: list, + * default_language?: scalar|null|Param, // Default: "en" + * disable_usage_statistics?: bool|Param, // Default: false + * debug_admin_translations?: bool|Param, // Debug Admin-Translations (text in UI will be displayed wrapped in +) // Default: false + * }, + * maintenance?: array{ + * housekeeping?: array{ + * cleanup_tmp_files_atime_older_than?: int|Param, // Integer value in seconds. // Default: 86400 + * cleanup_profiler_files_atime_older_than?: int|Param, // Integer value in seconds. // Default: 1800 + * }, + * }, + * objects?: array{ + * ignore_localized_query_fallback?: bool|Param, // Default: false + * tree_paging_limit?: int|Param, // Default: 30 + * auto_save_interval?: int|Param, // Default: 60 + * versions?: array{ + * days?: scalar|null|Param, // Default: null + * steps?: scalar|null|Param, // Default: null + * disable_events?: bool|Param, // Default: false + * disable_stack_trace?: bool|Param, // Default: false + * }, + * custom_layouts?: array{ + * definitions?: list, + * }, + * select_options?: array{ + * definitions?: list, + * }>, + * }, + * class_definitions?: array{ + * data?: array{ + * map?: array, + * prefixes?: list, + * }, + * layout?: array{ + * map?: array, + * prefixes?: list, + * }, + * }, + * ... + * }, + * assets?: array{ + * thumbnails?: array{ + * allowed_formats?: list, + * max_scaling_factor?: float|Param, // Default: 5.0 + * }, + * frontend_prefixes?: array{ + * source?: scalar|null|Param, // Default: "" + * thumbnail?: scalar|null|Param, // Default: "" + * thumbnail_deferred?: scalar|null|Param, // Default: "" + * }, + * preview_image_thumbnail?: scalar|null|Param, // Default: null + * default_upload_path?: scalar|null|Param, // Default: "_default_upload_bucket" + * tree_paging_limit?: int|Param, // Default: 100 + * image?: array{ + * max_pixels?: int|Param, // Maximum number of pixels an image can have when added (width Γ— height). // Default: 40000000 + * low_quality_image_preview?: bool|array{ // Allow a LQIP SVG image to be generated alongside any other thumbnails. + * enabled?: bool|Param, // Default: true + * }, + * thumbnails?: array{ + * definitions?: list, + * }>, + * medias?: list, + * }>>, + * }>, + * clip_auto_support?: bool|Param, // Try to detect and use clipping paths and masks in images when generating thumbnails. // Default: true + * max_srcset_dpi_factor?: int|Param, // Maximum generated srcset DPI factor for web images. // Default: 2 + * image_optimizers?: bool|array{ + * enabled?: bool|Param, // Default: true + * }, + * auto_formats?: list, + * status_cache?: bool|Param, // Store image metadata such as filename and modification date in assets_image_thumbnail_cache, this is helpful when using remote object storage for thumbnails. // Default: true + * auto_clear_temp_files?: bool|Param, // Automatically delete all image thumbnail files any time an image or its metadata is updated. // Default: true + * }, + * }, + * video?: array{ + * thumbnails?: array{ + * definitions?: list, + * }>, + * medias?: list, + * }>>, + * }>, + * auto_clear_temp_files?: bool|Param, // Automatically delete all video thumbnail files any time an image or its metadata is updated. // Default: true + * }, + * }, + * document?: array{ + * thumbnails?: array{ + * enabled?: bool|Param, // Process thumbnails for Asset documents. // Default: true + * }, + * process_page_count?: bool|Param, // Process & store page count for Asset documents. Internally required for thumbnails & text generation // Default: true + * process_text?: bool|Param, // Process text for Asset documents (e.g. used by backend search). // Default: true + * scan_pdf?: bool|Param, // Scan PDF documents for unsafe JavaScript. // Default: true + * open_pdf_in_new_tab?: "all-pdfs"|"only-unsafe"|"none"|Param, // Default: "only-unsafe" + * }, + * versions?: array{ + * days?: scalar|null|Param, // Default: null + * steps?: scalar|null|Param, // Default: null + * disable_events?: bool|Param, // Default: false + * use_hardlinks?: bool|Param, // Default: true + * disable_stack_trace?: bool|Param, // Default: false + * }, + * icc_rgb_profile?: scalar|null|Param, // Absolute path to default ICC RGB profile (if no embedded profile is given) // Default: null + * icc_cmyk_profile?: scalar|null|Param, // Absolute path to default ICC CMYK profile (if no embedded profile is given) // Default: null + * metadata?: array{ + * alt?: scalar|null|Param, // Set to replace the default metadata used for auto alt functionality in frontend // Default: "" + * copyright?: scalar|null|Param, // Set to replace the default metadata used for copyright in frontend // Default: "" + * title?: scalar|null|Param, // Set to replace the default metadata used for title in frontend // Default: "" + * predefined?: array{ + * definitions?: list, + * }, + * class_definitions?: array{ + * data?: array{ + * map?: array, + * prefixes?: list, + * }, + * }, + * }, + * type_definitions?: array{ + * map?: list, + * }>, + * }, + * }, + * documents?: array{ + * doc_types?: array{ + * definitions?: list, + * }, + * versions?: array{ + * days?: scalar|null|Param, // Default: null + * steps?: scalar|null|Param, // Default: null + * disable_events?: bool|Param, // Default: false + * disable_stack_trace?: bool|Param, // Default: false + * }, + * default_controller?: scalar|null|Param, // Default: "App\\Controller\\DefaultController::defaultAction" + * error_pages?: array{ + * default?: scalar|null|Param, // Default: null + * localized?: list, + * }, + * allow_trailing_slash?: scalar|null|Param, // Default: "no" + * generate_preview?: bool|Param, // Default: false + * preview_url_prefix?: scalar|null|Param, // Default: "" + * tree_paging_limit?: int|Param, // Default: 50 + * editables?: array{ + * map?: array, + * prefixes?: list, + * }, + * areas?: array{ + * autoload?: bool|Param, // Default: true + * }, + * auto_save_interval?: int|Param, // Default: 60 + * static_page_router?: array{ + * enabled?: bool|Param, // Enable Static Page router for document when using remote storage for generated pages // Default: false + * route_pattern?: scalar|null|Param, // Optionally define route patterns to lookup static pages. Regular Expressions like: /^\/en\/Magazine/ // Default: null + * }, + * static_page_generator?: array{ + * use_main_domain?: bool|Param, // Use main domain for static pages folder in tmp/pages // Default: false + * headers?: list, + * }, + * type_definitions?: array{ + * map?: list, + * }, + * ... + * }, + * encryption?: array{ + * secret?: scalar|null|Param, // Default: null + * }, + * models?: array{ + * class_overrides?: array, + * }, + * routing?: array{ + * static?: array{ + * locale_params?: list, + * }, + * }, + * full_page_cache?: bool|array{ + * enabled?: bool|Param, // Default: true + * lifetime?: scalar|null|Param, // Optional output-cache lifetime (in seconds) after the cache expires, if not defined the cache will be cleaned on every action inside the CMS, otherwise not (for high traffic sites) // Default: null + * exclude_patterns?: scalar|null|Param, // Regular Expressions like: /^\/dir\/toexclude/ + * exclude_cookie?: scalar|null|Param, // Comma separated list of cookie names, that will automatically disable the full-page cache + * ... + * }, + * context?: array, + * }>, + * }>, + * web_profiler?: array{ + * toolbar?: array{ + * excluded_routes?: list, + * }>, + * }, + * }, + * security?: array{ + * password?: array{ + * algorithm?: "2y"|"argon2i"|"argon2id"|Param, // The hashing algorithm to use for backend users and objects containing a "password" field. // Default: "2y" + * options?: list, + * }, + * factory_type?: "encoder"|"password_hasher"|Param, // Default: "encoder" + * encoder_factories?: array, + * password_hasher_factories?: array, + * }, + * email?: array{ + * sender?: array{ + * name?: scalar|null|Param, // Default: "" + * email?: scalar|null|Param, // Default: "" + * }, + * return?: array{ + * name?: scalar|null|Param, // Default: "" + * email?: scalar|null|Param, // Default: "" + * }, + * debug?: array{ + * email_addresses?: scalar|null|Param, // Default: "" + * }, + * usespecific?: scalar|null|Param, // Default: false + * }, + * workflows?: array, + * custom_extensions?: array, + * enabled?: bool|Param, // Can be used to enable or disable the workflow. // Default: true + * priority?: int|Param, // When multiple custom view or permission settings from different places in different workflows are valid, the workflow with the highest priority will be used. // Default: 0 + * label?: scalar|null|Param, // Will be used in the backend interface as nice name for the workflow. If not set the technical workflow name will be used as label too. + * audit_trail?: bool|array{ // Enable default audit trail feature provided by Symfony. Take a look at the Symfony docs for more details. + * enabled?: bool|Param, // Default: false + * }, + * type?: "workflow"|"state_machine"|Param, // A workflow with type "workflow" can handle multiple places at one time whereas a state_machine provides a finite state_machine (only one place at one time). Take a look at the Symfony docs for more details. + * marking_store?: array{ // Handles the way how the state/place is stored. If not defined "state_table" will be used as default. Take a look at @TODO for a description of the different types. + * type?: "multiple_state"|"single_state"|"state_table"|"data_object_multiple_state"|"data_object_splitted_state"|Param, + * arguments?: list, + * service?: scalar|null|Param, + * }, + * supports?: list, + * support_strategy?: array{ // Can be used to implement a special logic which subjects are supported by the workflow. For example only products matching certain criteria. + * type?: "expression"|Param, // Type "expression": a symfony expression to define a criteria. + * arguments?: list, + * service?: scalar|null|Param, // Define a custom service to handle the logic. Take a look at the Symfony docs for more details. + * }, + * initial_markings?: list, + * places?: list