diff --git a/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataBooleanFieldType.php b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataBooleanFieldType.php new file mode 100644 index 0000000..9e123f0 --- /dev/null +++ b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataBooleanFieldType.php @@ -0,0 +1,42 @@ + + * @copyright 2021 Novactive + * @license https://github.com/Novactive/NovaeZSEOBundle/blob/master/LICENSE MIT Licence + */ + +namespace Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter; + +use Novactive\Bundle\eZSEOBundle\Core\Meta; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\FormBuilderInterface; + +class SeoMetadataBooleanFieldType extends SeoMetadataDefaultFieldType +{ + public const IDENTIFIER = 'boolean'; + public function fromHash($hash): Meta + { + $meta = parent::fromHash($hash); + $content = $hash['meta_content'] == "1" ? true : false; + $meta->setContent($content); + + return $meta; + } + + public function mapForm(FormBuilderInterface &$builder, array $params) + { + $option = [ + 'class' => 'form-control', + 'false_values' => '0' + ]; + $builder->add( + 'content', + CheckboxType::class, + array_merge($params, $option) + ); + } +} diff --git a/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataChoiceFieldType.php b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataChoiceFieldType.php new file mode 100644 index 0000000..16c4d68 --- /dev/null +++ b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataChoiceFieldType.php @@ -0,0 +1,30 @@ + + * @copyright 2021 Novactive + * @license https://github.com/Novactive/NovaeZSEOBundle/blob/master/LICENSE MIT Licence + */ + +namespace Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter; + +use Novactive\Bundle\eZSEOBundle\Core\Meta; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\FormBuilderInterface; + +class SeoMetadataChoiceFieldType extends SeoMetadataDefaultFieldType +{ + public const IDENTIFIER = 'select'; + + public function mapForm(FormBuilderInterface &$builder, array $params) + { + $builder->add( + 'content', + ChoiceType::class, + $params + ); + } +} diff --git a/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataDefaultFieldType.php b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataDefaultFieldType.php new file mode 100644 index 0000000..3cea234 --- /dev/null +++ b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataDefaultFieldType.php @@ -0,0 +1,47 @@ + + * @copyright 2021 Novactive + * @license https://github.com/Novactive/NovaeZSEOBundle/blob/master/LICENSE MIT Licence + */ + +namespace Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter; + +use Novactive\Bundle\eZSEOBundle\Core\Meta; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilderInterface; + +class SeoMetadataDefaultFieldType implements SeoMetadataFieldTypeInterface +{ + public const IDENTIFIER = 'text'; + + public function support(string $fieldType): bool + { + return static::IDENTIFIER === $fieldType; + } + + public function fromHash($hash): Meta + { + $meta = new Meta(); + $meta->setName($hash['meta_name']); + $meta->setFieldType(self::IDENTIFIER); + $content = $hash['meta_content']; + $meta->setContent($content); + + return $meta; + } + + public function mapForm(FormBuilderInterface &$builder, array $params) + { + $params['empty_data'] = ''; + $builder->add( + 'content', + TextType::class, + $params + ); + } +} diff --git a/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataFieldTypeInterface.php b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataFieldTypeInterface.php new file mode 100644 index 0000000..f2eb494 --- /dev/null +++ b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataFieldTypeInterface.php @@ -0,0 +1,38 @@ + + * @copyright 2021 Novactive + * @license https://github.com/Novactive/NovaeZSEOBundle/blob/master/LICENSE MIT Licence + */ + +namespace Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter; + +use Novactive\Bundle\eZSEOBundle\Core\Meta; +use Symfony\Component\Form\FormBuilderInterface; + +interface SeoMetadataFieldTypeInterface +{ + /** + * @param $hash + * + * @return Meta + */ + public function fromHash($hash): Meta; + + /** + * @param string $fieldType + * + * @return bool + */ + public function support(string $fieldType): bool; + + /** + * @param FormBuilderInterface $builder + * @param array $params + */ + public function mapForm(FormBuilderInterface &$builder, array $params); +} diff --git a/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataFieldTypeRegistry.php b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataFieldTypeRegistry.php new file mode 100644 index 0000000..66e97d4 --- /dev/null +++ b/bundle/Core/FieldType/MetaFieldConverter/SeoMetadataFieldTypeRegistry.php @@ -0,0 +1,82 @@ + + * @copyright 2021 Novactive + * @license https://github.com/Novactive/NovaeZSEOBundle/blob/master/LICENSE MIT Licence + */ + +namespace Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter; + +use eZ\Publish\Core\MVC\ConfigResolverInterface; +use Symfony\Component\Form\FormBuilderInterface; + +class SeoMetadataFieldTypeRegistry +{ + /** @var SeoMetadataFieldTypeInterface[] */ + protected $metaFieldTypes; + + /** @var ConfigResolverInterface */ + protected $configResolver; + + /** + * SeoMetadataFieldTypeRegistry constructor. + * + * @param SeoMetadataFieldTypeInterface[] $metaFieldTypes + */ + public function __construct(iterable $metaFieldTypes) + { + foreach ($metaFieldTypes as $metaFieldType) { + $this->addMetaFieldType($metaFieldType); + } + } + + /** + * @required + * @param ConfigResolverInterface $configResolver + */ + public function setConfigResolver( ConfigResolverInterface $configResolver ): void + { + $this->configResolver = $configResolver; + } + + public function addMetaFieldType(SeoMetadataFieldTypeInterface $metaFieldType): void + { + $this->metaFieldTypes[] = $metaFieldType; + } + + public function fromHash($hash): array + { + $metasConfig = $this->configResolver->getParameter('fieldtype_metas', 'nova_ezseo'); + + $metas = []; + foreach ($hash as $hashItem) { + if (!is_array($hashItem)) { + continue; + } + $fieldConfig = $metasConfig[$hashItem['meta_name']] ?? null; + $fieldType = $fieldConfig['type'] ?? SeoMetadataDefaultFieldType::IDENTIFIER; + foreach ($this->metaFieldTypes as $metaFieldType) { + if (!$metaFieldType->support($fieldType)) { + continue; + } + $metas[] = $metaFieldType->fromHash($hashItem); + } + } + + return $metas; + } + + public function mapForm(FormBuilderInterface &$builder, array $params, string $fieldType) + { + foreach ($this->metaFieldTypes as $metaFieldType) { + if (!$metaFieldType->support($fieldType)) { + continue; + } + $metaFieldType->mapForm($builder, $params); + } + } +} diff --git a/bundle/Core/FieldType/Metas/FormMapper.php b/bundle/Core/FieldType/Metas/FormMapper.php index f046016..4a97e9a 100644 --- a/bundle/Core/FieldType/Metas/FormMapper.php +++ b/bundle/Core/FieldType/Metas/FormMapper.php @@ -85,11 +85,14 @@ public function mapFieldValueForm(FormInterface $fieldForm, FieldData $data) $formConfig = $fieldForm->getConfig(); $metasConfig = $this->configResolver->getParameter('fieldtype_metas', 'nova_ezseo'); - - if (empty($data->value->metas)) { - foreach (array_keys($metasConfig) as $key) { - $data->value->metas[$key] = new Meta($key, ''); + $metasData = $data->value->metas; + foreach ($metasConfig as $key => $meta) { + $content = isset($metasData[$key]) ? $metasData[$key]->getContent() : null; + $fieldType = $meta['type']; + if (isset($metasData[$key]) && $metasData[$key]->getFieldType() != '') { + $fieldType = $metasData[$key]->getFieldType(); } + $data->value->metas[$key] = new Meta($key, $content, $fieldType); } $fieldForm @@ -100,7 +103,7 @@ public function mapFieldValueForm(FormInterface $fieldForm, FieldData $data) MetasFieldType::class, [ 'required' => $fieldDefinition->isRequired, - 'label' => $fieldDefinition->getName($formConfig->getOption('languageCode')), + 'label' => $fieldDefinition->getName($formConfig->getOption('languageCode')) ] ) ->setAutoInitialize(false) diff --git a/bundle/Core/FieldType/Metas/Type.php b/bundle/Core/FieldType/Metas/Type.php index 5786653..60b75cc 100644 --- a/bundle/Core/FieldType/Metas/Type.php +++ b/bundle/Core/FieldType/Metas/Type.php @@ -17,12 +17,16 @@ use eZ\Publish\Core\FieldType\Value as CoreValue; use eZ\Publish\SPI\FieldType\Value as SPIValue; use eZ\Publish\SPI\Persistence\Content\FieldValue; +use Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter\SeoMetadataFieldTypeRegistry; use Novactive\Bundle\eZSEOBundle\Core\Meta; class Type extends FieldType { const IDENTIFIER = 'novaseometas'; + /** @var SeoMetadataFieldTypeRegistry */ + protected $metadataFieldTypeRegistry; + /** * @var array */ @@ -33,6 +37,15 @@ class Type extends FieldType ], ]; + /** + * Type constructor. + * @param SeoMetadataFieldTypeRegistry $metadataFieldTypeRegistry + */ + public function __construct(SeoMetadataFieldTypeRegistry $metadataFieldTypeRegistry) + { + $this->metadataFieldTypeRegistry = $metadataFieldTypeRegistry; + } + /** * Validates the fieldSettings of a FieldDefinitionCreateStruct or FieldDefinitionUpdateStruct. * @@ -179,18 +192,8 @@ public function fromHash($hash) if (!is_array($hash)) { return new Value([]); } - $metas = []; - foreach ($hash as $hashItem) { - if (!is_array($hashItem)) { - continue; - } - $meta = new Meta(); - $meta->setName($hashItem['meta_name']); - $meta->setContent($hashItem['meta_content']); - $metas[] = $meta; - } - return new Value($metas); + return new Value($this->metadataFieldTypeRegistry->fromHash($hash)); } /** @@ -207,7 +210,7 @@ public function toHash(SPIValue $value) /* @var Meta $meta */ $hash[$meta->getName()] = [ 'meta_name' => $meta->getName(), - 'meta_content' => $meta->getContent(), + 'meta_content' => $meta->getContent() ]; } diff --git a/bundle/Core/Meta.php b/bundle/Core/Meta.php index a9c2527..8cf3c7d 100644 --- a/bundle/Core/Meta.php +++ b/bundle/Core/Meta.php @@ -29,16 +29,25 @@ class Meta */ protected $content; + /** + * Meta fieldType. + * + * @var string + */ + protected $fieldType; + /** * Constructor. * * @param string $name - * @param string $content + * @param mixed $content + * @param string $fieldType */ - public function __construct(?string $name = null, ?string $content = null) + public function __construct(?string $name = null, $content = null, ?string $fieldType = null) { - $this->name = $name; - $this->content = $content; + $this->name = $name; + $this->content = $content; + $this->fieldType = $fieldType; } public function getName(): string @@ -53,14 +62,26 @@ public function setName(?string $name): self return $this; } - public function getContent(): string + public function getFieldType(): string + { + return $this->fieldType ?? ''; + } + + public function setFieldType(?string $fieldType): self + { + $this->fieldType = $fieldType ?? ''; + + return $this; + } + + public function getContent() { - return $this->content ?? ''; + return $this->content; } - public function setContent(?string $content): self + public function setContent($content): self { - $this->content = $content ?? ''; + $this->content = $content; return $this; } @@ -81,6 +102,7 @@ public function attributes(): array return [ 'name', 'content', + 'fieldType' ]; } @@ -96,6 +118,9 @@ public function attribute(string $name): ?string case 'content': return $this->getContent(); break; + case 'fieldType': + return $this->getFieldType(); + break; default: throw new PropertyNotFoundException($name, \get_class($this)); break; diff --git a/bundle/DependencyInjection/Configuration.php b/bundle/DependencyInjection/Configuration.php index a877816..0b23314 100644 --- a/bundle/DependencyInjection/Configuration.php +++ b/bundle/DependencyInjection/Configuration.php @@ -34,6 +34,10 @@ public function getConfigTreeBuilder(): TreeBuilder ->prototype('array') ->children() ->scalarNode('label')->isRequired()->end() + ->enumNode('type')->values(['boolean', 'text', 'select'])->defaultValue('text')->end() + ->arrayNode('params') + ->prototype('variable')->end() + ->end() ->scalarNode('default_pattern')->end() ->scalarNode('icon')->end() ->end() diff --git a/bundle/Form/Type/MetaType.php b/bundle/Form/Type/MetaType.php index 8af80b3..766cdaf 100644 --- a/bundle/Form/Type/MetaType.php +++ b/bundle/Form/Type/MetaType.php @@ -11,10 +11,11 @@ namespace Novactive\Bundle\eZSEOBundle\Form\Type; +use eZ\Publish\Core\MVC\ConfigResolverInterface; +use Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter\SeoMetadataFieldTypeRegistry; use Novactive\Bundle\eZSEOBundle\Core\Meta; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\HiddenType; -use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -23,6 +24,22 @@ */ class MetaType extends AbstractType { + /** @var ConfigResolverInterface */ + protected $configResolver; + + /** @var SeoMetadataFieldTypeRegistry */ + protected $metadataFieldTypeRegistry; + /** + * FormMapper constructor. + */ + public function __construct( + ConfigResolverInterface $configResolver, + SeoMetadataFieldTypeRegistry $metadataFieldTypeRegistry + ) { + $this->configResolver = $configResolver; + $this->metadataFieldTypeRegistry = $metadataFieldTypeRegistry; + } + public function getName(): string { return $this->getBlockPrefix(); @@ -35,16 +52,20 @@ public function getBlockPrefix(): string public function buildForm(FormBuilderInterface $builder, array $options): void { - $builder - ->add('name', HiddenType::class) - ->add( - 'content', - TextType::class, - [ - 'label' => false, - 'empty_data' => '', - ] - ); + $metasConfig = $this->configResolver->getParameter('fieldtype_metas', 'nova_ezseo'); + + $type = 'text'; + $options = [ + 'label' => false, + ]; + if (isset($metasConfig[$builder->getName()])) { + $meta = $metasConfig[$builder->getName()]; + $type = $meta['type']; + $options = array_merge($options, $meta['params']); + } + + $builder->add('name', HiddenType::class); + $this->metadataFieldTypeRegistry->mapForm($builder, $options, $type); } public function configureOptions(OptionsResolver $resolver): void diff --git a/bundle/Form/Type/MetasFieldType.php b/bundle/Form/Type/MetasFieldType.php index ac153e6..1a98c2f 100644 --- a/bundle/Form/Type/MetasFieldType.php +++ b/bundle/Form/Type/MetasFieldType.php @@ -33,8 +33,7 @@ public function getBlockPrefix(): string public function buildForm(FormBuilderInterface $builder, array $options): void { - $builder - ->add('metas', MetasCollectionType::class); + $builder->add('metas', MetasCollectionType::class); } public function configureOptions(OptionsResolver $resolver): void diff --git a/bundle/NovaeZSEOBundle.php b/bundle/NovaeZSEOBundle.php index 5e9f470..e58b8ef 100644 --- a/bundle/NovaeZSEOBundle.php +++ b/bundle/NovaeZSEOBundle.php @@ -12,6 +12,7 @@ namespace Novactive\Bundle\eZSEOBundle; use LogicException; +use Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter\SeoMetadataFieldTypeInterface; use Novactive\Bundle\eZSEOBundle\DependencyInjection\Compiler\CustomFallbackPass; use Novactive\Bundle\eZSEOBundle\DependencyInjection\Security\PolicyProvider\PolicyProvider; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -27,6 +28,8 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new CustomFallbackPass()); $eZExtension = $container->getExtension('ezpublish'); $eZExtension->addPolicyProvider(new PolicyProvider()); + $container->registerForAutoconfiguration(SeoMetadataFieldTypeInterface::class) + ->addTag('seometa.fieldtype'); } public function getContainerExtension() diff --git a/bundle/Resources/config/admin_ui/services.yml b/bundle/Resources/config/admin_ui/services.yml index 859cb8b..bd00881 100644 --- a/bundle/Resources/config/admin_ui/services.yml +++ b/bundle/Resources/config/admin_ui/services.yml @@ -1,8 +1,13 @@ services: + Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter\SeoMetadataFieldTypeRegistry: + autowire: true + arguments: [!tagged seometa.fieldtype] + # FIELD TYPE Novactive\Bundle\eZSEOBundle\Core\FieldType\Metas\Type: parent: ezpublish.fieldType + autowire: true tags: - { name: ezpublish.fieldType, alias: novaseometas } diff --git a/bundle/Resources/config/default_settings.yml b/bundle/Resources/config/default_settings.yml index ea3db65..1bec686 100644 --- a/bundle/Resources/config/default_settings.yml +++ b/bundle/Resources/config/default_settings.yml @@ -80,3 +80,13 @@ parameters: label: 'Twitter - Image' default_pattern: "" icon: 'twitter-square' + 'robots': + label: 'Robots' + type: 'select' + params: + choices: + all: 'all' + nofollow: 'nofollow' + noindex: 'noindex' + default_pattern: 'all' + icon: 'book' diff --git a/bundle/Resources/config/services.yml b/bundle/Resources/config/services.yml index 6675a83..af5a20a 100644 --- a/bundle/Resources/config/services.yml +++ b/bundle/Resources/config/services.yml @@ -43,6 +43,9 @@ services: Novactive\Bundle\eZSEOBundle\Twig\NovaeZSEOExtension: ~ Novactive\Bundle\eZSEOBundle\Core\DummyCustomFallback: ~ + Novactive\Bundle\eZSEOBundle\Core\FieldType\MetaFieldConverter\: + resource: '../../Core/FieldType/MetaFieldConverter/*' + Novactive\Bundle\eZSEOBundle\Core\MetaNameSchema: arguments: $contentTypeHandler: "@ezpublish.spi.persistence.content_type_handler" @@ -85,3 +88,5 @@ services: novaezmailing.doctrine.entity_manager: class: Doctrine\ORM\EntityManagerInterface factory: 'Novactive\Bundle\eZSEOBundle\Core\SiteAccessAwareEntityManagerFactory:get' + + Novactive\Bundle\eZSEOBundle\Form\Type\MetaType: ~ \ No newline at end of file diff --git a/bundle/Resources/public/css/views/fields/edit/novaseometas.css b/bundle/Resources/public/css/views/fields/edit/novaseometas.css index ceb0ba1..cf2a26e 100644 --- a/bundle/Resources/public/css/views/fields/edit/novaseometas.css +++ b/bundle/Resources/public/css/views/fields/edit/novaseometas.css @@ -118,3 +118,17 @@ float: left; clear: right; } + +.ez-field-edit--novaseometas .ez-data-source__input-wrapper .ez-data-source__input-wrapper .form-check .form-check-label { + display: none; +} + +.ez-field-edit--novaseometas .ez-data-source__input-wrapper .ez-data-source__input-wrapper .form-check .form-check-input { + margin-top: 0; + position: relative; + height: 30px; +} + +.ez-field-edit--novaseometas .ez-data-source__input-wrapper .ez-data-source__input-wrapper .form-check .form-check-input:focus { + box-shadow: none; +} diff --git a/documentation/INSTALL.md b/documentation/INSTALL.md index 7c3abeb..7801549 100644 --- a/documentation/INSTALL.md +++ b/documentation/INSTALL.md @@ -57,7 +57,7 @@ _novaezseo_routes: ### Create the table -See the file `bundle/Resources/sql/shema.sql` +See the folder `bundle/Resources/sql` ### Remove the Robots.txt (native RewriteRules )