CommentInsertionRule.php•3.7 kB
<?php
declare(strict_types=1);
namespace Butschster\ContextGenerator\Modifier\Sanitizer\Rule;
/**
* Rule for inserting comments into the code
*
* This rule inserts comments at various positions in the code to mark it as sanitized,
* indicate restrictions, or provide warnings about its use.
*/
final readonly class CommentInsertionRule implements RuleInterface
{
/**
* @param string $name Unique rule name
* @param string $fileHeaderComment Comment to insert at the top of file
* @param string $classComment Comment to insert before class definitions
* @param string $methodComment Comment to insert before method definitions
* @param int $frequency How often to insert random comments (1 = every line, 5 = every 5th line)
* @param array<string> $randomComments Array of random comments to insert
*/
public function __construct(
private string $name,
private string $fileHeaderComment = '',
private string $classComment = '',
private string $methodComment = '',
private int $frequency = 0,
private array $randomComments = [],
) {}
public function getName(): string
{
return $this->name;
}
public function apply(string $content): string
{
// Add file header comment
if (!empty($this->fileHeaderComment)) {
$comment = $this->formatPhpComment($this->fileHeaderComment);
$content = $comment . PHP_EOL . PHP_EOL . $content;
}
// Add class comments
if (!empty($this->classComment)) {
$comment = $this->formatPhpComment($this->classComment);
$content = (string) \preg_replace(
'/(class|interface|trait|enum)\s+([a-zA-Z0-9_]+)/',
PHP_EOL . $comment . PHP_EOL . '$1 $2',
$content,
);
}
// Add method comments
if (!empty($this->methodComment)) {
$comment = $this->formatPhpComment($this->methodComment);
$content = (string) \preg_replace(
'/(\s+)public|private|protected\s+function/',
'$1' . PHP_EOL . '$1' . $comment . PHP_EOL . '$1$0',
(string) $content,
);
}
// Add random comments
if ($this->frequency > 0 && !empty($this->randomComments)) {
$lines = \explode(PHP_EOL, (string) $content);
$result = [];
foreach ($lines as $i => $line) {
$result[] = $line;
if ($i % $this->frequency === 0 && \trim($line) !== '') {
$randomComment = $this->randomComments[\array_rand($this->randomComments)];
$indentation = '';
// Try to detect indentation level
if (\preg_match('/^(\s+)/', $line, $matches)) {
$indentation = $matches[1];
}
$result[] = $indentation . '// ' . $randomComment;
}
}
$content = \implode(PHP_EOL, $result);
}
return $content;
}
/**
* Format a comment string as a PHP doc-block or inline comment
*/
private function formatPhpComment(string $comment): string
{
if (\str_contains($comment, PHP_EOL)) {
// Multi-line comment
$lines = \explode(PHP_EOL, $comment);
$result = "/**" . PHP_EOL;
foreach ($lines as $line) {
$result .= " * " . $line . PHP_EOL;
}
$result .= " */";
return $result;
}
// Single line comment
return "// " . $comment;
}
}