├── .gitignore
├── Exception
├── SettingsException.php
├── UnknownSettingException.php
├── UnknownSerializerException.php
└── WrongScopeException.php
├── .editorconfig
├── phpstan.neon.dist
├── Entity
├── SettingsOwnerInterface.php
└── Setting.php
├── Resources
├── config
│ ├── routing.yml
│ └── services.yml
├── translations
│ ├── settings.en.yml
│ ├── settings.es.yml
│ ├── settings.it.yml
│ ├── settings.ru.yml
│ ├── settings.uk.yml
│ ├── settings.sv.yml
│ ├── settings.nl.yml
│ ├── settings.de.yml
│ └── settings.fr.yml
├── views
│ ├── Settings
│ │ └── manage.html.twig
│ └── layout.html.twig
└── doc
│ ├── faq.md
│ ├── customization.md
│ ├── i18n.md
│ ├── scopes.md
│ ├── installation.md
│ ├── advanced-configuration.md
│ └── general-usage.md
├── Tests
├── Resources
│ └── app
│ │ └── config
│ │ └── config.yml
├── Serializer
│ └── CustomSerializer.php
├── ServiceTest.php
├── SerializerTest.php
├── Functional
│ └── ServiceInstantiationTest.php
├── AbstractTest.php
├── CachedSettingsManagerTest.php
└── SettingsManagerTest.php
├── DmishhSettingsBundle.php
├── Serializer
├── SerializerInterface.php
├── PhpSerializer.php
├── JsonSerializer.php
└── SerializerFactory.php
├── .php_cs
├── Makefile
├── Twig
└── SettingsExtension.php
├── LICENSE
├── phpunit.xml.dist
├── Manager
├── SettingsManagerInterface.php
├── CachedSettingsManager.php
└── SettingsManager.php
├── UPGRADE.md
├── CHANGELOG.md
├── composer.json
├── .github
└── workflows
│ └── main.yml
├── README.md
├── DependencyInjection
├── DmishhSettingsExtension.php
└── Configuration.php
├── Form
└── Type
│ └── SettingsType.php
├── Controller
└── SettingsController.php
└── phpstan-baseline.neon
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | composer.lock
3 | phpunit.xml
4 | .php_cs.cache
5 | .phpunit.result.cache
6 |
--------------------------------------------------------------------------------
/Exception/SettingsException.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 | class DmishhSettingsBundle extends Bundle
13 | {
14 | }
15 |
--------------------------------------------------------------------------------
/Exception/UnknownSettingException.php:
--------------------------------------------------------------------------------
1 | setRules(array(
5 | '@Symfony' => true,
6 | '@Symfony:risky' => true,
7 | 'no_superfluous_phpdoc_tags' => true,
8 | ))
9 | ->setRiskyAllowed(true)
10 | ->setFinder(
11 | PhpCsFixer\Finder::create()
12 | ->in(__DIR__)
13 | ->exclude('vendor')
14 | ->name('*.php')
15 | )
16 | ;
17 |
--------------------------------------------------------------------------------
/Resources/translations/settings.nl.yml:
--------------------------------------------------------------------------------
1 | settings: Instellingen
2 | save: Opslaan
3 | settings_updated: Instellingen zijn succesvolg opgeslagen!
4 | not_allowed_to_edit_global_settings: Je bent niet toegestaan om globale instellingen te wijzigen.
5 | must_be_logged_in_to_edit_own_settings: Je dient ingelogd te zijn om je instellingen te wijzigen.
6 | not_allowed_to_edit_own_settings: Je bent niet toegestaan om je instellingen te wijzigen.
7 |
--------------------------------------------------------------------------------
/Resources/views/Settings/manage.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'DmishhSettingsBundle::layout.html.twig' %}
2 |
3 | {% block content %}
4 |
{% trans from 'settings' %}settings{% endtrans %}
5 |
6 | {{ form_start(settings_form) }}
7 | {{ form_widget(settings_form) }}
8 |
9 | {{ form_end(settings_form) }}
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/Resources/translations/settings.de.yml:
--------------------------------------------------------------------------------
1 | settings: Einstellungen
2 | save: Speichern
3 | settings_updated: Einstellungen wurden erfolgreich aktualisiert!
4 | not_allowed_to_edit_global_settings: Sie dürfen nicht bearbeiten globale einstellungen
5 | must_be_logged_in_to_edit_own_settings: Sie müssen eingeloggt sein, um ihre einstellungen zu bearbeiten
6 | not_allowed_to_edit_own_settings: Sie sind nicht zulässig, um ihre einstellungen zu bearbeiten
7 |
--------------------------------------------------------------------------------
/Resources/translations/settings.fr.yml:
--------------------------------------------------------------------------------
1 | settings: Les paramètres de
2 | save: Enregistrer
3 | settings_updated: Les paramètres ont été correctement mis à jour!
4 | not_allowed_to_edit_global_settings: Vous n'êtes pas autorisé à modifier des paramètres globaux
5 | must_be_logged_in_to_edit_own_settings: Vous devez être connecté afin de modifier vos paramètres
6 | not_allowed_to_edit_own_settings: Vous n'êtes pas autorisé à modifier vos paramètres
7 |
--------------------------------------------------------------------------------
/Tests/Serializer/CustomSerializer.php:
--------------------------------------------------------------------------------
1 | phpstan-baseline.neon
9 |
10 | test:
11 | composer update --prefer-dist --no-interaction ${COMPOSER_PARAMS}
12 | vendor/bin/phpunit
13 |
14 | test-lowest:
15 | COMPOSER_PARAMS='--prefer-lowest' $(MAKE) test
16 |
17 | codestyle:
18 | docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) php-cs-fixer fix
19 |
--------------------------------------------------------------------------------
/Resources/views/layout.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {% block title %}{% endblock %}
6 | {% block stylesheets %}{% endblock %}
7 |
8 |
9 | {% for flashMessage in app.session.flashbag.get('error') %}
10 | {{ flashMessage }}
11 | {% endfor %}
12 | {% for flashMessage in app.session.flashbag.get('success') %}
13 | {{ flashMessage }}
14 | {% endfor %}
15 | {% block content %}{% endblock %}
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Resources/doc/faq.md:
--------------------------------------------------------------------------------
1 | ## SettingsBundle
2 |
3 | * [Installation](installation.md)
4 | * [General usage](general-usage.md)
5 | * [Scopes](scopes.md)
6 | * [Advanced configuration](advanced-configuration.md)
7 | * [I18n](i18n.md)
8 | * [Customization](customization.md)
9 | * **FAQ**
10 |
11 | ## FAQ
12 |
13 | **? How to add optional setting?**
14 |
15 | Add `required: false` to setting validation options
16 |
17 | ```yaml
18 | dmishh_settings:
19 | settings:
20 | my_first_setting:
21 | options:
22 | required: false
23 | ```
24 |
25 | **? How to add an `array` setting?**
26 |
27 | TODO
28 |
29 | **? How to inject `settings_manager` into form?**
30 |
31 | TODO
32 |
--------------------------------------------------------------------------------
/Twig/SettingsExtension.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class SettingsExtension extends AbstractExtension
15 | {
16 | private $settingsManager;
17 |
18 | public function __construct(SettingsManagerInterface $settingsManager)
19 | {
20 | $this->settingsManager = $settingsManager;
21 | }
22 |
23 | public function getFunctions()
24 | {
25 | return [
26 | new TwigFunction('get_setting', [$this->settingsManager, 'get']),
27 | new TwigFunction('get_all_settings', [$this->settingsManager, 'all']),
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Resources/doc/customization.md:
--------------------------------------------------------------------------------
1 | ## SettingsBundle
2 |
3 | * [Installation](installation.md)
4 | * [General usage](general-usage.md)
5 | * [Scopes](scopes.md)
6 | * [Advanced configuration](advanced-configuration.md)
7 | * [I18n](i18n.md)
8 | * **Customization**
9 | * [FAQ](faq.md)
10 |
11 | ## Customization
12 |
13 | #### Overriding layout via bundle inheritance
14 |
15 | Make use of Symfony Bundle Inheritance to expose the bundle via your own template. See the Symfony Cookbook for an
16 | article about how to override parts of a bundle.
17 |
18 | * [How to Use Bundle Inheritance to Override Parts of a Bundle »](http://symfony.com/doc/current/cookbook/bundles/inheritance.html#overriding-resources-templates-routing-etc)
19 |
20 | #### Overriding template
21 |
22 | The template the bundle controller will use can be overwritten by changing the configuration parameter.
23 |
24 | ```yaml
25 | dmishh_settings:
26 | template: DmishhSettingsBundle:Settings:manage.html.twig # change to your own
27 | ```
28 |
29 |
30 | #### Overriding controller
31 |
32 | TODO
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | © 2013 Dmitriy Scherbina
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
15 | ./Tests
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | ./
27 |
28 | ./Resources
29 | ./Tests
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Serializer/SerializerFactory.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class ServiceTest extends AbstractExtensionTestCase
15 | {
16 | protected function getContainerExtensions(): array
17 | {
18 | return [
19 | new DmishhSettingsExtension(),
20 | ];
21 | }
22 |
23 | public function testAlias()
24 | {
25 | $this->load();
26 | $this->assertContainerBuilderHasAlias(SettingsManagerInterface::class, SettingsManager::class);
27 | }
28 |
29 | /**
30 | * If we provide a cache_service we should use the CachedSettingsManager as default.
31 | */
32 | public function testCacheServiceAlias()
33 | {
34 | $this->load(['cache_service' => 'cache']);
35 | $this->assertContainerBuilderHasAlias(SettingsManagerInterface::class, CachedSettingsManager::class);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Resources/config/services.yml:
--------------------------------------------------------------------------------
1 | services:
2 | Dmishh\SettingsBundle\Manager\SettingsManagerInterface: '@Dmishh\SettingsBundle\Manager\SettingsManager'
3 |
4 | Dmishh\SettingsBundle\Manager\SettingsManager:
5 | arguments: [ '@doctrine.orm.entity_manager', '@Dmishh\SettingsBundle\Serializer\SerializerInterface', ~ ]
6 |
7 | Dmishh\SettingsBundle\Manager\CachedSettingsManager:
8 | arguments: [ '@Dmishh\SettingsBundle\Manager\SettingsManager', ~, ~ ]
9 |
10 | Dmishh\SettingsBundle\Serializer\SerializerInterface:
11 | class: Dmishh\SettingsBundle\Serializer\PhpSerializer
12 | factory: Dmishh\SettingsBundle\Serializer\SerializerFactory::create
13 | arguments: ['%settings_manager.serialization%']
14 |
15 | Dmishh\SettingsBundle\Form\Type\SettingsType:
16 | arguments: [ ~ ]
17 | tags:
18 | - { name: form.type }
19 |
20 | Dmishh\SettingsBundle\Twig\SettingsExtension:
21 | arguments: [ '@Dmishh\SettingsBundle\Manager\SettingsManagerInterface' ]
22 | tags:
23 | - { name: twig.extension }
24 |
25 | Dmishh\SettingsBundle\Controller\SettingsController:
26 | arguments:
27 | - '@translator'
28 | - '@Dmishh\SettingsBundle\Manager\SettingsManagerInterface'
29 | - ~ # template
30 | - ~ # manage own settings
31 | - ~ # security role
32 |
--------------------------------------------------------------------------------
/Resources/doc/i18n.md:
--------------------------------------------------------------------------------
1 | ## SettingsBundle
2 |
3 | * [Installation](installation.md)
4 | * [General usage](general-usage.md)
5 | * [Scopes](scopes.md)
6 | * [Advanced configuration](advanced-configuration.md)
7 | * **I18n**
8 | * [Customization](customization.md)
9 | * [FAQ](faq.md)
10 |
11 | ## I18n
12 |
13 | #### Define custom settings names
14 |
15 | 1. Create _yml_ or _xliff_ file for domain _settings_ (example: _settings.en.yml_) in any of your bundles or directly in _app/Resources_ (note: your bundle must be activated after _DmishhSettingsBundle_ in _AppKernel.php_)
16 | 1. Add your settings translations like in the following example for _yml_ format:
17 |
18 | ```yaml
19 | labels:
20 | my_custom_setting: My Custom Label
21 | profile_update_interval: Profile update interval
22 | ```
23 |
24 | Clear your cache with ```app/console cache:clear```
25 |
26 | #### Provide translations for choice type
27 |
28 | 1. Create, if not yet, _yml_ or _xliff_ file for domain _settings_ (example: _settings.en.yml_) in any of your bundles or directly in _app/Resources_ (note: your bundle must be activated after _DmishhSettingsBundle_ in _AppKernel.php_)
29 | 1. Add your choices translations like in the following example for _yml_ format (add _choice postfix to your setting's name):
30 |
31 | ```yaml
32 | labels:
33 | gender: Gender
34 | gender_choices:
35 | m: Male
36 | f: Female
37 | ```
38 |
39 | Clear your cache with ```app/console cache:clear```
40 |
--------------------------------------------------------------------------------
/UPGRADE.md:
--------------------------------------------------------------------------------
1 | # Upgrade
2 |
3 | ## Upgrade from 1.0.x to 2.0.0
4 |
5 | Your User entity should implement the `Dmishh\SettingsBundle\Entity\SettingsOwnerInterface` interface. In order to maintain
6 | your user setting you need to implement the `getSettingIdentifier` to return the username.
7 |
8 | ``` php
9 | class MyUser implements SettingsOwnerInterface
10 | {
11 | // ..
12 |
13 | public function getSettingIdentifier()
14 | {
15 | return $this->getUsername();
16 | }
17 | }
18 | ```
19 |
20 | You do also need to update your database tables.
21 |
22 | * Via [DoctrineMigrationsBundle](http://symfony.com/doc/current/bundles/DoctrineMigrationsBundle/index.html):**
23 |
24 | ```bash
25 | php app/console doctrine:migrations:diff
26 | php app/console doctrine:migrations:migrate
27 | ```
28 |
29 | * Using Doctrine schema update tool
30 |
31 | ```bash
32 | php app/console doctrine:schema:update --force
33 | ```
34 |
35 | * The following queries should be executed:
36 |
37 | ``` sql
38 | DROP INDEX name_user_name_idx ON dmishh_settings;
39 | ALTER TABLE dmishh_settings CHANGE username ownerId VARCHAR(255) DEFAULT NULL;
40 | CREATE INDEX name_owner_id_idx ON dmishh_settings (name, ownerId);
41 | ```
42 |
43 | ### Namespace changed
44 |
45 | The "\Bundle" part of the namespace has been removed between `2.0.0-beta1` and `2.0.0-beta2`. The use statements
46 | and `AppKernel` bundle declaration should be changed:
47 |
48 | * Old: `Dmishh\Bundle\SettingsBundle`
49 | * New: `Dmishh\SettingsBundle`
50 |
--------------------------------------------------------------------------------
/Tests/SerializerTest.php:
--------------------------------------------------------------------------------
1 | '123', 123, 5.0];
10 |
11 | public function testPhpSerializer()
12 | {
13 | $serializer = SerializerFactory::create('php');
14 | $this->assertEquals(serialize(self::$testData), $serializer->serialize(self::$testData));
15 | $this->assertEquals(self::$testData, $serializer->unserialize($serializer->serialize(self::$testData)));
16 | }
17 |
18 | public function testJsonSerializer()
19 | {
20 | $serializer = SerializerFactory::create('json');
21 | $this->assertEquals(json_encode(self::$testData), $serializer->serialize(self::$testData));
22 | $this->assertEquals(self::$testData, $serializer->unserialize($serializer->serialize(self::$testData)));
23 | }
24 |
25 | public function testCustomSerializer()
26 | {
27 | $serializer = SerializerFactory::create('Dmishh\SettingsBundle\Tests\Serializer\CustomSerializer');
28 | $this->assertEquals(self::$testData, $serializer->unserialize($serializer->serialize(self::$testData)));
29 | }
30 |
31 | public function testUnknownSerializer()
32 | {
33 | $this->expectException('\Dmishh\SettingsBundle\Exception\UnknownSerializerException');
34 | $serializer = SerializerFactory::create('unknown_serializer');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## Changelog
2 |
3 | #### Version 3.0.0-beta3
4 |
5 | * Run tests using Github Actions, and test lowest set of dependencies #121
6 | * Support PHP8.0 #117
7 | * Fix PHPUnit deprecations #120
8 |
9 | #### Version 3.0.0-beta2
10 |
11 | * Documentation and bugfixes
12 |
13 | #### Version 3.0.0-beta1
14 |
15 | * Added support for Symfony 4 & 5
16 | * Added FCQN as service names
17 | * Added PHP 7 type hints
18 | * Dropped support for Symfony < 3.4
19 | * Dropped support for PHP < 7.2
20 |
21 | #### Version 2.0.0-dev
22 |
23 | * Added optional caching
24 | * New interface for your entity. We are no longer using `UserInterface`. Use `SettingsOwnerInterface` instead.
25 | * Changed behavior of `SettingsManager::all`. It will not return global config if the user/local values are missing
26 | * Added possibility to add default value as third parameter on `SettingsManager::get`
27 | * Updated namespace to `Dmishh\SettingsBundle` instead of `Dmishh\Bundle\SettingsBundle`
28 | * Updated the configuration. This break BC but makes sure the configuration is not as "deep". [#31](https://github.com/dmishh/SettingsBundle/issues/31)
29 | * Bump PHP to `^5.5.9` and Symfony to `^2.7|^3.0` [#50](https://github.com/dmishh/SettingsBundle/issues/50)
30 |
31 | #### Version 1.0.2-1.0.7 (9 Mar 2015)
32 | * Minor code improvements and bug fixes
33 | * System messages translations to en, it, es, fr, de, ru, uk, sv languages
34 |
35 | #### Version 1.0.1 (13 May 2014)
36 | * Ability to choose serialization mechanism (php or json)
37 | * Ability to add constraints to validation
38 |
39 | #### Version 1.0.0 (3 Apr 2014)
40 | * First stable version
41 |
--------------------------------------------------------------------------------
/Entity/Setting.php:
--------------------------------------------------------------------------------
1 | id;
46 | }
47 |
48 | public function setName(?string $name)
49 | {
50 | $this->name = $name;
51 | }
52 |
53 | public function getName(): ?string
54 | {
55 | return $this->name;
56 | }
57 |
58 | public function setValue(?string $value): void
59 | {
60 | $this->value = $value;
61 | }
62 |
63 | public function getValue(): ?string
64 | {
65 | return $this->value;
66 | }
67 |
68 | public function getOwnerId(): ?string
69 | {
70 | return $this->ownerId;
71 | }
72 |
73 | public function setOwnerId(?string $ownerId)
74 | {
75 | $this->ownerId = $ownerId;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Tests/Functional/ServiceInstantiationTest.php:
--------------------------------------------------------------------------------
1 | addCompilerPass(new PublicServicePass('|Dmishh.*|'));
25 | }
26 |
27 | public function testInitBundle()
28 | {
29 | $kernel = $this->createKernel();
30 | $kernel->addConfigFile(\dirname(__DIR__).'/Resources/app/config/config.yml');
31 | $kernel->addBundle(DoctrineBundle::class);
32 | $this->bootKernel();
33 | $container = $this->getContainer();
34 |
35 | // Test if you services exists
36 | self::assertTrue($container->has(SerializerInterface::class));
37 | $service = $container->get(SerializerInterface::class);
38 | self::assertInstanceOf(PhpSerializer::class, $service);
39 |
40 | $service = $container->get(SettingsManagerInterface::class);
41 | self::assertInstanceOf(SettingsManager::class, $service);
42 | }
43 |
44 | protected function getBundleClass()
45 | {
46 | return DmishhSettingsBundle::class;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dmishh/settings-bundle",
3 | "description": "Database centric Symfony configuration management. Global and per-user settings supported.",
4 | "keywords": ["symfony", "bundle", "config", "configuration", "settings"],
5 | "homepage": "https://github.com/dmishh/SettingsBundle",
6 | "type": "symfony-bundle",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Dmitriy Scherbina",
11 | "homepage": "http://dmishh.com"
12 | },
13 | {
14 | "name": "Tobias Nyholm",
15 | "homepage": "https://github.com/Nyholm"
16 | },
17 | {
18 | "name": "Richard van Laak",
19 | "homepage": "https://github.com/rvanlaak"
20 | }
21 | ],
22 | "require": {
23 | "php": "^7.2|^8.0",
24 | "psr/cache": "^1.0",
25 | "symfony/framework-bundle": "^3.4 || ^4.3 || ^5.0",
26 | "symfony/form": "^3.4 || ^4.3 || ^5.0",
27 | "doctrine/orm": "^2.6.3|^2.7"
28 | },
29 | "require-dev": {
30 | "phpunit/phpunit": "^8.5",
31 | "mockery/mockery": "^1.3",
32 | "doctrine/doctrine-bundle": "^1.12 || ^2.0",
33 | "polishsymfonycommunity/symfony-mocker-container": "^1.0",
34 | "matthiasnoback/symfony-dependency-injection-test": "^4.1",
35 | "nyholm/symfony-bundle-test": "^1.6",
36 | "symfony/translation": "^4.4 || ^5.0",
37 | "symfony/security-core": "^4.4 || ^5.0",
38 | "twig/twig": "^2.0 || ^3.0"
39 | },
40 | "autoload": {
41 | "psr-4": { "Dmishh\\SettingsBundle\\": "" }
42 | },
43 | "extra": {
44 | "branch-alias": {
45 | "dev-master": "3.0.x-dev"
46 | }
47 | },
48 | "suggest": {
49 | "cache/adapter-bundle": "This bundle will help you to add your PSR-6 cache implementations as Symfony services"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Tests/AbstractTest.php:
--------------------------------------------------------------------------------
1 | em = $this->createEntityManager();
22 | $this->generateSchema();
23 | }
24 |
25 | /**
26 | * {@inheritdoc}
27 | */
28 | protected function tearDown(): void
29 | {
30 | $this->em->close();
31 | }
32 |
33 | protected function createEntityManager()
34 | {
35 | $config = new Configuration();
36 | $config->setProxyDir(sys_get_temp_dir());
37 | $config->setProxyNamespace('EntityProxy');
38 | $config->setAutoGenerateProxyClasses(true);
39 |
40 | AnnotationRegistry::registerFile(
41 | __DIR__.
42 | '/../vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php'
43 | );
44 | $driver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver(
45 | new \Doctrine\Common\Annotations\AnnotationReader(),
46 | [__DIR__.'/../Entity']
47 | );
48 | $config->setMetadataDriverImpl($driver);
49 |
50 | $conn = [
51 | 'driver' => 'pdo_sqlite',
52 | 'memory' => true,
53 | ];
54 |
55 | $em = \Doctrine\ORM\EntityManager::create($conn, $config);
56 |
57 | return $em;
58 | }
59 |
60 | protected function generateSchema()
61 | {
62 | $metadatas = $this->em->getMetadataFactory()->getAllMetadata();
63 |
64 | if (!empty($metadatas)) {
65 | $tool = new \Doctrine\ORM\Tools\SchemaTool($this->em);
66 | $tool->dropSchema($metadatas);
67 | $tool->createSchema($metadatas);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Resources/doc/scopes.md:
--------------------------------------------------------------------------------
1 | ## SettingsBundle
2 |
3 | * [Installation](installation.md)
4 | * [General usage](general-usage.md)
5 | * **Scopes**
6 | * [Advanced configuration](advanced-configuration.md)
7 | * [I18n](i18n.md)
8 | * [Customization](customization.md)
9 | * [FAQ](faq.md)
10 |
11 | ## Understanding scopes
12 |
13 | Bundle provides settings separation into 3 scopes: `ALL`, `GLOBAL` and `USER`.
14 |
15 | * GLOBAL and USER scopes are totally independent.
16 | * ALL scope provides you to inherit global settings when user setting with the same name is not setted.
17 |
18 | Examples must give more clearance:
19 |
20 | ```php
21 | set('all_scope_setting', 'value');
25 | $settingsMaanger->get('all_scope_setting'); // => 'value'
26 | $settingsMaanger->get('all_scope_setting', $this->getUser()); // => 'value'
27 | $settingsMaanger->set('all_scope_setting', 'user_value', $this->getUser());
28 | $settingsMaanger->get('all_scope_setting', $this->getUser()); // => 'user_value'
29 |
30 | // Example #1 with GLOBAL and USER scopes
31 | $settingsMaanger->set('global_scope_setting', 'value');
32 | $settingsMaanger->get('global_scope_setting'); // => 'value'
33 | $settingsMaanger->get('global_scope_setting', $this->getUser()); // => WrongScopeException
34 | $settingsMaanger->set('global_scope_setting', 'value', $this->getUser()); // => WrongScopeException
35 |
36 | // Example #2 with GLOBAL and USER scopes
37 | $settingsMaanger->set('user_scope_setting', 'value', $this->getUser());
38 | $settingsMaanger->get('user_scope_setting', $this->getUser()); // => 'value'
39 | $settingsMaanger->get('user_scope_setting'); // => WrongScopeException
40 | $settingsMaanger->set('user_scope_setting', 'value'); // => WrongScopeException
41 | ```
42 |
43 | #### Configuring scope
44 |
45 | You may configure a scope to each of your settings. You can use ALL (default), GLOBAL or USER scope.
46 |
47 | ```yaml
48 | dmishh_settings:
49 | settings:
50 | my_first_user_setting:
51 | scope: user # all, global
52 | ```
53 |
--------------------------------------------------------------------------------
/Resources/doc/installation.md:
--------------------------------------------------------------------------------
1 | ## SettingsBundle
2 |
3 | * **Installation**
4 | * [General usage](general-usage.md)
5 | * [Scopes](scopes.md)
6 | * [Advanced configuration](advanced-configuration.md)
7 | * [I18n](i18n.md)
8 | * [Customization](customization.md)
9 | * [FAQ](faq.md)
10 |
11 | ## Installation (using Composer)
12 |
13 | * Add the following to your `composer.json` file:
14 |
15 | ```js
16 | // composer.json
17 | {
18 | "require": {
19 | // ...
20 | "dmishh/settings-bundle": "2.0.*@dev"
21 | }
22 | }
23 | ```
24 |
25 | * Update dependencies, run from command line:
26 |
27 | ```bash
28 | php composer.phar update
29 | ```
30 |
31 | * Register the bundle in your ``AppKernel.php`` file:
32 |
33 | ```php
34 | http://YOUR-PROJECT-URL/app_dev.php/settings/global and start managing your settings!
75 |
76 | **Note:** If you're using Symfony 3, please see the instructions in [Advanced configuration](advanced-configuration.md).
77 |
78 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on: [ pull_request ]
4 |
5 | jobs:
6 | static-code-analysis:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v1
10 | - name: Run PHPStan
11 | uses: docker://jakzal/phpqa
12 | with:
13 | args: phpstan analyze
14 | test:
15 | runs-on: ubuntu-latest
16 | strategy:
17 | matrix:
18 | php: [ '7.2', '7.4', '8.0' ]
19 | symfony: [ '4.4.*', '5.3.*' ]
20 | name: Test on Symfony ${{ matrix.symfony }} with PHP ${{ matrix.php }}
21 | steps:
22 | - uses: actions/checkout@v2
23 | - uses: shivammathur/setup-php@v2
24 | with:
25 | php-version: ${{ matrix.php }}
26 | coverage: none # disable xdebug, pcov
27 | - run: composer require symfony/framework-bundle:${{ matrix.symfony }} --no-update
28 | - run: composer require symfony/form:${{ matrix.symfony }} --no-update
29 | - run: composer install
30 | - run: make test
31 | test-lowest:
32 | runs-on: ubuntu-latest
33 | strategy:
34 | matrix:
35 | php: [ '7.2', '7.3' ]
36 | symfony: [ '3.4.*', '4.4.*' ]
37 | name: Test lowest on Symfony ${{ matrix.symfony }} with PHP ${{ matrix.php }}
38 | steps:
39 | - uses: actions/checkout@v2
40 | - uses: shivammathur/setup-php@v2
41 | with:
42 | php-version: ${{ matrix.php }}
43 | coverage: none # disable xdebug, pcov
44 | - run: composer require symfony/framework-bundle:${{ matrix.symfony }} --no-update
45 | - run: composer require symfony/form:${{ matrix.symfony }} --no-update
46 | - run: composer install
47 | - run: make test-lowest
48 | php-cs-fixer:
49 | runs-on: ubuntu-latest
50 | steps:
51 | - uses: actions/checkout@v1
52 | - name: Run PHP-CS-Fixer
53 | uses: docker://jakzal/phpqa
54 | with:
55 | args: php-cs-fixer fix --dry-run
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SettingsBundle
2 | ==============
3 |
4 | Bundle for storing configuration with Symfony in database using Doctrine ORM.
5 |
6 | 👀 This bundle was previously known as `dmissh/settings-bundle`, and the Packagist installation instruction will stay as is.
7 |
8 | ## Features
9 |
10 | * Easy-to-use (Twig extension, container service)
11 | * Settings scopes per user, global or all
12 | * Settings validation by using the Symfony Form Component
13 | * 2 serialization mechanisms: PHP `serialize()` and JSON (+ you can write your own)
14 | * Settings caching (PSR-6)
15 | * Fast and extensible
16 |
17 | ## Quick usage examples
18 |
19 | Symfony controller:
20 |
21 | ```php
22 | // Global settings
23 | $settingsManager->set('name', 'foo');
24 | $settingsManager->get('name'); // returns 'foo'
25 |
26 | // User settings
27 | $settingsManager->get('name', $user); // returns global 'foo'
28 | $settingsManager->set('name', 'bar', $user);
29 | $settingsManager->get('name', $user); // returns 'bar'
30 | ```
31 |
32 | Twig template:
33 |
34 | ```twig
35 | {# Global setting #}
36 | {{ get_setting('some_setting') }} {# => 'value' #}
37 |
38 | {# User setting #}
39 | {{ get_setting('some_user_setting', app.user) }} {# => 'value' #}
40 | ```
41 |
42 | See the [general usage](/Resources/doc/general-usage.md) documentation for more examples.
43 |
44 | ## Documentation
45 |
46 | * [Installation](/Resources/doc/installation.md)
47 | * [General usage](/Resources/doc/general-usage.md)
48 | * [Scopes](/Resources/doc/scopes.md)
49 | * [Advanced configuration](/Resources/doc/advanced-configuration.md)
50 | * [I18n](/Resources/doc/i18n.md)
51 | * [Customization](/Resources/doc/customization.md)
52 | * [FAQ](/Resources/doc/faq.md)
53 |
54 | ## Changelog, Roadmap and contribution
55 |
56 | Please, do not hesitate to [report bugs](https://github.com/dmishh/SettingsBundle/issues) or send
57 | [pull requests](https://github.com/dmishh/SettingsBundle/pulls). It will help to motivate me to support
58 | library better than anything else :)
59 |
60 | See [CHANGELOG.md](CHANGELOG.md) for all major changes.
61 |
62 | ### Upgrade from 1.0.*
63 |
64 | Make sure to read the [UPGRADE.md](UPGRADE.md) to successfully migrate your application.
65 |
66 | ## License
67 |
68 | The MIT License. For the full text of license, please, see [LICENSE](/LICENSE)
69 |
--------------------------------------------------------------------------------
/DependencyInjection/DmishhSettingsExtension.php:
--------------------------------------------------------------------------------
1 | processConfiguration($configuration, $configs);
30 |
31 | $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
32 | $loader->load('services.yml');
33 |
34 | $container->setParameter('settings_manager.serialization', $config['serialization']);
35 |
36 | // Configure the correct storage
37 | if (null === $config['cache_service']) {
38 | $container->removeDefinition(CachedSettingsManager::class);
39 | } else {
40 | $container->getDefinition(CachedSettingsManager::class)
41 | ->replaceArgument(1, new Reference($config['cache_service']))
42 | ->replaceArgument(2, $config['cache_lifetime']);
43 |
44 | // set an alias to make sure the cached settings manager is the default
45 | $container->setAlias(SettingsManagerInterface::class, CachedSettingsManager::class);
46 | }
47 |
48 | $container->getDefinition(SettingsManager::class)
49 | ->replaceArgument(2, $config['settings']);
50 |
51 | $container->getDefinition(SettingsType::class)
52 | ->replaceArgument(0, $config['settings']);
53 |
54 | $container->getDefinition(SettingsController::class)
55 | ->replaceArgument(2, $config['template'])
56 | ->replaceArgument(3, $config['security']['users_can_manage_own_settings'])
57 | ->replaceArgument(4, $config['security']['manage_global_settings_role']);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Form/Type/SettingsType.php:
--------------------------------------------------------------------------------
1 |
14 | * @author Artem Zhuravlov
15 | */
16 | class SettingsType extends AbstractType
17 | {
18 | protected $settingsConfiguration;
19 |
20 | public function __construct(array $settingsConfiguration)
21 | {
22 | $this->settingsConfiguration = $settingsConfiguration;
23 | }
24 |
25 | /**
26 | * {@inheritdoc}
27 | */
28 | public function buildForm(FormBuilderInterface $builder, array $options)
29 | {
30 | foreach ($this->settingsConfiguration as $name => $configuration) {
31 | // If setting's value exists in data and setting isn't disabled
32 | if (\array_key_exists($name, $options['data']) && !\in_array($name, $options['disabled_settings'])) {
33 | $fieldType = $configuration['type'];
34 | $fieldOptions = $configuration['options'];
35 | $fieldOptions['constraints'] = $configuration['constraints'];
36 |
37 | // Validator constraints
38 | if (!empty($fieldOptions['constraints']) && \is_array($fieldOptions['constraints'])) {
39 | $constraints = [];
40 | foreach ($fieldOptions['constraints'] as $class => $constraintOptions) {
41 | if (class_exists($class)) {
42 | $constraints[] = new $class($constraintOptions);
43 | } else {
44 | throw new SettingsException(sprintf('Constraint class "%s" not found', $class));
45 | }
46 | }
47 |
48 | $fieldOptions['constraints'] = $constraints;
49 | }
50 |
51 | // Label I18n
52 | $fieldOptions['label'] = 'labels.'.$name;
53 | $fieldOptions['translation_domain'] = 'settings';
54 |
55 | // Choices I18n
56 | if (!empty($fieldOptions['choices'])) {
57 | $fieldOptions['choices'] = array_flip(
58 | array_map(
59 | function ($label) use ($fieldOptions) {
60 | return $fieldOptions['label'].'_choices.'.$label;
61 | },
62 | array_combine($fieldOptions['choices'], $fieldOptions['choices'])
63 | )
64 | );
65 | }
66 | $builder->add($name, $fieldType, $fieldOptions);
67 | }
68 | }
69 | }
70 |
71 | public function configureOptions(OptionsResolver $resolver)
72 | {
73 | $resolver->setDefaults(
74 | [
75 | 'disabled_settings' => [],
76 | ]
77 | );
78 | }
79 |
80 | public function getBlockPrefix()
81 | {
82 | return 'settings_management';
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Resources/doc/advanced-configuration.md:
--------------------------------------------------------------------------------
1 | ## SettingsBundle
2 |
3 | * [Installation](installation.md)
4 | * [General usage](general-usage.md)
5 | * [Scopes](scopes.md)
6 | * **Advanced configuration**
7 | * [I18n](i18n.md)
8 | * [Customization](customization.md)
9 | * [FAQ](faq.md)
10 |
11 | ## Advanced configuration
12 |
13 | Full list of options:
14 |
15 | ```yaml
16 | dmishh_settings:
17 | template: DmishhSettingsBundle:Settings:manage.html.twig
18 | cache_service: null
19 | cache_lifetime: 3600
20 | security:
21 | manage_global_settings_role: ROLE_USER
22 | users_can_manage_own_settings: true
23 | serialization: php # database serialization mechanism (php|json)
24 | settings:
25 | my_first_setting:
26 | scope: all # global or user
27 | type: number # any Symfony form type, or FQCN for Symfony >=3.0
28 | options: # options passed to form
29 | required: false
30 | constraints:
31 | Symfony\Component\Validator\Constraints\Range:
32 | min: 1
33 | max: 65535
34 | ```
35 |
36 | **Note:** In Symfony 3, use the fully qualified class name instead of the form type name.
37 |
38 |
39 | #### Settings validation
40 |
41 | Settings validation uses [Symfony Forms Component](http://symfony.com/doc/current/book/forms.html#built-in-field-types).
42 | You just specify, for example, type *[text](http://symfony.com/doc/current/reference/forms/types/text.html)* and use it's options like *max_length*, etc.
43 | Also you can use [built-in](http://symfony.com/doc/current/reference/constraints.html) or [custom constraints](http://symfony.com/doc/current/cookbook/validation/custom_constraint.html).
44 |
45 | ```yaml
46 | dmishh_settings:
47 | settings:
48 | my_first_setting:
49 | type: text
50 | options:
51 | max_length: 15
52 | constraints:
53 | Symfony\Component\Validator\Constraints\Regex:
54 | pattern: "/^\d+$/"
55 | ```
56 |
57 | __Note:__ [validation](#validation) is provided only at the form level.
58 |
59 | #### Security
60 |
61 | To protect settings modification bundle uses Symfony Security Component.
62 | You can limit global settings modification with ```manage_global_settings_role``` and grant access to authenticated users to modify their settings.
63 |
64 | ```yaml
65 | dmishh_settings:
66 | security:
67 | manage_global_settings_role: ROLE_USER
68 | users_can_manage_own_settings: true
69 | ```
70 |
71 | #### Caching
72 |
73 | If you want to cache your settings you may provide a cache service that implements `Psr\Cache\CacheItemPoolInterface`.
74 | Every time you fetch a setting from the database we will cache it for `cache_lifetime` seconds. If you edit the
75 | setting we will automatically invalidate the cache.
76 |
77 | ```yaml
78 | dmishh_settings:
79 | cache_service: cache.provider.my_redis
80 | cache_lifetime: 3600
81 |
82 | # Using cache/adapter-bundle
83 | cache_adapter:
84 | providers:
85 | my_redis:
86 | factory: 'cache.factory.redis'
87 | ```
88 |
89 | Read more about how you configure the cache adapter bundle on [www.php-cache.com](http://www.php-cache.com).
90 |
91 |
--------------------------------------------------------------------------------
/Resources/doc/general-usage.md:
--------------------------------------------------------------------------------
1 | ## SettingsBundle
2 |
3 | * [Installation](installation.md)
4 | * **General usage**
5 | * [Scopes](scopes.md)
6 | * [Advanced configuration](advanced-configuration.md)
7 | * [I18n](i18n.md)
8 | * [Customization](customization.md)
9 | * [FAQ](faq.md)
10 |
11 | ## General usage
12 |
13 | * In controllers:
14 |
15 | ```php
16 | set('my_first_setting', 'value');
22 |
23 | // Get setting value by its name
24 | $settingsManager->get('my_first_setting'); // => 'value'
25 |
26 | // Get all settings
27 | $settingsManager->all(); // => array('my_first_setting' => 'value')
28 |
29 | // Set settings' values from associative name-value array
30 | $settingsManager->setMany(array('my_first_setting' => 'new_value'));
31 | $this->get('settings_manager')->get('my_first_setting'); // => 'new_value'$settingsManager
32 |
33 | ```
34 |
35 | ```php
36 | id;
47 | // }
48 | // }
49 |
50 | // These are same examples as above with only difference that they are for current user
51 | $settingsManager->set('my_first_setting', 'user_value', $this->getUser());
52 | $settingsManager->get('my_first_setting', $this->getUser()); // => 'user_value'
53 | $settingsManager->all($this->getUser()); // array('my_first_setting' => 'user_value')
54 | $settingsManager->setMany(array('my_first_setting' => 'new_user_value'), $this->getUser());
55 | $settingsManager->get('my_first_setting', $this->getUser()); // => 'new_user_value'
56 |
57 |
58 | // PER ENTITY SETTINGS
59 |
60 | // This is the most interesting part. You can have settings for any entity.
61 | // Just make sure you have unique values for getSettingIdentifier()
62 |
63 | // class Company implements SettingsOwnerInterface {
64 | // public function getSettingIdentifier() {
65 | // return 'company_' . $this->id;
66 | // }
67 | // }
68 |
69 | $myCompany = new Company();
70 | $settingsManager->set('delivery_frequency_setting', 'daily', $myCompany);
71 | $settingsManager->get('delivery_frequency_setting', $this->getUser()); // => 'daily'
72 | ```
73 |
74 | * In services: you must inject @settings_manager or the whole @service_container into your service and use it in the same way as in controllers (like in the example above)
75 |
76 | * In Twig templates:
77 |
78 | ```twig
79 | {# Global setting #}
80 | {{ get_setting('some_setting') }} {# => 'value' #}
81 |
82 | {# User setting #}
83 | {{ get_setting('some_user_setting', app.user) }} {# => 'value' #}
84 |
85 | {# Getting all global settings #}
86 | {% for setting in get_all_settings() %}
87 | {{ setting }} {# => 'value', ... #}
88 | {% endfor %}
89 | ```
90 |
--------------------------------------------------------------------------------
/Controller/SettingsController.php:
--------------------------------------------------------------------------------
1 | translator = $translator;
49 | $this->settingsManager = $settingsManager;
50 | $this->template = $template;
51 | $this->securityManageOwnSettings = $securityManageOwnSettings;
52 | $this->securityRole = $securityRole;
53 | }
54 |
55 | /**
56 | * @throws AccessDeniedException
57 | */
58 | public function manageGlobalAction(Request $request): Response
59 | {
60 | if (null !== $this->securityRole && !$this->get('security.authorization_checker')->isGranted($this->securityRole)) {
61 | throw new AccessDeniedException($this->translator->trans('not_allowed_to_edit_global_settings', [], 'settings'));
62 | }
63 |
64 | return $this->manage($request);
65 | }
66 |
67 | /**
68 | * @throws AccessDeniedException
69 | */
70 | public function manageOwnAction(Request $request): Response
71 | {
72 | if (null === $this->get('security.token_storage')->getToken()) {
73 | throw new AccessDeniedException($this->translator->trans('must_be_logged_in_to_edit_own_settings', [], 'settings'));
74 | }
75 |
76 | if (!$this->securityManageOwnSettings) {
77 | throw new AccessDeniedException($this->translator->trans('not_allowed_to_edit_own_settings', [], 'settings'));
78 | }
79 |
80 | $user = $this->get('security.token_storage')->getToken()->getUser();
81 | if (!$user instanceof SettingsOwnerInterface) {
82 | //For this to work the User entity must implement SettingsOwnerInterface
83 | throw new AccessDeniedException();
84 | }
85 |
86 | return $this->manage($request, $user);
87 | }
88 |
89 | protected function manage(Request $request, ?SettingsOwnerInterface $owner = null): Response
90 | {
91 | $form = $this->createForm(SettingsType::class, $this->settingsManager->all($owner));
92 | $form->handleRequest($request);
93 |
94 | if ($form->isSubmitted() && $form->isValid()) {
95 | $this->settingsManager->setMany($form->getData(), $owner);
96 | $this->addFlash('success', $this->translator->trans('settings_updated', [], 'settings'));
97 |
98 | return $this->redirect($request->getUri());
99 | }
100 |
101 | return $this->render($this->template, [
102 | 'settings_form' => $form->createView(),
103 | ]);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/DependencyInjection/Configuration.php:
--------------------------------------------------------------------------------
1 | root('dmishh_settings');
22 | } else {
23 | $rootNode = $treeBuilder->getRootNode();
24 | }
25 |
26 | $scopes = [
27 | SettingsManagerInterface::SCOPE_ALL,
28 | SettingsManagerInterface::SCOPE_GLOBAL,
29 | SettingsManagerInterface::SCOPE_USER,
30 | ];
31 |
32 | $rootNode
33 | ->children()
34 | ->scalarNode('template')
35 | ->defaultValue('DmishhSettingsBundle:Settings:manage.html.twig')
36 | ->end()
37 | ->scalarNode('cache_service')->defaultNull()->info('A service implementing Psr\Cache\CacheItemPoolInterface')->end()
38 | ->integerNode('cache_lifetime')->defaultValue(3600)->end()
39 | ->arrayNode('security')
40 | ->addDefaultsIfNotSet()
41 | ->children()
42 | ->scalarNode('manage_global_settings_role')->defaultValue(null)->end()
43 | ->booleanNode('users_can_manage_own_settings')->defaultValue(true)->end()
44 | ->end()
45 | ->end()
46 | ->enumNode('serialization')
47 | ->defaultValue('php')
48 | ->values(['php', 'json'])
49 | ->end()
50 | ->arrayNode('settings')
51 | ->prototype('array')
52 | ->addDefaultsIfNotSet()
53 | ->children()
54 | ->scalarNode('scope')
55 | ->defaultValue('all')
56 | ->validate()
57 | ->ifNotInArray($scopes)
58 | ->thenInvalid('Invalid scope %s. Valid scopes are: '.implode(', ', array_map(function ($s) { return '"'.$s.'"'; }, $scopes)).'.')
59 | ->end()
60 | ->end()
61 | ->scalarNode('type')->defaultValue(TextType::class)->end()
62 |
63 | ->variableNode('options')
64 | ->info('The options given to the form builder')
65 | ->defaultValue([])
66 | ->validate()
67 | ->always(function ($v) {
68 | if (!\is_array($v)) {
69 | throw new InvalidTypeException();
70 | }
71 |
72 | return $v;
73 | })
74 | ->end()
75 | ->end()
76 | ->variableNode('constraints')
77 | ->info('The constraints on this option. Example, use constraits found in Symfony\Component\Validator\Constraints')
78 | ->defaultValue([])
79 | ->validate()
80 | ->always(function ($v) {
81 | if (!\is_array($v)) {
82 | throw new InvalidTypeException();
83 | }
84 |
85 | return $v;
86 | })
87 | ->end()
88 | ->end()
89 | ->end()
90 | ->end()
91 | ->end()
92 | ->end();
93 |
94 | return $treeBuilder;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/Manager/CachedSettingsManager.php:
--------------------------------------------------------------------------------
1 | settingsManager = $settingsManager;
33 | $this->storage = $storage;
34 | $this->cacheLifeTime = $cacheLifeTime;
35 | }
36 |
37 | /**
38 | * {@inheritdoc}
39 | */
40 | public function get(string $name, ?SettingsOwnerInterface $owner = null, $default = null)
41 | {
42 | if (null !== $cached = $this->fetchFromCache($name, $owner)) {
43 | return $cached;
44 | }
45 |
46 | $value = $this->settingsManager->get($name, $owner, $default);
47 | $this->storeInCache($name, $value, $owner);
48 |
49 | return $value;
50 | }
51 |
52 | /**
53 | * {@inheritdoc}
54 | */
55 | public function all(?SettingsOwnerInterface $owner = null): array
56 | {
57 | if (null !== $cached = $this->fetchFromCache(null, $owner)) {
58 | return $cached;
59 | }
60 |
61 | $value = $this->settingsManager->all($owner);
62 | $this->storeInCache(null, $value, $owner);
63 |
64 | return $value;
65 | }
66 |
67 | /**
68 | * {@inheritdoc}
69 | */
70 | public function set(string $name, $value, ?SettingsOwnerInterface $owner = null): void
71 | {
72 | $this->invalidateCache($name, $owner);
73 | $this->invalidateCache(null, $owner);
74 |
75 | $this->settingsManager->set($name, $value, $owner);
76 | }
77 |
78 | /**
79 | * {@inheritdoc}
80 | */
81 | public function setMany(array $settings, ?SettingsOwnerInterface $owner = null): void
82 | {
83 | foreach ($settings as $key => $value) {
84 | $this->invalidateCache($key, $owner);
85 | }
86 | $this->invalidateCache(null, $owner);
87 |
88 | $this->settingsManager->setMany($settings, $owner);
89 | }
90 |
91 | /**
92 | * {@inheritdoc}
93 | */
94 | public function clear(string $name, ?SettingsOwnerInterface $owner = null): void
95 | {
96 | $this->invalidateCache($name, $owner);
97 | $this->invalidateCache(null, $owner);
98 |
99 | $this->settingsManager->clear($name, $owner);
100 | }
101 |
102 | /**
103 | * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise
104 | */
105 | protected function invalidateCache(?string $name, ?SettingsOwnerInterface $owner = null): bool
106 | {
107 | return $this->storage->deleteItem($this->getCacheKey($name, $owner));
108 | }
109 |
110 | /**
111 | * Get from cache.
112 | *
113 | * @return mixed|null if nothing was found in cache
114 | */
115 | protected function fetchFromCache(?string $name, ?SettingsOwnerInterface $owner = null)
116 | {
117 | $cacheKey = $this->getCacheKey($name, $owner);
118 |
119 | return $this->storage->getItem($cacheKey)->get();
120 | }
121 |
122 | /**
123 | * Store in cache.
124 | *
125 | * @param SettingsOwnerInterface $owner
126 | *
127 | * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise
128 | */
129 | protected function storeInCache(?string $name, $value, ?SettingsOwnerInterface $owner = null): bool
130 | {
131 | $item = $this->storage->getItem($this->getCacheKey($name, $owner))
132 | ->set($value)
133 | ->expiresAfter($this->cacheLifeTime);
134 |
135 | return $this->storage->save($item);
136 | }
137 |
138 | /**
139 | * @param SettingsOwnerInterface $owner
140 | */
141 | protected function getCacheKey(?string $key, ?SettingsOwnerInterface $owner = null): string
142 | {
143 | return sprintf(self::PREFIX, $owner ? $owner->getSettingIdentifier() : '', $key);
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Tests/CachedSettingsManagerTest.php:
--------------------------------------------------------------------------------
1 | createOwner();
15 | $name = 'name';
16 | $value = 'foobar';
17 | $defaultValue = 'default';
18 |
19 | $settingsManager = \Mockery::mock(SettingsManager::class);
20 | $settingsManager->shouldReceive('get')->once()->with($name, $owner, $defaultValue)->andReturn($value);
21 |
22 | $cachedSettingsManager = $this->getMockBuilder(CachedSettingsManager::class)
23 | ->setMethods(['fetchFromCache', 'storeInCache'])
24 | ->setConstructorArgs([$settingsManager, $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(), 4711])
25 | ->getMock();
26 | $cachedSettingsManager->expects($this->once())
27 | ->method('fetchFromCache')
28 | ->with($this->equalTo($name), $this->equalTo($owner))
29 | ->willReturn(null);
30 | $cachedSettingsManager->expects($this->once())
31 | ->method('storeInCache')
32 | ->with($this->equalTo($name), $this->equalTo($value), $this->equalTo($owner))
33 | ->willReturn(false);
34 |
35 | $this->assertEquals($value, $cachedSettingsManager->get($name, $owner, $defaultValue));
36 | }
37 |
38 | public function testGetHit()
39 | {
40 | $owner = $this->createOwner();
41 | $name = 'name';
42 | $value = 'foobar';
43 | $defaultValue = 'default';
44 |
45 | $settingsManager = \Mockery::mock(SettingsManager::class);
46 |
47 | $cachedSettingsManager = $this->getMockBuilder(CachedSettingsManager::class)
48 | ->setMethods(['fetchFromCache', 'storeInCache'])
49 | ->setConstructorArgs([$settingsManager, $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(), 4711])
50 | ->getMock();
51 | $cachedSettingsManager->expects($this->once())
52 | ->method('fetchFromCache')
53 | ->with($this->equalTo($name), $this->equalTo($owner))
54 | ->willReturn($value);
55 |
56 | $this->assertEquals($value, $cachedSettingsManager->get($name, $owner, $defaultValue));
57 | }
58 |
59 | public function testAll()
60 | {
61 | $owner = $this->createOwner();
62 | $value = ['foo' => 'bar'];
63 |
64 | $settingsManager = \Mockery::mock(SettingsManager::class);
65 | $settingsManager->shouldReceive('all')->once()->with($owner)->andReturn($value);
66 |
67 | $cachedSettingsManager = $this->getMockBuilder(CachedSettingsManager::class)
68 | ->setMethods(['fetchFromCache', 'storeInCache'])
69 | ->setConstructorArgs([$settingsManager, $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(), 4711])
70 | ->getMock();
71 | $cachedSettingsManager->expects($this->once())
72 | ->method('fetchFromCache')
73 | ->with($this->equalTo(null), $this->equalTo($owner))
74 | ->willReturn(null);
75 | $cachedSettingsManager->expects($this->once())
76 | ->method('storeInCache')
77 | ->with($this->equalTo(null), $this->equalTo($value), $this->equalTo($owner))
78 | ->willReturn(false);
79 |
80 | $this->assertEquals($value, $cachedSettingsManager->all($owner));
81 | }
82 |
83 | public function testAllHit()
84 | {
85 | $owner = $this->createOwner();
86 | $value = ['foo' => 'bar'];
87 |
88 | $settingsManager = \Mockery::mock(SettingsManager::class);
89 |
90 | $cachedSettingsManager = $this->getMockBuilder(CachedSettingsManager::class)
91 | ->setMethods(['fetchFromCache', 'storeInCache'])
92 | ->setConstructorArgs([$settingsManager, $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(), 4711])
93 | ->getMock();
94 | $cachedSettingsManager->expects($this->once())
95 | ->method('fetchFromCache')
96 | ->with($this->equalTo(null), $this->equalTo($owner))
97 | ->willReturn($value);
98 |
99 | $this->assertEquals($value, $cachedSettingsManager->all($owner));
100 | }
101 |
102 | public function testSet()
103 | {
104 | $owner = $this->createOwner();
105 | $name = 'name';
106 | $value = 'foobar';
107 |
108 | $settingsManager = \Mockery::mock(SettingsManager::class);
109 | $settingsManager->shouldReceive('set')->once()->with($name, $value, $owner);
110 |
111 | $cachedSettingsManager = $this->getMockBuilder(CachedSettingsManager::class)
112 | ->setMethods(['invalidateCache'])
113 | ->setConstructorArgs([$settingsManager, $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(), 4711])
114 | ->getMock();
115 |
116 | // Clear the cache
117 | $cachedSettingsManager->expects($this->at(0))
118 | ->method('invalidateCache')
119 | ->with($this->equalTo($name), $this->equalTo($owner))
120 | ->willReturn(true);
121 |
122 | // Clear all cache for this owner
123 | $cachedSettingsManager->expects($this->at(1))
124 | ->method('invalidateCache')
125 | ->with($this->equalTo(null), $this->equalTo($owner))
126 | ->willReturn(true);
127 |
128 | $cachedSettingsManager->set($name, $value, $owner);
129 | }
130 |
131 | public function testSetMany()
132 | {
133 | $owner = $this->createOwner();
134 | $settings = ['name0' => 'value0', 'name1' => 'value1', 'name2' => 'value2'];
135 |
136 | $settingsManager = \Mockery::mock(SettingsManager::class);
137 | $settingsManager->shouldReceive('setMany')->once()->with($settings, $owner);
138 |
139 | $cachedSettingsManager = $this->getMockBuilder(CachedSettingsManager::class)
140 | ->setMethods(['invalidateCache'])
141 | ->setConstructorArgs([$settingsManager, $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(), 4711])
142 | ->getMock();
143 | $cachedSettingsManager->expects($this->exactly(4))
144 | ->method('invalidateCache')
145 | ->with($this->logicalOr('name0', 'name1', 'name2', null), $owner);
146 |
147 | $cachedSettingsManager->setMany($settings, $owner);
148 | }
149 |
150 | public function testClear()
151 | {
152 | $owner = $this->createOwner();
153 | $name = 'name';
154 |
155 | $settingsManager = \Mockery::mock(SettingsManager::class);
156 | $settingsManager->shouldReceive('clear')->once()->with($name, $owner);
157 |
158 | $cachedSettingsManager = $this->getMockBuilder(CachedSettingsManager::class)
159 | ->setMethods(['invalidateCache'])
160 | ->setConstructorArgs([$settingsManager, $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(), 4711])
161 | ->getMock();
162 | $cachedSettingsManager->expects($this->at(0))
163 | ->method('invalidateCache')
164 | ->with($this->equalTo($name), $this->equalTo($owner))
165 | ->willReturn(true);
166 | $cachedSettingsManager->expects($this->at(1))
167 | ->method('invalidateCache')
168 | ->with($this->equalTo(null), $this->equalTo($owner))
169 | ->willReturn(true);
170 |
171 | $cachedSettingsManager->clear($name, $owner);
172 | }
173 |
174 | /**
175 | * Make sure we do always return a string, no matter input.
176 | */
177 | public function testGetCacheKey()
178 | {
179 | $name = 'name';
180 | $owner = $this->createOwner();
181 |
182 | $getCacheKey = new \ReflectionMethod(CachedSettingsManager::class, 'getCacheKey');
183 | $getCacheKey->setAccessible(true);
184 |
185 | $cachedSettingsManager = $this->getMockBuilder(CachedSettingsManager::class)
186 | ->disableOriginalConstructor()
187 | ->getMock();
188 |
189 | $this->assertStringContainsString('dmishh_settings', $getCacheKey->invoke($cachedSettingsManager, $name, $owner));
190 | $this->assertStringContainsString('dmishh_settings', $getCacheKey->invoke($cachedSettingsManager, $name, null));
191 | $this->assertStringContainsString('dmishh_settings', $getCacheKey->invoke($cachedSettingsManager, null, $owner));
192 | $this->assertStringContainsString('dmishh_settings', $getCacheKey->invoke($cachedSettingsManager, null, null));
193 | }
194 |
195 | /**
196 | * @param string $ownerId
197 | *
198 | * @return \Dmishh\SettingsBundle\Entity\SettingsOwnerInterface
199 | */
200 | protected function createOwner($ownerId = 'user1')
201 | {
202 | return \Mockery::mock(
203 | 'Dmishh\SettingsBundle\Entity\SettingsOwnerInterface',
204 | ['getSettingIdentifier' => $ownerId]
205 | );
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/Manager/SettingsManager.php:
--------------------------------------------------------------------------------
1 |
19 | * @author Artem Zhuravlov
20 | */
21 | class SettingsManager implements SettingsManagerInterface
22 | {
23 | /**
24 | * @var array
25 | */
26 | private $globalSettings;
27 |
28 | /**
29 | * @var array
30 | */
31 | private $ownerSettings;
32 |
33 | /**
34 | * @var ObjectManager
35 | */
36 | private $em;
37 |
38 | /**
39 | * @var EntityRepository
40 | */
41 | private $repository;
42 |
43 | /**
44 | * @var SerializerInterface
45 | */
46 | private $serializer;
47 |
48 | /**
49 | * @var array
50 | */
51 | private $settingsConfiguration;
52 |
53 | public function __construct(
54 | EntityManagerInterface $em,
55 | SerializerInterface $serializer,
56 | array $settingsConfiguration = []
57 | ) {
58 | $this->em = $em;
59 | $this->repository = $em->getRepository(Setting::class);
60 | $this->serializer = $serializer;
61 | $this->settingsConfiguration = $settingsConfiguration;
62 | }
63 |
64 | /**
65 | * {@inheritdoc}
66 | */
67 | public function get(string $name, ?SettingsOwnerInterface $owner = null, $default = null)
68 | {
69 | $this->validateSetting($name, $owner);
70 | $this->loadSettings($owner);
71 |
72 | $value = null;
73 |
74 | switch ($this->settingsConfiguration[$name]['scope']) {
75 | case SettingsManagerInterface::SCOPE_GLOBAL:
76 | $value = $this->globalSettings[$name] ?? null;
77 | break;
78 | case SettingsManagerInterface::SCOPE_ALL:
79 | $value = $this->globalSettings[$name] ?? null;
80 | // Do not break here. Try to fetch the users settings
81 | // no break
82 | case SettingsManagerInterface::SCOPE_USER:
83 | if (null !== $owner) {
84 | $value = $this->ownerSettings[$owner->getSettingIdentifier()][$name] ?? $value;
85 | }
86 | break;
87 | }
88 |
89 | return null === $value ? $default : $value;
90 | }
91 |
92 | /**
93 | * {@inheritdoc}
94 | */
95 | public function all(?SettingsOwnerInterface $owner = null): array
96 | {
97 | $this->loadSettings($owner);
98 |
99 | if (null === $owner) {
100 | return $this->globalSettings;
101 | }
102 |
103 | $settings = $this->ownerSettings[$owner->getSettingIdentifier()];
104 |
105 | // If some user setting is not defined, please use the value from global
106 | foreach ($settings as $key => $value) {
107 | if (null === $value && isset($this->globalSettings[$key])) {
108 | $settings[$key] = $this->globalSettings[$key];
109 | }
110 | }
111 |
112 | return $settings;
113 | }
114 |
115 | /**
116 | * {@inheritdoc}
117 | */
118 | public function set(string $name, $value, ?SettingsOwnerInterface $owner = null): void
119 | {
120 | $this->setWithoutFlush($name, $value, $owner);
121 | $this->flush([$name], $owner);
122 | }
123 |
124 | /**
125 | * {@inheritdoc}
126 | */
127 | public function setMany(array $settings, ?SettingsOwnerInterface $owner = null): void
128 | {
129 | foreach ($settings as $name => $value) {
130 | $this->setWithoutFlush($name, $value, $owner);
131 | }
132 |
133 | $this->flush(array_keys($settings), $owner);
134 | }
135 |
136 | /**
137 | * {@inheritdoc}
138 | */
139 | public function clear(string $name, ?SettingsOwnerInterface $owner = null): void
140 | {
141 | $this->set($name, null, $owner);
142 | }
143 |
144 | /**
145 | * Find a setting by name form an array of settings.
146 | *
147 | * @param Setting[] $haystack
148 | */
149 | protected function findSettingByName(array $haystack, string $needle): ?Setting
150 | {
151 | foreach ($haystack as $setting) {
152 | if ($setting->getName() === $needle) {
153 | return $setting;
154 | }
155 | }
156 |
157 | return null;
158 | }
159 |
160 | /**
161 | * Sets setting value to private array. Used for settings' batch saving.
162 | */
163 | private function setWithoutFlush(string $name, $value, ?SettingsOwnerInterface $owner = null): void
164 | {
165 | $this->validateSetting($name, $owner);
166 | $this->loadSettings($owner);
167 |
168 | if (null === $owner) {
169 | $this->globalSettings[$name] = $value;
170 | } else {
171 | $this->ownerSettings[$owner->getSettingIdentifier()][$name] = $value;
172 | }
173 | }
174 |
175 | /**
176 | * Flushes settings defined by $names to database.
177 | *
178 | * @throws UnknownSerializerException
179 | */
180 | private function flush(array $names, ?SettingsOwnerInterface $owner = null): void
181 | {
182 | $settings = $this->repository->findBy([
183 | 'name' => $names,
184 | 'ownerId' => null === $owner ? null : $owner->getSettingIdentifier(),
185 | ]);
186 |
187 | // Assert: $settings might be a smaller set than $names
188 |
189 | // For each settings that you are trying to save
190 | foreach ($names as $name) {
191 | try {
192 | $value = $this->get($name, $owner);
193 | } catch (WrongScopeException $e) {
194 | continue;
195 | }
196 |
197 | /** @var Setting $setting */
198 | $setting = $this->findSettingByName($settings, $name);
199 |
200 | if (!$setting) {
201 | // if the setting does not exist in DB, create it
202 | $setting = new Setting();
203 | $setting->setName($name);
204 | if (null !== $owner) {
205 | $setting->setOwnerId($owner->getSettingIdentifier());
206 | }
207 | $this->em->persist($setting);
208 | }
209 |
210 | $setting->setValue($this->serializer->serialize($value));
211 | }
212 |
213 | $this->em->flush();
214 | }
215 |
216 | /**
217 | * Checks that $name is valid setting and it's scope is also valid.
218 | *
219 | * @param SettingsOwnerInterface $owner
220 | *
221 | * @return SettingsManager
222 | *
223 | * @throws UnknownSettingException
224 | * @throws WrongScopeException
225 | */
226 | private function validateSetting(string $name, ?SettingsOwnerInterface $owner = null): void
227 | {
228 | // Name validation
229 | if (!\is_string($name) || !\array_key_exists($name, $this->settingsConfiguration)) {
230 | throw new UnknownSettingException($name);
231 | }
232 |
233 | // Scope validation
234 | $scope = $this->settingsConfiguration[$name]['scope'];
235 | if (SettingsManagerInterface::SCOPE_ALL !== $scope) {
236 | if (SettingsManagerInterface::SCOPE_GLOBAL === $scope && null !== $owner || SettingsManagerInterface::SCOPE_USER === $scope && null === $owner) {
237 | throw new WrongScopeException($scope, $name);
238 | }
239 | }
240 | }
241 |
242 | /**
243 | * Settings lazy loading.
244 | */
245 | private function loadSettings(SettingsOwnerInterface $owner = null): void
246 | {
247 | // Global settings
248 | if (null === $this->globalSettings) {
249 | $this->globalSettings = $this->getSettingsFromRepository();
250 | }
251 |
252 | // User settings
253 | if (null !== $owner && (null === $this->ownerSettings || !\array_key_exists($owner->getSettingIdentifier(), $this->ownerSettings))) {
254 | $this->ownerSettings[$owner->getSettingIdentifier()] = $this->getSettingsFromRepository($owner);
255 | }
256 | }
257 |
258 | /**
259 | * Retreives settings from repository.
260 | *
261 | * @throws UnknownSerializerException
262 | */
263 | private function getSettingsFromRepository(?SettingsOwnerInterface $owner = null): array
264 | {
265 | $settings = [];
266 |
267 | foreach (array_keys($this->settingsConfiguration) as $name) {
268 | try {
269 | $this->validateSetting($name, $owner);
270 | $settings[$name] = null;
271 | } catch (WrongScopeException $e) {
272 | continue;
273 | }
274 | }
275 |
276 | /** @var Setting $setting */
277 | foreach ($this->repository->findBy(['ownerId' => null === $owner ? null : $owner->getSettingIdentifier()]) as $setting) {
278 | if (\array_key_exists($setting->getName(), $settings)) {
279 | $settings[$setting->getName()] = $this->serializer->unserialize($setting->getValue());
280 | }
281 | }
282 |
283 | return $settings;
284 | }
285 | }
286 |
--------------------------------------------------------------------------------
/phpstan-baseline.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | ignoreErrors:
3 | -
4 | message: "#^Call to an undefined method object\\:\\:isGranted\\(\\)\\.$#"
5 | count: 1
6 | path: Controller/SettingsController.php
7 |
8 | -
9 | message: "#^Call to an undefined method object\\:\\:getToken\\(\\)\\.$#"
10 | count: 2
11 | path: Controller/SettingsController.php
12 |
13 | -
14 | message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\TreeBuilder\\:\\:root\\(\\)\\.$#"
15 | count: 1
16 | path: DependencyInjection/Configuration.php
17 |
18 | -
19 | message: "#^Method Dmishh\\\\SettingsBundle\\\\DependencyInjection\\\\DmishhSettingsExtension\\:\\:load\\(\\) has no return typehint specified\\.$#"
20 | count: 1
21 | path: DependencyInjection/DmishhSettingsExtension.php
22 |
23 | -
24 | message: "#^Method Dmishh\\\\SettingsBundle\\\\DependencyInjection\\\\DmishhSettingsExtension\\:\\:load\\(\\) has parameter \\$configs with no value type specified in iterable type array\\.$#"
25 | count: 1
26 | path: DependencyInjection/DmishhSettingsExtension.php
27 |
28 | -
29 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Entity\\\\Setting\\:\\:setName\\(\\) has no return typehint specified\\.$#"
30 | count: 1
31 | path: Entity/Setting.php
32 |
33 | -
34 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Entity\\\\Setting\\:\\:setOwnerId\\(\\) has no return typehint specified\\.$#"
35 | count: 1
36 | path: Entity/Setting.php
37 |
38 | -
39 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Entity\\\\SettingsOwnerInterface\\:\\:getSettingIdentifier\\(\\) has no return typehint specified\\.$#"
40 | count: 1
41 | path: Entity/SettingsOwnerInterface.php
42 |
43 | -
44 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Exception\\\\UnknownSerializerException\\:\\:__construct\\(\\) has parameter \\$serializerClass with no typehint specified\\.$#"
45 | count: 1
46 | path: Exception/UnknownSerializerException.php
47 |
48 | -
49 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Exception\\\\UnknownSettingException\\:\\:__construct\\(\\) has parameter \\$settingName with no typehint specified\\.$#"
50 | count: 1
51 | path: Exception/UnknownSettingException.php
52 |
53 | -
54 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Exception\\\\WrongScopeException\\:\\:__construct\\(\\) has parameter \\$scope with no typehint specified\\.$#"
55 | count: 1
56 | path: Exception/WrongScopeException.php
57 |
58 | -
59 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Exception\\\\WrongScopeException\\:\\:__construct\\(\\) has parameter \\$settingName with no typehint specified\\.$#"
60 | count: 1
61 | path: Exception/WrongScopeException.php
62 |
63 | -
64 | message: "#^Property Dmishh\\\\SettingsBundle\\\\Form\\\\Type\\\\SettingsType\\:\\:\\$settingsConfiguration has no typehint specified\\.$#"
65 | count: 1
66 | path: Form/Type/SettingsType.php
67 |
68 | -
69 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Form\\\\Type\\\\SettingsType\\:\\:__construct\\(\\) has parameter \\$settingsConfiguration with no value type specified in iterable type array\\.$#"
70 | count: 1
71 | path: Form/Type/SettingsType.php
72 |
73 | -
74 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Form\\\\Type\\\\SettingsType\\:\\:buildForm\\(\\) has no return typehint specified\\.$#"
75 | count: 1
76 | path: Form/Type/SettingsType.php
77 |
78 | -
79 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Form\\\\Type\\\\SettingsType\\:\\:buildForm\\(\\) has parameter \\$builder with no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormBuilderInterface\\.$#"
80 | count: 1
81 | path: Form/Type/SettingsType.php
82 |
83 | -
84 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Form\\\\Type\\\\SettingsType\\:\\:buildForm\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
85 | count: 1
86 | path: Form/Type/SettingsType.php
87 |
88 | -
89 | message: "#^Cannot instantiate interface Dmishh\\\\SettingsBundle\\\\Exception\\\\SettingsException\\.$#"
90 | count: 1
91 | path: Form/Type/SettingsType.php
92 |
93 | -
94 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Form\\\\Type\\\\SettingsType\\:\\:configureOptions\\(\\) has no return typehint specified\\.$#"
95 | count: 1
96 | path: Form/Type/SettingsType.php
97 |
98 | -
99 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\CachedSettingsManager\\:\\:__construct\\(\\) has parameter \\$cacheLifeTime with no typehint specified\\.$#"
100 | count: 1
101 | path: Manager/CachedSettingsManager.php
102 |
103 | -
104 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\CachedSettingsManager\\:\\:get\\(\\) has no return typehint specified\\.$#"
105 | count: 1
106 | path: Manager/CachedSettingsManager.php
107 |
108 | -
109 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\CachedSettingsManager\\:\\:all\\(\\) return type has no value type specified in iterable type array\\.$#"
110 | count: 1
111 | path: Manager/CachedSettingsManager.php
112 |
113 | -
114 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\CachedSettingsManager\\:\\:set\\(\\) has parameter \\$value with no typehint specified\\.$#"
115 | count: 1
116 | path: Manager/CachedSettingsManager.php
117 |
118 | -
119 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\CachedSettingsManager\\:\\:setMany\\(\\) has parameter \\$settings with no value type specified in iterable type array\\.$#"
120 | count: 1
121 | path: Manager/CachedSettingsManager.php
122 |
123 | -
124 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\CachedSettingsManager\\:\\:storeInCache\\(\\) has parameter \\$value with no typehint specified\\.$#"
125 | count: 1
126 | path: Manager/CachedSettingsManager.php
127 |
128 | -
129 | message: "#^Property Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:\\$globalSettings type has no value type specified in iterable type array\\.$#"
130 | count: 1
131 | path: Manager/SettingsManager.php
132 |
133 | -
134 | message: "#^Property Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:\\$ownerSettings type has no value type specified in iterable type array\\.$#"
135 | count: 1
136 | path: Manager/SettingsManager.php
137 |
138 | -
139 | message: "#^Property Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:\\$settingsConfiguration type has no value type specified in iterable type array\\.$#"
140 | count: 1
141 | path: Manager/SettingsManager.php
142 |
143 | -
144 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:__construct\\(\\) has parameter \\$settingsConfiguration with no value type specified in iterable type array\\.$#"
145 | count: 1
146 | path: Manager/SettingsManager.php
147 |
148 | -
149 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:get\\(\\) has no return typehint specified\\.$#"
150 | count: 1
151 | path: Manager/SettingsManager.php
152 |
153 | -
154 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:all\\(\\) return type has no value type specified in iterable type array\\.$#"
155 | count: 1
156 | path: Manager/SettingsManager.php
157 |
158 | -
159 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:set\\(\\) has parameter \\$value with no typehint specified\\.$#"
160 | count: 1
161 | path: Manager/SettingsManager.php
162 |
163 | -
164 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:setMany\\(\\) has parameter \\$settings with no value type specified in iterable type array\\.$#"
165 | count: 1
166 | path: Manager/SettingsManager.php
167 |
168 | -
169 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:setWithoutFlush\\(\\) has parameter \\$value with no typehint specified\\.$#"
170 | count: 1
171 | path: Manager/SettingsManager.php
172 |
173 | -
174 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:flush\\(\\) has parameter \\$names with no value type specified in iterable type array\\.$#"
175 | count: 1
176 | path: Manager/SettingsManager.php
177 |
178 | -
179 | message: "#^Negated boolean expression is always false\\.$#"
180 | count: 1
181 | path: Manager/SettingsManager.php
182 |
183 | -
184 | message: "#^PHPDoc tag @return with type Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager is incompatible with native type void\\.$#"
185 | count: 1
186 | path: Manager/SettingsManager.php
187 |
188 | -
189 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManager\\:\\:getSettingsFromRepository\\(\\) return type has no value type specified in iterable type array\\.$#"
190 | count: 1
191 | path: Manager/SettingsManager.php
192 |
193 | -
194 | message: "#^Parameter \\#1 \\$key of function array_key_exists expects int\\|string, string\\|null given\\.$#"
195 | count: 1
196 | path: Manager/SettingsManager.php
197 |
198 | -
199 | message: "#^Parameter \\#1 \\$serialized of method Dmishh\\\\SettingsBundle\\\\Serializer\\\\SerializerInterface\\:\\:unserialize\\(\\) expects string, string\\|null given\\.$#"
200 | count: 1
201 | path: Manager/SettingsManager.php
202 |
203 | -
204 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManagerInterface\\:\\:get\\(\\) has no return typehint specified\\.$#"
205 | count: 1
206 | path: Manager/SettingsManagerInterface.php
207 |
208 | -
209 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManagerInterface\\:\\:all\\(\\) return type has no value type specified in iterable type array\\.$#"
210 | count: 1
211 | path: Manager/SettingsManagerInterface.php
212 |
213 | -
214 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManagerInterface\\:\\:set\\(\\) has parameter \\$value with no typehint specified\\.$#"
215 | count: 1
216 | path: Manager/SettingsManagerInterface.php
217 |
218 | -
219 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Manager\\\\SettingsManagerInterface\\:\\:setMany\\(\\) has parameter \\$settings with no value type specified in iterable type array\\.$#"
220 | count: 1
221 | path: Manager/SettingsManagerInterface.php
222 |
223 | -
224 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Serializer\\\\JsonSerializer\\:\\:serialize\\(\\) has parameter \\$data with no typehint specified\\.$#"
225 | count: 1
226 | path: Serializer/JsonSerializer.php
227 |
228 | -
229 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Serializer\\\\JsonSerializer\\:\\:serialize\\(\\) should return string but returns string\\|false\\.$#"
230 | count: 1
231 | path: Serializer/JsonSerializer.php
232 |
233 | -
234 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Serializer\\\\JsonSerializer\\:\\:unserialize\\(\\) has no return typehint specified\\.$#"
235 | count: 1
236 | path: Serializer/JsonSerializer.php
237 |
238 | -
239 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Serializer\\\\PhpSerializer\\:\\:serialize\\(\\) has parameter \\$data with no typehint specified\\.$#"
240 | count: 1
241 | path: Serializer/PhpSerializer.php
242 |
243 | -
244 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Serializer\\\\PhpSerializer\\:\\:unserialize\\(\\) has no return typehint specified\\.$#"
245 | count: 1
246 | path: Serializer/PhpSerializer.php
247 |
248 | -
249 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Serializer\\\\SerializerInterface\\:\\:serialize\\(\\) has parameter \\$data with no typehint specified\\.$#"
250 | count: 1
251 | path: Serializer/SerializerInterface.php
252 |
253 | -
254 | message: "#^Method Dmishh\\\\SettingsBundle\\\\Serializer\\\\SerializerInterface\\:\\:unserialize\\(\\) has no return typehint specified\\.$#"
255 | count: 1
256 | path: Serializer/SerializerInterface.php
257 |
258 |
--------------------------------------------------------------------------------
/Tests/SettingsManagerTest.php:
--------------------------------------------------------------------------------
1 | expectException('\Dmishh\SettingsBundle\Exception\UnknownSettingException');
15 | $settingsManager = $this->createSettingsManager();
16 | $settingsManager->get('unknown_setting');
17 | }
18 |
19 | public function testGlobalSettingsAccessor()
20 | {
21 | $settingsManager = $this->createSettingsManager();
22 | $settingsManager->set('some_setting', 'VALUE_GLOBAL');
23 | $this->assertEquals('VALUE_GLOBAL', $settingsManager->get('some_setting'));
24 | }
25 |
26 | public function testGlobalSettingsClear()
27 | {
28 | $settingsManager = $this->createSettingsManager();
29 | $settingsManager->set('some_setting', 'VALUE_GLOBAL');
30 | $settingsManager->clear('some_setting');
31 | $this->assertNull($settingsManager->get('some_setting'));
32 | }
33 |
34 | public function testUserSettingsAccessor()
35 | {
36 | $owner = $this->createOwner();
37 | $settingsManager = $this->createSettingsManager();
38 | $settingsManager->set('some_setting', 'VALUE_USER', $owner);
39 | $this->assertEquals('VALUE_USER', $settingsManager->get('some_setting', $owner));
40 | }
41 |
42 | public function testUserSettingsClear()
43 | {
44 | $owner = $this->createOwner();
45 | $settingsManager = $this->createSettingsManager();
46 | $settingsManager->set('some_setting', 'VALUE_GLOBAL', $owner);
47 | $settingsManager->clear('some_setting', $owner);
48 | $this->assertNull($settingsManager->get('some_setting', $owner));
49 | }
50 |
51 | public function testGlobalAndUserSettingsArentIntersect()
52 | {
53 | $owner = $this->createOwner();
54 | $settingsManager = $this->createSettingsManager();
55 | $settingsManager->set('some_setting', 'VALUE_GLOBAL');
56 | $settingsManager->set('some_setting', 'VALUE_USER', $owner);
57 | $this->assertEquals('VALUE_GLOBAL', $settingsManager->get('some_setting'));
58 | $this->assertEquals('VALUE_USER', $settingsManager->get('some_setting', $owner));
59 |
60 | // in reverse order
61 | $settingsManager->set('some_setting', 'VALUE_USER_2', $owner);
62 | $settingsManager->set('some_setting', 'VALUE_GLOBAL_2');
63 | $this->assertEquals('VALUE_GLOBAL_2', $settingsManager->get('some_setting'));
64 | $this->assertEquals('VALUE_USER_2', $settingsManager->get('some_setting', $owner));
65 | }
66 |
67 | public function testUsersSettingsArentIntersect()
68 | {
69 | $owner1 = $this->createOwner(1);
70 | $owner2 = $this->createOwner(2);
71 | $settingsManager = $this->createSettingsManager();
72 | $settingsManager->set('some_setting', 'VALUE_USER_1', $owner1);
73 | $settingsManager->set('some_setting', 'VALUE_USER_2', $owner2);
74 | $this->assertEquals('VALUE_USER_1', $settingsManager->get('some_setting', $owner1));
75 | $this->assertEquals('VALUE_USER_2', $settingsManager->get('some_setting', $owner2));
76 |
77 | // in reverse order
78 | $settingsManager->set('some_setting', 'VALUE_USER_2', $owner2);
79 | $settingsManager->set('some_setting', 'VALUE_USER_1', $owner1);
80 | $this->assertEquals('VALUE_USER_1', $settingsManager->get('some_setting', $owner1));
81 | $this->assertEquals('VALUE_USER_2', $settingsManager->get('some_setting', $owner2));
82 | }
83 |
84 | public function testPersistence()
85 | {
86 | $settingsManager = $this->createSettingsManager();
87 | $settingsManager->set('some_setting', 'VALUE_GLOBAL');
88 |
89 | // creating new manager and cheking for some_setting
90 | $settingsManager = $this->createSettingsManager();
91 | $this->assertEquals('VALUE_GLOBAL', $settingsManager->get('some_setting'));
92 |
93 | // clear
94 | $settingsManager->clear('some_setting');
95 | $settingsManager = $this->createSettingsManager();
96 | $this->assertNull($settingsManager->get('some_setting'));
97 | }
98 |
99 | public function testSetUserSettingInGlobalScopeRaisesException()
100 | {
101 | $this->expectException('\Dmishh\SettingsBundle\Exception\WrongScopeException');
102 |
103 | $owner = $this->createOwner();
104 | $settingsManager = $this->createSettingsManager();
105 | $settingsManager->set('some_global_setting', 'VALUE_GLOBAL');
106 | $this->assertEquals('VALUE_GLOBAL', $settingsManager->get('some_global_setting'));
107 |
108 | $settingsManager->set('some_global_setting', 'VALUE_GLOBAL', $owner);
109 | }
110 |
111 | public function testGetUserSettingInGlobalScopeRaisesException()
112 | {
113 | $this->expectException('\Dmishh\SettingsBundle\Exception\WrongScopeException');
114 |
115 | $owner = $this->createOwner();
116 | $settingsManager = $this->createSettingsManager();
117 | $settingsManager->get('some_global_setting', $owner);
118 | }
119 |
120 | public function testSetGlobalSettingInUserScopeRaisesException()
121 | {
122 | $this->expectException('\Dmishh\SettingsBundle\Exception\WrongScopeException');
123 |
124 | $owner = $this->createOwner();
125 | $settingsManager = $this->createSettingsManager();
126 | $settingsManager->set('some_user_setting', 'VALUE_USER', $owner);
127 | $this->assertEquals('VALUE_USER', $settingsManager->get('some_global_setting', $owner));
128 |
129 | $settingsManager->set('some_user_setting', 'VALUE_USER');
130 | }
131 |
132 | public function testGetGlobalSettingInUserScopeRaisesException()
133 | {
134 | $this->expectException('\Dmishh\SettingsBundle\Exception\WrongScopeException');
135 |
136 | $settingsManager = $this->createSettingsManager();
137 | $settingsManager->get('some_user_setting');
138 | }
139 |
140 | public function testGetAllGlobalSettings()
141 | {
142 | $settingsManager = $this->createSettingsManager();
143 | $this->assertEquals(
144 | ['some_setting' => null, 'some_setting2' => null, 'some_global_setting' => null],
145 | $settingsManager->all()
146 | );
147 | }
148 |
149 | public function testGetAllUserSettings()
150 | {
151 | $owner = $this->createOwner();
152 | $settingsManager = $this->createSettingsManager();
153 | $this->assertEquals(
154 | ['some_setting' => null, 'some_setting2' => null, 'some_user_setting' => null],
155 | $settingsManager->all($owner)
156 | );
157 | }
158 |
159 | public function testScopeAll()
160 | {
161 | $owner = $this->createOwner();
162 | $settingsManager = $this->createSettingsManager();
163 |
164 | // Global settings should be shown if there is no user setting defined
165 | $settingsManager->set('some_setting', 'value');
166 | $this->assertEquals('value', $settingsManager->get('some_setting'));
167 | $this->assertEquals(
168 | 'value',
169 | $settingsManager->get('some_setting', $owner),
170 | 'Did not get global value when local value was undefined.'
171 | );
172 | $this->assertEquals(
173 | ['some_setting' => 'value', 'some_setting2' => null, 'some_user_setting' => null],
174 | $settingsManager->all($owner),
175 | 'Did not get global value when local value was undefined.'
176 | );
177 |
178 | // The users settings should always be prioritised over the global one (if it exists)
179 | $settingsManager->set('some_setting', 'user_value', $owner);
180 | $this->assertEquals(
181 | 'user_value',
182 | $settingsManager->get('some_setting', $owner),
183 | 'User/Local value should have priority over global.'
184 | );
185 | $this->assertEquals('value', $settingsManager->get('some_setting'));
186 | $this->assertEquals(
187 | ['some_setting' => 'user_value', 'some_setting2' => null, 'some_user_setting' => null],
188 | $settingsManager->all($owner),
189 | 'User/Local value should have priority over global.'
190 | );
191 | }
192 |
193 | public function testValidSerizalizationTypes()
194 | {
195 | $settingsManager = $this->createSettingsManager([], 'php');
196 | $settingsManager->set('some_setting', 123);
197 | $this->assertEquals(123, $settingsManager->get('some_setting'));
198 |
199 | $settingsManager = $this->createSettingsManager([], 'json');
200 | $settingsManager->set('some_setting', 123);
201 | $this->assertEquals(123, $settingsManager->get('some_setting'));
202 | }
203 |
204 | public function testSetSettingWithInvalidSerizalizationType()
205 | {
206 | $this->expectException('\Dmishh\SettingsBundle\Exception\SettingsException');
207 |
208 | $settingsManager = $this->createSettingsManager([], 'unknown_serialization_type');
209 | $settingsManager->set('some_setting', 123);
210 | }
211 |
212 | public function testGetSettingWithInvalidSerizalizationType()
213 | {
214 | $this->expectException('\Dmishh\SettingsBundle\Exception\SettingsException');
215 |
216 | $settingsManager = $this->createSettingsManager([]);
217 | $settingsManager->set('some_setting', 123);
218 |
219 | $settingsManager = $this->createSettingsManager([], 'unknown_serialization_type');
220 | $settingsManager->get('some_setting');
221 | }
222 |
223 | public function testGetDefaultValue()
224 | {
225 | $user = $this->createOwner();
226 | $settingsManager = $this->createSettingsManager();
227 |
228 | //test default global value
229 | $this->assertNull($settingsManager->get('some_setting'));
230 | $this->assertEquals('foobar', $settingsManager->get('some_setting', null, 'foobar'));
231 |
232 | //test default user value
233 | $this->assertNull($settingsManager->get('some_setting'));
234 | $this->assertEquals('foobar', $settingsManager->get('some_setting', $user, 'foobar'));
235 |
236 | //test when there is an actual value
237 | $settingsManager->set('some_setting', 'value');
238 | $this->assertEquals('value', $settingsManager->get('some_setting', null, 'foobar'));
239 | $this->assertEquals('value', $settingsManager->get('some_setting', $user, 'foobar'));
240 | }
241 |
242 | /**
243 | * @see https://github.com/dmishh/SettingsBundle/issues/28
244 | */
245 | public function testFlush()
246 | {
247 | $names = ['foo', 'bar', 'baz'];
248 | $settings = 'foobar';
249 | $owner = null;
250 | $value = 'settingValue';
251 | $serializedValue = 'sValue';
252 |
253 | $flushMethod = new \ReflectionMethod('Dmishh\SettingsBundle\Manager\SettingsManager', 'flush');
254 | $flushMethod->setAccessible(true);
255 |
256 | $serializer = $this
257 | ->getMockBuilder('Dmishh\SettingsBundle\Serializer\PhpSerializer')
258 | ->setMethods(['serialize'])
259 | ->getMock();
260 |
261 | $serializer
262 | ->expects($this->exactly(\count($names)))
263 | ->method('serialize')
264 | ->with($this->equalTo($value))
265 | ->willReturn($serializedValue);
266 |
267 | $repo = $this
268 | ->getMockBuilder('Doctrine\ORM\EntityRepository')
269 | ->disableOriginalConstructor()
270 | ->setMethods(['findBy'])
271 | ->getMock();
272 |
273 | $repo->expects($this->once())->method('findBy')->with(
274 | $this->equalTo(
275 | [
276 | 'name' => $names,
277 | 'ownerId' => $owner,
278 | ]
279 | )
280 | )->willReturn($settings);
281 |
282 | $em = $this
283 | ->getMockBuilder('Doctrine\Orm\EntityManager')
284 | ->disableOriginalConstructor()
285 | ->setMethods(['getRepository', 'flush'])
286 | ->getMock();
287 |
288 | $em->expects($this->once())->method('getRepository')->willReturn($repo);
289 | $em->expects($this->once())->method('flush');
290 |
291 | $setting = $this
292 | ->getMockBuilder('Dmishh\SettingsBundle\Entity\Settings')
293 | ->disableOriginalConstructor()
294 | ->setMethods(['setValue'])
295 | ->getMock();
296 |
297 | $setting->expects($this->exactly(\count($names)))->method('setValue')->with($this->equalTo($serializedValue));
298 |
299 | $manager = $this
300 | ->getMockBuilder('Dmishh\SettingsBundle\Manager\SettingsManager')
301 | ->setConstructorArgs([$em, $serializer, []])
302 | ->setMethods(['findSettingByName', 'get'])
303 | ->getMock();
304 |
305 | $manager
306 | ->expects($this->exactly(\count($names)))
307 | ->method('get')
308 | ->withConsecutive(
309 | [$this->equalTo('foo'), $owner],
310 | [$this->equalTo('bar'), $owner],
311 | [$this->equalTo('baz'), $owner]
312 | )
313 | ->willReturn($value);
314 |
315 | $manager
316 | ->expects($this->exactly(\count($names)))
317 | ->method('findSettingByName')
318 | ->withConsecutive(
319 | [$settings, $this->equalTo('foo')],
320 | [$settings, $this->equalTo('bar')],
321 | [$settings, $this->equalTo('baz')]
322 | )->willReturn($setting);
323 |
324 | $flushMethod->invoke($manager, $names, $owner);
325 | }
326 |
327 | public function testFindSettingByName()
328 | {
329 | $settingsManager = $this->createSettingsManager();
330 |
331 | $s1 = $this->createSetting('foo');
332 | $s2 = $this->createSetting('bar');
333 | $s3 = $this->createSetting('baz');
334 | $s4 = $this->createSetting('foo');
335 | $settings = [$s1, $s2, $s3, $s4];
336 |
337 | $method = new \ReflectionMethod('Dmishh\SettingsBundle\Manager\SettingsManager', 'findSettingByName');
338 | $method->setAccessible(true);
339 |
340 | $result = $method->invoke($settingsManager, $settings, 'bar');
341 | $this->assertEquals($s2, $result);
342 |
343 | $result = $method->invoke($settingsManager, $settings, 'biz');
344 | $this->assertNull($result);
345 |
346 | $result = $method->invoke($settingsManager, $settings, 'foo');
347 | $this->assertEquals($s1, $result);
348 | }
349 |
350 | protected function createSetting($name)
351 | {
352 | $s = $this->getMockBuilder('Dmishh\SettingsBundle\Entity\Setting')
353 | ->setMethods(['getName'])
354 | ->getMock();
355 |
356 | $s->expects($this->any())
357 | ->method('getName')
358 | ->willReturn($name);
359 |
360 | return $s;
361 | }
362 |
363 | /**
364 | * @param string $ownerId
365 | *
366 | * @return \Dmishh\SettingsBundle\Entity\SettingsOwnerInterface
367 | */
368 | protected function createOwner($ownerId = 'user1')
369 | {
370 | return Mockery::mock(
371 | 'Dmishh\SettingsBundle\Entity\SettingsOwnerInterface',
372 | ['getSettingIdentifier' => $ownerId]
373 | );
374 | }
375 |
376 | protected function createSettingsManager(array $configuration = [], $serialization = 'php')
377 | {
378 | if (empty($configuration)) {
379 | $configuration = [
380 | 'some_setting' => ['scope' => SettingsManagerInterface::SCOPE_ALL],
381 | 'some_setting2' => ['scope' => SettingsManagerInterface::SCOPE_ALL],
382 | 'some_global_setting' => ['scope' => SettingsManagerInterface::SCOPE_GLOBAL],
383 | 'some_user_setting' => ['scope' => SettingsManagerInterface::SCOPE_USER],
384 | ];
385 | }
386 |
387 | $serializer = SerializerFactory::create($serialization);
388 |
389 | return new SettingsManager($this->em, $serializer, $configuration);
390 | }
391 | }
392 |
--------------------------------------------------------------------------------