use modules define and readonly properties

This commit is contained in:
Jean-Christian Denis 2023-03-18 00:18:41 +01:00
parent 39888e2abc
commit 23376ff9ae
Signed by: JcDenis
GPG key ID: 1B5B8C5B90B6C951
5 changed files with 130 additions and 142 deletions

View file

@ -39,7 +39,7 @@ class Manage extends dcNsProcess
return false;
}
$current = ManageContainer::init();
$current = ManageVars::init();
// execute action
try {
@ -150,7 +150,7 @@ class Manage extends dcNsProcess
return;
}
$current = ManageContainer::init();
$current = ManageVars::init();
$breadcrumb = [My::name() => dcCore::app()->adminurl->get(My::id(), ['type' => '-'])];
if (empty($current->type)) {

View file

@ -16,16 +16,16 @@ namespace Dotclear\Plugin\translater;
use dcCore;
class ManageContainer
class ManageVars
{
/**
* @var ManageContainer self instance
* @var ManageVars self instance
*/
private static $container;
public readonly Translater $translater;
public readonly string|TranslaterModule $module;
public readonly string|TranslaterLang $lang;
public readonly ?TranslaterModule $module;
public readonly ?TranslaterLang $lang;
public readonly string $type;
public readonly string $action;
@ -34,8 +34,8 @@ class ManageContainer
$this->translater = new Translater();
$type = $_REQUEST['type'] ?? $this->translater->start_page ?: '';
$module = $_REQUEST['module'] ?? '';
$lang = $_REQUEST['lang'] ?? '';
$module = $_REQUEST['module'] ?? null;
$lang = $_REQUEST['lang'] ?? null;
$action = $_POST['action'] ?? '';
// check module type
@ -48,7 +48,7 @@ class ManageContainer
$module = $this->translater->getModule($type, $module);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
$module = '';
$module = null;
}
}
//check if module lang exists
@ -57,7 +57,7 @@ class ManageContainer
$lang = $this->translater->getLang($module, $lang);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
$lang = '';
$lang = null;
}
}
@ -67,7 +67,7 @@ class ManageContainer
$this->action = $action;
}
public static function init(): ManageContainer
public static function init(): ManageVars
{
if (!(self::$container instanceof self)) {
self::$container = new self();

View file

@ -15,6 +15,7 @@ declare(strict_types=1);
namespace Dotclear\Plugin\translater;
use dcCore;
use dcModuleDefine;
use dcThemes;
use files;
use l10n;
@ -50,25 +51,19 @@ class Translater extends Settings
*/
private function loadModules(): void
{
$this->modules['theme'] = $this->modules['plugin'] = [];
$this->modules = ['theme' => [], 'plugin' => []];
if (!(dcCore::app()->themes instanceof dcThemes)) {
dcCore::app()->themes = new dcThemes();
dcCore::app()->themes->loadModules(dcCore::app()->blog->themes_path, null);
}
$list = [
'theme' => dcCore::app()->themes->getModules(),
'plugin' => dcCore::app()->plugins->getModules(),
];
foreach ($list as $type => $modules) {
foreach ($modules as $id => $info) {
if (!$info['root_writable']) {
// continue;
}
$info['id'] = $id;
$info['type'] = $type;
$this->modules[$type][$id] = new TranslaterModule($this, $info);
foreach ([
dcCore::app()->themes->getDefines(['state' => dcModuleDefine::STATE_ENABLED]),
dcCore::app()->plugins->getDefines(['state' => dcModuleDefine::STATE_ENABLED]),
] as $modules) {
foreach ($modules as $define) {
$this->modules[$define->get('type')][$define->get('id')] = new TranslaterModule($this, $define);
}
}
}

View file

@ -14,47 +14,31 @@ declare(strict_types=1);
namespace Dotclear\Plugin\translater;
use dcModuleDefine;
use files;
use l10n;
use path;
class TranslaterLang
{
/** @var Translater Translater instance */
public $translater = null;
/** @var TranslaterModule TranslaterModule instance */
public $module = null;
/** @var string Lang code */
public readonly string $code;
/** @var array Lang properies */
private $prop = [];
/** @var string Lang name */
public readonly string $name;
/** @var array Lang plural forms */
public readonly array $plural;
/** @var TranslaterModule TranslaterModule instance */
private TranslaterModule $module;
public function __construct(TranslaterModule $module, string $lang)
{
$this->translater = $module->translater;
$this->module = $module;
$this->prop['code'] = $lang;
$this->prop['name'] = l10n::getLanguageName($lang);
$this->prop['plural'] = explode(':', l10n::getLanguagePluralExpression($lang));
}
/**
* Get a lang property
*
* @param string $key The lang property key
* @return mixed The lang property value or null
*/
public function get(string $key): mixed
{
return array_key_exists($key, $this->prop) ? $this->prop[$key] : null;
}
/**
* Magic get
*/
public function __get(string $key): mixed
{
return $this->get($key);
$this->module = $module;
$this->code = $lang;
$this->name = l10n::getLanguageName($lang);
$this->plural = explode(':', l10n::getLanguagePluralExpression($lang));
}
/**
@ -68,13 +52,16 @@ class TranslaterLang
$m_msgids = $this->getMsgIds();
$m_msgstrs = $this->getMsgStrs();
foreach ($this->translater->getModules() as $module) {
if ($module->id != $this->module->get('id')) {
$m_o_msgstrs[$module->get('id')] = $this->translater->getlang($module, $this->get('code'))->getMsgStrs();
foreach ($this->module->translater->getModules() as $module) {
if ($module->id != $this->module->id) {
$m_o_msgstrs[$module->id] = $this->module->translater->getlang($module, $this->code)->getMsgStrs();
}
}
$dc_module = new TranslaterModule($this->translater, ['id' => 'dotclear', 'root' => DC_ROOT]);
$dc_lang = new TranslaterLang($dc_module, $this->get('code'));
# Add Dotclear str
$dc_define = (new dcModuleDefine('dotclear'))->set('root', DC_ROOT);
$dc_module = new TranslaterModule($this->module->translater, $dc_define);
$dc_lang = new TranslaterLang($dc_module, $this->code);
$m_o_msgstrs['dotclear'] = $dc_lang->getMsgStrs();
# From id list
@ -130,17 +117,17 @@ class TranslaterLang
{
$res = [];
$scan_ext = ['php'];
if ($this->translater->scan_tpl) {
if ($this->module->translater->scan_tpl) {
$scan_ext[] = 'html';
}
$files = Translater::scandir($this->module->get('root'));
$files = Translater::scandir($this->module->root);
foreach ($files as $file) {
$extension = files::getExtension($file);
if (is_dir($this->module->get('root') . '/' . $file) || !in_array($extension, $scan_ext)) {
if (is_dir($this->module->root . DIRECTORY_SEPARATOR . $file) || !in_array($extension, $scan_ext)) {
continue;
}
$contents = file_get_contents($this->module->get('root') . '/' . $file);
$contents = file_get_contents($this->module->root . '/' . $file);
$msgs = [];
# php files
if ($extension == 'php') {
@ -175,16 +162,16 @@ class TranslaterLang
$res = $exists = $scanned = [];
$langs = $this->module->getLangs(true);
if (!isset($langs[$this->get('code')])) {
if (!isset($langs[$this->code])) {
return $res;
}
foreach ($langs[$this->get('code')] as $file) {
foreach ($langs[$this->code] as $file) {
if (in_array($file, $scanned)) {
continue;
}
$scanned[] = $file;
$path = path::clean($this->module->get('locales') . '/' . $file);
$path = path::clean($this->module->locales . DIRECTORY_SEPARATOR . $file);
if (Translater::isPoFile($file)) {
$po = l10n::parsePoFile($path);
@ -197,7 +184,7 @@ class TranslaterLang
'msgid' => $entry['msgid'],
'msgid_plural' => $entry['msgid_plural'] ?? '',
'msgstr' => is_array($entry['msgstr']) ? $entry['msgstr'] : [$entry['msgstr']],
'lang' => $this->get('code'),
'lang' => $this->code,
'type' => 'po',
'path' => $path,
'file' => basename($file),

View file

@ -15,6 +15,7 @@ declare(strict_types=1);
namespace Dotclear\Plugin\translater;
use dcCore;
use dcModuleDefine;
use dt;
use html;
use files;
@ -28,43 +29,47 @@ use path;
*/
class TranslaterModule
{
/** @var Translater Translater instance */
public $translater = null;
/** @var string Module id */
public readonly string $id;
/** @var array Module properies */
private $prop = [];
/** @var string Module type */
public readonly string $type;
/** @var string Module name */
public readonly string $name;
/** @var string Module author */
public readonly string $author;
/** @var string Module version */
public readonly string $version;
/** @var bool Module root writable */
public readonly bool $root_writable;
/** @var string Module root (cleaned) */
public readonly string $root;
/** @var string Module locales root path */
public readonly string $locales;
/** @var Translater Translater instance */
public readonly Translater $translater;
/** @var string Backup file regexp */
private $backup_file_regexp = '/^l10n-%s-(.*?)-[0-9]*?\.bck\.zip$/';
public function __construct(Translater $translater, array $module)
public function __construct(Translater $translater, dcModuleDefine $define)
{
$this->translater = $translater;
$this->prop = $module;
$this->prop['root'] = path::real($this->prop['root']);
$i = path::info($this->prop['root']);
$this->prop['basename'] = $i['basename'];
$this->prop['locales'] = $this->prop['root'] . '/locales';
}
/**
* Get a module property
*
* @param string $key The module property key
* @return mixed The module property value or null
*/
public function get(string $key): mixed
{
return array_key_exists($key, $this->prop) ? $this->prop[$key] : null;
}
/**
* Magic get
*/
public function __get(string $key): mixed
{
return $this->get($key);
$this->translater = $translater;
$this->id = $define->get('id');
$this->type = $define->get('type');
$this->name = $define->get('name');
$this->author = $define->get('author');
$this->version = $define->get('version');
$this->root_writable = $define->get('root_writable');
$this->root = path::real($define->get('root'));
$this->locales = $this->root . DIRECTORY_SEPARATOR . 'locales';
}
/// @name backup methods
@ -80,8 +85,8 @@ class TranslaterModule
$dir = false;
switch ($this->translater->backup_folder) {
case 'module':
if ($this->prop['root_writable']) {
$dir = $this->prop['locales'];
if ($this->root_writable) {
$dir = $this->locales;
}
break;
@ -124,7 +129,7 @@ class TranslaterModule
if (!$dir && $throw) {
throw new Exception(sprintf(
__('Failed to find backups folder for module %s'),
$this->prop['basename']
$this->id
));
}
@ -147,7 +152,7 @@ class TranslaterModule
$res = [];
$files = Translater::scandir($backup);
foreach ($files as $file) {
$is_backup = preg_match(sprintf($this->backup_file_regexp, preg_quote($this->prop['id'])), $file, $m);
$is_backup = preg_match(sprintf($this->backup_file_regexp, preg_quote($this->id)), $file, $m);
if (is_dir($backup . '/' . $file)
|| !$is_backup
@ -164,7 +169,7 @@ class TranslaterModule
$res[$m[1]][$file]['path'] = path::info($backup . '/' . $file);
$res[$m[1]][$file]['time'] = filemtime($backup . '/' . $file);
$res[$m[1]][$file]['size'] = filesize($backup . '/' . $file);
$res[$m[1]][$file]['module'] = $this->prop['id'];
$res[$m[1]][$file]['module'] = $this->id;
}
}
@ -180,8 +185,9 @@ class TranslaterModule
public function createBackup(string $lang): bool
{
$backup = $this->getBackupRoot(true);
$dir = $this->locales . DIRECTORY_SEPARATOR . $lang;
if (!is_dir($this->prop['locales'] . '/' . $lang)) {
if (!is_dir($dir)) {
throw new Exception(sprintf(
__('Failed to find language %s'),
$lang
@ -189,20 +195,20 @@ class TranslaterModule
}
$res = [];
$files = Translater::scandir($this->prop['locales'] . '/' . $lang);
$files = Translater::scandir($dir);
foreach ($files as $file) {
if (!is_dir($this->prop['locales'] . '/' . $lang . '/' . $file)
if (!is_dir($dir . DIRECTORY_SEPARATOR . $file)
&& (Translater::isLangphpFile($file) || Translater::isPoFile($file))
) {
$res[$this->prop['locales'] . '/' . $lang . '/' . $file] = $this->prop['id'] . '/locales/' . $lang . '/' . $file;
$res[$dir . DIRECTORY_SEPARATOR . $file] = implode(DIRECTORY_SEPARATOR, [$this->locales, $lang, $file]);
}
}
if (!empty($res)) {
Translater::isBackupLimit($this->prop['id'], $backup, $this->translater->backup_limit, true);
Translater::isBackupLimit($this->id, $backup, $this->translater->backup_limit, true);
@set_time_limit(300);
$fp = fopen($backup . '/l10n-' . $this->prop['id'] . '-' . $lang . '-' . time() . '.bck.zip', 'wb');
$fp = fopen($backup . '/l10n-' . $this->id . '-' . $lang . '-' . time() . '.bck.zip', 'wb');
$zip = new fileZip($fp);
foreach ($res as $from => $to) {
$zip->addFile($from, $to);
@ -239,7 +245,7 @@ class TranslaterModule
foreach ($zip_files as $zip_file) {
$f = $this->parseZipFilename($zip_file, true);
$zip->unzip($zip_file, $this->prop['locales'] . '/' . $f['lang'] . '/' . $f['group'] . $f['ext']);
$zip->unzip($zip_file, implode(DIRECTORY_SEPARATOR, [$this->locales, $f['lang'], $f['group'] . $f['ext']]));
$done = true;
}
$zip->close();
@ -258,7 +264,7 @@ class TranslaterModule
{
$backup = $this->getBackupRoot(true);
$is_backup = preg_match(sprintf($this->backup_file_regexp, preg_quote($this->prop['id'])), $file, $m);
$is_backup = preg_match(sprintf($this->backup_file_regexp, preg_quote($this->id)), $file, $m);
if (!file_exists($backup . '/' . $file)
|| !$is_backup
@ -301,7 +307,7 @@ class TranslaterModule
$f = $this->parseZipFilename($file, true);
if (!$this->translater->import_overwrite
&& file_exists($this->prop['locales'] . '/' . $f['lang'] . '/' . $f['group'] . $f['ext'])
&& file_exists(implode(DIRECTORY_SEPARATOR, [$this->locales, $f['lang'], $f['group'] . $f['ext']]))
) {
$not_overwrited[] = implode('-', [$f['lang'], $f['group'], $f['ext']]);
@ -310,8 +316,8 @@ class TranslaterModule
$res[] = [
'from' => $file,
'root' => $this->prop['locales'] . '/' . $f['lang'],
'to' => $this->prop['locales'] . '/' . $f['lang'] . '/' . $f['group'] . $f['ext'],
'root' => implode(DIRECTORY_SEPARATOR, [$this->locales, $f['lang']]),
'to' => implode(DIRECTORY_SEPARATOR, [$this->locales, $f['lang'], $f['group'] . $f['ext']]),
];
}
@ -363,20 +369,20 @@ class TranslaterModule
$res = [];
foreach ($langs as $lang) {
if (!is_dir($this->prop['locales'] . '/' . $lang)) {
if (!is_dir($this->locales . DIRECTORY_SEPARATOR . $lang)) {
continue;
}
$files = Translater::scandir($this->prop['locales'] . '/' . $lang);
$files = Translater::scandir($this->locales . DIRECTORY_SEPARATOR . $lang);
foreach ($files as $file) {
if (is_dir($this->prop['locales'] . '/' . $lang . '/' . $file)
if (is_dir(implode(DIRECTORY_SEPARATOR, [$this->locales, $lang, $file]))
|| !Translater::isLangphpFile($file)
&& !Translater::isPoFile($file)
) {
continue;
}
$res[$this->prop['locales'] . '/' . $lang . '/' . $file] = $this->prop['id'] . '/locales/' . $lang . '/' . $file;
$res[implode(DIRECTORY_SEPARATOR, [$this->locales, $lang, $file])] = implode(DIRECTORY_SEPARATOR, [$this->locales, $lang, $file]);
}
}
@ -395,7 +401,7 @@ class TranslaterModule
$filename = files::tidyFileName(dt::str(str_replace(
['timestamp', 'module', 'type', 'version'],
[time(), $this->prop['id'], $this->prop['type'], $this->prop['version']],
[time(), $this->id, $this->type, $this->version],
$this->translater->export_filename
)));
@ -418,7 +424,7 @@ class TranslaterModule
$is_file = preg_match('/^(.*?)\/locales\/(.*?)\/(.*?)(.po|.lang.php)$/', $file, $f);
if ($is_file) {
$module = $f[1] == $this->prop['id'] ? $f[1] : false;
$module = $f[1] == $this->id ? $f[1] : false;
$lang = l10n::isCode($f[2]) ? $f[2] : false;
$group = in_array($f[3], My::l10nGroupsCombo()) ? $f[3] : false;
$ext = Translater::isLangphpFile($f[4]) || Translater::isPoFile($f[4]) ? $f[4] : false;
@ -456,9 +462,9 @@ class TranslaterModule
{
$res = [];
$prefix = preg_match('/(locales(.*))$/', $this->prop['locales']) ? 'locales' : '';
$prefix = preg_match('/(locales(.*))$/', $this->locales) ? 'locales' : '';
$files = Translater::scandir($this->prop['locales']);
$files = Translater::scandir($this->locales);
foreach ($files as $file) {
if (!preg_match('/.*?locales\/([^\/]*?)\/([^\/]*?)(.lang.php|.po)$/', $prefix . $file, $m)) {
continue;
@ -522,7 +528,7 @@ class TranslaterModule
));
}
files::makeDir($this->prop['locales'] . '/' . $lang, true);
files::makeDir($this->locales . DIRECTORY_SEPARATOR . $lang, true);
if (!empty($from_lang) && !isset($langs[$from_lang])) {
throw new Exception(sprintf(
@ -532,9 +538,9 @@ class TranslaterModule
}
if (!empty($from_lang) && isset($langs[$from_lang])) {
$files = Translater::scandir($this->prop['locales'] . '/' . $from_lang);
$files = Translater::scandir($this->locales . DIRECTORY_SEPARATOR . $from_lang);
foreach ($files as $file) {
if (is_dir($this->prop['locales'] . '/' . $from_lang . '/' . $file)
if (is_dir(implode(DIRECTORY_SEPARATOR, [$this->locales, $from_lang, $file]))
|| !Translater::isLangphpFile($file)
&& !Translater::isPoFile($file)
) {
@ -542,8 +548,8 @@ class TranslaterModule
}
files::putContent(
$this->prop['locales'] . '/' . $lang . '/' . $file,
file_get_contents($this->prop['locales'] . '/' . $from_lang . '/' . $file)
implode(DIRECTORY_SEPARATOR, [$this->locales, $lang, $file]),
file_get_contents(implode(DIRECTORY_SEPARATOR, [$this->locales, $from_lang, $file]))
);
}
} else {
@ -594,8 +600,8 @@ class TranslaterModule
continue;
}
$po_file = $this->prop['locales'] . '/' . $lang . '/' . $group . '.po';
$langphp_file = $this->prop['locales'] . '/' . $lang . '/' . $group . '.lang.php';
$po_file = implode(DIRECTORY_SEPARATOR, [$this->locales, $lang, $group . '.po']);
$langphp_file = implode(DIRECTORY_SEPARATOR, [$this->locales, $lang, $group . '.lang.php']);
if (file_exists($po_file)) {
unlink($po_file);
@ -644,17 +650,17 @@ class TranslaterModule
}
foreach ($files[$lang] as $file) {
unlink($this->prop['locales'] . '/' . $file);
unlink($this->locales . DIRECTORY_SEPARATOR . $file);
}
$dir = Translater::scandir($this->prop['locales'] . '/' . $lang);
$dir = Translater::scandir($this->locales . DIRECTORY_SEPARATOR . $lang);
if (empty($dir)) {
rmdir($this->prop['locales'] . '/' . $lang);
rmdir($this->locales . DIRECTORY_SEPARATOR . $lang);
}
$loc = Translater::scandir($this->prop['locales']);
$loc = Translater::scandir($this->locales);
if (empty($loc)) {
rmdir($this->prop['locales']);
rmdir($this->locales);
}
return true;
@ -673,8 +679,8 @@ class TranslaterModule
$content = '';
if ($this->translater->parse_comment) {
$content .= '# Language: ' . $lang->get('name') . "\n" .
'# Module: ' . $this->get('id') . ' - ' . $this->get('version') . "\n" .
$content .= '# Language: ' . $lang->name . "\n" .
'# Module: ' . $this->id . ' - ' . $this->version . "\n" .
'# Date: ' . dt::str('%Y-%m-%d %H:%M:%S') . "\n";
if ($this->translater->parse_user && $this->translater->parse_userinfo != '') {
@ -693,7 +699,7 @@ class TranslaterModule
$content .= "msgid \"\"\n" .
"msgstr \"\"\n" .
'"Content-Type: text/plain; charset=UTF-8\n"' . "\n" .
'"Project-Id-Version: ' . $this->get('id') . ' ' . $this->get('version') . '\n"' . "\n" .
'"Project-Id-Version: ' . $this->id . ' ' . $this->version . '\n"' . "\n" .
'"POT-Creation-Date: \n"' . "\n" .
'"PO-Revision-Date: ' . date('c') . '\n"' . "\n" .
'"Last-Translator: ' . dcCore::app()->auth->getInfo('user_cn') . '\n"' . "\n" .
@ -730,7 +736,7 @@ class TranslaterModule
$content .= "\n";
}
$file = $this->get('locales') . '/' . $lang->get('code') . '/' . $group . '.po';
$file = implode(DIRECTORY_SEPARATOR, [$this->locales, $lang->code, $group . '.po']);
$path = path::info($file);
if (is_dir($path['dirname']) && !is_writable($path['dirname'])
|| file_exists($file) && !is_writable($file)) {
@ -765,8 +771,8 @@ class TranslaterModule
$content = '';
if ($this->translater->parse_comment) {
$content .= '// Language: ' . $lang->get('name') . "\n" .
'// Module: ' . $this->get('id') . ' - ' . $this->get('verison') . "\n" .
$content .= '// Language: ' . $lang->name . "\n" .
'// Module: ' . $this->id . ' - ' . $this->version . "\n" .
'// Date: ' . dt::str('%Y-%m-%d %H:%M:%S') . "\n";
if ($this->translater->parse_user && !empty($this->translater->parse_userinfo)) {
@ -783,7 +789,7 @@ class TranslaterModule
$content .= '// Translated with Translater - ' . dcCore::app()->plugins->moduleInfo(My::id(), 'version') . "\n\n";
}
l10n::generatePhpFileFromPo($this->get('locales') . '/' . $lang->get('code') . '/' . $group, $content);
l10n::generatePhpFileFromPo(implode(DIRECTORY_SEPARATOR, [$this->locales, $lang->code, $group]), $content);
}
//@}
}