Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fixtures #60

Merged
merged 34 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
57ea789
feat(fixtures): Add yaml fixtures into test app configuration
jacquesbh Jul 24, 2023
84e09ec
doc(fixtures): Update readme
jacquesbh Jul 24, 2023
d3e8cc3
feat: init fixture files
etienne-monsieurbiz Jul 24, 2023
29b076e
chore(fixtures): reformat
jacquesbh Jul 24, 2023
36c06b4
feat(fixtures): Channel and locale can be empty values
jacquesbh Jul 24, 2023
8a7b2d2
chore(readme): Update badges
jacquesbh Jul 24, 2023
8bee774
feat(fixtures): Add two more fixtures in test application
jacquesbh Jul 24, 2023
2dd6032
feat(fixture): Add fixture factory
etienne-monsieurbiz Jul 24, 2023
11a7ac0
feat(fixtures): Use factory
jacquesbh Jul 24, 2023
4a7d86d
feat(fixture): DI for autowiring
etienne-monsieurbiz Jul 24, 2023
2384626
feat(fixtures): Configure options
jacquesbh Jul 24, 2023
25a3536
fix(fixtures): Use keys in list
jacquesbh Jul 24, 2023
8e1622d
feat(fixtures): Add more default value for testing purposes
jacquesbh Jul 24, 2023
d0b0b9a
feat(fixture): add setAllowedType in fixture factory
etienne-monsieurbiz Jul 24, 2023
0dadf89
feat(fixtures): Format value according to type
jacquesbh Jul 24, 2023
a090dc1
fix(fixtures): AllowedType for value and AllowedValues for type
etienne-monsieurbiz Jul 24, 2023
4a65196
refactor(fixtures): Use constants for setAllowedValues
etienne-monsieurbiz Jul 24, 2023
a6eb28b
fix(fixtures): Json values are properly formated
jacquesbh Jul 24, 2023
1089122
feat(fixtures): Run only local suite
jacquesbh Jul 24, 2023
6d50972
doc(fixtures): Add local fixtures sentence
jacquesbh Jul 24, 2023
798ca7c
refactor(fixture): phpcs fix
etienne-monsieurbiz Jul 24, 2023
374edd5
fix: error phpcs phpstan
etienne-monsieurbiz Jul 24, 2023
c6dd356
feat(fixtures): Update values instead of adding new ones
jacquesbh Jul 24, 2023
0a3047d
fix: MakeFile to setup messenger
etienne-monsieurbiz Jul 24, 2023
f10ea79
fix(fixtures): reset value correctly with a type (always)
jacquesbh Jul 24, 2023
8e23c91
feat(fixtures): Add logger for testing fixtures
jacquesbh Jul 24, 2023
d9d3342
feat(fixtures): Add ignore_if_exists to avoid overwritting settings
jacquesbh Jul 24, 2023
bf922ca
feat: Add cli to set values for settings in db
etienne-monsieurbiz Jul 24, 2023
7e06676
feat: Update Readme for sf cli set settings
etienne-monsieurbiz Jul 24, 2023
5010f7f
feat: Add validate type for cli
etienne-monsieurbiz Jul 24, 2023
b3f33cc
feat(fixtures): Update Readme with info from flag ignore_if_exists
etienne-monsieurbiz Jul 24, 2023
68b4776
refactor(fixtures): Create new SettingProvider to get an existing one…
etienne-monsieurbiz Jul 25, 2023
422c62c
fix(fixtures): handle flag ignore_if_exists after refactoring + add d…
etienne-monsieurbiz Jul 25, 2023
7e23bc8
feat(cli): cli set value put type as option instead of argument and i…
etienne-monsieurbiz Jul 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ jobs:

- run: make install

- run: make sylius.fixtures.local

- run: make test.composer

