Skip to content

Commit 6e1fa43

Browse files
authored
Merge branch '2.x' into dropzone-multiple-uploads
2 parents e3a731f + 0c63ac0 commit 6e1fa43

File tree

101 files changed

+917
-210
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+917
-210
lines changed

.github/workflows/.utils.sh

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,29 @@ _run_task() {
2929
}
3030
export -f _run_task
3131

32-
install_property_info_for_version() {
33-
local php_version="$1"
34-
local min_stability="$2"
32+
# Install specific versions of PropertyInfo and TypeInfo based on PHP and Symfony versions
33+
# To remove in Symfony UX 4.0
34+
live_component_post_install() {
35+
local php_version=$1
3536

36-
if [ "$php_version" = "8.2" ]; then
37-
composer require symfony/property-info:7.1.* symfony/type-info:7.2.*
38-
elif [ "$php_version" = "8.3" ]; then
39-
composer require symfony/property-info:7.2.* symfony/type-info:7.2.*
40-
elif [ "$php_version" = "8.4" ] && [ "$min_stability" = "stable" ]; then
41-
composer require symfony/property-info:7.3.* symfony/type-info:7.3.*
42-
elif [ "$php_version" = "8.4" ] && [ "$min_stability" = "dev" ]; then
43-
composer require symfony/property-info:>=7.3 symfony/type-info:>=7.3
44-
fi
37+
case "$php_version" in
38+
8.1)
39+
# no-op, let Composer install the best PropertyInfo version (defined in composer.json), but do not require TypeInfo
40+
return 0
41+
;;
42+
8.2)
43+
# PropertyInfo 7.1 (experimental PropertyTypeExtractorInterface::getType) and TypeInfo 7.2 (lowest non-experimental)
44+
composer require symfony/property-info:7.1.* symfony/type-info:7.2.*
45+
return $?
46+
;;
47+
8.3)
48+
# Install PropertyInfo 7.3 (deprecate PropertyTypeExtractorInterface::getTypes) and TypeInfo 7.3 (new features and deprecations)
49+
composer require symfony/property-info:7.3.* symfony/type-info:7.3.*
50+
return $?
51+
;;
52+
esac
53+
54+
# Install the best TypeInfo version available
55+
composer require symfony/type-info
4556
}
46-
export -f install_property_info_for_version
57+
export -f live_component_post_install

.github/workflows/unit-tests.yaml

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,29 @@ jobs:
3636
include:
3737
- minimum-stability: 'dev'
3838
php-version: '8.5'
39+
3940
# lowest deps
4041
- php-version: '8.1'
4142
dependency-version: 'lowest'
43+
4244
# LTS version of Symfony
4345
- php-version: '8.1'
4446
symfony-version: '6.4.*'
4547
- php-version: '8.1'
4648
symfony-version: '6.4.*'
4749
os: 'windows-latest'
48-
# Explicit Symfony versions
50+
4951
- php-version: '8.2'
50-
symfony-version: '^7.4.0-RC1' # TODO: change to '7.4.*' when Symfony 7.4 is released
52+
symfony-version: '7.4.*'
53+
- php-version: '8.2'
54+
symfony-version: '7.4.*'
55+
os: 'windows-latest'
56+
57+
# Explicit Symfony versions
5158
- php-version: '8.4'
52-
symfony-version: '^8.0.0-RC1' # TODO: change to '8.0.*' when Symfony 8.0 is released
59+
symfony-version: '8.0.*'
5360
- php-version: '8.5'
54-
symfony-version: '^8.0.0-RC1' # TODO: change to '8.0.*' when Symfony 8.0 is released
61+
symfony-version: '8.0.*'
5562

5663
env:
5764
SYMFONY_REQUIRE: ${{ matrix.symfony-version || '>=5.4' }} # TODO: To change to '>=6.4' in 3.x
@@ -84,7 +91,7 @@ jobs:
8491
uses: shivammathur/setup-php@v2
8592
with:
8693
php-version: ${{ matrix.php-version }}
87-
extensions: ${{ matrix.os == 'windows-latest' && 'pdo_sqlite,sqlite3,fileinfo,gd' || '' }}
94+
extensions: ${{ matrix.os == 'windows-latest' && 'pdo_sqlite,sqlite3,fileinfo,gd,zip' || '' }}
8895
tools: flex
8996

