Compare commits

..

10 Commits

Author SHA1 Message Date
tim
306414e24b Update to symfony 7+ 2024-07-05 23:08:05 +02:00
tim
35228c8496 Allow caching of parameter values
Increase composer php version to match
2023-06-12 01:00:36 +02:00
tim
61b8a68705 Allow choice type in parameter config 2023-02-21 01:03:37 +01:00
tim
7040fd5ea7 Refactor to new bundle style (Symfony v6) 2023-02-21 00:44:28 +01:00
tim
a2fe3584be Improve parsing of parameters when giving them back
Update some things to php 8
2022-02-01 21:46:27 +01:00
tim
dacf3d6687 Allow symfony 6 2022-01-30 01:15:39 +01:00
tim
cd3c5a0a52 Allow for bool type as config type 2022-01-30 01:11:39 +01:00
da8a1e37ca Fix line endings? 2021-07-21 00:25:37 +02:00
d20f7401c1 Add categories overview 2020-10-23 23:39:45 +02:00
69abbcaf4b Improve phpdocs of service 2020-07-27 01:23:13 +02:00
17 changed files with 899 additions and 935 deletions

View File

@ -1,13 +0,0 @@
<?php
namespace Ardent\ParameterBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* Bundle.
*/
class ArdentParameterBundle extends Bundle
{
}

View File

@ -1,26 +0,0 @@
<?php
namespace Ardent\ParameterBundle\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class ArdentParameterExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$loader = new YamlFileLoader(
$container,
new FileLocator(dirname(__DIR__).'/Resources/config')
);
$loader->load('services.yaml');
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$def = $container->findDefinition('ardent.parameter');
$def->setArgument('$config', $config['parameters']);
}
}

View File

@ -1,38 +0,0 @@
<?php
namespace Ardent\ParameterBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public const TYPE_TEXT = 'text';
public const TYPE_NUMBER = 'number';
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('ardent_parameter');
$treeBuilder->getRootNode()
->children()
->arrayNode('parameters')
->arrayPrototype()
->arrayPrototype()
->children()
->scalarNode('name')->end()
->enumNode('type')
->values([self::TYPE_TEXT, self::TYPE_NUMBER])
->defaultValue(self::TYPE_TEXT)
->end()
->end()
->end()
->end()
->end()
->end();
return $treeBuilder;
}
}

View File

@ -1,75 +0,0 @@
<?php
namespace Ardent\ParameterBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="parameter_bundle_parameters")
*/
class Parameter
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string")
*/
private $name;
/**
* @ORM\Column(type="string")
*/
private $value;
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
* @return Parameter
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* @param mixed $value
* @return Parameter
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
}

1346
LICENSE

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,14 @@
"description": "Simple bundle for storing parameters in a database", "description": "Simple bundle for storing parameters in a database",
"type": "symfony-bundle", "type": "symfony-bundle",
"require": { "require": {
"doctrine/orm": "^2.7", "php": "^8.1",
"symfony/form": "^5.0", "doctrine/orm": "^2.0",
"symfony/twig-bundle": "^5.0" "symfony/form": "^5.0|^6.0|^7.0",
"symfony/twig-bundle": "^5.0|^6.0|^7.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Ardent\\ParameterBundle\\": "" "Ardent\\ParameterBundle\\": "src/"
} }
}, },
"license": "GPL-3.0-only" "license": "GPL-3.0-only"

View File

@ -7,6 +7,6 @@ services:
autowire: true autowire: true
Ardent\ParameterBundle\Controller\: Ardent\ParameterBundle\Controller\:
resource: '../../Controller' resource: '../src/Controller'
tags: ['controller.service_arguments'] tags: ['controller.service_arguments', 'container.service_subscriber']
autowire: true autowire: true

View File

@ -0,0 +1,52 @@
<?php
namespace Ardent\ParameterBundle;
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class ArdentParameterBundle extends AbstractBundle
{
public const TYPE_TEXT = 'text';
public const TYPE_NUMBER = 'number';
public const TYPE_BOOL = 'bool';
public const TYPE_CHOICE = 'choice';
public function configure(DefinitionConfigurator $definition): void
{
// $treeBuilder = new TreeBuilder('ardent_parameter');
$definition->rootNode()
->children()
->arrayNode('parameters')
->arrayPrototype()
->arrayPrototype()
->children()
->scalarNode('name')->end()
->enumNode('type')
->values([self::TYPE_TEXT, self::TYPE_NUMBER, self::TYPE_BOOL, self::TYPE_CHOICE])
->defaultValue(self::TYPE_TEXT)
->end()
->arrayNode('choices')
->scalarPrototype()->end()
->end()
->end()
->end()
->end()
->end()
->end();
}
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
$container->import('../config/services.yaml');
// Retrieves the parameters from the config and injects them info the ardent.parameter service
$def = $builder->findDefinition('ardent.parameter');
$def->setArgument('$config', $config['parameters']);
}
}

