Skip to content

Commit

Permalink
Merge branch 'next-30847/prevent-after-statements-phpstan-rule' into …
Browse files Browse the repository at this point in the history
…'trunk'

NEXT-30847 - Add AFTER statement rule

See merge request shopware/6/product/platform!11587
  • Loading branch information
OliverSkroblin committed Oct 17, 2023
2 parents a08b578 + 5979fad commit 618d5db
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: phpstan-rule-to-prevent-after-statement-in-migration
issue: NEXT-30847
author: Alexandru Dumea
author_email: [email protected]
author_github: Alexandru Dumea
---
# Core
* Added a PHPStan rule, NoAfterStatementRule.php, to prevent using AFTER statement in migrations
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php declare(strict_types=1);

namespace Shopware\Core\DevOps\StaticAnalyze\PHPStan\Rules;

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use Shopware\Core\Framework\Log\Package;
use Shopware\Core\Framework\Migration\MigrationStep;

/**
* @internal
*
* @implements Rule<MethodCall>
*/
#[Package('core')]
class NoAfterStatementRule implements Rule
{
private const CUTOFF_UNIX_TIMESTAMP = '2023-10-11 00:00:00';

public function getNodeType(): string
{
return MethodCall::class;
}

public function processNode(Node $node, Scope $scope): array
{
if (!$node instanceof MethodCall) {
return [];
}

if (!$this->isRecentMigration($scope)) {
return [];
}

if (!$node->name instanceof Node\Identifier) {
return [];
}

if (empty($node->getArgs())) {
return [];
}

$arg = $node->getArgs()[0]->value;
if (!$arg instanceof Node\Scalar\String_) {
return [];
}

$pattern = '/ALTER\s+TABLE\s+.+?\s+ADD\s+.+?\s+AFTER\s+`?[a-zA-Z0-9_]+`?/i';

if (preg_match($pattern, $arg->value)) {
return ['Usage of ALTER TABLE .. AFTER is disallowed in migrations to avoid implicit temporary table usage.'];
}

return [];
}

private function isRecentMigration(Scope $scope): bool
{
$class = $scope->getClassReflection();
if (!$class || !$class->isSubclassOf(MigrationStep::class)) {
return false;
}

$className = substr($class->getName(), strrpos($class->getName(), '\\') + 1);

if (preg_match('/Migration(\d{10})/', $className, $matches)) {
$migrationUnixTimestamp = (int) $matches[1];
$cutoffUnixTimestamp = strtotime(self::CUTOFF_UNIX_TIMESTAMP);

return $migrationUnixTimestamp > $cutoffUnixTimestamp;
}

return false;
}
}
3 changes: 2 additions & 1 deletion src/Core/DevOps/StaticAnalyze/PHPStan/core-rules.neon
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ rules:
- Shopware\Core\DevOps\StaticAnalyze\PHPStan\Rules\FinalClassRule
- Shopware\Core\DevOps\StaticAnalyze\PHPStan\Rules\DecorationPatternRule
- Shopware\Core\DevOps\StaticAnalyze\PHPStan\Rules\PackageAnnotationRule
- Shopware\Core\DevOps\StaticAnalyze\PHPStan\Rules\DomainExceptionRule
- Shopware\Core\DevOps\StaticAnalyze\PHPStan\Rules\DomainExceptionRule
- Shopware\Core\DevOps\StaticAnalyze\PHPStan\Rules\NoAfterStatementRule

0 comments on commit 618d5db

Please sign in to comment.