Skip to content

Commit

Permalink
Merge branch 'main' into next-6.6
Browse files Browse the repository at this point in the history
  • Loading branch information
bojanrajh committed Mar 7, 2024
2 parents 37d689d + 2f53830 commit 500b1ca
Show file tree
Hide file tree
Showing 15 changed files with 452 additions and 74 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/validate-external-links.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: External link validation

on:
pull_request:
types: [opened, edited]
schedule:
- cron: 0 11 * * *

Expand All @@ -13,8 +11,7 @@ jobs:
- uses: actions/checkout@v4
- name: lychee Link Checker
id: lychee
uses: lycheeverse/lychee-action@v1.0.8
uses: lycheeverse/lychee-action@v1.9.3
with:
fail: true
args: --accept=200,403,429 -s "https" "**/*.html" "**/*.md" "**/*.txt" "**/*.json" --exclude "https://github.com/\[your*" --exclude "https://localhost:9200" --exclude-mail
- name: Fail if there were link errors
run: exit ${{ steps.lychee.outputs.exit_code }}
5 changes: 5 additions & 0 deletions .wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ createPropertyFixture
createSalesChannelFixture
createShippingFixture
createSnippetFixture
CreateTagAction
createValidatorDefinition
CredentialsBuilder
CredentialsEntity
Expand Down Expand Up @@ -536,6 +537,7 @@ filesystems
firstname
Fk
FkField
FlowAction
flattenDeep
FloatField
FlowBuilder
Expand Down Expand Up @@ -625,6 +627,7 @@ gRPC
GuestWishlistPage
GuestWishlistPagelet
guid
handleFlow
hardcoded
hasError
hasOwnProperty
Expand Down Expand Up @@ -1207,6 +1210,7 @@ ReverseInherited
Reviewdog
ReviewFormDataAware
ReviewFormDataStorer
rethrown
rfc
roadmap
Roadmap
Expand Down Expand Up @@ -1452,6 +1456,7 @@ tradeoff
transactional
transactionCapture
transactionId
TransactionalAction
TranslatedField
TranslationDataSet
TranslationsAssociation
Expand Down
2 changes: 1 addition & 1 deletion guides/hosting/performance/lock-store.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ By default, Symfony will use a local lock store. This means in multi-machine (cl
## Using Redis as a lock store

As Redis can already be used for [caching](./caches), [increment store](./increment), and [session storage](./session), you can also use that Redis host as a remote lock store.
To use Redis, create a `config/packages/framework.yml` file with the following content:
To use Redis, create a `config/packages/lock.yaml` file with the following content:

```yaml
framework:
Expand Down
5 changes: 4 additions & 1 deletion guides/installation/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,10 @@ The template is small and does not contain any dev-tooling or integrations like

```bash
# Install profiler and other dev tools, eg Faker for demo data generation
composer require --dev dev-tools
composer require --dev shopware/dev-tools

# Or Install symfony dev tools
composer require --dev symfony/profiler-pack

# Install PaaS integration
composer require paas
Expand Down
2 changes: 1 addition & 1 deletion guides/plugins/apps/administration/adding-snippets.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ nav:
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: `<app root>/Resources/app/administration/snippet`
Additionally, you need JSON file for each language you want to support, using its specific language locale, e.g. `de-DE.json`, `en-GB.json`.

Since everything else works the same, please refer to our [Adding translations for plugins](../plugins/administration/adding-snippets) guide for more information.
Since everything else works the same, please refer to our [Adding translations for plugins](../../plugins/administration/adding-snippets) guide for more information.
6 changes: 3 additions & 3 deletions guides/plugins/plugins/administration/using-custom-fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ The next step is loading your custom fields. First things first, create a variab
data() {
return {
...
yourCustomFields: null
customFieldSets: null
};
}
```
Expand Down Expand Up @@ -87,6 +87,6 @@ Now you can access your custom fields, e.g. within a `method`. In order to achie
// this will fetch the customFieldSets
this.customFieldSetRepository.search(this.customFieldSetCriteria, Shopware.Context.api)
.then((customFieldSets) => {
this.currencyCustomFields = customFieldSets;
this.customFieldSets = customFieldSets;
});
```
```
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ $this->customFieldSetRepository->create([
'label' => [
'en-GB' => 'English custom field set label',
'de-DE' => 'German custom field set label',
Defaults::SYSTEM_LANGUAGE => "Mention the fallback label here"
Defaults::LANGUAGE_SYSTEM => "Mention the fallback label here"
]
],
'customFields' => [
Expand All @@ -259,7 +259,7 @@ $this->customFieldSetRepository->create([
'label' => [
'en-GB' => 'English custom field label',
'de-DE' => 'German custom field label',
Defaults::SYSTEM_LANGUAGE => "Mention the fallback label here"
Defaults::LANGUAGE_SYSTEM => "Mention the fallback label here"
],
'customFieldPosition' => 1
]
Expand Down Expand Up @@ -287,4 +287,4 @@ While theoretically your custom field is now properly defined for the Administra

## Next steps

If you want to extend an entity with new associations and non-scalar values, head over to our guide regarding [Extending existing entities](../data-handling/add-complex-data-to-existing-entities).
If you want to extend an entity with new associations and non-scalar values, head over to our guide regarding [Extending existing entities](../data-handling/add-complex-data-to-existing-entities).
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ nav:

## Overview

Sometimes you want to extend existing entities with some custom information, this guide will have you covered. Extensions are technical and not configurable by the admin user just like that. Also, they can deal with more complex types than scalar ones.
Sometimes you want to extend existing entities with some custom information. Extensions are technical and not configurable by the admin user. Also, they can deal with more complex types than scalar ones.

## Prerequisites

In order to create your own entity extension for your plugin, you first need a plugin as base. Therefore, you can refer to the [Plugin Base Guide](../../plugin-base-guide).
To create your own entity extension for your plugin, you first need a plugin as base. Please refer to the [Plugin Base Guide](../../plugin-base-guide).

Also, basic knowledge of [creating a custom entity](add-custom-complex-data) and [adding associations](add-data-associations) to it are very helpful here.
Basic knowledge of [creating a custom entity](add-custom-complex-data) and [adding associations](add-data-associations) will also be helpful for this guide.

## Creating the extension

In this example, we're going to add a new string field to the `product` entity.

You can choose whether or not you want to save the new string field to the database or not. Therefore, you're going to see two sections, one for each way.
You can choose whether you want to save the new string field to the database or not. Therefore, you're going to see two sections, one for each way.

For both cases, you need to create a new "extension" class in the directory `<plugin root>/src/Extension/`. In this case, we want to extend the `product` entity, so we create a subdirectory `Content/Product/` since the entity is located there in the Core. Our class then has to extend from the abstract `Shopware\Core\Framework\DataAbstractionLayer\EntityExtension` class, which forces you to implement the `getDefinitionClass` method. It has to point to the entity definition you want to extend, so `ProductDefinition` in this case.
For both cases, you need to create a new "extension" class in the directory `<plugin root>/src/Extension/`. In this case, we want to extend the `product` entity, so we create a subdirectory `Content/Product/` since the entity location in the Core is the same. Our class needs to extend from the abstract `Shopware\Core\Framework\DataAbstractionLayer\EntityExtension` class, which forces you to implement the `getDefinitionClass` method. It has to point to the entity definition you want to extend, so `ProductDefinition` in this case.

Now you add new fields by overriding the method `extendFields` and add your new fields in there.
You add new fields by overriding the method `extendFields` and add your new fields in there.

Here's an example class called `CustomExtension`:

Expand Down Expand Up @@ -75,7 +75,7 @@ Here's our `services.xml`:
</container>
```

### Adding a field with database
### Adding a field with a database

In this guide, you're extending the product entity in order to add a new string field to it. Since you must not extend the `product` table with a new column, you'll have to add a new table which contains the new data for the product. This new table will then be associated using a [OneToOne association](add-data-associations#One%20to%20One%20associations).

Expand Down Expand Up @@ -170,11 +170,11 @@ We've created a new entity definition called `ExampleExtensionDefinition`, as me

So let's have a look at the `defineFields` method. There's the default `IdField`, that almost every entity owns. The next field is the actual `product_id` column, which will be necessary in order to properly this entity with the product and vice versa. It has to be defined as `FkField` since that's what it is: a foreign key.

Now we're getting to the actual new data, in this example this is just a new string field. It is called `customString` and can now be used in order to store new string data for the product in the database.
Now we're getting to the actual new data, in this example, this is just a new string field. It is called `customString` and can now be used in order to store new string data for the product in the database.

The last field is the inverse side of the `OneToOneAssociationField`. The first parameter defines the name of the property again, which will contain the `ProductEntity`. Now have a look at the second and third parameters - those are the same as in the `ProductDefinition`, but the other way around. This is important, do not forget to do that!
The last field is the inverse side of the `OneToOneAssociationField`. The first parameter defines the name of the property again, which will contain the `ProductEntity`. Now take a look at the second and third parameters. Those are the same as in the `ProductDefinition`, but the other way around. This order is important.

The fourth parameter is the class of the associated definition, the `ProductDefinition` in this case. The last parameter, once again, defines the auto-loading. In this example, the product definition will **not** be loaded, when you're just trying to load this extension entity. Yet, the extension entity will always automatically be loaded when the product entity is loaded, just like we defined earlier.
The fourth parameter is the class of the associated definition, the `ProductDefinition` in this case. The last parameter, once again, defines the autoloading. In this example, the product definition will **not** be loaded, when you're just trying to load this extension entity. Yet, the extension entity will always automatically be loaded when the product entity is loaded, just like we defined earlier.

Of course, this new definition also needs to be registered to the DI container:

Expand Down Expand Up @@ -261,45 +261,11 @@ $this->productRepository->upsert([[

In this case, you'd write "foo bar" to the product with your desired ID. Note the keys `exampleExtension`, as defined in the product extension class `CustomExtension`, and the key `customString`, which is the property name that you defined in the `ExampleExtensionDefinition` class.

### Adding a field without database

Adding a field without saving its value to the database is a lot less complicated. First of all, you'll have to let Shopware know that you're going to take care of this field yourself and it doesn't have to search for it in the database. This is done by using the `Runtime` flag on the new field.

```php
// <plugin root>/src/Extension/Content/Product/CustomExtension.php
<?php declare(strict_types=1);

namespace Swag\BasicExample\Extension\Content\Product;

use Shopware\Core\Content\Product\ProductDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\EntityExtension;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Runtime;
use Shopware\Core\Framework\DataAbstractionLayer\Field\StringField;
use Shopware\Core\Framework\DataAbstractionLayer\FieldCollection;

class CustomExtension extends EntityExtension
{
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new StringField('custom_string', 'customString'))->addFlags(new Runtime())
);
}

public function getDefinitionClass(): string
{
return ProductDefinition::class;
}
}
```

In this case, you directly add the `StringField` to the extension class itself. Afterwards, we're adding the `Runtime` flag to this field, so Shopware knows that it doesn't have to take care of this new field automatically. We're doing this ourselves now.

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.
### Adding a field without a database

We can use the DAL event which gets fired every time the product entity is loaded. You can find those kinds of events in the respective entities' event class. In this case, it is `Shopware\Core\Content\Product\ProductEvents`.

Below you can find an example implementation where we add our extension when the product gets loaded.
Below, you can find an example implementation where we add our extension when the product gets loaded.

```php
// <plugin root>/src/Subscriber/ProductSubscriber.php
Expand Down Expand Up @@ -347,10 +313,6 @@ After we've created our subscriber, we have to adjust our `services.xml` to regi
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="Swag\BasicExample\Extension\Content\Product\CustomExtension">
<tag name="shopware.entity.extension"/>
</service>

<service id="Swag\BasicExample\Subscriber\ProductSubscriber">
<tag name="kernel.event_subscriber"/>
</service>
Expand All @@ -360,4 +322,4 @@ After we've created our subscriber, we have to adjust our `services.xml` to regi

## Entity extension vs. Custom fields

[Custom fields](../custom-field/add-custom-field) are by default configurable by the admin user in the Administration and they mostly support scalar types, e.g. a text-field, a number field, or the likes. If you'd like to create associations between entities, you'll need to use an entity extension, just like we did here. Of course, you can also add scalar values without an association to an entity via an extension.
[Custom fields](../custom-field/add-custom-field) are by default configurable by the admin user in the Administration, and they mostly support scalar types, e.g. a text-field, a number field, or the likes. If you'd like to create associations between entities, you'll need to use an entity extension, just like we did here. Of course, you can also add scalar values without an association to an entity via an extension.
18 changes: 9 additions & 9 deletions guides/plugins/plugins/framework/filesystem/filesystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,26 @@ 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) as well as 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](../../plugin-fundamentals/add-custom-service).

## Flysystem overview

The Flysystem enables your plugin to read and write files through a common interface. There are several default namespaces/directories that are available, for example:

* One for general private files of the shop: invoices, delivery notes
* One for general public files: product pictures, media files
* One for private files of the shop: invoices, delivery notes
* One for public files: product pictures, media files
* One for theme files
* One for sitemap files
* One for bundle assets files

However, every plugin/bundle gets an own namespace that should be used for private or public plugin files. These are automatically generated during the plugin installation. The namespace is prefixed with the [Snake case](https://en.wikipedia.org/wiki/Snake_case) plugin name followed by `filesystem` `.` `private` or `plugin`. For our example plugin this would be
However, every plugin/bundle gets an own namespace that should be used for private or public plugin files. These are automatically generated during the plugin installation. The namespace is prefixed with the [Snake case](https://en.wikipedia.org/wiki/Snake_case) plugin name followed by `filesystem` `.` `private` or `public`. For our example plugin, this would be

* `swag_example_plugin.filesystem.public` for public plugin files
* `swag_example_plugin.filesystem.private` for private plugin files
* `swag_basic_example.filesystem.public` for public plugin files
* `swag_basic_example.filesystem.private` for private plugin files

## Use filesystem in a service

To make use of the filesystem we register a new service, which helps to read and write files to the filesystem.
To make use of the filesystem, we register a new service, which helps to read and write files to the filesystem.

```php
// <plugin root>/src/Service/ExampleFilesystemService.php
Expand Down Expand Up @@ -78,7 +78,7 @@ class ExampleFilesystemService
}
```

This service makes use of the private und public filesystem of the plugin. As you already know, this php class has to be registered as a service in the dependency injection container. This is also the place where we define which filesystem will be handed over to the constructor. To make use of the plugin private and public files, the service definition could look like this:
This service makes use of the private und public filesystem. As you already know, this php class has to be registered as a service in the dependency injection container. This is also the place where we define which filesystem will be handed over to the constructor. To make use of the plugin private and public files, the service definition could look like this:

```xml
// <plugin root>/src/Resources/config/services.xml
Expand All @@ -101,4 +101,4 @@ This service makes use of the private und public filesystem of the plugin. As yo
</container>
```

Now, this service can be used to read or write files to the private plugin filesystem or to list all files in the public plugin filesystem. You should visit the [Flysystem API documentation](https://flysystem.thephpleague.com/v1/docs/usage/filesystem-api/) for more information.
Now, this service can be used to read or write files to the private plugin filesystem or to list all files in the public plugin filesystem. You should visit the [Flysystem API documentation](https://flysystem.thephpleague.com/v1/docs/usage/filesystem-api/) for more information.
Loading

0 comments on commit 500b1ca

Please sign in to comment.