Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions guides/plugins/plugins/bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ project-root/
│ │ └── Migration1234567890YourMigration.php
│ └── Resources/
│ ├── config/
│ │ ├── services.xml
│ │ ├── services.php
│ │ └── routes.xml
│ ├── views/
│ │ └── storefront/
Expand Down Expand Up @@ -92,7 +92,7 @@ App\YourBundleName\YourBundleName::class => ['all' => true],
## Adding services, twig templates, routes, theme, etc

You can add services, twig templates, routes, etc. to your bundle like you would do in a plugin.
Just create `Resources/config/services.xml` and `Resources/config/routes.xml` files or `Resources/views` for twig templates.
Just create `Resources/config/services.php` and `Resources/config/routes.xml` 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.
Expand Down
14 changes: 13 additions & 1 deletion guides/plugins/plugins/checkout/cart/add-cart-discounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
use Shopware\Core\Checkout\Cart\Price\Struct\PercentagePriceDefinition;
use Shopware\Core\Checkout\Cart\Rule\LineItemRule;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;

#[AutoconfigureTag('shopware.cart.processor', ['priority' => 4500])]
class ExampleProcessor implements CartProcessorInterface
{
private PercentagePriceCalculator $calculator;
Expand Down Expand Up @@ -120,4 +122,14 @@

After adding the definition to the line item, we have to calculate the current price of the discount. Therefore we can use the `PercentagePriceCalculator` of the core. The last step is to add the discount to the new cart which is provided as `Cart $toCalculate`.

That's it for the main code of our custom `CartProcessor`. Now we only have to register it in our `services.xml` using the tag `shopware.cart.processor` and priority `4500`, which is used to get access to the calculation after the [product processor](https://github.com/shopware/shopware/blob/v6.3.4.1/src/Core/Checkout/DependencyInjection/cart.xml#L223-L231) handled the products.
That's it for the main code of our custom `CartProcessor`. Now we only have to tag it with `shopware.cart.processor` and priority `4500`, which is used to get access to the calculation after the [product processor](https://github.com/shopware/shopware/blob/v6.3.4.1/src/Core/Checkout/DependencyInjection/cart.xml#L223-L231) handled the products. This is done by adding the `#[AutoconfigureTag]` PHP attribute directly to the class:

```php

Check warning on line 127 in guides/plugins/plugins/checkout/cart/add-cart-discounts.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] guides/plugins/plugins/checkout/cart/add-cart-discounts.md#L127

File types are normally capitalized. (FILE_EXTENSIONS_CASE[1]) Suggestions: `PHP` URL: https://languagetool.org/insights/post/spelling-capital-letters/ Rule: https://community.languagetool.org/rule/show/FILE_EXTENSIONS_CASE?lang=en-US&subId=1 Category: CASING
Raw output
guides/plugins/plugins/checkout/cart/add-cart-discounts.md:127:3: File types are normally capitalized. (FILE_EXTENSIONS_CASE[1])
 Suggestions: `PHP`
 URL: https://languagetool.org/insights/post/spelling-capital-letters/ 
 Rule: https://community.languagetool.org/rule/show/FILE_EXTENSIONS_CASE?lang=en-US&subId=1
 Category: CASING
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;

#[AutoconfigureTag('shopware.cart.processor', ['priority' => 4500])]
class ExampleProcessor implements CartProcessorInterface
{
// ...
}
```
34 changes: 4 additions & 30 deletions guides/plugins/plugins/checkout/cart/add-cart-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,7 @@

Sometimes you really want to have a custom line item handler, e.g. for your own new entity, such as a bundle entity or alike. For that case, you can create your own line item handler, which will then be available in the `LineItemFactoryRegistry` as a valid `type` option.

You need to create a new class which implements the interface `\Shopware\Core\Checkout\Cart\LineItemFactoryHandler\LineItemFactoryInterface` and it needs to be registered in the DI container with the tag `shopware.cart.line_item.factory`.

```xml
// <plugin root>/src/Resources/config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="Swag\BasicExample\Service\ExampleHandler">
<tag name="shopware.cart.line_item.factory" />
</service>
</services>
</container>
```
You need to create a new class which implements the interface `\Shopware\Core\Checkout\Cart\LineItemFactoryHandler\LineItemFactoryInterface`. With `autoconfigure` enabled, the class is automatically tagged with `shopware.cart.line_item.factory` because it implements `LineItemFactoryInterface` — no additional configuration or attributes are needed.

Let's first have a look at an example handler:

Expand Down Expand Up @@ -166,7 +151,7 @@

Here you can define which properties of your line item may actually be updated. E.g. if you really want property X to contain "Y", you can do so here.

Now you'll need to add a processor for your type. Otherwise your item won't be persisted in the cart. A simple processor for our ExampleHandler could look like this:
Now you'll need to add a processor for your type. Otherwise your item won't be persisted in the cart. While `CartProcessorInterface` is autoconfigured, we use `#[AutoconfigureTag]` here to set a custom `priority`. A simple processor for our ExampleHandler could look like this:

Check warning on line 154 in guides/plugins/plugins/checkout/cart/add-cart-items.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] guides/plugins/plugins/checkout/cart/add-cart-items.md#L154