- run: make test.phpcs
Expand Down
13 changes: 7 additions & 6 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@
'binary_operator_spaces' => true,
'blank_line_after_opening_tag' => true,
'blank_line_after_namespace' => true,
'blank_lines_before_namespace' => true,
'blank_line_before_statement' => true,
'braces' => [
'allow_single_line_closure' => true,
],
'cast_spaces' => true,
'class_attributes_separation' => true,
'class_definition' => [
Expand Down Expand Up @@ -88,7 +86,6 @@
'fully_qualified_strict_types' => true,
'function_declaration' => true,
'function_to_constant' => true,
'function_typehint_space' => true,
'general_phpdoc_tag_rename' => true,
'global_namespace_import' => [
'import_classes' => true,
Expand All @@ -115,6 +112,7 @@
'lowercase_static_reference' => true,
'magic_constant_casing' => true,
'method_argument_space' => true,
'modernize_strpos' => false,
'modernize_types_casting' => true,
'multiline_comment_opening_closing' => true,
'multiline_whitespace_before_semicolons' => [
Expand Down Expand Up @@ -181,6 +179,7 @@
'no_whitespace_in_blank_line' => true,
'non_printable_character' => true,
'normalize_index_brace' => true,
'nullable_type_declaration_for_default_null_value' => false,
'object_operator_without_whitespace' => true,
'ordered_imports' => [
'imports_order' => [
Expand Down Expand Up @@ -215,7 +214,9 @@
'phpdoc_order' => true,
'phpdoc_return_self_reference' => true,
'phpdoc_scalar' => true,
'phpdoc_separation' => true,
'phpdoc_separation' => ['groups' => [
['ORM\\*'], ['Assert\\*'],
]],
'phpdoc_single_line_var_spacing' => true,
'phpdoc_tag_type' => true,
'phpdoc_to_comment' => false,
Expand All @@ -235,7 +236,6 @@
'self_accessor' => true,
'short_scalar_cast' => true,
'single_blank_line_at_eof' => true,
'single_blank_line_before_namespace' => true,
'single_class_element_per_statement' => true,
'single_import_per_statement' => true,
'single_line_after_imports' => true,
Expand All @@ -252,6 +252,7 @@
'elements' => ['arrays'],
],
'trim_array_spaces' => true,
'type_declaration_spaces' => true,
'unary_operator_spaces' => true,
'visibility_required' => [
'elements' => [
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ test.twig: ## Validate Twig templates
### SYLIUS
### ¯¯¯¯¯¯

sylius: dependencies sylius.database sylius.fixtures sylius.assets ## Install Sylius
sylius: dependencies sylius.database sylius.fixtures sylius.assets messenger.setup ## Install Sylius
.PHONY: sylius

sylius.database: ## Setup the database
Expand All @@ -153,11 +153,17 @@ sylius.database: ## Setup the database
sylius.fixtures: ## Run the fixtures
${CONSOLE} sylius:fixtures:load -n default

sylius.fixtures.local: ## Run the local fixtures (for testing purpose)
${CONSOLE} sylius:fixtures:load -n local

sylius.assets: ## Install all assets with symlinks
${CONSOLE} assets:install --symlink
${CONSOLE} sylius:install:assets
${CONSOLE} sylius:theme:assets:install --symlink

messenger.setup: ## Setup Messenger transports
${CONSOLE} messenger:setup-transports

###
### PLATFORM
### ¯¯¯¯¯¯¯¯
Expand Down
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
<h1 align="center">Settings for Sylius</h1>

[![Settings Plugin license](https://img.shields.io/github/license/monsieurbiz/SyliusSettingsPlugin?public)](https://github.com/monsieurbiz/SyliusSettingsPlugin/blob/master/LICENSE.txt)
[![Tests Status](https://img.shields.io/github/workflow/status/monsieurbiz/SyliusSettingsPlugin/Tests?logo=github)](https://github.com/monsieurbiz/SyliusSettingsPlugin/actions?query=workflow%3ATests)
[![Security Status](https://img.shields.io/github/workflow/status/monsieurbiz/SyliusSettingsPlugin/Security?label=security&logo=github)](https://github.com/monsieurbiz/SyliusSettingsPlugin/actions?query=workflow%3ASecurity)
[![Tests](https://github.com/monsieurbiz/SyliusSettingsPlugin/actions/workflows/tests.yaml/badge.svg?branch=master&event=push)](https://github.com/monsieurbiz/SyliusSettingsPlugin/actions/workflows/tests.yaml)
[![Security](https://github.com/monsieurbiz/SyliusSettingsPlugin/actions/workflows/security.yaml/badge.svg?branch=master&event=push)](https://github.com/monsieurbiz/SyliusSettingsPlugin/actions/workflows/security.yaml)

This plugin gives you the ability to have Plugins oriented settings in your favorite e-commerce platform, Sylius.

Expand Down Expand Up @@ -101,6 +101,38 @@ use MonsieurBiz\SyliusSettingsPlugin\Provider\SettingsProviderInterface;
}
```

### Use fixtures

We've implemented a fixtures loader to help you to create your settings if you need to have different settings for your
tests or project (by channel, by locale…).

You need to create a yaml file with your fixtures, like explained in the documentation of Sylius.
You can find our own example in the source code, section `sylius_fixtures`: [configuration file](dist/config/packages/monsieurbiz_settings_plugin_custom.yaml).

It's also possible to run test fixtures with a local suite in development: `make sylius.fixtures.local`.

By default, a fixture will replace the value of a setting if it already exists.
If you want to keep a value as it is in the database when running this fixture, you can use the flag `ignore_if_exists: true` for each element that you want to be kept.

### Use CLI

You can use a CLI command to set a value for a setting directly from the console:
`$ ./bin/console monsieurbiz:settings:set {alias} {path} {value} --channel="FASHION_WEB" --locale="en_US" --type="text"`


Examples:
```bash
$ ./bin/console monsieurbiz:settings:set app.default demo_message 'fashion message' --channel="FASHION_WEB" --locale="en_US"
$ ./bin/console monsieurbiz:settings:set app.default demo_json '{"foo":"baz"}' --channel="FASHION_WEB" --locale="en_US" --type="json"
$ ./bin/console monsieurbiz:settings:set app.default demo_datetime '2023-07-24 01:02:03' --channel="FASHION_WEB" --locale="en_US" --type="datetime"
$ ./bin/console monsieurbiz:settings:set app.default enabled 0
```
The options channel and locale can be omitted if you want to set the value for a global scope.
If a value exists for the given scope the type can be omitted as it will be the same as the existing one unless you want to change the type.
For a new value you need to specify the type.

⚠️ When specifying the type, be sure to know what you are doing as it should be coherent with the Form Type of the field.

## Contributing

You can find a way to run the plugin without effort in the file [DEVELOPMENT.md](./DEVELOPMENT.md).
Expand Down
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,18 @@
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
},
"symfony": {
"allow-contrib": "true"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
"symfony/thanks": true,
"ergebnis/composer-normalize": true,
"symfony/flex": true
"symfony/flex": true,
"php-http/discovery": true
}
}
}
80 changes: 80 additions & 0 deletions dist/config/packages/monsieurbiz_settings_plugin_custom.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,83 @@ sylius_ui:
blocks:
demo_message:
template: '/views/message.html.twig'

sylius_fixtures:
suites:
default:
fixtures:
monsieurbiz_settings:
options:
custom:
-
alias: app.default
path: demo_message
channel: FASHION_WEB
locale: en_US
type: text
value: My amazing very fashion message
-
alias: app.default
path: demo_message
# no channel because we want the default
locale: fr_FR
type: text
value: Mon message vraiment très fashion
-
alias: app.default
path: demo_message
# no channel because we want the default
# no locale because we want the default
type: text
value: My very default message

local:
listeners:
logger: ~
fixtures:
monsieurbiz_settings:
options:
custom:
-
alias: app.default
path: test_bool
type: boolean
value: true
ignore_if_exists: true
-
alias: app.default
path: test_bool2
type: boolean
value: false
-
alias: app.default
path: test_json
type: json
value: |
{"foo":"bar"}
-
alias: app.default
path: test_json_array
type: json
value: {"foo":"baz"}
-
alias: app.default
path: test_int
type: integer
value: 42
-
alias: app.default
path: test_float
type: float
value: 13.37
-
alias: app.default
path: test_date
type: date
value: 2023-07-24
-
alias: app.default
path: test_datetime
type: datetime
value: 2023-07-24 01:02:03

137 changes: 137 additions & 0 deletions src/Command/SetSettingsCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

/*
* This file is part of Monsieur Biz' Settings plugin for Sylius.
*
* (c) Monsieur Biz <[email protected]>
*
* For the full copyright and license information, please view the LICENSE.txt
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace MonsieurBiz\SyliusSettingsPlugin\Command;

use Doctrine\ORM\EntityManagerInterface;
use Exception;
use MonsieurBiz\SyliusSettingsPlugin\Exception\SettingsException;
use MonsieurBiz\SyliusSettingsPlugin\Formatter\SettingsFormatterInterface;
use MonsieurBiz\SyliusSettingsPlugin\Provider\SettingProviderInterface;
use MonsieurBiz\SyliusSettingsPlugin\Settings\RegistryInterface;
use MonsieurBiz\SyliusSettingsPlugin\Settings\SettingsInterface;
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class SetSettingsCommand extends Command
{
private const ARGUMENT_ALIAS = 'alias';

private const ARGUMENT_PATH = 'path';

private const OPTION_CHANNEL = 'channel';

private const OPTION_LOCALE = 'locale';

private const OPTION_TYPE = 'type';

private const ARGUMENT_VALUE = 'value';

private RegistryInterface $settingsRegistry;

private ChannelRepositoryInterface $channelRepository;

private EntityManagerInterface $settingManager;

private SettingsFormatterInterface $settingsFormatter;

private SettingProviderInterface $settingProvider;

protected static $defaultName = 'monsieurbiz:settings:set';

public function __construct(
RegistryInterface $settingsRegistry,
ChannelRepositoryInterface $channelRepository,
EntityManagerInterface $settingManager,
SettingsFormatterInterface $settingsFormatter,
SettingProviderInterface $settingProvider,
string $name = null
) {
$this->settingsRegistry = $settingsRegistry;
$this->channelRepository = $channelRepository;
$this->settingManager = $settingManager;
$this->settingsFormatter = $settingsFormatter;
$this->settingProvider = $settingProvider;
parent::__construct($name);
}

protected function configure(): void
{
$this
->setDescription('Set a settings value for a given path')
->setHelp('This command allows you to set a settings value for a given path')
->addArgument(self::ARGUMENT_ALIAS, InputArgument::REQUIRED, 'Alias of the settings like {vendor}.{plugin} from the setting definition')
->addArgument(self::ARGUMENT_PATH, InputArgument::REQUIRED, 'Path of the settings')
->addArgument(self::ARGUMENT_VALUE, InputArgument::REQUIRED, 'Value of the settings')
->addOption(self::OPTION_TYPE, 't', InputOption::VALUE_OPTIONAL, 'Type of the settings', null)
->addOption(self::OPTION_CHANNEL, 'c', InputOption::VALUE_OPTIONAL, 'Channel code')
->addOption(self::OPTION_LOCALE, 'l', InputOption::VALUE_OPTIONAL, 'Locale code')
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
try {
/** @var string $alias */
$alias = $input->getArgument(self::ARGUMENT_ALIAS);
/** @var string $path */
$path = $input->getArgument(self::ARGUMENT_PATH);
$channelCode = $input->getOption(self::OPTION_CHANNEL);
/** @var ?string $locale */
$locale = $input->getOption(self::OPTION_LOCALE);

$channel = null;
if (null !== $channelCode) {
/** @var ?ChannelInterface $channel */
$channel = $this->channelRepository->findOneBy(['code' => $channelCode]);
}

/** @var ?SettingsInterface $settings */
$settings = $this->settingsRegistry->getByAlias($alias);
jacquesbh marked this conversation as resolved.
Show resolved Hide resolved

if (null === $settings) {
throw new SettingsException(sprintf('The alias "%s" is not valid.', $alias));
}

['vendor' => $vendor, 'plugin' => $plugin] = $settings->getAliasAsArray();
$setting = $this->settingProvider->getSettingOrCreateNew($vendor, $plugin, $path, $locale, $channel);

/** @var string $type */
$type = $input->getOption(self::OPTION_TYPE) ?? $setting->getStorageType();
$this->settingProvider->validateType($type);

$value = $input->getArgument(self::ARGUMENT_VALUE);

$this->settingProvider->resetExistingValue($setting);
$setting->setStorageType($type);
/** @phpstan-ignore-next-line */
$setting->setValue($this->settingsFormatter->formatValue($type, $value));

$this->settingManager->persist($setting);
$this->settingManager->flush();
} catch (Exception $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));

return Command::FAILURE;
}

$output->writeln(sprintf('<info>%s</info>', 'The setting has been saved'));

return Command::SUCCESS;
}
}
Loading
Loading