View File

@ -9,21 +9,17 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
abstract class BaseController extends AbstractController abstract class BaseController extends AbstractController
{ {
/** public function baseIndex(ParameterService $param, Request $request, array $configuration): Response
* @param ParameterService $param
* @param Request $request
* @param [] $configuration
*/
public function baseIndex(ParameterService $param, Request $request, $configuration)
{ {
// gather the values // gather the values
$data = []; $data = [];
foreach ($configuration as $config) { foreach ($configuration as $config) {
$name = $config['name']; $name = $config['name'];
$data[$name] = $this->valueParser($config['type'], $param->get($name, false)); $data[$name] = $param->get($name, false);
} }
// build the form // build the form
@ -51,36 +47,26 @@ abstract class BaseController extends AbstractController
} }
return $this->render('@ArdentParameter/form.html.twig', [ return $this->render('@ArdentParameter/form.html.twig', [
'parameter_form' => $form->createView(), 'parameter_form' => $form->createView(),
]); ]);
}
private function valueParser($type, $value)
{
switch ($type) {
case CheckboxType::class:
return boolval($value);
break;
default:
return $value;
break;
}
} }
/** /**
* @param $config * @param $config
* @param FormBuilderInterface $formBuilder * @param FormBuilderInterface $formBuilder
*/ */
private function configParser($config, &$formBuilder) private function configParser($config, FormBuilderInterface $formBuilder): void
{ {
$type = $config['type']; $type = $config['type'];
$options = []; $options = [];
switch ($type) { switch ($type) {
case ChoiceType::class: case ChoiceType::class:
if (is_callable($config['choices'])) { $choices = array_combine($config['choices'], $config['choices']);
$options['choices'] = $config['choices']();
if (is_callable($choices)) {
$options['choices'] = $choices();
} else { } else {
$options['choices'] = $config['choices']; $options['choices'] = $choices;
} }
break; break;
case CheckboxType::class: case CheckboxType::class:

View File

@ -1,41 +1,42 @@
<?php <?php
namespace Ardent\ParameterBundle\Controller; namespace Ardent\ParameterBundle\Controller;
use Ardent\ParameterBundle\Service\ParameterService; use Ardent\ParameterBundle\Service\ParameterService;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class ParameterController extends BaseController
{ class ParameterController extends BaseController
/** {
* @Route("/{category}", name="parameter_bundle_parameters") #[Route('/{category}', name: 'parameter_bundle_parameters')]
*/ public function parameters(
public function parameters($category, ParameterService $param,
ParameterService $param, Request $request,
Request $request) ?string $category = 'categories',
{ ): Response
$configs = $param->getConfig(); {
$configs = $param->getConfig();
// Handle all special cases for the name
/*if ('list' === $name) { // List all the categories // Handle all special cases for the name
$routes = []; if ('categories' === $category) { // List all the categories
foreach ($configs as $key => $config) { $categories = [];
$routes[] = ['route' => 'parameters', 'params' => ['name' => $key], 'title' => $key]; foreach ($configs as $key => $config) {
} $categories[] = $key;
}
return $this->render('list.routes.twig', ['routes' => $routes]); $categories[] = 'all';
} else*/if ('all' === $category) { // Show all parameters from all categories return $this->render('@ArdentParameter/categories.html.twig', ['categories' => $categories]);
$allConfigs = []; } elseif ('all' === $category) { // Show all parameters from all categories
foreach ($configs as $config) { $allConfigs = [];
$allConfigs = array_merge($allConfigs, $config); foreach ($configs as $config) {
} $allConfigs = array_merge($allConfigs, $config);
}
return parent::baseIndex($param, $request, $allConfigs);
} else { // Show the parameters from one category return parent::baseIndex($param, $request, $allConfigs);
return parent::baseIndex($param, $request, $configs[$category]); } else { // Show the parameters from one category
} return parent::baseIndex($param, $request, $configs[$category]);
} }
}
} }

61
src/Entity/Parameter.php Normal file
View File

@ -0,0 +1,61 @@
<?php
namespace Ardent\ParameterBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
#[ORM\Entity()]
#[ORM\Table(name: 'parameter_bundle_parameters')]
class Parameter
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column]
private ?string $name;
#[ORM\Column(type: 'string')]
private mixed $value;
public function getId(): int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getValue(): mixed
{
return $this->value;
}
static function parseValue(mixed $value, string $type): mixed
{
return match ($type) {
NumberType::class => intval($value),
CheckboxType::class => boolval($value),
default => $value,
};
}
public function setValue(mixed $value): self
{
$this->value = $value;
return $this;
}
}

View File