A comma may be missing after the conjunctive/linking adverb ‘Otherwise’. (SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA[1]) Suggestions: `Otherwise,` URL: https://languagetool.org/insights/post/linking-words/ Rule: https://community.languagetool.org/rule/show/SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA?lang=en-US&subId=1 Category: PUNCTUATION
Raw output
guides/plugins/plugins/checkout/cart/add-cart-items.md:154:48: A comma may be missing after the conjunctive/linking adverb ‘Otherwise’. (SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA[1])
 Suggestions: `Otherwise,`
 URL: https://languagetool.org/insights/post/linking-words/ 
 Rule: https://community.languagetool.org/rule/show/SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA?lang=en-US&subId=1
 Category: PUNCTUATION

```php
// <plugin root>/Core/Checkout/Cart/ExampleProcessor.php
Expand All @@ -180,7 +165,9 @@
use Shopware\Core\Checkout\Cart\CartProcessorInterface;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\Checkout\Cart\LineItem\CartDataCollection;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;

#[AutoconfigureTag('shopware.cart.processor', ['priority' => 4800])]
class ExampleProcessor implements CartProcessorInterface
{

Expand All @@ -199,19 +186,6 @@

Of course you can use processors to do much more than this. Have a look at [adding cart processors and collectors](./add-cart-processor-collector).

Now register this processor in your `services.xml` like this:

```html
// <plugin root>/Resources/config/services.xml
...
<services>
...
<service id="Swag\BasicExample\Core\Checkout\Cart\ExampleProcessor">
<tag name="shopware.cart.processor" priority="4800"/>
</service>
</services>
```

And that's it. You should now be able to create line items of type `example`.

## Adding nested line item
Expand Down
19 changes: 1 addition & 18 deletions guides/plugins/plugins/checkout/cart/add-cart-validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +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).

Your validator has to be registered using the tag `shopware.cart.validator`:

```xml
// <plugin root>/src/Resources/config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="Swag\BasicExample\Core\Checkout\Cart\Custom\CustomCartValidator">
<tag name="shopware.cart.validator"/>
</service>
</services>
</container>
```
With `autoconfigure` enabled, the validator is automatically registered because it implements `CartValidatorInterface` — no additional configuration or attributes are needed.

### Adding the custom cart error

Expand Down
32 changes: 14 additions & 18 deletions guides/plugins/plugins/checkout/cart/change-price-of-item.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;

#[AutoconfigureTag('shopware.cart.processor', ['priority' => 4500])]
#[AutoconfigureTag('shopware.cart.collector', ['priority' => 4500])]
class OverwritePriceCollector implements CartDataCollectorInterface, CartProcessorInterface
{
private QuantityPriceCalculator $calculator;
Expand Down Expand Up @@ -259,27 +262,20 @@

### Registering to DI container

One last thing, we need to register our processor and collector to the DI container. Our collector / processor has to be registered using the two tags `shopware.cart.processor` and `shopware.cart.collector`.
One last thing, we need to tag our processor and collector with `shopware.cart.processor` and `shopware.cart.collector`. This is done by adding `#[AutoconfigureTag]` PHP attributes directly to the class. The `QuantityPriceCalculator` dependency is resolved automatically via autowiring.

Let's have a look at it:
Add the following attributes to the `OverwritePriceCollector` class:

```xml
// <plugin root>/src/Resources/config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="Swag\BasicExample\Core\Checkout\Cart\OverwritePriceCollector">
<argument type="service" id="Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator"/>
```php

Check warning on line 269 in guides/plugins/plugins/checkout/cart/change-price-of-item.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] guides/plugins/plugins/checkout/cart/change-price-of-item.md#L269

File types are normally capitalized. (FILE_EXTENSIONS_CASE[1]) Suggestions: `PHP` URL: https://languagetool.org/insights/post/spelling-capital-letters/ Rule: https://community.languagetool.org/rule/show/FILE_EXTENSIONS_CASE?lang=en-US&subId=1 Category: CASING
Raw output
guides/plugins/plugins/checkout/cart/change-price-of-item.md:269:3: File types are normally capitalized. (FILE_EXTENSIONS_CASE[1])
 Suggestions: `PHP`
 URL: https://languagetool.org/insights/post/spelling-capital-letters/ 
 Rule: https://community.languagetool.org/rule/show/FILE_EXTENSIONS_CASE?lang=en-US&subId=1
 Category: CASING
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;

