Clean errors detected by PHPstan (level 0) and configure CI to run it on each commit

This commit is contained in:
Benjamin Renard 2022-12-31 02:01:17 +01:00
parent a8e0707e7a
commit 7f862c9765
38 changed files with 535 additions and 484 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
upgrade.log
*.sav
*~
vendor
/src/local.*

18
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,18 @@
stages:
- tests
tests:
image: composer
stage: tests
rules:
- changes:
- src/*
script:
- composer install
- ./vendor/bin/phpstan analyse --no-interaction --configuration=phpstan.neon --error-format=junit > tests-report.xml
artifacts:
when: always
paths:
- tests-report.xml
reports:
junit: tests-report.xml

5
composer.json Normal file
View File

@ -0,0 +1,5 @@
{
"require-dev": {
"phpstan/phpstan": "^1.9"
}
}

22
phpstan.neon Normal file
View File

@ -0,0 +1,22 @@
parameters:
level: 0
paths:
- src
excludePaths:
- src/local
- src/tmp
# Error message "Class Smarty_Resource_LdapSaisie extends unknown class Smarty_Resource_Custom." cannot be ignored, use excludePaths instead.
- src/includes/class/class.LStemplate_smarty3_support.php
ignoreErrors:
- "#Instantiated class (Smarty|Console_Table|ZxcvbnPhp\\\\Zxcvbn|phpseclib\\\\Crypt\\\\RSA|phpseclib\\\\Net\\\\SFTP|phpseclib\\\\Net\\\\SSH2|Net_FTP) not found\\.#"
- "#Call to static method (connect|isError)\\(\\) on an unknown class Net_LDAP2\\.#"
- "#Class (Net_LDAP2_Filter|Net_LDAP2_Entry|PEAR_Error) not found\\.#"
- "#Call to static method (create|parse|combine|escape)\\(\\) on an unknown class Net_LDAP2_Filter\\.#"
- "#Call to static method (createFresh)\\(\\) on an unknown class Net_LDAP2_Entry\\.#"
- "#Call to static method (forceAuthentication|getUser|logout|setDebug|client|setNoCasServerValidation|setCasServerCACert|setExtraCurlOption)\\(\\) on an unknown class phpCAS\\.#"
-
message: "#Call to static method factory\\(\\) on an unknown class Mail\\.#"
path: src/includes/addons/LSaddons.mail.php
-
message: "#Instantiated class Mail_mime not found\\.#"
path: src/includes/addons/LSaddons.mail.php

View File

@ -122,10 +122,6 @@ $GLOBALS['LSobjects']['LSpeople'] = array (
),
),
'before_modify' => 'valid',
'after_modify' => 'valid',
//'after_create' => 'createMaildirByFTP',
//'after_delete' => 'removeMaildirByFTP',
'display_name_format' => '%{cn}',
'label' => 'Users',

View File

@ -115,7 +115,7 @@ function organizationalChartData() {
$parent_id_attr = LSconfig :: get('parent_id_attr', '', 'string', $conf);
if ($parent_id_attr) {
if (!$obj_type :: hasAttr($parent_id_attr))
LStemplate :: fatal_error("Object '$obj_type' does not have attribute '$id_attr'.");
LStemplate :: fatal_error("Object '$obj_type' does not have attribute '$parent_id_attr'.");
$requested_attrs[$obj_type][] = $parent_id_attr;
}
$objects_conf[$obj_type]['parent_id_attr'] = $parent_id_attr;
@ -130,7 +130,7 @@ function organizationalChartData() {
foreach(getFieldInFormat($attr) as $a) {
if (!$obj_type :: hasAttr($a))
LStemplate :: fatal_error("Object '$obj_type' does not have attribute '$a'.");
if (!in_array($a, $attrs))
if (!in_array($a, $requested_attrs[$obj_type]))
$requested_attrs[$obj_type][] = $a;
}
}
@ -276,7 +276,7 @@ function organizationalChartData() {
echo json_encode(
$entities,
(
$pretty || isset($_REQUEST['pretty'])?
isset($_REQUEST['pretty'])?
JSON_PRETTY_PRINT:
0
)

View File

@ -282,7 +282,7 @@ function ppolicy_export_search_info($LSsearch, $as_csv=true, $return=false) {
if ($return)
return $data;
header("Content-disposition: attachment; filename=ppolicy-".$LSsearch->LSobject.".json");
displayAjaxReturn($data);
LSsession :: displayAjaxReturn($data);
exit();
}
@ -330,9 +330,11 @@ function _ppolicy_write_row_in_csv(&$csv, &$row) {
* @return void
**/
function handle_api_LSobject_exportPpolicyInfo($request) {
get_LSobject_from_API_request($request);
$object = get_LSobject_from_API_request($request);
if (!$object)
return;
$container_dn = LSconfig::get(
"LSobjects.".$LSsearch->LSobject.".container_dn",
"LSobjects.".$object->LSobject.".container_dn",
"", "string");
$whoami = LSsession :: whoami(
$container_dn?
@ -423,8 +425,8 @@ function cli_export_ppolicy_info($command_args) {
print($data);
exit();
}
$fd = fopen($output, 'w') or fatal_error("Fail to open output file '$output'");
fwrite($fd, $data) or fatal_error("Fail to write result in output file '$output'");
$fd = fopen($output, 'w') or LStemplate::fatal_error("Fail to open output file '$output'");
fwrite($fd, $data) or LStemplate::fatal_error("Fail to write result in output file '$output'");
@fclose($fd);
}

View File

@ -491,7 +491,7 @@ function generate_sambaProfilePath($ldapObject) {
function generate_shadowExpire_from_sambaPwdMustChange($ldapObject) {
$time = $ldapObject -> getValue('sambaPwdMustChange', true, null);
if ($time)
return str_val(round(int_val($time)/86400));
return strval(round(intval($time)/86400));
return '';
}
@ -507,7 +507,7 @@ function generate_shadowExpire_from_sambaPwdMustChange($ldapObject) {
function generate_timestamp_from_shadowExpire($ldapObject) {
$days = $ldapObject -> getValue('shadowExpire', true, null);
if ($days)
return str_val(int_val($days) * 86400);
return strval(intval($days) * 86400);
return '';
}

View File

@ -65,7 +65,6 @@ function showTechInfo($object) {
'creatorsName' => _('Creator DN'),
'modifyTimestamp' => _('Last modification date'),
'modifiersName' => _('Last modifier DN'),
'modifiersName' => _('Last modifier DN'),
'entryCSN' => _('LDAP entry change sequence number'),
'entryUUID' => _('LDAP entry UUID'),
'hasSubordinates' => _('LDAP entry has children'),

View File

@ -814,6 +814,26 @@ function supannGetOIDCGenrePossibleValues($options, $name, $ldapObject) {
return supannGetNomenclaturePossibleValues('oidc_genre', false);
}
/**
* Détecte et alimente la liste des codes de populations dans la variable
* $GLOBALS['supannNomenclatures']['SUPANN']['codePopulation'].
*
* @param array $populations
* @param string $prefix
* @return void
*/
function supannDetectCodesPopulations($populations, $prefix="") {
if (!$populations) {
return;
}
foreach($populations as $letter => $infos) {
$code = "$prefix$letter";
if (isset($infos['label']))
$GLOBALS['supannNomenclatures']['SUPANN']['codePopulation'][$code] = $infos['label']." ($code)";
supannDetectCodesPopulations($infos['subpopulations'], $code);
}
}
/*
* Charge une nomenclature SUPANN
*
@ -866,19 +886,7 @@ function supannLoadNomenclature($table) {
return false;
}
$GLOBALS['supannNomenclatures']['SUPANN']['codePopulation'] = array();
function _detectCodesPopulations($populations, $prefix="") {
if (!$populations) {
return;
}
foreach($populations as $letter => $infos) {
$code = "$prefix$letter";
if (isset($infos['label']))
$GLOBALS['supannNomenclatures']['SUPANN']['codePopulation'][$code] = $infos['label']." ($code)";
_detectCodesPopulations($infos['subpopulations'], $code);
}
}
_detectCodesPopulations($GLOBALS['supannPopulations']);
supannDetectCodesPopulations($GLOBALS['supannPopulations']);
break;
case 'etuDiplome':

View File

@ -35,7 +35,7 @@ class LSattr_html_maildir extends LSattr_html {
public function __construct($name, $config, &$attribute) {
$attribute -> addObjectEvent('before_delete',$this,'beforeDelete');
$attribute -> addObjectEvent('after_delete',$this,'deleteMaildirByFTP');
return parent :: __construct($name, $config, $attribute);
parent :: __construct($name, $config, $attribute);
}
public function doOnModify($action,$cur,$new) {

View File

@ -309,7 +309,7 @@ class LSattr_html_select_list extends LSattr_html{
* @retval array Tableau associatif des valeurs possible de la liste avec en clé
* la valeur des balises option et en valeur ce qui sera affiché.
*/
protected function getLSattributePossibleValues($attr, $options ,$name ,&$ldapObject) {
protected static function getLSattributePossibleValues($attr, $options ,$name ,&$ldapObject) {
$retInfos=array();
if (is_string($attr)) {
if (isset($ldapObject->attrs[$attr]) && $ldapObject->attrs[$attr] instanceof LSattribute) {
@ -410,7 +410,7 @@ class LSattr_html_select_list extends LSattr_html{
);
}
catch (Exception $er) {
self :: log_exception($er, strval($this)." -> _getPossibleValues(): exception occured running ".format_callable($get_possible_values));
self :: log_exception($er, get_called_class()." -> _getPossibleValues(): exception occured running ".format_callable($get_possible_values));
$retInfos = null;
}

View File

@ -188,7 +188,7 @@ class LSattr_ldap_password extends LSattr_ldap {
if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) ) {
mt_srand( (double) microtime() * 1000000 );
if (is_null($salt))
$salt = mhash_keygen_s2k( MHASH_MD5, $password_clear, substr( pack( "h*", md5( mt_rand() ) ), 0, 8 ), 4 );
$salt = mhash_keygen_s2k( MHASH_MD5, $clearPassword, substr( pack( "h*", md5( mt_rand() ) ), 0, 8 ), 4 );
return "{SMD5}".base64_encode( mhash( MHASH_MD5, $clearPassword.$salt ).$salt );
}
else {

View File

@ -41,7 +41,6 @@ class LSauthMethod extends LSlog_staticLoggerClass {
self :: log_debug(get_class($this)." :: __construct(): config file ($conf_file) loaded");
else
self :: log_debug(get_class($this)." :: __construct(): config file ($conf_file) not found");
return true;
}
/**
@ -69,7 +68,7 @@ class LSauthMethod extends LSlog_staticLoggerClass {
self :: log_debug("No user found for provided username '".$this -> authData['username']."'");
return false;
}
if (count($authobjects) > 1) {
self :: log_debug('Multiple users match with provided username: '.implode(', ', array_keys($authobjects)));
LSerror :: addErrorCode('LSauth_02');

View File

@ -33,8 +33,7 @@ class LSauthMethod_CAS extends LSauthMethod {
public function __construct() {
LSauth :: disableLoginForm();
if (!parent :: __construct())
return;
parent :: __construct();
if (LSsession :: includeFile(PHP_CAS_PATH, true)) {
if (defined('PHP_CAS_DEBUG_FILE')) {
@ -67,7 +66,7 @@ class LSauthMethod_CAS extends LSauthMethod {
// Check CAS server SSL validation is now configured
if (!$cas_server_ssl_validation_configured) {
LSerror :: addErrorCode('LSauthMethod_CAS_02');
return false;
return;
}
if (defined('LSAUTH_CAS_CURL_SSLVERION')) {
@ -82,12 +81,10 @@ class LSauthMethod_CAS extends LSauthMethod {
// Set configured flag
$this -> configured = true;
return true;
}
else {
LSerror :: addErrorCode('LSauthMethod_CAS_01');
}
return false;
}
/**

View File

@ -37,7 +37,6 @@ class LSauthMethod_HTTP extends LSauthMethod_basic {
LSauth :: disableLoginForm();
if (!defined('LSAUTHMETHOD_HTTP_LOGOUT_REMOTE_URL'))
LSauth :: disableLogoutBtn();
return True;
}
/**

View File

@ -34,8 +34,7 @@ class LSauthMethod_anonymous extends LSauthMethod {
LSauth :: disableLoginForm();
LSauth :: disableSelfAccess();
if (!parent :: __construct())
return;
parent :: __construct();
if ( (!defined('LSAUTHMETHOD_ANONYMOUS_DISABLE_LOGOUT')) || (constant('LSAUTHMETHOD_ANONYMOUS_DISABLE_LOGOUT') === True)) {
self :: log_debug('logout : '.constant('LSAUTHMETHOD_ANONYMOUS_DISABLE_LOGOUT'));
@ -46,7 +45,6 @@ class LSauthMethod_anonymous extends LSauthMethod {
LSerror :: addErrorCode('LSauthMethod_anonymous_01');
return;
}
return true;
}
/**

View File

@ -55,6 +55,7 @@ class LSform extends LSlog_staticLoggerClass {
var $api_mode = false;
private $submited = false;
private $submit = null;
/**
* Constructeur
@ -528,7 +529,7 @@ class LSform extends LSlog_staticLoggerClass {
}
// Retrieve POST data of the element
if( !($element -> getPostData($this -> _postData, $onlyIfPresent)) ) {
LSerror :: addErrorCode('LSform_02',$element_name);
LSerror :: addErrorCode('LSform_02',$elementName);
return;
}
}

View File

@ -36,6 +36,7 @@ class LSformElement extends LSlog_staticLoggerClass {
var $label;
var $params;
var $values = array();
var $form = null;
var $_required = false;
var $_freeze = false;
var $attr_html;

View File

@ -71,7 +71,7 @@ class LSformElement_maildir extends LSformElement_text {
'nodo' => _("Click to enable maildir creation/modification on user creation/modification.")
)
);
return parent :: getDisplay($return);
return parent :: getDisplay();
}
/**

View File

@ -50,7 +50,7 @@ class LSformElement_rss extends LSformElement_text {
'display' => _("Display RSS stack.")
)
);
return parent :: getDisplay($return);
return parent :: getDisplay();
}
}

View File

@ -309,7 +309,7 @@ class LSformElement_supannCompositeAttribute extends LSformElement {
break;
default:
self :: error('Unrecognized component type "'.$this -> components[$c]['type'].'"');
self :: log_error('Unrecognized component type "'.$this -> components[$c]['type'].'"');
}
}
self :: log_debug("translateComponentValue($c, $val): ".varDump($retval));

View File

@ -84,7 +84,7 @@ class LSformElement_supannEmpProfil extends LSformElement_supannCompositeAttribu
'required' => false,
),
);
return parent :: __construct($form, $name, $label, $params, $attr_html);
parent :: __construct($form, $name, $label, $params, $attr_html);
}
}

View File

@ -122,7 +122,7 @@ class LSformElement_supannEtuInscription extends LSformElement_supannCompositeAt
'required' => false,
),
);
return parent :: __construct($form, $name, $label, $params, $attr_html);
parent :: __construct($form, $name, $label, $params, $attr_html);
}
}

View File

@ -83,7 +83,7 @@ class LSformElement_supannExtProfil extends LSformElement_supannCompositeAttribu
'required' => false,
),
);
return parent :: __construct($form, $name, $label, $params, $attr_html);
parent :: __construct($form, $name, $label, $params, $attr_html);
}
}

View File

@ -58,7 +58,7 @@ class LSformElement_supannRessourceEtat extends LSformElement_supannCompositeAtt
'required' => false,
),
);
return parent :: __construct($form, $name, $label, $params, $attr_html);
parent :: __construct($form, $name, $label, $params, $attr_html);
}
/**
@ -91,7 +91,7 @@ class LSformElement_supannRessourceEtat extends LSformElement_supannCompositeAtt
if (!$value['ressource'] || !$value['etat'])
return null;
$ret = "{".$value['ressource']."}".$value['etat'];
if (isset($value['sous_etat']) && !is_empty($matches['sous_etat']))
if (isset($value['sous_etat']) && !is_empty($value['sous_etat']))
$ret .= ":".$value['sous_etat'];
return $ret;
}

View File

@ -70,7 +70,7 @@ class LSformElement_supannRessourceEtatDate extends LSformElement_supannComposit
'required' => false,
),
);
return parent :: __construct($form, $name, $label, $params, $attr_html);
parent :: __construct($form, $name, $label, $params, $attr_html);
}
/**

View File

@ -54,7 +54,7 @@ class LSformElement_supannRoleEntite extends LSformElement_supannCompositeAttrib
'required' => false
)
);
return parent :: __construct($form, $name, $label, $params, $attr_html);
parent :: __construct($form, $name, $label, $params, $attr_html);
}
}

View File

@ -50,7 +50,7 @@ class LSformElement_xmpp extends LSformElement_text {
'chat' => _("Chat with this person.")
)
);
return parent :: getDisplay($return);
return parent :: getDisplay();
}
}

View File

@ -290,7 +290,9 @@ class LSio extends LSlog_staticLoggerClass {
$object = new $LSobject();
if (!$object -> loadData($dn)) {
self :: log_debug('import(): Failed to load data of '.$dn);
$globalErrors[] = getFData(_("Failed to load existing object %{dn} from LDAP server. Can't update object."));
$globalErrors[] = getFData(
_("Failed to load existing object %{dn} from LDAP server. Can't update object."),
$dn);
}
else {
// Instanciate a modify form (in API mode)
@ -585,7 +587,7 @@ class LSio extends LSlog_staticLoggerClass {
$ioFormat = $command_args[$i];
}
else
LScli :: usage("Invalid $arg parameter.");
LScli :: usage("Invalid ".$command_args[$i]." parameter.");
}
}

View File

@ -33,6 +33,7 @@ class LSioFormatCSV extends LSioFormatDriver {
private $enclosure = null;
private $escape = null;
private $length = null;
private $multiple_value_delimiter = null;
private $rows = null;
private $headers = null;

View File

@ -231,10 +231,360 @@ if (php_sapi_name() != "cli") return true;
*
* @retval boolean True on success, false otherwise
**/
global $LSlang_cli_logger, $available_onlys, $available_withouts;
global $LSlang_cli_logger, $available_onlys, $available_withouts;
$available_onlys = array("config", "templates", "addons", "auth_methods", "includes");
$available_withouts = array_merge($available_onlys, array("select-list"));
function _cli_relative2absolute_path($path) {
if ($path[0] == '/')
return $path;
global $curdir;
return realpath($curdir)."/".$path;
}
function _cli_absolute2relative_path($path) {
if ($path[0] == '/')
$path = realpath($path);
if (substr($path, 0, strlen(LS_ROOT_DIR)) == LS_ROOT_DIR)
return substr($path, strlen(LS_ROOT_DIR)+1);
return $path;
}
function _cli_interactive_ask($context, $msg) {
global $copyoriginalvalue, $interactive_exit;
if ($interactive_exit) {
if ($copyoriginalvalue)
return $msg;
return true;
}
// Format question
$empty_action = ($copyoriginalvalue?'copy original message':'pass');
$question ="\"$msg\"\n\n => Please enter translated string";
$question .= " (i";
if (!$copyoriginalvalue)
$question .= "/c";
$question .= "/q/? or leave empty to $empty_action): ";
while (true) {
if ($context)
fwrite(STDERR, "\n# $context\n");
fwrite(STDERR, $question);
$in = trim(fgets(STDIN));
switch($in) {
case 'q': // Exit interactive mode
case 'Q':
$interactive_exit = true;
return True;
case 'i': // Ignore
case 'I':
return True;
case 'c':
case 'C': // Copy
if (!$copyoriginalvalue)
return $msg;
case '?': // Help message
fwrite(STDERR, "Available choices:\n");
fwrite(STDERR, " - i: ignore this message\n");
if (!$copyoriginalvalue)
fwrite(STDERR, " - c: copy original message\n");
fwrite(STDERR, " - q: quit interactive mode and ignore all following untranslated messages\n");
fwrite(STDERR, " - ?: Show this message\n");
fwrite(STDERR, "Or leave empty to $empty_action.\n");
break;
case "": // Empty
// On copy orignal value mode, return $msg
if ($copyoriginalvalue)
return $msg;
// Otherwise, leave translation empty
return "";
default:
// Return user input
return $in;
}
}
// Supposed to never happen
return true;
}
function _cli_add_str_to_translate($msg, $context=null) {
global $LSlang_cli_logger, $lang, $data, $translations, $interactive, $interactive_exit, $copyoriginalvalue, $format;
$LSlang_cli_logger -> trace("_cli_add_str_to_translate($msg, $context)");
if ($msg == '')
return;
if (!is_null($lang) && _($msg) != "$msg")
return;
// Message already exists ?
if (array_key_exists($msg, $data)) {
if ($context && !in_array($context, $data[$msg]['contexts']))
$data[$msg]['contexts'][] = $context;
return True;
}
// Handle translation
$translation = "";
if (array_key_exists($msg, $translations)) {
$translation = $translations[$msg];
}
elseif (!is_null($lang) && _($msg) != $msg) {
$translation = _($msg);
}
elseif ($interactive && $format != 'pot') {
$translation = _cli_interactive_ask($context, $msg);
if (!is_string($translation))
return true;
}
$data[$msg] = array (
'translation' => $translation,
'contexts' => ($context?array($context):array()),
);
}
function _cli_add_str_to_translate_from_LSconfig($pattern, $value='value', $excludes=array()) {
global $LSlang_cli_logger;
$LSlang_cli_logger -> trace("_cli_add_str_to_translate_from_LSconfig($pattern, array(".implode(',', $excludes)."))");
$keys = LSconfig :: getMatchingKeys($pattern);
$LSlang_cli_logger -> trace("addFromLSconfig : ".count($keys)." matching key(s)");
foreach ($keys as $key => $value) {
$LSlang_cli_logger -> trace("addFromLSconfig : $key = ".varDump($value));
if ($value == 'key') {
// Get the last key parts as value and all other as key
$key_parts = explode('.', $key);
$value = $key_parts[count($key_parts)-1];
$key = implode('.', array_slice($key_parts, 0, count($key_parts)-1));
}
if (!in_array($value, $excludes) && is_string($value))
_cli_add_str_to_translate($value, $key);
}
}
function _cli_add_possible_values_from_LSconfig($context, $withouts, $level=0) {
global $LSlang_cli_logger;
$LSlang_cli_logger -> trace("_cli_add_possible_values_from_LSconfig($context)");
if (in_array('select-list', $withouts))
return true;
if (!LSconfig :: get("$context.translate_labels", True, "bool"))
return true;
foreach(LSconfig :: get("$context.possible_values", array()) as $pkey => $plabel) {
if (is_array($plabel)) {
// Sub possible values
// Check level
if ($level > 1) {
$LSlang_cli_logger -> warning(
"_cli_add_possible_values_from_LSconfig($context): Level to hight to handle sub possible values of $context.possible_values.$pkey"
);
return true;
}
_cli_add_str_to_translate_from_LSconfig("$context.possible_values.$pkey.label");
$LSlang_cli_logger -> trace("_cli_add_possible_values_from_LSconfig($context): handle sub possible values of $context.possible_values.$pkey");
_cli_add_possible_values_from_LSconfig("$context.possible_values.$pkey", $withouts, $level+1);
}
else {
switch ($pkey) {
case 'OTHER_OBJECT':
$LSlang_cli_logger -> trace("_cli_add_possible_values_from_LSconfig($context): ignore $context.possible_values.$pkey (OTHER_OBJECT)");
break;
case 'OTHER_ATTRIBUTE':
if (is_array($plabel)) {
if (isset($plabel['json_component_key']))
_cli_add_str_to_translate_from_LSconfig("$context.possible_values.OTHER_ATTRIBUTE.json_component_label");
else
_cli_add_str_to_translate_from_LSconfig("$context.possible_values.OTHER_ATTRIBUTE.*");
}
else {
$LSlang_cli_logger -> warning("_cli_add_possible_values_from_LSconfig($context): invalid $context.possible_values.OTHER_ATTRIBUTE config => Must be an array.");
}
break;
default:
_cli_add_str_to_translate($plabel, "$context.possible_values.$pkey");
break;
}
}
}
}
function _cli_parse_template_file($file) {
global $LSlang_cli_logger;
$LSlang_cli_logger -> debug("Looking for string to translate in '$file' template file");
$count = 0;
foreach(file($file) as $line) {
$count ++;
if (preg_match_all('/\{ *tr +msg=["\']([^\}]+)["\'] *\}/',$line,$matches)) {
foreach($matches[1] as $t) {
$t = preg_replace('/[\'"]\|escape\:.*$/', '', $t);
$LSlang_cli_logger -> trace(" - \"$t\" # Line $count");
_cli_add_str_to_translate($t, _cli_absolute2relative_path($file).":$count");
}
}
}
$LSlang_cli_logger -> trace("_cli_parse_template_file($file) : done.");
}
function _cli_find_and_parse_template_file($dir) {
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if ($file=='.' || $file=='..') continue;
if (is_dir($dir.'/'.$file)) {
_cli_find_and_parse_template_file($dir.'/'.$file);
}
elseif (is_file($dir."/".$file) && preg_match('/\.tpl$/',$file)) {
_cli_parse_template_file($dir.'/'.$file);
}
}
closedir($dh);
}
}
}
function _cli_parse_php_file($file) {
global $LSlang_cli_logger;
$LSlang_cli_logger -> debug("Looking for string to translate in '$file' PHP file");
$count = 0;
$quote='';
$res='';
foreach(file($file) as $line) {
$count++;
$LSlang_cli_logger -> trace("Handle line #$count of '$file' PHP file");
$offset=0;
while ($pos = strpos($line,'__(',$offset)) {
$LSlang_cli_logger -> trace("$file:$count: detect keyword at position #$pos ('$line')");
for ($i=$pos+3;$i<strlen($line);$i++) {
$offset=$i; // Always increase offset to avoid infinity-loop
if (empty($quote)) {
// Quote char not detected : try to detect it
if ($line[$i]=='\\' || $line[$i]==" " || $line[$i]=="\t") {
// Space or escape char : pass
$i++;
}
elseif ($line[$i]=='"' || $line[$i]=="'") {
// Quote detected
$quote=$line[$i];
}
elseif ($line[$i]=='$' || $line[$i]==')') {
// Variable translation not possible or end function call detected
break;
}
else {
// Unknown case : continue
$i++;
}
}
elseif (!empty($quote)) {
// Quote char already detected : try to detect end quote char
if ($line[$i]=='\\') {
// Escape char detected : pass this char and the following one
$res.=$line[$i];
$i++;
$res.=$line[$i];
}
elseif ($line[$i]==$quote) {
// End quote char detected : reset quote char detection and break detection
$quote='';
break;
}
else {
// End quote char not detected : append current char to result
$res.=$line[$i];
}
}
}
// Include detected string if not empty and quote char was detected and reseted
if (!empty($res) && empty($quote)) {
_cli_add_str_to_translate($res, _cli_absolute2relative_path($file).":$count");
$res='';
}
}
}
}
function _cli_find_and_parse_php_file($dir, $filename_regex) {
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if (preg_match($filename_regex, $file)) {
_cli_parse_php_file($dir.'/'.$file);
}
}
closedir($dh);
}
}
}
function _cli_output_php($fd) {
global $LSlang_cli_logger, $additionalfileformat, $data, $copyoriginalvalue, $keep_unused, $translations;
fwrite($fd, "<?php\n\n");
if (!$additionalfileformat) fwrite($fd, "\$GLOBALS['LSlang'] = array (\n");
foreach($data as $key => $key_data) {
if ($copyoriginalvalue && $key_data['translation'] == "") {
$val = $key;
}
else
$val = $key_data['translation'];
$key=str_replace('"','\\"',$key);
$val=str_replace('"','\\"',$val);
foreach ($key_data['contexts'] as $context)
fwrite($fd, "\n# $context");
if ($additionalfileformat) {
fwrite($fd, "\n\$GLOBALS['LSlang'][\"$key\"] = \"$val\";\n");
}
else {
fwrite($fd, "\n\"$key\" =>\n \"$val\",\n");
}
}
// Handle keep unused mode
if ($keep_unused) {
$unused_msgs = array();
foreach ($translations as $msg => $trans)
if (!array_key_exists($msg, $data))
$unused_msgs[$msg] = $trans;
if ($unused_msgs) {
fwrite($fd, "\n\n");
fwrite($fd, "######################################################################\n");
fwrite($fd, "# Unused translations keeped #\n");
fwrite($fd, "######################################################################\n");
foreach($unused_msgs as $key => $val) {
$key=str_replace('"','\\"',$key);
$val=str_replace('"','\\"',$val);
if ($additionalfileformat) {
fwrite($fd, "\n\$GLOBALS['LSlang'][\"$key\"] = \"$val\";\n");
}
else {
fwrite($fd, "\n\"$key\" =>\n \"$val\",\n");
}
}
}
}
if (!$additionalfileformat) fwrite($fd, "\n);\n");
}
function _cli_clean_for_pot_file($val) {
$val = str_replace('"', '\\"', $val);
return str_replace("\n", "\\n", $val);
}
function _cli_output_pot($fd) {
global $LSlang_cli_logger, $data, $copyoriginalvalue;
foreach($data as $key => $key_data) {
if ($copyoriginalvalue && $key_data['translation'] == "") {
$val = $key;
}
else
$val = $key_data['translation'];
foreach ($key_data['contexts'] as $context)
fwrite($fd, "#: $context\n");
$key = _cli_clean_for_pot_file($key);
$val = _cli_clean_for_pot_file($val);
fwrite($fd, "msgid \"$key\"\nmsgstr \"$val\"\n\n");
}
}
$available_onlys = array("config", "templates", "addons", "auth_methods", "includes");
$available_withouts = array_merge($available_onlys, array("select-list"));
function cli_generate_lang_file($command_args) {
// Use global variables to share it with sub-functions
global $LSlang_cli_logger, $available_onlys, $available_withouts, $data, $translations, $interactive,
@ -273,21 +623,6 @@ function cli_generate_lang_file($command_args) {
$curdir = getcwd();
chdir(dirname(__FILE__).'/../');
function relative2absolute_path($path) {
if ($path[0] == '/')
return $path;
global $curdir;
return realpath($curdir)."/".$path;
}
function absolute2relative_path($path) {
if ($path[0] == '/')
$path = realpath($path);
if (substr($path, 0, strlen(LS_ROOT_DIR)) == LS_ROOT_DIR)
return substr($path, strlen(LS_ROOT_DIR)+1);
return $path;
}
for ($i=0; $i < count($command_args); $i++) {
switch ($command_args[$i]) {
case '--without':
@ -377,7 +712,7 @@ function cli_generate_lang_file($command_args) {
break;
default:
$path = relative2absolute_path($command_args[$i]);
$path = _cli_relative2absolute_path($command_args[$i]);
if (is_file($path))
$load_files[] = $path;
else
@ -385,115 +720,7 @@ function cli_generate_lang_file($command_args) {
}
}
function interactive_ask($context, $msg) {
global $copyoriginalvalue, $interactive_exit;
if ($interactive_exit) {
if ($copyoriginalvalue)
return $msg;
return true;
}
// Format question
$empty_action = ($copyoriginalvalue?'copy original message':'pass');
$question ="\"$msg\"\n\n => Please enter translated string";
$question .= " (i";
if (!$copyoriginalvalue)
$question .= "/c";
$question .= "/q/? or leave empty to $empty_action): ";
while (true) {
if ($context)
fwrite(STDERR, "\n# $context\n");
fwrite(STDERR, $question);
$in = trim(fgets(STDIN));
switch($in) {
case 'q': // Exit interactive mode
case 'Q':
$interactive_exit = true;
return True;
case 'i': // Ignore
case 'I':
return True;
case 'c':
case 'C': // Copy
if (!$copyoriginalvalue)
return $msg;
case '?': // Help message
fwrite(STDERR, "Available choices:\n");
fwrite(STDERR, " - i: ignore this message\n");
if (!$copyoriginalvalue)
fwrite(STDERR, " - c: copy original message\n");
fwrite(STDERR, " - q: quit interactive mode and ignore all following untranslated messages\n");
fwrite(STDERR, " - ?: Show this message\n");
fwrite(STDERR, "Or leave empty to $empty_action.\n");
break;
case "": // Empty
// On copy orignal value mode, return $msg
if ($copyoriginalvalue)
return $msg;
// Otherwise, leave translation empty
return "";
default:
// Return user input
return $in;
}
}
// Supposed to never happen
return true;
}
function add($msg, $context=null) {
global $LSlang_cli_logger, $lang, $data, $translations, $interactive, $interactive_exit, $copyoriginalvalue, $format;
$LSlang_cli_logger -> trace("add($msg, $context)");
if ($msg == '')
return;
if (!is_null($lang) && _($msg) != "$msg")
return;
// Message already exists ?
if (array_key_exists($msg, $data)) {
if ($context && !in_array($context, $data[$msg]['contexts']))
$data[$msg]['contexts'][] = $context;
return True;
}
// Handle translation
$translation = "";
if (array_key_exists($msg, $translations)) {
$translation = $translations[$msg];
}
elseif (!is_null($lang) && _($msg) != $msg) {
$translation = _($msg);
}
elseif ($interactive && $format != 'pot') {
$translation = interactive_ask($context, $msg);
if (!is_string($translation))
return true;
}
$data[$msg] = array (
'translation' => $translation,
'contexts' => ($context?array($context):array()),
);
}
function addFromLSconfig($pattern, $value='value', $excludes=array()) {
global $LSlang_cli_logger;
$LSlang_cli_logger -> trace("addFromLSconfig($pattern, array(".implode(',', $excludes)."))");
$keys = LSconfig :: getMatchingKeys($pattern);
$LSlang_cli_logger -> trace("addFromLSconfig : ".count($keys)." matching key(s)");
foreach ($keys as $key => $value) {
$LSlang_cli_logger -> trace("addFromLSconfig : $key = ".varDump($value));
if ($value == 'key') {
// Get the last key parts as value and all other as key
$key_parts = explode('.', $key);
$value = $key_parts[count($key_parts)-1];
$key = implode('.', array_slice($key_parts, 0, count($key_parts)-1));
}
if (!in_array($value, $excludes) && is_string($value))
add($value, $key);
}
}
// In fix-utf8 mode, load ForceUT8/Encoding lib
if ($fix_utf8)
@ -524,51 +751,6 @@ function cli_generate_lang_file($command_args) {
}
}
function addPossibleValuesFromLSconfig($context, $withouts, $level=0) {
global $LSlang_cli_logger;
$LSlang_cli_logger -> trace("addPossibleValuesFromLSconfig($context)");
if (in_array('select-list', $withouts))
return true;
if (!LSconfig :: get("$context.translate_labels", True, "bool"))
return true;
foreach(LSconfig :: get("$context.possible_values", array()) as $pkey => $plabel) {
if (is_array($plabel)) {
// Sub possible values
// Check level
if ($level > 1) {
$LSlang_cli_logger -> warning(
"addPossibleValuesFromLSconfig($context): Level to hight to handle sub possible values of $context.possible_values.$pkey"
);
return true;
}
addFromLSconfig("$context.possible_values.$pkey.label");
$LSlang_cli_logger -> trace("addPossibleValuesFromLSconfig($context): handle sub possible values of $context.possible_values.$pkey");
addPossibleValuesFromLSconfig("$context.possible_values.$pkey", $withouts, $level+1);
}
else {
switch ($pkey) {
case 'OTHER_OBJECT':
$LSlang_cli_logger -> trace("addPossibleValuesFromLSconfig($context): ignore $context.possible_values.$pkey (OTHER_OBJECT)");
break;
case 'OTHER_ATTRIBUTE':
if (is_array($plabel)) {
if (isset($plabel['json_component_key']))
addFromLSconfig("$context.possible_values.OTHER_ATTRIBUTE.json_component_label");
else
addFromLSconfig("$context.possible_values.OTHER_ATTRIBUTE.*");
}
else {
$LSlang_cli_logger -> warning("addPossibleValuesFromLSconfig($context): invalid $context.possible_values.OTHER_ATTRIBUTE config => Must be an array.");
}
break;
default:
add($plabel, "$context.possible_values.$pkey");
break;
}
}
}
}
/*
* Manage configuration parameters
*/
@ -578,14 +760,14 @@ function cli_generate_lang_file($command_args) {
$LSlang_cli_logger -> info("Looking for string to translate configuration of LDAP servers");
foreach(LSconfig :: keys('ldap_servers') as $ldap_server_id) {
$LSlang_cli_logger -> debug("Looking for string to translate configuration of LDAP server #$ldap_server_id");
addFromLSconfig("ldap_servers.$ldap_server_id.name");
addFromLSconfig("ldap_servers.$ldap_server_id.subDnLabel");
addFromLSconfig("ldap_servers.$ldap_server_id.recoverPassword.recoveryHashMail.subject");
addFromLSconfig("ldap_servers.$ldap_server_id.recoverPassword.recoveryHashMail.msg");
addFromLSconfig("ldap_servers.$ldap_server_id.recoverPassword.newPasswordMail.subject");
addFromLSconfig("ldap_servers.$ldap_server_id.recoverPassword.newPasswordMail.msg");
addFromLSconfig("ldap_servers.$ldap_server_id.subDn.*", 'key', array("LSobject"));
addFromLSconfig("ldap_servers.$ldap_server_id.LSprofiles.*.label");
_cli_add_str_to_translate_from_LSconfig("ldap_servers.$ldap_server_id.name");
_cli_add_str_to_translate_from_LSconfig("ldap_servers.$ldap_server_id.subDnLabel");
_cli_add_str_to_translate_from_LSconfig("ldap_servers.$ldap_server_id.recoverPassword.recoveryHashMail.subject");
_cli_add_str_to_translate_from_LSconfig("ldap_servers.$ldap_server_id.recoverPassword.recoveryHashMail.msg");
_cli_add_str_to_translate_from_LSconfig("ldap_servers.$ldap_server_id.recoverPassword.newPasswordMail.subject");
_cli_add_str_to_translate_from_LSconfig("ldap_servers.$ldap_server_id.recoverPassword.newPasswordMail.msg");
_cli_add_str_to_translate_from_LSconfig("ldap_servers.$ldap_server_id.subDn.*", 'key', array("LSobject"));
_cli_add_str_to_translate_from_LSconfig("ldap_servers.$ldap_server_id.LSprofiles.*.label");
// LSaccess
foreach (LSconfig :: get("ldap_servers.$ldap_server_id.LSaccess", array()) as $LSobject) {
@ -606,76 +788,76 @@ function cli_generate_lang_file($command_args) {
// LSobject
foreach($objects as $obj) {
$LSlang_cli_logger -> info("Looking for string to translate configuration of object type $obj");
addFromLSconfig("LSobjects.$obj.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.label");
// LSrelation
addFromLSconfig("LSobjects.$obj.LSrelation.*.label");
addFromLSconfig("LSobjects.$obj.LSrelation.*.emptyText");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSrelation.*.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSrelation.*.emptyText");
// Custom Actions
addFromLSconfig("LSobjects.$obj.customActions.*.label");
addFromLSconfig("LSobjects.$obj.customActions.*.helpInfo");
addFromLSconfig("LSobjects.$obj.customActions.*.question_format");
addFromLSconfig("LSobjects.$obj.customActions.*.onSuccessMsgFormat");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.customActions.*.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.customActions.*.helpInfo");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.customActions.*.question_format");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.customActions.*.onSuccessMsgFormat");
// LSform
addFromLSconfig("LSobjects.$obj.LSform.layout.*.label");
addFromLSconfig("LSobjects.$obj.LSform.dataEntryForm.*.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSform.layout.*.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSform.dataEntryForm.*.label");
// LSsearch
addFromLSconfig("LSobjects.$obj.LSsearch.predefinedFilters.*");
addFromLSconfig("LSobjects.$obj.LSsearch.extraDisplayedColumns.*.label");
addFromLSconfig("LSobjects.$obj.LSsearch.extraDisplayedColumns.*.LSformat");
addFromLSconfig("LSobjects.$obj.LSsearch.extraDisplayedColumns.*.alternativeLSformats.*");
addFromLSconfig("LSobjects.$obj.LSsearch.extraDisplayedColumns.*.formaterLSformat");
addFromLSconfig("LSobjects.$obj.LSsearch.customActions.*.label");
addFromLSconfig("LSobjects.$obj.LSsearch.customActions.*.question_format");
addFromLSconfig("LSobjects.$obj.LSsearch.customActions.*.onSuccessMsgFormat");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSsearch.predefinedFilters.*");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSsearch.extraDisplayedColumns.*.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSsearch.extraDisplayedColumns.*.LSformat");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSsearch.extraDisplayedColumns.*.alternativeLSformats.*");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSsearch.extraDisplayedColumns.*.formaterLSformat");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSsearch.customActions.*.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSsearch.customActions.*.question_format");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.LSsearch.customActions.*.onSuccessMsgFormat");
// Attributes
foreach(LSconfig :: keys("LSobjects.$obj.attrs") as $attr) {
addFromLSconfig("LSobjects.$obj.attrs.$attr.label");
addFromLSconfig("LSobjects.$obj.attrs.$attr.help_info");
addFromLSconfig("LSobjects.$obj.attrs.$attr.no_value_label");
addFromLSconfig("LSobjects.$obj.attrs.$attr.check_data.*.msg");
addFromLSconfig("LSobjects.$obj.attrs.$attr.validation.*.msg");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.help_info");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.no_value_label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.check_data.*.msg");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.validation.*.msg");
// HTML Options
$html_type = LSconfig :: get("LSobjects.$obj.attrs.$attr.html_type");
switch($html_type) {
case 'boolean':
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.true_label");
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.false_label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.true_label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.false_label");
break;
case 'jsonCompositeAttribute':
$components = LSconfig :: keys("LSobjects.$obj.attrs.$attr.html_options.components");
foreach($components as $c) {
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.components.$c.label");
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.components.$c.help_info");
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.components.$c.check_data.*.msg");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.components.$c.label");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.components.$c.help_info");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.components.$c.check_data.*.msg");
if (LSconfig :: get("LSobjects.$obj.attrs.$attr.html_options.components.$c.type") == 'select_list')
addPossibleValuesFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.components.$c.options", $withouts);
_cli_add_possible_values_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.components.$c.options", $withouts);
}
break;
case 'labeledValue':
if (LSconfig :: get("LSobjects.$obj.attrs.$attr.html_options.translate_labels", True, "bool"))
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.labels.*");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.labels.*");
break;
case 'password':
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.mail.subject");
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.mail.msg");
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.confirmChangeQuestion");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.mail.subject");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.mail.msg");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.confirmChangeQuestion");
break;
case 'select_list':
case 'select_box':
addPossibleValuesFromLSconfig("LSobjects.$obj.attrs.$attr.html_options", $withouts);
_cli_add_possible_values_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options", $withouts);
break;
case 'valueWithUnit':
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.units.*");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.units.*");
break;
case 'date':
addFromLSconfig("LSobjects.$obj.attrs.$attr.html_options.special_values.*");
_cli_add_str_to_translate_from_LSconfig("LSobjects.$obj.attrs.$attr.html_options.special_values.*");
break;
}
}
@ -686,151 +868,39 @@ function cli_generate_lang_file($command_args) {
* Manage template file
*/
if (!in_array('templates', $withouts) && (!$only || $only == 'templates')) {
function parse_template_file($file) {
global $LSlang_cli_logger;
$LSlang_cli_logger -> debug("Looking for string to translate in '$file' template file");
$count = 0;
foreach(file($file) as $line) {
$count ++;
if (preg_match_all('/\{ *tr +msg=["\']([^\}]+)["\'] *\}/',$line,$matches)) {
foreach($matches[1] as $t) {
$t = preg_replace('/[\'"]\|escape\:.*$/', '', $t);
$LSlang_cli_logger -> trace(" - \"$t\" # Line $count");
add($t, absolute2relative_path($file).":$count");
}
}
}
$LSlang_cli_logger -> trace("parse_template_file($file) : done.");
}
function find_and_parse_template_file($dir) {
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if ($file=='.' || $file=='..') continue;
if (is_dir($dir.'/'.$file)) {
find_and_parse_template_file($dir.'/'.$file);
}
elseif (is_file($dir."/".$file) && preg_match('/\.tpl$/',$file)) {
parse_template_file($dir.'/'.$file);
}
}
closedir($dh);
}
}
}
$LSlang_cli_logger -> info("Looking for string to translate in templates file");
if ($include_upstream) find_and_parse_template_file(LS_ROOT_DIR.'/'.LS_TEMPLATES_DIR);
find_and_parse_template_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_TEMPLATES_DIR);
if ($include_upstream) _cli_find_and_parse_template_file(LS_ROOT_DIR.'/'.LS_TEMPLATES_DIR);
_cli_find_and_parse_template_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_TEMPLATES_DIR);
}
/*
* Manage custom PHP code/config files
*/
function parse_php_file($file) {
global $LSlang_cli_logger;
$LSlang_cli_logger -> debug("Looking for string to translate in '$file' PHP file");
$count = 0;
$quote='';
$res='';
foreach(file($file) as $line) {
$count++;
$LSlang_cli_logger -> trace("Handle line #$count of '$file' PHP file");
$offset=0;
while ($pos = strpos($line,'__(',$offset)) {
$LSlang_cli_logger -> trace("$file:$count: detect keyword at position #$pos ('$line')");
for ($i=$pos+3;$i<strlen($line);$i++) {
$offset=$i; // Always increase offset to avoid infinity-loop
if (empty($quote)) {
// Quote char not detected : try to detect it
if ($line[$i]=='\\' || $line[$i]==" " || $line[$i]=="\t") {
// Space or escape char : pass
$i++;
}
elseif ($line[$i]=='"' || $line[$i]=="'") {
// Quote detected
$quote=$line[$i];
}
elseif ($line[$i]=='$' || $line[$i]==')') {
// Variable translation not possible or end function call detected
break;
}
else {
// Unknown case : continue
$i++;
}
}
elseif (!empty($quote)) {
// Quote char already detected : try to detect end quote char
if ($line[$i]=='\\') {
// Escape char detected : pass this char and the following one
$res.=$line[$i];
$i++;
$res.=$line[$i];
}
elseif ($line[$i]==$quote) {
// End quote char detected : reset quote char detection and break detection
$quote='';
break;
}
else {
// End quote char not detected : append current char to result
$res.=$line[$i];
}
}
}
// Include detected string if not empty and quote char was detected and reseted
if (!empty($res) && empty($quote)) {
add($res, absolute2relative_path($file).":$count");
$res='';
}
}
}
}
function find_and_parse_php_file($dir, $filename_regex) {
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if (preg_match($filename_regex, $file)) {
parse_php_file($dir.'/'.$file);
}
}
closedir($dh);
}
}
}
/*
* Manage includes files
*/
// Manage includes files
if (!in_array('includes', $withouts) && (!$only || $only == 'includes')) {
// Note: Upstream code most only use gettext translation, do not handle it here
if ($include_upstream) find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_INCLUDE_DIR, '/^(.+)\.php$/');
find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_INCLUDE_DIR, '/^(.+)\.php$/');
if ($include_upstream) find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_CLASS_DIR, '/^class\.(.+)\.php$/');
find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_CLASS_DIR, '/^class\.(.+)\.php$/');
if ($include_upstream) _cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_INCLUDE_DIR, '/^(.+)\.php$/');
_cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_INCLUDE_DIR, '/^(.+)\.php$/');
if ($include_upstream) _cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_CLASS_DIR, '/^class\.(.+)\.php$/');
_cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_CLASS_DIR, '/^class\.(.+)\.php$/');
}
/*
* Manage addons files
*/
// Manage addons files
if (!in_array('addons', $withouts) && (!$only || $only == 'addons')) {
$LSlang_cli_logger -> info("Looking for string to translate in LSaddons PHP code");
if ($include_upstream) find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_ADDONS_DIR, '/^LSaddons\.(.+)\.php$/');
find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_ADDONS_DIR, '/^LSaddons\.(.+)\.php$/');
if ($include_upstream) _cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_ADDONS_DIR, '/^LSaddons\.(.+)\.php$/');
_cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_ADDONS_DIR, '/^LSaddons\.(.+)\.php$/');
$LSlang_cli_logger -> info("Looking for string to translate in LSaddons configuration files");
if ($include_upstream) find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_CONF_DIR.'/LSaddons', '/^config\.LSaddons\.(.+)\.php$$/');
find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_CONF_DIR.'/LSaddons', '/^config\.LSaddons\.(.+)\.php$$/');
if ($include_upstream) _cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_CONF_DIR.'/LSaddons', '/^config\.LSaddons\.(.+)\.php$$/');
_cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_CONF_DIR.'/LSaddons', '/^config\.LSaddons\.(.+)\.php$$/');
}
/*
* Manage auth methods files
*/
// Manage auth methods files
if (!in_array('auth_methods', $withouts) && (!$only || $only == 'auth_methods')) {
$LSlang_cli_logger -> info("Looking for string to translate in LSauthMethods configuration files");
if ($include_upstream) find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_CONF_DIR.'/LSauth', '/^config\.(.+)\.php$$/');
find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_CONF_DIR.'/LSauth', '/^config\.(.+)\.php$$/');
if ($include_upstream) _cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_CONF_DIR.'/LSauth', '/^config\.(.+)\.php$$/');
_cli_find_and_parse_php_file(LS_ROOT_DIR.'/'.LS_LOCAL_DIR.LS_CONF_DIR.'/LSauth', '/^config\.(.+)\.php$$/');
}
// Sort resulting strings
@ -839,81 +909,10 @@ function cli_generate_lang_file($command_args) {
/*
* Handle output file format
*/
function output_php($fd) {
global $LSlang_cli_logger, $additionalfileformat, $data, $copyoriginalvalue, $keep_unused, $translations;
fwrite($fd, "<?php\n\n");
if (!$additionalfileformat) fwrite($fd, "\$GLOBALS['LSlang'] = array (\n");
foreach($data as $key => $key_data) {
if ($copyoriginalvalue && $key_data['translation'] == "") {
$val = $key;
}
else
$val = $key_data['translation'];
$key=str_replace('"','\\"',$key);
$val=str_replace('"','\\"',$val);
foreach ($key_data['contexts'] as $context)
fwrite($fd, "\n# $context");
if ($additionalfileformat) {
fwrite($fd, "\n\$GLOBALS['LSlang'][\"$key\"] = \"$val\";\n");
}
else {
fwrite($fd, "\n\"$key\" =>\n \"$val\",\n");
}
}
// Handle keep unused mode
if ($keep_unused) {
$unused_msgs = array();
foreach ($translations as $msg => $trans)
if (!array_key_exists($msg, $data))
$unused_msgs[$msg] = $trans;
if ($unused_msgs) {
fwrite($fd, "\n\n");
fwrite($fd, "######################################################################\n");
fwrite($fd, "# Unused translations keeped #\n");
fwrite($fd, "######################################################################\n");
foreach($unused_msgs as $key => $val) {
$key=str_replace('"','\\"',$key);
$val=str_replace('"','\\"',$val);
if ($additionalfileformat) {
fwrite($fd, "\n\$GLOBALS['LSlang'][\"$key\"] = \"$val\";\n");
}
else {
fwrite($fd, "\n\"$key\" =>\n \"$val\",\n");
}
}
}
}
if (!$additionalfileformat) fwrite($fd, "\n);\n");
}
function clean_for_pot_file($val) {
$val = str_replace('"', '\\"', $val);
return str_replace("\n", "\\n", $val);
}
function output_pot($fd) {
global $LSlang_cli_logger, $data, $copyoriginalvalue;
foreach($data as $key => $key_data) {
if ($copyoriginalvalue && $key_data['translation'] == "") {
$val = $key;
}
else
$val = $key_data['translation'];
foreach ($key_data['contexts'] as $context)
fwrite($fd, "#: $context\n");
$key = clean_for_pot_file($key);
$val = clean_for_pot_file($val);
fwrite($fd, "msgid \"$key\"\nmsgstr \"$val\"\n\n");
}
}
// Determine where to write result
if ($output) {
$output = relative2absolute_path($output);
$output = _cli_relative2absolute_path($output);
$LSlang_cli_logger -> info("Write result in output file ($output)");
try {
$LSlang_cli_logger -> debug("Open output file ($output)");
@ -935,11 +934,11 @@ function cli_generate_lang_file($command_args) {
$LSlang_cli_logger -> debug("Output format : $format");
switch($format) {
case 'pot':
output_pot($fd);
_cli_output_pot($fd);
break;
case 'php':
default:
output_php($fd);
_cli_output_php($fd);
break;
}

View File

@ -2329,7 +2329,7 @@ class LSldapObject extends LSlog_staticLoggerClass {
}
if ($confirm) {
$obj -> _cli_show($raw_values);
$obj -> _cli_show();
// Sure ?
if (!LScli :: confirm("\nAre you sure you want to delete this object?"))
return True;

View File

@ -237,7 +237,7 @@ class LSlog_handler extends LSlog_staticLoggerClass {
if (isset(LSsession :: $ldapServer['name']))
return LSsession :: $ldapServer['name'];
else
return "#".LSsession :: $ldapServerId;
return "#".LSsession :: get('ldap_server_id');
}
return "Not connected";
}

View File

@ -135,7 +135,7 @@ class LSsearch extends LSlog_staticLoggerClass {
foreach($this -> config['predefinedFilters'] as $filter => $label) {
if(!LSldap::isValidFilter($filter)) {
LSerror::addErrorCode('LSsearch_15',array('label' => $label, 'filter' => $filter, 'type' => $this -> LSobject));
unset($this -> config['predefinedFilters'][$key]);
unset($this -> config['predefinedFilters'][$filter]);
}
}
}
@ -1049,7 +1049,7 @@ class LSsearch extends LSlog_staticLoggerClass {
}
if (!$searchParams)
return false;
if ($searchParams['filter'] instanceof Net_LDAP_Filter) {
if ($searchParams['filter'] instanceof Net_LDAP2_Filter) {
$searchParams['filter'] = $searchParams['filter'] -> asString();
}
$to_hash = print_r($searchParams, true);

View File

@ -140,6 +140,8 @@ class LSsession {
return self :: getEmailSender();
case 'api_mode':
return boolval(self :: $api_mode);
case 'ldap_server_id':
return boolval(self :: $ldapServerId);
}
return null;
}
@ -2414,7 +2416,7 @@ class LSsession {
* @param string $authorized The authorized maximum right
* @return boolean
*/
public function checkRight($requested, $authorized) {
public static function checkRight($requested, $authorized) {
if ($requested == $authorized)
return true;
if ($requested == 'r' && $authorized == 'w')
@ -3161,7 +3163,7 @@ class LSsession {
'LSsession_21',
array(
'func' => $func -> getName(),
'addon' => $addon,
'addon' => $LSaddon,
'view' => $viewId,
)
);
@ -3172,7 +3174,7 @@ class LSsession {
'LSsession_23',
array(
'func' => $viewFunction,
'addon' => $addon,
'addon' => $LSaddon,
'view' => $viewId,
)
);

View File

@ -788,7 +788,7 @@ function dateTime2LdapDate($datetime, $timezone=null, $format=null) {
$datetime -> setTimezone(timezone_open(is_null($timezone)?'UTC':$timezone));
}
if (is_null($format))
$format = ($naive?'YmdHis':'YmdHisO');
$format = ($timezone == 'naive'?'YmdHis':'YmdHisO');
$datetime_string = $datetime -> format($format);
// Replace +0000 or -0000 end by Z

View File

@ -1775,7 +1775,7 @@ function handle_api_LSobject_import($request) {
$data['updateIfExists'],
$data['justTry']
);
LSlog :: debug("LSio::importFromPostData(): result = ".varDump($result));
LSlog :: debug("LSio::importFromPostData(): result = ".varDump($data));
}
LSsession :: displayAjaxReturn($data);
@ -1946,7 +1946,7 @@ function handle_api_LSobject_remove($request) {
$data['success'] = true;
}
else {
LSerror :: addErrorCode('LSldapObject_15', $objectname);
LSerror :: addErrorCode('LSldapObject_15', $data['name']);
}
LSsession :: displayAjaxReturn($data);
}
@ -1972,7 +1972,7 @@ function handle_api_LSobject_relation($request) {
// Handle relation URL parameter
$relationName = $request -> relation;
if (!is_array($object -> getConfig("LSrelation.$relationName"))) {
LSlog :: log_error("LSobject $LSobject have no relation '$relationName'.");
LSlog :: error("LSobject $LSobject have no relation '$relationName'.");
LSsession :: displayAjaxReturn();
return false;
}