/**
* Execute the console command.
*
* @return mixed
*/
public function fire()
{
$folders = $this->manager->getPath($this->folders);
$this->display = !$this->option('silent');
$extension = $this->option('php-file-extension');
$obsolete_prefix = empty($this->obsolete_array_key) ? '' : $this->obsolete_array_key . '.';
//////////////////////////////////////////////////
// Display where translations are searched in //
//////////////////////////////////////////////////
if ($this->option('verbose')) {
$this->writeLine("Lemmas will be searched in the following directories:");
foreach ($folders as $path) {
$this->writeLine(' <info>' . $path . '</info>');
}
$this->writeLine('');
}
////////////////////////////////
// Parse all lemmas from code //
////////////////////////////////
$lemmas = $this->manager->extractTranslationsFromFolders($folders, $this->trans_methods, $extension);
if (count($lemmas) === 0) {
$this->writeComment("No lemma has been found in code.");
$this->writeLine("I have searched recursively in PHP files in these directories:");
foreach ($this->manager->getPath($this->folders) as $path) {
$this->writeLine(" " . $path);
}
$this->writeLine("for these functions/methods:");
foreach ($this->trans_methods as $k => $v) {
$this->writeLine(" " . $k);
}
return self::SUCCESS;
}
$this->writeLine(count($lemmas) > 1 ? count($lemmas) . " lemmas have been found in code" : "1 lemma has been found in code");
if ($this->option('verbose')) {
foreach ($lemmas as $key => $value) {
if (strpos($key, '.') !== false) {
$this->writeLine(' <info>' . $key . '</info> in file <comment>' . $this->manager->getShortPath($value) . '</comment>');
}
}
}
/////////////////////////////////////////////
// Convert dot lemmas to structured lemmas //
/////////////////////////////////////////////
if ($this->option('output-flat')) {
$lemmas_structured = $this->manager->convertLemmaToFlatArray($lemmas);
} else {
$lemmas_structured = $this->manager->convertLemmaToStructuredArray($lemmas);
}
$this->writeLine('');
/////////////////////////////////////
// Generate lang files : //
// - add missing lemmas on top //
// - keep already defined lemmas //
// - add obsolete lemmas on bottom //
/////////////////////////////////////
try {
$dir_lang = $this->manager->getLangPath($this->lang_folder_path);
} catch (Exception $e) {
switch ($e->getCode()) {
//@codeCoverageIgnoreStart
case Localization::NO_LANG_FOLDER_FOUND_IN_THESE_PATHS:
$this->writeError("No lang folder found in these paths:");
foreach ($e->getParameter() as $path) {
$this->writeError("- " . $path);
}
break;
//@codeCoverageIgnoreEnd
//@codeCoverageIgnoreEnd
case Localization::NO_LANG_FOLDER_FOUND_IN_YOUR_CUSTOM_PATH:
$this->writeError('No lang folder found in your custom path: "' . $e->getParameter() . '"');
break;
}
$this->writeLine('');
return self::ERROR;
}
$job = array();
$there_are_new = false;
$this->writeLine('Scan files:');
foreach (scandir($dir_lang) as $lang) {
if (Tools::isValidDirectory($dir_lang, $lang)) {
foreach ($lemmas_structured as $family => $array) {
if (in_array($family, $this->ignore_lang_files)) {
if ($this->option('verbose')) {
$this->writeLine('');
$this->writeInfo(" ! Skip lang file '{$family}' !");
}
continue;
}
$file_lang_path = $dir_lang . DIRECTORY_SEPARATOR . $lang . DIRECTORY_SEPARATOR . $family . '.php';
if ($this->option('verbose')) {
$this->writeLine('');
}
$this->writeLine(' ' . $this->manager->getShortPath($file_lang_path));
if (!is_writable(dirname($file_lang_path))) {
// @codeCoverageIgnoreStart
$this->writeError(" > Unable to write file in directory " . dirname($file_lang_path));
return self::ERROR;
// @codeCoverageIgnoreEnd
}
if (!file_exists($file_lang_path)) {
// @codeCoverageIgnoreStart
$this->writeInfo(" > File has been created");
// @codeCoverageIgnoreEnd
}
if (!touch($file_lang_path)) {
// @codeCoverageIgnoreStart
$this->writeError(" > Unable to touch file {$file_lang_path}");
return self::ERROR;
// @codeCoverageIgnoreEnd
}
if (!is_readable($file_lang_path)) {
// @codeCoverageIgnoreStart
$this->writeError(" > Unable to read file {$file_lang_path}");
return self::ERROR;
// @codeCoverageIgnoreEnd
}
if (!is_writable($file_lang_path)) {
// @codeCoverageIgnoreStart
$this->writeError(" > Unable to write in file {$file_lang_path}");
return self::ERROR;
// @codeCoverageIgnoreEnd
}
/** @noinspection PhpIncludeInspection */
$a = (include $file_lang_path);
$old_lemmas_with_obsolete = is_array($a) ? array_dot($a) : array();
$new_lemmas = array_dot($array);
$final_lemmas = array();
$display_already_comment = false;
$something_to_do = false;
$i = 0;
// Remove the obsolete prefix key
$old_lemmas = array();
$obsolete_prefix_length = strlen($obsolete_prefix);
foreach ($old_lemmas_with_obsolete as $key => $value) {
if (starts_with($key, $obsolete_prefix)) {
$key = substr($key, $obsolete_prefix_length);
if (!isset($old_lemmas[$key])) {
$old_lemmas[$key] = $value;
}
} else {
$old_lemmas[$key] = $value;
}
}
$obsolete_lemmas = array_diff_key($old_lemmas, $new_lemmas);
$welcome_lemmas = array_diff_key($new_lemmas, $old_lemmas);
$already_lemmas = array_intersect_key($old_lemmas, $new_lemmas);
// disable check for obsolete lemma and consolidate with already_lemmas
if ($this->option('disable-obsolete-check')) {
$already_lemmas = array_unique($obsolete_lemmas + $already_lemmas);
$obsolete_lemmas = array();
}
ksort($obsolete_lemmas);
ksort($welcome_lemmas);
ksort($already_lemmas);
//////////////////////////
// Deal with new lemmas //
//////////////////////////
if (count($welcome_lemmas) > 0) {
$display_already_comment = true;
$something_to_do = true;
$there_are_new = true;
$final_lemmas["POTSKY___NEW___POTSKY"] = "POTSKY___NEW___POTSKY";
$this->writeInfo(' ' . ($c = count($welcome_lemmas)) . ' new string' . Tools::getPlural($c) . ' to translate');
foreach ($welcome_lemmas as $key => $value) {
if ($this->option('verbose')) {
$this->writeLine(" <info>" . $key . "</info> in " . $this->manager->getShortPath($value));
}
if (!$this->option('no-comment')) {
$final_lemmas['POTSKY___COMMENT___POTSKY' . $i] = "Defined in file {$value}";
$i = $i + 1;
}
$key_last_token = explode('.', $key);
if ($this->option('translation')) {
$translation = $this->manager->translate(end($key_last_token), $lang);
} else {
$translation = end($key_last_token);
}
if (strtolower($this->option('new-value')) === 'null') {
$translation = null;
} else {
$translation = str_replace('%LEMMA', $translation, $this->option('new-value'));
}
array_set($final_lemmas, $key, $translation);
}
}
///////////////////////////////
// Deal with existing lemmas //
///////////////////////////////
if (count($already_lemmas) > 0) {
if ($this->option('verbose')) {
$this->writeLine(' ' . ($c = count($already_lemmas)) . ' already translated string' . Tools::getPlural($c));
}
$final_lemmas["POTSKY___OLD___POTSKY"] = "POTSKY___OLD___POTSKY";
foreach ($already_lemmas as $key => $value) {
array_set($final_lemmas, $key, $value);
}
}
///////////////////////////////
// Deal with obsolete lemmas //
///////////////////////////////
if (count($obsolete_lemmas) > 0) {
$protected_already_included = false;
// Remove all dynamic fields
foreach ($obsolete_lemmas as $key => $value) {
foreach ($this->never_obsolete_keys as $remove) {
if (strpos($key, '.' . $remove . '.') !== false || starts_with($key, $remove . '.')) {
if ($this->option('verbose')) {
$this->writeLine(" <comment>" . $key . "</comment> is protected as a dynamic lemma");
}
unset($obsolete_lemmas[$key]);
if ($protected_already_included === false) {
$final_lemmas["POTSKY___PROTECTED___POTSKY"] = "POTSKY___PROTECTED___POTSKY";
$protected_already_included = true;
}
// Given that this lemma is never obsolete, we need to send it back to the final lemma array
array_set($final_lemmas, $key, $value);
}
}
}
}
/////////////////////////////////////
// Fill the final lemmas array now //
/////////////////////////////////////
if (count($obsolete_lemmas) > 0) {
$display_already_comment = true;
$something_to_do = true;
if ($this->option('no-obsolete')) {
$this->writeComment(" " . ($c = count($obsolete_lemmas)) . ' obsolete string' . Tools::getPlural($c) . ' (will be deleted)');
} else {
$this->writeComment(" " . ($c = count($obsolete_lemmas)) . ' obsolete string' . Tools::getPlural($c) . ' (can be deleted manually in the generated file)');
$final_lemmas["POTSKY___OBSOLETE___POTSKY"] = "POTSKY___OBSOLETE___POTSKY";
foreach ($obsolete_lemmas as $key => $value) {
if ($this->option('verbose')) {
$this->writeLine(" <comment>" . $key . "</comment>");
}
array_set($final_lemmas, $obsolete_prefix . $key, $value);
}
}
}
// Flat style
if ($this->option('output-flat')) {
$final_lemmas = array_dot($final_lemmas);
}
if ($something_to_do === true || $this->option('force')) {
$content = var_export($final_lemmas, true);
$content = preg_replace("@'POTSKY___COMMENT___POTSKY[0-9]*' => '(.*)',@", '// $1', $content);
$content = str_replace(array("'POTSKY___NEW___POTSKY' => 'POTSKY___NEW___POTSKY',", "'POTSKY___OLD___POTSKY' => 'POTSKY___OLD___POTSKY',", "'POTSKY___PROTECTED___POTSKY' => 'POTSKY___PROTECTED___POTSKY',", "'POTSKY___OBSOLETE___POTSKY' => 'POTSKY___OBSOLETE___POTSKY',"), array('//============================== New strings to translate ==============================//', $display_already_comment === true ? '//==================================== Translations ====================================//' : '', '//============================== Dynamic protected strings =============================//', '//================================== Obsolete strings ==================================//'), $content);
$file_content = "<?php\n";
if (!$this->option('no-date')) {
$a = " Generated via \"php artisan " . $this->argument('command') . "\" at " . date("Y/m/d H:i:s") . " ";
$file_content .= "/" . str_repeat('*', strlen($a)) . "\n" . $a . "\n" . str_repeat('*', strlen($a)) . "/\n";
}
$file_content .= "\nreturn " . $content . ";";
$job[$file_lang_path] = $file_content;
} else {
if ($this->option('verbose')) {
$this->writeLine(" > <comment>Nothing to do for this file</comment>");
}
}
}
}
}
///////////////////////////////////////////
// Silent mode //
// only return an exit code on new lemma //
///////////////////////////////////////////
if ($this->option('silent')) {
if ($there_are_new === true) {
return self::ERROR;
} else {
// @codeCoverageIgnoreStart
return self::SUCCESS;
// @codeCoverageIgnoreEnd
}
}
///////////////////////////////////////////
// Normal mode //
///////////////////////////////////////////
if (count($job) > 0) {
if ($this->option('no-interaction')) {
$do = true;
} else {
$this->writeLine('');
$do = $this->ask('Do you wish to apply these changes now? [yes|no]') === 'yes';
$this->writeLine('');
}
// @codeCoverageIgnoreEnd
if ($do === true) {
if (!$this->option('no-backup')) {
$this->writeLine('Backup files:');
$now = $this->manager->getBackupDate();
foreach ($job as $file_lang_path => $file_content) {
$backup_path = $this->manager->getBackupPath($file_lang_path, $now, $extension);
if (!$this->option('dry-run')) {
rename($file_lang_path, $backup_path);
}
$this->writeLine(" <info>" . $this->manager->getShortPath($file_lang_path) . "</info> -> <info>" . $this->manager->getShortPath($backup_path) . "</info>");
}
$this->writeLine('');
}
$this->writeLine('Save files:');
$open_files = '';
foreach ($job as $file_lang_path => $file_content) {
if (!$this->option('dry-run')) {
file_put_contents($file_lang_path, $file_content);
}
$this->writeLine(" <info>" . $this->manager->getShortPath($file_lang_path) . "</info>");
// Fix code style
if (!empty($this->code_style_level) || !empty($this->code_style_fixers)) {
try {
$this->manager->fixCodeStyle($file_lang_path, $this->code_style_fixers, $this->code_style_level);
} catch (Exception $e) {
$this->writeError(" Cannot fix code style (" . $e->getMessage() . ")");
}
// @codeCoverageIgnoreEnd
}
// @codeCoverageIgnoreStart
if ($this->option('editor')) {
$open_files .= ' ' . escapeshellarg($file_lang_path);
}
// @codeCoverageIgnoreEnd
}
$this->writeLine('');
$this->writeInfo('Process done!');
// @codeCoverageIgnoreStart
if ($this->option('editor')) {
exec($this->editor . $open_files);
}
// @codeCoverageIgnoreEnd
// @codeCoverageIgnoreStart
} else {
$this->writeLine('');
$this->writeComment('Process aborted. No file has been changed.');
}
} else {
$this->writeLine('');
$this->writeInfo('Drink a Piña colada and/or smoke Super Skunk, you have nothing to do!');
}
$this->writeLine('');
return self::SUCCESS;
}