<!-- after product collector/processor -->
<tag name="shopware.cart.processor" priority="4500" />
<tag name="shopware.cart.collector" priority="4500" />
</service>
</services>
</container>
// after product collector/processor
#[AutoconfigureTag('shopware.cart.processor', ['priority' => 4500])]
#[AutoconfigureTag('shopware.cart.collector', ['priority' => 4500])]
class OverwritePriceCollector implements CartDataCollectorInterface, CartProcessorInterface
{
// ...
}
```

And that's it. Your processor / collector should now be working.
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,21 @@ Here's an example decorated calculator:
namespace Swag\BasicExample\Service;

use Shopware\Core\Content\Product\SalesChannel\Price\AbstractProductPriceCalculator;
use Shopware\Core\Content\Product\SalesChannel\Price\ProductPriceCalculator;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;

#[AsDecorator(decorates: ProductPriceCalculator::class)]
class CustomProductPriceCalculator extends AbstractProductPriceCalculator
{
/**
* @var AbstractProductPriceCalculator
*/
private AbstractProductPriceCalculator $productPriceCalculator;

public function __construct(AbstractProductPriceCalculator $productPriceCalculator)
public function __construct(#[AutowireDecorated] AbstractProductPriceCalculator $productPriceCalculator)
{
$this->productPriceCalculator = $productPriceCalculator;
}
Expand Down Expand Up @@ -79,22 +83,7 @@ Most likely you also want to narrow down which product's prices you want to edit

### Registering the decorator

Do not forget to actually register your decoration to the service container, otherwise it will not have any effect.

```xml
// <plugin root>/src/Resources/config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="Swag\BasicExample\Service\CustomProductPriceCalculator" decorates="Shopware\Core\Content\Product\SalesChannel\Price\ProductPriceCalculator">
<argument type="service" id="Swag\BasicExample\Service\CustomProductPriceCalculator.inner" />
</service>
</services>
</container>
```
With autowiring enabled, the `#[AsDecorator]` attribute on the class is sufficient to register the decorator. No explicit service configuration is needed. The `#[AsDecorator(decorates: ProductPriceCalculator::class)]` attribute tells Symfony to automatically decorate the `ProductPriceCalculator` service with `CustomProductPriceCalculator`.

## Next steps

Expand Down
17 changes: 1 addition & 16 deletions guides/plugins/plugins/checkout/cart/tax-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,22 +83,7 @@ class TaxProvider extends AbstractTaxProvider

## Registering the tax provider in the DI container

After you have created your tax provider, you need to register it in the DI container. To do so, you need to create a new service in the `services.xml` file and tag the service as `shopware.tax.provider`.

```xml
// <plugin root>/src/Resources/config/services.xml
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="Swag\BasicExample\Checkout\Cart\Tax\TaxProvider">
<tag name="shopware.tax.provider" />
</service>
</services>
```
With `autoconfigure` enabled, the class is automatically registered because it extends `AbstractTaxProvider` — no additional configuration or attributes are needed.

## Migrate your tax provider to the database

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ 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`.
With `autoconfigure` enabled, the renderer is automatically registered because it extends `AbstractDocumentRenderer` — no additional configuration or attributes are needed.

Let's have a look at an example renderer:

Expand Down Expand Up @@ -339,50 +339,16 @@ Here's what the function does:
* If an error occurs, the exception is caught and the error message is added to the `RendererResult` object as an error.
* The `RendererResult` object is returned.

The service definition for our custom renderer would look like this:

```xml
<service id="Swag\BasicExample\Core\Checkout\Document\Render\ExampleDocumentRenderer">
<argument type="service" id="order.repository"/>
<argument type="service" id="Shopware\Core\Checkout\Document\Service\DocumentConfigLoader"/>
<argument type="service" id="Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface"/>
<argument type="service" id="Shopware\Core\Checkout\Document\Service\DocumentFileRendererRegistry"/>
<tag name="document.renderer"/>
</service>
```
With autowire enabled, all constructor dependencies are injected automatically.

### Adding a file type renderer

Depending on the file type we either get the content with `$this->fileRendererRegistry->render()` or we need to create the content on our own.
`DocumentFileRendererRegistry` acts as a central registry for document file renderers based on file extensions (e.g., .pdf, .html). It delegates the rendering of documents to the appropriate renderer implementation.

### Registering the renderer in the service container

Now we need to register our custom `ExampleDocumentRenderer` in the service container. Create or update your `services.xml` file:

::: code-group

```xml [PLUGIN_ROOT/src/Resources/config/services.xml]
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="Swag\BasicExample\Core\Checkout\Document\Render\ExampleDocumentRenderer">
<argument type="service" id="order.repository"/>
<argument type="service" id="Shopware\Core\Checkout\Document\Service\DocumentConfigLoader"/>
<argument type="service" id="Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface"/>
<argument type="service" id="Shopware\Core\Checkout\Document\Service\DocumentFileRendererRegistry"/>
<tag name="document.renderer"/>
</service>
</services>
</container>
```

:::
### Registering the renderer

Note that we're using the tag `document.renderer` to register our custom document renderer. The tag name matches what was mentioned earlier - your renderer has to be registered using the tag `document.renderer`.
With `autoconfigure` enabled, the renderer is automatically registered because it extends `AbstractDocumentRenderer`. Combined with autowire, all constructor dependencies are injected automatically. No explicit service configuration is needed.

### Adding a document type template

Expand Down
Loading
Loading