Skip to content

Commit

Permalink
Merge pull request #2 from elbformat/fieldtype
Browse files Browse the repository at this point in the history
Added Fieldtype + Configuration
  • Loading branch information
hgiesenow authored Dec 15, 2023
2 parents c70a77a + 0e8eeaa commit 3231e4f
Show file tree
Hide file tree
Showing 19 changed files with 429 additions and 5 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Ibexa Icon Fieldtype
This bundle provides a new field type "icon".
It allows an editor to select an icon from a predefined set of icons

## Features
* Configure multiple icon-sets
* Select the icon-set at content-type edit level
* Select icon from a dropdown instead of text

## Installation
1. Add the bundle
```shell
composer require elbformat/icon-bundle
```

2. Activate the bundle
```php
Elbformat\IconBundle\ElbformatIconBundle::class => ['all' => true],
```

3. Add iconset configuration
Add `config/packages/elbformat_icon.yaml`
```yaml
elbformat_icon:
iconset1:
- clock
- house
iconset2:
folder: "vendor/ezsystems/ezplatform-admin-ui/src/bundle/Resources/public/img/icons"
```
See [configuration](doc/configuration.md) for more advanced examples
## Usage
Edit a content-type and add an "Icon" field. Select icon-set to use.
When editing the content, a dropdown with icons will be shown.
17 changes: 12 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "elbformat/ibexa-icon-fieldtype",
"description": "Field type to select an icon from a predefined set.",
"name": "elbformat/icon-bundle",
"description": "Ibexa fieldtype to select an icon from a predefined set.",
"type": "symfony-bundle",
"license": "MIT",
"keywords": [
Expand All @@ -17,12 +17,14 @@
],
"autoload": {
"psr-4": {
"Elbformat\\IbexaIconFieldtype\\": "src/"
"Elbformat\\IconBundle\\": "src/"
}
},
"require": {
"php": ">=8.1",
"ezsystems/ezplatform-core": "^2.3"
"php": "^8.1",
"ezsystems/ezplatform-core": "^2.3",
"ezsystems/ezplatform-admin-ui": "^2.3",
"symfony/finder": "^5.4|^6.4"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
Expand All @@ -36,5 +38,10 @@
"symfony/flex": true,
"ibexa/post-install": true
}
},
"extra": {
"platform": {
"php": "8.1"
}
}
}
7 changes: 7 additions & 0 deletions config/ezplatform.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ezplatform:
system:
default:
field_templates:
- { template: '@ElbformatIconFieldtype/icon_field.html.twig', priority: 0 }
fielddefinition_edit_templates:
- { template: '@ElbformatIconFieldtype/icon_field_type_definition.html.twig', priority: 0 }
29 changes: 29 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
services:
Elbformat\IbexaIconFieldtype\FieldType\Icon\Type:
arguments:
$serializer: '@eZ\Publish\SPI\FieldType\ValueSerializerInterface'
$validator: '@Symfony\Component\Validator\Validator\ValidatorInterface'
tags:
- { name: ezplatform.field_type, alias: icon }
- { name: ezplatform.field_type.form_mapper.value, fieldType: icon }
- { name: ezplatform.field_type.form_mapper.definition, fieldType: icon }

Elbformat\IbexaIconFieldtype\FieldType\Icon\SearchField:
class: '%ezpublish.fieldType.indexable.unindexed.class%'
tags:
- { name: ezplatform.field_type.indexable, alias: icon }

Elbformat\IbexaIconFieldtype\Form\Type\IconType:
arguments:
$iconSetManager: '@Elbformat\IbexaIconFieldtype\IconSet\IconSetManager'
tags:
- { name: form.type }
Elbformat\IbexaIconFieldtype\Form\Type\IconSettingsType:
arguments:
$iconSetManager: '@Elbformat\IbexaIconFieldtype\IconSet\IconSetManager'
tags:
- { name: form.type }

Elbformat\IbexaIconFieldtype\IconSet\IconSetManager:
arguments:
$configs: [] # Will be set from bundle config
24 changes: 24 additions & 0 deletions doc/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Configuration

To configure your icon sets, there are two options:
1. Fixed sets of icon names
2. A list of icons derived from a filesystem folder

## Fixed set
To configure a fixed set of icons (e.g. "myicons"), use the following config syntax
```yaml
elbformat_icon:
myicons:
- clock
- house
```
## From filesystem
You can specify a folder that is being scanned for files. Optionally you can add a pattern to ignore non-icon files.
This example will look into the public/assets/build/images/icons folder and scans for svg files.
```yaml
elbformat_icon:
myiconsfromfolder:
folder: '%webroot_dir%/assets/build/images/icons'
pattern: '*.svg'
```
32 changes: 32 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);

namespace Elbformat\IconBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('elbformat_icon');

$treeBuilder->getRootNode()
->arrayPrototype() // Name of the set
->normalizeKeys(false)
->children()
->arrayNode('items') // Fix list
->requiresAtLeastOneElement()
->normalizeKeys(false)
->scalarPrototype()->end()
->end()
->scalarNode('folder')->end() // Path to look in
->scalarNode('pattern')->end() // Glob expression
->end()
->end()
;

return $treeBuilder;
}
}
42 changes: 42 additions & 0 deletions src/DependencyInjection/ElbformatIconExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);

