Symfony Demo 3.1.0: what Rateo prints

The Rateo engine, run on Symfony Demo, the official reference application of the Symfony framework. Every number below comes from the engine's output, which is linked in full at the end.

License
MIT
Source
https://github.com/symfony/demo/archive/refs/tags/v3.1.0.zip
Engine
2026.10.12
Rules
2026.10.7-provisional
Ran on
2026-10-16
Zip SHA-256
655456d87a6657f6cb066d80437a2292ebb544aea4c0e30df503b1aa095502b8
Command
build/rateo demo-3.1.0 --cache=none
from the folder the zip was extracted into

At a glance

Files analysed
53
Findings
7
Errors
0
Warnings
7

platform PHP: Symfony (composer.json requires symfony/framework-bundle; bin/console)

not analysed: 191 files (XML 59, Twig 32, YAML 30, SVG 29, JavaScript 9, SCSS 5, binary 4, JSON 3, Markdown 3, CSS 2, Ignore List 2, NEON 2, ApacheConf 1, EditorConfig 1, JSON with Comments 1, Shell 1, Text 1, demo 1, dev 1, lock 1, robots.txt 1, test 1, unknown 1)

What it checks

Checked today

  • Size: long files, classes and functions
  • Complexity: functions and file level code with too many paths
  • Naming: mixed styles in a file, generic, one letter and very long names
  • Duplication: blocks repeated inside a file, even with renamed variables
  • Security: eval, shell commands, unserialize and includes built from data, SQL with values pasted in, request input never sanitized, output never escaped

Not checked yet

  • Symfony rules: best practices for controllers, services and templates
  • Security checks: hard coded secrets
  • Tests: whether there are any, and how much test code there is next to the app code
  • Repository hygiene: .gitignore, a lockfile, no committed vendor/ or .env, a README with setup steps

The security checks read one call or statement at a time and never follow a value through variables, so they show where to look, not proof of a hole. A long or branchy function is common in a large, mature project; each finding is a place worth a closer look, not a judgement of the code as a whole.

Findings by check

CheckLimits (warning / error)WarningsErrorsTotal
Size
length.function
A function or method body with too many lines
body lines: above 50 / above 100101
Duplication
duplication.repeated_block
A block repeated later in the same file, even with its names changed
tokens: 50 or more / never an error202
Naming
naming.generic
A local variable or parameter with a name that says nothing, like $data or $tmp
name: on the list of 16 generic names / never an error101
naming.too_short
A one letter name other than i, j, k, n, x, y, z or e
characters: under 2 / never an error101
naming.too_long
A very long name
characters: above 30 / never an error202

A value equal to a limit is no finding.

Where they concentrate

The 10 files with the most findings

FileFindings
demo-3.1.0/config/bundles.php1
demo-3.1.0/src/Command/AddUserCommand.php1
demo-3.1.0/src/Controller/UserController.php1
demo-3.1.0/src/Entity/User.php1
demo-3.1.0/src/EventSubscriber/RedirectToPreferredLocaleSubscriber.php1
demo-3.1.0/src/Twig/SourceCodeExtension.php1
demo-3.1.0/tests/Form/DataTransformer/TagArrayToStringTransformerTest.php1

Findings per top level folder

FolderFindings
src/5
config/1
tests/1

Grades

AOverall: 99 out of 100
3 of 5 metrics graded

round((3 × 100Complexity+2 × 98Duplication+1 × 99Naming) ÷ 6) = 99

Weights: Complexity 3, Duplication 2, Naming 1. Size and Security are not graded, so they are left out and the other weights are rescaled.

A summary of the grades below, which you can recompute. Not a pass mark, and not a hiring decision.

The table shows how many files got each letter. A file with nothing to judge for a metric gets no grade for it. The whole project column pools every file's grade, so a file with more code to judge counts for more. The overall above weights those whole project grades. In the full engine output these are CodeLength, CyclomaticComplexity, Duplication, NamingConvention and Security.

MetricABCDFNot gradedWhole project
SizeFindings only, no grade
Complexity5300000100 A
Duplication510002098 A
Naming480000599 A

Security

Findings only, never a grade: a wrong security grade would hurt more than none. A finding the author already silenced with a phpcs comment counts as suppressed, apart from Errors and Warnings, so you can tell reviewed code from unreviewed code.

