mirror of
https://github.com/Combodo/iTop.git
synced 2026-06-22 15:56:37 +02:00
Compare commits
9 Commits
fatal-setu
...
feature/63
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5a6b34b1e | ||
|
|
9b4f3290e8 | ||
|
|
67792155dd | ||
|
|
a23b9aa596 | ||
|
|
017481af21 | ||
|
|
4f70441618 | ||
|
|
fb6a332bd0 | ||
|
|
a9af4fc060 | ||
|
|
6a8dc159c1 |
@@ -97,33 +97,125 @@ class RestUtils
|
||||
* @throws Exception
|
||||
* @api
|
||||
*/
|
||||
public static function GetFieldList($sClass, $oData, $sParamName)
|
||||
public static function GetFieldList($sClass, $oData, $sParamName, $bFailIfNotFound = true)
|
||||
{
|
||||
$sFields = self::GetOptionalParam($oData, $sParamName, '*');
|
||||
$aShowFields = [];
|
||||
if ($sFields == '*') {
|
||||
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
|
||||
$aShowFields[$sClass][] = $sAttCode;
|
||||
}
|
||||
} elseif ($sFields == '*+') {
|
||||
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
|
||||
foreach (MetaModel::ListAttributeDefs($sRefClass) as $sAttCode => $oAttDef) {
|
||||
$aShowFields[$sRefClass][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (explode(',', $sFields) as $sAttCode) {
|
||||
$sAttCode = trim($sAttCode);
|
||||
if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode))) {
|
||||
throw new Exception("$sParamName: invalid attribute code '$sAttCode'");
|
||||
}
|
||||
$aShowFields[$sClass][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
|
||||
return $aShowFields;
|
||||
return match($sFields) {
|
||||
'*' => self::GetFieldListForClass($sClass),
|
||||
'*+' => self::GetFieldListForParentClass($sClass),
|
||||
default => self::GetLimitedFieldListForClass($sClass, $sFields, $sParamName, $bFailIfNotFound),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the requested field list asks for an extended output.
|
||||
*
|
||||
* Extended output is requested when using '*+' or class-scoped field definitions.
|
||||
*
|
||||
* @param string $sFields Requested field specification.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function HasRequestedExtendedOutput(string $sFields): bool
|
||||
{
|
||||
return match($sFields) {
|
||||
'*' => false,
|
||||
'*+' => true,
|
||||
default => substr_count($sFields, ':') > 1,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the requested field list asks for all output fields.
|
||||
*
|
||||
* @param string $sFields Requested field specification.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function HasRequestedAllOutputFields(string $sFields): bool
|
||||
{
|
||||
return match($sFields) {
|
||||
'*', '*+' => true,
|
||||
default => false,
|
||||
};
|
||||
}
|
||||
|
||||
protected static function GetFieldListForClass(string $sClass): array
|
||||
{
|
||||
return [$sClass => array_keys(MetaModel::ListAttributeDefs($sClass))];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a field list for all child classes of the given parent class.
|
||||
*
|
||||
* @param string $sClass Parent class name.
|
||||
*
|
||||
* @return array Array of class => list of attribute codes.
|
||||
*/
|
||||
protected static function GetFieldListForParentClass(string $sClass): array
|
||||
{
|
||||
$aFieldList = array();
|
||||
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
|
||||
$aFieldList = array_merge($aFieldList, self::GetFieldListForClass($sRefClass));
|
||||
}
|
||||
return $aFieldList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a restricted field list for one class from a comma-separated attribute list.
|
||||
*
|
||||
* @param string $sClass Class name.
|
||||
* @param string $sFields Comma-separated list of requested attribute codes.
|
||||
* @param string $sParamName Input parameter name used in error messages.
|
||||
* @param bool $bFailIfNotFound If true, throws when an attribute code is invalid.
|
||||
*
|
||||
* @return array Array containing one class => list of attribute codes.
|
||||
* @throws Exception When an attribute code is invalid and $bFailIfNotFound is true.
|
||||
*/
|
||||
protected static function GetLimitedFieldListForSingleClass(string $sClass, string $sFields, string $sParamName, bool $bFailIfNotFound = true): array
|
||||
{
|
||||
$aFieldList = [$sClass => []];
|
||||
foreach (explode(',', $sFields) as $sAttCode) {
|
||||
$sAttCode = trim($sAttCode);
|
||||
if (($sAttCode == 'id') || (MetaModel::IsValidAttCode($sClass, $sAttCode))) {
|
||||
$aFieldList[$sClass][] = $sAttCode;
|
||||
} else {
|
||||
if ($bFailIfNotFound) {
|
||||
throw new Exception("$sParamName: invalid attribute code '$sAttCode' for class '$sClass'");
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aFieldList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a restricted field list for one or several classes.
|
||||
*
|
||||
* Accepted formats are either "att1,att2" for a single class, or
|
||||
* "ClassA:att1,att2;ClassB:att3" for class-scoped field definitions.
|
||||
*
|
||||
* @param string $sClass Default class name used when no class scope is specified.
|
||||
* @param string $sFields Requested field specification.
|
||||
* @param string $sParamName Input parameter name used in error messages.
|
||||
* @param bool $bFailIfNotFound If true, throws when an attribute code is invalid.
|
||||
*
|
||||
* @return array Array of class => list of attribute codes.
|
||||
* @throws Exception Propagated from GetLimitedFieldListForSingleClass.
|
||||
*/
|
||||
protected static function GetLimitedFieldListForClass(string $sClass, string $sFields, string $sParamName, bool $bFailIfNotFound = true): array
|
||||
{
|
||||
if (!str_contains($sFields, ':')) {
|
||||
return self::GetLimitedFieldListForSingleClass($sClass, $sFields, $sParamName, $bFailIfNotFound);
|
||||
}
|
||||
|
||||
$aFieldList = [];
|
||||
$aFieldListParts = explode(';', $sFields);
|
||||
foreach ($aFieldListParts as $sClassFields) {
|
||||
list($sSubClass, $sSubClassFields) = explode(':', $sClassFields);
|
||||
$aFieldList = array_merge($aFieldList, self::GetLimitedFieldListForSingleClass(trim($sSubClass), trim($sSubClassFields), $sParamName, $bFailIfNotFound));
|
||||
}
|
||||
return $aFieldList;
|
||||
}
|
||||
/**
|
||||
* Read and interpret object search criteria from a Rest/Json structure
|
||||
*
|
||||
|
||||
@@ -284,7 +284,8 @@ class UIExtKeyWidget
|
||||
if ($bAddingValue) {
|
||||
$aArguments = [];
|
||||
foreach ($aAdditionalField as $sAdditionalField) {
|
||||
array_push($aArguments, $oObj->Get($sAdditionalField));
|
||||
//getAsCSV to have user friendly value in text format
|
||||
array_push($aArguments, $oObj->GetAsCSV($sAdditionalField, ' ', ''));
|
||||
}
|
||||
$aOption['additional_field'] = utils::HtmlEntities(utils::VSprintf($sFormatAdditionalField, $aArguments));
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class ormPassword
|
||||
public function SetPassword($sClearTextPassword)
|
||||
{
|
||||
$iHashAlgo = MetaModel::GetConfig()->GetPasswordHashAlgo();
|
||||
$this->m_sHashed = password_hash($sClearTextPassword, $iHashAlgo);
|
||||
$this->m_sHashed = password_hash($sClearTextPassword ?? '', $iHashAlgo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,10 +99,10 @@ class ormPassword
|
||||
$aInfo = password_get_info($this->m_sHashed);
|
||||
if (is_null($aInfo["algo"]) || $aInfo["algo"] === 0) {
|
||||
// - Unknown algorithm, assume it's a legacy password
|
||||
$sHashedPwd = $this->ComputeHash($sClearTextPassword);
|
||||
$sHashedPwd = $this->ComputeHash($sClearTextPassword ?? '');
|
||||
$bResult = hash_equals($this->m_sHashed, $sHashedPwd);
|
||||
} else {
|
||||
$bResult = password_verify($sClearTextPassword, $this->m_sHashed);
|
||||
$bResult = password_verify($sClearTextPassword ?? '', $this->m_sHashed);
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
@@ -248,6 +248,45 @@ class RestResultWithObjects extends RestResult
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @package RESTAPI
|
||||
* @api
|
||||
*/
|
||||
class RestResultWithObjectSets extends RestResultWithObjects
|
||||
{
|
||||
private $current_object = null;
|
||||
|
||||
public function MakeNewObjectSet()
|
||||
{
|
||||
$arr = array();
|
||||
$this->current_object = &$arr;
|
||||
$this->objects[] = &$arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report the given object
|
||||
*
|
||||
* @api
|
||||
* @param string $sObjectAlias Name of the subobject, usually the OQL class alias
|
||||
* @param int $iCode An error code (RestResult::OK is no issue has been found)
|
||||
* @param string $sMessage Description of the error if any, an empty string otherwise
|
||||
* @param DBObject $oObject The object being reported
|
||||
* @param array|null $aFieldSpec An array of class => attribute codes (Cf. RestUtils::GetFieldList). List of the attributes to be reported.
|
||||
* @param boolean $bExtendedOutput Output all of the link set attributes ?
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function AppendSubObject($sObjectAlias, $iCode, $sMessage, $oObject, $aFieldSpec = null, $bExtendedOutput = false)
|
||||
{
|
||||
$oObjRes = ObjectResult::FromDBObject($oObject, $aFieldSpec, $bExtendedOutput, $iCode, $sMessage);
|
||||
$this->current_object[$sObjectAlias] = $oObjRes;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @package RESTAPI
|
||||
* @api
|
||||
@@ -500,15 +539,22 @@ class CoreServices implements iRestServiceProvider, iRestInputSanitizer
|
||||
break;
|
||||
|
||||
case 'core/get':
|
||||
$sClass = RestUtils::GetClass($aParams, 'class');
|
||||
$sClassParam = RestUtils::GetMandatoryParam($aParams, 'class');
|
||||
$key = RestUtils::GetMandatoryParam($aParams, 'key');
|
||||
$aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
|
||||
$bExtendedOutput = (RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+');
|
||||
$sShowFields = RestUtils::GetOptionalParam($aParams, 'output_fields', '*');
|
||||
$iLimit = (int)RestUtils::GetOptionalParam($aParams, 'limit', 0);
|
||||
$iPage = (int)RestUtils::GetOptionalParam($aParams, 'page', 1);
|
||||
|
||||
$oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key, $iLimit, self::getOffsetFromLimitAndPage($iLimit, $iPage));
|
||||
$sTargetClass = $oObjectSet->GetFilter()->GetClass();
|
||||
// Validate the class(es)
|
||||
$aClass = explode(',', $sClassParam);
|
||||
foreach ($aClass as $sClass) {
|
||||
if (!MetaModel::IsValidClass(trim($sClass))) {
|
||||
throw new Exception("class '$sClass' is not valid");
|
||||
}
|
||||
}
|
||||
|
||||
$oObjectSet = RestUtils::GetObjectSetFromKey($sClassParam, $key, $iLimit, self::getOffsetFromLimitAndPage($iLimit, $iPage));
|
||||
$sTargetClass = $oObjectSet->GetFilter()->GetClass();
|
||||
|
||||
if (UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ) != UR_ALLOWED_YES) {
|
||||
$oResult->code = RestResult::UNAUTHORIZED;
|
||||
@@ -519,19 +565,67 @@ class CoreServices implements iRestServiceProvider, iRestInputSanitizer
|
||||
} elseif ($iPage < 1) {
|
||||
$oResult->code = RestResult::INVALID_PAGE;
|
||||
$oResult->message = "The request page number is not valid. It must be an integer greater than 0";
|
||||
} else {
|
||||
if (!$bExtendedOutput && RestUtils::GetOptionalParam($aParams, 'output_fields', '*') != '*') {
|
||||
$aFields = $aShowFields[$sClass];
|
||||
//Id is not a valid attribute to optimize
|
||||
if (in_array('id', $aFields)) {
|
||||
unset($aFields[array_search('id', $aFields)]);
|
||||
}
|
||||
$aAttToLoad = [$oObjectSet->GetClassAlias() => $aFields];
|
||||
$oObjectSet->OptimizeColumnLoad($aAttToLoad);
|
||||
} elseif (count($oObjectSet->GetSelectedClasses()) > 1) {
|
||||
$oResult = new RestResultWithObjectSets();
|
||||
$aCache = [];
|
||||
$aShowFields = [];
|
||||
foreach ($oObjectSet->GetSelectedClasses() as $sSelectedClass) {
|
||||
$aShowFields = array_merge( $aShowFields, RestUtils::GetFieldList($sSelectedClass, $aParams, 'output_fields', false));
|
||||
}
|
||||
|
||||
while ($oObjects = $oObjectSet->FetchAssoc()) {
|
||||
$oResult->MakeNewObjectSet();
|
||||
|
||||
foreach ($oObjects as $sAlias => $oObject) {
|
||||
if (!$oObject) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!array_key_exists($sAlias, $aCache)) {
|
||||
$sClass = get_class($oObject);
|
||||
$bExtendedOutput = RestUtils::HasRequestedExtendedOutput($sShowFields);
|
||||
|
||||
if (!RestUtils::HasRequestedAllOutputFields($sShowFields)) {
|
||||
$aFields = $aShowFields[$sClass];
|
||||
//Id is not a valid attribute to optimize
|
||||
if ($aFields && in_array('id', $aFields)) {
|
||||
unset($aFields[array_search('id', $aFields)]);
|
||||
}
|
||||
$aAttToLoad = [$sAlias => $aFields];
|
||||
$oObjectSet->OptimizeColumnLoad($aAttToLoad);
|
||||
}
|
||||
$aCache[$sAlias] = [
|
||||
'aShowFields' => $aShowFields,
|
||||
'bExtendedOutput' => $bExtendedOutput,
|
||||
];
|
||||
} else {
|
||||
$aShowFields = $aCache[$sAlias]['aShowFields'];
|
||||
$bExtendedOutput = $aCache[$sAlias]['bExtendedOutput'];
|
||||
}
|
||||
|
||||
$oResult->AppendSubObject($sAlias, 0, '', $oObject, $aShowFields, $bExtendedOutput);
|
||||
}
|
||||
}
|
||||
$oResult->message = "Found: ".$oObjectSet->Count();
|
||||
} else {
|
||||
$aShowFields =[];
|
||||
foreach ($aClass as $sSelectedClass) {
|
||||
$sSelectedClass = trim($sSelectedClass);
|
||||
$aShowFields = array_merge($aShowFields, RestUtils::GetFieldList($sSelectedClass, $aParams, 'output_fields', false));
|
||||
}
|
||||
|
||||
if (!RestUtils::HasRequestedAllOutputFields($sShowFields) && count($aShowFields) == 1) {
|
||||
$aFields = $aShowFields[$sClass];
|
||||
//Id is not a valid attribute to optimize
|
||||
if (in_array('id', $aFields)) {
|
||||
unset($aFields[array_search('id', $aFields)]);
|
||||
}
|
||||
$aAttToLoad = [$oObjectSet->GetClassAlias() => $aFields];
|
||||
$oObjectSet->OptimizeColumnLoad($aAttToLoad);
|
||||
}
|
||||
|
||||
while ($oObject = $oObjectSet->Fetch()) {
|
||||
$oResult->AddObject(0, '', $oObject, $aShowFields, $bExtendedOutput);
|
||||
$oResult->AddObject(0, '', $oObject, $aShowFields, RestUtils::HasRequestedExtendedOutput($sShowFields));
|
||||
}
|
||||
$oResult->message = "Found: ".$oObjectSet->Count();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ abstract class Trigger extends cmdbAbstractObject
|
||||
"category" => "grant_by_profile,core/cmdb",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger",
|
||||
@@ -174,7 +174,7 @@ abstract class TriggerOnObject extends Trigger
|
||||
"category" => "grant_by_profile,core/cmdb",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobject",
|
||||
@@ -401,7 +401,7 @@ class TriggerOnPortalUpdate extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onportalupdate",
|
||||
@@ -434,7 +434,7 @@ abstract class TriggerOnStateChange extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onstatechange",
|
||||
@@ -469,7 +469,7 @@ class TriggerOnStateEnter extends TriggerOnStateChange
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onstateenter",
|
||||
@@ -503,7 +503,7 @@ class TriggerOnStateLeave extends TriggerOnStateChange
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onstateleave",
|
||||
@@ -537,7 +537,7 @@ class TriggerOnObjectCreate extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobjcreate",
|
||||
@@ -572,7 +572,7 @@ class TriggerOnObjectDelete extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobjdelete",
|
||||
@@ -607,7 +607,7 @@ class TriggerOnObjectUpdate extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobjupdate",
|
||||
@@ -695,7 +695,7 @@ class TriggerOnObjectMention extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobjmention",
|
||||
@@ -773,7 +773,7 @@ class TriggerOnAttributeBlobDownload extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onattblobdownload",
|
||||
@@ -852,7 +852,7 @@ class TriggerOnThresholdReached extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_threshold",
|
||||
|
||||
@@ -404,7 +404,8 @@ class ValueSetObjects extends ValueSetDefinition
|
||||
if (count($aAdditionalField) > 0) {
|
||||
$aArguments = [];
|
||||
foreach ($aAdditionalField as $sAdditionalField) {
|
||||
array_push($aArguments, $oObject->Get($sAdditionalField));
|
||||
//getAsCSV to have user friendly value in text format
|
||||
array_push($aArguments, $oObject->GetAsCSV($sAdditionalField,' ',''));
|
||||
}
|
||||
$aData['additional_field'] = utils::VSprintf($sFormatAdditionalField, $aArguments);
|
||||
} else {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -24,7 +24,7 @@ class TriggerOnAttachmentCreate extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onattcreate",
|
||||
|
||||
@@ -24,7 +24,7 @@ class TriggerOnAttachmentDelete extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onattdelete",
|
||||
|
||||
@@ -19,7 +19,7 @@ class TriggerOnAttachmentDownload extends TriggerOnAttributeBlobDownload
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onattdownload",
|
||||
|
||||
@@ -14,13 +14,11 @@ use Combodo\iTop\CoreUpdate\Service\CoreUpdater;
|
||||
use Combodo\iTop\DBTools\Service\DBToolsUtils;
|
||||
use Combodo\iTop\FilesInformation\Service\FileNotExistException;
|
||||
use Combodo\iTop\FilesInformation\Service\FilesInformation;
|
||||
use Config;
|
||||
use ContextTag;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
use RunTimeEnvironment;
|
||||
use SecurityException;
|
||||
use SetupUtils;
|
||||
use utils;
|
||||
@@ -232,29 +230,6 @@ class AjaxController extends Controller
|
||||
$this->DisplayJSONPage($aParams, $iResponseCode);
|
||||
}
|
||||
|
||||
public function OperationRebuildToolkitEnvironment()
|
||||
{
|
||||
$sTransactionId = utils::GetNewTransactionId();
|
||||
$aParams = [];
|
||||
$aParams['sTransactionId'] = $sTransactionId;
|
||||
$aParams['bStatus'] = true;
|
||||
|
||||
$iResponseCode = 200;
|
||||
try {
|
||||
$aParams['sAjaxURL'] = utils::GetAbsoluteUrlAppRoot().'/pages/UI.php';
|
||||
$oConfig = new Config(APPCONF.ITOP_DEFAULT_ENV.'/'.ITOP_CONFIG_FILE);
|
||||
$oEnvironment = new RunTimeEnvironment(ITOP_DEFAULT_ENV);
|
||||
$oEnvironment->WriteConfigFileSafe($oConfig);
|
||||
$oEnvironment->CompileFrom(ITOP_DEFAULT_ENV);
|
||||
} catch (Exception $e) {
|
||||
IssueLog::Error('RebuildToolkitEnvironment: '.$e->getMessage());
|
||||
$aParams['sError'] = $e->getMessage();
|
||||
$iResponseCode = 500;
|
||||
$aParams['bStatus'] = false;
|
||||
}
|
||||
$this->DisplayJSONPage($aParams, $iResponseCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \SecurityException if CSRF token invalid
|
||||
*
|
||||
|
||||
@@ -90,13 +90,6 @@
|
||||
{% UIForm Standard {'sId':'launch-setup-form', Action:sLaunchSetupUrl} %}
|
||||
{% UIButton ForDestructiveAction {'sLabel':'iTopUpdate:UI:SetupLaunch'|dict_s, 'sName':'launch-setup', 'sValue':'launch-setup', 'bIsSubmit':true, 'sId':'launch-setup'} %}
|
||||
{% EndUIForm %}
|
||||
{% UIAlert ForInformation {sId:'fast-setup-alert', AddCSSClass:'ibo-is-hidden'} %}
|
||||
{% UIContentBlock Standard {sId:'fast-setup-content', aContainerClasses:['ibo-fast-setup-content']} %}
|
||||
{{ 'iTopUpdate:UI:SetupMessage:Compile'|dict_s }}
|
||||
{% EndUIContentBlock %}
|
||||
{% EndUIAlert %}
|
||||
{% UIButton ForDestructiveAction {sLabel:'iTopUpdate:UI:FastSetupLaunch'|dict_s, sName:'launch-fast-setup', sValue:'launch-fast-setup', sId:'launch-fast-setup'} %}
|
||||
{% UISpinner Standard {sId:'fast-setup-wait', IsHidden:true} %}
|
||||
{% EndUIFieldSet %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -116,51 +116,4 @@ $("#launch-setup-form").on("submit", function () {
|
||||
return window.confirm("{{ 'iTopUpdate:UI:SetupLaunchConfirm'|dict_s }}");
|
||||
});
|
||||
|
||||
$("#launch-fast-setup").on("click", function(e) {
|
||||
var oMessage = $("#fast-setup-alert");
|
||||
var oContent = $("#fast-setup-content");
|
||||
oMessage.removeClass("ibo-is-hidden");
|
||||
oMessage.removeClass("ibo-is-failure");
|
||||
oMessage.removeClass("ibo-is-success");
|
||||
oMessage.addClass("ibo-is-information");
|
||||
oContent.html("{{ 'iTopUpdate:UI:SetupMessage:Compile'|dict_s }}");
|
||||
|
||||
let fast_setup_wait = $("#fast-setup-wait");
|
||||
fast_setup_wait.removeClass("ibo-is-hidden");
|
||||
$(this).prop("disabled", true);
|
||||
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ sAjaxURL|raw }}",
|
||||
data: {
|
||||
route: "core_update_ajax.rebuild_toolkit_environment"
|
||||
},
|
||||
dataType: "json",
|
||||
complete: function(jqXHR, textStatus) {
|
||||
$("#fast-setup-wait").addClass("ibo-is-hidden");
|
||||
$("#launch-fast-setup").prop("disabled", false);
|
||||
fast_setup_wait.addClass("ibo-is-hidden");
|
||||
},
|
||||
success: function (data) {
|
||||
oMessage.removeClass("ibo-is-information");
|
||||
|
||||
if (data.bStatus) {
|
||||
oMessage.removeClass("ibo-is-failure");
|
||||
oMessage.addClass("ibo-is-success");
|
||||
oContent.html("{{ 'iTopUpdate:UI:SetupMessage:UpdateDone'|dict_s }}");
|
||||
} else {
|
||||
oMessage.removeClass("ibo-is-success");
|
||||
oMessage.addClass("ibo-is-failure");
|
||||
oContent.html(data.sError);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
oMessage.removeClass("ibo-is-information");
|
||||
oMessage.removeClass("ibo-is-success");
|
||||
oMessage.addClass("ibo-is-failure");
|
||||
oContent.html(textStatus + ' ' + errorThrown);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -612,7 +612,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'Class:Trigger' => 'Triger',
|
||||
'Class:Trigger+' => '',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Popis',
|
||||
'Class:Trigger/Attribute:description+' => 'Krátký popis',
|
||||
'Class:Trigger/Attribute:action_list' => 'Spouštěné akce',
|
||||
|
||||
@@ -611,7 +611,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'Class:Trigger' => 'Triggere',
|
||||
'Class:Trigger+' => '',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Beskrivelse',
|
||||
'Class:Trigger/Attribute:description+' => '',
|
||||
'Class:Trigger/Attribute:action_list' => 'Triggerede handlinger',
|
||||
|
||||
@@ -608,7 +608,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'Class:Trigger' => 'Trigger',
|
||||
'Class:Trigger+' => 'Custom event handler',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Beschreibung',
|
||||
'Class:Trigger/Attribute:description+' => 'Kurzbeschreibung',
|
||||
'Class:Trigger/Attribute:action_list' => 'Verbundene Trigger-Aktionen',
|
||||
|
||||
@@ -705,7 +705,7 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
'Class:Trigger' => 'Trigger',
|
||||
'Class:Trigger+' => 'Custom event handler',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s',
|
||||
'Class:Trigger/Attribute:description' => 'Description',
|
||||
'Class:Trigger/Attribute:description+' => 'Be precise as your users will base their potential unsubscription on this information',
|
||||
'Class:Trigger/Attribute:action_list' => 'Triggered actions',
|
||||
|
||||
@@ -688,7 +688,7 @@ Dict::Add('EN GB', 'British English', 'British English', [
|
||||
Dict::Add('EN GB', 'British English', 'British English', [
|
||||
'Class:Trigger' => 'Trigger',
|
||||
'Class:Trigger+' => 'Custom event handler',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Description',
|
||||
'Class:Trigger/Attribute:description+' => 'Be precise as your users will base their potential unsubscribing on this information',
|
||||
'Class:Trigger/Attribute:action_list' => 'Triggered actions',
|
||||
|
||||
@@ -599,7 +599,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
'Class:Trigger' => 'Disparador',
|
||||
'Class:Trigger+' => 'Disparador',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Descripción',
|
||||
'Class:Trigger/Attribute:description+' => 'Descripción',
|
||||
'Class:Trigger/Attribute:action_list' => 'Acciones',
|
||||
|
||||
@@ -650,7 +650,7 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:Trigger' => 'Déclencheur',
|
||||
'Class:Trigger+' => '',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, classe cible : %2$s',
|
||||
'Class:Trigger/Attribute:description' => 'Description',
|
||||
'Class:Trigger/Attribute:description+' => 'Soyez explicite, afin que vos utilisateurs comprennent à quelles notifications précisement ils se désabonnent',
|
||||
'Class:Trigger/Attribute:action_list' => 'Actions déclenchées',
|
||||
|
||||
@@ -606,7 +606,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
'Class:Trigger' => 'Eseményindító',
|
||||
'Class:Trigger+' => 'Egyéni eseménykezelés',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Leírás',
|
||||
'Class:Trigger/Attribute:description+' => 'Egysoros leírás',
|
||||
'Class:Trigger/Attribute:action_list' => 'Elindított műveletek',
|
||||
|
||||
@@ -606,7 +606,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'Class:Trigger' => 'Trigger',
|
||||
'Class:Trigger+' => 'Gestore di eventi personalizzati',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Descrizione',
|
||||
'Class:Trigger/Attribute:description+' => 'Una linea di descrizione',
|
||||
'Class:Trigger/Attribute:action_list' => 'Azioni triggerate',
|
||||
|
||||
@@ -610,7 +610,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'Class:Trigger' => 'トリガー',
|
||||
'Class:Trigger+' => 'カスタムイベントハンドラー',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => '説明',
|
||||
'Class:Trigger/Attribute:description+' => '1行の説明',
|
||||
'Class:Trigger/Attribute:action_list' => 'トリガーされたアクション',
|
||||
|
||||
@@ -608,7 +608,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
'Class:Trigger' => 'Trigger',
|
||||
'Class:Trigger+' => 'Aanleiding tot het uitvoeren van een actie',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Beschrijving',
|
||||
'Class:Trigger/Attribute:description+' => 'Beschrijving in één regel',
|
||||
'Class:Trigger/Attribute:action_list' => 'Getriggerde acties',
|
||||
|
||||
@@ -608,7 +608,7 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
'Class:Trigger' => 'Wyzwalacz',
|
||||
'Class:Trigger+' => 'Niestandardowa obsługa zdarzeń',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Opis',
|
||||
'Class:Trigger/Attribute:description+' => 'jedna linia opisu',
|
||||
'Class:Trigger/Attribute:action_list' => 'Działania wyzwalacza',
|
||||
|
||||
@@ -606,7 +606,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
'Class:Trigger' => 'Gatilho',
|
||||
'Class:Trigger+' => 'Manipulador de eventos personalizado',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Descrição',
|
||||
'Class:Trigger/Attribute:description+' => 'Uma descrição curta',
|
||||
'Class:Trigger/Attribute:action_list' => 'Ações desencadeadas',
|
||||
|
||||
@@ -611,7 +611,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
'Class:Trigger' => 'Триггер',
|
||||
'Class:Trigger+' => 'Пользовательский обработчик событий',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Описание',
|
||||
'Class:Trigger/Attribute:description+' => 'Описание триггера',
|
||||
'Class:Trigger/Attribute:action_list' => 'Действия триггера',
|
||||
|
||||
@@ -624,7 +624,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'Class:Trigger' => 'Spúštač',
|
||||
'Class:Trigger+' => 'Custom event handler~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Popis',
|
||||
'Class:Trigger/Attribute:description+' => 'Be precise as your users will base their potential unsubscription on this information~~',
|
||||
'Class:Trigger/Attribute:action_list' => 'Spúšťané akcie',
|
||||
|
||||
@@ -611,7 +611,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'Class:Trigger' => 'Tetikleyici',
|
||||
'Class:Trigger+' => 'Özel olay yürütücü',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s~~',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => 'Tanımlama',
|
||||
'Class:Trigger/Attribute:description+' => 'tek satır tanımlama',
|
||||
'Class:Trigger/Attribute:action_list' => 'Tetiklenen işlemler',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -10,11 +10,17 @@
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installé',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'Cette extension fait partie de l\'installation actuelle.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'va être installé',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'Cette extension sera installée lors de l\'installation.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'pas installé',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'Cette extension ne fait pas partie de l\'installation actuelle.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'va être désinstallé',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'Cette extension sera désinstallée lors de l\'installation.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'non désinstallable',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Une fois cette extension installée, elle ne devrait pas être désinstallée.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'supprimé du disque',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'Le dossier local de l\'extension a été supprimé du disque. Cela forcera la désinstallation de cette extension.',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'À propos de %1$s',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'Plus d\'informations',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Forcer la désinstallation',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*/
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'This extension is part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'This extension will be uninstalled during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'cannot be uninstalled~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Once this extension has been installed, it should not be uninstalled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'missing from disk~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'The local extension folder has been removed from the disk. This will force the uninstallation of this extension.~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
|
||||
|
||||
@@ -705,7 +705,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:Trigger' => '触发器',
|
||||
'Class:Trigger+' => '自定义事件处理',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
|
||||
'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s~~',
|
||||
'Class:Trigger/Attribute:description' => '描述',
|
||||
'Class:Trigger/Attribute:description+' => '简短描述',
|
||||
'Class:Trigger/Attribute:action_list' => '触发的操作',
|
||||
|
||||
@@ -124,6 +124,7 @@ require_once('./xmldataloader.class.inc.php');
|
||||
// Never cache this page
|
||||
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
|
||||
header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); // Date in the past
|
||||
$oCtx = new ContextTag(ContextTag::TAG_SETUP);
|
||||
|
||||
/**
|
||||
* Main program
|
||||
|
||||
@@ -3,21 +3,6 @@
|
||||
require_once(dirname(__FILE__, 3).'/approot.inc.php');
|
||||
require_once(__DIR__.'/InstallationFileService.php');
|
||||
|
||||
function fatalHandler()
|
||||
{
|
||||
$error = error_get_last();
|
||||
if ($error) {
|
||||
if ($error['type'] === E_ERROR) {
|
||||
// fatal error has occured
|
||||
echo "PHP Fatal captured: {$error["message"]}";
|
||||
SetupLog::Error("Fatal error during setup", null, $error);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register_shutdown_function("fatalHandler");
|
||||
|
||||
function PrintUsageAndExit()
|
||||
{
|
||||
echo <<<EOF
|
||||
|
||||
@@ -61,6 +61,7 @@ if (!function_exists('json_decode')) {
|
||||
//N°3671 setup context: force $bForceTrustProxy to be persisted in next calls
|
||||
utils::GetAbsoluteUrlAppRoot(true);
|
||||
$oWizard = new WizardController('WizStepWelcome');
|
||||
$oCtx = new ContextTag(ContextTag::TAG_SETUP);
|
||||
//N°3952
|
||||
if (SetupUtils::IsSessionSetupTokenValid()) {
|
||||
// Normal operation
|
||||
|
||||
@@ -196,6 +196,8 @@ class WizardController
|
||||
SetupLog::Info("=== Setup screen: ".$oStep->GetTitle().' ('.get_class($oStep).')');
|
||||
$oPage = new SetupPage($oStep->GetTitle());
|
||||
$oPage->LinkScriptFromAppRoot('setup/setup.js');
|
||||
$oStep->PreFormDisplay($oPage);
|
||||
|
||||
$oPage->add('<form id="wiz_form" class="ibo-setup--wizard" method="post">');
|
||||
$oPage->add('<div class="ibo-setup--wizard--content">');
|
||||
$oStep->Display($oPage);
|
||||
@@ -263,8 +265,8 @@ EOF
|
||||
$oPage->output();
|
||||
}
|
||||
/**
|
||||
* Make the wizard run: Start, Next or Back depending WizardUpdateButtons();
|
||||
on the page's parameters
|
||||
* Make the wizard run: 'Start', 'Next' or 'Back' depending WizardUpdateButtons();
|
||||
* on the page's parameters
|
||||
*/
|
||||
public function Run()
|
||||
{
|
||||
|
||||
@@ -52,6 +52,17 @@ class WizStepLandingBeforeAudit extends WizStepModulesChoice
|
||||
*/
|
||||
public function UpdateWizardStateAndGetNextStep($bMoveForward = true): WizardState
|
||||
{
|
||||
if ($this->oWizard->GetParameter('skip_wizard', false)) {
|
||||
$oRuntimeEnv = new RunTimeEnvironment();
|
||||
$sBuildConfigFile = APPCONF.$oRuntimeEnv->GetBuildEnv().'/'.ITOP_CONFIG_FILE;
|
||||
$oConfig = new Config($sBuildConfigFile);
|
||||
$oExtensionMap = iTopExtensionsMap::GetExtensionsMap($oRuntimeEnv->GetBuildEnv());
|
||||
$aExtensionsFromDatabase = $oExtensionMap->GetChoicesFromDatabase($oConfig);
|
||||
$this->oWizard->SetParameter('selected_extensions', json_encode($aExtensionsFromDatabase));
|
||||
$adModulesFromDatabase = ModuleInstallationRepository::GetInstance()->ReadComputeInstalledModules($oConfig);
|
||||
$this->oWizard->SetParameter('selected_modules', json_encode(array_keys($adModulesFromDatabase)));
|
||||
}
|
||||
|
||||
$aWizardSteps = $this->GetWizardSteps();
|
||||
$this->oWizard->SetWizardSteps($aWizardSteps);
|
||||
$this->sCurrentState = count($aWizardSteps) - 1;
|
||||
|
||||
@@ -869,18 +869,18 @@ EOF
|
||||
|
||||
$sTooltip = '';
|
||||
if ($aFlags['missing']) {
|
||||
$sTooltip .= '<div class="ibo-badge ibo-block ibo-is-red" title="The local extension folder has been removed from the disk. This will force the uninstallation of this extension." >source removed</div>';
|
||||
$sTooltip .= '<div id="badge--'.$sId.'--missing-from-disk" class="ibo-badge ibo-block ibo-is-red" title="The local extension folder has been removed from the disk. This will force the uninstallation of this extension." >source removed</div>';
|
||||
}
|
||||
if ($aFlags['installed']) {
|
||||
$sTooltip .= '<div class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div>';
|
||||
$sTooltip .= '<div id="badge--'.$sId.'--installed" class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div>';
|
||||
|
||||
$sTooltip .= '<div class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div>';
|
||||
$sTooltip .= '<div id="badge--'.$sId.'--to-be-uninstalled" class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div>';
|
||||
} else {
|
||||
$sTooltip .= '<div class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div>';
|
||||
$sTooltip .= '<div class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>';
|
||||
$sTooltip .= '<div id="badge--'.$sId.'--to-be-installed" class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div>';
|
||||
$sTooltip .= '<div id="badge--'.$sId.'--not-installed" class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>';
|
||||
}
|
||||
if (!$aFlags['uninstallable']) {
|
||||
$sTooltip .= '<div class="ibo-badge ibo-block ibo-is-orange" title="Once this extension has been installed, it should not be uninstalled." >cannot be uninstalled</div>';
|
||||
$sTooltip .= '<div id="badge--'.$sId.'--not-uninstallable" class="ibo-badge ibo-block ibo-is-orange" title="Once this extension has been installed, it should not be uninstalled." >cannot be uninstalled</div>';
|
||||
}
|
||||
|
||||
$sMetadata = '';
|
||||
|
||||
@@ -24,6 +24,15 @@
|
||||
class WizStepWelcome extends WizardStep
|
||||
{
|
||||
protected $bCanMoveForward;
|
||||
private array $aInfo;
|
||||
private array $aWarnings;
|
||||
private array $aErrors;
|
||||
|
||||
public function __construct(WizardController $oWizard, $sCurrentState)
|
||||
{
|
||||
parent::__construct($oWizard, $sCurrentState);
|
||||
$this->CheckInstallation();
|
||||
}
|
||||
|
||||
public function GetTitle()
|
||||
{
|
||||
@@ -66,39 +75,14 @@ class WizStepWelcome extends WizardStep
|
||||
EOF
|
||||
);
|
||||
$oPage->add('<h1>'.ITOP_APPLICATION.' Installation Wizard</h1>');
|
||||
$aResults = SetupUtils::CheckPhpAndExtensions();
|
||||
$this->bCanMoveForward = true;
|
||||
$aInfo = [];
|
||||
$aWarnings = [];
|
||||
$aErrors = [];
|
||||
foreach ($aResults as $oCheckResult) {
|
||||
switch ($oCheckResult->iSeverity) {
|
||||
case CheckResult::ERROR:
|
||||
$aErrors[] = $oCheckResult->sLabel;
|
||||
$this->bCanMoveForward = false;
|
||||
break;
|
||||
|
||||
case CheckResult::WARNING:
|
||||
$aWarnings[] = $oCheckResult->sLabel;
|
||||
break;
|
||||
|
||||
case CheckResult::INFO:
|
||||
$aInfo[] = $oCheckResult->sLabel;
|
||||
break;
|
||||
|
||||
case CheckResult::TRACE:
|
||||
SetupLog::Ok($oCheckResult->sLabel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$sStyle = 'style="display:none;overflow:auto;"';
|
||||
$sToggleButtons = '<button type="button" id="show_details" class="ibo-button ibo-is-alternative ibo-is-neutral" onclick="$(\'#details\').toggle(); $(this).toggle(); $(\'#hide_details\').toggle();"><span class="ibo-button--icon fa fa-caret-down"></span><span class="ibo-button--label">Show details</span></button><button type="button" id="hide_details" class="ibo-button ibo-is-alternative ibo-is-neutral" style="display:none;" onclick="$(\'#details\').toggle(); $(this).toggle(); $(\'#show_details\').toggle();"><span class="ibo-button--icon fa fa-caret-up"></span><span class="ibo-button--label">Hide details</span></button>';
|
||||
if (count($aErrors) > 0) {
|
||||
if (count($this->aErrors) > 0) {
|
||||
$sStyle = 'style="overflow:auto;"';
|
||||
$sTitle = count($aErrors).' Error(s), '.count($aWarnings).' Warning(s).';
|
||||
$sTitle = count($this->aErrors).' Error(s), '.count($this->aWarnings).' Warning(s).';
|
||||
$sH2Class = 'text-error';
|
||||
} elseif (count($aWarnings) > 0) {
|
||||
$sTitle = count($aWarnings).' Warning(s) '.$sToggleButtons;
|
||||
} elseif (count($this->aWarnings) > 0) {
|
||||
$sTitle = count($this->aWarnings).' Warning(s) '.$sToggleButtons;
|
||||
$sH2Class = 'text-warning';
|
||||
} else {
|
||||
$sTitle = 'Ok. '.$sToggleButtons;
|
||||
@@ -110,13 +94,13 @@ EOF
|
||||
<div id="details" $sStyle>
|
||||
HTML
|
||||
);
|
||||
foreach ($aErrors as $sText) {
|
||||
foreach ($this->aErrors as $sText) {
|
||||
$oPage->error($sText);
|
||||
}
|
||||
foreach ($aWarnings as $sText) {
|
||||
foreach ($this->aWarnings as $sText) {
|
||||
$oPage->warning($sText);
|
||||
}
|
||||
foreach ($aInfo as $sText) {
|
||||
foreach ($this->aInfo as $sText) {
|
||||
$oPage->ok($sText);
|
||||
}
|
||||
$oPage->add('</div>');
|
||||
@@ -127,8 +111,68 @@ HTML
|
||||
$oPage->add_ready_script('CheckDirectoryConfFilesPermissions("'.utils::GetItopVersionWikiSyntax().'")');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add post display stuff to the setup screen
|
||||
* @param \SetupPage $oPage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function PostFormDisplay(SetupPage $oPage)
|
||||
{
|
||||
if ($this->bCanMoveForward) {
|
||||
$sBuildConfigFile = APPCONF.ITOP_DEFAULT_ENV.'/'.ITOP_CONFIG_FILE;
|
||||
if (file_exists($sBuildConfigFile)) {
|
||||
$oPage->add(
|
||||
<<<HTML
|
||||
<form method="post">
|
||||
<input type="hidden" name="_class" value="WizStepLandingBeforeAudit"/>
|
||||
<input type="hidden" name="operation" value="next"/>
|
||||
<input type="hidden" name="_params[skip_wizard]" value="1"/>
|
||||
<table style="width:100%;" class="ibo-setup--wizard--buttons-container">
|
||||
<tr>
|
||||
<td style="text-align: right"><button type="submit" class="ibo-button ibo-is-regular ibo-is-secondary">Keep current choices</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
HTML
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function CanMoveForward()
|
||||
{
|
||||
return $this->bCanMoveForward;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function CheckInstallation(): void
|
||||
{
|
||||
$aResults = SetupUtils::CheckPhpAndExtensions();
|
||||
$this->bCanMoveForward = true;
|
||||
$this->aInfo = [];
|
||||
$this->aWarnings = [];
|
||||
$this->aErrors = [];
|
||||
foreach ($aResults as $oCheckResult) {
|
||||
switch ($oCheckResult->iSeverity) {
|
||||
case CheckResult::ERROR:
|
||||
$this->aErrors[] = $oCheckResult->sLabel;
|
||||
$this->bCanMoveForward = false;
|
||||
break;
|
||||
|
||||
case CheckResult::WARNING:
|
||||
$this->aWarnings[] = $oCheckResult->sLabel;
|
||||
break;
|
||||
|
||||
case CheckResult::INFO:
|
||||
$this->aInfo[] = $oCheckResult->sLabel;
|
||||
break;
|
||||
|
||||
case CheckResult::TRACE:
|
||||
SetupLog::Ok($oCheckResult->sLabel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,10 @@ abstract class WizardStep
|
||||
{
|
||||
}
|
||||
|
||||
public function PreFormDisplay(SetupPage $oPage)
|
||||
{
|
||||
}
|
||||
|
||||
protected function CheckDependencies()
|
||||
{
|
||||
if (is_null($this->bDependencyCheck)) {
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
namespace Combodo\iTop\Application\TwigBase\Controller;
|
||||
|
||||
require_once APPROOT.'setup/setuppage.class.inc.php';
|
||||
|
||||
use ApplicationMenu;
|
||||
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
|
||||
use Combodo\iTop\Application\WebPage\AjaxPage;
|
||||
|
||||
@@ -13,6 +13,13 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
/** @inheritDoc */
|
||||
public const UI_BLOCK_CLASS_NAME = ExtensionDetails::class;
|
||||
|
||||
private const BADGE_ID_INSTALLED = 'installed';
|
||||
private const BADGE_ID_NOT_INSTALLED = 'not-installed';
|
||||
private const BADGE_ID_TO_BE_INSTALLED = 'to-be-installed';
|
||||
private const BADGE_ID_TO_BE_UNINSTALLED = 'to-be-uninstalled';
|
||||
private const BADGE_ID_NOT_UNINSTALLABLE = 'not-uninstallable';
|
||||
private const BADGE_ID_MISSING_FROM_DISK = 'missing-from-disk';
|
||||
|
||||
public static function MakeInstalled(string $sCode, string $sLabel, string $sDescription = '', array $aMetaData = [], array $aExtraFlags = [], string $sAbout = '')
|
||||
{
|
||||
$aBadges = [];
|
||||
@@ -21,11 +28,19 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
$bSelected = $aExtraFlags['selected'] ?? true;
|
||||
$bDisabled = $aExtraFlags['disabled'] ?? false;
|
||||
$bRemote = $aExtraFlags['remote'] ?? false;
|
||||
self::AddExtraBadges($aBadges, $bUninstallable, $bMissingFromDisk);
|
||||
$oBadgeInstalled = BadgeUIBlockFactory::MakeGreen(Dict::S('UI:Layout:ExtensionsDetails:BadgeInstalled'));
|
||||
self::AddExtraBadges($aBadges, $bUninstallable, $bMissingFromDisk, $sCode);
|
||||
$oBadgeInstalled = BadgeUIBlockFactory::MakeGreen(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeInstalled'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeInstalled+'),
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_INSTALLED)
|
||||
);
|
||||
$oBadgeInstalled->AddCSSClass('checked');
|
||||
$aBadges[] = $oBadgeInstalled;
|
||||
$oBadgeToBeUninstalled = BadgeUIBlockFactory::MakeRed(Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeUninstalled'));
|
||||
$oBadgeToBeUninstalled = BadgeUIBlockFactory::MakeRed(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeUninstalled'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+'),
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_TO_BE_UNINSTALLED)
|
||||
);
|
||||
$oBadgeToBeUninstalled->AddCSSClass('unchecked');
|
||||
$aBadges[] = $oBadgeToBeUninstalled;
|
||||
|
||||
@@ -56,11 +71,19 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
$bUninstallable = $aExtraFlags['uninstallable'] ?? true;
|
||||
$bSelected = $aExtraFlags['selected'] ?? false;
|
||||
$bDisabled = $aExtraFlags['disabled'] ?? false;
|
||||
self::AddExtraBadges($aBadges, $bUninstallable, false);
|
||||
$oBadgeInstalled = BadgeUIBlockFactory::MakeGrey(Dict::S('UI:Layout:ExtensionsDetails:BadgeNotInstalled'));
|
||||
self::AddExtraBadges($aBadges, $bUninstallable, false, $sCode);
|
||||
$oBadgeInstalled = BadgeUIBlockFactory::MakeGrey(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeNotInstalled'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeNotInstalled+'),
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_NOT_INSTALLED)
|
||||
);
|
||||
$oBadgeInstalled->AddCSSClass('unchecked');
|
||||
$aBadges[] = $oBadgeInstalled;
|
||||
$oBadgeToBeUninstalled = BadgeUIBlockFactory::MakeCyan(Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeInstalled'));
|
||||
$oBadgeToBeUninstalled = BadgeUIBlockFactory::MakeCyan(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeInstalled'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeInstalled+'),
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_TO_BE_INSTALLED)
|
||||
);
|
||||
$oBadgeToBeUninstalled->AddCSSClass('checked');
|
||||
$aBadges[] = $oBadgeToBeUninstalled;
|
||||
$oExtensionDetails = new ExtensionDetails($sCode, $sLabel, $sDescription, $aMetaData, $aBadges, $sAbout);
|
||||
@@ -76,13 +99,35 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
return $oExtensionDetails;
|
||||
}
|
||||
|
||||
private static function AddExtraBadges(array &$aBadges, bool $bUninstallable, bool $bMissingFromDisk)
|
||||
private static function AddExtraBadges(array &$aBadges, bool $bUninstallable, bool $bMissingFromDisk, string $sCode)
|
||||
{
|
||||
if (!$bUninstallable) {
|
||||
$aBadges[] = BadgeUIBlockFactory::MakeOrange(Dict::S('UI:Layout:ExtensionsDetails:BadgeNotUninstallable'));
|
||||
$aBadges[] = BadgeUIBlockFactory::MakeOrange(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeNotUninstallable'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeNotUninstallable+'),
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_NOT_UNINSTALLABLE)
|
||||
);
|
||||
}
|
||||
if ($bMissingFromDisk) {
|
||||
$aBadges[] = BadgeUIBlockFactory::MakeRed(Dict::S('UI:Layout:ExtensionsDetails:BadgeMissingFromDisk'));
|
||||
$aBadges[] = BadgeUIBlockFactory::MakeRed(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeMissingFromDisk'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+'),
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_MISSING_FROM_DISK)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a badge ID for an extension
|
||||
*
|
||||
* @param string $sExtensionCode The extension code
|
||||
* @param string $sBadgeType The badge type (one of the BADGE_ID_* constants)
|
||||
*
|
||||
* @return string The badge ID in the format: badge--{extensionCode}--{badgeType}
|
||||
*/
|
||||
public static function GetBadgeId(string $sExtensionCode, string $sBadgeType): string
|
||||
{
|
||||
return 'badge--'.$sExtensionCode.'--'.$sBadgeType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class AttributeOneWayPassword extends AttributeDefinition implements iAttributeN
|
||||
if (is_object($oPassword)) {
|
||||
$oPassword = clone $proposedValue;
|
||||
} else {
|
||||
$oPassword = new ormPassword('', '');
|
||||
$oPassword = new ormPassword();
|
||||
$oPassword->SetPassword($proposedValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -210,7 +210,8 @@ class ObjectRepository
|
||||
$aData['has_additional_field'] = true;
|
||||
$aArguments = [];
|
||||
foreach ($aComplementAttributeSpec[1] as $sAdditionalField) {
|
||||
$aArguments[] = $oDbObject->Get($sAdditionalField);
|
||||
//getAsCSV to have user friendly value in text format
|
||||
$aArguments[] = $oDbObject->GetAsCSV($sAdditionalField,' ','');
|
||||
}
|
||||
$aData['additional_field'] = utils::VSprintf($aComplementAttributeSpec[0], $aArguments);
|
||||
$sAdditionalFieldForHtml = utils::EscapeHtml($aData['additional_field']);
|
||||
|
||||
@@ -52,4 +52,11 @@ class ormPasswordTest extends ItopDataTestCase
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function testSetPasswordNullShouldNotCrash()
|
||||
{
|
||||
$oPassword = new ormPassword();
|
||||
$oPassword->SetPassword(null);
|
||||
static::assertTrue($oPassword->CheckPassword(null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ $aAddedExtensions = [];
|
||||
if (mb_strlen($sAddedExtensions) > 0) {
|
||||
$aAddedExtensions = explode(',', $sAddedExtensions);
|
||||
}
|
||||
$oExtensionMap = new iTopExtensionsMap();
|
||||
$oExtensionMap = iTopExtensionsMap::GetExtensionsMap();
|
||||
foreach ($aAddedExtensions as $iIndex => $sExtensionCode) {
|
||||
if (mb_strlen($sExtensionCode) <= 0) {
|
||||
unset($aAddedExtensions[$iIndex]);
|
||||
|
||||
@@ -1004,7 +1004,7 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-ext-not-installed"><b>My extension</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
<div id="badge--itop-ext-not-installed--to-be-installed" class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div id="badge--itop-ext-not-installed--not-installed" class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
<span>v1.2.3</span><span>Local extensions folder</span>
|
||||
@@ -1048,7 +1048,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-ext-installed"><b>My extension</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div><div class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div>
|
||||
<div id="badge--itop-ext-installed--installed" class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div><div id="badge--itop-ext-installed--to-be-uninstalled" class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
<span>v1.2.3</span><span>Local extensions folder</span>
|
||||
@@ -1093,7 +1093,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-ext-installed"><b>My extension</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div><div class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div><div class="ibo-badge ibo-block ibo-is-orange" title="Once this extension has been installed, it should not be uninstalled." >cannot be uninstalled</div>
|
||||
<div id="badge--itop-ext-installed--installed" class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div><div id="badge--itop-ext-installed--to-be-uninstalled" class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div><div id="badge--itop-ext-installed--not-uninstallable" class="ibo-badge ibo-block ibo-is-orange" title="Once this extension has been installed, it should not be uninstalled." >cannot be uninstalled</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
<span>v1.2.3</span><span>Local extensions folder</span>
|
||||
@@ -1137,7 +1137,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-ext-not-installed"><b>My extension</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
<div id="badge--itop-ext-not-installed--to-be-installed" class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div id="badge--itop-ext-not-installed--not-installed" class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
<span>v1.2.3</span><span>Local extensions folder</span>
|
||||
@@ -1175,7 +1175,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-alt-nothing"><b>No Change</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
<div id="badge--itop-alt-nothing--to-be-installed" class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div id="badge--itop-alt-nothing--not-installed" class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
|
||||
@@ -1221,7 +1221,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-alt-something"><b>Change</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div><div class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div>
|
||||
<div id="badge--itop-alt-something--installed" class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div><div id="badge--itop-alt-something--to-be-uninstalled" class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
|
||||
@@ -1242,7 +1242,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-alt-nothing"><b>No Change</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
<div id="badge--itop-alt-nothing--to-be-installed" class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div id="badge--itop-alt-nothing--not-installed" class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
|
||||
@@ -1302,7 +1302,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-alt-something"><b>Change</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div><div class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div>
|
||||
<div id="badge--itop-alt-something--installed" class="ibo-badge ibo-block checked ibo-is-green" title="This extension is part of the current installation." >installed</div><div id="badge--itop-alt-something--to-be-uninstalled" class="ibo-badge ibo-block unchecked ibo-is-red" title="This extension will be uninstalled during the setup." >to be uninstalled</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
|
||||
@@ -1319,7 +1319,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-ext-not-installed"><b>My extension</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
<div id="badge--itop-ext-not-installed--to-be-installed" class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div id="badge--itop-ext-not-installed--not-installed" class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
|
||||
@@ -1344,7 +1344,7 @@ HTML,
|
||||
<div class="ibo-extension-details--information--label">
|
||||
<label for="itop-alt-nothing"><b>No Change</b></label>
|
||||
|
||||
<div class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
<div id="badge--itop-alt-nothing--to-be-installed" class="ibo-badge ibo-block checked ibo-is-cyan" title="This extension will be installed during the setup." >to be installed</div><div id="badge--itop-alt-nothing--not-installed" class="ibo-badge ibo-block unchecked ibo-is-blue-grey" title="This extension is not part of the current installation." >not installed</div>
|
||||
</div>
|
||||
<div class="ibo-extension-details--information--metadata">
|
||||
|
||||
|
||||
@@ -139,6 +139,158 @@ JSON;
|
||||
$this->assertJsonStringEqualsJsonString($sExpectedJsonOuput, $sJSONOutput);
|
||||
}
|
||||
|
||||
|
||||
public function testCoreApiGet_Select2SubClasses(){
|
||||
// Create ticket
|
||||
$description = date('dmY H:i:s');
|
||||
$iIdCaller = $this->CreatePerson(1)->GetKey();
|
||||
$oUserRequest = $this->CreateSampleTicket($description, 'UserRequest', $iIdCaller);
|
||||
$oChange = $this->CreateSampleTicket($description, 'Change', $iIdCaller);
|
||||
$iIdUserRequest = $oUserRequest->GetKey();
|
||||
$iIdChange = $oChange->GetKey();
|
||||
|
||||
$sJSONOutput = $this->CallCoreRestApi_Internally(<<<JSON
|
||||
{
|
||||
"operation": "core/get",
|
||||
"class": "UserRequest, Change",
|
||||
"key": "SELECT UserRequest WHERE id=$iIdUserRequest UNION SELECT Change WHERE id=$iIdChange",
|
||||
"output_fields": "id, description, outage"
|
||||
}
|
||||
JSON);
|
||||
|
||||
$sExpectedJsonOuput = <<<JSON
|
||||
{
|
||||
"code": 0,
|
||||
"message": "Found: 2",
|
||||
"objects": {
|
||||
"UserRequest::$iIdUserRequest": {
|
||||
"class": "UserRequest",
|
||||
"code": 0,
|
||||
"fields": {
|
||||
"description": "<p>$description</p>",
|
||||
"id": "$iIdUserRequest"
|
||||
},
|
||||
"key": "$iIdUserRequest",
|
||||
"message": ""
|
||||
},
|
||||
"Change::$iIdChange": {
|
||||
"class": "Change",
|
||||
"code": 0,
|
||||
"fields": {
|
||||
"description": "<p>$description</p>",
|
||||
"id": "$iIdChange",
|
||||
"outage": "no"
|
||||
},
|
||||
"key": "$iIdChange",
|
||||
"message": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
JSON;
|
||||
$this->assertJsonStringEqualsJsonString($sExpectedJsonOuput, $sJSONOutput);
|
||||
}
|
||||
|
||||
|
||||
public function testCoreApiGet_SelectTicketAndPerson(){
|
||||
// Create ticket
|
||||
$description = date('dmY H:i:s');
|
||||
$iIdCaller = $this->CreatePerson(1)->GetKey();
|
||||
$oUserRequest = $this->CreateSampleTicket($description, 'UserRequest', $iIdCaller);
|
||||
$iIdUserRequest = $oUserRequest->GetKey();
|
||||
|
||||
$sJSONOutput = $this->CallCoreRestApi_Internally(<<<JSON
|
||||
{
|
||||
"operation": "core/get",
|
||||
"class": "UserRequest, Change",
|
||||
"key": "SELECT UR, P FROM UserRequest AS UR JOIN Person AS P ON UR.caller_id = P.id WHERE UR.id=$iIdUserRequest ",
|
||||
"output_fields": "id, title, description, name, email"
|
||||
}
|
||||
JSON);
|
||||
|
||||
$sExpectedJsonOuput = <<<JSON
|
||||
{
|
||||
"code": 0,
|
||||
"message": "Found: 1",
|
||||
"objects": [{
|
||||
"UR": {
|
||||
"class": "UserRequest",
|
||||
"code": 0,
|
||||
"fields": {
|
||||
"description": "<p>$description</p>",
|
||||
"id": "$iIdUserRequest",
|
||||
"title": "Houston, got a problem"
|
||||
},
|
||||
"key": "$iIdUserRequest",
|
||||
"message": ""
|
||||
},
|
||||
"P": {
|
||||
"class": "Person",
|
||||
"code": 0,
|
||||
"fields": {
|
||||
"email": "",
|
||||
"id": "$iIdCaller",
|
||||
"name": "Person_1"
|
||||
},
|
||||
"key": "$iIdCaller",
|
||||
"message": ""
|
||||
}
|
||||
}]
|
||||
}
|
||||
JSON;
|
||||
$this->assertJsonStringEqualsJsonString($sExpectedJsonOuput, $sJSONOutput);
|
||||
}
|
||||
|
||||
public function testCoreApiGetWithUnionAndDifferentOutputFields(){
|
||||
// Create ticket
|
||||
$description = date('dmY H:i:s');
|
||||
$oUserRequest = $this->CreateSampleTicket($description);
|
||||
$oChange = $this->CreateSampleTicket($description, 'Change');
|
||||
$iUserRequestId = $oUserRequest->GetKey();
|
||||
$sUserRequestRef = $oUserRequest->Get('ref');
|
||||
$iChangeId = $oChange->GetKey();
|
||||
$sChangeRef = $oChange->Get('ref');
|
||||
|
||||
$sJSONOutput = $this->CallCoreRestApi_Internally(<<<JSON
|
||||
{
|
||||
"operation": "core/get",
|
||||
"class": "Ticket",
|
||||
"key": "SELECT UserRequest WHERE id=$iUserRequestId UNION SELECT Change WHERE id=$iChangeId",
|
||||
"output_fields": "Ticket:ref;UserRequest:ref,status,origin;Change:ref,status,outage"
|
||||
}
|
||||
JSON);
|
||||
|
||||
$sExpectedJsonOuput = <<<JSON
|
||||
{
|
||||
"code": 0,
|
||||
"message": "Found: 2",
|
||||
"objects": {
|
||||
"Change::$iChangeId": {
|
||||
"class": "Change",
|
||||
"code": 0,
|
||||
"fields": {
|
||||
"outage": "no",
|
||||
"ref": "$sChangeRef",
|
||||
"status": "new"
|
||||
},
|
||||
"key": "$iChangeId",
|
||||
"message": ""
|
||||
},
|
||||
"UserRequest::$iUserRequestId": {
|
||||
"class": "UserRequest",
|
||||
"code": 0,
|
||||
"fields": {
|
||||
"origin": "phone",
|
||||
"ref": "$sUserRequestRef",
|
||||
"status": "new"
|
||||
},
|
||||
"key": "$iUserRequestId",
|
||||
"message": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
JSON;
|
||||
$this->assertJsonStringEqualsJsonString($sExpectedJsonOuput, $sJSONOutput);
|
||||
}
|
||||
public function testCoreApiCreate()
|
||||
{
|
||||
// Create ticket
|
||||
@@ -251,12 +403,13 @@ JSON;
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private function CreateSampleTicket($description)
|
||||
private function CreateSampleTicket($description, $sType = 'UserRequest', $iIdCaller = null)
|
||||
{
|
||||
$oTicket = $this->createObject('UserRequest', [
|
||||
$oTicket = $this->createObject($sType, [
|
||||
'org_id' => $this->getTestOrgId(),
|
||||
"title" => "Houston, got a problem",
|
||||
"description" => $description,
|
||||
"caller_id" => $iIdCaller,
|
||||
]);
|
||||
return $oTicket;
|
||||
}
|
||||
|
||||
109
tests/php-unit-tests/unitary-tests/webservices/RestUtilsTest.php
Normal file
109
tests/php-unit-tests/unitary-tests/webservices/RestUtilsTest.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Webservices;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use MetaModel;
|
||||
use RestUtils;
|
||||
use Ticket;
|
||||
use UserRequest;
|
||||
|
||||
|
||||
class RestUtilsTest extends ItopDataTestCase
|
||||
{
|
||||
public function testGetFieldListForSingleClass(): void
|
||||
{
|
||||
$aList = RestUtils::GetFieldList(Ticket::class, (object) ['output_fields' => 'ref,start_date,end_date'], 'output_fields');
|
||||
$this->assertSame([Ticket::class => ['ref', 'start_date', 'end_date']], $aList);
|
||||
}
|
||||
|
||||
public function testGetFieldListForSingleClassWithInvalidFieldNameFails(): void
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('output_fields: invalid attribute code \'something\' for class \'Ticket\'');
|
||||
$aList = RestUtils::GetFieldList(Ticket::class, (object) ['output_fields' => 'ref,something'], 'output_fields');
|
||||
$this->assertSame([Ticket::class => ['ref', 'start_date', 'end_date']], $aList);
|
||||
}
|
||||
|
||||
public function testGetFieldListWithAsteriskOnParentClass(): void
|
||||
{
|
||||
$aList = RestUtils::GetFieldList(Ticket::class, (object) ['output_fields' => '*'], 'output_fields');
|
||||
$this->assertArrayHasKey(Ticket::class, $aList);
|
||||
$this->assertContains('operational_status', $aList[Ticket::class]);
|
||||
$this->assertNotContains('status', $aList[Ticket::class], 'Representation of Class Ticket should not contain status, since it is defined by children');
|
||||
}
|
||||
|
||||
public function testGetFieldListWithAsteriskPlusOnParentClass(): void
|
||||
{
|
||||
$aList = RestUtils::GetFieldList(Ticket::class, (object) ['output_fields' => '*+'], 'output_fields');
|
||||
$this->assertArrayHasKey(Ticket::class, $aList);
|
||||
$this->assertArrayHasKey(UserRequest::class, $aList);
|
||||
$this->assertContains('operational_status', $aList[Ticket::class]);
|
||||
$this->assertContains('status', $aList[UserRequest::class]);
|
||||
}
|
||||
|
||||
public function testGetFieldListForMultipleClasses(): void
|
||||
{
|
||||
$aList = RestUtils::GetFieldList(Ticket::class, (object) ['output_fields' => 'Ticket:ref,start_date,end_date;UserRequest:ref,status'], 'output_fields');
|
||||
$this->assertArrayHasKey(Ticket::class, $aList);
|
||||
$this->assertArrayHasKey(UserRequest::class, $aList);
|
||||
$this->assertContains('ref', $aList[Ticket::class]);
|
||||
$this->assertContains('end_date', $aList[Ticket::class]);
|
||||
$this->assertNotContains('status', $aList[Ticket::class]);
|
||||
$this->assertContains('status', $aList[UserRequest::class]);
|
||||
$this->assertNotContains('end_date', $aList[UserRequest::class]);
|
||||
}
|
||||
|
||||
public function testGetFieldListForMultipleClassesWithInvalidFieldNameFails(): void
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('output_fields: invalid attribute code \'something\'');
|
||||
RestUtils::GetFieldList(Ticket::class, (object) ['output_fields' => 'Ticket:ref;UserRequest:ref,something'], 'output_fields');
|
||||
}
|
||||
|
||||
|
||||
public function testGetFieldListForMultipleClassesWithInvalidFieldName(): void
|
||||
{
|
||||
$aList = RestUtils::GetFieldList(Ticket::class, (object) ['output_fields' => 'ref, something'], 'output_fields', false);
|
||||
$this->assertContains('ref', $aList[Ticket::class]);
|
||||
$this->assertNotContains('something', $aList[Ticket::class]);
|
||||
}
|
||||
|
||||
public static function extendedOutputDataProvider(): array
|
||||
{
|
||||
return [
|
||||
[false, 'ref,start_date,end_date'],
|
||||
[false, '*'],
|
||||
[true, '*+'],
|
||||
[false, 'Ticket:ref'],
|
||||
[true, 'Ticket:ref;UserRequest:ref'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider extendedOutputDataProvider
|
||||
*/
|
||||
public function testIsExtendedOutputRequest(bool $bExpected, string $sFields): void
|
||||
{
|
||||
$this->assertSame($bExpected, RestUtils::HasRequestedExtendedOutput($sFields));
|
||||
}
|
||||
|
||||
public static function allFieldsOutputDataProvider(): array
|
||||
{
|
||||
return [
|
||||
[false, 'ref,start_date,end_date'],
|
||||
[true, '*'],
|
||||
[true, '*+'],
|
||||
[false, 'Ticket:ref'],
|
||||
[false, 'Ticket:ref;UserRequest:ref'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider allFieldsOutputDataProvider
|
||||
*/
|
||||
public function testIsAllFieldsOutputRequest(bool $bExpected, string $sFields): void
|
||||
{
|
||||
$this->assertSame($bExpected, RestUtils::HasRequestedAllOutputFields($sFields));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user