Skip to content

Commit

Permalink
Merge pull request #217 from delyriand/feature/attribute-declaration
Browse files Browse the repository at this point in the history
Allow UI Elements to be declared using PHP attributes
  • Loading branch information
jacquesbh authored Apr 11, 2024
2 parents 15c927f + e644acb commit 466c0fa
Show file tree
Hide file tree
Showing 19 changed files with 456 additions and 54 deletions.
17 changes: 2 additions & 15 deletions .github/workflows/recipe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,8 @@ jobs:
strategy:
fail-fast: false
matrix:
php: ['7.4', '8.0', '8.1']
sylius: ['~1.8.0', '~1.9.0', '~1.10.0', '~1.11.0', '~1.12.0']
exclude:
- php: 8.0
sylius: '~1.8.0'
- php: 8.0
sylius: '~1.9.0'
- php: 8.1
sylius: '~1.8.0'
- php: 8.1
sylius: '~1.9.0'
- php: 7.4
sylius: '~1.11.0'
- php: 7.4
sylius: '~1.12.0'
php: ['8.0', '8.1']
sylius: ['~1.10.0', '~1.11.0', '~1.12.0']

steps:
- name: Setup PHP
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php: ['7.4', '8.0', '8.1']
php: ['8.0', '8.1']

steps:
- uses: actions/checkout@v3
Expand Down
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,23 @@ You can distinguish the `Row` element and the `Column` element by their dotted b

In this example, we will add a Google Maps element.

### Define your UiElement
With the Maker Bundle, you can create a new UiElement very easily:

```bash
bin/console make:ui-element
```

Then you will have to answer some questions, or you can add arguments to the command to avoid the questions.

```bash
bin/console make:ui-element app.google_maps "map pin"
```

Just add the translations!

### Define your UiElement (for PHP < 8.1)

**Tips:** If you are using PHP 8.1 or newer, you can use the `#[AsUiElement]` attribute to define your UiElement. You can skip this step.

Define your UiElement in your configuration folder, let's say in `config/packages/monsieurbiz_sylius_richeditor_plugin.yaml` as example.

Expand Down Expand Up @@ -273,6 +289,48 @@ class GoogleMapsType extends AbstractType
}
```

For PHP 8.1 and newer, you can use the `#[AsUiElement]` attribute to define your UiElement. For example:

```php
<?php
// ...
use MonsieurBiz\SyliusRichEditorPlugin\Attribute\AsUiElement;
#[AsUiElement(
code: 'app.google_maps',
icon: 'map pin',
)]
class GoogleMapsType extends AbstractType
// ...
```

The title, description and templates values are generated automatically from the code. In this example :

- the title will be `app.ui_element.google_maps.title`,
- the description will be `app.ui_element.google_maps.description`,
- the admin template will be `/Admin/UiElement/google_maps.html.twig`,
- and the front template will be `/Shop/UiElement/google_maps.html.twig`.

But you can override them if you want:

```php
#[AsUiElement(
code: 'app.google_maps',
title: 'my_cusom.title', // Use your own translation key or a string
description: 'my_custom.description',
icon: 'map pin',
templates: new TemplatesUiElement(
adminRender: 'MyCusomPath/google_maps.html.twig',
frontRender: 'MyCusomPath/google_maps.html.twig',
),
uiElement: GoogleMapsUiElement::class, // Use your own UiElement class
tags: ['map'], // Add some tags to filter the UiElement
wireframe: 'google_maps', // Add a wireframe to help the user to understand the UiElement, see below
)]
```

### Add your translations of course

Here is an example of possible translation for the GMap element :
Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
"description": "A Rich Editor plugin for Sylius.",
"license": "MIT",
"require": {
"php": "~7.4|~8.0|~8.1",
"php": "^8.0",
"ext-json": "*",
"ext-intl": "*",
"sylius/sylius": ">=1.8 <1.13"
"sylius/sylius": ">=1.10 <1.13"
},
"require-dev": {
"behat/behat": "^3.6.1",
Expand Down Expand Up @@ -43,7 +43,8 @@
"symfony/dotenv": "^4.4",
"symfony/flex": "^1.7",
"symfony/web-profiler-bundle": "^4.4",
"phpmd/phpmd": "@stable"
"phpmd/phpmd": "@stable",
"symfony/maker-bundle": "^1.39"
},
"prefer-stable": true,
"autoload": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ monsieurbiz_sylius_richeditor:
tags: [ html ]
monsieurbiz.youtube:
tags: [ youtube ]
app.google_maps:
title: 'app.ui_element.google_maps.title'
description: 'app.ui_element.google_maps.description'
icon: map pin
tags: [ map ]
classes:
form: App\Form\Type\UiElement\GoogleMapsType
ui_element: App\UiElement\GoogleMapsUiElement
templates:
admin_render: '/Admin/UiElement/google_maps.html.twig'
front_render: '/Shop/UiElement/google_maps.html.twig'
# Example without PHP Attributes or for PHP version < 8.1
# app.google_maps:
# title: 'app.ui_element.google_maps.title'
# description: 'app.ui_element.google_maps.description'
# icon: map pin
# tags: [ map ]
# classes:
# form: App\Form\Type\UiElement\GoogleMapsType
# ui_element: App\UiElement\GoogleMapsUiElement
# templates:
# admin_render: '/Admin/UiElement/google_maps.html.twig'
# front_render: '/Shop/UiElement/google_maps.html.twig'
app.noseeme:
title: 'You should not see me'
description: 'The invisible Ui Element'
Expand Down
8 changes: 8 additions & 0 deletions dist/src/Form/Type/UiElement/GoogleMapsType.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,19 @@

