mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-21 17:48:43 +02:00
Compare commits
197 Commits
2.7.10
...
support/2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b46644786 | ||
|
|
3356856a5f | ||
|
|
554e9aa205 | ||
|
|
d5c0202094 | ||
|
|
cbd866e988 | ||
|
|
b19b9e7b27 | ||
|
|
50dc4aec1e | ||
|
|
513d813566 | ||
|
|
f4a546a9ec | ||
|
|
14a498a374 | ||
|
|
af4729ac6a | ||
|
|
f3f01f5cc8 | ||
|
|
c29d7f9a07 | ||
|
|
ab6cf18445 | ||
|
|
a0171ac9cf | ||
|
|
4b4bb6aa0b | ||
|
|
ff8397edf6 | ||
|
|
d46dc519e1 | ||
|
|
fe7eb22d32 | ||
|
|
bafb6ab212 | ||
|
|
6c0e986563 | ||
|
|
cf06f3e0d5 | ||
|
|
fe887f01c0 | ||
|
|
9109138127 | ||
|
|
51b19c03b1 | ||
|
|
8cb584abdd | ||
|
|
3480d478b0 | ||
|
|
3a34417a7d | ||
|
|
6ca3ca108b | ||
|
|
037036ce6a | ||
|
|
9d2dab5eba | ||
|
|
3169b39952 | ||
|
|
ba33b01d84 | ||
|
|
7db69ed158 | ||
|
|
a6f6d536e0 | ||
|
|
880faf2021 | ||
|
|
f96902c03e | ||
|
|
6e810322f7 | ||
|
|
dd9984be7f | ||
|
|
98f3f88ea2 | ||
|
|
8be0c36859 | ||
|
|
8c5a65d836 | ||
|
|
db47973063 | ||
|
|
028e815bfa | ||
|
|
caf07affa6 | ||
|
|
bdef9e59de | ||
|
|
4bf001d108 | ||
|
|
a095208e53 | ||
|
|
2429ec4eec | ||
|
|
55655e3fca | ||
|
|
7e98b04ed3 | ||
|
|
59c6c0250d | ||
|
|
18a5afb8a6 | ||
|
|
4b6258dfa1 | ||
|
|
44b9f23117 | ||
|
|
2ddefcd2fc | ||
|
|
39b15fec50 | ||
|
|
c180dd9863 | ||
|
|
1172130d7c | ||
|
|
8172e14345 | ||
|
|
6e4836f5e0 | ||
|
|
4ee6e6f915 | ||
|
|
e5b318b94f | ||
|
|
c081b89f03 | ||
|
|
f237a98c1d | ||
|
|
fd2a41aee6 | ||
|
|
25b1a0d8af | ||
|
|
985b366cc7 | ||
|
|
d1e2bc9b2b | ||
|
|
757b3d1cc3 | ||
|
|
8c0bbadbfe | ||
|
|
cbd3d2c165 | ||
|
|
b286bd48c7 | ||
|
|
c4efbe2891 | ||
|
|
58506441cf | ||
|
|
d575ee50ee | ||
|
|
997fa3a856 | ||
|
|
70abd8027e | ||
|
|
4c6e6ffc9c | ||
|
|
b268df7bb4 | ||
|
|
7aaa35f88e | ||
|
|
4bb91b819c | ||
|
|
656cae3e66 | ||
|
|
292735b4b2 | ||
|
|
dcc4061261 | ||
|
|
ff7ac731df | ||
|
|
c784afdb06 | ||
|
|
5e60e8d725 | ||
|
|
564bf04647 | ||
|
|
17d18eb75f | ||
|
|
a9a6460747 | ||
|
|
1fa1a053e4 | ||
|
|
01e151632f | ||
|
|
c17d0b1027 | ||
|
|
517d16e3d9 | ||
|
|
696a5d1a48 | ||
|
|
96288db97b | ||
|
|
e6072cd8b6 | ||
|
|
db8bb7d94a | ||
|
|
1b2dbf751c | ||
|
|
b6805af20e | ||
|
|
4cc6290c88 | ||
|
|
c79d17516d | ||
|
|
a2154d6418 | ||
|
|
f820d3bd81 | ||
|
|
0a914f527a | ||
|
|
a8c749a46a | ||
|
|
e58c8afeab | ||
|
|
005b0eab1d | ||
|
|
55b34b5d11 | ||
|
|
7b4f00ee45 | ||
|
|
cc99cec250 | ||
|
|
105dc46f46 | ||
|
|
770fbe157c | ||
|
|
21d44c664f | ||
|
|
b318cbe211 | ||
|
|
7106501812 | ||
|
|
567dd39270 | ||
|
|
b292621f82 | ||
|
|
46f0b48add | ||
|
|
9a5f16bd3e | ||
|
|
6224ec7a37 | ||
|
|
c460edcd5e | ||
|
|
b839b42cd4 | ||
|
|
fabc8b91d7 | ||
|
|
4c38cd570c | ||
|
|
c4fd15ae90 | ||
|
|
bbca491118 | ||
|
|
0d04bd8b0e | ||
|
|
3bcb3a2154 | ||
|
|
aa863c40d3 | ||
|
|
5d7ad9f6dd | ||
|
|
72cb41dd7e | ||
|
|
6ef39c9f5b | ||
|
|
614b948c82 | ||
|
|
7c0715ad59 | ||
|
|
31819497ae | ||
|
|
c86e2c6c79 | ||
|
|
1d54b66de9 | ||
|
|
f932765e19 | ||
|
|
11b4085566 | ||
|
|
12afcd7cce | ||
|
|
666c95a656 | ||
|
|
fde9c28263 | ||
|
|
52c3ff0406 | ||
|
|
9f4d07aaa5 | ||
|
|
70561d6331 | ||
|
|
ae8311e224 | ||
|
|
e09fa0ffc1 | ||
|
|
5b6a20048f | ||
|
|
d86c211b73 | ||
|
|
8499babcb3 | ||
|
|
2d44cbbb60 | ||
|
|
3d89ef9076 | ||
|
|
e896f8af3d | ||
|
|
23268e8969 | ||
|
|
421e12debd | ||
|
|
389848cef4 | ||
|
|
7da4423346 | ||
|
|
2a770b9dc4 | ||
|
|
8df12e64f2 | ||
|
|
341261c14e | ||
|
|
bfc7c73e18 | ||
|
|
9a6c4ba7bb | ||
|
|
dc47c34981 | ||
|
|
3ac5131a19 | ||
|
|
134a9aa684 | ||
|
|
a98c0d32ae | ||
|
|
38af2b85c4 | ||
|
|
c9c84735c4 | ||
|
|
646972838a | ||
|
|
ce92241593 | ||
|
|
715eeff627 | ||
|
|
651de821df | ||
|
|
2233ea5f54 | ||
|
|
39e6915e05 | ||
|
|
6279f4ac70 | ||
|
|
badf10e74e | ||
|
|
2e9cd6a342 | ||
|
|
cef70ee9a2 | ||
|
|
37e15706b2 | ||
|
|
4b210273d2 | ||
|
|
951e8e03b0 | ||
|
|
c016ca364d | ||
|
|
4611442665 | ||
|
|
c7e7976607 | ||
|
|
0ca9fac04b | ||
|
|
7edc79f398 | ||
|
|
c110206264 | ||
|
|
b3ad2030cb | ||
|
|
0938ba939c | ||
|
|
bca393def3 | ||
|
|
796ac55ff4 | ||
|
|
66ae89e91d | ||
|
|
361cca465a | ||
|
|
7462d66643 | ||
|
|
a177b9b1d4 |
122
.gitignore
vendored
Normal file
122
.gitignore
vendored
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
|
||||||
|
/toolkit/
|
||||||
|
/conf/*
|
||||||
|
/env-*/*
|
||||||
|
|
||||||
|
# composer reserver directory, from sources, populate/update using "composer install"
|
||||||
|
vendor/*
|
||||||
|
test/vendor/*
|
||||||
|
|
||||||
|
# all datas but listing prevention
|
||||||
|
data/*
|
||||||
|
!data/.htaccess
|
||||||
|
!data/index.php
|
||||||
|
!data/web.config
|
||||||
|
|
||||||
|
# iTop extensions
|
||||||
|
extensions/*
|
||||||
|
!extensions/readme.txt
|
||||||
|
|
||||||
|
# all logs but listing prevention
|
||||||
|
log/*
|
||||||
|
!log/.htaccess
|
||||||
|
!log/index.php
|
||||||
|
!log/web.config
|
||||||
|
|
||||||
|
|
||||||
|
# Jetbrains
|
||||||
|
.idea/**
|
||||||
|
!.idea/encodings.xml
|
||||||
|
!.idea/codeStyles
|
||||||
|
!.idea/codeStyles/*
|
||||||
|
!.idea/inspectionProfiles
|
||||||
|
!.idea/inspectionProfiles/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
### Eclipse template
|
||||||
|
|
||||||
|
.metadata
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
*~.nib
|
||||||
|
local.properties
|
||||||
|
.settings/
|
||||||
|
.loadpath
|
||||||
|
.recommenders
|
||||||
|
.project
|
||||||
|
|
||||||
|
# External tool builders
|
||||||
|
.externalToolBuilders/
|
||||||
|
|
||||||
|
# Locally stored "Eclipse launch configurations"
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
# PyDev specific (Python IDE for Eclipse)
|
||||||
|
*.pydevproject
|
||||||
|
|
||||||
|
# CDT-specific (C/C++ Development Tooling)
|
||||||
|
.cproject
|
||||||
|
|
||||||
|
# CDT- autotools
|
||||||
|
.autotools
|
||||||
|
|
||||||
|
# Java annotation processor (APT)
|
||||||
|
.factorypath
|
||||||
|
|
||||||
|
# PDT-specific (PHP Development Tools)
|
||||||
|
.buildpath
|
||||||
|
|
||||||
|
# sbteclipse plugin
|
||||||
|
.target
|
||||||
|
|
||||||
|
# Tern plugin
|
||||||
|
.tern-project
|
||||||
|
|
||||||
|
# TeXlipse plugin
|
||||||
|
.texlipse
|
||||||
|
|
||||||
|
# STS (Spring Tool Suite)
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
# Code Recommenders
|
||||||
|
.recommenders/
|
||||||
|
|
||||||
|
# Annotation Processing
|
||||||
|
.apt_generated/
|
||||||
|
|
||||||
|
# Scala IDE specific (Scala & Java development for Eclipse)
|
||||||
|
.cache-main
|
||||||
|
.scala_dependencies
|
||||||
|
.worksheet
|
||||||
@@ -214,62 +214,69 @@ PrepareWidgets();
|
|||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$sHtml = '';
|
||||||
$s_captured_output = $this->ob_get_clean_safe();
|
$s_captured_output = $this->ob_get_clean_safe();
|
||||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
||||||
{
|
{
|
||||||
// inline content != attachment && html => filter all scripts for malicious XSS scripts
|
// inline content != attachment && html => filter all scripts for malicious XSS scripts
|
||||||
echo self::FilterXSS($this->s_content);
|
$sHtml .= self::FilterXSS($this->s_content);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
echo $this->s_content;
|
$sHtml .= $this->s_content;
|
||||||
}
|
}
|
||||||
if (!empty($this->m_sMenu))
|
if (!empty($this->m_sMenu))
|
||||||
{
|
{
|
||||||
$uid = time();
|
$uid = time();
|
||||||
echo "<div id=\"accordion_temp_$uid\">\n";
|
$sHtml .= "<div id=\"accordion_temp_$uid\">\n";
|
||||||
echo "<div id=\"accordion\">\n";
|
$sHtml .= "<div id=\"accordion\">\n";
|
||||||
echo "<!-- Beginning of the accordion menu -->\n";
|
$sHtml .= "<!-- Beginning of the accordion menu -->\n";
|
||||||
echo self::FilterXSS($this->m_sMenu);
|
$sHtml .= self::FilterXSS($this->m_sMenu);
|
||||||
echo "<!-- End of the accordion menu-->\n";
|
$sHtml .= "<!-- End of the accordion menu-->\n";
|
||||||
echo "</div>\n";
|
$sHtml .= "</div>\n";
|
||||||
echo "</div>\n";
|
$sHtml .= "</div>\n";
|
||||||
|
|
||||||
echo "<script type=\"text/javascript\">\n";
|
$sHtml .= "<script type=\"text/javascript\">\n";
|
||||||
echo "$('#inner_menu').html($('#accordion_temp_$uid').html());\n";
|
$sHtml .= "$('#inner_menu').html($('#accordion_temp_$uid').html());\n";
|
||||||
echo "$('#accordion_temp_$uid').remove();\n";
|
$sHtml .= "$('#accordion_temp_$uid').remove();\n";
|
||||||
echo "\n</script>\n";
|
$sHtml .= "\n</script>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//echo $this->s_deferred_content;
|
//$sHtml .= $this->s_deferred_content;
|
||||||
if (count($this->a_scripts) > 0)
|
if (count($this->a_scripts) > 0)
|
||||||
{
|
{
|
||||||
echo "<script type=\"text/javascript\">\n";
|
$sHtml .= "<script type=\"text/javascript\">\n";
|
||||||
echo implode("\n", $this->a_scripts);
|
$sHtml .= implode("\n", $this->a_scripts);
|
||||||
echo "\n</script>\n";
|
$sHtml .= "\n</script>\n";
|
||||||
}
|
}
|
||||||
if (!empty($this->s_deferred_content))
|
if (!empty($this->s_deferred_content))
|
||||||
{
|
{
|
||||||
echo "<script type=\"text/javascript\">\n";
|
$sHtml .= "<script type=\"text/javascript\">\n";
|
||||||
echo "\$('body').append('".addslashes(str_replace("\n", '', $this->s_deferred_content))."');\n";
|
$sHtml .= "\$('body').append('".addslashes(str_replace("\n", '', $this->s_deferred_content))."');\n";
|
||||||
echo "\n</script>\n";
|
$sHtml .= "\n</script>\n";
|
||||||
}
|
}
|
||||||
if (!empty($this->m_sReadyScript))
|
if (!empty($this->m_sReadyScript))
|
||||||
{
|
{
|
||||||
echo "<script type=\"text/javascript\">\n";
|
$sHtml .= "<script type=\"text/javascript\">\n";
|
||||||
echo $this->m_sReadyScript; // Ready Scripts are output as simple scripts
|
$sHtml .= $this->m_sReadyScript; // Ready Scripts are output as simple scripts
|
||||||
echo "\n</script>\n";
|
$sHtml .= "\n</script>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trim($s_captured_output) != "")
|
if (trim($s_captured_output) != "")
|
||||||
{
|
{
|
||||||
echo self::FilterXSS($s_captured_output);
|
$sHtml .= self::FilterXSS($s_captured_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$oKPI = new ExecutionKPI();
|
||||||
|
echo $sHtml;
|
||||||
|
$oKPI->ComputeAndReport('Echoing ('.round(strlen($sHtml) / 1024).' Kb)');
|
||||||
|
|
||||||
if (class_exists('DBSearch'))
|
if (class_exists('DBSearch'))
|
||||||
{
|
{
|
||||||
DBSearch::RecordQueryTrace();
|
DBSearch::RecordQueryTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExecutionKPI::ReportStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -118,8 +118,7 @@ class ApplicationContext
|
|||||||
$oSearchFilter = new DBObjectSearch('Organization');
|
$oSearchFilter = new DBObjectSearch('Organization');
|
||||||
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
|
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
|
||||||
$oSet = new CMDBObjectSet($oSearchFilter);
|
$oSet = new CMDBObjectSet($oSearchFilter);
|
||||||
$iCount = $oSet->Count();
|
if ($oSet->Count(2) == 1)
|
||||||
if ($iCount == 1)
|
|
||||||
{
|
{
|
||||||
// Only one possible value for org_id, set it in the context
|
// Only one possible value for org_id, set it in the context
|
||||||
$oOrg = $oSet->Fetch();
|
$oOrg = $oSet->Fetch();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -755,33 +755,65 @@ EOF
|
|||||||
|
|
||||||
public static function GetDashletCreationForm($sOQL = null)
|
public static function GetDashletCreationForm($sOQL = null)
|
||||||
{
|
{
|
||||||
|
$oAppContext = new ApplicationContext();
|
||||||
|
$sContextMenuId = $oAppContext->GetCurrentValue('menu', null);
|
||||||
|
|
||||||
$oForm = new DesignerForm();
|
$oForm = new DesignerForm();
|
||||||
|
|
||||||
// Get the list of all 'dashboard' menus in which we can insert a dashlet
|
// Get the list of all 'dashboard' menus in which we can insert a dashlet
|
||||||
$aAllMenus = ApplicationMenu::ReflectionMenuNodes();
|
$aAllMenus = ApplicationMenu::ReflectionMenuNodes();
|
||||||
|
$sRootMenuId = ApplicationMenu::GetRootMenuId($sContextMenuId);
|
||||||
$aAllowedDashboards = array();
|
$aAllowedDashboards = array();
|
||||||
foreach($aAllMenus as $idx => $aMenu)
|
$sDefaultDashboard = null;
|
||||||
|
|
||||||
|
// Store the parent menus for acces check
|
||||||
|
$aParentMenus = array();
|
||||||
|
foreach($aAllMenus as $idx => $aMenu)
|
||||||
|
{
|
||||||
|
/** @var MenuNode $oMenu */
|
||||||
|
$oMenu = $aMenu['node'];
|
||||||
|
if (count(ApplicationMenu::GetChildren($oMenu->GetIndex())) > 0)
|
||||||
|
{
|
||||||
|
$aParentMenus[$oMenu->GetMenuId()] = $aMenu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($aAllMenus as $idx => $aMenu)
|
||||||
{
|
{
|
||||||
$oMenu = $aMenu['node'];
|
$oMenu = $aMenu['node'];
|
||||||
$sParentId = $aMenu['parent'];
|
if ($oMenu instanceof DashboardMenuNode)
|
||||||
if ($oMenu instanceof DashboardMenuNode)
|
{
|
||||||
{
|
// Get the root parent for access check
|
||||||
$sMenuLabel = $oMenu->GetTitle();
|
$sParentId = $aMenu['parent'];
|
||||||
$sParentLabel = Dict::S('Menu:'.$sParentId);
|
$aParentMenu = $aParentMenus[$sParentId];
|
||||||
if ($sParentLabel != $sMenuLabel)
|
while (isset($aParentMenus[$aParentMenu['parent']]))
|
||||||
{
|
{
|
||||||
$aAllowedDashboards[$oMenu->GetMenuId()] = $sParentLabel.' - '.$sMenuLabel;
|
// grand parent exists
|
||||||
}
|
$sParentId = $aParentMenu['parent'];
|
||||||
else
|
$aParentMenu = $aParentMenus[$sParentId];
|
||||||
{
|
}
|
||||||
$aAllowedDashboards[$oMenu->GetMenuId()] = $sMenuLabel;
|
$oParentMenu = $aParentMenu['node'];
|
||||||
}
|
if ($oMenu->IsEnabled() && $oParentMenu->IsEnabled())
|
||||||
}
|
{
|
||||||
|
$sMenuLabel = $oMenu->GetTitle();
|
||||||
|
$sParentLabel = Dict::S('Menu:'.$sParentId);
|
||||||
|
if ($sParentLabel != $sMenuLabel)
|
||||||
|
{
|
||||||
|
$aAllowedDashboards[$oMenu->GetMenuId()] = $sParentLabel.' - '.$sMenuLabel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aAllowedDashboards[$oMenu->GetMenuId()] = $sMenuLabel;
|
||||||
|
}
|
||||||
|
if (empty($sDefaultDashboard) && ($sRootMenuId == ApplicationMenu::GetRootMenuId($oMenu->GetMenuId())))
|
||||||
|
{
|
||||||
|
$sDefaultDashboard = $oMenu->GetMenuId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
asort($aAllowedDashboards);
|
asort($aAllowedDashboards);
|
||||||
|
|
||||||
$aKeys = array_keys($aAllowedDashboards); // Select the first one by default
|
|
||||||
$sDefaultDashboard = $aKeys[0];
|
|
||||||
$oField = new DesignerComboField('menu_id', Dict::S('UI:DashletCreation:Dashboard'), $sDefaultDashboard);
|
$oField = new DesignerComboField('menu_id', Dict::S('UI:DashletCreation:Dashboard'), $sDefaultDashboard);
|
||||||
$oField->SetAllowedValues($aAllowedDashboards);
|
$oField->SetAllowedValues($aAllowedDashboards);
|
||||||
$oField->SetMandatory(true);
|
$oField->SetMandatory(true);
|
||||||
@@ -842,7 +874,7 @@ EOF
|
|||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#dashlet_creation_dlg').dialog({
|
$('#dashlet_creation_dlg').dialog({
|
||||||
width: 400,
|
width: 600,
|
||||||
modal: true,
|
modal: true,
|
||||||
title: '$sDialogTitle',
|
title: '$sDialogTitle',
|
||||||
buttons: [
|
buttons: [
|
||||||
|
|||||||
@@ -661,7 +661,7 @@ class DisplayBlock
|
|||||||
case 'links':
|
case 'links':
|
||||||
//$bDashboardMode = isset($aExtraParams['dashboard']) ? ($aExtraParams['dashboard'] == 'true') : false;
|
//$bDashboardMode = isset($aExtraParams['dashboard']) ? ($aExtraParams['dashboard'] == 'true') : false;
|
||||||
//$bSelectMode = isset($aExtraParams['select']) ? ($aExtraParams['select'] == 'true') : false;
|
//$bSelectMode = isset($aExtraParams['select']) ? ($aExtraParams['select'] == 'true') : false;
|
||||||
if ( ($this->m_oSet->Count()> 0) && (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) )
|
if ( ($this->m_oSet->Count(1)> 0) && (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) )
|
||||||
{
|
{
|
||||||
//$sLinkage = isset($aExtraParams['linkage']) ? $aExtraParams['linkage'] : '';
|
//$sLinkage = isset($aExtraParams['linkage']) ? $aExtraParams['linkage'] : '';
|
||||||
$sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $aExtraParams);
|
$sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $aExtraParams);
|
||||||
@@ -774,21 +774,38 @@ class DisplayBlock
|
|||||||
{
|
{
|
||||||
$aStates = explode(',', $sStatesList);
|
$aStates = explode(',', $sStatesList);
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sStateAttrCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sStateAttrCode);
|
||||||
|
|
||||||
|
// Generate one count + group by query [#1330]
|
||||||
|
$sClassAlias = $this->m_oFilter->GetClassAlias();
|
||||||
|
$oGroupByExpr = Expression::FromOQL($sClassAlias.'.'.$sStateAttrCode);
|
||||||
|
$aGroupBy = array('group1' => $oGroupByExpr);
|
||||||
|
$sCountGroupByQuery = $this->m_oFilter->MakeGroupByQuery(array(), $aGroupBy, false);
|
||||||
|
$aCountGroupByResults = CMDBSource::QueryToArray($sCountGroupByQuery);
|
||||||
|
$aCountsQueryResults = array();
|
||||||
|
foreach ($aCountGroupByResults as $aCountGroupBySingleResult)
|
||||||
|
{
|
||||||
|
$aCountsQueryResults[$aCountGroupBySingleResult[0]] = $aCountGroupBySingleResult[1];
|
||||||
|
}
|
||||||
|
|
||||||
foreach($aStates as $sStateValue)
|
foreach($aStates as $sStateValue)
|
||||||
{
|
{
|
||||||
$oFilter = $this->m_oFilter->DeepClone();
|
|
||||||
$oFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
|
|
||||||
$oSet = new DBObjectSet($oFilter);
|
|
||||||
$oSet->SetShowObsoleteData($this->m_bShowObsoleteData);
|
|
||||||
$aCounts[$sStateValue] = $oSet->Count();
|
|
||||||
$aStateLabels[$sStateValue] = htmlentities($oAttDef->GetValueLabel($sStateValue), ENT_QUOTES, 'UTF-8');
|
$aStateLabels[$sStateValue] = htmlentities($oAttDef->GetValueLabel($sStateValue), ENT_QUOTES, 'UTF-8');
|
||||||
|
|
||||||
|
$aCounts[$sStateValue] = (array_key_exists($sStateValue, $aCountsQueryResults))
|
||||||
|
? $aCountsQueryResults[$sStateValue]
|
||||||
|
: 0;
|
||||||
|
|
||||||
if ($aCounts[$sStateValue] == 0)
|
if ($aCounts[$sStateValue] == 0)
|
||||||
{
|
{
|
||||||
$aCounts[$sStateValue] = '-';
|
$aCounts[$sStateValue] = '-';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($oFilter->serialize());
|
$oSingleGroupByValueFilter = $this->m_oFilter->DeepClone();
|
||||||
|
$oSingleGroupByValueFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
|
||||||
|
$sHyperlink = utils::GetAbsoluteUrlAppRoot()
|
||||||
|
.'pages/UI.php?operation=search&'.$oAppContext->GetForLink()
|
||||||
|
.'&filter='.urlencode($oSingleGroupByValueFilter->serialize());
|
||||||
$aCounts[$sStateValue] = "<a href=\"$sHyperlink\">{$aCounts[$sStateValue]}</a>";
|
$aCounts[$sStateValue] = "<a href=\"$sHyperlink\">{$aCounts[$sStateValue]}</a>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1567,7 +1584,7 @@ class MenuBlock extends DisplayBlock
|
|||||||
// Do not perform time consuming computations if there are too may objects in the list
|
// Do not perform time consuming computations if there are too may objects in the list
|
||||||
$iLimit = MetaModel::GetConfig()->Get('complex_actions_limit');
|
$iLimit = MetaModel::GetConfig()->Get('complex_actions_limit');
|
||||||
|
|
||||||
if ((count($aStates) > 0) && (($iLimit == 0) || ($oSet->Count() < $iLimit)))
|
if ((count($aStates) > 0) && (($iLimit == 0) || ($oSet->Count($iLimit + 1) < $iLimit)))
|
||||||
{
|
{
|
||||||
// Life cycle actions may be available... if all objects are in the same state
|
// Life cycle actions may be available... if all objects are in the same state
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ EOF
|
|||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$sDialogId').dialog({
|
$('#$sDialogId').dialog({
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
|
maxHeight: $(window).height() - 8,
|
||||||
width: $iDialogWidth,
|
width: $iDialogWidth,
|
||||||
modal: true,
|
modal: true,
|
||||||
autoOpen: $sAutoOpen,
|
autoOpen: $sAutoOpen,
|
||||||
|
|||||||
@@ -331,31 +331,6 @@ EOF
|
|||||||
// This selector will be reused when selecting actual tab widget A elements.
|
// This selector will be reused when selecting actual tab widget A elements.
|
||||||
var tab_a_selector = 'ul.ui-tabs-nav a';
|
var tab_a_selector = 'ul.ui-tabs-nav a';
|
||||||
|
|
||||||
// This helper will be used to resize tab width
|
|
||||||
var resizeTab = function(oElem){
|
|
||||||
var iTableWidth = (oElem.children('table:first').length > 0) ? oElem.children('table:first').outerWidth() : 0;
|
|
||||||
var oLayoutContentElem = oElem.closest('.ui-layout-content');
|
|
||||||
var bEditMode = (oLayoutContentElem.find('.wizContainer').length > 0);
|
|
||||||
var oContainerElem = (bEditMode) ? oLayoutContentElem.find('.wizContainer:first') : oLayoutContentElem.find('.ui-tabs:first');
|
|
||||||
|
|
||||||
// Resizing wizard container
|
|
||||||
oContainerElem.css('min-width',
|
|
||||||
parseInt(iTableWidth) +
|
|
||||||
parseInt(oElem.css('margin-left'))*2 +
|
|
||||||
parseInt(oElem.css('padding-left'))*2 +
|
|
||||||
parseInt(tabs.css('margin-left'))*2 +
|
|
||||||
parseInt(tabs.css('padding-left'))*2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Resizing header according to content container
|
|
||||||
var iLayoutContentWidth = parseInt(oContainerElem.width());
|
|
||||||
if(bEditMode)
|
|
||||||
{
|
|
||||||
iLayoutContentWidth += parseInt(oContainerElem.css('margin-left'))*2 + parseInt(oContainerElem.css('padding-left'))*2
|
|
||||||
}
|
|
||||||
oLayoutContentElem.find('.page_header').css('min-width', iLayoutContentWidth);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ugly patch for a change in the behavior of jQuery UI:
|
// Ugly patch for a change in the behavior of jQuery UI:
|
||||||
// Before jQuery UI 1.9, tabs were always considered as "local" (opposed to Ajax)
|
// Before jQuery UI 1.9, tabs were always considered as "local" (opposed to Ajax)
|
||||||
// when their href was beginning by #. Starting with 1.9, a <base> tag in the page
|
// when their href was beginning by #. Starting with 1.9, a <base> tag in the page
|
||||||
@@ -379,9 +354,6 @@ EOF
|
|||||||
event: 'change', 'show': function(event, ui) {
|
event: 'change', 'show': function(event, ui) {
|
||||||
$('.resizable', ui.panel).resizable(); // Make resizable everything that claims to be resizable !
|
$('.resizable', ui.panel).resizable(); // Make resizable everything that claims to be resizable !
|
||||||
},
|
},
|
||||||
create: function( event, ui ) {
|
|
||||||
resizeTab(ui.panel);
|
|
||||||
},
|
|
||||||
beforeLoad: function( event, ui ) {
|
beforeLoad: function( event, ui ) {
|
||||||
if ( ui.tab.data('loaded') && (ui.tab.attr('data-cache') == 'true')) {
|
if ( ui.tab.data('loaded') && (ui.tab.attr('data-cache') == 'true')) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -391,9 +363,6 @@ EOF
|
|||||||
ui.jqXHR.success(function() {
|
ui.jqXHR.success(function() {
|
||||||
ui.tab.data( "loaded", true );
|
ui.tab.data( "loaded", true );
|
||||||
});
|
});
|
||||||
},
|
|
||||||
activate: function( event, ui ) {
|
|
||||||
resizeTab(ui.newPanel);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ class ApplicationMenu
|
|||||||
// the menu already exists, let's combine the conditions that make it visible
|
// the menu already exists, let's combine the conditions that make it visible
|
||||||
self::$aMenusIndex[$index]['node']->AddCondition($oMenuNode);
|
self::$aMenusIndex[$index]['node']->AddCondition($oMenuNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $index;
|
return $index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +175,7 @@ class ApplicationMenu
|
|||||||
{
|
{
|
||||||
$oMenuNode = self::GetMenuNode($aMenu['index']);
|
$oMenuNode = self::GetMenuNode($aMenu['index']);
|
||||||
if (!$oMenuNode->IsEnabled()) continue; // Don't display a non-enabled menu
|
if (!$oMenuNode->IsEnabled()) continue; // Don't display a non-enabled menu
|
||||||
$oPage->AddToMenu('<h3 id="Menu_'.$oMenuNode->GetMenuID().'">'.$oMenuNode->GetTitle().'</h3>');
|
$oPage->AddToMenu('<h3 id="'.utils::GetSafeId('AccordionMenu_'.$oMenuNode->GetMenuID()).'">'.$oMenuNode->GetTitle().'</h3>');
|
||||||
$oPage->AddToMenu('<div>');
|
$oPage->AddToMenu('<div>');
|
||||||
$aChildren = self::GetChildren($aMenu['index']);
|
$aChildren = self::GetChildren($aMenu['index']);
|
||||||
if (count($aChildren) > 0)
|
if (count($aChildren) > 0)
|
||||||
@@ -217,11 +218,11 @@ EOF
|
|||||||
$sHyperlink = $oMenu->GetHyperlink($aExtraParams);
|
$sHyperlink = $oMenu->GetHyperlink($aExtraParams);
|
||||||
if ($sHyperlink != '')
|
if ($sHyperlink != '')
|
||||||
{
|
{
|
||||||
$oPage->AddToMenu('<li id="Menu_'.$oMenu->GetMenuID().'"'.$sCSSClass.'><a href="'.$oMenu->GetHyperlink($aExtraParams).'">'.$oMenu->GetTitle().'</a></li>');
|
$oPage->AddToMenu('<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'"'.$sCSSClass.'><a href="'.$oMenu->GetHyperlink($aExtraParams).'">'.$oMenu->GetTitle().'</a></li>');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oPage->AddToMenu('<li id="Menu_'.$oMenu->GetMenuID().'"'.$sCSSClass.'>'.$oMenu->GetTitle().'</li>');
|
$oPage->AddToMenu('<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'"'.$sCSSClass.'>'.$oMenu->GetTitle().'</li>');
|
||||||
}
|
}
|
||||||
$aCurrentMenu = self::$aMenusIndex[$index];
|
$aCurrentMenu = self::$aMenusIndex[$index];
|
||||||
if ($iActiveMenu == $index)
|
if ($iActiveMenu == $index)
|
||||||
@@ -320,6 +321,21 @@ EOF
|
|||||||
}
|
}
|
||||||
return $sDefaultMenuId;
|
return $sDefaultMenuId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public function GetRootMenuId($sMenuId)
|
||||||
|
{
|
||||||
|
$iMenuIndex = self::GetMenuIndexById($sMenuId);
|
||||||
|
if ($iMenuIndex == -1)
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
$oMenu = ApplicationMenu::GetMenuNode($iMenuIndex);
|
||||||
|
while ($oMenu->GetParentIndex() != -1)
|
||||||
|
{
|
||||||
|
$oMenu = ApplicationMenu::GetMenuNode($oMenu->GetParentIndex());
|
||||||
|
}
|
||||||
|
return $oMenu->GetMenuId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -418,7 +434,12 @@ abstract class MenuNode
|
|||||||
{
|
{
|
||||||
return $this->sMenuId;
|
return $this->sMenuId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function GetParentIndex()
|
||||||
|
{
|
||||||
|
return $this->iParentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
public function GetTitle()
|
public function GetTitle()
|
||||||
{
|
{
|
||||||
return Dict::S("Menu:$this->sMenuId", str_replace('_', ' ', $this->sMenuId));
|
return Dict::S("Menu:$this->sMenuId", str_replace('_', ' ', $this->sMenuId));
|
||||||
|
|||||||
@@ -1,49 +1,62 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2016 Combodo SARL
|
// Copyright (C) 2010-2016 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// 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
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
//
|
//
|
||||||
// iTop is distributed in the hope that it will be useful,
|
// iTop is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU Affero General Public License for more details.
|
// GNU Affero General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File to include to initialize the datamodel in memory
|
* File to include to initialize the datamodel in memory
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
|
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
|
||||||
require_once(APPROOT.'/application/utils.inc.php');
|
require_once(APPROOT.'/application/utils.inc.php');
|
||||||
require_once(APPROOT.'/core/contexttag.class.inc.php');
|
require_once(APPROOT.'/core/contexttag.class.inc.php');
|
||||||
session_name('itop-'.md5(APPROOT));
|
session_name('itop-'.md5(APPROOT));
|
||||||
session_start();
|
session_start();
|
||||||
$sSwitchEnv = utils::ReadParam('switch_env', null);
|
$sSwitchEnv = utils::ReadParam('switch_env', null);
|
||||||
if (($sSwitchEnv != null) && (file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE)))
|
$bAllowCache = true;
|
||||||
{
|
if (($sSwitchEnv != null) && (file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE)) && isset($_SESSION['itop_env']) && ($_SESSION['itop_env'] !== $sSwitchEnv))
|
||||||
$_SESSION['itop_env'] = $sSwitchEnv;
|
{
|
||||||
$sEnv = $sSwitchEnv;
|
$_SESSION['itop_env'] = $sSwitchEnv;
|
||||||
// TODO: reset the credentials as well ??
|
$sEnv = $sSwitchEnv;
|
||||||
}
|
$bAllowCache = false;
|
||||||
else if (isset($_SESSION['itop_env']))
|
// Reset the opcache since otherwise the PHP "model" files may still be cached !!
|
||||||
{
|
if (function_exists('opcache_reset'))
|
||||||
$sEnv = $_SESSION['itop_env'];
|
{
|
||||||
}
|
// Zend opcode cache
|
||||||
else
|
opcache_reset();
|
||||||
{
|
}
|
||||||
$sEnv = ITOP_DEFAULT_ENV;
|
if (function_exists('apc_clear_cache'))
|
||||||
$_SESSION['itop_env'] = ITOP_DEFAULT_ENV;
|
{
|
||||||
}
|
// APC(u) cache
|
||||||
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
|
apc_clear_cache();
|
||||||
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, true /* $bAllowCache */, false /* $bTraceSourceFiles */, $sEnv);
|
}
|
||||||
|
// TODO: reset the credentials as well ??
|
||||||
|
}
|
||||||
|
else if (isset($_SESSION['itop_env']))
|
||||||
|
{
|
||||||
|
$sEnv = $_SESSION['itop_env'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sEnv = ITOP_DEFAULT_ENV;
|
||||||
|
$_SESSION['itop_env'] = ITOP_DEFAULT_ENV;
|
||||||
|
}
|
||||||
|
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
|
||||||
|
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
|
||||||
@@ -142,7 +142,12 @@ class UIExtKeyWidget
|
|||||||
throw new Exception('Implementation: null value for allowed values definition');
|
throw new Exception('Implementation: null value for allowed values definition');
|
||||||
}
|
}
|
||||||
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||||
if ($oAllowedValues->Count() < $iMaxComboLength)
|
// Don't automatically launch the search if the table is huge
|
||||||
|
$bDoSearch = !utils::IsHighCardinality($this->sTargetClass);
|
||||||
|
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
||||||
|
|
||||||
|
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
||||||
|
if ($oAllowedValues->Count($iMaxComboLength * 2) < $iMaxComboLength)
|
||||||
{
|
{
|
||||||
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
|
||||||
switch($sDisplayStyle)
|
switch($sDisplayStyle)
|
||||||
@@ -226,7 +231,7 @@ class UIExtKeyWidget
|
|||||||
}
|
}
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode);
|
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
|
||||||
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||||
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
|
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
|
||||||
$('#$this->iId').bind('change', function() { $(this).trigger('extkeychange') } );
|
$('#$this->iId').bind('change', function() { $(this).trigger('extkeychange') } );
|
||||||
@@ -261,7 +266,7 @@ EOF
|
|||||||
$iFieldSize = isset($aArgs['iFieldSize']) ? $aArgs['iFieldSize'] : 20; //@@@ $this->oAttDef->GetMaxSize();
|
$iFieldSize = isset($aArgs['iFieldSize']) ? $aArgs['iFieldSize'] : 20; //@@@ $this->oAttDef->GetMaxSize();
|
||||||
|
|
||||||
// the input for the auto-complete
|
// the input for the auto-complete
|
||||||
$sHTMLValue .= "<input class=\"field_autocomplete\" count=\"".$oAllowedValues->Count()."\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
|
$sHTMLValue .= "<input class=\"field_autocomplete\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
|
||||||
$sHTMLValue .= "<span class=\"field_input_btn\"><img id=\"mini_search_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_search.gif?itopversion=".ITOP_VERSION."\" onClick=\"oACWidget_{$this->iId}.Search();\"/></span>";
|
$sHTMLValue .= "<span class=\"field_input_btn\"><img id=\"mini_search_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_search.gif?itopversion=".ITOP_VERSION."\" onClick=\"oACWidget_{$this->iId}.Search();\"/></span>";
|
||||||
|
|
||||||
// another hidden input to store & pass the object's Id
|
// another hidden input to store & pass the object's Id
|
||||||
@@ -271,7 +276,7 @@ EOF
|
|||||||
// Scripts to start the autocomplete and bind some events to it
|
// Scripts to start the autocomplete and bind some events to it
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode);
|
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
|
||||||
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||||
$('#label_$this->iId').autocomplete(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', { scroll:true, minChars:{$iMinChars}, autoFill:false, matchContains:true, mustMatch: true, keyHolder:'#{$this->iId}', extraParams:{operation:'ac_extkey', sTargetClass:'{$this->sTargetClass}',sFilter:'$sFilter',bSearchMode:$JSSearchMode, json: function() { return $sWizHelperJSON; } }});
|
$('#label_$this->iId').autocomplete(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', { scroll:true, minChars:{$iMinChars}, autoFill:false, matchContains:true, mustMatch: true, keyHolder:'#{$this->iId}', extraParams:{operation:'ac_extkey', sTargetClass:'{$this->sTargetClass}',sFilter:'$sFilter',bSearchMode:$JSSearchMode, json: function() { return $sWizHelperJSON; } }});
|
||||||
$('#label_$this->iId').keyup(function() { if ($(this).val() == '') { $('#$this->iId').val(''); } } ); // Useful for search forms: empty value in the "label", means no value, immediatly !
|
$('#label_$this->iId').keyup(function() { if ($(this).val() == '') { $('#$this->iId').val(''); } } ); // Useful for search forms: empty value in the "label", means no value, immediatly !
|
||||||
@@ -338,7 +343,7 @@ EOF
|
|||||||
$aParams = array();
|
$aParams = array();
|
||||||
$oFilter = new DBObjectSearch($this->sTargetClass);
|
$oFilter = new DBObjectSearch($this->sTargetClass);
|
||||||
}
|
}
|
||||||
$bOpen = MetaModel::GetConfig()->Get('legacy_search_drawer_open');
|
$bOpen = MetaModel::GetConfig()->Get('legacy_search_drawer_open') || utils::IsHighCardinality($this->sTargetClass);
|
||||||
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
||||||
$oBlock = new DisplayBlock($oFilter, 'search', false, $aParams);
|
$oBlock = new DisplayBlock($oFilter, 'search', false, $aParams);
|
||||||
$sHTML .= $oBlock->GetDisplay($oPage, $this->iId, array('open' => $bOpen, 'currentId' => $this->iId));
|
$sHTML .= $oBlock->GetDisplay($oPage, $this->iId, array('open' => $bOpen, 'currentId' => $this->iId));
|
||||||
@@ -408,14 +413,22 @@ EOF
|
|||||||
$iCurrentExtKeyId = (is_null($oObj) || $this->sAttCode === '') ? 0 : $oObj->Get($this->sAttCode);
|
$iCurrentExtKeyId = (is_null($oObj) || $this->sAttCode === '') ? 0 : $oObj->Get($this->sAttCode);
|
||||||
|
|
||||||
$oValuesSet = new ValueSetObjects($sFilter, 'friendlyname'); // Bypass GetName() to avoid the encoding by htmlentities
|
$oValuesSet = new ValueSetObjects($sFilter, 'friendlyname'); // Bypass GetName() to avoid the encoding by htmlentities
|
||||||
|
$iMax = 150;
|
||||||
|
$oValuesSet->SetLimit($iMax);
|
||||||
|
$oValuesSet->SetSort(false);
|
||||||
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
|
||||||
$aValues = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains);
|
|
||||||
foreach($aValues as $sKey => $sFriendlyName)
|
$aValuesContains = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
|
||||||
|
asort($aValuesContains);
|
||||||
|
foreach($aValuesContains as $sKey => $sFriendlyName)
|
||||||
{
|
{
|
||||||
$oP->add(trim($sFriendlyName)."\t".$sKey."\n");
|
if (!isset($aValuesEquals[$sKey]))
|
||||||
|
{
|
||||||
|
$oP->add(trim($sFriendlyName)."\t".$sKey."\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the display name of the selected object, to fill back the autocomplete
|
* Get the display name of the selected object, to fill back the autocomplete
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,7 +30,14 @@ class UILinksWidgetDirect
|
|||||||
protected $sInputid;
|
protected $sInputid;
|
||||||
protected $sNameSuffix;
|
protected $sNameSuffix;
|
||||||
protected $sLinkedClass;
|
protected $sLinkedClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UILinksWidgetDirect constructor.
|
||||||
|
* @param string $sClass
|
||||||
|
* @param string $sAttCode
|
||||||
|
* @param string $sInputId
|
||||||
|
* @param string $sNameSuffix
|
||||||
|
*/
|
||||||
public function __construct($sClass, $sAttCode, $sInputId, $sNameSuffix = '')
|
public function __construct($sClass, $sAttCode, $sInputId, $sNameSuffix = '')
|
||||||
{
|
{
|
||||||
$this->sClass = $sClass;
|
$this->sClass = $sClass;
|
||||||
@@ -74,12 +81,12 @@ class UILinksWidgetDirect
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param WebPage $oPage
|
||||||
* @param DBObjectSet $oValue
|
* @param DBObjectSet|ormLinkSet $oValue
|
||||||
* @param array $aArgs
|
* @param array $aArgs
|
||||||
* @param $sFormPrefix
|
* @param string $sFormPrefix
|
||||||
* @param $oCurrentObj
|
* @param DBObject $oCurrentObj
|
||||||
*/
|
*/
|
||||||
public function Display(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
|
public function Display(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
|
||||||
{
|
{
|
||||||
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
|
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
|
||||||
switch($oLinksetDef->GetEditMode())
|
switch($oLinksetDef->GetEditMode())
|
||||||
@@ -127,11 +134,11 @@ class UILinksWidgetDirect
|
|||||||
* @param WebPage $oPage
|
* @param WebPage $oPage
|
||||||
* @param DBObjectSet $oValue
|
* @param DBObjectSet $oValue
|
||||||
* @param array $aArgs
|
* @param array $aArgs
|
||||||
* @param $sFormPrefix
|
* @param string $sFormPrefix
|
||||||
* @param $oCurrentObj
|
* @param DBObject $oCurrentObj
|
||||||
* @param $bDisplayMenu
|
* @param bool $bDisplayMenu
|
||||||
*/
|
*/
|
||||||
protected function DisplayAsBlock(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $bDisplayMenu)
|
protected function DisplayAsBlock(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $bDisplayMenu)
|
||||||
{
|
{
|
||||||
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
|
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
|
||||||
$sTargetClass = $oLinksetDef->GetLinkedClass();
|
$sTargetClass = $oLinksetDef->GetLinkedClass();
|
||||||
@@ -170,50 +177,8 @@ class UILinksWidgetDirect
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WebPage $oPage
|
* @param WebPage $oPage
|
||||||
* @param DBObjectSet $oValue
|
* @param string $sProposedRealClass
|
||||||
* @param array $aArgs
|
|
||||||
* @param $sFormPrefix
|
|
||||||
* @param $oCurrentObj
|
|
||||||
* @param array $aButtons
|
|
||||||
*/
|
*/
|
||||||
protected function DisplayEditInPlace(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $aButtons = array('create', 'delete'))
|
|
||||||
{
|
|
||||||
$aAttribs = $this->GetTableConfig();
|
|
||||||
|
|
||||||
$oValue->Rewind();
|
|
||||||
$oPage->add('<table class="listContainer" id="'.$this->sInputid.'"><tr><td>');
|
|
||||||
|
|
||||||
$aData = array();
|
|
||||||
while($oLinkObj = $oValue->Fetch())
|
|
||||||
{
|
|
||||||
$aRow = array();
|
|
||||||
$aRow['form::select'] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.$oLinkObj->GetKey().'"/>';
|
|
||||||
foreach($this->aZlist as $sLinkedAttCode)
|
|
||||||
{
|
|
||||||
$aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode);
|
|
||||||
}
|
|
||||||
$aData[] = $aRow;
|
|
||||||
}
|
|
||||||
$oPage->table($aAttribs, $aData);
|
|
||||||
$oPage->add('</td></tr></table>'); //listcontainer
|
|
||||||
$sInputName = $sFormPrefix.'attr_'.$this->sAttCode;
|
|
||||||
$aLabels = array(
|
|
||||||
'delete' => Dict::S('UI:Button:Delete'),
|
|
||||||
// 'modify' => 'Modify...' ,
|
|
||||||
'creation_title' => Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($this->sLinkedClass)),
|
|
||||||
'create' => Dict::Format('UI:ClickToCreateNew', MetaModel::GetName($this->sLinkedClass)),
|
|
||||||
'remove' => Dict::S('UI:Button:Remove'),
|
|
||||||
'add' => Dict::Format('UI:AddAnExisting_Class', MetaModel::GetName($this->sLinkedClass)),
|
|
||||||
'selection_title' => Dict::Format('UI:SelectionOf_Class', MetaModel::GetName($this->sLinkedClass)),
|
|
||||||
);
|
|
||||||
$oContext = new ApplicationContext();
|
|
||||||
$sSubmitUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?'.$oContext->GetForLink();
|
|
||||||
$sJSONLabels = json_encode($aLabels);
|
|
||||||
$sJSONButtons = json_encode($aButtons);
|
|
||||||
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
|
||||||
$oPage->add_ready_script("$('#{$this->sInputid}').directlinks({class_name: '$this->sClass', att_code: '$this->sAttCode', input_name:'$sInputName', labels: $sJSONLabels, submit_to: '$sSubmitUrl', buttons: $sJSONButtons, oWizardHelper: $sWizHelper });");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetObjectCreationDlg(WebPage $oPage, $sProposedRealClass = '')
|
public function GetObjectCreationDlg(WebPage $oPage, $sProposedRealClass = '')
|
||||||
{
|
{
|
||||||
// For security reasons: check that the "proposed" class is actually a subclass of the linked class
|
// For security reasons: check that the "proposed" class is actually a subclass of the linked class
|
||||||
@@ -239,14 +204,14 @@ class UILinksWidgetDirect
|
|||||||
$aKeys = array_keys($aPossibleClasses);
|
$aKeys = array_keys($aPossibleClasses);
|
||||||
$sRealClass = $aKeys[0];
|
$sRealClass = $aKeys[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($sRealClass != '')
|
if ($sRealClass != '')
|
||||||
{
|
{
|
||||||
$oPage->add("<h1>".MetaModel::GetClassIcon($sRealClass)." ".Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($sRealClass))."</h1>\n");
|
$oPage->add("<h1>".MetaModel::GetClassIcon($sRealClass)." ".Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($sRealClass))."</h1>\n");
|
||||||
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
|
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
|
||||||
$sExtKeyToMe = $oLinksetDef->GetExtKeyToMe();
|
$sExtKeyToMe = $oLinksetDef->GetExtKeyToMe();
|
||||||
$aFieldFlags = array( $sExtKeyToMe => OPT_ATT_HIDDEN);
|
$aFieldFlags = array( $sExtKeyToMe => OPT_ATT_HIDDEN);
|
||||||
cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, null, array(), array('formPrefix' => $this->sInputid, 'noRelations' => true, 'fieldsFlags' => $aFieldFlags));
|
cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, null, array(), array('formPrefix' => $this->sInputid, 'noRelations' => true, 'fieldsFlags' => $aFieldFlags));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -263,7 +228,61 @@ class UILinksWidgetDirect
|
|||||||
}
|
}
|
||||||
$oPage->add('</div></div>');
|
$oPage->add('</div></div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebPage $oPage
|
||||||
|
* @param DBObjectSet $oValue
|
||||||
|
* @param array $aArgs
|
||||||
|
* @param string $sFormPrefix
|
||||||
|
* @param DBObject $oCurrentObj
|
||||||
|
* @param array $aButtons
|
||||||
|
*/
|
||||||
|
protected function DisplayEditInPlace(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $aButtons = array('create', 'delete'))
|
||||||
|
{
|
||||||
|
$aAttribs = $this->GetTableConfig();
|
||||||
|
|
||||||
|
$oValue->Rewind();
|
||||||
|
$oPage->add('<table class="listContainer" id="'.$this->sInputid.'"><tr><td>');
|
||||||
|
|
||||||
|
$aData = array();
|
||||||
|
while($oLinkObj = $oValue->Fetch())
|
||||||
|
{
|
||||||
|
$aRow = array();
|
||||||
|
$aRow['form::select'] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.$oLinkObj->GetKey().'"/>';
|
||||||
|
foreach($this->aZlist as $sLinkedAttCode)
|
||||||
|
{
|
||||||
|
$aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode);
|
||||||
|
}
|
||||||
|
$aData[] = $aRow;
|
||||||
|
}
|
||||||
|
$oPage->table($aAttribs, $aData);
|
||||||
|
$oPage->add('</td></tr></table>'); //listcontainer
|
||||||
|
$sInputName = $sFormPrefix.'attr_'.$this->sAttCode;
|
||||||
|
$aLabels = array(
|
||||||
|
'delete' => Dict::S('UI:Button:Delete'),
|
||||||
|
// 'modify' => 'Modify...' ,
|
||||||
|
'creation_title' => Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($this->sLinkedClass)),
|
||||||
|
'create' => Dict::Format('UI:ClickToCreateNew', MetaModel::GetName($this->sLinkedClass)),
|
||||||
|
'remove' => Dict::S('UI:Button:Remove'),
|
||||||
|
'add' => Dict::Format('UI:AddAnExisting_Class', MetaModel::GetName($this->sLinkedClass)),
|
||||||
|
'selection_title' => Dict::Format('UI:SelectionOf_Class', MetaModel::GetName($this->sLinkedClass)),
|
||||||
|
);
|
||||||
|
$oContext = new ApplicationContext();
|
||||||
|
$sSubmitUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?'.$oContext->GetForLink();
|
||||||
|
$sJSONLabels = json_encode($aLabels);
|
||||||
|
$sJSONButtons = json_encode($aButtons);
|
||||||
|
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
||||||
|
// Don't automatically launch the search if the table is huge
|
||||||
|
$bDoSearch = !utils::IsHighCardinality($this->sLinkedClass);
|
||||||
|
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
||||||
|
$oPage->add_ready_script("$('#{$this->sInputid}').directlinks({class_name: '$this->sClass', att_code: '$this->sAttCode', input_name:'$sInputName', labels: $sJSONLabels, submit_to: '$sSubmitUrl', buttons: $sJSONButtons, oWizardHelper: $sWizHelper, do_search: $sJSDoSearch});");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebPage $oPage
|
||||||
|
* @param DBObject $oCurrentObj
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public function GetObjectsSelectionDlg($oPage, $oCurrentObj)
|
public function GetObjectsSelectionDlg($oPage, $oCurrentObj)
|
||||||
{
|
{
|
||||||
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
|
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
|
||||||
@@ -286,7 +305,7 @@ class UILinksWidgetDirect
|
|||||||
{
|
{
|
||||||
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
||||||
}
|
}
|
||||||
$bOpen = MetaModel::GetConfig()->Get('legacy_search_drawer_open');
|
$bOpen = MetaModel::GetConfig()->Get('legacy_search_drawer_open') || utils::IsHighCardinality($this->sLinkedClass);
|
||||||
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
||||||
$sHtml .= $oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->sInputid}", array('open' => $bOpen));
|
$sHtml .= $oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->sInputid}", array('open' => $bOpen));
|
||||||
$sHtml .= "<form id=\"ObjectsAddForm_{$this->sInputid}\">\n";
|
$sHtml .= "<form id=\"ObjectsAddForm_{$this->sInputid}\">\n";
|
||||||
@@ -299,13 +318,14 @@ class UILinksWidgetDirect
|
|||||||
$sHtml .= "</form>\n";
|
$sHtml .= "</form>\n";
|
||||||
$oPage->add($sHtml);
|
$oPage->add($sHtml);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for objects to be linked to the current object (i.e "remote" objects)
|
* Search for objects to be linked to the current object (i.e "remote" objects)
|
||||||
* @param WebPage $oP The page used for the output (usually an AjaxWebPage)
|
* @param WebPage $oP The page used for the output (usually an AjaxWebPage)
|
||||||
* @param string $sRemoteClass Name of the "remote" class to perform the search on, must be a derived class of $this->sLinkedClass
|
* @param string $sRemoteClass Name of the "remote" class to perform the search on, must be a derived class of $this->sLinkedClass
|
||||||
* @param array $aAlreadyLinked Array of indentifiers of objects which are already linke to the current object (or about to be linked)
|
* @param array $aAlreadyLinked Array of indentifiers of objects which are already linke to the current object (or about to be linked)
|
||||||
* @param DBObject $oCurrentObj The object currently being edited... if known...
|
* @param DBObject $oCurrentObj The object currently being edited... if known...
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinked = array(), $oCurrentObj = null)
|
public function SearchObjectsToAdd(WebPage $oP, $sRemoteClass = '', $aAlreadyLinked = array(), $oCurrentObj = null)
|
||||||
{
|
{
|
||||||
@@ -350,6 +370,10 @@ class UILinksWidgetDirect
|
|||||||
$oBlock->Display($oP, "ResultsToAdd_{$this->sInputid}", array('menu' => false, 'cssCount'=> '#count_'.$this->sInputid , 'selection_mode' => true, 'table_id' => 'add_'.$this->sInputid)); // Don't display the 'Actions' menu on the results
|
$oBlock->Display($oP, "ResultsToAdd_{$this->sInputid}", array('menu' => false, 'cssCount'=> '#count_'.$this->sInputid , 'selection_mode' => true, 'table_id' => 'add_'.$this->sInputid)); // Don't display the 'Actions' menu on the results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebPage $oP
|
||||||
|
* @param $oFullSetFilter
|
||||||
|
*/
|
||||||
public function DoAddObjects(WebPage $oP, $oFullSetFilter)
|
public function DoAddObjects(WebPage $oP, $oFullSetFilter)
|
||||||
{
|
{
|
||||||
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
||||||
@@ -377,7 +401,14 @@ class UILinksWidgetDirect
|
|||||||
}
|
}
|
||||||
return $aAttribs;
|
return $aAttribs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebPage $oPage
|
||||||
|
* @param string $sRealClass
|
||||||
|
* @param array $aValues
|
||||||
|
* @param int $iTempId
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function GetRow($oPage, $sRealClass, $aValues, $iTempId)
|
public function GetRow($oPage, $sRealClass, $aValues, $iTempId)
|
||||||
{
|
{
|
||||||
if ($sRealClass == '')
|
if ($sRealClass == '')
|
||||||
@@ -389,7 +420,13 @@ class UILinksWidgetDirect
|
|||||||
|
|
||||||
return $this->GetObjectRow($oPage, $oLinkObj, $iTempId);
|
return $this->GetObjectRow($oPage, $oLinkObj, $iTempId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebPage $oPage
|
||||||
|
* @param $oLinkObj
|
||||||
|
* @param int $iTempId
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
protected function GetObjectRow($oPage, $oLinkObj, $iTempId)
|
protected function GetObjectRow($oPage, $oLinkObj, $iTempId)
|
||||||
{
|
{
|
||||||
$aAttribs = $this->GetTableConfig();
|
$aAttribs = $this->GetTableConfig();
|
||||||
@@ -405,7 +442,7 @@ class UILinksWidgetDirect
|
|||||||
/**
|
/**
|
||||||
* Initializes the default search parameters based on 1) a 'current' object and 2) the silos defined by the context
|
* Initializes the default search parameters based on 1) a 'current' object and 2) the silos defined by the context
|
||||||
* @param DBObject $oSourceObj
|
* @param DBObject $oSourceObj
|
||||||
* @param DBSearch $oSearch
|
* @param DBSearch|DBObjectSearch $oSearch
|
||||||
*/
|
*/
|
||||||
protected function SetSearchDefaultFromContext($oSourceObj, &$oSearch)
|
protected function SetSearchDefaultFromContext($oSourceObj, &$oSearch)
|
||||||
{
|
{
|
||||||
@@ -424,7 +461,6 @@ class UILinksWidgetDirect
|
|||||||
|
|
||||||
if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode))
|
if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode))
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sSrcClass, $sAttCode);
|
|
||||||
$defaultValue = $oSourceObj->Get($sAttCode);
|
$defaultValue = $oSourceObj->Get($sAttCode);
|
||||||
|
|
||||||
// Find the attcode for the same 'context' parameter in the destination class
|
// Find the attcode for the same 'context' parameter in the destination class
|
||||||
|
|||||||
@@ -39,7 +39,15 @@ class UILinksWidget
|
|||||||
protected $m_sLinkedClass;
|
protected $m_sLinkedClass;
|
||||||
protected $m_sRemoteClass;
|
protected $m_sRemoteClass;
|
||||||
protected $m_bDuplicatesAllowed;
|
protected $m_bDuplicatesAllowed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UILinksWidget constructor.
|
||||||
|
* @param string $sClass
|
||||||
|
* @param string $sAttCode
|
||||||
|
* @param int $iInputId
|
||||||
|
* @param string $sNameSuffix
|
||||||
|
* @param bool $bDuplicatesAllowed
|
||||||
|
*/
|
||||||
public function __construct($sClass, $sAttCode, $iInputId, $sNameSuffix = '', $bDuplicatesAllowed = false)
|
public function __construct($sClass, $sAttCode, $iInputId, $sNameSuffix = '', $bDuplicatesAllowed = false)
|
||||||
{
|
{
|
||||||
$this->m_sClass = $sClass;
|
$this->m_sClass = $sClass;
|
||||||
@@ -98,11 +106,11 @@ class UILinksWidget
|
|||||||
* @param WebPage $oP Web page used for the ouput
|
* @param WebPage $oP Web page used for the ouput
|
||||||
* @param DBObject $oLinkedObj Remote object
|
* @param DBObject $oLinkedObj Remote object
|
||||||
* @param mixed $linkObjOrId Either the object linked or a unique number for new link records to add
|
* @param mixed $linkObjOrId Either the object linked or a unique number for new link records to add
|
||||||
* @param array|Hash $aArgs Extra context arguments
|
* @param array $aArgs Extra context arguments
|
||||||
* @param $oCurrentObj The object to which all the elements of the linked set refer to
|
* @param DBObject $oCurrentObj The object to which all the elements of the linked set refer to
|
||||||
* @param $iUniqueId A unique identifier of new links
|
* @param int $iUniqueId A unique identifier of new links
|
||||||
* @param boolean $bReadOnly Display link as editable or read-only. Default is false (editable)
|
* @param boolean $bReadOnly Display link as editable or read-only. Default is false (editable)
|
||||||
* @return string The HTML fragment of the one-row form
|
* @return array The HTML fragment of the one-row form
|
||||||
*/
|
*/
|
||||||
protected function GetFormRow(WebPage $oP, DBObject $oLinkedObj, $linkObjOrId, $aArgs, $oCurrentObj, $iUniqueId, $bReadOnly = false)
|
protected function GetFormRow(WebPage $oP, DBObject $oLinkedObj, $linkObjOrId, $aArgs, $oCurrentObj, $iUniqueId, $bReadOnly = false)
|
||||||
{
|
{
|
||||||
@@ -138,7 +146,9 @@ class UILinksWidget
|
|||||||
$sValue = $linkObjOrId->Get($sFieldCode);
|
$sValue = $linkObjOrId->Get($sFieldCode);
|
||||||
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
|
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
|
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
|
||||||
$aRow[$sFieldCode] = cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId, $sNameSuffix, 0, $aArgs);
|
$aRow[$sFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'.
|
||||||
|
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId, $sNameSuffix, 0, $aArgs).
|
||||||
|
'</div></div></div>';
|
||||||
$aFieldsMap[$sFieldCode] = $sSafeId;
|
$aFieldsMap[$sFieldCode] = $sSafeId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,7 +176,7 @@ class UILinksWidget
|
|||||||
$sPrefix .= "[-$iUniqueId][";
|
$sPrefix .= "[-$iUniqueId][";
|
||||||
$sNameSuffix = "]"; // To make a tabular form
|
$sNameSuffix = "]"; // To make a tabular form
|
||||||
$aArgs['prefix'] = $sPrefix;
|
$aArgs['prefix'] = $sPrefix;
|
||||||
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}_".$iUniqueId;
|
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}_".($iUniqueId < 0 ? -$iUniqueId : $iUniqueId);
|
||||||
$aArgs['this'] = $oNewLinkObj;
|
$aArgs['this'] = $oNewLinkObj;
|
||||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"-$iUniqueId\">";
|
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"-$iUniqueId\">";
|
||||||
foreach($this->m_aEditableFields as $sFieldCode)
|
foreach($this->m_aEditableFields as $sFieldCode)
|
||||||
@@ -176,17 +186,24 @@ class UILinksWidget
|
|||||||
$sValue = $oNewLinkObj->Get($sFieldCode);
|
$sValue = $oNewLinkObj->Get($sFieldCode);
|
||||||
$sDisplayValue = $oNewLinkObj->GetEditValue($sFieldCode);
|
$sDisplayValue = $oNewLinkObj->GetEditValue($sFieldCode);
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
|
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
|
||||||
$aRow[$sFieldCode] = cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId /* id */, $sNameSuffix, 0, $aArgs);
|
$aRow[$sFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'.
|
||||||
|
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId /* id */, $sNameSuffix, 0, $aArgs).
|
||||||
|
'</div></div></div>';
|
||||||
$aFieldsMap[$sFieldCode] = $sSafeId;
|
$aFieldsMap[$sFieldCode] = $sSafeId;
|
||||||
}
|
}
|
||||||
$sState = '';
|
$sState = '';
|
||||||
|
|
||||||
$oP->add_script(
|
// Rows created with ajax call need OnLinkAdded call.
|
||||||
<<<EOF
|
// Rows added before loading the form cannot call OnLinkAdded.
|
||||||
|
if ($iUniqueId > 0)
|
||||||
|
{
|
||||||
|
$oP->add_script(
|
||||||
|
<<<EOF
|
||||||
PrepareWidgets();
|
PrepareWidgets();
|
||||||
oWidget{$this->m_iInputId}.OnLinkAdded($iUniqueId, $iRemoteObjKey);
|
oWidget{$this->m_iInputId}.OnLinkAdded($iUniqueId, $iRemoteObjKey);
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$bReadOnly)
|
if(!$bReadOnly)
|
||||||
@@ -220,7 +237,11 @@ EOF
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Display one row of the whole form
|
* Display one row of the whole form
|
||||||
* @return none
|
* @param WebPage $oP
|
||||||
|
* @param array $aConfig
|
||||||
|
* @param array $aRow
|
||||||
|
* @param int $iRowId
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function DisplayFormRow(WebPage $oP, $aConfig, $aRow, $iRowId)
|
protected function DisplayFormRow(WebPage $oP, $aConfig, $aRow, $iRowId)
|
||||||
{
|
{
|
||||||
@@ -238,8 +259,8 @@ EOF
|
|||||||
/**
|
/**
|
||||||
* Display the table with the form for editing all the links at once
|
* Display the table with the form for editing all the links at once
|
||||||
* @param WebPage $oP The web page used for the output
|
* @param WebPage $oP The web page used for the output
|
||||||
* @param Hash $aConfig The table's header configuration
|
* @param array $aConfig The table's header configuration
|
||||||
* @param Hash $aData The tabular data to be displayed
|
* @param array $aData The tabular data to be displayed
|
||||||
* @return string Html fragment representing the form table
|
* @return string Html fragment representing the form table
|
||||||
*/
|
*/
|
||||||
protected function DisplayFormTable(WebPage $oP, $aConfig, $aData)
|
protected function DisplayFormTable(WebPage $oP, $aConfig, $aData)
|
||||||
@@ -276,21 +297,20 @@ EOF
|
|||||||
|
|
||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the HTML fragment corresponding to the linkset editing widget
|
* Get the HTML fragment corresponding to the linkset editing widget
|
||||||
* @param WebPage $oP The web page used for all the output
|
* @param WebPage $oPage
|
||||||
* @param DBObjectSet The initial value of the linked set
|
* @param DBObject|ormLinkSet $oValue
|
||||||
* @param Hash $aArgs Extra context arguments
|
* @param array $aArgs Extra context arguments
|
||||||
* @param string $sFormPrefix prefix of the fields in the current form
|
* @param string $sFormPrefix prefix of the fields in the current form
|
||||||
* @param DBObject $oCurrentObj the current object to which the linkset is related
|
* @param DBObject $oCurrentObj the current object to which the linkset is related
|
||||||
* @return string The HTML fragment to be inserted into the page
|
* @return string The HTML fragment to be inserted into the page
|
||||||
*/
|
*/
|
||||||
public function Display(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
|
public function Display(WebPage $oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
|
||||||
{
|
{
|
||||||
$sHtmlValue = '';
|
$sHtmlValue = '';
|
||||||
$sTargetClass = self::GetTargetClass($this->m_sClass, $this->m_sAttCode);
|
|
||||||
$sHtmlValue .= "<div id=\"linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix}\">\n";
|
$sHtmlValue .= "<div id=\"linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix}\">\n";
|
||||||
$sHtmlValue .= "<input type=\"hidden\" id=\"{$sFormPrefix}{$this->m_iInputId}\">\n";
|
$sHtmlValue .= "<input type=\"hidden\" id=\"{$sFormPrefix}{$this->m_iInputId}\">\n";
|
||||||
$oValue->Rewind();
|
$oValue->Rewind();
|
||||||
@@ -324,9 +344,12 @@ EOF
|
|||||||
}
|
}
|
||||||
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
||||||
$sDuplicates = ($this->m_bDuplicatesAllowed) ? 'true' : 'false';
|
$sDuplicates = ($this->m_bDuplicatesAllowed) ? 'true' : 'false';
|
||||||
|
// Don't automatically launch the search if the table is huge
|
||||||
|
$bDoSearch = !utils::IsHighCardinality($this->m_sRemoteClass);
|
||||||
|
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
|
||||||
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
||||||
$oPage->add_ready_script(<<<EOF
|
$oPage->add_ready_script(<<<EOF
|
||||||
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper, '{$this->m_sExtKeyToRemote}');
|
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper, '{$this->m_sExtKeyToRemote}', $sJSDoSearch);
|
||||||
oWidget{$this->m_iInputId}.Init();
|
oWidget{$this->m_iInputId}.Init();
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
@@ -337,11 +360,17 @@ EOF
|
|||||||
$oPage->add_at_the_end("<div id=\"dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}\"></div>"); // To prevent adding forms inside the main form
|
$oPage->add_at_the_end("<div id=\"dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}\"></div>"); // To prevent adding forms inside the main form
|
||||||
return $sHtmlValue;
|
return $sHtmlValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sClass
|
||||||
|
* @param string $sAttCode
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
protected static function GetTargetClass($sClass, $sAttCode)
|
protected static function GetTargetClass($sClass, $sAttCode)
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||||
$sLinkedClass = $oAttDef->GetLinkedClass();
|
$sLinkedClass = $oAttDef->GetLinkedClass();
|
||||||
|
$sTargetClass = '';
|
||||||
switch(get_class($oAttDef))
|
switch(get_class($oAttDef))
|
||||||
{
|
{
|
||||||
case 'AttributeLinkedSetIndirect':
|
case 'AttributeLinkedSetIndirect':
|
||||||
@@ -356,10 +385,14 @@ EOF
|
|||||||
|
|
||||||
return $sTargetClass;
|
return $sTargetClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebPage $oPage
|
||||||
|
* @param DBObject $oCurrentObj
|
||||||
|
*/
|
||||||
public function GetObjectPickerDialog($oPage, $oCurrentObj)
|
public function GetObjectPickerDialog($oPage, $oCurrentObj)
|
||||||
{
|
{
|
||||||
$bOpen = MetaModel::GetConfig()->Get('legacy_search_drawer_open');
|
$bOpen = MetaModel::GetConfig()->Get('legacy_search_drawer_open') || utils::IsHighCardinality($this->m_sRemoteClass);
|
||||||
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
|
$sHtml = "<div class=\"wizContainer\" style=\"vertical-align:top;\">\n";
|
||||||
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||||
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter);
|
||||||
@@ -405,7 +438,13 @@ EOF
|
|||||||
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
||||||
$oBlock->Display($oP, "ResultsToAdd_{$this->m_sAttCode}", array('menu' => false, 'cssCount'=> '#count_'.$this->m_sAttCode.$this->m_sNameSuffix , 'selection_mode' => true, 'table_id' => 'add_'.$this->m_sAttCode)); // Don't display the 'Actions' menu on the results
|
$oBlock->Display($oP, "ResultsToAdd_{$this->m_sAttCode}", array('menu' => false, 'cssCount'=> '#count_'.$this->m_sAttCode.$this->m_sNameSuffix , 'selection_mode' => true, 'table_id' => 'add_'.$this->m_sAttCode)); // Don't display the 'Actions' menu on the results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param WebPage $oP
|
||||||
|
* @param int $iMaxAddedId
|
||||||
|
* @param $oFullSetFilter
|
||||||
|
* @param DBObject $oCurrentObj
|
||||||
|
*/
|
||||||
public function DoAddObjects(WebPage $oP, $iMaxAddedId, $oFullSetFilter, $oCurrentObj)
|
public function DoAddObjects(WebPage $oP, $iMaxAddedId, $oFullSetFilter, $oCurrentObj)
|
||||||
{
|
{
|
||||||
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
||||||
@@ -430,7 +469,7 @@ EOF
|
|||||||
/**
|
/**
|
||||||
* Initializes the default search parameters based on 1) a 'current' object and 2) the silos defined by the context
|
* Initializes the default search parameters based on 1) a 'current' object and 2) the silos defined by the context
|
||||||
* @param DBObject $oSourceObj
|
* @param DBObject $oSourceObj
|
||||||
* @param DBSearch $oSearch
|
* @param DBSearch|DBObjectSearch $oSearch
|
||||||
*/
|
*/
|
||||||
protected function SetSearchDefaultFromContext($oSourceObj, &$oSearch)
|
protected function SetSearchDefaultFromContext($oSourceObj, &$oSearch)
|
||||||
{
|
{
|
||||||
@@ -449,7 +488,6 @@ EOF
|
|||||||
|
|
||||||
if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode))
|
if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode))
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sSrcClass, $sAttCode);
|
|
||||||
$defaultValue = $oSourceObj->Get($sAttCode);
|
$defaultValue = $oSourceObj->Get($sAttCode);
|
||||||
|
|
||||||
// Find the attcode for the same 'context' parameter in the destination class
|
// Find the attcode for the same 'context' parameter in the destination class
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ class utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static $bPageMode = null;
|
protected static $bPageMode = null;
|
||||||
|
/**
|
||||||
|
* @var boolean[]
|
||||||
|
*/
|
||||||
protected static $aModes = array();
|
protected static $aModes = array();
|
||||||
|
|
||||||
public static function InitArchiveMode()
|
public static function InitArchiveMode()
|
||||||
@@ -164,6 +167,10 @@ class utils
|
|||||||
self::$bPageMode = ($iCurrent == 1);
|
self::$bPageMode = ($iCurrent == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $bMode if true then activate archive mode (archived objects are visible), otherwise archived objects are
|
||||||
|
* hidden (archive = "soft deletion")
|
||||||
|
*/
|
||||||
public static function PushArchiveMode($bMode)
|
public static function PushArchiveMode($bMode)
|
||||||
{
|
{
|
||||||
array_push(self::$aModes, $bMode);
|
array_push(self::$aModes, $bMode);
|
||||||
@@ -174,6 +181,9 @@ class utils
|
|||||||
array_pop(self::$aModes);
|
array_pop(self::$aModes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean true if archive mode is enabled
|
||||||
|
*/
|
||||||
public static function IsArchiveMode()
|
public static function IsArchiveMode()
|
||||||
{
|
{
|
||||||
if (count(self::$aModes) > 0)
|
if (count(self::$aModes) > 0)
|
||||||
@@ -605,16 +615,20 @@ class utils
|
|||||||
{
|
{
|
||||||
if (self::$oConfig == null)
|
if (self::$oConfig == null)
|
||||||
{
|
{
|
||||||
$sConfigFile = self::GetConfigFilePath();
|
self::$oConfig = MetaModel::GetConfig();
|
||||||
if (file_exists($sConfigFile))
|
if (self::$oConfig == null)
|
||||||
{
|
{
|
||||||
self::$oConfig = new Config($sConfigFile);
|
$sConfigFile = self::GetConfigFilePath();
|
||||||
}
|
if (file_exists($sConfigFile))
|
||||||
else
|
{
|
||||||
{
|
self::$oConfig = new Config($sConfigFile);
|
||||||
// When executing the setup, the config file may be still missing
|
}
|
||||||
self::$oConfig = new Config();
|
else
|
||||||
}
|
{
|
||||||
|
// When executing the setup, the config file may be still missing
|
||||||
|
self::$oConfig = new Config();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return self::$oConfig;
|
return self::$oConfig;
|
||||||
}
|
}
|
||||||
@@ -917,7 +931,7 @@ class utils
|
|||||||
*/
|
*/
|
||||||
public static function GetCachePath()
|
public static function GetCachePath()
|
||||||
{
|
{
|
||||||
return APPROOT.'data/cache-'.self::GetCurrentEnvironment().'/';
|
return APPROOT.'data/cache-'.MetaModel::GetEnvironment().'/';
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Merge standard menu items with plugin provided menus items
|
* Merge standard menu items with plugin provided menus items
|
||||||
@@ -957,8 +971,8 @@ class utils
|
|||||||
// PDF export requires GD
|
// PDF export requires GD
|
||||||
$aResult[] = new JSPopupMenuItem('UI:Menu:ExportPDF', Dict::S('UI:Menu:ExportPDF'), "ExportListDlg('$sOQL', '$sDataTableId', 'pdf', ".json_encode(Dict::S('UI:Menu:ExportPDF')).")");
|
$aResult[] = new JSPopupMenuItem('UI:Menu:ExportPDF', Dict::S('UI:Menu:ExportPDF'), "ExportListDlg('$sOQL', '$sDataTableId', 'pdf', ".json_encode(Dict::S('UI:Menu:ExportPDF')).")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$aResult[] = new JSPopupMenuItem('UI:Menu:AddToDashboard', Dict::S('UI:Menu:AddToDashboard'), "DashletCreationDlg('$sOQL')");
|
$aResult[] = new JSPopupMenuItem('UI:Menu:AddToDashboard', Dict::S('UI:Menu:AddToDashboard'), "DashletCreationDlg('$sOQL', '$sContext')");
|
||||||
$aResult[] = new JSPopupMenuItem('UI:Menu:ShortcutList', Dict::S('UI:Menu:ShortcutList'), "ShortcutListDlg('$sOQL', '$sDataTableId', '$sContext')");
|
$aResult[] = new JSPopupMenuItem('UI:Menu:ShortcutList', Dict::S('UI:Menu:ShortcutList'), "ShortcutListDlg('$sOQL', '$sDataTableId', '$sContext')");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1054,8 +1068,7 @@ class utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the absolute URL to the modules root path
|
* @return string the absolute URL to the modules root path
|
||||||
* @return string ...
|
|
||||||
*/
|
*/
|
||||||
static public function GetAbsoluteUrlModulesRoot()
|
static public function GetAbsoluteUrlModulesRoot()
|
||||||
{
|
{
|
||||||
@@ -1063,33 +1076,67 @@ class utils
|
|||||||
return $sUrl;
|
return $sUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URL to a page that will execute the requested module page
|
* To be compatible with this mechanism, the called page must include approot with an absolute path OR not include
|
||||||
*
|
* it at all (losing the direct access to the page) :
|
||||||
* To be compatible with this mechanism, the called page must include approot
|
*
|
||||||
* with an absolute path OR not include it at all (losing the direct access to the page)
|
* ```php
|
||||||
* if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
* if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||||
* require_once(__DIR__.'/../../approot.inc.php');
|
* require_once(__DIR__.'/../../approot.inc.php');
|
||||||
*
|
* ```
|
||||||
* @return string ...
|
*
|
||||||
*/
|
* @param string $sModule
|
||||||
|
* @param string $sPage
|
||||||
|
* @param string[] $aArguments
|
||||||
|
* @param string $sEnvironment
|
||||||
|
*
|
||||||
|
* @return string the URL to a page that will execute the requested module page, with query string values url encoded
|
||||||
|
*
|
||||||
|
* @see GetExecPageArguments can be used to submit using the GET method (see bug in N.1108)
|
||||||
|
* @see GetAbsoluteUrlExecPage
|
||||||
|
*/
|
||||||
static public function GetAbsoluteUrlModulePage($sModule, $sPage, $aArguments = array(), $sEnvironment = null)
|
static public function GetAbsoluteUrlModulePage($sModule, $sPage, $aArguments = array(), $sEnvironment = null)
|
||||||
|
{
|
||||||
|
$aArgs = self::GetExecPageArguments($sModule, $sPage, $aArguments, $sEnvironment);
|
||||||
|
$sArgs = http_build_query($aArgs);
|
||||||
|
|
||||||
|
return self::GetAbsoluteUrlExecPage()."?".$sArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sModule
|
||||||
|
* @param string $sPage
|
||||||
|
* @param string[] $aArguments
|
||||||
|
* @param string $sEnvironment
|
||||||
|
*
|
||||||
|
* @return string[] key/value pair for the exec page query string. <b>Warning</b> : values are not url encoded !
|
||||||
|
* @throws \Exception if one of the argument has a reserved name
|
||||||
|
*/
|
||||||
|
static public function GetExecPageArguments($sModule, $sPage, $aArguments = array(), $sEnvironment = null)
|
||||||
{
|
{
|
||||||
$sEnvironment = is_null($sEnvironment) ? self::GetCurrentEnvironment() : $sEnvironment;
|
$sEnvironment = is_null($sEnvironment) ? self::GetCurrentEnvironment() : $sEnvironment;
|
||||||
$aArgs = array();
|
$aArgs = array();
|
||||||
$aArgs[] = 'exec_module='.$sModule;
|
$aArgs['exec_module'] = $sModule;
|
||||||
$aArgs[] = 'exec_page='.$sPage;
|
$aArgs['exec_page'] = $sPage;
|
||||||
$aArgs[] = 'exec_env='.$sEnvironment;
|
$aArgs['exec_env'] = $sEnvironment;
|
||||||
foreach($aArguments as $sName => $sValue)
|
foreach($aArguments as $sName => $sValue)
|
||||||
{
|
{
|
||||||
if (($sName == 'exec_module')||($sName == 'exec_page')||($sName == 'exec_env'))
|
if (($sName == 'exec_module') || ($sName == 'exec_page') || ($sName == 'exec_env'))
|
||||||
{
|
{
|
||||||
throw new Exception("Module page: $sName is a reserved page argument name");
|
throw new Exception("Module page: $sName is a reserved page argument name");
|
||||||
}
|
}
|
||||||
$aArgs[] = $sName.'='.urlencode($sValue);
|
$aArgs[$sName] = $sValue;
|
||||||
}
|
}
|
||||||
$sArgs = implode('&', $aArgs);
|
|
||||||
return self::GetAbsoluteUrlAppRoot().'pages/exec.php?'.$sArgs;
|
return $aArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
static public function GetAbsoluteUrlExecPage()
|
||||||
|
{
|
||||||
|
return self::GetAbsoluteUrlAppRoot().'pages/exec.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1590,4 +1637,220 @@ class utils
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given path/url is an http(s) URL
|
||||||
|
* @param string $sPath
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function IsURL($sPath)
|
||||||
|
{
|
||||||
|
$bRet = false;
|
||||||
|
if ((substr($sPath, 0, 7) == 'http://') || (substr($sPath, 0, 8) == 'https://') || (substr($sPath, 0, 8) == 'ftp://'))
|
||||||
|
{
|
||||||
|
$bRet = true;
|
||||||
|
}
|
||||||
|
return $bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @param string $sPath
|
||||||
|
* @return false|ormDocument
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function IsSelfURL($sPath)
|
||||||
|
{
|
||||||
|
$result = false;
|
||||||
|
$sPageUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.document.php';
|
||||||
|
if (substr($sPath, 0, strlen($sPageUrl)) == $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)
|
||||||
|
{
|
||||||
|
$aParams = array();
|
||||||
|
foreach(explode('&', $sQuery) as $sChunk)
|
||||||
|
{
|
||||||
|
$aParts = explode('=', $sChunk);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ormDocument $result
|
||||||
|
*/
|
||||||
|
$result = clone $oObj->Get($sAttCode);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception('Invalid URL. This iTop URL is not pointing to a valid Document/Image.');
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the content of a file (and retrieve its MIME type) from either:
|
||||||
|
* - 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
|
||||||
|
* @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))
|
||||||
|
{
|
||||||
|
// Empty path (NULL or '') means that there is no input, making an empty document.
|
||||||
|
$oUploadedDoc = new ormDocument('', '', '');
|
||||||
|
}
|
||||||
|
elseif (static::IsURL($sPath))
|
||||||
|
{
|
||||||
|
if ($oUploadedDoc = static::IsSelfURL($sPath))
|
||||||
|
{
|
||||||
|
// Nothing more to do, we've got it !!
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Remote file, let's use the HTTP headers to find the MIME Type
|
||||||
|
$sData = @file_get_contents($sPath);
|
||||||
|
if ($sData === false)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sFileName .= $sExtension;
|
||||||
|
}
|
||||||
|
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
else if (extension_loaded('fileinfo'))
|
||||||
|
{
|
||||||
|
$finfo = new finfo(FILEINFO_MIME);
|
||||||
|
$sMimeType = $finfo->file($sPath);
|
||||||
|
}
|
||||||
|
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
|
||||||
|
}
|
||||||
|
return $oUploadedDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function ParseHeaders($aHeaders)
|
||||||
|
{
|
||||||
|
$aCleanHeaders = array();
|
||||||
|
foreach( $aHeaders as $sKey => $sValue )
|
||||||
|
{
|
||||||
|
$aTokens = explode(':', $sValue, 2);
|
||||||
|
if(isset($aTokens[1]))
|
||||||
|
{
|
||||||
|
$aCleanHeaders[trim($aTokens[0])] = trim($aTokens[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The header is not in the form Header-Code: Value
|
||||||
|
$aCleanHeaders[] = $sValue; // Store the value as-is
|
||||||
|
$aMatches = array();
|
||||||
|
// Check if it's not the HTTP response code
|
||||||
|
if( preg_match("|HTTP/[0-9\.]+\s+([0-9]+)|", $sValue, $aMatches) )
|
||||||
|
{
|
||||||
|
$aCleanHeaders['reponse_code'] = intval($aMatches[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aCleanHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given class if configured as a high cardinality class.
|
||||||
|
*
|
||||||
|
* @param $sClass
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function IsHighCardinality($sClass)
|
||||||
|
{
|
||||||
|
$aHugeClasses = MetaModel::GetConfig()->Get('high_cardinality_classes');
|
||||||
|
return in_array($sClass, $aHugeClasses);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,59 +55,11 @@ class WizardHelper
|
|||||||
if ( ($sAttCode !='id') && ($value !== '$$NULL$$'))
|
if ( ($sAttCode !='id') && ($value !== '$$NULL$$'))
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
|
||||||
if (($oAttDef->IsLinkSet()) && ($value != '') )
|
if ($oAttDef->IsLinkSet())
|
||||||
{
|
{
|
||||||
// special handling for lists
|
continue;
|
||||||
// assumes this is handled as an array of objects
|
}
|
||||||
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
|
else if ($oAttDef->GetEditClass() == 'Document' )
|
||||||
$aData = json_decode($value, true); // true means decode as a hash array (not an object)
|
|
||||||
// Check what are the meaningful attributes
|
|
||||||
$aFields = $this->GetLinkedWizardStructure($oAttDef);
|
|
||||||
$sLinkedClass = $oAttDef->GetLinkedClass();
|
|
||||||
$aLinkedObjectsArray = array();
|
|
||||||
if (!is_array($aData))
|
|
||||||
{
|
|
||||||
echo ("aData: '$aData' (value: '$value')\n");
|
|
||||||
}
|
|
||||||
foreach($aData as $aLinkedObject)
|
|
||||||
{
|
|
||||||
$oLinkedObj = MetaModel::NewObject($sLinkedClass);
|
|
||||||
foreach($aFields as $sLinkedAttCode)
|
|
||||||
{
|
|
||||||
if ( isset($aLinkedObject[$sLinkedAttCode]) && ($aLinkedObject[$sLinkedAttCode] !== null) )
|
|
||||||
{
|
|
||||||
$sLinkedAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sLinkedAttCode);
|
|
||||||
if (($sLinkedAttDef->IsExternalKey()) && ($aLinkedObject[$sLinkedAttCode] != '') && ($aLinkedObject[$sLinkedAttCode] > 0) )
|
|
||||||
{
|
|
||||||
// For external keys: load the target object so that external fields
|
|
||||||
// get filled too
|
|
||||||
$oTargetObj = MetaModel::GetObject($sLinkedAttDef->GetTargetClass(), $aLinkedObject[$sLinkedAttCode]);
|
|
||||||
$oLinkedObj->Set($sLinkedAttCode, $oTargetObj);
|
|
||||||
}
|
|
||||||
elseif($sLinkedAttDef instanceof AttributeDateTime)
|
|
||||||
{
|
|
||||||
$sDate = $aLinkedObject[$sLinkedAttCode];
|
|
||||||
if($sDate !== null && $sDate !== '')
|
|
||||||
{
|
|
||||||
$oDateTimeFormat = AttributeDateTime::GetFormat();
|
|
||||||
$oDate = $oDateTimeFormat->Parse($sDate);
|
|
||||||
$sDate = $oDate->format('Y-m-d H:i:s');
|
|
||||||
}
|
|
||||||
|
|
||||||
$oLinkedObj->Set($sLinkedAttCode, $sDate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$oLinkedObj->Set($sLinkedAttCode, $aLinkedObject[$sLinkedAttCode]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$aLinkedObjectsArray[] = $oLinkedObj;
|
|
||||||
}
|
|
||||||
$oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray);
|
|
||||||
$oObj->Set($sAttCode, $oSet);
|
|
||||||
}
|
|
||||||
else if ( $oAttDef->GetEditClass() == 'Document' )
|
|
||||||
{
|
{
|
||||||
if ($bReadUploadedFiles)
|
if ($bReadUploadedFiles)
|
||||||
{
|
{
|
||||||
|
|||||||
10
composer.json
Normal file
10
composer.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.6 <7.2.0"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"platform": {
|
||||||
|
"php": "5.3.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2016 Combodo SARL
|
// Copyright (C) 2016-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -67,3 +67,32 @@ if (!function_exists('apc_store') && function_exists('apcu_store'))
|
|||||||
return apcu_store($key, $var, $ttl);
|
return apcu_store($key, $var, $ttl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns user cache info... beware of the format of the returned structure that may vary (See usages)
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function apc_cache_info_compat()
|
||||||
|
{
|
||||||
|
if (!function_exists('apc_cache_info')) return array();
|
||||||
|
|
||||||
|
$oFunction = new ReflectionFunction('apc_cache_info');
|
||||||
|
if ($oFunction->getNumberOfParameters() != 2)
|
||||||
|
{
|
||||||
|
// Beware: APCu behaves slightly differently from APC !!
|
||||||
|
// Worse: the compatibility layer integrated into APC differs from apcu-bc (testing the number of parameters is a must)
|
||||||
|
// In CLI mode (PHP > 7) apc_cache_info returns null and outputs an error message.
|
||||||
|
$aCacheUserData = @apc_cache_info();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aCacheUserData = @apc_cache_info('user');
|
||||||
|
}
|
||||||
|
return $aCacheUserData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache emulation
|
||||||
|
if (!function_exists('apc_store'))
|
||||||
|
{
|
||||||
|
require_once(APPROOT.'core/apc-emulation.php');
|
||||||
|
}
|
||||||
301
core/apc-emulation.php
Normal file
301
core/apc-emulation.php
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
<?php
|
||||||
|
// Copyright (c) 2010-2017 Combodo SARL
|
||||||
|
//
|
||||||
|
// This file is part of iTop.
|
||||||
|
//
|
||||||
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// iTop is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date: 27/09/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $cache_type
|
||||||
|
* @param bool $limited
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
function apc_cache_info($cache_type = '', $limited = false)
|
||||||
|
{
|
||||||
|
$aInfo = array();
|
||||||
|
$sRootCacheDir = apc_emul_get_cache_filename('');
|
||||||
|
$aInfo['cache_list'] = apc_emul_get_cache_entries($sRootCacheDir);
|
||||||
|
return $aInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function apc_emul_get_cache_entries($sEntry)
|
||||||
|
{
|
||||||
|
$aResult = array();
|
||||||
|
if (is_dir($sEntry))
|
||||||
|
{
|
||||||
|
$aFiles = array_diff(scandir($sEntry), array('.', '..'));
|
||||||
|
foreach($aFiles as $sFile)
|
||||||
|
{
|
||||||
|
$sSubFile = $sEntry.'/'.$sFile;
|
||||||
|
$aResult = array_merge($aResult, apc_emul_get_cache_entries($sSubFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sKey = basename($sEntry);
|
||||||
|
if (strpos($sKey, '-') === 0)
|
||||||
|
{
|
||||||
|
$sKey = substr($sKey, 1);
|
||||||
|
}
|
||||||
|
$aResult[] = array('info' => $sKey);
|
||||||
|
}
|
||||||
|
return $aResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array|string $key
|
||||||
|
* @param $var
|
||||||
|
* @param int $ttl
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
function apc_store($key, $var = NULL, $ttl = 0)
|
||||||
|
{
|
||||||
|
if (is_array($key))
|
||||||
|
{
|
||||||
|
$aResult = array();
|
||||||
|
foreach($key as $sKey => $value)
|
||||||
|
{
|
||||||
|
$aResult[] = apc_emul_store_unit($sKey, $value, $ttl);
|
||||||
|
}
|
||||||
|
return $aResult;
|
||||||
|
}
|
||||||
|
return apc_emul_store_unit($key, $var, $ttl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sKey
|
||||||
|
* @param $value
|
||||||
|
* @param int $iTTL time to live
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function apc_emul_store_unit($sKey, $value, $iTTL)
|
||||||
|
{
|
||||||
|
if ($iTTL > 0)
|
||||||
|
{
|
||||||
|
// hint for ttl management
|
||||||
|
$sKey = '-'.$sKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sFilename = apc_emul_get_cache_filename($sKey);
|
||||||
|
// try to create the folder
|
||||||
|
$sDirname = dirname($sFilename);
|
||||||
|
if (!file_exists($sDirname))
|
||||||
|
{
|
||||||
|
if (!@mkdir($sDirname, 0755, true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$bRes = !(@file_put_contents($sFilename, serialize($value), LOCK_EX) === false);
|
||||||
|
apc_emul_manage_new_entry($sFilename);
|
||||||
|
return $bRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $key string|array
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
function apc_fetch($key)
|
||||||
|
{
|
||||||
|
if (is_array($key))
|
||||||
|
{
|
||||||
|
$aResult = array();
|
||||||
|
foreach($key as $sKey)
|
||||||
|
{
|
||||||
|
$aResult[$sKey] = apc_emul_fetch_unit($sKey);
|
||||||
|
}
|
||||||
|
return $aResult;
|
||||||
|
}
|
||||||
|
return apc_emul_fetch_unit($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $sKey
|
||||||
|
* @return bool|mixed
|
||||||
|
*/
|
||||||
|
function apc_emul_fetch_unit($sKey)
|
||||||
|
{
|
||||||
|
// Try the 'TTLed' version
|
||||||
|
$sValue = apc_emul_readcache_locked(apc_emul_get_cache_filename('-'.$sKey));
|
||||||
|
if ($sValue === false)
|
||||||
|
{
|
||||||
|
$sValue = apc_emul_readcache_locked(apc_emul_get_cache_filename($sKey));
|
||||||
|
if ($sValue === false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$oRes = @unserialize($sValue);
|
||||||
|
return $oRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function apc_emul_readcache_locked($sFilename)
|
||||||
|
{
|
||||||
|
$file = @fopen($sFilename, 'r');
|
||||||
|
if ($file === false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
flock($file, LOCK_SH);
|
||||||
|
$sContent = @fread($file, @filesize($sFilename));
|
||||||
|
flock($file, LOCK_UN);
|
||||||
|
fclose($file);
|
||||||
|
return $sContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $cache_type
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function apc_clear_cache($cache_type = '')
|
||||||
|
{
|
||||||
|
$sRootCacheDir = apc_emul_get_cache_filename('');
|
||||||
|
apc_emul_delete_entry($sRootCacheDir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function apc_emul_delete_entry($sCache)
|
||||||
|
{
|
||||||
|
if (is_dir($sCache))
|
||||||
|
{
|
||||||
|
$aFiles = array_diff(scandir($sCache), array('.', '..'));
|
||||||
|
foreach($aFiles as $sFile)
|
||||||
|
{
|
||||||
|
$sSubFile = $sCache.'/'.$sFile;
|
||||||
|
if (!apc_emul_delete_entry($sSubFile))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!@rmdir($sCache))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!@unlink($sCache))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $key
|
||||||
|
* @return bool|string[]
|
||||||
|
*/
|
||||||
|
function apc_delete($key)
|
||||||
|
{
|
||||||
|
return apc_emul_delete_entry(apc_emul_get_cache_filename($key));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function apc_emul_get_cache_filename($sKey)
|
||||||
|
{
|
||||||
|
$sPath = str_replace(array(' ', '/', '\\', '.'), '-', $sKey);
|
||||||
|
return utils::GetCachePath().'apc-emul/'.$sPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Manage the cache files when a new cache entry is added
|
||||||
|
* @param string $sNewFilename new cache file added
|
||||||
|
*/
|
||||||
|
function apc_emul_manage_new_entry($sNewFilename)
|
||||||
|
{
|
||||||
|
// Check only once per request
|
||||||
|
static $aFilesByTime = null;
|
||||||
|
static $iFileCount = 0;
|
||||||
|
$iMaxFiles = MetaModel::GetConfig()->Get('apc_cache_emulation.max_entries');
|
||||||
|
if ($iMaxFiles == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!$aFilesByTime)
|
||||||
|
{
|
||||||
|
$sRootCacheDir = apc_emul_get_cache_filename('');
|
||||||
|
$aFilesByTime = apc_emul_list_files_time($sRootCacheDir);
|
||||||
|
$iFileCount = count($aFilesByTime);
|
||||||
|
if ($iMaxFiles !== 0)
|
||||||
|
{
|
||||||
|
asort($aFilesByTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aFilesByTime[$sNewFilename] = time();
|
||||||
|
$iFileCount++;
|
||||||
|
}
|
||||||
|
if ($iFileCount > $iMaxFiles)
|
||||||
|
{
|
||||||
|
$iFileNbToRemove = $iFileCount - $iMaxFiles;
|
||||||
|
foreach($aFilesByTime as $sFileToRemove => $iTime)
|
||||||
|
{
|
||||||
|
@unlink($sFileToRemove);
|
||||||
|
if ($iFileNbToRemove-- === 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$aFilesByTime = array_slice($aFilesByTime, $iFileCount - $iMaxFiles, null, true);
|
||||||
|
$iFileCount = $iMaxFiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the list of files with their associated access time
|
||||||
|
* @param string $sCheck Directory to scan
|
||||||
|
* @param array $aFilesByTime used by recursion
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function apc_emul_list_files_time($sCheck, &$aFilesByTime = array())
|
||||||
|
{
|
||||||
|
// Garbage collection
|
||||||
|
$aFiles = array_diff(@scandir($sCheck), array('.', '..'));
|
||||||
|
foreach($aFiles as $sFile)
|
||||||
|
{
|
||||||
|
$sSubFile = $sCheck.'/'.$sFile;
|
||||||
|
if (is_dir($sSubFile))
|
||||||
|
{
|
||||||
|
apc_emul_list_files_time($sSubFile, $aFilesByTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$iTime = apc_emul_get_file_time($sSubFile);
|
||||||
|
if ($iTime !== false)
|
||||||
|
{
|
||||||
|
$aFilesByTime[$sSubFile] = $iTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aFilesByTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the file access time if TTL is managed
|
||||||
|
* @param string $sFilename
|
||||||
|
* @return bool|int returns the file atime or false if not relevant
|
||||||
|
*/
|
||||||
|
function apc_emul_get_file_time($sFilename)
|
||||||
|
{
|
||||||
|
if (strpos(basename($sFilename), '-') === 0)
|
||||||
|
{
|
||||||
|
return @fileatime($sFilename);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -702,7 +702,7 @@ abstract class AttributeDefinition
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObj));
|
throw new Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObject));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -1053,20 +1053,20 @@ class AttributeLinkedSet extends AttributeDefinition
|
|||||||
|
|
||||||
$oLinkSet = clone $value; // Workaround/Safety net for Trac #887
|
$oLinkSet = clone $value; // Workaround/Safety net for Trac #887
|
||||||
$iLimit = MetaModel::GetConfig()->Get('max_linkset_output');
|
$iLimit = MetaModel::GetConfig()->Get('max_linkset_output');
|
||||||
if ($iLimit > 0)
|
$iCount = 0;
|
||||||
|
$aNames = array();
|
||||||
|
foreach($oLinkSet as $oItem)
|
||||||
{
|
{
|
||||||
$oLinkSet->SetLimit($iLimit);
|
if (($iLimit > 0) && ($iCount == $iLimit))
|
||||||
}
|
|
||||||
$aNames = $oLinkSet->GetColumnAsArray($sRemoteName);
|
|
||||||
if ($iLimit > 0)
|
|
||||||
{
|
|
||||||
$iTotal = $oLinkSet->Count();
|
|
||||||
if ($iTotal > count($aNames))
|
|
||||||
{
|
{
|
||||||
$aNames[] = '... '.Dict::Format('UI:TruncatedResults', count($aNames), $iTotal);
|
$iTotal = $oLinkSet->Count();
|
||||||
|
$aNames[] = '... '.Dict::Format('UI:TruncatedResults', $iCount, $iTotal);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
$aNames[] = $oItem->Get($sRemoteName);
|
||||||
|
$iCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch($sVerb)
|
switch($sVerb)
|
||||||
{
|
{
|
||||||
case '':
|
case '':
|
||||||
@@ -1342,6 +1342,29 @@ class AttributeLinkedSet extends AttributeDefinition
|
|||||||
return $oSet;
|
return $oSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $proposedValue
|
||||||
|
* @param $oHostObj
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function MakeRealValue($proposedValue, $oHostObj){
|
||||||
|
if($proposedValue === null)
|
||||||
|
{
|
||||||
|
$sLinkedClass = $this->GetLinkedClass();
|
||||||
|
$aLinkedObjectsArray = array();
|
||||||
|
$oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray);
|
||||||
|
|
||||||
|
return new ormLinkSet(
|
||||||
|
get_class($oHostObj),
|
||||||
|
$this->GetCode(),
|
||||||
|
$oSet
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $proposedValue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ormLinkSet $val1
|
* @param ormLinkSet $val1
|
||||||
* @param ormLinkSet $val2
|
* @param ormLinkSet $val2
|
||||||
@@ -1355,7 +1378,7 @@ class AttributeLinkedSet extends AttributeDefinition
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$bAreEquivalent = $val1->Equals($val2);
|
$bAreEquivalent = ($val2->HasDelta() === false);
|
||||||
}
|
}
|
||||||
return $bAreEquivalent;
|
return $bAreEquivalent;
|
||||||
}
|
}
|
||||||
@@ -3963,6 +3986,42 @@ class AttributeDateTime extends AttributeDBField
|
|||||||
return $oFormField;
|
return $oFormField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function EnumTemplateVerbs()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'' => 'Formatted representation',
|
||||||
|
'raw' => 'Not formatted representation',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true)
|
||||||
|
{
|
||||||
|
switch ($sVerb)
|
||||||
|
{
|
||||||
|
case '':
|
||||||
|
case 'text':
|
||||||
|
return static::GetFormat()->format($value);
|
||||||
|
break;
|
||||||
|
case 'html':
|
||||||
|
// Note: Not passing formatted value as the method will format it.
|
||||||
|
return $this->GetAsHTML($value);
|
||||||
|
break;
|
||||||
|
case 'raw':
|
||||||
|
return $value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return parent::GetForTemplate($value, $sVerb, $oHostObject, $bLocalize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static public function ListExpectedParams()
|
static public function ListExpectedParams()
|
||||||
{
|
{
|
||||||
return parent::ListExpectedParams();
|
return parent::ListExpectedParams();
|
||||||
@@ -5207,75 +5266,34 @@ class AttributeBlob extends AttributeDefinition
|
|||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// Facilitate things: allow administrators to upload a document
|
* Users can provide the document from an URL (including an URL on iTop itself)
|
||||||
// from a CSV by specifying its path/URL
|
* for CSV import. Administrators can even provide the path to a local file
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @see AttributeDefinition::MakeRealValue()
|
||||||
|
*/
|
||||||
public function MakeRealValue($proposedValue, $oHostObj)
|
public function MakeRealValue($proposedValue, $oHostObj)
|
||||||
{
|
{
|
||||||
|
if ($proposedValue === null) return null;
|
||||||
|
|
||||||
if (is_object($proposedValue))
|
if (is_object($proposedValue))
|
||||||
{
|
{
|
||||||
$proposedValue = clone $proposedValue;
|
$proposedValue = clone $proposedValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (file_exists($proposedValue) && UserRights::IsAdministrator())
|
try
|
||||||
{
|
{
|
||||||
$sContent = file_get_contents($proposedValue);
|
// Read the file from iTop, an URL (or the local file system - for admins only)
|
||||||
$sExtension = strtolower(pathinfo($proposedValue, PATHINFO_EXTENSION));
|
$proposedValue = Utils::FileGetContentsAndMIMEType($proposedValue);
|
||||||
$sMimeType = "application/x-octet-stream";
|
|
||||||
$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.xlsx',
|
|
||||||
'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'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!array_key_exists($sExtension, $aKnownExtensions) && extension_loaded('fileinfo'))
|
|
||||||
{
|
|
||||||
$finfo = new finfo(FILEINFO_MIME);
|
|
||||||
$sMimeType = $finfo->file($proposedValue);
|
|
||||||
}
|
|
||||||
return new ormDocument($sContent, $sMimeType);
|
|
||||||
}
|
}
|
||||||
else
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
return new ormDocument($proposedValue, 'text/plain');
|
IssueLog::Warning(get_class($this)."::MakeRealValue - ".$e->getMessage());
|
||||||
}
|
// Not a real document !! store is as text !!! (This was the default behavior before)
|
||||||
|
$proposedValue = new ormDocument($e->getMessage()." \n".$proposedValue, 'text/plain');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $proposedValue;
|
return $proposedValue;
|
||||||
}
|
}
|
||||||
@@ -5390,6 +5408,11 @@ class AttributeBlob extends AttributeDefinition
|
|||||||
|
|
||||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, $bConvertToPlainText = false)
|
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, $bConvertToPlainText = false)
|
||||||
{
|
{
|
||||||
|
$sAttCode = $this->GetCode();
|
||||||
|
if ($sValue instanceof ormDocument && !$sValue->IsEmpty())
|
||||||
|
{
|
||||||
|
return $sValue->GetDownloadURL(get_class($oHostObject), $oHostObject->GetKey(), $sAttCode);
|
||||||
|
}
|
||||||
return ''; // Not exportable in CSV !
|
return ''; // Not exportable in CSV !
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5493,48 +5516,49 @@ class AttributeImage extends AttributeBlob
|
|||||||
{
|
{
|
||||||
public function GetEditClass() {return "Image";}
|
public function GetEditClass() {return "Image";}
|
||||||
|
|
||||||
// Facilitate things: allow administrators to upload a document
|
/**
|
||||||
// from a CSV by specifying its path/URL
|
* {@inheritDoc}
|
||||||
|
* @see AttributeBlob::MakeRealValue()
|
||||||
|
*/
|
||||||
public function MakeRealValue($proposedValue, $oHostObj)
|
public function MakeRealValue($proposedValue, $oHostObj)
|
||||||
{
|
{
|
||||||
if (is_object($proposedValue))
|
$oDoc = parent::MakeRealValue($proposedValue, $oHostObj);
|
||||||
{
|
// The validation of the MIME Type is done by CheckFormat below
|
||||||
$proposedValue = clone $proposedValue;
|
return $oDoc;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (file_exists($proposedValue) && UserRights::IsAdministrator())
|
|
||||||
{
|
|
||||||
$sContent = file_get_contents($proposedValue);
|
|
||||||
$sExtension = strtolower(pathinfo($proposedValue, PATHINFO_EXTENSION));
|
|
||||||
$sMimeType = "application/x-octet-stream";
|
|
||||||
$aKnownExtensions = array(
|
|
||||||
'jpg' => 'image/jpeg',
|
|
||||||
'jpeg' => 'image/jpeg',
|
|
||||||
'gif' => 'image/gif',
|
|
||||||
'png' => 'image/png'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!array_key_exists($sExtension, $aKnownExtensions) && extension_loaded('fileinfo'))
|
|
||||||
{
|
|
||||||
$finfo = new finfo(FILEINFO_MIME);
|
|
||||||
$sMimeType = $finfo->file($proposedValue);
|
|
||||||
}
|
|
||||||
return new ormDocument($sContent, $sMimeType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $proposedValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the supplied ormDocument actually contains an image
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @see AttributeDefinition::CheckFormat()
|
||||||
|
*/
|
||||||
|
public function CheckFormat($value)
|
||||||
|
{
|
||||||
|
if ($value instanceof ormDocument && !$value->IsEmpty())
|
||||||
|
{
|
||||||
|
return ($value->GetMainMimeType() == 'image');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
|
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
|
||||||
{
|
{
|
||||||
$iMaxWidthPx = $this->Get('display_max_width');
|
$iMaxWidthPx = $this->Get('display_max_width');
|
||||||
$iMaxHeightPx = $this->Get('display_max_height');
|
$iMaxHeightPx = $this->Get('display_max_height');
|
||||||
$sUrl = $this->Get('default_image');
|
$sUrl = $this->Get('default_image');
|
||||||
$sRet = '<img src="'.$sUrl.'" style="max-width: '.$iMaxWidthPx.'px; max-height: '.$iMaxHeightPx.'px">';
|
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="max-width: '.$iMaxWidthPx.'px; max-height: '.$iMaxHeightPx.'px">' : '';
|
||||||
if (is_object($value) && !$value->IsEmpty())
|
if (is_object($value) && !$value->IsEmpty())
|
||||||
{
|
{
|
||||||
$sUrl = $value->GetDownloadURL(get_class($oHostObject), $oHostObject->GetKey(), $this->GetCode());
|
if ($oHostObject->IsNew() || ($oHostObject->IsModified() && (array_key_exists($this->GetCode(), $oHostObject->ListChanges()))))
|
||||||
|
{
|
||||||
|
// If the object is modified (or not yet stored in the database) we must serve the content of the image directly inline
|
||||||
|
// otherwise (if we just give an URL) the browser will be given the wrong content... and may cache it
|
||||||
|
$sUrl = 'data:'.$value->GetMimeType().';base64,'.base64_encode($value->GetData());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sUrl = $value->GetDownloadURL(get_class($oHostObject), $oHostObject->GetKey(), $this->GetCode());
|
||||||
|
}
|
||||||
$sRet = '<img src="'.$sUrl.'" style="max-width: '.$iMaxWidthPx.'px; max-height: '.$iMaxHeightPx.'px">';
|
$sRet = '<img src="'.$sUrl.'" style="max-width: '.$iMaxWidthPx.'px; max-height: '.$iMaxHeightPx.'px">';
|
||||||
}
|
}
|
||||||
return '<div class="view-image" style="width: '.$iMaxWidthPx.'px; height: '.$iMaxHeightPx.'px;"><span class="helper-middle"></span>'.$sRet.'</div>';
|
return '<div class="view-image" style="width: '.$iMaxWidthPx.'px; height: '.$iMaxHeightPx.'px;"><span class="helper-middle"></span>'.$sRet.'</div>';
|
||||||
@@ -7370,7 +7394,7 @@ class AttributeCustomFields extends AttributeDefinition
|
|||||||
|
|
||||||
public function GetEditValue($sValue, $oHostObj = null)
|
public function GetEditValue($sValue, $oHostObj = null)
|
||||||
{
|
{
|
||||||
return 'GetEditValueNotImplemented for '.get_class($this);
|
return $this->GetForTemplate($sValue, '', $oHostObj, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -7773,3 +7797,16 @@ class AttributeObsolescenceFlag extends AttributeBoolean
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AttributeObsolescenceDate extends AttributeDate
|
||||||
|
{
|
||||||
|
public function GetLabel($sDefault = null)
|
||||||
|
{
|
||||||
|
$sDefault = Dict::S('Core:AttributeObsolescenceDate/Label', $sDefault);
|
||||||
|
return parent::GetLabel($sDefault);
|
||||||
|
}
|
||||||
|
public function GetDescription($sDefault = null)
|
||||||
|
{
|
||||||
|
$sDefault = Dict::S('Core:AttributeObsolescenceDate/Label+', $sDefault);
|
||||||
|
return parent::GetDescription($sDefault);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -468,10 +468,11 @@ class BulkChange
|
|||||||
//
|
//
|
||||||
foreach ($this->m_aAttList as $sAttCode => $iCol)
|
foreach ($this->m_aAttList as $sAttCode => $iCol)
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
|
||||||
|
|
||||||
// skip the private key, if any
|
// skip the private key, if any
|
||||||
if ($sAttCode == 'id') continue;
|
if ($sAttCode == 'id') continue;
|
||||||
|
|
||||||
|
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||||
|
|
||||||
// skip reconciliation keys
|
// skip reconciliation keys
|
||||||
if (!$oAttDef->IsWritable() && in_array($sAttCode, $this->m_aReconcilKeys)){ continue; }
|
if (!$oAttDef->IsWritable() && in_array($sAttCode, $this->m_aReconcilKeys)){ continue; }
|
||||||
|
|
||||||
|
|||||||
@@ -33,13 +33,15 @@ class MySQLException extends CoreException
|
|||||||
{
|
{
|
||||||
if ($oException != null)
|
if ($oException != null)
|
||||||
{
|
{
|
||||||
$aContext['mysql_error'] = $oException->getCode();
|
$aContext['mysql_errno'] = $oException->getCode();
|
||||||
$aContext['mysql_errno'] = $oException->getMessage();
|
$this->code = $oException->getCode();
|
||||||
|
$aContext['mysql_error'] = $oException->getMessage();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$aContext['mysql_error'] = CMDBSource::GetError();
|
|
||||||
$aContext['mysql_errno'] = CMDBSource::GetErrNo();
|
$aContext['mysql_errno'] = CMDBSource::GetErrNo();
|
||||||
|
$this->code = CMDBSource::GetErrNo();
|
||||||
|
$aContext['mysql_error'] = CMDBSource::GetError();
|
||||||
}
|
}
|
||||||
parent::__construct($sIssue, $aContext);
|
parent::__construct($sIssue, $aContext);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
|
|
||||||
define('ITOP_APPLICATION', 'iTop');
|
define('ITOP_APPLICATION', 'iTop');
|
||||||
define('ITOP_VERSION', '2.4.x');
|
define('ITOP_APPLICATION_SHORT', 'iTop');
|
||||||
|
define('ITOP_VERSION', '2.4.0');
|
||||||
define('ITOP_REVISION', 'svn');
|
define('ITOP_REVISION', 'svn');
|
||||||
define('ITOP_BUILD_DATE', '$WCNOW$');
|
define('ITOP_BUILD_DATE', '$WCNOW$');
|
||||||
|
|
||||||
@@ -435,6 +436,14 @@ class Config
|
|||||||
'source_of_value' => '',
|
'source_of_value' => '',
|
||||||
'show_in_conf_sample' => true,
|
'show_in_conf_sample' => true,
|
||||||
),
|
),
|
||||||
|
'apc_cache_emulation.max_entries' => array(
|
||||||
|
'type' => 'integer',
|
||||||
|
'description' => 'Maximum number of cache entries (0 means no limit)',
|
||||||
|
'default' => 1000,
|
||||||
|
'value' => 1000,
|
||||||
|
'source_of_value' => '',
|
||||||
|
'show_in_conf_sample' => false,
|
||||||
|
),
|
||||||
'timezone' => array(
|
'timezone' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'description' => 'Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitely configured in PHP',
|
'description' => 'Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitely configured in PHP',
|
||||||
@@ -953,6 +962,30 @@ class Config
|
|||||||
'source_of_value' => '',
|
'source_of_value' => '',
|
||||||
'show_in_conf_sample' => false,
|
'show_in_conf_sample' => false,
|
||||||
),
|
),
|
||||||
|
'disable_attachments_download_legacy_portal' => array(
|
||||||
|
'type' => 'bool',
|
||||||
|
'description' => 'Disable attachments download from legacy portal',
|
||||||
|
'default' => true,
|
||||||
|
'value' => true,
|
||||||
|
'source_of_value' => '',
|
||||||
|
'show_in_conf_sample' => true,
|
||||||
|
),
|
||||||
|
'optimize_requests_for_join_count' => array(
|
||||||
|
'type' => 'bool',
|
||||||
|
'description' => 'Optimize request joins to minimize the count (default is true, try to set it to false in case of performance issues)',
|
||||||
|
'default' => true,
|
||||||
|
'value' => true,
|
||||||
|
'source_of_value' => '',
|
||||||
|
'show_in_conf_sample' => true,
|
||||||
|
),
|
||||||
|
'high_cardinality_classes' => array(
|
||||||
|
'type' => 'array',
|
||||||
|
'description' => 'List of classes with high cardinality (force auto-complete mode)',
|
||||||
|
'default' => array(),
|
||||||
|
'value' => array(),
|
||||||
|
'source_of_value' => '',
|
||||||
|
'show_in_conf_sample' => true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
public function IsProperty($sPropCode)
|
public function IsProperty($sPropCode)
|
||||||
|
|||||||
@@ -112,4 +112,13 @@ class SecurityException extends CoreException
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throwned when querying on an object that exists in the database but is archived
|
||||||
|
*
|
||||||
|
* @see N.1108
|
||||||
|
*/
|
||||||
|
class ArchivedObjectException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -1731,6 +1731,14 @@ abstract class DBObject implements iDisplay
|
|||||||
|
|
||||||
$this->m_bIsInDB = true;
|
$this->m_bIsInDB = true;
|
||||||
$this->m_bDirty = false;
|
$this->m_bDirty = false;
|
||||||
|
foreach ($this->m_aCurrValues as $sAttCode => $value)
|
||||||
|
{
|
||||||
|
if (is_object($value))
|
||||||
|
{
|
||||||
|
$value = clone $value;
|
||||||
|
}
|
||||||
|
$this->m_aOrigValues[$sAttCode] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
$this->AfterInsert();
|
$this->AfterInsert();
|
||||||
|
|
||||||
@@ -2922,7 +2930,7 @@ abstract class DBObject implements iDisplay
|
|||||||
$oSearch->AllowAllData();
|
$oSearch->AllowAllData();
|
||||||
}
|
}
|
||||||
$oSet = new CMDBObjectSet($oSearch);
|
$oSet = new CMDBObjectSet($oSearch);
|
||||||
if ($oSet->Count() > 0)
|
if ($oSet->Count(1) > 0)
|
||||||
{
|
{
|
||||||
$aDependentObjects[$sRemoteClass][$sExtKeyAttCode] = array(
|
$aDependentObjects[$sRemoteClass][$sExtKeyAttCode] = array(
|
||||||
'attribute' => $oExtKeyAttDef,
|
'attribute' => $oExtKeyAttDef,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2017 Combodo SARL
|
// Copyright (c) 2010-2018 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// 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
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -15,14 +15,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
//
|
||||||
|
|
||||||
/**
|
|
||||||
* Define filters for a given class of objects (formerly named "filter")
|
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Dev hack for disabling the some query build optimizations (Folding/Merging)
|
// Dev hack for disabling the some query build optimizations (Folding/Merging)
|
||||||
define('ENABLE_OPT', true);
|
define('ENABLE_OPT', true);
|
||||||
@@ -33,7 +26,6 @@ class DBObjectSearch extends DBSearch
|
|||||||
private $m_aSelectedClasses; // selected for the output (alias => class name)
|
private $m_aSelectedClasses; // selected for the output (alias => class name)
|
||||||
private $m_oSearchCondition;
|
private $m_oSearchCondition;
|
||||||
private $m_aParams;
|
private $m_aParams;
|
||||||
private $m_aFullText;
|
|
||||||
private $m_aPointingTo;
|
private $m_aPointingTo;
|
||||||
private $m_aReferencedBy;
|
private $m_aReferencedBy;
|
||||||
|
|
||||||
@@ -54,7 +46,6 @@ class DBObjectSearch extends DBSearch
|
|||||||
$this->m_aClasses = array($sClassAlias => $sClass);
|
$this->m_aClasses = array($sClassAlias => $sClass);
|
||||||
$this->m_oSearchCondition = new TrueExpression;
|
$this->m_oSearchCondition = new TrueExpression;
|
||||||
$this->m_aParams = array();
|
$this->m_aParams = array();
|
||||||
$this->m_aFullText = array();
|
|
||||||
$this->m_aPointingTo = array();
|
$this->m_aPointingTo = array();
|
||||||
$this->m_aReferencedBy = array();
|
$this->m_aReferencedBy = array();
|
||||||
}
|
}
|
||||||
@@ -285,7 +276,6 @@ class DBObjectSearch extends DBSearch
|
|||||||
public function IsAny()
|
public function IsAny()
|
||||||
{
|
{
|
||||||
if (!$this->m_oSearchCondition->IsTrue()) return false;
|
if (!$this->m_oSearchCondition->IsTrue()) return false;
|
||||||
if (count($this->m_aFullText) > 0) return false;
|
|
||||||
if (count($this->m_aPointingTo) > 0) return false;
|
if (count($this->m_aPointingTo) > 0) return false;
|
||||||
if (count($this->m_aReferencedBy) > 0) return false;
|
if (count($this->m_aReferencedBy) > 0) return false;
|
||||||
return true;
|
return true;
|
||||||
@@ -367,10 +357,19 @@ class DBObjectSearch extends DBSearch
|
|||||||
$this->AddConditionExpression($oNewCondition);
|
$this->AddConditionExpression($oNewCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function AddCondition($sFilterCode, $value, $sOpCode = null, $bParseSeachString = false)
|
/**
|
||||||
|
* @param string $sFilterCode
|
||||||
|
* @param mixed $value
|
||||||
|
* @param string $sOpCode operator to use : 'IN', 'NOT IN', 'Contains',' Begins with', 'Finishes with', ...
|
||||||
|
* @param bool $bParseSearchString
|
||||||
|
*
|
||||||
|
* @throws \CoreException
|
||||||
|
*
|
||||||
|
* @see AddConditionForInOperatorUsingParam for IN/NOT IN queries with lots of params
|
||||||
|
*/
|
||||||
|
public function AddCondition($sFilterCode, $value, $sOpCode = null, $bParseSearchString = false)
|
||||||
{
|
{
|
||||||
MyHelpers::CheckKeyInArray('filter code in class: '.$this->GetClass(), $sFilterCode, MetaModel::GetClassFilterDefs($this->GetClass()));
|
MyHelpers::CheckKeyInArray('filter code in class: '.$this->GetClass(), $sFilterCode, MetaModel::GetClassFilterDefs($this->GetClass()));
|
||||||
$oFilterDef = MetaModel::GetClassFilterDef($this->GetClass(), $sFilterCode);
|
|
||||||
|
|
||||||
$oField = new FieldExpression($sFilterCode, $this->GetClassAlias());
|
$oField = new FieldExpression($sFilterCode, $this->GetClassAlias());
|
||||||
if (empty($sOpCode))
|
if (empty($sOpCode))
|
||||||
@@ -382,15 +381,15 @@ class DBObjectSearch extends DBSearch
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($this->GetClass(), $sFilterCode);
|
$oAttDef = MetaModel::GetAttributeDef($this->GetClass(), $sFilterCode);
|
||||||
$oNewCondition = $oAttDef->GetSmartConditionExpression($value, $oField, $this->m_aParams, $bParseSeachString);
|
$oNewCondition = $oAttDef->GetSmartConditionExpression($value, $oField, $this->m_aParams, $bParseSearchString);
|
||||||
$this->AddConditionExpression($oNewCondition);
|
$this->AddConditionExpression($oNewCondition);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Parse search strings if needed and if the filter code corresponds to a valid attcode
|
// Parse search strings if needed and if the filter code corresponds to a valid attcode
|
||||||
if($bParseSeachString && MetaModel::IsValidAttCode($this->GetClass(), $sFilterCode))
|
if($bParseSearchString && MetaModel::IsValidAttCode($this->GetClass(), $sFilterCode))
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sFilterCode);
|
$oAttDef = MetaModel::GetAttributeDef($this->GetClass(), $sFilterCode);
|
||||||
$value = $oAttDef->ParseSearchString($value);
|
$value = $oAttDef->ParseSearchString($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,14 +407,14 @@ class DBObjectSearch extends DBSearch
|
|||||||
throw new CoreException('Deprecated operator, please consider using OQL (SQL) expressions like "(TO_DAYS(NOW()) - TO_DAYS(x)) AS AgeDays"', array('operator' => $sOpCode));
|
throw new CoreException('Deprecated operator, please consider using OQL (SQL) expressions like "(TO_DAYS(NOW()) - TO_DAYS(x)) AS AgeDays"', array('operator' => $sOpCode));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "IN":
|
case 'IN':
|
||||||
if (!is_array($value)) $value = array($value);
|
if (!is_array($value)) $value = array($value);
|
||||||
if (count($value) === 0) throw new Exception('AddCondition '.$sOpCode.': Value cannot be an empty array.');
|
if (count($value) === 0) throw new Exception('AddCondition '.$sOpCode.': Value cannot be an empty array.');
|
||||||
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
|
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
|
||||||
$sOQLCondition = $oField->Render()." IN $sListExpr";
|
$sOQLCondition = $oField->Render()." IN $sListExpr";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "NOTIN":
|
case 'NOTIN':
|
||||||
if (!is_array($value)) $value = array($value);
|
if (!is_array($value)) $value = array($value);
|
||||||
if (count($value) === 0) throw new Exception('AddCondition '.$sOpCode.': Value cannot be an empty array.');
|
if (count($value) === 0) throw new Exception('AddCondition '.$sOpCode.': Value cannot be an empty array.');
|
||||||
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
|
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
|
||||||
@@ -469,6 +468,8 @@ class DBObjectSearch extends DBSearch
|
|||||||
break;
|
break;
|
||||||
case "IN":
|
case "IN":
|
||||||
case "NOTIN":
|
case "NOTIN":
|
||||||
|
// this will parse all of the values... Can take forever if there are lots of them !
|
||||||
|
// In this case using a parameter is far better : WHERE ... IN (:my_param)
|
||||||
$oNewCondition = Expression::FromOQL($sOQLCondition);
|
$oNewCondition = Expression::FromOQL($sOQLCondition);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -483,6 +484,44 @@ class DBObjectSearch extends DBSearch
|
|||||||
$this->AddConditionExpression($oNewCondition);
|
$this->AddConditionExpression($oNewCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sFilterCode attribute code to use
|
||||||
|
* @param array $aValues
|
||||||
|
* @param bool $bPositiveMatch if true will add a IN filter, else a NOT IN
|
||||||
|
*
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
|
public function AddConditionForInOperatorUsingParam($sFilterCode, $aValues, $bPositiveMatch = true)
|
||||||
|
{
|
||||||
|
$oFieldExpression = new FieldExpression($sFilterCode, $this->GetClassAlias());
|
||||||
|
|
||||||
|
$sOperator = $bPositiveMatch ? 'IN' : 'NOT IN';
|
||||||
|
|
||||||
|
$sInParamName = $this->GenerateUniqueParamName();
|
||||||
|
$oParamExpression = new VariableExpression($sInParamName);
|
||||||
|
$this->SetInternalParams(array($sInParamName => $aValues));
|
||||||
|
|
||||||
|
$oListExpression = new ListExpression(array($oParamExpression));
|
||||||
|
|
||||||
|
$oInCondition = new BinaryExpression($oFieldExpression, $sOperator, $oListExpression);
|
||||||
|
$this->AddConditionExpression($oInCondition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string a unique param name
|
||||||
|
*/
|
||||||
|
private function GenerateUniqueParamName() {
|
||||||
|
$iExistingParamsNb = count($this->m_aParams);
|
||||||
|
$iCurrentArrayParamNb = $iExistingParamsNb + 1;
|
||||||
|
$sParamName = 'param'.$iCurrentArrayParamNb;
|
||||||
|
|
||||||
|
if (isset($this->m_aParams[$sParamName])) {
|
||||||
|
$sParamName .= '_'.microtime(true) . '_' .rand(0,100);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sParamName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a condition on external keys or link sets
|
* Specify a condition on external keys or link sets
|
||||||
* @param sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
|
* @param sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
|
||||||
@@ -549,9 +588,24 @@ class DBObjectSearch extends DBSearch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function AddCondition_FullText($sFullText)
|
public function AddCondition_FullText($sNeedle)
|
||||||
{
|
{
|
||||||
$this->m_aFullText[] = $sFullText;
|
// Transform the full text condition into additional condition expression
|
||||||
|
$aFullTextFields = array();
|
||||||
|
foreach (MetaModel::ListAttributeDefs($this->GetClass()) as $sAttCode => $oAttDef)
|
||||||
|
{
|
||||||
|
if (!$oAttDef->IsScalar()) continue;
|
||||||
|
if ($oAttDef->IsExternalKey()) continue;
|
||||||
|
$aFullTextFields[] = new FieldExpression($sAttCode, $this->GetClassAlias());
|
||||||
|
}
|
||||||
|
$oTextFields = new CharConcatWSExpression(' ', $aFullTextFields);
|
||||||
|
|
||||||
|
$sQueryParam = 'needle';
|
||||||
|
$oFlexNeedle = new CharConcatExpression(array(new ScalarExpression('%'), new VariableExpression($sQueryParam), new ScalarExpression('%')));
|
||||||
|
|
||||||
|
$oNewCond = new BinaryExpression($oTextFields, 'LIKE', $oFlexNeedle);
|
||||||
|
$this->AddConditionExpression($oNewCond);
|
||||||
|
$this->m_aParams[$sQueryParam] = $sNeedle;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function AddToNameSpace(&$aClassAliases, &$aAliasTranslation, $bTranslateMainAlias = true)
|
protected function AddToNameSpace(&$aClassAliases, &$aAliasTranslation, $bTranslateMainAlias = true)
|
||||||
@@ -973,8 +1027,6 @@ class DBObjectSearch extends DBSearch
|
|||||||
// Translate search condition into our aliasing scheme
|
// Translate search condition into our aliasing scheme
|
||||||
$aAliasTranslation[$oFilter->GetClassAlias()]['*'] = $this->GetClassAlias();
|
$aAliasTranslation[$oFilter->GetClassAlias()]['*'] = $this->GetClassAlias();
|
||||||
|
|
||||||
$this->m_aFullText = array_merge($this->m_aFullText, $oFilter->m_aFullText);
|
|
||||||
|
|
||||||
foreach($oFilter->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo)
|
foreach($oFilter->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo)
|
||||||
{
|
{
|
||||||
foreach($aPointingTo as $iOperatorCode => $aFilter)
|
foreach($aPointingTo as $iOperatorCode => $aFilter)
|
||||||
@@ -1001,7 +1053,7 @@ class DBObjectSearch extends DBSearch
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function GetCriteria() {return $this->m_oSearchCondition;}
|
public function GetCriteria() {return $this->m_oSearchCondition;}
|
||||||
public function GetCriteria_FullText() {return $this->m_aFullText;}
|
public function GetCriteria_FullText() {throw new Exception("Removed GetCriteria_FullText");}
|
||||||
protected function GetCriteria_PointingTo($sKeyAttCode = "")
|
protected function GetCriteria_PointingTo($sKeyAttCode = "")
|
||||||
{
|
{
|
||||||
if (empty($sKeyAttCode))
|
if (empty($sKeyAttCode))
|
||||||
@@ -1119,11 +1171,6 @@ class DBObjectSearch extends DBSearch
|
|||||||
$sRes .= $this->ToOQL_Joins();
|
$sRes .= $this->ToOQL_Joins();
|
||||||
$sRes .= " WHERE ".$this->m_oSearchCondition->Render($aParams, $bRetrofitParams);
|
$sRes .= " WHERE ".$this->m_oSearchCondition->Render($aParams, $bRetrofitParams);
|
||||||
|
|
||||||
// Temporary: add more info about other conditions, necessary to avoid strange behaviors with the cache
|
|
||||||
foreach($this->m_aFullText as $sFullText)
|
|
||||||
{
|
|
||||||
$sRes .= " AND MATCHES '$sFullText'";
|
|
||||||
}
|
|
||||||
if ($bWithAllowAllFlag && $this->m_bAllowAllData)
|
if ($bWithAllowAllFlag && $this->m_bAllowAllData)
|
||||||
{
|
{
|
||||||
$sRes .= " ALLOW ALL DATA";
|
$sRes .= " ALLOW ALL DATA";
|
||||||
@@ -1468,10 +1515,32 @@ class DBObjectSearch extends DBSearch
|
|||||||
|
|
||||||
// Create a unique cache id
|
// Create a unique cache id
|
||||||
//
|
//
|
||||||
|
$aContextData = array();
|
||||||
|
$bCanCache = true;
|
||||||
if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
|
if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
|
||||||
{
|
{
|
||||||
|
if (isset($_SERVER['REQUEST_URI']))
|
||||||
|
{
|
||||||
|
$aContextData['sRequestUri'] = $_SERVER['REQUEST_URI'];
|
||||||
|
}
|
||||||
|
else if (isset($_SERVER['SCRIPT_NAME']))
|
||||||
|
{
|
||||||
|
$aContextData['sRequestUri'] = $_SERVER['SCRIPT_NAME'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aContextData['sRequestUri'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
// Need to identify the query
|
// Need to identify the query
|
||||||
$sOqlQuery = $oSearch->ToOql(false, null, true);
|
$sOqlQuery = $oSearch->ToOql(false, null, true);
|
||||||
|
if ((strpos($sOqlQuery, '`id` IN (') !== false) || (strpos($sOqlQuery, '`id` NOT IN (') !== false))
|
||||||
|
{
|
||||||
|
// Requests containing "id IN" are not worth caching
|
||||||
|
$bCanCache = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$aContextData['sOqlQuery'] = $sOqlQuery;
|
||||||
|
|
||||||
if (count($aModifierProperties))
|
if (count($aModifierProperties))
|
||||||
{
|
{
|
||||||
@@ -1482,12 +1551,14 @@ class DBObjectSearch extends DBSearch
|
|||||||
{
|
{
|
||||||
$sModifierProperties = '';
|
$sModifierProperties = '';
|
||||||
}
|
}
|
||||||
|
$aContextData['sModifierProperties'] = $sModifierProperties;
|
||||||
|
|
||||||
$sRawId = $sOqlQuery.$sModifierProperties;
|
$sRawId = $sOqlQuery.$sModifierProperties;
|
||||||
if (!is_null($aAttToLoad))
|
if (!is_null($aAttToLoad))
|
||||||
{
|
{
|
||||||
$sRawId .= json_encode($aAttToLoad);
|
$sRawId .= json_encode($aAttToLoad);
|
||||||
}
|
}
|
||||||
|
$aContextData['aAttToLoad'] = $aAttToLoad;
|
||||||
if (!is_null($aGroupByExpr))
|
if (!is_null($aGroupByExpr))
|
||||||
{
|
{
|
||||||
foreach($aGroupByExpr as $sAlias => $oExpr)
|
foreach($aGroupByExpr as $sAlias => $oExpr)
|
||||||
@@ -1495,13 +1566,20 @@ class DBObjectSearch extends DBSearch
|
|||||||
$sRawId .= 'g:'.$sAlias.'!'.$oExpr->Render();
|
$sRawId .= 'g:'.$sAlias.'!'.$oExpr->Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$aContextData['aGroupByExpr'] = $aGroupByExpr;
|
||||||
$sRawId .= $bGetCount;
|
$sRawId .= $bGetCount;
|
||||||
|
$aContextData['bGetCount'] = $bGetCount;
|
||||||
if (is_array($aSelectedClasses))
|
if (is_array($aSelectedClasses))
|
||||||
{
|
{
|
||||||
$sRawId .= implode(',', $aSelectedClasses); // Unions may alter the list of selected columns
|
$sRawId .= implode(',', $aSelectedClasses); // Unions may alter the list of selected columns
|
||||||
}
|
}
|
||||||
$sRawId .= $oSearch->GetArchiveMode() ? '--arch' : '';
|
$aContextData['aSelectedClasses'] = $aSelectedClasses;
|
||||||
$sRawId .= $oSearch->GetShowObsoleteData() ? '--obso' : '';
|
$bIsArchiveMode = $oSearch->GetArchiveMode();
|
||||||
|
$sRawId .= $bIsArchiveMode ? '--arch' : '';
|
||||||
|
$bShowObsoleteData = $oSearch->GetShowObsoleteData();
|
||||||
|
$sRawId .= $bShowObsoleteData ? '--obso' : '';
|
||||||
|
$aContextData['bIsArchiveMode'] = $bIsArchiveMode;
|
||||||
|
$aContextData['bShowObsoleteData'] = $bShowObsoleteData;
|
||||||
$sOqlId = md5($sRawId);
|
$sOqlId = md5($sRawId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1557,8 +1635,9 @@ class DBObjectSearch extends DBSearch
|
|||||||
|
|
||||||
if (self::$m_bQueryCacheEnabled)
|
if (self::$m_bQueryCacheEnabled)
|
||||||
{
|
{
|
||||||
if (self::$m_bUseAPCCache)
|
if ($bCanCache && self::$m_bUseAPCCache)
|
||||||
{
|
{
|
||||||
|
$oSQLQuery->m_aContextData = $aContextData;
|
||||||
$oKPI = new ExecutionKPI();
|
$oKPI = new ExecutionKPI();
|
||||||
apc_store($sOqlAPCCacheId, $oSQLQuery, self::$m_iQueryCacheTTL);
|
apc_store($sOqlAPCCacheId, $oSQLQuery, self::$m_iQueryCacheTTL);
|
||||||
$oKPI->ComputeStats('Query APC (store)', $sOqlQuery);
|
$oKPI->ComputeStats('Query APC (store)', $sOqlQuery);
|
||||||
@@ -1570,6 +1649,14 @@ class DBObjectSearch extends DBSearch
|
|||||||
return $oSQLQuery;
|
return $oSQLQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $aAttToLoad
|
||||||
|
* @param $bGetCount
|
||||||
|
* @param $aModifierProperties
|
||||||
|
* @param null $aGroupByExpr
|
||||||
|
* @param null $aSelectedClasses
|
||||||
|
* @return null|SQLObjectQuery
|
||||||
|
*/
|
||||||
protected function BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null)
|
protected function BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null)
|
||||||
{
|
{
|
||||||
$oBuild = new QueryBuilderContext($this, $aModifierProperties, $aGroupByExpr, $aSelectedClasses);
|
$oBuild = new QueryBuilderContext($this, $aModifierProperties, $aGroupByExpr, $aSelectedClasses);
|
||||||
@@ -1614,6 +1701,12 @@ class DBObjectSearch extends DBSearch
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $oBuild
|
||||||
|
* @param null $aAttToLoad
|
||||||
|
* @param array $aValues
|
||||||
|
* @return null|SQLObjectQuery
|
||||||
|
*/
|
||||||
protected function MakeSQLObjectQuery(&$oBuild, $aAttToLoad = null, $aValues = array())
|
protected function MakeSQLObjectQuery(&$oBuild, $aAttToLoad = null, $aValues = array())
|
||||||
{
|
{
|
||||||
// Note: query class might be different than the class of the filter
|
// Note: query class might be different than the class of the filter
|
||||||
@@ -1623,9 +1716,9 @@ class DBObjectSearch extends DBSearch
|
|||||||
|
|
||||||
$bIsOnQueriedClass = array_key_exists($sClassAlias, $oBuild->GetRootFilter()->GetSelectedClasses());
|
$bIsOnQueriedClass = array_key_exists($sClassAlias, $oBuild->GetRootFilter()->GetSelectedClasses());
|
||||||
|
|
||||||
self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
|
//self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
|
||||||
|
|
||||||
$sRootClass = MetaModel::GetRootClass($sClass);
|
//$sRootClass = MetaModel::GetRootClass($sClass);
|
||||||
$sKeyField = MetaModel::DBGetKey($sClass);
|
$sKeyField = MetaModel::DBGetKey($sClass);
|
||||||
|
|
||||||
if ($bIsOnQueriedClass)
|
if ($bIsOnQueriedClass)
|
||||||
@@ -1658,30 +1751,10 @@ class DBObjectSearch extends DBSearch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform the full text condition into additional condition expression
|
|
||||||
$aFullText = $this->GetCriteria_FullText();
|
|
||||||
if (count($aFullText) > 0)
|
|
||||||
{
|
|
||||||
$aFullTextFields = array();
|
|
||||||
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
|
||||||
{
|
|
||||||
if (!$oAttDef->IsScalar()) continue;
|
|
||||||
if ($oAttDef->IsExternalKey()) continue;
|
|
||||||
$aFullTextFields[] = new FieldExpression($sAttCode, $sClassAlias);
|
|
||||||
}
|
|
||||||
$oTextFields = new CharConcatWSExpression(' ', $aFullTextFields);
|
|
||||||
|
|
||||||
foreach($aFullText as $sFTNeedle)
|
|
||||||
{
|
|
||||||
$oNewCond = new BinaryExpression($oTextFields, 'LIKE', new ScalarExpression("%$sFTNeedle%"));
|
|
||||||
$oBuild->m_oQBExpressions->AddCondition($oNewCond);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n";
|
//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n";
|
||||||
$aExpectedAtts = array(); // array of (attcode => fieldexpression)
|
$aExpectedAtts = array(); // array of (attcode => fieldexpression)
|
||||||
//echo "<p>".__LINE__.": GetUnresolvedFields($sClassAlias, ...)</p>\n";
|
//echo "<p>".__LINE__.": GetUnresolvedFields($sClassAlias, ...)</p>\n";
|
||||||
$oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts);
|
$oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts);
|
||||||
|
|
||||||
// Compute a clear view of required joins (from the current class)
|
// Compute a clear view of required joins (from the current class)
|
||||||
@@ -1798,37 +1871,86 @@ class DBObjectSearch extends DBSearch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// First query built upon on the leaf (ie current) class
|
$bRootFirst = MetaModel::GetConfig()->Get('optimize_requests_for_join_count');
|
||||||
//
|
if ($bRootFirst)
|
||||||
self::DbgTrace("Main (=leaf) class, call MakeSQLObjectQuerySingleTable()");
|
|
||||||
if (MetaModel::HasTable($sClass))
|
|
||||||
{
|
{
|
||||||
$oSelectBase = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sClass, $aExtKeys, $aValues);
|
// First query built from the root, adding all tables including the leaf
|
||||||
|
// Before N.1065 we were joining from the leaf first, but this wasn't a good choice :
|
||||||
|
// most of the time (obsolescence, friendlyname, ...) we want to get a root attribute !
|
||||||
|
//
|
||||||
|
$oSelectBase = null;
|
||||||
|
$aClassHierarchy = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL, true);
|
||||||
|
$bIsClassStandaloneClass = (count($aClassHierarchy) == 1);
|
||||||
|
foreach($aClassHierarchy as $sSomeClass)
|
||||||
|
{
|
||||||
|
if (!MetaModel::HasTable($sSomeClass))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::DbgTrace("Adding join from root to leaf: $sSomeClass... let's call MakeSQLObjectQuerySingleTable()");
|
||||||
|
$oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sSomeClass, $aExtKeys, $aValues);
|
||||||
|
if (is_null($oSelectBase))
|
||||||
|
{
|
||||||
|
$oSelectBase = $oSelectParentTable;
|
||||||
|
if (!$bIsClassStandaloneClass && (MetaModel::IsRootClass($sSomeClass)))
|
||||||
|
{
|
||||||
|
// As we're linking to root class first, we're adding a where clause on the finalClass attribute :
|
||||||
|
// COALESCE($sRootClassFinalClass IN ('$sExpectedClasses'), 1)
|
||||||
|
// If we don't, the child classes can be removed in the query optimisation phase, including the leaf that was queried
|
||||||
|
// So we still need to filter records to only those corresponding to the child classes !
|
||||||
|
// The coalesce is mandatory if we have a polymorphic query (left join)
|
||||||
|
$oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
|
||||||
|
$sFinalClassSqlColumnName = MetaModel::DBGetClassField($sSomeClass);
|
||||||
|
$oClassExpr = new FieldExpression($sFinalClassSqlColumnName, $oSelectBase->GetTableAlias());
|
||||||
|
$oInExpression = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr);
|
||||||
|
$oTrueExpression = new TrueExpression();
|
||||||
|
$aCoalesceAttr = array($oInExpression, $oTrueExpression);
|
||||||
|
$oFinalClassRestriction = new FunctionExpression("COALESCE", $aCoalesceAttr);
|
||||||
|
|
||||||
|
$oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sSomeClass));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oSelectBase = null;
|
// First query built upon on the leaf (ie current) class
|
||||||
|
//
|
||||||
// As the join will not filter on the expected classes, we have to specify it explicitely
|
self::DbgTrace("Main (=leaf) class, call MakeSQLObjectQuerySingleTable()");
|
||||||
$sExpectedClasses = implode("', '", MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
|
if (MetaModel::HasTable($sClass))
|
||||||
$oFinalClassRestriction = Expression::FromOQL("`$sClassAlias`.finalclass IN ('$sExpectedClasses')");
|
|
||||||
$oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then we join the queries of the eventual parent classes (compound model)
|
|
||||||
foreach(MetaModel::EnumParentClasses($sClass) as $sParentClass)
|
|
||||||
{
|
|
||||||
if (!MetaModel::HasTable($sParentClass)) continue;
|
|
||||||
|
|
||||||
self::DbgTrace("Parent class: $sParentClass... let's call MakeSQLObjectQuerySingleTable()");
|
|
||||||
$oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sParentClass, $aExtKeys, $aValues);
|
|
||||||
if (is_null($oSelectBase))
|
|
||||||
{
|
{
|
||||||
$oSelectBase = $oSelectParentTable;
|
$oSelectBase = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sClass, $aExtKeys, $aValues);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sParentClass));
|
$oSelectBase = null;
|
||||||
|
|
||||||
|
// As the join will not filter on the expected classes, we have to specify it explicitely
|
||||||
|
$sExpectedClasses = implode("', '", MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
|
||||||
|
$oFinalClassRestriction = Expression::FromOQL("`$sClassAlias`.finalclass IN ('$sExpectedClasses')");
|
||||||
|
$oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then we join the queries of the eventual parent classes (compound model)
|
||||||
|
foreach(MetaModel::EnumParentClasses($sClass) as $sParentClass)
|
||||||
|
{
|
||||||
|
if (!MetaModel::HasTable($sParentClass)) continue;
|
||||||
|
|
||||||
|
self::DbgTrace("Parent class: $sParentClass... let's call MakeSQLObjectQuerySingleTable()");
|
||||||
|
$oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sParentClass, $aExtKeys, $aValues);
|
||||||
|
if (is_null($oSelectBase))
|
||||||
|
{
|
||||||
|
$oSelectBase = $oSelectParentTable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sParentClass));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2159,8 +2281,14 @@ class DBObjectSearch extends DBSearch
|
|||||||
* Get the expression for the class and its subclasses (if finalclass = 'subclass' ...)
|
* Get the expression for the class and its subclasses (if finalclass = 'subclass' ...)
|
||||||
* Simplifies the final expression by grouping classes having the same expression
|
* Simplifies the final expression by grouping classes having the same expression
|
||||||
*/
|
*/
|
||||||
static protected function GetPolymorphicExpression($sClass, $sAttCode)
|
static public function GetPolymorphicExpression($sClass, $sAttCode)
|
||||||
{
|
{
|
||||||
|
$oExpression = ExpressionCache::GetCachedExpression($sClass, $sAttCode);
|
||||||
|
if (!empty($oExpression))
|
||||||
|
{
|
||||||
|
return $oExpression;
|
||||||
|
}
|
||||||
|
|
||||||
// 1st step - get all of the required expressions (instantiable classes)
|
// 1st step - get all of the required expressions (instantiable classes)
|
||||||
// and group them using their OQL representation
|
// and group them using their OQL representation
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $m_iCurrRow;
|
protected $m_iCurrRow;
|
||||||
/*
|
/**
|
||||||
* @var DBSearch
|
* @var DBSearch
|
||||||
*/
|
*/
|
||||||
protected $m_oFilter;
|
protected $m_oFilter;
|
||||||
@@ -77,18 +77,20 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
* @var mysqli_result
|
* @var mysqli_result
|
||||||
*/
|
*/
|
||||||
protected $m_oSQLResult;
|
protected $m_oSQLResult;
|
||||||
|
protected $m_bSort;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new set based on a Search definition.
|
* Create a new set based on a Search definition.
|
||||||
*
|
*
|
||||||
* @param DBSearch $oFilter The search filter defining the objects which are part of the set (multiple columns/objects per row are supported)
|
* @param DBSearch $oFilter The search filter defining the objects which are part of the set (multiple columns/objects per row are supported)
|
||||||
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
|
* @param array $aOrderBy Array of '[<classalias>.]attcode' => bAscending
|
||||||
* @param hash $aArgs Values to substitute for the search/query parameters (if any). Format: param_name => value
|
* @param array $aArgs Values to substitute for the search/query parameters (if any). Format: param_name => value
|
||||||
* @param hash $aExtendedDataSpec
|
* @param hash $aExtendedDataSpec
|
||||||
* @param int $iLimitCount Maximum number of rows to load (i.e. equivalent to MySQL's LIMIT start, count)
|
* @param int $iLimitCount Maximum number of rows to load (i.e. equivalent to MySQL's LIMIT start, count)
|
||||||
* @param int $iLimitStart Index of the first row to load (i.e. equivalent to MySQL's LIMIT start, count)
|
* @param int $iLimitStart Index of the first row to load (i.e. equivalent to MySQL's LIMIT start, count)
|
||||||
|
* @param bool $bSort if false no order by is done
|
||||||
*/
|
*/
|
||||||
public function __construct(DBSearch $oFilter, $aOrderBy = array(), $aArgs = array(), $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0)
|
public function __construct(DBSearch $oFilter, $aOrderBy = array(), $aArgs = array(), $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bSort = true)
|
||||||
{
|
{
|
||||||
$this->m_oFilter = $oFilter->DeepClone();
|
$this->m_oFilter = $oFilter->DeepClone();
|
||||||
$this->m_aAddedIds = array();
|
$this->m_aAddedIds = array();
|
||||||
@@ -98,6 +100,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
$this->m_aExtendedDataSpec = $aExtendedDataSpec;
|
$this->m_aExtendedDataSpec = $aExtendedDataSpec;
|
||||||
$this->m_iLimitCount = $iLimitCount;
|
$this->m_iLimitCount = $iLimitCount;
|
||||||
$this->m_iLimitStart = $iLimitStart;
|
$this->m_iLimitStart = $iLimitStart;
|
||||||
|
$this->m_bSort = $bSort;
|
||||||
|
|
||||||
$this->m_iNumTotalDBRows = null;
|
$this->m_iNumTotalDBRows = null;
|
||||||
$this->m_iNumLoadedDBRows = 0;
|
$this->m_iNumLoadedDBRows = 0;
|
||||||
@@ -195,11 +198,25 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad);
|
||||||
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad] = $oAttDef;
|
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad] = $oAttDef;
|
||||||
if ($oAttDef->IsExternalKey())
|
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
|
||||||
{
|
{
|
||||||
// Add the external key friendly name anytime
|
// Add the external key friendly name anytime
|
||||||
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad.'_friendlyname');
|
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad.'_friendlyname');
|
||||||
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad.'_friendlyname'] = $oFriendlyNameAttDef;
|
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad.'_friendlyname'] = $oFriendlyNameAttDef;
|
||||||
|
|
||||||
|
if (MetaModel::IsArchivable($oAttDef->GetTargetClass(EXTKEY_ABSOLUTE)))
|
||||||
|
{
|
||||||
|
// Add the archive flag if necessary
|
||||||
|
$oArchiveFlagAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad.'_archive_flag');
|
||||||
|
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad.'_archive_flag'] = $oArchiveFlagAttDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MetaModel::IsObsoletable($oAttDef->GetTargetClass(EXTKEY_ABSOLUTE)))
|
||||||
|
{
|
||||||
|
// Add the obsolescence flag if necessary
|
||||||
|
$oObsoleteFlagAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad.'_obsolescence_flag');
|
||||||
|
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad.'_obsolescence_flag'] = $oObsoleteFlagAttDef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,6 +224,20 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, 'friendlyname');
|
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, 'friendlyname');
|
||||||
$aAttToLoadWithAttDef[$sClassAlias]['friendlyname'] = $oFriendlyNameAttDef;
|
$aAttToLoadWithAttDef[$sClassAlias]['friendlyname'] = $oFriendlyNameAttDef;
|
||||||
|
|
||||||
|
if (MetaModel::IsArchivable($sClass))
|
||||||
|
{
|
||||||
|
// Add the archive flag if necessary
|
||||||
|
$oArchiveFlagAttDef = MetaModel::GetAttributeDef($sClass, 'archive_flag');
|
||||||
|
$aAttToLoadWithAttDef[$sClassAlias]['archive_flag'] = $oArchiveFlagAttDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MetaModel::IsObsoletable($sClass))
|
||||||
|
{
|
||||||
|
// Add the obsolescence flag if necessary
|
||||||
|
$oObsoleteFlagAttDef = MetaModel::GetAttributeDef($sClass, 'obsolescence_flag');
|
||||||
|
$aAttToLoadWithAttDef[$sClassAlias]['obsolescence_flag'] = $oObsoleteFlagAttDef;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that the final class is requested anytime, whatever the specification (needed for object construction!)
|
// Make sure that the final class is requested anytime, whatever the specification (needed for object construction!)
|
||||||
if (!MetaModel::IsStandaloneClass($sClass) && !array_key_exists('finalclass', $aAttToLoadWithAttDef[$sClassAlias]))
|
if (!MetaModel::IsStandaloneClass($sClass) && !array_key_exists('finalclass', $aAttToLoadWithAttDef[$sClassAlias]))
|
||||||
{
|
{
|
||||||
@@ -312,7 +343,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: After calling this method, the set cursor will be at the end of the set. You might to rewind it.
|
* Note: After calling this method, the set cursor will be at the end of the set. You might want to rewind it.
|
||||||
*
|
*
|
||||||
* @param bool $bWithId
|
* @param bool $bWithId
|
||||||
* @return array
|
* @return array
|
||||||
@@ -386,7 +417,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: After calling this method, the set cursor will be at the end of the set. You might to rewind it.
|
* Note: After calling this method, the set cursor will be at the end of the set. You might want to rewind it.
|
||||||
*
|
*
|
||||||
* @param string $sAttCode
|
* @param string $sAttCode
|
||||||
* @param bool $bWithId
|
* @param bool $bWithId
|
||||||
@@ -573,10 +604,15 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
*
|
*
|
||||||
* Limitation: the sort order has no effect on objects added in-memory
|
* Limitation: the sort order has no effect on objects added in-memory
|
||||||
*
|
*
|
||||||
* @return hash Format: field_code => boolean (true = ascending, false = descending)
|
* @return array Format: field_code => boolean (true = ascending, false = descending)
|
||||||
*/
|
*/
|
||||||
public function GetRealSortOrder()
|
public function GetRealSortOrder()
|
||||||
{
|
{
|
||||||
|
if (!$this->m_bSort)
|
||||||
|
{
|
||||||
|
// No order by
|
||||||
|
return array();
|
||||||
|
}
|
||||||
// Get the class default sort order if not specified with the API
|
// Get the class default sort order if not specified with the API
|
||||||
//
|
//
|
||||||
if (empty($this->m_aOrderBy))
|
if (empty($this->m_aOrderBy))
|
||||||
@@ -598,14 +634,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
// Note: it is mandatory to set this value now, to protect against reentrance
|
// Note: it is mandatory to set this value now, to protect against reentrance
|
||||||
$this->m_bLoaded = true;
|
$this->m_bLoaded = true;
|
||||||
|
|
||||||
if ($this->m_iLimitCount > 0)
|
$sSQL = $this->_makeSelectQuery($this->m_aAttToLoad);
|
||||||
{
|
|
||||||
$sSQL = $this->m_oFilter->MakeSelectQuery($this->GetRealSortOrder(), $this->m_aArgs, $this->m_aAttToLoad, $this->m_aExtendedDataSpec, $this->m_iLimitCount, $this->m_iLimitStart);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$sSQL = $this->m_oFilter->MakeSelectQuery($this->GetRealSortOrder(), $this->m_aArgs, $this->m_aAttToLoad, $this->m_aExtendedDataSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_object($this->m_oSQLResult))
|
if (is_object($this->m_oSQLResult))
|
||||||
{
|
{
|
||||||
@@ -614,8 +643,36 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
$this->m_oSQLResult = null;
|
$this->m_oSQLResult = null;
|
||||||
}
|
}
|
||||||
$this->m_iNumTotalDBRows = null;
|
$this->m_iNumTotalDBRows = null;
|
||||||
|
|
||||||
$this->m_oSQLResult = CMDBSource::Query($sSQL);
|
try
|
||||||
|
{
|
||||||
|
$this->m_oSQLResult = CMDBSource::Query($sSQL);
|
||||||
|
} catch (MySQLException $e)
|
||||||
|
{
|
||||||
|
// 1116 = ER_TOO_MANY_TABLES
|
||||||
|
// https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_too_many_tables
|
||||||
|
if ($e->getCode() != 1116)
|
||||||
|
{
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// N.689 Workaround for the 61 max joins in MySQL : full lazy load !
|
||||||
|
$aAttToLoad = array();
|
||||||
|
foreach($this->m_oFilter->GetSelectedClasses() as $sClassAlias => $sClass)
|
||||||
|
{
|
||||||
|
$aAttToLoad[$sClassAlias] = array();
|
||||||
|
$bIsAbstractClass = MetaModel::IsAbstract($sClass);
|
||||||
|
$bIsClassWithChildren = MetaModel::HasChildrenClasses($sClass);
|
||||||
|
if ($bIsAbstractClass || $bIsClassWithChildren)
|
||||||
|
{
|
||||||
|
// we need finalClass field at least to be able to instantiate the real corresponding object !
|
||||||
|
$aAttToLoad[$sClassAlias]['finalclass'] = MetaModel::GetAttributeDef($sClass, 'finalclass');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sSQL = $this->_makeSelectQuery($aAttToLoad);
|
||||||
|
$this->m_oSQLResult = CMDBSource::Query($sSQL); // may fail again
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->m_oSQLResult === false) return;
|
if ($this->m_oSQLResult === false) return;
|
||||||
|
|
||||||
if (($this->m_iLimitCount == 0) && ($this->m_iLimitStart == 0))
|
if (($this->m_iLimitCount == 0) && ($this->m_iLimitStart == 0))
|
||||||
@@ -626,24 +683,54 @@ class DBObjectSet implements iDBObjectSetIterator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The total number of rows in this set. Independently of the SetLimit used for loading the set and taking into account the rows added in-memory.
|
* @param string[] $aAttToLoad
|
||||||
*
|
*
|
||||||
* May actually perform the SQL query SELECT COUNT... if the set was not previously loaded, or loaded with a SetLimit
|
* @return string SQL query
|
||||||
*
|
|
||||||
* @return int The total number of rows for this set.
|
|
||||||
*/
|
*/
|
||||||
public function Count()
|
private function _makeSelectQuery($aAttToLoad)
|
||||||
|
{
|
||||||
|
if ($this->m_iLimitCount > 0)
|
||||||
|
{
|
||||||
|
$sSQL = $this->m_oFilter->MakeSelectQuery($this->GetRealSortOrder(), $this->m_aArgs, $aAttToLoad,
|
||||||
|
$this->m_aExtendedDataSpec, $this->m_iLimitCount, $this->m_iLimitStart);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sSQL = $this->m_oFilter->MakeSelectQuery($this->GetRealSortOrder(), $this->m_aArgs, $aAttToLoad,
|
||||||
|
$this->m_aExtendedDataSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sSQL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of rows in this set. Independently of the SetLimit used for loading the set and taking into
|
||||||
|
* account the rows added in-memory.
|
||||||
|
*
|
||||||
|
* May actually perform the SQL query SELECT COUNT... if the set was not previously loaded, or loaded with a
|
||||||
|
* SetLimit
|
||||||
|
*
|
||||||
|
* @param int $iLimit used for autocomplete: the count is only used to know if the number of entries exceed
|
||||||
|
* a certain amount or not
|
||||||
|
*
|
||||||
|
* @return int The total number of rows for this set.
|
||||||
|
* @throws \CoreException
|
||||||
|
* @throws \MissingQueryArgument
|
||||||
|
* @throws \MySQLException
|
||||||
|
*/
|
||||||
|
public function Count($iLimit = 0)
|
||||||
{
|
{
|
||||||
if (is_null($this->m_iNumTotalDBRows))
|
if (is_null($this->m_iNumTotalDBRows))
|
||||||
{
|
{
|
||||||
$sSQL = $this->m_oFilter->MakeSelectQuery(array(), $this->m_aArgs, null, null, 0, 0, true);
|
$sSQL = $this->m_oFilter->MakeSelectQuery(array(), $this->m_aArgs, null, null, $iLimit, 0, true);
|
||||||
$resQuery = CMDBSource::Query($sSQL);
|
$resQuery = CMDBSource::Query($sSQL);
|
||||||
if (!$resQuery) return 0;
|
if (!$resQuery) return 0;
|
||||||
|
|
||||||
$aRow = CMDBSource::FetchArray($resQuery);
|
$aRow = CMDBSource::FetchArray($resQuery);
|
||||||
CMDBSource::FreeResult($resQuery);
|
CMDBSource::FreeResult($resQuery);
|
||||||
$this->m_iNumTotalDBRows = $aRow['COUNT'];
|
$this->m_iNumTotalDBRows = $aRow['COUNT'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->m_iNumTotalDBRows + count($this->m_aAddedObjects); // Does it fix Trac #887 ??
|
return $this->m_iNumTotalDBRows + count($this->m_aAddedObjects); // Does it fix Trac #887 ??
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -474,7 +474,7 @@ class DBUnionSearch extends DBSearch
|
|||||||
throw new Exception('MakeUpdateQuery is not implemented for the unions!');
|
throw new Exception('MakeUpdateQuery is not implemented for the unions!');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null)
|
public function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null)
|
||||||
{
|
{
|
||||||
if (count($this->aSearches) == 1)
|
if (count($this->aSearches) == 1)
|
||||||
{
|
{
|
||||||
@@ -496,19 +496,30 @@ class DBUnionSearch extends DBSearch
|
|||||||
$aSearchSelectedClasses[$sSearchAlias] = $this->aSelectedClasses[$sAlias];
|
$aSearchSelectedClasses[$sSearchAlias] = $this->aSelectedClasses[$sAlias];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_null($aAttToLoad))
|
if ($bGetCount)
|
||||||
{
|
{
|
||||||
$aQueryAttToLoad = null;
|
// Select only ids for the count to allow optimization of joins
|
||||||
|
foreach($aSearchAliases as $sSearchAlias)
|
||||||
|
{
|
||||||
|
$aQueryAttToLoad[$sSearchAlias] = array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// (Eventually) Transform the aliases
|
if (is_null($aAttToLoad))
|
||||||
$aQueryAttToLoad = array();
|
|
||||||
foreach ($aAttToLoad as $sAlias => $aAttributes)
|
|
||||||
{
|
{
|
||||||
$iColumn = array_search($sAlias, $aAliases);
|
$aQueryAttToLoad = null;
|
||||||
$sQueryAlias = ($iColumn === false) ? $sAlias : $aSearchAliases[$iColumn];
|
}
|
||||||
$aQueryAttToLoad[$sQueryAlias] = $aAttributes;
|
else
|
||||||
|
{
|
||||||
|
// (Eventually) Transform the aliases
|
||||||
|
$aQueryAttToLoad = array();
|
||||||
|
foreach($aAttToLoad as $sAlias => $aAttributes)
|
||||||
|
{
|
||||||
|
$iColumn = array_search($sAlias, $aAliases);
|
||||||
|
$sQueryAlias = ($iColumn === false) ? $sAlias : $aSearchAliases[$iColumn];
|
||||||
|
$aQueryAttToLoad[$sQueryAlias] = $aAttributes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1270,6 +1270,7 @@ class DisplayableGraph extends SimpleGraph
|
|||||||
|
|
||||||
$oPdf->SetAutoPageBreak(true, $fBreakMargin);
|
$oPdf->SetAutoPageBreak(true, $fBreakMargin);
|
||||||
$oPdf->SetAlpha(1);
|
$oPdf->SetAlpha(1);
|
||||||
|
$oPdf->SetTextColor(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2013 Combodo SARL
|
// Copyright (C) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -408,4 +408,30 @@ class EventLoginUsage extends Event
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
class EventOnObject extends Event
|
||||||
|
{
|
||||||
|
public static function Init()
|
||||||
|
{
|
||||||
|
$aParams = array
|
||||||
|
(
|
||||||
|
"category" => "core/cmdb,view_in_gui",
|
||||||
|
"key_type" => "autoincrement",
|
||||||
|
"name_attcode" => "",
|
||||||
|
"state_attcode" => "",
|
||||||
|
"reconc_keys" => array(),
|
||||||
|
"db_table" => "priv_event_onobject",
|
||||||
|
"db_key_field" => "id",
|
||||||
|
"db_finalclass_field" => "",
|
||||||
|
"display_template" => "",
|
||||||
|
"order_by_default" => array('date' => false)
|
||||||
|
);
|
||||||
|
MetaModel::Init_Params($aParams);
|
||||||
|
MetaModel::Init_InheritAttributes();
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeString("obj_class", array("allowed_values"=>null, "sql"=>"obj_class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeInteger("obj_key", array("allowed_values"=>null, "sql"=>"obj_key", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
|
// Display lists
|
||||||
|
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'obj_class', 'obj_key', 'message')); // Attributes to be displayed for the complete details
|
||||||
|
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'obj_class', 'obj_key', 'message')); // Attributes to be displayed for a list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -188,10 +188,10 @@ EOF
|
|||||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
|
||||||
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
|
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
|
||||||
}
|
}
|
||||||
else if ($value instanceOf ormCustomFieldsValue)
|
else if ($value instanceOf ormDocument)
|
||||||
{
|
{
|
||||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
|
||||||
$sRet = $oAttDef->GetAsCSV($value, "\n", '', $oObj);
|
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
110
core/expressioncache.class.inc.php
Normal file
110
core/expressioncache.class.inc.php
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
// Copyright (c) 2010-2017 Combodo SARL
|
||||||
|
//
|
||||||
|
// This file is part of iTop.
|
||||||
|
//
|
||||||
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// iTop is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
//
|
||||||
|
|
||||||
|
class ExpressionCache
|
||||||
|
{
|
||||||
|
static private $aCache = array();
|
||||||
|
|
||||||
|
static public function GetCachedExpression($sClass, $sAttCode)
|
||||||
|
{
|
||||||
|
// read current cache
|
||||||
|
@include_once (static::GetCacheFileName());
|
||||||
|
|
||||||
|
$oExpr = null;
|
||||||
|
$sKey = static::GetKey($sClass, $sAttCode);
|
||||||
|
if (array_key_exists($sKey, static::$aCache))
|
||||||
|
{
|
||||||
|
$oExpr = static::$aCache[$sKey];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (class_exists('ExpressionCacheData'))
|
||||||
|
{
|
||||||
|
if (array_key_exists($sKey, ExpressionCacheData::$aCache))
|
||||||
|
{
|
||||||
|
$sVal = ExpressionCacheData::$aCache[$sKey];
|
||||||
|
$oExpr = unserialize($sVal);
|
||||||
|
static::$aCache[$sKey] = $oExpr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $oExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public function Warmup()
|
||||||
|
{
|
||||||
|
$sFilePath = static::GetCacheFileName();
|
||||||
|
|
||||||
|
if (!is_file($sFilePath))
|
||||||
|
{
|
||||||
|
$content = <<<EOF
|
||||||
|
<?php
|
||||||
|
// Copyright (c) 2010-2017 Combodo SARL
|
||||||
|
// Generated Expression Cache file
|
||||||
|
|
||||||
|
class ExpressionCacheData
|
||||||
|
{
|
||||||
|
static \$aCache = array(
|
||||||
|
EOF;
|
||||||
|
|
||||||
|
foreach(MetaModel::GetClasses() as $sClass)
|
||||||
|
{
|
||||||
|
$content .= static::GetSerializedExpression($sClass, 'friendlyname');
|
||||||
|
if (MetaModel::IsObsoletable($sClass))
|
||||||
|
{
|
||||||
|
$content .= static::GetSerializedExpression($sClass, 'obsolescence_flag');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$content .= <<<EOF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
EOF;
|
||||||
|
|
||||||
|
file_put_contents($sFilePath, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static private function GetSerializedExpression($sClass, $sAttCode)
|
||||||
|
{
|
||||||
|
$sKey = static::GetKey($sClass, $sAttCode);
|
||||||
|
$oExpr = DBObjectSearch::GetPolymorphicExpression($sClass, $sAttCode);
|
||||||
|
return "'".$sKey."' => '".serialize($oExpr)."',\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $sClass
|
||||||
|
* @param $sAttCode
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
static private function GetKey($sClass, $sAttCode)
|
||||||
|
{
|
||||||
|
return $sClass.'::'.$sAttCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function GetCacheFileName()
|
||||||
|
{
|
||||||
|
return utils::GetCachePath().'expressioncache.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -156,6 +156,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
|||||||
'body' => array(),
|
'body' => array(),
|
||||||
'a' => array('href', 'name', 'style', 'target', 'title'),
|
'a' => array('href', 'name', 'style', 'target', 'title'),
|
||||||
'p' => array('style'),
|
'p' => array('style'),
|
||||||
|
'blockquote' => array('style'),
|
||||||
'br' => array(),
|
'br' => array(),
|
||||||
'span' => array('style'),
|
'span' => array('style'),
|
||||||
'div' => array('style'),
|
'div' => array('style'),
|
||||||
@@ -212,9 +213,17 @@ class HTMLDOMSanitizer extends HTMLSanitizer
|
|||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
// Building href validation pattern from url and email validation patterns as the patterns are not used the same way in HTML content than in standard attributes value.
|
||||||
|
// eg. "foo@bar.com" vs "mailto:foo@bar.com?subject=Title&body=Hello%20world"
|
||||||
if (!array_key_exists('href', self::$aAttrsWhiteList))
|
if (!array_key_exists('href', self::$aAttrsWhiteList))
|
||||||
{
|
{
|
||||||
$sPattern = '/'.str_replace('/', '\/', utils::GetConfig()->Get('url_validation_pattern')).'/i';
|
// Regular urls
|
||||||
|
$sUrlPattern = utils::GetConfig()->Get('url_validation_pattern');
|
||||||
|
// Mailto urls
|
||||||
|
$sMailtoPattern = '(mailto:(' . utils::GetConfig()->Get('email_validation_pattern') . ')(?:\?(?:subject|body)=([a-zA-Z0-9+\$_.-]*)(?:&(?:subject|body)=([a-zA-Z0-9+\$_.-]*))?)?)';
|
||||||
|
|
||||||
|
$sPattern = $sUrlPattern . '|' . $sMailtoPattern;
|
||||||
|
$sPattern = '/'.str_replace('/', '\/', $sPattern).'/i';
|
||||||
self::$aAttrsWhiteList['href'] = $sPattern;
|
self::$aAttrsWhiteList['href'] = $sPattern;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2017 Combodo SARL
|
// Copyright (c) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// 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
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
//
|
||||||
|
|
||||||
require_once(APPROOT.'core/modulehandler.class.inc.php');
|
require_once(APPROOT.'core/modulehandler.class.inc.php');
|
||||||
require_once(APPROOT.'core/querybuildercontext.class.inc.php');
|
require_once(APPROOT.'core/querybuildercontext.class.inc.php');
|
||||||
@@ -23,6 +24,7 @@ require_once(APPROOT.'core/metamodelmodifier.inc.php');
|
|||||||
require_once(APPROOT.'core/computing.inc.php');
|
require_once(APPROOT.'core/computing.inc.php');
|
||||||
require_once(APPROOT.'core/relationgraph.class.inc.php');
|
require_once(APPROOT.'core/relationgraph.class.inc.php');
|
||||||
require_once(APPROOT.'core/apc-compat.php');
|
require_once(APPROOT.'core/apc-compat.php');
|
||||||
|
require_once(APPROOT.'core/expressioncache.class.inc.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metamodel
|
* Metamodel
|
||||||
@@ -331,9 +333,16 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
final static public function GetObsolescenceExpression($sClass)
|
final static public function GetObsolescenceExpression($sClass)
|
||||||
{
|
{
|
||||||
self::_check_subclass($sClass);
|
if (self::IsObsoletable($sClass))
|
||||||
$sOql = self::$m_aClassParams[$sClass]['obsolescence_expression'];
|
{
|
||||||
$oRet = Expression::FromOQL("COALESCE($sOql, 0)");
|
self::_check_subclass($sClass);
|
||||||
|
$sOql = self::$m_aClassParams[$sClass]['obsolescence_expression'];
|
||||||
|
$oRet = Expression::FromOQL("COALESCE($sOql, 0)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oRet = Expression::FromOQL("0");
|
||||||
|
}
|
||||||
return $oRet;
|
return $oRet;
|
||||||
}
|
}
|
||||||
final static public function GetNameSpec($sClass)
|
final static public function GetNameSpec($sClass)
|
||||||
@@ -413,13 +422,13 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the friendly name IIF it is equivalent to a single attribute
|
* Returns the friendly name IIF it is equivalent to a single attribute
|
||||||
*/
|
*/
|
||||||
final static public function GetFriendlyNameAttributeCode($sClass)
|
final static public function GetFriendlyNameAttributeCode($sClass)
|
||||||
{
|
{
|
||||||
$aNameSpec = self::GetNameSpec($sClass);
|
$aNameSpec = self::GetNameSpec($sClass);
|
||||||
$sFormat = trim($aNameSpec[0]);
|
$sFormat = trim($aNameSpec[0]);
|
||||||
$aAttributes = $aNameSpec[1];
|
$aAttributes = $aNameSpec[1];
|
||||||
if (($sFormat != '') && ($sFormat != '%1$s'))
|
if (($sFormat != '') && ($sFormat != '%1$s'))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -431,6 +440,20 @@ abstract class MetaModel
|
|||||||
return reset($aAttributes);
|
return reset($aAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of attributes composing the friendlyname
|
||||||
|
*
|
||||||
|
* @param $sClass
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
final static public function GetFriendlyNameAttributeCodeList($sClass)
|
||||||
|
{
|
||||||
|
$aNameSpec = self::GetNameSpec($sClass);
|
||||||
|
$aAttributes = $aNameSpec[1];
|
||||||
|
return $aAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
final static public function GetStateAttributeCode($sClass)
|
final static public function GetStateAttributeCode($sClass)
|
||||||
{
|
{
|
||||||
self::_check_subclass($sClass);
|
self::_check_subclass($sClass);
|
||||||
@@ -1082,11 +1105,37 @@ abstract class MetaModel
|
|||||||
return $aClassRelations;
|
return $aClassRelations;
|
||||||
}
|
}
|
||||||
|
|
||||||
final static public function GetRelationDescription($sRelCode)
|
/**
|
||||||
|
* @param string $sRelCode Relation code
|
||||||
|
* @param bool $bDown Relation direction, is it downstream (true) or upstream (false). Default is true.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
final static public function GetRelationDescription($sRelCode, $bDown = true)
|
||||||
{
|
{
|
||||||
return Dict::S("Relation:$sRelCode/Description");
|
// Legacy convention had only one description describing the relation.
|
||||||
|
// Now, as the relation is bidirectional, we have a description for each directions.
|
||||||
|
$sLegacy = Dict::S("Relation:$sRelCode/Description");
|
||||||
|
|
||||||
|
if($bDown)
|
||||||
|
{
|
||||||
|
$sKey = "Relation:$sRelCode/DownStream+";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sKey = "Relation:$sRelCode/UpStream+";
|
||||||
|
}
|
||||||
|
$sRet = Dict::S($sKey, $sLegacy);
|
||||||
|
|
||||||
|
return $sRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sRelCode Relation code
|
||||||
|
* @param bool $bDown Relation direction, is it downstream (true) or upstream (false). Default is true.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
final static public function GetRelationLabel($sRelCode, $bDown = true)
|
final static public function GetRelationLabel($sRelCode, $bDown = true)
|
||||||
{
|
{
|
||||||
if ($bDown)
|
if ($bDown)
|
||||||
@@ -1857,15 +1906,13 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare external fields and filters
|
// Add magic attributes to the classes
|
||||||
// Add final class to external keys
|
|
||||||
//
|
|
||||||
foreach (self::GetClasses() as $sClass)
|
foreach (self::GetClasses() as $sClass)
|
||||||
{
|
{
|
||||||
$sRootClass = self::$m_aRootClasses[$sClass];
|
$sRootClass = self::$m_aRootClasses[$sClass];
|
||||||
|
|
||||||
// Create the friendly name attribute
|
// Create the friendly name attribute
|
||||||
$sFriendlyNameAttCode = 'friendlyname';
|
$sFriendlyNameAttCode = 'friendlyname';
|
||||||
$oFriendlyName = new AttributeFriendlyName($sFriendlyNameAttCode);
|
$oFriendlyName = new AttributeFriendlyName($sFriendlyNameAttCode);
|
||||||
self::AddMagicAttribute($oFriendlyName, $sClass);
|
self::AddMagicAttribute($oFriendlyName, $sClass);
|
||||||
|
|
||||||
@@ -1875,7 +1922,7 @@ abstract class MetaModel
|
|||||||
$oArchiveFlag = new AttributeArchiveFlag('archive_flag');
|
$oArchiveFlag = new AttributeArchiveFlag('archive_flag');
|
||||||
self::AddMagicAttribute($oArchiveFlag, $sClass);
|
self::AddMagicAttribute($oArchiveFlag, $sClass);
|
||||||
|
|
||||||
$oArchiveDate = new AttributeDate('archive_date', array('magic' => true, "allowed_values"=>null, "sql"=>'archive_date', "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array()));
|
$oArchiveDate = new AttributeArchiveDate('archive_date', array('magic' => true, "allowed_values" => null, "sql" => 'archive_date', "default_value" => '', "is_null_allowed" => true, "depends_on" => array()));
|
||||||
self::AddMagicAttribute($oArchiveDate, $sClass);
|
self::AddMagicAttribute($oArchiveDate, $sClass);
|
||||||
}
|
}
|
||||||
elseif (self::$m_aClassParams[$sClass]["archive"])
|
elseif (self::$m_aClassParams[$sClass]["archive"])
|
||||||
@@ -1898,7 +1945,7 @@ abstract class MetaModel
|
|||||||
|
|
||||||
if (self::$m_aRootClasses[$sClass] == $sClass)
|
if (self::$m_aRootClasses[$sClass] == $sClass)
|
||||||
{
|
{
|
||||||
$oObsolescenceDate = new AttributeDate('obsolescence_date', array('magic' => true, "allowed_values" => null, "sql" => 'obsolescence_date', "default_value" => '', "is_null_allowed" => true, "depends_on" => array()));
|
$oObsolescenceDate = new AttributeObsolescenceDate('obsolescence_date', array('magic' => true, "allowed_values" => null, "sql" => 'obsolescence_date', "default_value" => '', "is_null_allowed" => true, "depends_on" => array()));
|
||||||
self::AddMagicAttribute($oObsolescenceDate, $sClass);
|
self::AddMagicAttribute($oObsolescenceDate, $sClass);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1909,6 +1956,13 @@ abstract class MetaModel
|
|||||||
self::$m_aAttribOrigins[$sClass]['obsolescence_date'] = $sRootClass;
|
self::$m_aAttribOrigins[$sClass]['obsolescence_date'] = $sRootClass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare external fields and filters
|
||||||
|
// Add final class to external keys
|
||||||
|
// Add magic attributes to external keys (finalclass, friendlyname, archive_flag, obsolescence_flag)
|
||||||
|
foreach (self::GetClasses() as $sClass)
|
||||||
|
{
|
||||||
foreach (self::$m_aAttribDefs[$sClass] as $sAttCode => $oAttDef)
|
foreach (self::$m_aAttribDefs[$sClass] as $sAttCode => $oAttDef)
|
||||||
{
|
{
|
||||||
// Compute the filter codes
|
// Compute the filter codes
|
||||||
@@ -3766,6 +3820,7 @@ abstract class MetaModel
|
|||||||
//
|
//
|
||||||
$aTableInfo = CMDBSource::GetTableInfo($sTable);
|
$aTableInfo = CMDBSource::GetTableInfo($sTable);
|
||||||
$aTableInfo['Fields'][$sKeyField]['used'] = true;
|
$aTableInfo['Fields'][$sKeyField]['used'] = true;
|
||||||
|
$aFriendlynameAttcodes = self::GetFriendlyNameAttributeCodeList($sClass);
|
||||||
foreach(self::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
|
foreach(self::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
|
||||||
{
|
{
|
||||||
if (!$oAttDef->CopyOnAllTables())
|
if (!$oAttDef->CopyOnAllTables())
|
||||||
@@ -3779,6 +3834,14 @@ abstract class MetaModel
|
|||||||
$aTableInfo['Fields'][$sField]['used'] = true;
|
$aTableInfo['Fields'][$sField]['used'] = true;
|
||||||
|
|
||||||
$bIndexNeeded = $oAttDef->RequiresIndex();
|
$bIndexNeeded = $oAttDef->RequiresIndex();
|
||||||
|
if (!$bIndexNeeded)
|
||||||
|
{
|
||||||
|
// Add an index on the columns of the friendlyname
|
||||||
|
if (in_array($sField, $aFriendlynameAttcodes))
|
||||||
|
{
|
||||||
|
$bIndexNeeded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$sFieldDefinition = "`$sField` $sDBFieldSpec";
|
$sFieldDefinition = "`$sField` $sDBFieldSpec";
|
||||||
if (!CMDBSource::IsField($sTable, $sField))
|
if (!CMDBSource::IsField($sTable, $sField))
|
||||||
@@ -3787,6 +3850,7 @@ abstract class MetaModel
|
|||||||
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` ADD $sFieldDefinition";
|
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` ADD $sFieldDefinition";
|
||||||
if ($bIndexNeeded)
|
if ($bIndexNeeded)
|
||||||
{
|
{
|
||||||
|
$aTableInfo['Indexes'][$sField]['used'] = true;
|
||||||
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` ADD INDEX (`$sField`)";
|
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` ADD INDEX (`$sField`)";
|
||||||
}
|
}
|
||||||
if (array_key_exists($sTable, $aCreateTable))
|
if (array_key_exists($sTable, $aCreateTable))
|
||||||
@@ -3794,6 +3858,7 @@ abstract class MetaModel
|
|||||||
$aCreateTableItems[$sTable][$sField] = $sFieldDefinition;
|
$aCreateTableItems[$sTable][$sField] = $sFieldDefinition;
|
||||||
if ($bIndexNeeded)
|
if ($bIndexNeeded)
|
||||||
{
|
{
|
||||||
|
$aTableInfo['Indexes'][$sField]['used'] = true;
|
||||||
$aCreateTableItems[$sTable][] = "INDEX (`$sField`)";
|
$aCreateTableItems[$sTable][] = "INDEX (`$sField`)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3802,6 +3867,7 @@ abstract class MetaModel
|
|||||||
$aAlterTableItems[$sTable][$sField] = "ADD $sFieldDefinition";
|
$aAlterTableItems[$sTable][$sField] = "ADD $sFieldDefinition";
|
||||||
if ($bIndexNeeded)
|
if ($bIndexNeeded)
|
||||||
{
|
{
|
||||||
|
$aTableInfo['Indexes'][$sField]['used'] = true;
|
||||||
$aAlterTableItems[$sTable][] = "ADD INDEX (`$sField`)";
|
$aAlterTableItems[$sTable][] = "ADD INDEX (`$sField`)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3827,6 +3893,7 @@ abstract class MetaModel
|
|||||||
//
|
//
|
||||||
if ($bIndexNeeded && !CMDBSource::HasIndex($sTable, $sField, array($sField)))
|
if ($bIndexNeeded && !CMDBSource::HasIndex($sTable, $sField, array($sField)))
|
||||||
{
|
{
|
||||||
|
$aTableInfo['Indexes'][$sField]['used'] = true;
|
||||||
$aErrors[$sClass][$sAttCode][] = "Foreign key '$sField' in table '$sTable' should have an index";
|
$aErrors[$sClass][$sAttCode][] = "Foreign key '$sField' in table '$sTable' should have an index";
|
||||||
if (CMDBSource::HasIndex($sTable, $sField))
|
if (CMDBSource::HasIndex($sTable, $sField))
|
||||||
{
|
{
|
||||||
@@ -3848,7 +3915,10 @@ abstract class MetaModel
|
|||||||
foreach (self::DBGetIndexes($sClass) as $aColumns)
|
foreach (self::DBGetIndexes($sClass) as $aColumns)
|
||||||
{
|
{
|
||||||
$sIndexId = implode('_', $aColumns);
|
$sIndexId = implode('_', $aColumns);
|
||||||
|
if (isset($aTableInfo['Indexes'][$sIndexId]['used']) && $aTableInfo['Indexes'][$sIndexId]['used'])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(!CMDBSource::HasIndex($sTable, $sIndexId, $aColumns))
|
if(!CMDBSource::HasIndex($sTable, $sIndexId, $aColumns))
|
||||||
{
|
{
|
||||||
$sColumns = "`".implode("`, `", $aColumns)."`";
|
$sColumns = "`".implode("`, `", $aColumns)."`";
|
||||||
@@ -4394,6 +4464,8 @@ abstract class MetaModel
|
|||||||
echo "Debug<br/>\n";
|
echo "Debug<br/>\n";
|
||||||
self::static_var_dump();
|
self::static_var_dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpressionCache::Warmup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function LoadConfig($oConfiguration, $bAllowCache = false)
|
public static function LoadConfig($oConfiguration, $bAllowCache = false)
|
||||||
@@ -4590,6 +4662,14 @@ abstract class MetaModel
|
|||||||
return self::$m_oConfig;
|
return self::$m_oConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string The environment in which the model has been loaded (e.g. 'production')
|
||||||
|
*/
|
||||||
|
public static function GetEnvironment()
|
||||||
|
{
|
||||||
|
return self::$m_sEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
public static function GetEnvironmentId()
|
public static function GetEnvironmentId()
|
||||||
{
|
{
|
||||||
return md5(APPROOT).'-'.self::$m_sEnvironment;
|
return md5(APPROOT).'-'.self::$m_sEnvironment;
|
||||||
@@ -4675,6 +4755,18 @@ abstract class MetaModel
|
|||||||
return $iTotalHits.' ('.implode(', ', $aRes).')';
|
return $iTotalHits.' ('.implode(', ', $aRes).')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sClass
|
||||||
|
* @param int $iKey
|
||||||
|
* @param bool $bMustBeFound
|
||||||
|
* @param bool $bAllowAllData if true then no rights filtering
|
||||||
|
* @param array $aModifierProperties
|
||||||
|
*
|
||||||
|
* @return string[] column name / value array
|
||||||
|
* @throws CoreException if no result found and $bMustBeFound=true
|
||||||
|
*
|
||||||
|
* @see utils::PushArchiveMode() to enable search on archived objects
|
||||||
|
*/
|
||||||
public static function MakeSingleRow($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
public static function MakeSingleRow($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
||||||
{
|
{
|
||||||
// Build the query cache signature
|
// Build the query cache signature
|
||||||
@@ -4731,13 +4823,27 @@ abstract class MetaModel
|
|||||||
|
|
||||||
$aRow = CMDBSource::FetchArray($res);
|
$aRow = CMDBSource::FetchArray($res);
|
||||||
CMDBSource::FreeResult($res);
|
CMDBSource::FreeResult($res);
|
||||||
|
|
||||||
if ($bMustBeFound && empty($aRow))
|
if ($bMustBeFound && empty($aRow))
|
||||||
{
|
{
|
||||||
throw new CoreException("No result for the single row query: '$sSQL'");
|
throw new CoreException("No result for the single row query: '$sSQL'");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $aRow;
|
return $aRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a column name / value array to a {@link DBObject}
|
||||||
|
*
|
||||||
|
* @param string $sClass
|
||||||
|
* @param string[] $aRow column name / value array
|
||||||
|
* @param string $sClassAlias
|
||||||
|
* @param string[] $aAttToLoad
|
||||||
|
* @param array $aExtendedDataSpec
|
||||||
|
*
|
||||||
|
* @return DBObject
|
||||||
|
* @throws CoreException if finalClass cannot be found
|
||||||
|
*/
|
||||||
public static function GetObjectByRow($sClass, $aRow, $sClassAlias = '', $aAttToLoad = null, $aExtendedDataSpec = null)
|
public static function GetObjectByRow($sClass, $aRow, $sClassAlias = '', $aAttToLoad = null, $aExtendedDataSpec = null)
|
||||||
{
|
{
|
||||||
self::_check_subclass($sClass);
|
self::_check_subclass($sClass);
|
||||||
@@ -4771,30 +4877,75 @@ abstract class MetaModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $sClass
|
* Search for the specified class and id.
|
||||||
|
*
|
||||||
|
* @param string $sClass
|
||||||
* @param $iKey
|
* @param $iKey
|
||||||
* @param bool $bMustBeFound
|
* @param bool $bMustBeFound
|
||||||
* @param bool $bAllowAllData
|
* @param bool $bAllowAllData
|
||||||
* @param null $aModifierProperties
|
* @param null $aModifierProperties
|
||||||
* @return DBObject|null
|
* @return DBObject|null null if : (the object is not found) or (archive mode disabled and object is archived and $bMustBeFound=false)
|
||||||
|
* @throws CoreException if no result found and $bMustBeFound=true
|
||||||
|
* @throws ArchivedObjectException if archive mode disabled and result is archived and $bMustBeFound=true
|
||||||
|
*
|
||||||
|
* @see MetaModel::GetObjectWithArchive to get object even if it's archived
|
||||||
|
* @see utils::PushArchiveMode() to enable search on archived objects
|
||||||
*/
|
*/
|
||||||
public static function GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
public static function GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
||||||
{
|
{
|
||||||
self::_check_subclass($sClass);
|
$oObject = self::GetObjectWithArchive($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
|
||||||
|
|
||||||
|
if (empty($oObject))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!utils::IsArchiveMode() && $oObject->IsArchived())
|
||||||
|
{
|
||||||
|
if ($bMustBeFound)
|
||||||
|
{
|
||||||
|
throw new ArchivedObjectException("The object $sClass::$iKey is archived");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $oObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for the specified class and id. If the object is archived it will be returned anyway (this is for pre-2.4
|
||||||
|
* module compatibility, see N.1108)
|
||||||
|
*
|
||||||
|
* @param string $sClass
|
||||||
|
* @param int $iKey
|
||||||
|
* @param bool $bMustBeFound
|
||||||
|
* @param bool $bAllowAllData
|
||||||
|
* @param array $aModifierProperties
|
||||||
|
*
|
||||||
|
* @return DBObject|null
|
||||||
|
* @throws CoreException if no result found and $bMustBeFound=true
|
||||||
|
*
|
||||||
|
* @since 2.4 introduction of the archive functionalities
|
||||||
|
*
|
||||||
|
* @see MetaModel::GetObject() same but returns null or ArchivedObjectFoundException if object exists but is archived
|
||||||
|
*/
|
||||||
|
public static function GetObjectWithArchive($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
||||||
|
{
|
||||||
|
self::_check_subclass($sClass);
|
||||||
|
|
||||||
|
utils::PushArchiveMode(true);
|
||||||
$aRow = self::MakeSingleRow($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
|
$aRow = self::MakeSingleRow($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
|
||||||
|
utils::PopArchiveMode();
|
||||||
|
|
||||||
if (empty($aRow))
|
if (empty($aRow))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return self::GetObjectByRow($sClass, $aRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function GetObjectWithArchive($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
return self::GetObjectByRow($sClass, $aRow); // null should not be returned, this is handled in the callee
|
||||||
{
|
|
||||||
utils::PushArchiveMode(true);
|
|
||||||
$oObject = static::GetObject($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
|
|
||||||
utils::PopArchiveMode();
|
|
||||||
return $oObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetObjectByName($sClass, $sName, $bMustBeFound = true)
|
public static function GetObjectByName($sClass, $sName, $bMustBeFound = true)
|
||||||
@@ -5226,21 +5377,12 @@ abstract class MetaModel
|
|||||||
|
|
||||||
public static function GetCacheEntries($sEnvironment = null)
|
public static function GetCacheEntries($sEnvironment = null)
|
||||||
{
|
{
|
||||||
if (!function_exists('apc_cache_info')) return array();
|
|
||||||
if (is_null($sEnvironment))
|
if (is_null($sEnvironment))
|
||||||
{
|
{
|
||||||
$sEnvironment = MetaModel::GetEnvironmentId();
|
$sEnvironment = MetaModel::GetEnvironmentId();
|
||||||
}
|
}
|
||||||
$aEntries = array();
|
$aEntries = array();
|
||||||
if (extension_loaded('apcu'))
|
$aCacheUserData = apc_cache_info_compat();
|
||||||
{
|
|
||||||
// Beware: APCu behaves slightly differently from APC !!
|
|
||||||
$aCacheUserData = @apc_cache_info();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$aCacheUserData = @apc_cache_info('user');
|
|
||||||
}
|
|
||||||
if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list']))
|
if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list']))
|
||||||
{
|
{
|
||||||
$sPrefix = 'itop-'.$sEnvironment.'-';
|
$sPrefix = 'itop-'.$sEnvironment.'-';
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class iTopMutex
|
|||||||
}
|
}
|
||||||
$sDBName = $oConfig->GetDBName();
|
$sDBName = $oConfig->GetDBName();
|
||||||
$sDBSubname = $oConfig->GetDBSubname();
|
$sDBSubname = $oConfig->GetDBSubname();
|
||||||
$this->sName = 'itop.'.$sName;
|
$this->sName = $sName;
|
||||||
if (substr($sName, -strlen($sDBName.$sDBSubname)) != $sDBName.$sDBSubname)
|
if (substr($sName, -strlen($sDBName.$sDBSubname)) != $sDBName.$sDBSubname)
|
||||||
{
|
{
|
||||||
// If the name supplied already ends with the expected suffix
|
// If the name supplied already ends with the expected suffix
|
||||||
@@ -54,6 +54,9 @@ class iTopMutex
|
|||||||
$this->sName .= $sDBName.$sDBSubname;
|
$this->sName .= $sDBName.$sDBSubname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Limit the length of the name for MySQL > 5.7.5
|
||||||
|
$this->sName = 'itop.'.md5($this->sName);
|
||||||
|
|
||||||
$this->bLocked = false; // Not yet locked
|
$this->bLocked = false; // Not yet locked
|
||||||
|
|
||||||
if (!array_key_exists($this->sName, self::$aAcquiredLocks))
|
if (!array_key_exists($this->sName, self::$aAcquiredLocks))
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2017 Combodo SARL
|
// Copyright (c) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// 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
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -15,14 +15,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
//
|
||||||
|
|
||||||
/**
|
|
||||||
* General definition of an expression tree (could be OQL, SQL or whatever)
|
|
||||||
*
|
|
||||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
class MissingQueryArgument extends CoreException
|
class MissingQueryArgument extends CoreException
|
||||||
{
|
{
|
||||||
@@ -89,9 +82,15 @@ abstract class Expression
|
|||||||
*/
|
*/
|
||||||
static public function FromOQL($sConditionExpr)
|
static public function FromOQL($sConditionExpr)
|
||||||
{
|
{
|
||||||
|
static $aCache = array();
|
||||||
|
if (array_key_exists($sConditionExpr, $aCache))
|
||||||
|
{
|
||||||
|
return unserialize($aCache[$sConditionExpr]);
|
||||||
|
}
|
||||||
$oOql = new OqlInterpreter($sConditionExpr);
|
$oOql = new OqlInterpreter($sConditionExpr);
|
||||||
$oExpression = $oOql->ParseExpression();
|
$oExpression = $oOql->ParseExpression();
|
||||||
|
$aCache[$sConditionExpr] = serialize($oExpression);
|
||||||
|
|
||||||
return $oExpression;
|
return $oExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +226,10 @@ class BinaryExpression extends Expression
|
|||||||
{
|
{
|
||||||
throw new CoreException('Expecting an Expression object on the right hand', array('found_class' => get_class($oRightExpr)));
|
throw new CoreException('Expecting an Expression object on the right hand', array('found_class' => get_class($oRightExpr)));
|
||||||
}
|
}
|
||||||
|
if ( (($sOperator == "IN") || ($sOperator == "NOT IN")) && !$oRightExpr instanceof ListExpression)
|
||||||
|
{
|
||||||
|
throw new CoreException("Expecting a List Expression object on the right hand for operator $sOperator", array('found_class' => get_class($oRightExpr)));
|
||||||
|
}
|
||||||
$this->m_oLeftExpr = $oLeftExpr;
|
$this->m_oLeftExpr = $oLeftExpr;
|
||||||
$this->m_oRightExpr = $oRightExpr;
|
$this->m_oRightExpr = $oRightExpr;
|
||||||
$this->m_sOperator = $sOperator;
|
$this->m_sOperator = $sOperator;
|
||||||
|
|||||||
@@ -191,8 +191,15 @@ class ormCaseLog {
|
|||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return $this->m_sLog;
|
if($this->IsEmpty()) return '';
|
||||||
|
|
||||||
|
return $this->m_sLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function IsEmpty()
|
||||||
|
{
|
||||||
|
return ($this->m_sLog === null);
|
||||||
|
}
|
||||||
|
|
||||||
public function ClearModifiedFlag()
|
public function ClearModifiedFlag()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ class ormDocument
|
|||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
|
if($this->IsEmpty()) return '';
|
||||||
|
|
||||||
return MyHelpers::beautifulstr($this->m_data, 100, true);
|
return MyHelpers::beautifulstr($this->m_data, 100, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
* Object from the original set, minus the removed objects
|
* Object from the original set, minus the removed objects
|
||||||
* @var DBObject[] array of iObjectId => DBObject
|
* @var DBObject[] array of iObjectId => DBObject
|
||||||
*/
|
*/
|
||||||
protected $aPreserved;
|
protected $aPreserved = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var DBObject[] New items
|
* @var DBObject[] New items
|
||||||
@@ -74,6 +74,14 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
*/
|
*/
|
||||||
protected $iCursor = 0;
|
protected $iCursor = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __toString magical function overload.
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ormLinkSet constructor.
|
* ormLinkSet constructor.
|
||||||
* @param $sHostClass
|
* @param $sHostClass
|
||||||
@@ -123,19 +131,18 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
{
|
{
|
||||||
assert($oLink instanceof $this->sClass);
|
assert($oLink instanceof $this->sClass);
|
||||||
// No impact on the iteration algorithm
|
// No impact on the iteration algorithm
|
||||||
$this->aAdded[] = $oLink;
|
$iObjectId = $oLink->GetKey();
|
||||||
|
$this->aAdded[$iObjectId] = $oLink;
|
||||||
$this->bHasDelta = true;
|
$this->bHasDelta = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param DBObject $oObject
|
* @param DBObject $oObject
|
||||||
* @param string $sClassAlias
|
* @param string $sClassAlias
|
||||||
* @deprecated
|
* @deprecated Since iTop 2.4, use ormLinkset->AddItem() instead.
|
||||||
*/
|
*/
|
||||||
public function AddObject(DBObject $oObject, $sClassAlias = '')
|
public function AddObject(DBObject $oObject, $sClassAlias = '')
|
||||||
{
|
{
|
||||||
trigger_error('iTop: ormLinkSet::AddObject() is deprecated use ormLinkSet::AddItem() instead.', E_USER_DEPRECATED);
|
|
||||||
|
|
||||||
$this->AddItem($oObject);
|
$this->AddItem($oObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +157,13 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
$this->aRemoved[$iObjectId] = $iObjectId;
|
$this->aRemoved[$iObjectId] = $iObjectId;
|
||||||
$this->bHasDelta = true;
|
$this->bHasDelta = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (array_key_exists($iObjectId, $this->aAdded))
|
||||||
|
{
|
||||||
|
unset($this->aAdded[$iObjectId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,9 +172,14 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
public function ModifyItem(DBObject $oLink)
|
public function ModifyItem(DBObject $oLink)
|
||||||
{
|
{
|
||||||
assert($oLink instanceof $this->sClass);
|
assert($oLink instanceof $this->sClass);
|
||||||
|
|
||||||
$iObjectId = $oLink->GetKey();
|
$iObjectId = $oLink->GetKey();
|
||||||
$this->aModified[$iObjectId] = $oLink;
|
if (array_key_exists($iObjectId, $this->aPreserved))
|
||||||
$this->bHasDelta = true;
|
{
|
||||||
|
unset($this->aPreserved[$iObjectId]);
|
||||||
|
$this->aModified[$iObjectId] = $oLink;
|
||||||
|
$this->bHasDelta = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function LoadOriginalIds()
|
protected function LoadOriginalIds()
|
||||||
@@ -169,15 +188,22 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
{
|
{
|
||||||
if ($this->oOriginalSet)
|
if ($this->oOriginalSet)
|
||||||
{
|
{
|
||||||
$this->aOriginalObjects = $this->oOriginalSet->ToArray();
|
$this->aOriginalObjects = $this->GetArrayOfIndex();
|
||||||
$this->aPreserved = $this->aOriginalObjects; // Copy (not effective until aPreserved gets modified)
|
$this->aPreserved = $this->aOriginalObjects; // Copy (not effective until aPreserved gets modified)
|
||||||
foreach ($this->aRemoved as $iObjectId)
|
foreach ($this->aRemoved as $iObjectId)
|
||||||
{
|
{
|
||||||
if (array_key_exists($iObjectId, $this->aPreserved))
|
if (array_key_exists($iObjectId, $this->aPreserved))
|
||||||
{
|
{
|
||||||
unset($this->aPreserved[$iObjectId]);
|
unset($this->aPreserved[$iObjectId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
foreach ($this->aModified as $iObjectId => $oLink)
|
||||||
|
{
|
||||||
|
if (array_key_exists($iObjectId, $this->aPreserved))
|
||||||
|
{
|
||||||
|
unset($this->aPreserved[$iObjectId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -189,17 +215,29 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: After calling this method, the set cursor will be at the end of the set. You might want to rewind it.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function GetArrayOfIndex()
|
||||||
|
{
|
||||||
|
$aRet = array();
|
||||||
|
$this->oOriginalSet->Rewind();
|
||||||
|
$iRow = 0;
|
||||||
|
while ($oObject = $this->oOriginalSet->Fetch())
|
||||||
|
{
|
||||||
|
$aRet[$oObject->GetKey()] = $iRow++;
|
||||||
|
}
|
||||||
|
return $aRet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: After calling this method, the set cursor will be at the end of the set. You might to rewind it.
|
|
||||||
*
|
|
||||||
* @param bool $bWithId
|
* @param bool $bWithId
|
||||||
* @return array
|
* @return array
|
||||||
* @deprecated
|
* @deprecated Since iTop 2.4, use foreach($this as $oItem){} instead
|
||||||
*/
|
*/
|
||||||
public function ToArray($bWithId = true)
|
public function ToArray($bWithId = true)
|
||||||
{
|
{
|
||||||
trigger_error('iTop: ormLinkSet::ToArray() is deprecated use foreach instead.', E_USER_DEPRECATED);
|
|
||||||
|
|
||||||
$aRet = array();
|
$aRet = array();
|
||||||
foreach($this as $oItem)
|
foreach($this as $oItem)
|
||||||
{
|
{
|
||||||
@@ -215,6 +253,28 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
return $aRet;
|
return $aRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sAttCode
|
||||||
|
* @param bool $bWithId
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function GetColumnAsArray($sAttCode, $bWithId = true)
|
||||||
|
{
|
||||||
|
$aRet = array();
|
||||||
|
foreach($this as $oItem)
|
||||||
|
{
|
||||||
|
if ($bWithId)
|
||||||
|
{
|
||||||
|
$aRet[$oItem->GetKey()] = $oItem->Get($sAttCode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aRet[] = $oItem->Get($sAttCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aRet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class of the objects of the collection (at least a common ancestor)
|
* The class of the objects of the collection (at least a common ancestor)
|
||||||
*
|
*
|
||||||
@@ -233,7 +293,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
public function Count()
|
public function Count()
|
||||||
{
|
{
|
||||||
$this->LoadOriginalIds();
|
$this->LoadOriginalIds();
|
||||||
$iRet = count($this->aPreserved) + count($this->aAdded);
|
$iRet = count($this->aPreserved) + count($this->aAdded) + count($this->aModified);
|
||||||
return $iRet;
|
return $iRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,11 +350,21 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
$iPreservedCount = count($this->aPreserved);
|
$iPreservedCount = count($this->aPreserved);
|
||||||
if ($this->iCursor < $iPreservedCount)
|
if ($this->iCursor < $iPreservedCount)
|
||||||
{
|
{
|
||||||
$oRet = current($this->aPreserved);
|
$iRet = current($this->aPreserved);
|
||||||
|
$this->oOriginalSet->Seek($iRet);
|
||||||
|
$oRet = $this->oOriginalSet->Fetch();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oRet = current($this->aAdded);
|
$iModifiedCount = count($this->aModified);
|
||||||
|
if($this->iCursor < $iPreservedCount + $iModifiedCount)
|
||||||
|
{
|
||||||
|
$oRet = current($this->aModified);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oRet = current($this->aAdded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $oRet;
|
return $oRet;
|
||||||
}
|
}
|
||||||
@@ -315,9 +385,17 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
next($this->aAdded);
|
$iModifiedCount = count($this->aModified);
|
||||||
|
if($this->iCursor < $iPreservedCount + $iModifiedCount)
|
||||||
|
{
|
||||||
|
next($this->aModified);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next($this->aAdded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Increment AFTER moving the internal cursors because when starting aAdded, we must leave it intact
|
// Increment AFTER moving the internal cursors because when starting aModified / aAdded, we must leave it intact
|
||||||
$this->iCursor++;
|
$this->iCursor++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,11 +431,12 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
*/
|
*/
|
||||||
public function rewind()
|
public function rewind()
|
||||||
{
|
{
|
||||||
$this->LoadOriginalIds();
|
$this->LoadOriginalIds();
|
||||||
|
|
||||||
$this->iCursor = 0;
|
$this->iCursor = 0;
|
||||||
reset($this->aPreserved);
|
reset($this->aPreserved);
|
||||||
reset($this->aAdded);
|
reset($this->aAdded);
|
||||||
|
reset($this->aModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function HasDelta()
|
public function HasDelta()
|
||||||
@@ -429,7 +508,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
$this->aAdded = array();
|
$this->aAdded = array();
|
||||||
$this->aRemoved = array();
|
$this->aRemoved = array();
|
||||||
$this->aModified = array();
|
$this->aModified = array();
|
||||||
$this->aPreserved = $this->aOriginalObjects;
|
$this->aPreserved = ($this->aOriginalObjects === null) ? array() : $this->aOriginalObjects;
|
||||||
$this->bHasDelta = false;
|
$this->bHasDelta = false;
|
||||||
|
|
||||||
/** @var AttributeLinkedSet $oAttDef */
|
/** @var AttributeLinkedSet $oAttDef */
|
||||||
@@ -504,12 +583,15 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
|
|
||||||
// Check for the existing links
|
// Check for the existing links
|
||||||
//
|
//
|
||||||
|
/** @var DBObject[] $aExistingLinks */
|
||||||
|
$aExistingLinks = array();
|
||||||
|
/** @var Int[] $aExistingRemote */
|
||||||
|
$aExistingRemote = array();
|
||||||
if (count($aCheckLinks) > 0)
|
if (count($aCheckLinks) > 0)
|
||||||
{
|
{
|
||||||
$oSearch = new DBObjectSearch($this->sClass);
|
$oSearch = new DBObjectSearch($this->sClass);
|
||||||
$oSearch->AddCondition('id', $aCheckLinks, 'IN');
|
$oSearch->AddCondition('id', $aCheckLinks, 'IN');
|
||||||
$oSet = new DBObjectSet($oSearch);
|
$oSet = new DBObjectSet($oSearch);
|
||||||
/** @var DBObject[] $aExistingLinks */
|
|
||||||
$aExistingLinks = $oSet->ToArray();
|
$aExistingLinks = $oSet->ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,8 +603,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
$oSearch->AddCondition($sExtKeyToMe, $oHostObject->GetKey(), '=');
|
$oSearch->AddCondition($sExtKeyToMe, $oHostObject->GetKey(), '=');
|
||||||
$oSearch->AddCondition($sExtKeyToRemote, $aCheckRemote, 'IN');
|
$oSearch->AddCondition($sExtKeyToRemote, $aCheckRemote, 'IN');
|
||||||
$oSet = new DBObjectSet($oSearch);
|
$oSet = new DBObjectSet($oSearch);
|
||||||
/** @var Int[] $aExistingRemote */
|
$aExistingRemote = $oSet->GetColumnAsArray($sExtKeyToRemote, true);
|
||||||
$aExistingRemote = $oSet->GetColumnAsArray($sExtKeyToRemote);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the links according to the existing links
|
// Write the links according to the existing links
|
||||||
@@ -536,11 +617,28 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
{
|
{
|
||||||
if (count($aCheckRemote) > 0)
|
if (count($aCheckRemote) > 0)
|
||||||
{
|
{
|
||||||
if (in_array($oLink->Get($sExtKeyToRemote), $aExistingRemote))
|
$bIsDuplicate = false;
|
||||||
{
|
foreach($aExistingRemote as $sLinkKey => $sExtKey)
|
||||||
// Do not create a duplicate
|
{
|
||||||
continue;
|
if ($sExtKey == $oLink->Get($sExtKeyToRemote))
|
||||||
}
|
{
|
||||||
|
// Do not create a duplicate
|
||||||
|
// + In the case of a remove action followed by an add action
|
||||||
|
// of an existing link,
|
||||||
|
// the final state to consider is add action,
|
||||||
|
// so suppress the entry in the removed list.
|
||||||
|
if (array_key_exists($sLinkKey, $this->aRemoved))
|
||||||
|
{
|
||||||
|
unset($this->aRemoved[$sLinkKey]);
|
||||||
|
}
|
||||||
|
$bIsDuplicate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($bIsDuplicate)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -598,4 +696,34 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
|||||||
//
|
//
|
||||||
$oMtx->Unlock();
|
$oMtx->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ToDBObjectSet($bShowObsolete = true)
|
||||||
|
{
|
||||||
|
$oAttDef = MetaModel::GetAttributeDef($this->sHostClass, $this->sAttCode);
|
||||||
|
$oLinkSearch = $this->GetFilter();
|
||||||
|
if ($oAttDef->IsIndirect())
|
||||||
|
{
|
||||||
|
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||||
|
$oLinkingAttDef = MetaModel::GetAttributeDef($this->sClass, $sExtKeyToRemote);
|
||||||
|
$sTargetClass = $oLinkingAttDef->GetTargetClass();
|
||||||
|
if (!$bShowObsolete && MetaModel::IsObsoletable($sTargetClass))
|
||||||
|
{
|
||||||
|
$oNotObsolete = new BinaryExpression(
|
||||||
|
new FieldExpression('obsolescence_flag', $sTargetClass),
|
||||||
|
'=',
|
||||||
|
new ScalarExpression(0)
|
||||||
|
);
|
||||||
|
$oNotObsoleteRemote = new DBObjectSearch($sTargetClass);
|
||||||
|
$oNotObsoleteRemote->AddConditionExpression($oNotObsolete);
|
||||||
|
$oLinkSearch->AddCondition_PointingTo($oNotObsoleteRemote, $sExtKeyToRemote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$oLinkSet = new DBObjectSet($oLinkSearch);
|
||||||
|
$oLinkSet->SetShowObsoleteData($bShowObsolete);
|
||||||
|
if ($this->HasDelta())
|
||||||
|
{
|
||||||
|
$oLinkSet->AddObjectArray($this->aAdded);
|
||||||
|
}
|
||||||
|
return $oLinkSet;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -226,9 +226,9 @@ EOF
|
|||||||
$iNewWidth = $iWidth * $fScale;
|
$iNewWidth = $iWidth * $fScale;
|
||||||
$iNewHeight = $iHeight * $fScale;
|
$iNewHeight = $iHeight * $fScale;
|
||||||
|
|
||||||
$sUrl = 'data:' . $value->GetMimeType() . ';base64,' . base64_encode($value->GetData());
|
$sUrl = 'data:'.$value->GetMimeType().';base64,'.base64_encode($value->GetData());
|
||||||
}
|
}
|
||||||
$sRet = '<img src="' . $sUrl . '" style="width: ' . $iNewWidth . 'px; height: ' . $iNewHeight . 'px">';
|
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="width: '.$iNewWidth.'px; height: '.$iNewHeight.'px">' : '';
|
||||||
$sRet = '<div class="view-image">'.$sRet.'</div>';
|
$sRet = '<div class="view-image">'.$sRet.'</div>';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -175,7 +175,8 @@ EOF
|
|||||||
}
|
}
|
||||||
elseif ($oAttDef instanceof AttributeCustomFields)
|
elseif ($oAttDef instanceof AttributeCustomFields)
|
||||||
{
|
{
|
||||||
$sRet = $oObj->GetAsHTML($sAttCode);
|
// Stick to the weird implementation made in GetNextChunk
|
||||||
|
$sRet = utils::TextToHtml($oObj->GetEditValue($sAttCode));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -326,6 +327,12 @@ EOF
|
|||||||
}
|
}
|
||||||
$sData .= "<td x:str>$sField</td>";
|
$sData .= "<td x:str>$sField</td>";
|
||||||
}
|
}
|
||||||
|
elseif ($oAttDef instanceof AttributeCustomFields)
|
||||||
|
{
|
||||||
|
// GetAsHTML returns a table that would not fit
|
||||||
|
$sField = utils::TextToHtml($oObj->GetEditValue($sAttCode));
|
||||||
|
$sData .= "<td x:str>$sField</td>";
|
||||||
|
}
|
||||||
else if($oAttDef instanceof AttributeString)
|
else if($oAttDef instanceof AttributeString)
|
||||||
{
|
{
|
||||||
$sField = $oObj->GetAsHTML($sAttCode, $this->bLocalizeOutput);
|
$sField = $oObj->GetAsHTML($sAttCode, $this->bLocalizeOutput);
|
||||||
|
|||||||
@@ -36,7 +36,8 @@
|
|||||||
|
|
||||||
class SQLObjectQuery extends SQLQuery
|
class SQLObjectQuery extends SQLQuery
|
||||||
{
|
{
|
||||||
private $m_SourceOQL = '';
|
public $m_aContextData = null;
|
||||||
|
public $m_iOriginalTableCount = 0;
|
||||||
private $m_sTable = '';
|
private $m_sTable = '';
|
||||||
private $m_sTableAlias = '';
|
private $m_sTableAlias = '';
|
||||||
private $m_aFields = array();
|
private $m_aFields = array();
|
||||||
@@ -46,7 +47,7 @@ class SQLObjectQuery extends SQLQuery
|
|||||||
private $m_aValues = array(); // Values to set in case of an update query
|
private $m_aValues = array(); // Values to set in case of an update query
|
||||||
private $m_oSelectedIdField = null;
|
private $m_oSelectedIdField = null;
|
||||||
private $m_aJoinSelects = array();
|
private $m_aJoinSelects = array();
|
||||||
private $m_bBeautifulQuery = false;
|
protected $m_bBeautifulQuery = false;
|
||||||
|
|
||||||
// Data set by PrepareRendering()
|
// Data set by PrepareRendering()
|
||||||
private $__aFrom;
|
private $__aFrom;
|
||||||
@@ -311,6 +312,14 @@ class SQLObjectQuery extends SQLQuery
|
|||||||
$this->PrepareRendering();
|
$this->PrepareRendering();
|
||||||
$sFrom = self::ClauseFrom($this->__aFrom, $sIndent);
|
$sFrom = self::ClauseFrom($this->__aFrom, $sIndent);
|
||||||
$sWhere = self::ClauseWhere($this->m_oConditionExpr, $aArgs);
|
$sWhere = self::ClauseWhere($this->m_oConditionExpr, $aArgs);
|
||||||
|
if ($iLimitCount > 0)
|
||||||
|
{
|
||||||
|
$sLimit = 'LIMIT '.$iLimitStart.', '.$iLimitCount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sLimit = '';
|
||||||
|
}
|
||||||
if ($bGetCount)
|
if ($bGetCount)
|
||||||
{
|
{
|
||||||
if (count($this->__aSelectedIdFields) > 0)
|
if (count($this->__aSelectedIdFields) > 0)
|
||||||
@@ -321,11 +330,13 @@ class SQLObjectQuery extends SQLQuery
|
|||||||
$aCountFields[] = "COALESCE($sFieldExpr, 0)"; // Null values are excluded from the count
|
$aCountFields[] = "COALESCE($sFieldExpr, 0)"; // Null values are excluded from the count
|
||||||
}
|
}
|
||||||
$sCountFields = implode(', ', $aCountFields);
|
$sCountFields = implode(', ', $aCountFields);
|
||||||
$sSQL = "SELECT$sLineSep COUNT(DISTINCT $sCountFields) AS COUNT$sLineSep FROM $sFrom$sLineSep WHERE $sWhere";
|
// Count can be limited for performance reason, in this case the total amount is not important,
|
||||||
|
// we only need to know if the number of entries is greater than a certain amount.
|
||||||
|
$sSQL = "SELECT COUNT(*) AS COUNT FROM (SELECT$sLineSep DISTINCT $sCountFields $sLineSep FROM $sFrom$sLineSep WHERE $sWhere $sLimit) AS _tatooine_";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$sSQL = "SELECT$sLineSep COUNT(*) AS COUNT$sLineSep FROM $sFrom$sLineSep WHERE $sWhere";
|
$sSQL = "SELECT COUNT(*) AS COUNT FROM (SELECT$sLineSep 1 $sLineSep FROM $sFrom$sLineSep WHERE $sWhere $sLimit) AS _tatooine_";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -336,14 +347,7 @@ class SQLObjectQuery extends SQLQuery
|
|||||||
{
|
{
|
||||||
$sOrderBy = "ORDER BY $sOrderBy$sLineSep";
|
$sOrderBy = "ORDER BY $sOrderBy$sLineSep";
|
||||||
}
|
}
|
||||||
if ($iLimitCount > 0)
|
|
||||||
{
|
|
||||||
$sLimit = 'LIMIT '.$iLimitStart.', '.$iLimitCount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$sLimit = '';
|
|
||||||
}
|
|
||||||
$sSQL = "SELECT$sLineSep DISTINCT $sSelect$sLineSep FROM $sFrom$sLineSep WHERE $sWhere$sLineSep $sOrderBy $sLimit";
|
$sSQL = "SELECT$sLineSep DISTINCT $sSelect$sLineSep FROM $sFrom$sLineSep WHERE $sWhere$sLineSep $sOrderBy $sLimit";
|
||||||
}
|
}
|
||||||
return $sSQL;
|
return $sSQL;
|
||||||
@@ -510,6 +514,7 @@ class SQLObjectQuery extends SQLQuery
|
|||||||
|
|
||||||
public function OptimizeJoins($aUsedTables, $bTopCall = true)
|
public function OptimizeJoins($aUsedTables, $bTopCall = true)
|
||||||
{
|
{
|
||||||
|
$this->m_iOriginalTableCount = $this->CountTables();
|
||||||
if ($bTopCall)
|
if ($bTopCall)
|
||||||
{
|
{
|
||||||
// Top call: complete the list of tables absolutely required to perform the right query
|
// Top call: complete the list of tables absolutely required to perform the right query
|
||||||
@@ -545,7 +550,7 @@ class SQLObjectQuery extends SQLQuery
|
|||||||
return $iRet;
|
return $iRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function CollectUsedTables(&$aTables)
|
public function CollectUsedTables(&$aTables)
|
||||||
{
|
{
|
||||||
$this->m_oConditionExpr->CollectUsedParents($aTables);
|
$this->m_oConditionExpr->CollectUsedParents($aTables);
|
||||||
foreach($this->m_aFields as $sFieldAlias => $oField)
|
foreach($this->m_aFields as $sFieldAlias => $oField)
|
||||||
@@ -612,4 +617,5 @@ class SQLObjectQuery extends SQLQuery
|
|||||||
// None of the tables is in the list of required tables
|
// None of the tables is in the list of required tables
|
||||||
return $bResult;
|
return $bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ require_once('cmdbsource.class.inc.php');
|
|||||||
abstract class SQLQuery
|
abstract class SQLQuery
|
||||||
{
|
{
|
||||||
private $m_SourceOQL = '';
|
private $m_SourceOQL = '';
|
||||||
private $m_bBeautifulQuery = false;
|
protected $m_bBeautifulQuery = false;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class SQLUnionQuery extends SQLQuery
|
|||||||
{
|
{
|
||||||
$aQueriesHtml[] = '<p>'.$oSQLQuery->DisplayHtml().'</p>';
|
$aQueriesHtml[] = '<p>'.$oSQLQuery->DisplayHtml().'</p>';
|
||||||
}
|
}
|
||||||
echo implode('UNION', $aQueries);
|
echo implode('UNION', $aQueriesHtml);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function AddInnerJoin($oSQLQuery, $sLeftField, $sRightField, $sRightTable = '')
|
public function AddInnerJoin($oSQLQuery, $sLeftField, $sRightField, $sRightTable = '')
|
||||||
@@ -85,7 +85,6 @@ class SQLUnionQuery extends SQLQuery
|
|||||||
{
|
{
|
||||||
$this->m_bBeautifulQuery = $bBeautifulQuery;
|
$this->m_bBeautifulQuery = $bBeautifulQuery;
|
||||||
$sLineSep = $this->m_bBeautifulQuery ? "\n" : '';
|
$sLineSep = $this->m_bBeautifulQuery ? "\n" : '';
|
||||||
$sIndent = $this->m_bBeautifulQuery ? " " : null;
|
|
||||||
|
|
||||||
$aSelects = array();
|
$aSelects = array();
|
||||||
foreach ($this->aQueries as $oSQLQuery)
|
foreach ($this->aQueries as $oSQLQuery)
|
||||||
@@ -93,36 +92,33 @@ class SQLUnionQuery extends SQLQuery
|
|||||||
// Render SELECTS without orderby/limit/count
|
// Render SELECTS without orderby/limit/count
|
||||||
$aSelects[] = $oSQLQuery->RenderSelect(array(), $aArgs, 0, 0, false, $bBeautifulQuery);
|
$aSelects[] = $oSQLQuery->RenderSelect(array(), $aArgs, 0, 0, false, $bBeautifulQuery);
|
||||||
}
|
}
|
||||||
$sSelects = '('.implode(")$sLineSep UNION$sLineSep(", $aSelects).')';
|
if ($iLimitCount > 0)
|
||||||
|
|
||||||
if ($bGetCount)
|
|
||||||
{
|
{
|
||||||
$sFrom = "($sLineSep$sSelects$sLineSep) as __selects__";
|
$sLimit = 'LIMIT '.$iLimitStart.', '.$iLimitCount;
|
||||||
$sSQL = "SELECT$sLineSep COUNT(*) AS COUNT$sLineSep FROM $sFrom$sLineSep";
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sLimit = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($bGetCount)
|
||||||
|
{
|
||||||
|
$sSelects = '('.implode(" $sLimit)$sLineSep UNION$sLineSep(", $aSelects)." $sLimit)";
|
||||||
|
$sFrom = "($sLineSep$sSelects$sLineSep) as __selects__";
|
||||||
|
$sSQL = "SELECT COUNT(*) AS COUNT FROM (SELECT$sLineSep 1 $sLineSep FROM $sFrom$sLineSep) AS _union_tatooine_";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$aSelects = array();
|
|
||||||
foreach ($this->aQueries as $oSQLQuery)
|
|
||||||
{
|
|
||||||
// Render SELECT without orderby/limit/count
|
|
||||||
$aSelects[] = $oSQLQuery->RenderSelect(array(), $aArgs, 0, 0, false, $bBeautifulQuery);
|
|
||||||
}
|
|
||||||
$sSelect = $this->aQueries[0]->RenderSelectClause();
|
|
||||||
$sOrderBy = $this->aQueries[0]->RenderOrderByClause($aOrderBy);
|
$sOrderBy = $this->aQueries[0]->RenderOrderByClause($aOrderBy);
|
||||||
if (!empty($sOrderBy))
|
if (!empty($sOrderBy))
|
||||||
{
|
{
|
||||||
$sOrderBy = "ORDER BY $sOrderBy$sLineSep";
|
$sOrderBy = "ORDER BY $sOrderBy$sLineSep $sLimit";
|
||||||
}
|
$sSQL = '('.implode(")$sLineSep UNION$sLineSep (", $aSelects).')'.$sLineSep.$sOrderBy;
|
||||||
if ($iLimitCount > 0)
|
|
||||||
{
|
|
||||||
$sLimit = 'LIMIT '.$iLimitStart.', '.$iLimitCount;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$sLimit = '';
|
$sSQL = '('.implode(" $sLimit)$sLineSep UNION$sLineSep (", $aSelects)." $sLimit)";
|
||||||
}
|
}
|
||||||
$sSQL = $sSelects.$sLineSep.$sOrderBy.' '.$sLimit;
|
|
||||||
}
|
}
|
||||||
return $sSQL;
|
return $sSQL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,6 +338,8 @@ abstract class User extends cmdbAbstractObject
|
|||||||
'bulkread' => $this->GetGrantAsHtml($sClass, UR_ACTION_BULK_READ),
|
'bulkread' => $this->GetGrantAsHtml($sClass, UR_ACTION_BULK_READ),
|
||||||
'write' => $this->GetGrantAsHtml($sClass, UR_ACTION_MODIFY),
|
'write' => $this->GetGrantAsHtml($sClass, UR_ACTION_MODIFY),
|
||||||
'bulkwrite' => $this->GetGrantAsHtml($sClass, UR_ACTION_BULK_MODIFY),
|
'bulkwrite' => $this->GetGrantAsHtml($sClass, UR_ACTION_BULK_MODIFY),
|
||||||
|
'delete' => $this->GetGrantAsHtml($sClass, UR_ACTION_DELETE),
|
||||||
|
'bulkdelete' => $this->GetGrantAsHtml($sClass, UR_ACTION_BULK_DELETE),
|
||||||
'stimuli' => $sStimuli,
|
'stimuli' => $sStimuli,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -350,6 +352,8 @@ abstract class User extends cmdbAbstractObject
|
|||||||
$aDisplayConfig['bulkread'] = array('label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+'));
|
$aDisplayConfig['bulkread'] = array('label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+'));
|
||||||
$aDisplayConfig['write'] = array('label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+'));
|
$aDisplayConfig['write'] = array('label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+'));
|
||||||
$aDisplayConfig['bulkwrite'] = array('label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+'));
|
$aDisplayConfig['bulkwrite'] = array('label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+'));
|
||||||
|
$aDisplayConfig['delete'] = array('label' => Dict::S('UI:UserManagement:Action:Delete'), 'description' => Dict::S('UI:UserManagement:Action:Delete+'));
|
||||||
|
$aDisplayConfig['bulkdelete'] = array('label' => Dict::S('UI:UserManagement:Action:BulkDelete'), 'description' => Dict::S('UI:UserManagement:Action:BulkDelete+'));
|
||||||
$aDisplayConfig['stimuli'] = array('label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+'));
|
$aDisplayConfig['stimuli'] = array('label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+'));
|
||||||
$oPage->table($aDisplayConfig, $aDisplayData);
|
$oPage->table($aDisplayConfig, $aDisplayData);
|
||||||
}
|
}
|
||||||
@@ -1153,7 +1157,7 @@ class UserRights
|
|||||||
self::$m_aAdmins = array();
|
self::$m_aAdmins = array();
|
||||||
self::$m_aPortalUsers = array();
|
self::$m_aPortalUsers = array();
|
||||||
}
|
}
|
||||||
if (!isset($_SESSION))
|
if (!isset($_SESSION) && !utils::IsModeCLI())
|
||||||
{
|
{
|
||||||
session_name('itop-'.md5(APPROOT));
|
session_name('itop-'.md5(APPROOT));
|
||||||
session_start();
|
session_start();
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ abstract class ValueSetDefinition
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function GetValues($aArgs, $sContains = '')
|
public function GetValues($aArgs, $sContains = '', $sOperation = 'contains')
|
||||||
{
|
{
|
||||||
if (!$this->m_bIsLoaded)
|
if (!$this->m_bIsLoaded)
|
||||||
{
|
{
|
||||||
@@ -93,12 +93,16 @@ abstract class ValueSetDefinition
|
|||||||
class ValueSetObjects extends ValueSetDefinition
|
class ValueSetObjects extends ValueSetDefinition
|
||||||
{
|
{
|
||||||
protected $m_sContains;
|
protected $m_sContains;
|
||||||
|
protected $m_sOperation;
|
||||||
protected $m_sFilterExpr; // in OQL
|
protected $m_sFilterExpr; // in OQL
|
||||||
protected $m_sValueAttCode;
|
protected $m_sValueAttCode;
|
||||||
protected $m_aOrderBy;
|
protected $m_aOrderBy;
|
||||||
protected $m_aExtraConditions;
|
protected $m_aExtraConditions;
|
||||||
private $m_bAllowAllData;
|
private $m_bAllowAllData;
|
||||||
private $m_aModifierProperties;
|
private $m_aModifierProperties;
|
||||||
|
private $m_bSort;
|
||||||
|
private $m_iLimit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
|
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
|
||||||
@@ -106,12 +110,15 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array(), $bAllowAllData = false, $aModifierProperties = array())
|
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array(), $bAllowAllData = false, $aModifierProperties = array())
|
||||||
{
|
{
|
||||||
$this->m_sContains = '';
|
$this->m_sContains = '';
|
||||||
|
$this->m_sOperation = '';
|
||||||
$this->m_sFilterExpr = $sFilterExp;
|
$this->m_sFilterExpr = $sFilterExp;
|
||||||
$this->m_sValueAttCode = $sValueAttCode;
|
$this->m_sValueAttCode = $sValueAttCode;
|
||||||
$this->m_aOrderBy = $aOrderBy;
|
$this->m_aOrderBy = $aOrderBy;
|
||||||
$this->m_bAllowAllData = $bAllowAllData;
|
$this->m_bAllowAllData = $bAllowAllData;
|
||||||
$this->m_aModifierProperties = $aModifierProperties;
|
$this->m_aModifierProperties = $aModifierProperties;
|
||||||
$this->m_aExtraConditions = array();
|
$this->m_aExtraConditions = array();
|
||||||
|
$this->m_bSort = true;
|
||||||
|
$this->m_iLimit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetModifierProperty($sPluginClass, $sProperty, $value)
|
public function SetModifierProperty($sPluginClass, $sProperty, $value)
|
||||||
@@ -163,11 +170,11 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
return new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs);
|
return new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetValues($aArgs, $sContains = '')
|
public function GetValues($aArgs, $sContains = '', $sOperation = 'contains')
|
||||||
{
|
{
|
||||||
if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains))
|
if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains) || ($sOperation != $this->m_sOperation))
|
||||||
{
|
{
|
||||||
$this->LoadValues($aArgs, $sContains);
|
$this->LoadValues($aArgs, $sContains, $sOperation);
|
||||||
$this->m_bIsLoaded = true;
|
$this->m_bIsLoaded = true;
|
||||||
}
|
}
|
||||||
// The results are already filtered and sorted (on friendly name)
|
// The results are already filtered and sorted (on friendly name)
|
||||||
@@ -175,9 +182,10 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
return $aRet;
|
return $aRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function LoadValues($aArgs, $sContains = '')
|
protected function LoadValues($aArgs, $sContains = '', $sOperation = 'contains')
|
||||||
{
|
{
|
||||||
$this->m_sContains = $sContains;
|
$this->m_sContains = $sContains;
|
||||||
|
$this->m_sOperation = $sOperation;
|
||||||
|
|
||||||
$this->m_aValues = array();
|
$this->m_aValues = array();
|
||||||
|
|
||||||
@@ -202,12 +210,67 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$oValueExpr = new ScalarExpression('%'.$sContains.'%');
|
$oExpression = DBObjectSearch::GetPolymorphicExpression($oFilter->GetClass(), 'friendlyname');
|
||||||
$oNameExpr = new FieldExpression('friendlyname', $oFilter->GetClassAlias());
|
$aFields = $oExpression->ListRequiredFields();
|
||||||
$oNewCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
$sClass = $oFilter->GetClass();
|
||||||
$oFilter->AddConditionExpression($oNewCondition);
|
foreach($aFields as $sField)
|
||||||
|
{
|
||||||
|
$aFieldItems = explode('.', $sField);
|
||||||
|
if ($aFieldItems[0] != $sClass)
|
||||||
|
{
|
||||||
|
$sOperation = 'contains';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs);
|
switch ($sOperation)
|
||||||
|
{
|
||||||
|
case 'equals_start_with':
|
||||||
|
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($oFilter->GetClass());
|
||||||
|
$sClassAlias = $oFilter->GetClassAlias();
|
||||||
|
$aFilters = array();
|
||||||
|
// Equals first
|
||||||
|
$oValueExpr = new ScalarExpression($sContains);
|
||||||
|
foreach($aAttributes as $sAttribute)
|
||||||
|
{
|
||||||
|
$oNewFilter = $oFilter->DeepClone();
|
||||||
|
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||||
|
$oCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||||
|
$oNewFilter->AddConditionExpression($oCondition);
|
||||||
|
$aFilters[] = $oNewFilter;
|
||||||
|
}
|
||||||
|
// start with next
|
||||||
|
$oValueExpr = new ScalarExpression($sContains.'%');
|
||||||
|
foreach($aAttributes as $sAttribute)
|
||||||
|
{
|
||||||
|
$oNewFilter = $oFilter->DeepClone();
|
||||||
|
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
|
||||||
|
$oCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||||
|
$oNewFilter->AddConditionExpression($oCondition);
|
||||||
|
$aFilters[] = $oNewFilter;
|
||||||
|
}
|
||||||
|
// Unions are much faster than OR conditions
|
||||||
|
$oFilter = new DBUnionSearch($aFilters);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$oValueExpr = new ScalarExpression('%'.$sContains.'%');
|
||||||
|
$oNameExpr = new FieldExpression('friendlyname', $oFilter->GetClassAlias());
|
||||||
|
$oNewCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
|
||||||
|
$oFilter->AddConditionExpression($oNewCondition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs, null, $this->m_iLimit, 0, $this->m_bSort);
|
||||||
|
if (empty($this->m_sValueAttCode))
|
||||||
|
{
|
||||||
|
$aAttToLoad = array($oFilter->GetClassAlias() => array('friendlyname'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aAttToLoad = array($oFilter->GetClassAlias() => array($this->m_sValueAttCode));
|
||||||
|
}
|
||||||
|
$oObjects->OptimizeColumnLoad($aAttToLoad);
|
||||||
while ($oObject = $oObjects->Fetch())
|
while ($oObject = $oObjects->Fetch())
|
||||||
{
|
{
|
||||||
if (empty($this->m_sValueAttCode))
|
if (empty($this->m_sValueAttCode))
|
||||||
@@ -231,6 +294,22 @@ class ValueSetObjects extends ValueSetDefinition
|
|||||||
{
|
{
|
||||||
return $this->m_sFilterExpr;
|
return $this->m_sFilterExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $iLimit
|
||||||
|
*/
|
||||||
|
public function SetLimit($iLimit)
|
||||||
|
{
|
||||||
|
$this->m_iLimit = $iLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $bSort
|
||||||
|
*/
|
||||||
|
public function SetSort($bSort)
|
||||||
|
{
|
||||||
|
$this->m_bSort = $bSort;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ $complement-light: #d6e8ef;
|
|||||||
$frame-background-color: #F1F1F1;
|
$frame-background-color: #F1F1F1;
|
||||||
$text-color: #000;
|
$text-color: #000;
|
||||||
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
|
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
|
||||||
$version: "v2.4.0-beta";
|
$version: "v2.4.0";
|
||||||
BIN
css/font-combodo/combodo-webfont.ttf
Normal file
BIN
css/font-combodo/combodo-webfont.ttf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -21,7 +21,7 @@ OS2Version: 0
|
|||||||
OS2_WeightWidthSlopeOnly: 0
|
OS2_WeightWidthSlopeOnly: 0
|
||||||
OS2_UseTypoMetrics: 1
|
OS2_UseTypoMetrics: 1
|
||||||
CreationTime: 1463745065
|
CreationTime: 1463745065
|
||||||
ModificationTime: 1464178421
|
ModificationTime: 1506001058
|
||||||
OS2TypoAscent: 0
|
OS2TypoAscent: 0
|
||||||
OS2TypoAOffset: 1
|
OS2TypoAOffset: 1
|
||||||
OS2TypoDescent: 0
|
OS2TypoDescent: 0
|
||||||
@@ -35,7 +35,6 @@ HheadAscent: 0
|
|||||||
HheadAOffset: 1
|
HheadAOffset: 1
|
||||||
HheadDescent: 0
|
HheadDescent: 0
|
||||||
HheadDOffset: 1
|
HheadDOffset: 1
|
||||||
OS2Vendor: 'PfEd'
|
|
||||||
MarkAttachClasses: 1
|
MarkAttachClasses: 1
|
||||||
DEI: 91125
|
DEI: 91125
|
||||||
Encoding: ISO8859-1
|
Encoding: ISO8859-1
|
||||||
@@ -47,7 +46,7 @@ FitToEm: 0
|
|||||||
WinInfo: 0 31 10
|
WinInfo: 0 31 10
|
||||||
BeginPrivate: 0
|
BeginPrivate: 0
|
||||||
EndPrivate
|
EndPrivate
|
||||||
BeginChars: 256 8
|
BeginChars: 256 11
|
||||||
|
|
||||||
StartChar: zero
|
StartChar: zero
|
||||||
Encoding: 48 48 0
|
Encoding: 48 48 0
|
||||||
@@ -210,7 +209,7 @@ StartChar: three
|
|||||||
Encoding: 51 51 3
|
Encoding: 51 51 3
|
||||||
Width: 1022
|
Width: 1022
|
||||||
VWidth: 0
|
VWidth: 0
|
||||||
Flags: MO
|
Flags: M
|
||||||
LayerCount: 3
|
LayerCount: 3
|
||||||
Fore
|
Fore
|
||||||
SplineSet
|
SplineSet
|
||||||
@@ -261,11 +260,13 @@ StartChar: C
|
|||||||
Encoding: 67 67 4
|
Encoding: 67 67 4
|
||||||
Width: 1080
|
Width: 1080
|
||||||
VWidth: 0
|
VWidth: 0
|
||||||
Flags: HW
|
Flags: W
|
||||||
|
HStem: -112 36<398.67 444.211> 97 36<463.993 575.071> 116 37<411.524 459.906> 250 37<334.123 402.464> 335 37<749.246 821.773> 387 37<836.543 929.295> 396 37<873.093 933.545> 442 37<475 482 739.647 795.664> 621 37<286.042 389.13> 650 37<510.192 579.789>
|
||||||
|
VStem: 53 37<216.048 298> 218 37<457.867 579.651> 272 36<60.6299 128.446> 439 37<479.452 577.67> 451 37<-73.2171 5.85426> 472 37<568.829 649.107> 553 37<359.872 417.574> 651 38<-34.3438 62.6665> 718 38<8.82031 164.606> 934 38<341.569 396>
|
||||||
LayerCount: 3
|
LayerCount: 3
|
||||||
Fore
|
Fore
|
||||||
SplineSet
|
SplineSet
|
||||||
641 -116 m 4x9b20
|
641 -116 m 4x9b39f0
|
||||||
637 -116 633 -115 630 -113 c 4
|
637 -116 633 -115 630 -113 c 4
|
||||||
624 -110 616 -102 616 -88 c 4
|
624 -110 616 -102 616 -88 c 4
|
||||||
616 -84 617 -80 618 -75 c 4
|
616 -84 617 -80 618 -75 c 4
|
||||||
@@ -275,14 +276,14 @@ SplineSet
|
|||||||
651 31 641 52 624 75 c 4
|
651 31 641 52 624 75 c 4
|
||||||
609 94 595 108 586 115 c 5
|
609 94 595 108 586 115 c 5
|
||||||
562 107 523 97 500 97 c 6
|
562 107 523 97 500 97 c 6
|
||||||
499 97 l 6xdb20
|
499 97 l 6xdb39f0
|
||||||
479 97 468 105 460 111 c 4
|
479 97 468 105 460 111 c 4
|
||||||
457 114 455 115 453 116 c 4
|
457 114 455 115 453 116 c 4
|
||||||
450 116 438 112 423 104 c 4
|
450 116 438 112 423 104 c 4
|
||||||
412 98 405 94 401 90 c 5
|
412 98 405 94 401 90 c 5
|
||||||
411 80 436 61 448 52 c 4
|
411 80 436 61 448 52 c 4
|
||||||
460 43 468 37 473 32 c 4
|
460 43 468 37 473 32 c 4
|
||||||
485 20 488 -4 488 -20 c 4
|
485 20 488 -4 488 -20 c 4xb93af0
|
||||||
488 -27 487 -33 487 -36 c 4
|
488 -27 487 -33 487 -36 c 4
|
||||||
485 -55 477 -90 452 -105 c 4
|
485 -55 477 -90 452 -105 c 4
|
||||||
444 -110 435 -112 426 -112 c 4
|
444 -110 435 -112 426 -112 c 4
|
||||||
@@ -321,10 +322,10 @@ SplineSet
|
|||||||
219 484 218 493 218 504 c 4
|
219 484 218 493 218 504 c 4
|
||||||
218 526 222 550 231 575 c 4
|
218 526 222 550 231 575 c 4
|
||||||
237 593 255 636 284 651 c 4
|
237 593 255 636 284 651 c 4
|
||||||
293 656 305 658 320 658 c 4xb9a0
|
293 656 305 658 320 658 c 4
|
||||||
342 658 367 653 389 644 c 4
|
342 658 367 653 389 644 c 4
|
||||||
416 633 437 617 452 597 c 4
|
416 633 437 617 452 597 c 4
|
||||||
472 571 476 537 476 508 c 4
|
472 571 476 537 476 508 c 4xb9bcf0
|
||||||
476 497 476 487 475 479 c 5
|
476 497 476 487 475 479 c 5
|
||||||
482 479 l 5
|
482 479 l 5
|
||||||
505 499 l 5
|
505 499 l 5
|
||||||
@@ -352,7 +353,7 @@ SplineSet
|
|||||||
766 473 767 473 768 473 c 4
|
766 473 767 473 768 473 c 4
|
||||||
787 473 808 460 831 446 c 4
|
787 473 808 460 831 446 c 4
|
||||||
845 437 865 424 873 424 c 4
|
845 437 865 424 873 424 c 4
|
||||||
874 424 l 6x9d60
|
874 424 l 6x9d79f0
|
||||||
875 424 880 425 884 426 c 4
|
875 424 880 425 884 426 c 4
|
||||||
897 429 915 433 930 433 c 4
|
897 429 915 433 930 433 c 4
|
||||||
956 433 965 421 969 412 c 4
|
956 433 965 421 969 412 c 4
|
||||||
@@ -362,7 +363,7 @@ SplineSet
|
|||||||
916 289 911 288 905 288 c 4
|
916 289 911 288 905 288 c 4
|
||||||
888 288 863 299 835 311 c 4
|
888 288 863 299 835 311 c 4
|
||||||
810 322 780 335 766 335 c 4
|
810 322 780 335 766 335 c 4
|
||||||
765 335 764 335 764 335 c 4
|
764 335 l 4
|
||||||
763 335 757 331 748 315 c 4
|
763 335 757 331 748 315 c 4
|
||||||
741 301 734 283 727 264 c 4
|
741 301 734 283 727 264 c 4
|
||||||
721 248 715 231 708 216 c 5
|
721 248 715 231 708 216 c 5
|
||||||
@@ -370,7 +371,7 @@ SplineSet
|
|||||||
756 69 755 58 753 47 c 4
|
756 69 755 58 753 47 c 4
|
||||||
748 19 727 -22 708 -51 c 4
|
748 19 727 -22 708 -51 c 4
|
||||||
697 -68 687 -82 677 -93 c 4
|
697 -68 687 -82 677 -93 c 4
|
||||||
663 -109 652 -116 641 -116 c 4x9b20
|
663 -109 652 -116 641 -116 c 4x9b39f0
|
||||||
308 85 m 5
|
308 85 m 5
|
||||||
308 83 312 72 340 46 c 4
|
308 83 312 72 340 46 c 4
|
||||||
357 30 374 18 374 18 c 6
|
357 30 374 18 374 18 c 6
|
||||||
@@ -387,14 +388,14 @@ SplineSet
|
|||||||
383 55 362 72 362 90 c 4
|
383 55 362 72 362 90 c 4
|
||||||
362 92 362 93 362 95 c 4
|
362 92 362 93 362 95 c 4
|
||||||
363 100 366 113 402 134 c 4
|
363 100 366 113 402 134 c 4
|
||||||
410 138 435 153 453 153 c 4xb9a0
|
410 138 435 153 453 153 c 4xb9baf0
|
||||||
455 153 458 152 460 152 c 4
|
455 153 458 152 460 152 c 4
|
||||||
470 150 476 145 482 141 c 4
|
470 150 476 145 482 141 c 4
|
||||||
488 136 491 133 499 133 c 6
|
488 136 491 133 499 133 c 6
|
||||||
500 133 l 6xd920
|
500 133 l 6xd93af0
|
||||||
521 133 562 145 581 153 c 6
|
521 133 562 145 581 153 c 6
|
||||||
589 156 l 5
|
589 156 l 5
|
||||||
596 153 l 6xb920
|
596 153 l 6xb93af0
|
||||||
612 146 637 119 654 97 c 4
|
612 146 637 119 654 97 c 4
|
||||||
670 75 689 44 689 16 c 4
|
670 75 689 44 689 16 c 4
|
||||||
689 13 689 10 688 7 c 4
|
689 13 689 10 688 7 c 4
|
||||||
@@ -413,7 +414,7 @@ SplineSet
|
|||||||
868 337 893 326 903 325 c 5
|
868 337 893 326 903 325 c 5
|
||||||
907 329 916 340 924 359 c 4
|
907 329 916 340 924 359 c 4
|
||||||
932 377 934 390 934 396 c 4
|
932 377 934 390 934 396 c 4
|
||||||
933 396 932 396 930 396 c 4xdb20
|
933 396 932 396 930 396 c 4xdb3af0
|
||||||
919 396 902 392 892 390 c 4
|
919 396 902 392 892 390 c 4
|
||||||
886 389 881 388 878 388 c 4
|
886 389 881 388 878 388 c 4
|
||||||
876 388 875 387 873 387 c 4
|
876 388 875 387 873 387 c 4
|
||||||
@@ -433,9 +434,9 @@ SplineSet
|
|||||||
629 559 619 566 619 566 c 6
|
629 559 619 566 619 566 c 6
|
||||||
615 569 l 5
|
615 569 l 5
|
||||||
580 633 l 5
|
580 633 l 5
|
||||||
566 639 539 650 520 650 c 4x9d60
|
566 639 539 650 520 650 c 4
|
||||||
514 650 512 650 511 649 c 4
|
514 650 512 650 511 649 c 4
|
||||||
510 648 509 644 509 637 c 4
|
510 648 509 644 509 637 c 4x9d79f0
|
||||||
509 629 510 618 514 602 c 4
|
509 629 510 618 514 602 c 4
|
||||||
517 589 520 577 523 569 c 5
|
517 589 520 577 523 569 c 5
|
||||||
562 561 l 5
|
562 561 l 5
|
||||||
@@ -446,7 +447,7 @@ SplineSet
|
|||||||
435 465 l 6
|
435 465 l 6
|
||||||
437 474 439 491 439 510 c 4
|
437 474 439 491 439 510 c 4
|
||||||
439 533 436 558 423 575 c 4
|
439 533 436 558 423 575 c 4
|
||||||
400 605 354 621 320 621 c 4x99a0
|
400 605 354 621 320 621 c 4x99bcf0
|
||||||
310 621 304 619 301 618 c 4
|
310 621 304 619 301 618 c 4
|
||||||
281 608 255 548 255 504 c 4
|
281 608 255 548 255 504 c 4
|
||||||
255 497 255 490 257 484 c 4
|
255 497 255 490 257 484 c 4
|
||||||
@@ -475,22 +476,25 @@ SplineSet
|
|||||||
424 204 390 196 377 186 c 4
|
424 204 390 196 377 186 c 4
|
||||||
330 149 310 105 308 85 c 5
|
330 149 310 105 308 85 c 5
|
||||||
EndSplineSet
|
EndSplineSet
|
||||||
|
Validated: 1
|
||||||
EndChar
|
EndChar
|
||||||
|
|
||||||
StartChar: I
|
StartChar: I
|
||||||
Encoding: 73 73 5
|
Encoding: 73 73 5
|
||||||
Width: 1024
|
Width: 1024
|
||||||
VWidth: 0
|
VWidth: 0
|
||||||
Flags: HW
|
Flags: W
|
||||||
|
HStem: -154 166<226 365 659 798> 126 26<498.267 525.733> 151 131<288 343 681 735> 313 132<288 343 681 735> 330 32<424.389 599.754> 443 26<498.267 525.733> 584 184<226 365 659 798>
|
||||||
|
VStem: 51 175<12 151 445 584> 365 132<74 126 469 521> 366 31<282 313> 527 132<74 126 469 521> 627 31<282 313> 798 175<12 151 445 584>
|
||||||
LayerCount: 3
|
LayerCount: 3
|
||||||
Fore
|
Fore
|
||||||
SplineSet
|
SplineSet
|
||||||
51 -154 m 1
|
51 -154 m 1x8308
|
||||||
51 768 l 1
|
51 768 l 1
|
||||||
973 768 l 1
|
973 768 l 1
|
||||||
973 -154 l 1
|
973 -154 l 1
|
||||||
51 -154 l 1
|
51 -154 l 1x8308
|
||||||
497 469 m 2
|
497 469 m 1x87a8
|
||||||
502 469 507 470 512 470 c 0
|
502 469 507 470 512 470 c 0
|
||||||
517 470 522 469 527 469 c 1
|
517 470 522 469 527 469 c 1
|
||||||
527 521 l 1
|
527 521 l 1
|
||||||
@@ -498,35 +502,34 @@ SplineSet
|
|||||||
512 702 l 1
|
512 702 l 1
|
||||||
414 604 l 1
|
414 604 l 1
|
||||||
497 521 l 1
|
497 521 l 1
|
||||||
497 469 l 1
|
497 469 l 1x87a8
|
||||||
497 469 l 2
|
|
||||||
653 417 m 1
|
653 417 m 1
|
||||||
681 445 l 1
|
681 445 l 1
|
||||||
798 445 l 1
|
798 445 l 1x9328
|
||||||
798 584 l 1
|
798 584 l 1
|
||||||
659 584 l 1
|
659 584 l 1
|
||||||
659 467 l 1
|
659 467 l 1
|
||||||
633 440 l 1
|
633 440 l 1
|
||||||
643 433 649 425 653 417 c 1
|
643 433 649 425 653 417 c 1
|
||||||
366 282 m 1
|
366 282 m 1xb348
|
||||||
366 313 l 1
|
366 313 l 1
|
||||||
288 313 l 1
|
288 313 l 1
|
||||||
206 396 l 1
|
206 396 l 1
|
||||||
108 298 l 1
|
108 298 l 1
|
||||||
206 200 l 1
|
206 200 l 1
|
||||||
288 282 l 1
|
288 282 l 1
|
||||||
366 282 l 1
|
366 282 l 1xb348
|
||||||
343 445 m 1
|
343 445 m 1
|
||||||
371 417 l 1
|
371 417 l 1
|
||||||
375 425 381 433 391 440 c 1
|
375 425 381 433 391 440 c 1
|
||||||
365 467 l 1
|
365 467 l 1
|
||||||
365 584 l 1
|
365 584 l 1x9388
|
||||||
226 584 l 1
|
226 584 l 1
|
||||||
226 445 l 1
|
226 445 l 1
|
||||||
343 445 l 1
|
343 445 l 1
|
||||||
371 178 m 1
|
371 178 m 1
|
||||||
343 151 l 1
|
343 151 l 1
|
||||||
226 151 l 1
|
226 151 l 1xa388
|
||||||
226 12 l 1
|
226 12 l 1
|
||||||
365 12 l 1
|
365 12 l 1
|
||||||
365 129 l 1
|
365 129 l 1
|
||||||
@@ -535,7 +538,7 @@ SplineSet
|
|||||||
818 396 m 1
|
818 396 m 1
|
||||||
735 313 l 1
|
735 313 l 1
|
||||||
658 313 l 1
|
658 313 l 1
|
||||||
658 282 l 1
|
658 282 l 1xb318
|
||||||
735 282 l 1
|
735 282 l 1
|
||||||
818 200 l 1
|
818 200 l 1
|
||||||
916 298 l 1
|
916 298 l 1
|
||||||
@@ -543,12 +546,12 @@ SplineSet
|
|||||||
653 178 m 1
|
653 178 m 1
|
||||||
649 170 643 162 633 155 c 1
|
649 170 643 162 633 155 c 1
|
||||||
659 129 l 1
|
659 129 l 1
|
||||||
659 12 l 1
|
659 12 l 1xa328
|
||||||
798 12 l 1
|
798 12 l 1
|
||||||
798 151 l 1
|
798 151 l 1
|
||||||
681 151 l 1
|
681 151 l 1
|
||||||
653 178 l 1
|
653 178 l 1
|
||||||
527 126 m 1
|
527 126 m 1xc3a8
|
||||||
522 126 517 126 512 126 c 0
|
522 126 517 126 512 126 c 0
|
||||||
507 126 502 126 497 126 c 1
|
507 126 502 126 497 126 c 1
|
||||||
497 74 l 1
|
497 74 l 1
|
||||||
@@ -556,8 +559,7 @@ SplineSet
|
|||||||
512 -106 l 1
|
512 -106 l 1
|
||||||
610 -8 l 1
|
610 -8 l 1
|
||||||
527 74 l 1
|
527 74 l 1
|
||||||
527 126 l 1
|
527 126 l 1xc3a8
|
||||||
527 126 l 1
|
|
||||||
610 348 m 0
|
610 348 m 0
|
||||||
584 337 549 330 512 330 c 0
|
584 337 549 330 512 330 c 0
|
||||||
475 330 441 337 414 348 c 0
|
475 330 441 337 414 348 c 0
|
||||||
@@ -567,9 +569,9 @@ SplineSet
|
|||||||
449 157 479 152 512 152 c 0
|
449 157 479 152 512 152 c 0
|
||||||
545 152 575 157 598 167 c 0
|
545 152 575 157 598 167 c 0
|
||||||
616 174 627 184 627 192 c 2
|
616 174 627 184 627 192 c 2
|
||||||
627 356 l 1
|
627 356 l 1xcb58
|
||||||
622 353 616 351 610 348 c 0
|
622 353 616 351 610 348 c 0
|
||||||
512 443 m 1
|
512 443 m 1x8f58
|
||||||
479 443 449 438 426 428 c 0
|
479 443 449 438 426 428 c 0
|
||||||
408 421 397 410 397 402 c 0
|
408 421 397 410 397 402 c 0
|
||||||
397 394 408 384 426 377 c 0
|
397 394 408 384 426 377 c 0
|
||||||
@@ -577,8 +579,7 @@ SplineSet
|
|||||||
545 362 575 367 598 377 c 0
|
545 362 575 367 598 377 c 0
|
||||||
616 384 627 394 627 402 c 0
|
616 384 627 394 627 402 c 0
|
||||||
627 410 616 421 598 428 c 0
|
627 410 616 421 598 428 c 0
|
||||||
575 438 545 443 512 443 c 1
|
575 438 545 443 512 443 c 1x8f58
|
||||||
512 443 l 1
|
|
||||||
EndSplineSet
|
EndSplineSet
|
||||||
Validated: 5
|
Validated: 5
|
||||||
EndChar
|
EndChar
|
||||||
@@ -587,7 +588,8 @@ StartChar: four
|
|||||||
Encoding: 52 52 6
|
Encoding: 52 52 6
|
||||||
Width: 1024
|
Width: 1024
|
||||||
VWidth: 0
|
VWidth: 0
|
||||||
Flags: H
|
HStem: -2 41<389.544 635.489> 292 109<316 441 550 675> 639 41<389.544 636.396>
|
||||||
|
VStem: 117 41<241.556 436.857> 441 109<167 292 401 525> 868 41<249.643 435.223>
|
||||||
LayerCount: 3
|
LayerCount: 3
|
||||||
Fore
|
Fore
|
||||||
SplineSet
|
SplineSet
|
||||||
@@ -607,7 +609,6 @@ SplineSet
|
|||||||
909 288 892 238 861 189 c 0
|
909 288 892 238 861 189 c 0
|
||||||
835 149 801 111 757 77 c 1
|
835 149 801 111 757 77 c 1
|
||||||
801 -67 l 1
|
801 -67 l 1
|
||||||
801 -67 l 1
|
|
||||||
649 63 m 1
|
649 63 m 1
|
||||||
733 17 l 1
|
733 17 l 1
|
||||||
710 93 l 1
|
710 93 l 1
|
||||||
@@ -618,7 +619,6 @@ SplineSet
|
|||||||
158 174 317 39 513 39 c 0
|
158 174 317 39 513 39 c 0
|
||||||
552 39 592 49 634 59 c 2
|
552 39 592 49 634 59 c 2
|
||||||
649 63 l 1
|
649 63 l 1
|
||||||
649 63 l 1
|
|
||||||
675 306 m 1
|
675 306 m 1
|
||||||
675 298 667 292 657 292 c 2
|
675 298 667 292 657 292 c 2
|
||||||
550 292 l 1
|
550 292 l 1
|
||||||
@@ -640,7 +640,6 @@ SplineSet
|
|||||||
657 401 l 2
|
657 401 l 2
|
||||||
667 401 675 394 675 386 c 2
|
667 401 675 394 675 386 c 2
|
||||||
675 306 l 1
|
675 306 l 1
|
||||||
675 306 l 1
|
|
||||||
EndSplineSet
|
EndSplineSet
|
||||||
Validated: 5
|
Validated: 5
|
||||||
EndChar
|
EndChar
|
||||||
@@ -649,15 +648,17 @@ StartChar: D
|
|||||||
Encoding: 68 68 7
|
Encoding: 68 68 7
|
||||||
Width: 1080
|
Width: 1080
|
||||||
VWidth: 0
|
VWidth: 0
|
||||||
Flags: HW
|
Flags: W
|
||||||
|
HStem: 198 131<79.9424 131.341> 306 98<835.102 921.871> 353 100<731.982 810.871>
|
||||||
|
VStem: 238 219<460.138 583.719> 292 88<67.6511 114.863> 369 100<-72.2559 6.9753> 667 66<3.74069 76.8123>
|
||||||
LayerCount: 3
|
LayerCount: 3
|
||||||
Fore
|
Fore
|
||||||
SplineSet
|
SplineSet
|
||||||
469 -14 m 4
|
469 -14 m 4x26
|
||||||
469 -45 459 -89 425 -89 c 4
|
469 -45 459 -89 425 -89 c 4
|
||||||
397 -89 372 -53 369 -41 c 4
|
397 -89 372 -53 369 -41 c 4x26
|
||||||
365 -27 363 7 363 7 c 5
|
365 -27 363 7 363 7 c 5
|
||||||
363 7 292 63 292 88 c 4
|
363 7 292 63 292 88 c 4x2a
|
||||||
292 113 317 164 366 202 c 4
|
292 113 317 164 366 202 c 4
|
||||||
388 219 439 225 439 225 c 5
|
388 219 439 225 439 225 c 5
|
||||||
439 225 414 269 373 269 c 4
|
439 225 414 269 373 269 c 4
|
||||||
@@ -669,7 +670,7 @@ SplineSet
|
|||||||
119 206 108 198 97 198 c 4
|
119 206 108 198 97 198 c 4
|
||||||
78 198 76 234 76 261 c 4
|
78 198 76 234 76 261 c 4
|
||||||
76 268 76 274 76 279 c 4
|
76 268 76 274 76 279 c 4
|
||||||
76 288 76 295 76 295 c 6
|
76 295 l 6
|
||||||
76 295 82 320 96 328 c 4
|
76 295 82 320 96 328 c 4
|
||||||
97 328 98 329 99 329 c 4
|
97 328 98 329 99 329 c 4
|
||||||
121 329 217 268 217 268 c 6
|
121 329 217 268 217 268 c 6
|
||||||
@@ -696,12 +697,12 @@ SplineSet
|
|||||||
570 401 569 394 569 388 c 4
|
570 401 569 394 569 388 c 4
|
||||||
569 355 614 330 614 330 c 5
|
569 355 614 330 614 330 c 5
|
||||||
614 330 646 364 662 384 c 4
|
614 330 646 364 662 384 c 4
|
||||||
678 404 734 453 763 453 c 4
|
678 404 734 453 763 453 c 4xb2
|
||||||
790 453 841 404 867 404 c 4
|
790 453 841 404 867 404 c 4
|
||||||
878 404 902 413 924 413 c 4
|
878 404 902 413 924 413 c 4
|
||||||
938 413 945 409 945 396 c 4
|
938 413 945 409 945 396 c 4
|
||||||
945 371 922 318 905 307 c 4
|
945 371 922 318 905 307 c 4
|
||||||
903 306 902 306 899 306 c 4
|
903 306 902 306 899 306 c 4x52
|
||||||
872 306 795 353 761 353 c 4
|
872 306 795 353 761 353 c 4
|
||||||
758 353 756 353 754 352 c 4
|
758 353 756 353 754 352 c 4
|
||||||
723 342 708 263 682 213 c 5
|
723 342 708 263 682 213 c 5
|
||||||
@@ -714,11 +715,232 @@ SplineSet
|
|||||||
667 64 605 129 586 138 c 5
|
667 64 605 129 586 138 c 5
|
||||||
565 130 522 118 499 118 c 4
|
565 130 522 118 499 118 c 4
|
||||||
475 118 470 137 453 137 c 4
|
475 118 470 137 453 137 c 4
|
||||||
437 137 380 108 380 93 c 4
|
437 137 380 108 380 93 c 4x2a
|
||||||
380 77 446 36 460 23 c 4
|
380 77 446 36 460 23 c 4
|
||||||
465 18 469 3 469 -14 c 4
|
465 18 469 3 469 -14 c 4x26
|
||||||
EndSplineSet
|
EndSplineSet
|
||||||
Validated: 1
|
Validated: 1
|
||||||
EndChar
|
EndChar
|
||||||
|
|
||||||
|
StartChar: E
|
||||||
|
Encoding: 69 69 8
|
||||||
|
Width: 1024
|
||||||
|
VWidth: 0
|
||||||
|
HStem: -65 248<767.992 903.557> 62.9598 56.9516<226.56 349.224 705.189 710> 143 26.9554<256.859 324.845> 192.776 27.2245<289.957 314.952> 295.071 27.9295<269.575 354.789> 344 66<376.038 439.962> 433 25<407.015 431.988> 469 248<767.951 904.873>
|
||||||
|
VStem: 66.5097 115.469<193.203 298.14> 204 32.9583<187.285 267.499> 257.966 57.0345<194.835 224.243> 335.831 30.8205<177.895 239.59> 388.713 44.4108<157.773 270.37> 407 25<433.012 457.985> 442 55.4336<365.791 447.874> 711 249<-8.06335 62 583 662.557>
|
||||||
|
LayerCount: 3
|
||||||
|
Fore
|
||||||
|
SplineSet
|
||||||
|
279 573 m 0x7ffb
|
||||||
|
292 573 313 570 343 563 c 0
|
||||||
|
462 535 489 420 496 389 c 0
|
||||||
|
496.963 384.737 497.434 380.795 497.434 377.167 c 0
|
||||||
|
497.434 354.414 478.912 344 447 344 c 0
|
||||||
|
422.333 344 394.111 344.889 359.074 344.889 c 0
|
||||||
|
341.556 344.889 322.333 344.667 301 344 c 0
|
||||||
|
237 342 192 300 183 241 c 0
|
||||||
|
182.31 236.477 181.979 231.948 181.979 227.44 c 0
|
||||||
|
181.979 173.142 230.063 121.847 279 120 c 0
|
||||||
|
280.57 119.941 282.134 119.911 283.69 119.911 c 0
|
||||||
|
334.636 119.911 377.296 151.452 387 199 c 0
|
||||||
|
388.159 204.678 388.713 210.303 388.713 215.813 c 0
|
||||||
|
388.713 257.852 356.437 293.232 314 295 c 0
|
||||||
|
312.865 295.047 311.742 295.071 310.63 295.071 c 0
|
||||||
|
264.267 295.071 236.958 255.02 236.958 229.128 c 0
|
||||||
|
236.958 206.914 253.918 170.972 286 170 c 0
|
||||||
|
287.107 169.97 288.186 169.955 289.238 169.955 c 0
|
||||||
|
323.358 169.955 329.15 185.419 334 199 c 0
|
||||||
|
335.206 202.378 335.831 206.221 335.831 210.207 c 0
|
||||||
|
335.831 222.743 329.657 236.689 316 242 c 0
|
||||||
|
298 249 291 238 290 234 c 0
|
||||||
|
289 228 294 220 299 220 c 0
|
||||||
|
306 220 316 220 315 206 c 0
|
||||||
|
314.143 195.714 302.265 192.776 292.592 192.776 c 0
|
||||||
|
290.98 192.776 289.429 192.857 288 193 c 0
|
||||||
|
278.231 193.977 257.966 202.588 257.966 228.155 c 0
|
||||||
|
257.966 248.46 275.443 271.256 306.289 271.256 c 0
|
||||||
|
308.143 271.256 310.047 271.172 312 271 c 0
|
||||||
|
351.28 267.429 366.651 246.325 366.651 219.783 c 0
|
||||||
|
366.651 216.594 366.429 213.326 366 210 c 0
|
||||||
|
362 179 343 143 284 143 c 0
|
||||||
|
225 143 204 192 204 229 c 0
|
||||||
|
204 266 232 322 318 323 c 0
|
||||||
|
318.502 323.006 319.002 323.009 319.501 323.009 c 0
|
||||||
|
394.354 323.009 433.124 257.543 433.124 205.254 c 0
|
||||||
|
433.124 198.198 432.418 191.383 431 185 c 0
|
||||||
|
420.148 134.686 398.59 62.9598 273.187 62.9598 c 0
|
||||||
|
271.478 62.9598 269.749 62.9731 268 63 c 0
|
||||||
|
134.539 65.8599 66.5097 196.855 66.5097 295.718 c 0
|
||||||
|
66.5097 300.562 66.673 305.329 67 310 c 0
|
||||||
|
74 410 112 447 146 480 c 0
|
||||||
|
204.987 537.114 264.85 531.109 264.85 543.245 c 0
|
||||||
|
264.85 544.071 264.573 544.981 264 546 c 0
|
||||||
|
260.913 551.732 257.827 557.659 257.827 562.495 c 0
|
||||||
|
257.827 568.625 262.788 573 279 573 c 0x7ffb
|
||||||
|
408 478 m 0
|
||||||
|
389 478 374 463 374 444 c 0
|
||||||
|
374 425 389 410 408 410 c 0
|
||||||
|
427 410 442 425 442 444 c 0
|
||||||
|
442 463 427 478 408 478 c 0
|
||||||
|
835 717 m 0
|
||||||
|
904 717 960 662 960 593 c 0
|
||||||
|
960 524 904 469 835 469 c 0
|
||||||
|
798 469 751 495 731 526 c 1
|
||||||
|
515 456 l 1
|
||||||
|
503 483 491 498 481 511 c 1
|
||||||
|
712 583 l 2
|
||||||
|
712 586 711 590 711 593 c 0
|
||||||
|
711 662 766 717 835 717 c 0
|
||||||
|
462 207 m 1
|
||||||
|
727 121 l 1
|
||||||
|
747 155 795 183 834 183 c 0
|
||||||
|
903 183 958 128 958 59 c 0
|
||||||
|
958 -10 903 -65 834 -65 c 0x9ff3
|
||||||
|
765 -65 710 -10 710 59 c 0
|
||||||
|
710 60 710 61 710 62 c 2
|
||||||
|
456 143 l 1
|
||||||
|
458.679 159.077 462.157 171.165 462.157 197.076 c 0
|
||||||
|
462.157 200.176 462.107 203.474 462 207 c 1
|
||||||
|
407 445 m 0x1ff7
|
||||||
|
407 453 412 458 420 458 c 0
|
||||||
|
428 458 432 453 432 445 c 0
|
||||||
|
432 437 428 433 420 433 c 0
|
||||||
|
412 433 407 437 407 445 c 0x1ff7
|
||||||
|
EndSplineSet
|
||||||
|
Validated: 1
|
||||||
|
EndChar
|
||||||
|
|
||||||
|
StartChar: F
|
||||||
|
Encoding: 70 70 9
|
||||||
|
Width: 1024
|
||||||
|
VWidth: 0
|
||||||
|
HStem: -36 87<438.038 591.036> 87 39<470.027 570.5> 163 41<517.914 555.989> 241 41<519.089 577.135> 317 43<482.813 612.995> 394 100<654.807 741.193> 528 39<697.004 734.996>
|
||||||
|
VStem: 177 177<195.689 296.938> 387 50<156.758 272.234> 469 87<171.273 203.985> 588 47<139.283 231.811> 669 67<122.953 266.087> 697 38<528.004 566.995> 750 85<426.5 559.5>
|
||||||
|
LayerCount: 3
|
||||||
|
Fore
|
||||||
|
SplineSet
|
||||||
|
502 742 m 0xfff4
|
||||||
|
522 742 553 738 599 727 c 0
|
||||||
|
780 684 822 509 833 462 c 0
|
||||||
|
835 456 835 450 835 444 c 0
|
||||||
|
835 409 806 392 758 392 c 0
|
||||||
|
721 392 678 394 624 394 c 0
|
||||||
|
597 394 568 393 535 392 c 0
|
||||||
|
437 388 368 325 355 235 c 0
|
||||||
|
354 228 354 222 354 215 c 0
|
||||||
|
354 132 426 55 501 51 c 0
|
||||||
|
504 51 507 51 510 51 c 0
|
||||||
|
587 51 652 99 666 171 c 0
|
||||||
|
668 180 669 188 669 196 c 0
|
||||||
|
669 260 620 313 555 317 c 0
|
||||||
|
553 317 550 317 548 317 c 0
|
||||||
|
478 317 437 256 437 218 c 0
|
||||||
|
437 184 463 127 512 126 c 0
|
||||||
|
514 126 516 126 518 126 c 0
|
||||||
|
569 126 578 150 586 171 c 0
|
||||||
|
588 176 588 181 588 187 c 0
|
||||||
|
588 207 579 228 557 237 c 0
|
||||||
|
550 240 545 241 540 241 c 0
|
||||||
|
525 241 520 230 518 225 c 0
|
||||||
|
516 216 524 204 532 204 c 0
|
||||||
|
543 204 556 202 556 183 c 0
|
||||||
|
556 166 541 163 525 163 c 0
|
||||||
|
522 163 518 163 515 163 c 0
|
||||||
|
499 164 469 177 469 217 c 0
|
||||||
|
469 247 497 282 543 282 c 0
|
||||||
|
546 282 549 282 552 282 c 0
|
||||||
|
611 277 635 243 635 202 c 0
|
||||||
|
635 197 635 193 634 188 c 0
|
||||||
|
628 141 598 87 508 87 c 0
|
||||||
|
418 87 387 162 387 218 c 0
|
||||||
|
387 274 430 358 561 360 c 0
|
||||||
|
562 360 563 360 564 360 c 0
|
||||||
|
677 360 736 262 736 182 c 0
|
||||||
|
736 171 735 160 733 150 c 0
|
||||||
|
716 74 683 -36 494 -36 c 0
|
||||||
|
491 -36 487 -36 484 -36 c 0
|
||||||
|
280 -32 177 170 177 321 c 0
|
||||||
|
177 328 178 335 178 342 c 0
|
||||||
|
188 495 246 549 298 600 c 0
|
||||||
|
388 687 479 677 479 696 c 0
|
||||||
|
479 697 479 698 478 700 c 0
|
||||||
|
473 709 469 718 469 725 c 0
|
||||||
|
469 735 477 742 502 742 c 0xfff4
|
||||||
|
698 597 m 0
|
||||||
|
669 597 646 574 646 545 c 0
|
||||||
|
646 516 669 494 698 494 c 0
|
||||||
|
727 494 750 516 750 545 c 0
|
||||||
|
750 574 727 597 698 597 c 0
|
||||||
|
697 547 m 0xffec
|
||||||
|
697 560 703 567 716 567 c 0
|
||||||
|
729 567 735 560 735 547 c 0
|
||||||
|
735 534 729 528 716 528 c 0
|
||||||
|
703 528 697 534 697 547 c 0xffec
|
||||||
|
EndSplineSet
|
||||||
|
Validated: 1
|
||||||
|
EndChar
|
||||||
|
|
||||||
|
StartChar: O
|
||||||
|
Encoding: 79 79 10
|
||||||
|
Width: 1024
|
||||||
|
VWidth: 0
|
||||||
|
HStem: 1.59961 8<801.97 829.007> 20 35.2002<801.975 810.774 823.574 824.837> 33.5996 5.60059<810.774 817.806> 48.7998 6.40039<810.774 818.736> 61.5996 8.7998<801.043 829.91> 434.399 245.601<441.712 567.228>
|
||||||
|
VStem: 780.375 8.7998<21.8033 49.6942> 801.975 8.7998<20 33.5996 39.2002 48.7998> 819.574 8.80078<40.0451 47.9513> 841.175 8.7998<21.5374 50.3356>
|
||||||
|
LayerCount: 3
|
||||||
|
Fore
|
||||||
|
SplineSet
|
||||||
|
504.375 680 m 0x8fc0
|
||||||
|
672.375 680 816.375 560 846.774 395.2 c 0
|
||||||
|
877.175 230.399 785.975 67.2002 629.175 7.2002 c 0
|
||||||
|
621.975 4.7998 613.975 8 611.574 15.2002 c 2
|
||||||
|
533.175 218.399 l 2
|
||||||
|
530.774 225.6 533.975 234.399 541.175 236.8 c 0
|
||||||
|
587.574 254.399 613.975 301.6 605.175 350.399 c 0
|
||||||
|
596.375 399.2 553.975 434.399 504.375 434.399 c 0
|
||||||
|
454.774 434.399 413.175 399.2 404.375 350.399 c 0
|
||||||
|
395.574 301.6 421.175 254.399 467.574 236.8 c 0
|
||||||
|
474.774 234.399 477.975 225.6 475.574 218.399 c 2
|
||||||
|
397.975 15.2002 l 2
|
||||||
|
395.574 8 386.774 4.7998 379.574 7.2002 c 0
|
||||||
|
222.774 67.2002 131.574 230.399 161.975 395.2 c 0
|
||||||
|
192.375 560 336.375 680 504.375 680 c 0x8fc0
|
||||||
|
815.574 70.3994 m 0
|
||||||
|
834.774 70.3994 849.975 55.2002 849.975 36 c 0
|
||||||
|
849.975 16.7998 834.774 1.59961 815.574 1.59961 c 0
|
||||||
|
796.375 1.59961 780.375 16.7998 780.375 36 c 0
|
||||||
|
780.375 55.2002 796.375 70.3994 815.574 70.3994 c 0
|
||||||
|
815.574 61.5996 m 0
|
||||||
|
801.175 61.5996 789.175 50.3994 789.175 36 c 0
|
||||||
|
789.175 21.5996 801.175 9.59961 815.574 9.59961 c 0
|
||||||
|
829.975 9.59961 841.175 21.5996 841.175 36 c 0
|
||||||
|
841.175 50.3994 829.975 61.5996 815.574 61.5996 c 0
|
||||||
|
814.774 39.2002 m 2xbfc0
|
||||||
|
816.375 39.2002 817.975 40 818.774 40.7998 c 0
|
||||||
|
819.574 41.5996 819.574 42.3994 819.574 44 c 0
|
||||||
|
819.574 45.5996 819.574 46.3994 818.774 47.2002 c 0
|
||||||
|
817.975 48 816.375 48.7998 814.774 48.7998 c 2
|
||||||
|
810.774 48.7998 l 1
|
||||||
|
810.774 39.2002 l 1
|
||||||
|
814.774 39.2002 l 2xbfc0
|
||||||
|
810.774 33.5996 m 1
|
||||||
|
810.774 20 l 1
|
||||||
|
801.975 20 l 1
|
||||||
|
801.975 55.2002 l 1xcfc0
|
||||||
|
815.574 55.2002 l 2x9fc0
|
||||||
|
820.375 55.2002 822.774 54.3994 825.175 52.7998 c 0
|
||||||
|
827.574 51.2002 828.375 48.7998 828.375 45.5996 c 0
|
||||||
|
828.375 43.2002 827.574 41.5996 826.774 40 c 0
|
||||||
|
825.975 38.3994 824.375 36.7998 821.975 36 c 1
|
||||||
|
823.574 36 824.375 35.2002 825.175 34.3994 c 0
|
||||||
|
825.975 33.5996 827.574 32 828.375 29.5996 c 2
|
||||||
|
833.175 20 l 1
|
||||||
|
823.574 20 l 1xcfc0
|
||||||
|
819.574 28.7998 l 2
|
||||||
|
818.774 30.3994 817.175 31.2002 816.375 32 c 0
|
||||||
|
815.574 32.7998 814.774 33.5996 813.175 33.5996 c 2
|
||||||
|
810.774 33.5996 l 1
|
||||||
|
EndSplineSet
|
||||||
|
Validated: 524321
|
||||||
|
EndChar
|
||||||
EndChars
|
EndChars
|
||||||
EndSplineFont
|
EndSplineFont
|
||||||
|
|||||||
Binary file not shown.
@@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'CombodoRegular';
|
font-family: 'CombodoRegular';
|
||||||
src: url('combodo-webfont.woff2?v=1.0') format('woff2'),
|
src: url('combodo-webfont.woff2?v=2.0') format('woff2'),
|
||||||
url('combodo-webfont.woff?v=1.0') format('woff'),
|
url('combodo-webfont.woff?v=2.0') format('woff'),
|
||||||
url('combodo-webfont.ttf?v=1.0') format('truetype');
|
url('combodo-webfont.ttf?v=2.0') format('truetype');
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
|
||||||
@@ -193,7 +193,16 @@
|
|||||||
.fc-combodo-icon:before {
|
.fc-combodo-icon:before {
|
||||||
content: "D";
|
content: "D";
|
||||||
}
|
}
|
||||||
|
.fc-itophub-icon:before {
|
||||||
|
content: "E";
|
||||||
|
}
|
||||||
|
.fc-chameleon-icon:before {
|
||||||
|
content: "F";
|
||||||
|
}
|
||||||
.fc-itop-icon:before {
|
.fc-itop-icon:before {
|
||||||
content: "I";
|
content: "I";
|
||||||
}
|
}
|
||||||
|
.fc-opensource-icon:before {
|
||||||
|
content: "O";
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
50
css/font-combodo/glyphs/E.svg
Executable file
50
css/font-combodo/glyphs/E.svg
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1000"
|
||||||
|
height="1000"
|
||||||
|
viewBox="0 0 264.58333 264.58334"
|
||||||
|
version="1.1"
|
||||||
|
id="svg909">
|
||||||
|
<defs
|
||||||
|
id="defs903" />
|
||||||
|
<metadata
|
||||||
|
id="metadata906">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
style="fill:#000000;fill-opacity:1"
|
||||||
|
transform="matrix(2.6189878,0,0,2.6189878,-138.11438,-66.566639)"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 77.776825,48.628779 c -3.105953,0.0165 -2.465143,1.56905 -1.672249,3.00189 0.969595,1.75214 -6.046384,0.53457 -12.856064,7.17372 -3.69523,3.60269 -7.8302,7.46233 -8.56485,18.39112 -0.73465,10.9288 6.57401,26.601051 21.834325,26.890351 14.098468,0.26727 16.523001,-7.762201 17.760671,-13.268961 1.323287,-5.88768 -2.939907,-15.10068 -12.294338,-14.96704 -9.354428,0.13364 -12.428178,6.14692 -12.428178,10.15597 0,4.00904 2.27182,9.35447 8.686288,9.35447 6.414468,0 8.552552,-3.87524 8.953457,-7.2161 0.400905,-3.34087 -1.12866,-6.23284 -5.863206,-6.68176 -3.664545,-0.34747 -5.823431,2.30622 -5.896281,4.44314 -0.100228,2.93996 2.194808,3.98392 3.307291,4.04264 1.112483,0.0587 2.766575,-0.003 2.856155,-1.33635 0.10023,-1.49182 -0.935023,-1.63676 -1.686717,-1.62005 -0.534409,0.0119 -1.147985,-0.88438 -0.985986,-1.50379 0.121989,-0.46643 0.78549,-1.62036 2.790009,-0.81855 2.004523,0.8018 2.544982,3.13823 2.021065,4.67723 -0.534538,1.57021 -1.18617,3.2909 -5.228621,3.17397 -3.536694,-0.1023 -5.411874,-4.25964 -5.328354,-6.68177 0.0939,-2.724 3.190312,-7.1826 8.402068,-6.91534 5.211754,0.26728 8.953352,5.07775 7.884274,10.42314 -1.069079,5.34539 -6.013196,8.82024 -11.759488,8.55297 -5.746294,-0.26727 -11.359094,-6.68189 -10.423654,-13.09636 0.93544,-6.41447 5.87967,-10.95789 12.828675,-11.22516 6.949005,-0.26727 11.885592,0.016 15.894636,0.016 4.009047,0 6.155487,-1.61955 5.353677,-4.96042 -0.8018,-3.34086 -3.786135,-15.85543 -16.689419,-18.91977 -3.29736,-0.78307 -5.483391,-1.09268 -6.895186,-1.0852 z m 13.978992,10.35854 a 3.685268,3.685268 0 0 1 3.685563,3.68505 3.685268,3.685268 0 0 1 -3.685563,3.68556 3.685268,3.685268 0 0 1 -3.685048,-3.68556 3.685268,3.685268 0 0 1 3.685048,-3.68505 z"
|
||||||
|
id="path882" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 138.24445,32.953249 a 13.49711,13.49711 0 0 0 -13.49685,13.49685 13.49711,13.49711 0 0 0 0.0465,1.06195 l -25.043431,7.84087 c 1.104251,1.4075 2.257151,3.10658 3.611151,6.01255 l 23.55566,-7.5799 a 13.49711,13.49711 0 0 0 11.32696,6.1619 13.49711,13.49711 0 0 0 13.49737,-13.49737 13.49711,13.49711 0 0 0 -13.49737,-13.49685 z"
|
||||||
|
id="rect827" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 97.624193,88.491979 c 0.07421,3.57897 -0.303877,5.04652 -0.587044,6.95772 l 27.570411,8.739001 a 13.49711,13.49711 0 0 0 -0.0134,0.37258 13.49711,13.49711 0 0 0 13.49737,13.49737 13.49711,13.49711 0 0 0 13.49685,-13.49737 13.49711,13.49711 0 0 0 -13.49685,-13.496851 13.49711,13.49711 0 0 0 -11.65201,6.71794 z"
|
||||||
|
id="rect827-1" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path888"
|
||||||
|
cx="93.031555"
|
||||||
|
cy="62.530666"
|
||||||
|
r="1.3701637" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
41
css/font-combodo/glyphs/F.svg
Executable file
41
css/font-combodo/glyphs/F.svg
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1000"
|
||||||
|
height="1000"
|
||||||
|
viewBox="0 0 264.58333 264.58334"
|
||||||
|
version="1.1"
|
||||||
|
id="svg909">
|
||||||
|
<defs
|
||||||
|
id="defs903" />
|
||||||
|
<metadata
|
||||||
|
id="metadata906">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
transform="translate(0,-32.41665)"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
style="fill:#1b1b1b;fill-opacity:1;stroke:#000000;stroke-width:1.71210456;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 128.74663,48.188011 c -13.29429,0.07062 -10.55146,6.715944 -7.15766,12.848874 4.15012,7.499617 -25.880108,2.288099 -55.027316,30.705397 -15.81655,15.420458 -33.515303,31.940728 -36.659797,78.718798 -3.144494,46.77813 28.138482,113.85946 93.456613,115.09774 60.34513,1.14398 70.72277,-33.22425 76.02032,-56.79463 5.66401,-25.20081 -12.58357,-64.63485 -52.62298,-64.06284 -40.0394,0.57201 -53.195848,26.31042 -53.195848,43.47021 0,17.15974 9.723978,40.03957 37.179578,40.03957 27.4556,0 36.60716,-16.58704 38.32314,-30.88679 1.71598,-14.2998 -4.83096,-26.67818 -25.09606,-28.59968 -15.68521,-1.48726 -24.9258,9.87122 -25.23762,19.0178 -0.429,12.5838 9.39435,17.05222 14.15607,17.30356 4.76172,0.25125 11.84166,-0.0128 12.22509,-5.71993 0.42901,-6.38538 -4.00214,-7.00576 -7.21959,-6.93424 -2.28741,0.0509 -4.91368,-3.78538 -4.22028,-6.43661 0.52215,-1.99644 3.3621,-6.93557 11.94197,-3.50361 8.57988,3.43191 10.89319,13.43244 8.65069,20.01977 -2.28797,6.72091 -5.07712,14.08591 -22.37987,13.58542 -15.13797,-0.43787 -23.16423,-18.23237 -22.80675,-28.59972 0.40192,-11.65944 13.65537,-30.74341 35.96305,-29.59947 22.30767,1.14403 38.32269,21.7341 33.74675,44.61377 -4.57593,22.87966 -25.73805,37.75293 -50.33368,36.60894 -24.59564,-1.14398 -48.619888,-28.60023 -44.615958,-56.05584 4.00393,-27.45561 25.166518,-46.90263 54.910078,-48.04662 29.74356,-1.14398 50.87344,0.0685 68.0332,0.0685 17.15977,0 26.34709,-6.93209 22.91514,-21.23189 -3.43192,-14.29975 -16.20565,-67.865386 -71.43508,-80.981563 -14.11356,-3.351744 -23.47035,-4.676956 -29.5132,-4.644939 z m 59.83374,44.337259 a 15.77391,15.77391 0 0 1 15.77517,15.77298 15.77391,15.77391 0 0 1 -15.77517,15.77516 15.77391,15.77391 0 0 1 -15.77297,-15.77516 15.77391,15.77391 0 0 1 15.77297,-15.77298 z"
|
||||||
|
id="path882" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#101010;fill-opacity:1;stroke:#000000;stroke-width:1.71210456;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path888"
|
||||||
|
cx="194.04086"
|
||||||
|
cy="107.69173"
|
||||||
|
r="5.8646588" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.0 KiB |
87
css/font-combodo/glyphs/O.svg
Executable file
87
css/font-combodo/glyphs/O.svg
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000"
|
||||||
|
height="1000"
|
||||||
|
viewBox="0 0 264.58333 264.58334"
|
||||||
|
version="1.1"
|
||||||
|
id="svg876"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||||
|
sodipodi:docname="O.svg">
|
||||||
|
<defs
|
||||||
|
id="defs870" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.35"
|
||||||
|
inkscape:cx="-272.85714"
|
||||||
|
inkscape:cy="560"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1005"
|
||||||
|
inkscape:window-x="1911"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata873">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Calque 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-32.41664)">
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:middle;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8.99672318;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 131.53572,50.179132 c -54.174274,0 -100.702568,38.6765 -110.575582,91.938598 -9.873159,53.26282 19.698102,106.06258 70.277674,125.4761 2.319548,0.89024 4.921621,-0.26836 5.811987,-2.58786 L 122.30183,199.2106 c 0.89023,-2.31957 -0.26838,-4.92164 -2.58789,-5.812 -14.87072,-5.70891 -23.515673,-21.14784 -20.612431,-36.80689 2.903191,-15.6588 16.504681,-26.96534 32.434211,-26.96534 15.92952,0 29.53338,11.30654 32.43657,26.96534 2.90326,15.65905 -5.74171,31.09798 -20.61242,36.80689 -2.31951,0.89036 -3.47812,3.49245 -2.58788,5.812 l 25.25202,65.79537 c 0.89038,2.31821 3.49074,3.47652 5.8096,2.58786 50.57958,-19.41352 80.15083,-72.21328 70.27768,-125.4761 -9.87301,-53.262098 -56.4013,-91.938598 -110.57557,-91.938598 z"
|
||||||
|
id="path3773"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ssccscsssccccss" />
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
id="g3797"
|
||||||
|
transform="matrix(1.2200654,0,0,1.2200654,455.86197,1099.5367)"
|
||||||
|
inkscape:export-filename="/home/rafael/workspace/logo-osi/3/png/logo396x412.png"
|
||||||
|
inkscape:export-xdpi="48.18"
|
||||||
|
inkscape:export-ydpi="48.18">
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.25831962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m -183.5617,-698.57555 c -5.02556,0 -9.12392,4.09113 -9.12392,9.10782 0,5.01668 4.09836,9.10781 9.12392,9.10781 5.02556,0 9.12392,-4.09113 9.12392,-9.10781 0,-5.01669 -4.09836,-9.10782 -9.12392,-9.10782 z m 0,2.25596 c 3.80399,0 6.8633,3.05458 6.8633,6.85186 0,3.79727 -3.05931,6.85119 -6.8633,6.85119 -3.80399,0 -6.86397,-3.05392 -6.86397,-6.85119 0,-3.79728 3.05998,-6.85186 6.86397,-6.85186 z"
|
||||||
|
id="path3015"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<g
|
||||||
|
aria-label="R"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:0%;font-family:OpenSymbol;-inkscape-font-specification:'OpenSymbol Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
id="text3793">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
d="m -183.7552,-690.46513 q 0.74769,0 1.06902,-0.27807 0.3275,-0.27807 0.3275,-0.91454 0,-0.63028 -0.3275,-0.90217 -0.32133,-0.27189 -1.06902,-0.27189 h -1.00105 v 2.36667 z m -1.00105,1.64369 v 3.4913 h -2.37902 v -9.22569 h 3.63342 q 1.82289,0 2.66946,0.61175 0.85274,0.61175 0.85274,1.93412 0,0.91454 -0.44491,1.50157 -0.43873,0.58703 -1.32855,0.8651 0.48817,0.11123 0.87128,0.50671 0.3893,0.38929 0.78477,1.18642 l 1.29147,2.62002 h -2.53351 l -1.12463,-2.29252 q -0.33986,-0.69208 -0.69208,-0.94543 -0.34604,-0.25335 -0.92689,-0.25335 z"
|
||||||
|
style="font-size:12.65519524px;line-height:1.25"
|
||||||
|
id="path863" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.6 KiB |
@@ -18,6 +18,9 @@ aIcons = {
|
|||||||
'combodo-icon': 'Combodo icon',
|
'combodo-icon': 'Combodo icon',
|
||||||
'combodo-icon-o': 'Combodo icon (outline)',
|
'combodo-icon-o': 'Combodo icon (outline)',
|
||||||
'itop-icon': 'iTop icon',
|
'itop-icon': 'iTop icon',
|
||||||
|
'itophub-icon': 'iTop Hub icon',
|
||||||
|
'chameleon-icon': 'Hub\'s Chameleon icon',
|
||||||
|
'opensource-icon': 'Open Source Logo',
|
||||||
}
|
}
|
||||||
|
|
||||||
function GenerateTable() {
|
function GenerateTable() {
|
||||||
|
|||||||
BIN
css/font-open-sans/OpenSans-Bold-cyrillic-ext.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Bold-cyrillic-ext.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Bold-cyrillic.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Bold-cyrillic.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Bold-greek-ext.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Bold-greek-ext.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Bold-greek.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Bold-greek.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Bold-latin-ext.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Bold-latin-ext.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Bold-latin.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Bold-latin.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Bold-vietnamese.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Bold-vietnamese.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Regular-cyrillic-ext.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Regular-cyrillic-ext.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Regular-cyrillic.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Regular-cyrillic.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Regular-greek-ext.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Regular-greek-ext.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Regular-greek.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Regular-greek.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Regular-latin-ext.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Regular-latin-ext.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Regular-latin.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Regular-latin.woff2
Normal file
Binary file not shown.
BIN
css/font-open-sans/OpenSans-Regular-vietnamese.woff2
Normal file
BIN
css/font-open-sans/OpenSans-Regular-vietnamese.woff2
Normal file
Binary file not shown.
112
css/font-open-sans/font-open-sans.css
Normal file
112
css/font-open-sans/font-open-sans.css
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/* cyrillic-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-cyrillic-ext.woff2') format('woff2');
|
||||||
|
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||||
|
}
|
||||||
|
/* cyrillic */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-cyrillic.woff2') format('woff2');
|
||||||
|
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||||
|
}
|
||||||
|
/* greek-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-greek-ext.woff2') format('woff2');
|
||||||
|
unicode-range: U+1F00-1FFF;
|
||||||
|
}
|
||||||
|
/* greek */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-greek.woff2') format('woff2');
|
||||||
|
unicode-range: U+0370-03FF;
|
||||||
|
}
|
||||||
|
/* vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-vietnamese.woff2') format('woff2');
|
||||||
|
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||||
|
}
|
||||||
|
/* latin-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-latin-ext.woff2') format('woff2');
|
||||||
|
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
/* latin */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-latin.woff2') format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
|
/* cyrillic-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-cyrillic-ext.woff2') format('woff2');
|
||||||
|
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||||
|
}
|
||||||
|
/* cyrillic */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-cyrillic.woff2') format('woff2');
|
||||||
|
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||||
|
}
|
||||||
|
/* greek-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-greek-ext.woff2') format('woff2');
|
||||||
|
unicode-range: U+1F00-1FFF;
|
||||||
|
}
|
||||||
|
/* greek */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-greek.woff2') format('woff2');
|
||||||
|
unicode-range: U+0370-03FF;
|
||||||
|
}
|
||||||
|
/* vietnamese */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-vietnamese.woff2') format('woff2');
|
||||||
|
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||||
|
}
|
||||||
|
/* latin-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-latin-ext.woff2') format('woff2');
|
||||||
|
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
/* latin */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-latin.woff2') format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ body {
|
|||||||
font-family: Tahoma, Verdana, Arial, Helvetica;
|
font-family: Tahoma, Verdana, Arial, Helvetica;
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
color: #000;
|
color: #000;
|
||||||
|
background-color: white;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
/* Remove body margin/padding */
|
/* Remove body margin/padding */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -20,6 +21,13 @@ body.printable-version {
|
|||||||
.ui-layout-content {
|
.ui-layout-content {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
.ui-layout-content .ui-tabs-nav li {
|
||||||
|
/* Overriding jQuery UI theme to see active tab better */
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
.ui-layout-content .ui-tabs-nav li.ui-tabs-active {
|
||||||
|
padding-bottom: 3px;
|
||||||
|
}
|
||||||
.raw_output {
|
.raw_output {
|
||||||
font-family: Courier-New, Courier, Arial, Helvetica;
|
font-family: Courier-New, Courier, Arial, Helvetica;
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
@@ -85,6 +93,9 @@ table.listResults td .view-image img {
|
|||||||
.edit-image .view-image {
|
.edit-image .view-image {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
.edit-image .view-image img[src=""], .edit-image .view-image img[src="null"] {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
.edit-image .view-image.dirty.compat {
|
.edit-image .view-image.dirty.compat {
|
||||||
background-image: url("ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png");
|
background-image: url("ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png");
|
||||||
}
|
}
|
||||||
@@ -292,13 +303,13 @@ td a.mailto, td a.mailto:visited {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #000;
|
color: #000;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
background: url(../images/mail.png?v=v2.4.0-beta) no-repeat left;
|
background: url(../images/mail.png?v=v2.4.0) no-repeat left;
|
||||||
}
|
}
|
||||||
td a.mailto:hover {
|
td a.mailto:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: #e87c1e;
|
color: #e87c1e;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
background: url(../images/mail.png?v=v2.4.0-beta) no-repeat left;
|
background: url(../images/mail.png?v=v2.4.0) no-repeat left;
|
||||||
}
|
}
|
||||||
a.small_action {
|
a.small_action {
|
||||||
font-family: Tahoma, Verdana, Arial, Helvetica;
|
font-family: Tahoma, Verdana, Arial, Helvetica;
|
||||||
@@ -316,10 +327,10 @@ a.small_action {
|
|||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
background: #e87c1e url(../images/actions_left.png?v=v2.4.0-beta) no-repeat left;
|
background: #e87c1e url(../images/actions_left.png?v=v2.4.0) no-repeat left;
|
||||||
}
|
}
|
||||||
.actions_details span {
|
.actions_details span {
|
||||||
background: url(../images/actions_right.png?v=v2.4.0-beta) no-repeat right;
|
background: url(../images/actions_right.png?v=v2.4.0) no-repeat right;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
@@ -493,7 +504,7 @@ div.actions_menu > ul {
|
|||||||
nowidth: 70px;
|
nowidth: 70px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
/* Nasty work-around for IE... en attendant mieux */
|
/* Nasty work-around for IE... en attendant mieux */
|
||||||
background: #e87c1e url(../images/actions_left.png?v=v2.4.0-beta) no-repeat top left;
|
background: #e87c1e url(../images/actions_left.png?v=v2.4.0) no-repeat top left;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@@ -505,7 +516,7 @@ div.actions_menu > ul > li {
|
|||||||
height: 17px;
|
height: 17px;
|
||||||
padding-right: 16px;
|
padding-right: 16px;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
background: url(../images/actions_right.png?v=v2.4.0-beta) no-repeat top right transparent;
|
background: url(../images/actions_right.png?v=v2.4.0) no-repeat top right transparent;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
@@ -648,7 +659,7 @@ td a.dp-choose-date, a.dp-choose-date, td a.dp-choose-date:hover, a.dp-choose-da
|
|||||||
display: block;
|
display: block;
|
||||||
text-indent: -2000px;
|
text-indent: -2000px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: url(../images/calendar.png?v=v2.4.0-beta) no-repeat;
|
background: url(../images/calendar.png?v=v2.4.0) no-repeat;
|
||||||
}
|
}
|
||||||
td a.dp-choose-date.dp-disabled, a.dp-choose-date.dp-disabled {
|
td a.dp-choose-date.dp-disabled, a.dp-choose-date.dp-disabled {
|
||||||
background-position: 0 -20px;
|
background-position: 0 -20px;
|
||||||
@@ -745,19 +756,19 @@ div.HRDrawer {
|
|||||||
}
|
}
|
||||||
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
||||||
table.listResults tr.odd td.truncated, table.listResults tr td.truncated, .wizContainer table.listResults tr.odd td.truncated, .wizContainer table.listResults tr td.truncated {
|
table.listResults tr.odd td.truncated, table.listResults tr td.truncated, .wizContainer table.listResults tr.odd td.truncated, .wizContainer table.listResults tr td.truncated {
|
||||||
background: url(../images/truncated.png?v=v2.4.0-beta) bottom repeat-x;
|
background: url(../images/truncated.png?v=v2.4.0) bottom repeat-x;
|
||||||
}
|
}
|
||||||
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
||||||
table.listResults tr.even td.truncated, .wizContainer table.listResults tr.even td.truncated {
|
table.listResults tr.even td.truncated, .wizContainer table.listResults tr.even td.truncated {
|
||||||
background: #f9f9f1 url(../images/truncated.png?v=v2.4.0-beta) bottom repeat-x;
|
background: #f9f9f1 url(../images/truncated.png?v=v2.4.0) bottom repeat-x;
|
||||||
}
|
}
|
||||||
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
||||||
table.listResults tr.even td.hover.truncated, .wizContainer table.listResults tr.even td.hover.truncated {
|
table.listResults tr.even td.hover.truncated, .wizContainer table.listResults tr.even td.hover.truncated {
|
||||||
background: #fdf5d0 url(../images/truncated.png?v=v2.4.0-beta) bottom repeat-x;
|
background: #fdf5d0 url(../images/truncated.png?v=v2.4.0) bottom repeat-x;
|
||||||
}
|
}
|
||||||
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
||||||
table.listResults tr.odd td.hover.truncated, table.listResults tr td.hover.truncated, .wizContainer table.listResults tr.odd td.hover.truncated, .wizContainer table.listResults tr td.hover.truncated {
|
table.listResults tr.odd td.hover.truncated, table.listResults tr td.hover.truncated, .wizContainer table.listResults tr.odd td.hover.truncated, .wizContainer table.listResults tr td.hover.truncated {
|
||||||
background: #fdf5d0 url(../images/truncated.png?v=v2.4.0-beta) bottom repeat-x;
|
background: #fdf5d0 url(../images/truncated.png?v=v2.4.0) bottom repeat-x;
|
||||||
}
|
}
|
||||||
table.listResults.truncated {
|
table.listResults.truncated {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
@@ -865,7 +876,7 @@ div#logo {
|
|||||||
div#logo div {
|
div#logo div {
|
||||||
height: 88px;
|
height: 88px;
|
||||||
width: 244px;
|
width: 244px;
|
||||||
background: url(../images/itop-logo-2.png?v=v2.4.0-beta) left no-repeat;
|
background: url(../images/itop-logo-2.png?v=v2.4.0) left no-repeat;
|
||||||
}
|
}
|
||||||
#left-pane .ui-layout-north {
|
#left-pane .ui-layout-north {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -957,7 +968,7 @@ div#logo div {
|
|||||||
}
|
}
|
||||||
#global-search-image {
|
#global-search-image {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
background: url(../images/search.png?v=v2.4.0-beta) center center no-repeat;
|
background: url(../images/search.png?v=v2.4.0) center center no-repeat;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
@@ -986,7 +997,7 @@ span.ui-icon {
|
|||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
}
|
}
|
||||||
.ui-layout-button-pin-down {
|
.ui-layout-button-pin-down {
|
||||||
background: url(../images/splitter-bkg.png?v=v2.4.0-beta) transparent;
|
background: url(../images/splitter-bkg.png?v=v2.4.0) transparent;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
background-position: -144px -144px;
|
background-position: -144px -144px;
|
||||||
}
|
}
|
||||||
@@ -1152,6 +1163,17 @@ span.form_validation {
|
|||||||
margin-top: 0.25em;
|
margin-top: 0.25em;
|
||||||
margin-bottom: 0.25em;
|
margin-bottom: 0.25em;
|
||||||
}
|
}
|
||||||
|
/* Helper classes for object details display. */
|
||||||
|
.one-col-details {
|
||||||
|
min-width: 400px;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
.n-cols-details {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.n-cols-details > tbody > tr > td {
|
||||||
|
min-width: 240px;
|
||||||
|
}
|
||||||
.details {
|
.details {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
noborder-bottom: 2px #fff solid;
|
noborder-bottom: 2px #fff solid;
|
||||||
@@ -1187,6 +1209,10 @@ fieldset .details > .field_container {
|
|||||||
width: inherit;
|
width: inherit;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
.field_container.field_large > div.field_data {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
.field_container * {
|
.field_container * {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
@@ -1347,6 +1373,13 @@ fieldset .details > .field_container {
|
|||||||
.field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn > img {
|
.field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn > img {
|
||||||
max-width: 20px;
|
max-width: 20px;
|
||||||
}
|
}
|
||||||
|
.one-col-details .details .field_container.field_small {
|
||||||
|
/* On a single column, field labels can take more width but they are limited so it doesn't feel weird when all labels are short */
|
||||||
|
}
|
||||||
|
.one-col-details .details .field_container.field_small div.field_label {
|
||||||
|
width: 175px;
|
||||||
|
max-width: inherit;
|
||||||
|
}
|
||||||
/* This is extracted from the ".details > .field_container ..." because of the fullscreen option (element is moved at the end of the body */
|
/* This is extracted from the ".details > .field_container ..." because of the fullscreen option (element is moved at the end of the body */
|
||||||
.field_input_text {
|
.field_input_text {
|
||||||
border: none;
|
border: none;
|
||||||
@@ -1408,6 +1441,9 @@ fieldset .details > .field_container {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
#SiloSelection .ac_input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
#SiloSelection .field_input_extkey {
|
#SiloSelection .field_input_extkey {
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -1422,8 +1458,8 @@ fieldset .details > .field_container {
|
|||||||
}
|
}
|
||||||
#SiloSelection .field_input_extkey .field_input_btn {
|
#SiloSelection .field_input_extkey .field_input_btn {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
width: 20px;
|
width: 25px;
|
||||||
margin-left: 0.4em;
|
padding-left: 0.4em;
|
||||||
}
|
}
|
||||||
.ac_dlg_loading {
|
.ac_dlg_loading {
|
||||||
background: white url('../images/indicator.gif') right center no-repeat;
|
background: white url('../images/indicator.gif') right center no-repeat;
|
||||||
@@ -1461,7 +1497,7 @@ img.prev, img.first, img.next, img.last {
|
|||||||
}
|
}
|
||||||
div.actions_button {
|
div.actions_button {
|
||||||
float: right;
|
float: right;
|
||||||
background: #e87c1e url("../images/actions_left.png?v=v2.4.0-beta") no-repeat scroll left top;
|
background: #e87c1e url("../images/actions_left.png?v=v2.4.0") no-repeat scroll left top;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
@@ -1469,7 +1505,7 @@ div.actions_button {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
div.actions_button a, .actions_button a:hover, .actions_button a:visited {
|
div.actions_button a, .actions_button a:hover, .actions_button a:visited {
|
||||||
background: #e87c1e url(../images/actions_bkg.png?v=v2.4.0-beta) no-repeat scroll right top;
|
background: #e87c1e url(../images/actions_bkg.png?v=v2.4.0) no-repeat scroll right top;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -1493,10 +1529,10 @@ select#org_id {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.dragHover {
|
.dragHover {
|
||||||
background: url(./ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=v2.4.0-beta);
|
background: url(./ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=v2.4.0);
|
||||||
}
|
}
|
||||||
.edit_mode .dashlet {
|
.edit_mode .dashlet {
|
||||||
background: url(./ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=v2.4.0-beta);
|
background: url(./ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=v2.4.0);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -1514,6 +1550,7 @@ td.layout_cell {
|
|||||||
.dashlet-content {
|
.dashlet-content {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
table.prop_table {
|
table.prop_table {
|
||||||
border-bottom: 2px solid #f9f9f1;
|
border-bottom: 2px solid #f9f9f1;
|
||||||
@@ -1528,7 +1565,7 @@ table.prop_table {
|
|||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
background: transparent url(../images/delete.png?v=v2.4.0-beta) no-repeat center;
|
background: transparent url(../images/delete.png?v=v2.4.0) no-repeat center;
|
||||||
}
|
}
|
||||||
td.prop_value {
|
td.prop_value {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -1722,17 +1759,17 @@ a.summary, a.summary:hover {
|
|||||||
}
|
}
|
||||||
.message_info {
|
.message_info {
|
||||||
border: 1px solid #993;
|
border: 1px solid #993;
|
||||||
background: url(../images/info-mini.png?v=v2.4.0-beta) 1em 1em no-repeat #ffc;
|
background: url(../images/info-mini.png?v=v2.4.0) 1em 1em no-repeat #ffc;
|
||||||
padding-left: 3em;
|
padding-left: 3em;
|
||||||
}
|
}
|
||||||
.message_ok {
|
.message_ok {
|
||||||
border: 1px solid #393;
|
border: 1px solid #393;
|
||||||
background: url(../images/ok.png?v=v2.4.0-beta) 1em 1em no-repeat #cfc;
|
background: url(../images/ok.png?v=v2.4.0) 1em 1em no-repeat #cfc;
|
||||||
padding-left: 3em;
|
padding-left: 3em;
|
||||||
}
|
}
|
||||||
.message_error {
|
.message_error {
|
||||||
border: 1px solid #933;
|
border: 1px solid #933;
|
||||||
background: url(../images/error.png?v=v2.4.0-beta) 1em 1em no-repeat #fcc;
|
background: url(../images/error.png?v=v2.4.0) 1em 1em no-repeat #fcc;
|
||||||
padding-left: 3em;
|
padding-left: 3em;
|
||||||
}
|
}
|
||||||
.fg-menu a img {
|
.fg-menu a img {
|
||||||
@@ -1863,18 +1900,18 @@ div.explain-printable {
|
|||||||
}
|
}
|
||||||
#hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span {
|
#hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
background: url(../images/eye-open-555.png?v=v2.4.0-beta) 2px center no-repeat;
|
background: url(../images/eye-open-555.png?v=v2.4.0) 2px center no-repeat;
|
||||||
}
|
}
|
||||||
#hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span {
|
#hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
background: url(../images/eye-closed-555.png?v=v2.4.0-beta) 2px center no-repeat;
|
background: url(../images/eye-closed-555.png?v=v2.4.0) 2px center no-repeat;
|
||||||
}
|
}
|
||||||
.printable-version legend {
|
.printable-version legend {
|
||||||
padding-left: 26px;
|
padding-left: 26px;
|
||||||
background: #1c94c4 url(../images/eye-open-fff.png?v=v2.4.0-beta) 8px center no-repeat;
|
background: #1c94c4 url(../images/eye-open-fff.png?v=v2.4.0) 8px center no-repeat;
|
||||||
}
|
}
|
||||||
.printable-version .strikethrough legend {
|
.printable-version .strikethrough legend {
|
||||||
background: #1c94c4 url(../images/eye-closed-fff.png?v=v2.4.0-beta) 8px center no-repeat;
|
background: #1c94c4 url(../images/eye-closed-fff.png?v=v2.4.0) 8px center no-repeat;
|
||||||
}
|
}
|
||||||
.printable-version fieldset.strikethrough span {
|
.printable-version fieldset.strikethrough span {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -1893,7 +1930,7 @@ span.refresh-button {
|
|||||||
width: 21px;
|
width: 21px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: transparent url(../images/refresh-fff.png?v=v2.4.0-beta) left center no-repeat;
|
background: transparent url(../images/refresh-fff.png?v=v2.4.0) left center no-repeat;
|
||||||
}
|
}
|
||||||
.case-log-history-entry {
|
.case-log-history-entry {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -2021,7 +2058,7 @@ span.refresh-button {
|
|||||||
#itop-breadcrumb .breadcrumb-item a::after {
|
#itop-breadcrumb .breadcrumb-item a::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-image: url(../images/breadcrumb-separator.png?v=v2.4.0-beta);
|
background-image: url(../images/breadcrumb-separator.png?v=v2.4.0);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ body {
|
|||||||
font-family: Tahoma, Verdana, Arial, Helvetica;
|
font-family: Tahoma, Verdana, Arial, Helvetica;
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
|
background-color: white;
|
||||||
margin: 0; /* Remove body margin/padding */
|
margin: 0; /* Remove body margin/padding */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden; /* Remove scroll bars on browser window */
|
overflow: hidden; /* Remove scroll bars on browser window */
|
||||||
@@ -35,6 +36,14 @@ body.printable-version {
|
|||||||
.ui-layout-content {
|
.ui-layout-content {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
.ui-layout-content .ui-tabs-nav li {
|
||||||
|
/* Overriding jQuery UI theme to see active tab better */
|
||||||
|
margin-bottom: 2px;
|
||||||
|
|
||||||
|
&.ui-tabs-active{
|
||||||
|
padding-bottom: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.raw_output {
|
.raw_output {
|
||||||
font-family: Courier-New, Courier, Arial, Helvetica;
|
font-family: Courier-New, Courier, Arial, Helvetica;
|
||||||
@@ -107,6 +116,12 @@ table.listResults td .view-image {
|
|||||||
.view-image {
|
.view-image {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
|
img[src=""],
|
||||||
|
img[src="null"] {
|
||||||
|
// Hiding "broken" image when src is not set
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
&.dirty {
|
&.dirty {
|
||||||
// The image will be modified when saving the changes
|
// The image will be modified when saving the changes
|
||||||
|
|
||||||
@@ -835,7 +850,7 @@ table.listResults tr.even td.truncated, .wizContainer table.listResults tr.even
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
|
||||||
table.listResults tr.even td.hover.truncated, , .wizContainer table.listResults tr.even td.hover.truncated {
|
table.listResults tr.even td.hover.truncated, .wizContainer table.listResults tr.even td.hover.truncated {
|
||||||
background: #fdf5d0 url(../images/truncated.png?v=#{$version}) bottom repeat-x;
|
background: #fdf5d0 url(../images/truncated.png?v=#{$version}) bottom repeat-x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1245,6 +1260,18 @@ span.form_validation {
|
|||||||
margin-bottom: 0.25em;
|
margin-bottom: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper classes for object details display. */
|
||||||
|
.one-col-details {
|
||||||
|
min-width: 400px;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
.n-cols-details {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
> tbody > tr > td {
|
||||||
|
min-width: 240px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.details {
|
.details {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
noborder-bottom: 2px #fff solid;
|
noborder-bottom: 2px #fff solid;
|
||||||
@@ -1269,18 +1296,23 @@ fieldset .details>.field_container {
|
|||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.field_large{
|
&.field_large {
|
||||||
display: inherit;
|
display: inherit;
|
||||||
|
|
||||||
/* .field_label, .field_data */
|
/* .field_label, .field_data */
|
||||||
> div {
|
> div {
|
||||||
display: inherit;
|
display: inherit;
|
||||||
|
|
||||||
&.field_label{
|
&.field_label {
|
||||||
width: inherit;
|
width: inherit;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.field_data {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/* .field_value, .field_comments, .field_infos */
|
/* .field_value, .field_comments, .field_infos */
|
||||||
> div {
|
> div {
|
||||||
}
|
}
|
||||||
@@ -1496,6 +1528,13 @@ fieldset .details>.field_container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.one-col-details .details .field_container.field_small {
|
||||||
|
div.field_label {
|
||||||
|
/* On a single column, field labels can take more width but they are limited so it doesn't feel weird when all labels are short */
|
||||||
|
width: 175px;
|
||||||
|
max-width: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* This is extracted from the ".details > .field_container ..." because of the fullscreen option (element is moved at the end of the body */
|
/* This is extracted from the ".details > .field_container ..." because of the fullscreen option (element is moved at the end of the body */
|
||||||
.field_input_text{
|
.field_input_text{
|
||||||
border: none;
|
border: none;
|
||||||
@@ -1563,6 +1602,10 @@ fieldset .details>.field_container {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ac_input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.field_input_extkey{
|
.field_input_extkey{
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -1579,8 +1622,8 @@ fieldset .details>.field_container {
|
|||||||
|
|
||||||
.field_input_btn{
|
.field_input_btn{
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
width: 20px;
|
width: 25px;
|
||||||
margin-left: 0.4em;
|
padding-left: 0.4em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1674,6 +1717,7 @@ td.layout_cell {
|
|||||||
.dashlet-content {
|
.dashlet-content {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
margin:0;
|
margin:0;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
table.prop_table {
|
table.prop_table {
|
||||||
border-bottom: 2px solid #F9F9F1;
|
border-bottom: 2px solid #F9F9F1;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -21,13 +21,13 @@
|
|||||||
* Authent External
|
* Authent External
|
||||||
* Module definition file for the "External Authentication" module
|
* Module definition file for the "External Authentication" module
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SetupWebPage::AddModule(
|
SetupWebPage::AddModule(
|
||||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||||
'authent-external/2.2.0',
|
'authent-external/2.4.0',
|
||||||
array(
|
array(
|
||||||
// Identification
|
// Identification
|
||||||
//
|
//
|
||||||
@@ -63,4 +63,3 @@ SetupWebPage::AddModule(
|
|||||||
'settings' => array(),
|
'settings' => array(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
?>
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
/**
|
/**
|
||||||
* Localized data
|
* Localized data
|
||||||
*
|
*
|
||||||
* @author Robert Deng <denglx@gmail.com>
|
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
@@ -41,7 +40,7 @@
|
|||||||
|
|
||||||
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||||
'Class:UserExternal' => '外部用户',
|
'Class:UserExternal' => '外部用户',
|
||||||
'Class:UserExternal+' => '用户在 iTop 外部验证身份',
|
'Class:UserExternal+' => '用户在iTop 之外验证身份',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ if (function_exists('ldap_connect'))
|
|||||||
|
|
||||||
SetupWebPage::AddModule(
|
SetupWebPage::AddModule(
|
||||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||||
'authent-ldap/2.2.0',
|
'authent-ldap/2.4.0',
|
||||||
array(
|
array(
|
||||||
// Identification
|
// Identification
|
||||||
//
|
//
|
||||||
@@ -63,5 +63,3 @@ SetupWebPage::AddModule(
|
|||||||
);
|
);
|
||||||
|
|
||||||
} // if (function_exists('ldap_connect'))
|
} // if (function_exists('ldap_connect'))
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
/**
|
/**
|
||||||
* Localized data
|
* Localized data
|
||||||
*
|
*
|
||||||
* @author Robert Deng <denglx@gmail.com>
|
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
@@ -41,9 +40,9 @@
|
|||||||
|
|
||||||
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||||
'Class:UserLDAP' => 'LDAP 用户',
|
'Class:UserLDAP' => 'LDAP 用户',
|
||||||
'Class:UserLDAP+' => '用户由 LDAP 鉴别身份',
|
'Class:UserLDAP+' => '用户身份由LDAP 认证',
|
||||||
'Class:UserLDAP/Attribute:password' => '密码',
|
'Class:UserLDAP/Attribute:password' => '密码',
|
||||||
'Class:UserLDAP/Attribute:password+' => '用户身份验证串',
|
'Class:UserLDAP/Attribute:password+' => '用于验证用户身份的字符串',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
SetupWebPage::AddModule(
|
SetupWebPage::AddModule(
|
||||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||||
'authent-local/2.2.0',
|
'authent-local/2.4.0',
|
||||||
array(
|
array(
|
||||||
// Identification
|
// Identification
|
||||||
//
|
//
|
||||||
@@ -40,5 +40,3 @@ SetupWebPage::AddModule(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
/**
|
/**
|
||||||
* Localized data
|
* Localized data
|
||||||
*
|
*
|
||||||
* @author Robert Deng <denglx@gmail.com>
|
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
@@ -41,9 +40,9 @@
|
|||||||
|
|
||||||
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||||
'Class:UserLocal' => 'iTop 用户',
|
'Class:UserLocal' => 'iTop 用户',
|
||||||
'Class:UserLocal+' => '用户由 iTop 验证身份',
|
'Class:UserLocal+' => '用户身份由iTop 验证',
|
||||||
'Class:UserLocal/Attribute:password' => '密码',
|
'Class:UserLocal/Attribute:password' => '密码',
|
||||||
'Class:UserLocal/Attribute:password+' => '用户身份验证串',
|
'Class:UserLocal/Attribute:password+' => '用户身份验证字符串',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
<module>itop-profiles-itil</module>
|
<module>itop-profiles-itil</module>
|
||||||
<module>itop-welcome-itil</module>
|
<module>itop-welcome-itil</module>
|
||||||
<module>itop-tickets</module>
|
<module>itop-tickets</module>
|
||||||
|
<module>itop-hub-connector</module>
|
||||||
</modules>
|
</modules>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
</choice>
|
</choice>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">
|
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
|
||||||
<classes>
|
<classes>
|
||||||
<class id="Attachment" _delta="define">
|
<class id="Attachment" _delta="define">
|
||||||
<parent>DBObject</parent>
|
<parent>DBObject</parent>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2014 Combodo SARL
|
// Copyright (C) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -39,4 +39,3 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
|||||||
'Attachments:NoAttachment' => 'Kein Attachment. ',
|
'Attachments:NoAttachment' => 'Kein Attachment. ',
|
||||||
'Attachments:PreviewNotAvailable' => 'Vorschau für diesen Attachment-Typ nicht verfügbar.',
|
'Attachments:PreviewNotAvailable' => 'Vorschau für diesen Attachment-Typ nicht verfügbar.',
|
||||||
));
|
));
|
||||||
?>
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2016 Combodo SARL
|
// Copyright (C) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
SetupWebPage::AddModule(
|
SetupWebPage::AddModule(
|
||||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||||
'itop-attachments/2.3.0',
|
'itop-attachments/2.4.0',
|
||||||
array(
|
array(
|
||||||
// Identification
|
// Identification
|
||||||
//
|
//
|
||||||
@@ -145,5 +145,3 @@ if (!class_exists('AttachmentInstaller'))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
|||||||
'Attachment:Max_Ko' => '(Максимальный размер файла: %1$s кБ)',
|
'Attachment:Max_Ko' => '(Максимальный размер файла: %1$s кБ)',
|
||||||
'Attachments:NoAttachment' => 'Нет вложений.',
|
'Attachments:NoAttachment' => 'Нет вложений.',
|
||||||
'Attachments:PreviewNotAvailable' => 'Предварительный просмотр не доступен для этого типа вложений.',
|
'Attachments:PreviewNotAvailable' => 'Предварительный просмотр не доступен для этого типа вложений.',
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
// Copyright (C) 2010-2012 Combodo SARL
|
||||||
|
//
|
||||||
|
// This file is part of iTop.
|
||||||
|
//
|
||||||
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// iTop is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localized data
|
||||||
|
*
|
||||||
|
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||||
|
'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_Mo' => '(最大文件尺寸: %1$s MB)',
|
||||||
|
'Attachment:Max_Ko' => '(最大文件尺寸: %1$s KB)',
|
||||||
|
'Attachments:NoAttachment' => '没有附件. ',
|
||||||
|
'Attachments:PreviewNotAvailable' => '该附件类型不支持预览.',
|
||||||
|
));
|
||||||
|
?>
|
||||||
@@ -61,6 +61,7 @@ try
|
|||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
$oPage->p('Error: '.$e->getMessage());
|
$oPage->p('Error: '.$e->getMessage());
|
||||||
|
IssueLog::Error($sOperation.' - '.$e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$oPage->output();
|
$oPage->output();
|
||||||
@@ -156,6 +157,7 @@ EOF
|
|||||||
{
|
{
|
||||||
$oRestoreMutex->Unlock();
|
$oRestoreMutex->Unlock();
|
||||||
$oPage->p('Error: '.$e->getMessage());
|
$oPage->p('Error: '.$e->getMessage());
|
||||||
|
IssueLog::Error($sOperation.' - '.$e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$oPage->output();
|
$oPage->output();
|
||||||
@@ -179,6 +181,6 @@ EOF
|
|||||||
}
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
IssueLog::Error($e->getMessage());
|
IssueLog::Error($sOperation.' - '.$e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ catch(Exception $e)
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sZipArchiveFile = MakeArchiveFileName();
|
$sZipArchiveFile = MakeArchiveFileName().'.tar.gz';
|
||||||
echo date('Y-m-d H:i:s')." - Checking file: $sZipArchiveFile\n";
|
echo date('Y-m-d H:i:s')." - Checking file: $sZipArchiveFile\n";
|
||||||
|
|
||||||
if (file_exists($sZipArchiveFile))
|
if (file_exists($sZipArchiveFile))
|
||||||
@@ -223,7 +223,7 @@ if (file_exists($sZipArchiveFile))
|
|||||||
if ($iSize > $iMIN)
|
if ($iSize > $iMIN)
|
||||||
{
|
{
|
||||||
echo "Found the archive\n";
|
echo "Found the archive\n";
|
||||||
$sOldArchiveFile = MakeArchiveFileName(time() - 86400); // yesterday's archive
|
$sOldArchiveFile = MakeArchiveFileName(time() - 86400).'.tar.gz'; // yesterday's archive
|
||||||
if (file_exists($sOldArchiveFile))
|
if (file_exists($sOldArchiveFile))
|
||||||
{
|
{
|
||||||
if ($aOldStat = stat($sOldArchiveFile))
|
if ($aOldStat = stat($sOldArchiveFile))
|
||||||
|
|||||||
@@ -99,8 +99,10 @@ class DBRestore extends DBBackup
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $sFile A file with the extension .zip or .tar.gz
|
* @param string $sFile A file with the extension .zip or .tar.gz
|
||||||
* @param string $sEnvironment Target environment
|
* @param string $sEnvironment Target environment
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function RestoreFromCompressedBackup($sFile, $sEnvironment = 'production')
|
public function RestoreFromCompressedBackup($sFile, $sEnvironment = 'production')
|
||||||
{
|
{
|
||||||
@@ -111,7 +113,7 @@ class DBRestore extends DBBackup
|
|||||||
{
|
{
|
||||||
$this->LogInfo('zip file detected');
|
$this->LogInfo('zip file detected');
|
||||||
$oArchive = new ZipArchiveEx();
|
$oArchive = new ZipArchiveEx();
|
||||||
$res = $oArchive->open($sFile);
|
$oArchive->open($sFile);
|
||||||
}
|
}
|
||||||
elseif (substr($sNormalizedFile, -7) == '.tar.gz')
|
elseif (substr($sNormalizedFile, -7) == '.tar.gz')
|
||||||
{
|
{
|
||||||
@@ -125,21 +127,22 @@ class DBRestore extends DBBackup
|
|||||||
|
|
||||||
// Load the database
|
// Load the database
|
||||||
//
|
//
|
||||||
$sDataDir = tempnam(SetupUtils::GetTmpDir(), 'itop-');
|
$sDataDir = APPROOT.'data/tmp-backup-'.rand(10000, getrandmax());
|
||||||
unlink($sDataDir); // I need a directory, not a file...
|
|
||||||
SetupUtils::builddir($sDataDir); // Here is the directory
|
SetupUtils::builddir($sDataDir); // Here is the directory
|
||||||
$oArchive->extractFileTo($sDataDir, 'itop-dump.sql');
|
$oArchive->extractTo($sDataDir);
|
||||||
|
|
||||||
$sDataFile = $sDataDir.'/itop-dump.sql';
|
$sDataFile = $sDataDir.'/itop-dump.sql';
|
||||||
$this->LoadDatabase($sDataFile);
|
$this->LoadDatabase($sDataFile);
|
||||||
unlink($sDataFile);
|
|
||||||
|
|
||||||
// Update the code
|
// Update the code
|
||||||
//
|
//
|
||||||
$sDeltaFile = APPROOT.'data/'.$sEnvironment.'.delta.xml';
|
$sDeltaFile = APPROOT.'data/'.$sEnvironment.'.delta.xml';
|
||||||
if ($oArchive->hasFile('delta.xml') !== false)
|
|
||||||
|
if (is_file($sDataDir.'/delta.xml'))
|
||||||
{
|
{
|
||||||
// Extract and rename delta.xml => <env>.delta.xml;
|
// Extract and rename delta.xml => <env>.delta.xml;
|
||||||
file_put_contents($sDeltaFile, $oArchive->getFromName('delta.xml'));
|
rename($sDataDir.'/delta.xml', $sDeltaFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -149,16 +152,18 @@ class DBRestore extends DBBackup
|
|||||||
{
|
{
|
||||||
SetupUtils::rrmdir(APPROOT.'data/production-modules/');
|
SetupUtils::rrmdir(APPROOT.'data/production-modules/');
|
||||||
}
|
}
|
||||||
if ($oArchive->hasDir('production-modules/') !== false)
|
if (is_dir($sDataDir.'/production-modules'))
|
||||||
{
|
{
|
||||||
$oArchive->extractDirTo(APPROOT.'data/', 'production-modules/');
|
rename($sDataDir.'/production-modules', APPROOT.'data/production-modules/');
|
||||||
}
|
}
|
||||||
|
|
||||||
$sConfigFile = APPROOT.'conf/'.$sEnvironment.'/config-itop.php';
|
$sConfigFile = APPROOT.'conf/'.$sEnvironment.'/config-itop.php';
|
||||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||||
$oArchive->extractFileTo(APPROOT.'conf/'.$sEnvironment, 'config-itop.php');
|
rename($sDataDir.'/config-itop.php', $sConfigFile);
|
||||||
@chmod($sConfigFile, 0444); // Read-only
|
@chmod($sConfigFile, 0444); // Read-only
|
||||||
|
|
||||||
|
SetupUtils::rrmdir($sDataDir);
|
||||||
|
|
||||||
$oEnvironment = new RunTimeEnvironment($sEnvironment);
|
$oEnvironment = new RunTimeEnvironment($sEnvironment);
|
||||||
$oEnvironment->CompileFrom($sEnvironment);
|
$oEnvironment->CompileFrom($sEnvironment);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2014 Combodo SARL
|
// Copyright (C) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -291,4 +291,3 @@ class ItopBackup extends ModuleHandlerAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
SetupWebPage::AddModule(
|
SetupWebPage::AddModule(
|
||||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||||
'itop-backup/2.2.0',
|
'itop-backup/2.4.0',
|
||||||
array(
|
array(
|
||||||
// Identification
|
// Identification
|
||||||
//
|
//
|
||||||
@@ -56,5 +56,3 @@ SetupWebPage::AddModule(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -47,4 +47,3 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
|||||||
'bkp-wait-restore' => 'Пожалуйста, дождитесь завершения восстановления...',
|
'bkp-wait-restore' => 'Пожалуйста, дождитесь завершения восстановления...',
|
||||||
'bkp-success-restore' => 'Восстановление успешно завершено.',
|
'bkp-success-restore' => 'Восстановление успешно завершено.',
|
||||||
));
|
));
|
||||||
?>
|
|
||||||
|
|||||||
46
datamodels/2.x/itop-backup/zh_cn.dict.itop-backup.php
Normal file
46
datamodels/2.x/itop-backup/zh_cn.dict.itop-backup.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Localized data
|
||||||
|
*
|
||||||
|
* @copyright Copyright (C) 2013 Combodo
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||||
|
|
||||||
|
'bkp-backup-running' => '备份正在进行,请稍后...',
|
||||||
|
'bkp-restore-running' => '还原正在进行,请稍等...',
|
||||||
|
|
||||||
|
'Menu:BackupStatus' => '定时备份',
|
||||||
|
'bkp-status-title' => '定时备份',
|
||||||
|
'bkp-status-checks' => '设置与检查',
|
||||||
|
'bkp-mysqldump-ok' => '已找到mysqldump : %1$s',
|
||||||
|
'bkp-mysqldump-notfound' => 'mysqldump 找不到: %1$s - 请确认它安装在正确的路径, 或者调整iTop 配置文件的选项mysql_bindir.',
|
||||||
|
'bkp-mysqldump-issue' => 'mysqldump 无法运行 (retcode=%1$d): 请确认它安装在正确的路径, 或者调整iTop 配置文件的选项mysql_bindir',
|
||||||
|
'bkp-missing-dir' => '目标目录 %1$s 找不到',
|
||||||
|
'bkp-free-disk-space' => '<b>%1$s 空闲</b> 在 %2$s',
|
||||||
|
'bkp-dir-not-writeable' => '%1$s 没有写入权限',
|
||||||
|
'bkp-wrong-format-spec' => '当前文件名格式错误 (%1$s). 默认格式应该是: %2$s',
|
||||||
|
'bkp-name-sample' => '备份文件将以数据库名、日期和时间进行命名. 例如: %1$s',
|
||||||
|
'bkp-week-days' => '在每个 <b> %1$s 的 %2$s</b> 进行备份',
|
||||||
|
'bkp-retention' => '最多 <b>%1$d 份备份文件 </b> 在目标目录.',
|
||||||
|
'bkp-next-to-delete' => '当下一次备份时将被删除 (see the setting "retention_count")',
|
||||||
|
'bkp-table-file' => 'File',
|
||||||
|
'bkp-table-file+' => '只有扩展名是.zip的文件才被认为是备份文件',
|
||||||
|
'bkp-table-size' => '大小',
|
||||||
|
'bkp-table-size+' => '',
|
||||||
|
'bkp-table-actions' => '操作',
|
||||||
|
'bkp-table-actions+' => '',
|
||||||
|
'bkp-status-backups-auto' => '定时备份',
|
||||||
|
'bkp-status-backups-manual' => '手动备份',
|
||||||
|
'bkp-status-backups-none' => '尚未开始备份',
|
||||||
|
'bkp-next-backup' => '下一次备份将发生在 <b>%1$s</b> (%2$s) 的 %3$s',
|
||||||
|
'bkp-button-backup-now' => '立即备份!',
|
||||||
|
'bkp-button-restore-now' => '还原!',
|
||||||
|
'bkp-confirm-backup' => '请确认是否立即开始备份.',
|
||||||
|
'bkp-confirm-restore' => '请确认要还原的备份文件是 %1$s.',
|
||||||
|
'bkp-wait-backup' => '请等待备份完成...',
|
||||||
|
'bkp-wait-restore' => '请等待还原完成...',
|
||||||
|
'bkp-success-restore' => '还原成功.',
|
||||||
|
));
|
||||||
|
?>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">
|
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
|
||||||
<classes>
|
<classes>
|
||||||
<class id="lnkVirtualDeviceToVolume" _delta="define">
|
<class id="lnkVirtualDeviceToVolume" _delta="define">
|
||||||
<parent>cmdbAbstractObject</parent>
|
<parent>cmdbAbstractObject</parent>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
SetupWebPage::AddModule(
|
SetupWebPage::AddModule(
|
||||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||||
'itop-bridge-virtualization-storage/2.3.0',
|
'itop-bridge-virtualization-storage/2.4.0',
|
||||||
array(
|
array(
|
||||||
// Identification
|
// Identification
|
||||||
//
|
//
|
||||||
@@ -43,6 +43,3 @@ SetupWebPage::AddModule(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">
|
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
|
||||||
<classes>
|
<classes>
|
||||||
<class id="Change" _delta="define">
|
<class id="Change" _delta="define">
|
||||||
<parent>Ticket</parent>
|
<parent>Ticket</parent>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<comment><![CDATA[/**
|
<comment><![CDATA[/**
|
||||||
* Persistent classes for a CMDB
|
* Persistent classes for a CMDB
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/]]></comment>
|
*/]]></comment>
|
||||||
<category>bizmodel,searchable,changemgmt</category>
|
<category>bizmodel,searchable,changemgmt</category>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2014 Combodo SARL
|
// Copyright (C) 2010-2017 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
SetupWebPage::AddModule(
|
SetupWebPage::AddModule(
|
||||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||||
'itop-change-mgmt-itil/2.3.0',
|
'itop-change-mgmt-itil/2.4.0',
|
||||||
array(
|
array(
|
||||||
// Identification
|
// Identification
|
||||||
//
|
//
|
||||||
@@ -42,5 +42,3 @@ SetupWebPage::AddModule(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user