mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-05 00:58:45 +02:00
Compare commits
115 Commits
issue/7726
...
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 | ||
|
|
32ef639ce1 | ||
|
|
8647a76dbf | ||
|
|
47cd8bce31 | ||
|
|
86c677b2ca | ||
|
|
960129316d | ||
|
|
1fa50f695d | ||
|
|
692cf4f635 | ||
|
|
95aa444ee6 | ||
|
|
f5de808c7c | ||
|
|
fc388313d7 | ||
|
|
d544ee5498 | ||
|
|
ce187550f6 | ||
|
|
5d15a08824 | ||
|
|
8135316119 | ||
|
|
868c0ae836 | ||
|
|
d03d4fce5f | ||
|
|
aa55c2b30f | ||
|
|
9d3b46b919 | ||
|
|
01b4dbba71 | ||
|
|
72ac4096c1 | ||
|
|
19559b08a7 | ||
|
|
346564ca0e | ||
|
|
1bf53bae2a | ||
|
|
29ce042916 | ||
|
|
83539d6d4c | ||
|
|
e6a7b926f6 | ||
|
|
b30e053236 | ||
|
|
afd96a0f49 | ||
|
|
a77765ec7b | ||
|
|
64b4b03ea9 | ||
|
|
a797878b17 | ||
|
|
1fa0f7bdd9 | ||
|
|
f718b4173d | ||
|
|
e057c0f081 | ||
|
|
5a49fc7654 | ||
|
|
6fca659c9d | ||
|
|
eacd08f31e | ||
|
|
5f7d8f6cc0 | ||
|
|
cbb4281a37 | ||
|
|
d7a8d335d5 | ||
|
|
bd1d447677 | ||
|
|
bb405d5173 | ||
|
|
4723fc885c | ||
|
|
06dcae1dd1 | ||
|
|
e03033ce52 | ||
|
|
19eae916f0 | ||
|
|
596e26a96f | ||
|
|
ef42a49009 | ||
|
|
51e5f1e7de | ||
|
|
9cffd17e19 | ||
|
|
e9f16935b6 | ||
|
|
e7488b2c89 | ||
|
|
8ac4086e71 | ||
|
|
6b5273fa1c | ||
|
|
9b1e854bf7 | ||
|
|
926700856d | ||
|
|
ab93d59a77 | ||
|
|
c70d62a51e |
@@ -79,8 +79,6 @@ Then, **for a method** of an eligible class:
|
||||
|
||||
## Installation
|
||||
|
||||
Note : PHP7 is required. Migrating to PHP8 requires some additional work which is questionable as an alternative way to generate a documentation is being considered.
|
||||
|
||||
```
|
||||
cd .doc
|
||||
composer require phpdocumentor/phpdocumentor:~2 --dev
|
||||
|
||||
@@ -90,7 +90,6 @@ We would like to give a special thank you 🤗 to the people from the community
|
||||
- Dejin, Bie (a.k.a [@bdejin](https://github.com/bdejin))
|
||||
- Dvořák, Lukáš
|
||||
- Goethals, Stefan
|
||||
- Giuva, Vincenzo Katriel (a.k.a [@DarkNight97boss](https://github.com/DarkNight97boss))
|
||||
- Gumble, David
|
||||
- Ji, Leeb (冀利斌) (a.k.a [@chileeb](https://github.com/chileeb))
|
||||
- Kaltefleiter, Lars (a.k.a [@larhip](https://www.github.com/larhip))
|
||||
|
||||
@@ -825,49 +825,38 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
{
|
||||
// We are protected by GetSelectFilter: the object set contains objects allowed or shared for reading
|
||||
// We have to answer NO for objects shared for reading purposes
|
||||
if (self::HasSharing())
|
||||
{
|
||||
$aClassProps = SharedObject::GetSharedClassProperties($sClass);
|
||||
if ($aClassProps)
|
||||
{
|
||||
// This class is shared, GetSelectFilter may allow some objects for read only
|
||||
// But currently we are checking wether the objects might be written...
|
||||
// Let's exclude the objects based on the relevant criteria
|
||||
if (self::HasSharing() && SharedObject::GetSharedClassProperties($sClass)) {
|
||||
// This class is shared, GetSelectFilter may allow some objects for read only
|
||||
// But currently we are checking whether the objects might be written...
|
||||
// Let's exclude the objects based on the relevant criteria
|
||||
|
||||
$sOrgAttCode = self::GetOwnerOrganizationAttCode($sClass);
|
||||
if (!is_null($sOrgAttCode))
|
||||
{
|
||||
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
||||
if (!is_null($aUserOrgs) && count($aUserOrgs) > 0)
|
||||
{
|
||||
$iCountNO = 0;
|
||||
$iCountYES = 0;
|
||||
$oInstanceSet->Rewind();
|
||||
while($oObject = $oInstanceSet->Fetch())
|
||||
{
|
||||
$iOrg = $oObject->Get($sOrgAttCode);
|
||||
if (in_array($iOrg, $aUserOrgs))
|
||||
{
|
||||
$iCountYES++;
|
||||
}
|
||||
else
|
||||
{
|
||||
$iCountNO++;
|
||||
}
|
||||
}
|
||||
if ($iCountNO == 0)
|
||||
{
|
||||
$iPermission = UR_ALLOWED_YES;
|
||||
}
|
||||
elseif ($iCountYES == 0)
|
||||
{
|
||||
$iPermission = UR_ALLOWED_NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
$iPermission = UR_ALLOWED_DEPENDS;
|
||||
// Use $oInstanceSet only if sClass is the main class
|
||||
if (!is_a($oInstanceSet->GetClass(), $sClass, true)) {
|
||||
/** @var \DBObjectSet $oInstanceSet */
|
||||
throw new CoreException(__FUNCTION__.': Expecting object set to be of class '.$sClass.' but it is of class '.$oInstanceSet->GetClass(), ['OQL_Query' => $oInstanceSet->GetFilter()->ToOQL(), 'classes' => $oInstanceSet->GetSelectedClasses()]);
|
||||
}
|
||||
$sOrgAttCode = self::GetOwnerOrganizationAttCode($sClass);
|
||||
if (!is_null($sOrgAttCode)) {
|
||||
$aUserOrgs = $this->GetUserOrgs($oUser, $sClass);
|
||||
if (!is_null($aUserOrgs) && count($aUserOrgs) > 0) {
|
||||
$iCountNO = 0;
|
||||
$iCountYES = 0;
|
||||
$oInstanceSet->Rewind();
|
||||
while ($oObject = $oInstanceSet->Fetch()) {
|
||||
$iOrg = $oObject->Get($sOrgAttCode);
|
||||
if (in_array($iOrg, $aUserOrgs)) {
|
||||
$iCountYES++;
|
||||
} else {
|
||||
$iCountNO++;
|
||||
}
|
||||
}
|
||||
if ($iCountNO == 0) {
|
||||
$iPermission = UR_ALLOWED_YES;
|
||||
} elseif ($iCountYES == 0) {
|
||||
$iPermission = UR_ALLOWED_NO;
|
||||
} else {
|
||||
$iPermission = UR_ALLOWED_DEPENDS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -982,4 +971,3 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
|
||||
UserRights::SelectModule('UserRightsProfile');
|
||||
|
||||
?>
|
||||
|
||||
@@ -805,16 +805,16 @@ HTML
|
||||
if (!$this->IsNew()) {
|
||||
// Look for any trigger that considers this object as "In Scope"
|
||||
// If any trigger has been found then display a tab with notifications
|
||||
// If all triggers on an object have been deleted, we consider that we no longer need the event notification information
|
||||
//
|
||||
$aTriggers = $this->GetRelatedTriggersIDs();
|
||||
if (count($aTriggers) > 0) {
|
||||
$iId = $this->GetKey();
|
||||
$aParams = array('class' => get_class($this), 'id' => $iId);
|
||||
$aParams = array('triggers' => $aTriggers, 'id' => $iId);
|
||||
$aNotifSearches = array();
|
||||
$iNotifsCount = 0;
|
||||
$aNotificationClasses = MetaModel::EnumChildClasses('EventNotification');
|
||||
foreach ($aNotificationClasses as $sNotifClass) {
|
||||
$aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT $sNotifClass AS Ev WHERE Ev.object_id = :id AND Ev.object_class = :class");
|
||||
$aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT $sNotifClass AS Ev JOIN Trigger AS T ON Ev.trigger_id = T.id WHERE T.id IN (:triggers) AND Ev.object_id = :id");
|
||||
$aNotifSearches[$sNotifClass]->SetInternalParams($aParams);
|
||||
$oNotifSet = new DBObjectSet($aNotifSearches[$sNotifClass], array());
|
||||
$iNotifsCount += $oNotifSet->Count();
|
||||
@@ -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>',
|
||||
@@ -5923,14 +5933,14 @@ JS
|
||||
*
|
||||
* @since 3.1.0
|
||||
*/
|
||||
final protected function FireEventCheckToWrite(): void
|
||||
final protected function FireEventCheckToWrite(?string $sStimulusBeingApplied): void
|
||||
{
|
||||
$this->FireEvent(EVENT_DB_CHECK_TO_WRITE, ['is_new' => $this->IsNew()]);
|
||||
$this->FireEvent(EVENT_DB_CHECK_TO_WRITE, ['is_new' => $this->IsNew(), 'stimulus_applied' => $sStimulusBeingApplied]);
|
||||
}
|
||||
|
||||
final protected function FireEventBeforeWrite()
|
||||
final protected function FireEventBeforeWrite(?string $sStimulusBeingApplied)
|
||||
{
|
||||
$this->FireEvent(EVENT_DB_BEFORE_WRITE, ['is_new' => $this->IsNew()]);
|
||||
$this->FireEvent(EVENT_DB_BEFORE_WRITE, ['is_new' => $this->IsNew(), 'stimulus_applied' => $sStimulusBeingApplied]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5942,11 +5952,11 @@ JS
|
||||
* @throws \CoreException
|
||||
* @since 3.1.0
|
||||
*/
|
||||
final protected function FireEventAfterWrite(array $aChanges, bool $bIsNew): void
|
||||
final protected function FireEventAfterWrite(array $aChanges, bool $bIsNew, ?string $sStimulusBeingApplied): void
|
||||
{
|
||||
$this->NotifyAttachedObjectsOnLinkClassModification();
|
||||
$this->RemoveObjectAwaitingEventDbLinksChanged(get_class($this), $this->GetKey());
|
||||
$this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges]);
|
||||
$this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges, 'stimulus_applied' => $sStimulusBeingApplied]);
|
||||
}
|
||||
|
||||
//////////////
|
||||
@@ -6179,9 +6189,9 @@ JS
|
||||
* @inheritDoc
|
||||
* @throws \CoreException
|
||||
*/
|
||||
final protected function FireEventComputeValues(): void
|
||||
final protected function FireEventComputeValues(?string $sStimulusBeingApplied): void
|
||||
{
|
||||
$this->FireEvent(EVENT_DB_COMPUTE_VALUES);
|
||||
$this->FireEvent(EVENT_DB_COMPUTE_VALUES, ['is_new' => $this->IsNew(), 'stimulus_applied' => $sStimulusBeingApplied]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1266,13 +1266,12 @@ EOF
|
||||
$sOkButtonLabel = Dict::S('UI:Button:Save');
|
||||
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
|
||||
|
||||
$sId = utils::HtmlEntities($this->sId);
|
||||
$sLayoutClass = utils::HtmlEntities($this->sLayoutClass);
|
||||
$sId = json_encode($this->sId);
|
||||
$sLayoutClass = json_encode($this->sLayoutClass);
|
||||
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
|
||||
$sAutoReloadSec = (string) $this->iAutoReloadSec;
|
||||
$sTitle = utils::HtmlEntities($this->sTitle);
|
||||
$sFile = utils::HtmlEntities($this->GetDefinitionFile());
|
||||
$sFileForJS = json_encode($this->GetDefinitionFile());
|
||||
$sTitle = json_encode($this->sTitle);
|
||||
$sFile = json_encode($this->GetDefinitionFile());
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
|
||||
$sReloadURL = $this->GetReloadURL();
|
||||
|
||||
@@ -1328,15 +1327,15 @@ $('#dashboard_editor').dialog({
|
||||
});
|
||||
|
||||
$('#dashboard_editor .ui-layout-center').runtimedashboard({
|
||||
dashboard_id: '$sId',
|
||||
layout_class: '$sLayoutClass',
|
||||
title: '$sTitle',
|
||||
dashboard_id: $sId,
|
||||
layout_class: $sLayoutClass,
|
||||
title: $sTitle,
|
||||
auto_reload: $sAutoReload,
|
||||
auto_reload_sec: $sAutoReloadSec,
|
||||
submit_to: '$sUrl',
|
||||
submit_parameters: {operation: 'save_dashboard', file: {$sFileForJS}, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
|
||||
submit_parameters: {operation: 'save_dashboard', file: $sFile, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
|
||||
render_to: '$sUrl',
|
||||
render_parameters: {operation: 'render_dashboard', file: {$sFileForJS}, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
|
||||
render_parameters: {operation: 'render_dashboard', file: $sFile, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
|
||||
new_dashlet_parameters: {operation: 'new_dashlet'}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<classes>
|
||||
<class id="AbstractResource" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
@@ -45,7 +45,7 @@
|
||||
<properties>
|
||||
<comment>/** Acknowledge welcome popup messages */</comment>
|
||||
<abstract>false</abstract>
|
||||
<category/>
|
||||
<category></category>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>priv_welcome_popup_acknowledge</db_table>
|
||||
</properties>
|
||||
@@ -238,6 +238,10 @@ The object can be modified.]]></description>
|
||||
<description>Creation flag</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus_applied">
|
||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
@@ -263,6 +267,10 @@ Call $this->AddCheckWarning($sWarningMessage) to display a warning.
|
||||
<description>Creation flag</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus_applied">
|
||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
@@ -290,6 +298,10 @@ The modifications can be propagated to other objects.]]></description>
|
||||
<description><![CDATA[For updates, the list of changes done during this operation]]></description>
|
||||
<type>array</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus_applied">
|
||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
@@ -420,6 +432,14 @@ The only action allowed is to deny transitions with $this->DenyTransition($sTran
|
||||
<description>The object inserted</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="is_new">
|
||||
<description>Creation flag</description>
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="stimulus_applied">
|
||||
<description>Life cycle stimulus applied (null if not within a transition)</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
|
||||
@@ -2024,8 +2024,8 @@ class MenuBlock extends DisplayBlock
|
||||
$sSelectedClassName = MetaModel::GetName($sSelectedClass);
|
||||
|
||||
// Check rights on class
|
||||
$bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sSelectedClass)) && UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_MODIFY, $oSet) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject'));
|
||||
$bIsBulkDeleteAllowed = (bool) UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_DELETE, $sSelectedClass);
|
||||
$bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sSelectedClass)) && UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_MODIFY) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject'));
|
||||
$bIsBulkDeleteAllowed = (bool) UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_DELETE);
|
||||
|
||||
// Refine filter on selected class so bullk actions occur on the right class
|
||||
$oSelectedClassFilter = $this->GetFilter()->DeepClone();
|
||||
|
||||
@@ -303,7 +303,7 @@ class ExcelExporter
|
||||
{
|
||||
if ($this->sOutputFilePath == null)
|
||||
{
|
||||
return utils::GetDataPath().'bulk_export/'.$this->sToken.'.xlsx';
|
||||
return APPROOT.'data/bulk_export/'.$this->sToken.'.xlsx';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -313,14 +313,14 @@ class ExcelExporter
|
||||
|
||||
public static function GetExcelFileFromToken($sToken)
|
||||
{
|
||||
return @file_get_contents(utils::GetDataPath().'bulk_export/'.$sToken.'.xlsx');
|
||||
return @file_get_contents(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
||||
}
|
||||
|
||||
public static function CleanupFromToken($sToken)
|
||||
{
|
||||
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.status');
|
||||
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.data');
|
||||
@unlink(utils::GetDataPath().'bulk_export/'.$sToken.'.xlsx');
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.status');
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.data');
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
||||
}
|
||||
|
||||
public function Cleanup()
|
||||
@@ -334,7 +334,7 @@ class ExcelExporter
|
||||
*/
|
||||
public static function CleanupOldFiles()
|
||||
{
|
||||
$aFiles = glob(utils::GetDataPath().'bulk_export/*.*');
|
||||
$aFiles = glob(APPROOT.'data/bulk_export/*.*');
|
||||
$iDelay = MetaModel::GetConfig()->Get('xlsx_exporter_cleanup_old_files_delay');
|
||||
|
||||
if($iDelay > 0)
|
||||
@@ -416,14 +416,14 @@ class ExcelExporter
|
||||
|
||||
protected function CheckDataDir()
|
||||
{
|
||||
if(!is_dir(utils::GetDataPath()."bulk_export"))
|
||||
if(!is_dir(APPROOT."data/bulk_export"))
|
||||
{
|
||||
@mkdir(utils::GetDataPath()."bulk_export", 0777, true /* recursive */);
|
||||
@mkdir(APPROOT."data/bulk_export", 0777, true /* recursive */);
|
||||
clearstatcache();
|
||||
}
|
||||
if (!is_writable(utils::GetDataPath()."bulk_export"))
|
||||
if (!is_writable(APPROOT."data/bulk_export"))
|
||||
{
|
||||
throw new Exception('Data directory "'.utils::GetDataPath().'bulk_export" could not be written.');
|
||||
throw new Exception('Data directory "'.APPROOT.'data/bulk_export" could not be written.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,12 +433,12 @@ class ExcelExporter
|
||||
{
|
||||
$sToken = $this->sToken;
|
||||
}
|
||||
return utils::GetDataPath()."bulk_export/$sToken.status";
|
||||
return APPROOT."data/bulk_export/$sToken.status";
|
||||
}
|
||||
|
||||
protected function GetDataFile()
|
||||
{
|
||||
return utils::GetDataPath().'bulk_export/'.$this->sToken.'.data';
|
||||
return APPROOT.'data/bulk_export/'.$this->sToken.'.data';
|
||||
}
|
||||
|
||||
protected function GetNewToken()
|
||||
|
||||
@@ -1159,11 +1159,11 @@ class OQLMenuNode extends MenuNode
|
||||
{
|
||||
$sUsageId = utils::GetSafeId($sUsageId);
|
||||
$oSearch = DBObjectSearch::FromOQL($sOql);
|
||||
$sClass= $oSearch->GetClass();
|
||||
$sClass= $oSearch->GetClass();
|
||||
$sIcon = MetaModel::GetClassIcon($sClass, false);
|
||||
if ($bSearchPane) {
|
||||
$aParams = array_merge(['open' => $bSearchOpen, 'table_id' => $sUsageId, 'submit_on_load' => false], $aExtraParams);
|
||||
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
|
||||
$oBlock = new DisplayBlock($oSearch, DisplayBlock::ENUM_STYLE_SEARCH, false /* Asynchronous */, $aParams);
|
||||
$oBlock->Display($oPage, 0);
|
||||
$oPage->add("<div class='sf_results_area ibo-add-margin-top-250' data-target='search_results'>");
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ class privUITransactionFile
|
||||
*/
|
||||
public static function GetNewTransactionId()
|
||||
{
|
||||
if (!is_dir(utils::GetDataPath().'transactions'))
|
||||
if (!is_dir(APPROOT.'data/transactions'))
|
||||
{
|
||||
if (!is_writable(APPROOT.'data'))
|
||||
{
|
||||
@@ -236,22 +236,22 @@ class privUITransactionFile
|
||||
}
|
||||
// condition avoids race condition N°2345
|
||||
// See https://github.com/kalessil/phpinspectionsea/blob/master/docs/probable-bugs.md#mkdir-race-condition
|
||||
if (!mkdir($concurrentDirectory = utils::GetDataPath().'transactions') && !is_dir($concurrentDirectory))
|
||||
if (!mkdir($concurrentDirectory = APPROOT.'data/transactions') && !is_dir($concurrentDirectory))
|
||||
{
|
||||
throw new Exception('Failed to create the directory "'.utils::GetDataPath().'transactions". Ajust the rights on the parent directory or let an administrator create the transactions directory and give the web sever enough rights to write into it.');
|
||||
throw new Exception('Failed to create the directory "'.APPROOT.'data/transactions". Ajust the rights on the parent directory or let an administrator create the transactions directory and give the web sever enough rights to write into it.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_writable(utils::GetDataPath().'transactions'))
|
||||
if (!is_writable(APPROOT.'data/transactions'))
|
||||
{
|
||||
throw new Exception('The directory "'.utils::GetDataPath().'transactions" must be writable to the application.');
|
||||
throw new Exception('The directory "'.APPROOT.'data/transactions" must be writable to the application.');
|
||||
}
|
||||
|
||||
$iCurrentUserId = static::GetCurrentUserId();
|
||||
|
||||
self::CleanupOldTransactions();
|
||||
|
||||
$sTransactionIdFullPath = tempnam(utils::GetDataPath().'transactions', static::GetUserPrefix());
|
||||
$sTransactionIdFullPath = tempnam(APPROOT.'data/transactions', static::GetUserPrefix());
|
||||
file_put_contents($sTransactionIdFullPath, $iCurrentUserId, LOCK_EX);
|
||||
|
||||
$sTransactionIdFileName = basename($sTransactionIdFullPath);
|
||||
@@ -274,8 +274,8 @@ class privUITransactionFile
|
||||
*/
|
||||
public static function IsTransactionValid($id, $bRemoveTransaction = true)
|
||||
{
|
||||
// Constraint the transaction file within utils::GetDataPath().'transactions'
|
||||
$sTransactionDir = realpath(utils::GetDataPath().'transactions');
|
||||
// Constraint the transaction file within APPROOT.'data/transactions'
|
||||
$sTransactionDir = realpath(APPROOT.'data/transactions');
|
||||
$sFilepath = utils::RealPath($sTransactionDir.'/'.$id, $sTransactionDir);
|
||||
if (($sFilepath === false) || (strlen($sTransactionDir) == strlen($sFilepath)))
|
||||
{
|
||||
@@ -348,7 +348,7 @@ class privUITransactionFile
|
||||
|
||||
clearstatcache();
|
||||
$iLimit = time() - 24*3600;
|
||||
$sPattern = $sTransactionDir ? "$sTransactionDir/*" : utils::GetDataPath().'transactions/*';
|
||||
$sPattern = $sTransactionDir ? "$sTransactionDir/*" : APPROOT.'data/transactions/*';
|
||||
$aTransactions = glob($sPattern);
|
||||
foreach($aTransactions as $sFileName)
|
||||
{
|
||||
@@ -368,7 +368,7 @@ class privUITransactionFile
|
||||
{
|
||||
clearstatcache();
|
||||
$aResult = array();
|
||||
$aTransactions = glob(utils::GetDataPath().'transactions/'.self::GetUserPrefix().'*');
|
||||
$aTransactions = glob(APPROOT.'data/transactions/'.self::GetUserPrefix().'*');
|
||||
foreach($aTransactions as $sFileName)
|
||||
{
|
||||
$aResult[] = date('Y-m-d H:i:s', filemtime($sFileName)).' - '.basename($sFileName);
|
||||
|
||||
@@ -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)) {
|
||||
@@ -1451,9 +1452,12 @@ class utils
|
||||
* @return string A path to a folder into which any module can store cache data
|
||||
* The corresponding folder is created or cleaned upon code compilation
|
||||
*/
|
||||
public static function GetCachePath()
|
||||
public static function GetCachePath(string $sEnvironment = null): string
|
||||
{
|
||||
return static::GetDataPath().'cache-'.MetaModel::GetEnvironment().'/';
|
||||
if (is_null($sEnvironment)) {
|
||||
$sEnvironment = MetaModel::GetEnvironment();
|
||||
}
|
||||
return static::GetDataPath()."cache-$sEnvironment/";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2390,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2444,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
|
||||
@@ -2514,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)
|
||||
@@ -3132,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];
|
||||
|
||||
@@ -11,7 +11,7 @@ define('APPCONF', APPROOT.'conf/');
|
||||
*
|
||||
* @see ITOP_CORE_VERSION to get full iTop core version
|
||||
*/
|
||||
define('ITOP_DESIGN_LATEST_VERSION', '3.3');
|
||||
define('ITOP_DESIGN_LATEST_VERSION', '3.2');
|
||||
|
||||
/**
|
||||
* Constant containing the iTop core version, whatever application was built
|
||||
@@ -23,7 +23,7 @@ define('ITOP_DESIGN_LATEST_VERSION', '3.3');
|
||||
* @used-by utils::GetItopVersionWikiSyntax()
|
||||
* @used-by iTopModulesPhpVersionIntegrationTest
|
||||
*/
|
||||
define('ITOP_CORE_VERSION', '3.3.0');
|
||||
define('ITOP_CORE_VERSION', '3.2.0');
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
||||
102
composer.lock
generated
102
composer.lock
generated
@@ -3929,6 +3929,82 @@
|
||||
],
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.31.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
|
||||
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php81\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php83",
|
||||
"version": "v1.28.0",
|
||||
@@ -4976,30 +5052,38 @@
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.8.0",
|
||||
"version": "v3.16.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
|
||||
"reference": "475ad2dc97d65d8631393e721e7e44fb544f0561"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
|
||||
"reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/475ad2dc97d65d8631393e721e7e44fb544f0561",
|
||||
"reference": "475ad2dc97d65d8631393e721e7e44fb544f0561",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"php": ">=8.0.2",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-ctype": "^1.8",
|
||||
"symfony/polyfill-mbstring": "^1.3",
|
||||
"symfony/polyfill-php80": "^1.22"
|
||||
"symfony/polyfill-php81": "^1.29"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"psr/container": "^1.0|^2.0",
|
||||
"symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
|
||||
"symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Resources/core.php",
|
||||
"src/Resources/debug.php",
|
||||
"src/Resources/escaper.php",
|
||||
"src/Resources/string_loader.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Twig\\": "src/"
|
||||
}
|
||||
@@ -5032,7 +5116,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.8.0"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.16.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5044,7 +5128,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-21T18:54:41+00:00"
|
||||
"time": "2024-11-29T08:27:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
|
||||
@@ -181,7 +181,7 @@ abstract class Action extends cmdbAbstractObject
|
||||
{
|
||||
parent::DisplayBareRelations($oPage, false);
|
||||
|
||||
if ($oPage instanceof iTopWebPage) {
|
||||
if ($oPage instanceof iTopWebPage && !$this->IsNew()) {
|
||||
$this->GenerateLastExecutionsTab($oPage, $bEditMode);
|
||||
}
|
||||
}
|
||||
@@ -566,7 +566,6 @@ class ActionEmail extends ActionNotification
|
||||
$oLog->Set('trigger_id', $oTrigger->GetKey());
|
||||
$oLog->Set('action_id', $this->GetKey());
|
||||
$oLog->Set('object_id', $aContextArgs['this->object()']->GetKey());
|
||||
$oLog->Set('object_class', get_class($aContextArgs['this->object()']));
|
||||
// Must be inserted now so that it gets a valid id that will make the link
|
||||
// between an eventual asynchronous task (queued) and the log
|
||||
$oLog->DBInsertNoReload();
|
||||
|
||||
@@ -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())));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1715,8 +1715,8 @@ class AttributeLinkedSet extends AttributeDefinition
|
||||
public function GetEditMode()
|
||||
{
|
||||
return $this->GetOptional('edit_mode', LINKSET_EDITMODE_ACTIONS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int see LINKSET_EDITWHEN_* constants
|
||||
* @since 3.1.1 3.2.0 N°6385
|
||||
@@ -1758,7 +1758,7 @@ class AttributeLinkedSet extends AttributeDefinition
|
||||
{
|
||||
return $this->GetOptional('with_php_computation', false);
|
||||
}
|
||||
|
||||
|
||||
public function GetLinkedClass()
|
||||
{
|
||||
return $this->Get('linked_class');
|
||||
@@ -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();
|
||||
}
|
||||
@@ -9433,8 +9436,13 @@ class AttributeStopWatch extends AttributeDefinition
|
||||
case 'deadline':
|
||||
if ($value)
|
||||
{
|
||||
$sDate = date(AttributeDateTime::GetInternalFormat(), $value);
|
||||
$sRet = AttributeDeadline::FormatDeadline($sDate);
|
||||
if (is_int($value))
|
||||
{
|
||||
$sDate = date(AttributeDateTime::GetInternalFormat(), $value);
|
||||
$sRet = AttributeDeadline::FormatDeadline($sDate);
|
||||
} else {
|
||||
$sRet = $value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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())));
|
||||
@@ -474,14 +474,14 @@ abstract class BulkExport
|
||||
*/
|
||||
protected function MakeTmpFile($sExtension)
|
||||
{
|
||||
if(!is_dir(utils::GetDataPath()."bulk_export"))
|
||||
if(!is_dir(APPROOT."data/bulk_export"))
|
||||
{
|
||||
@mkdir(utils::GetDataPath()."bulk_export", 0777, true /* recursive */);
|
||||
@mkdir(APPROOT."data/bulk_export", 0777, true /* recursive */);
|
||||
clearstatcache();
|
||||
}
|
||||
if (!is_writable(utils::GetDataPath()."bulk_export"))
|
||||
if (!is_writable(APPROOT."data/bulk_export"))
|
||||
{
|
||||
throw new Exception('Data directory "'.utils::GetDataPath().'bulk_export" could not be written.');
|
||||
throw new Exception('Data directory "'.APPROOT.'data/bulk_export" could not be written.');
|
||||
}
|
||||
|
||||
$iNum = rand();
|
||||
@@ -489,7 +489,7 @@ abstract class BulkExport
|
||||
{
|
||||
$iNum++;
|
||||
$sToken = sprintf("%08x", $iNum);
|
||||
$sFileName = utils::GetDataPath()."bulk_export/$sToken.".$sExtension;
|
||||
$sFileName = APPROOT."data/bulk_export/$sToken.".$sExtension;
|
||||
$hFile = @fopen($sFileName, 'x');
|
||||
}
|
||||
while($hFile === false);
|
||||
|
||||
@@ -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())));
|
||||
|
||||
@@ -29,7 +29,7 @@ define('ITOP_APPLICATION_SHORT', 'iTop');
|
||||
*
|
||||
* @see ITOP_CORE_VERSION to get iTop core version
|
||||
*/
|
||||
define('ITOP_VERSION', '3.3.0-dev');
|
||||
define('ITOP_VERSION', '3.2.0-dev');
|
||||
|
||||
define('ITOP_VERSION_NAME', 'Fullmoon');
|
||||
define('ITOP_REVISION', 'svn');
|
||||
@@ -71,7 +71,7 @@ define('DEFAULT_MAX_DISPLAY_LIMIT', 30);
|
||||
define('DEFAULT_STANDARD_RELOAD_INTERVAL', 5 * 60);
|
||||
define('DEFAULT_FAST_RELOAD_INTERVAL', 1 * 60);
|
||||
define('DEFAULT_SECURE_CONNECTION_REQUIRED', false);
|
||||
define('DEFAULT_ALLOWED_LOGIN_TYPES', 'form|external|basic');
|
||||
define('DEFAULT_ALLOWED_LOGIN_TYPES', 'form|external|basic|token');
|
||||
define('DEFAULT_EXT_AUTH_VARIABLE', '$_SERVER[\'REMOTE_USER\']');
|
||||
define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random generated key later (if possible)
|
||||
define('DEFAULT_ENCRYPTION_LIB', 'Mcrypt'); // We'll define the best encryption available later
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<classes>
|
||||
<class id="lnkActionNotificationToContact" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
@@ -99,7 +99,7 @@
|
||||
</presentation>
|
||||
<methods/>
|
||||
</class>
|
||||
<class id="ActionNewsroom" _delta="define">
|
||||
<class id="ActionNewsroom" _delta="define">
|
||||
<php_parent>
|
||||
<name>ActionNotification</name>
|
||||
</php_parent>
|
||||
@@ -148,7 +148,7 @@
|
||||
<display_max_height>96</display_max_height>
|
||||
<storage_max_width>256</storage_max_width>
|
||||
<storage_max_height>256</storage_max_height>
|
||||
<default_image/>
|
||||
<default_image />
|
||||
</field>
|
||||
<field id="priority" xsi:type="AttributeEnum">
|
||||
<sql>priority</sql>
|
||||
@@ -183,7 +183,7 @@
|
||||
</field>
|
||||
<field id="url" xsi:type="AttributeString">
|
||||
<sql>url</sql>
|
||||
<default_value>$this->url()$</default_value>
|
||||
<default_value>$this->url()$</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
</fields>
|
||||
@@ -355,37 +355,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ($bIsAsync === true) {
|
||||
AsyncSendNewsroom::AddToQueue($this->GetKey(), $oTrigger->GetKey(), $aRecipientsIds, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
|
||||
} else {
|
||||
foreach ($aRecipientsIds as $iRecipientId) {
|
||||
$oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this, $iRecipientId, $oTrigger->GetKey(), $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
|
||||
$oEvent->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
} catch (CoreCannotSaveObjectException $e) {
|
||||
ExceptionLog::LogException($e);
|
||||
foreach($aRecipientsIds as $iRecipientId) {
|
||||
$oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this,
|
||||
$iRecipientId,
|
||||
$oTrigger->GetKey(),
|
||||
Dict::S('Core:EventNotificationNewsroom:ErrorOnDBInsert'),
|
||||
Dict::S('Core:EventNotificationNewsroom:ErrorNotificationNotSent'),
|
||||
$sUrl,
|
||||
$iObjectId,
|
||||
$sObjectClass
|
||||
);
|
||||
$oEvent->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
if ($bIsAsync === true) {
|
||||
AsyncSendNewsroom::AddToQueue($this->GetKey(), $oTrigger->GetKey(), $aRecipientsIds, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
|
||||
} else {
|
||||
foreach ($aRecipientsIds as $iRecipientId) {
|
||||
$oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this, $iRecipientId, $oTrigger->GetKey(), $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass);
|
||||
$oEvent->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
|
||||
$this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null);
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="GetAsynchronousGlobalSetting">
|
||||
<comment/>
|
||||
<comment></comment>
|
||||
<static>true</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
@@ -397,7 +381,7 @@
|
||||
</method>
|
||||
</methods>
|
||||
</class>
|
||||
<class id="EventNotificationNewsroom" _delta="define">
|
||||
<class id="EventNotificationNewsroom" _delta="define">
|
||||
<php_parent>
|
||||
<name>EventNotification</name>
|
||||
</php_parent>
|
||||
@@ -421,7 +405,7 @@
|
||||
</reconciliation>
|
||||
<order>
|
||||
<columns>
|
||||
<column id="date" ascending="false"/>
|
||||
<column id="date" ascending="false" />
|
||||
</columns>
|
||||
</order>
|
||||
</properties>
|
||||
@@ -435,7 +419,7 @@
|
||||
<sql>icon</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<default_image/>
|
||||
<default_image />
|
||||
</field>
|
||||
<field id="priority" xsi:type="AttributeEnum">
|
||||
<sql>priority</sql>
|
||||
@@ -517,14 +501,14 @@
|
||||
</items>
|
||||
</details>
|
||||
<summary>
|
||||
<items>
|
||||
<item id="date">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="message">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
<items>
|
||||
<item id="date">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="message">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</summary>
|
||||
<list>
|
||||
<items>
|
||||
@@ -866,6 +850,18 @@
|
||||
<field id="language" xsi:type="AttributeApplicationLanguage"/>
|
||||
</fields>
|
||||
</class>
|
||||
<class id="Event" _delta="define">
|
||||
<!-- Generated by toolkit/export-class-to-meta.php -->
|
||||
<parent>DBObject</parent>
|
||||
<properties>
|
||||
<category>core/cmdb,view_in_gui</category>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="message" xsi:type="AttributeText"/>
|
||||
<field id="date" xsi:type="AttributeDateTime"/>
|
||||
<field id="userinfo" xsi:type="AttributeString"/>
|
||||
</fields>
|
||||
</class>
|
||||
<class id="EventNotification" _delta="define">
|
||||
<!-- Generated by toolkit/export-class-to-meta.php -->
|
||||
<parent>Event</parent>
|
||||
|
||||
@@ -212,6 +212,8 @@ abstract class DBObject implements iDisplay
|
||||
private $aEventListeners = [];
|
||||
private array $aAllowedTransitions = [];
|
||||
|
||||
private ?string $sStimulusBeingApplied = null;
|
||||
|
||||
/**
|
||||
* DBObject constructor.
|
||||
*
|
||||
@@ -1206,7 +1208,7 @@ abstract class DBObject implements iDisplay
|
||||
if ($aCallInfo["function"] != "ComputeValues") continue;
|
||||
return; //skip!
|
||||
}
|
||||
$this->FireEventComputeValues();
|
||||
$this->FireEventComputeValues($this->sStimulusBeingApplied);
|
||||
$oKPI = new ExecutionKPI();
|
||||
$this->ComputeValues();
|
||||
$oKPI->ComputeStatsForExtension($this, 'ComputeValues');
|
||||
@@ -2130,7 +2132,7 @@ abstract class DBObject implements iDisplay
|
||||
|
||||
return "Bad type";
|
||||
}
|
||||
elseif (($oAtt instanceof AttributeClassAttCodeSet) || ($oAtt instanceof AttributeEnumSet))
|
||||
elseif ($oAtt instanceof AttributeSet)
|
||||
{
|
||||
if (is_string($toCheck))
|
||||
{
|
||||
@@ -2669,7 +2671,7 @@ abstract class DBObject implements iDisplay
|
||||
|
||||
// Ultimate check - ensure DB integrity
|
||||
$this->SetReadOnly('No modification allowed during CheckToCreate');
|
||||
$this->FireEventCheckToWrite();
|
||||
$this->FireEventCheckToWrite($this->sStimulusBeingApplied);
|
||||
$this->SetReadWrite();
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
@@ -2865,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))
|
||||
@@ -3398,7 +3408,7 @@ abstract class DBObject implements iDisplay
|
||||
$this->OnInsert();
|
||||
$oKPI->ComputeStatsForExtension($this, 'OnInsert');
|
||||
|
||||
$this->FireEventBeforeWrite();
|
||||
$this->FireEventBeforeWrite(null);
|
||||
|
||||
// If not automatically computed, then check that the key is given by the caller
|
||||
if (!MetaModel::IsAutoIncrementKey($sRootClass)) {
|
||||
@@ -3533,7 +3543,7 @@ abstract class DBObject implements iDisplay
|
||||
*/
|
||||
protected function PostInsertActions(): void
|
||||
{
|
||||
$this->FireEventAfterWrite([], true);
|
||||
$this->FireEventAfterWrite([], true, null);
|
||||
$oKPI = new ExecutionKPI();
|
||||
$this->AfterInsert();
|
||||
$oKPI->ComputeStatsForExtension($this, 'AfterInsert');
|
||||
@@ -3641,7 +3651,7 @@ abstract class DBObject implements iDisplay
|
||||
$this->OnUpdate();
|
||||
$oKPI->ComputeStatsForExtension($this, 'OnUpdate');
|
||||
|
||||
$this->FireEventBeforeWrite();
|
||||
$this->FireEventBeforeWrite($this->sStimulusBeingApplied);
|
||||
|
||||
// Freeze the changes at this point
|
||||
$this->InitPreviousValuesForUpdatedAttributes();
|
||||
@@ -3809,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());
|
||||
@@ -3852,7 +3862,7 @@ abstract class DBObject implements iDisplay
|
||||
*/
|
||||
protected function PostUpdateActions(array $aChanges): void
|
||||
{
|
||||
$this->FireEventAfterWrite($aChanges, false);
|
||||
$this->FireEventAfterWrite($aChanges, false, $this->sStimulusBeingApplied);
|
||||
$oKPI = new ExecutionKPI();
|
||||
$this->AfterUpdate();
|
||||
$oKPI->ComputeStatsForExtension($this, 'AfterUpdate');
|
||||
@@ -3864,39 +3874,38 @@ abstract class DBObject implements iDisplay
|
||||
$this->ActivateOnObjectUpdateTriggersForTargetObjects();
|
||||
|
||||
$sClass = get_class($this);
|
||||
if (MetaModel::HasLifecycle($sClass))
|
||||
if (utils::IsNotNullOrEmptyString($this->sStimulusBeingApplied))
|
||||
{
|
||||
$this->sStimulusBeingApplied = null;
|
||||
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||
if (isset($this->m_aPreviousValuesForUpdatedAttributes[$sStateAttCode])) {
|
||||
$sPreviousState = $this->m_aPreviousValuesForUpdatedAttributes[$sStateAttCode];
|
||||
// Change state triggers...
|
||||
$aParams = array(
|
||||
'class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL),
|
||||
'previous_state' => $sPreviousState,
|
||||
'new_state' => $this->Get($sStateAttCode),
|
||||
);
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT TriggerOnStateLeave AS t WHERE t.target_class IN (:class_list) AND t.state=:previous_state'), array(), $aParams);
|
||||
while ($oTrigger = $oSet->Fetch()) {
|
||||
/** @var \TriggerOnStateLeave $oTrigger */
|
||||
try {
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
$sPreviousState = $this->m_aPreviousValuesForUpdatedAttributes[$sStateAttCode];
|
||||
// Change state triggers...
|
||||
$aParams = array(
|
||||
'class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL),
|
||||
'previous_state' => $sPreviousState,
|
||||
'new_state' => $this->Get($sStateAttCode),
|
||||
);
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT TriggerOnStateLeave AS t WHERE t.target_class IN (:class_list) AND t.state=:previous_state'), array(), $aParams);
|
||||
while ($oTrigger = $oSet->Fetch()) {
|
||||
/** @var \TriggerOnStateLeave $oTrigger */
|
||||
try {
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
}
|
||||
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT TriggerOnStateEnter AS t WHERE t.target_class IN (:class_list) AND t.state=:new_state'), array(), $aParams);
|
||||
while ($oTrigger = $oSet->Fetch()) {
|
||||
/** @var \TriggerOnStateEnter $oTrigger */
|
||||
try {
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT TriggerOnStateEnter AS t WHERE t.target_class IN (:class_list) AND t.state=:new_state'), array(), $aParams);
|
||||
while ($oTrigger = $oSet->Fetch()) {
|
||||
/** @var \TriggerOnStateEnter $oTrigger */
|
||||
try {
|
||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$oTrigger->LogException($e, $this);
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4024,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
|
||||
@@ -4603,6 +4612,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
if ($bSuccess)
|
||||
{
|
||||
$this->sStimulusBeingApplied = $sStimulusCode;
|
||||
// Stop watches
|
||||
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
||||
{
|
||||
@@ -6617,7 +6627,7 @@ abstract class DBObject implements iDisplay
|
||||
* @return void
|
||||
* @since 3.1.0
|
||||
*/
|
||||
protected function FireEventCheckToWrite(): void
|
||||
protected function FireEventCheckToWrite(?string $sStimulusBeingApplied): void
|
||||
{
|
||||
}
|
||||
|
||||
@@ -6625,7 +6635,7 @@ abstract class DBObject implements iDisplay
|
||||
* @return void
|
||||
* @since 3.1.0
|
||||
*/
|
||||
protected function FireEventBeforeWrite()
|
||||
protected function FireEventBeforeWrite(?string $sStimulusBeingApplied)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -6635,7 +6645,7 @@ abstract class DBObject implements iDisplay
|
||||
* @return void
|
||||
* @since 3.1.0
|
||||
*/
|
||||
protected function FireEventAfterWrite(array $aChanges, bool $bIsNew): void
|
||||
protected function FireEventAfterWrite(array $aChanges, bool $bIsNew, ?string $sStimulusBeingApplied): void
|
||||
{
|
||||
}
|
||||
|
||||
@@ -6673,7 +6683,7 @@ abstract class DBObject implements iDisplay
|
||||
* @return void
|
||||
* @since 3.1.0
|
||||
*/
|
||||
protected function FireEventComputeValues(): void
|
||||
protected function FireEventComputeValues(?string $sStimulusBeingApplied): void
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
|
||||
|
||||
@@ -1552,13 +1552,13 @@ abstract class DBSearch
|
||||
}
|
||||
|
||||
$sLogFile = 'queries.latest';
|
||||
file_put_contents(utils::GetDataPath().$sLogFile.'.html', $sHtml);
|
||||
file_put_contents(APPROOT.'data/'.$sLogFile.'.html', $sHtml);
|
||||
|
||||
$sLog = "<?php\n\$aQueriesLog = ".var_export(self::$m_aQueriesLog, true).";";
|
||||
file_put_contents(utils::GetDataPath().$sLogFile.'.log', $sLog);
|
||||
file_put_contents(APPROOT.'data/'.$sLogFile.'.log', $sLog);
|
||||
|
||||
// Cumulate the queries
|
||||
$sAllQueries = utils::GetDataPath().'queries.log';
|
||||
$sAllQueries = APPROOT.'data/queries.log';
|
||||
if (file_exists($sAllQueries))
|
||||
{
|
||||
// Merge the new queries into the existing log
|
||||
|
||||
@@ -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())));
|
||||
|
||||
@@ -131,7 +131,7 @@ class EventNotification extends Event
|
||||
"db_finalclass_field" => "",
|
||||
"order_by_default" => array('date' => false),
|
||||
'indexes' => array(
|
||||
array( 'object_class', 'object_id'),
|
||||
array('object_id'),
|
||||
)
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
@@ -139,11 +139,9 @@ class EventNotification extends Event
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass"=>"Trigger", "jointype"=> "", "allowed_values"=>null, "sql"=>"trigger_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass" => "Action", "jointype" => "", "allowed_values" => null, "sql" => "action_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("object_id", array("allowed_values" => null, "sql" => "object_id", "default_value" => 0, "is_null_allowed" => false, "depends_on" => array())));
|
||||
//@since 3.2.0
|
||||
MetaModel::Init_AddAttribute(new AttributeClass("object_class", array("class_category"=>"", "more_values"=>"", "sql"=>"object_class", "default_value"=>null, "is_null_allowed"=>true /*to avoid setting AbstractResource as default in database*/, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('date', 'message', 'userinfo', 'trigger_id', 'action_id', 'object_class', 'object_id')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('date', 'message', 'userinfo', 'trigger_id', 'action_id', 'object_id')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('date', 'message')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
|
||||
@@ -178,7 +176,7 @@ class EventNotificationEmail extends EventNotification
|
||||
MetaModel::Init_AddAttribute(new AttributeTable("attachments", array("allowed_values"=>null, "sql"=>"attachments", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'message', 'trigger_id', 'action_id', 'object_class', 'object_id', 'to', 'cc', 'bcc', 'from', 'subject', 'body', 'attachments')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'message', 'trigger_id', 'action_id', 'object_id', 'to', 'cc', 'bcc', 'from', 'subject', 'body', 'attachments')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('date', 'message', 'to', 'subject', 'attachments')); // Attributes to be displayed for a list
|
||||
|
||||
// Search criteria
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -7532,8 +7532,41 @@ abstract class MetaModel
|
||||
return $aEntries;
|
||||
}
|
||||
|
||||
public static function ResetAllCaches($sEnvironment = null)
|
||||
{
|
||||
if (is_null($sEnvironment)) {
|
||||
$sEnvironment = MetaModel::GetEnvironment();
|
||||
}
|
||||
|
||||
$sEnvironmentId = md5(APPROOT).'-'.$sEnvironment;
|
||||
$sAppIdentity = 'itop-'.$sEnvironmentId;
|
||||
require_once(APPROOT.'/core/dict.class.inc.php');
|
||||
Dict::ResetCache($sAppIdentity);
|
||||
|
||||
if (function_exists('apc_delete')) {
|
||||
foreach (self::GetCacheEntries($sEnvironmentId) as $sKey => $aAPCInfo) {
|
||||
$sAPCKey = $aAPCInfo['info'];
|
||||
apc_delete($sAPCKey);
|
||||
}
|
||||
}
|
||||
|
||||
require_once(APPROOT.'core/userrights.class.inc.php');
|
||||
UserRights::FlushPrivileges();
|
||||
|
||||
// Reset the opcache since otherwise the PHP "model" files may still be cached !!
|
||||
if (function_exists('opcache_reset')) {
|
||||
// Zend opcode cache
|
||||
opcache_reset();
|
||||
}
|
||||
|
||||
require_once(APPROOT.'setup/setuputils.class.inc.php');
|
||||
SetupUtils::rrmdir(utils::GetCachePath($sEnvironment));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param string $sEnvironmentId
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
public static function ResetCache($sEnvironmentId = null)
|
||||
{
|
||||
@@ -7557,6 +7590,13 @@ abstract class MetaModel
|
||||
|
||||
require_once(APPROOT.'core/userrights.class.inc.php');
|
||||
UserRights::FlushPrivileges();
|
||||
|
||||
// Reset the opcache since otherwise the PHP "model" files may still be cached !!
|
||||
if (function_exists('opcache_reset'))
|
||||
{
|
||||
// Zend opcode cache
|
||||
opcache_reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -182,14 +182,14 @@ class PHP_LexerGenerator_Lexer
|
||||
$this->token = self::COMMENTEND;
|
||||
return true;
|
||||
}
|
||||
if (preg_match('/\G%([a-z]+)/', $this->data, $token, null, $this->N)) {
|
||||
if (preg_match('/\G%([a-z]+)/', $this->data, $token, 0, $this->N)) {
|
||||
$this->value = $token[1];
|
||||
$this->N += strlen($token[1]) + 1;
|
||||
$this->state = 'DeclarePI';
|
||||
$this->token = self::PI;
|
||||
return true;
|
||||
}
|
||||
if (preg_match('/\G[a-zA-Z_][a-zA-Z0-9_]*/', $this->data, $token, null, $this->N)) {
|
||||
if (preg_match('/\G[a-zA-Z_][a-zA-Z0-9_]*/', $this->data, $token, 0, $this->N)) {
|
||||
$this->value = $token[0];
|
||||
$this->token = self::PATTERN;
|
||||
$this->N += strlen($token[0]);
|
||||
@@ -216,7 +216,7 @@ class PHP_LexerGenerator_Lexer
|
||||
if ($this->data[$this->N] == '{') {
|
||||
return $this->lexCode();
|
||||
}
|
||||
if (!preg_match("/\G[^\n]+/", $this->data, $token, null, $this->N)) {
|
||||
if (!preg_match("/\G[^\n]+/", $this->data, $token, 0, $this->N)) {
|
||||
$this->error('Unexpected end of file');
|
||||
return false;
|
||||
}
|
||||
@@ -242,7 +242,7 @@ class PHP_LexerGenerator_Lexer
|
||||
if ($this->data[$this->N] == '{') {
|
||||
return $this->lexCode();
|
||||
}
|
||||
if (!preg_match("/\G[^\n]+/", $this->data, $token, null, $this->N)) {
|
||||
if (!preg_match("/\G[^\n]+/", $this->data, $token, 0, $this->N)) {
|
||||
$this->error('Unexpected end of file');
|
||||
return false;
|
||||
}
|
||||
@@ -406,7 +406,7 @@ class PHP_LexerGenerator_Lexer
|
||||
if ($this->data[$this->N] == '\'') {
|
||||
return $this->lexQuote('\'');
|
||||
}
|
||||
if (preg_match('/\G%([a-zA-Z_]+)/', $this->data, $token, null, $this->N)) {
|
||||
if (preg_match('/\G%([a-zA-Z_]+)/', $this->data, $token, 0, $this->N)) {
|
||||
$this->value = $token[1];
|
||||
$this->N += strlen($token[1]) + 1;
|
||||
$this->state = 'DeclarePIRule';
|
||||
@@ -419,7 +419,7 @@ class PHP_LexerGenerator_Lexer
|
||||
if ($this->data[$this->N] == '"') {
|
||||
return $this->lexQuote();
|
||||
}
|
||||
if (preg_match('/\G[a-zA-Z_][a-zA-Z0-9_]*/', $this->data, $token, null, $this->N)) {
|
||||
if (preg_match('/\G[a-zA-Z_][a-zA-Z0-9_]*/', $this->data, $token, 0, $this->N)) {
|
||||
$this->value = $token[0];
|
||||
$this->N += strlen($token[0]);
|
||||
$this->token = self::SUBPATTERN;
|
||||
|
||||
@@ -33,17 +33,19 @@ class PHP_LexerGenerator_ParseryyToken implements ArrayAccess
|
||||
return $this->_string;
|
||||
}
|
||||
|
||||
function offsetExists($offset)
|
||||
function offsetExists($offset): bool
|
||||
{
|
||||
return isset($this->metadata[$offset]);
|
||||
}
|
||||
|
||||
// Return type mixed is not supported by PHP 7.4, we can remove the following PHP attribute and add the return type once iTop min PHP version is PHP 8.0+
|
||||
#[\ReturnTypeWillChange]
|
||||
function offsetGet($offset)
|
||||
{
|
||||
return $this->metadata[$offset];
|
||||
}
|
||||
|
||||
function offsetSet($offset, $value)
|
||||
function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($offset === null) {
|
||||
if (isset($value[0])) {
|
||||
@@ -66,7 +68,7 @@ class PHP_LexerGenerator_ParseryyToken implements ArrayAccess
|
||||
}
|
||||
}
|
||||
|
||||
function offsetUnset($offset)
|
||||
function offsetUnset($offset): void
|
||||
{
|
||||
unset($this->metadata[$offset]);
|
||||
}
|
||||
@@ -278,7 +280,7 @@ class PHP_LexerGenerator_Parser#line 171 "Parser.php"
|
||||
$match = false;
|
||||
foreach ($yy_yymore_patterns[' . $this->token . '] as $index => $rule) {
|
||||
if (preg_match(\'/\' . $rule . \'/' . $this->patternFlags . '\',
|
||||
' . $this->input . ', $yymatches, null, ' . $this->counter . ')) {
|
||||
' . $this->input . ', $yymatches, 0, ' . $this->counter . ')) {
|
||||
$yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns
|
||||
if ($match) {
|
||||
if (strlen($yymatches[0]) > strlen($match[0][0])) {
|
||||
@@ -350,7 +352,7 @@ class PHP_LexerGenerator_Parser#line 171 "Parser.php"
|
||||
$pattern . '\';' . "\n");
|
||||
fwrite($this->out, '
|
||||
do {
|
||||
if (preg_match($yy_global_pattern,' . $this->input . ', $yymatches, null, ' .
|
||||
if (preg_match($yy_global_pattern,' . $this->input . ', $yymatches, 0, ' .
|
||||
$this->counter .
|
||||
')) {
|
||||
$yysubmatches = $yymatches;
|
||||
@@ -408,7 +410,7 @@ class PHP_LexerGenerator_Parser#line 171 "Parser.php"
|
||||
}
|
||||
$yysubmatches = array();
|
||||
if (preg_match(\'/\' . $yy_yymore_patterns[' . $this->token . '][1] . \'/' . $this->patternFlags . '\',
|
||||
' . $this->input . ', $yymatches, null, ' . $this->counter .')) {
|
||||
' . $this->input . ', $yymatches, 0, ' . $this->counter .')) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
|
||||
@@ -187,7 +187,7 @@ require_once 'PHP/LexerGenerator/Exception.php';
|
||||
$match = false;
|
||||
foreach ($yy_yymore_patterns[' . $this->token . '] as $index => $rule) {
|
||||
if (preg_match(\'/\' . $rule . \'/' . $this->patternFlags . '\',
|
||||
' . $this->input . ', $yymatches, null, ' . $this->counter . ')) {
|
||||
' . $this->input . ', $yymatches, 0, ' . $this->counter . ')) {
|
||||
$yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns
|
||||
if ($match) {
|
||||
if (strlen($yymatches[0]) > strlen($match[0][0])) {
|
||||
@@ -259,7 +259,7 @@ require_once 'PHP/LexerGenerator/Exception.php';
|
||||
$pattern . '\';' . "\n");
|
||||
fwrite($this->out, '
|
||||
do {
|
||||
if (preg_match($yy_global_pattern,' . $this->input . ', $yymatches, null, ' .
|
||||
if (preg_match($yy_global_pattern,' . $this->input . ', $yymatches, 0, ' .
|
||||
$this->counter .
|
||||
')) {
|
||||
$yysubmatches = $yymatches;
|
||||
@@ -317,7 +317,7 @@ require_once 'PHP/LexerGenerator/Exception.php';
|
||||
}
|
||||
$yysubmatches = array();
|
||||
if (preg_match(\'/\' . $yy_yymore_patterns[' . $this->token . '][1] . \'/' . $this->patternFlags . '\',
|
||||
' . $this->input . ', $yymatches, null, ' . $this->counter .')) {
|
||||
' . $this->input . ', $yymatches, 0, ' . $this->counter .')) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
|
||||
@@ -110,7 +110,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
$yy_global_pattern = '/\G(\\\\\\\\)|\G([^[\\\\^$.|()?*+{}]+)|\G(\\\\[][{}*.^$|?()+])|\G(\\[)|\G(\\|)|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[0-9][0-9])|\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)/';
|
||||
|
||||
do {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
if (!count($yymatches)) {
|
||||
@@ -180,7 +180,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
}
|
||||
$yysubmatches = array();
|
||||
if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/',
|
||||
$this->input, $yymatches, null, $this->N)) {
|
||||
$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
@@ -360,7 +360,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
$yy_global_pattern = '/\G(\\^)|\G(\\])|\G(.)/';
|
||||
|
||||
do {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
if (!count($yymatches)) {
|
||||
@@ -410,7 +410,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
}
|
||||
$yysubmatches = array();
|
||||
if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/',
|
||||
$this->input, $yymatches, null, $this->N)) {
|
||||
$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
@@ -497,7 +497,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
$yy_global_pattern = '/\G(\\\\\\\\)|\G(\\])|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G(\\\\[]\.\-\^])|\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)/';
|
||||
|
||||
do {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
if (!count($yymatches)) {
|
||||
@@ -555,7 +555,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
}
|
||||
$yysubmatches = array();
|
||||
if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/',
|
||||
$this->input, $yymatches, null, $this->N)) {
|
||||
$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
@@ -678,7 +678,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
$yy_global_pattern = '/\G(\\\\\\\\)|\G(\\\\\\])|\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G([^\-\\\\])|\G(\\\\)/';
|
||||
|
||||
do {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
if (!count($yymatches)) {
|
||||
@@ -732,7 +732,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
}
|
||||
$yysubmatches = array();
|
||||
if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/',
|
||||
$this->input, $yymatches, null, $this->N)) {
|
||||
$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
@@ -842,7 +842,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
$yy_global_pattern = '/\G([imsxUX]+-[imsxUX]+|[imsxUX]+|-[imsxUX]+)|\G(:)|\G(\\))|\G(P<[^>]+>)|\G(<=)|\G(<!)|\G(=)|\G(!)|\G(>)|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)/';
|
||||
|
||||
do {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) {
|
||||
if (preg_match($yy_global_pattern,$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
if (!count($yymatches)) {
|
||||
@@ -902,7 +902,7 @@ class PHP_LexerGenerator_Regex_Lexer
|
||||
}
|
||||
$yysubmatches = array();
|
||||
if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/',
|
||||
$this->input, $yymatches, null, $this->N)) {
|
||||
$this->input, $yymatches, 0, $this->N)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
|
||||
@@ -33,17 +33,19 @@ class PHP_LexerGenerator_Regex_yyToken implements ArrayAccess
|
||||
return $this->_string;
|
||||
}
|
||||
|
||||
function offsetExists($offset)
|
||||
function offsetExists($offset): bool
|
||||
{
|
||||
return isset($this->metadata[$offset]);
|
||||
}
|
||||
|
||||
// Return type mixed is not supported by PHP 7.4, we can remove the following PHP attribute and add the return type once iTop min PHP version is PHP 8.0+
|
||||
#[\ReturnTypeWillChange]
|
||||
function offsetGet($offset)
|
||||
{
|
||||
return $this->metadata[$offset];
|
||||
}
|
||||
|
||||
function offsetSet($offset, $value)
|
||||
function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($offset === null) {
|
||||
if (isset($value[0])) {
|
||||
@@ -66,7 +68,7 @@ class PHP_LexerGenerator_Regex_yyToken implements ArrayAccess
|
||||
}
|
||||
}
|
||||
|
||||
function offsetUnset($offset)
|
||||
function offsetUnset($offset): void
|
||||
{
|
||||
unset($this->metadata[$offset]);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -235,7 +235,7 @@ class OQLLexerRaw
|
||||
$match = false;
|
||||
foreach ($yy_yymore_patterns[$this->token] as $index => $rule) {
|
||||
if (preg_match('/' . $rule . '/',
|
||||
$this->data, $yymatches, null, $this->count)) {
|
||||
$this->data, $yymatches, 0, $this->count)) {
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
if ($match) {
|
||||
if (strlen($yymatches[0]) > strlen($match[0][0])) {
|
||||
|
||||
@@ -36,7 +36,13 @@ class UnknownClassOqlException extends OqlNormalizeException
|
||||
{
|
||||
public function __construct($sInput, OqlName $oName, $aExpecting = null)
|
||||
{
|
||||
parent::__construct('Unknown class', $sInput, $oName, $aExpecting);
|
||||
$aAllowedClasses = [];
|
||||
foreach ($aExpecting as $sClass) {
|
||||
if (UserRights::IsActionAllowed($sClass, UR_ACTION_READ)) {
|
||||
$aAllowedClasses[] = $sClass;
|
||||
}
|
||||
}
|
||||
parent::__construct('Unknown class', $sInput, $oName, $aAllowedClasses);
|
||||
}
|
||||
|
||||
public function GetUserFriendlyDescription()
|
||||
|
||||
@@ -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 '';
|
||||
@@ -314,7 +380,7 @@ class ormDocument
|
||||
'document' => $oDocument,
|
||||
'content_disposition' => $sContentDisposition,
|
||||
);
|
||||
EventService::FireEvent(new EventData(EVENT_DOWNLOAD_DOCUMENT, $sClass, $aEventData));
|
||||
EventService::FireEvent(new EventData(\EVENT_DOWNLOAD_DOCUMENT, $sClass, $aEventData));
|
||||
$oPage->TrashUnexpectedOutput();
|
||||
$oPage->SetContentType($oDocument->GetMimeType());
|
||||
$oPage->SetContentDisposition($sContentDisposition,$oDocument->GetFileName());
|
||||
|
||||
@@ -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())));
|
||||
|
||||
@@ -500,17 +500,17 @@ EOF
|
||||
if (file_exists($sDotExecutable))
|
||||
{
|
||||
// create the file with Graphviz
|
||||
if (!is_dir(utils::GetDataPath()))
|
||||
if (!is_dir(APPROOT."data"))
|
||||
{
|
||||
@mkdir(utils::GetDataPath());
|
||||
@mkdir(APPROOT."data");
|
||||
}
|
||||
if (!is_dir(utils::GetDataPath()."tmp"))
|
||||
if (!is_dir(APPROOT."data/tmp"))
|
||||
{
|
||||
@mkdir(utils::GetDataPath()."tmp");
|
||||
@mkdir(APPROOT."data/tmp");
|
||||
}
|
||||
$sImageFilePath = tempnam(utils::GetDataPath()."tmp", 'png-');
|
||||
$sImageFilePath = tempnam(APPROOT."data/tmp", 'png-');
|
||||
$sDotDescription = $this->GetDotDescription();
|
||||
$sDotFilePath = tempnam(utils::GetDataPath()."tmp", 'dot-');
|
||||
$sDotFilePath = tempnam(APPROOT."data/tmp", 'dot-');
|
||||
|
||||
$rFile = @fopen($sDotFilePath, "w");
|
||||
@fwrite($rFile, $sDotDescription);
|
||||
@@ -556,17 +556,17 @@ EOF
|
||||
if (file_exists($sDotExecutable))
|
||||
{
|
||||
// create the file with Graphviz
|
||||
if (!is_dir(utils::GetDataPath()))
|
||||
if (!is_dir(APPROOT."data"))
|
||||
{
|
||||
@mkdir(utils::GetDataPath());
|
||||
@mkdir(APPROOT."data");
|
||||
}
|
||||
if (!is_dir(utils::GetDataPath()."tmp"))
|
||||
if (!is_dir(APPROOT."data/tmp"))
|
||||
{
|
||||
@mkdir(utils::GetDataPath()."tmp");
|
||||
@mkdir(APPROOT."data/tmp");
|
||||
}
|
||||
$sXdotFilePath = tempnam(utils::GetDataPath()."tmp", 'xdot-');
|
||||
$sXdotFilePath = tempnam(APPROOT."data/tmp", 'xdot-');
|
||||
$sDotDescription = $this->GetDotDescription(true); // true => don't put (localized) labels in the file, since it makes it harder to parse
|
||||
$sDotFilePath = tempnam(utils::GetDataPath()."tmp", 'dot-');
|
||||
$sDotFilePath = tempnam(APPROOT."data/tmp", 'dot-');
|
||||
|
||||
$rFile = @fopen($sDotFilePath, "w");
|
||||
@fwrite($rFile, $sDotDescription);
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
2
css/backoffice/vendors/ckeditor/_all.scss
vendored
2
css/backoffice/vendors/ckeditor/_all.scss
vendored
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
5
css/c3.min.css
vendored
Normal file
5
css/c3.min.css
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
* @deprecated 3.2.0 N°5621 Moved to NPM
|
||||
*/
|
||||
|
||||
.c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*!
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
|
||||
/* Semantic palettes */
|
||||
/* - Primary color of the brand */
|
||||
$common-color-primary-100: $common-color-blue-100 !default;
|
||||
$common-color-primary-200: $common-color-blue-200 !default;
|
||||
$common-color-primary-300: $common-color-blue-300 !default;
|
||||
$common-color-primary-400: $common-color-blue-400 !default;
|
||||
$common-color-primary-500: $common-color-blue-500 !default;
|
||||
$common-color-primary-600: $common-color-blue-600 !default;
|
||||
$common-color-primary-700: $common-color-blue-700 !default;
|
||||
$common-color-primary-800: $common-color-blue-800 !default;
|
||||
$common-color-primary-900: $common-color-blue-900 !default;
|
||||
$common-color-primary-950: $common-color-blue-950 !default;
|
||||
$common-color-primary-100: $common-color-orange-100 !default;
|
||||
$common-color-primary-200: $common-color-orange-200 !default;
|
||||
$common-color-primary-300: $common-color-orange-300 !default;
|
||||
$common-color-primary-400: $common-color-orange-400 !default;
|
||||
$common-color-primary-500: $common-color-orange-500 !default;
|
||||
$common-color-primary-600: $common-color-orange-600 !default;
|
||||
$common-color-primary-700: $common-color-orange-700 !default;
|
||||
$common-color-primary-800: $common-color-orange-800 !default;
|
||||
$common-color-primary-900: $common-color-orange-900 !default;
|
||||
$common-color-primary-950: $common-color-orange-950 !default;
|
||||
|
||||
/* - Secondary color of the brand */
|
||||
$common-color-secondary-100: $common-color-grey-100 !default;
|
||||
|
||||
146
css/jquery.contextMenu.css
Executable file
146
css/jquery.contextMenu.css
Executable file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @deprecated 3.2.0 N°5621 Moved to NPM
|
||||
*/
|
||||
|
||||
/*!
|
||||
* jQuery contextMenu - Plugin for simple contextMenu handling
|
||||
*
|
||||
* Version: git-master
|
||||
*
|
||||
* Authors: Rodney Rehm, Addy Osmani (patches for FF)
|
||||
* Web: http://medialize.github.com/jQuery-contextMenu/
|
||||
*
|
||||
* Licensed under
|
||||
* MIT License http://www.opensource.org/licenses/mit-license
|
||||
* GPL v3 http://opensource.org/licenses/GPL-3.0
|
||||
*
|
||||
*/
|
||||
|
||||
.context-menu-list {
|
||||
margin:0;
|
||||
padding:0;
|
||||
|
||||
min-width: 120px;
|
||||
max-width: 250px;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
list-style-type: none;
|
||||
|
||||
border: 1px solid #DDD;
|
||||
background: #EEE;
|
||||
|
||||
-webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
|
||||
-ms-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
|
||||
-o-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
|
||||
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.context-menu-item {
|
||||
padding: 2px 2px 2px 24px;
|
||||
background-color: #EEE;
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: -moz-none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.context-menu-separator {
|
||||
padding-bottom:0;
|
||||
border-bottom: 1px solid #DDD;
|
||||
}
|
||||
|
||||
.context-menu-item > label > input,
|
||||
.context-menu-item > label > textarea {
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.context-menu-item.hover {
|
||||
cursor: pointer;
|
||||
background-color: #39F;
|
||||
}
|
||||
|
||||
.context-menu-item.disabled {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.context-menu-input.hover,
|
||||
.context-menu-item.disabled.hover {
|
||||
cursor: default;
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
.context-menu-submenu:after {
|
||||
content: ">";
|
||||
color: #666;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 3px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* icons
|
||||
#protip:
|
||||
In case you want to use sprites for icons (which I would suggest you do) have a look at
|
||||
http://css-tricks.com/13224-pseudo-spriting/ to get an idea of how to implement
|
||||
.context-menu-item.icon:before {}
|
||||
*/
|
||||
.context-menu-item.icon { min-height: 18px; background-repeat: no-repeat; background-position: 4px 2px; }
|
||||
.context-menu-item.icon-edit { background-image: url(images/page_white_edit.png); }
|
||||
.context-menu-item.icon-cut { background-image: url(images/cut.png); }
|
||||
.context-menu-item.icon-copy { background-image: url(images/page_white_copy.png); }
|
||||
.context-menu-item.icon-paste { background-image: url(images/page_white_paste.png); }
|
||||
.context-menu-item.icon-delete { background-image: url(images/page_white_delete.png); }
|
||||
.context-menu-item.icon-add { background-image: url(images/page_white_add.png); }
|
||||
.context-menu-item.icon-quit { background-image: url(images/door.png); }
|
||||
|
||||
/* vertically align inside labels */
|
||||
.context-menu-input > label > * { vertical-align: top; }
|
||||
|
||||
/* position checkboxes and radios as icons */
|
||||
.context-menu-input > label > input[type="checkbox"],
|
||||
.context-menu-input > label > input[type="radio"] {
|
||||
margin-left: -17px;
|
||||
}
|
||||
.context-menu-input > label > span {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.context-menu-input > label,
|
||||
.context-menu-input > label > input[type="text"],
|
||||
.context-menu-input > label > textarea,
|
||||
.context-menu-input > label > select {
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
-o-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.context-menu-input > label > textarea {
|
||||
height: 100px;
|
||||
}
|
||||
.context-menu-item > .context-menu-list {
|
||||
display: none;
|
||||
/* re-positioned by js */
|
||||
right: -5px;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.context-menu-item.hover > .context-menu-list {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.context-menu-accesskey {
|
||||
text-decoration: underline;
|
||||
}
|
||||
378
css/magnific-popup.css
Normal file
378
css/magnific-popup.css
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* @deprecated 3.2.0 N°5621 Moved to NPM
|
||||
*/
|
||||
|
||||
/* Magnific Popup CSS */
|
||||
.mfp-bg {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1042;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
background: #0b0b0b;
|
||||
opacity: 0.8;
|
||||
filter: alpha(opacity=80); }
|
||||
|
||||
.mfp-wrap {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1043;
|
||||
position: fixed;
|
||||
outline: none !important;
|
||||
-webkit-backface-visibility: hidden; }
|
||||
|
||||
.mfp-container {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
padding: 0 8px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box; }
|
||||
|
||||
.mfp-container:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
vertical-align: middle; }
|
||||
|
||||
.mfp-align-top .mfp-container:before {
|
||||
display: none; }
|
||||
|
||||
.mfp-content {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 0 auto;
|
||||
text-align: left;
|
||||
z-index: 1045; }
|
||||
|
||||
.mfp-inline-holder .mfp-content, .mfp-ajax-holder .mfp-content {
|
||||
width: 100%;
|
||||
cursor: auto; }
|
||||
|
||||
.mfp-ajax-cur {
|
||||
cursor: progress; }
|
||||
|
||||
.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
|
||||
cursor: -moz-zoom-out;
|
||||
cursor: -webkit-zoom-out;
|
||||
cursor: zoom-out; }
|
||||
|
||||
.mfp-zoom {
|
||||
cursor: pointer;
|
||||
cursor: -webkit-zoom-in;
|
||||
cursor: -moz-zoom-in;
|
||||
cursor: zoom-in; }
|
||||
|
||||
.mfp-auto-cursor .mfp-content {
|
||||
cursor: auto; }
|
||||
|
||||
.mfp-close, .mfp-arrow, .mfp-preloader, .mfp-counter {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none; }
|
||||
|
||||
.mfp-loading.mfp-figure {
|
||||
display: none; }
|
||||
|
||||
.mfp-hide {
|
||||
display: none !important; }
|
||||
|
||||
.mfp-preloader {
|
||||
color: #CCC;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: auto;
|
||||
text-align: center;
|
||||
margin-top: -0.8em;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
z-index: 1044; }
|
||||
.mfp-preloader a {
|
||||
color: #CCC; }
|
||||
.mfp-preloader a:hover {
|
||||
color: #FFF; }
|
||||
|
||||
.mfp-s-ready .mfp-preloader {
|
||||
display: none; }
|
||||
|
||||
.mfp-s-error .mfp-content {
|
||||
display: none; }
|
||||
|
||||
button.mfp-close, button.mfp-arrow {
|
||||
overflow: visible;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
-webkit-appearance: none;
|
||||
display: block;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
z-index: 1046;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none; }
|
||||
button::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0; }
|
||||
|
||||
.mfp-close {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
opacity: 0.65;
|
||||
filter: alpha(opacity=65);
|
||||
padding: 0 0 18px 10px;
|
||||
color: #FFF;
|
||||
font-style: normal;
|
||||
font-size: 28px;
|
||||
font-family: Arial, Baskerville, monospace; }
|
||||
.mfp-close:hover, .mfp-close:focus {
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100); }
|
||||
.mfp-close:active {
|
||||
top: 1px; }
|
||||
|
||||
.mfp-close-btn-in .mfp-close {
|
||||
color: #333; }
|
||||
|
||||
.mfp-image-holder .mfp-close, .mfp-iframe-holder .mfp-close {
|
||||
color: #FFF;
|
||||
right: -6px;
|
||||
text-align: right;
|
||||
padding-right: 6px;
|
||||
width: 100%; }
|
||||
|
||||
.mfp-counter {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
color: #CCC;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap; }
|
||||
|
||||
.mfp-arrow {
|
||||
position: absolute;
|
||||
opacity: 0.65;
|
||||
filter: alpha(opacity=65);
|
||||
margin: 0;
|
||||
top: 50%;
|
||||
margin-top: -55px;
|
||||
padding: 0;
|
||||
width: 90px;
|
||||
height: 110px;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
|
||||
.mfp-arrow:active {
|
||||
margin-top: -54px; }
|
||||
.mfp-arrow:hover, .mfp-arrow:focus {
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100); }
|
||||
.mfp-arrow:before, .mfp-arrow:after, .mfp-arrow .mfp-b, .mfp-arrow .mfp-a {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin-top: 35px;
|
||||
margin-left: 35px;
|
||||
border: medium inset transparent; }
|
||||
.mfp-arrow:after, .mfp-arrow .mfp-a {
|
||||
border-top-width: 13px;
|
||||
border-bottom-width: 13px;
|
||||
top: 8px; }
|
||||
.mfp-arrow:before, .mfp-arrow .mfp-b {
|
||||
border-top-width: 21px;
|
||||
border-bottom-width: 21px;
|
||||
opacity: 0.7; }
|
||||
|
||||
.mfp-arrow-left {
|
||||
left: 0; }
|
||||
.mfp-arrow-left:after, .mfp-arrow-left .mfp-a {
|
||||
border-right: 17px solid #FFF;
|
||||
margin-left: 31px; }
|
||||
.mfp-arrow-left:before, .mfp-arrow-left .mfp-b {
|
||||
margin-left: 25px;
|
||||
border-right: 27px solid #3F3F3F; }
|
||||
|
||||
.mfp-arrow-right {
|
||||
right: 0; }
|
||||
.mfp-arrow-right:after, .mfp-arrow-right .mfp-a {
|
||||
border-left: 17px solid #FFF;
|
||||
margin-left: 39px; }
|
||||
.mfp-arrow-right:before, .mfp-arrow-right .mfp-b {
|
||||
border-left: 27px solid #3F3F3F; }
|
||||
|
||||
.mfp-iframe-holder {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px; }
|
||||
.mfp-iframe-holder .mfp-content {
|
||||
line-height: 0;
|
||||
width: 100%;
|
||||
max-width: 900px; }
|
||||
.mfp-iframe-holder .mfp-close {
|
||||
top: -40px; }
|
||||
|
||||
.mfp-iframe-scaler {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
padding-top: 56.25%; }
|
||||
.mfp-iframe-scaler iframe {
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
||||
background: #000; }
|
||||
|
||||
/* Main image in popup */
|
||||
img.mfp-img {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
line-height: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
padding: 40px 0 40px;
|
||||
margin: 0 auto; }
|
||||
|
||||
/* The shadow behind the image */
|
||||
.mfp-figure {
|
||||
line-height: 0; }
|
||||
.mfp-figure:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 40px;
|
||||
bottom: 40px;
|
||||
display: block;
|
||||
right: 0;
|
||||
width: auto;
|
||||
height: auto;
|
||||
z-index: -1;
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
||||
background: #444; }
|
||||
.mfp-figure small {
|
||||
color: #BDBDBD;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
line-height: 14px; }
|
||||
.mfp-figure figure {
|
||||
margin: 0; }
|
||||
|
||||
.mfp-bottom-bar {
|
||||
margin-top: -36px;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
cursor: auto; }
|
||||
|
||||
.mfp-title {
|
||||
text-align: left;
|
||||
line-height: 18px;
|
||||
color: #F3F3F3;
|
||||
word-wrap: break-word;
|
||||
padding-right: 36px; }
|
||||
|
||||
.mfp-image-holder .mfp-content {
|
||||
max-width: 100%; }
|
||||
|
||||
.mfp-gallery .mfp-image-holder .mfp-figure {
|
||||
cursor: pointer; }
|
||||
|
||||
@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) {
|
||||
/**
|
||||
* Remove all paddings around the image on small screen
|
||||
*/
|
||||
.mfp-img-mobile .mfp-image-holder {
|
||||
padding-left: 0;
|
||||
padding-right: 0; }
|
||||
.mfp-img-mobile img.mfp-img {
|
||||
padding: 0; }
|
||||
.mfp-img-mobile .mfp-figure:after {
|
||||
top: 0;
|
||||
bottom: 0; }
|
||||
.mfp-img-mobile .mfp-figure small {
|
||||
display: inline;
|
||||
margin-left: 5px; }
|
||||
.mfp-img-mobile .mfp-bottom-bar {
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
top: auto;
|
||||
padding: 3px 5px;
|
||||
position: fixed;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box; }
|
||||
.mfp-img-mobile .mfp-bottom-bar:empty {
|
||||
padding: 0; }
|
||||
.mfp-img-mobile .mfp-counter {
|
||||
right: 5px;
|
||||
top: 3px; }
|
||||
.mfp-img-mobile .mfp-close {
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
padding: 0; }
|
||||
}
|
||||
|
||||
@media all and (max-width: 900px) {
|
||||
.mfp-arrow {
|
||||
-webkit-transform: scale(0.75);
|
||||
transform: scale(0.75); }
|
||||
|
||||
.mfp-arrow-left {
|
||||
-webkit-transform-origin: 0;
|
||||
transform-origin: 0; }
|
||||
|
||||
.mfp-arrow-right {
|
||||
-webkit-transform-origin: 100%;
|
||||
transform-origin: 100%; }
|
||||
|
||||
.mfp-container {
|
||||
padding-left: 6px;
|
||||
padding-right: 6px; }
|
||||
}
|
||||
|
||||
.mfp-ie7 .mfp-img {
|
||||
padding: 0; }
|
||||
.mfp-ie7 .mfp-bottom-bar {
|
||||
width: 600px;
|
||||
left: 50%;
|
||||
margin-left: -300px;
|
||||
margin-top: 5px;
|
||||
padding-bottom: 5px; }
|
||||
.mfp-ie7 .mfp-container {
|
||||
padding: 0; }
|
||||
.mfp-ie7 .mfp-content {
|
||||
padding-top: 44px; }
|
||||
.mfp-ie7 .mfp-close {
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding-top: 0; }
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<constants>
|
||||
</constants>
|
||||
<classes>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'CAS:Error:UserNotAllowed' => 'User not allowed',
|
||||
'CAS:Login:SignIn' => 'Sign in with CAS',
|
||||
'CAS:Login:SignInTooltip' => 'Click here to authenticate yourself with the CAS server',
|
||||
));
|
||||
@@ -4,11 +4,8 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'CAS:Error:UserNotAllowed' => '用户被禁止登录',
|
||||
'CAS:Login:SignIn' => '使用CAS登录',
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-cas/3.3.0',
|
||||
'authent-cas/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -160,8 +160,7 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
private static function InitCASClient()
|
||||
{
|
||||
$bCASDebug = Config::Get('cas_debug');
|
||||
if ($bCASDebug)
|
||||
{
|
||||
if ($bCASDebug) {
|
||||
phpCAS::setLogger(new CASLogger(APPROOT.'log/cas.log'));
|
||||
}
|
||||
|
||||
@@ -171,18 +170,17 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
|
||||
$iCASPort = Config::Get('cas_port');
|
||||
$sCASContext = Config::Get('cas_context');
|
||||
$sServiceBaseURL = Config::Get('service_base_url', self::GetServiceBaseURL());
|
||||
phpCAS::client($sCASVersion, $sCASHost, $iCASPort, $sCASContext, $sServiceBaseURL, false /* session already started */);
|
||||
if (!phpCAS::isInitialized()) {
|
||||
phpCAS::client($sCASVersion, $sCASHost, $iCASPort, $sCASContext, $sServiceBaseURL, false /* session already started */);
|
||||
}
|
||||
$sCASCACertPath = Config::Get('cas_server_ca_cert_path');
|
||||
if (empty($sCASCACertPath))
|
||||
{
|
||||
if (empty($sCASCACertPath)) {
|
||||
// If no certificate authority is provided, do not attempt to validate
|
||||
// the server's certificate
|
||||
// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
|
||||
// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
|
||||
phpCAS::setNoCasServerValidation();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
phpCAS::setCasServerCACert($sCASCACertPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserExternal
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Class:UserExternal' => 'External user',
|
||||
'Class:UserExternal+' => 'User authentified outside of '.ITOP_APPLICATION_SHORT,
|
||||
));
|
||||
@@ -4,12 +4,39 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Robert Deng <denglx@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserExternal
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:UserExternal' => '外部用户',
|
||||
'Class:UserExternal+' => '用户在'.ITOP_APPLICATION_SHORT.'外部验证身份',
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-external/3.3.0',
|
||||
'authent-external/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<classes>
|
||||
<class id="UserLDAP" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
|
||||
@@ -37,6 +37,6 @@
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:UserLDAP' => 'LDAP user',
|
||||
'Class:UserLDAP+' => 'User authentified by LDAP',
|
||||
'Class:UserLDAP+' => 'User authenticated by LDAP',
|
||||
'UserLDAP:server' => 'LDAP specifics',
|
||||
));
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLDAP
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Class:UserLDAP' => 'LDAP user',
|
||||
'Class:UserLDAP+' => 'User authenticated by LDAP',
|
||||
'UserLDAP:server' => 'LDAP specifics',
|
||||
));
|
||||
@@ -11,6 +11,6 @@
|
||||
*/
|
||||
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'Class:UserLDAP' => 'LDAP užívateľ',
|
||||
'Class:UserLDAP+' => 'User authentified by LDAP~~',
|
||||
'Class:UserLDAP+' => 'User authenticated by LDAP~~',
|
||||
'UserLDAP:server' => 'LDAP specifics~~',
|
||||
]);
|
||||
|
||||
@@ -4,12 +4,38 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Robert Deng <denglx@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLDAP
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:UserLDAP' => 'LDAP用户',
|
||||
'Class:UserLDAP+' => '用户身份由LDAP认证',
|
||||
|
||||
@@ -9,7 +9,7 @@ if (function_exists('ldap_connect'))
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-ldap/3.3.0',
|
||||
'authent-ldap/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<module_parameters>
|
||||
<parameters id="authent-local" _delta="define">
|
||||
<password_validation.pattern>^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$</password_validation.pattern>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLocal
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Class:UserLocal' => ITOP_APPLICATION_SHORT.' user',
|
||||
'Class:UserLocal+' => 'User authentified by '.ITOP_APPLICATION_SHORT,
|
||||
'Class:UserLocal/Attribute:password' => 'Password',
|
||||
'Class:UserLocal/Attribute:password+' => 'User authentication string',
|
||||
|
||||
'Class:UserLocal/Attribute:expiration' => 'Password expiration',
|
||||
'Class:UserLocal/Attribute:expiration+' => 'Password expiration status (requires an extension to have an effect)',
|
||||
'Class:UserLocal/Attribute:expiration/Value:can_expire' => 'Can expire',
|
||||
'Class:UserLocal/Attribute:expiration/Value:can_expire+' => '',
|
||||
'Class:UserLocal/Attribute:expiration/Value:never_expire' => 'Never expire',
|
||||
'Class:UserLocal/Attribute:expiration/Value:never_expire+' => '',
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire' => 'Expired',
|
||||
'Class:UserLocal/Attribute:expiration/Value:force_expire+' => '',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => 'One-time Password',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => 'Password cannot be changed by the user.',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => 'Password renewed on',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => 'When the password was last changed',
|
||||
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Password must be at least 8 characters and include uppercase, lowercase, numeric and special characters.',
|
||||
'UserLocal:password:expiration' => 'The fields below require an extension',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User',
|
||||
));
|
||||
@@ -4,15 +4,44 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Robert Deng <denglx@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLocal
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:UserLocal' => ITOP_APPLICATION_SHORT.' 用户',
|
||||
'Class:UserLocal+' => '用户由'.ITOP_APPLICATION_SHORT.'验证身份',
|
||||
'Class:UserLocal/Attribute:password' => '密码',
|
||||
'Class:UserLocal/Attribute:password+' => '用于验证用户身份的字符串',
|
||||
|
||||
'Class:UserLocal/Attribute:expiration' => '密码过期',
|
||||
'Class:UserLocal/Attribute:expiration+' => '密码过期状态 (需要一个扩展才能生效)',
|
||||
'Class:UserLocal/Attribute:expiration/Value:can_expire' => '允许过期',
|
||||
@@ -23,11 +52,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:UserLocal/Attribute:expiration/Value:never_expire+' => '',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire' => '一次性密码',
|
||||
'Class:UserLocal/Attribute:expiration/Value:otp_expire+' => '用户不允许修改密码.',
|
||||
'Class:UserLocal/Attribute:password' => '密码',
|
||||
'Class:UserLocal/Attribute:password+' => '用于验证用户身份的字符串',
|
||||
'Class:UserLocal/Attribute:password_renewed_date' => '密码更新',
|
||||
'Class:UserLocal/Attribute:password_renewed_date+' => '上次修改密码的时间',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => '不允许用户为自己设置 "一次性密码" 的失效期限',
|
||||
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => '密码必须至少8个字符, 包含大小写, 数字和特殊字符.',
|
||||
'UserLocal:password:expiration' => '下面的区域需要插件扩展',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => '不允许用户为自己设置 "一次性密码" 的失效期限',
|
||||
]);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-local/3.3.0',
|
||||
'authent-local/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<branding>
|
||||
<themes>
|
||||
<theme id="darkmoon" _delta="define">
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'theme:darkmoon' => 'Dark moon',
|
||||
));
|
||||
@@ -4,11 +4,23 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'theme:darkmoon' => '暗月',
|
||||
]);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-darkmoon-theme/3.3.0',
|
||||
'combodo-backoffice-darkmoon-theme/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<branding>
|
||||
<themes>
|
||||
<theme id="fullmoon-high-contrast" _delta="define">
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'theme:fullmoon-high-contrast' => 'Fullmoon (High contrast)',
|
||||
));
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-high-contrast-theme/3.3.0',
|
||||
'combodo-backoffice-fullmoon-high-contrast-theme/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<branding>
|
||||
<themes>
|
||||
<theme id="fullmoon-protanopia-deuteranopia" _delta="define">
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'theme:fullmoon-protanopia-deuteranopia' => 'Fullmoon (Protanopia & Deuteranopia)'
|
||||
));
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/3.3.0',
|
||||
'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<branding>
|
||||
<themes>
|
||||
<theme id="fullmoon-tritanopia" _delta="define">
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'theme:fullmoon-tritanopia' => 'Fullmoon (Tritanopia)',
|
||||
));
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-tritanopia-theme/3.3.0',
|
||||
'combodo-backoffice-fullmoon-tritanopia-theme/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<menus>
|
||||
<menu id="DBToolsMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>30</rank>
|
||||
|
||||
@@ -170,7 +170,7 @@ class DatabaseAnalyzer
|
||||
$this->CheckHK($sClass, $sAttCode, $aErrorsAndFixes);
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef->IsDirectField() && !($oAttDef instanceof AttributeTagSet))
|
||||
elseif ($oAttDef->IsDirectField() && !($oAttDef instanceof AttributeSet))
|
||||
{
|
||||
$this->CheckAllowedValues($sClass, $sAttCode, $oAttDef, $sTable, $sKeyField, $aErrorsAndFixes);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contain a valid class~~',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~',
|
||||
'DBTools:Analyze' => 'Analyzuj',
|
||||
'DBTools:Base' => 'Base~~',
|
||||
@@ -41,7 +41,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Restore~~',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, it does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~',
|
||||
'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~',
|
||||
|
||||
@@ -17,7 +17,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contain a valid class~~',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~',
|
||||
'DBTools:Analyze' => 'Analyze~~',
|
||||
'DBTools:Base' => 'Base~~',
|
||||
@@ -41,7 +41,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Restore~~',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, it does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~',
|
||||
'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~',
|
||||
|
||||
@@ -59,7 +59,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'DBAnalyzer-Integrity-HKInvalid' => 'Broken hierarchical key `%1$s`',
|
||||
'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted',
|
||||
'DBAnalyzer-Integrity-FinalClass' => 'Field `%2$s`.`%1$s` must have the same value as `%3$s`.`%1$s`',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contain a valid class',
|
||||
));
|
||||
|
||||
// Database Info
|
||||
@@ -72,7 +72,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
// Lost attachments
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'DBTools:LostAttachments' => 'Lost attachments',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, it does not retrieve deleted data.',
|
||||
|
||||
'DBTools:LostAttachments:Button:Analyze' => 'Analyze',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Restore',
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
// Database inconsistencies
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => 'Database integrity',
|
||||
'DBTools:Class' => 'Class',
|
||||
'DBTools:Title' => 'Database integrity check',
|
||||
'DBTools:ErrorsFound' => 'Errors Found',
|
||||
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES',
|
||||
'DBTools:Error' => 'Error',
|
||||
'DBTools:Count' => 'Count',
|
||||
'DBTools:SQLquery' => 'SQL query',
|
||||
'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)',
|
||||
'DBTools:SQLresult' => 'SQL result',
|
||||
'DBTools:NoError' => 'The database is OK',
|
||||
'DBTools:HideIds' => 'Error List',
|
||||
'DBTools:ShowIds' => 'Detailed view',
|
||||
'DBTools:ShowReport' => 'Report',
|
||||
'DBTools:IntegrityCheck' => 'Integrity check',
|
||||
'DBTools:FetchCheck' => 'Fetch Check (long)',
|
||||
'DBTools:SelectAnalysisType' => 'Select analysis type',
|
||||
|
||||
'DBTools:Analyze' => 'Analyse',
|
||||
'DBTools:Details' => 'Show Details',
|
||||
'DBTools:ShowAll' => 'Show All Errors',
|
||||
|
||||
'DBTools:Inconsistencies' => 'Database inconsistencies',
|
||||
'DBTools:DetailedErrorTitle' => '%2$s error(s) in class %1$s: %3$s',
|
||||
'DBTools:DetailedErrorLimit' => 'List limited to %1$s errors',
|
||||
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`',
|
||||
'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => 'Broken hierarchical key `%1$s`',
|
||||
'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted',
|
||||
'DBAnalyzer-Integrity-FinalClass' => 'Field `%2$s`.`%1$s` must have the same value as `%3$s`.`%1$s`',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contain a valid class',
|
||||
));
|
||||
|
||||
// Database Info
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'DBTools:DatabaseInfo' => 'Database Information',
|
||||
'DBTools:Base' => 'Base',
|
||||
'DBTools:Size' => 'Size',
|
||||
));
|
||||
|
||||
// Lost attachments
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'DBTools:LostAttachments' => 'Lost attachments',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, it does not retrieve deleted data.',
|
||||
|
||||
'DBTools:LostAttachments:Button:Analyze' => 'Analyse',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Restore',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.',
|
||||
'DBTools:LostAttachments:Button:Busy' => 'Please wait...',
|
||||
|
||||
'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analysing the database.',
|
||||
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyse results:',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...',
|
||||
|
||||
'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:',
|
||||
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.',
|
||||
|
||||
'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image',
|
||||
'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools'
|
||||
));
|
||||
@@ -17,7 +17,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contain a valid class~~',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~',
|
||||
'DBTools:Analyze' => 'Analyze~~',
|
||||
'DBTools:Base' => 'Base~~',
|
||||
@@ -41,7 +41,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Restore~~',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, it does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~',
|
||||
'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~',
|
||||
|
||||
@@ -18,7 +18,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Недопустимое значение для %1$s (столбец: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Отсутствует внешний ключ %1$s (столбец: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Сиротская запись в `%1$s`, она должна иметь свой аналог в таблице `%2$s`',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contain a valid class~~',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Некоторые учетные записи пользователей не имеют профилей',
|
||||
'DBTools:Analyze' => 'Анализировать',
|
||||
'DBTools:Base' => 'База',
|
||||
|
||||
@@ -17,7 +17,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contain a valid class~~',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~',
|
||||
'DBTools:Analyze' => 'Analyze~~',
|
||||
'DBTools:Base' => 'Base~~',
|
||||
@@ -41,7 +41,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Restore~~',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, it does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~',
|
||||
'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~',
|
||||
|
||||
@@ -17,7 +17,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class~~',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contain a valid class~~',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~',
|
||||
'DBTools:Analyze' => 'Analyze~~',
|
||||
'DBTools:Base' => 'Base~~',
|
||||
@@ -41,7 +41,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~',
|
||||
'DBTools:LostAttachments:Button:Restore' => 'Restore~~',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, it does not retrieve deleted data.~~',
|
||||
'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~',
|
||||
'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~',
|
||||
|
||||
@@ -4,63 +4,93 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* 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
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'DBAnalyzer-Fetch-Count-Error' => '读取计数出错于 `%1$s`, %2$d个记录已读取 / %3$d已',
|
||||
'DBAnalyzer-Integrity-FinalClass' => '字段 `%2$s`.`%1$s` 必须是相同的值, 而不是 `%3$s`.`%1$s`',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => '损坏的层级链 `%1$s`',
|
||||
'DBAnalyzer-Integrity-InvalidExtKey' => '无效的外键%1$s (列: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-InvalidValue' => '无效的值%1$s (列: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => '外键丢失%1$s (列: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => '孤立记录位于 `%1$s`, 其应该有副本位于表 `%2$s`',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => '字段 `%2$s`.`%1$s` 必须包含一个有效的类型',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => '一些用户账号没有角色',
|
||||
'DBTools:Analyze' => '分析',
|
||||
'DBTools:Base' => '数据库',
|
||||
|
||||
// Database inconsistencies
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||
// Dictionary entries go here
|
||||
'Menu:DBToolsMenu' => '数据库工具',
|
||||
'DBTools:Class' => '类型',
|
||||
'DBTools:Count' => '个数',
|
||||
'DBTools:DatabaseInfo' => '数据库信息',
|
||||
'DBTools:DetailedErrorLimit' => '列表限制为%1$s错误',
|
||||
'DBTools:DetailedErrorTitle' => '%2$s个错误在类型%1$s: %3$s',
|
||||
'DBTools:Details' => '显示详情',
|
||||
'DBTools:Title' => '数据库维护工具',
|
||||
'DBTools:ErrorsFound' => '发现错误',
|
||||
'DBTools:Indication' => '重要: 修复数据库错误后, 可能会出现新的不一致, 您必须重新运行一次分析.',
|
||||
'DBTools:Disclaimer' => '免责申明: 在应用修复之前, 应先备份数据库',
|
||||
'DBTools:Error' => '错误',
|
||||
'DBTools:ErrorsFound' => '发现错误',
|
||||
'DBTools:FetchCheck' => '提取检查 (耗时长)',
|
||||
'DBTools:FixitSQLquery' => '修复问题的SQL查询 (指示)',
|
||||
'DBTools:HideIds' => '错误列表',
|
||||
'DBTools:Inconsistencies' => '数据库不一致',
|
||||
'DBTools:Indication' => '重要: 修复数据库错误后, 可能会出现新的不一致, 您必须重新运行一次分析.',
|
||||
'DBTools:IntegrityCheck' => '完整性检查',
|
||||
'DBTools:LostAttachments' => '附件缺失',
|
||||
'DBTools:LostAttachments:Button:Analyze' => '分析',
|
||||
'DBTools:LostAttachments:Button:Busy' => '请稍后...',
|
||||
'DBTools:LostAttachments:Button:Restore' => '还原',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => '此操作无法回退, 请确认是否继续还原.',
|
||||
'DBTools:LostAttachments:Disclaimer' => '可以在此搜索数据库中丢失或错放的附件. 这不是数据恢复工具, 其无法恢复已删除的数据.',
|
||||
'DBTools:LostAttachments:History' => '附件 "%1$s" 已使用数据库工具还原',
|
||||
'DBTools:LostAttachments:Step:Analyze' => '首先, 通过分析数据库来搜索丢失或误挪动的附件.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => '分析结果:',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => '当前位置',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => '文件名',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => '移动到...',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:None' => '非常好! 所有附件都是正常的.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => '某些附件 (%1$d) 看起来放错了位置. 请检查下面的列表并选择要挪动的文件.',
|
||||
'DBTools:LostAttachments:Step:RestoreResults' => '还原结果:',
|
||||
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d的附件被还原.',
|
||||
'DBTools:LostAttachments:StoredAsInlineImage' => '存储为内嵌图像',
|
||||
'DBTools:NoError' => '数据库正确',
|
||||
'DBTools:Count' => '个数',
|
||||
'DBTools:SQLquery' => 'SQL查询',
|
||||
'DBTools:FixitSQLquery' => '修复问题的SQL查询 (指示)',
|
||||
'DBTools:SQLresult' => 'SQL结果',
|
||||
'DBTools:SelectAnalysisType' => '请选择分析类型',
|
||||
'DBTools:ShowAll' => '显示所有错误',
|
||||
'DBTools:NoError' => '数据库正确',
|
||||
'DBTools:HideIds' => '错误列表',
|
||||
'DBTools:ShowIds' => '详细视图',
|
||||
'DBTools:ShowReport' => '报告',
|
||||
'DBTools:IntegrityCheck' => '完整性检查',
|
||||
'DBTools:FetchCheck' => '提取检查 (耗时长)',
|
||||
'DBTools:SelectAnalysisType' => '请选择分析类型',
|
||||
|
||||
'DBTools:Analyze' => '分析',
|
||||
'DBTools:Details' => '显示详情',
|
||||
'DBTools:ShowAll' => '显示所有错误',
|
||||
|
||||
'DBTools:Inconsistencies' => '数据库不一致',
|
||||
'DBTools:DetailedErrorTitle' => '%2$s个错误在类型%1$s: %3$s',
|
||||
'DBTools:DetailedErrorLimit' => '列表限制为%1$s错误',
|
||||
|
||||
'DBAnalyzer-Integrity-OrphanRecord' => '孤立记录位于 `%1$s`, 其应该有副本位于表 `%2$s`',
|
||||
'DBAnalyzer-Integrity-InvalidExtKey' => '无效的外键%1$s (列: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => '外键丢失%1$s (列: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-InvalidValue' => '无效的值%1$s (列: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => '一些用户账号没有角色',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => '损坏的层级链 `%1$s`',
|
||||
'DBAnalyzer-Fetch-Count-Error' => '读取计数出错于 `%1$s`, %2$d个记录已读取 / %3$d已',
|
||||
'DBAnalyzer-Integrity-FinalClass' => '字段 `%2$s`.`%1$s` 必须是相同的值, 而不是 `%3$s`.`%1$s`',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => '字段 `%2$s`.`%1$s` 必须包含一个有效的类型',
|
||||
));
|
||||
|
||||
// Database Info
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||
'DBTools:DatabaseInfo' => '数据库信息',
|
||||
'DBTools:Base' => '数据库',
|
||||
'DBTools:Size' => '大小',
|
||||
'DBTools:Title' => '数据库维护工具',
|
||||
'Menu:DBToolsMenu' => '数据库工具',
|
||||
]);
|
||||
));
|
||||
|
||||
// Lost attachments
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||
'DBTools:LostAttachments' => '附件缺失',
|
||||
'DBTools:LostAttachments:Disclaimer' => '可以在此搜索数据库中丢失或错放的附件. 这不是数据恢复工具, 其无法恢复已删除的数据.',
|
||||
|
||||
'DBTools:LostAttachments:Button:Analyze' => '分析',
|
||||
'DBTools:LostAttachments:Button:Restore' => '还原',
|
||||
'DBTools:LostAttachments:Button:Restore:Confirm' => '此操作无法回退, 请确认是否继续还原.',
|
||||
'DBTools:LostAttachments:Button:Busy' => '请稍候...',
|
||||
|
||||
'DBTools:LostAttachments:Step:Analyze' => '首先, 通过分析数据库来搜索丢失或误挪动的附件.',
|
||||
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults' => '分析结果:',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:None' => '非常好! 所有附件都是正常的.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => '某些附件 (%1$d) 看起来放错了位置. 请检查下面的列表并选择要挪动的文件.',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => '文件名',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => '当前位置',
|
||||
'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => '移动到...',
|
||||
|
||||
'DBTools:LostAttachments:Step:RestoreResults' => '还原结果:',
|
||||
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d的附件被还原.',
|
||||
|
||||
'DBTools:LostAttachments:StoredAsInlineImage' => '存储为内嵌图像',
|
||||
'DBTools:LostAttachments:History' => '附件 "%1$s" 已使用数据库工具还原',
|
||||
));
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-db-tools/3.3.0',
|
||||
'combodo-db-tools/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<classes>
|
||||
<class id="Attachment" _delta="define">
|
||||
<parent>DBObject</parent>
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Attachments:TabTitle_Count' => 'Attachments (%1$d)',
|
||||
'Attachments:EmptyTabTitle' => 'Attachments',
|
||||
'Attachments:FieldsetTitle' => 'Attachments',
|
||||
'Attachments:DeleteBtn' => 'Delete',
|
||||
'Attachments:History_File_Added' => 'Attachment %1$s added.',
|
||||
'Attachments:History_File_Removed' => 'Attachment %1$s removed.',
|
||||
'Attachments:AddAttachment' => 'Add attachment: ',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => 'File upload in NOT allowed on this system.',
|
||||
'Attachment:Max_Go' => '(Maximum file size: %1$s GB)',
|
||||
'Attachment:Max_Mo' => '(Maximum file size: %1$s MB)',
|
||||
'Attachment:Max_Ko' => '(Maximum file size: %1$s KB)',
|
||||
'Attachments:NoAttachment' => 'No attachment.',
|
||||
'Attachments:PreviewNotAvailable' => 'Preview not available for this type of attachment.',
|
||||
'Attachments:Error:FileTooLarge' => 'File is too large to be uploaded. %1$s',
|
||||
'Attachments:Error:UploadedFileEmpty' => 'The received file is empty and cannot be attached.
|
||||
Either you have pushed an empty file,
|
||||
or ask your '.ITOP_APPLICATION_SHORT.' administrator if the '.ITOP_APPLICATION_SHORT.' server disk is full.',
|
||||
'Attachments:Render:Icons' => 'Display as icons',
|
||||
'Attachments:Render:Table' => 'Display as list',
|
||||
'UI:Attachments:DropYourFileHint' => 'Drop files anywhere in this area',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: Attachment
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Class:Attachment' => 'Attachment',
|
||||
'Class:Attachment+' => '',
|
||||
'Class:Attachment/Attribute:expire' => 'Expire',
|
||||
'Class:Attachment/Attribute:expire+' => '',
|
||||
'Class:Attachment/Attribute:temp_id' => 'Temporary id',
|
||||
'Class:Attachment/Attribute:temp_id+' => '',
|
||||
'Class:Attachment/Attribute:item_class' => 'Item class',
|
||||
'Class:Attachment/Attribute:item_class+' => '',
|
||||
'Class:Attachment/Attribute:item_id' => 'Item',
|
||||
'Class:Attachment/Attribute:item_id+' => '',
|
||||
'Class:Attachment/Attribute:item_org_id' => 'Item organisation',
|
||||
'Class:Attachment/Attribute:item_org_id+' => '',
|
||||
'Class:Attachment/Attribute:contents' => 'Contents',
|
||||
'Class:Attachment/Attribute:contents+' => '',
|
||||
));
|
||||
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Attachments:File:Thumbnail' => 'Icon',
|
||||
'Attachments:File:Name' => 'File name',
|
||||
'Attachments:File:Date' => 'Upload date',
|
||||
'Attachments:File:Uploader' => 'Uploaded by',
|
||||
'Attachments:File:Size' => 'Size',
|
||||
'Attachments:File:MimeType' => 'Type',
|
||||
'Attachments:File:DownloadsCount' => 'Downloads',
|
||||
));
|
||||
//
|
||||
// Class: Attachment
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Class:Attachment/Attribute:creation_date' => 'Creation date',
|
||||
'Class:Attachment/Attribute:creation_date+' => '',
|
||||
'Class:Attachment/Attribute:user_id' => 'User id',
|
||||
'Class:Attachment/Attribute:user_id+' => '',
|
||||
'Class:Attachment/Attribute:contact_id' => 'Contact id',
|
||||
'Class:Attachment/Attribute:contact_id+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: TriggerOnAttachmentDownload
|
||||
//
|
||||
|
||||
Dict::Add('EN GB', 'British English', 'British English', array(
|
||||
'Class:TriggerOnAttachmentDownload' => 'Trigger (on object\'s attachment download)',
|
||||
'Class:TriggerOnAttachmentDownload+' => 'Trigger on object\'s attachment download of [a child class of] the given class',
|
||||
));
|
||||
@@ -4,57 +4,83 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Attachments:TabTitle_Count' => '附件 (%1$d)',
|
||||
'Attachments:EmptyTabTitle' => '附件',
|
||||
'Attachments:FieldsetTitle' => '附件',
|
||||
'Attachments:DeleteBtn' => '删除',
|
||||
'Attachments:History_File_Added' => '附件%1$s已添加.',
|
||||
'Attachments:History_File_Removed' => '附件%1$s已移除.',
|
||||
'Attachments:AddAttachment' => '添加附件: ',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => '本系统不支持文件上传.',
|
||||
'Attachment:Max_Go' => '(最大文件尺寸: %1$s GB)',
|
||||
'Attachment:Max_Ko' => '(最大文件尺寸: %1$s KB)',
|
||||
'Attachment:Max_Mo' => '(最大文件尺寸: %1$s MB)',
|
||||
'Attachments:AddAttachment' => '添加附件: ',
|
||||
'Attachments:DeleteBtn' => '删除',
|
||||
'Attachments:EmptyTabTitle' => '附件',
|
||||
'Attachments:Error:FileTooLarge' => '上传的文件过大. %1$s',
|
||||
'Attachments:Error:UploadedFileEmpty' => '收到的文件为空, 无法添加. 可能是因为您发送的是空文件,或者咨询'.ITOP_APPLICATION_SHORT.'管理员服务器磁盘是否已满.',
|
||||
'Attachments:FieldsetTitle' => '附件',
|
||||
'Attachments:File:Date' => '上传日期',
|
||||
'Attachments:File:DownloadsCount' => '下载',
|
||||
'Attachments:File:MimeType' => '类型',
|
||||
'Attachments:File:Name' => '文件名',
|
||||
'Attachments:File:Size' => '大小',
|
||||
'Attachments:File:Thumbnail' => '图标',
|
||||
'Attachments:File:Uploader' => '上传者',
|
||||
'Attachments:History_File_Added' => '附件%1$s已添加.',
|
||||
'Attachments:History_File_Removed' => '附件%1$s已移除.',
|
||||
'Attachments:NoAttachment' => '没有附件. ',
|
||||
'Attachments:PreviewNotAvailable' => '此附件类型不支持预览.',
|
||||
'Attachments:Error:FileTooLarge' => '上传的文件过大. %1$s',
|
||||
'Attachments:Error:UploadedFileEmpty' => '收到的文件为空, 无法添加.
|
||||
可能是因为您发送的是空文件,
|
||||
或者咨询 '.ITOP_APPLICATION_SHORT.' 管理员,检查 '.ITOP_APPLICATION_SHORT.' 服务器硬盘是否满了.',
|
||||
'Attachments:Render:Icons' => '显示为图标',
|
||||
'Attachments:Render:Table' => '显示为列表',
|
||||
'Attachments:TabTitle_Count' => '附件 (%1$d)',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => '本系统不支持文件上传.',
|
||||
'Class:Attachment' => '附件',
|
||||
'Class:Attachment+' => '',
|
||||
'Class:Attachment/Attribute:contact_id' => '联系人编号',
|
||||
'Class:Attachment/Attribute:contact_id+' => '~~',
|
||||
'Class:Attachment/Attribute:contents' => '内容',
|
||||
'Class:Attachment/Attribute:contents+' => '',
|
||||
'Class:Attachment/Attribute:creation_date' => '创建日期',
|
||||
'Class:Attachment/Attribute:creation_date+' => '~~',
|
||||
'Class:Attachment/Attribute:expire' => '过期',
|
||||
'Class:Attachment/Attribute:expire+' => '~~',
|
||||
'Class:Attachment/Attribute:item_class' => '项目类型',
|
||||
'Class:Attachment/Attribute:item_class+' => '~~',
|
||||
'Class:Attachment/Attribute:item_id' => '项目',
|
||||
'Class:Attachment/Attribute:item_id+' => '~~',
|
||||
'Class:Attachment/Attribute:item_org_id' => '项目组织',
|
||||
'Class:Attachment/Attribute:item_org_id+' => '',
|
||||
'Class:Attachment/Attribute:temp_id' => '临时编号',
|
||||
'Class:Attachment/Attribute:temp_id+' => '~~',
|
||||
'Class:Attachment/Attribute:user_id' => '用户编号',
|
||||
'Class:Attachment/Attribute:user_id+' => '~~',
|
||||
'Class:TriggerOnAttachmentDownload' => '触发器 (于对象附件下载时)',
|
||||
'Class:TriggerOnAttachmentDownload+' => '触发器于指定类型 [子类型] 对象附件下载时',
|
||||
'UI:Attachments:DropYourFileHint' => '将文件拖放到此区域的任意位置',
|
||||
]);
|
||||
|
||||
//
|
||||
// Class: Attachment
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:Attachment' => '附件',
|
||||
'Class:Attachment+' => '',
|
||||
'Class:Attachment/Attribute:expire' => '过期',
|
||||
'Class:Attachment/Attribute:expire+' => '',
|
||||
'Class:Attachment/Attribute:temp_id' => '临时编号',
|
||||
'Class:Attachment/Attribute:temp_id+' => '',
|
||||
'Class:Attachment/Attribute:item_class' => '项目类型',
|
||||
'Class:Attachment/Attribute:item_class+' => '',
|
||||
'Class:Attachment/Attribute:item_id' => '项目',
|
||||
'Class:Attachment/Attribute:item_id+' => '',
|
||||
'Class:Attachment/Attribute:item_org_id' => '项目组织',
|
||||
'Class:Attachment/Attribute:item_org_id+' => '',
|
||||
'Class:Attachment/Attribute:contents' => '内容',
|
||||
'Class:Attachment/Attribute:contents+' => '',
|
||||
]);
|
||||
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Attachments:File:Thumbnail' => '图标',
|
||||
'Attachments:File:Name' => '文件名',
|
||||
'Attachments:File:Date' => '上传日期',
|
||||
'Attachments:File:Uploader' => '上传者',
|
||||
'Attachments:File:Size' => '大小',
|
||||
'Attachments:File:MimeType' => '类型',
|
||||
'Attachments:File:DownloadsCount' => '下载',
|
||||
]);
|
||||
//
|
||||
// Class: Attachment
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:Attachment/Attribute:creation_date' => '创建日期',
|
||||
'Class:Attachment/Attribute:creation_date+' => '~~',
|
||||
'Class:Attachment/Attribute:user_id' => '用户编号',
|
||||
'Class:Attachment/Attribute:user_id+' => '~~',
|
||||
'Class:Attachment/Attribute:contact_id' => '联系人编号',
|
||||
'Class:Attachment/Attribute:contact_id+' => '~~',
|
||||
]);
|
||||
|
||||
//
|
||||
// Class: TriggerOnAttachmentDownload
|
||||
//
|
||||
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Class:TriggerOnAttachmentDownload' => '触发器 (于对象附件下载时)',
|
||||
'Class:TriggerOnAttachmentDownload+' => '触发器于指定类型 [子类型] 对象附件下载时',
|
||||
]);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user