Skip to content

Commit

Permalink
[create-pull-request] automated change (#1586)
Browse files Browse the repository at this point in the history
Co-authored-by: shopwareBot <[email protected]>
  • Loading branch information
github-actions[bot] and shopwareBot authored Dec 3, 2024
1 parent 45d1628 commit a9eb4a4
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 82 deletions.
23 changes: 11 additions & 12 deletions resources/guidelines/code/core/6.5-new-php-language-features.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@


::: info
This document represents core guidelines and has been mirrored from the core in our Shopware 6 repository.
You can find the original version [here](https://github.com/shopware/shopware/blob/trunk/coding-guidelines/core/6.5-new-php-language-features.md)
Expand Down Expand Up @@ -51,7 +52,7 @@ class Point {
}
```

Note: It is still possible to use normal property definitions/assignments with promoted properties. For example, if you need to manipulate some dependencies.
Note: It is still possible to use normal property definitions/assignments with promoted properties. For example, if you need to manipulate some dependencies.

Advantages:

Expand Down Expand Up @@ -144,7 +145,6 @@ $message = match ($statusCode) {
default => 'unknown status code',
};
```

Note: Conditions can be combined in a much simpler fashion.

#### Backwards Compatibility / Migration Strategy
Expand Down Expand Up @@ -172,7 +172,7 @@ Advantages:
* [PHP Docs](https://www.php.net/manual/en/functions.arguments.php)
* [PHP Watch](https://php.watch/versions/8.0/named-parameters)

Named arguments are useful when calling code with bad and/or large API's. For example, many of PHP's global functions.
Named arguments are useful when calling code with bad and/or large API's. For example, many of PHP's global functions.

In terms of calling bad PHP API's, the following advantages apply:

Expand Down Expand Up @@ -208,7 +208,7 @@ Named parameters should only be used when calling PHP API's.

**It will now only be necessary to reach for @var & @param annotations when defining array shapes, generics and more specific types such as `class-string`, `positive-int` etc. Everything else should be natively typed.**

When a type can really be any value, this can now be expressed as `mixed`.
When a type can really be any value, this can now be expressed as `mixed`.

When a type can be multiple, but not all, this can now be expressed as a union type, eg: `int|string`.

Expand Down Expand Up @@ -500,11 +500,11 @@ Advantages:

### Other

* `never` return type: <https://www.php.net/manual/en/language.types.never.php>
* `array_is_list` function: <https://www.php.net/manual/en/function.array-is-list.php>
* `final const X` final for class constants: <https://www.php.net/manual/en/language.oop5.final.php>
* `$object::class` instead of `get_class($object)`: <https://wiki.php.net/rfc/class_name_literal_on_object>
* Array unpacking with string keys is now supported: <https://www.php.net/manual/en/language.types.array.php#language.types.array.unpacking>
* `never` return type: https://www.php.net/manual/en/language.types.never.php
* `array_is_list` function: https://www.php.net/manual/en/function.array-is-list.php
* `final const X` final for class constants: https://www.php.net/manual/en/language.oop5.final.php
* `$object::class` instead of `get_class($object)`: https://wiki.php.net/rfc/class_name_literal_on_object
* Array unpacking with string keys is now supported: https://www.php.net/manual/en/language.types.array.php#language.types.array.unpacking

There are many more changes, including deprecations and backwards compatibility breaks. Please read the official announcement pages for both PHP 8.0 & PHP 8.1 for a deeper understanding:

Expand All @@ -528,7 +528,7 @@ use Symfony\Component\Routing\Requirement\EnumRequirement;
#[Route('/foo/{bar}', requirements: ['bar' => new EnumRequirement(SomeEnum::class)])]
```

### Service autowiring attributes
### Service autowiring attributes

[Symfony Blog](https://symfony.com/blog/new-in-symfony-6-1-service-autowiring-attributes)

Expand All @@ -548,8 +548,7 @@ class Mailer
) {}
}
```

Further to that, we can decorate services with attributes: <https://symfony.com/blog/new-in-symfony-6-1-service-decoration-attributes>
Further to that, we can decorate services with attributes: https://symfony.com/blog/new-in-symfony-6-1-service-decoration-attributes

#### Backwards Compatibility / Migration Strategy

Expand Down
2 changes: 1 addition & 1 deletion resources/guidelines/code/core/adr.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@


::: info
This document represents core guidelines and has been mirrored from the core in our Shopware 6 repository.
You can find the original version [here](https://github.com/shopware/shopware/blob/trunk/coding-guidelines/core/adr.md)
Expand All @@ -13,7 +14,6 @@ Joel Parker Henderson has done a lot of work on this topic, collected excellent
The ADRs examples published there are good.

Expectations for an ADR:

- Write a complete description of the requirements
- List all technical domains that are affected by the ADR
- List all affected logic in the system that are affected
Expand Down
9 changes: 4 additions & 5 deletions resources/guidelines/code/core/decorator-pattern.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@


::: info
This document represents core guidelines and has been mirrored from the core in our Shopware 6 repository.
You can find the original version [here](https://github.com/shopware/shopware/blob/trunk/coding-guidelines/core/decorator-pattern.md)
:::

# Decorator pattern

The decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.
The decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.

## When to use the decorator pattern

You should choose the decorator pattern, when you want that other developers can extend your functionality. The most common use case is that other developers should be allowed to decorate or rewrite your DI container services.

<https://symfony.com/doc/current/service_container/service_decoration.html>
https://symfony.com/doc/current/service_container/service_decoration.html

## How to use the decorator pattern

Instead of interfaces, we use abstract classes to define the base functionality of a service. This allows us to add more functions without breaking existing code. This decision was made in this [ADR](https://github.com/shopware/shopware/blob/trunk/adr/2020-11-25-decoration-pattern.md).

## Rules for the decorator pattern

When defining a service, which should be decorated, you have to follow these rules:

When defining a service, which should be decorated, you have to follow these rules:
- The abstract class has to implement a `getDecorated()` function which returns the abstract class.
- The core service has to throw a `DecorationPatternException` if the `getDecorated()` function is called.
- The abstract class **can not** be marked as `@internal` or `@final`
Expand Down Expand Up @@ -93,7 +93,6 @@ This can be the case when you "just" want to implement a logging or cache layer
In this case, you should not use the decorator pattern described above and only inject the inner service and delegate the calls to it.

In this case you should mark the service as follows:

- if this is private api and should not be used by other developers, mark all classes as `@internal`
- if you want that developers can call public functions of your service but should not extend it, mark all classes as `@final`

Expand Down
4 changes: 1 addition & 3 deletions resources/guidelines/code/core/domain-exceptions.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@


::: info
This document represents core guidelines and has been mirrored from the core in our Shopware 6 repository.
You can find the original version [here](https://github.com/shopware/shopware/blob/trunk/coding-guidelines/core/domain-exceptions.md)
Expand All @@ -11,7 +12,6 @@ To ensure a consistent exception handling, we introduced domain exceptions. Thes
Each domain exception class extends the `Shopware\Core\Framework\HttpException` class, which ensure a unique error code and http handling. Error codes of each domain exception class are unique within the domain. The error codes are defined within the corresponding domain exception.

Domain exception are always stored directly inside the top level domain in each area. Top level domains are:

- `Checkout\Cart`
- `Checkout\Customer`
- `Content\Category`
Expand Down Expand Up @@ -45,7 +45,6 @@ class CustomerException extends HttpException
```

## Exceptions which should be catchable

However, the DomainExceptions are not (necessarily) made to be caught and handled in a try-catch. Therefore, we will continue to implement own exception classes, for exceptions that we want to catch ourselves in the system via a try-catch, which extends the DomainException. These exceptions are then stored in an exception sub folder:

```php
Expand Down Expand Up @@ -81,5 +80,4 @@ class CustomerNotFoundException extends CustomerException
```

## Http status code

Each specific type of domain exceptions should provide a specific http status code. Please use the following official http status defined by [https://developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
34 changes: 12 additions & 22 deletions resources/guidelines/code/core/extendability.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@


::: info
This document represents core guidelines and has been mirrored from the core in our Shopware 6 repository.
You can find the original version [here](https://github.com/shopware/shopware/blob/trunk/coding-guidelines/core/extendability.md)
Expand All @@ -13,7 +14,6 @@ Regarding software extendability, different business cases and requirements must
The requirements are divided into technical requirements and business requirements.

## Technical requirements

When talking about technical requirements, we talk about how we have to design our software for different extension use cases. These use cases include:

* Functional extensibility
Expand All @@ -30,9 +30,7 @@ When talking about technical requirements, we talk about how we have to design o
* Ex: An external newsletter system should be connected

## Business requirements

When talking about business requirements, we talk about how the above technical requirements are used in different business cases. These business cases include:

* Marketplace extensions
* We should build the software so everyone can easily provide new features in certain areas.
* Ex: There should be a plugin to integrate a CMS Page publishing system
Expand All @@ -44,22 +42,19 @@ When talking about business requirements, we talk about how the above technical
* Ex: Assets should be able to be loaded via CDN as there are several App Servers.

## Approaches

These business cases are realized with the following three conceptual approaches:

* Project templates
* Large customers have their deployments in which they deploy a fork of our production template.
* In project templates, local customizations are not implemented as a plugin but as a bundle.
* We have a SaaS product that has special configurations for cloud compatibility
* Apps
* Apps provide minor extensions for our system
* The app technology is designed for use in cloud products
* Plugins
* Plugins can provide larger extensions to the system
* Plugin technology is designed to replace all areas in Shopware
- Project templates
- Large customers have their deployments in which they deploy a fork of our production template.
- In project templates, local customizations are not implemented as a plugin but as a bundle.
- We have a SaaS product that has special configurations for cloud compatibility
- Apps
- Apps provide minor extensions for our system
- The app technology is designed for use in cloud products
- Plugins
- Plugins can provide larger extensions to the system
- Plugin technology is designed to replace all areas in Shopware

## Patterns

All the above requirements and approaches are based on different design patterns within our architecture. To realize the extensibility, we use the following patterns, which allow the third-party developer to extend our software:

* Decoration
Expand All @@ -69,38 +64,33 @@ All the above requirements and approaches are based on different design patterns
* Adapter

### Decoration

With the Decoration pattern, we make it possible to replace or extend certain areas in Shopware completely. We often use this pattern for our Store API routes to provide more functionality in the Store API. Another use case is the **functional replacement market** case, where we can completely replace features with other technologies or external libraries.

An example Store API route is the CategoryRoute. For this route, there is an [Abstract class](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Content/Category/SalesChannel/AbstractCategoryRoute.php) to which we type behind a [Concrete implementation](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Content/Category/SalesChannel/CategoryRoute.php) and a [Cache decorator](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Content/Category/SalesChannel/CachedCategoryRoute.php)

### Factory

The factory pattern is often used when we have to interpret user input and validate or enrich this input before it is passed to the application.
One use case for the factory pattern is the **Functional extensibility**, to allow third-party developers to add new factories, which allow other user input.

A good example is the [line item factory registry](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Checkout/Cart/LineItemFactoryRegistry.php). This registry is used when an item is to be added to the shopping cart via store-API. [The corresponding handler](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Checkout/Cart/LineItemFactoryHandler/ProductLineItemFactory.php) is responsible for the instantiation of the line item and enriches it with necessary data.

### Visitor

The visitor pattern is often used when we process some objects within our application. This pattern is often used to fit the **Functional extensibility** and **Functional modifiability** requirements. In theory, after or before the core visitors are executed, the third party visitors are executed, and they can visit the objects and manipulate or extend the processed data beforehand or afterward to manipulate the result.

A good example of the visitor pattern is the [cart processor](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Checkout/Cart/Processor.php). The processor calls all line item processors, like the [product cart process](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Content/Product/Cart/ProductCartProcessor.php), to modify the provided cart object and transport the line items from the previous cart to the calculated.

### Mediator

We often use this pattern to realize **functional extensibility** and **functional modifiability** to manipulate data or extend it with additional data sources. The best-known example of this pattern in our application is Events. We use events to create different entry points for developers to trigger specific processes.

The best-known example is the [`checkout.order.placed`](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Checkout/Cart/Event/CheckoutOrderPlacedEvent.php) event. This event is [dispatched](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Core/Checkout/Cart/SalesChannel/CartOrderRoute.php#L151) as soon as an order is created in the system. However, over time, it has been shown that it is best practice not to pass objects or entities around in events, but only a corresponding primary key so that the connected listeners can determine the data for themselves. Furthermore, possible asynchronous processing of the underlying processes is easier to realize this way. An optimized variant of this event would not contain the `private OrderEntity $order;` but only the primary key for the order `private string $orderId;`.

#### Hooks

Hooks are another good example of the observer pattern. Hooks are entry points for apps in which the so-called [**App scripts**](/docs/guides/plugins/apps/app-scripts/) is 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 controller level](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Storefront/Controller/ProductController.php#L100). Each app script, which is registered to the hook, is executed.

### Adapter

The adapter pattern is perfectly designed for **Functional exchange market**. We often realize this by allowing the user to do some configuration and select a corresponding adapter. These adapters are usually registered inside a registry, and third-party developers can easily add new adapters via events or via tagged services.

A good example is the captcha implementation. The store owner can configure a [captcha type](https://docs.shopware.com/en/shopware-en/settings/basic-information#captcha), and we then use the [corresponding adapter](https://github.com/shopware/shopware/blob/v6.4.12.0/src/Storefront/Framework/Captcha/HoneypotCaptcha.php#L11) in the code for the configured captcha.

5 changes: 2 additions & 3 deletions resources/guidelines/code/core/final-and-internal.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@


::: info
This document represents core guidelines and has been mirrored from the core in our Shopware 6 repository.
You can find the original version [here](https://github.com/shopware/shopware/blob/trunk/coding-guidelines/core/final-and-internal.md)
Expand All @@ -10,17 +11,15 @@ We use `@final` and `@internal` annotations to mark classes as final or internal

## Final

We mark classes as `@final` when developers can use the class but should not extend it.
We mark classes as `@final` when developers can use the class but should not extend it.

Following changes of the class are allowed:

- Adding new public methods/properties/constants
- Adding new optional parameters to public methods
- Protected and private methods/properties/constants can be changed without any restrictions.
- Widening the type of public method params

Following changes of the class are not allowed:

- Removing public methods/properties/constants
- Removing public methods parameters
- Narrowing the type of public methods/properties/constants
Expand Down
Loading

0 comments on commit a9eb4a4

Please sign in to comment.