9097
- name: Get composer cache directory
@@ -116,7 +123,7 @@ jobs:
116123
'(cd src/{} \
117124
&& $COMPOSER_MIN_STAB \
118125
&& $COMPOSER_UP \
119-
&& if [ {} = LiveComponent ]; then install_property_info_for_version \"${{ matrix.php-version }}\" \"${{ matrix.minimum-stability }}\"; fi \
126+
&& if [ {} = LiveComponent ]; then live_component_post_install \"${{ matrix.php-version }}\"; fi \
120127
&& $PHPUNIT)'"
121128
122129
- name: Run packages tests (Windows)
@@ -131,7 +138,7 @@ jobs:
131138
'(cd src/$PACKAGE \
132139
&& $COMPOSER_MIN_STAB \
133140
&& $COMPOSER_UP \
134-
&& if [ "$PACKAGE" = "LiveComponent" ]; then install_property_info_for_version \"${{ matrix.php-version }}\" \"${{ matrix.minimum-stability }}\"; fi \
141+
&& if [ "$PACKAGE" = "LiveComponent" ]; then live_component_post_install ${{ matrix.php-version }}; fi \
135142
&& $PHPUNIT)'; then
136143
FAILED_PACKAGES="$FAILED_PACKAGES $PACKAGE"
137144
fi

biome.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"rules": {
2222
"suspicious": {
2323
"noExplicitAny": "off",
24-
"noEmptyBlockStatements": "off"
24+
"noEmptyBlockStatements": "off",
25+
"noPrototypeBuiltins": "off"
2526
},
2627
"complexity": {
2728
"noStaticOnlyClass": "off",

src/Autocomplete/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
},
3434
"require-dev": {
3535
"doctrine/collections": "^1.6.8|^2.0",
36-
"doctrine/doctrine-bundle": "^2.4.3|^3.0.0",
36+
"doctrine/doctrine-bundle": "^2.4.3|^3.0|^4.0",
3737
"doctrine/orm": "^2.9.4|^3.0",
3838
"fakerphp/faker": "^1.22",
3939
"mtdowling/jmespath.php": "^2.6",

src/Autocomplete/doc/index.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ e.g. ``FoodAutocompleteField`` from above):
206206
``tom_select_options`` (default: ``[]``)
207207
Use this to set custom `Tom Select Options`_. If you need to set
208208
an option using JavaScript, see `Extending Tom Select`_.
209+
Read also about `Managing plugins`_.
209210

210211
``options_as_html`` (default: ``false``)
211212
Set to ``true`` if your options (e.g. ``choice_label``) contain HTML. Not
@@ -415,6 +416,36 @@ all of the options - separated by the ``delimiter`` - will be sent as a string.
415416
You *can* add autocompletion to this via the ``autocomplete_url`` option - but you'll
416417
likely need to create your own :ref:`custom autocomplete endpoint <custom-autocomplete-endpoint>`.
417418

419+
Managing plugins
420+
----------------
421+
422+
`Tom Select Plugins`_ can be configured through the ``tom_select_options.plugins`` option:
423+
424+
$resolver->setDefaults([
425+
'class' => Ingredient::class,
426+
'tom_select_options' => [
427+
'plugins' => [
428+
// Enable Input Autogrow plugin
429+
'input_autogrow',
430+
431+
// Enable Dropdown Header plugin, with custom configuration
432+
'dropdown_header' => [
433+
'title' => 'Select an ingredient',
434+
],
435+
436+
// Force natively-enabled plugins (by UX Autocomplete) to be disabled
437+
'clear_button' => false,
438+
'remove_button' => false,
439+
],
440+
],
441+
]);
442+
443+
.. note::
444+
445+
Some configuration could not be supported through the `tom_select_options.plugins` option,
446+
for example when a plugin requires a JavaScript function as configuration value.
447+
In that case, you must use the `Extending Tom Select`_ approach to configure plugins.
448+
418449
Customizing the AJAX URL/Route
419450
------------------------------
420451

@@ -758,3 +789,4 @@ the Symfony framework: https://symfony.com/doc/current/contributing/code/bc.html
758789
.. _`Tom Select Option Group`: https://tom-select.js.org/examples/optgroups/
759790
.. _`Symfony Form`: https://symfony.com/doc/current/forms.html
760791
.. _`@symfony/ux-autocomplete npm package`: https://www.npmjs.com/package/@symfony/ux-autocomplete
792+
.. _`Tom Select Plugins`: https://tom-select.js.org/plugins/

src/Autocomplete/tests/Fixtures/Kernel.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ protected function configureContainer(ContainerConfigurator $c): void
138138
$doctrineConfig['orm']['controller_resolver']['auto_mapping'] = true;
139139
}
140140
}
141-
if (\PHP_VERSION_ID >= 80400 && version_compare($doctrineBundleVersion, '2.15.0', '>=')) {
141+
142+
if (\PHP_VERSION_ID >= 80400 && version_compare($doctrineBundleVersion, '2.15.0', '>=') && version_compare($doctrineBundleVersion, '4.0.0', '<')) {
142143
$doctrineConfig['orm']['enable_native_lazy_objects'] = true;
143144
}
144145
}

