mirror of
https://github.com/Combodo/iTop.git
synced 2026-03-22 17:34:14 +01:00
Compare commits
57 Commits
feature/73
...
issue/7662
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0d4f11146 | ||
|
|
5ce1788d4a | ||
|
|
38fe31c9fc | ||
|
|
ec61b52238 | ||
|
|
072596a53b | ||
|
|
160bfd714b | ||
|
|
3b51124f1c | ||
|
|
19fa836758 | ||
|
|
1c5cb1547f | ||
|
|
8d58372074 | ||
|
|
e98c6637ac | ||
|
|
7d2a9d0bfc | ||
|
|
762d1162ca | ||
|
|
95dbe4c859 | ||
|
|
ec6adee9c1 | ||
|
|
baa8bba926 | ||
|
|
8dc5411717 | ||
|
|
f1d448fd78 | ||
|
|
a4490e2b5f | ||
|
|
efb7831a5a | ||
|
|
9fadbb5eb1 | ||
|
|
93dba0644d | ||
|
|
ec324bb28e | ||
|
|
dc8f521b12 | ||
|
|
bf6277fcd2 | ||
|
|
886db5d6ad | ||
|
|
0e8ddf990c | ||
|
|
346a8eadec | ||
|
|
6948c594c2 | ||
|
|
301a7a92a0 | ||
|
|
73bb80ebea | ||
|
|
1e674d7bdc | ||
|
|
1225ee1e78 | ||
|
|
a91de9fb36 | ||
|
|
71b3a415a6 | ||
|
|
b97c7433c8 | ||
|
|
11fc958a7b | ||
|
|
a151e40b75 | ||
|
|
5780f26817 | ||
|
|
9a690861a3 | ||
|
|
343f3286b8 | ||
|
|
37fc1a5723 | ||
|
|
7a09b3effc | ||
|
|
4f6d514694 | ||
|
|
8f8b65a71d | ||
|
|
49e72e83fe | ||
|
|
f0685e33e1 | ||
|
|
42f391472b | ||
|
|
30ef2735b6 | ||
|
|
bbff0b72d3 | ||
|
|
2dffab9ca0 | ||
|
|
1cbfa4f1b1 | ||
|
|
5f85757630 | ||
|
|
56d3ac668c | ||
|
|
0a3b02bf45 | ||
|
|
74ebbc5fa4 | ||
|
|
a762b6a2bb |
@@ -3439,8 +3439,18 @@ EOF
|
||||
}
|
||||
$sInputType = '';
|
||||
$sInputId = 'att_'.$iFieldIndex;
|
||||
$value = $this->Get($sAttCode);
|
||||
$sDisplayValue = $this->GetEditValue($sAttCode);
|
||||
if ($oAttDef instanceof AttributeDateTime && !$oAttDef->IsNullAllowed() && $value === $oAttDef->GetNullValue()) {
|
||||
$value = $oAttDef->GetDefaultValue($this);
|
||||
if ($value !== $oAttDef->GetNullValue()) {
|
||||
// Set default date
|
||||
$this->Set($sAttCode, $value);
|
||||
$sDisplayValue = $this->GetEditValue($sAttCode);
|
||||
}
|
||||
}
|
||||
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef,
|
||||
$this->Get($sAttCode), $this->GetEditValue($sAttCode), $sInputId, '', $iExpectCode,
|
||||
$value, $sDisplayValue, $sInputId, '', $iExpectCode,
|
||||
$aArgs, true, $sInputType);
|
||||
$aAttrib = array(
|
||||
'label' => '<span>'.$oAttDef->GetLabel().'</span>',
|
||||
|
||||
@@ -249,9 +249,9 @@ class appUserPreferences extends DBObject
|
||||
(
|
||||
"category" => "gui",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "userid",
|
||||
"name_attcode" => "login",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array("userid"),
|
||||
"reconc_keys" => array("userid","login"),
|
||||
"db_table" => "priv_app_preferences",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
@@ -260,8 +260,10 @@ class appUserPreferences extends DBObject
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"User", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributePropertySet("preferences", array("allowed_values"=>null, "sql"=>"preferences", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_SetZListItems('list', array('preferences',));
|
||||
MetaModel::Init_SetZListItems('default_search', array('userid'));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("org_id", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "org_id")));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("allowed_values" => null, "extkey_attcode" => 'userid', "target_attcode" => "login")));
|
||||
MetaModel::Init_SetZListItems('list', array('org_id','preferences'));
|
||||
MetaModel::Init_SetZListItems('default_search', array('userid','login','org_id'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -180,6 +180,7 @@ class utils
|
||||
*/
|
||||
private static $sAbsoluteUrlAppRootCache = null;
|
||||
|
||||
|
||||
protected static function LoadParamFile($sParamFile)
|
||||
{
|
||||
if (!file_exists($sParamFile)) {
|
||||
@@ -2393,53 +2394,75 @@ SQL;
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sPath
|
||||
*
|
||||
* @return false|\ormDocument
|
||||
* @throws \Exception
|
||||
*
|
||||
* @deprecated 3.2.1 use utils::GetDocumentFromSelfURL instead
|
||||
*/
|
||||
public static function IsSelfURL($sPath)
|
||||
{
|
||||
return self::GetDocumentFromSelfURL($sPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given URL is a link to download a document/image on the CURRENT iTop
|
||||
* In such a case we can read the content of the file directly in the database (if the users rights allow) and return the ormDocument
|
||||
*
|
||||
* @Since 3.2.1 a local URL is transformed into a local file to read
|
||||
*
|
||||
* @param string $sPath
|
||||
* @return false|ormDocument
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function IsSelfURL($sPath)
|
||||
public static function GetDocumentFromSelfURL(string $sPath)
|
||||
{
|
||||
$result = false;
|
||||
$sPageUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.document.php';
|
||||
if (substr($sPath, 0, strlen($sPageUrl)) == $sPageUrl)
|
||||
{
|
||||
if (utils::StartsWith($sPath, $sPageUrl)) {
|
||||
// If the URL is an URL pointing to this instance of iTop, then
|
||||
// extract the "query" part of the URL and analyze it
|
||||
$sQuery = parse_url($sPath, PHP_URL_QUERY);
|
||||
if ($sQuery !== null)
|
||||
{
|
||||
if ($sQuery !== null) {
|
||||
$aParams = array();
|
||||
foreach(explode('&', $sQuery) as $sChunk)
|
||||
{
|
||||
foreach (explode('&', $sQuery) as $sChunk) {
|
||||
$aParts = explode('=', $sChunk ?? '');
|
||||
if (count($aParts) != 2) continue;
|
||||
if (count($aParts) != 2) {
|
||||
continue;
|
||||
}
|
||||
$aParams[$aParts[0]] = urldecode($aParts[1]);
|
||||
}
|
||||
$result = array_key_exists('operation', $aParams) && array_key_exists('class', $aParams) && array_key_exists('id', $aParams) && array_key_exists('field', $aParams) && ($aParams['operation'] == 'download_document');
|
||||
if ($result)
|
||||
{
|
||||
if ($result) {
|
||||
// This is a 'download_document' operation, let's retrieve the document directly from the database
|
||||
$sClass = $aParams['class'];
|
||||
$iKey = $aParams['id'];
|
||||
$sAttCode = $aParams['field'];
|
||||
|
||||
$oObj = MetaModel::GetObject($sClass, $iKey, false /* must exist */); // Users rights apply here !!
|
||||
if ($oObj)
|
||||
{
|
||||
if ($oObj) {
|
||||
/**
|
||||
* @var ormDocument $result
|
||||
*/
|
||||
$result = clone $oObj->Get($sAttCode);
|
||||
return $result;
|
||||
return clone $oObj->Get($sAttCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Exception('Invalid URL. This iTop URL is not pointing to a valid Document/Image.');
|
||||
}
|
||||
return $result;
|
||||
|
||||
if (utils::StartsWith($sPath, utils::GetAbsoluteUrlAppRoot())) {
|
||||
$sFilePath = utils::LocalPath(APPROOT.substr($sPath, strlen(utils::GetAbsoluteUrlAppRoot())));
|
||||
if (false === $sFilePath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sFilePath = APPROOT.$sFilePath;
|
||||
return ormDocument::FromFile($sFilePath);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2447,68 +2470,28 @@ SQL;
|
||||
* - an URL pointing to a blob (image/document) on the current iTop server
|
||||
* - an http(s) URL
|
||||
* - the local file system (but only if you are an administrator)
|
||||
* @param string $sPath
|
||||
*
|
||||
* @param string|null $sPath
|
||||
* @return ormDocument|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function FileGetContentsAndMIMEType($sPath)
|
||||
{
|
||||
$oUploadedDoc = null;
|
||||
$aKnownExtensions = array(
|
||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
|
||||
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
|
||||
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'gif' => 'image/gif',
|
||||
'png' => 'image/png',
|
||||
'pdf' => 'application/pdf',
|
||||
'doc' => 'application/msword',
|
||||
'dot' => 'application/msword',
|
||||
'xls' => 'application/vnd.ms-excel',
|
||||
'ppt' => 'application/vnd.ms-powerpoint',
|
||||
'vsd' => 'application/x-visio',
|
||||
'vdx' => 'application/visio.drawing',
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
||||
'zip' => 'application/zip',
|
||||
'txt' => 'text/plain',
|
||||
'htm' => 'text/html',
|
||||
'html' => 'text/html',
|
||||
'exe' => 'application/octet-stream',
|
||||
);
|
||||
|
||||
$sData = null;
|
||||
$sMimeType = 'text/plain'; // Default MIME Type: treat the file as a bunch a characters...
|
||||
$sFileName = 'uploaded-file'; // Default name for downloaded-files
|
||||
$sExtension = '.txt'; // Default file extension in case we don't know the MIME Type
|
||||
|
||||
if(empty($sPath))
|
||||
{
|
||||
if (utils::IsNullOrEmptyString($sPath)) {
|
||||
// Empty path (NULL or '') means that there is no input, making an empty document.
|
||||
$oUploadedDoc = new ormDocument('', '', '');
|
||||
return new ormDocument('', '', '');
|
||||
}
|
||||
elseif (static::IsURL($sPath))
|
||||
{
|
||||
if ($oUploadedDoc = static::IsSelfURL($sPath))
|
||||
{
|
||||
// Nothing more to do, we've got it !!
|
||||
|
||||
if (static::IsURL($sPath)) {
|
||||
$oUploadedDoc = static::GetDocumentFromSelfURL($sPath);
|
||||
if ($oUploadedDoc) {
|
||||
return $oUploadedDoc;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remote file, let's use the HTTP headers to find the MIME Type
|
||||
$sData = @file_get_contents($sPath);
|
||||
if ($sData === false)
|
||||
{
|
||||
IssueLog::Error(<<<TXT
|
||||
|
||||
// Remote file, let's use the HTTP headers to find the MIME Type
|
||||
$sData = @file_get_contents($sPath);
|
||||
if ($sData === false) {
|
||||
IssueLog::Error(<<<TXT
|
||||
Failed to load the file from URL. This can happen for multiple reasons:
|
||||
- Invalid URL
|
||||
- URL using HTTPS with an untrusted certificate on the remote server
|
||||
@@ -2517,54 +2500,40 @@ TXT
|
||||
, LogChannels::CORE, [
|
||||
'URL' => $sPath,
|
||||
]);
|
||||
throw new Exception("Failed to load the file from the URL '$sPath'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($http_response_header))
|
||||
{
|
||||
$aHeaders = static::ParseHeaders($http_response_header);
|
||||
$sMimeType = array_key_exists('Content-Type', $aHeaders) ? strtolower($aHeaders['Content-Type']) : 'application/x-octet-stream';
|
||||
// Compute the file extension from the MIME Type
|
||||
foreach ($aKnownExtensions as $sExtValue => $sMime) {
|
||||
if ($sMime === $sMimeType) {
|
||||
$sExtension = '.'.$sExtValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$sPathName = pathinfo($sPath, PATHINFO_FILENAME);
|
||||
if (utils::IsNotNullOrEmptyString($sPathName)) {
|
||||
$sFileName = $sPathName;
|
||||
}
|
||||
$sFileName .= $sExtension;
|
||||
}
|
||||
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
|
||||
throw new Exception("Failed to load the file from the URL '$sPath'.");
|
||||
}
|
||||
}
|
||||
else if (UserRights::IsAdministrator())
|
||||
{
|
||||
// Only administrators are allowed to read local files
|
||||
$sData = @file_get_contents($sPath);
|
||||
if ($sData === false)
|
||||
{
|
||||
throw new Exception("Failed to load the file '$sPath'. The file does not exist or the current process is not allowed to access it.");
|
||||
}
|
||||
$sExtension = strtolower(pathinfo($sPath, PATHINFO_EXTENSION));
|
||||
$sFileName = basename($sPath);
|
||||
|
||||
if (array_key_exists($sExtension, $aKnownExtensions))
|
||||
{
|
||||
$sMimeType = $aKnownExtensions[$sExtension];
|
||||
$sMimeType = 'text/plain'; // Default MIME Type: treat the file as a bunch a characters...
|
||||
$sFileName = 'uploaded-file'; // Default name for downloaded-files
|
||||
$sExtension = '.txt'; // Default file extension in case we don't know the MIME Type
|
||||
|
||||
if (isset($http_response_header)) {
|
||||
$aHeaders = static::ParseHeaders($http_response_header);
|
||||
$sMimeType = array_key_exists('Content-Type', $aHeaders) ? strtolower($aHeaders['Content-Type']) : 'application/x-octet-stream';
|
||||
// Compute the file extension from the MIME Type
|
||||
foreach (ormDocument::GetKnownExtensions() as $sExtValue => $sMime) {
|
||||
if ($sMime === $sMimeType) {
|
||||
$sExtension = '.'.$sExtValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (extension_loaded('fileinfo'))
|
||||
{
|
||||
$finfo = new finfo(FILEINFO_MIME);
|
||||
$sMimeType = $finfo->file($sPath);
|
||||
$sPathName = pathinfo($sPath, PATHINFO_FILENAME);
|
||||
if (utils::IsNotNullOrEmptyString($sPathName)) {
|
||||
$sFileName = $sPathName;
|
||||
}
|
||||
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
|
||||
$sFileName .= $sExtension;
|
||||
|
||||
return new ormDocument($sData, $sMimeType, $sFileName);
|
||||
}
|
||||
return $oUploadedDoc;
|
||||
|
||||
// Local file
|
||||
if (UserRights::IsAdministrator()) {
|
||||
// Only administrators are allowed to read local files
|
||||
return ormDocument::FromFile($sPath);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static function ParseHeaders($aHeaders)
|
||||
@@ -3135,29 +3104,13 @@ TXT
|
||||
* @throws \Exception
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function GetMentionedObjectsFromText(string $sText, string $sFormat = self::ENUM_TEXT_FORMAT_HTML): array
|
||||
public static function GetMentionedObjectsFromText(string $sText): array
|
||||
{
|
||||
// First transform text so it can be parsed
|
||||
switch ($sFormat) {
|
||||
case static::ENUM_TEXT_FORMAT_HTML:
|
||||
$sText = static::HtmlToText($sText);
|
||||
break;
|
||||
$aMentionedObjects = [];
|
||||
$aMentionMatches = [];
|
||||
$sText = html_entity_decode($sText);
|
||||
|
||||
default:
|
||||
// Don't transform it
|
||||
break;
|
||||
}
|
||||
|
||||
// Then parse text to find objects
|
||||
$aMentionedObjects = array();
|
||||
$aMentionMatches = array();
|
||||
|
||||
// Note: As the sanitizer (or CKEditor autocomplete plugin? 🤔) removes data-* attributes from the hyperlink,
|
||||
// - we can't use the following (simpler) regexp that only checks data attributes on hyperlinks, which would have worked for hyperlinks pointing to any GUIs: '/<a\s*([^>]*)data-object-class="([^"]*)"\s*data-object-id="([^"]*)">/i'
|
||||
// - instead we use a regexp to match the following pattern '[Some object label](<APP_ROOT_URL>...&class=<OBJECT_CLASS>&id=<OBJECT_ID>...)' which only works for the backoffice
|
||||
// If we change the sanitizer, we might want to switch to the other regexp as it's universal and easier to read
|
||||
$sAppRootUrlForRegExp = addcslashes(utils::GetAbsoluteUrlAppRoot(), '/&');
|
||||
preg_match_all("/\[([^\]]*)\]\({$sAppRootUrlForRegExp}[^\)]*\&class=([^\)\&]*)\&id=([\d]*)[^\)]*\)/i", $sText, $aMentionMatches);
|
||||
preg_match_all('/<a\s*([^>]*)data-object-class="([^"]*)"\s*data-object-key="([^"]*)"/i', $sText, $aMentionMatches);
|
||||
|
||||
foreach ($aMentionMatches[0] as $iMatchIdx => $sCompleteMatch) {
|
||||
$sMatchedClass = $aMentionMatches[2][$iMatchIdx];
|
||||
|
||||
@@ -89,7 +89,7 @@ abstract class AsyncTask extends DBObject
|
||||
// The value is set from null to planned in the setup program
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('planned,running,idle,error'), "sql"=>"status", "default_value"=>"planned", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("started", array("allowed_values"=>null, "sql"=>"started", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("planned", array("allowed_values"=>null, "sql"=>"planned", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("event_id", array("targetclass"=>"Event", "jointype"=> "", "allowed_values"=>null, "sql"=>"event_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
@@ -489,7 +489,7 @@ class AsyncSendNewsroom extends AsyncTask {
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("object_id", array("allowed_values"=>null, "sql"=>"object_id", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("object_class", array("allowed_values"=>null, "sql"=>"object_class", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("url", array("allowed_values"=>null, "sql"=>"url", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>null, "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>'NOW()', "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6346,9 +6346,6 @@ class AttributeDateTime extends AttributeDBField
|
||||
|
||||
$oFormField = parent::MakeFormField($oObject, $oFormField);
|
||||
|
||||
// After call to the parent as it sets the current value
|
||||
$oFormField->SetCurrentValue($this->GetFormat()->Format($oObject->Get($this->GetCode())));
|
||||
|
||||
return $oFormField;
|
||||
}
|
||||
|
||||
@@ -6433,8 +6430,14 @@ class AttributeDateTime extends AttributeDBField
|
||||
|
||||
public function GetDefaultValue(DBObject $oHostObject = null)
|
||||
{
|
||||
if (!$this->IsNullAllowed()) {
|
||||
return date($this->GetInternalFormat());
|
||||
$sDefaultValue = $this->Get('default_value');
|
||||
if (utils::IsNotNullOrEmptyString($sDefaultValue)) {
|
||||
try {
|
||||
$oDate = new DateTimeImmutable($sDefaultValue);
|
||||
} catch (Exception $e) {
|
||||
$oDate = new DateTimeImmutable(Expression::FromOQL($sDefaultValue)->Evaluate([]));
|
||||
}
|
||||
return $oDate->format($this->GetInternalFormat());
|
||||
}
|
||||
return $this->GetNullValue();
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class BulkExportResult extends DBObject
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("created", array("allowed_values"=>null, "sql"=>"created", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("user_id", array("allowed_values"=>null, "sql"=>"user_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("chunk_size", array("allowed_values"=>null, "sql"=>"chunk_size", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("format", array("allowed_values"=>null, "sql"=>"format", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
@@ -33,7 +33,7 @@ class CMDBChange extends DBObject
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("allowed_values"=>null, "sql"=>"user_id", "targetclass"=>"User", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("origin", array("allowed_values"=>new ValueSetEnum(implode(',', [CMDBChangeOrigin::INTERACTIVE, CMDBChangeOrigin::CSV_INTERACTIVE, CMDBChangeOrigin::CSV_IMPORT, CMDBChangeOrigin::WEBSERVICE_SOAP, CMDBChangeOrigin::WEBSERVICE_REST, CMDBChangeOrigin::SYNCHRO_DATA_SOURCE, CMDBChangeOrigin::EMAIL_PROCESSING, CMDBChangeOrigin::CUSTOM_EXTENSION])), "sql"=>"origin", "default_value"=>CMDBChangeOrigin::INTERACTIVE, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
@@ -2867,6 +2867,14 @@ abstract class DBObject implements iDisplay
|
||||
protected function ListChangedValues(array $aProposal)
|
||||
{
|
||||
$aDelta = array();
|
||||
$sClass = get_class($this);
|
||||
if (MetaModel::HasLifecycle($sClass) && utils::IsNotNullOrEmptyString($this->sStimulusBeingApplied)) {
|
||||
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||
if (!in_array($sStateAttCode, $aProposal)) {
|
||||
// Same state but the transition was asked, act as if the state was changed
|
||||
$aDelta[$sStateAttCode] = $this->m_aCurrValues[$sStateAttCode];
|
||||
}
|
||||
}
|
||||
foreach ($aProposal as $sAtt => $proposedValue)
|
||||
{
|
||||
if (!array_key_exists($sAtt, $this->m_aOrigValues))
|
||||
@@ -3811,7 +3819,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
|
||||
try {
|
||||
$this->PostUpdateActions($aChanges, $sClass);
|
||||
$this->PostUpdateActions($this->m_aPreviousValuesForUpdatedAttributes, $sClass);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->LogCRUDExit(__METHOD__, 'Error: '.$e->getMessage());
|
||||
@@ -4025,7 +4033,7 @@ abstract class DBObject implements iDisplay
|
||||
foreach ($aUpdatedLogAttCodes as $sAttCode) {
|
||||
/** @var \ormCaseLog $oUpdatedCaseLog */
|
||||
$oUpdatedCaseLog = $this->Get($sAttCode);
|
||||
$aMentionedObjects = array_merge_recursive($aMentionedObjects, utils::GetMentionedObjectsFromText($oUpdatedCaseLog->GetModifiedEntry()));
|
||||
$aMentionedObjects = array_merge_recursive($aMentionedObjects, utils::GetMentionedObjectsFromText($oUpdatedCaseLog->GetModifiedEntry(ormCaseLog::ENUM_FORMAT_HTML)));
|
||||
}
|
||||
|
||||
// 3 - Trigger for those objects
|
||||
|
||||
@@ -51,7 +51,7 @@ class DBProperty extends DBObject
|
||||
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("value", array("allowed_values"=>null, "sql"=>"value", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("change_date", array("allowed_values"=>null, "sql"=>"change_date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("change_date", array("allowed_values"=>null, "sql"=>"change_date", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("change_comment", array("allowed_values"=>null, "sql"=>"change_comment", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class Event extends DBObject implements iDisplay
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"NOW()", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
// MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ class HTMLDOMSanitizer extends DOMSanitizer
|
||||
protected static $aTagsWhiteList = array(
|
||||
'html' => array(),
|
||||
'body' => array(),
|
||||
'a' => array('href', 'name', 'style', 'class', 'target', 'title', 'data-role', 'data-object-class', 'data-object-id'),
|
||||
'a' => array('href', 'name', 'style', 'class', 'target', 'title', 'data-role', 'data-object-class', 'data-object-id', 'data-object-key'),
|
||||
'p' => array('style', 'class'),
|
||||
'blockquote' => array('style', 'class'),
|
||||
'br' => array(),
|
||||
@@ -354,6 +354,8 @@ class HTMLDOMSanitizer extends DOMSanitizer
|
||||
'font-style',
|
||||
'height',
|
||||
'margin',
|
||||
'margin-left',
|
||||
'margin-right',
|
||||
'padding',
|
||||
'text-align',
|
||||
'vertical-align',
|
||||
|
||||
@@ -575,6 +575,15 @@ class BinaryExpression extends Expression
|
||||
case 'LIKE':
|
||||
$sType = 'like';
|
||||
break;
|
||||
case 'NOT LIKE':
|
||||
$sType = 'notlike';
|
||||
break;
|
||||
case 'IN':
|
||||
$sType = 'in';
|
||||
break;
|
||||
case 'NOT IN':
|
||||
$sType = 'notin';
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Operator '$sOperator' not yet supported");
|
||||
}
|
||||
@@ -639,7 +648,26 @@ class BinaryExpression extends Expression
|
||||
case 'like':
|
||||
$sEscaped = preg_quote($mRight, '/');
|
||||
$sEscaped = str_replace(array('%', '_', '\\\\.*', '\\\\.'), array('.*', '.', '%', '_'), $sEscaped);
|
||||
$result = (int) preg_match("/$sEscaped/i", $mLeft);
|
||||
$pregRes = preg_match("/$sEscaped/i", $mLeft);
|
||||
if ($pregRes === false) {
|
||||
throw new Exception("Error in regular expression '$sEscaped'");
|
||||
}
|
||||
$result = ($pregRes === 1);
|
||||
break;
|
||||
case 'notlike':
|
||||
$sEscaped = preg_quote($mRight, '/');
|
||||
$sEscaped = str_replace(array('%', '_', '\\\\.*', '\\\\.'), array('.*', '.', '%', '_'), $sEscaped);
|
||||
$pregRes = preg_match("/$sEscaped/i", $mLeft);
|
||||
if ($pregRes === false) {
|
||||
throw new Exception("Error in regular expression '$sEscaped'");
|
||||
}
|
||||
$result = ($pregRes !== 1);
|
||||
break;
|
||||
case 'in':
|
||||
$result = in_array($mLeft, $mRight);
|
||||
break;
|
||||
case 'notin':
|
||||
$result = !in_array($mLeft, $mRight);
|
||||
break;
|
||||
}
|
||||
return $result;
|
||||
@@ -2250,7 +2278,12 @@ class ListExpression extends Expression
|
||||
*/
|
||||
public function Evaluate(array $aArgs)
|
||||
{
|
||||
throw new Exception('list expression not yet supported');
|
||||
//throw new Exception('list expression not yet supported');
|
||||
$aResult = [];
|
||||
foreach ($this->m_aExpressions as $oExpressions) {
|
||||
$aResult[] = $oExpressions->Evaluate($aArgs);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,6 +48,42 @@ class ormDocument
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public const DEFAULT_DOWNLOADS_COUNT = 0;
|
||||
private static $aKnownExtensions = [
|
||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
|
||||
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
|
||||
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'gif' => 'image/gif',
|
||||
'png' => 'image/png',
|
||||
'pdf' => 'application/pdf',
|
||||
'doc' => 'application/msword',
|
||||
'dot' => 'application/msword',
|
||||
'xls' => 'application/vnd.ms-excel',
|
||||
'ppt' => 'application/vnd.ms-powerpoint',
|
||||
'vsd' => 'application/x-visio',
|
||||
'vdx' => 'application/visio.drawing',
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
||||
'zip' => 'application/zip',
|
||||
'txt' => 'text/plain',
|
||||
'htm' => 'text/html',
|
||||
'html' => 'text/html',
|
||||
'exe' => 'application/octet-stream',
|
||||
];
|
||||
|
||||
public static function GetKnownExtensions(): array
|
||||
{
|
||||
return self::$aKnownExtensions;
|
||||
}
|
||||
|
||||
protected $m_data;
|
||||
protected $m_sMimeType;
|
||||
@@ -76,6 +112,36 @@ class ormDocument
|
||||
$this->m_iDownloadsCount = $iDownloadsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPath Absolute path of the document to read
|
||||
*
|
||||
* @return \ormDocument
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function FromFile(string $sPath): ormDocument
|
||||
{
|
||||
$sPath = utils::RealPath($sPath, APPROOT);
|
||||
if (false === $sPath) {
|
||||
throw new Exception("Failed to load the file '$sPath'. The file does not exist or the current process is not allowed to access it.");
|
||||
}
|
||||
$sData = @file_get_contents($sPath);
|
||||
if (false === $sData) {
|
||||
throw new Exception("Failed to load the file '$sPath'. The file does not exist or the current process is not allowed to access it.");
|
||||
}
|
||||
$sExtension = strtolower(pathinfo($sPath, PATHINFO_EXTENSION));
|
||||
$sFileName = basename($sPath);
|
||||
|
||||
$sMimeType = 'text/plain';
|
||||
if (array_key_exists($sExtension, ormDocument::$aKnownExtensions)) {
|
||||
$sMimeType = ormDocument::$aKnownExtensions[$sExtension];
|
||||
} else if (extension_loaded('fileinfo')) {
|
||||
$fInfo = new finfo(FILEINFO_MIME);
|
||||
$sMimeType = $fInfo->file($sPath);
|
||||
}
|
||||
|
||||
return new ormDocument($sData, $sMimeType, $sFileName);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
if($this->IsEmpty()) return '';
|
||||
|
||||
@@ -42,8 +42,8 @@ class iTopOwnershipToken extends DBObject
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("acquired", array("allowed_values"=>null, "sql"=>'acquired', "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("last_seen", array("allowed_values"=>null, "sql"=>'last_seen', "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("acquired", array("allowed_values"=>null, "sql"=>'acquired', "default_value"=>'NOW()', "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("last_seen", array("allowed_values"=>null, "sql"=>'last_seen', "default_value"=>'NOW()', "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("obj_class", array("allowed_values"=>null, "sql"=>'obj_class', "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("obj_key", array("allowed_values"=>null, "sql"=>'obj_key', "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("token", array("allowed_values"=>null, "sql"=>'token', "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
@@ -1921,50 +1921,45 @@ class UserRights
|
||||
*/
|
||||
protected static function FindUser($sLogin, $sAuthentication = 'any', $bAllowDisabledUsers = false)
|
||||
{
|
||||
if ($sAuthentication == 'any')
|
||||
{
|
||||
$oUser = self::FindUser($sLogin, 'internal');
|
||||
if ($oUser == null)
|
||||
{
|
||||
$oUser = self::FindUser($sLogin, 'external');
|
||||
if ($sAuthentication === 'any') {
|
||||
$oUser = self::FindUser($sLogin, 'internal', $bAllowDisabledUsers);
|
||||
if ($oUser !== null) {
|
||||
return $oUser;
|
||||
}
|
||||
|
||||
return self::FindUser($sLogin, 'external', $bAllowDisabledUsers);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isset(self::$m_aCacheUsers))
|
||||
{
|
||||
self::$m_aCacheUsers = array('internal' => array(), 'external' => array());
|
||||
}
|
||||
|
||||
if (!isset(self::$m_aCacheUsers[$sAuthentication][$sLogin]))
|
||||
{
|
||||
switch($sAuthentication)
|
||||
{
|
||||
case 'external':
|
||||
$sBaseClass = 'UserExternal';
|
||||
break;
|
||||
|
||||
case 'internal':
|
||||
$sBaseClass = 'UserInternal';
|
||||
break;
|
||||
|
||||
default:
|
||||
echo "<p>sAuthentication = $sAuthentication</p>\n";
|
||||
assert(false); // should never happen
|
||||
}
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT $sBaseClass WHERE login = :login");
|
||||
$oSearch->AllowAllData();
|
||||
if (!$bAllowDisabledUsers)
|
||||
{
|
||||
$oSearch->AddCondition('status', 'enabled');
|
||||
}
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('login' => $sLogin));
|
||||
$oUser = $oSet->fetch();
|
||||
self::$m_aCacheUsers[$sAuthentication][$sLogin] = $oUser;
|
||||
}
|
||||
$oUser = self::$m_aCacheUsers[$sAuthentication][$sLogin];
|
||||
if (!isset(self::$m_aCacheUsers)) {
|
||||
self::$m_aCacheUsers = [ 'internal' => [], 'external' => [] ];
|
||||
}
|
||||
return $oUser;
|
||||
|
||||
if (! isset(self::$m_aCacheUsers[$sAuthentication]) || ! array_key_exists($sLogin, self::$m_aCacheUsers[$sAuthentication])) {
|
||||
switch($sAuthentication) {
|
||||
case 'external':
|
||||
$sBaseClass = 'UserExternal';
|
||||
break;
|
||||
|
||||
case 'internal':
|
||||
$sBaseClass = 'UserInternal';
|
||||
break;
|
||||
|
||||
default:
|
||||
echo "<p>sAuthentication = $sAuthentication</p>\n";
|
||||
assert(false); // should never happen
|
||||
}
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT $sBaseClass WHERE login = :login");
|
||||
$oSearch->AllowAllData();
|
||||
if (!$bAllowDisabledUsers) {
|
||||
$oSearch->AddCondition('status', 'enabled');
|
||||
}
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('login' => $sLogin));
|
||||
$oUser = $oSet->fetch();
|
||||
|
||||
self::$m_aCacheUsers[$sAuthentication][$sLogin] = $oUser;
|
||||
}
|
||||
|
||||
return self::$m_aCacheUsers[$sAuthentication][$sLogin];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -952,5 +952,22 @@ HTML
|
||||
</classes>
|
||||
</group>
|
||||
</groups>
|
||||
<profiles>
|
||||
<profile id="117" _delta="if_exists">
|
||||
<!-- SuperUser -->
|
||||
<groups>
|
||||
<group id="OauthConnection">
|
||||
<actions>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:bulk delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
</profile>
|
||||
</profiles>
|
||||
</user_rights>
|
||||
</itop_design>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'Class:OAuthClient' => 'OAuth Client~~',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id~~',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret~~',
|
||||
@@ -40,7 +40,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -62,7 +62,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -84,7 +84,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)~~',
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...~~',
|
||||
'Menu:GenerateTokens' => 'Generate access token...~~',
|
||||
'Menu:OAuthClient' => 'OAuth client~~',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...~~',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'Class:OAuthClient' => 'OAuth Client~~',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id~~',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret~~',
|
||||
@@ -40,7 +40,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -62,7 +62,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -84,7 +84,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)~~',
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...~~',
|
||||
'Menu:GenerateTokens' => 'Generate access token...~~',
|
||||
'Menu:OAuthClient' => 'OAuth client~~',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...~~',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'Class:OAuthClient' => 'OAuth-Client',
|
||||
'Class:OAuthClient' => 'Mailpostfach-OAuth-Client',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client ID',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'Eine lange Zeichenfolge, die durch den oAuth2-Provider bereitgestellt wird',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client Secret',
|
||||
@@ -40,7 +40,7 @@ Löschen Sie das Feld, um den Standardwert neu zu berechnen.',
|
||||
'Class:OAuthClient/Attribute:token+' => '',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Zugriffstoken Ablaufszeitpunkt',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '',
|
||||
'Class:OAuthClientAzure' => 'OAuth-Client für Microsoft Azure',
|
||||
'Class:OAuthClientAzure' => 'Mailpostfach-OAuth-Client für Microsoft Azure',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Erweiterter Scope',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'Sobald Sie hier etwas eingeben, hat es Vorrang vor der Auswahl im Feld "Scope", die dann ignoriert wird.',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope',
|
||||
@@ -62,7 +62,7 @@ Löschen Sie das Feld, um den Standardwert neu zu berechnen.',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Einfach',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientGoogle' => 'OAuth-Client für Google',
|
||||
'Class:OAuthClientGoogle' => 'Mailpostfach-OAuth-Client für Google',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Erweiterter Scope',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'Sobald Sie hier etwas eingeben, hat es Vorrang vor der Auswahl im Feld "Scope", die dann ignoriert wird.',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope',
|
||||
@@ -84,7 +84,7 @@ Löschen Sie das Feld, um den Standardwert neu zu berechnen.',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Menu:CreateMailbox' => 'Mailpostfach erstellen...',
|
||||
'Menu:GenerateTokens' => 'Zugriffstoken generieren...',
|
||||
'Menu:OAuthClient' => 'OAuth-Client',
|
||||
'Menu:OAuthClient' => 'Mailpostfach-OAuth-Client',
|
||||
'Menu:OAuthClient+' => '',
|
||||
'Menu:RegenerateTokens' => 'Zugriffstoken neu generieren...',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'Die Kombination aus "Login" (%1$s) und "Verwendung für SMTP" (%2$s) existiert bereits.',
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...',
|
||||
'Menu:OAuthClient' => 'OAuth client',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access',
|
||||
'Menu:OAuthClient+' => 'Oauth for email access',
|
||||
'Menu:GenerateTokens' => 'Generate access token...',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...',
|
||||
@@ -35,7 +35,7 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
'Class:OAuthClient' => 'OAuth Client',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access',
|
||||
'Class:OAuthClient/Attribute:provider' => 'Provider',
|
||||
'Class:OAuthClient/Attribute:provider+' => '',
|
||||
'Class:OAuthClient/Attribute:name' => 'Login',
|
||||
@@ -73,7 +73,7 @@ EOF
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope',
|
||||
'Class:OAuthClientAzure/Attribute:scope+' => 'Usually default selection is appropriate',
|
||||
@@ -102,7 +102,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope',
|
||||
'Class:OAuthClientGoogle/Attribute:scope+' => 'Usually default selection is appropriate',
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', [
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...',
|
||||
'Menu:OAuthClient' => 'OAuth client',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access',
|
||||
'Menu:OAuthClient+' => '',
|
||||
'Menu:GenerateTokens' => 'Generate access token...',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...',
|
||||
@@ -35,7 +35,7 @@ Dict::Add('EN GB', 'British English', 'British English', [
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', [
|
||||
'Class:OAuthClient' => 'OAuth Client',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access',
|
||||
'Class:OAuthClient/Attribute:provider' => 'Provider',
|
||||
'Class:OAuthClient/Attribute:provider+' => '',
|
||||
'Class:OAuthClient/Attribute:name' => 'Login',
|
||||
@@ -73,7 +73,7 @@ EOF
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope',
|
||||
'Class:OAuthClientAzure/Attribute:scope+' => 'Usually default selection is appropriate',
|
||||
@@ -102,7 +102,7 @@ Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope',
|
||||
'Class:OAuthClientGoogle/Attribute:scope+' => 'Usually default selection is appropriate',
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
* @author Miguel Turrubiates <miguel_tf@yahoo.com>
|
||||
* @notas Utilizar codificación UTF-8 para mostrar acentos y otros caracteres especiales
|
||||
* @notas Utilizar codificación UTF-8 para mostrar acentos y otros caracteres especiales
|
||||
*/
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
'Class:OAuthClient' => 'Cliente OAuth',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Id Cliente',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'Una cadena larga de caracteres proporcionada por su proveedor de OAuth2',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Secreto del Cliente',
|
||||
@@ -82,7 +82,7 @@ Borre el campo para recalcular el valor predeterminado',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Menu:CreateMailbox' => 'Crear un buzón...',
|
||||
'Menu:GenerateTokens' => 'Generar token de acceso...',
|
||||
'Menu:OAuthClient' => 'Cliente OAuth',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => 'Cliente OAuth',
|
||||
'Menu:RegenerateTokens' => 'Regenerar token de acceso...',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'La combinación Inicio de sesión (%1$s) y Uso para SMTP (%2$s) ya se ha utilizado para el Cliente OAuth',
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:OAuthClient' => 'Client OAuth',
|
||||
'Class:OAuthClient' => 'Client OAuth pour l\'Accès Mail',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'ID Client',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'Recopier la chaine fournie par votre fournisseur OAuth2',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Code secret du client',
|
||||
@@ -86,7 +86,7 @@ Pour recalculer la valeur par défaut, il faut effacer le champ',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Menu:CreateMailbox' => 'Créer une boite mail...',
|
||||
'Menu:GenerateTokens' => 'Créer un jeton d\'accès...',
|
||||
'Menu:OAuthClient' => 'Client OAuth',
|
||||
'Menu:OAuthClient' => 'Client OAuth pour l\'Accès Mail',
|
||||
'Menu:OAuthClient+' => 'Client OAuth pour l\'email',
|
||||
'Menu:RegenerateTokens' => 'Recréer un jeton d\'accès..',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'La combinaison Login (%1$s) and Utilisé pour SMTP (%2$s) a déjà été utilisée pour OAuth Client',
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
'Class:OAuthClient' => 'OAuth ügyfél',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Ügyfél azonosító',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Ügyfél kulcs',
|
||||
@@ -40,7 +40,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Hozzáférési token lejárata',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth ügyfél Microsoft Azure-hoz',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -62,7 +62,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientGoogle' => 'OAuth ügyfél a Google-höz',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -84,7 +84,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Menu:CreateMailbox' => 'Postafiók létrehozása...',
|
||||
'Menu:GenerateTokens' => 'Hozzáférési tokenek generálása...',
|
||||
'Menu:OAuthClient' => 'OAuth ügyfél',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Hozzáférési tokenek újragenerálása...',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'Class:OAuthClient' => 'Client OAuth',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'ID cliente',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Segreto del cliente',
|
||||
@@ -39,7 +39,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Scadenza del token di accesso',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'Client OAuth per Microsoft Azure',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Ambito avanzato',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'Non appena inserisci qualcosa qui, essa ha la precedenza sulla selezione “Ambito” che viene quindi ignorata',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Ambito',
|
||||
@@ -61,7 +61,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Semplice',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientGoogle' => 'Client OAuth per Google',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Ambito avanzato',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'Non appena inserisci qualcosa qui, essa ha la precedenza sulla selezione “Ambito” che viene quindi ignorata',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Ambito',
|
||||
@@ -83,7 +83,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Menu:CreateMailbox' => 'Crea una casella di posta...',
|
||||
'Menu:GenerateTokens' => 'Genera token di accesso...',
|
||||
'Menu:OAuthClient' => 'Client OAuth',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Rigenera token di accesso...',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'La combinazione Login (%1$s) e Uso per SMTP (%2$s) è già stata utilizzata per un altro Client OAuth',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'Class:OAuthClient' => 'OAuth Client~~',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id~~',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret~~',
|
||||
@@ -40,7 +40,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -62,7 +62,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -84,7 +84,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)~~',
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...~~',
|
||||
'Menu:GenerateTokens' => 'Generate access token...~~',
|
||||
'Menu:OAuthClient' => 'OAuth client~~',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...~~',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* @author Thomas Casteleyn <thomas.casteleyn@super-visions.com>
|
||||
*/
|
||||
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
'Class:OAuthClient' => 'OAuth Client~~',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id~~',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret~~',
|
||||
@@ -41,7 +41,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '',
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -63,7 +63,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Eenvoudig',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -85,7 +85,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...~~',
|
||||
'Menu:GenerateTokens' => 'Generate access token...~~',
|
||||
'Menu:OAuthClient' => 'OAuth client~~',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...~~',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
'Class:OAuthClient' => 'Klient OAuth',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Id klienta',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'Długi ciąg znaków dostarczony przez dostawcę protokołu OAuth2',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Sekretny ciąg',
|
||||
@@ -80,7 +80,7 @@ Usuń pole, aby ponownie obliczyć wartość domyślną',
|
||||
'Class:OAuthClient/Attribute:token+' => '',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Wygaśnięcie tokenu dostępu',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '',
|
||||
'Class:OAuthClientAzure' => 'Klient OAuth dla Microsoft Azure',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Zaawansowany zakres',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'Gdy tylko coś tu wpiszesz, będzie to miało pierwszeństwo przed wyborem „Zakres”, który zostanie następnie zignorowany',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Zakres',
|
||||
@@ -150,7 +150,7 @@ Usuń pole, aby ponownie obliczyć wartość domyślną',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Prosty',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientGoogle' => 'Klient OAuth dla Google',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Zaawansowany zakres',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'Gdy tylko coś tu wpiszesz, będzie to miało pierwszeństwo przed wyborem „Zakres”, który zostanie następnie zignorowany',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Zakres',
|
||||
@@ -220,7 +220,7 @@ Usuń pole, aby ponownie obliczyć wartość domyślną',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Menu:CreateMailbox' => 'Utwórz skrzynkę pocztową...',
|
||||
'Menu:GenerateTokens' => 'Wygeneruj token dostępu...',
|
||||
'Menu:OAuthClient' => 'Klient OAuth',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '',
|
||||
'Menu:RegenerateTokens' => 'Wygeneruj ponownie token dostępu...',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'Kombinacja Loginu (%1$s) i SMTP (%2$s) była już użyta dla klienta OAuth',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
'Class:OAuthClient' => 'OAuth Client~~',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id~~',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret~~',
|
||||
@@ -40,7 +40,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -62,7 +62,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -84,7 +84,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)~~',
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...~~',
|
||||
'Menu:GenerateTokens' => 'Generate access token...~~',
|
||||
'Menu:OAuthClient' => 'OAuth client~~',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...~~',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
'Class:OAuthClient' => 'OAuth Client~~',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id~~',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret~~',
|
||||
@@ -40,7 +40,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -62,7 +62,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -84,7 +84,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)~~',
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...~~',
|
||||
'Menu:GenerateTokens' => 'Generate access token...~~',
|
||||
'Menu:OAuthClient' => 'OAuth client~~',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...~~',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'Class:OAuthClient' => 'OAuth Client~~',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id~~',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret~~',
|
||||
@@ -38,7 +38,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -60,7 +60,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -82,7 +82,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)~~',
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...~~',
|
||||
'Menu:GenerateTokens' => 'Generate access token...~~',
|
||||
'Menu:OAuthClient' => 'OAuth client~~',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...~~',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'Class:OAuthClient' => 'OAuth Client~~',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:client_id' => 'Client id~~',
|
||||
'Class:OAuthClient/Attribute:client_id+' => 'A long string of characters provided by your OAuth2 provider~~',
|
||||
'Class:OAuthClient/Attribute:client_secret' => 'Client secret~~',
|
||||
@@ -40,7 +40,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClient/Attribute:token+' => '~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration' => 'Access token expiration~~',
|
||||
'Class:OAuthClient/Attribute:token_expiration+' => '~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth client for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientAzure/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => 'Scope~~',
|
||||
@@ -62,7 +62,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple' => 'Simple~~',
|
||||
'Class:OAuthClientAzure/Attribute:used_scope/Value:simple+' => '~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth client for Google~~',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope' => 'Advanced scope~~',
|
||||
'Class:OAuthClientGoogle/Attribute:advanced_scope+' => 'As soon as you enter something here it takes precedence over the “Scope” selection which is then ignored~~',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => 'Scope~~',
|
||||
@@ -84,7 +84,7 @@ Erase the field to recalculate default value~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)~~',
|
||||
'Menu:CreateMailbox' => 'Create a mailbox...~~',
|
||||
'Menu:GenerateTokens' => 'Generate access token...~~',
|
||||
'Menu:OAuthClient' => 'OAuth client~~',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '~~',
|
||||
'Menu:RegenerateTokens' => 'Regenerate access token...~~',
|
||||
'OAuthClient:Name/UseForSMTPMustBeUnique' => 'The combination Login (%1$s) and Use for SMTP (%2$s) has already been used for OAuth Client~~',
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Menu:CreateMailbox' => '创建邮箱...',
|
||||
'Menu:OAuthClient' => 'OAuth客户端',
|
||||
'Menu:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Menu:OAuthClient+' => '',
|
||||
'Menu:GenerateTokens' => '生成访问令牌...',
|
||||
'Menu:RegenerateTokens' => '重新生成访问令牌...',
|
||||
@@ -35,7 +35,7 @@
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:OAuthClient' => 'OAuth客户端',
|
||||
'Class:OAuthClient' => 'OAuth Mail Access~~',
|
||||
'Class:OAuthClient/Attribute:provider' => '提供商',
|
||||
'Class:OAuthClient/Attribute:provider+' => '~~',
|
||||
'Class:OAuthClient/Attribute:name' => '登录',
|
||||
@@ -73,7 +73,7 @@ EOF
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:OAuthClientAzure' => '用于微软Azure的OAuth客户端',
|
||||
'Class:OAuthClientAzure' => 'OAuth Mail Access for Microsoft Azure~~',
|
||||
'Class:OAuthClientAzure/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientAzure/Attribute:scope' => '范围',
|
||||
'Class:OAuthClientAzure/Attribute:scope+' => '通常情况下使用默认选择最合适',
|
||||
@@ -102,7 +102,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:OAuthClientGoogle' => '用于Google的OAuth客户端',
|
||||
'Class:OAuthClientGoogle' => 'OAuth Mail Access for Google~~',
|
||||
'Class:OAuthClientGoogle/Name' => '%1$s (%2$s)',
|
||||
'Class:OAuthClientGoogle/Attribute:scope' => '范围',
|
||||
'Class:OAuthClientGoogle/Attribute:scope+' => '通常情况下使用默认选择最合适',
|
||||
|
||||
@@ -50,7 +50,7 @@ class PopupMenuExtension implements \iPopupMenuExtension
|
||||
|
||||
if ($bHasToken) {
|
||||
$aScopes = $oObj->Get('scope')->GetValues();
|
||||
if (in_array('IMAP', $aScopes)) {
|
||||
if (in_array('IMAP', $aScopes) && class_exists('MailInboxOAuth')) {
|
||||
$aParams = $oAppContext->GetAsHash();
|
||||
$sMenu = 'Menu:CreateMailbox';
|
||||
$sObjClass = get_class($oObj);
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
framework:
|
||||
cache:
|
||||
# Unique name of your app: used to compute stable namespaces for cache keys.
|
||||
#prefix_seed: your_vendor_name/app_name
|
||||
# Unique name of your app: used to compute stable namespaces for cache keys.
|
||||
prefix_seed: combodo/itop
|
||||
|
||||
# The "app" cache stores to the filesystem by default.
|
||||
# The data in this cache should persist between deploys.
|
||||
# Other options include:
|
||||
# filesystem
|
||||
app: cache.adapter.filesystem
|
||||
|
||||
# Redis
|
||||
#app: cache.adapter.redis
|
||||
#default_redis_provider: redis://localhost
|
||||
# Namespaced pools use the above "app" backend by default
|
||||
pools:
|
||||
|
||||
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||
#app: cache.adapter.apcu
|
||||
|
||||
# Namespaced pools use the above "app" backend by default
|
||||
#pools:
|
||||
#my.dedicated.cache: null
|
||||
templates_cache_pool:
|
||||
adapter: cache.app
|
||||
|
||||
@@ -23,9 +23,13 @@ namespace Combodo\iTop\Portal\Brick;
|
||||
require_once APPROOT.'/core/moduledesign.class.inc.php';
|
||||
require_once APPROOT.'/setup/compiler.class.inc.php';
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderInterface;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use DOMFormatException;
|
||||
use ModuleDesign;
|
||||
use Combodo\iTop\DesignElement;
|
||||
|
||||
/**
|
||||
* Description of AbstractBrick
|
||||
@@ -36,7 +40,7 @@ use Combodo\iTop\DesignElement;
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
abstract class AbstractBrick
|
||||
abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
{
|
||||
/** @var string ENUM_DATA_LOADING_LAZY */
|
||||
const ENUM_DATA_LOADING_LAZY = 'lazy';
|
||||
@@ -53,7 +57,7 @@ abstract class AbstractBrick
|
||||
const DEFAULT_VISIBLE = true;
|
||||
/** @var float DEFAULT_RANK */
|
||||
const DEFAULT_RANK = 1.0;
|
||||
/** @var string|null DEFAULT_PAGE_TEMPLATE_PATH */
|
||||
/** @var string|null DEFAULT_PAGE_TEMPLATE_PATH @deprecated since 3.2.1 */
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = null;
|
||||
/** @var string DEFAULT_TITLE */
|
||||
const DEFAULT_TITLE = '';
|
||||
@@ -65,6 +69,8 @@ abstract class AbstractBrick
|
||||
const DEFAULT_ALLOWED_PROFILES_OQL = '';
|
||||
/** @var string DEFAULT_DENIED_PROFILES_OQL */
|
||||
const DEFAULT_DENIED_PROFILES_OQL = '';
|
||||
/** @var string TEMPLATES_BASE_PATH */
|
||||
const TEMPLATES_BASE_PATH = 'itop-portal-base/portal/templates/bricks/';
|
||||
|
||||
/** @var string $sId */
|
||||
protected $sId;
|
||||
@@ -76,7 +82,7 @@ abstract class AbstractBrick
|
||||
protected $bVisible;
|
||||
/** @var float $fRank */
|
||||
protected $fRank;
|
||||
/** @var string|null $sPageTemplatePath */
|
||||
/** @var string|null $sPageTemplatePath @deprecated since 3.2.1 */
|
||||
protected $sPageTemplatePath;
|
||||
/** @var string $sTitle */
|
||||
protected $sTitle;
|
||||
@@ -93,6 +99,37 @@ abstract class AbstractBrick
|
||||
/** @var string $sDeniedProfilesOql */
|
||||
protected $sDeniedProfilesOql;
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService Templating provider service for registering default templates paths */
|
||||
private static TemplatesProviderService $oTemplatesProviderService;
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'layout.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService $oTemplateProviderService
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function SetTemplatesProviderService(TemplatesProviderService $oTemplateProviderService): void
|
||||
{
|
||||
self::$oTemplatesProviderService = $oTemplateProviderService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the templates provider service.
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService
|
||||
*/
|
||||
protected static function GetTemplatesProviderService(): TemplatesProviderService
|
||||
{
|
||||
return self::$oTemplatesProviderService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all enum values for the data loading modes in an array.
|
||||
*
|
||||
@@ -112,7 +149,9 @@ abstract class AbstractBrick
|
||||
$this->bActive = static::DEFAULT_ACTIVE;
|
||||
$this->bVisible = static::DEFAULT_VISIBLE;
|
||||
$this->fRank = static::DEFAULT_RANK;
|
||||
// BEGIN cleaning 3.2.1 deprecated
|
||||
$this->sPageTemplatePath = static::DEFAULT_PAGE_TEMPLATE_PATH;
|
||||
// END cleaning 3.2.1 deprecated
|
||||
$this->sTitle = static::DEFAULT_TITLE;
|
||||
$this->sDescription = static::DEFAULT_DESCRIPTION;
|
||||
$this->sDataLoading = static::DEFAULT_DATA_LOADING;
|
||||
@@ -176,10 +215,12 @@ abstract class AbstractBrick
|
||||
* Returns the brick page template path
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated since 3.2.1 use GetTemplatePath('page') instead
|
||||
*/
|
||||
public function GetPageTemplatePath()
|
||||
{
|
||||
return $this->sPageTemplatePath;
|
||||
return $this->GetTemplatePath('page');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,10 +364,13 @@ abstract class AbstractBrick
|
||||
* @param string $sPageTemplatePath
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @deprecated since 3.2.1 use SetTemplatePath('page') instead
|
||||
*/
|
||||
public function SetPageTemplatePath($sPageTemplatePath)
|
||||
{
|
||||
$this->sPageTemplatePath = $sPageTemplatePath;
|
||||
$this->SetTemplatePath( 'page', $sPageTemplatePath);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -616,7 +660,7 @@ abstract class AbstractBrick
|
||||
{
|
||||
/** @var \Combodo\iTop\DesignElement $oTemplateNode */
|
||||
$oTemplateNode = $oTemplateNodeList->item(0);
|
||||
$this->SetPageTemplatePath($oTemplateNode->GetText(static::DEFAULT_PAGE_TEMPLATE_PATH));
|
||||
$this->SetTemplatePath('page', $oTemplateNode->GetText(static::DEFAULT_PAGE_TEMPLATE_PATH));
|
||||
}
|
||||
break;
|
||||
case 'title':
|
||||
@@ -660,37 +704,48 @@ abstract class AbstractBrick
|
||||
}
|
||||
|
||||
/**
|
||||
* Load brick configuration that is not part of the brick definition but is part of the portal global properties.
|
||||
* Override the brick default template path.
|
||||
* Template is managed by the TemplatesProviderService.
|
||||
*
|
||||
* @param $aPortalProperties
|
||||
*
|
||||
* @return void
|
||||
* @throws \DOMFormatException
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param string $sTemplateId
|
||||
* @param string $sTileTemplatePath
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function LoadFromPortalProperties($aPortalProperties)
|
||||
public function SetTemplatePath(string $sTemplateId, string $sTileTemplatePath): AbstractBrick
|
||||
{
|
||||
// Get the bricks templates
|
||||
$aBricksTemplates = $aPortalProperties['templates']['bricks'];
|
||||
$sClassFQCN = get_class($this);
|
||||
|
||||
// Get the current brick templates
|
||||
$aCurrentBricksTemplates = array_key_exists($sClassFQCN, $aBricksTemplates) ? $aBricksTemplates[$sClassFQCN] : [];
|
||||
foreach($aCurrentBricksTemplates as $sTemplateKey => $sTemplate) {
|
||||
// Clean the template id
|
||||
$sTemplateId = str_ireplace($sClassFQCN.':', '', $sTemplateKey);
|
||||
|
||||
// Call the set method for the template
|
||||
$sSetTemplateMethodName = 'Set'.$sTemplateId.'TemplatePath';
|
||||
|
||||
if(method_exists($this, $sSetTemplateMethodName)) {
|
||||
$this->{$sSetTemplateMethodName}($sTemplate);
|
||||
}
|
||||
else {
|
||||
throw new DOMFormatException(
|
||||
'Template "'.$sTemplateId.'" is not a valid template for brick ' . $sClassFQCN,
|
||||
null, null);
|
||||
}
|
||||
}
|
||||
static::GetTemplatesProviderService()->OverrideInstanceTemplatePath($this, $sTemplateId, $sTileTemplatePath);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the brick template path.
|
||||
* Template is managed by the TemplatesProviderService.
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param string $sTemplateId template identifier
|
||||
*
|
||||
* @return string template path
|
||||
*/
|
||||
public function GetTemplatePath(string $sTemplateId): string
|
||||
{
|
||||
return static::GetTemplatesProviderService()->GetProviderInstanceTemplatePath($this, $sTemplateId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this brick template path is overridden.
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param string $sTemplateId template identifier
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function HasInstanceOverriddenTemplate(string $sTemplateId): ?string
|
||||
{
|
||||
return static::GetTemplatesProviderService()->HasInstanceOverriddenTemplate($this, $sTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use Dict;
|
||||
use DOMFormatException;
|
||||
|
||||
@@ -38,6 +40,8 @@ class AggregatePageBrick extends PortalBrick
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-tachometer-alt';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-tachometer-alt fa-2x';
|
||||
|
||||
/** @var string @deprecated since 3.2.1 */
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/aggregate-page/layout.html.twig';
|
||||
|
||||
// Overloaded variables
|
||||
@@ -48,6 +52,15 @@ class AggregatePageBrick extends PortalBrick
|
||||
*/
|
||||
private $aAggregatePageBricks = array();
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'aggregate-page/layout.html.twig')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AggregatePageBrick constructor.
|
||||
*/
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService;
|
||||
use DOMFormatException;
|
||||
use Exception;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use UserRights;
|
||||
use ModuleDesign;
|
||||
use Combodo\iTop\Portal\Helper\ApplicationHelper;
|
||||
@@ -48,21 +48,20 @@ class BrickCollection
|
||||
private $aHomeOrdering;
|
||||
/** @var array $aNavigationMenuOrdering */
|
||||
private $aNavigationMenuOrdering;
|
||||
/** @var \array $aCombodoPortalInstanceConf
|
||||
* @since 3.2.1
|
||||
*/
|
||||
private $aCombodoPortalInstanceConf;
|
||||
|
||||
/**
|
||||
* BrickCollection constructor.
|
||||
*
|
||||
* @param \ModuleDesign $oModuleDesign
|
||||
* @param $aCombodoPortalInstanceConf
|
||||
* @param \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService $oTemplatesProviderService
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 3.2.1 Added $aCombodoPortalInstanceConf parameter
|
||||
*
|
||||
* @since 3.2.1 Added $oTemplatesProviderService parameter
|
||||
* Important: The service is not directly used, but the injection ensure that the service is initialized.
|
||||
* Bricks may need to use the service to get the templates.
|
||||
*/
|
||||
public function __construct(ModuleDesign $oModuleDesign, $aCombodoPortalInstanceConf)
|
||||
public function __construct(ModuleDesign $oModuleDesign, TemplatesProviderService $oTemplatesProviderService)
|
||||
{
|
||||
$this->oModuleDesign = $oModuleDesign;
|
||||
$this->aAllowedBricks = null;
|
||||
@@ -70,7 +69,6 @@ class BrickCollection
|
||||
$this->iDisplayedInNavigationMenu = 0;
|
||||
$this->aHomeOrdering = array();
|
||||
$this->aNavigationMenuOrdering = array();
|
||||
$this->aCombodoPortalInstanceConf = $aCombodoPortalInstanceConf;
|
||||
|
||||
$this->Load();
|
||||
}
|
||||
@@ -205,9 +203,6 @@ class BrickCollection
|
||||
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oBrick */
|
||||
$oBrick = new $sBrickClass();
|
||||
|
||||
// Load the portal properties that are common to all bricks of this type
|
||||
$oBrick->LoadFromPortalProperties($this->aCombodoPortalInstanceConf['properties']);
|
||||
|
||||
// Load the brick specific properties from its XML definition
|
||||
$oBrick->LoadFromXml($oBrickNode);
|
||||
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use DOMFormatException;
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use DOMFormatException;
|
||||
|
||||
/**
|
||||
* Description of BrowseBrick
|
||||
@@ -32,6 +34,23 @@ use Combodo\iTop\DesignElement;
|
||||
*/
|
||||
class BrowseBrick extends PortalBrick
|
||||
{
|
||||
/**
|
||||
* @var string DEFAULT_PAGE_TEMPLATE_PATH
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_MODE_LIST_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig';
|
||||
/**
|
||||
* @var string DEFAULT_MODE_MOSAIC_TEMPLATE_PATH
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_MODE_MOSAIC_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_mosaic.html.twig';
|
||||
/**
|
||||
* @var string DEFAULT_MODE_TREE_TEMPLATE_PATH
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_MODE_TREE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_tree.html.twig';
|
||||
|
||||
|
||||
/** @var string ENUM_BROWSE_MODE_LIST */
|
||||
const ENUM_BROWSE_MODE_LIST = 'list';
|
||||
/** @var string ENUM_BROWSE_MODE_TREE */
|
||||
@@ -97,6 +116,18 @@ class BrowseBrick extends PortalBrick
|
||||
/** @var int $iDefaultListLength */
|
||||
protected $iDefaultListLength;
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'browse/layout.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_list', static::TEMPLATES_BASE_PATH . 'browse/mode_list.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_tree', static::TEMPLATES_BASE_PATH . 'browse/mode_tree.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_mosaic', static::TEMPLATES_BASE_PATH . 'browse/mode_mosaic.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* BrowseBrick constructor.
|
||||
*/
|
||||
@@ -355,13 +386,8 @@ class BrowseBrick extends PortalBrick
|
||||
$oTemplateNode = $oModeNode->GetOptionalElement('template');
|
||||
if (($oTemplateNode !== null) && ($oTemplateNode->GetText() !== null))
|
||||
{
|
||||
$sTemplatePath = $oTemplateNode->GetText();
|
||||
$this->SetTemplatePath('page_'.$sModeId, $oTemplateNode->GetText());
|
||||
}
|
||||
else
|
||||
{
|
||||
$sTemplatePath = 'itop-portal-base/portal/templates/bricks/browse/mode_'.$sModeId.'.html.twig';
|
||||
}
|
||||
$aModeData['template'] = $sTemplatePath;
|
||||
|
||||
$this->AddAvailableBrowseMode($sModeId, $aModeData);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use DOMFormatException;
|
||||
use Combodo\iTop\DesignElement;
|
||||
use DOMFormatException;
|
||||
|
||||
/**
|
||||
* Description of CreateBrick
|
||||
@@ -35,8 +35,6 @@ class CreateBrick extends PortalBrick
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-plus';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-plus fa-2x';
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/create/modal.html.twig';
|
||||
|
||||
/** @var string DEFAULT_CLASS */
|
||||
const DEFAULT_CLASS = '';
|
||||
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use DOMFormatException;
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use DOMFormatException;
|
||||
|
||||
/**
|
||||
* Description of FilterBrick
|
||||
@@ -34,10 +36,12 @@ class FilterBrick extends PortalBrick
|
||||
{
|
||||
// Overloaded constants
|
||||
const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/filter/tile.html.twig';
|
||||
/**
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/filter/tile.html.twig';
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-search';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-search fa-2x';
|
||||
|
||||
/** @var string DEFAULT_TARGET_BRICK_CLASS */
|
||||
const DEFAULT_TARGET_BRICK_CLASS = 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick';
|
||||
/** @var string DEFAULT_SEARCH_PLACEHOLDER_VALUE */
|
||||
@@ -60,6 +64,15 @@ class FilterBrick extends PortalBrick
|
||||
/** @var string $sSearchSubmitClass */
|
||||
protected $sSearchSubmitClass;
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH . 'filter/tile.html.twig')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* FilterBrick constructor.
|
||||
*/
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use Exception;
|
||||
use DOMFormatException;
|
||||
use DBSearch;
|
||||
use MetaModel;
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use DBSearch;
|
||||
use DOMFormatException;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use ModuleDesign;
|
||||
|
||||
class ManageBrick extends PortalBrick
|
||||
{
|
||||
@@ -51,16 +54,26 @@ class ManageBrick extends PortalBrick
|
||||
/** @var string ENUM_DISPLAY_MODE_BAR */
|
||||
const ENUM_DISPLAY_MODE_BAR = 'bar-chart';
|
||||
|
||||
/** @var string ENUM_PAGE_TEMPLATE_PATH_TABLE */
|
||||
/** @var string ENUM_PAGE_TEMPLATE_PATH_TABLE
|
||||
* @deprecated since 3.2.1
|
||||
* */
|
||||
const ENUM_PAGE_TEMPLATE_PATH_TABLE = 'itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig';
|
||||
/** @var string ENUM_PAGE_TEMPLATE_PATH_CHART */
|
||||
/** @var string ENUM_PAGE_TEMPLATE_PATH_CHART
|
||||
* @deprecated since 3.2.1
|
||||
* */
|
||||
const ENUM_PAGE_TEMPLATE_PATH_CHART = 'itop-portal-base/portal/templates/bricks/manage/layout-chart.html.twig';
|
||||
|
||||
// Overloaded constants
|
||||
/** Overloaded constants */
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-pen-square';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-pen-square fa-2x';
|
||||
/**
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = self::ENUM_PAGE_TEMPLATE_PATH_TABLE;
|
||||
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_LAZY;
|
||||
/**
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/tile-default.html.twig';
|
||||
const DEFAULT_TILE_CONTROLLER_ACTION = 'Combodo\\iTop\\Portal\\Controller\\ManageBrickController::TileAction';
|
||||
|
||||
@@ -84,20 +97,24 @@ class ManageBrick extends PortalBrick
|
||||
const DEFAULT_GROUP_SHOW_OTHERS = true;
|
||||
|
||||
/** @var array $aDisplayModes */
|
||||
static $aDisplayModes = array(
|
||||
public static array $aDisplayModes = array(
|
||||
self::ENUM_DISPLAY_MODE_LIST,
|
||||
self::ENUM_DISPLAY_MODE_PIE,
|
||||
self::ENUM_DISPLAY_MODE_BAR,
|
||||
);
|
||||
|
||||
/** @var array $aTileModes */
|
||||
public static $aTileModes = array(
|
||||
public static array $aTileModes = array(
|
||||
self::ENUM_TILE_MODE_TEXT,
|
||||
self::ENUM_TILE_MODE_BADGE,
|
||||
self::ENUM_TILE_MODE_PIE,
|
||||
self::ENUM_TILE_MODE_BAR,
|
||||
self::ENUM_TILE_MODE_TOP,
|
||||
);
|
||||
/** @var array $aPresentationData */
|
||||
|
||||
/** @var array $aPresentationData
|
||||
* @deprecated since 3.2.1
|
||||
*/
|
||||
public static $aPresentationData = array(
|
||||
self::ENUM_TILE_MODE_BADGE => array(
|
||||
'decorationCssClass' => 'fas fa-id-card fa-2x',
|
||||
@@ -136,6 +153,38 @@ class ManageBrick extends PortalBrick
|
||||
),
|
||||
);
|
||||
|
||||
/** @var array $aDefaultTileData */
|
||||
private static array $aDefaultTileData = [
|
||||
self::ENUM_TILE_MODE_BADGE => [
|
||||
'decorationCssClass' => 'fas fa-id-card fa-2x',
|
||||
],
|
||||
self::ENUM_TILE_MODE_TOP => [
|
||||
'decorationCssClass' => 'fas fa-list-ol fa-2x',
|
||||
],
|
||||
self::ENUM_TILE_MODE_PIE => [
|
||||
'decorationCssClass' => 'fas fa-chart-pie fa-2x',
|
||||
],
|
||||
self::ENUM_TILE_MODE_TEXT => [
|
||||
'decorationCssClass' => 'fas fa-pen-square fa-2x',
|
||||
],
|
||||
self::ENUM_TILE_MODE_BAR => [
|
||||
'decorationCssClass' => 'fas fa-chart-bar fa-2x',
|
||||
],
|
||||
];
|
||||
|
||||
/** @var array $aDefaultLayoutData */
|
||||
private static array $aDefaultLayoutData = [
|
||||
self::ENUM_DISPLAY_MODE_LIST => [
|
||||
'need_details' => true,
|
||||
],
|
||||
self::ENUM_DISPLAY_MODE_PIE => [
|
||||
'need_details' => false,
|
||||
],
|
||||
self::ENUM_DISPLAY_MODE_BAR => [
|
||||
'need_details' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Overloaded variables
|
||||
public static $sRouteName = 'p_manage_brick';
|
||||
|
||||
@@ -164,48 +213,21 @@ class ManageBrick extends PortalBrick
|
||||
/** @var int $iDefaultListLength */
|
||||
protected $iDefaultListLength;
|
||||
|
||||
/**
|
||||
* Returns true if the $sDisplayMode need objects details for rendering.
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static public function AreDetailsNeededForDisplayMode($sDisplayMode)
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
$bNeedDetails = false;
|
||||
foreach (static::$aPresentationData as $aData)
|
||||
{
|
||||
if ($aData['layoutDisplayMode'] === $sDisplayMode)
|
||||
{
|
||||
$bNeedDetails = $aData['need_details'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $bNeedDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page template path for the $sDisplayMode
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function GetPageTemplateFromDisplayMode($sDisplayMode)
|
||||
{
|
||||
$sTemplate = static::DEFAULT_PAGE_TEMPLATE_PATH;
|
||||
foreach (static::$aPresentationData as $aData)
|
||||
{
|
||||
if ($aData['layoutDisplayMode'] === $sDisplayMode)
|
||||
{
|
||||
$sTemplate = $aData['layoutTemplate'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $sTemplate;
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH . 'manage/tile-default.html.twig'),
|
||||
TemplateDefinitionDto::Create('tile_badge', static::TEMPLATES_BASE_PATH. 'manage/tile-badge.html.twig'),
|
||||
TemplateDefinitionDto::Create('tile_chart', static::TEMPLATES_BASE_PATH . 'manage/tile-chart.html.twig'),
|
||||
TemplateDefinitionDto::Create('tile_top_list', static::TEMPLATES_BASE_PATH . 'manage/tile-top-list.html.twig'),
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'manage/layout.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_table', static::TEMPLATES_BASE_PATH . 'manage/layout-table.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_chart', static::TEMPLATES_BASE_PATH . 'manage/layout-chart.html.twig'),
|
||||
TemplateDefinitionDto::Create('mode_chart_bar', static::TEMPLATES_BASE_PATH . 'manage/mode-bar-chart.html.twig', true, self::ENUM_DISPLAY_MODE_BAR),
|
||||
TemplateDefinitionDto::Create('mode_chart_pie', static::TEMPLATES_BASE_PATH . 'manage/mode-pie-chart.html.twig', true,self::ENUM_DISPLAY_MODE_PIE),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,6 +254,101 @@ class ManageBrick extends PortalBrick
|
||||
$this->AddGrouping('areas', array('attribute' => 'finalclass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the $sDisplayMode need objects details for rendering.
|
||||
*
|
||||
* @deprecated since 3.2.1
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static public function AreDetailsNeededForDisplayMode($sDisplayMode)
|
||||
{
|
||||
$bNeedDetails = false;
|
||||
foreach (static::$aPresentationData as $aData)
|
||||
{
|
||||
if ($aData['layoutDisplayMode'] === $sDisplayMode)
|
||||
{
|
||||
$bNeedDetails = $aData['need_details'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $bNeedDetails;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns if the $sLayoutMode need objects details for rendering.
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param string $sLayoutMode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsDetailsNeeded(string $sLayoutMode): bool
|
||||
{
|
||||
return static::$aDefaultLayoutData[$sLayoutMode]['need_details'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page template path for the $sDisplayMode
|
||||
*
|
||||
* @deprecated since 3.2.1
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
* @return string
|
||||
*/
|
||||
static public function GetPageTemplateFromDisplayMode($sDisplayMode)
|
||||
{
|
||||
$sTemplate = static::DEFAULT_PAGE_TEMPLATE_PATH;
|
||||
foreach (static::$aPresentationData as $aData)
|
||||
{
|
||||
if ($aData['layoutDisplayMode'] === $sDisplayMode)
|
||||
{
|
||||
$sTemplate = $aData['layoutTemplate'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $sTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page template path for the $sDisplayMode
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetPageTemplate(string $sDisplayMode): string
|
||||
{
|
||||
return match ($sDisplayMode) {
|
||||
self::ENUM_DISPLAY_MODE_BAR, self::ENUM_DISPLAY_MODE_PIE => $this->GetTemplatePath('page_chart'),
|
||||
default => $this->GetTemplatePath('page_table'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page template path for the $sDisplayMode
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetTileTemplate(): string
|
||||
{
|
||||
return match ($this->GetTileMode()) {
|
||||
self::ENUM_TILE_MODE_BADGE => $this->GetTemplatePath('tile_badge'),
|
||||
self::ENUM_TILE_MODE_PIE, self::ENUM_TILE_MODE_BAR => $this->GetTemplatePath('tile_chart'),
|
||||
self::ENUM_TILE_MODE_TOP => $this->GetTemplatePath('tile_top_list'),
|
||||
default => $this->GetTemplatePath('tile'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the brick oql
|
||||
*
|
||||
@@ -326,10 +443,24 @@ class ManageBrick extends PortalBrick
|
||||
return $this->sTileMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 3.2.1
|
||||
*/
|
||||
public function GetDecorationCssClass()
|
||||
{
|
||||
return static::$aPresentationData[$this->sTileMode]['decorationCssClass'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function GetDecoration()
|
||||
{
|
||||
return static::$aDefaultTileData[$this->sTileMode]['decorationCssClass'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tile mode (display)
|
||||
*
|
||||
@@ -345,6 +476,8 @@ class ManageBrick extends PortalBrick
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 3.2.1
|
||||
*
|
||||
* @param string $sTileMode
|
||||
*
|
||||
* @return string[] parameters for specified type, default parameters if type is invalid
|
||||
@@ -466,7 +599,7 @@ class ManageBrick extends PortalBrick
|
||||
$this->iDefaultListLength = $iDefaultListLength;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a grouping.
|
||||
*
|
||||
@@ -781,10 +914,11 @@ class ManageBrick extends PortalBrick
|
||||
|
||||
case 'tile';
|
||||
$this->SetTileMode($oDisplayNode->GetText(static::DEFAULT_TILE_MODE));
|
||||
|
||||
$aTileParametersForType = $this->GetPresentationDataForTileMode($this->sTileMode);
|
||||
$this->SetTileTemplatePath($aTileParametersForType['tileTemplate']);
|
||||
$this->SetPageTemplatePath($aTileParametersForType['layoutTemplate']);
|
||||
if($this->sDecorationClassHome === static::DEFAULT_DECORATION_CLASS_HOME){
|
||||
$this->sDecorationClassHome = static::$aDefaultTileData[$this->GetTileMode()]['decorationCssClass'];
|
||||
$this->SetDecorationClassNavigationMenu(static::$aDefaultTileData[$this->GetTileMode()]['decorationCssClass']);
|
||||
$this->SetDecorationClassHome(static::$aDefaultTileData[$this->GetTileMode()]['decorationCssClass']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -918,6 +1052,19 @@ class ManageBrick extends PortalBrick
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'templates':
|
||||
$aTemplatesIds = static::GetTemplatesProviderService()->GetRegister()->GetProviderTemplatesIds(self::class);
|
||||
/** @var TemplateDefinitionDto $oTemplateDefinition */
|
||||
foreach ($aTemplatesIds as $sTemplateId) {
|
||||
$oTemplateNodeList = $oBrickSubNode->GetNodes('template[@id='.ModuleDesign::XPathQuote($sTemplateId).']');
|
||||
if ($oTemplateNodeList->length > 0) {
|
||||
/** @var \Combodo\iTop\DesignElement $oTemplateNode */
|
||||
$oTemplateNode = $oTemplateNodeList->item(0);
|
||||
$this->SetTemplatePath($sTemplateId, $oTemplateNode->GetText(static::DEFAULT_TILE_TEMPLATE_PATH));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,10 +1112,10 @@ class ManageBrick extends PortalBrick
|
||||
|
||||
// Checking the navigation icon
|
||||
$sDecorationClassNavigationMenu = $this->GetDecorationClassNavigationMenu();
|
||||
if (empty($sDecorationClassNavigationMenu) && isset(static::$aPresentationData[$this->sTileMode]))
|
||||
if (empty($sDecorationClassNavigationMenu) && isset(static::$aDefaultTileData[$this->sTileMode]))
|
||||
{
|
||||
/** @var string $sDecorationClassNavigationMenu */
|
||||
$sDecorationClassNavigationMenu = static::$aPresentationData[$this->sTileMode]['decorationCssClass'];
|
||||
$sDecorationClassNavigationMenu = static::$aDefaultTileData[$this->sTileMode]['decorationCssClass'];
|
||||
if (!empty($sDecorationClassNavigationMenu))
|
||||
{
|
||||
$this->SetDecorationClassNavigationMenu($sDecorationClassNavigationMenu);
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use DOMFormatException;
|
||||
use ModuleDesign;
|
||||
use Combodo\iTop\DesignElement;
|
||||
|
||||
/**
|
||||
* Description of PortalBrick
|
||||
@@ -70,6 +72,8 @@ abstract class PortalBrick extends AbstractBrick
|
||||
|
||||
/** @var int $iWidth */
|
||||
protected $iWidth;
|
||||
/** @var bool width in pixel flag */
|
||||
public bool $bIsWidthPixel = false;
|
||||
/** @var int $iHeight */
|
||||
protected $iHeight;
|
||||
/** @var bool $bModal */
|
||||
@@ -82,7 +86,7 @@ abstract class PortalBrick extends AbstractBrick
|
||||
protected $sDecorationClassHome;
|
||||
/** @var string $sDecorationClassNavigationMenu */
|
||||
protected $sDecorationClassNavigationMenu;
|
||||
/** @var string $sTileTemplatePath */
|
||||
/** @var string $sTileTemplatePath @deprecated since 3.2.1 */
|
||||
protected $sTileTemplatePath;
|
||||
/** @var string|null $sTileControllerAction */
|
||||
protected $sTileControllerAction;
|
||||
@@ -99,6 +103,17 @@ abstract class PortalBrick extends AbstractBrick
|
||||
/** @var string $sTitleNavigationMenu */
|
||||
protected $sTitleNavigationMenu;
|
||||
|
||||
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH . 'tile.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
@@ -121,7 +136,9 @@ abstract class PortalBrick extends AbstractBrick
|
||||
$this->bVisibleNavigationMenu = static::DEFAULT_VISIBLE_NAVIGATION_MENU;
|
||||
$this->sDecorationClassHome = static::DEFAULT_DECORATION_CLASS_HOME;
|
||||
$this->sDecorationClassNavigationMenu = static::DEFAULT_DECORATION_CLASS_NAVIGATION_MENU;
|
||||
// BEGIN cleaning 3.2.1 deprecated
|
||||
$this->sTileTemplatePath = static::DEFAULT_TILE_TEMPLATE_PATH;
|
||||
// END cleaning 3.2.1 deprecated
|
||||
$this->sTileControllerAction = static::DEFAULT_TILE_CONTROLLER_ACTION;
|
||||
$this->sOpeningTarget = static::DEFAULT_OPENING_TARGET;
|
||||
}
|
||||
@@ -250,10 +267,12 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Returns the brick tile template path
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated since 3.2.1 use GetTemplatePath('tile') instead
|
||||
*/
|
||||
public function GetTileTemplatePath()
|
||||
{
|
||||
return $this->sTileTemplatePath;
|
||||
return $this->GetTemplatePath('tile');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,10 +445,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* @param string $sTileTemplatePath
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @deprecated since 3.2.1 use SetTemplatePath('tile') instead
|
||||
*/
|
||||
public function SetTileTemplatePath($sTileTemplatePath)
|
||||
{
|
||||
$this->sTileTemplatePath = $sTileTemplatePath;
|
||||
$this->SetTemplatePath('tile', $sTileTemplatePath);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -483,7 +505,9 @@ abstract class PortalBrick extends AbstractBrick
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
case 'width':
|
||||
$this->SetWidth((int)$oBrickSubNode->GetText(static::DEFAULT_WIDTH));
|
||||
$sWidth = $oBrickSubNode->GetText(static::DEFAULT_WIDTH);
|
||||
$this->bIsWidthPixel = str_contains($sWidth, 'px');
|
||||
$this->SetWidth((int)$sWidth);
|
||||
break;
|
||||
|
||||
case 'height':
|
||||
@@ -526,7 +550,7 @@ abstract class PortalBrick extends AbstractBrick
|
||||
{
|
||||
/** @var \Combodo\iTop\DesignElement $oTemplateNode */
|
||||
$oTemplateNode = $oTemplateNodeList->item(0);
|
||||
$this->SetTileTemplatePath($oTemplateNode->GetText(static::DEFAULT_TILE_TEMPLATE_PATH));
|
||||
$this->SetTemplatePath('tile', $oTemplateNode->GetText(static::DEFAULT_TILE_TEMPLATE_PATH));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use DOMFormatException;
|
||||
|
||||
/**
|
||||
@@ -32,14 +34,10 @@ use DOMFormatException;
|
||||
class UserProfileBrick extends PortalBrick
|
||||
{
|
||||
// Overloaded constants
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/user-profile/layout.html.twig';
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/user-profile/tile.html.twig';
|
||||
const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
|
||||
const DEFAULT_VISIBLE_HOME = false;
|
||||
const DEFAUT_TITLE = 'Brick:Portal:UserProfile:Title';
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'glyphicon glyphicon-user';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'glyphicon glyphicon-user';
|
||||
|
||||
/** @var bool DEFAULT_SHOW_PICTURE_FORM */
|
||||
const DEFAULT_SHOW_PICTURE_FORM = true;
|
||||
/** @var bool DEFAULT_SHOW_PREFERENCES_FORM */
|
||||
@@ -59,6 +57,17 @@ class UserProfileBrick extends PortalBrick
|
||||
/** @var bool $bShowPasswordForm */
|
||||
protected $bShowPasswordForm;
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'user-profile/layout.html.twig'),
|
||||
TemplateDefinitionDto::Create('user_info', static::TEMPLATES_BASE_PATH.'user-profile/user_info.html.twig'),
|
||||
TemplateDefinitionDto::Create('user_info_ready_js', static::TEMPLATES_BASE_PATH.'user-profile/user_info.ready.js.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* UserProfileBrick constructor.
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Controller;
|
||||
|
||||
use \Symfony\Bundle\FrameworkBundle\Controller\AbstractController as SymfonyAbstractController;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderInterface;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as SymfonyAbstractController;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
use Symfony\Contracts\Service\Attribute\Required;
|
||||
|
||||
@@ -31,8 +35,23 @@ use Symfony\Contracts\Service\Attribute\Required;
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
abstract class AbstractController extends SymfonyAbstractController
|
||||
abstract class AbstractController extends SymfonyAbstractController implements TemplatesProviderInterface
|
||||
{
|
||||
const TEMPLATES_BASE_PATH = 'itop-portal-base/portal/templates/';
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'layout.html.twig'),
|
||||
TemplateDefinitionDto::Create('modal', static::TEMPLATES_BASE_PATH . 'modal/layout.html.twig'),
|
||||
TemplateDefinitionDto::Create('loader', static::TEMPLATES_BASE_PATH.'helpers/loader.html.twig'),
|
||||
TemplateDefinitionDto::Create('tagset_clic_handler_js', static::TEMPLATES_BASE_PATH.'helpers/tagset_clic_handler.js.twig'),
|
||||
TemplateDefinitionDto::Create('session_message', static::TEMPLATES_BASE_PATH.'helpers/session_messages/session_message.html.twig'),
|
||||
TemplateDefinitionDto::Create('session_messages', static::TEMPLATES_BASE_PATH.'helpers/session_messages/session_messages.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\Routing\RouterInterface symfony router
|
||||
*
|
||||
@@ -46,6 +65,25 @@ abstract class AbstractController extends SymfonyAbstractController
|
||||
$this->oRouter = $oRouter;
|
||||
}
|
||||
|
||||
/** @var TemplatesProviderService templates provider service */
|
||||
private TemplatesProviderService $oTemplatesService;
|
||||
#[Required]
|
||||
public function SetTemplatesService(TemplatesProviderService $oTemplatesService): void
|
||||
{
|
||||
$this->oTemplatesService = $oTemplatesService;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the templates provider service.
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService
|
||||
*/
|
||||
protected function GetTemplatesProviderService(): TemplatesProviderService
|
||||
{
|
||||
return $this->oTemplatesService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike {@see \Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait::redirectToRoute()}, this method directly calls the route controller without creating a redirection client side
|
||||
*
|
||||
@@ -104,4 +142,33 @@ abstract class AbstractController extends SymfonyAbstractController
|
||||
|
||||
return $aRouteDefaults['_controller'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the controller template path
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param string $sTemplateId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetTemplatePath(string $sTemplateId): string
|
||||
{
|
||||
return static::GetTemplatesProviderService()->GetProviderInstanceTemplatePath($this, $sTemplateId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the brick template path
|
||||
*
|
||||
* @since 3.2.1
|
||||
* @param string $sTemplateId
|
||||
* @param string $sTileTemplatePath
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Controller\AbstractController
|
||||
*/
|
||||
public function SetTemplatePath(string $sTemplateId, string $sTileTemplatePath): AbstractController
|
||||
{
|
||||
static::GetTemplatesProviderService()->OverrideInstanceTemplatePath($this, $sTemplateId, $sTileTemplatePath);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ class AggregatePageBrickController extends BrickController
|
||||
|
||||
$aTilesRendering = $this->GetBricksTileRendering($oRequest, $aAggregatePageBricks);
|
||||
|
||||
$sLayoutTemplate = $oBrick->GetPageTemplatePath();
|
||||
$sLayoutTemplate = $oBrick->GetTemplatePath('page');
|
||||
$aData = array(
|
||||
'oBrick' => $oBrick,
|
||||
'aggregatepage_bricks' => $aAggregatePageBricks,
|
||||
|
||||
@@ -495,13 +495,13 @@ class BrowseBrickController extends BrickController
|
||||
// - Create a template for that browse mode,
|
||||
// - Add the mode to those available in the brick configuration,
|
||||
// - Create a router and add a route for the new browse mode
|
||||
if ($oBrick->GetPageTemplatePath() !== null)
|
||||
if ($oBrick->HasInstanceOverriddenTemplate('page'))
|
||||
{
|
||||
$sTemplatePath = $oBrick->GetPageTemplatePath();
|
||||
$sTemplatePath = $oBrick->GetTemplatePath('page');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sTemplatePath = $aBrowseModes[$sBrowseMode]['template'];
|
||||
$sTemplatePath = $oBrick->GetTemplatePath('page_' .$sBrowseMode);
|
||||
}
|
||||
$oResponse = $this->render($sTemplatePath, $aData);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace Combodo\iTop\Portal\Controller;
|
||||
use Combodo\iTop\Portal\Brick\BrickCollection;
|
||||
use Combodo\iTop\Portal\Helper\ContextManipulatorHelper;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Class CreateBrickController
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
namespace Combodo\iTop\Portal\Controller;
|
||||
|
||||
use Combodo\iTop\Portal\Brick\BrickCollection;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@@ -33,6 +35,15 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
*/
|
||||
class DefaultController extends AbstractController
|
||||
{
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('home', static::TEMPLATES_BASE_PATH . 'home/layout.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Symfony\Component\HttpFoundation\Request $oRequest
|
||||
* @param \Combodo\iTop\Portal\Brick\BrickCollection $oBricksCollection
|
||||
@@ -72,7 +83,7 @@ class DefaultController extends AbstractController
|
||||
}
|
||||
|
||||
// Home page template
|
||||
$sTemplatePath = $this->getParameter('combodo.portal.instance.conf')['properties']['templates']['home'];
|
||||
$sTemplatePath = $this->GetTemplatePath('home');
|
||||
|
||||
return $this->render($sTemplatePath, $aData);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ use Combodo\iTop\Portal\Helper\RequestManipulatorHelper;
|
||||
use Combodo\iTop\Portal\Helper\ScopeValidatorHelper;
|
||||
use Combodo\iTop\Portal\Helper\SecurityHelper;
|
||||
use Combodo\iTop\Portal\Routing\UrlGenerator;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use DBObject;
|
||||
use DBObjectSet;
|
||||
use DBSearch;
|
||||
@@ -70,8 +72,20 @@ use utils;
|
||||
*/
|
||||
class ManageBrickController extends BrickController
|
||||
{
|
||||
/** @var string EXCEL_EXPORT_TEMPLATE_PATH */
|
||||
/**
|
||||
* @var string EXCEL_EXPORT_TEMPLATE_PATH
|
||||
* @deprecated since 3.2.1
|
||||
*/
|
||||
const EXCEL_EXPORT_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig';
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('modal_export_excel', static::TEMPLATES_BASE_PATH . 'bricks/manage/popup-export-excel.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection
|
||||
@@ -121,7 +135,7 @@ class ManageBrickController extends BrickController
|
||||
$sDisplayMode = $oBrick->GetDefaultDisplayMode();
|
||||
}
|
||||
|
||||
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, $oBrick::AreDetailsNeededForDisplayMode($sDisplayMode));
|
||||
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, $oBrick->IsDetailsNeeded($sDisplayMode));
|
||||
|
||||
$aExportFields = $oBrick->GetExportFields();
|
||||
$aData = $aData + array(
|
||||
@@ -135,7 +149,7 @@ class ManageBrickController extends BrickController
|
||||
}
|
||||
else
|
||||
{
|
||||
$sLayoutTemplate = $oBrick::GetPageTemplateFromDisplayMode($sDisplayMode);
|
||||
$sLayoutTemplate = $oBrick->GetPageTemplate($sDisplayMode);
|
||||
$oResponse = $this->render($sLayoutTemplate, $aData);
|
||||
}
|
||||
|
||||
@@ -167,7 +181,7 @@ class ManageBrickController extends BrickController
|
||||
$aData = array();
|
||||
}
|
||||
|
||||
return $this->render($oBrick->GetTileTemplatePath(), $aData);
|
||||
return $this->render($oBrick->GetTileTemplate(), $aData);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +295,7 @@ class ManageBrickController extends BrickController
|
||||
'sWikiUrl' => 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Auser%3Alists#excel_export',
|
||||
);
|
||||
|
||||
return $this->render(static::EXCEL_EXPORT_TEMPLATE_PATH, $aData);
|
||||
return $this->render($this->GetTemplatePath('modal_export_excel'), $aData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,6 +37,8 @@ use Combodo\iTop\Portal\Helper\RequestManipulatorHelper;
|
||||
use Combodo\iTop\Portal\Helper\ScopeValidatorHelper;
|
||||
use Combodo\iTop\Portal\Helper\SecurityHelper;
|
||||
use Combodo\iTop\Portal\Routing\UrlGenerator;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister;
|
||||
use Combodo\iTop\Renderer\Bootstrap\FieldRenderer\BsLinkedSetFieldRenderer;
|
||||
use DBObject;
|
||||
use DBObjectSearch;
|
||||
@@ -74,6 +76,24 @@ class ObjectController extends BrickController
|
||||
const DEFAULT_PAGE_NUMBER = 1;
|
||||
const DEFAULT_LIST_LENGTH = 10;
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH. 'bricks/object/layout.html.twig'),
|
||||
TemplateDefinitionDto::Create('modal', static::TEMPLATES_BASE_PATH. 'bricks/object/modal.html.twig'),
|
||||
TemplateDefinitionDto::Create('mode_create', static::TEMPLATES_BASE_PATH.'bricks/object/mode_create.html.twig', true, 'create'),
|
||||
TemplateDefinitionDto::Create('mode_edit', static::TEMPLATES_BASE_PATH.'bricks/object/mode_edit.html.twig', true, 'edit'),
|
||||
TemplateDefinitionDto::Create('mode_search_hierarchy', static::TEMPLATES_BASE_PATH.'bricks/object/mode_search_hierarchy.html.twig', true, 'search_hierarchy'),
|
||||
TemplateDefinitionDto::Create('mode_search_regular', static::TEMPLATES_BASE_PATH.'bricks/object/mode_search_regular.html.twig', true, 'search_regular'),
|
||||
TemplateDefinitionDto::Create('mode_view', static::TEMPLATES_BASE_PATH.'bricks/object/mode_view.html.twig', true, 'view'),
|
||||
TemplateDefinitionDto::Create('mode_apply_stimulus', static::TEMPLATES_BASE_PATH.'bricks/object/mode_apply_stimulus.html.twig', true, 'apply_stimulus'),
|
||||
TemplateDefinitionDto::Create('mode_loader', static::TEMPLATES_BASE_PATH.'modal/mode_loader.html.twig'),
|
||||
TemplateDefinitionDto::Create('plugins_buttons', static::TEMPLATES_BASE_PATH.'bricks/object/plugins_buttons.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\Portal\Helper\SecurityHelper $oSecurityHelper
|
||||
* @param \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidatorHelper
|
||||
@@ -82,8 +102,11 @@ class ObjectController extends BrickController
|
||||
* @param \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection
|
||||
* @param \Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper $oObjectFormHandlerHelper
|
||||
* @param \Combodo\iTop\Portal\Helper\NavigationRuleHelper $oNavigationRuleHelper
|
||||
* @param \Combodo\iTop\Portal\Helper\ContextManipulatorHelper $oContextManipulatorHelper
|
||||
* @param array $aCombodoPortalInstanceConf
|
||||
*
|
||||
* @since 3.2.0 N°6933
|
||||
* @since 3.2.1 Added $aCombodoPortalInstanceConf parameter
|
||||
*/
|
||||
public function __construct(
|
||||
protected SecurityHelper $oSecurityHelper,
|
||||
@@ -93,10 +116,11 @@ class ObjectController extends BrickController
|
||||
protected BrickCollection $oBrickCollection,
|
||||
protected ObjectFormHandlerHelper $oObjectFormHandlerHelper,
|
||||
protected NavigationRuleHelper $oNavigationRuleHelper,
|
||||
protected ContextManipulatorHelper $oContextManipulatorHelper
|
||||
|
||||
protected ContextManipulatorHelper $oContextManipulatorHelper,
|
||||
protected array $aCombodoPortalInstanceConf = []
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +256,7 @@ class ObjectController extends BrickController
|
||||
if ($oRequest->isXmlHttpRequest()) {
|
||||
// We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
|
||||
if (empty($sOperation)) {
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/modal.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('modal'), $aData);
|
||||
} else {
|
||||
$oResponse = new JsonResponse($aData);
|
||||
}
|
||||
@@ -246,7 +270,7 @@ class ObjectController extends BrickController
|
||||
}
|
||||
}
|
||||
$aData['sPageTitle'] = $aData['form']['title'];
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/layout.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('page'), $aData);
|
||||
}
|
||||
|
||||
return $oResponse;
|
||||
@@ -307,7 +331,7 @@ class ObjectController extends BrickController
|
||||
// We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
|
||||
if (empty($sOperation))
|
||||
{
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/modal.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('modal'), $aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -327,7 +351,7 @@ class ObjectController extends BrickController
|
||||
}
|
||||
}
|
||||
$aData['sPageTitle'] = $aData['form']['title'];
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/layout.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('page'), $aData);
|
||||
}
|
||||
|
||||
return $oResponse;
|
||||
@@ -534,11 +558,11 @@ class ObjectController extends BrickController
|
||||
// We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
|
||||
if (empty($sOperation))
|
||||
{
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/modal.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('modal'), $aData);
|
||||
}
|
||||
elseif ($sOperation === 'redirect')
|
||||
{
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/modal/mode_loader.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('mode_loader'), $aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -547,7 +571,7 @@ class ObjectController extends BrickController
|
||||
}
|
||||
else
|
||||
{
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/layout.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('page'), $aData);
|
||||
}
|
||||
|
||||
return $oResponse;
|
||||
@@ -1011,12 +1035,12 @@ class ObjectController extends BrickController
|
||||
|
||||
if ($oRequest->isXmlHttpRequest())
|
||||
{
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/modal.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('modal'), $aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
//throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/layout.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('page'), $aData);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1597,7 +1621,7 @@ class ObjectController extends BrickController
|
||||
// We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
|
||||
if (empty($sOperation))
|
||||
{
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/modal.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('modal'), $aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1617,7 +1641,7 @@ class ObjectController extends BrickController
|
||||
}
|
||||
}
|
||||
$aData['sPageTitle'] = $aData['form']['title'];
|
||||
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/layout.html.twig', $aData);
|
||||
$oResponse = $this->render($this->GetTemplatePath('page'), $aData);
|
||||
}
|
||||
|
||||
return $oResponse;
|
||||
@@ -1651,7 +1675,7 @@ class ObjectController extends BrickController
|
||||
if (!empty($sBrickId))
|
||||
{
|
||||
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
|
||||
$sTemplatePath = $oBrick->GetPageTemplatePath();
|
||||
$sTemplatePath = $oBrick->GetTemplatePath('page');
|
||||
|
||||
$aData['sBrickId'] = $sBrickId;
|
||||
$aData['oBrick'] = $oBrick;
|
||||
|
||||
@@ -152,7 +152,7 @@ class UserProfileBrickController extends BrickController
|
||||
// Preparing forms
|
||||
$aData['forms']['contact'] = $this->ObjectFormHandlerHelper->HandleForm($oRequest, $sFormMode, $sCurContactClass,
|
||||
$sCurContactId,
|
||||
$oBrick->GetForm());
|
||||
);
|
||||
$aData['forms']['preferences'] = $this->HandlePreferencesForm($oRequest, $sFormMode);
|
||||
// - If user can change password, we display the form
|
||||
$aData['forms']['password'] = (UserRights::CanChangePassword()) ? $this->HandlePasswordForm($oRequest, $sFormMode) : null;
|
||||
@@ -166,7 +166,7 @@ class UserProfileBrickController extends BrickController
|
||||
|
||||
$this->ManageUserProfileBrickExtensibility($sTab, $aData);
|
||||
|
||||
$oResponse = $this->render($oBrick->GetPageTemplatePath(), $aData);
|
||||
$oResponse = $this->render($oBrick->GetTemplatePath('page'), $aData);
|
||||
}
|
||||
|
||||
return $oResponse;
|
||||
@@ -428,7 +428,7 @@ class UserProfileBrickController extends BrickController
|
||||
'sObjectField' => $sPictureAttCode,
|
||||
'cache' => 86400,
|
||||
's' => $oOrmDoc->GetSignature(),
|
||||
]);
|
||||
]);
|
||||
$aFormData['validation'] = array(
|
||||
'valid' => true,
|
||||
'messages' => array(),
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Portal\DataCollector;
|
||||
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService;
|
||||
use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Template information collector for Symfony profiler.
|
||||
*
|
||||
* @package Combodo\iTop\Portal\DataCollector
|
||||
* @since 3.2.1
|
||||
*/
|
||||
class PortalCollector extends AbstractDataCollector
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService $oTemplatesProviderService
|
||||
*/
|
||||
public function __construct(private readonly TemplatesProviderService $oTemplatesProviderService)
|
||||
{
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function collect(Request $request, Response $response, Throwable $exception = null): void
|
||||
{
|
||||
$oRegister = $this->oTemplatesProviderService->GetRegister();
|
||||
$aTemplatesDefinitions = $oRegister->GetTemplatesDefinitions();
|
||||
$this->data = [
|
||||
'templates_definitions' => $aTemplatesDefinitions,
|
||||
'instances_overridden_templates' => $this->oTemplatesProviderService->GetInstancesOverriddenTemplatesPaths(),
|
||||
'templates_count' => $this->ComputeOverridesCount($aTemplatesDefinitions),
|
||||
'ui_version' => $oRegister->GetUIVersion(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getTemplate(): ?string
|
||||
{
|
||||
return 'itop-portal-base/portal/templates/data_collector/portal.html.twig';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function GetTemplatesDefinitions(): array
|
||||
{
|
||||
return $this->data['templates_definitions'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function GetInstancesOverriddenTemplates(): array
|
||||
{
|
||||
return $this->data['instances_overridden_templates'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function GetTemplatesCount(): array
|
||||
{
|
||||
return $this->data['templates_count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function GetUIVersion(): string
|
||||
{
|
||||
return $this->data['ui_version'];
|
||||
}
|
||||
|
||||
private function ComputeOverridesCount($aTemplatesDefinitions): array
|
||||
{
|
||||
$iCount = 0;
|
||||
$iOverridesCount = 0;
|
||||
$aExtensions = [];
|
||||
|
||||
foreach($aTemplatesDefinitions as $templates){
|
||||
foreach ($templates as $template) {
|
||||
|
||||
$aMatches = [];
|
||||
preg_match('#([\w-]+)/#', $template->GetPath(), $aMatches);
|
||||
|
||||
if(!in_array($aMatches[1], $aExtensions)){
|
||||
$aExtensions[] = $aMatches[1];
|
||||
}
|
||||
|
||||
$iCount++;
|
||||
if ($template->IsOverridden()) {
|
||||
$iOverridesCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
'count' => $iCount,
|
||||
'providers_count' => count($aTemplatesDefinitions),
|
||||
'overrides_count' => $iOverridesCount,
|
||||
'extensions_count' => count($aExtensions),
|
||||
'bricks_count' => count($this->oTemplatesProviderService->GetInstancesOverriddenTemplatesPaths()),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function GetInstanceDescriptionName(): string
|
||||
{
|
||||
return 'portal';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,9 +21,10 @@ namespace Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXml
|
||||
|
||||
use Combodo\iTop\Application\Branding;
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\Portal\Helper\UIExtensionsHelper;
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderInterface;
|
||||
use DOMFormatException;
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use utils;
|
||||
|
||||
@@ -74,6 +75,7 @@ class Basic extends AbstractConfiguration
|
||||
$aPortalConf = array(
|
||||
'properties' => array(
|
||||
'id' => $_ENV['PORTAL_ID'],
|
||||
'ui_version' => '2017',
|
||||
'name' => 'Page:DefaultTitle',
|
||||
'logo' => Branding::GetPortalLogoAbsoluteUrl(),
|
||||
'favicon' => Branding::GetPortalFavIconAbsoluteUrl(),
|
||||
@@ -85,7 +87,6 @@ class Basic extends AbstractConfiguration
|
||||
'templates' => array(
|
||||
'layout' => 'itop-portal-base/portal/templates/layout.html.twig',
|
||||
'home' => 'itop-portal-base/portal/templates/home/layout.html.twig',
|
||||
'bricks' => array(),
|
||||
),
|
||||
'urlmaker_class' => null,
|
||||
'triggers_query' => null,
|
||||
@@ -117,6 +118,7 @@ class Basic extends AbstractConfiguration
|
||||
{
|
||||
switch ($oPropertyNode->nodeName)
|
||||
{
|
||||
case 'ui_version':
|
||||
case 'name':
|
||||
case 'urlmaker_class':
|
||||
case 'triggers_query':
|
||||
@@ -186,19 +188,22 @@ class Basic extends AbstractConfiguration
|
||||
$aPortalConf['properties']['templates'][$sNodeId] = $oSubNode->GetText(null);
|
||||
break;
|
||||
default:
|
||||
// Try to accept the value as a global brick template, brick id format is "FQCN:page"
|
||||
[$sBrickFQCN, $sPage] = explode(':', $sNodeId);
|
||||
if (utils::IsNotNullOrEmptyString($sBrickFQCN) && utils::IsNotNullOrEmptyString($sPage))
|
||||
{
|
||||
$aPortalConf['properties']['templates']['bricks'][$sBrickFQCN][$sPage] = $oSubNode->GetText(null);
|
||||
break;
|
||||
$aMatches = [];
|
||||
// allowed format is: <class implementing TemplatesProviderInterface>:<template_id>
|
||||
if(preg_match('#([\w\\\d_]+):(\w+)#', $sNodeId, $aMatches)){
|
||||
try{
|
||||
$oClass = new ReflectionClass($aMatches[1]);
|
||||
if($oClass->implementsInterface(TemplatesProviderInterface::class)){
|
||||
$aPortalConf['properties']['templates'][$aMatches[1]][$aMatches[2]] = $oSubNode->GetText(null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(Exception){}
|
||||
}
|
||||
|
||||
throw new DOMFormatException(
|
||||
'Value "'.$sNodeId.'" is not handled for template[@id]',
|
||||
'Template ID "'.$sNodeId.'" is not handled in module design templates property',
|
||||
null, null, $oSubNode
|
||||
);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -100,9 +100,9 @@ class ApplicationHelper
|
||||
try
|
||||
{
|
||||
// Allowed profiles
|
||||
if ($oBrick->GetAllowedProfilesOql() !== null && $oBrick->GetAllowedProfilesOql() !== '')
|
||||
if (utils::IsNotNullOrEmptyString($oBrick->GetAllowedProfilesOql()))
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL($oBrick->GetAllowedProfilesOql());
|
||||
$oSearch = DBObjectSearch::FromOQL_AllData($oBrick->GetAllowedProfilesOql());
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
while ($oProfile = $oSet->Fetch())
|
||||
{
|
||||
@@ -111,9 +111,9 @@ class ApplicationHelper
|
||||
}
|
||||
|
||||
// Denied profiles
|
||||
if ($oBrick->GetDeniedProfilesOql() !== null && $oBrick->GetDeniedProfilesOql() !== '')
|
||||
if (utils::IsNotNullOrEmptyString($oBrick->GetDeniedProfilesOql()))
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL($oBrick->GetDeniedProfilesOql());
|
||||
$oSearch = DBObjectSearch::FromOQL_AllData($oBrick->GetDeniedProfilesOql());
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
while ($oProfile = $oSet->Fetch())
|
||||
{
|
||||
|
||||
@@ -124,17 +124,15 @@ class ObjectFormHandlerHelper
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function HandleForm(Request $oRequest, $sMode, $sObjectClass, $sObjectId = null, $aFormProperties = null)
|
||||
public function HandleForm(Request $oRequest, $sMode, $sObjectClass, $sObjectId = null, array $aFormProperties = null)
|
||||
{
|
||||
$aFormData = array();
|
||||
$sOperation = $this->oRequestManipulator->ReadParam('operation', '');
|
||||
$bModal = ($oRequest->isXmlHttpRequest() && empty($sOperation));
|
||||
|
||||
// - Retrieve form properties
|
||||
if ($aFormProperties === null)
|
||||
{
|
||||
$aFormProperties = ApplicationHelper::GetLoadedFormFromClass($this->aCombodoPortalInstanceConf['forms'], $sObjectClass, $sMode);
|
||||
}
|
||||
$aFormProperties = $aFormProperties ?? ApplicationHelper::GetLoadedFormFromClass($this->aCombodoPortalInstanceConf['forms'], $sObjectClass, $sMode);
|
||||
|
||||
// - Create and
|
||||
if (empty($sOperation))
|
||||
{
|
||||
@@ -281,7 +279,8 @@ class ObjectFormHandlerHelper
|
||||
->SetActionRulesToken($sActionRulesToken)
|
||||
->SetRenderer($oFormRenderer)
|
||||
->SetFormProperties($aFormProperties);
|
||||
|
||||
$oFormManager->PrepareFormAndHTMLDocument();
|
||||
$oFormManager->PrepareFields();
|
||||
$oFormManager->Build();
|
||||
$aFormData['hidden_fields'] = $oFormManager->GetHiddenFieldsId();
|
||||
// Check the number of editable fields
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Service\TemplatesProvider;
|
||||
|
||||
/**
|
||||
* Template definition DTO.
|
||||
*
|
||||
* Describes a template.
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Service\TemplatesProvider
|
||||
* @since 3.2.1
|
||||
*/
|
||||
class TemplateDefinitionDto
|
||||
{
|
||||
/**
|
||||
* Create a new template definition instance.
|
||||
*
|
||||
* @param string $sTemplateId template identifier
|
||||
* @param string $sPath template path
|
||||
* @param bool $isOverridable flag set when the template is overridable
|
||||
* @param string|null $sAlias template alias
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto
|
||||
*/
|
||||
public static function Create(string $sTemplateId, string $sPath, bool $isOverridable = true, ?string $sAlias = null): TemplateDefinitionDto
|
||||
{
|
||||
return new TemplateDefinitionDto($sTemplateId, $sPath, $isOverridable, $sAlias);
|
||||
}
|
||||
|
||||
/** @var bool $bIsOverridden flag set when overriding a template */
|
||||
private bool $bIsOverridden = false;
|
||||
|
||||
/** @var string|null $sInitialValue Initial template value */
|
||||
private ?string $sInitialValue;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $sId template identifier
|
||||
* @param string|null $sPath template path
|
||||
* @param bool|null $bIsOverridable flag set when the template is overridable
|
||||
* @param string|null $sAlias template alias
|
||||
*/
|
||||
private function __construct(
|
||||
private readonly string $sId,
|
||||
private ?string $sPath = null,
|
||||
private readonly ?bool $bIsOverridable = false,
|
||||
private readonly ?string $sAlias = null,
|
||||
)
|
||||
{
|
||||
// save overridable values
|
||||
$this->sInitialValue = $sPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the template identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetId(): string
|
||||
{
|
||||
return $this->sId !== null ? $this->sId : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the template path.
|
||||
*
|
||||
* @param bool $bInitialValue Return the initial value instead of the overridden one.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetPath(bool $bInitialValue = false): string
|
||||
{
|
||||
if($bInitialValue){
|
||||
return $this->sInitialValue !== null ? $this->sInitialValue : '';
|
||||
}
|
||||
|
||||
return $this->sPath !== null ? $this->sPath : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the overridable state.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsOverridable(): bool
|
||||
{
|
||||
return $this->bIsOverridable !== null ? $this->bIsOverridable : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the template alias.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetAlias(): string
|
||||
{
|
||||
return $this->sAlias !== null ? $this->sAlias : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Override a template.
|
||||
*
|
||||
* @param string $sPath template path
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function OverrideTemplatePath(string $sPath): TemplateDefinitionDto
|
||||
{
|
||||
if ($this->IsOverridable() && $sPath !== $this->sPath) {
|
||||
$this->sPath = $sPath;
|
||||
$this->bIsOverridden = true;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the overridden flag.
|
||||
*
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function IsOverridden(): bool
|
||||
{
|
||||
return $this->bIsOverridden;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Service\TemplatesProvider;
|
||||
|
||||
/**
|
||||
* Template provider interface.
|
||||
*
|
||||
* This interface is used to register templates in the templates provider service.
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Service\TemplatesProvider
|
||||
* @since 3.2.1
|
||||
*/
|
||||
interface TemplatesProviderInterface
|
||||
{
|
||||
/**
|
||||
* @param \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister $oTemplatesRegister
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void;
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Service\TemplatesProvider;
|
||||
|
||||
use Combodo\iTop\Portal\Brick\AbstractBrick;
|
||||
use Combodo\iTop\Portal\Controller\AbstractController;
|
||||
use Combodo\iTop\Portal\Controller\DefaultController;
|
||||
use Combodo\iTop\Service\InterfaceDiscovery\InterfaceDiscovery;
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
/**
|
||||
* Service responsible for managing portal templates.
|
||||
*
|
||||
* The templates provider interface allows any provider to register templates for the portal.
|
||||
* The templates registered may be overridden by the portal configuration and for a specific instance (brick instance).
|
||||
*
|
||||
* Templates are defined in module_design properties section, under the templates key.
|
||||
* The layouts for home and default layout still allow to be defined in the portal configuration.
|
||||
* Otherwise, the templates for providers are defined as follows:
|
||||
* <template id="{class implementing TemplatesProviderInterface}:{template_id}">{path to template}</template>
|
||||
*
|
||||
* Templates are store in register object.
|
||||
* This register is cached.
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Service\TemplatesProvider
|
||||
* @since 3.2.1
|
||||
*/
|
||||
class TemplatesProviderService
|
||||
{
|
||||
/** @var \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister templates register */
|
||||
protected TemplatesRegister $oTemplateRegister;
|
||||
|
||||
/** @var array instances overridden templates paths */
|
||||
protected array $aInstancesOverriddenTemplatesPaths = [];
|
||||
|
||||
/**
|
||||
* TemplatesService constructor.
|
||||
*
|
||||
* @param array $aCombodoPortalInstanceConf configuration for the current portal instance
|
||||
* @param \Symfony\Contracts\Cache\CacheInterface $templatesCachePool cache pool for templates
|
||||
*
|
||||
* @throws \Psr\Cache\InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $aCombodoPortalInstanceConf, CacheInterface $templatesCachePool)
|
||||
{
|
||||
// template register cache
|
||||
$this->oTemplateRegister = $templatesCachePool->get('portal_templates_register', function (ItemInterface $item) use ($aCombodoPortalInstanceConf): TemplatesRegister {
|
||||
|
||||
// initialize register
|
||||
return $this->InitializeTemplatesRegister($aCombodoPortalInstanceConf);
|
||||
});
|
||||
|
||||
// brick should be able to give the templates with GetTileTemplate, GetPageTemplate (so it needs to know the service)
|
||||
// a more elegant way would be to use a controller to achieve this
|
||||
AbstractBrick::SetTemplatesProviderService($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize templates register.
|
||||
* Store the UI version defined in portal instance configuration.
|
||||
* Iterate throw TemplatesProviderInterface implementations to register templates.
|
||||
* Override templates with portal instance configuration.
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
private function InitializeTemplatesRegister(array $aCombodoPortalInstanceConf): TemplatesRegister
|
||||
{
|
||||
// UI version
|
||||
$sUIVersion = 'unset';
|
||||
if (isset($aCombodoPortalInstanceConf['properties']['ui_version'])) {
|
||||
$sUIVersion = $aCombodoPortalInstanceConf['properties']['ui_version'];
|
||||
}
|
||||
|
||||
// create template register
|
||||
$oTemplateRegister = new TemplatesRegister($sUIVersion);
|
||||
|
||||
// search for templates providers
|
||||
// only non-abstract classes are discovered.
|
||||
// classes implementing the interface needs to call the parent to ensure abstracted class levels templates are registered.
|
||||
$oTemplatesProviders = InterfaceDiscovery::GetInstance()->FindItopClasses(TemplatesProviderInterface::class);
|
||||
|
||||
// register default templates...
|
||||
foreach ($oTemplatesProviders as $oTemplateProvider) {
|
||||
$oTemplateProvider::RegisterTemplates($oTemplateRegister);
|
||||
}
|
||||
|
||||
// overrides the templates declared in portal configuration...
|
||||
foreach ($aCombodoPortalInstanceConf['properties']['templates'] as $sKey => $oValue) {
|
||||
|
||||
switch ($sKey) {
|
||||
case 'layout': // legacy configuration
|
||||
$oTemplateDefinition = $oTemplateRegister->GetTemplateDefinition(AbstractController::class, 'page');
|
||||
$oTemplateDefinition->OverrideTemplatePath($oValue);
|
||||
break;
|
||||
case 'home': // legacy configuration
|
||||
$oTemplateDefinition = $oTemplateRegister->GetTemplateDefinition(DefaultController::class, 'home');
|
||||
$oTemplateDefinition->OverrideTemplatePath($oValue);
|
||||
break;
|
||||
default:
|
||||
if (is_array($oValue)) {
|
||||
foreach ($oValue as $sTemplateId => $sTemplatePath) {
|
||||
$oTemplateDefinition = $oTemplateRegister->GetTemplateDefinition($sKey, $sTemplateId);
|
||||
$oTemplateDefinition?->OverrideTemplatePath($sTemplatePath);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $oTemplateRegister;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override an object instance template path.
|
||||
*
|
||||
* @param object $oObject object instance
|
||||
* @param string $sTemplateId the template id
|
||||
* @param string $sTemplatePath the template path
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function OverrideInstanceTemplatePath(object $oObject, string $sTemplateId, string $sTemplatePath): TemplatesProviderService
|
||||
{
|
||||
// get object UUID
|
||||
$sObjectId = spl_object_id($oObject);
|
||||
|
||||
// initialize overridden object templates and information
|
||||
if (array_key_exists($sObjectId, $this->aInstancesOverriddenTemplatesPaths) === false) {
|
||||
|
||||
$this->aInstancesOverriddenTemplatesPaths[$sObjectId] = [];
|
||||
$this->aInstancesOverriddenTemplatesPaths[$sObjectId]['templates'] = [];
|
||||
|
||||
// friendly id
|
||||
$sId = $sObjectId;
|
||||
if ($oObject instanceof AbstractBrick) {
|
||||
$sId = $oObject->GetId();
|
||||
}
|
||||
|
||||
// store object information
|
||||
$this->aInstancesOverriddenTemplatesPaths[$sObjectId]['info'] = [
|
||||
'class' => get_class($oObject),
|
||||
'id' => $sId,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
// store template path
|
||||
$this->aInstancesOverriddenTemplatesPaths[$sObjectId]['templates'][$sTemplateId] = $sTemplatePath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a template path.
|
||||
*
|
||||
* @param string $sProviderClass the templates provider class
|
||||
* @param string $sTemplateId the template id
|
||||
* @param bool $bIsInitial
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \ReflectionException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetTemplatePath(string $sProviderClass, string $sTemplateId, bool $bIsInitial = false): ?string
|
||||
{
|
||||
if ($this->oTemplateRegister->IsProviderExists($sProviderClass)) {
|
||||
|
||||
// I
|
||||
// SERVICE DECLARATION
|
||||
// the provider class is known by service
|
||||
// the class register its templates with service
|
||||
|
||||
// search for the template definition
|
||||
$oTemplateDefinition = $this->oTemplateRegister->GetTemplateDefinition($sProviderClass, $sTemplateId);
|
||||
|
||||
// return the template path
|
||||
return $oTemplateDefinition?->GetPath($bIsInitial);
|
||||
|
||||
} else {
|
||||
|
||||
// II
|
||||
// LEGACY DECLARATION
|
||||
// the provider class is unknown by service
|
||||
// the class register its templates with legacy constants
|
||||
|
||||
return $this->GetLegacyTemplatePath($sProviderClass, $sTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sProviderClass
|
||||
* @param string $sTemplateId
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
private function GetLegacyTemplatePath(string $sProviderClass, string $sTemplateId): ?string
|
||||
{
|
||||
// reflexion for class
|
||||
$oReflexion = new ReflectionClass($sProviderClass);
|
||||
|
||||
// class defined constants
|
||||
$aClassDefinedConstants = array_diff($oReflexion->getConstants(), $oReflexion->getParentClass()->getConstants());
|
||||
|
||||
// return the constant if exists
|
||||
return match ($sTemplateId) {
|
||||
'page' => array_key_exists('DEFAULT_PAGE_TEMPLATE_PATH', $aClassDefinedConstants) ? $oReflexion->getConstant('DEFAULT_PAGE_TEMPLATE_PATH') : null,
|
||||
'tile' => array_key_exists('DEFAULT_TILE_TEMPLATE_PATH', $aClassDefinedConstants) ? $oReflexion->getConstant('DEFAULT_TILE_TEMPLATE_PATH') : null,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a provider instance template path.
|
||||
*
|
||||
* @param object $oObject
|
||||
* @param string $sTemplateId
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
*/
|
||||
public function GetProviderInstanceTemplatePath(object $oObject, string $sTemplateId): ?string
|
||||
{
|
||||
// object UUID
|
||||
$sObjectId = spl_object_id($oObject);
|
||||
|
||||
// get the provider instance class name
|
||||
$sCurrentClass = get_class($oObject);
|
||||
|
||||
// get template definition if it exists
|
||||
$oTemplateDefinition = $this->oTemplateRegister->GetTemplateDefinition($sCurrentClass, $sTemplateId);
|
||||
$sId = $oTemplateDefinition != null ? $oTemplateDefinition->GetId() : $sTemplateId;
|
||||
|
||||
// if instance override exists, return it
|
||||
if (array_key_exists($sObjectId, $this->aInstancesOverriddenTemplatesPaths)
|
||||
&& array_key_exists($sId, $this->aInstancesOverriddenTemplatesPaths[$sObjectId]['templates'])) {
|
||||
return $this->aInstancesOverriddenTemplatesPaths[$sObjectId]['templates'][$sId];
|
||||
}
|
||||
|
||||
// now, we search in class hierarchy for a template
|
||||
do {
|
||||
$oParent = null;
|
||||
try {
|
||||
|
||||
// get template path for current class
|
||||
$sTemplate = $this->GetTemplatePath($sCurrentClass, $sTemplateId);
|
||||
if ($sTemplate !== null) {
|
||||
return $sTemplate;
|
||||
}
|
||||
|
||||
// no template defined at this level, try parent class
|
||||
$oReflexion = new ReflectionClass($sCurrentClass);
|
||||
$oParent = $oReflexion->getParentClass();
|
||||
if ($oParent) {
|
||||
$sCurrentClass = $oReflexion->getParentClass()->getName();
|
||||
}
|
||||
}
|
||||
catch (Exception) {
|
||||
}
|
||||
|
||||
} while ($oParent); // continue while parent class exists
|
||||
|
||||
return null; // no template found
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the register.
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister
|
||||
*/
|
||||
public function GetRegister(): TemplatesRegister
|
||||
{
|
||||
return $this->oTemplateRegister;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return instances overridden templates paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetInstancesOverriddenTemplatesPaths(): array
|
||||
{
|
||||
return $this->aInstancesOverriddenTemplatesPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if brick template path is overridden.
|
||||
*
|
||||
* @param object $oObject object instance
|
||||
* @param string $sTemplateId template identifier
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function HasInstanceOverriddenTemplate(object $oObject, string $sTemplateId): bool
|
||||
{
|
||||
// object UUID
|
||||
$sObjectId = spl_object_id($oObject);
|
||||
|
||||
return (array_key_exists($sObjectId, $this->aInstancesOverriddenTemplatesPaths)
|
||||
&& array_key_exists($sTemplateId, $this->aInstancesOverriddenTemplatesPaths[$sObjectId]['templates']));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Service\TemplatesProvider;
|
||||
|
||||
/**
|
||||
* Template register.
|
||||
*
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Service\TemplatesProvider
|
||||
* @since 3.2.1
|
||||
*/
|
||||
class TemplatesRegister
|
||||
{
|
||||
|
||||
/** @var array Templates definitions (possibly altered by portal configuration) */
|
||||
private array $aTemplatesDefinitions = [];
|
||||
|
||||
|
||||
public function __construct(private string $sTemplateUIVersion = 'unset')
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetUIVersion(): string
|
||||
{
|
||||
return $this->sTemplateUIVersion;
|
||||
}
|
||||
|
||||
public function IsProviderExists(string $sProviderId): bool
|
||||
{
|
||||
return array_key_exists($sProviderId, $this->aTemplatesDefinitions);
|
||||
}
|
||||
|
||||
public function IsTemplateExists(string $sProviderId, string $sTemplateId): bool
|
||||
{
|
||||
return array_key_exists($sProviderId, $this->aTemplatesDefinitions) && array_key_exists($sTemplateId, $this->aTemplatesDefinitions[$sProviderId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register templates.
|
||||
*
|
||||
* @param string $sProviderId the templates provider id
|
||||
* @param \Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto ...$aTemplatesDefinitions
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesRegister
|
||||
*/
|
||||
public function RegisterTemplates(string $sProviderId, TemplateDefinitionDto...$aTemplatesDefinitions): TemplatesRegister
|
||||
{
|
||||
// prevent child classes to erase parent templates
|
||||
if (array_key_exists($sProviderId, $this->aTemplatesDefinitions)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
// register templates...
|
||||
$this->aTemplatesDefinitions[$sProviderId] = [];
|
||||
foreach ($aTemplatesDefinitions as $oTemplateDefinition) {
|
||||
$this->aTemplatesDefinitions[$sProviderId][$oTemplateDefinition->GetId()] = $oTemplateDefinition;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a template definition.
|
||||
*
|
||||
* @param string $sProviderId the templates provider id
|
||||
* @param string $sTemplateId the template id
|
||||
*
|
||||
* @return TemplateDefinitionDto|null
|
||||
*/
|
||||
public function GetTemplateDefinition(string $sProviderId, string $sTemplateId): ?TemplateDefinitionDto
|
||||
{
|
||||
// retrieve template path
|
||||
if (array_key_exists($sProviderId, $this->aTemplatesDefinitions)) {
|
||||
|
||||
// search in template definitions
|
||||
if (array_key_exists($sTemplateId, $this->aTemplatesDefinitions[$sProviderId])) {
|
||||
return $this->aTemplatesDefinitions[$sProviderId][$sTemplateId];
|
||||
}
|
||||
|
||||
// search in aliases
|
||||
foreach ($this->aTemplatesDefinitions[$sProviderId] as $item) {
|
||||
/** @var \Combodo\iTop\Portal\Service\TemplatesProvider\TemplateDefinitionDto $item */
|
||||
if ($item->GetAlias() === $sTemplateId) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sProviderId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetProviderTemplatesIds(string $sProviderId): array
|
||||
{
|
||||
return array_map(fn($oTemplateDefinition) => $oTemplateDefinition->GetId(), $this->aTemplatesDefinitions[$sProviderId] ?? ['tile', 'page']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return templates definitions.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetTemplatesDefinitions(): array
|
||||
{
|
||||
return $this->aTemplatesDefinitions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2023 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Twig;
|
||||
|
||||
use Combodo\iTop\Portal\Service\TemplatesProvider\TemplatesProviderService;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* New Twig function useful for extending or including template handled by templates provider service.
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Twig
|
||||
* @since 3.2.1
|
||||
*/
|
||||
class TemplatesTwigExtension extends AbstractExtension
|
||||
{
|
||||
const DEFAULT_PROVIDER_CLASS = 'Combodo\\iTop\\Portal\\Controller\\AbstractController';
|
||||
|
||||
public function __construct(private readonly TemplatesProviderService $oTemplatesService)
|
||||
{
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('template', [$this, 'GetTemplate'], ['id' => null, 'provider' => null, 'provider_instance' => null]),
|
||||
new TwigFunction('template_initial', [$this, 'GetInitialTemplate'], ['id' => null, 'provider' => null]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the path of the desired template (maybe overridden by configuration or by instance).
|
||||
*
|
||||
* @param string $sId template identifier
|
||||
* @param string $sProviderClass provider class FQN
|
||||
* @param object|null $oProviderInstance the provider instance
|
||||
*
|
||||
* @return string the template path
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function GetTemplate(string $sId, string $sProviderClass = self::DEFAULT_PROVIDER_CLASS, object $oProviderInstance = null): string
|
||||
{
|
||||
if ($oProviderInstance === null) {
|
||||
return $this->oTemplatesService->GetTemplatePath($sProviderClass, $sId);
|
||||
} else {
|
||||
return $this->oTemplatesService->GetProviderInstanceTemplatePath($oProviderInstance, $sId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the initial path of the desired template (hardcoded).
|
||||
*
|
||||
* @param string $sId template identifier
|
||||
* @param string $sProviderClass provider class FQN
|
||||
*
|
||||
* @return string the template path
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function GetInitialTemplate(string $sId, string $sProviderClass = self::DEFAULT_PROVIDER_CLASS): string
|
||||
{
|
||||
return $this->oTemplatesService->GetTemplatePath($sProviderClass, $sId, true);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/aggregate-page/layout.html.twig #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\AbstractBrick') %}
|
||||
|
||||
{% block pPageBodyClass %}{{ parent() }} page_aggregate_page_brick home{% endblock %}
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
{# itop-portal-base/portal/templates/bricks/browse/layout.html.twig #}
|
||||
{# Browse brick base layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\AbstractBrick') %}
|
||||
|
||||
{% block pPageBodyClass %}{{ parent() }} page_browse_brick page_browse_brick_as_{{ sBrowseMode }}{% endblock %}
|
||||
|
||||
{% block pPageReadyScripts %}
|
||||
{{ parent() }}
|
||||
{% include 'itop-portal-base/portal/templates/helpers/tagset_clic_handler.js.twig' %}
|
||||
{% include template('tagset_clic_handler_js') %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig #}
|
||||
{# Browse brick list mode layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/browse/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick', oBrick) %}
|
||||
|
||||
{% block bBrowseMainContent%}
|
||||
<table id="brick-content-table" class="object-list table table-striped table-bordered responsive" cellspacing="0" width="100%">
|
||||
@@ -11,8 +9,8 @@
|
||||
|
||||
{% block pPageLiveScripts %}
|
||||
{{ parent() }}
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
<script type="text/javascript">
|
||||
var sBrowseMode = '{{ sBrowseMode }}';
|
||||
var sDataLoading = '{{ sDataLoading }}';
|
||||
var oLevelsProperties = {{ aLevelsProperties|raw }};
|
||||
@@ -22,8 +20,8 @@
|
||||
var iSearchThrottle = 600;
|
||||
var oKeyTimeout;
|
||||
var aKeyTimeoutFilteredKeys = [9, 16, 17, 18, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40]; // Tab, Shift, Ctrl, Alt, Pause, Esc, Page Up/Down, Home, End, Left/Up/Right/Down arrows
|
||||
|
||||
// Show a loader inside the table
|
||||
|
||||
// Show a loader inside the table
|
||||
var showTableLoader = function(oElem)
|
||||
{
|
||||
oElem.children('tbody').html('<tr><td class="datatables_overlay" colspan="100">' + $('#page_overlay').html() + '</td></tr>');
|
||||
@@ -32,8 +30,8 @@
|
||||
var getColumnsDefinition = function()
|
||||
{
|
||||
var aColumnsDefinition = [];
|
||||
|
||||
for(sKey in oLevelsProperties)
|
||||
|
||||
for (sKey in oLevelsProperties)
|
||||
{
|
||||
// Level main column
|
||||
aColumnsDefinition.push({
|
||||
@@ -189,8 +187,8 @@
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Level's fields columns
|
||||
|
||||
// Level's fields columns
|
||||
if(oLevelsProperties[sKey].fields !== undefined)
|
||||
{
|
||||
for(var i in oLevelsProperties[sKey].fields)
|
||||
@@ -231,15 +229,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aColumnsDefinition;
|
||||
|
||||
return aColumnsDefinition;
|
||||
};
|
||||
|
||||
$(document).ready(function()
|
||||
|
||||
$(document).ready(function ()
|
||||
{
|
||||
showTableLoader($('#brick-content-table'));
|
||||
|
||||
// Note : Those options should be externalized in an library so we can use them on any DataTables for the portal.
|
||||
|
||||
// Note : Those options should be externalized in an library so we can use them on any DataTables for the portal.
|
||||
// We would just have to override / complete the necessary elements
|
||||
oTable = $('#brick-content-table').DataTable({
|
||||
"language": {
|
||||
@@ -331,8 +329,8 @@
|
||||
// Note : The '.off()' call is to unbind event from DataTables that where triggered before we could intercept anything
|
||||
$('#brick-content-table_filter input').off().on('keyup', function(event){
|
||||
var me = this;
|
||||
|
||||
// We trigger the search only if those keys where not pressed
|
||||
|
||||
// We trigger the search only if those keys where not pressed
|
||||
if(aKeyTimeoutFilteredKeys.indexOf(event.which) < 0)
|
||||
{
|
||||
clearTimeout(oKeyTimeout);
|
||||
@@ -348,8 +346,8 @@
|
||||
showTableLoader($(this));
|
||||
}
|
||||
});
|
||||
|
||||
// Auto collapse item actions popup
|
||||
|
||||
// Auto collapse item actions popup
|
||||
$('body').on('click', function(){
|
||||
$('table .item-action-wrapper.collapse.in').collapse('hide');
|
||||
});
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/browse/mode_mosaic.html.twig #}
|
||||
{# Browse brick mosaic mode layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/browse/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick', oBrick) %}
|
||||
|
||||
{% block bBrowseMainContent %}
|
||||
<div id="brick_content_mosaic">
|
||||
@@ -21,7 +19,7 @@
|
||||
<div id="brick_mosaic_overlay">
|
||||
{% block bBrowseMosaicOverlay %}
|
||||
<div class="overlay_content">
|
||||
{% include 'itop-portal-base/portal/templates/helpers/loader.html.twig' %}
|
||||
{% include template('loader') %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/browse/mode_tree.html.twig #}
|
||||
{# Browse brick tree mode layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/browse/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick', oBrick) %}
|
||||
|
||||
{#
|
||||
Documentation :
|
||||
@@ -36,7 +34,7 @@
|
||||
</div>
|
||||
<div id="brick_tree_overlay">
|
||||
<div class="overlay_content">
|
||||
{% include 'itop-portal-base/portal/templates/helpers/loader.html.twig' %}
|
||||
{% include template('loader') %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
{# itop-portal-base/portal/templates/bricks/create/layout.html.twig #}
|
||||
{# Create brick base layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/modal/layout.html.twig' %}
|
||||
|
||||
{% block pModalTitle %}
|
||||
{{ sPageTitle|dict_s }}
|
||||
{% endblock %}
|
||||
|
||||
{% block pModalBody %}
|
||||
<p>{{ 'Brick:Portal:Create:ChooseType'|dict_s }}</p>
|
||||
<ul id="{{ sLeafClassesListId }}">
|
||||
{% for aLeafClass in aLeafClasses %}
|
||||
<li><a href="#" data-target-class="{{ aLeafClass.id }}">{{ aLeafClass.name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$('#{{ sLeafClassesListId }} a').off('click').on('click', function(oEvent){
|
||||
oEvent.preventDefault();
|
||||
|
||||
// Preparing target class url
|
||||
var sUrl = '{{ app['url_generator'].generate('p_object_create', {sObjectClass : '-sObjectClass-'})|raw }}';
|
||||
sUrl = sUrl.replace(/-sObjectClass-/, $(this).attr('data-target-class') );
|
||||
sUrl = CombodoGlobalToolbox.AddParameterToUrl(sUrl, 'ar_token', '{{ ar_token }}');
|
||||
|
||||
// Creating a new modal
|
||||
CombodoModal.OpenModal({
|
||||
base_modal: {
|
||||
usage: 'replace',
|
||||
selector: $(this).closest('.modal'),
|
||||
},
|
||||
content: {
|
||||
endpoint: sUrl,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block pModalFooter %}
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'Portal:Button:Cancel'|dict_s }}</button>
|
||||
{% endblock %}
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/layout.html.twig #}
|
||||
{# Brick base layout #}
|
||||
{% extends app['combodo.portal.instance.conf'].properties.templates.layout %}
|
||||
{% extends template('page') %}
|
||||
|
||||
{% block pPageTitle %}
|
||||
{# Overloading the default template's title to show the brick's title #}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/manage/layout-chart.html.twig #}
|
||||
{# Manage brick base layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/manage/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\ManageBrick', oBrick) %}
|
||||
|
||||
{% block pPageBodyClass %}{{ parent() }} page_manage_brick{% endblock %}
|
||||
|
||||
@@ -8,7 +6,7 @@
|
||||
{% block pMainContentHolder %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
{% include 'itop-portal-base/portal/templates/bricks/manage/mode-' ~ sDisplayMode ~ '.html.twig' with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
|
||||
{% include template(sDisplayMode, 'Combodo\\iTop\\Portal\\Brick\\ManageBrick', oBrick) with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig #}
|
||||
{# Manage brick base layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/manage/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\ManageBrick', oBrick) %}
|
||||
|
||||
{% block pPageBodyClass %}{{ parent() }} page_manage_brick{% endblock %}
|
||||
|
||||
@@ -23,25 +21,23 @@
|
||||
{% set iTableCount = 0 %}
|
||||
{% if aGroupingAreasData|length > 0 %}
|
||||
{% for aAreaData in aGroupingAreasData %}
|
||||
{% if aAreaData.iItemsCount > 0 %}
|
||||
{% set iTableCount = iTableCount + 1 %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading clearfix">
|
||||
<h3 class="panel-title" style="float: left;">{{ aAreaData.sTitle }}</h3>
|
||||
{% if bCanExport %}
|
||||
<a href="{{ app.url_generator.generate('p_manage_brick_excel_export_start', {'sBrickId': sBrickId, 'sGroupingTab': sGroupingTab, 'sGroupingArea': aAreaData.sId})|raw }}"
|
||||
id="btn_export_excel_for_{{ aAreaData.sId }}"
|
||||
data-toggle="modal" data-target="#modal-for-all">
|
||||
<span class="fas fa-download fa-lg" style="float: right;"
|
||||
data-tooltip-content="{{ 'ExcelExporter:ExportMenu'|dict_s }}"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table id="table-{{ aAreaData.sId }}" class="object-list table table-striped table-bordered responsive" width="100%"></table>
|
||||
</div>
|
||||
{% set iTableCount = iTableCount + 1 %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading clearfix">
|
||||
<h3 class="panel-title" style="float: left;">{{ aAreaData.sTitle }}</h3>
|
||||
{% if bCanExport %}
|
||||
<a href="{{ app.url_generator.generate('p_manage_brick_excel_export_start', {'sBrickId': sBrickId, 'sGroupingTab': sGroupingTab, 'sGroupingArea': aAreaData.sId})|raw }}"
|
||||
id="btn_export_excel_for_{{ aAreaData.sId }}"
|
||||
data-toggle="modal" data-target="#modal-for-all">
|
||||
<span class="fas fa-download fa-lg" style="float: right;"
|
||||
data-tooltip-content="{{ 'ExcelExporter:ExportMenu'|dict_s }}"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel-body">
|
||||
<table id="table-{{ aAreaData.sId }}" class="object-list table table-striped table-bordered responsive" width="100%"></table>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/manage/layout.html.twig #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\AbstractBrick') %}
|
||||
|
||||
{% block pMainHeaderTitle %}{{ oBrick.GetTitle()|dict_s }} {% if iCount >= 0 %} ({{ iCount }}){% endif %} {% endblock %}
|
||||
|
||||
@@ -9,7 +8,7 @@
|
||||
{% for sDisplay in oBrick.GetAvailablesDisplayModes %}
|
||||
<a href="{{ app.url_generator.generate('p_manage_brick_display_as', {'sBrickId': sBrickId, 'sDisplayMode': sDisplay}) }}{% if app['combodo.portal.instance.routes'][oBrick.GetRouteName]['hash'] is defined %}#{{ app['combodo.portal.instance.routes'][oBrick.GetRouteName]['hash'] }}{% endif %}"
|
||||
id="btn_tab_for_{{ sDisplay }}"
|
||||
class="btn btn-default {% if sDisplay == oBrick.GetPresentationDataForTileMode(sDisplayMode).layoutDisplayMode %}active{% endif %}">
|
||||
class="btn btn-default {% if sDisplay == sDisplayMode %}active{% endif %}">
|
||||
{{ ('Brick:Portal:Manage:DisplayMode:' ~ sDisplay)|dict_s }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
@@ -19,5 +18,5 @@
|
||||
|
||||
{% block pPageReadyScripts %}
|
||||
{{ parent() }}
|
||||
{% include 'itop-portal-base/portal/templates/helpers/tagset_clic_handler.js.twig' %}
|
||||
{% include template('tagset_clic_handler_js') %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
id="brick-{{ oBrick.GetId }}"
|
||||
data-brick-id="{{ oBrick.GetId }}">
|
||||
<div>
|
||||
<div class="tile_title"><span class="icon fas fa-{{ oBrick.GetDecorationCssClass }}"></span> {{ oBrick.GetTitle()|dict_s }}
|
||||
<div class="tile_title"><span class="icon {{ oBrick.GetDecorationClassHome }}"></span> {{ oBrick.GetTitle()|dict_s }}
|
||||
({{ iCount }})</span> </div>
|
||||
{% include 'itop-portal-base/portal/templates/bricks/manage/mode-' ~ oBrick.GetTileMode ~ '.html.twig' with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
|
||||
{% include template(oBrick.GetTileMode, 'Combodo\\iTop\\Portal\\Brick\\ManageBrick', oBrick) with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
|
||||
</div>
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
data-brick-id="{{ oBrick.GetId }}">
|
||||
<div style="background-color:#fff;padding:0.25em;">
|
||||
<div class="tile_title">
|
||||
<span class="icon fas fa-signal fa-rotate-270"></span> {{ oBrick.GetTitle()|dict_s }}
|
||||
<span class="icon {{ oBrick.GetDecorationClassHome }}"></span> {{ oBrick.GetTitle()|dict_s }}
|
||||
({{ iCount }})</span> </div>
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/object/layout.html.twig #}
|
||||
{# Object brick base layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
|
||||
{% extends template('page') %}
|
||||
|
||||
{% block pPageBodyClass %}{{ parent() }} page_object_brick page_object_brick_as_{{ sMode }}{% endblock %}
|
||||
|
||||
@@ -27,7 +25,7 @@
|
||||
{% block pMainContentHolder%}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
{% include 'itop-portal-base/portal/templates/bricks/object/mode_' ~ sMode ~ '.html.twig' %}
|
||||
{% include template(sMode, 'Combodo\\iTop\\Portal\\Controller\\ObjectController') %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/object/modal.html.twig #}
|
||||
{# Object brick base layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/modal/layout.html.twig' %}
|
||||
{% extends template('modal') %}
|
||||
|
||||
{% block pModalTitle %}
|
||||
{% if form.title_clipboard_text is defined %}
|
||||
@@ -19,5 +17,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block pModalBody %}
|
||||
{% include 'itop-portal-base/portal/templates/bricks/object/mode_' ~ sMode ~ '.html.twig' with {tIsModal: true} %}
|
||||
{% include template(sMode, 'Combodo\\iTop\\Portal\\Controller\\ObjectController') with {tIsModal: true} %}
|
||||
{% endblock %}
|
||||
@@ -1,5 +1,3 @@
|
||||
{# itop-portal-base/portal/templates/bricks/object/mode_apply_stimulus.html.twig #}
|
||||
{# Object brick apply stimulus layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/object/mode_create.html.twig' %}
|
||||
{% extends template('mode_create', 'Combodo\\iTop\\Portal\\Controller\\ObjectController') %}
|
||||
|
||||
{# This layout is exactly the same as the mode_create.html.twig, we duplicated it in case we need to have some subtle differences #}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
{# Misc. buttons #}
|
||||
{% if form.buttons is defined and (form.buttons.actions is defined or form.buttons.links is defined) %}
|
||||
<div class="form_btn_misc">
|
||||
{% include 'itop-portal-base/portal/templates/bricks/object/plugins_buttons.html.twig' with {'aButtons': form.buttons} %}
|
||||
{% include template('plugins_buttons', 'Combodo\\iTop\\Portal\\Controller\\ObjectController') with {'aButtons': form.buttons} %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{# Transition buttons #}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
{# itop-portal-base/portal/templates/bricks/object/mode_create.html.twig #}
|
||||
{# Object brick edit layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/object/mode_create.html.twig' %}
|
||||
{% extends template('mode_create', 'Combodo\\iTop\\Portal\\Controller\\ObjectController') %}
|
||||
|
||||
{# This layout is exactly the same as the mode_create.html.twig, we duplicated it in case we need to have some subtle differences #}
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/object/mode_view.html.twig #}
|
||||
{# Object brick view layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/object/mode_create.html.twig' %}
|
||||
{% extends template('mode_create', 'Combodo\\iTop\\Portal\\Controller\\ObjectController') %}
|
||||
|
||||
{# This layout is exactly the same as the mode_create.html.twig, we duplicated it in case we need to have some subtle differences #}
|
||||
|
||||
@@ -8,7 +6,7 @@
|
||||
{# Misc. buttons #}
|
||||
{% if form.buttons is defined and (form.buttons.actions is defined or form.buttons.links is defined) %}
|
||||
<div class="form_btn_misc">
|
||||
{% include 'itop-portal-base/portal/templates/bricks/object/plugins_buttons.html.twig' with {'aButtons': form.buttons} %}
|
||||
{% include template('plugins_buttons', 'Combodo\\iTop\\Portal\\Controller\\ObjectController') with {'aButtons': form.buttons} %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{# itop-portal-base/portal/templates/bricks/user-profile/layout.html.twig #}
|
||||
{# User profile brick base layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
|
||||
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\AbstractBrick') %}
|
||||
|
||||
{% if sTab == "" %}
|
||||
{% set sTab = "user-info" %}
|
||||
@@ -57,7 +55,7 @@
|
||||
{% set oContactForm = forms.contact %}
|
||||
{% set oPreferencesForm = forms.preferences %}
|
||||
{% set oPasswordForm = forms.password %}
|
||||
{% include 'itop-portal-base/portal/templates/bricks/user-profile/user_info.html.twig' %}
|
||||
{% include template('user_info', 'Combodo\\iTop\\Portal\\Brick\\UserProfileBrick') %}
|
||||
{% else %}
|
||||
<div id="user-profile-wrapper">
|
||||
<div class="row">
|
||||
@@ -82,7 +80,7 @@
|
||||
{% set oContactForm = forms.contact %}
|
||||
{% set oPreferencesForm = forms.preferences %}
|
||||
{% set oPasswordForm = forms.password %}
|
||||
{% include 'itop-portal-base/portal/templates/bricks/user-profile/user_info.ready.js.twig' %}
|
||||
{% include template('user_info_ready_js', 'Combodo\\iTop\\Portal\\Brick\\UserProfileBrick') %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
|
||||
|
||||
{% block toolbar %}
|
||||
|
||||
{# toolbar text & icon #}
|
||||
{% set icon %}
|
||||
<span class="icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M192 64l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32zM82.7 207c-15.3 8.8-20.5 28.4-11.7 43.7l32 55.4c8.8 15.3 28.4 20.5 43.7 11.7l55.4-32c15.3-8.8 20.5-28.4 11.7-43.7l-32-55.4c-8.8-15.3-28.4-20.5-43.7-11.7L82.7 207zM288 192c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0zm64 160c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0zM160 384l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32zM32 352c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0z"/></svg>
|
||||
</span>
|
||||
<span class="sf-toolbar-label">Portal{% if collector.GetTemplatesCount.overrides_count > 0 %} <span style=" color: var(--sf-toolbar-yellow-600);"> Overrides</span>{% endif %}</span>
|
||||
{% endset %}
|
||||
|
||||
{# toolbar panel #}
|
||||
{% set text %}
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Templates registered</b><span class="sf-toolbar-status">{{ collector.GetTemplatesCount.count }}</span>
|
||||
</div>
|
||||
{% if collector.GetTemplatesCount.overrides_count %}
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Templates overridden</b><span class="sf-toolbar-status">{{ collector.GetTemplatesCount.overrides_count }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endset %}
|
||||
|
||||
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ parent() }}
|
||||
|
||||
<style>
|
||||
.overridden_value {
|
||||
color: var(--color-link);
|
||||
}
|
||||
.old_value {
|
||||
color: grey;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block menu %}
|
||||
|
||||
{# menu #}
|
||||
<span class="label label-status-none">
|
||||
<span class="icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M192 64l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32zM82.7 207c-15.3 8.8-20.5 28.4-11.7 43.7l32 55.4c8.8 15.3 28.4 20.5 43.7 11.7l55.4-32c15.3-8.8 20.5-28.4 11.7-43.7l-32-55.4c-8.8-15.3-28.4-20.5-43.7-11.7L82.7 207zM288 192c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0zm64 160c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0zM160 384l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32zM32 352c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0z"/></svg>
|
||||
</span>
|
||||
<strong>Portal</strong>
|
||||
<span class="count">
|
||||
{{ collector.GetTemplatesCount.count }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
|
||||
{# title #}
|
||||
<h2>Templates</h2>
|
||||
|
||||
{# metrics #}
|
||||
<div class="metrics">
|
||||
{# ui version #}
|
||||
<div class="metric">
|
||||
<span class="value">{{ collector.GetUIVersion }}</span>
|
||||
<span class="label">UI Version</span>
|
||||
</div>
|
||||
<div class="metric-divider"></div>
|
||||
{# templates #}
|
||||
<div class="metric-group">
|
||||
<div class="metric">
|
||||
<span class="value">{{ collector.GetTemplatesCount.count }}</span>
|
||||
<span class="label">Templates</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="value">{{ collector.GetTemplatesCount.overrides_count }}</span>
|
||||
<span class="label">Overridden</span>
|
||||
</div>
|
||||
</div>
|
||||
{# additional info #}
|
||||
<div class="metric-divider"></div>
|
||||
<div class="metric-group">
|
||||
<div class="metric">
|
||||
<span class="value">{{ collector.GetTemplatesCount.extensions_count }}</span>
|
||||
<span class="label">Extensions</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="value">{{ collector.GetTemplatesCount.providers_count }}</span>
|
||||
<span class="label">Providers</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Instances overloads #}
|
||||
<h2>Bricks declared templates list</h2>
|
||||
{# help #}
|
||||
<p class="help">
|
||||
Bricks overridden templates are templates defined in brick declarations.
|
||||
</p>
|
||||
{% if collector.GetInstancesOverriddenTemplates|length == 0 %}
|
||||
No instance overridden template.
|
||||
{% else %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Brick</th>
|
||||
<th>Class</th>
|
||||
<th>ID</th>
|
||||
<th>Template</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for instance,item in collector.GetInstancesOverriddenTemplates %}
|
||||
{% for id,template in item.templates %}
|
||||
<tr>
|
||||
<td>{{ item.info.id }}</td>
|
||||
<td>{{ item.info.class }}</td>
|
||||
<td>{{ id }}</td>
|
||||
<td>{{ template }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{# templates list #}
|
||||
<h2>Templates list</h2>
|
||||
|
||||
{# help #}
|
||||
<p class="help">
|
||||
Templates doesn't necessary covers all existing templates, only the ones that are registered in the portal.
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Provider</th>
|
||||
<th>ID</th>
|
||||
<th>Template</th>
|
||||
<th>Alias</th>
|
||||
<th>Override</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for provider,item in collector.GetTemplatesDefinitions %}
|
||||
{% for id,template in item %}
|
||||
<tr {% if template.IsOverridden %}class="overridden_value"{% endif %}>
|
||||
<td>{{ provider }}</td>
|
||||
<td>{{ template.Id }}</td>
|
||||
<td>{{ template.path }}{% if template.IsOverridden %}
|
||||
<div class="old_value">{{ template.GetPath(true) }}</div>{% endif %}</td>
|
||||
<td>{{ template.Alias }}</td>
|
||||
<td>{% if template.IsOverridable %}
|
||||
{% if template.IsOverridden %}
|
||||
Yes
|
||||
{% else %}
|
||||
No
|
||||
{% endif %}
|
||||
{% else %}
|
||||
Not allowed
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,5 +1,5 @@
|
||||
<div id="session-messages">
|
||||
{% for aSessionMessage in app['session_message_helper'] %}
|
||||
{% include 'itop-portal-base/portal/templates/helpers/session_messages/session_message.html.twig' with {aSessionMessage: aSessionMessage} %}
|
||||
{% include template('session_message') with {aSessionMessage: aSessionMessage} %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="col-xs-12 col-sm-9 col-md-10 col-sm-offset-3 col-md-offset-2">
|
||||
<section class="row">
|
||||
<div class="col-xs-12">
|
||||
{% include 'itop-portal-base/portal/templates/helpers/session_messages/session_messages.html.twig' %}
|
||||
{% include template('session_messages') %}
|
||||
</div>
|
||||
</section>
|
||||
<section class="row tiles_wrapper">
|
||||
|
||||
@@ -335,7 +335,7 @@
|
||||
<div class="col-xs-12 col-sm-9 col-md-10 col-sm-offset-3 col-md-offset-2">
|
||||
<section class="row">
|
||||
<div class="col-xs-12">
|
||||
{% include 'itop-portal-base/portal/templates/helpers/session_messages/session_messages.html.twig' %}
|
||||
{% include template('session_messages') %}
|
||||
</div>
|
||||
</section>
|
||||
<section class="row" id="main-header">
|
||||
@@ -367,7 +367,7 @@
|
||||
<div class="modal fade" id="modal-for-all" role="dialog" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
{% include 'itop-portal-base/portal/templates/helpers/loader.html.twig' %}
|
||||
{% include template('loader') %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -395,7 +395,7 @@
|
||||
{% block pPageOverlay %}
|
||||
<div id="page_overlay" class="global_overlay">
|
||||
<div class="overlay_content">
|
||||
{% include 'itop-portal-base/portal/templates/helpers/loader.html.twig' %}
|
||||
{% include template('loader') %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% extends 'itop-portal-base/portal/templates/modal/layout.html.twig' %}
|
||||
|
||||
{% block pModalContent %}
|
||||
{% include 'itop-portal-base/portal/templates/helpers/loader.html.twig' %}
|
||||
{% include template('loader') %}
|
||||
|
||||
{% if redirection is defined and redirection.url is defined %}
|
||||
<script type="text/javascript">
|
||||
|
||||
@@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInitdf408f3f8ea034d298269cdf7647358b::getLoader();
|
||||
return ComposerAutoloaderInitd751713988987e9331980363e24189ce::getLoader();
|
||||
|
||||
@@ -27,6 +27,7 @@ return array(
|
||||
'Combodo\\iTop\\Portal\\Controller\\ObjectController' => $baseDir . '/src/Controller/ObjectController.php',
|
||||
'Combodo\\iTop\\Portal\\Controller\\SessionMessageController' => $baseDir . '/src/Controller/SessionMessageController.php',
|
||||
'Combodo\\iTop\\Portal\\Controller\\UserProfileBrickController' => $baseDir . '/src/Controller/UserProfileBrickController.php',
|
||||
'Combodo\\iTop\\Portal\\DataCollector\\PortalCollector' => $baseDir . '/src/DataCollector/PortalCollector.php',
|
||||
'Combodo\\iTop\\Portal\\DependencyInjection\\SilexCompatBootstrap\\PortalXmlConfiguration\\AbstractConfiguration' => $baseDir . '/src/DependencyInjection/SilexCompatBootstrap/PortalXmlConfiguration/AbstractConfiguration.php',
|
||||
'Combodo\\iTop\\Portal\\DependencyInjection\\SilexCompatBootstrap\\PortalXmlConfiguration\\Basic' => $baseDir . '/src/DependencyInjection/SilexCompatBootstrap/PortalXmlConfiguration/Basic.php',
|
||||
'Combodo\\iTop\\Portal\\DependencyInjection\\SilexCompatBootstrap\\PortalXmlConfiguration\\Forms' => $baseDir . '/src/DependencyInjection/SilexCompatBootstrap/PortalXmlConfiguration/Forms.php',
|
||||
@@ -59,6 +60,10 @@ return array(
|
||||
'Combodo\\iTop\\Portal\\Kernel' => $baseDir . '/src/Kernel.php',
|
||||
'Combodo\\iTop\\Portal\\Routing\\ItopExtensionsExtraRoutes' => $baseDir . '/src/Routing/ItopExtensionsExtraRoutes.php',
|
||||
'Combodo\\iTop\\Portal\\Routing\\UrlGenerator' => $baseDir . '/src/Routing/UrlGenerator.php',
|
||||
'Combodo\\iTop\\Portal\\Service\\TemplatesProvider\\TemplateDefinitionDto' => $baseDir . '/src/Service/TemplatesProvider/TemplateDefinitionDto.php',
|
||||
'Combodo\\iTop\\Portal\\Service\\TemplatesProvider\\TemplatesProviderInterface' => $baseDir . '/src/Service/TemplatesProvider/TemplatesProviderInterface.php',
|
||||
'Combodo\\iTop\\Portal\\Service\\TemplatesProvider\\TemplatesProviderService' => $baseDir . '/src/Service/TemplatesProvider/TemplatesProviderService.php',
|
||||
'Combodo\\iTop\\Portal\\Service\\TemplatesProvider\\TemplatesRegister' => $baseDir . '/src/Service/TemplatesProvider/TemplatesRegister.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\AppExtension' => $baseDir . '/src/Twig/AppExtension.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\AppGlobal' => $baseDir . '/src/Twig/AppGlobal.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\AppVariable' => $baseDir . '/src/Twig/AppVariable.php',
|
||||
@@ -66,6 +71,7 @@ return array(
|
||||
'Combodo\\iTop\\Portal\\Twig\\CurrentUserAccessor' => $baseDir . '/src/Twig/CurrentUserAccessor.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\PortalBlockExtension' => $baseDir . '/src/Twig/PortalBlockExtension.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\PortalTwigContext' => $baseDir . '/src/Twig/PortalTwigContext.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\TemplatesTwigExtension' => $baseDir . '/src/Twig/TemplatesTwigExtension.php',
|
||||
'Combodo\\iTop\\Portal\\UrlMaker\\AbstractPortalUrlMaker' => $baseDir . '/src/UrlMaker/AbstractPortalUrlMaker.php',
|
||||
'Combodo\\iTop\\Portal\\VariableAccessor\\AbstractStringVariableAccessor' => $baseDir . '/src/VariableAccessor/AbstractStringVariableAccessor.php',
|
||||
'Combodo\\iTop\\Portal\\VariableAccessor\\AbstractVariableAccessor' => $baseDir . '/src/VariableAccessor/AbstractVariableAccessor.php',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInitdf408f3f8ea034d298269cdf7647358b
|
||||
class ComposerAutoloaderInitd751713988987e9331980363e24189ce
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@@ -22,14 +22,13 @@ class ComposerAutoloaderInitdf408f3f8ea034d298269cdf7647358b
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInitdf408f3f8ea034d298269cdf7647358b', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInitd751713988987e9331980363e24189ce', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitdf408f3f8ea034d298269cdf7647358b', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitd751713988987e9331980363e24189ce', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitdf408f3f8ea034d298269cdf7647358b::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitd751713988987e9331980363e24189ce::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
return $loader;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInitdf408f3f8ea034d298269cdf7647358b
|
||||
class ComposerStaticInitd751713988987e9331980363e24189ce
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'C' =>
|
||||
@@ -47,6 +47,7 @@ class ComposerStaticInitdf408f3f8ea034d298269cdf7647358b
|
||||
'Combodo\\iTop\\Portal\\Controller\\ObjectController' => __DIR__ . '/../..' . '/src/Controller/ObjectController.php',
|
||||
'Combodo\\iTop\\Portal\\Controller\\SessionMessageController' => __DIR__ . '/../..' . '/src/Controller/SessionMessageController.php',
|
||||
'Combodo\\iTop\\Portal\\Controller\\UserProfileBrickController' => __DIR__ . '/../..' . '/src/Controller/UserProfileBrickController.php',
|
||||
'Combodo\\iTop\\Portal\\DataCollector\\PortalCollector' => __DIR__ . '/../..' . '/src/DataCollector/PortalCollector.php',
|
||||
'Combodo\\iTop\\Portal\\DependencyInjection\\SilexCompatBootstrap\\PortalXmlConfiguration\\AbstractConfiguration' => __DIR__ . '/../..' . '/src/DependencyInjection/SilexCompatBootstrap/PortalXmlConfiguration/AbstractConfiguration.php',
|
||||
'Combodo\\iTop\\Portal\\DependencyInjection\\SilexCompatBootstrap\\PortalXmlConfiguration\\Basic' => __DIR__ . '/../..' . '/src/DependencyInjection/SilexCompatBootstrap/PortalXmlConfiguration/Basic.php',
|
||||
'Combodo\\iTop\\Portal\\DependencyInjection\\SilexCompatBootstrap\\PortalXmlConfiguration\\Forms' => __DIR__ . '/../..' . '/src/DependencyInjection/SilexCompatBootstrap/PortalXmlConfiguration/Forms.php',
|
||||
@@ -79,6 +80,10 @@ class ComposerStaticInitdf408f3f8ea034d298269cdf7647358b
|
||||
'Combodo\\iTop\\Portal\\Kernel' => __DIR__ . '/../..' . '/src/Kernel.php',
|
||||
'Combodo\\iTop\\Portal\\Routing\\ItopExtensionsExtraRoutes' => __DIR__ . '/../..' . '/src/Routing/ItopExtensionsExtraRoutes.php',
|
||||
'Combodo\\iTop\\Portal\\Routing\\UrlGenerator' => __DIR__ . '/../..' . '/src/Routing/UrlGenerator.php',
|
||||
'Combodo\\iTop\\Portal\\Service\\TemplatesProvider\\TemplateDefinitionDto' => __DIR__ . '/../..' . '/src/Service/TemplatesProvider/TemplateDefinitionDto.php',
|
||||
'Combodo\\iTop\\Portal\\Service\\TemplatesProvider\\TemplatesProviderInterface' => __DIR__ . '/../..' . '/src/Service/TemplatesProvider/TemplatesProviderInterface.php',
|
||||
'Combodo\\iTop\\Portal\\Service\\TemplatesProvider\\TemplatesProviderService' => __DIR__ . '/../..' . '/src/Service/TemplatesProvider/TemplatesProviderService.php',
|
||||
'Combodo\\iTop\\Portal\\Service\\TemplatesProvider\\TemplatesRegister' => __DIR__ . '/../..' . '/src/Service/TemplatesProvider/TemplatesRegister.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\AppExtension' => __DIR__ . '/../..' . '/src/Twig/AppExtension.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\AppGlobal' => __DIR__ . '/../..' . '/src/Twig/AppGlobal.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\AppVariable' => __DIR__ . '/../..' . '/src/Twig/AppVariable.php',
|
||||
@@ -86,6 +91,7 @@ class ComposerStaticInitdf408f3f8ea034d298269cdf7647358b
|
||||
'Combodo\\iTop\\Portal\\Twig\\CurrentUserAccessor' => __DIR__ . '/../..' . '/src/Twig/CurrentUserAccessor.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\PortalBlockExtension' => __DIR__ . '/../..' . '/src/Twig/PortalBlockExtension.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\PortalTwigContext' => __DIR__ . '/../..' . '/src/Twig/PortalTwigContext.php',
|
||||
'Combodo\\iTop\\Portal\\Twig\\TemplatesTwigExtension' => __DIR__ . '/../..' . '/src/Twig/TemplatesTwigExtension.php',
|
||||
'Combodo\\iTop\\Portal\\UrlMaker\\AbstractPortalUrlMaker' => __DIR__ . '/../..' . '/src/UrlMaker/AbstractPortalUrlMaker.php',
|
||||
'Combodo\\iTop\\Portal\\VariableAccessor\\AbstractStringVariableAccessor' => __DIR__ . '/../..' . '/src/VariableAccessor/AbstractStringVariableAccessor.php',
|
||||
'Combodo\\iTop\\Portal\\VariableAccessor\\AbstractVariableAccessor' => __DIR__ . '/../..' . '/src/VariableAccessor/AbstractVariableAccessor.php',
|
||||
@@ -97,9 +103,9 @@ class ComposerStaticInitdf408f3f8ea034d298269cdf7647358b
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitdf408f3f8ea034d298269cdf7647358b::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitdf408f3f8ea034d298269cdf7647358b::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitdf408f3f8ea034d298269cdf7647358b::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitd751713988987e9331980363e24189ce::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitd751713988987e9331980363e24189ce::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitd751713988987e9331980363e24189ce::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
'name' => '__root__',
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => 'c9beba0ceadf11c644a8eb1b254efff9b17d804c',
|
||||
'reference' => '4f6d514694b9813b9a5ebda4c38f29b4847ff9c3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -13,7 +13,7 @@
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => 'c9beba0ceadf11c644a8eb1b254efff9b17d804c',
|
||||
'reference' => '4f6d514694b9813b9a5ebda4c38f29b4847ff9c3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<module_design id="itop-portal" xsi:type="portal" _delta="define">
|
||||
<properties>
|
||||
<name>portal:itop-portal</name>
|
||||
<ui_version>2017</ui_version>
|
||||
<!-- Can be either a fileref or a relative path to the file (To be tested). Takes over env-xxx/branding/portal-logo.png -->
|
||||
<!-- Priority order is <logo> from xml > env-xxx/branding/portal-logo.png > /images/logo-itop-dark-bg.svg -->
|
||||
<!--<fileref ref="brt_6a2be154b2a62659d3332c513bdad715" />-->
|
||||
|
||||
@@ -183,8 +183,103 @@
|
||||
<class id="SynchroLog"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="AdminSysReadOnly" _delta="define">
|
||||
<classes>
|
||||
<class id="ItopFenceLogin"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="AdminSys" _delta="define">
|
||||
<classes>
|
||||
<class id="ResourceDesignerConnectorMenu"/>
|
||||
<class id="ResourceSystemMenu"/>
|
||||
<class id="RessourceHybridAuthMenu"/>
|
||||
</classes>
|
||||
</group>
|
||||
</groups>
|
||||
<profiles>
|
||||
<profile id="117" _delta="define">
|
||||
<name>SuperUser</name>
|
||||
<description>This profil allows all actions which are not Administrator restricted.</description>
|
||||
<groups>
|
||||
<group id="AdminTools">
|
||||
<actions>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:bulk delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="AdminSysReadOnly">
|
||||
<actions>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="AdminSys">
|
||||
<actions>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="History">
|
||||
<actions>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:bulk delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="UserRequest">
|
||||
<actions>
|
||||
<action id="stimulus:ev_approve">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
<action id="stimulus:ev_dispatch">allow</action>
|
||||
<action id="stimulus:ev_pending">allow</action>
|
||||
<action id="stimulus:ev_reassign">allow</action>
|
||||
<action id="stimulus:ev_reject">allow</action>
|
||||
<action id="stimulus:ev_reopen">allow</action>
|
||||
<action id="stimulus:ev_resolve">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Incident">
|
||||
<actions>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_reassign">allow</action>
|
||||
<action id="stimulus:ev_resolve">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
<action id="stimulus:ev_pending">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Change">
|
||||
<actions>
|
||||
<action id="stimulus:ev_approve">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_finish">allow</action>
|
||||
<action id="stimulus:ev_plan">allow</action>
|
||||
<action id="stimulus:ev_reject">allow</action>
|
||||
<action id="stimulus:ev_reopen">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Problem">
|
||||
<actions>
|
||||
<action id="stimulus:ev_reassign">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_resolve">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
</profile>
|
||||
<profile id="3" _delta="define">
|
||||
<name>Configuration Manager</name>
|
||||
<description>Person in charge of the documentation of the managed CIs</description>
|
||||
|
||||
@@ -74,7 +74,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:Organization/Attribute:deliverymodel_id' => '交付模式',
|
||||
'Class:Organization/Attribute:deliverymodel_id+' => 'This is required for Tickets handling.
|
||||
The delivery model specifies the teams to which tickets can be assigned.~~',
|
||||
The delivery model specifies the teams to which tickets can be assigned.~~',
|
||||
'Class:Organization/Attribute:deliverymodel_name' => '交付模式名称',
|
||||
]);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ SetupWebPage::AddModule(
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().':admin:cron',
|
||||
'doc.manual_setup' => '',
|
||||
'doc.more_information' => '',
|
||||
|
||||
// Default settings
|
||||
|
||||
@@ -31,7 +31,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
// Create
|
||||
'UI:Links:Create:Button' => '创建',
|
||||
'UI:Links:Create:Button+' => '创建一个 %4$s',
|
||||
'UI:Links:Create:Modal:Title' => '创建一个 %4$s 至% 2$s',
|
||||
'UI:Links:Create:Modal:Title' => '创建一个 %4$s 至 %2$s',
|
||||
|
||||
// Add
|
||||
'UI:Links:Add:Button' => '添加',
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
* Localized data
|
||||
*
|
||||
* This file is part of iTop.
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
// Quick create
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'UI:Component:QuickCreate:Tooltip' => '快速创建任意类型的对象',
|
||||
'UI:Component:QuickCreate:Input:Placeholder' => '请选择对象类型...',
|
||||
'UI:Component:QuickCreate:Recents:Title' => '最近',
|
||||
'UI:Component:QuickCreate:LastClasses:NoClass:Placeholder' => '您尚未创建任何对象',
|
||||
'UI:Component:QuickCreate:HistoryDisabled' => '历史记录已禁用',
|
||||
'UI:Component:QuickCreate:Input:Placeholder' => '请选择对象类型...',
|
||||
'UI:Component:QuickCreate:KeyboardShortcut:OpenDrawer' => '打开快速创建',
|
||||
]);
|
||||
'UI:Component:QuickCreate:LastClasses:NoClass:Placeholder' => '您尚未创建任何对象',
|
||||
'UI:Component:QuickCreate:MostPopular:Title' => '最常用',
|
||||
'UI:Component:QuickCreate:Recents:Title' => '最近',
|
||||
'UI:Component:QuickCreate:Tooltip' => '快速创建任意类型的对象',
|
||||
]);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3
node_modules/.package-lock.json
generated
vendored
3
node_modules/.package-lock.json
generated
vendored
@@ -71,7 +71,8 @@
|
||||
},
|
||||
"node_modules/ckeditor5-itop-build": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "git+ssh://git@github.com/Combodo/ckeditor5-itop-build.git#7366299c6c4b659736b958c5e9496e98c22a3c36"
|
||||
"resolved": "git+ssh://git@github.com/Combodo/ckeditor5-itop-build.git#deab849bf05e66948c5e66a57079ad1baea66b94",
|
||||
"license": "SEE LICENSE IN LICENSE.md"
|
||||
},
|
||||
"node_modules/clipboard": {
|
||||
"version": "2.0.11",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user