Skip to content

Commit 8c810b0

Browse files
committed
Merge branch '6.4' into 7.0
* 6.4: DX: PHP CS Fixer - update excluded paths and apply some minor CS [AssetMapper] Optimize memory usage (load only "compilable" assets) [AssetMapper] Split ImportmapManager into 2 Rename fixtures paths to be consistent Add WorflowGuardListenerPass only if it exists [AssetMapper] Using ?specifier=* does not match unstable packages on jsdelivr [Worflow] Add a TraceableWorkflow
2 parents d671385 + 124706b commit 8c810b0

File tree

180 files changed

+1655
-1196
lines changed

Some content is hidden

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

180 files changed

+1655
-1196
lines changed

.php-cs-fixer.dist.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
'modernize_strpos' => true,
3939
'get_class_to_class_keyword' => true,
4040
'nullable_type_declaration' => true,
41+
// 'get_class_to_class_keyword' => true, // to be enabled when Bridge/PhpUnit will require PHP 8+
4142
])
4243
->setRiskyAllowed(true)
4344
->setFinder(
@@ -55,12 +56,15 @@
5556
'Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/',
5657
'Symfony/Component/Intl/Resources/data/',
5758
])
59+
// explicit tests for ommited @param type, against `no_superfluous_phpdoc_tags`
60+
->notPath('Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php')
61+
->notPath('Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php')
5862
// Support for older PHPunit version
5963
->notPath('Symfony/Bridge/PhpUnit/SymfonyTestsListener.php')
6064
->notPath('#Symfony/Bridge/PhpUnit/.*Mock\.php#')
6165
->notPath('#Symfony/Bridge/PhpUnit/.*Legacy#')
6266
// file content autogenerated by `var_export`
63-
->notPath('Symfony/Component/Translation/Tests/fixtures/resources.php')
67+
->notPath('Symfony/Component/Translation/Tests/Fixtures/resources.php')
6468
// file content autogenerated by `VarExporter::export`
6569
->notPath('Symfony/Component/Serializer/Tests/Fixtures/serializer.class.metadata.php')
6670
// test template

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public static function collectDeprecations($outputFile)
9696
{
9797
$deprecations = [];
9898
$previousErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations, &$previousErrorHandler) {
99-
if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || false === strpos($msg, '" targeting switch is equivalent to "break'))) {
99+
if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || !str_contains($msg, '" targeting switch is equivalent to "break'))) {
100100
if ($previousErrorHandler) {
101101
return $previousErrorHandler($type, $msg, $file, $line, $context);
102102
}
@@ -128,7 +128,7 @@ public static function collectDeprecations($outputFile)
128128
*/
129129
public function handleError($type, $msg, $file, $line, $context = [])
130130
{
131-
if ((\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || false === strpos($msg, '" targeting switch is equivalent to "break'))) || !$this->getConfiguration()->isEnabled()) {
131+
if ((\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || !str_contains($msg, '" targeting switch is equivalent to "break'))) || !$this->getConfiguration()->isEnabled()) {
132132
return \call_user_func(self::getPhpUnitErrorHandler(), $type, $msg, $file, $line, $context);
133133
}
134134

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public function __construct(string $message, array $trace, string $file, bool $l
9999
$this->getOriginalFilesStack();
100100
array_splice($this->originalFilesStack, 0, $j, [$this->triggeringFile]);
101101

102-
if (preg_match('/(?|"([^"]++)" that is deprecated|should implement method "(?:static )?([^:]++))/', $message, $m) || (false === strpos($message, '()" will return') && false === strpos($message, 'native return type declaration') && preg_match('/^(?:The|Method) "([^":]++)/', $message, $m))) {
102+
if (preg_match('/(?|"([^"]++)" that is deprecated|should implement method "(?:static )?([^:]++))/', $message, $m) || (!str_contains($message, '()" will return') && !str_contains($message, 'native return type declaration') && preg_match('/^(?:The|Method) "([^":]++)/', $message, $m))) {
103103
$this->triggeringFile = (new \ReflectionClass($m[1]))->getFileName();
104104
array_unshift($this->originalFilesStack, $this->triggeringFile);
105105
}
@@ -137,7 +137,7 @@ public function __construct(string $message, array $trace, string $file, bool $l
137137
return;
138138
}
139139

140-
if (!isset($line['class'], $trace[$i - 2]['function']) || 0 !== strpos($line['class'], SymfonyTestsListenerFor::class)) {
140+
if (!isset($line['class'], $trace[$i - 2]['function']) || !str_starts_with($line['class'], SymfonyTestsListenerFor::class)) {
141141
$this->originClass = isset($line['object']) ? \get_class($line['object']) : $line['class'];
142142
$this->originMethod = $line['function'];
143143

@@ -161,7 +161,7 @@ private function lineShouldBeSkipped(array $line): bool
161161
}
162162
$class = $line['class'];
163163

164-
return 'ReflectionMethod' === $class || 0 === strpos($class, 'PHPUnit\\');
164+
return 'ReflectionMethod' === $class || str_starts_with($class, 'PHPUnit\\');
165165
}
166166

167167
public function originatesFromDebugClassLoader(): bool
@@ -191,7 +191,7 @@ public function originatingClass(): string
191191

192192
$class = $this->originClass;
193193

194-
return false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class;
194+
return str_contains($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class;
195195
}
196196

197197
public function originatingMethod(): string
@@ -217,9 +217,9 @@ public function isLegacy(): bool
217217
$method = $this->originatingMethod();
218218
$groups = class_exists(Groups::class, false) ? [new Groups(), 'groups'] : [Test::class, 'getGroups'];
219219

220-
return 0 === strpos($method, 'testLegacy')
221-
|| 0 === strpos($method, 'provideLegacy')
222-
|| 0 === strpos($method, 'getLegacy')
220+
return str_starts_with($method, 'testLegacy')
221+
|| str_starts_with($method, 'provideLegacy')
222+
|| str_starts_with($method, 'getLegacy')
223223
|| strpos($this->originClass, '\Legacy')
224224
|| \in_array('legacy', $groups($this->originClass, $method), true);
225225
}
@@ -230,10 +230,10 @@ public function isMuted(): bool
230230
return false;
231231
}
232232
if (isset($this->trace[1]['class'])) {
233-
return 0 === strpos($this->trace[1]['class'], 'PHPUnit\\');
233+
return str_starts_with($this->trace[1]['class'], 'PHPUnit\\');
234234
}
235235

236-
return false !== strpos($this->triggeringFile, \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR.'phpunit'.\DIRECTORY_SEPARATOR);
236+
return str_contains($this->triggeringFile, \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR.'phpunit'.\DIRECTORY_SEPARATOR);
237237
}
238238