src/Icons/src/DependencyInjection/UXIconsExtension.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\UX\Icons\DependencyInjection;
1313

1414
use Symfony\Component\AssetMapper\Event\PreAssetsCompileEvent;
15+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
1516
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
1617
use Symfony\Component\Config\Definition\ConfigurationInterface;
1718
use Symfony\Component\Config\FileLocator;
@@ -38,10 +39,15 @@ public function getConfigTreeBuilder(): TreeBuilder
3839
->info('The local directory where icons are stored.')
3940
->defaultValue('%kernel.project_dir%/assets/icons')
4041
->end()
41-
->variableNode('default_icon_attributes')
42+
->arrayNode('default_icon_attributes')
4243
->info('Default attributes to add to all icons.')
4344
->defaultValue(['fill' => 'currentColor'])
4445
->example(['class' => 'icon'])
46+
->normalizeKeys(false)
47+
->useAttributeAsKey('key')
48+
->scalarPrototype()
49+
->cannotBeEmpty()
50+
->end()
4551
->end()
4652
->arrayNode('icon_sets')
4753
->info('Icon sets configuration.')
@@ -63,7 +69,9 @@ public function getConfigTreeBuilder(): TreeBuilder
6369
->info('Override default icon attributes for icons in this set.')
6470
->example(['class' => 'icon icon-acme', 'fill' => 'none'])
6571
->normalizeKeys(false)
66-
->variablePrototype()
72+
->useAttributeAsKey('key')
73+
->scalarPrototype()
74+
->cannotBeEmpty()
6775
->end()
6876
->end()
6977
->end()
@@ -80,7 +88,8 @@ public function getConfigTreeBuilder(): TreeBuilder
8088
'privacy' => 'bi:cookie',
8189
])
8290
->normalizeKeys(false)
83-
->scalarPrototype()
91+
->useAttributeAsKey('key')
92+
->{method_exists(ArrayNodeDefinition::class, 'stringPrototype') ? 'stringPrototype' : 'scalarPrototype'}()
8493
->cannotBeEmpty()
8594
->end()
8695
->end()
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\Icons\Tests;
13+
14+
use PHPUnit\Framework\Attributes\DataProvider;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
17+
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
18+
use Symfony\Component\Config\Definition\Processor;
19+
use Symfony\UX\Icons\DependencyInjection\UXIconsExtension;
20+
21+
class UXIconsBundleTest extends TestCase
22+
{
23+
public static function provideTestInvalidAliasConfiguration(): iterable
24+
{
25+
yield ['', 'Invalid type for path "ux_icons.aliases". Expected "array", but got "string"'];
26+
yield [123, 'Invalid type for path "ux_icons.aliases". Expected "array", but got "int'];
27+
yield [false, 'Invalid type for path "ux_icons.aliases". Expected "array", but got "bool"'];
28+
29+
if (method_exists(ArrayNodeDefinition::class, 'stringPrototype')) {
30+
yield [[1, 2, 3], 'Invalid type for path "ux_icons.aliases.0". Expected "string", but got "int"'];
31+
yield [['foo' => 123], 'Invalid type for path "ux_icons.aliases.foo". Expected "string", but got "int"'];
32+
}
33+
}
34+
35+
/**
36+
* @dataProvider provideTestInvalidAliasConfiguration
37+
*/
38+
#[DataProvider('provideTestInvalidAliasConfiguration')]
39+
public function testInvalidAliasConfiguration(mixed $value, string $expectedMessage)
40+
{
41+
self::expectException(InvalidConfigurationException::class);
42+
self::expectExceptionMessage($expectedMessage);
43+
44+
$processor = new Processor();
45+
$configurableExtension = new UXIconsExtension();
46+
$processor->processConfiguration($configurableExtension, [
47+
[
48+
'aliases' => $value,
49+
],
50+
]);
51+
}
52+
53+
public static function provideTestValidAliasConfiguration(): iterable
54+
{
55+
yield [[]];
56+
yield [['foo' => 'bar']];
57+
}
58+
59+
/**
60+
* @dataProvider provideTestValidAliasConfiguration
61+
*/
62+
#[DataProvider('provideTestValidAliasConfiguration')]
63+
public function testValidAliasConfiguration(array $value)
64+
{
65+
$processor = new Processor();
66+
$configurableExtension = new UXIconsExtension();
67+
$processedConfig = $processor->processConfiguration($configurableExtension, [
68+
[
69+
'aliases' => $value,
70+
],
71+
]);
72+
73+
$this->assertSame($value, $processedConfig['aliases']);
74+
}
75+
76+
public static function provideTestInvalidIconAttributesConfiguration(): iterable
77+
{
78+
yield ['', 'Invalid type for path "ux_icons.default_icon_attributes". Expected "array", but got "string"'];
79+
yield [123, 'Invalid type for path "ux_icons.default_icon_attributes". Expected "array", but got "int"'];
80+
yield [false, 'Invalid type for path "ux_icons.default_icon_attributes". Expected "array", but got "bool"'];
81+
}
82+
83+
/**
84+
* @dataProvider provideTestInvalidIconAttributesConfiguration
85+
*/
86+
#[DataProvider('provideTestInvalidIconAttributesConfiguration')]
87+
public function testInvalidIconAttributeConfiguration(mixed $value, string $expectedMessage)
88+
{
89+
self::expectException(InvalidConfigurationException::class);
90+
self::expectExceptionMessage($expectedMessage);
91+
92+
$processor = new Processor();
93+
$configurableExtension = new UXIconsExtension();
94+
$processor->processConfiguration($configurableExtension, [
95+
[
96+
'default_icon_attributes' => $value,
97+
],
98+
]);
99+
}
100+
101+
public static function provideTestValidIconAttributesConfiguration(): iterable
102+
{
103+
yield [[]];
104+
yield [['class' => 'icon-large', 'aria-hidden' => 'true', 'data-test' => 123]];
105+
}
106+
107+
/**
108+
* @dataProvider provideTestValidIconAttributesConfiguration
109+
*/
110+
#[DataProvider('provideTestValidIconAttributesConfiguration')]
111+
public function testValidIconAttributeConfiguration(array $value)
112+
{
113+
$processor = new Processor();
114+
$configurableExtension = new UXIconsExtension();
115+
$processedConfig = $processor->processConfiguration($configurableExtension, [
116+
[
117+
'default_icon_attributes' => $value,
118+
],
119+
]);
120+
$this->assertSame($value, $processedConfig['default_icon_attributes']);
121+
}
122+
}

src/LiveComponent/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
"require-dev": {
3838
"doctrine/annotations": "^1.0|^2.0",
3939
"doctrine/collections": "^1.6.8|^2.0",
40-
"doctrine/doctrine-bundle": "^2.4.3|^3.0.0",
40+
"doctrine/doctrine-bundle": "^2.4.3|^3.0|^4.0",
4141
"doctrine/orm": "^2.9.4|^3.0",
42-
"doctrine/persistence": "^2.5.2|^3.0",
42+
"doctrine/persistence": "^2.5.2|^3.0|^4.0",
4343
"phpdocumentor/reflection-docblock": "5.x-dev",
4444
"symfony/dependency-injection": "^5.4|^6.0|^7.0|^8.0",
4545
"symfony/expression-language": "^5.4|^6.0|^7.0|^8.0",

0 commit comments

Comments
 (0)