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

Use the file 1's value, rather in file 2, when syncing and line the key has been rewritten #9

Merged
merged 5 commits into from
Sep 23, 2024
Merged
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
15 changes: 15 additions & 0 deletions src/IO/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

namespace SupportPal\LanguageTools\IO;

use RuntimeException;

use function file_get_contents;
use function sprintf;

class File
{
/** @var string */
Expand All @@ -22,4 +27,14 @@ protected function validate(string $file1, string $file2): bool
{
return true;
}

protected function getFileContents(string $path): string
{
$contents = file_get_contents($path);
if ($contents === false) {
throw new RuntimeException(sprintf('Failed to read contents of %s.', $path));
}

return $contents;
}
}
55 changes: 44 additions & 11 deletions src/IO/Sync/SyncFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
namespace SupportPal\LanguageTools\IO\Sync;

use InvalidArgumentException;
use RuntimeException;
use SupportPal\LanguageTools\IO\File;

use function addcslashes;
use function file_exists;
use function file_get_contents;
use function file_put_contents;
use function is_array;
use function preg_match_all;
use function preg_quote;
use function preg_replace_callback;
use function sprintf;
use function str_replace;
use function str_split;
use function substr;
use function substr_count;
use function uniqid;

use const PHP_EOL;
use const PREG_OFFSET_CAPTURE;

class SyncFile extends File
{
/** @var string */
Expand All @@ -28,13 +32,8 @@ class SyncFile extends File

public function sync(): self
{
$contents = file_get_contents($this->file1);
if ($contents === false) {
throw new RuntimeException('Failed to read file contents.');
}

$this->uniqId = uniqid('__');
$this->contents = $contents;
$this->contents = $this->getFileContents($this->file1);
if (file_exists($this->file2)) {
$this->replaceArray(require $this->file2);
}
Expand Down Expand Up @@ -77,14 +76,25 @@ private function replaceArray(array $data): void

private function replaceValue(string $key, string $value): void
{
$lineNumberFile1 = $this->getLineNumber($this->contents, $key);
$lineNumberFile2 = $this->getLineNumber($this->getFileContents($this->file2), $key);

$contents = preg_replace_callback(
$this->getRegex($key),
function (array $matches) use ($key, $value) {
function (array $matches) use ($key, $value, $lineNumberFile1, $lineNumberFile2) {
// Use file 1's value.
if ($lineNumberFile1 !== $lineNumberFile2) {
return str_replace($key, $key . $this->uniqId, $matches[1])
. $matches['value']
. $matches[5];
}

$usingDoubleQuotes = substr($matches[1], -1) === '"';

// Use file 2's value.
return str_replace($key, $key . $this->uniqId, $matches[1])
. $this->mapValue($value, $usingDoubleQuotes)
. $matches[4];
. $matches[5];
},
$this->contents,
1
Expand All @@ -100,7 +110,7 @@ function (array $matches) use ($key, $value) {
private function getRegex(string $key): string
{
return sprintf(
'/^(\s*(["\'])%s\2\s*=>\s*([\'"]))(?:[^"\\\\]|\\\\.)*(\3,?.*?)$/m',
'/^(\s*(["\'])%s\2\s*=>\s*([\'"]))(?<value>(?:[^"\\\\]|\\\\.)*)(\3,?.*?)$/m',
preg_quote($key, '/')
);
}
Expand All @@ -112,4 +122,27 @@ private function mapValue(string $value, bool $usingDoubleQuotes): string

return $escapedValue;
}

/**
* If a key is duplicated in the array, only the line number of the first matching is returned.
*/
private function getLineNumber(string $contents, string $key): ?int
{
preg_match_all($this->getRegex($key), $contents, $matches, PREG_OFFSET_CAPTURE);

foreach ($matches[0] as $match) {
if ($match[1] < 1) {
continue;
}

$string = str_split($contents, $match[1]);
if (! isset($string[0])) {
continue;
}

return substr_count($string[0], PHP_EOL) + 1;
}

return null;
}
}
15 changes: 15 additions & 0 deletions tests/SyncFileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ public function syncProvider(): iterable
"array" => "The :attribute must have between :min and :max items.",
],
];
'
];

yield [
$base . '/en/replaced-strings.php',
$base . '/es/replaced-strings.php',
'<?php declare(strict_types=1);

return [
/*
* 1.0.0
*/
"foo" => "Foo Bar",
"bar" => "Bar",
];
'
];
}
Expand Down
9 changes: 9 additions & 0 deletions tests/__fixtures__/sync/en/replaced-strings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php declare(strict_types=1);

return [
/*
* 1.0.0
*/
"foo" => "Foo Bar",
"bar" => "Bar",
];
5 changes: 5 additions & 0 deletions tests/__fixtures__/sync/es/replaced-strings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php declare(strict_types=1);

return [
"foo" => "Foo",
];