namespace Elbformat\IconBundle\DependencyInjection;

use Elbformat\IconBundle\IconSet\IconSetManager;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Yaml\Yaml;

class ElbformatIconExtension extends Extension implements PrependExtensionInterface
{
public function load(array $configs, ContainerBuilder $container): void
{
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../../config/'));
$loader->load('services.yaml');

$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$definition = $container->getDefinition(IconSetManager::class);
$definition->setArgument('$configs', $config);
}

public function prepend(ContainerBuilder $container): void
{
// Add template for rendering
$configFile = __DIR__.'/../../config/ezplatform.yaml';
$config = Yaml::parse(file_get_contents($configFile));
$container->prependExtensionConfig('ezpublish', $config['ezplatform']);

// Register namespace (as this is not done automatically. Maybe the missing "bundle" in path?)
$container->prependExtensionConfig('twig', ['paths' => [__DIR__.'/../../templates' => 'ElbformatIconFieldtype']]);

// Register translations (as this is not done automatically. Maybe the missing "bundle" in path?)
$container->prependExtensionConfig('framework', ['translator' => ['paths' => [__DIR__.'/../../translations']]]);

}
}
11 changes: 11 additions & 0 deletions src/ElbformatIconBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

namespace Elbformat\IconBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ElbformatIconBundle extends Bundle
{

}
49 changes: 49 additions & 0 deletions src/FieldType/Icon/Type.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);

namespace Elbformat\IconBundle\FieldType\Icon;

use Elbformat\IconBundle\Form\Type\IconSettingsType;
use Elbformat\IconBundle\Form\Type\IconType;
use eZ\Publish\SPI\FieldType\Generic\Type as GenericType;
use EzSystems\EzPlatformAdminUi\FieldType\FieldDefinitionFormMapperInterface;
use EzSystems\EzPlatformAdminUi\Form\Data\FieldDefinitionData;
use EzSystems\EzPlatformContentForms\Data\Content\FieldData;
use EzSystems\EzPlatformContentForms\FieldType\FieldValueFormMapperInterface;
use Symfony\Component\Form\FormInterface;

final class Type extends GenericType implements FieldValueFormMapperInterface, FieldDefinitionFormMapperInterface
{
public function getFieldTypeIdentifier(): string
{
return 'icon';
}

public function mapFieldValueForm(FormInterface $fieldForm, FieldData $data): void
{
$definition = $data->fieldDefinition;
$iconSet = $definition->getFieldSettings()['iconset'];
$fieldForm->add('value', IconType::class, [
'required' => $definition->isRequired,
'label' => $definition->getName(),
'icon_set' => $iconSet,
]);
}

public function getSettingsSchema(): array
{
return [
'iconset' => [
'type' => 'string',
'default' => '',
],
];
}

public function mapFieldDefinitionForm(FormInterface $fieldDefinitionForm, FieldDefinitionData $data): void
{
$fieldDefinitionForm->add('fieldSettings', IconSettingsType::class, [
'label' => false,
]);
}
}
28 changes: 28 additions & 0 deletions src/FieldType/Icon/Value.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);

namespace Elbformat\IconBundle\FieldType\Icon;

use eZ\Publish\SPI\FieldType\Value as ValueInterface;

final class Value implements ValueInterface
{
private ?string $icon;

public function __construct(?string $icon=null) { $this->icon = $icon; }

public function __toString(): string
{
return $this->icon;
}

public function getIcon(): ?string
{
return $this->icon;
}

public function setIcon(?string $icon): void
{
$this->icon = $icon;
}
}
23 changes: 23 additions & 0 deletions src/Form/Type/IconSettingsType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);

namespace Elbformat\IconBundle\Form\Type;

use Elbformat\IconBundle\IconSet\IconSetManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;

final class IconSettingsType extends AbstractType
{
public function __construct(
private readonly IconSetManager $iconSetManager,
) { }

public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('iconset', ChoiceType::class,[
'choices' => $this->iconSetManager->getSetList()
]);
}
}
36 changes: 36 additions & 0 deletions src/Form/Type/IconType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);

namespace Elbformat\IconBundle\Form\Type;

use Elbformat\IconBundle\FieldType\Icon\Value;
use Elbformat\IconBundle\IconSet\IconSetManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

final class IconType extends AbstractType
{
public function __construct(
private readonly IconSetManager $iconSetManager,
) { }


public function buildForm(FormBuilderInterface $builder, array $options): void
{
$iconSet = $options['icon_set'];
$builder->add('icon', ChoiceType::class,[
'choices' => $this->iconSetManager->getSet($iconSet)->getList()
]);
}

public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Value::class,
'icon_set' => null,
]);
$resolver->addAllowedTypes('icon_set','string');
}
}
24 changes: 24 additions & 0 deletions src/IconSet/IconSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);

namespace Elbformat\IconBundle\IconSet;

class IconSet
{
/** @var array<string,string> */
protected array $items;

/** @param string[] */
public function __construct(array $items)
{
// Convert to string => string array
$this->items = array_flip($items);
array_walk($this->items, fn(&$val, $key) => $val = $key);
}

/** @return string[] */
public function getList(): array
{
return $this->items;
}
}
Loading

0 comments on commit 3231e4f

Please sign in to comment.