namespace App\Form\Type\UiElement;

use App\UiElement\GoogleMapsUiElement;
use MonsieurBiz\SyliusRichEditorPlugin\Attribute\AsUiElement;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints as Assert;

#[AsUiElement(
code: 'app.google_maps',
icon: 'map pin',
uiElement: GoogleMapsUiElement::class,
tags: ['map'],
)]
class GoogleMapsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
Expand Down
13 changes: 13 additions & 0 deletions dist/templates/Admin/UiElement/google_maps.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{#
UI Element template
type: google_map
element fields:
link: string
element methods:
getLocale(): string
#}

<div style="width: 100%">
{{ ui_element.getLocale() }}
{{ element.link|replace({'hl=en': 'hl=' ~ ui_element.getLocale()}) }}
</div>
12 changes: 12 additions & 0 deletions dist/templates/Shop/UiElement/google_maps.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{#
UI Element template
type: google_map
element fields:
link: string
element methods:
getLocale(): string
#}

<div style="width: 100%">
<iframe width="100%" height="600" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="{{ element.link }}"><a href="https://www.gps.ie/">gps devices</a></iframe>
</div>
2 changes: 1 addition & 1 deletion phpmd.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<rule ref="rulesets/naming.xml/ShortClassName"/>
<rule ref="rulesets/naming.xml/ShortVariable">
<properties>
<property name="exceptions" value="id,em"/>
<property name="exceptions" value="id,em,io"/>
</properties>
</rule>
<rule ref="rulesets/naming.xml/ShortMethodName"/>
Expand Down
3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@ parameters:
- 'tests/Application/app/**.php'
- 'tests/Application/src/**.php'

# Skeleton files
- 'src/Resources/skeleton/*.php'

ignoreErrors:
- '/Parameter #1 \$configuration of method Symfony\\Component\\DependencyInjection\\Extension\\Extension::processConfiguration\(\) expects Symfony\\Component\\Config\\Definition\\ConfigurationInterface, Symfony\\Component\\Config\\Definition\\ConfigurationInterface\|null given\./'
96 changes: 96 additions & 0 deletions src/Attribute/AsUiElement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

/*
* This file is part of Monsieur Biz' Rich Editor plugin for Sylius.
*
* (c) Monsieur Biz <sylius@monsieurbiz.com>
*
* For the full copyright and license information, please view the LICENSE.txt
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace MonsieurBiz\SyliusRichEditorPlugin\Attribute;

use Attribute;
use MonsieurBiz\SyliusRichEditorPlugin\UiElement\UiElement;

#[Attribute(Attribute::TARGET_CLASS)]
class AsUiElement
{
/**
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
*/
public function __construct(
public string $code,
public string $icon,
public ?string $title = null,
public ?string $description = null,
public string $uiElement = UiElement::class,
public ?TemplatesUiElement $templates = null,
public string $alias = '',
public string $wireframe = '',
public bool $enabled = true,
public array $tags = [],
) {
}

public function getCode(): string
{
return $this->code;
}

public function getConfiguration(): array
{
$configuration = [
'title' => $this->getTitle(),
'description' => $this->getDescription(),
'icon' => $this->icon,
'wireframe' => $this->wireframe,
'enabled' => $this->enabled,
'tags' => $this->tags,
'classes' => [
'ui_element' => $this->uiElement,
],
'templates' => [
'admin_render' => $this->getTemplates()->adminRender,
'front_render' => $this->getTemplates()->frontRender,
'admin_form' => $this->getTemplates()->adminForm,
],
'form_options' => [],
];

if ($this->alias) {
$configuration['alias'] = $this->alias;
}

return $configuration;
}

private function getTitle(): string
{
return $this->title ?? 'app.ui_element.' . $this->getLastPartOfCode() . '.title';
}

private function getDescription(): string
{
return $this->description ?? 'app.ui_element.' . $this->getLastPartOfCode() . '.description';
}

private function getTemplates(): TemplatesUiElement
{
return $this->templates ?? new TemplatesUiElement(
adminRender: 'Admin/UiElement/' . $this->getLastPartOfCode() . '.html.twig',
frontRender: 'Shop/UiElement/' . $this->getLastPartOfCode() . '.html.twig',
);
}

private function getLastPartOfCode(): string
{
$parts = explode('.', $this->code);

return end($parts);
}
}
27 changes: 27 additions & 0 deletions src/Attribute/TemplatesUiElement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/*
* This file is part of Monsieur Biz' Rich Editor plugin for Sylius.
*
* (c) Monsieur Biz <sylius@monsieurbiz.com>
*
* For the full copyright and license information, please view the LICENSE.txt
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace MonsieurBiz\SyliusRichEditorPlugin\Attribute;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
final class TemplatesUiElement
{
public function __construct(
public string $adminRender,
public string $frontRender,
public string $adminForm = '@MonsieurBizSyliusRichEditorPlugin/Admin/form.html.twig',
) {
}
}
Loading

0 comments on commit 466c0fa

Please sign in to comment.