239239
/**
@@ -302,7 +302,7 @@ private function getPackage(string $path): string
302302
{
303303
$path = realpath($path) ?: $path;
304304
foreach (self::getVendors() as $vendorRoot) {
305-
if (0 === strpos($path, $vendorRoot)) {
305+
if (str_starts_with($path, $vendorRoot)) {
306306
$relativePath = substr($path, \strlen($vendorRoot) + 1);
307307
$vendor = strstr($relativePath, \DIRECTORY_SEPARATOR, true);
308308
if (false === $vendor) {
@@ -328,7 +328,7 @@ private static function getVendors(): array
328328
self::$vendors[] = \dirname((new \ReflectionClass(DebugClassLoader::class))->getFileName());
329329
}
330330
foreach (get_declared_classes() as $class) {
331-
if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
331+
if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) {
332332
$r = new \ReflectionClass($class);
333333
$v = \dirname($r->getFileName(), 2);
334334
if (file_exists($v.'/composer/installed.json')) {
@@ -343,7 +343,7 @@ private static function getVendors(): array
343343
}
344344
foreach ($paths as $path) {
345345
foreach (self::$vendors as $vendor) {
346-
if (0 !== strpos($path, $vendor)) {
346+
if (!str_starts_with($path, $vendor)) {
347347
self::$internalPaths[] = $path;
348348
}
349349
}
@@ -373,13 +373,13 @@ private function getPathType(string $path): string
373373
return self::PATH_TYPE_UNDETERMINED;
374374
}
375375
foreach (self::getVendors() as $vendor) {
376-
if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
376+
if (str_starts_with($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
377377
return self::PATH_TYPE_VENDOR;
378378
}
379379
}
380380

381381
foreach (self::$internalPaths as $internalPath) {
382-
if (0 === strpos($realPath, $internalPath)) {
382+
if (str_starts_with($realPath, $internalPath)) {
383383
return self::PATH_TYPE_SELF;
384384
}
385385
}

src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function test()
4343
exec("$php $phpunit -c $dir/phpunit-with-listener.xml.dist $dir/tests/ --coverage-text --colors=never 2> /dev/null", $output);
4444
$output = implode("\n", $output);
4545

46-
if (false === strpos($output, 'FooCov')) {
46+
if (!str_contains($output, 'FooCov')) {
4747
$this->addToAssertionCount(1);
4848
} else {
4949
$this->assertMatchesRegularExpression('/FooCov\n\s*Methods:\s+0.00%[^\n]+Lines:\s+0.00%/', $output);

src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
break;
5858
}
5959
// short option
60-
if (0 === strpos($cliArgument, '-c')) {
60+
if (str_starts_with($cliArgument, '-c')) {
6161
if ('-c' === $cliArgument && array_key_exists($cliArgumentIndex + 1, $argv)) {
6262
$phpunitConfigFilename = $getPhpUnitConfig($argv[$cliArgumentIndex + 1]);
6363
} else {

src/Symfony/Bridge/PhpUnit/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"require-dev": {
2424
"symfony/deprecation-contracts": "^2.5|^3.0",
2525
"symfony/error-handler": "^5.4|^6.4|^7.0",
26+
"symfony/polyfill-php80": "^1.27",
2627
"symfony/polyfill-php81": "^1.27"
2728
},
2829
"conflict": {

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass;
7070
use Symfony\Component\VarExporter\Internal\Hydrator;
7171
use Symfony\Component\VarExporter\Internal\Registry;
72+
use Symfony\Component\Workflow\DependencyInjection\WorkflowDebugPass;
7273
use Symfony\Component\Workflow\DependencyInjection\WorkflowGuardListenerPass;
7374

7475
// Help opcache.preload discover always-needed symbols
@@ -155,7 +156,7 @@ public function build(ContainerBuilder $container): void
155156
$container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING);
156157
$container->addCompilerPass(new CachePoolPrunerPass(), PassConfig::TYPE_AFTER_REMOVING);
157158
$this->addCompilerPassIfExists($container, FormPass::class);
158-
$container->addCompilerPass(new WorkflowGuardListenerPass());
159+
$this->addCompilerPassIfExists($container, WorkflowGuardListenerPass::class);
159160
$container->addCompilerPass(new ResettableServicePass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
160161
$container->addCompilerPass(new RegisterLocaleAwareServicesPass());
161162
$container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32);
@@ -176,6 +177,7 @@ public function build(ContainerBuilder $container): void
176177
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
177178
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING, -255);
178179
$container->addCompilerPass(new CacheCollectorPass(), PassConfig::TYPE_BEFORE_REMOVING);
180+
$this->addCompilerPassIfExists($container, WorkflowDebugPass::class);
179181
}
180182
}
181183

src/Symfony/Bundle/FrameworkBundle/Resources/config/asset_mapper.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use Symfony\Component\AssetMapper\Factory\MappedAssetFactory;
3232
use Symfony\Component\AssetMapper\ImportMap\ImportMapAuditor;
3333
use Symfony\Component\AssetMapper\ImportMap\ImportMapConfigReader;
34+
use Symfony\Component\AssetMapper\ImportMap\ImportMapGenerator;
3435
use Symfony\Component\AssetMapper\ImportMap\ImportMapManager;
3536
use Symfony\Component\AssetMapper\ImportMap\ImportMapRenderer;
3637
use Symfony\Component\AssetMapper\ImportMap\ImportMapUpdateChecker;
@@ -101,7 +102,7 @@
101102
->args([
102103
service('asset_mapper.public_assets_path_resolver'),
103104
service('asset_mapper'),
104-
service('asset_mapper.importmap.manager'),
105+
service('asset_mapper.importmap.generator'),
105106
service('filesystem'),
106107
param('kernel.project_dir'),
107108
abstract_arg('public directory name'),
@@ -137,7 +138,7 @@
137138

138139
->set('asset_mapper.compiler.javascript_import_path_compiler', JavaScriptImportPathCompiler::class)
139140
->args([
140-
service('asset_mapper.importmap.manager'),
141+
service('asset_mapper.importmap.config_reader'),
141142
abstract_arg('missing import mode'),
142143
service('logger'),
143144
])
@@ -153,13 +154,19 @@
153154
->set('asset_mapper.importmap.manager', ImportMapManager::class)
154155
->args([
155156
service('asset_mapper'),
156-
service('asset_mapper.public_assets_path_resolver'),
157157
service('asset_mapper.importmap.config_reader'),
158158
service('asset_mapper.importmap.remote_package_downloader'),
159159
service('asset_mapper.importmap.resolver'),
160160
])
161161
->alias(ImportMapManager::class, 'asset_mapper.importmap.manager')
162162

163+
->set('asset_mapper.importmap.generator', ImportMapGenerator::class)
164+
->args([
165+
service('asset_mapper'),
166+
service('asset_mapper.public_assets_path_resolver'),
167+
service('asset_mapper.importmap.config_reader'),
168+
])
169+
163170
->set('asset_mapper.importmap.remote_package_storage', RemotePackageStorage::class)
164171
->args([
165172
abstract_arg('vendor directory'),
@@ -183,7 +190,7 @@
183190

184191
->set('asset_mapper.importmap.renderer', ImportMapRenderer::class)
185192
->args([
186-
service('asset_mapper.importmap.manager'),
193+
service('asset_mapper.importmap.generator'),
187194
service('assets.packages')->nullOnInvalid(),
188195
param('kernel.charset'),
189196
abstract_arg('polyfill URL'),
@@ -205,7 +212,6 @@
205212
->set('asset_mapper.importmap.command.require', ImportMapRequireCommand::class)
206213
->args([
207214
service('asset_mapper.importmap.manager'),
208-
param('kernel.project_dir'),
209215
service('asset_mapper.importmap.version_checker'),
210216
])
211217
->tag('console.command')

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/workflow.html.twig

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
22

3+
{% block toolbar %}
4+
{% if collector.callsCount > 0 %}
5+
{% set icon %}
6+
{{ source('@WebProfiler/Icon/workflow.svg') }}
7+
<span class="sf-toolbar-value">{{ collector.callsCount }}</span>
8+
{% endset %}
9+
{% set text %}
10+
<div class="sf-toolbar-info-piece">
11+
<b>Workflow Calls</b>
12+
<span>{{ collector.callsCount }}</span>
13+
</div>
14+
{% endset %}
15+
16+
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url }) }}
17+
{% endif %}
18+
{% endblock %}
19+
320
{% block menu %}
421
<span class="label {{ collector.workflows|length == 0 ? 'disabled' }}">
522
<span class="icon">
@@ -45,15 +62,67 @@
4562
});
4663
</script>
4764

48-
<h2>Definitions</h2>
4965
<div class="sf-tabs js-tabs">
5066
{% for name, data in collector.workflows %}
5167
<div class="tab">
52-
<h3 class="tab-title">{{ name }}</h3>
68+
<h2 class="tab-title">{{ name }}{% if data.calls|length %} ({{ data.calls|length }}){% endif %}</h2>
69+
5370
<div class="tab-content">
71+
<h3>Definition</h3>
5472
<pre class="sf-mermaid">
5573
{{ data.dump|raw }}
5674
</pre>
75+
76+
<h3>Calls</h3>
77+
<table>
78+
<thead>
79+
<tr>
80+
<th>#</th>
81+
<th>Call</th>
82+
<th>Args</th>
83+
<th>Return</th>
84+
<th>Exception</th>
85+
<th>Duration</th>
86+
</tr>
87+
</thead>
88+
<tbody>
89+
{% for call in data.calls %}
90+
<tr>
91+
<td class="font-normal text-small text-muted nowrap">{{ loop.index }}</td>
92+
<td>
93+
<code>{{ call.method }}()</code>
94+
{% if call.previousMarking ?? null %}
95+
<hr />
96+
Previous marking:
97+
{{ profiler_dump(call.previousMarking) }}
98+
{% endif %}
99+
</td>
100+
<td>
101+
{{ profiler_dump(call.args) }}
102+
</td>
103+
<td>
104+
{% if call.return is defined %}
105+
{% if call.return is same as true %}
106+
<code>true</code>
107+
{% elseif call.return is same as false %}
108+
<code>false</code>
109+
{% else %}
110+
{{ profiler_dump(call.return) }}
111+
{% endif %}
112+
{% endif %}
113+
</td>
114+
<td>
115+
{% if call.exception is defined %}
116+
{{ profiler_dump(call.exception) }}
117+
{% endif %}
118+
</td>
119+
<td>
120+
{{ call.duration }}ms
121+
</td>
122+
</tr>
123+
{% endfor %}
124+
</tbody>
125+
</table>
57126
</div>
58127
</div>
59128
{% endfor %}

0 commit comments

Comments
 (0)