diff --git a/src/Configuration/StringAccessibleConfigTrait.php b/src/Configuration/StringAccessibleConfigTrait.php
index 9f9f7bd7..d8e564c0 100644
--- a/src/Configuration/StringAccessibleConfigTrait.php
+++ b/src/Configuration/StringAccessibleConfigTrait.php
@@ -26,9 +26,6 @@ trait StringAccessibleConfigTrait
*/
protected $initialized = false;
- /**
- * @param array $settings
- */
public function __construct(ConfigLoaderInterface $repository, array $settings)
{
$this->repository = $repository;
@@ -120,4 +117,45 @@ trait StringAccessibleConfigTrait
return $config[$search];
}
+
+ /**
+ * @return bool
+ */
+ public function offsetExists($offset)
+ {
+ try {
+ $this->find($offset);
+ } catch (\Exception $ex) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function offsetGet($offset)
+ {
+ return $this->find($offset);
+ }
+
+ /**
+ * @param mixed $offset
+ * @param mixed $value
+ * @throws \BadMethodCallException
+ */
+ public function offsetSet($offset, $value)
+ {
+ throw new \BadMethodCallException('SystemBundleConfiguration does not support offsetSet()');
+ }
+
+ /**
+ * @param mixed $offset
+ * @throws \BadMethodCallException
+ */
+ public function offsetUnset($offset)
+ {
+ throw new \BadMethodCallException('SystemBundleConfiguration does not support offsetUnset()');
+ }
}
diff --git a/src/Configuration/ThemeConfiguration.php b/src/Configuration/ThemeConfiguration.php
index 195df9d3..ed648140 100644
--- a/src/Configuration/ThemeConfiguration.php
+++ b/src/Configuration/ThemeConfiguration.php
@@ -9,7 +9,7 @@
namespace App\Configuration;
-class ThemeConfiguration implements SystemBundleConfiguration
+class ThemeConfiguration implements SystemBundleConfiguration, \ArrayAccess
{
use StringAccessibleConfigTrait;
diff --git a/src/Controller/SystemConfigurationController.php b/src/Controller/SystemConfigurationController.php
index 8645a1e6..8372df6e 100644
--- a/src/Controller/SystemConfigurationController.php
+++ b/src/Controller/SystemConfigurationController.php
@@ -312,6 +312,30 @@ class SystemConfigurationController extends AbstractController
->setType(TextType::class)
->setConstraints([new DateTime(['format' => 'H:i']), new NotNull()]),
]),
+ (new SystemConfigurationModel())
+ ->setSection(SystemConfigurationModel::SECTION_BRANDING)
+ ->setConfiguration([
+ (new Configuration())
+ ->setName('theme.branding.logo')
+ ->setTranslationDomain('system-configuration')
+ ->setRequired(false)
+ ->setType(TextType::class),
+ (new Configuration())
+ ->setName('theme.branding.company')
+ ->setTranslationDomain('system-configuration')
+ ->setRequired(false)
+ ->setType(TextType::class),
+ (new Configuration())
+ ->setName('theme.branding.mini')
+ ->setTranslationDomain('system-configuration')
+ ->setRequired(false)
+ ->setType(TextType::class),
+ (new Configuration())
+ ->setName('theme.branding.title')
+ ->setTranslationDomain('system-configuration')
+ ->setRequired(false)
+ ->setType(TextType::class),
+ ]),
];
}
}
diff --git a/src/DependencyInjection/Compiler/TwigContextCompilerPass.php b/src/DependencyInjection/Compiler/TwigContextCompilerPass.php
index 93b6404c..84168297 100644
--- a/src/DependencyInjection/Compiler/TwigContextCompilerPass.php
+++ b/src/DependencyInjection/Compiler/TwigContextCompilerPass.php
@@ -9,6 +9,7 @@
namespace App\DependencyInjection\Compiler;
+use App\Configuration\ThemeConfiguration;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -24,8 +25,8 @@ class TwigContextCompilerPass implements CompilerPassInterface
public function process(ContainerBuilder $container)
{
$twig = $container->getDefinition('twig');
- $theme = $container->getParameter('kimai.theme');
+ $theme = $container->getDefinition(ThemeConfiguration::class);
$twig->addMethodCall('addGlobal', ['kimai_context', $theme]);
if ($container->hasDefinition('twig.loader.native_filesystem')) {
diff --git a/src/Form/Model/Configuration.php b/src/Form/Model/Configuration.php
index 71df4b10..646c458a 100644
--- a/src/Form/Model/Configuration.php
+++ b/src/Form/Model/Configuration.php
@@ -33,6 +33,10 @@ final class Configuration
* @var string
*/
private $type;
+ /**
+ * @var array
+ */
+ private $options = [];
/**
* @var bool
*/
@@ -155,4 +159,16 @@ final class Configuration
return $this;
}
+
+ public function getOptions(): array
+ {
+ return $this->options;
+ }
+
+ public function setOptions(array $options): Configuration
+ {
+ $this->options = $options;
+
+ return $this;
+ }
}
diff --git a/src/Form/Model/SystemConfiguration.php b/src/Form/Model/SystemConfiguration.php
index a7367145..e9a2b468 100644
--- a/src/Form/Model/SystemConfiguration.php
+++ b/src/Form/Model/SystemConfiguration.php
@@ -16,6 +16,7 @@ class SystemConfiguration
public const SECTION_FORM_USER = 'form_user';
public const SECTION_THEME = 'theme';
public const SECTION_CALENDAR = 'calendar';
+ public const SECTION_BRANDING = 'branding';
/**
* @var string
diff --git a/src/Form/Type/SystemConfigurationType.php b/src/Form/Type/SystemConfigurationType.php
index fd4ce8dc..1111f35b 100644
--- a/src/Form/Type/SystemConfigurationType.php
+++ b/src/Form/Type/SystemConfigurationType.php
@@ -54,13 +54,15 @@ class SystemConfigurationType extends AbstractType
$type = HiddenType::class;
}
- $event->getForm()->add('value', $type, [
+ $options = [
'label' => 'label.' . ($preference->getLabel() ?? $preference->getName()),
'constraints' => $preference->getConstraints(),
'required' => $required,
'disabled' => !$preference->isEnabled(),
'translation_domain' => $preference->getTranslationDomain(),
- ]);
+ ];
+
+ $event->getForm()->add('value', $type, array_merge($options, $preference->getOptions()));
}
);
$builder->add('name', HiddenType::class);
diff --git a/src/Repository/ConfigurationRepository.php b/src/Repository/ConfigurationRepository.php
index 4884e479..4ec36217 100644
--- a/src/Repository/ConfigurationRepository.php
+++ b/src/Repository/ConfigurationRepository.php
@@ -47,6 +47,11 @@ class ConfigurationRepository extends EntityRepository implements ConfigLoaderIn
$entity = $this->findOneBy(['name' => $configuration->getName()]);
$value = $configuration->getValue();
+ if (null === $value && null !== $entity) {
+ $em->remove($entity);
+ continue;
+ }
+
if (null === $entity) {
$entity = new Configuration();
$entity->setName($configuration->getName());
diff --git a/tests/Controller/SystemConfigurationControllerTest.php b/tests/Controller/SystemConfigurationControllerTest.php
index 67914636..0da9e63a 100644
--- a/tests/Controller/SystemConfigurationControllerTest.php
+++ b/tests/Controller/SystemConfigurationControllerTest.php
@@ -53,6 +53,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
['form[name=system_configuration_form_form_user]', $this->createUrl('/admin/system-config/update/form_user')],
['form[name=system_configuration_form_theme]', $this->createUrl('/admin/system-config/update/theme')],
['form[name=system_configuration_form_calendar]', $this->createUrl('/admin/system-config/update/calendar')],
+ ['form[name=system_configuration_form_branding]', $this->createUrl('/admin/system-config/update/branding')],
];
}
diff --git a/translations/system-configuration.de.xliff b/translations/system-configuration.de.xliff
index 8836a3f2..ff713ec2 100644
--- a/translations/system-configuration.de.xliff
+++ b/translations/system-configuration.de.xliff
@@ -98,6 +98,26 @@
label.calendar.visibleHours.end
Ende des sichtbaren Zeitbereichs
+
+ branding
+ Markendarstellung
+
+
+ label.theme.branding.logo
+ Logo (Bild URL, ersetzt das Unternehmen im Anmeldebildschirm)
+
+
+ label.theme.branding.company
+ Unternehmen
+
+
+ label.theme.branding.mini
+ Mini Logo (zugeklappte Seitenleiste)
+
+
+ label.theme.branding.title
+ Browser Titel
+