diff --git a/.gitbook.yaml b/.gitbook.yaml index 2ca045364a..12d6ee41e3 100644 --- a/.gitbook.yaml +++ b/.gitbook.yaml @@ -19,6 +19,37 @@ redirects: resources/references/api-reference/admin-api-reference.html: guides/integrations-api/ concepts/extensions/elasticsearch-concept.html: concepts/framework/elasticsearch.html guides/plugins/plugins/storefront/use-csrf-protection.html: guides/hosting/configurations/framework/samesite-protection.html + guides/plugins/plugins/storefront/add-caching-to-custom-controller.html: guides/plugins/plugins/storefront/advanced/add-caching-to-custom-controller.html + guides/plugins/plugins/storefront/add-cookie-to-manager.html: guides/plugins/plugins/storefront/advanced/add-cookie-to-manager.html + guides/plugins/plugins/storefront/add-custom-assets.html: guides/plugins/plugins/storefront/styling/add-custom-assets.html + guides/plugins/plugins/storefront/add-custom-captcha.html: guides/plugins/plugins/storefront/howto/add-custom-captcha.html + guides/plugins/plugins/storefront/add-custom-controller.html: guides/plugins/plugins/storefront/controllers/add-custom-controller.html + guides/plugins/plugins/storefront/add-custom-javascript.html: guides/plugins/plugins/storefront/javascript/add-custom-javascript.html + guides/plugins/plugins/storefront/add-custom-page.html: guides/plugins/plugins/storefront/controllers/add-custom-page.html + guides/plugins/plugins/storefront/add-custom-pagelet.html: guides/plugins/plugins/storefront/controllers/add-custom-pagelet.html + guides/plugins/plugins/storefront/add-custom-sorting-product-listing.html: guides/plugins/plugins/storefront/howto/add-custom-sorting-product-listing.html + guides/plugins/plugins/storefront/add-custom-styling.html: guides/plugins/plugins/storefront/styling/add-custom-styling.html + guides/plugins/plugins/storefront/add-custom-twig-function.html: guides/plugins/plugins/storefront/templates/add-custom-twig-function.html + guides/plugins/plugins/storefront/add-data-to-storefront-page.html: guides/plugins/plugins/storefront/controllers/add-data-to-storefront-page.html + guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.html: guides/plugins/plugins/storefront/controllers/add-dynamic-content-via-ajax-calls.html + guides/plugins/plugins/storefront/add-icons.html: guides/plugins/plugins/storefront/styling/add-icons.html + guides/plugins/plugins/storefront/add-javascript-as-script-tag.html: guides/plugins/plugins/storefront/javascript/add-javascript-as-script-tag.html + guides/plugins/plugins/storefront/add-listing-filters.html: guides/plugins/plugins/storefront/howto/add-listing-filters.html + guides/plugins/plugins/storefront/add-scss-variables-via-subscriber.html: guides/plugins/plugins/storefront/styling/add-scss-variables-via-subscriber.html + guides/plugins/plugins/storefront/add-scss-variables.html: guides/plugins/plugins/storefront/styling/add-scss-variables.html + guides/plugins/plugins/storefront/add-translations.html: guides/plugins/plugins/storefront/styling/add-translations.html + guides/plugins/plugins/storefront/customize-header-footer.html: guides/plugins/plugins/storefront/templates/customize-header-footer.html + guides/plugins/plugins/storefront/customize-templates.html: guides/plugins/plugins/storefront/templates/customize-templates.html + guides/plugins/plugins/storefront/fetching-data-with-javascript.html: guides/plugins/plugins/storefront/javascript/fetching-data-with-javascript.html + guides/plugins/plugins/storefront/override-existing-javascript.html: guides/plugins/plugins/storefront/javascript/override-existing-javascript.html + guides/plugins/plugins/storefront/reacting-to-cookie-consent-changes.html: guides/plugins/plugins/storefront/advanced/reacting-to-cookie-consent-changes.html + guides/plugins/plugins/storefront/reacting-to-javascript-events.html: guides/plugins/plugins/storefront/javascript/reacting-to-javascript-events.html + guides/plugins/plugins/storefront/remove-unnecessary-js-plugin.html: guides/plugins/plugins/storefront/advanced/remove-unnecessary-js-plugin.html + guides/plugins/plugins/storefront/use-media-thumbnails.html: guides/plugins/plugins/storefront/howto/use-media-thumbnails.html + guides/plugins/plugins/storefront/use-nested-line-items.html: guides/plugins/plugins/storefront/howto/use-nested-line-items.html + guides/plugins/plugins/storefront/using-a-modal-window.html: guides/plugins/plugins/storefront/howto/using-a-modal-window.html + guides/plugins/plugins/storefront/using-custom-fields-storefront.html: guides/plugins/plugins/storefront/howto/using-custom-fields-storefront.html + guides/plugins/plugins/storefront/using-the-datepicker-plugin.html: guides/plugins/plugins/storefront/howto/using-the-datepicker-plugin.html products/extensions/b2b-suite/*: products/extensions/b2b/b2b-suite/* products/extensions/b2b-components/*: products/extensions/b2b/b2b-components/* guides/plugins/plugins/administration/add-shortcuts.html: guides/plugins/plugins/administration/advanced-configuration/add-shortcuts.html @@ -68,6 +99,27 @@ redirects: products/paas/fastly.html: products/paas/shopware-paas/fastly.html products/paas/blackfire.html: products/paas/shopware-paas/blackfire.html guides/plugins/apps/in-app-purchase/: guides/plugins/apps/in-app-purchases.html + guides/plugins/apps/app-registration-setup.html: guides/plugins/apps/lifecycle/app-registration-setup.html + guides/plugins/apps/app-signature-verification.html: guides/plugins/apps/lifecycle/app-signature-verification.html + guides/plugins/apps/clientside-to-app-backend.html: guides/plugins/apps/lifecycle/clientside-to-app-backend.html + guides/plugins/apps/configuration.html: guides/plugins/apps/lifecycle/configuration.html + guides/plugins/apps/payment.html: guides/plugins/apps/checkout/payment.html + guides/plugins/apps/shipping-methods.html: guides/plugins/apps/checkout/shipping-methods.html + guides/plugins/apps/starter/add-api-endpoint.html: guides/plugins/apps/app-scripts/add-api-endpoint.html + guides/plugins/apps/starter/index.html: guides/plugins/apps/index.html + guides/plugins/apps/starter/product-translator.html: guides/plugins/apps/lifecycle/product-translator.html + guides/plugins/apps/starter/starter-admin-extension.html: guides/plugins/apps/administration/starter-admin-extension.html + guides/plugins/apps/tax-provider.html: guides/plugins/apps/checkout/tax-provider.html + guides/plugins/apps/webhook.html: guides/plugins/apps/lifecycle/webhook.html + guides/plugins/plugins/plugin-fundamentals/add-custom-service.html: guides/plugins/plugins/services/add-custom-service.html + guides/plugins/plugins/plugin-fundamentals/add-plugin-dependencies.html: guides/plugins/plugins/dependencies/add-plugin-dependencies.html + guides/plugins/plugins/plugin-fundamentals/adjusting-service.html: guides/plugins/plugins/services/adjusting-service.html + guides/plugins/plugins/plugin-fundamentals/custom-fields-of-type-media.html: guides/plugins/plugins/database/custom-fields-of-type-media.html + guides/plugins/plugins/plugin-fundamentals/database-migrations.html: guides/plugins/plugins/database/database-migrations.html + guides/plugins/plugins/plugin-fundamentals/dependency-injection.html: guides/plugins/plugins/services/dependency-injection.html + guides/plugins/plugins/plugin-fundamentals/listening-to-events.html: guides/plugins/plugins/framework/event/listening-to-events.html + guides/plugins/plugins/plugin-fundamentals/using-composer-dependencies.html: guides/plugins/plugins/dependencies/using-composer-dependencies.html + guides/plugins/plugins/plugin-fundamentals/using-npm-dependencies.html: guides/plugins/plugins/dependencies/using-npm-dependencies.html guides/plugins/plugins/in-app-purchase/: guides/plugins/plugins/in-app-purchases.html products/paas/shopware/CLI/account.html: products/paas/shopware/fundamentals/account.html products/paas/shopware/CLI/applications.html: products/paas/shopware/fundamentals/applications.html @@ -110,6 +162,8 @@ redirects: resources/references/upgrades/core/translation/language-pack-migration.html: guides/upgrades-migrations/language-pack-migration.html resources/references/upgrades/administration/: guides/upgrades-migrations/administration/ resources/references/upgrades/: guides/upgrades-migrations/ + resources/references/storefront-reference/plugin-reference.html: guides/plugins/plugins/storefront/javascript/plugin-reference.html + resources/references/storefront-reference/twig-function-reference.html: guides/plugins/plugins/storefront/templates/twig-function-reference.html guides/plugins/plugins/testing/php-unit.html: guides/development/testing/unit/php-unit.html guides/plugins/plugins/testing/jest-storefront.html: guides/development/testing/unit/jest-storefront.html guides/plugins/plugins/testing/jest-admin.html: guides/development/testing/unit/jest-admin.html @@ -145,6 +199,7 @@ redirects: guides/plugins/plugins/testing/cypress/cypress-best-practises.html: guides/development/testing/legacy/cypress/cypress-best-practises.html guides/plugins/plugins/testing/cypress/cypress-end-to-end-testing/: guides/development/testing/legacy/cypress/ guides/resources/references/core-reference/dal-reference/filters-reference.html: resources/references/core-reference/dal-reference/filters-reference.html + resources/guidelines/code/core/database-migations.html: resources/guidelines/code/core/database-migrations.html resources/guidelines/code/core/final-and-internal.html: guides/development/extensions/architecture/final-and-internal.html resources/guidelines/code/core/internal.html: guides/development/extensions/architecture/internal.html resources/guidelines/code/core/extendability.html: guides/development/extensions/architecture/extendability.html diff --git a/concepts/commerce/content/cookie-consent-management.md b/concepts/commerce/content/cookie-consent-management.md index b4601176c3..82b98ad7a9 100644 --- a/concepts/commerce/content/cookie-consent-management.md +++ b/concepts/commerce/content/cookie-consent-management.md @@ -197,7 +197,7 @@ The cookie consent system can be extended in multiple ways: Use an event listener to add custom cookies. - + ### For Apps @@ -209,7 +209,7 @@ Define cookies in your `manifest.xml` file. React to user consent changes in your custom JavaScript. - + ## Best Practices diff --git a/concepts/extensions/apps-concept.md b/concepts/extensions/apps-concept.md index e14340f800..a3ce044110 100644 --- a/concepts/extensions/apps-concept.md +++ b/concepts/extensions/apps-concept.md @@ -22,7 +22,7 @@ Shopware communicates with your app exclusively via HTTP requests. Therefore, yo ![Communication between Shopware and your app](../../assets/extensions-apps-shopwareCommunication.svg) -To secure this communication, a registration handshake is performed during the installation of your app. During this registration, it is verified that Shopware talks to the right app backend server, and your app gets credentials used to authenticate against the API. See [App registration & backend setup](../../guides/plugins/apps/app-registration-setup.md). +To secure this communication, a registration handshake is performed during the installation of your app. During this registration, it is verified that Shopware talks to the right app backend server, and your app gets credentials used to authenticate against the API. See [App registration & backend setup](../../guides/plugins/apps/lifecycle/app-registration-setup.md). ::: info Note that this is optional if Shopware and your app don't need to communicate, e.g., because your app provides a [Theme](../../guides/plugins/themes/index.md). @@ -38,7 +38,7 @@ Your app can modify the Storefront's appearance by shipping your Storefront asse This functionality is available starting with Shopware 6.4.1.0. ::: -Shopware provides functionality that allows your app to integrate payment providers. You can use synchronous payments with providers that do not require user interaction; in that case, approval can be requested with a simple background request. You can use asynchronous payments if you want to redirect the user to a payment provider. Your app then provides a URL for redirection. After the user returns to the shop, Shopware will verify the payment status with your app. Find out more about providing payment endpoints in the [App payment guide](../../guides/plugins/apps/payment.md). +Shopware provides functionality that allows your app to integrate payment providers. You can use synchronous payments with providers that do not require user interaction; in that case, approval can be requested with a simple background request. You can use asynchronous payments if you want to redirect the user to a payment provider. Your app then provides a URL for redirection. After the user returns to the shop, Shopware will verify the payment status with your app. Find out more about providing payment endpoints in the [App payment guide](../../guides/plugins/apps/checkout/payment.md). ## Execute business logic inside Shopware with App Scripts diff --git a/concepts/framework/data-abstraction-layer.md b/concepts/framework/data-abstraction-layer.md index ef21cb43ab..3435e5e93e 100644 --- a/concepts/framework/data-abstraction-layer.md +++ b/concepts/framework/data-abstraction-layer.md @@ -32,7 +32,7 @@ This is the recommended way for developers to interface with the DAL or the data ### Provisioning code to use the repositories -Before using the repositories, you will need to get them from the [Dependency Injection Container (DIC)](../../guides/plugins/plugins/plugin-fundamentals/dependency-injection). +Before using the repositories, you will need to get them from the [Dependency Injection Container (DIC)](../../guides/plugins/plugins/services/dependency-injection.md). This is done with [Constructor injection](https://symfony.com/doc/current/service_container/injection_types.html#constructor-injection), so you will need to extend your services constructor by expecting an EntityRepository: ```php @@ -55,7 +55,7 @@ $services->set(Swag\ExamplePlugin\Service\DalExampleService::class) You can read more about dependency injection and service registration in Shopware in the services guides: - + ### Translations diff --git a/concepts/framework/migrations.md b/concepts/framework/migrations.md index 5f7b23dce5..2b35a6dbf6 100644 --- a/concepts/framework/migrations.md +++ b/concepts/framework/migrations.md @@ -15,10 +15,8 @@ For Shopware to recognize additional plugin migrations, they need to be placed i Each migration filename follows a specific pattern. To ease plugin development, Shopware provides a console command which can be used to generate a correctly named migration file with the default methods needed. - - ## Modifying the database Each migration can have two methods. The `update` and `updateDestructive`. The `update` method must contain only non-destructive changes which can be rolled back at any time. The `updateDestructive` method can contain destructive changes, like dropping columns or tables, which cannot be reversed. For examples of database migrations, refer to the below guide: - + diff --git a/guides/development/extensions/architecture/extendability.md b/guides/development/extensions/architecture/extendability.md index c9e9e8af2d..d4cb68a088 100644 --- a/guides/development/extensions/architecture/extendability.md +++ b/guides/development/extensions/architecture/extendability.md @@ -90,7 +90,7 @@ The best-known example is the [`checkout.order.placed`](https://github.com/shopw #### Hooks -Hooks are another good example of the observer pattern. Hooks are entry points for apps where the so-called [**App scripts**](/docs/guides/plugins/apps/app-scripts/) are enabled. Since apps do not have the permission to execute code on the server directly, hooks are a way to execute more complex business logic within the request without having to address the own app server via HTTP. Hooks are the equivalent of **events**. +Hooks are another good example of the observer pattern. Hooks are entry points for apps where the so-called [**App scripts**](../../../plugins/apps/app-scripts/index.md) are enabled. Since apps do not have the permission to execute code on the server directly, hooks are a way to execute more complex business logic within the request without having to address the own app server via HTTP. Hooks are the equivalent of **events**. One of the best-known hooks is the [`product page loaded hook`](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Storefront/Page/Product/ProductPageLoadedHook.php). This hook allows apps to load additional data on the product detail page. The hook is instantiated and dispatched [at the controller level](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Storefront/Controller/ProductController.php#L100). Each app script registered to the hook is executed. diff --git a/guides/development/monetization/quality-guidelines.md b/guides/development/monetization/quality-guidelines.md index 09b523c6ee..23486595ce 100644 --- a/guides/development/monetization/quality-guidelines.md +++ b/guides/development/monetization/quality-guidelines.md @@ -36,7 +36,7 @@ For apps, we additionally test: Before publishing an extension, review the full test process to ensure fast approval. ::: info -[Test your app for the Shopware Store (DE):](https://www.youtube.com/watch?v=gLb5CmOdi4g); EN version is coming soon. +[Test your app for the Shopware Store (DE):](https://www.youtube.com/watch?v=gLb5CmOdi4g); EN version is coming soon. ::: ## Store listing requirements @@ -158,7 +158,7 @@ All extensions must: * Be installable and uninstallable without issues. * During uninstall, users must be able to choose in the Extension Manager whether to "completely delete or "keep the app data, text snippets, media folder, including own media and table adjustments." The free [Adminer](https://store.shopware.com/en/frosh79014577529f/adminer-for-admin.html) extension from Friends of Shopware enables you to do this via your provided test environment. * Avoid extending or overwriting the Extension Manager. -* Properly register cookies in the [Cookie Consent Manager](../../../guides/plugins/plugins/storefront/add-cookie-to-manager). +* Properly register cookies in the [Cookie Consent Manager](../../../guides/plugins/plugins/storefront/advanced/add-cookie-to-manager.md). * Every cookie set from the store URL should be optional and not technically required for running Shopware. We differentiate between "Technically required", "Marketing," and "Comfort features." * All cookies must appear (unchecked) in the cookie configuration box in the frontend. * Do not introduce severe performance regressions. @@ -170,7 +170,7 @@ All extensions must: These apply only to plugins: -* [Composer dependencies](../../../guides/plugins/plugins/plugin-fundamentals/using-composer-dependencies) must be declared in `composer.json` so they are traceable. +* [Composer dependencies](../../../guides/plugins/plugins/dependencies/using-composer-dependencies.md) must be declared in `composer.json` so they are traceable. * If `executeComposerCommands() === true` is used, dependencies are installed dynamically and do not need to be bundled. * `composer.lock` must not be included in the archive. * Deliver uncompiled (readable) JavaScript in addition to compiled assets. Uncompiled sources must be included in a separate folder to allow code review. @@ -207,7 +207,7 @@ If the extension includes Composer dependencies: ## Storefront guidelines -* No inline CSS allowed in storefront templates. Use your own classes and let your CSS be compiled by the plugin. See [Add SCSS variables](../../../guides/plugins/plugins/storefront/add-scss-variables.md#add-scss-variables). +* No inline CSS allowed in storefront templates. Use your own classes and let your CSS be compiled by the plugin. See [Add SCSS variables](../../../guides/plugins/plugins/storefront/styling/add-scss-variables.md#add-scss-variables). * Avoid using the `!important` rule unless unavoidable. * All images must include meaningful `alt` tags, or original `alt` tags from the media manager. * All links must include meaningful `title` tags. @@ -312,7 +312,7 @@ Use Scheme.org's [Schema Markup Validator](https://validator.schema.org/) and Go ## Tools -Use the [Shopware CLI](/development/tooling/cli) to build, validate, and upload Shopware 6 plugin releases to the Community Store. It also supports efficiently managing store descriptions and plugin images. +Use the [Shopware CLI](../../../products/cli/index.md) to build, validate, and upload Shopware 6 plugin releases to the Community Store. It also supports efficiently managing store descriptions and plugin images. ## Final notes diff --git a/guides/development/testing/ci.md b/guides/development/testing/ci.md index 6c60684adf..55335a1081 100644 --- a/guides/development/testing/ci.md +++ b/guides/development/testing/ci.md @@ -30,6 +30,6 @@ Follow the [Deployment guide](../../hosting/installation-updates/deployments/ind ## Custom/Store plugins -* Build and validate with `shopware-cli extension build` ([Extension build command](../../products/cli/extension-commands/build.md)) to ensure the ZIP is reproducible. +* Build and validate with `shopware-cli extension build` ([Extension build command](../../../products/cli/extension-commands/build.md) to ensure the ZIP is reproducible. * Run unit/integration tests with the Shopware test environment; keep fixtures inside the plugin to avoid coupling to project data. * For Store plugins, add the Shopware Store validations early (linting, metadata, PHPStan) to catch review issues before submission ([Store submission via CLI](../../../products/cli/shopware-account-commands/releasing-extension-to-shopware-store.md)). diff --git a/guides/development/testing/unit/jest-storefront.md b/guides/development/testing/unit/jest-storefront.md index ef04b67296..887c54698d 100644 --- a/guides/development/testing/unit/jest-storefront.md +++ b/guides/development/testing/unit/jest-storefront.md @@ -23,7 +23,7 @@ Before you read this guide, make sure you understand the basics of unit testing In addition, you need a running Shopware 6 installation. Your repository for that should be based on the development template, as we will use some scripts provided by it. -For one example, we use a Javascript plugin. To follow this example, you need to know how to build a Javascript plugin in the first place. You can learn about it in the corresponding [guide](../../../plugins/plugins/storefront/add-custom-javascript.md). +For one example, we use a Javascript plugin. To follow this example, you need to know how to build a Javascript plugin in the first place. You can learn about it in the corresponding [guide](../../../plugins/plugins/storefront/javascript/add-custom-javascript.md). ## Test structure @@ -182,7 +182,7 @@ export default class HelloWorldPlugin extends Plugin { } ``` -Of course, you need to make sure your plugin is registered. For more details, see the guide on [Javascript plugins](../../../plugins/plugins/storefront/add-custom-javascript.md). +Of course, you need to make sure your plugin is registered. For more details, see the guide on [Javascript plugins](../../../plugins/plugins/storefront/javascript/add-custom-javascript.md). In the beginning, writing plugin tests is still similar to other Jest unit tests: You import your plugin's class and use the familiar test structure: diff --git a/guides/development/testing/unit/php-unit.md b/guides/development/testing/unit/php-unit.md index 2e3edfc945..7b1154bdf6 100644 --- a/guides/development/testing/unit/php-unit.md +++ b/guides/development/testing/unit/php-unit.md @@ -1,6 +1,6 @@ --- nav: - title: PHP unit testing + title: PHP Unit Testing position: 40 --- @@ -13,7 +13,7 @@ This guide covers creating PHPUnit tests in Shopware 6. Refer to the [official P To create tests for a plugin, you need a plugin as a base. Refer to the [Plugin Base Guide](../../../plugins/plugins/plugin-base-guide.md) for more information. -Furthermore, refer to [migrations](../../../plugins/plugins/plugin-fundamentals/database-migrations.md) guide to create a migration test for these examples. +Furthermore, refer to [migrations](../../../plugins/plugins/database/database-migrations.md) guide to create a migration test for these examples. ## PHPUnit configuration @@ -173,7 +173,7 @@ class Migration1611740369ExampleDescriptionTest extends TestCase ## Mocking services -In some cases, a service should behave differently in a test run. Such a case could be where a service deletes a file or makes a critical api call. To avoid this in a test run, you can create a `/Resources/config/services_test.{xml|yml}` file that overrides your `/Resources/config/services.{xml|yml}`. But only for the test environment. +In some cases, a service should behave differently in a test run. Such a case could be where a service deletes a file or makes a critical API call. To avoid this in a test run, you can create a `/Resources/config/services_test.{xml|yml}` file that overrides your `/Resources/config/services.{xml|yml}`. But only for the test environment. In this test-only service config, you can override arguments, aliases, or parameters to change what the service container injects into services during a test run. diff --git a/guides/plugins/apps/administration/add-cms-element-via-admin-sdk.md b/guides/plugins/apps/administration/add-cms-element-via-admin-sdk.md index 8d8889388b..126fc9c59f 100644 --- a/guides/plugins/apps/administration/add-cms-element-via-admin-sdk.md +++ b/guides/plugins/apps/administration/add-cms-element-via-admin-sdk.md @@ -7,15 +7,13 @@ nav: # Add CMS Element -## Overview - This guide explains how to create a new CMS element using the Meteor Admin SDK. The example plugin is named `SwagBasicAppCmsElementExample`, following the naming conventions used in other guides. ## Prerequisites -* Familiarity with creating [Plugins](../../plugins/plugin-base-guide) or [Apps](../app-base-guide) -* Familiarity with [creating custom admin components](../../plugins/administration/module-component-management/add-custom-component#creating-a-custom-component) +* Familiarity with creating [Plugins](../../plugins/plugin-base-guide.md) or [Apps](../app-base-guide.md) +* Familiarity with [creating custom admin components](../../plugins/administration/module-component-management/add-custom-component.md#creating-a-custom-component) * Understanding of the [Meteor Admin SDK](/resources/admin-extension-sdk/getting-started/installation) ::: info @@ -24,8 +22,7 @@ This example uses TypeScript, which is recommended but not required to develop S ## Creating your custom element -Similar to [creating a new custom element via plugin](../../plugins/content/cms/add-cms-element#creating-your-custom-element), this guide describes how to create a new -custom element via an app. Creating a new element requires the Meteor Admin SDK. +Similar to [creating a new custom element via plugin](../../plugins/content/cms/add-cms-element.md), this guide describes how to create a new custom element via an app. Creating a new element requires the Meteor Admin SDK. In this example, you will build a scenario where a shop manager can configure a link to display a Dailymotion video. diff --git a/guides/plugins/apps/administration/add-custom-action-button.md b/guides/plugins/apps/administration/add-custom-action-button.md index 843d552081..4f9b790a51 100644 --- a/guides/plugins/apps/administration/add-custom-action-button.md +++ b/guides/plugins/apps/administration/add-custom-action-button.md @@ -49,9 +49,9 @@ An action button must have the following attributes: * `action`: Unique identifier for the action, can be set freely. * `entity`: Here you define which entity you're working on. -* `view`: `detail`or `list`; to set the view the button should be added to. Currently, you can choose between detail and listing view. +* `view`: `detail`or `list`; to set the view the button should be added to. Currently, you can choose between detail and listing view. -When the user clicks on the action button your app receives a request similar to the one generated by a [webhook](../webhook.md). +When the user clicks on the action button your app receives a request similar to the one generated by a [webhook](../lifecycle/webhook.md). The main difference is that it contains the name of the entity and an array of ids that the user selected \(or an array containing only a single id if the action button was executed on a detail page\). A sample payload may look like the following: @@ -126,7 +126,7 @@ class ActionButtonController { Starting from Shopware version 6.4.1.0, the current shopware version will be sent as a `sw-version` header. ::: -Again you can verify the authenticity of the incoming request, like with [webhooks](../webhook.md), by checking the `shopware-shop-signature`. It also contains the SHA256 HMAC of the request body, that is signed with the secret your app assigned the shop during the [registration](../app-registration-setup.md#setup). +Again you can verify the authenticity of the incoming request, like with [webhooks](../lifecycle/webhook.md), by checking the `shopware-shop-signature`. It also contains the SHA256 HMAC of the request body, that is signed with the secret your app assigned the shop during the [registration](../lifecycle/app-registration-setup.md#setup). ## Providing feedback in the Administration diff --git a/guides/plugins/apps/administration/add-custom-modules.md b/guides/plugins/apps/administration/add-custom-modules.md index 8cd504b1ce..26833115a5 100644 --- a/guides/plugins/apps/administration/add-custom-modules.md +++ b/guides/plugins/apps/administration/add-custom-modules.md @@ -77,7 +77,7 @@ A sample request may look like this: https://example.com/promotion/view/promotion-config?shop-id=HKTOOpH9nUQ2&shop-url=http%3A%2F%2Fmy.shop.com×tamp=1592406102&shopware-shop-signature=3621fffa80187f6d43ce6cb25760340ab9ba2ea2f601e6a78a002e601579f415 ``` -In this case the `shopware-shop-signature` parameter contains an SHA256 HMAC of the rest of the query string, signed again with the secret your app assigned the shop during the [registration](../app-registration-setup.md#setup). The signature can be used to verify the authenticity of the request. +In this case the `shopware-shop-signature` parameter contains an SHA256 HMAC of the rest of the query string, signed again with the secret your app assigned the shop during the [registration](../lifecycle/app-registration-setup.md#setup). The signature can be used to verify the authenticity of the request. diff --git a/guides/plugins/apps/administration/adding-snippets.md b/guides/plugins/apps/administration/adding-snippets.md index 18cb02f7b3..75dc0e2a37 100644 --- a/guides/plugins/apps/administration/adding-snippets.md +++ b/guides/plugins/apps/administration/adding-snippets.md @@ -1,12 +1,13 @@ --- nav: - title: Add translations for apps + title: Adding Translations position: 30 --- -# Adding translations for apps +# Adding Translations + +Adding snippets to the Administration works the same way for plugins and apps. The only difference is the file structure and that apps are not allowed to override existing snippet keys. The only thing to do, therefore, is to create new files in the following directory: `/Resources/app/administration/snippet`. -Adding snippets to the administration works the same way for plugins and apps. The only difference is the file structure and that apps are not allowed to override existing snippet keys. The only thing to do, therefore, is to create new files in the following directory: `/Resources/app/administration/snippet` Additionally, you need JSON files for each language you want to support, using the respective language locale (e.g., `de.json`, `en.json`). You can also include patch files for dialects, such as `en-US.json`, to provide country-specific translations. For more details on selecting a fallback language and structuring your snippet files, see the [Fallback Languages guide](../../../../concepts/translations/fallback-language-selection.md). diff --git a/guides/plugins/apps/starter/starter-admin-extension.md b/guides/plugins/apps/administration/starter-admin-extension.md similarity index 80% rename from guides/plugins/apps/starter/starter-admin-extension.md rename to guides/plugins/apps/administration/starter-admin-extension.md index 74427e7ef2..3709e336d7 100644 --- a/guides/plugins/apps/starter/starter-admin-extension.md +++ b/guides/plugins/apps/administration/starter-admin-extension.md @@ -1,13 +1,13 @@ --- nav: - title: Starter Guide - Create Admin Extensions + title: Create Admin Extensions position: 30 --- -# Starter Guide - Create an Admin Extension +# Create an Admin Extension -In this guide, you will learn how to set up an extension for the Administration UI. +This guide explains how to set up an extension for the Administration UI. ![An admin notification](../../../../assets/extension-api-notification.png) @@ -18,16 +18,16 @@ In order to follow this guide, make sure you are familiar with and meet the foll * Basic CLI usage (creating files, directories, running commands) * Installed [shopware-cli](../../../../products/cli/) tools * We will use the following libraries/software - * npm - * live-server (small local development live-reloading server) + * npm + * live-server (small local development live-reloading server) ## Create the app wrapper -First of all, we need to create the app "wrapper", the so-called app manifest. It is just a single XML file with some basic configuration. +Create the app "wrapper", the so-called app manifest. It is just a single XML file with some basic configuration. ### Create manifest file -First of all, we create the manifest file in a new directory. We'll call that our "project directory". +Create the manifest file in a new directory. We'll call it our "project directory": ```text SimpleNotification/ @@ -35,10 +35,10 @@ SimpleNotification/ ``` ::: info -When you are using a self-hosted Shopware version, you can also create the project directory in the `custom/apps` directory of your Shopware installation. However, the descriptions in this guide apply to both Shopware cloud and self-hosted stores. +When using a self-hosted Shopware version, you can create the project directory in the `custom/apps` directory of your Shopware installation. However, the descriptions in this guide apply to both Shopware cloud and self-hosted stores. ::: -Next, we will put our basic configuration into the file we just created. +Next, add the basic configuration to the file: ::: code-group @@ -155,10 +155,10 @@ This command will create a zip file from the specified extension directory and u The `--increase-version` parameter increases the version specified in the `manifest.xml` file. This flag is required so Shopware picks up changes made to the `manifest.xml` since the last installation. When the app is successfully installed, you will see the notification pop up once you open the Shopware admin panel - congratulations! -## Where to continue +## Next steps This example showed end-to-end how to create a local dev environment and connect it with your Shopware Store. There is a lot more to learn and try out, so why not move on with one of those topics: -* Did you know, you can add [new sections](/resources/admin-extension-sdk/api-reference/ui/component-section) to the UI or even [entire modules](/resources/admin-extension-sdk/api-reference/ui/mainModule)? -* The Meteor Admin SDK also offers [TypeScript support](/resources/admin-extension-sdk/getting-started/installation#using-npm-require-bundling) (including autocompletion) -* Don't want to extend the admin panel? Have a look at [App Scripts](../../../../guides/plugins/apps/app-scripts/index.md) +* Add [new sections](../../../../resources/admin-extension-sdk/api-reference/ui/component-section) or [entire modules](../../../../resources/admin-extension-sdk/api-reference/ui/mainModule) to the UI +* The Meteor Admin SDK also offers [TypeScript support](../../../../resources/admin-extension-sdk/getting-started/installation#using-npm-require-bundling), including autocompletion +* Don't want to extend the admin panel? Have a look at [App Scripts](../app-scripts/index.md) diff --git a/guides/plugins/apps/app-base-guide.md b/guides/plugins/apps/app-base-guide.md index 57cc87211a..a8aae09a3c 100644 --- a/guides/plugins/apps/app-base-guide.md +++ b/guides/plugins/apps/app-base-guide.md @@ -18,7 +18,7 @@ There are multiple ways to begin building a Shopware app, but not all of them fi From there, continue with the path that matches your goal: -- **Apps requiring a backend:** apps that need registration, authenticated server-to-server communication, webhooks, signing, Admin API credentials and permissions, payment methods, tax providers, or other backend-driven features. See [App registration & backend setup](app-registration-setup.md) after you have a valid manifest. +- **Apps requiring a backend:** apps that need registration, authenticated server-to-server communication, webhooks, signing, Admin API credentials and permissions, payment methods, tax providers, or other backend-driven features. See [App registration & backend setup](../apps/lifecycle/app-registration-setup.md) after you have a valid manifest. - **Admin UI apps:** apps whose immediate goal is to add an Administration UI and iterate locally first with Vite and [Admin Extension SDK](https://www.npmjs.com/package/@shopware-ag/admin-extension-sdk). No app backend is required to see a module in the Administration. Continue with [Build an Admin UI app](create-admin-extension.md). ## Prerequisites @@ -115,4 +115,4 @@ bin/console cache:clear If needed, also run `bin/console cache:clear:http` or `bin/console cache:clear:all`. -Apps are [validated](app-registration-setup.md#validation) during installation. To skip validation only while debugging, use `--no-validate` with `app:install`. Run `bin/console app:validate` to identify configuration issues. +Apps are [validated](./lifecycle/app-registration-setup.md#validation) during installation. To skip validation only while debugging, use `--no-validate` with `app:install`. Run `bin/console app:validate` to identify configuration issues. diff --git a/guides/plugins/apps/starter/add-api-endpoint.md b/guides/plugins/apps/app-scripts/add-api-endpoint.md similarity index 98% rename from guides/plugins/apps/starter/add-api-endpoint.md rename to guides/plugins/apps/app-scripts/add-api-endpoint.md index 8b116596e0..64ea8e4318 100644 --- a/guides/plugins/apps/starter/add-api-endpoint.md +++ b/guides/plugins/apps/app-scripts/add-api-endpoint.md @@ -225,7 +225,7 @@ Ultimately, it gives a result of all products that have been ordered and the tot ::: info To learn more about the structure of search criteria, follow the link below: -[Search Criteria](./../../../integrations-api/general-concepts/search-criteria) +[Search Criteria](../../../development/integrations-api/search-criteria.md) ::: We now send a request to the database to retrieve the result using: @@ -327,4 +327,4 @@ In a proper app, you should consider the following points: * More on adding [custom endpoints](../app-scripts/custom-endpoints) * See how you can use [Twig functions](../app-scripts/#extended-syntax) in app scripts -* Working with [DAL Aggregations](./../../../../resources/references/core-reference/dal-reference/aggregations-reference) +* Working with [DAL Aggregations](../../../development/troubleshooting/dal-reference/aggregations-reference.md) diff --git a/guides/plugins/apps/app-scripts/cart-manipulation.md b/guides/plugins/apps/app-scripts/cart-manipulation.md index bdf533d72d..8b8f1a6b1a 100644 --- a/guides/plugins/apps/app-scripts/cart-manipulation.md +++ b/guides/plugins/apps/app-scripts/cart-manipulation.md @@ -1,6 +1,6 @@ --- nav: - title: Cart manipulation + title: Cart Manipulation position: 10 --- @@ -120,7 +120,7 @@ You can define price fields for [custom fields](../custom-data/custom-fields) ### Price fields inside app config -You can define price fields for [app configuration](../configuration). +You can define price fields for [app configuration](../lifecycle/configuration.md). ```xml // Resources/config/config.xml @@ -152,7 +152,7 @@ You can specify the `gross` and `net` prices for each currency. ### Prices inside the app config -As described above, it is also possible to use price fields inside the [app configuration](../configuration). In your cart scripts, you can access those config values over the [`config` service](../../../../resources/references/app-reference/script-reference/miscellaneous-script-services-reference#SystemConfigFacade) and pass them to the same price factory as the manual definitions. +As described above, it is also possible to use price fields inside the [app configuration](../lifecycle/configuration.md). In your cart scripts, you can access those config values over the [`config` service](../../../../resources/references/app-reference/script-reference/miscellaneous-script-services-reference#SystemConfigFacade) and pass them to the same price factory as the manual definitions. ```twig // Resources/scripts/cart/my-cart-script.twig @@ -259,7 +259,7 @@ You can add custom (meta-) data to line items in the cart by manipulating the pa ## Add errors and notifications to the cart Your app script can block the cart's checkout by raising an error. -As the first parameter you have to provide the [snippet key](../../plugins/storefront/add-translations) of the error message that should be displayed to the user. +As the first parameter you have to provide the [snippet key](../../plugins/storefront/styling/add-translations.md) of the error message that should be displayed to the user. As the second optional parameter, you can specify a `id` for the error, so you can reference the error later on in your script. Lastly, you can provide an array of parameters as the optional third parameter if you need to pass parameters to the snippet. @@ -284,8 +284,8 @@ The API is basically the same as for adding errors. ## Rule based cart scripts -The cart scripts automatically integrate with the [Rule Builder](../../../../concepts/framework/rule) and you can use the full power of the rule builder to only do your cart manipulations if a given rule matches. -For example, you can add an entity-single-select field to your [app's config](../configuration) to allow the merchant to choose a rule that needs to match your app script taking effect. +The cart scripts automatically integrate with the [Rule Builder](../../../../concepts/framework/rule-system/index.md) and you can use the full power of the rule builder to only do your cart manipulations if a given rule matches. +For example, you can add an entity-single-select field to your [app's config](../lifecycle/configuration.md) to allow the merchant to choose a rule that needs to match your app script taking effect. ```xml // Resources/config/config.xml @@ -316,4 +316,4 @@ Inside your cart script, you can check if the rule matches by checking if the co ## Further information -Take a look at the [cart manipulation script service reference](../../../../resources/references/app-reference/script-reference/cart-manipulation-script-services-reference). +Take a look at the [cart manipulation script service reference](../../../../resources/references/app-reference/script-reference/cart-manipulation-script-services-reference.md). diff --git a/guides/plugins/apps/app-scripts/custom-endpoints.md b/guides/plugins/apps/app-scripts/custom-endpoints.md index ddd4b50fd8..2368e06063 100644 --- a/guides/plugins/apps/app-scripts/custom-endpoints.md +++ b/guides/plugins/apps/app-scripts/custom-endpoints.md @@ -1,6 +1,6 @@ --- nav: - title: Custom endpoints + title: Custom Endpoints position: 30 --- @@ -48,7 +48,7 @@ The possible route scopes are `storefront`, `store-api`, `api` and `administrati ## Custom Endpoints There are specialized script-execution endpoints for the `api`, `store-api` and `storefront` scopes. -Refer to the [API docs](../../../integrations-api/) for more information on the distinction of those APIs. +Refer to the [API docs](../../../development/integrations-api/index.md) for more information on the distinction of those APIs. Those endpoints allow you to trigger the execution of your scripts with an HTTP request against those endpoints. Custom endpoint scripts need to be located in a folder that is prefixed with the name of the api scope (one of `api-`, `store-api-` or `storefront`). @@ -63,11 +63,11 @@ To prevent name collisions with other apps, you should always include your vendo The best practice is to add your app name after the API scope prefix and then use it as a REST style resource identifier, e.g., `/api/script/swagMyApp/test-script`. ::: -In your custom endpoint scripts, you get access to the JSON payload of the request (and the query parameters for GET-requests) and have access to the read & write functionality of the [Data Abstraction Layer](../../../../concepts/framework/data-abstraction-layer). -For a complete overview of the available data and service, refer to the [hook reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference#api-hook). +In your custom endpoint scripts, you get access to the JSON payload of the request (and the query parameters for GET-requests) and have access to the read & write functionality of the [Data Abstraction Layer](../../../../concepts/framework/data-abstraction-layer.md). +For a complete overview of the available data and service, refer to the [hook reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference.md#api-hook). By default, a `204 No Content` response will be sent after your script was executed. -To provide a custom response, you can use the [`response`-service](../../../../resources/references/app-reference/script-reference/custom-endpoint-script-services-reference#scriptresponsefactoryfacade) to create a response and set it as the `response` of the hook: +To provide a custom response, you can use the [`response`-service](../../../../resources/references/app-reference/script-reference/custom-endpoint-script-services-reference.md#scriptresponsefactoryfacade) to create a response and set it as the `response` of the hook: ```twig // Resources/scripts/api-custom-endpoint/my-example-script.twig @@ -93,7 +93,7 @@ This endpoint only allows `POST` requests. Caching of responses is not supported for Admin API responses. -For a complete overview of the available data and services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference#api-hook). +For a complete overview of the available data and services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference.md#api-hook). ### Store API endpoints @@ -102,7 +102,7 @@ The execution of those scripts is possible over the `/store-api/script/{hook-nam This endpoint allows `POST` and `GET` requests. -This hook is an [Interface Hook](./#interface-hooks). The execution of your logic should be implemented in the `response` block of your script. +This hook is an [Interface Hook](../app-scripts/index.md#interface-hooks). The execution of your logic should be implemented in the `response` block of your script. ```twig // Resources/scripts/store-api-custom-endpoint/my-example-script.twig @@ -126,7 +126,7 @@ A simple cache key generation would be to generate an `md5`-hash of all the inco {% endblock %} ``` -For a complete overview of the available data and services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference#store-api-hook). +For a complete overview of the available data and services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference.md#store-api-hook). ### Storefront endpoints @@ -161,14 +161,14 @@ Additionally, it is also possible to redirect to an existing route: {% do hook.setResponse(response) %} ``` -For a complete overview of the available data and services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference#storefront-hook). +For a complete overview of the available data and services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference.md#storefront-hook). ## Caching To improve the end-user experience and provide a scalable system, the customer-facing APIs (i.e., `store-api` and `storefront`) offer a caching mechanism to cache the response to specific requests and return the response from the cache on further requests instead of computing it again and again on each request. By default, caching is enabled for custom endpoints, but for `store-api` endpoints you have to generate the cache key in the script. -For `storefront` requests, however, shopware takes care of it so that responses get automatically cached (if the [HTTP-Cache](../../../../concepts/framework/http_cache) is enabled). +For `storefront` requests, however, shopware takes care of it so that responses get automatically cached (if the [HTTP-Cache](../../../../concepts/framework/http_cache.md) is enabled). ### Cache Config @@ -215,7 +215,7 @@ You can specify for how long a response should be cached by calling the `cache.m > **Note:** The cache states feature is deprecated and will be removed in v6.8.0.0. It also does not work when the `CACHE_REWORK` feature flag is enabled. You can specify that the cached response is not valid if one of the given states is present. -For more detailed information on the invalidation states, refer to the [HTTP-cache docs](../../../../concepts/framework/http_cache#sw-states). +For more detailed information on the invalidation states, refer to the [HTTP-cache docs](../../../../concepts/framework/http_cache.md#sw-states). ```twig {% set response = services.response.json({ 'foo': 'bar' }) %} @@ -275,4 +275,4 @@ You can then use the filtered-down list of ids to invalidate entity-specific tag {% do services.cache.invalidate(tags) %} ``` -For a complete overview of what data and services are available, refer to the [cache-invalidation hook reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference#cache-invalidation). +For a complete overview of what data and services are available, refer to the [cache-invalidation hook reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference.md#cache-invalidation). diff --git a/guides/plugins/apps/app-scripts/data-loading.md b/guides/plugins/apps/app-scripts/data-loading.md index b14552ccf1..2fa25c42c2 100644 --- a/guides/plugins/apps/app-scripts/data-loading.md +++ b/guides/plugins/apps/app-scripts/data-loading.md @@ -1,13 +1,13 @@ --- nav: - title: Data loading + title: Data Loading position: 20 --- -# Load additional data for the Storefront with App Scripts +# Load Additional Data for the Storefront with App Scripts -If your app needs additional data in your [customized Storefront templates](../../plugins/storefront/customize-templates.md), you can load that data with app scripts and make it available to your template. +If your app needs additional data in your [customized Storefront templates](../../plugins/storefront/templates/customize-templates.md), you can load that data with app scripts and make it available to your template. ::: info Note that app scripts were introduced in Shopware 6.4.8.0 and are not supported in previous versions. @@ -112,7 +112,7 @@ The `store` service only loads "public" entities. This means that the entities i One major difference is that when using the `repository` service, your app needs `read` permissions for every entity it reads, whereas you don't need additional permissions to use the `store` service (since it only searches for "public" data). -Refer to the [App registration & backend setup guide](../app-registration-setup.md#permissions) for more information on how permissions work for apps. +Refer to the [App registration & backend setup guide](../lifecycle/app-registration-setup.md#permissions) for more information on how permissions work for apps. The `repository` service exposes the same data as the CRUD operations of the [Admin API](../../../development/integrations-api/index.md#admin-api), whereas the `store` service gives access to the same data as the [Store API](../../../development/integrations-api/index.md#store-api). diff --git a/guides/plugins/apps/app-scripts/index.md b/guides/plugins/apps/app-scripts/index.md index 13a12f93fd..b1230cf2ab 100644 --- a/guides/plugins/apps/app-scripts/index.md +++ b/guides/plugins/apps/app-scripts/index.md @@ -16,7 +16,8 @@ Note that app scripts were introduced in Shopware 6.4.8.0 and are not supported ## Script hooks The entry point for each script is the so-called "Hooks". You can register one or more scripts inside your app that should be executed whenever a specific hook is triggered. -Through the hook, your script gets access to the data of the current execution context and can react to or manipulate the data in some way. + +Through the hook, your script gets access to the data of the current execution context and can react to or manipulate the data in some way. See the [Hooks reference](../../../../resources/references/app-reference/script-reference/script-hooks-reference) for a complete list of all available. @@ -47,7 +48,7 @@ The file structure of your apps should look like this: Sometimes scripts can become more complex or you want to extract common functionality. Thus it is handy to split your scripts into smaller parts that can later be included in other scripts. -In order to do that you can compose your reusable scripts into [twig macros](https://twig.symfony.com/doc/3.x/tags/macro.html), put them inside a dedicated `include` folder and then import them using the [twig import functionality](https://twig.symfony.com/doc/3.x/tags/import.html). +In order to do that you can compose your reusable scripts into [Twig macros](https://twig.symfony.com/doc/3.x/tags/macro.html), put them inside a dedicated `include` folder and then import them using the [twig import functionality](https://twig.symfony.com/doc/3.x/tags/import.html). ```text └── DemoApp @@ -108,7 +109,7 @@ The available data and services are described for each hook (or each function in ### Translation -Inside the app script, you have access to the [Storefront translation mechanism](../../plugins/storefront/add-translations) by using the `|trans`-filter. +Inside the app script, you have access to the [Storefront translation mechanism](../../plugins/storefront/styling/add-translations.md) by using the `|trans`-filter. ```twig {% set translated = 'my.snippet.key'|trans %} @@ -204,7 +205,7 @@ Instead of using `AND` or `OR` in if-conditions, you can use the `&&` or `||` sh You can use the `return` tag to return values from inside macros. ```twig -{% macro foo() %} +{% macro foo() %} {% return 'bar' %} {% endmacro %} ``` diff --git a/guides/plugins/apps/app-sdks/javascript/01-getting_started.md b/guides/plugins/apps/app-sdks/javascript/01-getting_started.md index 2f771f7981..4d6145ef24 100644 --- a/guides/plugins/apps/app-sdks/javascript/01-getting_started.md +++ b/guides/plugins/apps/app-sdks/javascript/01-getting_started.md @@ -1,13 +1,15 @@ --- nav: - title: Getting started + title: Getting Started position: 10 --- # Getting Started -The app server written in TypeScript and is an open-source project accessible at [app-sdk-js](https://github.com/shopware/app-sdk-js). +This example assumes you already have a running app backend. + +The app server is written in TypeScript and is an open-source project accessible at [app-sdk-js](https://github.com/shopware/app-sdk-js). ## Installation @@ -17,10 +19,17 @@ Install the App PHP SDK via NPM: npm install --save @shopware-ag/app-sdk-server ``` -After the installation, you can use the SDK in your project. Here is an example: +After installation, you can use the SDK in your project. Setting up the registration endpoints in your app is a natural next step. ## Registration process +To handle app registration, create an `AppServer` instance and expose two routes: + +- `/authorize` starts the registration flow +- `/authorize/callback` handles the callback from Shopware + +In the following example, `AppServer` is configured with your app name, app secret, and authorize callback URL. `InMemoryShopRepository` stores registered shops in memory, which is useful for local development and testing. For production, replace it with a persistent database-backed repository. + ```javascript import { AppServer, InMemoryShopRepository } from '@shopware-ag/app-server-sdk' @@ -70,7 +79,7 @@ deno serve index.js Node.JS does not support the `Request` and `Response` objects. You can use [@hono/node-server](https://github.com/honojs/node-server) to run the server. -The recommendation here is to use a Framework like [Hono](https://hono.dev/). +We recommend using a framework like [Hono](https://hono.dev/). diff --git a/guides/plugins/apps/app-sdks/javascript/03-context.md b/guides/plugins/apps/app-sdks/javascript/03-context.md index ae53f8e085..722e3c8e0b 100644 --- a/guides/plugins/apps/app-sdks/javascript/03-context.md +++ b/guides/plugins/apps/app-sdks/javascript/03-context.md @@ -7,7 +7,10 @@ nav: # Context -The ContextResolver helps you to validate the Request, resolve the Shop and provide types for the Context. +The `ContextResolver` validates incoming requests, resolves the corresponding shop, and returns a typed context for further processing. + +- `fromBrowser()` resolves requests coming from browser-based app modules, such as iframes. +- `fromAPI()` resolves requests coming from Shopware server-to-server calls, such as webhooks or action buttons. ## Usage @@ -23,7 +26,7 @@ app.contextResolver.fromBrowser(/** Request */); app.contextResolver.fromAPI(/** Request */); ``` -Both methods accepts a Type to specify the context type. +Both methods accept a generic type parameter to define the expected context payload. ```ts import { BrowserAppModuleRequest } from '@shopware-ag/app-server-sdk/types' @@ -34,9 +37,9 @@ const ctx = await app.contextResolver.fromBrowser(/** R console.log(ctx.payload['sw-version']); ``` -You can checkout the [types.ts](https://github.com/shopware/app-sdk-js/blob/main/src/types.ts) to see all available types. +See the [types.ts](https://github.com/shopware/app-sdk-js/blob/main/src/types.ts) for the available built-in types. -If you miss a type, feel free to open a PR or an issue. Otherwise you can also specify the type also in your project. +If a type is missing, either file an issue on the SDK repository or define your own in your project. ```ts type MyCustomWebHook = { @@ -48,4 +51,4 @@ const ctx = await app.contextResolver.fromBrowser(/** Request * ctx.payload.foo; // This is now typed and the IDE will help you ``` -Next, we will look into the [Signing of responses](./04-signing). +Next, we will look into [Signing Responses](./04-signing). diff --git a/guides/plugins/apps/app-sdks/javascript/04-signing.md b/guides/plugins/apps/app-sdks/javascript/04-signing.md index e86ed24568..85448fc782 100644 --- a/guides/plugins/apps/app-sdks/javascript/04-signing.md +++ b/guides/plugins/apps/app-sdks/javascript/04-signing.md @@ -1,15 +1,15 @@ --- nav: - title: Signing + title: Signing Responses position: 40 --- -# Signing of responses +# Signing Responses -The Shopware App System requires you to sign your responses to the Shopware server. +Shopware requires signed responses for requests that are handled server-to-server. The signature is used to verify the authenticity of the response and to ensure that the response was not tampered with. -The signing is required for all responses that are sent to the Shopware server. The signature is used to verify the authenticity of the response and to ensure that the response was not tampered with. +Use the `signResponse()` method to sign a `Response` with the corresponding shop. To sign the response, you can call the signer with `signResponse` method. The signer will sign the response with the provided shop. @@ -30,4 +30,4 @@ const response = new Response('Hello World', { const signedResponse = await app.signer.signResponse(response, shop); ``` -Next, we will look into the [Making HTTP requests to the Shop](./05-http-client). +Next, we will look into [Making HTTP requests to the Shop](./05-http-client). diff --git a/guides/plugins/apps/app-sdks/javascript/index.md b/guides/plugins/apps/app-sdks/javascript/index.md index a135f8feb7..0518a4974c 100644 --- a/guides/plugins/apps/app-sdks/javascript/index.md +++ b/guides/plugins/apps/app-sdks/javascript/index.md @@ -1,16 +1,16 @@ --- nav: - title: Official JavaScript SDK + title: JavaScript App Server SDK position: 10 --- -# JavaScript +# JavaScript App Server SDK -The App SDK for JavaScript abstracts and simplifies creating Shopware apps. The SDK uses JavaScript standardized Request/Response objects and therefore is supported to run in Node/Deno/Bun/Cloudflare Workers. +The [JavaScript App Server SDK](https://github.com/shopware/app-sdk-js) provides the building blocks for developing Shopware apps. Written in pure Typescript, the SDK is built on the standard JavaScript Request/Response APIs and therefore can run in environments such as Node.js. Deno, Bun, and Cloudflare Workers. -The app SDK provides a context object that grants access to relevant information and services within the Shopware environment. This context is essential for interacting with Shopware's APIs, accessing database entities, and executing various operations. +The SDK provides a context object that grants access to relevant information and services within the Shopware environment. This context is essential for interacting with Shopware's APIs, accessing database entities, and executing various operations. -To ensure secure communication between the application and Shopware, this SDK supports signing mechanisms, allowing developers to validate the authenticity and integrity of requests and responses. +To ensure secure communication between the application and Shopware, this SDK supports signing mechanisms that allow developers to validate the authenticity and integrity of requests and responses. -It also includes an HTTP client that simplifies making API requests to Shopware endpoints. It provides methods for handling authentication, executing HTTP requests, and processing responses. +It also includes an HTTP client that simplifies making API requests to Shopware endpoints. It provides methods for handling authentication, executing HTTP requests, and processing responses. diff --git a/guides/plugins/apps/app-sdks/symfony-bundle/index.md b/guides/plugins/apps/app-sdks/symfony-bundle/index.md index 07361783ab..a5886c97de 100644 --- a/guides/plugins/apps/app-sdks/symfony-bundle/index.md +++ b/guides/plugins/apps/app-sdks/symfony-bundle/index.md @@ -94,7 +94,7 @@ The registration flow also dispatches events for the different lifecycle stages. ### 5. Implement action buttons, webhooks, and payment handling -[Check out the official app documentation to learn more about the different integration points with this SDK](../../app-registration-setup.md#sdk-integration). +[Check out the official app documentation to learn more about the different integration points with this SDK](../../lifecycle/app-registration-setup.md#sdk-integration). You can also check out the [APP SDK](https://github.com/shopware/app-php-sdk) documentation. diff --git a/guides/plugins/apps/payment.md b/guides/plugins/apps/checkout/payment.md similarity index 99% rename from guides/plugins/apps/payment.md rename to guides/plugins/apps/checkout/payment.md index 5e9da8ce3e..ba19963e96 100644 --- a/guides/plugins/apps/payment.md +++ b/guides/plugins/apps/checkout/payment.md @@ -16,7 +16,7 @@ The requests and responses of all of your endpoints will be signed and feature J You should be familiar with the concept of Apps, their registration flow as well as signing and verifying requests and responses between Shopware and the App backend server. - + Your app server must be also accessible for the Shopware server. You can use a tunneling service like [ngrok](https://ngrok.com/) for development. @@ -795,4 +795,4 @@ The following lists are all possible refund state options: ## API docs -You can further take a look at [Payment references](../../../resources/references/app-reference/payment-reference.md). +You can further take a look at [Payment references](../../../../resources/references/app-reference/payment-reference.md). diff --git a/guides/plugins/apps/shipping-methods.md b/guides/plugins/apps/checkout/shipping-methods.md similarity index 99% rename from guides/plugins/apps/shipping-methods.md rename to guides/plugins/apps/checkout/shipping-methods.md index a6e18afa60..de221117b4 100644 --- a/guides/plugins/apps/shipping-methods.md +++ b/guides/plugins/apps/checkout/shipping-methods.md @@ -13,7 +13,7 @@ Starting with version 6.5.7.0 as **experimental feature**. Shopware has introduc You should be familiar with the concept of Apps, their registration flow as well as signing and verifying requests and responses between Shopware and the App backend server. - + Your app server must be also accessible for the Shopware server. diff --git a/guides/plugins/apps/tax-provider.md b/guides/plugins/apps/checkout/tax-provider.md similarity index 99% rename from guides/plugins/apps/tax-provider.md rename to guides/plugins/apps/checkout/tax-provider.md index 2b17c9637b..406ab4a07b 100644 --- a/guides/plugins/apps/tax-provider.md +++ b/guides/plugins/apps/checkout/tax-provider.md @@ -15,7 +15,7 @@ With version 6.5.0.0, Shopware allows apps to integrate custom tax calculations, You should be familiar with the concept of Apps, their registration flow as well as signing and verifying requests and responses between Shopware and the App backend server. - + Your app server must be also accessible for the Shopware server. You can use a tunneling service like [ngrok](https://ngrok.com/) for development. diff --git a/guides/plugins/apps/create-admin-extension.md b/guides/plugins/apps/create-admin-extension.md index 12fd5969b7..14d104817b 100644 --- a/guides/plugins/apps/create-admin-extension.md +++ b/guides/plugins/apps/create-admin-extension.md @@ -12,7 +12,7 @@ This guide shows how to create a Shopware app that adds an Administration module - build an app-based Admin UI locally - iterate on the frontend without setting up an app backend first -If you need app registration, signing, webhooks, or Admin API credentials, continue with [App registration & backend setup](app-registration-setup.md). +If you need app registration, signing, webhooks, or Admin API credentials, continue with [App registration & backend setup](../apps/lifecycle/app-registration-setup.md). ## What this guide covers @@ -161,6 +161,6 @@ At this point, Shopware loads the Admin module from your local Vite server. ## Next steps -- [App registration & backend setup](app-registration-setup.md) -- [App signature verification](app-signature-verification.md) -- [Webhooks](webhook.md) +- [App registration & backend setup](../apps/lifecycle/app-registration-setup.md) +- [App signature verification](../apps/lifecycle/app-signature-verification.md) +- [Webhooks](../apps/lifecycle/webhook.md) diff --git a/guides/plugins/apps/gateways/context/context-gateway.md b/guides/plugins/apps/gateways/context/context-gateway.md index 17cf232b6b..c94d0623cc 100644 --- a/guides/plugins/apps/gateways/context/context-gateway.md +++ b/guides/plugins/apps/gateways/context/context-gateway.md @@ -75,7 +75,7 @@ Your app server will receive the following payload: ::: info -Communication between Shopware and your app server is secured via the [app signature verification mechanism](../../app-signature-verification.md), ensuring that only your app server can respond to context gateway requests. +Communication between Shopware and your app server is secured via the [app signature verification mechanism](../../lifecycle/app-signature-verification.md), ensuring that only your app server can respond to context gateway requests. ::: diff --git a/guides/plugins/apps/gateways/in-app-purchase/in-app-purchase-gateway.md b/guides/plugins/apps/gateways/in-app-purchase/in-app-purchase-gateway.md index 20b59eb388..9f9c0a0e1f 100644 --- a/guides/plugins/apps/gateways/in-app-purchase/in-app-purchase-gateway.md +++ b/guides/plugins/apps/gateways/in-app-purchase/in-app-purchase-gateway.md @@ -1,3 +1,9 @@ +--- +nav: + title: In-App Purchase Gateway + position: 50 +--- + # In-App Purchase Gateway ## Context @@ -11,9 +17,9 @@ In-App Purchase Gateway was introduced to enhance flexibility in managing In-App The gateway enables app servers to restrict specific In-App Purchases based on advanced decision-making processes handled on the app server side. ::: info -**Current Limitations:** -At present, the In-App Purchase Gateway supports only restricting the checkout process for new In-App Purchases. -**Plans:** +**Current Limitations:** +At present, the In-App Purchase Gateway supports only restricting the checkout process for new In-App Purchases. +**Plans:** We aim to expand its functionality to include filtering entire lists of In-App Purchases before they are displayed to users. ::: @@ -21,7 +27,7 @@ We aim to expand its functionality to include filtering entire lists of In-App P You should be familiar with the concept of Apps, their registration flow as well as signing and verifying requests and responses between Shopware and the App backend server. - + Your app server must be also accessible for the Shopware server. You can use a tunneling service like [ngrok](https://ngrok.com/) for development. diff --git a/guides/plugins/apps/gateways/index.md b/guides/plugins/apps/gateways/index.md index d5267f8b13..d02d1b8714 100644 --- a/guides/plugins/apps/gateways/index.md +++ b/guides/plugins/apps/gateways/index.md @@ -6,10 +6,24 @@ nav: # Gateways -Gateways allow apps to participate in specific Shopware flows by sending requests to an app server and applying the returned result inside the shop. +Gateways allow apps to influence Shopware behavior at runtime by delegating decisions to an external app server. -This section covers the available gateway types and their command references: +They are designed for dynamic, context-aware business logic that cannot be handled purely inside the Shopware instance. -- [Checkout Gateway](../gateways/checkout/checkout-gateway.md) -- [Context Gateway](../gateways/context/context-gateway.md) -- [In-App Purchase Gateway](../gateways/in-app-purchase/in-app-purchase-gateway.md) +Use a gateway to: + +* Restrict or modify checkout behavior +* Manipulate the customer context dynamically +* Control In-App Purchase availability +* Apply external business logic during runtime +* Integrate secure server-side decision-making + +Gateways require a reachable and properly secured app server, as Shopware forwards sensitive contextual data during execution. + +## Available gateways + +* [Checkout](./checkout/checkout-gateway.md) +* [Context](./context/context-gateway.md) +* [In-App Purchases](./in-app-purchase/in-app-purchase-gateway.md) + +Each gateway supports a defined set of executable commands. diff --git a/guides/plugins/apps/index.md b/guides/plugins/apps/index.md index 245c29ceb9..514f07d149 100644 --- a/guides/plugins/apps/index.md +++ b/guides/plugins/apps/index.md @@ -23,7 +23,7 @@ You can develop apps using the Shopware [App SDKs](../apps/app-sdks/index.md), [ Some app extension points use a [gateway pattern](../apps/gateways/index.md), where Shopware delegates a specific task to an external app service and continues processing based on the returned result. A prominent example is the [checkout gateway](../apps/gateways/checkout/checkout-gateway.md). -For comparison, [App Scripts](./app-scripts/index.md) cover synchronous, sandboxed logic inside the app system, but come with caveats. +For comparison, [App Scripts](../apps/app-scripts/index.md) cover synchronous, sandboxed logic inside the app system, but come with caveats. ::: info Apps also provide theme support, so everything you can do with a theme plugin is also possible in an app. This makes them the preferred option for customizing design in Cloud shops. @@ -46,10 +46,10 @@ After the base setup, continue with the path that fits your app: - **Administration extensions:** Use [Build an Admin UI App Locally](create-admin-extension.md) if you want to add a custom Administration UI module and develop it locally with the [Meteor Admin SDK](../apps/administration/meteor-admin-sdk.md) and [Vite](https://vite.dev/), without setting up an app backend first. -- **Apps with a backend:** Use [App Registration & Backend Setup](app-registration-setup.md) if your app needs registration, authenticated server-to-server communication, webhooks, signing, Admin API credentials, payment methods, tax providers, or other backend-driven features. +- **Apps with a backend:** Use [App Registration & Backend Setup](../apps/lifecycle/app-registration-setup.md) if your app needs registration, authenticated server-to-server communication, webhooks, signing, Admin API credentials, payment methods, tax providers, or other backend-driven features. -- **Request signing and verification:** See [Signing & Verification in the App System](app-signature-verification.md) for secure request validation and response signing. +- **Request signing and verification:** See [Signing & Verification in the App System](../apps/lifecycle/app-signature-verification.md) for secure request validation and response signing. -- **Event-based integrations:** See [Webhook](webhook.md) to react to Shopware events asynchronously. +- **Event-based integrations:** See [Webhook](../apps/lifecycle/webhook.md) to react to Shopware events asynchronously. -- **Feature-specific integrations:** Continue with the dedicated guides for [Payment](payment.md), [Shipping methods](shipping-methods.md), [Tax provider](tax-provider.md), or [Configuration](configuration.md), depending on your app’s capabilities. +- **Feature-specific integrations:** Continue with the dedicated guides for [Payment](../apps/checkout/payment.md), [Shipping methods](../apps/checkout/shipping-methods.md), [Tax provider](../apps/checkout/tax-provider.md), or [Configuration](../apps/lifecycle/configuration.md), depending on your app’s capabilities. diff --git a/guides/plugins/apps/app-registration-setup.md b/guides/plugins/apps/lifecycle/app-registration-setup.md similarity index 97% rename from guides/plugins/apps/app-registration-setup.md rename to guides/plugins/apps/lifecycle/app-registration-setup.md index 9b507f2107..b4b8f530f1 100644 --- a/guides/plugins/apps/app-registration-setup.md +++ b/guides/plugins/apps/lifecycle/app-registration-setup.md @@ -28,7 +28,7 @@ Additionally, your app will provide a secret that Shopware will use to sign all The setup workflow is shown in the following schema. Each step will be explained in detail. -![Setup request workflow](../../../assets/plugins-apps-appBaseGuide.svg) +![Setup request workflow](../../../../assets/plugins-apps-appBaseGuide.svg) ::: info The timeout for the requests against the app server is 5 seconds. @@ -38,8 +38,8 @@ The timeout for the requests against the app server is 5 seconds. Integrating apps into your application can be daunting, but our PHP SDK simplifies registration and other common tasks. -* [Official PHP SDK](./app-sdks/php/index.md) -* [Official Symfony Bundle](./app-sdks/symfony-bundle/index.md) +* [Official PHP SDK](../app-sdks/php/index.md) +* [Official Symfony Bundle](../app-sdks/symfony-bundle/index.md) If no SDK is available for your language, you can implement the registration process by yourself. @@ -268,7 +268,7 @@ To prevent failure of in-flight requests during the secret rotation, your app ** ## Permissions -Shopware comes with the possibility to create fine-grained [Access Control Lists](../plugins/administration/permissions-error-handling/add-acl-rules.md) \(ACLs\). +Shopware comes with the possibility to create fine-grained [Access Control Lists](../administration/../../plugins/administration/permissions-error-handling/add-acl-rules.md) \(ACLs\). This means you need to request permissions if your app needs to read or write data via the API or receive webhooks. The permissions your app needs are defined in the manifest file and combine a privilege (`read`, `create`, `update`, or `delete`) with an entity. Since version 6.4.12.0, your app can also request additional non-CRUD privileges with the `` element. @@ -310,7 +310,7 @@ The permissions you request need to be accepted by the user during the installat After that, the permissions granted to your app and your API access via the credentials from the [confirmation request](app-registration-setup.md#confirmation-request) of the [setup workflow](app-registration-setup.md#setup) are limited to those permissions. ::: warning -Keep in mind that read permissions also extend to the data contained in the requests, so your app needs read permissions for the entities contained in the subscribed [webhooks](../apps/webhook.md). +Keep in mind that read permissions also extend to the data contained in the requests, so your app needs read permissions for the entities contained in the subscribed [webhooks](../lifecycle/webhook.md). ::: ### App notification @@ -409,10 +409,10 @@ function webhookController(RequestInterface $request): ResponseInterface #### App lifecycle events for app scripts -Since Shopware 6.4.9.0, it is also possible to create [App scripts](./app-scripts/index.md) that are executed during the lifecycle of your app. +Since Shopware 6.4.9.0, it is also possible to create [App scripts](../app-scripts/index.md) that are executed during the lifecycle of your app. You get access to the database and can change or create some data, e.g., when your app is activated, without needing an external server. -For a full list of the available hook points and the available services, refer to the [reference documentation](../../../resources/references/app-reference/script-reference/script-hooks-reference.md#app-lifecycle). +For a full list of the available hook points and the available services, refer to the [reference documentation](../../../../resources/references/app-reference/script-reference/script-hooks-reference.md#app-lifecycle). ## Validation diff --git a/guides/plugins/apps/app-signature-verification.md b/guides/plugins/apps/lifecycle/app-signature-verification.md similarity index 99% rename from guides/plugins/apps/app-signature-verification.md rename to guides/plugins/apps/lifecycle/app-signature-verification.md index c9b0de5b0e..2342075820 100644 --- a/guides/plugins/apps/app-signature-verification.md +++ b/guides/plugins/apps/lifecycle/app-signature-verification.md @@ -27,7 +27,7 @@ If you are not using these tools, ensure that you base signature generation on a You should be familiar with the concept of Apps and their registration flow. - + Your app server must be also accessible for the Shopware server. You can use a tunneling service like [ngrok](https://ngrok.com/) for development. diff --git a/guides/plugins/apps/clientside-to-app-backend.md b/guides/plugins/apps/lifecycle/clientside-to-app-backend.md similarity index 100% rename from guides/plugins/apps/clientside-to-app-backend.md rename to guides/plugins/apps/lifecycle/clientside-to-app-backend.md diff --git a/guides/plugins/apps/configuration.md b/guides/plugins/apps/lifecycle/configuration.md similarity index 80% rename from guides/plugins/apps/configuration.md rename to guides/plugins/apps/lifecycle/configuration.md index 94f7503875..af228d1b74 100644 --- a/guides/plugins/apps/configuration.md +++ b/guides/plugins/apps/lifecycle/configuration.md @@ -8,7 +8,7 @@ nav: # Configuration ::: info -Configurations for apps adhere to the same schema as [Plugin Configurations](../plugins/plugin-fundamentals/add-plugin-configuration.md). +Configurations for apps adhere to the same schema as [Plugin Configurations](../../plugins/plugin-fundamentals/add-plugin-configuration.md). ::: To offer configuration possibilities to your users you can provide a `config.xml` file that describes your configuration options. You can find detailed information about the possibilities and the structure of the `config.xml` in the according documentation page. To include a `config.xml` file in your app put it into the `Resources/config` folder: @@ -66,7 +66,7 @@ Keep in mind that your app needs the `system_config:update`, `system_config:crea ### Reading the config in templates -Inside twig templates you can use the twig function `config` (see [Shopware Twig functions](../../../resources/references/storefront-reference/twig-function-reference.md)). An example twig template could look like this: +Inside twig templates you can use the twig function `config` (see [Shopware Twig functions](../../plugins/storefront/templates/twig-function-reference.md). An example twig template could look like this: ```twig {{ config('DemoApp.config.field1') }} @@ -74,7 +74,7 @@ Inside twig templates you can use the twig function `config` (see [Shopware Twig ### Reading the config in app scripts -In app scripts you have access to the [`config` service](../../../resources/references/app-reference/script-reference/miscellaneous-script-services-reference.md#SystemConfigFacade), that can be used to access config values. +App scripts provide access to the [`config` service](../../../../resources/references/app-reference/script-reference/miscellaneous-script-services-reference.md#servicesconfig-shopwarecoresystemsystemconfigfacadesystemconfigfacade), which can be used to access config values. ::: info Note that app scripts were introduced in Shopware 6.4.8.0, and are not supported in previous versions. @@ -89,13 +89,14 @@ The `config` service provides an `app()` method, that can be used to access your Additionally, you can use the `get()` method, to access any configuration value and not just the ones of your app. ::: warning -Keep in mind that your app needs the `system_config:read` permission to use the `config.get()` method. +Your app needs the `system_config:read` permission to use the `config.get()` method. ::: ```twig {% set configValue = services.config.get('core.listing.productsPerPage') %} ``` -For a detailed description about app scripts refer to this [guide](./app-scripts/index.md). +## Next steps -For a full description of the `config` service take a look at the [service's reference](../../../resources/references/app-reference/script-reference/miscellaneous-script-services-reference.md#servicesconfig-shopwarecoresystemsystemconfigfacadesystemconfigfacade). +- Review the [App Scripts guide](../app-scripts/index.md) +- Find a full description of the `config` service at its [reference guide](../../../../resources/references/app-reference/script-reference/miscellaneous-script-services-reference.md#servicesconfig-shopwarecoresystemsystemconfigfacadesystemconfigfacade). diff --git a/guides/plugins/apps/starter/product-translator.md b/guides/plugins/apps/lifecycle/product-translator.md similarity index 98% rename from guides/plugins/apps/starter/product-translator.md rename to guides/plugins/apps/lifecycle/product-translator.md index 3cceb5b2aa..f4257f8b4e 100644 --- a/guides/plugins/apps/starter/product-translator.md +++ b/guides/plugins/apps/lifecycle/product-translator.md @@ -444,7 +444,7 @@ class ProductUpdatedListener In this last step, we will install the app using the Shopware CLI tools. ::: info -If this is your first time using the Shopware CLI, you have to [install](../../../../products/cli/installation) it first. Next, configure it using the `shopware-cli project config init` command. +If this is your first time using the Shopware CLI, you have to [install](../../../../products/cli/index.md) it first. Next, configure it using the `shopware-cli project config init` command. ::: ```sh @@ -460,6 +460,6 @@ And when you save a product, the description will automatically update. In this example, you have learned how to receive events and modify data through the app system. You can also: -* Add [new payments](../payment) as apps -* Write code that runs during checkout [app scripting](../app-scripts/cart-manipulation) -* Add new endpoints to the API [custom endpoints](./add-api-endpoint) +* Add [new payments](../checkout/payment.md) as apps +* Write code that runs during checkout [app scripting](../app-scripts/cart-manipulation.md) +* Add new endpoints to the API [custom endpoints](../app-scripts/add-api-endpoint.md) diff --git a/guides/plugins/apps/webhook.md b/guides/plugins/apps/lifecycle/webhook.md similarity index 95% rename from guides/plugins/apps/webhook.md rename to guides/plugins/apps/lifecycle/webhook.md index 9d21404754..5468ca6fdc 100644 --- a/guides/plugins/apps/webhook.md +++ b/guides/plugins/apps/lifecycle/webhook.md @@ -13,7 +13,7 @@ With webhooks, you can subscribe to events occurring in Shopware. Whenever such You should be familiar with the concept of Apps, especially their registration flow as well as signing and verifying requests and responses between Shopware and the App backend server, as that is required to authenticate the webhooks coming from the shops and showing the correct content in your modules. - + ## Webhook configuration @@ -120,7 +120,7 @@ Starting from Shopware version 6.4.5.0, the current language id of the shopware You can verify the authenticity of the incoming request by checking the `shopware-shop-signature`. Every request should have a SHA256 HMAC of the request body that is signed with the secret your app assigned the shop during the [registration](app-registration-setup.md#setup). The mechanism to verify the request is exactly the same as the one used for the [confirmation request](app-registration-setup.md#confirmation-request). -You can use a variety of events to react to changes in Shopware that way. See that table [Webhook-Events-Reference](../../../resources/references/app-reference/webhook-events-reference.md) for an overview. +You can use a variety of events to react to changes in Shopware that way. See the[Webhook-Events-Reference](../../../../resources/references/app-reference/webhook-events-reference.md) for an overview. ## Webhooks for live version only @@ -128,7 +128,7 @@ You can use a variety of events to react to changes in Shopware that way. See th This feature has been introduced with Shopware version 6.5.7.0 ::: -There might be cases when you only want to call the webhook when an entry is written to the database with live version ID (`Shopware\Core\Defaults::LIVE_VERSION`). For example when orders are created, you want to filter out drafts and only call your webhook when an order is actually placed. See more on versioning entities [here](../plugins/framework/data-handling/versioning-entities.md). +There might be cases when you only want to call the webhook when an entry is written to the database with live version ID (`Shopware\Core\Defaults::LIVE_VERSION`). For example when orders are created, you want to filter out drafts and only call your webhook when an order is actually placed. Review the [Versioning Entities guide](../../plugins/framework/data-handling/versioning-entities.md). You can achieve this by adding the option `onlyLiveVersion` to your webhook definition in the manifest file: diff --git a/guides/plugins/apps/rule-builder/add-custom-rule-conditions.md b/guides/plugins/apps/rule-builder/add-custom-rule-conditions.md index a27bc6138b..92213eff44 100644 --- a/guides/plugins/apps/rule-builder/add-custom-rule-conditions.md +++ b/guides/plugins/apps/rule-builder/add-custom-rule-conditions.md @@ -1,15 +1,13 @@ --- nav: - title: Add custom rule conditions + title: Add Custom Rule Conditions position: 10 --- -# Add custom rule conditions +# Add Custom Rule Conditions -## Overview - -In this guide, you'll learn how to make your app introduce custom conditions for use in the [Rule Builder](../../../../concepts/framework/rule/index.md). Custom conditions can be defined with fields to be rendered in the Administration and with their own logic, using the same approach as [App Scripts](../app-scripts/). +This guide explains how to make your app introduce custom conditions for use in the [Rule Builder](../../../../concepts/framework/rule-system/index.md). Custom conditions can be defined with fields to be rendered in the Administration and with their own logic, using the same approach as [App Scripts](../app-scripts/index.md). ::: info Note that app rule conditions were introduced in Shopware 6.4.12.0, and are not supported in previous versions. @@ -23,11 +21,11 @@ If you're not familiar with the app system, please take a look at the concept fi You should also be familiar with the general concept of the Rule Builder. - + -For the attached logic of your custom conditions, you'll use [twig files](https://twig.symfony.com/). Please refer to the App Scripts guide for a general introduction. +For the attached logic of your custom conditions, you'll use [Twig files](https://twig.symfony.com/). Please refer to the App Scripts guide for a general introduction. - + ## Definition @@ -35,7 +33,7 @@ App Rule Conditions are defined in the `manifest.xml` file of your app: <<< @/docs/snippets/config/app/rule-conditions.xml -For a complete reference of the structure of the manifest file, take a look at the [Manifest reference](../../../../resources/references/app-reference/manifest-reference). +For a complete reference of the structure of the manifest file, take a look at the [Manifest reference](../../../../resources/references/app-reference/manifest-reference.md). The following fields are required: @@ -47,7 +45,7 @@ The following fields are required: Constraints are optional and may be used to define fields, whose purpose is to provide data for use within the condition's script. -Constraints are a collection of [custom fields](../custom-data/), which allows you to provide a variety of different fields for setting parameters within the administration. Fields may be marked as `required`. The `name` attribute of the field is also the variable the field's value will be exposed as within the condition's script. So it is advisable to use a variable-friendly name and to use unique names within the confines of a single condition. +Constraints are a collection of [custom fields](../custom-data/index.md), which allows you to provide a variety of different fields for setting parameters within the administration. Fields may be marked as `required`. The `name` attribute of the field is also the variable the field's value will be exposed as within the condition's script. So it is advisable to use a variable-friendly name and to use unique names within the confines of a single condition. The above example will add the condition shown below for selection in the Administration: @@ -69,7 +67,7 @@ The corresponding scripts to the defined conditions within `manifest.xml` need t Scripts for rule conditions are [twig files](https://twig.symfony.com/) that are executed in a sandboxed environment. They offer the same extended syntax and debugging options as [App Scripts](../app-scripts/). -Within the script you will have access to the `scope` variable which is an instance of `RuleScope` as described in the [Rule Builder concept](../../../../concepts/framework/rule). The scope instance provides you with the current `SalesChannelContext` and, given the right scope, the current cart. Further available variables depend on the existence of constraints within the definition of your conditions. +Within the script you will have access to the `scope` variable which is an instance of `RuleScope` as described in the [Rule Builder concept](../../../../concepts/framework/rule-system/index.md). The scope instance provides you with the current `SalesChannelContext` and, given the right scope, the current cart. Further available variables depend on the existence of constraints within the definition of your conditions. A script _must_ return a boolean value, stating whether the condition is true or false. Anything but a boolean returned as value may lead to unexpected behavior. diff --git a/guides/plugins/apps/rule-builder/index.md b/guides/plugins/apps/rule-builder/index.md index 3389fc420f..4d392cd757 100644 --- a/guides/plugins/apps/rule-builder/index.md +++ b/guides/plugins/apps/rule-builder/index.md @@ -9,4 +9,4 @@ nav: Shopware allows you to enhance the capabilities of the rule builder by adding custom rules from an app. By creating a custom app and defining your own rules, you can incorporate specific conditions and actions based on your business requirements. This empowers you to create dynamic and personalized customer experiences, such as customized promotions, targeted discounts, or advanced product recommendations. -Starting with version 6.4.12.0, apps are able to [add custom rule conditions](./add-custom-rule-conditions) for use in the [Rule Builder](../../../../concepts/framework/rule). +Starting with version 6.4.12.0, apps are able to [add custom rule conditions](./add-custom-rule-conditions.md) for use in the [Rule Builder](../../../../concepts/framework/rule-system/index.md). diff --git a/guides/plugins/apps/starter/index.md b/guides/plugins/apps/starter/index.md deleted file mode 100644 index fb2212a72d..0000000000 --- a/guides/plugins/apps/starter/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -nav: - title: App Starter Guides - position: 10 - ---- - -# App Starter Guides - -The app starter guide provides a comprehensive approach to extending the platform's functionality. The following section guides you on creating custom API endpoints with App scripts, reading and writing data to/from Shopware, and creating custom admin extensions. diff --git a/guides/plugins/apps/storefront/cookies-with-apps.md b/guides/plugins/apps/storefront/cookies-with-apps.md index 147fa4fa42..f84fa63fc9 100644 --- a/guides/plugins/apps/storefront/cookies-with-apps.md +++ b/guides/plugins/apps/storefront/cookies-with-apps.md @@ -1,21 +1,15 @@ --- nav: - title: Add cookies to the consent manager + title: Add Cookies to the Consent Manager position: 20 --- -# Add cookies to the consent manager +# Add Cookies to the Consent Manager -## Prerequisites +Before proceeding, review the [app-base-guide](../app-base-guide.md). -You should be familiar with the concept of apps. - - - -::: info -For a comprehensive understanding of Shopware's cookie consent system, see the [Cookie Consent Management Concept](../../../../concepts/commerce/content/cookie-consent-management). -::: +The [Cookie Consent Management Concept](../../../../concepts/commerce/content/cookie-consent-management) provides a comprehensive guide to Shopware's cookie consent system. ## Create a single cookie @@ -89,7 +83,7 @@ A `group` element consists of three child elements to configure the cookie group * `entries` (required): Contains the grouped cookies. It is a collection of `cookie` elements described in the previous section. * `snippet-description` (optional): A string that represents the description of the cookie group in the cookie consent manager. To provide translations this should be the key of a Storefront snippet. -For a complete reference of the structure of the manifest file, take a look at the [Manifest reference](../../../../resources/references/app-reference/manifest-reference). +The [Manifest reference](../../../../resources/references/app-reference/manifest-reference.md) provides comprehensive information about manifest file structure. ## Assigning Cookies to Standard Cookie Groups @@ -136,9 +130,9 @@ The following example shows how to assign cookies to the **Marketing group**: As already mentioned in the previous sections, both the `cookie` and the `group` elements can contain `snippet-name` and `snippet-description` child elements. Although their values can be strings that will be displayed in the Storefront, the preferred way to set up cookie names and descriptions is to provide Storefront snippets. It gives you and the shop owner the possibility to add translations for your cookie's name and description. -If you are not familiar with setting up Storefront snippets, please refer to our snippet guide. +To learn how to set up Storefront snippets, refer to the snippet guide. - + ## Automatic Configuration Change Detection @@ -148,4 +142,4 @@ This process is handled by a configuration hash mechanism, which is explained in ## Reacting to cookie consent changes -As described in the previous section, `cookie` elements without a `value` element will not be set automatically. Instead, you have to react to cookie consent changes within your JavaScript. Find out how to [respond to cookie consent changes](../../../plugins/plugins/storefront/reacting-to-cookie-consent-changes). +As described in the previous section, `cookie` elements without a `value` element will not be set automatically. Instead, you have to react to cookie consent changes within your JavaScript. Find out how to [respond to cookie consent changes](../../../plugins/plugins/storefront/advanced/reacting-to-cookie-consent-changes.md). diff --git a/guides/plugins/apps/storefront/index.md b/guides/plugins/apps/storefront/index.md index d163cf6244..6e94b1aab2 100644 --- a/guides/plugins/apps/storefront/index.md +++ b/guides/plugins/apps/storefront/index.md @@ -7,7 +7,7 @@ nav: # Storefront -You can modify the whole appearance of the Storefront within your app. This includes [customizing templates](../../apps/storefront/customize-templates), [adding custom Javascript](../../plugins/storefront/add-custom-javascript) and [custom styling](../../plugins/storefront/add-custom-styling). +You can modify the whole appearance of the Storefront within your app. This includes [customizing templates](../../apps/storefront/customize-templates.md), [adding custom JavaScript](../../plugins/storefront/javascript/add-custom-javascript.md), and [custom styling](../../plugins/storefront/styling/add-custom-styling.md). As the Shopware server will build the Storefront, you don't have to set up any external servers for this. All you have to do is include your modifications \(in form of `.html.twig`, `.js` or `.scss` files\) inside the `Resources` folder of your app. The base folder structure of your app may look like this: @@ -28,16 +28,16 @@ As the Shopware server will build the Storefront, you don't have to set up any e └── manifest.xml ``` -## Custom Assets in Apps +## Custom assets in apps ::: info Note that this feature was introduced in Shopware 6.4.8.0, and is not supported in previous versions. ::: You may want to include custom assets inside your app, like custom fonts, etc. -Therefore, place the assets you need in the `/Resources/public` folder. All files inside this folder are available over the [asset-system](../../plugins/storefront/add-custom-assets#adding-custom-assets-to-your-plugin). +Therefore, place the assets you need in the `/Resources/public` folder. All files inside this folder are available over the [asset-system](../../plugins/storefront/styling/add-custom-assets.md#adding-custom-assets-to-your-plugin). -## Custom Template Priority +## Custom template priority ::: info Note that this feature was introduced in Shopware 6.4.12.0, and is not supported in previous versions. @@ -55,7 +55,7 @@ You may want your templates loaded before or after other extensions. To do so, y 100 - + ``` diff --git a/guides/plugins/plugins/administration/data-handling-processing/search-custom-data.md b/guides/plugins/plugins/administration/data-handling-processing/search-custom-data.md index 99ecf41fc5..eb9e810ab3 100644 --- a/guides/plugins/plugins/administration/data-handling-processing/search-custom-data.md +++ b/guides/plugins/plugins/administration/data-handling-processing/search-custom-data.md @@ -36,7 +36,7 @@ In addition, you need a custom entity to add to the search to begin with. Head o To support an entity in the untyped global search, the entity has to be defined in one of the Administration Modules. - + Add the `entity` and `defaultSearchConfiguration` values to your module to make it available to the search bar component. diff --git a/guides/plugins/plugins/administration/templates-styling/adding-snippets.md b/guides/plugins/plugins/administration/templates-styling/adding-snippets.md index adaa94fc7b..d135541bec 100644 --- a/guides/plugins/plugins/administration/templates-styling/adding-snippets.md +++ b/guides/plugins/plugins/administration/templates-styling/adding-snippets.md @@ -1,11 +1,11 @@ --- nav: - title: Adding snippets + title: Adding Snippets position: 60 --- -# Adding snippets +# Adding Snippets ## Overview @@ -13,7 +13,7 @@ By default Shopware 6 uses the [Vue I18n](https://kazupon.github.io/vue-i18n/sta ## Creating snippet files -Normally you use snippets in your custom module. To keep things organized, create a new directory named `snippet` inside module directory `/src/Resources/app/administration/src/module//snippet`. For each language you want to support, you need a JSON file inside it, e.g., `de-DE.json`, `en-GB.json`. For more details on selecting a fallback language and structuring your snippet files, see the [Fallback Languages guide](./../../../../../concepts/translations/fallback-language-selection). +Normally you use snippets in your custom module. To keep things organized, create a new directory named `snippet` inside module directory `/src/Resources/app/administration/src/module//snippet`. For each language you want to support, you need a JSON file inside it, e.g., `de-DE.json`, `en-GB.json`. For more details on selecting a fallback language and structuring your snippet files, see the [Fallback Languages guide](../../../../../concepts/translations/fallback-language-selection.md). ::: info Providing snippets for apps works the same as in plugins but it has a more simplistic file structure. Also, unlike plugins, App-Snippets **are not allowed** to override existing snippet keys. So, use the following path for vendor-prefixed app snippet files: `/Resources/app/administration/snippet` @@ -61,7 +61,7 @@ Component.register('my-custom-page', { }); ``` -Or use `Shopware.Snippet.tc('swag-example.general.myCustomText')` when `this` doesn't point to a component (see also [Vue3 upgrade](../../../../../resources/references/upgrades/administration/vue3.md)) +Or use `Shopware.Snippet.tc('swag-example.general.myCustomText')` when `this` doesn't point to a component (see also [Vue3 upgrade](../../../../upgrades-migrations/administration/vue3.md)). ## Using the snippets in templates diff --git a/guides/plugins/plugins/administration/templates-styling/using-assets.md b/guides/plugins/plugins/administration/templates-styling/using-assets.md index c199a81951..d4c137c5e6 100644 --- a/guides/plugins/plugins/administration/templates-styling/using-assets.md +++ b/guides/plugins/plugins/administration/templates-styling/using-assets.md @@ -1,11 +1,11 @@ --- nav: - title: Using assets + title: Using Assets position: 180 --- -# Using assets +# Using Assets ## Overview @@ -13,11 +13,7 @@ When working with an own plugin, the usage of own custom images or other assets ## Prerequisites -In order to be able to start with this guide, you need to have an own plugin running. As to most guides, this guide is also built upon the Plugin base guide: - - - -Needless to say, you should have your image or another asset at hand to work with. +Refer to the [plugin base guide](../../plugin-base-guide.md) to learn how to make a plugin. An image or other asset type is also required. ## Add custom assets @@ -36,10 +32,10 @@ In order to add your own custom assets, you need to save your assets in the `Res └── SwagBasicExample.php ``` -Similar as in [using custom assets in Storefront](../../storefront/add-custom-assets.md), you need to execute the following command: +Similar as in [using custom assets in Storefront](../../storefront/styling/add-custom-assets.md), you need to execute the following command: ```bash -// +// bin/console assets:install ``` diff --git a/guides/plugins/plugins/architecture/cart-process.md b/guides/plugins/plugins/architecture/cart-process.md index fa45cf927d..1c6aab500f 100644 --- a/guides/plugins/plugins/architecture/cart-process.md +++ b/guides/plugins/plugins/architecture/cart-process.md @@ -7,10 +7,25 @@ nav: # Cart Extension Architecture +The cart is recalculated multiple times per request to resolve dependencies between line items. Custom extensions must follow strict performance and determinism rules. + +## Design principles + +* Cart processing is multi-pass and must remain deterministic. +* Data loading must be separated from calculation to ensure stable performance. +* Price logic must be centralized and reusable. + ## Extension guidelines -* `CartProcessorInterface::process()` must not execute queries, as it runs multiple times per request to resolve the dependencies of the elements in the shopping cart. -* The `\Shopware\Core\Checkout\Cart\CartDataCollectorInterface::collect()` method must check whether the required data was already loaded. This is to avoid executing unnecessary queries on the database. loaded data will be appended to `CartDataCollection`. +* Use `CartDataCollector` to load external data once. +* Use `CartProcessor` to modify calculated items. +* Never perform database queries in `process()`. +* Always use `PriceCalculator` classes for price adjustments. + +## Technical rules + +* `CartProcessorInterface::process()` must not execute queries, as it runs multiple times per request. +* The `\Shopware\Core\Checkout\Cart\CartDataCollectorInterface::collect()` method must check whether data was already loaded and append it to `CartDataCollection`. This is to avoid having to execute unnecessarily many queries on the database. * Line items must be created via a `LineItemFactoryHandler` class. -* All price calculations and adjustments must take place via an appropriate `PriceCalculator`, which is stored inside the `Shopware\Core\Checkout\Cart\Price` class. +* All price calculations must use the `Shopware\Core\Checkout\Cart\Price` calculators, which are stored inside the `Shopware\Core\Checkout\Cart\Price` class. * Cart-related functions must be mapped via corresponding Store API routes in the `Shopware\Core\Checkout\Cart\SalesChannel` namespace. diff --git a/guides/plugins/plugins/architecture/context-rules-rule-systems.md b/guides/plugins/plugins/architecture/context-rules-rule-systems.md index c1bf8a361a..18f4005ce8 100644 --- a/guides/plugins/plugins/architecture/context-rules-rule-systems.md +++ b/guides/plugins/plugins/architecture/context-rules-rule-systems.md @@ -1,12 +1,30 @@ --- nav: - title: Context Rules & Rule Systems + title: Rule System Extension Architecture position: 40 --- -# Context Rules and Rule Systems +# Rule System Extension Architecture -* In a rule, there must never be a query against the database because all configured rules are validated in a request. -* Rules that check for the cart must always support the `\Shopware\Core\Checkout\Cart\Rule\CartRuleScope` class and the `\ Shopware\Core\Checkout\Cart\Rule\LineItemScope` class. -* Rules may only access data provided in the appropriate scopes. +Rules are evaluated synchronously during request handling. They must be deterministic and performant. Custom rule implementations must operate only on data already available in the evaluation context. + +## Design Principles + +* Rule evaluation must not introduce database queries, as all rules are evaluated during a request cycle. +* Rules must rely exclusively on the provided evaluation scope. +* Rule execution must be predictable and free of side effects. + +## Extension Guidelines + +* Never execute database queries inside rule classes. +* Use the provided rule scopes to access data. +* Do not mutate state during rule evaluation. +* Keep rule logic lightweight and computation-focused. + +## Technical requirements + +* Cart-related rules must support: + * the `\Shopware\Core\Checkout\Cart\Rule\CartRuleScope` class + * the `\Shopware\Core\Checkout\Cart\Rule\LineItemScope`class +* Rules may only access data exposed through their respective scope classes. diff --git a/guides/plugins/plugins/architecture/dependency-injection-dependency-handling.md b/guides/plugins/plugins/architecture/dependency-injection-dependency-handling.md index 4795ff3573..35c549e51d 100644 --- a/guides/plugins/plugins/architecture/dependency-injection-dependency-handling.md +++ b/guides/plugins/plugins/architecture/dependency-injection-dependency-handling.md @@ -7,4 +7,38 @@ nav: # Dependency Injection and Dependency Handling -Within the Core domain, it is not allowed to access the PHP session. There is only one PHP session if it is a storefront request. The appropriate implementation and consideration of session data must be handled in the Storefront domain. +Shopware separates responsibilities between domains (Core, Storefront, Administration). Plugins must respect these boundaries to ensure deterministic behavior, testability, and compatibility. + +## Domain separation + +The `Core` domain is framework-level logic. It must remain independent from HTTP state and presentation concerns. + +The `Storefront` domain handles HTTP requests, sessions, and customer interaction. + +## Core domain rules + +* The Core domain must never access the PHP session. +* Core services must not rely on request state. +* Business logic must remain stateless and deterministic. +* Dependencies must be injected via the service container. + +There is only one PHP session per storefront request. Session handling must be implemented in the Storefront domain and never inside Core services. + +## Extension guidelines + +When extending Core functionality: + +* Inject dependencies via the constructor. +* Avoid reading request data directly in Core classes. +* Avoid session access inside services registered in Core. +* Keep domain logic independent from HTTP concerns. +* Use Store API routes or Storefront controllers to bridge between HTTP/session state and Core services. + +Violating domain boundaries can lead to: + +* Unpredictable behavior in background jobs +* Broken CLI execution +* Inconsistent cart or rule evaluation +* Reduced testability + +Respecting these boundaries ensures stable, maintainable extensions. diff --git a/guides/plugins/plugins/architecture/events.md b/guides/plugins/plugins/architecture/events.md index 21129bde9b..f79260a76c 100644 --- a/guides/plugins/plugins/architecture/events.md +++ b/guides/plugins/plugins/architecture/events.md @@ -1,12 +1,32 @@ --- nav: - title: Events + title: Event Extension Architecture position: 70 --- -# Events +# Event Extension Architecture -* An event must always implement the `\Shopware\Core\Framework\Event\ShopwareEvent` interface. -* Events thrown in the context of a sales channel must always implement the interfaces `ShopwareSalesChannelEvent` and `Shopware\Core\Framework\Event\SalesChannelAware`. -* Events are mostly used to allow developers to load more data. They should, as a rule, not interfere with the program flow. The decoration pattern is intended to influence the program flow. +Events provide extension points for loading additional data or reacting to system changes. They are designed for observation and enrichment, not for altering core control flow. + +## Design Principles + +* Events expose extension points without breaking encapsulation. +* Events should not mutate core program flow. +* Business logic replacement must use decoration, not events. +* Events must remain predictable and side-effect aware. + +## Extension Guidelines + +* Use events to add data, not to override behavior. +* Avoid heavy computation or database queries inside event subscribers. +* Keep subscribers idempotent and deterministic. +* Prefer decoration when you need to change logic execution. + +## Technical Requirements + +* Events must always implement the `\Shopware\Core\Framework\Event\ShopwareEvent` interface. +* Sales channel events must implement these interfaces: + * `ShopwareSalesChannelEvent` + * `\Shopware\Core\Framework\Event\SalesChannelAware` +* Events are intended for enrichment and extension, not for control-flow modification. diff --git a/guides/plugins/plugins/architecture/pageloader.md b/guides/plugins/plugins/architecture/pageloader.md index 3c2b243e63..c1a91441e3 100644 --- a/guides/plugins/plugins/architecture/pageloader.md +++ b/guides/plugins/plugins/architecture/pageloader.md @@ -1,15 +1,36 @@ --- nav: - title: Page Loader + title: Page Loader Extension Architecture position: 80 --- -# Page Loader +# Page Loader Extension Architecture -* Pageloaders must be divided into appropriate domains that represent the different sections of the Storefront - "products", "account", etc. -* Each page loader must have an abstract class from which it derives (See [decoration pattern](../../../../resources/references/adr/2020-11-25-decoration-pattern.md)). This pattern can be used to replace the page loader in a project completely. -* Each page loader has a page object to return, in which all the necessary information for the page is present. -* At the end of each page loader, an individual `PageLoaded` event is thrown. Third-party developers can use this event to provide additional data. -* Page loaders are not allowed to work directly with repositories but are only allowed to load data via the Store API. This is to ensure that all storefront functionalities can also be accessed via the Store API. -* A Page object must always extend from the base `\Shopware\Storefront\Page\Page` class. +Page loaders assemble all data required to render a storefront page. They centralize data fetching and guarantee consistent storefront behavior. + +## Design principles + +* Page loaders separate HTTP concerns from business logic. +* Data must be fetched via Store API routes. +* Page loaders must remain replaceable via decoration. +* Pages must be fully constructed before rendering. + +## Extension guidelines + +* Divide page loaders by domains that represent different Storefront sections: e.g. products, account, checkout. +* Provide an abstract base class for [decoration](../../../../resources/references/adr/2020-11-25-decoration-pattern.md). The decoration pattern can be used to completely replace the page loader in a project. +* Return a dedicated page object containing all required data. +* Dispatch a corresponding `PageLoaded` event after loading. This event can be used to provide further data by third-party developers. +* Never access repositories directly inside a page loader. +* Use Store API routes for all data retrieval, to ensure that Store API can access all storefront functionalities. +* Page objects must extend from the base `\Shopware\Storefront\Page\Page` class. + +## Why this matters + +Page loaders guarantee that: + +* Storefront rendering remains deterministic. +* Data can be reused via the Store API. +* Extensions can replace or decorate page behavior safely. +* Rendering logic stays independent from database concerns. diff --git a/guides/plugins/plugins/bundle.md b/guides/plugins/plugins/bundle.md index 712e48e76c..8434d1bf6d 100644 --- a/guides/plugins/plugins/bundle.md +++ b/guides/plugins/plugins/bundle.md @@ -1,17 +1,50 @@ --- nav: - title: Bundle + title: Symfony Bundles position: 20 --- -# Bundle +# Using Symfony Bundles Instead of Plugins -Plugins are based on the Symfony bundle concept, but offer additional features like lifecycle events and the ability to be managed in the Shopware Administration. This may be undesirable for project-critical customizations that should always be active and not be managed through the Shopware Administration. In such cases, use a Symfony bundle instead of a plugin. +This guide handles some basic concepts of Shopware plugins covered in our [Plugin base guide](plugin-base-guide). You may want to have a look or refresh your knowledge on Symfony's [Bundle system](https://symfony.com/doc/current/bundles.html). + +::: info +Check out our [Shopware Toolbox PHPStorm extension](../../development/tooling/shopware-toolbox.md) with useful features like autocompletion, code generation or guideline checks. +::: + +You might use a Symfony bundle instead of a plugin when: + +* You do not need a plugin lifecycle +* You do not want Administration management +* You are building project-level customization +* You want pure Symfony integration + +A bundle is Symfony's preferred way to provide additional third-party features to any Symfony application. Those bundles are everywhere: Symfony even outsources many of its core features into external bundles. The template engine `Twig`, the `Security` bundle, the `WebProfiler`, as well as many other third-party bundles can be installed on demand to extend your Symfony application in any way. The Bundle System is Symfony's way of providing an extendable framework with plugin capabilities. + +## How Plugins extend bundles + +Shopware plugins extend Symfony bundles and add: + +* Plugin lifecycle (install, update, activate, uninstall) +* Automatic migration handling +* Asset building integration +* Administration management + +Class hierarchy: Plugin → Shopware\Bundle → Symfony\Bundle + +## When to use a bundle + +Use a pure Symfony bundle when: + +* You are customizing a single project +* You want no plugin lifecycle +* You manage everything via Composer +* You do not distribute the extension ## Project Structure -Here's how a typical Shopware 6 project structure looks like when using bundles: +How a typical Shopware 6 project structure looks when bundles are used: ```text project-root/ @@ -50,18 +83,14 @@ project-root/ The Bundle is typically placed in the `src/` folder of your project, which is the standard location for custom code in a Shopware project. You still will need to register the bundle in the `config/bundles.php` file of your project. -## Choosing the right Bundle class - -There are two Bundle classes you can choose from: +## Choosing the right bundle class -- `Shopware\Core\Framework\Bundle` -- `Symfony\Component\HttpKernel\Bundle\Bundle` +There are two bundle classes you can choose from: -The first one is the Shopware bundle class and the second one is the Symfony bundle class. -The Shopware bundle class extends the Symfony bundle class, but offers additional features like acting as theme, bringing JavaScript/CSS files, Migrations, etc. -If you don't need these features, you can use the Symfony bundle class instead. +* `Shopware\Core\Framework\Bundle`: the Shopware bundle class, which extends the Symfony bundle class with additional features like acting as theme, bringing JavaScript/CSS files, and migrations +* `Symfony\Component\HttpKernel\Bundle\Bundle`: the Symfony bundle class, which you can use if you don't need additional features -## Creating a Bundle +## Creating a bundle By default, The namespace `App\` is registered to the `src` folder in any Shopware project to be used for customizations. We recommend using this namespace, if you like to change the project structure, you can change the `App\` namespace in the `composer.json` file of your project. @@ -87,11 +116,9 @@ App\YourBundleName\YourBundleName::class => ['all' => true], //... ``` -## Adding services, Twig templates, routes, theme, etc +## Adding services, Twig templates, routes, and themes -You can add services, twig templates, routes, etc. to your bundle like you would do in a plugin. -Just create `Resources/config/services.php` and `Resources/config/routes.php` files or `Resources/views` for twig templates. -The bundle will be automatically detected and the files will be loaded. +You can add services, Twig templates, routes, etc. to your bundle like you would do in a plugin. Create `Resources/config/services.php` and `Resources/config/routes.php` files, or `Resources/views` for Twig templates. The bundle will be automatically detected and the files will be loaded. To mark your bundle as a theme, it's enough to implement the `Shopware\Core\Framework\ThemeInterface` interface in your bundle class. This will automatically register your bundle as a theme and make it available in the Shopware administration. @@ -99,8 +126,7 @@ You can also add a `theme.json` file to define the theme configuration like [des ## Adding migrations -Migrations are not automatically detected in bundles. -To enable migrations, you need to overwrite the `build` method in your bundle class like this: +Migrations are not automatically detected in bundles. To enable migrations, you need to overwrite the `build` method in your bundle class like this: ```php // /src/YourBundleName.php @@ -139,9 +165,9 @@ deployment: ## Integration into Shopware CLI -Shopware CLI cannot detect bundles automatically, therefore the assets of the bundles are not built automatically. -You will need to adjust the `composer.json` file of your project to specify the path to the bundle. -This is done by adding the `extra` section to the `composer.json` file: +The Shopware CLI cannot detect bundles automatically. Therefore, the assets of the bundles are not built automatically. +You will need to adjust your project's `composer.json` file of your project to specify the path to the bundle. +Do this by adding the `extra` section to the `composer.json` file: ```json { @@ -155,4 +181,20 @@ This is done by adding the `extra` section to the `composer.json` file: } ``` -This will tell Shopware CLI where the bundle is located and what the name of the bundle is. +This will tell Shopware CLI where the bundle is located and its name. + +## Next steps + +Now that you know about the differences between a Symfony bundle and a Shopware plugin, you might also want to have a look into the following Symfony-specific topics and how they are integrated in Shopware 6: + +* [Dependency Injection](../plugins/services/dependency-injection.md) +* [Listening to events](../plugins/framework/event/listening-to-events.md) + +::: info +Here are some useful videos explaining: + +* **[Bundle Methods in a plugin](https://www.youtube.com/watch?v=cUXcDwQwmPk)** +* **[Symfony services in Shopware 6](https://www.youtube.com/watch?v=l5QJ8EtilaY)** + +Also available on our free online training ["Shopware 6 Backend Development"](https://academy.shopware.com/courses/shopware-6-backend-development-with-jisse-reitsma). +::: diff --git a/guides/plugins/plugins/checkout/cart/add-cart-discounts.md b/guides/plugins/plugins/checkout/cart/add-cart-discounts.md index 04b6abedc9..1b80d6a987 100644 --- a/guides/plugins/plugins/checkout/cart/add-cart-discounts.md +++ b/guides/plugins/plugins/checkout/cart/add-cart-discounts.md @@ -1,6 +1,6 @@ --- nav: - title: Add cart discounts + title: Add Cart Discounts position: 30 --- @@ -9,13 +9,11 @@ nav: ## Overview -In this guide you'll learn how to create discounts for your cart. In this example, we will create a discount for products that have 'Example' in their name. +This guide explains how to create discounts for your cart. In this example, we will create a discount for products that have 'Example' in their name. ## Prerequisites -In order to create cart discounts for your plugin, you first need a plugin as base. Therefore, you can refer to the [Plugin Base Guide](../../plugin-base-guide). - -Furthermore you should be familiar with the service registration in Shopware, otherwise head over to our [Add custom service](../../plugin-fundamentals/add-custom-service) guide. +Refer to the [Plugin Base Guide](../../plugin-base-guide) for information on creating plugins, and to the [Add custom service](../../services/add-custom-service.md) guide for details on service registration. ## Creating the processor diff --git a/guides/plugins/plugins/checkout/cart/add-cart-items.md b/guides/plugins/plugins/checkout/cart/add-cart-items.md index 9e680e1d00..6597a17bc5 100644 --- a/guides/plugins/plugins/checkout/cart/add-cart-items.md +++ b/guides/plugins/plugins/checkout/cart/add-cart-items.md @@ -1,6 +1,6 @@ --- nav: - title: Add cart items + title: Add Cart Items position: 20 --- @@ -13,17 +13,17 @@ This guide will show you how to create line items like products, promotion and o ## Prerequisites -As most guides, this guide is also built upon the [Plugin base guide](../../plugin-base-guide), but you don't necessarily need that. It will use an example Storefront controller, so if you don't know how to add a custom Storefront controller yet, have a look at our guide about [Adding a custom page](../../storefront/add-custom-page). Furthermore, registering classes or services to the DI container is also not explained here, but it's covered in our guide about [Dependency injection](../../plugin-fundamentals/dependency-injection), so having this open in another tab won't hurt. +Review the [Plugin base guide](../../plugin-base-guide) for general information about plugins. The guides on [Adding a custom page](../../storefront/controllers/add-custom-page.md), which explains how to add a custom Storefront controller, and [Dependency injection](../../services/dependency-injection.md), which addresses registering classes or services to the DI container, are also recommended. ## Adding a simple item -For this guide, we will use an example controller, that is already registered. The process of creating such a controller is not explained here, for that case head over to our guide about [Adding a custom page](../../storefront/add-custom-page). +For this guide, we will use an example controller, that is already registered. The process of creating such a controller is not explained here, for that case head over to our guide about [Adding a custom page](../../storefront/controllers/add-custom-page.md). However, having a controller is not a necessity here, it just comes with the advantage of fetching the current cart by adding `\Shopware\Core\Checkout\Cart\Cart` as a method argument, which will automatically be filled by our argument resolver. If you're planning to use this guide for something else but a controller, you can fetch the current cart with the `\Shopware\Core\Checkout\Cart\SalesChannel\CartService::getCart` method. -So let's add an example product to the cart using code. For that case, you'll need to have access to both the services `\Shopware\Core\Checkout\Cart\LineItemFactoryRegistry` and `\Shopware\Core\Checkout\Cart\SalesChannel\CartService` supplied to your controller or service via [Dependency injection](../../plugin-fundamentals/dependency-injection). +So let's add an example product to the cart using code. For that case, you'll need to have access to both the services `\Shopware\Core\Checkout\Cart\LineItemFactoryRegistry` and `\Shopware\Core\Checkout\Cart\SalesChannel\CartService` supplied to your controller or service via [Dependency injection](../../services/dependency-injection.md). Let's have a look at an example. diff --git a/guides/plugins/plugins/checkout/cart/add-cart-validator.md b/guides/plugins/plugins/checkout/cart/add-cart-validator.md index 506fae05f8..5e1cfaf0ea 100644 --- a/guides/plugins/plugins/checkout/cart/add-cart-validator.md +++ b/guides/plugins/plugins/checkout/cart/add-cart-validator.md @@ -1,6 +1,6 @@ --- nav: - title: Add cart validator + title: Add Cart Validator position: 40 --- @@ -9,13 +9,13 @@ nav: ## Overview -The cart in Shopware is constantly being validated by so called "validators". This way we can check for an invalid cart, e.g. for invalid line items \(label missing\) or an invalid shipping address. +The cart in Shopware is continuously validated by so-called "validators" that check for invalid line items \(label missing\), shipping addresses, and other attributes. -This guide will cover the subject on how to add your own custom cart validator. +This guide explains how to add your own custom cart validator. ## Prerequisites -For this guide, you will need a working plugin, which you learn to create [here](../../plugin-base-guide). Also, you will have to know the [Dependency Injection container](../../plugin-fundamentals/dependency-injection), since that's going to be used in order to register your custom validator. +Review the [plugin base guide](../../plugin-base-guide) to create a plugin. Familiarity with the [Dependency Injection container](../../services/dependency-injection.md), which you will use to register your custom validator, is also necessary. ## Adding a custom cart validator @@ -72,7 +72,7 @@ Important to note is the `return` statement afterwards. If you wouldn't return h #### Registering the validator -One more thing to do is to register your new validator to the [dependency injection container](../../plugin-fundamentals/dependency-injection). +One more thing to do is to register your new validator to the [dependency injection container](../../services/dependency-injection.md). Your validator has to be registered using the tag `shopware.cart.validator`: @@ -176,7 +176,7 @@ Only the snippets are missing. ### Adding the snippet -First of all you should know our guide about [adding storefront snippets](../../storefront/add-translations), since that won't be explained in detail here. +Review the guide on [adding storefront snippets](../../storefront/styling/add-translations.md). You've defined the error key to be `custom-line-item-blocked` in your custom error class `CustomCartBlockedError`. Once your validator finds an invalid line item in your cart, Shopware is going to search for a respective snippet. In the cart, Shopware will be looking for the following snippet key: `checkout.custom-line-item-blocked`. Meanwhile it will be looking for a key `error.custom-line-item-blocked` in the checkout steps. This way you could technically define two different messages for the cart and the following checkout steps. @@ -200,4 +200,4 @@ And that's it, you've now successfully added your own cart validator. ## Next steps -In the examples mentioned above, we're asking for custom line item payloads. This subject is covered in our guide about [adding cart items](add-cart-items), so you might want to have a look at that. +Review the guide on [adding cart items](add-cart-items) for information on custom line-item payloads. diff --git a/guides/plugins/plugins/checkout/cart/change-price-of-item.md b/guides/plugins/plugins/checkout/cart/change-price-of-item.md index 946b821ed6..e56a48c484 100644 --- a/guides/plugins/plugins/checkout/cart/change-price-of-item.md +++ b/guides/plugins/plugins/checkout/cart/change-price-of-item.md @@ -1,15 +1,15 @@ --- nav: - title: Change price of items in cart + title: Change Price of Items in Cart position: 50 --- -# Change price of items in cart +# Change Price of Items in Cart ## Overview -This guide will tackle the issue of changing the price of a line item in the cart dynamically. The following example is **not** recommended if you want to add a discount / surcharge to your products. Make sure to check out the guide about [adding a discount into the cart](add-cart-discounts). +This guide will tackle the issue of changing the price of a line item in the cart dynamically. The following example is **not** recommended if you want to add a discount / surcharge to your products. Make sure to check out the guide about [adding a discount into the cart](add-cart-discounts.md). ::: warning Changing the price like it's done in the following example should rarely be done and only with great caution. A live-shopping plugin would be a good example about when to actually change an item's price instead of adding a discount / surcharge. @@ -19,7 +19,7 @@ Changing the price like it's done in the following example should rarely be done This guide is also built upon the [plugin base guide](../../plugin-base-guide), which creates a plugin first. The namespaces used in the examples of this guide match those of the plugin base guide, yet those are just examples. -Furthermore, you should know how to register a service to the [dependency injection container](../../plugin-fundamentals/dependency-injection). +Furthermore, you should know how to register a service to the [dependency injection container](../../services/dependency-injection.md). ## Changing the price @@ -125,7 +125,7 @@ Afterwards we're iterating over all product IDs, that still need to request a ne The last step is to save that new price to the `CartDataCollector`. -And that's it, we're now collecting the prices for our product line items. Registering the class to the [dependency injection container](../../plugin-fundamentals/dependency-injection) will be done in the [last section](change-price-of-item#Registering%20to%20DI%20container) of this guide. +And that's it, we're now collecting the prices for our product line items. Registering the class to the [dependency injection container](../../services/dependency-injection.md) will be done in the [last section](change-price-of-item#Registering%20to%20DI%20container) of this guide. ### The processor diff --git a/guides/plugins/plugins/checkout/cart/customize-price-calculation.md b/guides/plugins/plugins/checkout/cart/customize-price-calculation.md index a793082603..389dd1bc9e 100644 --- a/guides/plugins/plugins/checkout/cart/customize-price-calculation.md +++ b/guides/plugins/plugins/checkout/cart/customize-price-calculation.md @@ -1,29 +1,23 @@ --- nav: - title: Customize price calculation + title: Customize Price Calculation position: 60 --- # Customize Price Calculation -## Overview - -There are cases where you globally want to adjust the calculation of product prices. This can be achieved in Shopware by decorating a single service. - -This guide will cover this subject with a short example. +This guide explains how to globally adjust the calculation of product prices by decorating a single service, and includes a brief example. ## Prerequisites -As most guides, this guide is also built upon our [plugin base guide](../../plugin-base-guide), but it's not mandatory to use exactly that plugin as a foundation. The examples in this guide use the namespace however. - -Furthermore, you'll have to understand service decoration for this guide, so if you're not familiar with that, head over to our guide regarding [adjusting a service](../../plugin-fundamentals/adjusting-service). +Review the [plugin base guide](../../plugin-base-guide) and the guide on [adjusting a service](../../services/adjusting-service.md) for guidance on service decoration. ## Decorating the calculator In order to customize the price calculation for products as a whole, you'll have to decorate the service [ProductPriceCalculator](https://github.com/shopware/shopware/blob/trunk/src/Core/Content/Product/SalesChannel/Price/ProductPriceCalculator.php). It comes with a `calculate` method, which you can decorate and therefore customize. -So let's do that real quick. If you're looking for an in-depth explanation, head over to our guide about [adjusting a service](../../plugin-fundamentals/adjusting-service). +So let's do that real quick. If you're looking for an in-depth explanation, head over to our guide about [adjusting a service](../../services/adjusting-service.md). Here's an example decorated calculator: diff --git a/guides/plugins/plugins/checkout/cart/tax-provider.md b/guides/plugins/plugins/checkout/cart/tax-provider.md index 3fd9d9683a..a636996572 100644 --- a/guides/plugins/plugins/checkout/cart/tax-provider.md +++ b/guides/plugins/plugins/checkout/cart/tax-provider.md @@ -1,11 +1,11 @@ --- nav: - title: Tax provider + title: Tax Provider position: 70 --- -# Tax provider +# Tax Provider ## Overview @@ -15,7 +15,7 @@ With version 6.5.0.0, Shopware allows plugins to integrate custom tax calculatio ## Prerequisites -Refer to [plugin base guide](../../plugin-base-guide). It is not mandatory to use exactly the same plugin as a foundation. +Refer to the [plugin base guide](../../plugin-base-guide). It is not mandatory to use exactly the same plugin as a foundation. ## Creating a tax provider @@ -106,7 +106,7 @@ To let Shopware know of your new tax provider, you will have to persist it to th ### Via migration -You may want to have a look at the [migration guide](../../plugin-fundamentals/database-migrations) to learn more about migrations. +You may want to have a look at the [migration guide](../../database/database-migrations.md) to learn more about migrations. ```php // /src/Migration/MigrationTaxProvider.php @@ -155,11 +155,11 @@ class MigrationTaxProvider extends MigrationStep ### Via repository -You may want to have a look at the [repository guide](../../../../../concepts/framework/data-abstraction-layer#crud-operations) to learn more on how to use the entity repository to manipulate data. +The [repository guide](../../../../../concepts/framework/data-abstraction-layer#crud-operations) explains how to use the entity repository to manipulate data. A good place for persisting your tax provider to the database would be the `install` lifecycle method of your plugin. -If you do not know of plugin lifecycle methods yet, please refer to our [plugin lifecycle guide](../../plugin-fundamentals/plugin-lifecycle). +The [plugin lifecycle guide](../../plugin-fundamentals/plugin-lifecycle.md) provides more information about plugin lifecycle methods. ```php // /src/BasicExample.php diff --git a/guides/plugins/plugins/checkout/document/add-custom-document-type.md b/guides/plugins/plugins/checkout/document/add-custom-document-type.md index d85fbcf68b..cf2d16e4cd 100644 --- a/guides/plugins/plugins/checkout/document/add-custom-document-type.md +++ b/guides/plugins/plugins/checkout/document/add-custom-document-type.md @@ -1,6 +1,6 @@ --- nav: - title: Add custom document type + title: Add Custom Document Type position: 20 --- @@ -13,9 +13,7 @@ This guide will show you how to add a custom document type to your plugin. This ## Prerequisites -This guide is built upon the [plugin base guide](../../plugin-base-guide), but of course you can use those examples with any other plugin. - -Furthermore, adding a custom document type via your plugin is done by using [plugin database migrations](../../plugin-fundamentals/database-migrations). Since this isn't explained in this guide, you will have to know and understand the plugin database migrations first. +Reviewing the [plugin base guide](../../plugin-base-guide) and the guide on [plugin database migrations](../../database/database-migrations.md) is advisable. ## Adding a custom document type and its own base configuration to the database @@ -170,9 +168,9 @@ Your custom document renderer has to implement the `Shopware\Core\Checkout\Docum * `supports`: Has to return a string of the document type it supports. We named our document type "**example**", so our renderer has to return "**example**". * `render`: This needs to return the instance `Shopware\Core\Checkout\Document\Renderer\RendererResult`, which will contain the instance of `Shopware\Core\Checkout\Document\Renderer\RenderedDocument` based on each `orderId`. You will have access to the array of `DocumentGenerateOperation` which contains all respective orderIds, the context and the instance of `Shopware\Core\Checkout\Document\Renderer\DocumentRendererConfig` (additional configuration). -Furthermore, your renderer has to be registered to the [service container](../../plugin-fundamentals/dependency-injection) using the tag `document.renderer`. +Furthermore, your renderer has to be registered to the [service container](../../services/dependency-injection.md) using the tag `document.renderer`. -Let's have a look at an example renderer: +An example renderer: ::: code-group @@ -407,7 +405,7 @@ Note that we're using the tag `document.renderer` to register our custom documen ### Adding a document type template -Let's have a quick look at an example document type template. Go ahead and create a new file at the path `/src/Resources/views/documents/example_document.html.twig`. +Let's have a quick look at an example document type template. Create a new file at the path `/src/Resources/views/documents/example_document.html.twig`. In there, you should extend from the default document base template: @@ -419,13 +417,13 @@ In there, you should extend from the default document base template: ::: -This could be it already. The [base.html.twig](https://github.com/shopware/shopware/blob/v6.3.4.1/src/Core/Framework/Resources/views/documents/base.html.twig) template comes with a lot of default templating, which you can now override by using blocks. If you don't know how that's done, have a look at our guide regarding [customizing templates](../../storefront/customize-templates). +The [base.html.twig](https://github.com/shopware/shopware/blob/v6.3.4.1/src/Core/Framework/Resources/views/documents/base.html.twig) template comes with a default templating, which you can now override by using blocks. The guide on [customizing templates](../../storefront/templates/customize-templates.md) provides more details. ## Adding a number range You are almost done here. You have a new document type in the database, a renderer for your new document type, and it even uses a custom template. However, you also need to add a new number range for your documents; otherwise, a new number wouldn't be generated for your documents. -Adding a new number range is also done by using a [plugin database migration](../../plugin-fundamentals/database-migrations). +Adding a new number range is also done by using a [plugin database migration](../../database/database-migrations.md). For this we need a few more things: diff --git a/guides/plugins/plugins/checkout/document/add-custom-document.md b/guides/plugins/plugins/checkout/document/add-custom-document.md index 568bf3d14a..ed88f0386a 100644 --- a/guides/plugins/plugins/checkout/document/add-custom-document.md +++ b/guides/plugins/plugins/checkout/document/add-custom-document.md @@ -1,6 +1,6 @@ --- nav: - title: Add custom document + title: Add Custom Document position: 10 --- @@ -9,13 +9,11 @@ nav: ## Overview -Using the Shopware Administration, you can easily create new documents. This guide will teach you how to achieve the same result, which is creating a new document, using your plugin. +Using the Shopware Administration, you can easily create new documents. This guide explains how to create a new document using a plugin. ## Prerequisites -This guide is built upon the [plugin base guide](../../plugin-base-guide), but of course you can use those examples with any other plugin. - -Furthermore adding a document via your plugin is done by using [plugin database migrations](../../plugin-fundamentals/database-migrations). Since this isn't explained in this guide, you'll have to know and understand the plugin database migrations first. +Reviewing the [plugin base guide](../../plugin-base-guide) and the guide on [plugin database migrations](../../database/database-migrations.md) is advisable. ## Adding a custom document @@ -140,4 +138,4 @@ Basically, that's it already! You can now browse your Administration and use you ## Next steps -You might wonder "But where do I define my custom template for my custom document?". This is done by adding a new document **type**, which is covered in [this guide](add-custom-document-type). +Defining custom templates for custom documents is possible by adding a new document **type**, as explained in [the Add Custom Document Type guide](add-custom-document-type). diff --git a/guides/plugins/plugins/checkout/order/listen-to-order-changes.md b/guides/plugins/plugins/checkout/order/listen-to-order-changes.md index 3b7ec3b531..b315bacca9 100644 --- a/guides/plugins/plugins/checkout/order/listen-to-order-changes.md +++ b/guides/plugins/plugins/checkout/order/listen-to-order-changes.md @@ -1,6 +1,6 @@ --- nav: - title: Listen to order changes + title: Listen to Order Changes position: 20 --- @@ -14,7 +14,7 @@ This guide will teach you how to react to order changes, e.g. changes to the ord ## Prerequisites This guide is built upon our [plugin base guide](../../plugin-base-guide) and uses the same namespaces as the said plugin. -Also, since we're trying to listen to an event in this guide, you need to know about [subscribers](../../plugin-fundamentals/listening-to-events). +Also, since we're trying to listen to an event in this guide, you need to know about [subscribers](../../framework/event/listening-to-events.md). ## Listening to the event diff --git a/guides/plugins/plugins/checkout/order/using-the-state-machine.md b/guides/plugins/plugins/checkout/order/using-the-state-machine.md index 648ca9cd92..73e26eacc9 100644 --- a/guides/plugins/plugins/checkout/order/using-the-state-machine.md +++ b/guides/plugins/plugins/checkout/order/using-the-state-machine.md @@ -1,6 +1,6 @@ --- nav: - title: Using the state machine + title: Using the State Machine position: 10 --- @@ -23,7 +23,7 @@ Each of those states can be changed using the [StateMachineRegistry](https://git This section will cover an example for each kind of order state, for the order itself, the transaction \(aka payment\) and delivery. -For each example you have to inject the `Shopware\Core\System\StateMachine\StateMachineRegistry` into your service using the [Dependency Injection container](../../plugin-fundamentals/dependency-injection). +For each example you have to inject the `Shopware\Core\System\StateMachine\StateMachineRegistry` into your service using the [Dependency Injection container](../../services/dependency-injection.md). You then execute the method `transition` on the said `StateMachineRegistry`. It expects two parameters: @@ -129,7 +129,7 @@ Let's have a look at an example: $transitions = $this->stateMachineRegistry->getAvailableTransitions( OrderDefinition::ENTITY_NAME, '', - 'stateId', + 'stateId', $context ); ``` @@ -157,7 +157,7 @@ public function setOrderDeliveryToShipped(string $orderId, $context): void } ``` -So this example is making use of the repository for the `order_delivery` entity. It was injected previous using the [Dependency injection container](../../plugin-fundamentals/dependency-injection) and its respective ID `order_delivery.repository`. +So this example is making use of the repository for the `order_delivery` entity. It was injected previous using the [Dependency injection container](../../services/dependency-injection.md) and its respective ID `order_delivery.repository`. Then it's creating a new `Criteria` object and adds a filter in order to only search for `order_delivery` entities, whose order ID equals our given order ID. diff --git a/guides/plugins/plugins/checkout/payment/add-payment-plugin.md b/guides/plugins/plugins/checkout/payment/add-payment-plugin.md index 905c0c71a0..6e99b433d4 100644 --- a/guides/plugins/plugins/checkout/payment/add-payment-plugin.md +++ b/guides/plugins/plugins/checkout/payment/add-payment-plugin.md @@ -1,6 +1,6 @@ --- nav: - title: Add payment plugin + title: Add Payment Plugin position: 10 --- @@ -8,7 +8,7 @@ nav: # Add Payment Plugin ::: warning -From Shopware 6.7.0.0, the payment handling is refactored and is done via a single `AbstractPaymentHandler`. +From Shopware 6.7.0.0, payment handling is done with a single `AbstractPaymentHandler`. ::: ## Overview @@ -20,7 +20,7 @@ That's why Shopware 6 offers an easy platform on which you can build payment plu The examples mentioned in this guide are built upon our plugin base guide. - + If you want to understand the payment process in detail, head to our Payment Concept. @@ -34,7 +34,7 @@ Shopware provides you with a handy `Shopware\Core\Checkout\Payment\Cart\PaymentH ### Registering the service -Before we're going to have a look at some examples, we need to register our new service to the [Dependency Injection](../../plugin-fundamentals/dependency-injection) container. +Before we're going to have a look at some examples, we need to register our new service to the [Dependency Injection](../../services/dependency-injection.md) container. Please make sure to add the `shopware.payment.method` tag to your service definition, otherwise Shopware won't recognize your service as a payment handler. We'll use a class called `MyCustomPaymentHandler` here. diff --git a/guides/plugins/plugins/checkout/payment/customize-payment-provider.md b/guides/plugins/plugins/checkout/payment/customize-payment-provider.md index e3278b3798..ab6f07bd4e 100644 --- a/guides/plugins/plugins/checkout/payment/customize-payment-provider.md +++ b/guides/plugins/plugins/checkout/payment/customize-payment-provider.md @@ -1,6 +1,6 @@ --- nav: - title: Customize payment provider + title: Customize Payment Provider position: 20 --- @@ -9,14 +9,11 @@ nav: ## Overview -In this guide you'll learn how to customize an existing payment provider. -In this example we are customizing a synchronous payment flow, but the procedure also applies to an asynchronous approach. +This guide covers how to customize an existing payment provider. In this example we are customizing a synchronous payment flow, but the procedure also applies to an asynchronous approach. ## Prerequisites -As most guides, this guide is also built upon the [Plugin base guide](../../plugin-base-guide), but you don't necessarily need that. -It is helpful to have looked at the guide about [adding a custom payment method](add-payment-plugin) beforehand. -Furthermore, decorating a service is also not explained here, but it's covered in our guide about [adjusting a service](../../plugin-fundamentals/adjusting-service), so having this open in another tab won't hurt. +Review the [Plugin base guide](../../plugin-base-guide). The guides for [adding a custom payment method](add-payment-plugin) and [adjusting a service](../../services/adjusting-service.md), which provides information about decorating services, are also helpful. ## Customize the payment provider diff --git a/guides/plugins/plugins/content/mail/add-data-to-mails.md b/guides/plugins/plugins/content/mail/add-data-to-mails.md index 91007874ff..96134fbdb5 100644 --- a/guides/plugins/plugins/content/mail/add-data-to-mails.md +++ b/guides/plugins/plugins/content/mail/add-data-to-mails.md @@ -1,6 +1,6 @@ --- nav: - title: Add data to mails + title: Add Data to Mails position: 10 --- @@ -17,11 +17,11 @@ This guide will teach you how to add new data to the mail templates using your p This guide is built upon our [plugin base guide](../../plugin-base-guide), whose namespace is going to be used in the examples of this guide. However, you can use those examples with any plugin, you'll just have to adjust the namespace and the directory the files are located in. -Furthermore, you should know how to [decorate a service](../../plugin-fundamentals/adjusting-service). +Furthermore, you should know how to [decorate a service](../../services/adjusting-service.md). ## Adding data via decorator -In order to add new data to the mail templates, you'll have to decorate the [MailService](https://github.com/shopware/shopware/blob/trunk/src/Core/Content/Mail/Service/MailService.php). +To add new data to the mail templates, decorate the [MailService](https://github.com/shopware/shopware/blob/trunk/src/Core/Content/Mail/Service/MailService.php). To be precise, you have to extend the `send` method, whose last parameter is the `$templateData`, that we want to enrich. @@ -66,7 +66,7 @@ class AddDataToMails extends AbstractMailService ::: -If you don't recognise the decoration pattern used here, make sure to have a look at our guide about [decorations](../../plugin-fundamentals/adjusting-service). +If you don't recognise the decoration pattern used here, make sure to have a look at our guide about [decorations](../../services/adjusting-service.md). As always, we're passing in the original `MailService` as a constructor parameter, so we can return it in the `getDecorated` method, as well as use the original `send` method after having adjusted the `$templateData`. @@ -142,11 +142,9 @@ class MyMailSubscriber implements EventSubscriberInterface } ``` -::: - -### Register your event subscriber +### Register the event subscriber -You have to register the subscriber to the service container as well. +Register the subscriber to the service container. Here's the respective example `services.php`: diff --git a/guides/plugins/plugins/content/mail/add-mail-template.md b/guides/plugins/plugins/content/mail/add-mail-template.md index a2b85259a4..6430a2e99e 100644 --- a/guides/plugins/plugins/content/mail/add-mail-template.md +++ b/guides/plugins/plugins/content/mail/add-mail-template.md @@ -1,6 +1,6 @@ --- nav: - title: Add mail templates + title: Add Mail Templates position: 20 --- @@ -17,7 +17,7 @@ This guide will cover how to add a custom mail template with your plugin. The namespaces used in the examples of this guide are the same as the namespace from our [Plugin base guide](../../plugin-base-guide), so you might want to have a look at it first. -Furthermore, this guide will use [Database migrations](../../plugin-fundamentals/database-migrations) in order to add a custom mail template, which is not explained in depth here. Make sure to understand those first! +Furthermore, this guide will use [Database migrations](../../database/database-migrations.md) in order to add a custom mail template, which is not explained in depth here. Make sure to understand those first! ## Adding a mail template via migration @@ -131,7 +131,7 @@ class Migration1616418675AddMailTemplate extends MigrationStep ]); } - if (!empty($deDeLangId)) { + if (!empty($deDeLangId)) { $connection->executeStatement(" INSERT IGNORE INTO `mail_template_translation` (mail_template_id, language_id, sender_name, subject, description, content_html, content_plain, created_at) diff --git a/guides/plugins/plugins/content/mail/index.md b/guides/plugins/plugins/content/mail/index.md index 9a3390a6b2..59bfa6a0c9 100644 --- a/guides/plugins/plugins/content/mail/index.md +++ b/guides/plugins/plugins/content/mail/index.md @@ -7,7 +7,7 @@ nav: # Mail -Shopware Mail offers the ability to add mail data and configure mail templates for various email communications within the e-commerce platform. You can add relevant mail data such as transactional emails, order notifications, customer communication, marketing campaigns, or newsletters. These emails can be tailored to specific events or triggers, ensuring timely and personalized communication with customers. +Shopware Mail offers the ability to add mail data and configure mail templates for various email communications within the e-commerce platform. You can add relevant mail data such as transactional emails, order notifications, customer communication, marketing campaigns, or newsletters. These emails can be tailored to specific events or triggers, ensuring timely and personalized communication with customers. The plugin provides the functionality to create and customize these mail templates. Users can design and format the content of their emails, including text, images, logos, and dynamic variables, to personalize the messages. This allows for consistent branding and a professional appearance across all outgoing emails. diff --git a/guides/plugins/plugins/content/media/add-custom-file-extension.md b/guides/plugins/plugins/content/media/add-custom-file-extension.md index 2441821a08..a3870a4082 100644 --- a/guides/plugins/plugins/content/media/add-custom-file-extension.md +++ b/guides/plugins/plugins/content/media/add-custom-file-extension.md @@ -1,29 +1,27 @@ --- nav: - title: Add custom media extension + title: Add Custom Media File Extensions position: 20 --- -# Add Custom Media File Extension +# Add Custom Media File Extensions -You might have come across the fact that you cannot just upload any type of media to Shopware by using the Media -module in the Administration. -If that's the case for you, this guide will be the solution. -It will explain how to add new allowed file extensions to Shopware using a plugin. +Not all media types can be uploaded to Shopware with the Administration's Media module. This guide explains how to use plugins to add custom media file extensions. ## Prerequisites -As most of our plugin guides, this guide was also built upon our [Plugin base guide](../../plugin-base-guide). -Furthermore, you'll have to know about adding classes to the [Dependency injection](../../plugin-fundamentals/dependency-injection) container -and about using a subscriber to [Listen to events](../../plugin-fundamentals/listening-to-events). +Review these guides before proceeding: + +- [Plugin base guide](../../plugin-base-guide) +- [Dependency injection](../../services/dependency-injection.md), to learn how to add classes to the container +- [Listen to events](../../framework/event/listening-to-events.md), for guidance on using subscribers ## Adding a custom extension In this section, we're going to allow a new extension to Shopware first, without letting Shopware know exactly what kind of file this new extension represents (Images, videos, documents, etc.). -For this to work, all you have to do is register for the `MediaFileExtensionWhitelistEvent` event, which can be found [here](https://github.com/shopware/shopware/blob/v6.4.0.0/src/Core/Content/Media/File/FileSaver.php#L397-L398). -This is, of course, done via a [subscriber](../../plugin-fundamentals/listening-to-events). +For this to work, use a [subscriber](../../framework/event/listening-to-events.md) to register for the `MediaFileExtensionWhitelistEvent` event found [here](https://github.com/shopware/shopware/blob/v6.4.0.0/src/Core/Content/Media/File/FileSaver.php#L397-L398). Have a look at the following code example: @@ -150,8 +148,7 @@ Make sure to add flags to your media type, e.g., the `transparent` flag, or if i You can find all available flags in their respective media type classes, e.g. [here](https://github.com/shopware/shopware/blob/v6.4.0.0/src/Core/Content/Media/MediaType/ImageType.php#L7-L10) for the image media type. -Make sure to register your new type detector to the [Dependency injection container](../../plugin-fundamentals/dependency-injection) -by using the tag `shopware.media_type.detector`. +Make sure to register your new type detector to the [Dependency injection container](../../services/dependency-injection.md) by using the tag `shopware.media_type.detector`. Shopware will now recognise your new image extension and handle your new file like an image. diff --git a/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md b/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md index 756d76fc11..279d4c8a7e 100644 --- a/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md +++ b/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md @@ -1,20 +1,21 @@ --- nav: - title: Prevent Deletion of Media Files Referenced in your Plugins + title: Prevent Deletion of Media Files Referenced in Plugins position: 10 --- -# Prevent Deletion of Media Files Referenced in your Plugins +# Prevent Deletion of Media Files Referenced in Plugins ::: info -The ability to prevent Media entities from being deleted is available since Shopware 6.5.1.0. +Preventing media entities from being deleted has been possible since Shopware 6.5.1.0. ::: ## Overview -The Shopware CLI application provides a `media:delete-unused` command, which deletes all media entities and their corresponding files that are not used in your application. -Not used means that it is not referenced by any other entity. This works well in the simple case that all your entity definitions store references to Media entities with correct foreign keys. +The Shopware CLI provides a `media:delete-unused` command that deletes all media entities and corresponding files that are not used in your application. + +"Not used" means that it is not referenced by any other entity. This works well in the simple case that all your entity definitions store references to Media entities with correct foreign keys. However, this does not cover all the possible cases, even for many internal Shopware features. For example, the CMS entities store their configuration as JSON blobs with references to Media IDs stored in a nested data structure. @@ -25,8 +26,7 @@ If you are developing an extension that references Media entities, and you canno ## Prerequisites As most of our plugin guides, this guide was also built upon our [Plugin base guide](../../plugin-base-guide). -Furthermore, you'll have to know about adding classes to the [Dependency injection](../../plugin-fundamentals/dependency-injection) container -and about using a subscriber to [Listen to events](../../plugin-fundamentals/listening-to-events). +Furthermore, you'll have to know about adding classes to the [Dependency injection](../../services/dependency-injection.md) container and about using a subscriber to [Listen to events](../../framework/event/listening-to-events.md). ## The deletion process @@ -122,7 +122,7 @@ We check whether there are any references to the Media IDs from the event in the Finally, we return all the IDs of Media used in the slider config so they are not deleted. -Make sure to register your event subscriber to the [Dependency injection container](../../plugin-fundamentals/dependency-injection) +Make sure to register your event subscriber to the [Dependency injection container](../../services/dependency-injection.md) by using the tag `kernel.event_subscriber`. diff --git a/guides/plugins/plugins/content/seo/add-custom-seo-url.md b/guides/plugins/plugins/content/seo/add-custom-seo-url.md index 310305b4f1..42e74ad8b8 100644 --- a/guides/plugins/plugins/content/seo/add-custom-seo-url.md +++ b/guides/plugins/plugins/content/seo/add-custom-seo-url.md @@ -1,42 +1,33 @@ --- nav: - title: Add custom SEO URLs + title: Add Custom SEO URLs position: 10 --- -# Add custom SEO URLs +# Add Custom SEO URLs ## Overview -Every good website had to deal with it at some point: SEO URLs. Of course Shopware supports the usage of SEO URLs, e.g. for products or categories. - -This guide however will cover the question on how you can define your own SEO URLs, e.g. for your own custom entities. This will include both static SEO URLs, as well as dynamic SEO URLs. +Shopware supports SEO URL usage for products, categories, and other entities. This guide covers how to define both static and dynamic custom SEO URLs for custom entities. ## Prerequisites -As every almost every guide in the plugins section, this guide as well is built upon the plugin base guide. +Review the plugin base guide: -Furthermore, we're going to use a [Custom storefront controller](../../storefront/add-custom-controller) for the static SEO URL example, as well as [Custom entities](../../framework/data-handling/add-custom-complex-data) for the dynamic SEO URLs. Make sure you know and understand those two as well before diving deeper into this guide. Those come with two different solutions: - -* Using [plugin migrations](../../plugin-fundamentals/database-migrations) for static SEO URLs -* Using [DAL events](../../framework/data-handling/using-database-events) to react on entity changes and therefore generating a dynamic SEO URL - -## Custom SEO URLs - -As already mentioned in the overview, this guide will be divided into two parts: Static and dynamic SEO URLs. +It is also important to understand [Custom storefront controllers](../../storefront/controllers/add-custom-controller.md) and [plugin migrations](../../database/database-migrations.md), which are relevant to the static SEO URL example, and [Custom entities](../../framework/data-handling/add-custom-complex-data.md) and [DAL event](../../framework/data-handling/replacing-associated-data.md) usage for dynamic SEO URLs. -### Static SEO URLs +## Static SEO URLs A static SEO URL doesn't have to change every now and then. Imagine a custom controller, which is accessible via the link `yourShop.com/example`. -Now if you want this URL to be translatable, you'll have to add a custom SEO URL to your controller route, so it is accessible using both `Example-Page` in English, as well as e.g. `Beispiel-Seite` in German. +To make this URL translatable, add a custom SEO URL to the controller route so it is accessible using both `Example-Page` in English and`Beispiel-Seite` in German. -#### Example controller +### Example controller -For this example, the controller from the [Add custom controller guide](../../storefront/add-custom-controller) is being used. It creates a controller with a route like the example mentioned above: `/example` +This example uses the controller from the [Add custom controller guide](../../storefront/controllers/add-custom-controller.md). It creates a controller with a route like the example mentioned above: `/example` Let's now have a look at our example controller: @@ -69,9 +60,9 @@ class ExampleController extends StorefrontController The important information you'll need here is the route name, `frontend.example.example`, as well as the route itself: `/example`. Make sure to remember those for the next step. -#### Example migration +### Example migration -Creating a SEO URL in this scenario can be achieved by creating a [plugin migration](../../plugin-fundamentals/database-migrations). +Creating a SEO URL in this scenario can be achieved by creating a [plugin migration](../../database/database-migrations.md). The migration has to insert an entry for each sales channel and language into the `seo_url` table. For this case, we're making use of the `ImportTranslationsTrait`, which comes with a helper method `importTranslation`. @@ -150,25 +141,25 @@ SQL; } ``` -You might want to have a look at the `getSeoMetaArray` method, that we implemented here. Most important for you are the columns `route_name` and `path_info` here, which represent the values you've defined in your controller's route attributes. +Consider reviewing the `getSeoMetaArray` method, implemented here. Most important are the columns `route_name` and `path_info`, which represent the values you've defined in your controller's route attributes. By using the default PHP method `array_merge`, we're then also adding our translated SEO URL to the column `seo_path_info`. -And that's it! After installing our plugin, you should now be able to access your controller's route with the given SEO URLs. +And that's it! After installing the plugin, you should be able to access your controller's route with the given SEO URLs. ::: info You can only access the German SEO URL if you've configured a German domain in your respective sales channel first. ::: -### Dynamic SEO URLs +## Dynamic SEO URLs Dynamic SEO URLs are URLs, that have to change every now and then. Yet, there's another separation necessary. If you're going to generate custom SEO URLs for your custom entities, you'll have to follow the section about [Dynamic SEO URLs for entities](add-custom-seo-url#dynamic-seo-urls-for-entities). For all other kinds of dynamic content, that are not DAL entities, the section about [Dynamic SEO URLs for other content](add-custom-seo-url#dynamic-seo-urls-for-custom-content) is your way to go. -#### Dynamic SEO URLs for entities +### Dynamic SEO URLs for entities -This scenario will be about a custom entity, to be specific we're going to use the entity from our guide about [adding custom complex data](../../framework/data-handling/add-custom-complex-data), which then would have a custom Storefront route for each entity. +This scenario will be about a custom entity, to be specific we're going to use the entity from our guide about [adding custom complex data](../../framework/data-handling/add-custom-complex-data.md), which then would have a custom Storefront route for each entity. Each entity comes with a name, which eventually should be the SEO URL. Thus, your entity named `Foo` should be accessible using the route `yourShop.com/Foo` or `yourShop.com/Entities/Foo` or whatever you'd like. Now, everytime you create a new entity, a SEO URL has to be automatically created as well. When you update your entities' name, guess what, you'll have to change the SEO URL as well. @@ -295,9 +286,9 @@ It then has to be registered to the container using the tag `shopware.seo_url.ro Now that you've set up this class, there are two more things to be done, which are covered in the next sections. -**Example subscriber** +### Example subscriber -Every time your entity is written now, you have to let Shopware know, that you want to generate the SEO URLs for those entities now. This is done by reacting to the [DAL events](../../framework/data-handling/using-database-events) of your custom entity, to be specific we're going to use the `written` event. Everytime your entity is written, you then have to execute the `update` method of the `Shopware\Core\Content\Seo\SeoUrlUpdater` class. +Every time your entity is written now, you have to let Shopware know, that you want to generate the SEO URLs for those entities now. This is done by reacting to the [DAL events](../../framework/data-handling/using-database-events.md) of your custom entity, to be specific we're going to use the `written` event. Everytime your entity is written, you then have to execute the `update` method of the `Shopware\Core\Content\Seo\SeoUrlUpdater` class. Once again, let's have a look at an example subscriber here: @@ -369,9 +360,9 @@ As already said, we're using the `written` event of our custom entity by providi The `SeoUrlUpdater` will need one more thing in order to work properly: An entry in the table `seo_url_template`, which is done in the next step. -**Example SeoUrlTemplate migration** +### Example `SeoUrlTemplate` migration -Now we need to add an entry to the `seo_url_template` table for our new dynamic SEO URL template. This is done by adding a [database migration](../../plugin-fundamentals/database-migrations) to our plugin. +Now we need to add an entry to the `seo_url_template` table for our new dynamic SEO URL template. This is done by adding a [database migration](../../database/database-migrations.md) to our plugin. The most important values you'll have to set in the migration are: @@ -421,10 +412,10 @@ class Migration1619514731AddExampleSeoUrlTemplate extends MigrationStep And that's it! Every time your entity is written now, you'll automatically generate a SEO URL for it. ::: info -This guide will not cover creating an actual controller with the used example route. Learn how that is done in our guide about [creating a storefront controller](../../storefront/add-custom-controller). +Review the guide on [creating a storefront controller](../../storefront/controllers/add-custom-controller.md) to learn how to create a controller with the used example route. ::: -**Reacting to entity deletion** +### Reacting to entity deletion If your entity is deleted, you want the SEO URL to be updated as well. In detail, the column `is_deleted` of the respective entry in the `seo_url` table has to be set to `1`. @@ -463,7 +454,7 @@ class DynamicSeoUrlPageSubscriber implements EventSubscriberInterface } ``` -#### Dynamic SEO URLs for custom content +### Dynamic SEO URLs for custom content This section is specifically about dynamic content other than custom entities. This could be e.g. data from an external resource, maybe external APIs. @@ -471,7 +462,7 @@ You'll need some kind of event or some other way to execute code once your dynam In this example, we'll assume you've got a class called `DynamicSeoUrlsService` with a method `writeSeoEntries`. This method will get an array of entries to be written, including their respective payload, such as a name for the SEO URL. It also needs the current context. -Calling this method is up to you, depending on your set up and the type of "dynamic content" you're having. +Calling this method depends on your setup and the type of "dynamic content." This method will then use the `SeoUrlPersister` and its method `updateSeoUrls` in order to write entries to the `seo_url` table. @@ -556,12 +547,12 @@ The method `writeSeoEntries` will look for a Storefront sales channel and return * `seoPathInfo`: The actual SEO path you want to use - in this case the name of the said content ::: info -This guide will not cover creating an actual controller with the used example route. Learn how that is done in our guide about [creating a storefront controller](../../storefront/add-custom-controller). +The [creating a storefront controller](../../storefront/controllers/add-custom-controller.md) guide covers how to create a controller with the example route used here. ::: It will then use the built array and all of the other information like the context, the route name and an array of foreign keys for the method `updateSeoUrls` of the `SeoUrlPersister`. And that's it for your dynamic content. -#### Reacting to deletion of the content +## Reacting to content deletion If your custom dynamic content is deleted, you have to set the column `is_deleted` to `1` of the respective `seo_url` entry. This can be achieved with a new method, in this example we'll call it `deleteSeoEntries`. It will receive an array of IDs to be deleted. Those IDs have to match the value of the column `foreign_key` in the `seo_url` table. Also it needs the current context. It will take care of setting the generated SEO URLs to `deleted`. It will **not** delete an entry from the table `seo_url`. @@ -574,7 +565,7 @@ public function deleteSeoEntries(array $ids, Context $context): void This way the respective SEO URLs will be marked as `is_deleted` for the system. However, this SEO route will remain accessible, so make sure to implement a check whether or not the content still exists in your controller. -#### Writing SEO URLs for another language +## Writing SEO URLs for another language In the example mentioned above, we're just using a `Context` instance, for whichever language that is. You can be more specific here though, in order to properly define the language ID yourself here and therefore ensuring it is written for the right language. diff --git a/guides/plugins/plugins/content/seo/extend-robots-txt.md b/guides/plugins/plugins/content/seo/extend-robots-txt.md index ad759587b8..d7eec4d575 100644 --- a/guides/plugins/plugins/content/seo/extend-robots-txt.md +++ b/guides/plugins/plugins/content/seo/extend-robots-txt.md @@ -1,11 +1,11 @@ --- nav: - title: Extend robots.txt configuration + title: Extend robots.txt Configuration position: 20 --- -# Extend robots.txt configuration +# Extend robots.txt Configuration ## Overview @@ -30,10 +30,10 @@ This guide requires you to have a basic plugin running. If you don't know how to -You should also be familiar with [Event listeners](../../plugin-fundamentals/listening-to-events). +You should also be familiar with [Event listeners](../../framework/event/listening-to-events.md). ::: info -This guide uses EventListeners since each example listens to a single event. If you need to subscribe to multiple events in the same class, consider using an [EventSubscriber](../../plugin-fundamentals/listening-to-events#listening-to-events-via-subscriber) instead. +This guide uses EventListeners since each example listens to a single event. If you need to subscribe to multiple events in the same class, consider using an [EventSubscriber](../../framework/event/listening-to-events.md#creating-your-own-subscriber) instead. ::: ## Modifying parsed directives diff --git a/guides/plugins/plugins/content/sitemap/modify-sitemap-entries.md b/guides/plugins/plugins/content/sitemap/modify-sitemap-entries.md index b9fb206f89..7d6783e10f 100644 --- a/guides/plugins/plugins/content/sitemap/modify-sitemap-entries.md +++ b/guides/plugins/plugins/content/sitemap/modify-sitemap-entries.md @@ -1,6 +1,6 @@ --- nav: - title: Modifying sitemap entries + title: Modifying Sitemap Entries position: 20 --- @@ -10,15 +10,14 @@ nav: ## Overview You might have had a look at our guide about [adding custom sitemap entries](add-custom-sitemap-entries), -for example for a custom entity. -However, you might not want to add new URLs, but rather modify already existing ones. +for example for a custom entity. However, you might not want to add new URLs, but rather modify already existing ones. This guide covers how to modify existing sitemap URLs (for example product URLs) in a plugin. ## Prerequisites This guide is built upon the [Plugin base guide](../../plugin-base-guide), like most guides. -Knowing [service decoration](../../plugin-fundamentals/adjusting-service) and the sitemap URL provider system from +Knowing [service decoration](../../services/adjusting-service.md) and the sitemap URL provider system from [adding custom sitemap entries](add-custom-sitemap-entries) will be helpful. ## Ways to modify sitemap entries @@ -196,8 +195,7 @@ return static function (ContainerConfigurator $configurator): void { ## Important note about `getSeoUrls` -`getSeoUrls` is a protected method on `AbstractUrlProvider`. -If you only decorate a provider and forward `getUrls()` to the inner service, overriding `getSeoUrls` in your decorator +`getSeoUrls` is a protected method on `AbstractUrlProvider`. If you only decorate a provider and forward `getUrls()` to the inner service, overriding `getSeoUrls` in your decorator has no effect. If you really need to change SEO URL lookup internals, you have to implement the provider logic in your own service. diff --git a/guides/plugins/plugins/content/stock/implementing-your-own-stock-storage.md b/guides/plugins/plugins/content/stock/implementing-your-own-stock-storage.md index 854f0b3dc2..2897bf0e3c 100644 --- a/guides/plugins/plugins/content/stock/implementing-your-own-stock-storage.md +++ b/guides/plugins/plugins/content/stock/implementing-your-own-stock-storage.md @@ -1,11 +1,11 @@ --- nav: - title: Implementing your own stock storage + title: Implementing Your Own Stock Storage position: 10 --- -# Implementing your own stock storage +# Implementing Your Own Stock Storage ## Overview @@ -13,7 +13,7 @@ Shopware stores stock as simple integer values in the `product` table. If you ne ## Prerequisites -Here you will be decorating a service; therefore, it will be helpful to familiarize yourself with the [Adjusting a Service](../../../../../guides/plugins/plugins/plugin-fundamentals/adjusting-service) guide. +Here you will be decorating a service; therefore, it will be helpful to familiarize yourself with the [Adjusting a Service](../../../../../guides/plugins/plugins/services/adjusting-service.md) guide. ## Add a decorator to load the stock @@ -57,14 +57,14 @@ class StockStorageDecorator extends AbstractStockStorage } /** - * @param list $changes + * @param list $changes */ public function alter(array $changes, Context $context): void { foreach ($changes as $alteration) { $this->stockApi->updateStock($alteration->productId, $alteration->newQuantity); } - + $this->decorated->alter($changes, $context); } diff --git a/guides/plugins/plugins/content/stock/loading-stock-information-from-different-source.md b/guides/plugins/plugins/content/stock/loading-stock-information-from-different-source.md index 75c8647621..322386ff7e 100644 --- a/guides/plugins/plugins/content/stock/loading-stock-information-from-different-source.md +++ b/guides/plugins/plugins/content/stock/loading-stock-information-from-different-source.md @@ -1,6 +1,6 @@ --- nav: - title: Loading Stock Information from a different Source + title: Loading Stock Information from a Different Source position: 20 --- @@ -13,7 +13,7 @@ If Shopware is not the source of truth for your stock data, you can customize th ## Prerequisites -Here again, you will be decorating a service; therefore, it will be helpful to familiarize yourself with the [Adjusting a Service](../../../../../guides/plugins/plugins/plugin-fundamentals/adjusting-service) guide. +Here again, you will be decorating a service; therefore, it will be helpful to familiarize yourself with the [Adjusting a Service](../../../../../guides/plugins/plugins/services/adjusting-service.md) guide. ## Add a decorator to load the stock diff --git a/guides/plugins/plugins/plugin-fundamentals/custom-fields-of-type-media.md b/guides/plugins/plugins/database/custom-fields-of-type-media.md similarity index 100% rename from guides/plugins/plugins/plugin-fundamentals/custom-fields-of-type-media.md rename to guides/plugins/plugins/database/custom-fields-of-type-media.md diff --git a/guides/plugins/plugins/plugin-fundamentals/database-migrations.md b/guides/plugins/plugins/database/database-migrations.md similarity index 94% rename from guides/plugins/plugins/plugin-fundamentals/database-migrations.md rename to guides/plugins/plugins/database/database-migrations.md index 399a6f0feb..0584293f6a 100644 --- a/guides/plugins/plugins/plugin-fundamentals/database-migrations.md +++ b/guides/plugins/plugins/database/database-migrations.md @@ -1,15 +1,15 @@ --- nav: - title: Database migrations + title: Database Migrations position: 30 --- # Database Migrations -## Overview +This guide covers what migrations are and how to use them. -In this guide, you'll learn what migrations are and how to use them. Migrations are PHP classes used to manage incremental and reversible database schema changes. Shopware comes with a pre-built Migration System, to take away most of the work for you. Throughout this guide, you will find the `$` symbol representing your command line. +Migrations are PHP classes used to manage incremental and reversible database schema changes. Shopware comes with a pre-built Migration System, to take away most of the work for you. Throughout this guide, you will find the `$` symbol representing your command line. ## Prerequisites @@ -111,7 +111,7 @@ As you can see, your migration contains three methods: There is no need to change `getCreationTimestamp()`, it returns the timestamp that's also part of the file name. In the `update()` method you implement non-destructive changes which should always be **reversible**. The `updateDestructive()` method is the follow up step, that is run after `update()` and used for **destructive none reversible changes**, like dropping columns or tables. Destructive migrations are only executed explicitly. ::: info -You do not add instructions to revert your migrations within the migration class itself. `updateDestructive` is not meant to revert instructions in `update`. Reverting changes in the database is done explicitly in plugin lifecycle method `uninstall`. Read more about [it here](./plugin-lifecycle#uninstall). +You do not add instructions to revert your migrations within the migration class itself. `updateDestructive` is not meant to revert instructions in `update`. Reverting changes in the database is done explicitly in plugin lifecycle method `uninstall`, as explained in the [Plugin Lifecycle guide](../plugin-fundamentals/plugin-lifecycle.md#uninstall). ::: Here's an example of a non-destructive migration, creating a new table: diff --git a/guides/plugins/plugins/database/index.md b/guides/plugins/plugins/database/index.md new file mode 100644 index 0000000000..024224b551 --- /dev/null +++ b/guides/plugins/plugins/database/index.md @@ -0,0 +1,22 @@ +--- +nav: + title: Database + position: 40 +--- + +# Database + +Plugins can extend or interact with the Shopware database using migrations, entities, and custom fields. + +This section covers: + +* How to create and manage database migrations +* How to generate migrations from entity definitions +* How to work with custom fields (e.g., media custom fields) + +## Guides + +* +* + +Use migrations for schema changes and structural updates. Use custom fields to extend existing entities without modifying the core schema. diff --git a/guides/plugins/plugins/plugin-fundamentals/add-plugin-dependencies.md b/guides/plugins/plugins/dependencies/add-plugin-dependencies.md similarity index 100% rename from guides/plugins/plugins/plugin-fundamentals/add-plugin-dependencies.md rename to guides/plugins/plugins/dependencies/add-plugin-dependencies.md diff --git a/guides/plugins/plugins/dependencies/index.md b/guides/plugins/plugins/dependencies/index.md new file mode 100644 index 0000000000..d1d86047e1 --- /dev/null +++ b/guides/plugins/plugins/dependencies/index.md @@ -0,0 +1,19 @@ +--- +nav: + title: Dependencies + position: 70 +--- + +# Dependencies + +These guides explain how to manage plugin dependencies in Shopware, including plugin requirements, Composer packages, and NPM packages. Use them to: + +* Declare dependencies on other plugins +* Add and bundle Composer dependencies +* Install and configure NPM packages for Administration or Storefront + +Proper dependency management ensures compatibility, predictable installation behavior, and clean integration with Shopware’s build and package systems. + +* +* +* diff --git a/guides/plugins/plugins/plugin-fundamentals/using-composer-dependencies.md b/guides/plugins/plugins/dependencies/using-composer-dependencies.md similarity index 98% rename from guides/plugins/plugins/plugin-fundamentals/using-composer-dependencies.md rename to guides/plugins/plugins/dependencies/using-composer-dependencies.md index a8fad87114..e8f182e8a2 100644 --- a/guides/plugins/plugins/plugin-fundamentals/using-composer-dependencies.md +++ b/guides/plugins/plugins/dependencies/using-composer-dependencies.md @@ -54,7 +54,7 @@ class SwagBasicExample extends Plugin PHP doesn't require a build system, which means that we can just add `use` statements and then use the Composer dependency directly. -The following code sample imports `SebastianBergmann\Exporter\Exporter` and logs `hello, world!` to the Symfony profiler logs whenever the `NavigationPageLoadedEvent` is fired. Learn how to [register this listener](listening-to-events). +The following code sample imports `SebastianBergmann\Exporter\Exporter` and logs `hello, world!` to the Symfony profiler logs whenever the `NavigationPageLoadedEvent` is fired. Learn how to [register this listener](../framework/event/listening-to-events.md). ```php // /src/SwagBasicExample.php diff --git a/guides/plugins/plugins/plugin-fundamentals/using-npm-dependencies.md b/guides/plugins/plugins/dependencies/using-npm-dependencies.md similarity index 100% rename from guides/plugins/plugins/plugin-fundamentals/using-npm-dependencies.md rename to guides/plugins/plugins/dependencies/using-npm-dependencies.md diff --git a/guides/plugins/plugins/framework/caching/index.md b/guides/plugins/plugins/framework/caching/index.md index 9c416fe1d5..738ee0d994 100644 --- a/guides/plugins/plugins/framework/caching/index.md +++ b/guides/plugins/plugins/framework/caching/index.md @@ -11,7 +11,7 @@ Caching is a technique to store frequently accessed data in a temporary storage While caching enhances performance, it requires careful management of data consistency, cache invalidation strategies, and storage efficiency to prevent serving outdated or incorrect data. -This guide will show you how you can modify the default caching mechanisms to suite your needs. If you are looking for information on how to add your routes to the HTTP-Cache, take a look at [this guide](../../storefront/add-caching-to-custom-controller.md). +This guide will show you how you can modify the default caching mechanisms to suite your needs. If you are looking for information on how to add your routes to the HTTP-Cache, take a look at [this guide](../../storefront/advanced/add-caching-to-custom-controller.md). ## Cache Layers @@ -254,7 +254,7 @@ To invalidate the cache, you need to call the `CacheInvalidator` service and pas ```php class CacheInvalidationSubscriber implements EventSubscriberInterface { - public function __construct(private CacheInvalidator $cacheInvalidator) + public function __construct(private CacheInvalidator $cacheInvalidator) { } @@ -350,7 +350,7 @@ class TweakCacheInvalidation implements CompilerPassInterface ] ); } -} +} ``` ### Object Cache diff --git a/guides/plugins/plugins/framework/custom-field/add-custom-field.md b/guides/plugins/plugins/framework/custom-field/add-custom-field.md index 17d79ed13b..8c7884e94b 100644 --- a/guides/plugins/plugins/framework/custom-field/add-custom-field.md +++ b/guides/plugins/plugins/framework/custom-field/add-custom-field.md @@ -1,6 +1,6 @@ --- nav: - title: Add custom field + title: Add Custom Field position: 10 --- @@ -20,7 +20,7 @@ This guide will cover two similar subjects: This guide is built upon both the [Plugin base guide](../../plugin-base-guide) and the [Add custom complex data](../data-handling/add-custom-complex-data) guide. The latter explained how to create your very first entity, which is used in the following examples. -Since migrations will also be used here, it won't hurt to have a look at our guide about [Executing database queries](../../plugin-fundamentals/database-migrations). +Since migrations will also be used here, it won't hurt to have a look at our guide about [Executing database queries](../../database/database-migrations.md). Also, adding translatable custom fields is covered here in short as well, for which you'll need to understand how translatable entities work in general. This is covered in our guide about [Adding data translations](../data-handling/add-data-translations). This subject will **not** be covered in depth in this guide. diff --git a/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities.md b/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities.md index daf301dc93..d798005247 100644 --- a/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities.md +++ b/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities.md @@ -1,7 +1,7 @@ --- nav: - title: Adding complex data to existing entities - position: 40 + title: Adding Complex Data to Existing Entities + position: 20 --- @@ -55,7 +55,7 @@ class CustomExtension extends EntityExtension } ``` -Now we have to register our extension via the DI-container. If you don't know how that's done in general, head over to our guide about registering a custom service [Add a custom class / service](../../plugin-fundamentals/add-custom-service) or our guide about the [dependency injection](../../plugin-fundamentals/dependency-injection). +Now we have to register our extension via the DI-container, explained in greater detail in the [Add a custom class / service](../../services/add-custom-service.md) and [dependency injection](../../services/dependency-injection.md) guides. Here's our `services.php`: @@ -203,7 +203,7 @@ return static function (ContainerConfigurator $configurator): void { #### Adding the new database table -Of course, you have to add the new database table via a [Database migration](../../plugin-fundamentals/database-migrations). Look at the guide linked above to see how exactly this is done. Here's the example migration and how it could look like: +Of course, you have to add the new database table via a [Database migration](../../database/database-migrations.md). Look at the guide linked above to see how exactly this is done. Here's the example migration and how it could look like: ```php /src/Migration/Migration1611664789Example.php @@ -76,8 +76,7 @@ After reinstalling your plugin, you should see your new database table `swag_exa Introducing the table to Shopware 6 is done by adding a so called `EntityDefinition` for your table. As the name suggests, it defines your own entity, including its fields and name, the latter also represents the table name and therefore has to perfectly match. -Your custom entity definition should be placed inside a folder named after the domain it handles, e.g. "Checkout" if you were to include a Checkout entity. Thus, a good location for this example could be in a directory like this: `/src/Core/Content/Example` -This will also be the case for the `Entity` class itself, as well as the `EntityCollection` class, but those are explained later in this guide. +Your custom entity definition should be placed inside a folder named after the domain it handles, e.g. "Checkout" if you were to include a Checkout entity. Thus, a good location for this example could be in a directory like `/src/Core/Content/Example`. This will also be the case for the `Entity` class itself, as well as the `EntityCollection` class, but those are explained later in this guide. Start of with creating a new file named `ExampleDefinition.php` in the directory `/src/Core/Content/Example/ExampleDefinition.php`. Below you can see our example definition, which is explained afterwards: @@ -163,7 +162,7 @@ Another thing to note is the `addFlags` call on the `IdField`. Those flags are l If you want to know more about the flags and how to use them, head over to our guide on how to use flags [Using flags](using-flags). -All that's left to do now, is to introduce your `ExampleDefinition` to Shopware by registering your class in your `services.php` file and by using the `shopware.entity.definition` tag, because Shopware is looking for definitions this way. If your plugin does not have a `services.php` file yet or you don't know how that's done, head over to our guide about registering a custom service [Add a custom class / service](../../plugin-fundamentals/add-custom-service), or our guide about the [Dependency injection](../../plugin-fundamentals/dependency-injection). +All that's left to do now, is to introduce your `ExampleDefinition` to Shopware by registering your class in your `services.php` file and by using the `shopware.entity.definition` tag, because Shopware is looking for definitions this way. If your plugin does not have a `services.php` file yet or you don't know how that's done, head over to our guide about registering a custom service [Add a custom class / service](../../services/add-custom-service.md), or our guide about the [Dependency injection](../../services/dependency-injection.md). Here's the `services.php` as it should look like: @@ -319,4 +318,4 @@ You've now got a simple entity about a single database table. However, your enti For example we also have a guide about [Associations](add-data-associations), since you most likely will have multiple tables that have a relation to each other. Furthermore, the fields in this example are already [Using flags](using-flags). When dealing with products, you are also dealing with [Inheritance](field-inheritance), which we also got covered. -One more thing: Maybe you want to connect your database table to an already existing database table, hence an already existing entity. This is done by [extending the said existing entity](add-complex-data-to-existing-entities). +Learn how to connect your database table to an already existing database table/entity from the [Adding Complex Data to Existing Entities guide](add-complex-data-to-existing-entities). diff --git a/guides/plugins/plugins/framework/data-handling/add-data-associations.md b/guides/plugins/plugins/framework/data-handling/add-data-associations.md index 7f7221d3ab..5692b1f59c 100644 --- a/guides/plugins/plugins/framework/data-handling/add-data-associations.md +++ b/guides/plugins/plugins/framework/data-handling/add-data-associations.md @@ -1,7 +1,7 @@ --- nav: - title: Adding data associations - position: 70 + title: Adding Data Associations + position: 40 --- diff --git a/guides/plugins/plugins/framework/data-handling/add-data-indexer.md b/guides/plugins/plugins/framework/data-handling/add-data-indexer.md index 1abeedc2cb..d1c3c91847 100644 --- a/guides/plugins/plugins/framework/data-handling/add-data-indexer.md +++ b/guides/plugins/plugins/framework/data-handling/add-data-indexer.md @@ -1,3 +1,10 @@ +--- +nav: + title: Adding Data Indexer + position: 50 + +--- + # Adding Data Indexer ## Overview @@ -153,7 +160,7 @@ Let's take a closer look at the functions of the entity indexer class. * This function is called when entities are updated over the DAL. This function should react to the provided entity written events and generate a list of messages which has to be processed by the `handle` function. In the example implementation above, we get all customer identifiers that have been updated by `$updates = $event->getPrimaryKeys(CustomerDefinition::ENTITY_NAME);`. A closer look at the `EntityWrittenContainerEvent` class is also good idea. It is for example possible to filter the updated customer by the updated column. For example if you only need to index customers with a changed firstname. It is always a good idea to filter the entities as much as possible to save performance. * The `update()` can also be used to update data that has always to be changed synchronously. * `public function handle(EntityIndexingMessage $message): void` - * The `handle()` method handles the messages which were generated in the `self::iterate` or `self::update` function. In the example above a small log entry is written to the database indicating that a customer was indexed. The preferred way to manipulate data here is using the `connection` directly and not to use the DAL. See the section [Use DAL functionalities in the indexer](Use DAL functionalities in the indexer) for more information. + * The `handle()` method handles the messages which were generated in the `self::iterate` or `self::update` function. In the example above a small log entry is written to the database indicating that a customer was indexed. The preferred way to manipulate data here is using the `connection` directly and not to use the DAL. See the [Use DAL functionalities in the indexer](#use-dal-functionalities-in-the-indexer) section for more information. ### Handle messages asynchronously or synchronously @@ -198,7 +205,9 @@ There are already a bunch of indexers in shopware that you can use. If you take ### Subscribe to an indexer event -For this we need a new subscriber. If you are not familiar with a subscriber, have a look at our [Listening to events](../../plugin-fundamentals/listening-to-events) guide. For this example, we just write a new entry to the `log_entry` database table, indicating that a customer was updated. +A new subscriber is necessary. Refer to the [Listening to Events](../event/listening-to-events.md) guide for more details about subscribers. + +In this example a new entry is written to the `log_entry` database table indicating that a customer was updated: ```php // /src/Service/Subscriber.php @@ -272,4 +281,4 @@ return static function (ContainerConfigurator $configurator): void { }; ``` -It is recommended to work directly with the `Connection` since the event is dispatched in the context of an indexer. If we would use the Data Abstraction Layer \(DAL\) for writing changes to the database, the indexer would be triggered again, because it listens for `EntityWrittenContainerEvent` events. This would lead to an infinite loop. Using the `Connection` directly prevents the DAL from dispatching entity written events. Also the performance of plain sql is much higher, which is very important for indexers in general. +It is recommended to work directly with the `Connection` since the event is dispatched in the context of an indexer. If we would use the Data Abstraction Layer \(DAL\) for writing changes to the database, the indexer would be triggered again, because it listens for `EntityWrittenContainerEvent` events. This would lead to an infinite loop. Using the `Connection` directly prevents the DAL from dispatching entity written events. Also the performance of plain sql is much higher, which is very important for indexers in general. diff --git a/guides/plugins/plugins/framework/data-handling/add-data-translations.md b/guides/plugins/plugins/framework/data-handling/add-data-translations.md index b5c60a8c3f..9ac806aa85 100644 --- a/guides/plugins/plugins/framework/data-handling/add-data-translations.md +++ b/guides/plugins/plugins/framework/data-handling/add-data-translations.md @@ -1,7 +1,7 @@ --- nav: - title: Adding data translations - position: 80 + title: Adding Data Translations + position: 60 --- diff --git a/guides/plugins/plugins/framework/data-handling/deleting-associated-data.md b/guides/plugins/plugins/framework/data-handling/deleting-associated-data.md index 529f0946ae..62fb9e804c 100644 --- a/guides/plugins/plugins/framework/data-handling/deleting-associated-data.md +++ b/guides/plugins/plugins/framework/data-handling/deleting-associated-data.md @@ -1,7 +1,7 @@ --- nav: - title: Removing associated data - position: 60 + title: Removing Associated Data + position: 70 --- diff --git a/guides/plugins/plugins/framework/data-handling/entities-via-attributes.md b/guides/plugins/plugins/framework/data-handling/entities-via-attributes.md index 3431d1607c..190e4ded63 100644 --- a/guides/plugins/plugins/framework/data-handling/entities-via-attributes.md +++ b/guides/plugins/plugins/framework/data-handling/entities-via-attributes.md @@ -1,11 +1,11 @@ --- nav: - title: Entities via attributes - position: 1 + title: Entities via Attributes + position: 80 --- -# Entities via attributes +# Entities via Attributes Since Shopware v6.6.3.0, it has been possible to register entities via PHP attributes. This guide will demonstrate the process. diff --git a/guides/plugins/plugins/framework/data-handling/field-inheritance.md b/guides/plugins/plugins/framework/data-handling/field-inheritance.md index 88f79fcd9e..646e43dbe1 100644 --- a/guides/plugins/plugins/framework/data-handling/field-inheritance.md +++ b/guides/plugins/plugins/framework/data-handling/field-inheritance.md @@ -1,7 +1,7 @@ --- nav: - title: Field inheritance - position: 110 + title: Field Inheritance + position: 90 --- @@ -29,7 +29,9 @@ To start using inheritance, we have to update our definition and database. ### Make fields nullable -The first thing we need to do is to make all our fields that we want to make inheritable nullable in our migration. If you lack knowledge about migrations, have a look at our [Database migrations](../../plugin-fundamentals/database-migrations) guide. We also need a 'parent_id' field for the parent reference. +First, make all fields intended to be inheritable nullable in the migration. Review the [Database Migrations guide](../../database/database-migrations.md) for more information. + +A `parent_id` field for the parent reference is needed: ```sql ALTER TABLE `swag_example` ADD `parent_id` BINARY(16) NULL; @@ -56,7 +58,7 @@ class Migration1615363012MakeInheritedColumnsNullable extends MigrationStep public function update(Connection $connection): void { $query = <<addSorting(new FieldSorting('manufacturerNumber')); +$criteria->addSorting(new FieldSorting('manufacturerNumber')); //However, simply by adding a secondary sorting by ID, the sorting becomes deterministic again, as the IDs are unique per product. -$criteria->addSorting(new FieldSorting('id')); +$criteria->addSorting(new FieldSorting('id')); $criteria->setLimit(500); ``` @@ -389,4 +385,4 @@ And that's basically it for this guide! ## Next steps -Now that you know how to read data from the database using the Data Abstraction Layer, you can head over to our guide on [Writing data](writing-data). +Now that you know how to read data from the database using the Data Abstraction Layer, you can head over to our guide on [Writing data](writing-data.md). diff --git a/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md b/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md index 4ee9982f5e..740ec3d304 100644 --- a/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md +++ b/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md @@ -1,7 +1,7 @@ --- nav: - title: Replacing associated data - position: 50 + title: Replacing Associated Data + position: 110 --- diff --git a/guides/plugins/plugins/framework/data-handling/using-database-events.md b/guides/plugins/plugins/framework/data-handling/using-database-events.md index 853c83283c..e331d3ae23 100644 --- a/guides/plugins/plugins/framework/data-handling/using-database-events.md +++ b/guides/plugins/plugins/framework/data-handling/using-database-events.md @@ -1,15 +1,13 @@ --- nav: - title: Using database events - position: 90 + title: Using Database Events + position: 120 --- # Using Database Events -## Overview - -Events are the easiest way to extend the DataAbstractionLayer. Every entity comes with a set of events which will be dispatched in various situations. +Events are the easiest way to extend the Data Abstraction Layer (DAL). Every entity comes with a set of events which will be dispatched in various situations. All events are nested into one container event so that your subscriber should only get called once for e.g. a search request instead of dispatching the event 30 times. @@ -17,11 +15,11 @@ All events are nested into one container event so that your subscriber should on This guide is built upon the [Plugin base guide](../../plugin-base-guide), but any plugin will work here. Just note that all examples are using the plugin mentioned above. -Furthermore you should have a look at our [Listening to events](../../plugin-fundamentals/listening-to-events) guide since we are subscribing to events in this guide. +Furthermore you should have a look at our [Listening to Events](../../framework/event/listening-to-events.md) guide since we are subscribing to events in this guide. ## General event overview -The events below are dispatched during certain DAL operations, they are not necessarily associated with a particular entity, rather they are triggered with batches of commands. +The events below are dispatched during certain DAL operations. They are not necessarily associated with a particular entity, but are triggered with batches of commands. | Event | Description | |:------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------| @@ -92,7 +90,7 @@ class EntityWriteSubscriber implements EventSubscriberInterface } ``` -After creating the event subscriber, you have to register it. If you don't know how it is done, then refer to the [Listening to events](../../plugin-fundamentals/listening-to-events) guide. +After creating the event subscriber, you have to register it. If you don't know how it is done, then refer to the [Listening to events](../../framework/event/listening-to-events.md) guide. ### `Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeleteEvent` @@ -140,7 +138,7 @@ class DeleteSubscriber implements EventSubscriberInterface } ``` -After creating the event subscriber, you have to register it. If you don't know how it is done, then refer to the [Listening to events](../../plugin-fundamentals/listening-to-events) guide. +After creating the event subscriber, you have to register it. If you don't know how it is done, then refer to the [Listening to events](../../framework/event/listening-to-events.md) guide. ## Entity event overview @@ -244,7 +242,7 @@ class ProductSubscriber implements EventSubscriberInterface } ``` -After creating the event subscriber, you have to register it. If you don't know how that's done, head over to our guide about [Listening to events](../../plugin-fundamentals/listening-to-events). +After creating the event subscriber, you have to register it. If you don't know how that's done, head over to our guide about [Listening to events](../../framework/event/listening-to-events.md). Here's our `services.php`: diff --git a/guides/plugins/plugins/framework/data-handling/using-flags.md b/guides/plugins/plugins/framework/data-handling/using-flags.md index a12d9d73ff..0ce4ef41aa 100644 --- a/guides/plugins/plugins/framework/data-handling/using-flags.md +++ b/guides/plugins/plugins/framework/data-handling/using-flags.md @@ -1,14 +1,12 @@ --- nav: - title: Using flags - position: 100 + title: Using Flags + position: 130 --- # Using Flags -## Overview - In this guide you'll learn how to use flags of the DAL but this guide will not explain all flags and its purpose. ## Prerequisites diff --git a/guides/plugins/plugins/framework/data-handling/versioning-entities.md b/guides/plugins/plugins/framework/data-handling/versioning-entities.md index 9407ef389b..3246d3a86d 100644 --- a/guides/plugins/plugins/framework/data-handling/versioning-entities.md +++ b/guides/plugins/plugins/framework/data-handling/versioning-entities.md @@ -1,14 +1,12 @@ --- nav: - title: Versioning entities - position: 120 + title: Versioning Entities + position: 140 --- # Versioning Entities -## Overview - In this guide you will learn how to version your entities. The entity versioning system in Shopware gives you the opportunity to create multiple versions of an entity, which could be used to save drafts for example. Learn more about the versioning concept [here](../../../../../concepts/framework/data-abstraction-layer#versioning). diff --git a/guides/plugins/plugins/framework/data-handling/writing-data.md b/guides/plugins/plugins/framework/data-handling/writing-data.md index c8a089bb16..55c29a5f00 100644 --- a/guides/plugins/plugins/framework/data-handling/writing-data.md +++ b/guides/plugins/plugins/framework/data-handling/writing-data.md @@ -1,15 +1,13 @@ --- nav: - title: Writing data - position: 20 + title: Writing Data + position: 150 --- # Writing Data -## Overview - -This guide will teach you everything you need to know in order to write data to the database in Shopware 6. It will also include a short explanation about writing associated data. +This guide explains how to write data to the database in Shopware 6. It also includes a short explanation about writing associated data. ## Prerequisites @@ -29,8 +27,9 @@ Let's get started with examples to write data. This example will be about writin Dealing with the Data Abstraction Layer is done by using the automatically generated repositories for each entity, such as a product. This means, that you have to inject the repository into your service first. -The repository's service name follows this pattern: `entity_name.repository` -For products this then would be `product.repository`. Additional to that, you're going to need the `tax` repository later for this guide, so let's add this as well already. +The repository's service name follows this pattern: `entity_name.repository`. For products this would be `product.repository`. + +Add the `tax` repository, which will appear later in this guide: ```php // SwagBasicExample/src/Resources/config/services.php diff --git a/guides/plugins/plugins/framework/event/add-custom-event.md b/guides/plugins/plugins/framework/event/add-custom-event.md index 5967475079..84107f9173 100644 --- a/guides/plugins/plugins/framework/event/add-custom-event.md +++ b/guides/plugins/plugins/framework/event/add-custom-event.md @@ -1,6 +1,6 @@ --- nav: - title: Add custom event + title: Add Custom Event position: 10 --- @@ -65,7 +65,7 @@ class ExampleEvent implements ShopwareSalesChannelEvent } public function getContext(): Context - { + { return $this->salesChannelContext->getContext(); } @@ -109,4 +109,4 @@ class ExampleEventService ## Next steps -Now that you know how to create your own event, you may want to act on it. To get a grip on this, head over to our [Listening to events](../../plugin-fundamentals/listening-to-events) guide. +Now that you know how to create your own event, read the [Listening to events](../../framework/event/listening-to-events.md) guide for information on applying it. diff --git a/guides/plugins/plugins/framework/event/finding-events.md b/guides/plugins/plugins/framework/event/finding-events.md index c10715e1aa..846aab40f0 100644 --- a/guides/plugins/plugins/framework/event/finding-events.md +++ b/guides/plugins/plugins/framework/event/finding-events.md @@ -1,6 +1,6 @@ --- nav: - title: Finding events + title: Finding Events position: 20 --- @@ -9,15 +9,13 @@ nav: ## Overview -Shopware 6 is fully extensible via plugins. -Part of this extensibility is the usage of events, upon which one could react. +Shopware 6 is fully extensible via plugins. Part of this extensibility comes from the ability to react to events. -This guide will cover how you can find those events in the first place, in order to use them in your plugin. +This guide covers how to find events and use them in plugins. ## DAL Events -At first we will start with the [Data Abstraction Layer events](../data-handling/using-database-events). -They're fired whenever a [DAL entity](../data-handling/add-custom-complex-data) is read, written, created, or deleted. +[Data Abstraction Layer events](../data-handling/using-database-events) are fired whenever a [DAL entity](../data-handling/add-custom-complex-data) is read, written, created, or deleted. There usually is no need to find them, since the pattern for them is always the same. You can use them by following this pattern: `entity_name.event`. @@ -31,7 +29,7 @@ This way you can also find out about all the possible DAL events available in Sh Finding those "event classes" can be done by searching for the term `@Event` in your project. -You can use those events in a [subscriber](../../plugin-fundamentals/listening-to-events) like the following: +You can use those events in a [subscriber](../event/listening-to-events.md) like the following: ```php public static function getSubscribedEvents(): array @@ -116,10 +114,7 @@ Use one of the following search terms: ### Looking at the service definition -Every service, that wants to fire an event sooner or later, needs access to the `event_dispatcher` in order to do so. - -Hence, you can have a look at all the service definitions for the [Dependency injection container](../../plugin-fundamentals/dependency-injection) -and therefore quickly figure out, which services and classes are having access to the said `event_dispatcher`: +Services that want to fire events need access to the `event_dispatcher`. Noting the service definitions for the [Dependency injection container](../../services/dependency-injection.md) is advisable for determining which services and classes have access to the `event_dispatcher`: ```php { @@ -290,9 +275,9 @@ this.$emitter.subscribe('someEvent', (additionalData) => { }); ``` -### Searching for javascript events +### Searching for JavaScript events -Searching for the said javascript events is done by searching for the following term in either the `/platform/src/Storefront/Resources/app/storefront/src` directory for +Search for JavaScript events by searching for the following term in either the `/platform/src/Storefront/Resources/app/storefront/src` directory for the [development template](https://github.com/shopwareArchive/development) or the `/vendor/shopware/shopware/src/Storefront/Resources/app/storefront/src` directory for the [production template](https://github.com/shopware/template): `$emitter.publish`. @@ -300,26 +285,25 @@ This way, you'll find all occurrences of plugins actually firing a custom event. ## Administration events -In the Administration, most events you can find and deal with are default vue events, which you can learn about [here](https://vuejs.org/guide/essentials/event-handling.html). +In the Administration, most events are default Vue events. More details are available in [Vue documentation](https://vuejs.org/guide/essentials/event-handling.html). -However, for the sake of the two-way data-binding, we're sometimes firing events, which looks like this: +Regarding two-way data-binding, we're sometimes firing events, which looks like this: ```javascript this.$emit('some-event', additionalData); ``` -Therefore you can also find those occurrences by searching for `$emit` in the `/platform/src/Administration/Resources/app/administration/src` directory for +Find those occurrences by searching for `$emit` in the `/platform/src/Administration/Resources/app/administration/src` directory for the [development template](https://github.com/shopwareArchive/development) or the `/vendor/shopware/shopware/src/Administration/Resources/app/administration/src` directory for the [production template](https://github.com/shopware/template). ### Vue extension -One more note here: -There's a vue browser extension which can greatly help will development in general, but also with finding events. +A Vue browser extension helps with general development as well as with finding events: -[Vue.js devtools for Firefox](https://addons.mozilla.org/de/firefox/addon/vue-js-devtools/) -[Vue.js devtools for Google Chrome](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) +- [Vue.js devtools for Firefox](https://addons.mozilla.org/de/firefox/addon/vue-js-devtools/) +- [Vue.js devtools for Google Chrome](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) ## Flow builder events -From Shopware 6.5, all events data in the Flow Builder will be stored in the `StorableFlow`, hence the `getAvailableData` function can no more be used to get data from the Flow Builder. For more information on this refer to [Create a new trigger (event)](../../../../../guides/plugins/plugins/framework/flow/add-flow-builder-trigger#create-a-new-trigger-event) section of this guide. +All events data in the Flow Builder are stored in the `StorableFlow`. The `getAvailableData` function can no longer be used. For more information refer to [Create a new trigger (event)](../../../../../guides/plugins/plugins/framework/flow/add-flow-builder-trigger#create-a-new-trigger-event). diff --git a/guides/plugins/plugins/plugin-fundamentals/listening-to-events.md b/guides/plugins/plugins/framework/event/listening-to-events.md similarity index 98% rename from guides/plugins/plugins/plugin-fundamentals/listening-to-events.md rename to guides/plugins/plugins/framework/event/listening-to-events.md index 24c53541c3..e5869231a2 100644 --- a/guides/plugins/plugins/plugin-fundamentals/listening-to-events.md +++ b/guides/plugins/plugins/framework/event/listening-to-events.md @@ -1,6 +1,6 @@ --- nav: - title: Listening to events + title: Listening to Events position: 50 --- @@ -13,7 +13,7 @@ It is thus the same in Shopware, so this article will guide you on how to create ## Prerequisites In order to build your own subscriber for your plugin, of course you first need a plugin as base. -To create an own plugin, you can refer to the [Plugin Base Guide](../plugin-base-guide). +To create an own plugin, you can refer to the [Plugin Base Guide](../../plugin-base-guide.md). ::: info Refer to this video on **[Live coding example with product.loaded event.](https://www.youtube.com/watch?v=cJDaiuyjKJk)**. diff --git a/guides/plugins/plugins/framework/filesystem/filesystem.md b/guides/plugins/plugins/framework/filesystem/filesystem.md index 619f9d4573..49eb9669a4 100644 --- a/guides/plugins/plugins/framework/filesystem/filesystem.md +++ b/guides/plugins/plugins/framework/filesystem/filesystem.md @@ -13,7 +13,7 @@ Flysystem is a file storage library for PHP. It provides one interface to intera ## Prerequisites -This guide is built upon both the [Plugin base guide](../../plugin-base-guide) and the [Add custom service guide](../../plugin-fundamentals/add-custom-service). +This guide is built upon both the [Plugin base guide](../../plugin-base-guide) and the [Add custom service guide](../../services/add-custom-service.md). ## Flysystem overview diff --git a/guides/plugins/plugins/framework/flow/add-flow-builder-action.md b/guides/plugins/plugins/framework/flow/add-flow-builder-action.md index 6a3bee785f..ceb03efa14 100644 --- a/guides/plugins/plugins/framework/flow/add-flow-builder-action.md +++ b/guides/plugins/plugins/framework/flow/add-flow-builder-action.md @@ -1,11 +1,11 @@ --- nav: - title: Add Flow Builder action + title: Add Flow Builder Action position: 10 --- -# Add custom flow Action +# Add Flow Builder Action ## Overview @@ -15,7 +15,7 @@ In this guide, you'll learn how to create custom flow action in Shopware. The fl In order to add your own custom flow action for your plugin, you first need a plugin as base. Therefore, you can refer to the [Plugin Base Guide.](../../plugin-base-guide) -You also should be familiar with the [Dependency Injection container](../../plugin-fundamentals/dependency-injection) as this is used to register your custom flow action and [Listening to events](../../plugin-fundamentals/listening-to-events#creating-your-own-subscriber) to create a subscriber class. +You also should be familiar with the [Dependency Injection container](../../services/dependency-injection.md) as this is used to register your custom flow action and [Listening to events](../../framework/event/listening-to-events.md#creating-your-own-subscriber) to create a subscriber class. It might be helpful to gather some general understanding about the [concept of Flow Builder](../../../../../concepts/framework/flow-concept) as well. diff --git a/guides/plugins/plugins/framework/message-queue/add-message-handler.md b/guides/plugins/plugins/framework/message-queue/add-message-handler.md index cbec6f7034..1a63370e57 100644 --- a/guides/plugins/plugins/framework/message-queue/add-message-handler.md +++ b/guides/plugins/plugins/framework/message-queue/add-message-handler.md @@ -19,7 +19,7 @@ A [handler](https://symfony.com/doc/current/messenger.html#creating-a-message-ha ## Prerequisites -As most guides, this guide is also built upon the [Plugin base guide](../../plugin-base-guide), but you don't necessarily need that. It will use an example message, so if you don't know how to add a custom message yet, have a look at our guide about [Adding a message to queue](add-message-to-queue). Furthermore, registering classes or services to the DI container is also not explained here, but it's covered in our guide about [Dependency injection](../../plugin-fundamentals/dependency-injection), so having this open in another tab won't hurt. +As most guides, this guide is also built upon the [Plugin base guide](../../plugin-base-guide), but you don't necessarily need that. It will use an example message, so if you don't know how to add a custom message yet, have a look at our guide about [Adding a message to queue](add-message-to-queue). Furthermore, registering classes or services to the DI container is also not explained here, but it's covered in our guide about [Dependency injection](../../services/dependency-injection.md), so having this open in another tab won't hurt. ## Handling messages diff --git a/guides/plugins/plugins/framework/message-queue/add-message-to-queue.md b/guides/plugins/plugins/framework/message-queue/add-message-to-queue.md index 28769edbd6..210d120061 100644 --- a/guides/plugins/plugins/framework/message-queue/add-message-to-queue.md +++ b/guides/plugins/plugins/framework/message-queue/add-message-to-queue.md @@ -23,7 +23,7 @@ It will be wrapped in an [envelope](https://symfony.com/doc/current/components/m ## Prerequisites -As most guides, this guide is also built upon the [Plugin base guide](../../plugin-base-guide), but you don't necessarily need that. It will use an example service, so if you don't know how to add a custom service yet, have a look at our guide about [Adding a custom service](../../plugin-fundamentals/add-custom-service). Furthermore, registering classes or services to the DI container is also not explained here, but it's covered in our guide about [Dependency injection](../../plugin-fundamentals/dependency-injection), so having this open in another tab won't hurt. +As most guides, this guide is also built upon the [Plugin base guide](../../plugin-base-guide), but you don't necessarily need that. It will use an example service, so if you don't know how to add a custom service yet, have a look at our guide about [Adding a custom service](../../services/add-custom-service.md). Furthermore, registering classes or services to the DI container is also not explained here, but it's covered in our guide about [Dependency injection](../../services/dependency-injection.md), so having this open in another tab won't hurt. ## Create a message diff --git a/guides/plugins/plugins/framework/message-queue/add-middleware.md b/guides/plugins/plugins/framework/message-queue/add-middleware.md index 3292842cdd..8ba7010805 100644 --- a/guides/plugins/plugins/framework/message-queue/add-middleware.md +++ b/guides/plugins/plugins/framework/message-queue/add-middleware.md @@ -15,7 +15,7 @@ A [Middleware](https://symfony.com/doc/current/messenger.html#middleware) is cal ## Prerequisites -As most guides, this guide is also built upon the [Plugin base guide](../../plugin-base-guide), but you don't necessarily need that. Furthermore, registering classes or services to the DI container is also not explained here, but it's covered in our guide about [Dependency injection](../../plugin-fundamentals/dependency-injection), so having this open in another tab won't hurt. +As most guides, this guide is also built upon the [Plugin base guide](../../plugin-base-guide), but you don't necessarily need that. Furthermore, registering classes or services to the DI container is also not explained here, but it's covered in our guide about [Dependency injection](../../services/dependency-injection.md), so having this open in another tab won't hurt. ## Create middleware diff --git a/guides/plugins/plugins/framework/rate-limiter/add-rate-limiter-to-api-route.md b/guides/plugins/plugins/framework/rate-limiter/add-rate-limiter-to-api-route.md index 380621a2d5..f49e44b5a0 100644 --- a/guides/plugins/plugins/framework/rate-limiter/add-rate-limiter-to-api-route.md +++ b/guides/plugins/plugins/framework/rate-limiter/add-rate-limiter-to-api-route.md @@ -15,7 +15,7 @@ have a look at the [Rate limiter](../../../../hosting/infrastructure/rate-limite ## Prerequisites -This guide is built upon both the [Plugin base guide](../../plugin-base-guide) as well as the [Dependency injection](../../plugin-fundamentals/dependency-injection) guide. +This guide is built upon both the [Plugin base guide](../../plugin-base-guide) as well as the [Dependency injection](../../services/dependency-injection.md) guide. Furthermore you need an existing API route, to create a new one, head over to our [Add store API route](../store-api/add-store-api-route) guide. @@ -175,7 +175,7 @@ public function load(Request $request, SalesChannelContext $context): ExampleRou // Limit ip address for example $this->rateLimiter->ensureAccepted('example_route', $request->getClientIp()); - // if action was successfully, reset limit + // if action was successfully, reset limit if ($this->doAction() === true) { $this->rateLimiter->reset('example_route', $request->getClientIp()); } diff --git a/guides/plugins/plugins/framework/rule/add-custom-rules.md b/guides/plugins/plugins/framework/rule/add-custom-rules.md index 0962b7f1d2..8b54d86473 100644 --- a/guides/plugins/plugins/framework/rule/add-custom-rules.md +++ b/guides/plugins/plugins/framework/rule/add-custom-rules.md @@ -1,6 +1,6 @@ --- nav: - title: Add custom rules + title: Add Custom Rules position: 10 --- @@ -17,9 +17,9 @@ This example will introduce a new rule, which checks if it is the first monday o In order to add your own custom rules for your plugin, you first need a plugin as base. Therefore, you can refer to the [Plugin Base Guide](../../plugin-base-guide). -You also should be familiar with the [Dependency Injection container](../../plugin-fundamentals/dependency-injection) as this is used to register your custom rule. +You also should be familiar with the [Dependency Injection container](../../services/dependency-injection.md) as this is used to register your custom rule. -It might be helpful to gather some general understanding about the concept of [Rules](../../../../../concepts/framework/rule) as well. +It might be helpful to gather some general understanding about the concept of [Rules](../../../../../concepts/framework/rule-system/index.md) (../../../../../concepts/framework/rule) as well. ## Create custom rule diff --git a/guides/plugins/plugins/framework/store-api/add-store-api-route.md b/guides/plugins/plugins/framework/store-api/add-store-api-route.md index 9e0c6d324f..447b14100f 100644 --- a/guides/plugins/plugins/framework/store-api/add-store-api-route.md +++ b/guides/plugins/plugins/framework/store-api/add-store-api-route.md @@ -1,11 +1,11 @@ --- nav: - title: Add store API route + title: Add Store API Route position: 10 --- -# Add Store API route +# Add Store API Route ## Overview @@ -19,7 +19,7 @@ You also should have a look at our [Adding custom complex data](../data-handling ## Add Store API route -As you may already know from the [Adjusting a service](../../plugin-fundamentals/adjusting-service) guide, we use abstract classes to make our routes more decoratable. +As you may already know from the [Adjusting a service](../../../plugins/services/adjusting-service.md) guide, we use abstract classes to make our routes more decoratable. ::: warning All fields that should be available through the API require the flag `ApiAware` in the definition. @@ -297,7 +297,7 @@ Your generated request and response could look like this: ## Make the route available for the Storefront -If you want to access the functionality of your route also from the Storefront you need to make it available there by adding a custom [Storefront controller](../../storefront/add-custom-controller) that will wrap your just created route. +If you want to access the functionality of your route also from the Storefront you need to make it available there by adding a custom [Storefront controller](../../storefront/controllers/add-custom-controller.md) that will wrap your just created route. ```php // /src/Storefront/Controller/ExampleController.php @@ -376,8 +376,8 @@ return static function (RoutingConfigurator $routes): void { ### Requesting your route from the Storefront -You can request your new route from the Storefront from inside a [custom javascript plugin](../../storefront/add-custom-javascript). -We expect that you have followed that guide and know how to register your custom javascript plugin in the Storefront. +You can request your new route from the Storefront from inside a [custom JavaScript plugin](../../storefront/javascript/add-custom-javascript.md). +We expect that you have followed that guide and know how to register your custom JavaScript plugin in the Storefront. When you want to request your custom route you can use the existing `http-client` service for that. diff --git a/guides/plugins/plugins/index.md b/guides/plugins/plugins/index.md index b28c898d40..e2de9d1356 100644 --- a/guides/plugins/plugins/index.md +++ b/guides/plugins/plugins/index.md @@ -23,10 +23,10 @@ You will likely create a plugin when you need deep server-side integration or re | Create a new plugin from scratch | [Plugin base guide](plugin-base-guide.md) | | Add Admin configuration fields (`config.xml`) | [Add plugin configuration](plugin-fundamentals/add-plugin-configuration.md) | | Read config in PHP, Admin JS, or Storefront | [Use plugin configuration](plugin-fundamentals/use-plugin-configuration.md) | -| React to domain events | [Listening to events](plugin-fundamentals/listening-to-events.md) | -| Register services & DI | [Dependency injection](plugin-fundamentals/dependency-injection.md) | -| Database changes | [Database migrations](plugin-fundamentals/database-migrations.md) | -| Composer dependencies in a plugin | [Adding Composer dependencies](plugin-fundamentals/using-composer-dependencies.md) | +| React to domain events | [Listening to events](../plugins/framework/event/listening-to-events.md) | +| Register services & DI | [Dependency injection](../plugins/services/dependency-injection.md) | +| Database changes | [Database migrations](../plugins/database/database-migrations.md) | +| Composer dependencies in a plugin | [Adding Composer dependencies](../plugins/dependencies/using-composer-dependencies.md) | | More topics | [Plugin fundamentals](plugin-fundamentals/index.md) (logging, cache, routes, …) | ::: info diff --git a/guides/plugins/plugins/plugin-base-guide.md b/guides/plugins/plugins/plugin-base-guide.md index 3943ae6688..af947177e8 100644 --- a/guides/plugins/plugins/plugin-base-guide.md +++ b/guides/plugins/plugins/plugin-base-guide.md @@ -9,14 +9,14 @@ nav: ## Overview -Plugins in Shopware are essentially an extension of [Symfony bundles](plugins-for-symfony-developers.md). Such bundles and plugins can provide their own resources like assets, controllers, services or tests, which you'll learn in the next guides. A plugin is the main way to extend your Shopware 6 instance programmatically. +Plugins in Shopware are essentially an extension of [Symfony bundles](../plugins/bundle.md). Such bundles and plugins can provide their own resources like assets, controllers, services or tests, which you'll learn in the next guides. A plugin is the main way to extend your Shopware 6 instance programmatically. This section guides you through the basics of creating a plugin from scratch, which can then be installed on your Shopware 6 instance. Refer to the [Shopware 6 Installation guide](../../../guides/installation/index.md). ## Prerequisites * a running Shopware 6 instance -* full access to both the files and the command line +* full access to both the files and the command line * PHP knowledge ## Create your first plugin @@ -25,9 +25,7 @@ Let's get started with creating your plugin by finding a proper name for it. ### Name your plugin -First, you need to find a name for your plugin. We're talking about a technical name here, so it needs to describe your plugins functionality as short as possible, written in UpperCamelCase. To prevent issues with duplicated plugin names, you should add a shorthand prefix for your company. -Shopware uses "Swag" as a prefix for that case. -For this example guide we'll use the plugin name **SwagBasicExample.** +First, you need to find a name for your plugin. We're talking about a technical name here, so it needs to describe your plugins functionality as short as possible, written in UpperCamelCase. To prevent issues with duplicated plugin names, you should add a shorthand prefix for your company. Shopware uses "Swag" as a prefix for that case. For this example guide we'll use the plugin name **SwagBasicExample.** ::: info Using a prefix for your plugin name is not just a convention we'd recommend, but a hard requirement if you want to publish your plugin in the [Shopware Extension Store](https://store.shopware.com/en). @@ -60,10 +58,9 @@ First, navigate to the directory `custom/plugins` in your Shopware 6 installatio By convention, you'll have another directory called `src`. This is not required, but recommended. And that's it for the directory structure for now. -Inside your `src` directory, create a PHP class named after your plugin, `SwagBasicExample.php`. -This new class `SwagBasicExample` has to extend from Shopware's abstract Plugin class, which is `Shopware\Core\Framework\Plugin`. +Inside your `src` directory, create a PHP class named after your plugin, `SwagBasicExample.php`. This new class `SwagBasicExample` has to extend from Shopware's abstract Plugin class, which is `Shopware\Core\Framework\Plugin`. -Apart from this, only the namespace is missing. You can freely define it, but we'd recommend using a combination of your manufacturer prefix and the technical name, so in this `guide` this would be: `Swag\BasicExample` +Apart from this, only the namespace is missing. You can freely define it, but we'd recommend using a combination of your manufacturer prefix and the technical name. In this `guide` this would be `Swag\BasicExample`: ```php // /src/SwagBasicExample.php @@ -90,10 +87,9 @@ Refer to this video on **[Creating a plugin](https://www.youtube.com/watch?v=_Tk #### The composer.json file -You've created the necessary plugin structure and the plugin base class. The only thing missing for your plugin to be fully functional, is a `composer.json` file inside your plugin's root directory. -`custom/plugins/SwagBasicExample/composer.json` +You've created the necessary plugin structure and the plugin base class. The only thing missing for your plugin to be fully functional is a `composer.json` file inside your plugin's root directory: `custom/plugins/SwagBasicExample/composer.json`. -This file consists of basic information, that Shopware needs to know about your plugin, such as: +This file consists of basic information that Shopware needs to know about your plugin: * The technical name * The description @@ -103,9 +99,7 @@ This file consists of basic information, that Shopware needs to know about your * The required dependencies * ... and a few more -This file can also be read by [Composer](https://getcomposer.org/), but that's not part of this guide. -Further information you'll have to add in there: The `type` has to be `shopware-platform-plugin`, so Shopware can safely recognize your plugin as such -and the `require` field must include at least `shopware/core`, to check for compatibility. +This file can also be read by [Composer](https://getcomposer.org/), but that's not part of this guide. Further information you'll have to add in there: The `type` has to be `shopware-platform-plugin`, so Shopware can safely recognize your plugin. The `require` field must include at least `shopware/core` to check for compatibility. Here's an example `composer.json` for this guide, which will do the trick: @@ -171,8 +165,7 @@ Once inside there, you need to refresh the list of plugins, that Shopware knows php bin/console plugin:refresh ``` -There might be a warning appearing regarding the `version` of the `composer.json` file, but you can safely ignore that. -You should end up with a list like the following: +There might be a warning appearing regarding the `version` of the `composer.json` file, but you can safely ignore that. You should end up with a list like the following: ```bash Shopware Plugin Service @@ -203,16 +196,15 @@ Shopware Plugin Lifecycle Service Plugin "SwagBasicExample" has been installed and activated successfully. ``` -And that's basically it. -**You've just successfully created your Shopware 6 plugin!** +And that's basically it. **You've just successfully created your Shopware 6 plugin!** ## Next steps -There's many more things to discover when creating your first plugin. Hence, here's a list of important articles, that may be of interest for you. +These guides may be of interest when creating your first plugin: -* [Installing data with your plugin](../../../guides/plugins/plugins/plugin-fundamentals/database-migrations.md) +* [Installing data with your plugin](../../../guides/plugins/plugins/database/database-migrations.md) * [Learn more about the plugin lifecycle methods](../../../guides/plugins/plugins/plugin-fundamentals/plugin-lifecycle.md) * [Adding a configuration to your plugin](../../../guides/plugins/plugins/plugin-fundamentals/add-plugin-configuration.md) -* [Learning about the service container](../../../guides/plugins/plugins/plugin-fundamentals/dependency-injection.md) -* [Adding a custom service](../../../guides/plugins/plugins/plugin-fundamentals/add-custom-service.md) -* [Start listening to events](../../../guides/plugins/plugins/plugin-fundamentals/listening-to-events.md) +* [Learning about the service container](../../../guides/plugins/plugins/services/dependency-injection.md) +* [Adding a custom service](../../../guides/plugins/plugins/services/add-custom-service.md) +* [Start listening to events](../../../guides/plugins/plugins/framework/event/listening-to-events.md) diff --git a/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md b/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md index 4786adf86c..f4c69e14a2 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md +++ b/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md @@ -13,7 +13,7 @@ Quite often one might want to run any type of code on a regular basis, e.g. to c ## Prerequisites -This guide is built upon our [plugin base guide](../plugin-base-guide), but that one is not mandatory. Knowing how the `services.php` file in a plugin works is also helpful, which will be taught in our guides about [Dependency Injection](dependency-injection) and [Creating a service](add-custom-service). It is shortly explained here as well though, so no worries! +This guide is built upon our [plugin base guide](../plugin-base-guide), but that one is not mandatory. Knowing how the `services.php` file in a plugin works is also helpful, which will be taught in our guides about [Dependency Injection](../services/dependency-injection.md) and [Creating a service](../services/add-custom-service.md). It is shortly explained here as well though, so no worries! ::: info Refer to this video on **[Adding scheduled tasks](https://www.youtube.com/watch?v=88S9P3x6wYE)**. Also available on our free online training ["Shopware 6 Backend Development"](https://academy.shopware.com/courses/shopware-6-backend-development-with-jisse-reitsma). diff --git a/guides/plugins/plugins/plugin-fundamentals/plugin-lifecycle.md b/guides/plugins/plugins/plugin-fundamentals/plugin-lifecycle.md index 0598bb51e3..9da908f428 100644 --- a/guides/plugins/plugins/plugin-fundamentals/plugin-lifecycle.md +++ b/guides/plugins/plugins/plugin-fundamentals/plugin-lifecycle.md @@ -1,15 +1,49 @@ --- nav: - title: Plugin lifecycle methods + title: Plugin Lifecycle Methods position: 140 --- # Plugin Lifecycle Methods -## Overview +Shopware builds upon the `Symfony Bundle System` to extend its functionality. Whenever you create a Shopware plugin, you have to extend the `Shopware\Core\Framework\Plugin` class. If you investigate this class, you will see that this class extends `Shopware\Core\Framework\Bundle`, which in return extends the Symfony's `Bundle` class: -A Shopware plugin can be installed, activated, deactivated and then again uninstalled. Those are some plugin lifecycle methods, which will be covered a bit more in this guide. +```php +// +class YourNamespace\PluginName extends + + // plugin lifecycles + abstract class Shopware\Core\Framework\Plugin extends + + // adds support for migrations, filesystem, events, themes + abstract class Shopware\Core\Framework\Bundle extends + + // Symfony base bundle + abstract class Symfony\Component\HttpKernel\Bundle +``` + +A Shopware plugin goes through several lifecycle stages: + +- Install +- Activate +- Deactivate +- Update +- Uninstall + +| Lifecycle | Description | +| :--- | :--- | +| `install()` | Executed on plugin install | +| `activate()` | Executed **before** plugin activation | +| `deactivate()` | Executed **before** plugin deactivation | +| `update()` | Executed on plugin update | +| `postInstall()` | Executed **after** successful plugin install | +| `postUpdate()` | Executed **after** successful plugin update | +| `uninstall()` | Executed on plugin uninstallation | + +Each stage allows you to prepare, modify, or clean up your plugin’s integration with the system. + +Lifecycle methods are implemented in your base plugin class (`/src/SwagBasicExample.php`), which acts like a bootstrap file, and provide access to the [service container](../services/dependency-injection.md) via `$this->container`. ## Prerequisites @@ -19,7 +53,7 @@ This guide is built upon our [plugin base guide](../plugin-base-guide), which ex Each of the followings methods are going to be part of the plugin bootstrap, in this example the file will be `/src/SwagBasicExample.php`, which is the bootstrap file of the previously mentioned plugin base guide. -Throughout all of the lifecycle methods, you have access to the [service container](dependency-injection) via `$this->container`. +Throughout all of the lifecycle methods, you have access to the [service container](../services/dependency-injection.md) via `$this->container`. ### Install @@ -35,11 +69,11 @@ public function install(InstallContext $installContext): void In your install method, you have access to the `InstallContext`, which provides information such as: -* The current plugin version -* The current Shopware version -* The `Context`, which provides a lot more of system information, e.g. the currently used language -* A collection of the [plugin migrations](database-migrations) -* If the migrations should be executed \(`isAutoMigrate` or `setAutoMigrate` to prevent the execution\) +- The current plugin version +- The current Shopware version +- The `Context`, which provides a lot more of system information, e.g. the currently used language +- A collection of the [plugin migrations](../database/database-migrations.md) +- If the migrations should be executed \(`isAutoMigrate` or `setAutoMigrate` to prevent the execution\) ::: info You maybe don't want to create new data necessary for your plugin in the `install` method, even though it seems to be the perfect place. That's because an installed plugin is not automatically active yet - hence some data changes would have an impact on the system before the plugin is even active and therefore functioning. A good rule of thumb is: Only install new data or entities, that can be activated or deactivated themselves, such as a payment method. This way you can create a new payment method in the `install` method, but keep it inactive for now. @@ -89,8 +123,8 @@ Refer to this video on **[Uninstalling a plugin](https://www.youtube.com/watch?v The `activate` method is executed once the plugin gets actually activated. You most likely want to do one of the following things here: -* Activate entities that you created in the install method, e.g. such as a payment method -* Create new entities or data, that you couldn't create in the install method +- Activate entities that you created in the install method, e.g. such as a payment method +- Create new entities or data, that you couldn't create in the install method ```php // /src/SwagBasicExample @@ -107,8 +141,8 @@ The `ActivateContext` provides the same information as the `InstallContext`. The opposite of the `activate` method. It is triggered once the plugin deactivates the plugin. This method should mostly do the opposite of the plugin's `activate` method: -* Deactivate entities created by the `install` method -* Maybe remove entities, that cannot be deactivated but would harm the system, if they remained in the system while the plugin is inactive +- Deactivate entities created by the `install` method +- Maybe remove entities, that cannot be deactivated but would harm the system, if they remained in the system while the plugin is inactive ```php // /src/SwagBasicExample @@ -123,7 +157,7 @@ The `DeactivateContext` provides the same information as the `InstallContext`. ### Update -The `update` method is executed once your plugin gets updated to a new version. You do not need to update database entries here, since this should be done via [plugin migrations](database-migrations). Otherwise you'd have to check if this specific update to an entity was already done in a previous `update` method execution, mostly by using plugin version conditions. +The `update` method is executed once your plugin gets updated to a new version. You do not need to update database entries here, since this should be done via [plugin migrations](../database/database-migrations.md). Otherwise you'd have to check if this specific update to an entity was already done in a previous `update` method execution, mostly by using plugin version conditions. However, of course you can still do that if necessary. Also, non-database updates can be done here. diff --git a/guides/plugins/plugins/plugin-fundamentals/use-plugin-configuration.md b/guides/plugins/plugins/plugin-fundamentals/use-plugin-configuration.md index 11c0ac0352..118f69e6e2 100644 --- a/guides/plugins/plugins/plugin-fundamentals/use-plugin-configuration.md +++ b/guides/plugins/plugins/plugin-fundamentals/use-plugin-configuration.md @@ -1,6 +1,6 @@ --- nav: - title: Use plugin configuration + title: Use Plugin Configuration position: 20 --- @@ -13,7 +13,7 @@ The [Add a Plugin Configuration Guide](add-plugin-configuration.md) shows how to - A plugin [Plugin Base Guide](../plugin-base-guide.md) - [Plugin configuration](add-plugin-configuration.md) in the first instance -- Familiarity with the [Listening to events](listening-to-events.md) guide, as in this example the configuration is read inside of a subscriber +- Familiarity with the [Listening to events](../framework/event/listening-to-events.md) guide, as in this example the configuration is read inside of a subscriber ## Overview diff --git a/guides/plugins/plugins/plugins-for-symfony-developers.md b/guides/plugins/plugins/plugins-for-symfony-developers.md deleted file mode 100644 index 41ecf3581c..0000000000 --- a/guides/plugins/plugins/plugins-for-symfony-developers.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -nav: - title: Plugins for Symfony developers - position: 20 - ---- - -# Plugins for Symfony Developers - -## Overview - -This guide serves as an entry point for developers familiar with the concepts of `Symfony bundles`. - -::: info -Check out our [Shopware Toolbox PHPStorm extension](../../../resources/tooling/ide/shopware-toolbox) with useful features like autocompletion, code generation or guideline checks. -::: - -## Prerequisites - -This guide handles some base concepts of Shopware plugins. Therefore, you may want to have a look at [Plugin base guide](plugin-base-guide) first. - -As this guide also references the functionality of Symfony bundles, you should have at least a basic knowledge of it. You may want to have a look or refresh your knowledge on Symfony's [Bundle system](https://symfony.com/doc/current/bundles.html). - -## Symfony bundles - -A bundle is the Symfony's preferred way to provide additional third-party features to any Symfony application. Those bundles are everywhere: Symfony even outsources many of its core features into external bundles. The template engine `Twig`, the `Security` bundle, the `WebProfiler`, as well as many other third-party bundles can be installed on demand to extend your Symfony application in any way. The Bundle System is Symfony's way of providing an extendable framework with plugin capabilities. - -## Shopware plugins - -Shopware is building upon the `Symfony Bundle System` to extend its functionality even more. This allows the Shopware Plugin System to function as a traditional plugin system with features like plugin lifecycles and more. - -Whenever you create a Shopware plugin, you have to extend the `Shopware\Core\Framework\Plugin` class. If you investigate this class, you will see that this class extends `Shopware\Core\Framework\Bundle`, which in return extends the Symfony's `Bundle` class: - -```php -// -class YourNamespace\PluginName extends - - // plugin lifecycles - abstract class Shopware\Core\Framework\Plugin extends - - // adds support for migrations, filesystem, events, themes - abstract class Shopware\Core\Framework\Bundle extends - - // Symfony base bundle - abstract class Symfony\Component\HttpKernel\Bundle -``` - -As you can see, any Shopware plugin is also a Symfony bundle internally as well, and will be handled as such by Symfony. A plugin adds support for some cases, specific to the Shopware environment. These include, for example, handling plugin migrations and registering Shopware business events. - -### Plugin lifecycle - -As mentioned before, Shopware extends the `Symfony Bundle System` with some functionality to adjust its use for the Shopware ecosystem. For you as plugin developer, the most important addition is the extended plugin lifecycle. - -A Shopware plugin runs through a lifecycle. Your plugin's base class can implement the following methods to execute any sort of installation or maintenance tasks. - -| Lifecycle | Description | -| :--- | :--- | -| `install()` | Executed on plugin install | -| `postInstall()` | Executed **after** successful plugin install | -| `update()` | Executed on plugin update | -| `postUpdate()` | Executed **after** successful plugin update | -| `uninstall()` | Executed on plugin uninstallation | -| `activate()` | Executed **before** plugin activation | -| `deactivate()` | Executed **before** plugin deactivation | - -## Next steps - -Now that you know about the differences between a Symfony bundle and a Shopware plugin, you might also want to have a look into the following Symfony-specific topics and how they are integrated in Shopware 6: - -* [Dependency Injection](plugin-fundamentals/dependency-injection) -* [Listening to events](plugin-fundamentals/listening-to-events) - -::: info -Here are some useful videos explaining: - -* **[Bundle Methods in a plugin](https://www.youtube.com/watch?v=cUXcDwQwmPk)** -* **[Symfony services in Shopware 6](https://www.youtube.com/watch?v=l5QJ8EtilaY)** - -Also available on our free online training ["Shopware 6 Backend Development"](https://academy.shopware.com/courses/shopware-6-backend-development-with-jisse-reitsma). -::: diff --git a/guides/plugins/plugins/redis.md b/guides/plugins/plugins/redis.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md b/guides/plugins/plugins/services/add-custom-service.md similarity index 88% rename from guides/plugins/plugins/plugin-fundamentals/add-custom-service.md rename to guides/plugins/plugins/services/add-custom-service.md index 05089b96bc..dc932b72e6 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md +++ b/guides/plugins/plugins/services/add-custom-service.md @@ -1,20 +1,18 @@ --- nav: - title: Add custom service + title: Add Custom Service position: 60 --- # Add Custom Service -## Overview - In this guide you'll learn how to create a custom service using the Symfony [DI Container](https://symfony.com/doc/current/service_container.html). ## Prerequisites To add your own custom service for your plugin, you first need a plugin as a base. -Therefore, you can refer to the [Plugin Base Guide](../plugin-base-guide). +Therefore, you can refer to the [Plugin Base Guide](../plugin-base-guide.md). ## Adding service @@ -123,7 +121,6 @@ Choose the one that suits you best. ## Next steps -You have now created your own custom service. -In the same manner, you can create other important plugin classes, such as [commands](add-custom-commands), [scheduled tasks](add-scheduled-task) or a [subscriber to listen to events](listening-to-events). +You have now created your own custom service. In the same manner, you can create other important plugin classes, such as [commands](../plugin-fundamentals/add-custom-commands.md), [scheduled tasks](../plugin-fundamentals/add-scheduled-task.md), or a [subscriber to listen to events](../framework/event/listening-to-events.md). -Furthermore, we also have a guide explaining how to [customize an existing service](adjusting-service) instead. +Furthermore, we also have a guide explaining how to [customize an existing service](../services/adjusting-service.md) instead. diff --git a/guides/plugins/plugins/plugin-fundamentals/adjusting-service.md b/guides/plugins/plugins/services/adjusting-service.md similarity index 100% rename from guides/plugins/plugins/plugin-fundamentals/adjusting-service.md rename to guides/plugins/plugins/services/adjusting-service.md diff --git a/guides/plugins/plugins/plugin-fundamentals/dependency-injection.md b/guides/plugins/plugins/services/dependency-injection.md similarity index 100% rename from guides/plugins/plugins/plugin-fundamentals/dependency-injection.md rename to guides/plugins/plugins/services/dependency-injection.md diff --git a/guides/plugins/plugins/services/index.md b/guides/plugins/plugins/services/index.md new file mode 100644 index 0000000000..42f1c2f2c2 --- /dev/null +++ b/guides/plugins/plugins/services/index.md @@ -0,0 +1,13 @@ +--- +nav: + title: Services + position: 50 +--- + +# Services + +This section explains how to register, customize and extend services within your plugin: + +* [Dependency Injection](./dependency-injection.md) +* [Add Custom Service](./add-custom-service.md) +* [Adjusting a Service](./adjusting-service.md) diff --git a/guides/plugins/plugins/storefront/add-caching-to-custom-controller.md b/guides/plugins/plugins/storefront/advanced/add-caching-to-custom-controller.md similarity index 90% rename from guides/plugins/plugins/storefront/add-caching-to-custom-controller.md rename to guides/plugins/plugins/storefront/advanced/add-caching-to-custom-controller.md index d001a4ad70..f58a80d113 100644 --- a/guides/plugins/plugins/storefront/add-caching-to-custom-controller.md +++ b/guides/plugins/plugins/storefront/advanced/add-caching-to-custom-controller.md @@ -1,19 +1,17 @@ --- nav: - title: Add caching to custom controller + title: Add Caching to Custom Controller position: 30 --- # Add Caching to Custom Controller -## Overview - In this guide you will learn how to define a controller route as cacheable for the HTTP cache. ## Prerequisites -In order to add a cache to an own controller route, you first need a plugin with a controller. Therefore, you can refer to the [Add custom controller guide](./add-custom-controller). +In order to add a cache to an own controller route, you first need a plugin with a controller. Refer to the [Add custom controller guide](../controllers/add-custom-controller.md). ## Define the controller as cacheable @@ -55,6 +53,6 @@ class ExampleController extends StorefrontController As soon as a controller route has been defined as cacheable, and the corresponding response is written to the cache, it is tagged accordingly. For this purpose, the core uses all cache tags generated during the request or loaded from existing cache entries. The cache invalidation of the Storefront controller routes is controlled by the cache invalidation of the store API routes. -For more information about Store API cache invalidation, you can refer to the [Caching Guide](../framework/caching/index.md). +For more information about Store API cache invalidation, refer to the [Caching Guide](../../framework/caching/index.md). This is because all data loaded in a controller route, is loaded in the core via the corresponding Store API routes and provided with corresponding cache tags. So the tags of the HTTP cache entries we have in the core consists of the sum of all store api tags generated or loaded during the request. Therefore the invalidation of a controller route that loads all data via the store API, no additional invalidation needs to be written. diff --git a/guides/plugins/plugins/storefront/add-cookie-to-manager.md b/guides/plugins/plugins/storefront/advanced/add-cookie-to-manager.md similarity index 93% rename from guides/plugins/plugins/storefront/add-cookie-to-manager.md rename to guides/plugins/plugins/storefront/advanced/add-cookie-to-manager.md index d08c8d8d14..25a9f5ed9a 100644 --- a/guides/plugins/plugins/storefront/add-cookie-to-manager.md +++ b/guides/plugins/plugins/storefront/advanced/add-cookie-to-manager.md @@ -1,6 +1,6 @@ --- nav: - title: Add cookie to manager + title: Add Cookie to Manager position: 160 --- @@ -12,12 +12,12 @@ nav: Since the GDPR was introduced, every website has to be shipped with some sort of a cookie consent manager. This is also the case for Shopware 6 of course, which comes with a cookie consent manager by default. In this guide you will learn how you can add your own cookies to the cookie consent manager of Shopware 6. ::: info -For a comprehensive understanding of Shopware's cookie consent system, see the [Cookie Consent Management Concept](../../../../concepts/commerce/content/cookie-consent-management). +For a comprehensive understanding of Shopware's cookie consent system, see the [Cookie Consent Management Concept](../../../../../concepts/commerce/content/cookie-consent-management.md). ::: ## Prerequisites -This guide is built upon the [Plugin base guide](../plugin-base-guide), so take a look at that first if you're lacking a running plugin. Also, you will need to know how to [create your own service](../plugin-fundamentals/add-custom-service) and [subscribe to an event](../plugin-fundamentals/listening-to-events), so you might want to take a look at those guides as well. +Review the [Plugin base guide](../../plugin-base-guide.md) and create a running plugin. Also, you will need to know how to [create your own service](../../services/add-custom-service.md) and [subscribe to an event](../../framework/event/listening-to-events.md), so you might want to take a look at those guides as well. ## Extend the cookie consent manager diff --git a/guides/plugins/plugins/storefront/advanced/index.md b/guides/plugins/plugins/storefront/advanced/index.md new file mode 100644 index 0000000000..b6fd475ba3 --- /dev/null +++ b/guides/plugins/plugins/storefront/advanced/index.md @@ -0,0 +1,16 @@ +--- +nav: + title: Advanced + position: 100 +--- + +# Advanced Storefront Customization + +This section covers advanced topics for extending and customizing the Storefront in plugins. + +These guides focus on performance optimization, caching behavior, cookie consent integration, and JavaScript plugin control: + +* [Add caching to custom controller](./add-caching-to-custom-controller.md) +* [Add cookie to manager](./add-cookie-to-manager.md) +* [Reacting to cookie consent changes](./reacting-to-cookie-consent-changes.md) +* [Remove Javascript plugin](./remove-unnecessary-js-plugin.md) diff --git a/guides/plugins/plugins/storefront/reacting-to-cookie-consent-changes.md b/guides/plugins/plugins/storefront/advanced/reacting-to-cookie-consent-changes.md similarity index 91% rename from guides/plugins/plugins/storefront/reacting-to-cookie-consent-changes.md rename to guides/plugins/plugins/storefront/advanced/reacting-to-cookie-consent-changes.md index c20a229bb2..b9a391ccf7 100644 --- a/guides/plugins/plugins/storefront/reacting-to-cookie-consent-changes.md +++ b/guides/plugins/plugins/storefront/advanced/reacting-to-cookie-consent-changes.md @@ -1,22 +1,20 @@ --- nav: - title: Reacting to cookie consent changes + title: Reacting to Cookie Consent Changes position: 170 --- # Reacting to Cookie Consent Changes -## Overview - This guide explains how to react to changes in cookie consent made by the user via JavaScript. This is essential when your plugin needs to load third-party scripts, tracking codes, or other functionality only when users have given their consent. ## Prerequisites -This guide is built upon both the [Plugin base guide](../plugin-base-guide) and the [Adding a cookie to the consent manager](add-cookie-to-manager) guide, so make sure to know those beforehand. Also, nice to know is the guide about [Reacting to javascript events](reacting-to-javascript-events), since this will be done here, same as how to [create and load a JavaScript](add-custom-javascript) file in the first place. +This guide is built upon both the [Plugin base guide](../../plugin-base-guide.md) and the [Adding a cookie to the consent manager](../advanced/add-cookie-to-manager.md) guide, so make sure to know those beforehand. Reviewing the guides on [Reacting to JavaScript events](../javascript/reacting-to-javascript-events.md) and [creating and loading a JavaScript file](../javascript/add-custom-javascript.md) is also advisable. ::: info -For a comprehensive understanding of Shopware's cookie consent system, see the [Cookie Consent Management Concept](../../../../concepts/commerce/content/cookie-consent-management). +For a comprehensive understanding of Shopware's cookie consent system, see the [Cookie Consent Management Concept](../../../../../concepts/commerce/content/cookie-consent-management.md). ::: ## Key Principles diff --git a/guides/plugins/plugins/storefront/remove-unnecessary-js-plugin.md b/guides/plugins/plugins/storefront/advanced/remove-unnecessary-js-plugin.md similarity index 63% rename from guides/plugins/plugins/storefront/remove-unnecessary-js-plugin.md rename to guides/plugins/plugins/storefront/advanced/remove-unnecessary-js-plugin.md index 7abb7927f3..72ac892a37 100644 --- a/guides/plugins/plugins/storefront/remove-unnecessary-js-plugin.md +++ b/guides/plugins/plugins/storefront/advanced/remove-unnecessary-js-plugin.md @@ -1,27 +1,27 @@ --- nav: - title: Remove Javascript plugin + title: Remove JavaScript Plugin position: 200 --- -# Remove Javascript Plugin +# Remove JavaScript Plugin ## Overview -When you develop your own plugin, you might want to exclude Javascript plugins at some occasions. For example, if you don't want a Core plugin to interfere, with your own code. This guide will teach you how to remove this Javascript plugin with your own Shopware plugin. +When you develop your own plugin, you might want to exclude JavaScript plugins at some occasions. For example, if you don't want a Core plugin to interfere, with your own code. This guide will teach you how to remove this JavaScript plugin with your own Shopware plugin. ## Prerequisites -While this is not mandatory, having read the guide about adding custom javascript plugins beforehand might help you understand this guide a bit further: +While this is not mandatory, having read the guide about adding custom JavaScript plugins beforehand might help you understand this guide a bit further: - + Other than that, this guide just requires you to have a running plugin installed, e.g. our plugin from the plugin base guide: - + -## Unregistering Javascript Plugin +## Unregistering JavaScript Plugin Imagine we wanted to exclude the `OffCanvasCart` plugin, just to get a test case which can be inspected easily. In order to remove a Javascript plugin, you only need to add the following line to your `main.js` file: @@ -36,7 +36,7 @@ In our case, we shouldn't find `OffCanvasCart` in the listed plugins anymore. ## Next steps -Did you already take a look at our other storefront guides? They can give you some neat starting points on how to extend and customize Shopware's storefront. +These guides explain how to extend and customize Shopware's Storefront: -* [Override existing Javascript in your plugin](override-existing-javascript) -* [Reacting to Javascript events](reacting-to-javascript-events) +* [Override existing JavaScript in your plugin](../javascript/override-existing-javascript.md) +* [Reacting to JavaScript events](../javascript/reacting-to-javascript-events.md) diff --git a/guides/plugins/plugins/storefront/add-custom-controller.md b/guides/plugins/plugins/storefront/controllers/add-custom-controller.md similarity index 97% rename from guides/plugins/plugins/storefront/add-custom-controller.md rename to guides/plugins/plugins/storefront/controllers/add-custom-controller.md index 7409aa8f83..882e36fbf4 100644 --- a/guides/plugins/plugins/storefront/add-custom-controller.md +++ b/guides/plugins/plugins/storefront/controllers/add-custom-controller.md @@ -1,20 +1,18 @@ --- nav: - title: Add custom controller + title: Add Custom Controller position: 20 --- # Add Custom Controller -## Overview - In this guide you will learn how to create a custom Storefront controller. ## Prerequisites In order to add your own controller for your plugin, you first need a plugin as base. -Therefore, you can refer to the [Plugin Base Guide](../plugin-base-guide). +Therefore, you can refer to the [Plugin Base Guide](../../plugin-base-guide.md). ::: info Refer to this video on **[Common Storefront controller tasks](https://www.youtube.com/watch?v=5eXXNh4cQG0)** explaining the basics about Storefront controllers. @@ -190,7 +188,7 @@ Let's change that now. As previously mentioned, the code will try to render an `index.html.twig` file. Thus, we have to create an `index.html.twig` in the `/src/Resources/views/storefront/page/example` directory, as defined in our controller. Below you can find an example, where we extend from the template `base.html.twig` and override the block `base_content`. -In our [Customize templates](customize-templates) guide, you can learn more about customizing templates. +In our [Customize templates](../templates/customize-templates.md) guide, you can learn more about customizing templates. ::: code-group @@ -314,4 +312,4 @@ public function showExample(Request $request, SalesChannelContext $context): Res ## Next steps -Since you've already created a controller now, which is also part of creating a so-called "page" in Shopware, you might want to head over to our guide about [creating a page](add-custom-page). +Since you've already created a controller now, which is also part of creating a so-called "page" in Shopware, you might want to head over to our guide about [creating a page](../controllers/add-custom-page.md). diff --git a/guides/plugins/plugins/storefront/add-custom-page.md b/guides/plugins/plugins/storefront/controllers/add-custom-page.md similarity index 93% rename from guides/plugins/plugins/storefront/add-custom-page.md rename to guides/plugins/plugins/storefront/controllers/add-custom-page.md index 8c2b3b2036..950dae3e54 100644 --- a/guides/plugins/plugins/storefront/add-custom-page.md +++ b/guides/plugins/plugins/storefront/controllers/add-custom-page.md @@ -1,30 +1,28 @@ --- nav: - title: Add custom page + title: Add Custom Page position: 100 --- # Add Custom Page -## Overview - In this guide, you will learn how to create a custom page for your Storefront. A page in general consists of a controller, a page loader, a "page loaded" event and a page class, which is like a struct and contains the most necessary data for the page. ## Prerequisites To add your own custom page for your plugin, you first need a plugin as base. -Therefore, you can refer to the [Plugin Base Guide](../plugin-base-guide). Since you need to load your page with a controller, you might want to have a look at our guide about [creating a controller](add-custom-controller) first. +Therefore, you can refer to the [Plugin Base Guide](../../plugin-base-guide.md). Since you need to load your page with a controller, you might want to have a look at our guide about [creating a controller](../controllers/add-custom-controller.md) first. The controller created in the previously mentioned controller guide will also be used in this guide. ## Adding custom page In the following sections, we'll create each of the necessary classes one by one. The first one will be a controller, whose creation is not going to be explained here again. -Have a look at the guide about [creating a controller](add-custom-controller) to see why it works. +Have a look at the guide about [creating a controller](../controllers/add-custom-controller.md) to see why it works. -### Creating ExampleController +### Creating `ExampleController` Let's have a look at an example controller. @@ -56,7 +54,7 @@ class ExampleController extends StorefrontController It has a method `examplePage`, which is accessible via the route `example-page`. This method will be responsible for loading your page later on, but we'll leave it like that for now. -Don't forget to [register your controller via the DI](add-custom-controller#services-xml-example). +Don't forget to [register your controller via the DI](../controllers/add-custom-controller.md#servicesphp-example). ### Creating the pageloader @@ -201,7 +199,7 @@ Note, that we've added the page to the template variables. #### Adjusting the services.php -In addition, it is necessary to pass the argument with the ID of the `ExamplePageLoader` class to the [configuration](add-custom-controller#services-xml-example) of the controller service in the `services.php`. +In addition, it is necessary to pass the argument with the ID of the `ExamplePageLoader` class to the [configuration](add-custom-controller.md#servicesphp-example) of the controller service in the `services.php`. ::: code-group @@ -264,7 +262,7 @@ class ExamplePage extends Page As explained in the page loader section, your page can contain all kinds of custom data. It has to provide a getter and a setter for the custom data, so it can be applied and read. -In this example, the entity from our guide about [creating custom complex data](../framework/data-handling/add-custom-complex-data#entity-class) is being used. +In this example, the entity from our guide about [creating custom complex data](../../framework/data-handling/add-custom-complex-data.md#entity-class) is being used. And that's it already. Your page is ready to go. @@ -319,4 +317,4 @@ You've now successfully created a whole new page, including a custom controller, and the necessary classes to create a new page, a loader, the page struct and the page loaded event. In your `load` method, you've used the `GenericPageLoader`, which takes care of the meta-information of the page. -There are also "pagelets", basically reusable fractions of a page. Learn how to [create a custom pagelet](add-custom-pagelet). +There are also "pagelets", basically reusable fractions of a page. Learn how to [create a custom pagelet](add-custom-pagelet.md). diff --git a/guides/plugins/plugins/storefront/add-custom-pagelet.md b/guides/plugins/plugins/storefront/controllers/add-custom-pagelet.md similarity index 92% rename from guides/plugins/plugins/storefront/add-custom-pagelet.md rename to guides/plugins/plugins/storefront/controllers/add-custom-pagelet.md index b04e967841..3dbf44ea57 100644 --- a/guides/plugins/plugins/storefront/add-custom-pagelet.md +++ b/guides/plugins/plugins/storefront/controllers/add-custom-pagelet.md @@ -1,27 +1,25 @@ --- nav: - title: Add custom pagelet + title: Add Custom Pagelet position: 110 --- # Add Custom Pagelet -## Overview - In this guide, you will learn how to create custom pagelets for your Storefront pages. In short: Pages are exactly that, a fully functioning page of your store with a template loaded by a route. A pagelet is an important and reusable fraction of several pages, such as a footer or the navigation. ## Prerequisites -To add your own custom pagelet for your plugin, you first need a plugin as base. Therefore, you can refer to the [Plugin Base Guide](../plugin-base-guide). Since a pagelet is just part of another page, we are going to use the page created in our guide about [adding a custom page](add-custom-page). +To add your own custom pagelet for your plugin, you first need a plugin as base. Therefore, you can refer to the [Plugin Base Guide](../../plugin-base-guide.md). Since a pagelet is just part of another page, we are going to use the page created in our guide about [adding a custom page](../controllers/add-custom-page.md). ## Adding custom pagelet Basically a pagelet is created exactly like a page: You need a pagelet loader, a pagelet struct to hold the data and a pagelet loaded event. -Since creating this kind of classes is explained in detail in our guide about [adding a custom page](add-custom-page), it is not going to be explained here in detail again. Yet, there's some differences worth mentioning: +Since creating this kind of classes is explained in detail in our guide about [adding a custom page](../controllers/add-custom-page.md), it is not going to be explained here in detail again. Yet, there's some differences worth mentioning: * The struct to hold the data has to extend from the `Shopware\Storefront\Pagelet\Pagelet` class instead of `Shopware\Storefront\Page\Page` * A pagelet doesn't have to be bound to a controller, e.g. with an extra route. It can have a route though! @@ -159,7 +157,7 @@ Also, the getter method is no longer `getPage`, but `getPagelet` instead. Most times you want to load your pagelet as part of another page. This is simply done by calling the `load` method of your pagelet in another page's `load` method. -Using the example from our [adding a custom page](add-custom-page) guide, this is what the `load` method could look like: +Using the example from our [adding a custom page](../controllers/add-custom-page.md) guide, this is what the `load` method could look like: ::: code-group diff --git a/guides/plugins/plugins/storefront/add-data-to-storefront-page.md b/guides/plugins/plugins/storefront/controllers/add-data-to-storefront-page.md similarity index 92% rename from guides/plugins/plugins/storefront/add-data-to-storefront-page.md rename to guides/plugins/plugins/storefront/controllers/add-data-to-storefront-page.md index fc049d1388..4f7bb8cd50 100644 --- a/guides/plugins/plugins/storefront/add-data-to-storefront-page.md +++ b/guides/plugins/plugins/storefront/controllers/add-data-to-storefront-page.md @@ -1,14 +1,12 @@ --- nav: - title: Add data to storefront page + title: Add Data to Storefront Page position: 150 --- # Add Data to Storefront Page -## Overview - Pages or pagelets are the objects that get handed to the templates and provide all necessary information for the template to render. If you make template changes you probably want to display some data that is currently not available in the page. @@ -17,14 +15,14 @@ This guide will show you how to achieve this, by adding the total number of acti ## Prerequisites -This guide is built upon our [Plugin base guide](../plugin-base-guide), so keep that in mind. +This guide is built upon our [Plugin base guide](../../plugin-base-guide.md), so keep that in mind. Also the following knowledge is necessary, even though some of them are covered here as well: -* Knowing how to [listen to events by using a subscriber](../plugin-fundamentals/listening-to-events) -* Knowing how to [customize storefront templates](customize-templates) -* Knowing how to [read data using our data abstraction layer](../framework/data-handling/reading-data) -* Knowing how to [add a store-api route](../framework/store-api/add-store-api-route) +* Knowing how to [listen to events by using a subscriber](../../framework/event/listening-to-events.md) +* Knowing how to [customize storefront templates](../templates/customize-templates.md) +* Knowing how to [read data using our data abstraction layer](../../framework/data-handling/reading-data.md) +* Knowing how to [add a store-api route](../../framework/store-api/add-store-api-route.md) ## Adding data to the Storefront @@ -89,7 +87,7 @@ While the `ProductListRoute` could provide this data, it would return far more i Therefore, we will create a new `store-api` route tailored to our needs. -First you should read our guide for [adding store-api routes](../framework/store-api/add-store-api-route). +First you should read our guide for [adding store-api routes](../../framework/store-api/add-store-api-route.md). Our new Route should look like this: @@ -184,7 +182,7 @@ return static function (ContainerConfigurator $configurator): void { }; ``` -The routes.php according to our guide for [adding store-api routes](../framework/store-api/add-store-api-route) should look like this. +The routes.php according to our guide for [adding store-api routes](../../framework/store-api/add-store-api-route.md) should look like this. ```php // /src/Resources/config/routes.php @@ -199,7 +197,7 @@ return static function (RoutingConfigurator $routes): void { ### ProductCountRouteResponse -The RouteResponse according to our guide for [adding store-api routes](../framework/store-api/add-store-api-route) should look like this +The RouteResponse according to our guide for [adding store-api routes](../../framework/store-api/add-store-api-route.md) should look like this ```php [\Shopware\Storefront\Framework\Routing\StorefrontRouteScope::ID]])]`. +* Each action requires a `#Route` attribute. +* Route names should use the `frontend` prefix (unless explicitly configured otherwise). +* Each route must define the corresponding HTTP Method: GET, POST, DELETE, PATCH. +* Each action must declare a return type. +* The function name should be concise. +* Dependencies must be injected via the class constructor and defined in the DI-container service definition. +* Dependent services must be assigned to a private class property. + +Responsibilities: + +* A controller represents a single entry point. +* A route must have a single purpose. +* Controllers must not contain business logic. +* Business logic belongs in Store API routes. +* Controllers must not access repositories directly. + +Data Loading: + +* Read operations must delegate to Store API routes or page loaders. +* Routes that render full storefront pages should use a page loader class to load all corresponding data. +* Page loaders may call multiple Store API routes. + +Write Operations: + +* must call a corresponding Store API route. +* Use the `createActionResponse()` function for redirects or forwards. + +Caching: + +* Pages with identical data for all users should use the `_httpCache` attribute. + +## Additional guidelines + +* Use Symfony flash bags for error reporting. +* Storefront functionality should be available inside the Store API too. diff --git a/guides/plugins/plugins/storefront/add-custom-captcha.md b/guides/plugins/plugins/storefront/howto/add-custom-captcha.md similarity index 90% rename from guides/plugins/plugins/storefront/add-custom-captcha.md rename to guides/plugins/plugins/storefront/howto/add-custom-captcha.md index 96041d9923..39e8a4fb1e 100644 --- a/guides/plugins/plugins/storefront/add-custom-captcha.md +++ b/guides/plugins/plugins/storefront/howto/add-custom-captcha.md @@ -1,19 +1,17 @@ --- nav: - title: Add custom captcha + title: Add Custom Captcha position: 80 --- -# Add custom captcha +# Add Custom Captcha -## Overview - -You can add your custom captcha to the Shopware 6 core. This guide will show you how to do that. +Add your custom captcha to the Shopware 6 core. This guide shows you how. ## Prerequisites -In order to be able to start with this guide, you need to have an own plugin running. As to most guides, this guide is also built upon the [Plugin base guide](../plugin-base-guide) +A running plugin is required. Review the [Plugin base guide](../../plugin-base-guide.md) for guidance on creating one. ## Adding custom captcha to your plugin diff --git a/guides/plugins/plugins/storefront/add-custom-sorting-product-listing.md b/guides/plugins/plugins/storefront/howto/add-custom-sorting-product-listing.md similarity index 91% rename from guides/plugins/plugins/storefront/add-custom-sorting-product-listing.md rename to guides/plugins/plugins/storefront/howto/add-custom-sorting-product-listing.md index f8e36bbc53..bf0bb835eb 100644 --- a/guides/plugins/plugins/storefront/add-custom-sorting-product-listing.md +++ b/guides/plugins/plugins/storefront/howto/add-custom-sorting-product-listing.md @@ -1,23 +1,21 @@ --- nav: - title: Add custom sorting for product listing + title: Add Custom Sorting for Product Listing position: 220 --- # Add Custom Sorting for Product Listing -## Overview - Individual sortings are groups of sorting options which you can use to sort product listings. The sortings are available in the Storefront. This guide will show you how to add individual sorting options using a migration \(manageable\) or at runtime \(non-manageable\). ## Prerequisites -In order to add your own custom sorting for product listings for your plugin, you first need a plugin as base. Therefore, you can refer to the [Plugin Base Guide](../plugin-base-guide). +A running plugin is required. Read the [Plugin Base Guide](../../plugin-base-guide.md) for guidance on creating one. -You should also have a look at our [Database migrations](../plugin-fundamentals/database-migrations) guide, as we use one in this guide. +Reviewing the [Database migrations](../../database/database-migrations.md) guide is also advisable. ## Create individual sorting with migration @@ -95,7 +93,7 @@ class Migration1615470599ExampleSorting extends MigrationStep ## Create individual sorting at runtime -You can subscribe to the `ProductListingCriteriaEvent` to add a `ProductSortingEntity` as available sorting on the fly. If you don't know how to do this, head over to our [Listening to events](../plugin-fundamentals/listening-to-events) guide. +You can subscribe to the `ProductListingCriteriaEvent` to add a `ProductSortingEntity` as available sorting on the fly. If you don't know how to do this, head over to our [Listening to events](../../framework/event/listening-to-events.md) guide. ::: info While possible, it is not recommended adding an individual sorting at runtime. If you just wish for your individual sorting to be not editable by users in the Administration, create a migration and set the parameter `locked` to be `true`. @@ -156,4 +154,4 @@ class ExampleListingSubscriber implements EventSubscriberInterface ## Next steps -To [add a custom filter](add-listing-filters) to your listing in the Storefront head over to the corresponding guide. +To [add a custom filter](./add-listing-filters.md) to your listing in the Storefront head over to the corresponding guide. diff --git a/guides/plugins/plugins/storefront/add-listing-filters.md b/guides/plugins/plugins/storefront/howto/add-listing-filters.md similarity index 95% rename from guides/plugins/plugins/storefront/add-listing-filters.md rename to guides/plugins/plugins/storefront/howto/add-listing-filters.md index 43a95bacee..bd63f20651 100644 --- a/guides/plugins/plugins/storefront/add-listing-filters.md +++ b/guides/plugins/plugins/storefront/howto/add-listing-filters.md @@ -1,27 +1,25 @@ --- nav: - title: Add custom listing filters + title: Add Custom Listing Filters position: 130 --- # Add Custom Listing Filters -## Overview - In an online shop, filters are an important feature. So you might use filters in your custom plugin. This guide will get you covered on how to implement your own, custom filters in Shopware's Storefront. ## Prerequisites Before you start reading this guide, make sure you got an own plugin installed to work with. If you need a starting point for that, see this guide: - + ## Create new Filter At first, you need to create a subscriber. In this example, we will call it `ExampleListingSubscriber`. If you are not sure on working with subscribers, please refer to the guide on working with events in Shopware: - + As usual, we will start by creating this new class in the same path as you're seeing in Shopware's core - `/src/Subscriber/ExampleListingSubscriber.php`. @@ -125,7 +123,7 @@ Well, fine - you successfully created a filter via subscriber. However, you want In this template, the existing filters are contained in the block `component_filter_panel_items`. We are going to extend this block with our new filter. If you're not sure on how to customize templates in the Storefront, we got you covered with another guide: - + ::: info The block `component_filter_panel_items` is available from Shopware Version 6.4.8.0 @@ -179,4 +177,4 @@ If we instead want our filter to be placed before or after a specific filter in ## Next steps -To add [custom sorting options](add-custom-sorting-product-listing) to your listing in the Storefront, head over to the corresponding guide. +To add [custom sorting options](../howto/add-custom-sorting-product-listing.md) to your listing in the Storefront, head over to the corresponding guide. diff --git a/guides/plugins/plugins/storefront/howto/index.md b/guides/plugins/plugins/storefront/howto/index.md new file mode 100644 index 0000000000..5d8867e41e --- /dev/null +++ b/guides/plugins/plugins/storefront/howto/index.md @@ -0,0 +1,18 @@ +--- +nav: + title: How-To Guides + position: 300 +--- + +# How-To Guides + +This section contains practical guides for implementing common customization and extension scenarios in the Storefront: + +* [Add custom captcha](./add-custom-captcha.md) +* [Add custom sorting for product listing](./add-custom-sorting-product-listing.md) +* [Add custom listing filters](./add-listing-filters.md) +* [Working with media and thumbnails](./use-media-thumbnails.md) +* [Add custom field in the Storefront](./using-custom-fields-storefront.md) +* [Using a modal window](./using-a-modal-window.md) +* [Using the datepicker plugin](./using-the-datepicker-plugin.md) +* [Use nested line items](./use-nested-line-items.md) diff --git a/guides/plugins/plugins/storefront/use-media-thumbnails.md b/guides/plugins/plugins/storefront/howto/use-media-thumbnails.md similarity index 93% rename from guides/plugins/plugins/storefront/use-media-thumbnails.md rename to guides/plugins/plugins/storefront/howto/use-media-thumbnails.md index 50056bbcb6..0b76506649 100644 --- a/guides/plugins/plugins/storefront/use-media-thumbnails.md +++ b/guides/plugins/plugins/storefront/howto/use-media-thumbnails.md @@ -1,25 +1,21 @@ --- nav: - title: Working with media and thumbnails + title: Working with Media and Thumbnails position: 190 --- # Working with Media and Thumbnails -## Overview - In Shopware's Storefront, you can assign media objects to the different entities. To name an example, this is often used for products to show more information with images on the product detail page. This guide should give you a starting point on how to use media and thumbnails in your Storefront plugin. ## Prerequisites -In order to use your own media files or thumbnails of your plugin in the Storefront, of course you first need a plugin as base. To create an own plugin, you can refer to the Plugin Base Guide: - - +You will need a plugin as a base. Refer to the [plugin base guide](../../plugin-base-guide.md) to learn how to create one. -Displaying custom images is often done by using custom fields. To take full advantage of this guide, you might want to read the corresponding guide on using custom fields: +Displaying custom images is often done by using custom fields. To take full advantage of this guide, read the corresponding guide on using custom fields: - + ## Using searchMedia function @@ -228,4 +224,4 @@ By default, lazy loading is disabled for newly added `sw_thumbnail` elements. Yo ## More interesting topics -* [Use custom assets in general](add-custom-assets) +* [Adding custom assets](../styling/add-custom-assets.md) diff --git a/guides/plugins/plugins/storefront/use-nested-line-items.md b/guides/plugins/plugins/storefront/howto/use-nested-line-items.md similarity index 82% rename from guides/plugins/plugins/storefront/use-nested-line-items.md rename to guides/plugins/plugins/storefront/howto/use-nested-line-items.md index 0972118e71..1b9df47fbb 100644 --- a/guides/plugins/plugins/storefront/use-nested-line-items.md +++ b/guides/plugins/plugins/storefront/howto/use-nested-line-items.md @@ -1,19 +1,17 @@ --- nav: - title: Use nested line items + title: Use Nested Line Items position: 270 --- # Use Nested Line Items -## Overview - -This guide will show you how to use the nested line items in the Storefront. +This guide will show you how to use nested line items. It covers extending views and shows how the Custom Product plugin handles this. ## Prerequisites -As most guides, this guide is also built upon the [Plugin base guide](../plugin-base-guide), but you don't necessarily need that. This guide will only extend views and shows how the Custom Product plugin handles this. +Reviewing the [Plugin base guide](../../plugin-base-guide.md) is advisable but unnecessary. ## Make nested line item removable diff --git a/guides/plugins/plugins/storefront/using-a-modal-window.md b/guides/plugins/plugins/storefront/howto/using-a-modal-window.md similarity index 94% rename from guides/plugins/plugins/storefront/using-a-modal-window.md rename to guides/plugins/plugins/storefront/howto/using-a-modal-window.md index b5ef502fc8..b68ca553ac 100644 --- a/guides/plugins/plugins/storefront/using-a-modal-window.md +++ b/guides/plugins/plugins/storefront/howto/using-a-modal-window.md @@ -1,25 +1,19 @@ --- nav: - title: Using a modal window + title: Using a Modal Window position: 250 --- # Using a Modal Window -## Overview - This guide explains how you can use a modal window in your plugin in different scenarios. ## Prerequisites -This guide requires you to already have a basic plugin running. This guide **does not** explain how to create a new plugin for Shopware 6. Head over to our Plugin base guide to learn how to create a plugin at first: - - - -While this is not mandatory, having read the guide about adding custom JavaScript plugins beforehand might help you understand this guide a bit further: +This guide requires you to already have a basic plugin running. Head over to the [Plugin base guide](../../plugin-base-guide.md) to learn how to create a plugin. - +Reading the guide on [adding custom JavaScript plugins](../javascript/add-custom-javascript.md) beforehand might also be helpful. ## Create a modal manually from the DOM using Bootstrap @@ -87,7 +81,7 @@ This does not work when the trigger selector is being changed via JavaScript, e. To create a modal window you can use the `PseudoModalUtil` in your plugin. -As explained in the guide on [adding custom javascript](./add-custom-javascript) we load our JavaScript plugin by creating `index.html.twig` template in the `/src/Resources/views/storefront/page/content/` folder. +As explained in the guide on [adding custom JavaScript](../javascript/add-custom-javascript.md) we load our JavaScript plugin by creating `index.html.twig` template in the `/src/Resources/views/storefront/page/content/` folder. Inside this template, extend from the `@Storefront/storefront/page/content/index.html.twig` and overwrite the `base_main_inner` block. After the parent content of the blog, add a template tag with the `data-example-plugin` attribute. ```twig diff --git a/guides/plugins/plugins/storefront/using-custom-fields-storefront.md b/guides/plugins/plugins/storefront/howto/using-custom-fields-storefront.md similarity index 88% rename from guides/plugins/plugins/storefront/using-custom-fields-storefront.md rename to guides/plugins/plugins/storefront/howto/using-custom-fields-storefront.md index eca62a5db3..632f5edd6f 100644 --- a/guides/plugins/plugins/storefront/using-custom-fields-storefront.md +++ b/guides/plugins/plugins/storefront/howto/using-custom-fields-storefront.md @@ -1,21 +1,19 @@ --- nav: - title: Add custom field in the storefront + title: Add Custom Field in the Storefront position: 210 --- # Add Custom Field in the Storefront -## Overview - This guide will show you how to use custom fields, e.g., labels in the Storefront. ## Prerequisites -You won't learn to create a plugin in this guide, head over to our [Plugin base guide](../plugin-base-guide) to create a plugin first, if you don't know how it's done yet. +Read the [Plugin base guide](../../plugin-base-guide.md) for guidance on creating plugins. A running plugin is necessary. -Needless to say, you need a custom field itself to add to the Storefront via your own plugin. Head over to the guide on [adding custom fields to Shopware](../framework/custom-field/add-custom-field) to be able to prepare your own custom field. +You will also need a custom field to add to the Storefront using your plugin. The guide on [adding custom fields to Shopware](../../framework/custom-field/add-custom-field.md) provides details. ## Use snippets of custom fields diff --git a/guides/plugins/plugins/storefront/using-the-datepicker-plugin.md b/guides/plugins/plugins/storefront/howto/using-the-datepicker-plugin.md similarity index 95% rename from guides/plugins/plugins/storefront/using-the-datepicker-plugin.md rename to guides/plugins/plugins/storefront/howto/using-the-datepicker-plugin.md index 7eba75d499..14e422e42a 100644 --- a/guides/plugins/plugins/storefront/using-the-datepicker-plugin.md +++ b/guides/plugins/plugins/storefront/howto/using-the-datepicker-plugin.md @@ -1,15 +1,13 @@ --- nav: - title: Using the datepicker plugin + title: Using the Datepicker Plugin position: 260 --- # Using the Datepicker Plugin -## Overview - -To provide an input field for date and time values, you can use the datepicker plugin. This guide shows you how to use it. +To provide an input field for date and time values, use the datepicker plugin. This guide shows you how to use it. The datepicker plugin uses the `flatpickr` implementation under the hood. So, check out the `flatpickr` documentation, if you need more information about the date picker configuration itself. @@ -21,11 +19,11 @@ if you need more information about the date picker configuration itself. You won't learn how to create a plugin in this guide, head over to our Plugin base guide to create your first plugin: - + You should also know how to customize templates: - + ## Setup a datepicker input field diff --git a/guides/plugins/plugins/storefront/add-custom-javascript.md b/guides/plugins/plugins/storefront/javascript/add-custom-javascript.md similarity index 94% rename from guides/plugins/plugins/storefront/add-custom-javascript.md rename to guides/plugins/plugins/storefront/javascript/add-custom-javascript.md index 09c2d4ed8e..f7e422923f 100644 --- a/guides/plugins/plugins/storefront/add-custom-javascript.md +++ b/guides/plugins/plugins/storefront/javascript/add-custom-javascript.md @@ -1,15 +1,13 @@ --- nav: - title: Add custom Javascript + title: Add Custom JavaScript position: 50 --- -# Add Custom Javascript +# Add Custom JavaScript -## Overview - -If you want to add interactivity to your Storefront you probably have to write your own JavaScript plugin. Here you will be guided through the process of writing and registering your own JavaScript plugins. You will write a plugin that simply checks if the user has scrolled to the bottom of the page and then creates an alert. +Adding interactivity to your Storefront sometimes might require writing your own JavaScript plugin. This guide covers writing and registering your own JavaScript plugins. You will write a plugin that checks whether the user has scrolled to the bottom of the page, then creates an alert. ## Prerequisites @@ -119,7 +117,7 @@ When using the "normal" import (`import ExamplePlugin from './example-plugin/exa ### Loading your plugin -The following will create a new template with a very short explanation. If you're looking for more information on what's going on here, head over to our guide about [Customizing templates](customize-templates). +The following will create a new template with a very short explanation. If you're looking for more information on what's going on here, head over to our guide about [Customizing templates](../templates/customize-templates.md). You bound your plugin to the css selector `[data-example-plugin]`, so you have to add DOM elements with this attribute on the pages you want your plugin to be active. @@ -268,4 +266,4 @@ If you now scroll to the bottom of your page an alert should appear. ## Next steps -You've got your own first javascript plugin running. You might want to start [listening to javascript events](reacting-to-javascript-events) now, or even [override other javascript plugins](override-existing-javascript) instead. +With your own first JavaScript plugin now running, you might want to start [listening to JavaScript events](./reacting-to-javascript-events.md) or [overriding other JavaScript plugins](./override-existing-javascript.md). diff --git a/guides/plugins/plugins/storefront/add-javascript-as-script-tag.md b/guides/plugins/plugins/storefront/javascript/add-javascript-as-script-tag.md similarity index 94% rename from guides/plugins/plugins/storefront/add-javascript-as-script-tag.md rename to guides/plugins/plugins/storefront/javascript/add-javascript-as-script-tag.md index 298c245dd1..e639b1d3e4 100644 --- a/guides/plugins/plugins/storefront/add-javascript-as-script-tag.md +++ b/guides/plugins/plugins/storefront/javascript/add-javascript-as-script-tag.md @@ -1,23 +1,21 @@ --- nav: - title: Add Javascript as script tag + title: Add JavaScript as Script tag position: 65 --- -# Add JavaScript as script tag - -## Overview +# Add JavaScript as Script Tag You often want to add your JavaScript to your main entry point `/src/Resources/app/storefront/src/main.js` to automatically compile it alongside the Storefront JavaScript. -Please refer to [Add custom Javascript](add-custom-javascript.md) for more information. +Refer to the [Add custom JavaScript](./add-custom-javascript.md) guide for more information. However, you might want to add JavaScript as a separate `