portal.mkgtu.ru/console/controllers/ExtendedMessageController.php

297 lines
10 KiB
PHP
Raw Permalink Normal View History

2024-03-28 09:51:45 +03:00
<?php
namespace console\controllers;
use Yii;
use yii\base\InvalidConfigException;
use yii\base\UserException;
use yii\helpers\ArrayHelper;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use yii\helpers\VarDumper;
class ExtendedMessageController extends \yii\console\controllers\MessageController
{
public function actionReplaceSourceLanguage($configFile, $newSourceLanguage = false)
{
$config = [
'translator' => 'Yii::t',
'overwrite' => false,
'removeUnused' => false,
'sort' => false,
'format' => 'php',
];
$configFile = Yii::getAlias($configFile);
if (!is_file($configFile)) {
throw new UserException("The configuration file does not exist: $configFile");
}
$config = array_merge($config, require($configFile));
if (!is_dir($config['sourcePath'])) {
throw new UserException("The source path {$config['sourcePath']} is not a valid directory.");
}
$files = FileHelper::findFiles(realpath($config['sourcePath']), $config);
$unremoved = [];
foreach ($files as $fileName) {
if (!is_array($config['translator'])) {
$translator = [$config['translator']];
}
foreach ($translator as $currentTranslator) {
$n = 0;
$subject = file_get_contents($fileName);
$replacedSubject = preg_replace_callback(
'/\b(\\\\)?' . $currentTranslator . '\s*\(\s*(\'.*?(?<!\\\\)\'|".*?(?<!\\\\)")\s*,\s*(\'.*?(?<!\\\\)\'|".*?(?<!\\\\)")\s*[,\)]/s',
function ($matches) use ($newSourceLanguage, $fileName, &$unremoved) {
$category = substr($matches[2], 1, -1);
$message = $matches[3];
if ($newSourceLanguage !== false) {
$message = eval("return {$message};");
$result = str_replace($message, Yii::t($category, $message, [], $newSourceLanguage), $matches[0]);
} else {
if (strpos($matches[0], ')') != strlen((string)$matches[0]) - 1) {
$unremoved[$fileName][] = $message;
$result = $matches[0];
} else {
$result = $message;
}
}
return $result;
},
$subject,
-1,
$n
);
if (file_put_contents($fileName, $replacedSubject) !== false) {
Console::output("File: {$fileName}; Translator: {$currentTranslator}; Affected: {$n}");
} else {
Console::error("File: {$fileName}; Translator: {$currentTranslator}; Affected: {$n}");
};
}
}
if ($newSourceLanguage == false && !empty($unremoved)) {
Console::output('Messages with params, can`t be removed by this tool. Remove it manually');
foreach ($unremoved as $fileName => $messages) {
$messages = implode(PHP_EOL, $messages);
Console::output("$fileName:".PHP_EOL.$messages);
}
}
}
public function actionMigrate($inputConfigFile, $outputConfigFile)
{
$inputConfigFile = Yii::getAlias($inputConfigFile);
if (!is_file($inputConfigFile)) {
throw new \Exception("The configuration file does not exist: $inputConfigFile");
}
$inputConfig = array_merge([
'translator' => 'Yii::t',
'overwrite' => false,
'removeUnused' => false,
'sort' => false,
'format' => 'php',
], require($inputConfigFile));
switch($inputConfig['format']){
case 'php':
$messages = $this->readFromPhpInput($inputConfig);
break;
case 'db':
$messages = $this->readFromDbInput($inputConfig);
break;
case 'po':
$messages = $this->readFromPoInput($inputConfig);
break;
default:
throw new InvalidConfigException('Unknown input format '.$inputConfig['format']);
}
if ($this->confirm('All existing messages in the output source will be removed. Proceed?')) {
$outputConfigFile = Yii::getAlias($outputConfigFile);
if (!is_file($outputConfigFile)) {
throw new \Exception("The configuration file does not exist: $outputConfigFile");
}
$outputConfig = array_merge([
'translator' => 'Yii::t',
'overwrite' => false,
'removeUnused' => false,
'sort' => false,
'format' => 'php',
], require($outputConfigFile));
switch($outputConfig['format']){
case 'php':
$this->saveToPhpOutput($messages, $outputConfig);
break;
case 'db':
$this->saveToDbOutput($messages, $outputConfig);
break;
case 'po':
$this->saveToPoOutput($messages, $outputConfig);
break;
default:
throw new InvalidConfigException('Unknown output format');
}
};
}
protected function readFromPhpInput($config)
{
$messages = [];
foreach ($config['languages'] as $language) {
$messagePath = Yii::getAlias("$config[messagePath]/$language");
$files = FileHelper::findFiles(FileHelper::normalizePath($messagePath));
foreach ($files as $file) {
$category = pathinfo($file, PATHINFO_FILENAME);
$messages[$language][$category] = require($file);
}
}
return $messages;
}
protected function readFromDbInput($config)
{
$messages = [];
$db = Yii::$app->get(isset($config['db']) ? $config['db'] : 'db');
$sourceMessageTable = isset($config['sourceMessageTable']) ? $config['sourceMessageTable'] : '{{%source_message}}';
$messageTable = isset($config['messageTable']) ? $config['messageTable'] : '{{%message}}';
if (!$db instanceof \yii\db\Connection) {
throw new \Exception('The "db" option must refer to a valid database application component.');
}
$q = new \yii\db\Query;
Console::output('Reading messages from database');
$sourceMessages = $q->select(['*'])->from($sourceMessageTable)->all();
foreach ($config['languages'] as $language) {
$translations = $q->select(['*'])->from($messageTable)->where(['language'=>$language])->indexBy('id')->all();
foreach ($sourceMessages as $row) {
$translation = ArrayHelper::getValue($translations, $row['id']);
$messages[$language][$row['category']][$row['message']] = $translation ? $translation['translation'] : null;
}
}
return $messages;
}
protected function readFromPoInput($config)
{
throw new \Exception("PO migration didn't implemented yet");
}
protected function saveToDbOutput($messages, $config)
{
$db = Yii::$app->get(isset($config['db']) ? $config['db'] : 'db');
$sourceMessageTable = isset($config['sourceMessageTable']) ? $config['sourceMessageTable'] : '{{%source_message}}';
$messageTable = isset($config['messageTable']) ? $config['messageTable'] : '{{%message}}';
if (!$db instanceof \yii\db\Connection) {
throw new \Exception('The "db" option must refer to a valid database application component.');
}
$db->createCommand()->truncateTable($messageTable)->execute();
$db->createCommand()->delete($sourceMessageTable)->execute();
$insertedSourceMessages = [];
foreach ($messages as $language => $categories) {
Console::output("Language: $language");
foreach ($categories as $category => $msgs) {
$messagesCount = count($msgs, COUNT_RECURSIVE);
$i = 0;
Console::output("Category: $category");
Console::startProgress(0, $messagesCount);
foreach ($msgs as $m => $translation) {
Console::updateProgress(++$i, $messagesCount);
$lastId = array_search($m, ArrayHelper::getValue($insertedSourceMessages, $category, []));
if ($lastId == false) {
$db->createCommand()
->insert($sourceMessageTable, ['category' => $category, 'message' => $m])->execute();
$lastId = $db->getLastInsertID($db->driverName == 'pgsql' ? 'i18n_source_message_id_seq' : null);
$insertedSourceMessages[$category][$lastId] = $m;
}
$db->createCommand()
->insert($messageTable, ['id' => $lastId, 'language' => $language, 'translation'=>$translation])->execute();
}
Console::endProgress();
}
}
}
protected function saveToPhpOutput($messages, $config)
{
foreach ($messages as $language => $categories) {
$dirName = FileHelper::normalizePath(Yii::getAlias($config['messagePath'].'/'.$language));
FileHelper::createDirectory($dirName);
Console::output("Language: $language");
foreach ($categories as $category => $msgs) {
$array = VarDumper::export($msgs);
$content = "<?php\r\nreturn $array;\r\n";
$fileName = str_replace("\\", '/', "$dirName/$category.php");
if (file_put_contents($fileName, $content)) {
Console::output("Saved $fileName");
}
}
}
}
protected function saveToPoOutput($messages, $config)
{
throw new \Exception("PO migration didn't implemented yet");
}
}