@ -2,45 +2,44 @@
namespace Ardent\ParameterBundle\Service; namespace Ardent\ParameterBundle\Service;
use Ardent\ParameterBundle\DependencyInjection\Configuration; use Ardent\ParameterBundle\ArdentParameterBundle;
use Ardent\ParameterBundle\Entity\Parameter; use Ardent\ParameterBundle\Entity\Parameter;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\NumberType; use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
class ParameterService class ParameterService
{ {
/** @var EntityManagerInterface */ private array $config;
private $em;
/** @var ParameterBagInterface */ private array $cache = [];
private $parameter;
private $config;
/** public function __construct(
* ParameterService constructor. private readonly EntityManagerInterface $em,
* private readonly ParameterBagInterface $parameter,
* @param EntityManagerInterface $em array $config
* @param ParameterBagInterface $parameter )
* @param $config
*/
public function __construct(EntityManagerInterface $em, ParameterBagInterface $parameter, $config)
{ {
$this->em = $em;
$this->parameter = $parameter;
$this->config = $this->supplementConfig($config); $this->config = $this->supplementConfig($config);
} }
/** /**
* @param string $name * @param string $name The name of the parameter in the format <group>_<parameter>
* @param bool $parse
*
* @return string
*/ */
public function get($name, $parse = true) public function get(string $name, bool $parse = true): mixed
{ {
if (array_key_exists($name, $this->cache)) {
return $this->cache[$name];
}
$split = explode('_', $name);
$category = array_shift($split);
$paramRepo = $this->em->getRepository(Parameter::class); $paramRepo = $this->em->getRepository(Parameter::class);
/** @var Parameter $parameter */
$parameter = $paramRepo->findOneBy(['name' => $name]); $parameter = $paramRepo->findOneBy(['name' => $name]);
if ($parameter) { if ($parameter) {
if ($parse) { if ($parse) {
@ -60,17 +59,17 @@ class ParameterService
$value = $parameter->getValue(); $value = $parameter->getValue();
} }
return $value; $this->cache[$name] = Parameter::parseValue($value, $this->config[$category][$name]['type']);
return $this->cache[$name];
} else { } else {
return null; return null;
} }
} }
/** /**
* @param $name * @param string $name The name of the parameter in the format <group>_<parameter>
* @param $value
*/ */
public function set($name, $value) public function set(string $name, mixed $value): void
{ {
$paramRepo = $this->em->getRepository(Parameter::class); $paramRepo = $this->em->getRepository(Parameter::class);
/* @var Parameter $parameter */ /* @var Parameter $parameter */
@ -81,33 +80,39 @@ class ParameterService
$parameter->setValue($value); $parameter->setValue($value);
$this->em->persist($parameter); $this->em->persist($parameter);
$this->em->flush(); $this->em->flush();
$this->cache[$name] = $value;
} }
/** private function supplementConfig(array $rawConfig): array
* Replaces the types in the config by their classes
*
* @param $config
* @return array
*/
private function supplementConfig($config)
{ {
foreach ($config as $groupName => &$group) { $config = [];
foreach ($group as &$value) { foreach ($rawConfig as $groupName => $rawGroup) {
$group = [];
foreach ($rawGroup as &$value) {
switch ($value['type']) { switch ($value['type']) {
default: default:
case Configuration::TYPE_TEXT: case ArdentParameterBundle::TYPE_TEXT:
$class = TextType::class; $class = TextType::class;
break; break;
case Configuration::TYPE_NUMBER: case ArdentParameterBundle::TYPE_NUMBER:
$class = NumberType::class; $class = NumberType::class;
break; break;
case ArdentParameterBundle::TYPE_BOOL:
$class = CheckboxType::class;
break;
case ArdentParameterBundle::TYPE_CHOICE:
$class = ChoiceType::class;
break;
} }
// Add the group name in front of the parameter name
$value['name'] = sprintf('%s_%s', $groupName, $value['name']); $value['name'] = sprintf('%s_%s', $groupName, $value['name']);
$value['type'] = $class; $value['type'] = $class;
$group[$value['name']] = $value;
unset($value); unset($value);
} }
unset($group); $config[$groupName] = $group;
} }
return $config; return $config;
} }

View File

@ -0,0 +1,9 @@
{% extends '@ArdentParameter/layout.html.twig' %}
{% block par_user_content %}
<h2>Parameter categories</h2><br>
{% for category in categories %}
<a class="btn-primary btn" href="{{ path('parameter_bundle_parameters', {category:category}) }}">{{ category }}</a><br><br>
{% endfor %}
{% endblock %}

View File

@ -0,0 +1 @@
{# Add extra content on the bottom of the form #}

View File

@ -1,8 +1,8 @@
{% extends '@ArdentParameter/layout.html.twig' %} {% extends '@ArdentParameter/layout.html.twig' %}
{% block par_user_content %} {% block par_user_content %}
<a class="btn-primary btn" href="{{ path('parameter_bundle_parameters', {category:'categories'}) }}">Back</a> <br><br>
{{ form(parameter_form) }} {{ form(parameter_form) }}
{% include '@ArdentParameter/form.extra.html.twig' %} {% include '@ArdentParameter/form.extra.html.twig' %}
{% endblock %} {% endblock %}