CheckErrorsWarningsSuppressed
security.eval
A call to eval, which runs a string as PHP code
000
security.shell
A shell command built from data
000
security.unserialize
unserialize without allowed_classes => false
000
security.include_variable
An include or require whose path is built from a variable
000
security.extract_input
extract of request input, which turns its fields into variables
000
security.sql_interpolated
SQL with a value pasted in instead of passed through prepare
000
security.unescaped_output
An echo, print or <?= of a value that is not escaped
000
security.unsanitized_input
A request input read with no sanitizer around it
000

8 rules ran over 41 files, none found anything.

The 10 worst places

Security findings are listed in their own section above. A place is a file and a line, so a function that is both too long and too complex shows once, with both findings. Places rank by their worst finding: errors first, then by how far the measured value goes beyond its limit. Each message is the engine's own, word for word.

#1 demo-3.1.0/config/bundles.php:13

  • Warning duplication.repeated_block

    lines 13 to 18 repeat lines 4 to 9 (82 tokens); repeated code has to be fixed in every copy

13 Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
14 Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
15 Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
16 Symfony\UX\LiveComponent\LiveComponentBundle::class => ['all' => true],
17 Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true],
18 Symfonycasts\SassBundle\SymfonycastsSassBundle::class => ['all' => true],
19 Symfony\UX\Icons\UXIconsBundle::class => ['all' => true],
20];

#2 demo-3.1.0/src/EventSubscriber/RedirectToPreferredLocaleSubscriber.php:30

  • Warning naming.too_long

    class `RedirectToPreferredLocaleSubscriber` is 35 characters (limit 30); very long names make code hard to read

30final class RedirectToPreferredLocaleSubscriber implements EventSubscriberInterface
31{
32 public function __construct(
33 private readonly UrlGeneratorInterface $urlGenerator,
34 /** @var string[] */
35 private array $enabledLocales,
36 private ?string $defaultLocale = null,
37 ) {
38 if (empty($this->enabledLocales)) {
39 throw new \UnexpectedValueException('The list of supported locales must not be empty.');

#3 demo-3.1.0/src/Command/AddUserCommand.php:91

  • Warning length.function

    AddUserCommand::interact has 56 lines in its body, above 50

91 protected function interact(InputInterface $input, OutputInterface $output): void
92 {
93 /** @var string|null $username */
94 $username = $input->getArgument('username');
95 /** @var string|null $password */
96 $password = $input->getArgument('password');
97 /** @var string|null $email */
98 $email = $input->getArgument('email');
99 /** @var string|null $fullName */
100 $fullName = $input->getArgument('full-name');

#4 demo-3.1.0/src/Controller/UserController.php:63

  • Warning duplication.repeated_block

    lines 63 to 71 repeat lines 39 to 47 (54 tokens); repeated code has to be fixed in every copy

63 Request $request,
64 EntityManagerInterface $entityManager,
65 Security $security,
66 ): Response {
67 $form = $this->createForm(ChangePasswordType::class, $user);
68 $form->handleRequest($request);
69
70 if ($form->isSubmitted() && $form->isValid()) {
71 $entityManager->flush();
72

#5 demo-3.1.0/tests/Form/DataTransformer/TagArrayToStringTransformerTest.php:24

  • Warning naming.too_long

    class `TagArrayToStringTransformerTest` is 31 characters (limit 30); very long names make code hard to read

24final class TagArrayToStringTransformerTest extends TestCase
25{
26 /**
27 * Ensures that tags are created correctly.
28 */
29 public function testCreateTheRightAmountOfTags(): void
30 {
31 $tags = $this->getMockedTransformer()->reverseTransform('Hello, Demo, How');
32
33 $this->assertCount(3, $tags);

#6 demo-3.1.0/src/Entity/User.php:161

  • Warning naming.generic

    parameter `data` is a generic name; it says nothing about what it holds

161 public function __unserialize(array $data): void
162 {
163 [$this->id, $this->username, $this->password] = $data;
164 }
165}

#7 demo-3.1.0/src/Twig/SourceCodeExtension.php:136

  • Warning naming.too_short

    variable `r` is 1 character (at least 2); a one letter name hides its meaning

136 $r = new \ReflectionObject($callable);
137
138 return $r->getMethod('__invoke');
139 }
140
141 return new \ReflectionFunction($callable);
142 }
143
144 /**
145 * @return array{file_path: string|false, starting_line: int, source_code: string}

Full engine output

All 7 findings, exactly as the engine printed them: symfony-demo.txt (plain text).