diff --git a/.gitignore b/.gitignore
index 298f1e8..ecdb4c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,5 @@
###> smartbooster/standard-bundle ###
/.phpcs-cache
###< smartbooster/standard-bundle ###
+/.php-cs-fixer.cache
+/php_cs_fixer_report.json
diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php
new file mode 100644
index 0000000..c654f43
--- /dev/null
+++ b/.php-cs-fixer.dist.php
@@ -0,0 +1,47 @@
+in(__DIR__)
+ ->exclude('var')
+ ->exclude('vendor')
+ ->exclude('node_modules')
+ ->append([
+ 'bin/console',
+ ])
+ ->path([
+ 'bin/',
+ 'config/',
+ 'public/',
+ 'src/',
+ 'tests/',
+ ])
+;
+
+return (new PhpCsFixer\Config())
+ ->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect())
+ ->setRiskyAllowed(true)
+ ->setRules([
+ '@Symfony' => true,
+ # rules to keep
+ 'class_definition' => [
+ 'multi_line_extends_each_single_line' => true, # https://cs.symfony.com/doc/rules/class_notation/class_definition.html#example-4
+ ],
+ 'concat_space' => ['spacing' => 'one'], # the @PER like PSR12 preserve space
+ 'no_null_property_initialization' => false,
+ # rules to check with sfcs-diff
+ 'phpdoc_summary' => false, #39
+ 'yoda_style' => false, #35
+ 'phpdoc_separation' => false, #24
+ 'single_quote' => false, #16
+ 'ordered_imports' => false, #16
+ 'no_superfluous_phpdoc_tags' => false, #12
+ 'no_empty_phpdoc' => false, #9
+ 'trailing_comma_in_multiline' => false, #8
+ 'phpdoc_align' => false, #7
+ 'increment_style' => false, #5
+ 'blank_line_before_statement' => false, #5
+ 'no_extra_blank_lines' => false, #4
+ 'single_space_around_construct' => false, #3
+ ])
+ ->setFinder($finder)
+;
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4931063..29a2ce4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
CHANGELOG for 1.x
===================
+## v1.16.3 - (2026-02-26)
+# Fixed
+- QA changes to match standard-bundle related from version ^1.2 : .php-cs-fixer.dist + phpcs security + phpstan lvl10
+
## v1.16.2 - (2025-09-25)
### Added
- `ProcessStatusEnum::addQbOrderBy` Add method to add a qb order by on the enum
diff --git a/bin/console b/bin/console
index 4673200..11ebe70 100755
--- a/bin/console
+++ b/bin/console
@@ -4,11 +4,11 @@
use Smart\CoreBundle\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
-if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
+if (!is_file(dirname(__DIR__) . '/vendor/autoload_runtime.php')) {
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
}
-require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
+require_once dirname(__DIR__) . '/vendor/autoload_runtime.php';
return function (array $context) {
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
diff --git a/composer.json b/composer.json
index f6835a5..d063f81 100644
--- a/composer.json
+++ b/composer.json
@@ -45,9 +45,10 @@
},
"config": {
"allow-plugins": {
+ "dealerdirect/phpcodesniffer-composer-installer": true,
+ "php-http/discovery": true,
"symfony/flex": true,
- "symfony/runtime": true,
- "php-http/discovery": true
+ "symfony/runtime": true
},
"sort-packages": true,
"optimize-autoloader": true,
diff --git a/phpcs.xml b/phpcs.xml
index dbcf602..ac96056 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -9,6 +9,12 @@
+
+
+
+
+
+
diff --git a/phpstan.neon b/phpstan.neon
index e6db36d..2b11364 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -3,15 +3,63 @@ includes:
- vendor/phpstan/phpstan-doctrine/rules.neon
- vendor/phpstan/phpstan-symfony/extension.neon
- vendor/phpstan/phpstan-symfony/rules.neon
+ - ./vendor/yamadashy/phpstan-friendly-formatter/extension.neon
+ - vendor/spaze/phpstan-disallowed-calls/extension.neon
parameters:
+ disallowedFunctionCalls:
+ -
+ function: 'exec()'
+ message: 'for security reasons. Use Symfony Process component instead.'
+ -
+ function: 'eval()'
+ message: 'for security reasons.'
+ -
+ function: 'system()'
+ message: 'for security reasons.'
+ -
+ function: 'passthru()'
+ message: 'for security reasons.'
+ -
+ function: 'shell_exec()'
+ message: 'for security reasons.'
+ -
+ function: 'popen()'
+ message: 'is risky. Ensure you are handling the process handle correctly.'
+ friendly:
+ lineBefore: 0 # Number of lines to display before error line (default: 2)
+ lineAfter: 0 # Number of lines to display after error line (default: 2)
+ errorFormat: friendly
+ reportUnmatchedIgnoredErrors: false
symfony:
containerXmlPath: var/cache/dev/Smart_CoreBundle_KernelDevDebugContainer.xml
ignoreErrors:
# Ignore error by identifier
- identifier: missingType.generics
- identifier: missingType.iterableValue
- - identifier: trait.unused
- # https://github.com/symfony/symfony/issues/36202#issuecomment-769226149
+ - identifier: trait.unused # normal to ignore in the context of the bundle
+ -
+ identifier: class.notFound
+ # False positif post install during github qa
+ path: tests/bootstrap.php # 3
+ -
+ identifier: function.impossibleType
+ # False positif post install during github qa
+ path: tests/bootstrap.php # 1
+ # Level 8 rules to unstack
+ - identifier: argument.type # 44
+ - identifier: return.type # 3
+ # Level 9 rules to unstack
+ - identifier: offsetAccess.nonOffsetAccessible # 10
+ - identifier: foreach.nonIterable # 4
+ - identifier: offsetAccess.invalidOffset # 2
+ # Level 10 rules to unstack
+ - identifier: encapsedStringPart.nonString # 2
+ - identifier: binaryOp.invalid # 4
+
bootstrapFiles:
- vendor/bin/.phpunit/phpunit/vendor/autoload.php
+
+ # définit le répertoire temporaire où PHPStan stocke ses fichiers de cache et de travail pendant l'analyse.
+ # Par défaut: PHPStan utilise le répertoire temporaire système sys_get_temp_dir() . '/phpstan'
+ tmpDir: var/cache/phpstan
diff --git a/src/Command/EntityCleanupCommand.php b/src/Command/EntityCleanupCommand.php
index a6217ed..bf87a09 100644
--- a/src/Command/EntityCleanupCommand.php
+++ b/src/Command/EntityCleanupCommand.php
@@ -114,7 +114,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$propertiesToClean = $config['properties_to_clean'];
$removeEntity = empty($propertiesToClean);
foreach ($entities as $entity) {
- $this->processMonitor->log(sprintf("%d) #%d début nettoyage ...", $i, $entity->getId()));
+ $this->processMonitor->log(sprintf("%d) #%d début nettoyage ...", $i, $entity->getId())); // qa: Faux positif @phpstan-ignore method.nonObject
if ($removeEntity) {
$this->entityManager->remove($entity);
} else {
@@ -155,9 +155,9 @@ private function getTargetClass(array $config): string
return Cron::class; // @phpstan-ignore-line
} elseif ($class === 'api_call') {
return ApiCall::class; // @phpstan-ignore-line
- } else {
- return $class;
}
+
+ return $class;
}
public function setCommandConfigs(array $commandConfigs): void
diff --git a/src/Controller/MonitoringController.php b/src/Controller/MonitoringController.php
index f157cbf..3fd8128 100644
--- a/src/Controller/MonitoringController.php
+++ b/src/Controller/MonitoringController.php
@@ -23,10 +23,10 @@ public function uptime(): Response
]);
}
- public function phpinfo(): void
+ public function phpinfo(): void // phpcs:ignore
{
- phpinfo();
- die;
+ phpinfo(); // phpcs:ignore
+ exit;
}
public function simulateIniOverride(IniOverrideConfig $config): Response
@@ -53,7 +53,7 @@ public function dateFormatting(): Response
$content = "CURRENT TIME\n\n";
$content .= "default date function : \n" . date($format) . "\n";
$content .= "Datetime format : \n" . $datetime->format($format) . "\n";
- $content .= "date_format function : \n" . date_format($datetime, ($format)) . "\n";
+ $content .= "date_format function : \n" . date_format($datetime, $format) . "\n";
$content .= "IntlDateFormatter format : \n" . $formatter->format($datetime) . "\n";
$content .= "Timezone name : \n" . $datetime->getTimezone()->getName() . "\n";
diff --git a/src/Entity/MailableInterface.php b/src/Entity/MailableInterface.php
index 5b940c2..cec0e4a 100644
--- a/src/Entity/MailableInterface.php
+++ b/src/Entity/MailableInterface.php
@@ -16,6 +16,8 @@ interface MailableInterface extends \Stringable
* For example : getEmail() ?? getEmail2()
*/
public function getRecipientEmail(): ?string;
+
public function getCc(): ?string;
+
public function getCci(): ?string;
}
diff --git a/src/Entity/OrganizationTrait.php b/src/Entity/OrganizationTrait.php
index 2192508..2da6f12 100644
--- a/src/Entity/OrganizationTrait.php
+++ b/src/Entity/OrganizationTrait.php
@@ -3,7 +3,6 @@
namespace Smart\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
-use Smart\CoreBundle\Entity\AddressTrait;
use Symfony\Component\Validator\Constraints as Assert;
trait OrganizationTrait
diff --git a/src/Enum/ProcessStatusEnum.php b/src/Enum/ProcessStatusEnum.php
index 5b3442f..dd03a1f 100644
--- a/src/Enum/ProcessStatusEnum.php
+++ b/src/Enum/ProcessStatusEnum.php
@@ -72,6 +72,6 @@ public static function addQbOrderBy(QueryBuilder $qb, string $field, string $ord
$qb->setParameter($sortParamName, $case->value);
}
$sort .= ')';
- $qb->orderBy($sort, $order);
+ $qb->orderBy($sort, $order); // @phpcs:ignore
}
}
diff --git a/src/EventListener/HistoryLoggerListener.php b/src/EventListener/HistoryLoggerListener.php
index 324cb63..760c9bf 100644
--- a/src/EventListener/HistoryLoggerListener.php
+++ b/src/EventListener/HistoryLoggerListener.php
@@ -39,7 +39,7 @@ public function onKernelController(ControllerEvent $event): void
{
// Set the context base on the domain
$request = $this->requestStack->getCurrentRequest();
- $this->context = RequestUtils::getContextFromHost($request->getHost(), $this->domain);
+ $this->context = RequestUtils::getContextFromHost($request->getHost(), $this->domain); // qa: Faux positif car dans le context Controller on a bien toujours l'objet request @phpstan-ignore method.nonObject
$this->historyLogger->setContext($this->context);
// Set the origin based on the action controller
diff --git a/src/Form/DataTransformer/ParentFileTransformer.php b/src/Form/DataTransformer/ParentFileTransformer.php
index cef915c..3d04583 100644
--- a/src/Form/DataTransformer/ParentFileTransformer.php
+++ b/src/Form/DataTransformer/ParentFileTransformer.php
@@ -20,8 +20,8 @@ public function transform($value)
public function reverseTransform($value)
{
- if ($value !== null && $value->getParent() === null) {
- $value->setParent($this->parent);
+ if ($value !== null && $value->getParent() === null) { // qa: todo à typer @phpstan-ignore method.nonObject
+ $value->setParent($this->parent); // qa: todo à typer @phpstan-ignore method.nonObject
}
return $value;
diff --git a/src/Monitoring/ApiCallMonitor.php b/src/Monitoring/ApiCallMonitor.php
index 11e2fa4..e23b214 100644
--- a/src/Monitoring/ApiCallMonitor.php
+++ b/src/Monitoring/ApiCallMonitor.php
@@ -57,8 +57,9 @@ public function restart(ApiCallInterface $apiCall): ResponseInterface
{
$route = $apiCall->getType();
if (!in_array($route, $this->restartAllowedRoutes)) {
- throw new AccessDeniedHttpException("The API route '$route' is not allowed to be restarted. " .
- "Add it to the `smart_core.monitoring_api_restart_allowed_routes` config if you want to restart it.");
+ // phpcs:disable
+ throw new AccessDeniedHttpException("The API route '$route' is not allowed to be restarted. Add it to the `smart_core.monitoring_api_restart_allowed_routes` config if you want to restart it.");
+ // phpcs:enable
}
$options = ['headers' => $apiCall->getHeaders()];
diff --git a/src/Monitoring/ProcessMonitor.php b/src/Monitoring/ProcessMonitor.php
index d4b7b2c..04bfedc 100644
--- a/src/Monitoring/ProcessMonitor.php
+++ b/src/Monitoring/ProcessMonitor.php
@@ -43,7 +43,7 @@ public function end(?ProcessInterface $process, bool $isSuccess = true, bool $fl
$endedAt = new \DateTime();
$process->setEndedAt($endedAt);
- $process->setDuration((int) $endedAt->format('Uv') - (int) $process->getStartedAt()->format('Uv'));
+ $process->setDuration((int) $endedAt->format('Uv') - (int) $process->getStartedAt()?->format('Uv'));
if ($isSuccess) {
$process->setStatus(ProcessStatusEnum::SUCCESS);
} else {
diff --git a/src/Query/MySQL/GroupConcat.php b/src/Query/MySQL/GroupConcat.php
index fb8331a..3177c6c 100644
--- a/src/Query/MySQL/GroupConcat.php
+++ b/src/Query/MySQL/GroupConcat.php
@@ -72,13 +72,13 @@ public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker): string
$fields = [];
foreach ($this->pathExp as $pathExp) {
- $fields[] = $pathExp->dispatch($sqlWalker);
+ $fields[] = $pathExp->dispatch($sqlWalker); // qa: Faux positif @phpstan-ignore method.nonObject
}
$result .= sprintf('%s', implode(', ', $fields));
if ($this->orderBy) {
- $result .= ' ' . $sqlWalker->walkOrderByClause($this->orderBy);
+ $result .= ' ' . $sqlWalker->walkOrderByClause($this->orderBy); // phpcs:ignore
}
if ($this->separator) {
diff --git a/src/Utils/DateUtils.php b/src/Utils/DateUtils.php
index c7ed9d8..436610c 100644
--- a/src/Utils/DateUtils.php
+++ b/src/Utils/DateUtils.php
@@ -110,9 +110,9 @@ public static function getDaysBetween(\DateTimeInterface $startedAt, \DateTimeIn
$isAfterEndHour = ((int) $endedAt->format('H')) >= $options['end_hour'];
if (
- ($startedAt->format($dateFormat) === $endedAt->format($dateFormat) && (!$isBeforeStartHour || !$isAfterEndHour)) ||
- ($date->format($dateFormat) === $startedAt->format($dateFormat) && !$isBeforeStartHour) ||
- ($date->format($dateFormat) === $endedAt->format($dateFormat) && !$isAfterEndHour)
+ ($startedAt->format($dateFormat) === $endedAt->format($dateFormat) && (!$isBeforeStartHour || !$isAfterEndHour))
+ || ($date->format($dateFormat) === $startedAt->format($dateFormat) && !$isBeforeStartHour)
+ || ($date->format($dateFormat) === $endedAt->format($dateFormat) && !$isAfterEndHour)
) {
continue;
}
@@ -136,7 +136,7 @@ public static function getCalendarDays(int $month, int $year): array
$firstDayOfCalendar->modify('last Monday');
}
- $lastDayOfMonth = clone (new \DateTime())->setDate($year, $month, (int)$fistDayOfMonth->format('t'));
+ $lastDayOfMonth = clone (new \DateTime())->setDate($year, $month, (int) $fistDayOfMonth->format('t'));
$lastDayOfCalendar = clone $lastDayOfMonth;
// we will only search for the next Sunday if the day number is different from Sunday (7)
if ($lastDayOfMonth->format('N') !== '7') {
@@ -154,12 +154,12 @@ public static function getCalendarDays(int $month, int $year): array
'isSameMonth' => (int) $currentDay->format('n') === $month,
'isSameDay' => $today->format('d') === $currentDay->format('d') && (int) $currentDay->format('n') === $month,
'isToday' => $isToday,
- 'isWeekend' => (int) $currentDay->format('N') === 6 || (int)$currentDay->format('N') === 7,
+ 'isWeekend' => (int) $currentDay->format('N') === 6 || (int) $currentDay->format('N') === 7,
'isBeforeToday' => !$isToday && $currentDay < $today,
];
$currentDay->modify('+1 day');
- };
+ }
return $toReturn;
}
@@ -426,7 +426,7 @@ public static function getNextBirthdayDateTime(\DateTimeInterface $birthday, ?\D
if (!$currentDay instanceof \DateTime) {
$currentDay = new \DateTime();
}
- $nextBirthday->setDate((int)$currentDay->format('Y'), (int)$birthday->format('m'), (int)$birthday->format('d'));
+ $nextBirthday->setDate((int) $currentDay->format('Y'), (int) $birthday->format('m'), (int) $birthday->format('d'));
if ($nextBirthday <= $currentDay) {
$nextBirthday->modify('next year');
}
diff --git a/src/Utils/StringUtils.php b/src/Utils/StringUtils.php
index 13e3b2f..4ef20e7 100644
--- a/src/Utils/StringUtils.php
+++ b/src/Utils/StringUtils.php
@@ -117,7 +117,7 @@ public static function intToExcelColumn(int $n): string
$n--; // Decrement $n to match Excel's 1-based indexing
$remainder = $n % 26;
$result = chr(65 + $remainder) . $result;
- $n = (int)($n / 26);
+ $n = (int) ($n / 26);
}
return $result;
diff --git a/src/Validator/Constraints/FileRequiredOnNewValidator.php b/src/Validator/Constraints/FileRequiredOnNewValidator.php
index e03e3d2..f1af965 100644
--- a/src/Validator/Constraints/FileRequiredOnNewValidator.php
+++ b/src/Validator/Constraints/FileRequiredOnNewValidator.php
@@ -21,10 +21,10 @@ public function validate($value, Constraint $constraint): void
$object = $this->context->getObject();
// Need symfony/form dependency
if ($object instanceof FormInterface) { // MDT adjust if use the contraints from collection
- $object = $object->getParent()->getData();
+ $object = $object->getParent()->getData(); // qa: Faux positif @phpstan-ignore method.nonObject
}
- if ($object !== null && $object->getId() === null && $object->getFile() === null) {
+ if ($object !== null && $object->getId() === null && $object->getFile() === null) { // qa: Faux positif @phpstan-ignore-line
$this->context->buildViolation($constraint->message)
->atPath('file')
->addViolation();
diff --git a/tests/Utils/ArrayUtilsTest.php b/tests/Utils/ArrayUtilsTest.php
index 6f882d6..d103746 100644
--- a/tests/Utils/ArrayUtilsTest.php
+++ b/tests/Utils/ArrayUtilsTest.php
@@ -24,7 +24,7 @@ public static function getArrayFromTextareaProvider(): array
return [
'clean textarea' => [
// expected
- ["some","text"],
+ ["some", "text"],
// values
"some
@@ -32,7 +32,7 @@ public static function getArrayFromTextareaProvider(): array
],
'no special char deleted' => [
// expected
- ["some,","exemple;", "text*"],
+ ["some,", "exemple;", "text*"],
// values
"some,
exemple;
@@ -448,7 +448,7 @@ public static function getRemoveEmptyProvider(): array
2 => "exemple",
4 => "text"
],
- ["", "some","exemple", "", "text", null, ""]
+ ["", "some", "exemple", "", "text", null, ""]
],
];
}
diff --git a/tests/Utils/MathUtilsTest.php b/tests/Utils/MathUtilsTest.php
index 978a857..35e88fa 100644
--- a/tests/Utils/MathUtilsTest.php
+++ b/tests/Utils/MathUtilsTest.php
@@ -2,7 +2,6 @@
namespace Smart\CoreBundle\Tests\Utils;
-use App\Utils\NumberUtils;
use Smart\CoreBundle\Utils\MathUtils;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProvider;
diff --git a/tests/Utils/StringUtilsTest.php b/tests/Utils/StringUtilsTest.php
index e40e096..7319a2a 100644
--- a/tests/Utils/StringUtilsTest.php
+++ b/tests/Utils/StringUtilsTest.php
@@ -192,7 +192,7 @@ public static function intToExcelColumnProvider(): array
'lower 0' => ['', -1],
'0' => ['', 0],
'lower to 26' => ['A', 1],
- 'last letter 26' => ['Z', 26 ],
+ 'last letter 26' => ['Z', 26],
'after the 26 letter' => ['AA', 27],
'double alphabetical' => ['AZ', 52],
'past double alphabetical' => ['BA', 53],
@@ -281,7 +281,6 @@ public static function getFirstNameProvider()
];
}
-
#[DataProvider('formatSpaceBetweenProvider')]
public function testFormatSpaceBetween(string $expected, ?string $first, ?string $last): void
{