Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add possibility to extend regex functionality #4

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"openai-php/client": "^0.10.1",
"deeplcom/deepl-php": "^1.9"
},
"scripts": {
"test": "vendor/bin/phpunit tests"
},
"config": {
"allow-plugins": {
"php-http/discovery": true
Expand Down
58 changes: 41 additions & 17 deletions src/Extractor/RegexExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,59 @@

namespace Bottelet\TranslationChecker\Extractor;

use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use SplFileInfo;

class RegexExtractor implements ExtractorContract
{
/**
* @var array<string, string>
*/
private array $patterns = [
'doubleUnderscoreSyntax' => '/(__\()([\'"])(.*?)\2/',
'tSyntax' => '/(?<![\w\$])\$?t\((["\'])(.*?)\1\)/',
'dollarUnderscorePattern' => '/\$_\([\'"]([^\'"]+)[\'"]\)/',
];
/** @var Collection<int, array{regex: string, matchIndex: int, group: string}> */
private Collection $patterns;

public function __construct()
{
$this->patterns = collect([
[
'regex' => '/(__\()([\'"])(.*?)\2/',
'matchIndex' => 3,
'group' => 'doubleUnderscoreSyntax',
],
[
'regex' => '/(?<![\w\$])\$?t\((["\'])(.*?)\1\)/',
'matchIndex' => 2,
'group' => 'tSyntax',
],
[
'regex' => '/\$_\([\'"]([^\'"]+)[\'"]\)/',
'matchIndex' => 1,
'group' => 'dollarUnderscorePattern',
],
]);
}

public function addPattern(string $regex, int $matchIndex, ?string $group = null): void
{
$this->patterns->push([
'regex' => $regex,
'matchIndex' => $matchIndex,
'group' => $group ?? Str::random(10),
]);
}

public function extractFromFile(SplFileInfo $file): array
{
$found = [];
$contents = file_get_contents($file->getRealPath());
if (!$contents) {
return [];
}

if (preg_match_all($this->patterns['doubleUnderscoreSyntax'], $contents, $matches)) {
$found = array_merge($found, $matches[3]);
}
if (preg_match_all($this->patterns['tSyntax'], $contents, $matches)) {
$found = array_merge($found, $matches[2]);
}
if (preg_match_all($this->patterns['dollarUnderscorePattern'], $contents, $matches)) {
$found = array_merge($found, $matches[1]);
$found = [];

/** @var array{regex: string, matchIndex: int, group: string} $pattern */
foreach ($this->patterns as $pattern) {
if (preg_match_all($pattern['regex'], $contents, $matches)) {
$found = array_merge($found, $matches[$pattern['matchIndex']]);
}
}

return $found;
Expand Down
51 changes: 51 additions & 0 deletions tests/Extractors/RegexExtractorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,55 @@ public function should_not_find_emit_request_etc(): void
$this->assertNotContains('request', $translationKeys);
$this->assertNotContains('target', $translationKeys);
}

#[Test]
public function it_accepts_a_new_added_pattern(): void
{
$testPhpContent = <<<'TEXT'
mytranslatefunction('simple_string');
mytranslatefunction('String with "double quotes"');
mytranslatefunction('with :variable test', ['variable' => 'test']);
TEXT;

file_put_contents($this->tempDir . '/test.php', $testPhpContent);

$file = new SplFileInfo($this->tempDir . '/test.php');
$extractor = new RegexExtractor;

$extractor->addPattern('/(mytranslatefunction\()([\'"])(.*?)\2/', 3, 'mytranslatefunction');

$translationKeys = $extractor->extractFromFile($file);

$this->assertCount(3, $translationKeys);
$this->assertContains('simple_string', $translationKeys);
$this->assertContains('String with "double quotes"', $translationKeys);
$this->assertContains('with :variable test', $translationKeys);
}

#[Test]
public function it_accepts_a_new_added_pattern_that_matches_specific_cases(): void
{
$testPhpContent = <<<'TEXT'
mytranslatefunction('simple_string');
mytranslatefunction('String with "double quotes"');
mytranslatefunction('with :variable test', ['variable' => 'test']);
TEXT;

file_put_contents($this->tempDir . '/test.php', $testPhpContent);

$file = new SplFileInfo($this->tempDir . '/test.php');
$extractor = new RegexExtractor;

// Pattern that does not match translations with variables
$extractor->addPattern('/mytranslatefunction\((["\'])(.*?)\1\)/', 2, 'mytranslatefunction');

$translationKeys = $extractor->extractFromFile($file);

$this->assertCount(2, $translationKeys);
$this->assertContains('simple_string', $translationKeys);
$this->assertContains('String with "double quotes"', $translationKeys);

// Assert that the pattern does not match translations with variables
$this->assertNotContains('with :variable test', $translationKeys);
}
}