Compare commits

..

44 Commits
N941 ... 2.5.4

Author SHA1 Message Date
Molkobain
3dbbf296b8 Exclude combodo-db-tools module from packages by default 2020-01-22 09:10:54 +01:00
Stephen Abello
878c23892d Update version number for 2.5.4 2020-01-20 15:59:08 +01:00
Stephen Abello
248dab9289 N°2633 - Security hardening 2020-01-20 15:46:04 +01:00
Molkobain
3347f400b8 Internal: Revert files deleted by mistake 🙈 2020-01-08 11:57:29 +01:00
Molkobain
6082308e20 Add combodo-db-tools/1.0.7 module as a default module 2020-01-08 11:40:35 +01:00
Pierre Goiffon
b3369c8b0e Update version number for 2.5.3 beta 2019-07-02 14:54:36 +02:00
bruno DA SILVA
6c948873ff N°2323.6 Fix regression introduced in previous commit 2019-06-26 15:38:42 +02:00
Molkobain
93099ea3c7 N°2323.5 Fix regression introduced in previous commit
Could not upload images in HTML field anymore
2019-06-21 10:01:31 +02:00
Molkobain
2f9e050e2b N°2323.4 Fix regression introduced in previous commit
Current user picture was no longer displayed in the portal

(cherry picked from commit 56b9eb6cf3)
2019-06-20 17:52:26 +02:00
Eric
02c78d4044 N°2278 - Object-copier: Fix n:n link attributes set to default on copy
(cherry picked from commit 6564d84a2f)
2019-06-18 14:57:45 +02:00
Eric
5102b113ed N°2323 - Fix calls to ajax endpoints
(cherry picked from commit c723d19e01)
2019-06-18 10:45:50 +02:00
Eric
f1e4d94499 N°2323 - Fix calls to ajax endpoints for portal 2019-06-18 10:43:45 +02:00
OИUЯd da silva
23cf2b91f4 make demo_mode effect more expressive
closes #71
2019-05-06 11:42:27 +02:00
Thomas Casteleyn
2858d13fd5 🐛 Fix default usage of iTopMutex when TLS is enabled
See R-021467
2019-04-29 11:18:54 +02:00
Molkobain
16c8466841 N°2115 Fix regression introduced in N°1443: Left pane menu not showing due a JS error 2019-03-25 15:39:45 +01:00
Eric
764b0f8e31 N°1846 - Fix Object Copier: Create Ticket from CI, duplicate links
(cherry picked from commit 44b7821015)
2019-03-22 11:06:23 +01:00
Pierre Goiffon
7c7382f372 N°1835 add new 'transaction_id' sanitize filter 2019-03-21 14:28:24 +01:00
Pierre Goiffon
9f0e8dc49b 📦 Update CSS for 2.5.2 2019-03-19 11:47:29 +01:00
Pierre Goiffon
b8d5c01382 📦 Update versions for 2.5.2 2019-03-19 11:37:15 +01:00
Pierre Goiffon
d3db77c675 📦 Update modules versions for 2.5.2 2019-03-19 11:29:37 +01:00
Pierre Goiffon
533e65fcd1 🌐 Fix dict automatic update 2019-03-19 10:52:43 +01:00
Pierre Goiffon
3fb0c768e6 🌐 Update dictionnaries for iTop 2.5.2 2019-03-19 10:10:28 +01:00
Molkobain
3322074ce7 🐛 N°1889 Portal: Wrong encoding of special chars like in dashlets (eg. "ö", "&", ...)
(cherry picked from commit 83bb3b6d72)
2019-03-13 17:01:57 +01:00
Eric
229f800266 N° 1837 - Fix Synchro Obsolescence
(cherry picked from commit 75737b4ffe)
2019-03-13 14:19:25 +01:00
Molkobain
75a0979eee N°2045 Portal: Fix regression introduced with N°1980: New request with 2 Request Templates does not display fields 2019-03-06 14:46:01 +01:00
Pierre Goiffon
d6a0a279a5 N°1449 Update REST API version for new pagination params 2019-03-04 16:00:36 +01:00
Pierre Goiffon
44f5d71e1b 💡 PHPDoc for REST API 2019-03-04 16:00:35 +01:00
Pierre Goiffon
3de7aa1ada 🙈 Update ignore file 2019-03-04 09:15:38 +01:00
Stephen Abello
d4fec14123 N°1443: Handle disabled selectable rows in datatables when "All checking/unchecking" 2019-03-01 12:18:07 +01:00
Pierre Goiffon
e2c8237beb Allow params "limit" and "page" in REST-API
PR #25, code author Dennis Lassiter, many thanks !
Was commited to develop first but decided to retrofit this on support/2.5 (N°1449)
(cherry picked from commit fd55bdf9a8)
(cherry picked from commit 49e31ddb3d)
2019-02-28 10:06:42 +01:00
Pierre Goiffon
afb99c0f4b N°2054 fix search with sSearchValue GET param in BrowseBrick 2019-02-27 16:21:29 +01:00
Stephen Abello
c5943c6c28 Internal: Fix a regression introduced by 6b5cc7c on dot path 2019-02-22 10:06:10 +01:00
Pierre Goiffon
bc3b50ad23 Fix wrong method call 2019-02-22 10:00:23 +01:00
Pierre Goiffon
2f15bbdaf3 N°2033 backup : tar generation simplify buffer size computation
(cherry picked from commit 5b46644786)
2019-02-21 17:12:18 +01:00
Pierre Goiffon
cdba1e0d36 N°2033 backup : fix corrupted archive for files which size is a multiple of 1024 bytes
(cherry picked from commit 3356856a5f)
2019-02-20 17:29:10 +01:00
Eric
d0a766d424 N°1975 - Fix: Change Menu rights to "Admin only" leads in crash test
(cherry picked from commit a89bca4626)
2019-02-20 15:06:57 +01:00
Pierre Goiffon
23ec21e494 N°2031 backup : now logs using IssueLog, and remove debug config property 2019-02-19 14:46:44 +01:00
Pierre Goiffon
02617e8976 🔊 itop-backup : add some more logs 2019-02-19 12:21:53 +01:00
Stephen Abello
6b5cc7ca4b N°1877 & N°2012: Fix regression backup link on setup, security hardening 2019-02-18 10:40:51 +01:00
Eric
bf62b63173 N°1884 - Admin Tools Manager no longer has access to 'Schedule Backup' and 'Configuration' menus 2019-02-15 17:33:47 +01:00
Eric
b8fb1fa78a N°1884 - Admin Tools Manager no longer has access to 'Schedule Backup' and 'Configuration' menus
(cherry picked from commit 818b4d08da)
2019-02-15 17:31:37 +01:00
Stephen Abello
545504c0de (retrofit from master) N°1443 : Add table_id used by tables paging
(cherry picked from commit 43b0747b83)
2019-02-13 15:13:13 +01:00
Stephen Abello
32f1e97bcd (retrofit from master) N°1148: Fix regression on export
(cherry picked from commit 90e128f951)
2019-02-13 15:13:13 +01:00
Eric
9637e75f97 N°2011: Fix Issue with "ExecAsyncTask: async_task_retries" 2019-02-13 14:07:13 +01:00
773 changed files with 24628 additions and 42179 deletions

View File

@@ -1,9 +0,0 @@
[gitflow "branch"]
master = master
develop = develop
[gitflow "prefix"]
feature = feature/
release = release/
hotfix = hotfix/
versiontag =
support = support/

38
.gitignore vendored
View File

@@ -1,36 +1,37 @@
# no slash at the end to handle also symlinks
/toolkit
/conf/*
/env-*/*
/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
/data/**
!/data/.htaccess
!/data/index.php
!/data/web.config
# iTop extensions
extensions/*
!extensions/readme.txt
/extensions/**
!/extensions/readme.txt
# all logs but listing prevention
log/*
!log/.htaccess
!log/index.php
!log/web.config
/log/**
!/log/.htaccess
!/log/index.php
!/log/web.config
# Jetbrains
.idea/**
!.idea/encodings.xml
!.idea/codeStyles
!.idea/codeStyles/*
!.idea/inspectionProfiles
!.idea/inspectionProfiles/*
/.idea/**
!/.idea/encodings.xml
!/.idea/codeStyles
!/.idea/codeStyles/*
!/.idea/inspectionProfiles
!/.idea/inspectionProfiles/*
@@ -120,4 +121,3 @@ local.properties
.cache-main
.scala_dependencies
.worksheet

View File

@@ -1,11 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" />
<option name="RIGHT_MARGIN" value="320" />
<HTMLCodeStyleSettings>
<option name="HTML_DO_NOT_INDENT_CHILDREN_OF" value="html,body,thead,tbody,tfoot,script,style" />
<option name="HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES" value="4" />
</HTMLCodeStyleSettings>
<PHPCodeStyleSettings>
<option name="CONCAT_SPACES" value="false" />
<option name="PHPDOC_BLANK_LINE_BEFORE_TAGS" value="true" />
@@ -26,7 +20,6 @@
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="PHP">
<option name="RIGHT_MARGIN" value="320" />
<option name="BLANK_LINES_AFTER_PACKAGE" value="1" />
<option name="BRACE_STYLE" value="2" />
<option name="ELSE_ON_NEW_LINE" value="true" />
@@ -48,10 +41,5 @@
<option name="SMART_TABS" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

2
.idea/encodings.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

View File

@@ -1,44 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Combodo" />
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MysqlParsingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpIncludeInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMethodParametersCountMismatchInspection" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="PhpTooManyParametersInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="limit" value="7" />
</inspection_tool>
<inspection_tool class="PhpUndefinedClassInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="DONT_REPORT_MULTI_RESOLVE" value="true" />
</inspection_tool>
<inspection_tool class="PhpUndefinedMethodInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUnhandledExceptionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUnusedLocalVariableInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="DONT_REPORT_INSIDE_LIST" value="true" />
</inspection_tool>
<inspection_tool class="PhpUnusedParameterInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="DONT_REPORT_ABSTRACT_CLASS" value="true" />
</inspection_tool>
<inspection_tool class="SqlAddNotNullColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAmbiguousColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCheckUsingColumnsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlConstantConditionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDeprecateTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDerivedTableAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDropIndexedColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlIdentifierInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertValuesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNullComparisonInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlPostgresqlSelectFromProcedureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlResolveInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlShouldBeInGroupByInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSideEffectsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSignatureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlStorageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@@ -1,19 +1,154 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PhpIncludeInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMethodParametersCountMismatchInspection" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="PhpTooManyParametersInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="limit" value="7" />
<inspection_tool class="BladeControlDirectives" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckEmptyScriptTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckImageSize" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckNodeTest" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckTagEmptyBody" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckValidXmlInScriptTagBody" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptArgumentsOutsideFunction" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptFunctionSignatures" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptInfiniteLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptLiteralNotFunction" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptSillyAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptSwitchStatementWithNoDefaultBranch" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CoffeeScriptUnusedLocalSymbols" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ComposeFileStructure" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssFloatPxLength" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CssInvalidAtRule" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidCharsetRule" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssInvalidElement" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidFunction" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidHtmlTagReference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssInvalidImport" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssInvalidMediaFeature" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidPropertyValue" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssInvalidPseudoSelector" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssMissingComma" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssNegativeValue" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssNoGenericFontName" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssOptimizeSimilarProperties" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CssOverwrittenProperties" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssRedundantUnit" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssUnitlessNumber" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CssUnknownProperty" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myCustomPropertiesEnabled" value="false" />
<option name="myIgnoreVendorSpecificProperties" value="false" />
<option name="myCustomPropertiesList">
<value>
<list size="0" />
</value>
</option>
</inspection_tool>
<inspection_tool class="PhpUndefinedClassInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="DONT_REPORT_MULTI_RESOLVE" value="true" />
<inspection_tool class="CssUnknownTarget" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnresolvedClass" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnresolvedCustomProperty" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnresolvedCustomPropertySet" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CssUnusedSymbol" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CucumberExamplesColon" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CucumberMissedExamples" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CucumberTableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CucumberUndefinedStep" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DockerFileArgumentCount" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="DuplicateKeyInSection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DuplicateSectionInFile" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EmptyEventHandler" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="FileHeaderInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="GherkinBrokenTableInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="GherkinMisplacedBackground" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="HamlNestedTagContent" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HardwiredNamespacePrefix" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlDeprecatedTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlExtraClosingTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlFormInputWithoutLabel" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlMissingClosingTag" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="HtmlPresentationalElement" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownAnchorTarget" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownAttribute" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myValues">
<value>
<list size="0" />
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="PhpUnhandledExceptionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUnusedParameterInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="DONT_REPORT_ABSTRACT_CLASS" value="true" />
<inspection_tool class="HtmlUnknownBooleanAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownTag" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myValues">
<value>
<list size="6">
<item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" />
<item index="3" class="java.lang.String" itemvalue="noscript" />
<item index="4" class="java.lang.String" itemvalue="embed" />
<item index="5" class="java.lang.String" itemvalue="script" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="HtmlUnknownTarget" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ImplicitTypeConversion" enabled="false" level="WARNING" enabled_by_default="false">
<option name="BITS" value="1720" />
<option name="FLAG_EXPLICIT_CONVERSION" value="true" />
<option name="IGNORE_NODESET_TO_BOOLEAN_VIA_STRING" value="true" />
</inspection_tool>
<inspection_tool class="IndexZeroUsage" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSLastCommaInArrayLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSLastCommaInObjectLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSUnresolvedFunction" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="JSUnresolvedVariable" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="LossyEncoding" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MissingSinceTagDocInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="MysqlParsingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NonAsciiCharacters" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpDocMissingReturnTagInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpDocMissingThrowsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpIncludeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpRedundantClosingTagInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedClassConstantInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedClassInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedConstantInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedFieldInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedFunctionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedGotoLabelInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedMethodInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUndefinedNamespaceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpUnusedParameterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RedundantTypeConversion" enabled="false" level="WARNING" enabled_by_default="false">
<option name="CHECK_ANY" value="false" />
</inspection_tool>
<inspection_tool class="RequiredAttributes" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myAdditionalRequiredHtmlAttributes" value="" />
</inspection_tool>
<inspection_tool class="SqlAddNotNullColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAmbiguousColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCheckUsingColumnsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlConstantConditionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDeprecateTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDerivedTableAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDropIndexedColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlIdentifierInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertValuesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNullComparisonInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlPostgresqlSelectFromProcedureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlResolveInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlShouldBeInGroupByInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSignatureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlStorageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TaskProblemsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptPreferShortImport" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlDefaultAttributeValue" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlUnboundNsPrefix" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XmlUnusedNamespaceDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XsltUnusedDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XsltVariableShadowing" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@@ -1,7 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="projectProfile" value="Combodo" />
<option name="PROJECT_PROFILE" value="Combodo" />
<version value="1.0" />
</settings>
</component>

View File

@@ -1,105 +0,0 @@
# Contributing to iTop
You want to contribute to iTop? Many thanks to you! 🎉 👍
Here are some guidelines that will help us integrate your work!
## Contributions
### Subjects
You are welcome to create pull requests on any of those subjects:
* 🐛 `:bug:` bug fix
* 🔒 `:lock:` security
* 🌐 `:globe_with_meridians:` translation / i18n / l10n
If you want to implement a **new feature**, please [create a corresponding ticket](https://sourceforge.net/p/itop/tickets/new/) for review.
If you ever want to begin implementation, do so in a fork, and add a link to the corresponding commits in the ticket.
### License
iTop is distributed under the AGPL-3.0 license (see the [license.txt] file),
your code must comply with this license.
If you want to use another license, you may [create an extension][wiki new ext].
[license.txt]: https://github.com/Combodo/iTop/blob/develop/license.txt
[wiki new ext]: https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Astart#by_writing_your_own_extension
## Branch model
TL;DR:
> **create a fork from iTop main repository,
> create a branch based on either release branch if present, or develop otherwise**
We are using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. That means we have in our repo those
main branches:
- develop: ongoing development version
- release/\*: if present, that means we are working on a beta version
- master: previous stable version
For example, if no beta version is currently ongoing we could have:
- develop containing future 2.8.0 version
- master containing 2.7.x maintenance version
In this example, when 2.8.0-beta is shipped that will become:
- develop: future 2.9.0 version
- release/2.8: 2.8.0-beta
- master: 2.7.x maintenance version
And when 2.8.0 final will be out:
- develop: future 2.9.0 version
- master: 2.8.x maintenance version
- support/2.7 : 2.7.x maintenance version
## Coding
### PHP styleguide
Please follow [our guidelines](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Acoding_standards).
### 🌐 Translations
A [dedicated page](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Atranslation) is available in the official wiki.
### Tests
Please create tests that covers as much as possible the code you're submitting.
Our tests are located in the `test/` directory, containing a PHPUnit config file : `phpunit.xml.dist`.
### Git Commit Messages
* Describe the functional change instead of the technical modifications
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Limit the first line to 72 characters or less
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)). For example :
* 🌐 `:globe_with_meridians:` for translations
* 🎨 `:art:` when improving the format/structure of the code
* ⚡️ `:zap:` when improving performance
* 🐛 `:bug:` when fixing a bug
* 🔥 `:fire:` when removing code or files
* 💚 `:green_heart:` when fixing the CI build
*`:white_check_mark:` when adding tests
* 🔒 `:lock:` when dealing with security
* ⬆️ `:arrow_up:` when upgrading dependencies
* ⬇️ `:arrow_down:` when downgrading dependencies
* ♻️ `:recycle:` code refactoring
* 💄 `:lipstick:` Updating the UI and style files.
## Pull request
When your code is working, please:
* stash as much as possible your commits,
* rebase your branch on our repo last commit,
* create a pull request.
Detailed procedure to work on fork and create PR is available [in GitHub help pages](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).

140
README.md
View File

@@ -1,140 +0,0 @@
<p align="center"><a href="https://www.combodo.com/itop-193" target="_blank">
<img src="https://www.combodo.com/logos/logo-itop.svg">
</a></p>
# iTop - ITSM & CMDB
iTop stands for *IT Operations Portal*.
It is a complete open source, ITIL, web based service management tool including a fully customizable CMDB, a helpdesk system and a document management tool.
iTop also offers mass import tools and web services to integrate with your IT
## Features
- Fully configurable [Configuration Management (CMDB)][10]
- [HelpDesk][11] and Incident Management
- [Service and Contract Management][12]
- [Change][13] Management
- Configurable [SLA][14] Management
- Graphical [impact analysis][15]
- [CSV import][16] tool for any data
- Consistency [audit][17] to check data quality
- [Data synchronization][18] (for data federation)
## Resources
- [iTop Forums][1]: for support request
- [iTop Tickets][2]: for feature requests and bug reports
- [Releases download][3]
- [iTop documentation][4] for iTop and official extensions
- [iTop extensions][5] for discovering and installing extensions
## Releases
### Version 2.6
- [Changes since the previous version][58]
- [New features][59]
- [Migration notes][60]
- [Download iTop 2.6.0][61]
### Version 2.5
- [Changes since the previous version][54]
- [New features][55]
- [Migration notes][56]
- [Download iTop 2.5.1][57]
### Version 2.4
- [Changes since the previous version][50]
- [New features][51]
- [Migration notes][52]
- [Download iTop 2.4.1][53]
# About Us
iTop development is sponsored, led and supported by [Combodo][0].
# Contributors
We would like to give a special thank you to the people from the community who contributed to this project, including:
- Alves, David
- Beck, Pedro
- Bilger, Jean-François
- Bostoen, Jeffrey
- Cardoso, Anderson
- Cassaro, Bruno
- Casteleyn, Thomas
- Castro, Randall Badilla
- Colantoni, Maria Laura
- Dvořák, Lukáš
- Goethals, Stefan
- Gumble, David
- Hippler, Lars
- Khamit, Shamil
- Konečný, Kamil
- Kunin, Vladimir
- Lassiter, Dennis
- Lucas, Jonathan
- Malik, Remie
- Rosenke, Stephan
- Seki, Shoji
- Shilov, Vladimir
- Tulio, Marco
- Turrubiates, Miguel
#### Aliases
- chifu1234
- cprobst
- Karkoff1212
- larhip
- Laura
- Purple Grape
- Schlobinux
- theBigOne
- ulmerspatz
#### Companies
- Hardis
- ITOMIG
[0]: https://www.combodo.com
[1]: https://sourceforge.net/p/itop/discussion/
[2]: https://sourceforge.net/p/itop/tickets/
[3]: https://sourceforge.net/projects/itop/files/itop/
[4]: https://www.itophub.io/wiki
[5]: https://store.itophub.io/en_US/
[10]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#configuration_management_cmdb
[11]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#ticketing
[12]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#service_management
[13]: https://www.itophub.io/wiki/page?id=2_5_0%3Adatamodel%3Astart#change_management
[14]: https://www.itophub.io/wiki/page?id=2_5_0%3Aimplementation%3Astart#service_level_agreements_and_targets
[15]: https://www.itophub.io/wiki/page?id=2_5_0%3Auser%3Aactions#relations
[16]: https://www.itophub.io/wiki/page?id=2_5_0%3Auser%3Abulk_modify#uploading_data
[17]: https://www.itophub.io/wiki/page?id=2_5_0%3Aadmin%3Aaudit
[18]: https://www.itophub.io/wiki/page?id=2_5_0%3Aadvancedtopics%3Adata_synchro_overview
[50]: https://www.itophub.io/wiki/page?id=2_4_0:release:change_log
[51]: https://www.itophub.io/wiki/page?id=2_4_0:release:2_4_whats_new
[52]: https://www.itophub.io/wiki/page?id=2_4_0:install:230_to_240_migration_notes
[53]: https://sourceforge.net/projects/itop/files/itop/2.4.1
[54]: https://www.itophub.io/wiki/page?id=2_5_0:release:change_log
[55]: https://www.itophub.io/wiki/page?id=2_5_0:release:2_5_whats_new
[56]: https://www.itophub.io/wiki/page?id=2_5_0:install:240_to_250_migration_notes
[57]: https://sourceforge.net/projects/itop/files/itop/2.5.1
[58]: https://www.itophub.io/wiki/page?id=2_6_0:release:change_log
[59]: https://www.itophub.io/wiki/page?id=2_6_0:release:2_6_whats_new
[60]: https://www.itophub.io/wiki/page?id=2_6_0:install:250_to_260_migration_notes
[61]: https://sourceforge.net/projects/itop/files/itop/2.6.0

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2018 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
@@ -20,7 +20,7 @@
/**
* Class ApplicationContext
*
* @copyright Copyright (C) 2010-2018 Combodo SARL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -31,12 +31,6 @@ require_once(APPROOT."/application/utils.inc.php");
*/
interface iDBObjectURLMaker
{
/**
* @param string $sClass
* @param string $iId
*
* @return string
*/
public static function MakeObjectURL($sClass, $iId);
}
@@ -45,13 +39,6 @@ interface iDBObjectURLMaker
*/
class iTopStandardURLMaker implements iDBObjectURLMaker
{
/**
* @param string $sClass
* @param string $iId
*
* @return string
* @throws \Exception
*/
public static function MakeObjectURL($sClass, $iId)
{
$sPage = DBObject::ComputeStandardUIPage($sClass);
@@ -66,13 +53,6 @@ class iTopStandardURLMaker implements iDBObjectURLMaker
*/
class PortalURLMaker implements iDBObjectURLMaker
{
/**
* @param string $sClass
* @param string $iId
*
* @return string
* @throws \Exception
*/
public static function MakeObjectURL($sClass, $iId)
{
$sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot();
@@ -94,20 +74,10 @@ class PortalURLMaker implements iDBObjectURLMaker
*/
class ApplicationContext
{
public static $m_sUrlMakerClass = null;
protected static $m_aPluginProperties = null;
protected static $aDefaultValues; // Cache shared among all instances
protected $aNames;
protected $aValues;
/**
* ApplicationContext constructor.
*
* @param bool $bReadContext
*
* @throws \Exception
*/
protected static $aDefaultValues; // Cache shared among all instances
public function __construct($bReadContext = true)
{
$this->aNames = array(
@@ -119,13 +89,11 @@ class ApplicationContext
}
}
/**
* Read the context directly in the PHP parameters (either POST or GET)
* return nothing
*
* @throws \Exception
*/
/**
* Read the context directly in the PHP parameters (either POST or GET)
* return nothing
*/
protected function ReadContext()
{
if (!isset(self::$aDefaultValues))
@@ -142,26 +110,20 @@ class ApplicationContext
}
// Hmm, there must be a better (more generic) way to handle the case below:
// When there is only one possible (allowed) organization, the context must be
// fixed to this org unless there is only one organization in the system then
// no filter is applied
// fixed to this org
if ($sName == 'org_id')
{
if (MetaModel::IsValidClass('Organization'))
{
$oSearchFilter = new DBObjectSearch('Organization');
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
$oSet = new CMDBObjectSet($oSearchFilter);
$iCount = $oSet->CountWithLimit(2);
if ($iCount > 1)
if ($iCount == 1)
{
$oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
$oSet = new CMDBObjectSet($oSearchFilter);
$iCount = $oSet->CountWithLimit(2);
if ($iCount == 1)
{
// Only one possible value for org_id, set it in the context
$oOrg = $oSet->Fetch();
self::$aDefaultValues[$sName] = $oOrg->GetKey();
}
// Only one possible value for org_id, set it in the context
$oOrg = $oSet->Fetch();
self::$aDefaultValues[$sName] = $oOrg->GetKey();
}
}
}
@@ -169,15 +131,12 @@ class ApplicationContext
}
$this->aValues = self::$aDefaultValues;
}
/**
* Returns the current value for the given parameter
*
* @param string $sParamName Name of the parameter to read
* @param string $defaultValue
*
* @return mixed The value for this parameter
*/
/**
* Returns the current value for the given parameter
* @param string $sParamName Name of the parameter to read
* @return mixed The value for this parameter
*/
public function GetCurrentValue($sParamName, $defaultValue = '')
{
if (isset($this->aValues[$sParamName]))
@@ -189,7 +148,7 @@ class ApplicationContext
/**
* Returns the context as string with the format name1=value1&name2=value2....
* @return string The context as a string to be appended to an href property
* return string The context as a string to be appended to an href property
*/
public function GetForLink()
{
@@ -203,7 +162,7 @@ class ApplicationContext
/**
* Returns the context as sequence of input tags to be inserted inside a <form> tag
* @return string The context as a sequence of <input type="hidden" /> tags
* return string The context as a sequence of <input type="hidden" /> tags
*/
public function GetForForm()
{
@@ -217,7 +176,7 @@ class ApplicationContext
/**
* Returns the context as a hash array 'parameter_name' => value
* @return array The context information
* return array The context information
*/
public function GetAsHash()
{
@@ -240,7 +199,8 @@ class ApplicationContext
/**
* Removes the specified parameter from the context, for example when the same parameter
* is already a search parameter
* @param string $sParamName Name of the parameter to remove
* @param string $sParamName Name of the parameter to remove
* @return none
*/
public function Reset($sParamName)
{
@@ -252,11 +212,6 @@ class ApplicationContext
/**
* Initializes the given object with the default values provided by the context
*
* @param \DBObject $oObj
*
* @throws \Exception
* @throws \CoreUnexpectedValue
*/
public function InitObjectFromContext(DBObject &$oObj)
{
@@ -283,11 +238,13 @@ class ApplicationContext
}
}
}
static $m_sUrlMakerClass = null;
/**
* Set the current application url provider
* @param string $sClass Class implementing iDBObjectURLMaker
* @return string
* @param sClass string Class implementing iDBObjectURLMaker
* @return void
*/
public static function SetUrlMakerClass($sClass = 'iTopStandardURLMaker')
{
@@ -321,14 +278,7 @@ class ApplicationContext
/**
* Get the current application url provider
*
* @param string $sObjClass
* @param string $sObjKey
* @param null $sUrlMakerClass
* @param bool $bWithNavigationContext
*
* @return string the name of the class
* @throws \Exception
*/
public static function MakeObjectUrl($sObjClass, $sObjKey, $sUrlMakerClass = null, $bWithNavigationContext = true)
{
@@ -356,6 +306,8 @@ class ApplicationContext
}
}
protected static $m_aPluginProperties = null;
/**
* Load plugin properties for the current session
* @return void
@@ -374,9 +326,9 @@ class ApplicationContext
/**
* Set plugin properties
* @param string $sPluginClass Class implementing any plugin interface
* @param string $sProperty Name of the property
* @param mixed $value Value (numeric or string)
* @param sPluginClass string Class implementing any plugin interface
* @param sProperty string Name of the property
* @param value scalar Value (numeric or string)
* @return void
*/
public static function SetPluginProperty($sPluginClass, $sProperty, $value)
@@ -389,7 +341,7 @@ class ApplicationContext
/**
* Get plugin properties
* @param string $sPluginClass Class implementing any plugin interface
* @param sPluginClass string Class implementing any plugin interface
* @return array of sProperty=>value pairs
*/
public static function GetPluginProperties($sPluginClass)
@@ -407,3 +359,4 @@ class ApplicationContext
}
}
?>

View File

@@ -16,8 +16,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once(APPROOT.'application/newsroomprovider.class.inc.php');
/**
* Management of application plugins
*
@@ -124,8 +122,7 @@ interface iApplicationUIExtension
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
*
* @param DBObject $oObject The object being displayed
*
* @return string[] desc
* @return type desc
*/
public function EnumUsedAttributes($oObject); // Not yet implemented
@@ -444,9 +441,8 @@ abstract class ApplicationPopupMenuItem
/**
* Returns the components to create a popup menu item in HTML
*
* @return array A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => )
* @ignore
* @return Hash A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => )
* @ignore
*/
abstract public function GetMenuItem();
@@ -763,15 +759,11 @@ interface iRestServiceProvider
* @return array An array of hash 'verb' => verb, 'description' => description
*/
public function ListOperations($sVersion);
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @param string $sVerb
* @param array $aParams
*
* @return RestResult The standardized result structure (at least a message)
* @throws Exception in case of internal failure.
*/
public function ExecOperation($sVersion, $sVerb, $aParams);
}
@@ -825,6 +817,10 @@ class RestResult
* Result: the requested operation cannot be performed because it can cause data (integrity) loss
*/
const UNSAFE = 12;
/**
* Result: the request page number is not valid. It must be an integer greater than 0
*/
const INVALID_PAGE = 13;
/**
* Result: the operation could not be performed, see the message for troubleshooting
*/
@@ -874,7 +870,7 @@ class RestUtils
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
* @param string $sParamName Name of the parameter to fetch from the input data
*
* @return mixed parameter value if present
* @return string
* @throws Exception If the parameter is missing
* @api
*/
@@ -897,8 +893,7 @@ class RestUtils
* @param StdClass $oData Structured input data.
* @param string $sParamName Name of the parameter to fetch from the input data
* @param mixed $default Default value if the parameter is not found in the input data
*
* @return mixed
* @return void
* @throws Exception
* @api
*/
@@ -942,8 +937,7 @@ class RestUtils
* @param string $sClass Name of the class
* @param StdClass $oData Structured input data.
* @param string $sParamName Name of the parameter to fetch from the input data
*
* @return array of class => list of attributes (see RestResultWithObjects::AddObject that uses it)
* @return An array of class => list of attributes (see RestResultWithObjects::AddObject that uses it)
* @throws Exception
* @api
*/
@@ -1091,10 +1085,13 @@ class RestUtils
*
* @param string $sClass Name of the class
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
* @param int $iLimit The limit of results to return
* @param int $iOffset The offset of results to return
*
* @return DBObjectSet The search result set
* @throws Exception If the input structure is not valid
*/
public static function GetObjectSetFromKey($sClass, $key)
public static function GetObjectSetFromKey($sClass, $key, $iLimit = 0, $iOffset = 0)
{
if (is_object($key))
{
@@ -1123,12 +1120,13 @@ class RestUtils
{
// OQL
$oSearch = DBObjectSearch::FromOQL($key);
$oObjectSet = new DBObjectSet($oSearch);
}
else
{
throw new Exception("Wrong format for key");
}
$oObjectSet = new DBObjectSet($oSearch);
$oObjectSet = new DBObjectSet($oSearch, array(), array(), null, $iLimit, $iOffset);
return $oObjectSet;
}
@@ -1171,14 +1169,6 @@ class RestUtils
}
$value = DBObjectSet::FromArray($sLnkClass, $aLinks);
}
elseif ($oAttDef instanceof AttributeTagSet)
{
if (!is_array($value))
{
throw new Exception("A tag set must be defined by an array of tag codes");
}
$value = $oAttDef->FromJSONToValue($value);
}
else
{
$value = $oAttDef->FromJSONToValue($value);

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,6 @@ require_once(APPROOT.'application/dashlet.class.inc.php');
require_once(APPROOT.'core/modelreflection.class.inc.php');
/**
*
* A user editable dashboard page
*
* @copyright Copyright (C) 2010-2017 Combodo SARL
@@ -50,11 +49,6 @@ abstract class Dashboard
$this->sId = $sId;
}
/**
* @param $sXml
*
* @throws \Exception
*/
public function FromXml($sXml)
{
$this->aCells = array(); // reset the content of the dashboard
@@ -106,10 +100,10 @@ abstract class Dashboard
$oCellsList = $oCellsNode->getElementsByTagName('cell');
$aCellOrder = array();
$iCellRank = 0;
/** @var \DOMElement $oCellNode */
foreach($oCellsList as $oCellNode)
{
$oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
$aDashletList = array();
$oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
if ($oCellRank)
{
$iCellRank = (float)$oCellRank->textContent;
@@ -119,7 +113,6 @@ abstract class Dashboard
$oDashletList = $oDashletsNode->getElementsByTagName('dashlet');
$iRank = 0;
$aDashletOrder = array();
/** @var \DOMElement $oDomNode */
foreach($oDashletList as $oDomNode)
{
$oRank = $oDomNode->getElementsByTagName('rank')->item(0);
@@ -152,11 +145,6 @@ abstract class Dashboard
}
}
/**
* @param \DOMElement $oDomNode
*
* @return mixed
*/
protected function InitDashletFromDOMNode($oDomNode)
{
$sId = $oDomNode->getAttribute('id');
@@ -164,8 +152,7 @@ abstract class Dashboard
// Test if dashlet can be instanciated, otherwise (uninstalled, broken, ...) we display a placeholder
$sClass = static::GetDashletClassFromType($sDashletType);
/** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sClass($this->oMetaModel, $sId);
$oNewDashlet = new $sClass($this->oMetaModel, $sId);
$oNewDashlet->SetDashletType($sDashletType);
$oNewDashlet->FromDOMNode($oDomNode);
@@ -176,17 +163,8 @@ abstract class Dashboard
{
return ($aItem1['rank'] > $aItem2['rank']) ? +1 : -1;
}
/**
* Error handler to turn XML loading warnings into exceptions
*
* @param $errno
* @param $errstr
* @param $errfile
* @param $errline
*
* @return bool
* @throws \DOMException
*/
public static function ErrorHandler($errno, $errstr, $errfile, $errline)
{
@@ -216,12 +194,8 @@ abstract class Dashboard
return $sXml;
}
/**
* @param \DOMElement $oDefinition
*/
public function ToDOMNode($oDefinition)
{
/** @var \DOMDocument $oDoc */
$oDoc = $oDefinition->ownerDocument;
$oNode = $oDoc->createElement('layout', $this->sLayoutClass);
@@ -253,7 +227,6 @@ abstract class Dashboard
$iDashletRank = 0;
$oDashletsNode = $oDoc->createElement('dashlets');
$oCellNode->appendChild($oDashletsNode);
/** @var \Dashlet $oDashlet */
foreach ($aCell as $oDashlet)
{
$oNode = $oDoc->createElement('dashlet');
@@ -283,7 +256,6 @@ abstract class Dashboard
{
$sDashletClass = $aDashletParams['dashlet_class'];
$sId = $aDashletParams['dashlet_id'];
/** @var \Dashlet $oNewDashlet */
$oNewDashlet = new $sDashletClass($this->oMetaModel, $sId);
if (isset($aDashletParams['dashlet_type']))
{
@@ -346,28 +318,31 @@ abstract class Dashboard
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$iAutoReloadSec);
}
/**
* @param \Dashlet $oDashlet
*/
public function AddDashlet($oDashlet)
{
$sId = $this->GetNewDashletId();
$oDashlet->SetId($sId);
$this->aCells[] = array($oDashlet);
}
/**
* @param \WebPage $oPage *
* @param array $aExtraParams
*
* @throws \ReflectionException
*/
public function RenderProperties($oPage, $aExtraParams = array())
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
{
$oPage->add('<h1>'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'</h1>');
$oLayout = new $this->sLayoutClass;
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
if (!$bEditMode)
{
$oPage->add_linked_script('../js/dashlet.js');
$oPage->add_linked_script('../js/dashboard.js');
}
}
public function RenderProperties($oPage)
{
// menu to pick a layout and edit other properties of the dashboard
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Properties').'</div>');
$sUrl = utils::GetAbsoluteUrlAppRoot();
$oPage->add('<div style="text-align:center">'.Dict::S('UI:DashboardEdit:Layout').'</div>');
$oPage->add('<div id="select_layout" style="text-align:center">');
foreach( get_declared_classes() as $sLayoutClass)
@@ -385,13 +360,13 @@ abstract class Dashboard
}
}
$oPage->add('</div>');
$oForm = new DesignerForm();
$oField = new DesignerHiddenField('dashboard_id', '', $this->sId);
$oForm->AddField($oField);
$oField = new DesignerTextField('dashboard_title', Dict::S('UI:DashboardEdit:DashboardTitle'), $this->sTitle);
$oField = new DesignerLongTextField('dashboard_title', Dict::S('UI:DashboardEdit:DashboardTitle'), $this->sTitle);
$oForm->AddField($oField);
$oField = new DesignerBooleanField('auto_reload', Dict::S('UI:DashboardEdit:AutoReload'), $this->bAutoReload);
@@ -402,8 +377,8 @@ abstract class Dashboard
$oForm->AddField($oField);
$this->SetFormParams($oForm, $aExtraParams);
$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
$this->SetFormParams($oForm);
$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
$oPage->add('</div>');
@@ -447,28 +422,8 @@ abstract class Dashboard
EOF
);
}
/**
* @param \iTopWebPage $oPage
* @param bool $bEditMode
* @param array $aExtraParams
* @param bool $bCanEdit
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
{
$oPage->add('<div class="dashboard-title-line"><div class="dashboard-title">'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'</div></div>');
$oLayout = new $this->sLayoutClass;
/** @var \DashboardLayoutMultiCol $oLayout */
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
if (!$bEditMode)
{
$oPage->add_linked_script('../js/dashlet.js');
$oPage->add_linked_script('../js/dashboard.js');
}
}
public function RenderDashletsSelection(WebPage $oPage)
public function RenderDashletsSelection($oPage)
{
// Toolbox/palette to drag and drop dashlets
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Dashlets').'</div>');
@@ -486,7 +441,7 @@ EOF
$oPage->add_ready_script("$('.dashlet_icon').draggable({helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
}
public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = array())
public function RenderDashletsProperties($oPage)
{
// Toolbox/palette to edit the properties of each dashlet
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:DashletProperties').'</div>');
@@ -494,15 +449,15 @@ EOF
$oPage->add('<div id="dashlet_properties" style="text-align:center">');
foreach($this->aCells as $aCell)
{
/** @var \Dashlet $oDashlet */
foreach($aCell as $oDashlet)
{
$sId = $oDashlet->GetID();
$sClass = get_class($oDashlet);
if ($oDashlet->IsVisible())
{
$oPage->add('<div class="dashlet_properties" id="dashlet_properties_'.$sId.'" style="display:none">');
$oForm = $oDashlet->GetForm();
$this->SetFormParams($oForm, $aExtraParams);
$this->SetFormParams($oForm);
$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
$oPage->add('</div>');
}
@@ -517,7 +472,6 @@ EOF
* Return an array of dashlets available for selection.
*
* @return array
* @throws \ReflectionException
*/
protected function GetAvailableDashlets()
{
@@ -551,7 +505,6 @@ EOF
$iNewId = 0;
foreach($this->aCells as $aDashlets)
{
/** @var \Dashlet $oDashlet */
foreach($aDashlets as $oDashlet)
{
$iNewId = max($iNewId, (int)$oDashlet->GetID());
@@ -559,14 +512,8 @@ EOF
}
return $iNewId + 1;
}
/**
* @param $oForm
* @param array $aExtraParams
*
* @return mixed
*/
abstract protected function SetFormParams($oForm, $aExtraParams = array());
abstract protected function SetFormParams($oForm);
public static function GetDashletClassFromType($sType, $oFactory = null)
{
@@ -576,22 +523,11 @@ EOF
}
return 'DashletUnknown';
}
/**
* @return mixed
*/
public function GetId()
{
return $this->sId;
}
}
class RuntimeDashboard extends Dashboard
{
protected $bCustomized;
private $sDefinitionFile = '';
private $sReloadURL = null;
public function __construct($sId)
{
@@ -604,17 +540,10 @@ class RuntimeDashboard extends Dashboard
{
$this->bCustomized = $bCustomized;
}
/**
* @param \DesignerForm $oForm
*
* @param array $aExtraParams
*
* @throws \Exception
*/
protected function SetFormParams($oForm, $aExtraParams = array())
protected function SetFormParams($oForm)
{
$oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property', 'extra_params' => $aExtraParams));
$oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property'));
}
public function Save()
@@ -658,265 +587,41 @@ class RuntimeDashboard extends Dashboard
utils::PopArchiveMode();
}
}
/**
* @param string $sDashboardFile file name relative to the current module folder
* @param string $sDashBoardId code of the dashboard either menu_id or <class>__<attcode>
*
* @return null|RuntimeDashboard
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
public static function GetDashboard($sDashboardFile, $sDashBoardId)
{
$bCustomized = false;
if (!appUserPreferences::GetPref('display_original_dashboard_'.$sDashBoardId, false))
{
// Search for an eventual user defined dashboard
$oUDSearch = new DBObjectSearch('UserDashboard');
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $sDashBoardId, '=');
$oUDSet = new DBObjectSet($oUDSearch);
if ($oUDSet->Count() > 0)
{
// Assuming there is at most one couple {user, menu}!
$oUserDashboard = $oUDSet->Fetch();
$sDashboardDefinition = $oUserDashboard->Get('contents');
$bCustomized = true;
}
else
{
$sDashboardDefinition = @file_get_contents($sDashboardFile);
}
}
else
{
$sDashboardDefinition = @file_get_contents($sDashboardFile);
}
if ($sDashboardDefinition !== false)
{
$oDashboard = new RuntimeDashboard($sDashBoardId);
$oDashboard->FromXml($sDashboardDefinition);
$oDashboard->SetCustomFlag($bCustomized);
$oDashboard->SetDefinitionFile($sDashboardFile);
}
else
{
$oDashboard = null;
}
return $oDashboard;
}
/**
* @param \iTopWebPage $oPage
* @param bool $bEditMode
* @param array $aExtraParams (class and id of the current object
*
* @throws \Exception
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true)
{
if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class']))
{
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
}
else
{
$aRenderParams = $aExtraParams;
}
parent::Render($oPage, $bEditMode, $aRenderParams);
if (isset($aExtraParams['query_params']['this->object()']))
{
/** @var \DBObject $oObj */
$oObj = $aExtraParams['query_params']['this->object()'];
$aAjaxParams = array('this->class' => get_class($oObj), 'this->id' => $oObj->GetKey());
}
else
{
$aAjaxParams = $aExtraParams;
}
if (!$bEditMode && !$oPage->IsPrintableVersion())
{
$sId = $this->GetId();
$sDivId = preg_replace('/[^a-zA-Z0-9_]/', '', $sId);
if ($this->GetAutoReload())
{
$sFile = addslashes($this->GetDefinitionFile());
$sExtraParams = json_encode($aAjaxParams);
$iReloadInterval = 1000 * $this->GetAutoReloadInterval();
$sReloadURL = $this->GetReloadURL();
$oPage->add_script(
<<<EOF
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
{
clearInterval(AutoReloadDashboardId$sDivId);
delete AutoReloadDashboardId$sDivId;
}
AutoReloadDashboardId$sDivId = setInterval("ReloadDashboard$sDivId();", $iReloadInterval);
function ReloadDashboard$sDivId()
{
// Do not reload when a dialog box is active
if (!($('.ui-dialog:visible').length > 0) && $('.dashboard_contents#$sDivId').is(':visible'))
{
$('.dashboard_contents#$sDivId').block();
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL'},
function(data){
$('.dashboard_contents#$sDivId').html(data);
$('.dashboard_contents#$sDivId').unblock();
}
);
}
}
EOF
);
}
else
{
$oPage->add_script(
<<<EOF
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
{
clearInterval(AutoReloadDashboardId$sDivId);
delete AutoReloadDashboardId$sDivId;
}
EOF
);
}
if ($bCanEdit)
{
$this->RenderSelector($oPage, $aAjaxParams);
$this->RenderEditionTools($oPage, $aAjaxParams);
}
}
}
/**
* @param \iTopWebPage $oPage
* @param array $aAjaxParams
*/
protected function RenderSelector($oPage, $aAjaxParams = array())
{
$sId = $this->GetId();
$sDivId = preg_replace('/[^a-zA-Z0-9_]/', '', $sId);
$sExtraParams = json_encode($aAjaxParams);
$sSelectorHtml = '<div class="dashboard-selector">';
if ($this->HasCustomDashboard())
{
$bStandardSelected = appUserPreferences::GetPref('display_original_dashboard_'.$sId, false);
$sStandard = Dict::S('UI:Toggle:StandardDashboard');
$sSelectorHtml .= '<div class="selector-label">'.$sStandard.'</div>';
$sSelectorHtml .= '<label class="switch"><input type="checkbox" onchange="ToggleDashboardSelector'.$sDivId.'();" '.($bStandardSelected ? '' : 'checked').'><span class="slider round"></span></label></input></label>';
$sCustom = Dict::S('UI:Toggle:CustomDashboard');
$sSelectorHtml .= '<div class="selector-label">'.$sCustom.'</div>';
}
$sSelectorHtml .= '</div>';
$sSelectorHtml = addslashes($sSelectorHtml);
$sFile = addslashes($this->GetDefinitionFile());
$sReloadURL = $this->GetReloadURL();
$oPage->add_ready_script(
<<<EOF
$('.dashboard-title').after('$sSelectorHtml');
EOF
);
$oPage->add_script(
<<<EOF
function ToggleDashboardSelector$sDivId()
{
$('.dashboard_contents#$sDivId').block();
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
{ operation: 'toggle_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL' },
function(data) {
$('.dashboard_contents#$sDivId').html(data);
$('.dashboard_contents#$sDivId').unblock();
}
);
}
EOF
);
}
protected function HasCustomDashboard()
{
try
{
// Search for an eventual user defined dashboard
$oUDSearch = new DBObjectSearch('UserDashboard');
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $this->GetId(), '=');
$oUDSet = new DBObjectSet($oUDSearch);
return ($oUDSet->Count() > 0);
}
catch (Exception $e)
{
return false;
}
}
/**
* @param \WebPage $oPage
* @param array $aExtraParams
*
* @throws \Exception
*/
protected function RenderEditionTools(WebPage $oPage, $aExtraParams)
public function RenderEditionTools($oPage)
{
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
$sEditMenu = "<div id=\"DashboardMenu\"><ul><li><img src=\"../images/pencil-menu.png\"><ul>";
$sEditMenu = "<td><span id=\"DashboardMenu\"><ul><li><img src=\"../images/pencil-menu.png\"><ul>";
$aActions = array();
$sFile = addslashes($this->sDefinitionFile);
$sJSExtraParams = json_encode($aExtraParams);
$bCanEdit = true;
if ($this->HasCustomDashboard())
{
$bCanEdit = !appUserPreferences::GetPref('display_original_dashboard_'.$this->GetId(), false);
}
if ($bCanEdit)
{
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
}
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}')");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
if ($this->bCustomized)
{
$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:Revert'),
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}', $sJSExtraParams); else return false");
"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}'); else return false");
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
}
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
$sEditMenu .= $oPage->RenderPopupMenuItems($aActions);
$sEditMenu = addslashes($sEditMenu);
$sReloadURL = $this->GetReloadURL();
//$sEditBtn = addslashes('<div style="display: inline-block; height: 55px; width:200px;vertical-align:center;line-height:60px;text-align:left;"><button onclick="EditDashboard(\''.$this->sId.'\');">Edit This Page</button></div>');
$oPage->add_ready_script(
<<<EOF
$('.dashboard-title').after('$sEditMenu');
$('#logOffBtn').parent().before('$sEditMenu');
$('#DashboardMenu>ul').popupmenu();
EOF
);
$oPage->add_script(
<<<EOF
function EditDashboard(sId, sDashboardFile, aExtraParams)
function EditDashboard(sId)
{
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId, file: sDashboardFile, extra_params: aExtraParams, reload_url: '$sReloadURL'},
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId},
function(data)
{
$('body').append(data);
@@ -924,12 +629,12 @@ function EditDashboard(sId, sDashboardFile, aExtraParams)
);
return false;
}
function RevertDashboard(sId, aExtraParams)
function RevertDashboard(sId)
{
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'revert_dashboard', dashboard_id: sId, extra_params: aExtraParams, reload_url: '$sReloadURL'},
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'revert_dashboard', dashboard_id: sId},
function(data)
{
location.reload();
$('body').append(data);
}
);
return false;
@@ -938,14 +643,9 @@ EOF
);
}
/**
* @param \WebPage $oPage
*
* @throws \ReflectionException
*/
public function RenderProperties($oPage, $aExtraParams = array())
public function RenderProperties($oPage)
{
parent::RenderProperties($oPage, $aExtraParams);
parent::RenderProperties($oPage);
$oPage->add_ready_script(
<<<EOF
@@ -976,36 +676,16 @@ EOF
}
/**
* @param \iTopWebPage $oPage
*
* @param array $aExtraParams
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \ReflectionException
* @throws \Exception
*/
public function RenderEditor($oPage, $aExtraParams = array())
public function RenderEditor($oPage)
{
if (isset($aExtraParams['this->class']))
{
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
$aRenderParams = array('query_params' => $oObj->ToArgsForQuery());
}
else
{
$aRenderParams = $aExtraParams;
}
$sJSExtraParams = json_encode($aExtraParams);
$oPage->add('<div id="dashboard_editor">');
$oPage->add('<div class="ui-layout-center">');
$this->Render($oPage, true, $aRenderParams);
$this->Render($oPage, true);
$oPage->add('</div>');
$oPage->add('<div class="ui-layout-east">');
$this->RenderProperties($oPage, $aExtraParams);
$this->RenderProperties($oPage);
$this->RenderDashletsSelection($oPage);
$this->RenderDashletsProperties($oPage, $aExtraParams);
$this->RenderDashletsProperties($oPage);
$oPage->add('</div>');
$oPage->add('<div id="event_bus"/>'); // For exchanging messages between the panes, same as in the designer
$oPage->add('</div>');
@@ -1019,9 +699,7 @@ EOF
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
$sAutoReloadSec = (string) $this->iAutoReloadSec;
$sTitle = addslashes($this->sTitle);
$sFile = addslashes($this->GetDefinitionFile());
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
$sReloadURL = $this->GetReloadURL();
$sExitConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage'));
$sCancelConfirmationMessage = addslashes(Dict::S('UI:CancelConfirmationMessage'));
@@ -1051,7 +729,7 @@ $('#dashboard_editor').dialog({
}
}
window.bLeavingOnUserAction = true;
oDashboard.save($(this));
oDashboard.save();
} },
{ text: "$sCancelButtonLabel", click: function() {
var oDashboard = $('.itop-dashboard').data('itopRuntimedashboard');
@@ -1073,8 +751,8 @@ $('#dashboard_editor').dialog({
$('#dashboard_editor .ui-layout-center').runtimedashboard({
dashboard_id: '$sId', layout_class: '$sLayoutClass', title: '$sTitle',
auto_reload: $sAutoReload, auto_reload_sec: $sAutoReloadSec,
submit_to: '$sUrl', submit_parameters: {operation: 'save_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
render_to: '$sUrl', render_parameters: {operation: 'render_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
submit_to: '$sUrl', submit_parameters: {operation: 'save_dashboard'},
render_to: '$sUrl', render_parameters: {operation: 'render_dashboard'},
new_dashlet_parameters: {operation: 'new_dashlet'}
});
@@ -1157,8 +835,7 @@ EOF
$sParentId = $aParentMenu['parent'];
$aParentMenu = $aParentMenus[$sParentId];
}
/** @var \MenuNode $oParentMenu */
$oParentMenu = $aParentMenu['node'];
$oParentMenu = $aParentMenu['node'];
if ($oMenu->IsEnabled() && $oParentMenu->IsEnabled())
{
$sMenuLabel = $oMenu->GetTitle();
@@ -1213,7 +890,6 @@ EOF
{
$oSubForm = new DesignerForm();
$oMetaModel = new ModelReflectionRuntime();
/** @var \Dashlet $oDashlet */
$oDashlet = new $sDashletClass($oMetaModel, 0);
$oDashlet->GetPropertiesFieldsFromOQL($oSubForm, $sOQL);
@@ -1224,11 +900,7 @@ EOF
return $oForm;
}
/**
* @param \WebPage $oPage
* @param $sOQL
*/
public static function GetDashletCreationDlgFromOQL($oPage, $sOQL)
{
$oPage->add('<div id="dashlet_creation_dlg">');
@@ -1275,30 +947,4 @@ $('#dashlet_creation_dlg').dialog({
EOF
);
}
/**
* @return string
*/
public function GetDefinitionFile()
{
return $this->sDefinitionFile;
}
/**
* @param string $sDefinitionFile
*/
public function SetDefinitionFile($sDefinitionFile)
{
$this->sDefinitionFile = $sDefinitionFile;
}
public function GetReloadURL()
{
return $this->sReloadURL;
}
public function SetReloadURL($sReloadURL)
{
$this->sReloadURL = $sReloadURL;
}
}

View File

@@ -59,7 +59,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
$bNoVisibleFound = true;
while($idx < count($aKeys) && $bNoVisibleFound)
{
/** @var \Dashlet $oDashlet */
$oDashlet = $aDashlets[$aKeys[$idx]];
if ($oDashlet->IsVisible())
{
@@ -99,13 +98,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
return $aCells;
}
/**
* @param \WebPage $oPage
* @param $aCells
* @param bool $bEditMode
* @param array $aExtraParams
*/
public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = array())
{
// Trim the list of cells to remove the invisible/empty ones at the end of the array
@@ -129,7 +122,6 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
$aDashlets = $aCells[$iCellIdx];
if (count($aDashlets) > 0)
{
/** @var \Dashlet $oDashlet */
foreach($aDashlets as $oDashlet)
{
if ($oDashlet->IsVisible())

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.5">
<portals>
<portal id="legacy_portal" _delta="define">
<url>portal/index.php</url>

View File

@@ -756,10 +756,6 @@ class DataTableSettings implements Serializable
{
foreach($this->aClassAliases as $sAlias => $sClass)
{
if (!isset($this->aColumns[$sAlias]))
{
continue;
}
foreach($this->aColumns[$sAlias] as $sAttCode => $aData)
{
// Remove non-existent columns
@@ -775,7 +771,7 @@ class DataTableSettings implements Serializable
$aTempData = array();
foreach($aList as $sAttCode => $oAttDef)
{
if ( (!array_key_exists($sAttCode, $this->aColumns[$sAlias])) && (!($oAttDef instanceof AttributeLinkedSet || $oAttDef instanceof AttributeDashboard)))
if ( (!array_key_exists($sAttCode, $this->aColumns[$sAlias])) && (!$oAttDef instanceof AttributeLinkSet))
{
$aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, false /* bChecked */, 'none');
if ($aFieldData) $aTempData[$aFieldData['label']] = $aFieldData;

View File

@@ -220,26 +220,9 @@ class DisplayBlock
$aExtraParams['currentId'] = $sId;
$sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them
if (isset($aExtraParams['query_params']))
{
$aQueryParams = $aExtraParams['query_params'];
}
else
{
if (isset($aExtraParams['this->id']) && isset($aExtraParams['this->class']))
{
$sClass = $aExtraParams['this->class'];
$iKey = $aExtraParams['this->id'];
$oObj = MetaModel::GetObject($sClass, $iKey);
$aQueryParams = array('this->object()' => $oObj);
}
else
{
$aQueryParams = array();
}
}
$sFilter = addslashes($this->m_oFilter->serialize(false, $aQueryParams)); // Used either for asynchronous or auto_reload
$sFilter = $this->m_oFilter->serialize(); // Used either for asynchronous or auto_reload
if (!$this->m_bAsynchronous)
{
// render now
@@ -331,31 +314,20 @@ class DisplayBlock
* @throws MySQLException
* @throws Exception
*/
public function GetRenderContent(WebPage $oPage, $aExtraParams, $sId)
public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId)
{
$sHtml = '';
// Add the extra params into the filter if they make sense for such a filter
$bDoSearch = utils::ReadParam('dosearch', false);
$aQueryParams = array();
if (isset($aExtraParams['query_params']))
{
$aQueryParams = $aExtraParams['query_params'];
}
else
{
if (isset($aExtraParams['this->id']) && isset($aExtraParams['this->class']))
{
$sClass = $aExtraParams['this->class'];
$iKey = $aExtraParams['this->id'];
$oObj = MetaModel::GetObject($sClass, $iKey);
$aQueryParams = array('this->object()' => $oObj);
}
}
if ($this->m_oSet == null)
{
$aQueryParams = array();
if (isset($aExtraParams['query_params']))
{
$aQueryParams = $aExtraParams['query_params'];
}
// In case of search, the context filtering is done by the search itself
if (($this->m_sStyle != 'links') && ($this->m_sStyle != 'search') && ($this->m_sStyle != 'list_search'))
if (($this->m_sStyle != 'links') && ($this->m_sStyle != 'search'))
{
$oAppContext = new ApplicationContext();
$sClass = $this->m_oFilter->GetClass();
@@ -485,15 +457,7 @@ class DisplayBlock
$oSubsetSearch = $this->m_oFilter->DeepClone();
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
$oSubsetSearch->AddConditionExpression($oCondition);
if (isset($aExtraParams['query_params']))
{
$aQueryParams = $aExtraParams['query_params'];
}
else
{
$aQueryParams = array();
}
$sFilter = rawurlencode($oSubsetSearch->serialize(false, $aQueryParams));
$sFilter = urlencode($oSubsetSearch->serialize());
$aData[] = array ('group' => $aLabels[$iRow],
'value' => "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1&$sParams&filter=$sFilter\">$iCount</a>"); // TO DO: add the context information
@@ -616,7 +580,6 @@ class DisplayBlock
}
break;
case 'list_search':
case 'list':
$aClasses = $this->m_oSet->GetSelectedClasses();
$aAuthorizedClasses = array();
@@ -752,7 +715,7 @@ class DisplayBlock
$sClass = $this->m_oFilter->GetClass();
$oAppContext = new ApplicationContext();
$bContextFilter = isset($aExtraParams['context_filter']) ? isset($aExtraParams['context_filter']) != 0 : false;
if ($bContextFilter && is_null($this->m_oSet))
if ($bContextFilter)
{
foreach($oAppContext->GetNames() as $sFilterCode)
{
@@ -771,7 +734,7 @@ class DisplayBlock
$this->m_oSet->SetShowObsoleteData($this->m_bShowObsoleteData);
}
$iCount = $this->m_oSet->Count();
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($this->m_oFilter->serialize());
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize());
$sHtml .= '<p><a class="actions" href="'.$sHyperlink.'">';
// Note: border set to 0 due to various browser interpretations (IE9 adding a 2px border)
$sHtml .= MetaModel::GetClassIcon($sClass, true, 'float;left;margin-right:10px;border:0;');
@@ -860,7 +823,7 @@ class DisplayBlock
}
$sHyperlink = utils::GetAbsoluteUrlAppRoot()
.'pages/UI.php?operation=search&'.$oAppContext->GetForLink()
.'&filter='.rawurlencode($oSingleGroupByValueFilter->serialize());
.'&filter='.urlencode($oSingleGroupByValueFilter->serialize());
$aCounts[$sStateValue] = "<a href=\"$sHyperlink\">{$aCounts[$sStateValue]}</a>";
}
}
@@ -869,7 +832,7 @@ class DisplayBlock
$sHtml .= '<tr><td>'.implode('</td><td>', $aCounts).'</td></tr></table></div>';
// Title & summary
$iCount = $this->m_oSet->Count();
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($this->m_oFilter->serialize());
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize());
$sHtml .= '<h1>'.Dict::S(str_replace('_', ':', $sTitle)).'</h1>';
$sHtml .= '<a class="summary" href="'.$sHyperlink.'">'.Dict::Format(str_replace('_', ':', $sLabel), $iCount).'</a>';
$sHtml .= '<div style="clear:both;"></div>';
@@ -880,7 +843,7 @@ class DisplayBlock
$sCsvFile = strtolower($this->m_oFilter->GetClass()).'.csv';
$sDownloadLink = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?expression='.urlencode($this->m_oFilter->ToOQL(true)).'&format=csv&filename='.urlencode($sCsvFile);
$sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($this->m_oFilter->serialize()).'&format=csv';
$sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize()).'&format=csv';
// Pass the parameters via POST, since expression may be very long
$aParamsToPost = array(
'expression' => $this->m_oFilter->ToOQL(true),
@@ -950,10 +913,10 @@ class DisplayBlock
$sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
$sTitle = isset($aExtraParams['chart_title']) ? '<h1 style="text-align:center">'.htmlentities(Dict::S($aExtraParams['chart_title']), ENT_QUOTES, 'UTF-8').'</h1>' : '';
$sHtml = "$sTitle<div style=\"height:200px;width:100%\" class=\"dashboard_chart\" id=\"my_chart_$sId{$iChartCounter}\"><div style=\"height:200px;line-height:200px;vertical-align:center;text-align:center;width:100%\"><img src=\"../images/indicator.gif\"></div></div>\n";
$sHtml = "$sTitle<div style=\"height:200px;width:100%\" id=\"my_chart_$sId{$iChartCounter}\"><div style=\"height:200px;line-height:200px;vertical-align:center;text-align:center;width:100%\"><img src=\"../images/indicator.gif\"></div></div>\n";
$sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : '';
$sGroupByExpr = isset($aExtraParams['group_by_expr']) ? '&params[group_by_expr]='.$aExtraParams['group_by_expr'] : '';
$sFilter = $this->m_oFilter->serialize(false, $aQueryParams);
$sFilter = $this->m_oFilter->serialize();
$oContext = new ApplicationContext();
$sContextParam = $oContext->GetForLink();
$sAggregationFunction = isset($aExtraParams['aggregation_function']) ? $aExtraParams['aggregation_function'] : '';
@@ -964,11 +927,11 @@ class DisplayBlock
if (isset($aExtraParams['group_by_label']))
{
$sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]=$sChartType&params[currentId]=$sId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId{$iChartCounter}&filter=".rawurlencode($sFilter).'&'.$sContextParam);
$sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]=$sChartType&params[currentId]=$sId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId{$iChartCounter}&filter=".urlencode($sFilter).'&'.$sContextParam);
}
else
{
$sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[chart_type]=$sChartType&params[currentId]=$sId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId{$iChartCounter}&filter=".rawurlencode($sFilter).'&'.$sContextParam);
$sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart&params[group_by]=$sGroupBy{$sGroupByExpr}&params[chart_type]=$sChartType&params[currentId]=$sId{$iChartCounter}&params[order_direction]=$sOrderDirection&params[order_by]=$sOrderBy&params[limit]=$sLimit&params[aggregation_function]=$sAggregationFunction&params[aggregation_attribute]=$sAggregationAttr&id=$sId{$iChartCounter}&filter=".urlencode($sFilter).'&'.$sContextParam);
}
$oPage->add_ready_script(
@@ -1008,7 +971,7 @@ EOF
$oSubsetSearch = $this->m_oFilter->DeepClone();
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($sValue));
$oSubsetSearch->AddConditionExpression($oCondition);
$aURLs[] = utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&format=html&filter=".rawurlencode($oSubsetSearch->serialize()).'&'.$sContextParam;
$aURLs[] = utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&format=html&filter=".urlencode($oSubsetSearch->serialize()).'&'.$sContextParam;
}
$sJSURLs = json_encode($aURLs);
}
@@ -1026,7 +989,6 @@ EOF
$sJson = json_encode($aValues);
$oPage->add_ready_script(
<<<EOF
var chart = c3.generate({
bindto: d3.select('#my_chart_$sId'),
data: {
@@ -1074,12 +1036,6 @@ var chart = c3.generate({
}
}
});
if (typeof(charts) === "undefined")
{
charts = [];
}
charts.push(chart);
EOF
);
break;
@@ -1118,12 +1074,6 @@ var chart = c3.generate({
}
}
});
if (typeof(charts) === "undefined")
{
charts = [];
}
charts.push(chart);
EOF
);
break;
@@ -1172,7 +1122,7 @@ EOF
}
if (($bAutoReload) && ($this->m_sStyle != 'search')) // Search form do NOT auto-reload
{
$sFilter = addslashes(str_replace('"', "'", $this->m_oFilter->serialize())); // Used either for asynchronous or auto_reload
$sFilter = $this->m_oFilter->serialize(); // Used either for asynchronous or auto_reload
$sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them
$oPage->add_script('if (typeof window.oAutoReloadBlock == "undefined") {
@@ -1181,7 +1131,7 @@ EOF
if (typeof window.oAutoReloadBlock[\''.$sId.'\'] != "undefined") {
clearInterval(window.oAutoReloadBlock[\''.$sId.'\']);
}
window.oAutoReloadBlock[\''.$sId.'\'] = setInterval("ReloadBlock(\''.$sId.'\', \''.$this->m_sStyle.'\', \"'.$sFilter.'\", \"'.$sExtraParams.'\")", '.$iReloadInterval.');');
window.oAutoReloadBlock[\''.$sId.'\'] = setInterval("ReloadBlock(\''.$sId.'\', \''.$this->m_sStyle.'\', \''.$sFilter.'\', \"'.$sExtraParams.'\")", '.$iReloadInterval.');');
}
return $sHtml;
@@ -1441,7 +1391,7 @@ class HistoryBlock extends DisplayBlock
default:
if ($bTruncated)
{
$sFilter = htmlentities($this->m_oFilter->serialize(), ENT_QUOTES, 'UTF-8');
$sFilter = $this->m_oFilter->serialize();
$sHtml .= '<div id="history_container"><p>';
$sHtml .= Dict::Format('UI:TruncatedResults', $this->iLimitCount, $oSet->Count());
$sHtml .= ' ';

View File

@@ -378,9 +378,9 @@ $('#$sDialogId').dialog({
}
}
} },
{ text: "$sCancelButtonLabel", click: function() { $(this).dialog( "close" ); $(this).remove(); } },
{ text: "$sCancelButtonLabel", click: function() { KillAllMenus(); $(this).dialog( "close" ); $(this).remove(); } },
],
close: function() { $(this).remove(); }
close: function() { KillAllMenus(); $(this).remove(); }
});
var oForm = $('#$sDialogId form');
var sFormId = oForm.attr('id');
@@ -682,7 +682,6 @@ class DesignerFormField
protected $sLabel;
protected $sCode;
protected $defaultValue;
/** @var \DesignerForm $oForm */
protected $oForm;
protected $bMandatory;
protected $bReadOnly;
@@ -708,11 +707,8 @@ class DesignerFormField
{
return $this->sCode;
}
/**
* @param \DesignerForm $oForm
*/
public function SetForm(\DesignerForm $oForm)
public function SetForm($oForm)
{
$this->oForm = $oForm;
}

File diff suppressed because it is too large Load Diff

View File

@@ -50,9 +50,6 @@ class LoginWebPage extends NiceWebPage
self::$sHandlerClass = $sClass;
}
/**
* @return \LoginWebPage
*/
public static function NewLoginWebPage()
{
return new self::$sHandlerClass;
@@ -707,6 +704,7 @@ EOF
{
// No rights to be here, redirect to the portal
header('Location: '.$ret);
die();
}
}
}
@@ -846,8 +844,8 @@ EOF
{
$sAuthUser = $_SESSION['auth_user'];
UserRights::Login($sAuthUser); // Set the user's language
$sOldPwd = utils::ReadPostedParam('old_pwd', '', false, 'raw_data');
$sNewPwd = utils::ReadPostedParam('new_pwd', '', false, 'raw_data');
$sOldPwd = utils::ReadPostedParam('old_pwd', '', 'raw_data');
$sNewPwd = utils::ReadPostedParam('new_pwd', '', 'raw_data');
if (UserRights::CanChangePassword() && ((!UserRights::CheckCredentials($sAuthUser, $sOldPwd)) || (!UserRights::ChangePassword($sOldPwd, $sNewPwd))))
{
$oPage = self::NewLoginWebPage();

View File

@@ -84,11 +84,14 @@ class ApplicationMenu
{
// Build menus from module handlers
//
/** @var \ModuleHandlerApiInterface $oPHPClass */
foreach(MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass)
{
$oPHPClass::OnMenuCreation();
}
foreach(get_declared_classes() as $sPHPClass)
{
if (is_subclass_of($sPHPClass, 'ModuleHandlerAPI'))
{
$aCallSpec = array($sPHPClass, 'OnMenuCreation');
call_user_func($aCallSpec);
}
}
// Build menus from the menus themselves (e.g. the ShortcutContainerMenuNode will do that)
//
@@ -122,11 +125,9 @@ class ApplicationMenu
}
/**
* Check whether a menu Id is enabled or not
*
* Check wether a menu Id is enabled or not
* @param $sMenuId
*
* @throws \Exception
* @throws DictExceptionMissingString
*/
static public function CheckMenuIdEnabled($sMenuId)
{
@@ -166,9 +167,7 @@ class ApplicationMenu
}
else
{
/** @var \MenuNode $oNode */
$oNode = self::$aMenusIndex[$iParentIndex]['node'];
$sParentId = $oNode->GetMenuId();
$sParentId = self::$aMenusIndex[$iParentIndex]['node']->GetMenuId();
self::$aMenusIndex[$iParentIndex]['children'][] = array ('rank' => $fRank, 'index' => $index);
}
@@ -182,9 +181,7 @@ class ApplicationMenu
else
{
// the menu already exists, let's combine the conditions that make it visible
/** @var \MenuNode $oNode */
$oNode = self::$aMenusIndex[$index]['node'];
$oNode->AddCondition($oMenuNode);
self::$aMenusIndex[$index]['node']->AddCondition($oMenuNode);
}
return $index;
@@ -201,7 +198,7 @@ class ApplicationMenu
/**
* Entry point to display the whole menu into the web page, used by iTopWebPage
* @param \iTopWebPage $oPage
* @param $oPage
* @param $aExtraParams
* @throws DictExceptionMissingString
*/
@@ -211,7 +208,6 @@ class ApplicationMenu
// Sort the root menu based on the rank
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
$iAccordion = 0;
$iActiveAccordion = $iAccordion;
$iActiveMenu = self::GetMenuIndexById(self::GetActiveNodeId());
foreach(self::$aRootMenus as $aMenu)
{
@@ -225,18 +221,16 @@ class ApplicationMenu
$oPage->AddToMenu('</ul>');
if ($bActive)
{
$iActiveAccordion = $iAccordion;
$oPage->add_ready_script(
<<<EOF
// Accordion Menu
$("#accordion").css({display:'block'}).accordion({ header: "h3", navigation: true, heightStyle: "content", collapsible: true, active: $iAccordion, icons: false, animate:true }); // collapsible will be enabled once the item will be selected
EOF
);
}
$oPage->AddToMenu('</div>');
$iAccordion++;
}
$oPage->add_ready_script(
<<<EOF
// Accordion Menu
$("#accordion").css({display:'block'}).accordion({ header: "h3", heightStyle: "content", collapsible: true, active: $iActiveAccordion, icons: false, animate: true }); // collapsible will be enabled once the item will be selected
EOF
);
}
/**
@@ -270,7 +264,7 @@ EOF
/**
* Handles the display of the sub-menus (called recursively if necessary)
* @param \iTopWebPage $oPage
* @param WebPage $oPage
* @param array $aMenus
* @param array $aExtraParams
* @param int $iActiveMenu
@@ -362,7 +356,6 @@ EOF
static public function GetMenuIndexById($sTitle)
{
$index = -1;
/** @var MenuNode[] $aMenu */
foreach(self::$aMenusIndex as $aMenu)
{
if ($aMenu['node']->GetMenuId() == $sTitle)
@@ -844,7 +837,7 @@ class OQLMenuNode extends MenuNode
/**
* Set some extra parameters to be passed to the display block to fine tune its appearence
* @param array $aParams paramCode => value. See DisplayBlock::GetDisplay for the meaning of the parameters
* @param Hash $aParams paramCode => value. See DisplayBlock::GetDisplay for the meaning of the parameters
*/
public function SetParameters($aParams)
{
@@ -957,7 +950,7 @@ class SearchMenuNode extends MenuNode
}
/**
* @param \iTopWebPage $oPage
* @param WebPage $oPage
* @param array $aExtraParams
* @return mixed|void
* @throws DictExceptionMissingString
@@ -1061,9 +1054,7 @@ class NewObjectMenuNode extends MenuNode
/**
* @param string[] $aExtraParams
*
* @return string
* @throws \Exception
*/
public function GetHyperlink($aExtraParams)
{
@@ -1152,11 +1143,37 @@ class DashboardMenuNode extends MenuNode
*/
public function GetDashboard()
{
return RuntimeDashboard::GetDashboard($this->sDashboardFile, $this->sMenuId);
$sDashboardDefinition = @file_get_contents($this->sDashboardFile);
if ($sDashboardDefinition !== false)
{
$bCustomized = false;
// Search for an eventual user defined dashboard, overloading the existing one
$oUDSearch = new DBObjectSearch('UserDashboard');
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oUDSearch->AddCondition('menu_code', $this->sMenuId, '=');
$oUDSet = new DBObjectSet($oUDSearch);
if ($oUDSet->Count() > 0)
{
// Assuming there is at most one couple {user, menu}!
$oUserDashboard = $oUDSet->Fetch();
$sDashboardDefinition = $oUserDashboard->Get('contents');
$bCustomized = true;
}
$oDashboard = new RuntimeDashboard($this->sMenuId);
$oDashboard->FromXml($sDashboardDefinition);
$oDashboard->SetCustomFlag($bCustomized);
}
else
{
$oDashboard = null;
}
return $oDashboard;
}
/**
* @param \iTopWebPage $oPage
* @param WebPage $oPage
* @param string[] $aExtraParams
* @throws CoreException
* @throws Exception
@@ -1169,9 +1186,38 @@ class DashboardMenuNode extends MenuNode
{
$sDivId = preg_replace('/[^a-zA-Z0-9_]/', '', $this->sMenuId);
$oPage->add('<div class="dashboard_contents" id="'.$sDivId.'">');
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
$oDashboard->Render($oPage, false, $aExtraParams);
$oPage->add('</div>');
$oDashboard->RenderEditionTools($oPage);
if ($oDashboard->GetAutoReload())
{
$sId = $this->sMenuId;
$sExtraParams = json_encode($aExtraParams);
$iReloadInterval = 1000 * $oDashboard->GetAutoReloadInterval();
$oPage->add_script(
<<<EOF
setInterval("ReloadDashboard('$sDivId');", $iReloadInterval);
function ReloadDashboard(sDivId)
{
var oExtraParams = $sExtraParams;
// Do not reload when a dialog box is active
if (!($('.ui-dialog:visible').length > 0))
{
$('.dashboard_contents#'+sDivId).block();
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
{ operation: 'reload_dashboard', dashboard_id: '$sId', extra_params: oExtraParams},
function(data){
$('.dashboard_contents#'+sDivId).html(data);
$('.dashboard_contents#'+sDivId).unblock();
}
);
}
}
EOF
);
}
$bEdit = utils::ReadParam('edit', false);
if ($bEdit)

View File

@@ -1,159 +0,0 @@
<?php
// Copyright (C) 2010-2015 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/>
/**
* A provider for messages to be displayed in the iTop Newsroom
*/
interface iNewsroomProvider
{
/**
* Inject the current configuration in the provider
* @param Config $oConfig
* @return void
*/
public function SetConfig(Config $oConfig);
/**
* Tells if this provider is enabled for the given user
* @param User $oUser The user for who to check if the provider is applicable.
* return bool
*/
public function IsApplicable(User $oUser = null);
/**
* The human readable (localized) label for this provider
* @return string
*/
public function GetLabel();
/**
* The URL to query (from the browser, using jsonp) to fetch all unread messages
* @return string
*/
public function GetFetchURL();
/**
* The URL to navigate to in order to display all messages
* @return string
*/
public function GetViewAllURL();
/**
* The URL to query(from the browser, using jsonp) to mark all unread messages as read
* @return string
*/
public function GetMarkAllAsReadURL();
/**
* Return the URL to configure the preferences for this provider or null is there is nothing to configure
* @return string|null
*/
public function GetPreferencesUrl();
/**
* Return an array key => value to be replaced in URL of the messages
* Example: '%itop_root%' => utils::GetAbsoluteUrlAppRoot();
* @return string[]
*/
public function GetPlaceholders();
/**
* The duration between to refreshes of the cache (in seconds)
* @return int
*/
public function GetTTL();
}
/**
* Basic implementation of a Newsroom provider, to be overloaded by your own provider implementation
*
*/
abstract class NewsroomProviderBase implements iNewsroomProvider
{
/**
* The current configuration parameters
* @var Config
*/
protected $oConfig;
public function __construct()
{
$this->oConfig = null;
}
/**
* {@inheritDoc}
* @see iNewsroomProvider::SetConfig()
*/
public function SetConfig(Config $oConfig)
{
$this->oConfig = $oConfig;
}
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetPreferencesUrl()
*/
public function GetPreferencesUrl()
{
return null; // No preferences
}
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetLabel()
*/
public abstract function GetLabel();
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetFetchURL()
*/
public abstract function GetFetchURL();
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetMarkAllURL()
*/
public abstract function GetMarkAllAsReadURL();
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetViewAllURL()
*/
public abstract function GetViewAllURL();
public function IsApplicable(User $oUser = null)
{
return false;
}
/**
* {@inheritDoc}
* @see iNewsroomProvider::GetPlaceholders()
*/
public function GetPlaceholders()
{
return array(); // By default, empty set of placeholders
}
public function GetTTL()
{
return 10*60; // Refresh every 10 minutes
}
}

View File

@@ -37,15 +37,8 @@ class NiceWebPage extends WebPage
{
parent::__construct($s_title, $bPrintable);
$this->m_aReadyScripts = array();
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-3.3.1.min.js');
if(utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser
{
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate-3.0.1.dev.js');
}
else
{
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate-3.0.1.prod.min.js');
}
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-1.12.4.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate-1.4.1.min.js'); // Needed since many other plugins still rely on oldies like $.browser
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/ui-lightness/jquery-ui-1.11.4.custom.css');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui-1.11.4.custom.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
@@ -54,7 +47,6 @@ class NiceWebPage extends WebPage
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.pager.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablehover.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/table-selectable-lines.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_sorter.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/datatable.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.positionBy.js');
@@ -69,7 +61,6 @@ class NiceWebPage extends WebPage
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_external_field.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_numeric.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_enum.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_tag_set.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_external_key.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_hierarchical_key.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/search/search_form_criteria_date_abstract.js');

View File

@@ -35,7 +35,7 @@ class iTopPDF extends TCPDF
// Display the page number (right aligned)
// Warning: the 'R'ight alignment does not work when using placeholders like $this->getAliasNumPage() or $this->getAliasNbPages()
$this->MultiCell($iPageNumberWidth, 15, Dict::Format('Core:BulkExport:PDF:PageNumber' ,$this->page), 0, 'R', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
$this->MultiCell($iPageNumberWidth, 15, 'Page '.$this->page, 0, 'R', false, 0 /* $ln */, '', '', true, 0, false, true, 15, 'M' /* $valign */);
// Branding logo
$sBrandingIcon = APPROOT.'images/itop-logo.png';

View File

@@ -807,7 +807,7 @@ EOF
*/
public function DoUpdateObjectFromPostedForm(DBObject $oObj, $aAttList = null)
{
$sTransactionId = utils::ReadPostedParam('transaction_id', '', 'transaction_id');
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
if (!utils::IsTransactionValid($sTransactionId))
{
throw new TransactionException();

View File

@@ -47,12 +47,13 @@ abstract class Query extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("fields", array("allowed_values"=>null, "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'fields')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'description')); // Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'fields')); // Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', array('name', 'description')); // Criteria of the default search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
@@ -77,9 +78,6 @@ class QueryOQL extends Query
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array("allowed_values"=>null, "sql"=>"oql", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("fields", array("allowed_values"=>null, "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Rolled back to AttributeText until AttributeQueryAttCodeSet can manage fields order correctly
//MetaModel::Init_AddAttribute(new AttributeQueryAttCodeSet("fields", array("allowed_values"=>null,"max_items" => 1000, "query_field" => "oql", "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array('oql'))));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'oql', 'fields')); // Attributes to be displayed for the complete details
@@ -138,41 +136,6 @@ class QueryOQL extends Query
}
return $aFieldsMap;
}
// Rolled back until 'fields' can be properly managed by AttributeQueryAttCodeSet
//
// public function ComputeValues()
// {
// parent::ComputeValues();
//
// // Remove unwanted attribute codes
// $aChanges = $this->ListChanges();
// if (isset($aChanges['fields']))
// {
// $oAttDef = MetaModel::GetAttributeDef(get_class($this), 'fields');
// $aArgs = array('this' => $this);
// $aAllowedValues = $oAttDef->GetAllowedValues($aArgs);
//
// /** @var \ormSet $oValue */
// $oValue = $this->Get('fields');
// $aValues = $oValue->GetValues();
// $bChanged = false;
// foreach($aValues as $key => $sValue)
// {
// if (!isset($aAllowedValues[$sValue]))
// {
// unset($aValues[$key]);
// $bChanged = true;
// }
// }
// if ($bChanged)
// {
// $oValue->SetValues($aValues);
// $this->Set('fields', $oValue);
// }
// }
// }
}
?>

View File

@@ -24,26 +24,6 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
// This storage is freed on error (case of allowed memory exhausted)
$sReservedMemory = str_repeat('*', 1024 * 1024);
register_shutdown_function(function()
{
global $sReservedMemory;
$sReservedMemory = null;
if (!is_null($err = error_get_last()) && ($err['type'] == E_ERROR))
{
if (strpos($err['message'], 'Allowed memory size of') !== false)
{
$sLimit = ini_get('memory_limit');
echo "<p>iTop: Allowed memory size of $sLimit exhausted, contact your administrator to increase memory_limit in php.ini</p>\n";
}
else
{
echo "<p>iTop: An error occurred, check server error log for more information.</p>\n";
}
}
});
require_once(APPROOT.'/core/cmdbobject.class.inc.php');
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/core/contexttag.class.inc.php');

View File

@@ -119,7 +119,7 @@ class privUITransactionSession
// Strictly speaking, the two lines below should be grouped together
// by a critical section
// sem_acquire($rSemIdentified);
$id = static::GetUserPrefix() . str_replace(array('.', ' '), '', microtime()); //1 + count($_SESSION['transactions']);
$id = str_replace(array('.', ' '), '', microtime()); //1 + count($_SESSION['transactions']);
$_SESSION['transactions'][$id] = true;
// sem_release($rSemIdentified);
@@ -174,17 +174,6 @@ class privUITransactionSession
// sem_release($rSemIdentified);
}
}
/**
* Returns a string to prefix transaction ID with info from the current user.
*
* @return string
*/
protected static function GetUserPrefix()
{
$sPrefix = 'u'.UserRights::GetUserId();
return $sPrefix.'-';
}
}
/**
@@ -217,7 +206,7 @@ class privUITransactionFile
throw new Exception('The directory "'.APPROOT.'data/transactions" must be writable to the application.');
}
self::CleanupOldTransactions();
$id = basename(tempnam(APPROOT.'data/transactions', static::GetUserPrefix()));
$id = basename(tempnam(APPROOT.'data/transactions', self::GetUserPrefix()));
self::Info('GetNewTransactionId: Created transaction: '.$id);
return (string)$id;
@@ -321,11 +310,6 @@ class privUITransactionFile
return $aResult;
}
/**
* Returns a prefix based on the user login instead of its ID for a better usage in tempnam()
*
* @inheritdoc
*/
protected static function GetUserPrefix()
{
$sPrefix = substr(UserRights::GetUser(), 0, 10);

View File

@@ -332,8 +332,7 @@ EOF
if ( ($oCurrObject != null) && ($this->sAttCode != ''))
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode);
/** @var \DBObject $oCurrObject */
$aArgs = $oCurrObject->ToArgsForQuery();
$aArgs = array('this' => $oCurrObject);
$aParams = array('query_params' => $aArgs);
$oSet = $oAttDef->GetAllowedValuesAsObjectSet($aArgs);
$oFilter = $oSet->GetFilter();
@@ -403,7 +402,7 @@ EOF
// Current extkey value, so we can display event if it is not available anymore (eg. archived).
$iCurrentExtKeyId = (is_null($oObj)) ? 0 : $oObj->Get($this->sAttCode);
$oBlock = new DisplayBlock($oFilter, 'list_search', false, array('query_params' => array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId)));
$oBlock = new DisplayBlock($oFilter, 'list', false, array('query_params' => array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId)));
$oBlock->Display($oP, $this->iId.'_results', array('this' => $oObj, 'cssCount'=> '#count_'.$this->iId, 'menu' => false, 'selection_mode' => true, 'selection_type' => 'single', 'table_id' => 'select_'.$this->sAttCode)); // Don't display the 'Actions' menu on the results
}

View File

@@ -101,7 +101,7 @@ class UIHTMLEditorWidget
$oPage->add_ready_script(
<<<EOF
$('#$iId').bind('update', function(evt){
BlockField('cke_$iId', $('#$iId').prop('disabled'));
BlockField('cke_$iId', $('#$iId').attr('disabled'));
//Delayed execution - ckeditor must be properly initialized before setting readonly
var retryCount = 0;
var oMe = $('#$iId');

View File

@@ -133,14 +133,15 @@ class UILinksWidget
$sPrefix = "$this->m_sAttCode{$this->m_sNameSuffix}";
$aRow = array();
$aFieldsMap = array();
$iKey = 0;
if(is_object($linkObjOrId) && (!$linkObjOrId->IsNew()))
{
$key = $linkObjOrId->GetKey();
$iKey = $linkObjOrId->GetKey();
$iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote);
$sPrefix .= "[$key][";
$sPrefix .= "[$iKey][";
$sNameSuffix = "]"; // To make a tabular form
$aArgs['prefix'] = $sPrefix;
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}{$key}";
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}{$iKey}";
$aArgs['this'] = $linkObjOrId;
if($bReadOnly)
@@ -154,7 +155,7 @@ class UILinksWidget
}
else
{
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$key\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$key\">";
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$iKey\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$iKey\">";
foreach($this->m_aEditableFields as $sFieldCode)
{
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.$linkObjOrId->GetKey().']';
@@ -195,7 +196,30 @@ class UILinksWidget
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}_".($iUniqueId < 0 ? -$iUniqueId : $iUniqueId);
$aArgs['this'] = $oNewLinkObj;
$sInputValue = $iUniqueId > 0 ? "-$iUniqueId" : "$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=\"$sInputValue\">";
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"0\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$sInputValue\">";
if ($iUniqueId > 0)
{
// Rows created with ajax call need OnLinkAdded call.
//
$oP->add_ready_script(
<<<EOF
PrepareWidgets();
oWidget{$this->m_iInputId}.OnLinkAdded($iUniqueId, $iRemoteObjKey);
EOF
);
}
else
{
// Rows added before loading the form don't have to call OnLinkAdded.
// Listeners are already present and DOM is not recreated
$iPositiveUniqueId = -$iUniqueId;
$oP->add_ready_script(<<<EOF
oWidget{$this->m_iInputId}.AddLink($iPositiveUniqueId, $iRemoteObjKey);
EOF
);
}
foreach($this->m_aEditableFields as $sFieldCode)
{
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.-$iUniqueId.']';
@@ -207,20 +231,12 @@ class UILinksWidget
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId /* id */, $sNameSuffix, 0, $aArgs).
'</div></div></div>';
$aFieldsMap[$sFieldCode] = $sSafeId;
$oP->add_ready_script(<<<EOF
oWidget{$this->m_iInputId}.OnValueChange($iKey, $iUniqueId, '$sFieldCode', '$sValue');
EOF
);
}
$sState = '';
// Rows created with ajax call need OnLinkAdded call.
// Rows added before loading the form cannot call OnLinkAdded.
if ($iUniqueId > 0)
{
$oP->add_ready_script(
<<<EOF
PrepareWidgets();
oWidget{$this->m_iInputId}.OnLinkAdded($iUniqueId, $iRemoteObjKey);
EOF
);
}
}
if(!$bReadOnly)
@@ -337,8 +353,19 @@ EOF
$sHtmlValue .= "<input type=\"hidden\" id=\"{$sFormPrefix}{$this->m_iInputId}\">\n";
$oValue->Rewind();
$aForm = array();
$iAddedId = 1; // Unique id for new links
$aAddedLinks = array();
$iAddedId = -1; // Unique id for new links
$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;
$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}', $sJSDoSearch);
oWidget{$this->m_iInputId}.Init();
EOF
);
while($oCurrentLink = $oValue->Fetch())
{
// We try to retrieve the remote object as usual
@@ -357,9 +384,7 @@ EOF
if ($oCurrentLink->IsNew())
{
$key = -($iAddedId++);
$iUniqueId = -$key;
$aAddedLinks[] = array('iAddedId' => $iUniqueId, 'iRemote' => $oCurrentLink->Get($this->m_sExtKeyToRemote));
$key = $iAddedId--;
}
else
{
@@ -368,24 +393,6 @@ EOF
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
}
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
$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;
$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}', $sJSDoSearch);
oWidget{$this->m_iInputId}.Init();
EOF
);
foreach ($aAddedLinks as $aAddedLink)
{
$oPage->add_ready_script(<<<EOF
oWidget{$this->m_iInputId}.AddLink({$aAddedLink['iAddedId']}, {$aAddedLink['iRemote']});
EOF
);
}
$sHtmlValue .= "<span style=\"float:left;\">&nbsp;&nbsp;&nbsp;<img src=\"../images/tv-item-last.gif\">&nbsp;&nbsp;<input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >";
$sHtmlValue .= "&nbsp;&nbsp;&nbsp;<input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnAdd\" type=\"button\" value=\"".Dict::Format('UI:AddLinkedObjectsOf_Class', MetaModel::GetName($this->m_sRemoteClass))."\" onClick=\"oWidget{$this->m_iInputId}.AddObjects();\"><span id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_indicatorAdd\"></span></span>\n";

View File

@@ -73,17 +73,17 @@ class UIPasswordWidget
$oPage->add_ready_script("$('#{$this->iId}_confirm').bind('keyup change', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
$oPage->add_ready_script("$('#{$this->iId}').bind('update', function(evt, sFormId)
{
if ($(this).prop('disabled'))
if ($(this).attr('disabled'))
{
$('#{$this->iId}_confirm').prop('disabled', true);
$('#{$this->iId}_changed').prop('disabled', true);
$('#{$this->iId}_reset').prop('disabled', true);
$('#{$this->iId}_confirm').attr('disabled', 'disabled');
$('#{$this->iId}_changed').attr('disabled', 'disabled');
$('#{$this->iId}_reset').attr('disabled', 'disabled');
}
else
{
$('#{$this->iId}_confirm').prop('disabled', false);
$('#{$this->iId}_changed').prop('disabled', false);
$('#{$this->iId}_reset').prop('disabled', false);
$('#{$this->iId}_confirm').removeAttr('disabled');
$('#{$this->iId}_changed').removeAttr('disabled');
$('#{$this->iId}_reset').removeAttr('disabled');
}
}
);"); // Bind to a custom event: update to handle enabling/disabling

View File

@@ -273,7 +273,18 @@ class utils
}
return $retValue;
}
/**
* @param string|string[] $value
* @param string $sSanitizationFilter one of : integer, class, string, context_param, parameter, field_name,
* transaction_id, parameter, raw_data
*
* @return string|string[]|bool boolean for :
* * the 'class' filter (true if valid, false otherwise)
* * if the filter fails (@see \filter_var())
*
* @since 2.5.2 2.6.0 new 'transaction_id' filter
*/
protected static function Sanitize_Internal($value, $sSanitizationFilter)
{
switch($sSanitizationFilter)
@@ -320,14 +331,12 @@ class utils
// it must be included at the regexp beginning otherwise you'll get an invalid character error
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[\. A-Za-z0-9_=-]*$/')));
break;
case 'parameter':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[ A-Za-z0-9_=-]*$/'))); // the '=', '%3D, '%2B', '%2F'
// characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
break;
case 'parameter':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/^([ A-Za-z0-9_=-]|%3D|%2B|%2F)*$/'))); // the '=', '%3D, '%2B', '%2F' characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
break;
case 'field_name':
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/^[A-Za-z0-9_]+(->[A-Za-z0-9_]+)*$/'))); // att_code or att_code->name or AttCode->Name or AttCode->Key2->Name
break;
@@ -527,7 +536,7 @@ class utils
/**
* Returns a unique tmp id for the current upload based on the transaction system (db).
*
* Build as static::GetNewTransactionId()
* Build as session_id() . '_' . static::GetNewTransactionId()
*
* @return string
*/
@@ -537,7 +546,7 @@ class utils
{
$sTransactionId = static::GetNewTransactionId();
}
return $sTransactionId;
return session_id() . '_' . $sTransactionId;
}
public static function ReadFromFile($sFileName)
@@ -572,18 +581,6 @@ class utils
}
return $iReturn;
}
/**
* Checks if the memory limit is at least what is required
*
* @param int $memoryLimit set limit in bytes
* @param int $requiredLimit required limit in bytes
* @return bool
*/
public static function IsMemoryLimitOk($memoryLimit, $requiredLimit)
{
return ($memoryLimit >= $requiredLimit) || ($memoryLimit == -1);
}
/**
* Format a value into a more friendly format (KB, MB, GB, TB) instead a juste a Bytes amount.
@@ -728,11 +725,7 @@ class utils
}
/**
* Returns the absolute URL to the application root path
*
* @return string The absolute URL to the application root, without the first slash
*
* @throws \Exception
* @return string The absolute URL to the application, including host and path
*/
static public function GetAbsoluteUrlAppRoot()
{
@@ -761,15 +754,7 @@ class utils
return $sUrl;
}
/**
* Builds an root url from the server's variables.
* For most usages, when an root url is needed, use utils::GetAbsoluteUrlAppRoot() instead as uses this only as a fallback when the app_root_url conf parameter is not defined.
*
* @return string
*
* @throws \Exception
*/
static public function GetDefaultUrlAppRoot()
static public function GetDefaultUrlAppRoot()
{
// Build an absolute URL to this page on this server/port
$sServerName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
@@ -838,7 +823,7 @@ class utils
/**
* Helper to handle the variety of HTTP servers
* See 286 (fixed in [896]), and 634 (this fix)
* See #286 (fixed in [896]), and #634 (this fix)
*
* Though the official specs says 'a non empty string', some servers like IIS do set it to 'off' !
* nginx set it to an empty string
@@ -1091,7 +1076,12 @@ class utils
// $param is a DBObject
$oObj = $param;
$sOQL = "SELECT ".get_class($oObj)." WHERE id=".$oObj->GetKey();
$oFilter = DBObjectSearch::FromOQL($sOQL);
$sFilter = $oFilter->serialize();
$sUrl = ApplicationContext::MakeObjectUrl(get_class($oObj), $oObj->GetKey());
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage(get_class($oObj));
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/tabularfieldsselector.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.dragtable.js');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/dragtable.css');
@@ -1111,29 +1101,21 @@ class utils
break;
case iPopupMenuExtension::MENU_DASHBOARD_ACTIONS:
// $param is a Dashboard
/** @var \RuntimeDashboard $oDashboard */
$oDashboard = $param;
$sDashboardId = $oDashboard->GetId();
$sDashboardFile = $oDashboard->GetDefinitionFile();
$sDlgTitle = addslashes(Dict::S('UI:ImportDashboardTitle'));
$sDlgText = addslashes(Dict::S('UI:ImportDashboardText'));
$sCloseBtn = addslashes(Dict::S('UI:Button:Cancel'));
$sDashboardFileJS = addslashes($sDashboardFile);
$sDashboardFileURL = urlencode($sDashboardFile);
// $param is a Dashboard
$oAppContext = new ApplicationContext();
$aParams = $oAppContext->GetAsHash();
$sMenuId = ApplicationMenu::GetActiveNodeId();
$sDlgTitle = addslashes(Dict::S('UI:ImportDashboardTitle'));
$sDlgText = addslashes(Dict::S('UI:ImportDashboardText'));
$sCloseBtn = addslashes(Dict::S('UI:Button:Cancel'));
$sUploadDashboardTransactId = utils::GetNewTransactionId();
$aResult = array(
new SeparatorPopupMenuItem(),
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sDashboardId.'&file='.$sDashboardFileURL),
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sDashboardId', file: '$sDashboardFileJS', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn', transaction: '$sUploadDashboardTransactId' })"),
);
if ($oDashboard->GetReloadURL())
{
$aResult[] = new SeparatorPopupMenuItem();
$aResult[] = new URLPopupMenuItem('UI:Menu:PrintableVersion', Dict::S('UI:Menu:PrintableVersion'), $oDashboard->GetReloadURL().'&printable=1', '_blank');
}
break;
$aResult = array(
new SeparatorPopupMenuItem(),
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sMenuId),
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'),
"UploadDashboard({dashboard_id: '$sMenuId', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn', transaction: '$sUploadDashboardTransactId' })"),
);
break;
default:
// Unknown type of menu, do nothing
@@ -1500,7 +1482,7 @@ class utils
static public function GetCSSFromSASS($sSassRelPath, $aImportPaths = null)
{
// Avoiding compilation if file is already a css file.
if (preg_match('/\.css(\?.*)?$/', $sSassRelPath))
if (preg_match('/\.css$/', $sSassRelPath))
{
return $sSassRelPath;
}
@@ -2008,14 +1990,4 @@ class utils
$aHugeClasses = MetaModel::GetConfig()->Get('high_cardinality_classes');
return in_array($sClass, $aHugeClasses);
}
/**
* Check if iTop is in a development environment (VCS vs build number)
*
* @return bool
*/
public static function IsDevelopmentEnvironment()
{
return ITOP_REVISION === 'svn';
}
}

View File

@@ -311,10 +311,7 @@ class WebPage implements Page
}
/**
* Add a script (as an include, i.e. link) to the header of the page.<br>
* Handles duplicates : calling twice with the same script will add the script only once
*
* @param string $s_linked_script
* Add a script (as an include, i.e. link) to the header of the page
*/
public function add_linked_script($s_linked_script)
{

View File

@@ -154,7 +154,7 @@ class WizardHelper
}
else
{
// May happen for security reasons (portal, see ticket 1074)
// May happen for security reasons (portal, see ticket #1074)
$oObj->Set($sAttCode, $value);
}
}
@@ -174,30 +174,6 @@ class WizardHelper
}
$oObj->Set($sAttCode, $value);
}
else if ($oAttDef instanceof AttributeTagSet) // AttributeDate is derived from AttributeDateTime
{
if (is_null($value))
{
// happens if field is hidden (see N°1827)
$value = array();
}
else
{
$value = json_decode($value, true);
}
$oTagSet = new ormTagSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems());
$oTagSet->SetValues($value['orig_value']);
$oTagSet->ApplyDelta($value);
$oObj->Set($sAttCode, $oTagSet);
}
else if ($oAttDef instanceof AttributeSet) // AttributeDate is derived from AttributeDateTime
{
$value = json_decode($value, true);
$oTagSet = new ormSet(get_class($oObj), $sAttCode, $oAttDef->GetMaxItems());
$oTagSet->SetValues($value['orig_value']);
$oTagSet->ApplyDelta($value);
$oObj->Set($sAttCode, $oTagSet);
}
else
{
$oObj->Set($sAttCode, $value);
@@ -229,10 +205,11 @@ class WizardHelper
// this as to be handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
// NOT YET IMPLEMENTED !!
$sLinkedClass = $oAttDef->GetLinkedClass();
$oSet = $value;
$aData = array();
$aFields = $this->GetLinkedWizardStructure($oAttDef);
while($oLinkedObj = $oSet->fetch())
while($oSet->fetch())
{
foreach($aFields as $sLinkedAttCode)
{

View File

@@ -40,7 +40,7 @@ Class XLSXWriter
protected function tempFilename()
{
$filename = tempnam(SetupUtils::GettmpDir(), 'xlsx_writer_');
$filename = tempnam("/tmp", "xlsx_writer_");
$this->temp_files[] = $filename;
return $filename;
}

View File

@@ -9,8 +9,6 @@
"ext-json": "*",
"ext-zip": "*",
"ext-mysqli": "*",
"ext-dom": "*",
"ext-iconv": "*",
"ext-gd": "*"
},
"config": {

View File

@@ -223,14 +223,7 @@ class ActionEmail extends ActionNotification
return implode(', ', $aRecipients);
}
/**
* @param \Trigger $oTrigger
* @param array $aContextArgs
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
*/
public function DoExecute($oTrigger, $aContextArgs)
{
if (MetaModel::IsLogEnabledNotification())
@@ -299,14 +292,6 @@ class ActionEmail extends ActionNotification
}
/**
* @param \Trigger $oTrigger
* @param array $aContextArgs
* @param \EventNotification $oLog
*
* @return string
* @throws \CoreException
*/
protected function _DoExecute($oTrigger, $aContextArgs, &$oLog)
{
$sPreviousUrlMaker = ApplicationContext::SetUrlMakerClass();

View File

@@ -150,7 +150,7 @@ abstract class AsyncTask extends DBObject
public function GetRetryDelay($iErrorCode = null)
{
$iRetryDelay = 600;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
{
$aConfig = $aRetries[get_class($this)];
@@ -162,7 +162,7 @@ abstract class AsyncTask extends DBObject
public function GetMaxRetries($iErrorCode = null)
{
$iMaxRetries = 0;
$aRetries = MetaModel::GetConfig()->Get('async_task_retries');
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
{
$aConfig = $aRetries[get_class($this)];
@@ -381,6 +381,6 @@ class AsyncSendEmail extends AsyncTask
case EMAIL_SEND_ERROR:
return "Failed: ".implode(', ', $aIssues);
}
return '';
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,6 @@ MetaModel::IncludeModule('core/action.class.inc.php');
MetaModel::IncludeModule('core/trigger.class.inc.php');
MetaModel::IncludeModule('core/bulkexport.class.inc.php');
MetaModel::IncludeModule('core/ownershiplock.class.inc.php');
MetaModel::IncludeModule('core/tagsetfield.class.inc.php');
MetaModel::IncludeModule('synchro/synchrodatasource.class.inc.php');
MetaModel::IncludeModule('core/backgroundtask.class.inc.php');
MetaModel::IncludeModule('core/inlineimage.class.inc.php');

View File

@@ -242,64 +242,6 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
return $sResult;
}
}
/**
* Record the modification of a tag set attribute
*
* @package iTopORM
*/
class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_setatt_tagset",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeText("oldvalue", array("allowed_values"=>null, "sql"=>"oldvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("newvalue", array("allowed_values"=>null, "sql"=>"newvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
}
/**
* Describe (as a text string) the modifications corresponding to this change
*/
public function GetDescription()
{
$sResult = '';
$sTargetObjectClass = $this->Get('objclass');
$oTargetObjectKey = $this->Get('objkey');
$sAttCode = $this->Get('attcode');
$oTargetSearch = new DBObjectSearch($sTargetObjectClass);
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($sTargetObjectClass, $sAttCode, UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
$sNewValue = $this->Get('newvalue');
$sOldValue = $this->Get('oldvalue');
$sResult = $oAttDef->DescribeChangeAsHTML($sOldValue, $sNewValue);
}
return $sResult;
}
}
/**
* Record the modification of an URL
*

View File

@@ -188,16 +188,6 @@ abstract class CMDBObject extends DBObject
self::$m_oCurrChange->DBInsert();
}
/**
* @inheritdoc
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
protected function RecordObjCreation()
{
// Delete any existing change tracking about the current object (IDs can be reused due to InnoDb bug; see TRAC #886)
@@ -216,7 +206,6 @@ abstract class CMDBObject extends DBObject
MetaModel::PurgeData($oFilter);
parent::RecordObjCreation();
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpCreate");
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
@@ -243,17 +232,9 @@ abstract class CMDBObject extends DBObject
}
/**
* @param string $sAttCode
* @param $sAttCode
* @param $original Original value
* @param $value Current value
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
protected function RecordAttChange($sAttCode, $original, $value)
{
@@ -428,19 +409,7 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("newvalue", $value);
$iId = $oMyChangeOp->DBInsertNoReload();
}
elseif ($oAttDef instanceOf AttributeSet)
{
// Tag Set
//
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeTagSet");
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
$oMyChangeOp->Set("oldvalue", implode(' ', $original->GetValues()));
$oMyChangeOp->Set("newvalue", implode(' ', $value->GetValues()));
$iId = $oMyChangeOp->DBInsertNoReload();
}
else
else
{
// Scalars
//
@@ -457,14 +426,6 @@ abstract class CMDBObject extends DBObject
/**
* @param array $aValues
* @param array $aOrigValues
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
protected function RecordAttChanges(array $aValues, array $aOrigValues)
{
@@ -590,12 +551,6 @@ abstract class CMDBObject extends DBObject
$this->DBUpdate();
}
/**
* @param null $oDeletionPlan
*
* @return \DeletionPlan|null
* @throws \DeleteException
*/
public function DBDelete(&$oDeletionPlan = null)
{
return $this->DBDeleteTracked_Internal($oDeletionPlan);
@@ -608,12 +563,6 @@ abstract class CMDBObject extends DBObject
$this->DBDeleteTracked_Internal($oDeletionPlan);
}
/**
* @param null $oDeletionPlan
*
* @return \DeletionPlan|null
* @throws \DeleteException
*/
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
{
$prevkey = $this->GetKey();

View File

@@ -108,22 +108,18 @@ class MySQLHasGoneAwayException extends MySQLException
*/
class CMDBSource
{
const ENUM_DB_VENDOR_MYSQL = 'MySQL';
const ENUM_DB_VENDOR_MARIADB = 'MariaDB';
const ENUM_DB_VENDOR_PERCONA = 'Percona';
protected static $m_sDBHost;
protected static $m_sDBUser;
protected static $m_sDBPwd;
protected static $m_sDBName;
/**
* @var boolean
* @since 2.5 1260 MySQL TLS first implementation
* @since 2.5 #1260 MySQL TLS first implementation
*/
protected static $m_bDBTlsEnabled;
/**
* @var string
* @since 2.5 1260 MySQL TLS first implementation
* @since 2.5 #1260 MySQL TLS first implementation
*/
protected static $m_sDBTlsCA;
@@ -137,7 +133,7 @@ class CMDBSource
* use expression as value)
*
* @see https://dev.mysql.com/doc/refman/5.7/en/charset-column.html
* @since 2.5 1001 switch to utf8mb4
* @since 2.5 #1001 switch to utf8mb4
*/
public static function GetSqlStringColumnDefinition()
{
@@ -410,27 +406,6 @@ class CMDBSource
return $aVersions[0];
}
/**
* Get the DB vendor between MySQL and its main forks
* @return string
*/
static public function GetDBVendor()
{
$sDBVendor = static::ENUM_DB_VENDOR_MYSQL;
$sVersionComment = static::GetServerVariable('version') . ' - ' . static::GetServerVariable('version_comment');
if(preg_match('/mariadb/i', $sVersionComment) === 1)
{
$sDBVendor = static::ENUM_DB_VENDOR_MARIADB;
}
else if(preg_match('/percona/i', $sVersionComment) === 1)
{
$sDBVendor = static::ENUM_DB_VENDOR_PERCONA;
}
return $sDBVendor;
}
/**
* @param string $sSource
*
@@ -480,15 +455,10 @@ class CMDBSource
public static function DropTable($sTable)
{
$res = self::Query("DROP TABLE `$sTable`");
self::_TablesInfoCacheReset(); // reset the table info cache!
self::_TablesInfoCacheReset(true); // reset the table info cache!
return $res;
}
public static function CacheReset($sTable)
{
self::_TablesInfoCacheReset($sTable);
}
/**
* @return \mysqli
*/
@@ -900,20 +870,6 @@ class CMDBSource
return ($aFieldData["Type"]);
}
private static function IsNumericType($aFieldData)
{
$aNumericTypes = array('tinyint(', 'decimal(', 'int(' );
$sType = strtolower($aFieldData["Type"]);
foreach ($aNumericTypes as $sNumericType)
{
if (strpos($sType, $sNumericType) === 0)
{
return true;
}
}
return false;
}
/**
* @param string $sTable
* @param string $sField
@@ -952,15 +908,8 @@ class CMDBSource
}
else
{
if (self::IsNumericType($aFieldData))
{
$sRet .= ' DEFAULT '.$aFieldData["Default"];
}
else
{
$default = $aFieldData["Default"] + 0; // Coerce to a numeric variable
$sRet .= ' DEFAULT '.self::Quote($default);
}
$default = $aFieldData["Default"] + 0; // Coerce to a numeric variable
$sRet .= ' DEFAULT '.self::Quote($default);
}
}
elseif (is_string($aFieldData["Default"]) == 'string')
@@ -1018,16 +967,9 @@ class CMDBSource
// Cache the information about existing tables, and their fields
private static $m_aTablesInfo = array();
private static function _TablesInfoCacheReset($sTableName = null)
private static function _TablesInfoCacheReset()
{
if (is_null($sTableName))
{
self::$m_aTablesInfo = array();
}
else
{
self::$m_aTablesInfo[strtolower($sTableName)] = null;
}
self::$m_aTablesInfo = array();
}
/**
@@ -1100,7 +1042,7 @@ class CMDBSource
* @return string query to upgrade table charset and collation if needed, null if not
* @throws \MySQLException
*
* @since 2.5 1001 switch to utf8mb4
* @since 2.5 #1001 switch to utf8mb4
* @see https://dev.mysql.com/doc/refman/5.7/en/charset-table.html
*/
public static function DBCheckTableCharsetAndCollation($sTableName)
@@ -1250,7 +1192,7 @@ class CMDBSource
* @return string query to upgrade database charset and collation if needed, null if not
* @throws \MySQLException
*
* @since 2.5 1001 switch to utf8mb4
* @since 2.5 #1001 switch to utf8mb4
* @see https://dev.mysql.com/doc/refman/5.7/en/charset-database.html
*/
public static function DBCheckCharsetAndCollation()

View File

@@ -19,7 +19,7 @@
define('ITOP_APPLICATION', 'iTop');
define('ITOP_APPLICATION_SHORT', 'iTop');
define('ITOP_VERSION', '2.6.0');
define('ITOP_VERSION', '2.5.0');
define('ITOP_REVISION', 'svn');
define('ITOP_BUILD_DATE', '$WCNOW$');
@@ -37,7 +37,6 @@ define('ACCESS_READONLY', 0);
require_once('coreexception.class.inc.php');
require_once('attributedef.class.inc.php'); // For the defines
require_once('simplecrypt.class.inc.php');
class ConfigException extends CoreException
{
@@ -65,16 +64,13 @@ define('DEFAULT_FAST_RELOAD_INTERVAL', 1 * 60);
define('DEFAULT_SECURE_CONNECTION_REQUIRED', false);
define('DEFAULT_ALLOWED_LOGIN_TYPES', 'form|basic|external');
define('DEFAULT_EXT_AUTH_VARIABLE', '$_SERVER[\'REMOTE_USER\']');
define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random generated key later (if possible)
define('DEFAULT_ENCRYPTION_LIB', 'Mcrypt'); // We'll define the best encryption available later
define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random value, later...
/**
* Config
* configuration data (this class cannot not be localized, because it is responsible for loading the dictionaries)
*
* @package iTopORM
*
* @see \MetaModel::GetConfig() to get the config, if the metamodel was already loaded
* @see utils::GetConfig() to load config from the current env, if metamodel is not loaded
*/
class Config
{
@@ -97,7 +93,7 @@ class Config
protected $m_aSettings = array(
'app_env_label' => array(
'type' => 'string',
'description' => 'Label displayed to describe the current application environment, defaults to the environment name (e.g. "production")',
'description' => 'Label displayed to describe the current application environnment, defaults to the environment name (e.g. "production")',
'default' => '',
'value' => '',
'source_of_value' => '',
@@ -170,7 +166,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'db_character_set' => array( // @deprecated to remove in 2.7 ? 1001 utf8mb4 switch
'db_character_set' => array( // @deprecated to remove in 2.7 ? #1001 utf8mb4 switch
'type' => 'string',
'description' => 'Deprecated since iTop 2.5 : now using utf8mb4',
'default' => 'DEPRECATED_2.5',
@@ -178,7 +174,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'db_collation' => array( // @deprecated to remove in 2.7 ? 1001 utf8mb4 switch
'db_collation' => array( // @deprecated to remove in 2.7 ? #1001 utf8mb4 switch
'type' => 'string',
'description' => 'Deprecated since iTop 2.5 : now using utf8mb4_unicode_ci',
'default' => 'DEPRECATED_2.5',
@@ -204,7 +200,7 @@ class Config
),
'skip_strong_security' => array(
'type' => 'bool',
'description' => 'Disable strong security - TEMPORARY: this flag should be removed when we are more confident in the recent change in security',
'description' => 'Disable strong security - TEMPORY: this flag should be removed when we are more confident in the recent change in security',
'default' => true,
'value' => true,
'source_of_value' => '',
@@ -220,7 +216,7 @@ class Config
),
'query_indentation_enabled' => array(
'type' => 'bool',
'description' => 'For developers: format the SQL queries for human analysis',
'description' => 'For developpers: format the SQL queries for human analysis',
'default' => false,
'value' => false,
'source_of_value' => '',
@@ -228,7 +224,7 @@ class Config
),
'disable_mandatory_ext_keys' => array(
'type' => 'bool',
'description' => 'For developers: allow every external keys to be undefined',
'description' => 'For developpers: allow every external keys to be undefined',
'default' => false,
'value' => false,
'source_of_value' => '',
@@ -411,14 +407,6 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'tag_set_item_separator' => array(
'type' => 'string',
'description' => 'Tag set from string: tag label separator',
'default' => '|',
'value' => '|',
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'cron_max_execution_time' => array(
'type' => 'integer',
'description' => 'Duration (seconds) of the page cron.php, must be shorter than php setting max_execution_time and shorter than the web server response timeout',
@@ -453,7 +441,7 @@ class Config
),
'email_transport' => array(
'type' => 'string',
'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocol)',
'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocole)',
'default' => "PHPMail",
'value' => "PHPMail",
'source_of_value' => '',
@@ -549,7 +537,7 @@ class Config
),
'timezone' => array(
'type' => 'string',
'description' => 'Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitly 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',
// examples... not used (nor 'description')
'examples' => array(
'America/Sao_Paulo',
@@ -947,7 +935,7 @@ class Config
),
'tracking_level_linked_set_default' => array(
'type' => 'integer',
'description' => 'Default tracking level if not explicitly set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)',
'description' => 'Default tracking level if not explicitely set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)',
'default' => LINKSET_TRACKING_LIST,
'value' => LINKSET_TRACKING_LIST,
'source_of_value' => '',
@@ -955,7 +943,7 @@ class Config
),
'tracking_level_linked_set_indirect_default' => array(
'type' => 'integer',
'description' => 'Default tracking level if not explicitly set at the attribute level, for AttributeLinkedSetIndirect',
'description' => 'Default tracking level if not explicitely set at the attribute level, for AttributeLinkedSetIndirect',
'default' => LINKSET_TRACKING_ALL,
'value' => LINKSET_TRACKING_ALL,
'source_of_value' => '',
@@ -996,7 +984,7 @@ class Config
'transaction_storage' => array(
'type' => 'string',
'description' => 'The type of mechanism to use for storing the unique identifiers for transactions (Session|File).',
'default' => 'File',
'default' => 'Session',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
@@ -1068,7 +1056,7 @@ class Config
'draft_attachments_lifetime' => array(
'type' => 'integer',
'description' => 'Lifetime (in seconds) of drafts\' attachments and inline images: after this duration, the garbage collector will delete them.',
'default' => 86400,
'default' => 3600,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
@@ -1129,14 +1117,6 @@ class Config
'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 manual submit of search)',
@@ -1145,22 +1125,6 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'newsroom_enabled' => array(
'type' => 'bool',
'description' => 'Whether or not the whole newsroom is enabled',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'regenerate_session_id_enabled' => array(
'type' => 'bool',
'description' => 'If true then session id will be regenerated on each login, to prevent session fixation.',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
);
public function IsProperty($sPropCode)
@@ -1220,11 +1184,6 @@ class Config
}
/**
* @param string $sPropCode
*
* @return mixed
*/
public function Get($sPropCode)
{
return $this->m_aSettings[$sPropCode]['value'];
@@ -1287,29 +1246,13 @@ class Config
*/
protected $m_sEncryptionKey;
/**
* @var string Encryption key used for all attributes of type "encrypted string". Can be set to a random value
* unless you want to import a database from another iTop instance, in which case you must use
* the same encryption key in order to properly decode the encrypted fields
*/
protected $m_sEncryptionLibrary;
/**
* @var array Additional character sets to be supported by the interactive CSV import
* 'iconv_code' => 'display name'
*/
protected $m_aCharsets;
/**
* Config constructor.
*
* @param string|null $sConfigFile
* @param bool $bLoadConfig
*
* @throws \ConfigException
* @throws \CoreException
*/
public function __construct($sConfigFile = null, $bLoadConfig = true)
public function __construct($sConfigFile = null, $bLoadConfig = true)
{
$this->m_sFile = $sConfigFile;
if (is_null($sConfigFile))
@@ -1339,14 +1282,10 @@ class Config
$this->m_sDefaultLanguage = 'EN US';
$this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES;
$this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE;
$this->m_sEncryptionKey = DEFAULT_ENCRYPTION_KEY;
$this->m_aCharsets = array();
$this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED;
//define default encryption params according to php install
$aEncryptParams = SimpleCrypt::GetNewDefaultParams();
$this->m_sEncryptionLibrary = isset($aEncryptParams['lib']) ? $aEncryptParams['lib'] : DEFAULT_ENCRYPTION_LIB;
$this->m_sEncryptionKey= isset($aEncryptParams['key']) ? $aEncryptParams['key'] : DEFAULT_ENCRYPTION_KEY;
$this->m_aModuleSettings = array();
if ($bLoadConfig)
@@ -1371,13 +1310,7 @@ class Config
*/
}
/**
* @param string $sPurpose
* @param string $sFileName
*
* @throws \ConfigException
*/
protected function CheckFile($sPurpose, $sFileName)
protected function CheckFile($sPurpose, $sFileName)
{
if (!file_exists($sFileName))
{
@@ -1492,8 +1425,7 @@ class Config
$this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US';
$this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES;
$this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE;
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey;
$this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary;
$this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : DEFAULT_ENCRYPTION_KEY;
$this->m_aCharsets = isset($MySettings['csv_import_charsets']) ? $MySettings['csv_import_charsets'] : array();
}
@@ -1514,14 +1446,7 @@ class Config
return $this->GetModuleParameter($sModule, $sProperty, $defaultvalue);
}
/**
* @param string $sModule
* @param string $sProperty
* @param mixed|null $defaultvalue
*
* @return mixed|null
*/
public function GetModuleParameter($sModule, $sProperty, $defaultvalue = null)
public function GetModuleParameter($sModule, $sProperty, $defaultvalue = null)
{
$ret = $defaultvalue;
if (class_exists('ModulesXMLParameters'))
@@ -1553,7 +1478,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1564,7 +1488,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1575,7 +1498,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1586,8 +1508,7 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6 N°1001 utf8mb4 switch
* @deprecated 2.5 will be removed in 2.6 #1001 utf8mb4 switch
* @see Config::DEFAULT_CHARACTER_SET
*/
public function GetDBCharacterSet()
@@ -1597,8 +1518,7 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6 N°1001 utf8mb4 switch
* @deprecated 2.5 will be removed in 2.6 #1001 utf8mb4 switch
* @see Config::DEFAULT_COLLATION
*/
public function GetDBCollation()
@@ -1608,7 +1528,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1619,7 +1538,6 @@ class Config
/**
* @return string
*
* @deprecated 2.5 will be removed in 2.6
* @see Config::Get() as a replacement
*/
@@ -1693,11 +1611,6 @@ class Config
return $this->m_sEncryptionKey;
}
public function GetEncryptionLibrary()
{
return $this->m_sEncryptionLibrary;
}
public function GetAllowedLoginTypes()
{
return explode('|', $this->m_sAllowedLoginTypes);
@@ -1826,7 +1739,6 @@ class Config
$aSettings['allowed_login_types'] = $this->m_sAllowedLoginTypes;
$aSettings['ext_auth_variable'] = $this->m_sExtAuthVariable;
$aSettings['encryption_key'] = $this->m_sEncryptionKey;
$aSettings['encryption_library'] = $this->m_sEncryptionLibrary;
$aSettings['csv_import_charsets'] = $this->m_aCharsets;
foreach ($this->m_aModuleSettings as $sModule => $aProperties)
@@ -1844,16 +1756,14 @@ class Config
return $aSettings;
}
/**
* Write the configuration to a file (php format) that can be reloaded later
* By default write to the same file that was specified when constructing the object
*
* @param string $sFileName string Name of the file to write to (emtpy to write to the same file)
*
* @return boolean True otherwise throws an Exception
/**
* Write the configuration to a file (php format) that can be reloaded later
* By default write to the same file that was specified when constructing the object
*
* @throws \ConfigException
*/
* @param $sFileName string Name of the file to write to (emtpy to write to the same file)
*
* @return boolean True otherwise throws an Exception
*/
public function WriteToFile($sFileName = '')
{
if (empty($sFileName))
@@ -1915,7 +1825,6 @@ class Config
'allowed_login_types' => $this->m_sAllowedLoginTypes,
'ext_auth_variable' => $this->m_sExtAuthVariable,
'encryption_key' => $this->m_sEncryptionKey,
'encryption_library' => $this->m_sEncryptionLibrary,
'csv_import_charsets' => $this->m_aCharsets,
);
foreach ($aOtherValues as $sKey => $value)
@@ -2001,16 +1910,9 @@ class Config
}
}
/**
* Helper function to initialize a configuration from the page arguments
*
* @param array $aParamValues
* @param string|null $sModulesDir
* @param bool $bPreserveModuleSettings
*
* @throws \Exception
* @throws \CoreException
*/
/**
* Helper function to initialize a configuration from the page arguments
*/
public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false)
{
if (isset($aParamValues['application_path']))
@@ -2140,13 +2042,9 @@ class Config
}
}
/**
* Helper: for an array of string, change the prefix when found
*
* @param array $aStrings
* @param string $sSearchPrefix
* @param string $sNewPrefix
*/
/**
* Helper: for an array of string, change the prefix when found
*/
protected static function ChangePrefix(&$aStrings, $sSearchPrefix, $sNewPrefix)
{
foreach ($aStrings as &$sFile)
@@ -2158,13 +2056,10 @@ class Config
}
}
/**
* Obsolete: kept only for backward compatibility of the Toolkit
* Quick and dirty way to clone a config file into another environment
*
* @param string $sSourceEnv
* @param string $sTargetEnv
*/
/**
* Obsolete: kept only for backward compatibility of the Toolkit
* Quick and dirty way to clone a config file into another environment
*/
public function ChangeModulesPath($sSourceEnv, $sTargetEnv)
{
// Now does nothing since the includes are built into the environment itself
@@ -2201,3 +2096,5 @@ class Config
}
}
?>

View File

@@ -107,82 +107,6 @@ class CoreException extends Exception
}
}
/**
* Class CoreCannotSaveObjectException
*
* Specialized exception to raise if {@link DBObject::CheckToWrite()} fails, which allow easy data retrieval
*
* @see \DBObject::DBInsertNoReload()
* @see \DBObject::DBUpdate()
*
* @since 2.6 N°659 uniqueness constraint
*/
class CoreCannotSaveObjectException extends CoreException
{
/** @var string[] */
private $aIssues;
/** @var int */
private $iObjectId;
/** @var string */
private $sObjectClass;
/**
* CoreCannotSaveObjectException constructor.
*
* @param array $aContextData containing at least those keys : issues, id, class
*/
public function __construct($aContextData)
{
$this->aIssues = $aContextData['issues'];
$this->iObjectId = $aContextData['id'];
$this->sObjectClass = $aContextData['class'];
$sIssues = implode(', ', $this->aIssues);
parent::__construct($sIssues, $aContextData);
}
/**
* @return string
*/
public function getHtmlMessage()
{
$sTitle = Dict::S('UI:Error:SaveFailed');
$sContent = "<span><strong>{$sTitle}</strong></span>";
if (count($this->aIssues) == 1)
{
$sIssue = reset($this->aIssues);
$sContent .= " <span>{$sIssue}</span>";
}
else
{
$sContent .= '<ul>';
foreach ($this->aIssues as $sError)
{
$sContent .= "<li>$sError</li>";
}
$sContent .= '</ul>';
}
return $sContent;
}
public function getIssues()
{
return $this->aIssues;
}
public function getObjectId()
{
return $this->iObjectId;
}
public function getObjectClass()
{
return $this->sObjectClass;
}
}
class CoreWarning extends CoreException
{
}

View File

@@ -266,7 +266,7 @@ EOF
if ($this->aStatusInfo['charset'] != 'UTF-8')
{
// Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
// and thus to convert field by field and not the whole row or file at once (see ticket 991)
// and thus to convert field by field and not the whole row or file at once (see ticket #991)
$aData[$idx] = @iconv('UTF-8', $this->aStatusInfo['charset'].'//IGNORE//TRANSLIT', $aData[$idx]);
}
}
@@ -325,7 +325,7 @@ EOF
if ($this->aStatusInfo['charset'] != 'UTF-8')
{
// Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
// and thus to convert field by field and not the whole row or file at once (see ticket 991)
// and thus to convert field by field and not the whole row or file at once (see ticket #991)
$aData[] = @iconv('UTF-8', $this->aStatusInfo['charset'].'//IGNORE//TRANSLIT', $sField);
}
else

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.5">
<user_rights>
<profiles>
<profile id="1024" _delta="define">

File diff suppressed because it is too large Load Diff

View File

@@ -480,11 +480,6 @@ class DBObjectSearch extends DBSearch
$oNewCondition = Expression::FromOQL($sOQLCondition);
break;
case 'MATCHES':
$oRightExpr = new ScalarExpression($value);
$oNewCondition = new MatchExpression($oField, $oRightExpr);
break;
case 'Contains':
case 'Begins with':
case 'Finishes with':
@@ -1304,13 +1299,6 @@ class DBObjectSearch extends DBSearch
$oRight = $this->OQLExpressionToCondition($sQuery, $oExpression->GetRightExpr(), $aClassAliases);
return new BinaryExpression($oLeft, $sOperator, $oRight);
}
elseif ($oExpression instanceof MatchOqlExpression)
{
$oLeft = $this->OQLExpressionToCondition($sQuery, $oExpression->GetLeftExpr(), $aClassAliases);
$oRight = $this->OQLExpressionToCondition($sQuery, $oExpression->GetRightExpr(), $aClassAliases);
return new MatchExpression($oLeft, $oRight);
}
elseif ($oExpression instanceof FieldOqlExpression)
{
$sClassAlias = $oExpression->GetParent();
@@ -1937,86 +1925,46 @@ class DBObjectSearch extends DBSearch
}
}
$bRootFirst = MetaModel::GetConfig()->Get('optimize_requests_for_join_count');
if ($bRootFirst)
// 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)
{
// 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))
{
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));
}
continue;
}
}
else
{
// First query built upon on the leaf (ie current) class
//
self::DbgTrace("Main (=leaf) class, call MakeSQLObjectQuerySingleTable()");
if (MetaModel::HasTable($sClass))
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 = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sClass, $aExtKeys, $aValues);
$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 = 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));
}
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sSomeClass));
}
}

View File

@@ -38,7 +38,7 @@ class DBObjectSet implements iDBObjectSetIterator
*/
protected $m_aAddedIds; // Ids of objects added (discrete lists)
/**
* @var array array of (row => array of (classalias) => object/null) storing the objects added "in memory"
* @var hash array of (row => array of (classalias) => object/null) storing the objects added "in memory"
*/
protected $m_aAddedObjects;
/**
@@ -118,19 +118,12 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
/**
* @return string
*
* @throws \Exception
* @throws \CoreException
* @throws \MissingQueryArgument
*/
public function __toString()
{
$sRet = '';
$this->Rewind();
$sRet .= "Set (".$this->m_oFilter->ToOQL().")<br/>\n";
$sRet .= "Query: <pre style=\"font-size: smaller; display:inline;\">".$this->m_oFilter->MakeSelectQuery().")</pre>\n";
$sRet .= "Query: <pre style=\"font-size: smaller; display:inline;\">".$this->m_oFilter->MakeSelectQuery().")</pre>\n";
$sRet .= $this->Count()." records<br/>\n";
if ($this->Count() > 0)
@@ -178,16 +171,13 @@ class DBObjectSet implements iDBObjectSetIterator
return $this->m_oFilter->GetShowObsoleteData();
}
/**
* Specify the subset of attributes to load (for each class of objects) before performing the SQL query for retrieving the rows from the DB
*
* @param array $aAttToLoad Format: alias => array of attribute_codes
*
* @return void
*
* @throws \Exception
* @throws \CoreException
*/
/**
* Specify the subset of attributes to load (for each class of objects) before performing the SQL query for retrieving the rows from the DB
*
* @param array $aAttToLoad Format: alias => array of attribute_codes
*
* @return void
*/
public function OptimizeColumnLoad($aAttToLoad)
{
if (is_null($aAttToLoad))
@@ -259,15 +249,13 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
/**
* Create a set (in-memory) containing just the given object
*
* @param \DBobject $oObject
*
* @return \DBObjectSet The singleton set
*
* @throws \Exception
*/
/**
* Create a set (in-memory) containing just the given object
*
* @param DBobject $oObject
*
* @return DBObjectSet The singleton set
*/
static public function FromObject($oObject)
{
$oRetSet = self::FromScratch(get_class($oObject));
@@ -275,15 +263,13 @@ class DBObjectSet implements iDBObjectSetIterator
return $oRetSet;
}
/**
* Create an empty set (in-memory), for the given class (and its subclasses) of objects
*
* @param string $sClass The class (or an ancestor) for the objects to be added in this set
*
* @return \DBObjectSet The empty set
*
* @throws \Exception
*/
/**
* Create an empty set (in-memory), for the given class (and its subclasses) of objects
*
* @param string $sClass The class (or an ancestor) for the objects to be added in this set
*
* @return DBObjectSet The empty set
*/
static public function FromScratch($sClass)
{
$oFilter = new DBObjectSearch($sClass);
@@ -292,38 +278,34 @@ class DBObjectSet implements iDBObjectSetIterator
$oRetSet->m_bLoaded = true; // no DB load
$oRetSet->m_iNumTotalDBRows = 0; // Nothing from the DB
return $oRetSet;
}
}
/**
* Create a set (in-memory) with just one column (i.e. one object per row) and filled with the given array of objects
*
* @param string $sClass The class of the objects (must be a common ancestor to all objects in the set)
* @param array $aObjects The list of objects to add into the set
*
* @return \DBObjectSet
*
* @throws \Exception
*/
/**
* Create a set (in-memory) with just one column (i.e. one object per row) and filled with the given array of objects
*
* @param string $sClass The class of the objects (must be a common ancestor to all objects in the set)
* @param array $aObjects The list of objects to add into the set
*
* @return DBObjectSet
*/
static public function FromArray($sClass, $aObjects)
{
$oRetSet = self::FromScratch($sClass);
$oRetSet->AddObjectArray($aObjects, $sClass);
return $oRetSet;
}
}
/**
* Create a set in-memory with several classes of objects per row (with one alias per "column")
*
* Limitation:
* The filter/OQL query representing such a set can not be rebuilt (only the first column will be taken into account)
*
* @param array $aClasses Format: array of (alias => class)
* @param array $aObjects Format: array of (array of (classalias => object))
*
* @return \DBObjectSet
*
* @throws \Exception
*/
/**
* Create a set in-memory with several classes of objects per row (with one alias per "column")
*
* Limitation:
* The filter/OQL query representing such a set can not be rebuilt (only the first column will be taken into account)
*
* @param hash $aClasses Format: array of (alias => class)
* @param hash $aObjects Format: array of (array of (classalias => object))
*
* @return DBObjectSet
*/
static public function FromArrayAssoc($aClasses, $aObjects)
{
// In a perfect world, we should create a complete tree of DBObjectSearch,
@@ -342,19 +324,9 @@ class DBObjectSet implements iDBObjectSetIterator
$oRetSet->AddObjectExtended($aObjectsByClassAlias);
}
return $oRetSet;
}
}
/**
* @param $oObject
* @param string $sLinkSetAttCode
* @param string $sExtKeyToRemote
*
* @return \DBObjectSet
*
* @throws \Exception
* @throws \ArchivedObjectException
* @throws \CoreException
*/static public function FromLinkSet($oObject, $sLinkSetAttCode, $sExtKeyToRemote)
static public function FromLinkSet($oObject, $sLinkSetAttCode, $sExtKeyToRemote)
{
$oLinkAttCode = MetaModel::GetAttributeDef(get_class($oObject), $sLinkSetAttCode);
$oExtKeyAttDef = MetaModel::GetAttributeDef($oLinkAttCode->GetLinkedClass(), $sExtKeyToRemote);
@@ -374,13 +346,7 @@ class DBObjectSet implements iDBObjectSetIterator
* 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
*
* @return array
*
* @throws \Exception
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public function ToArray($bWithId = true)
{
@@ -398,16 +364,8 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
return $aRet;
}
}
/**
* @return array
*
* @throws \Exception
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public function ToArrayOfValues()
{
if (!$this->m_bLoaded) $this->Load();
@@ -463,11 +421,7 @@ class DBObjectSet implements iDBObjectSetIterator
*
* @param string $sAttCode
* @param bool $bWithId
*
* @return array
*
* @throws \Exception
* @throws \CoreException
*/
public function GetColumnAsArray($sAttCode, $bWithId = true)
{
@@ -487,16 +441,14 @@ class DBObjectSet implements iDBObjectSetIterator
return $aRet;
}
/**
* Retrieve the DBSearch corresponding to the objects present in this set
*
* Limitation:
* This method will NOT work for sets with several columns (i.e. several objects per row)
*
* @return \DBObjectSearch
*
* @throws \CoreException
*/
/**
* Retrieve the DBSearch corresponding to the objects present in this set
*
* Limitation:
* This method will NOT work for sets with several columns (i.e. several objects per row)
*
* @return DBObjectSearch
*/
public function GetFilter()
{
// Make sure that we carry on the parameters of the set with the filter
@@ -543,20 +495,18 @@ class DBObjectSet implements iDBObjectSetIterator
/**
* The list of all classes (one per column) which are part of this set
*
* @return array Format: alias => class
* @return hash Format: alias => class
*/
public function GetSelectedClasses()
{
return $this->m_oFilter->GetSelectedClasses();
}
/**
* The root class (i.e. highest ancestor in the MeaModel class hierarchy) for the first column on this set
*
* @return string The root class for the objects in the first column of the set
*
* @throws \CoreException
*/
/**
* The root class (i.e. highest ancestor in the MeaModel class hierarchy) for the first column on this set
*
* @return string The root class for the objects in the first column of the set
*/
public function GetRootClass()
{
return MetaModel::GetRootClass($this->GetClass());
@@ -565,7 +515,7 @@ class DBObjectSet implements iDBObjectSetIterator
/**
* The arguments used for building this set
*
* @return array Format: parameter_name => value
* @return hash Format: parameter_name => value
*/
public function GetArgs()
{
@@ -583,13 +533,11 @@ class DBObjectSet implements iDBObjectSetIterator
$this->m_iLimitStart = $iLimitStart;
}
/**
* Sets the sort order for loading the rows from the DB. Changing the order by causes a Reload.
*
* @param array $aOrderBy Format: [alias.]attcode => boolean (true = ascending, false = descending)
*
* @throws \MySQLException
*/
/**
* Sets the sort order for loading the rows from the DB. Changing the order by causes a Reload.
*
* @param hash $aOrderBy Format: [alias.]attcode => boolean (true = ascending, false = descending)
*/
public function SetOrderBy($aOrderBy)
{
if ($this->m_aOrderBy != $aOrderBy)
@@ -603,14 +551,11 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
/**
* Sets the sort order for loading the rows from the DB. Changing the order by causes a Reload.
*
* @param array $aAliases Format: alias => boolean (true = ascending, false = descending). If omitted, then it defaults to all the selected classes
*
* @throws \CoreException
* @throws \MySQLException
*/
/**
* Sets the sort order for loading the rows from the DB. Changing the order by causes a Reload.
*
* @param hash $aAliases Format: alias => boolean (true = ascending, false = descending). If omitted, then it defaults to all the selected classes
*/
public function SetOrderByClasses($aAliases = null)
{
if ($aAliases === null)
@@ -654,15 +599,13 @@ class DBObjectSet implements iDBObjectSetIterator
return $this->m_iLimitStart;
}
/**
* Get the sort order used for loading this set from the database
*
* Limitation: the sort order has no effect on objects added in-memory
*
* @return array Format: field_code => boolean (true = ascending, false = descending)
*
* @throws \CoreException
*/
/**
* Get the sort order used for loading this set from the database
*
* Limitation: the sort order has no effect on objects added in-memory
*
* @return array Format: field_code => boolean (true = ascending, false = descending)
*/
public function GetRealSortOrder()
{
if (!$this->m_bSort)
@@ -682,12 +625,9 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
/**
* Loads the set from the database. Actually performs the SQL query to retrieve the records from the DB.
*
* @throws \Exception
* @throws \MySQLException
*/
/**
* Loads the set from the database. Actually performs the SQL query to retrieve the records from the DB.
*/
public function Load()
{
if ($this->m_bLoaded) return;
@@ -742,14 +682,11 @@ class DBObjectSet implements iDBObjectSetIterator
$this->m_iNumLoadedDBRows = $this->m_oSQLResult->num_rows;
}
/**
* @param string[] $aAttToLoad
*
* @return string SQL query
*
* @throws \CoreException
* @throws \MissingQueryArgument
*/
/**
* @param string[] $aAttToLoad
*
* @return string SQL query
*/
private function _makeSelectQuery($aAttToLoad)
{
if ($this->m_iLimitCount > 0)
@@ -766,20 +703,15 @@ class DBObjectSet implements iDBObjectSetIterator
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
*
* @return int The total number of rows for this set.
*
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
/**
* 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
*
* @return int The total number of rows for this set.
*/
public function Count()
{
if (is_null($this->m_iNumTotalDBRows))
@@ -800,7 +732,6 @@ class DBObjectSet implements iDBObjectSetIterator
* @param $iLimit
*
* @return bool
*
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
@@ -815,8 +746,8 @@ class DBObjectSet implements iDBObjectSetIterator
if ($resQuery)
{
$aRow = CMDBSource::FetchArray($resQuery);
$iCount = intval($aRow['COUNT']);
CMDBSource::FreeResult($resQuery);
$iCount = intval($aRow['COUNT']);
}
else
{
@@ -835,7 +766,6 @@ class DBObjectSet implements iDBObjectSetIterator
* @param $iLimit
*
* @return int
*
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
@@ -876,17 +806,12 @@ class DBObjectSet implements iDBObjectSetIterator
return $this->m_iNumLoadedDBRows + count($this->m_aAddedObjects);
}
/**
* Fetch the object (with the given class alias) at the current position in the set and move the cursor to the next position.
*
* @param string $sRequestedClassAlias The class alias to fetch (if there are several objects/classes per row)
*
* @return \DBObject The fetched object or null when at the end
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
/**
* Fetch the object (with the given class alias) at the current position in the set and move the cursor to the next position.
*
* @param string $sRequestedClassAlias The class alias to fetch (if there are several objects/classes per row)
* @return DBObject The fetched object or null when at the end
*/
public function Fetch($sRequestedClassAlias = '')
{
if (!$this->m_bLoaded) $this->Load();
@@ -930,15 +855,11 @@ class DBObjectSet implements iDBObjectSetIterator
return $oRetObj;
}
/**
* Fetch the whole row of objects (if several classes have been specified in the query) and move the cursor to the next position
*
* @return array An associative with the format 'classAlias' => $oObj representing the current row of the set. Returns null when at the end.
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
/**
* Fetch the whole row of objects (if several classes have been specified in the query) and move the cursor to the next position
*
* @return hash A hash with the format 'classAlias' => $oObj representing the current row of the set. Returns null when at the end.
*/
public function FetchAssoc()
{
if (!$this->m_bLoaded) $this->Load();
@@ -981,8 +902,6 @@ class DBObjectSet implements iDBObjectSetIterator
/**
* Position the cursor (for iterating in the set) to the first position (equivalent to Seek(0))
*
* @throws \Exception
*/
public function Rewind()
{
@@ -992,18 +911,11 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
/**
* Position the cursor (for iterating in the set) to the given position
*
* @param int $iRow
*
* @return int|mixed
*
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
/**
* Position the cursor (for iterating in the set) to the given position
*
* @param int $iRow
*/
public function Seek($iRow)
{
if (!$this->m_bLoaded) $this->Load();
@@ -1016,17 +928,15 @@ class DBObjectSet implements iDBObjectSetIterator
return $this->m_iCurrRow;
}
/**
* Add an object to the current set (in-memory only, nothing is written to the database)
*
* Limitation:
* Sets with several objects per row are NOT supported
*
* @param \DBObject $oObject The object to add
* @param string $sClassAlias The alias for the class of the object
*
* @throws \MySQLException
*/
/**
* Add an object to the current set (in-memory only, nothing is written to the database)
*
* Limitation:
* Sets with several objects per row are NOT supported
*
* @param DBObject $oObject The object to add
* @param string $sClassAlias The alias for the class of the object
*/
public function AddObject($oObject, $sClassAlias = '')
{
if (!$this->m_bLoaded) $this->Load();
@@ -1044,18 +954,16 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
/**
* Add a hash containig objects into the current set.
*
* The expected format for the hash is: $aObjectArray[$idx][$sClassAlias] => $oObject
* Limitation:
* The aliases MUST match the ones used in the current set
* Only the ID of the objects associated to the first alias (column) is remembered.. in case we have to rebuild a filter
*
* @param array $aObjectArray
*
* @throws \MySQLException
*/
/**
* Add a hash containig objects into the current set.
*
* The expected format for the hash is: $aObjectArray[$idx][$sClassAlias] => $oObject
* Limitation:
* The aliases MUST match the ones used in the current set
* Only the ID of the objects associated to the first alias (column) is remembered.. in case we have to rebuild a filter
*
* @param hash $aObjectArray
*/
protected function AddObjectExtended($aObjectArray)
{
if (!$this->m_bLoaded) $this->Load();
@@ -1075,17 +983,15 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
/**
* Add an array of objects into the current set
*
* Limitation:
* Sets with several classes per row are not supported (use AddObjectExtended instead)
*
* @param array $aObjects The array of objects to add
* @param string $sClassAlias The Alias of the class for the added objects
*
* @throws \MySQLException
*/
/**
* Add an array of objects into the current set
*
* Limitation:
* Sets with several classes per row are not supported (use AddObjectExtended instead)
*
* @param array $aObjects The array of objects to add
* @param string $sClassAlias The Alias of the class for the added objects
*/
public function AddObjectArray($aObjects, $sClassAlias = '')
{
if (!$this->m_bLoaded) $this->Load();
@@ -1103,9 +1009,8 @@ class DBObjectSet implements iDBObjectSetIterator
* Limitation:
* The added objects are not checked for duplicates (i.e. one cann add several times the same object, or add an object already present in the set).
*
* @param \DBObjectSet $oObjectSet The set to append
*
* @throws \CoreException
* @param DBObjectSet $oObjectSet The set to append
* @throws CoreException
*/
public function Append(DBObjectSet $oObjectSet)
{
@@ -1122,24 +1027,17 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
/**
* Create a set containing the objects present in both the current set and another specified set
*
* Limitations:
* Will NOT work if only a subset of the sets was loaded with SetLimit.
* Works only with sets made of objects loaded from the database since the comparison is based on the objects identifiers
*
* @param \DBObjectSet $oObjectSet The set to intersect with. The current position inside the set will be lost (= at the end)
*
* @return \DBObjectSet A new set of objects, containing the objects present in both sets (based on their identifier)
*
* @throws \Exception
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
/**
* Create a set containing the objects present in both the current set and another specified set
*
* Limitations:
* Will NOT work if only a subset of the sets was loaded with SetLimit.
* Works only with sets made of objects loaded from the database since the comparison is based on the objects identifiers
*
* @param DBObjectSet $oObjectSet The set to intersect with. The current position inside the set will be lost (= at the end)
* @throws CoreException
* @return DBObjectSet A new set of objects, containing the objects present in both sets (based on their identifier)
*/
public function CreateIntersect(DBObjectSet $oObjectSet)
{
if ($this->GetRootClass() != $oObjectSet->GetRootClass())
@@ -1171,19 +1069,16 @@ class DBObjectSet implements iDBObjectSetIterator
return $oNewSet;
}
/**
* Compare two sets of objects to determine if their content is identical or not.
*
* Limitation:
* Works only for sets of 1 column (i.e. one class of object selected)
*
* @param \DBObjectSet $oObjectSet
* @param array $aExcludeColumns The list of columns to exclude frop the comparison
*
* @return boolean True if the sets are identical, false otherwise
*
* @throws \CoreException
*/
/**
* Compare two sets of objects to determine if their content is identical or not.
*
* Limitation:
* Works only for sets of 1 column (i.e. one class of object selected)
*
* @param DBObjectSet $oObjectSet
* @param array $aExcludeColumns The list of columns to exclude frop the comparison
* @return boolean True if the sets are identical, false otherwise
*/
public function HasSameContents(DBObjectSet $oObjectSet, $aExcludeColumns = array())
{
$oComparator = new DBObjectSetComparator($this, $oObjectSet, $aExcludeColumns);
@@ -1197,12 +1092,10 @@ class DBObjectSet implements iDBObjectSetIterator
* The objects inside the set must be written in the database since the comparison is based on their identifiers
* Sets with several objects per row are NOT supported
*
* @param \DBObjectSet $oObjectSet
* @param DBObjectSet $oObjectSet
* @throws CoreException
*
* @return \DBObjectSet The "delta" set.
*
* @throws \Exception
* @throws \CoreException
* @return DBObjectSet The "delta" set.
*/
public function CreateDelta(DBObjectSet $oObjectSet)
{
@@ -1235,11 +1128,9 @@ class DBObjectSet implements iDBObjectSetIterator
return $oNewSet;
}
/**
* Will be deprecated soon - use MetaModel::GetRelatedObjectsDown/Up instead to take redundancy into account
*
* @throws \Exception
*/
/**
* Will be deprecated soon - use MetaModel::GetRelatedObjectsDown/Up instead to take redundancy into account
*/
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99)
{
$aRelatedObjs = array();
@@ -1263,21 +1154,16 @@ class DBObjectSet implements iDBObjectSetIterator
return $aRelatedObjs;
}
/**
* Compute the "RelatedObjects" (forward or "down" direction) for the set
* for the specified relation
*
* @param string $sRelCode The code of the relation to use for the computation
* @param int $iMaxDepth Maximum recursion depth
* @param bool $bEnableRedundancy
*
* @return \RelationGraph The graph of all the related objects
*
* @throws \Exception
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
/**
* Compute the "RelatedObjects" (forward or "down" direction) for the set
* for the specified relation
*
* @param string $sRelCode The code of the relation to use for the computation
* @param int $iMaxDepth Maximum recursion depth
* @param boolean $bEnableReduncancy Whether or not to take into account the redundancy
*
* @return RelationGraph The graph of all the related objects
*/
public function GetRelatedObjectsDown($sRelCode, $iMaxDepth = 99, $bEnableRedundancy = true)
{
$oGraph = new RelationGraph();
@@ -1289,22 +1175,17 @@ class DBObjectSet implements iDBObjectSetIterator
$oGraph->ComputeRelatedObjectsDown($sRelCode, $iMaxDepth, $bEnableRedundancy);
return $oGraph;
}
/**
* Compute the "RelatedObjects" (reverse or "up" direction) for the set
* for the specified relation
*
* @param string $sRelCode The code of the relation to use for the computation
* @param int $iMaxDepth Maximum recursion depth
* @param bool $bEnableRedundancy
*
* @return \RelationGraph The graph of all the related objects
*
* @throws \Exception
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
/**
* Compute the "RelatedObjects" (reverse or "up" direction) for the set
* for the specified relation
*
* @param string $sRelCode The code of the relation to use for the computation
* @param int $iMaxDepth Maximum recursion depth
* @param boolean $bEnableReduncancy Whether or not to take into account the redundancy
*
* @return RelationGraph The graph of all the related objects
*/
public function GetRelatedObjectsUp($sRelCode, $iMaxDepth = 99, $bEnableRedundancy = true)
{
$oGraph = new RelationGraph();
@@ -1316,21 +1197,14 @@ class DBObjectSet implements iDBObjectSetIterator
$oGraph->ComputeRelatedObjectsUp($sRelCode, $iMaxDepth, $bEnableRedundancy);
return $oGraph;
}
/**
* Builds an object that contains the values that are common to all the objects
* in the set. If for a given attribute, objects in the set have various values
* then the resulting object will contain null for this value.
*
* @param array $aValues Hash Output: the distribution of the values, in the set, for each attribute
*
* @return \DBObject The object with the common values
*
* @throws \Exception
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
/**
* Builds an object that contains the values that are common to all the objects
* in the set. If for a given attribute, objects in the set have various values
* then the resulting object will contain null for this value.
* @param $aValues Hash Output: the distribution of the values, in the set, for each attribute
* @return DBObject The object with the common values
*/
public function ComputeCommonObject(&$aValues)
{
$sClass = $this->GetClass();
@@ -1414,7 +1288,7 @@ class DBObjectSet implements iDBObjectSetIterator
/**
* List the constant fields (and their value) in the given query
* @return array [Alias][AttCode] => value
* @return Hash [Alias][AttCode] => value
*/
public function ListConstantFields()
{
@@ -1504,12 +1378,10 @@ class DBObjectSetComparator
$this->oSet1 = $oSet1;
$this->oSet2 = $oSet2;
}
/**
* Builds the lists of fingerprints and initializes internal structures, if it was not already done
*
* @throws \CoreException
*/
/**
* Builds the lists of fingerprints and initializes internal structures, if it was not already done
*/
protected function ComputeFingerprints()
{
if ($this->aFingerprints1 === null)
@@ -1554,13 +1426,11 @@ class DBObjectSetComparator
}
}
}
/**
* Tells if the sets are equivalent or not. Returns as soon as the first difference is found.
* @return boolean true if the set have an equivalent content, false otherwise
*
* @throws \CoreException
*/
/**
* Tells if the sets are equivalent or not. Returns as soon as the first difference is found.
* @return boolean true if the set have an equivalent content, false otherwise
*/
public function SetsAreEquivalent()
{
if (($this->oSet1 === null) && ($this->oSet2 === null))
@@ -1599,16 +1469,13 @@ class DBObjectSetComparator
return true;
}
/**
* Get the list of differences between the two sets. In ordeer to write back into the database only the minimum changes
* THE FIRST SET MUST BE THE ONE LOADED FROM THE DATABASE
* Returns a hash: 'added' => DBObject(s), 'removed' => DBObject(s), 'modified' => DBObjects(s)
* @return array
*
* @throws \Exception
* @throws \CoreException
*/
/**
* Get the list of differences between the two sets. In ordeer to write back into the database only the minimum changes
* THE FIRST SET MUST BE THE ONE LOADED FROM THE DATABASE
* Returns a hash: 'added' => DBObject(s), 'removed' => DBObject(s), 'modified' => DBObjects(s)
* @return Ambigous <int:DBObject: , unknown>
*/
public function GetDifferences()
{
$aResult = array('added' => array(), 'removed' => array(), 'modified' => array());
@@ -1657,19 +1524,13 @@ class DBObjectSetComparator
}
return $aResult;
}
/**
* Helpr to clone (in memory) an object and to apply to it the values taken from a second object
*
* @param \DBObject $oObjToClone
* @param \DBObject $oObjWithValues
*
* @return \DBObject The modified clone
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
*/
/**
* Helpr to clone (in memory) an object and to apply to it the values taken from a second object
* @param DBObject $oObjToClone
* @param DBObject $oObjWithValues
* @return DBObject The modified clone
*/
protected function CopyFrom($oObjToClone, $oObjWithValues)
{
$oObj = MetaModel::GetObject(get_class($oObjToClone), $oObjToClone->GetKey());

View File

@@ -235,96 +235,29 @@ abstract class DBSearch
abstract public function GetInternalParams();
abstract public function GetQueryParams($bExcludeMagicParams = true);
abstract public function ListConstantFields();
/**
* Turn the parameters (:xxx) into scalar values in order to easily
* serialize a search
*
* @param array $aArgs
*
* @return string
*/
abstract public function ApplyParameters($aArgs);
public function serialize($bDevelopParams = false, $aContextParams = array())
public function serialize($bDevelopParams = false, $aContextParams = null)
{
$aQueryParams = $this->GetQueryParams();
$aContextParams = array_merge($this->GetInternalParams(), $aContextParams);
foreach($aQueryParams as $sParam => $sValue)
{
if (isset($aContextParams[$sParam]))
{
$aQueryParams[$sParam] = $aContextParams[$sParam];
}
elseif (($iPos = strpos($sParam, '->')) !== false)
{
$sParamName = substr($sParam, 0, $iPos);
if (isset($aContextParams[$sParamName.'->object()']))
{
$sAttCode = substr($sParam, $iPos + 2);
/** @var \DBObject $oObj */
$oObj = $aContextParams[$sParamName.'->object()'];
if ($oObj->IsModified())
{
if ($sAttCode == 'id')
{
$aQueryParams[$sParam] = $oObj->GetKey();
}
else
{
$aQueryParams[$sParam] = $oObj->Get($sAttCode);
}
}
else
{
unset($aQueryParams[$sParam]);
// For database objects, serialize only class, key
$aQueryParams[$sParamName.'->id'] = $oObj->GetKey();
$aQueryParams[$sParamName.'->class'] = get_class($oObj);
}
}
}
}
$sOql = $this->ToOql($bDevelopParams, $aContextParams);
return json_encode(array($sOql, $aQueryParams, $this->m_aModifierProperties));
return rawurlencode(base64_encode(serialize(array($sOql, $this->GetInternalParams(), $this->m_aModifierProperties))));
}
/**
* @param string $sValue Serialized OQL query
*
* @return \DBSearch
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \OQLException
*/
static public function unserialize($sValue)
{
$aData = json_decode($sValue, true);
if (is_null($aData))
{
throw new CoreException("Invalid filter parameter");
}
$aData = unserialize(base64_decode(rawurldecode($sValue)));
$sOql = $aData[0];
$aParams = $aData[1];
$aExtraParams = array();
foreach($aParams as $sParam => $sValue)
{
if (($iPos = strpos($sParam, '->class')) !== false)
{
$sParamName = substr($sParam, 0, $iPos);
if (isset($aParams[$sParamName.'->id']))
{
$sClass = $aParams[$sParamName.'->class'];
$iKey = $aParams[$sParamName.'->id'];
$oObj = MetaModel::GetObject($sClass, $iKey);
$aExtraParams[$sParamName.'->object()'] = $oObj;
}
}
}
$aParams = array_merge($aExtraParams, $aParams);
// We've tried to use gzcompress/gzuncompress, but for some specific queries
// it was not working at all (See Trac #193)
// gzuncompress was issuing a warning "data error" and the return object was null
@@ -402,7 +335,6 @@ abstract class DBSearch
}
}
/** @var DBObjectSearch | null $oResultFilter */
if (!isset($oResultFilter))
{
$oKPI = new ExecutionKPI();
@@ -441,20 +373,11 @@ abstract class DBSearch
return $oResultFilter;
}
// Alternative to object mapping: the data are transfered directly into an array
// This is 10 times faster than creating a set of objects, and makes sense when optimization is required
/**
* Alternative to object mapping: the data are transfered directly into an array
* This is 10 times faster than creating a set of objects, and makes sense when optimization is required
*
* @param array $aColumns
* @param array $aOrderBy Array of '[<classalias>.]attcode' => bAscending
* @param array $aArgs
*
* @return array|void
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
*/
public function ToDataArray($aColumns = array(), $aOrderBy = array(), $aArgs = array())
{
$sSQL = $this->MakeSelectQuery($aOrderBy, $aArgs);

View File

@@ -116,22 +116,6 @@ class Dict
self::$m_iErrorMode = $iErrorMode;
}
/**
* Check if a dictionary entry exists or not
* @param $sStringCode
*
* @return bool
*/
public static function Exists($sStringCode)
{
$sImpossibleString = 'aVlHYKEI3TZuDV5o0pghv7fvhYNYuzYkTk7WL0Zoqw8rggE7aq';
if (static::S($sStringCode, $sImpossibleString) === $sImpossibleString)
{
return false;
}
return true;
}
/**
* Returns a localised string from the dictonary
*
@@ -213,7 +197,7 @@ class Dict
/**
* Initialize a the entries for a given language (replaces the former Add() method)
* @param string $sLanguageCode Code identifying the language i.e. 'FR-FR', 'EN-US'
* @param array $aEntries Hash array of dictionnary entries
* @param hash $aEntries Hash array of dictionnary entries
*/
public static function SetEntries($sLanguageCode, $aEntries)
{

View File

@@ -188,16 +188,11 @@ EOF
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else if ($value instanceOf ormDocument)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else if ($value instanceOf ormTagSet)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else if ($value instanceOf ormDocument)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);

View File

@@ -78,6 +78,7 @@ EOF;
}
EOF;
SetupUtils::builddir(dirname($sFilePath));
file_put_contents($sFilePath, $content);
}
}

View File

@@ -154,7 +154,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
/**
* @var array
* @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations
* @see https://www.itophub.io/wiki/page?id=2_5_0%3Aadmin%3Arich_text_limitations
*/
protected static $aTagsWhiteList = array(
'html' => array(),
@@ -211,7 +211,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
/**
* @var array
* @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations
* @see https://www.itophub.io/wiki/page?id=2_5_0%3Aadmin%3Arich_text_limitations
*/
protected static $aStylesWhiteList = array(
'background-color',
@@ -230,9 +230,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
'margin',
'padding',
'text-align',
'vertical-align',
'width',
'white-space',
);
public function __construct()

View File

@@ -166,7 +166,7 @@ class InlineImage extends DBObject
*/
public static function FinalizeInlineImages(DBObject $oObject)
{
$iTransactionId = utils::ReadParam('transaction_id', null, false, 'transaction_id');
$iTransactionId = utils::ReadParam('transaction_id', null);
if (!is_null($iTransactionId))
{
// Attach new (temporary) inline images
@@ -183,19 +183,6 @@ class InlineImage extends DBObject
$oInlineImage->DBUpdate();
}
}
// For tracing issues with Inline Images... but beware not all updates are interactive, so this trace happens when creating objects non-interactively (REST, Synchro...)
// else
// {
// IssueLog::Error('InlineImage: Error during FinalizeInlineImages(), no transaction ID for object '.get_class($oObject).'#'.$oObject->GetKey().'.');
//
// IssueLog::Error('|- Call stack:');
// $oException = new Exception();
// $sStackTrace = $oException->getTraceAsString();
// IssueLog::Error($sStackTrace);
//
// IssueLog::Error('|- POST vars:');
// IssueLog::Error(print_r($_POST, true));
// }
}
/**
@@ -312,12 +299,8 @@ EOF
/**
* Check if an the given mimeType is an image that can be processed by the system
*
* @param string $sMimeType
*
* @return boolean always false if php-gd not installed
* otherwise true if file is one of those type : image/gif, image/jpeg, image/png
* @uses php-gd extension
* @return boolean
*/
public static function IsImage($sMimeType)
{
@@ -463,11 +446,9 @@ EOF
* Get the fragment of javascript needed to complete the initialization of
* CKEditor when creating/modifying an object
*
* @param \DBObject $oObject The object being edited
* @param string $sTempId Generated through utils::GetUploadTempId($iTransactionId)
*
* @param DBObject $oObject The object being edited
* @param string $sTempId The concatenation of session_id().'_'.$iTransactionId.
* @return string The JS fragment to insert in "on document ready"
* @throws \Exception
*/
public static function EnableCKEditorImageUpload(DBObject $oObject, $sTempId)
{
@@ -560,67 +541,49 @@ class InlineImageGC implements iBackgroundProcess
{
public function GetPeriodicity()
{
return 1; // Runs every 8 hours
return 3600; // Runs every hour
}
/**
* @param int $iTimeLimit
*
* @return string
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DeleteException
* @throws \MySQLException
* @throws \OQLException
*/
public function Process($iTimeLimit)
{
$sDateLimit = date(AttributeDateTime::GetSQLFormat(), time()); // Every temporary InlineImage/Attachment expired will be deleted
$aResults = array();
$aClasses = array('InlineImage', 'Attachment');
foreach($aClasses as $sClass)
{
$iProcessed = 0;
if(class_exists($sClass))
{
$iProcessed = $this->DeleteExpiredDocuments($sClass, $iTimeLimit, $sDateLimit);
}
$aResults[] = "$iProcessed old temporary $sClass(s)";
}
return "Cleaned ".implode(' and ', $aResults).".";
}
/**
* @param string $sClass
* @param int $iTimeLimit
* @param string $sDateLimit
*
* @return int
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DeleteException
* @throws \MySQLException
* @throws \OQLException
*/
protected function DeleteExpiredDocuments($sClass, $iTimeLimit, $sDateLimit)
{
$iProcessed = 0;
$sOQL = "SELECT $sClass WHERE (item_id = 0) AND (expire < '$sDateLimit')";
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('expire' => true) /* order by*/, array(), null,
1 /* limit count */);
$oSet->OptimizeColumnLoad(array());
while ((time() < $iTimeLimit) && ($oResult = $oSet->Fetch()))
$sOQL = "SELECT InlineImage WHERE (item_id = 0) AND (expire < '$sDateLimit')";
while (time() < $iTimeLimit)
{
/** @var \ormDocument $oDocument */
$oDocument = $oResult->Get('contents');
IssueLog::Info($sClass.' GC: Removed temp. file '.$oDocument->GetFileName().' on "'.$oResult->Get('item_class').'" #'.$oResult->Get('item_id').' as it has expired.');
$oResult->DBDelete();
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('expire' => true) /* order by*/, array(), null, 1 /* limit count */);
$oSet->OptimizeColumnLoad(array());
$oResult = $oSet->Fetch();
if (is_null($oResult))
{
// Nothing to be done
break;
}
$iProcessed++;
$oResult->DBDelete();
}
return $iProcessed;
}
$iProcessed2 = 0;
if (class_exists('Attachment'))
{
$sOQL = "SELECT Attachment WHERE (item_id = 0) AND (expire < '$sDateLimit')";
while (time() < $iTimeLimit)
{
// Next one ?
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('expire' => true) /* order by*/, array(), null, 1 /* limit count */);
$oSet->OptimizeColumnLoad(array());
$oResult = $oSet->Fetch();
if (is_null($oResult))
{
// Nothing to be done
break;
}
$iProcessed2++;
$oResult->DBDelete();
}
}
return "Cleaned $iProcessed old temporary InlineImage(s) and $iProcessed2 old temporary Attachment(s).";
}
}

View File

@@ -116,14 +116,13 @@ class ExecutionKPI
foreach (self::$m_aExecData as $aOpStats)
{
$sOperation = $aOpStats['op'];
$sBegin = $sEnd = $sDuration = $sMemBegin = $sMemEnd = $sMemPeak = '?';
$sBegin = round($aOpStats['time_begin'], 3);
$sEnd = round($aOpStats['time_end'], 3);
$fDuration = $aOpStats['time_end'] - $aOpStats['time_begin'];
$sDuration = round($fDuration, 3);
$sMemBegin = 'n/a';
$sMemEnd = 'n/a';
$sMemPeak = 'n/a';
if (isset($aOpStats['mem_begin']))
{
$sMemBegin = self::MemStr($aOpStats['mem_begin']);
@@ -198,13 +197,12 @@ class ExecutionKPI
self::Report("</div>");
self::Report("<p><a href=\"#end-".md5($sExecId)."\">Next page stats</a></p>");
// Report operation details
foreach (self::$m_aStats as $sOperation => $aOpStats)
{
$sOperationHtml = '<a name="'.md5($sExecId.$sOperation).'">'.$sOperation.'</a>';
self::Report("<h4>$sOperationHtml</h4>");
self::Report("<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>");
self::Report("<table border=\"1\" style=\"$sTableStyle\">");
self::Report("<thead>");
self::Report(" <th>Operation details (+ blame caller if log_kpi_duration = 2)</th><th>Count</th><th>Duration</th><th>Min</th><th>Max</th>");
@@ -253,9 +251,7 @@ class ExecutionKPI
self::Report("</tr>");
}
self::Report("</table>");
self::Report("<p><a href=\"#".md5($sExecId)."\">Back to page stats</a></p>");
}
self::Report('<a name="end-'.md5($sExecId).'">&nbsp;</a>');
}

View File

@@ -144,7 +144,7 @@ abstract class MetaModel
// $aBacktrace[1] is the info we want
if (!empty($sExpectedFunctionName))
{
assert($aBacktrace[2]['function'] == $sExpectedFunctionName);
assert('$aBacktrace[2]["function"] == $sExpectedFunctionName');
}
if ($bRecordSourceFile)
{
@@ -320,7 +320,8 @@ abstract class MetaModel
final static public function GetName($sClass)
{
self::_check_subclass($sClass);
return $sClass::GetClassName($sClass);
$sStringCode = 'Class:'.$sClass;
return Dict::S($sStringCode, str_replace('_', ' ', $sClass));
}
/**
@@ -410,7 +411,8 @@ abstract class MetaModel
final static public function GetClassDescription($sClass)
{
self::_check_subclass($sClass);
return $sClass::GetClassDescription($sClass);
$sStringCode = 'Class:'.$sClass.'+';
return Dict::S($sStringCode, '');
}
/**
@@ -526,104 +528,6 @@ abstract class MetaModel
return $oRet;
}
/**
* @param string $sClass
*
* @return array
* @throws \CoreException
*
* @since 2.6 N°659 uniqueness constraint
*/
final public static function GetUniquenessRules($sClass)
{
if (!isset(self::$m_aClassParams[$sClass]))
{
return array();
}
$aCurrentUniquenessRules = array();
if (array_key_exists('uniqueness_rules', self::$m_aClassParams[$sClass]))
{
$aCurrentUniquenessRules = self::$m_aClassParams[$sClass]['uniqueness_rules'];
}
$sParentClass = self::GetParentClass($sClass);
if ($sParentClass)
{
$aParentUniquenessRules = self::GetUniquenessRules($sParentClass);
foreach ($aParentUniquenessRules as $sUniquenessRuleId => $aParentUniquenessRuleProperties)
{
$bCopyDisabledKey = true;
$bCurrentDisabledValue = null;
if (array_key_exists($sUniquenessRuleId, $aCurrentUniquenessRules))
{
if (self::IsUniquenessRuleContainingOnlyDisabledKey($aCurrentUniquenessRules[$sUniquenessRuleId]))
{
$bCopyDisabledKey = false;
}
else
{
continue;
}
}
$aMergedUniquenessProperties = $aParentUniquenessRuleProperties;
if (!$bCopyDisabledKey)
{
$aMergedUniquenessProperties['disabled'] = $aCurrentUniquenessRules[$sUniquenessRuleId]['disabled'];
}
$aCurrentUniquenessRules[$sUniquenessRuleId] = $aMergedUniquenessProperties;
}
}
return $aCurrentUniquenessRules;
}
/**
* @param string $sRuleId
* @param string $sLeafClassName
*
* @return string name of the class, null if not present
*/
final public static function GetRootClassForUniquenessRule($sRuleId, $sLeafClassName)
{
$sFirstClassWithRuleId = null;
if (isset(self::$m_aClassParams[$sLeafClassName]['uniqueness_rules'][$sRuleId]))
{
$sFirstClassWithRuleId = $sLeafClassName;
}
$sParentClass = self::GetParentClass($sLeafClassName);
if ($sParentClass)
{
$sParentClassWithRuleId = self::GetRootClassForUniquenessRule($sRuleId, $sParentClass);
if (!is_null($sParentClassWithRuleId))
{
$sFirstClassWithRuleId = $sParentClassWithRuleId;
}
}
return $sFirstClassWithRuleId;
}
/**
* @param array $aRuleProperties
*
* @return bool
* @since 2.6 N°659 uniqueness constraint
*/
private static function IsUniquenessRuleContainingOnlyDisabledKey($aRuleProperties)
{
$aNonNullRuleProperties = array_filter($aRuleProperties, function ($v) {
return (!is_null($v));
});
return ((count($aNonNullRuleProperties) == 1) && (array_key_exists('disabled', $aNonNullRuleProperties)));
}
/**
* @param string $sClass
*
@@ -1120,7 +1024,7 @@ abstract class MetaModel
/**
* array of ("classname" => array of attributes)
*
* @var \AttributeDefinition[]
* @var array
*/
private static $m_aAttribDefs = array();
/**
@@ -2695,7 +2599,7 @@ abstract class MetaModel
// Build the list of available extensions
//
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider');
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension');
foreach($aInterfaces as $sInterface)
{
self::$m_aExtensionClasses[$sInterface] = array();
@@ -2778,25 +2682,6 @@ abstract class MetaModel
$oClassInit->OnAfterClassInitialization($sPHPClass);
}
}
$aCurrentClassUniquenessRules = MetaModel::GetUniquenessRules($sPHPClass);
if (!empty($aCurrentClassUniquenessRules))
{
$aClassFields = self::GetAttributesList($sPHPClass);
foreach ($aCurrentClassUniquenessRules as $sUniquenessRuleId => $aUniquenessRuleProperties)
{
$bHasSameRuleInParent = self::HasSameUniquenessRuleInParent($sPHPClass, $sUniquenessRuleId);
try
{
self::CheckUniquenessRuleValidity($aUniquenessRuleProperties, $bHasSameRuleInParent, $aClassFields);
}
catch (CoreUnexpectedValue $e)
{
throw new Exception("Invalid uniqueness rule declaration : class={$sPHPClass}, rule=$sUniquenessRuleId, reason={$e->getMessage()}");
}
}
}
}
catch (ReflectionException $e)
{
@@ -3065,101 +2950,6 @@ abstract class MetaModel
}
}
/**
* @param string $sClassName
* @param string $sUniquenessRuleId
*
* @return bool true if one of the parent class (recursive) has the same rule defined
* @throws \CoreException
*/
private static function HasSameUniquenessRuleInParent($sClassName, $sUniquenessRuleId)
{
$sParentClass = self::GetParentClass($sClassName);
if (empty($sParentClass))
{
return false;
}
$aParentClassUniquenessRules = self::GetUniquenessRules($sParentClass);
if (array_key_exists($sUniquenessRuleId, $aParentClassUniquenessRules))
{
return true;
}
return self::HasSameUniquenessRuleInParent($sParentClass, $sUniquenessRuleId);
}
/**
* @param array $aUniquenessRuleProperties
* @param bool $bRuleOverride if false then control an original declaration validity,
* otherwise an override validity (can have only the disabled key)
* @param string[] $aExistingClassFields if non empty, will check that all fields declared in the rules exists in the class
*
* @throws \CoreUnexpectedValue if the rule is invalid
*
* @since 2.6 N°659 uniqueness constraint
*/
public static function CheckUniquenessRuleValidity($aUniquenessRuleProperties, $bRuleOverride = true, $aExistingClassFields = array())
{
$MANDATORY_ATTRIBUTES = array('attributes');
$UNIQUENESS_MANDATORY_KEYS_NB = count($MANDATORY_ATTRIBUTES);
$bHasDisabledKey = false;
$bHasMissingMandatoryKey = true;
$iMissingMandatoryKeysNb = $UNIQUENESS_MANDATORY_KEYS_NB;
$bHasAllMandatoryKeysMissing = false;
$bHasNonDisabledKeys = false;
foreach ($aUniquenessRuleProperties as $sUniquenessRuleKey => $aUniquenessRuleProperty)
{
if (($sUniquenessRuleKey === 'disabled') && (!is_null($aUniquenessRuleProperty)))
{
$bHasDisabledKey = true;
continue;
}
$bHasNonDisabledKeys = true;
if (in_array($sUniquenessRuleKey, $MANDATORY_ATTRIBUTES, true)) {
$bHasMissingMandatoryKey = false;
$iMissingMandatoryKeysNb--;
}
if (($sUniquenessRuleKey === 'attributes') && (!empty($aExistingClassFields)))
{
foreach ($aUniquenessRuleProperties[$sUniquenessRuleKey] as $sRuleAttribute)
{
if (!in_array($sRuleAttribute, $aExistingClassFields, true))
{
throw new CoreUnexpectedValue("Uniqueness rule : non existing field '$sRuleAttribute'");
}
}
}
}
if ($iMissingMandatoryKeysNb == $UNIQUENESS_MANDATORY_KEYS_NB)
{
$bHasAllMandatoryKeysMissing = true;
}
if ($bHasDisabledKey)
{
if ($bRuleOverride && $bHasAllMandatoryKeysMissing && !$bHasNonDisabledKeys)
{
return;
}
if ($bHasMissingMandatoryKey)
{
throw new CoreUnexpectedValue('Uniqueness rule : missing mandatory properties');
}
return;
}
if ($bHasMissingMandatoryKey)
{
throw new CoreUnexpectedValue('Uniqueness rule : missing mandatory properties');
}
}
/**
* To be overriden, must be called for any object class (optimization)
*/
@@ -4715,7 +4505,7 @@ abstract class MetaModel
}
}
// Check SQL columns uniqueness
// Check unicity of the SQL columns
//
if (self::HasTable($sClass))
{
@@ -5181,7 +4971,6 @@ abstract class MetaModel
$aCreateTableItems = array(); // array of <table> => array of <create definition>
$aAlterTableMetaData = array();
$aAlterTableItems = array(); // array of <table> => <alter specification>
$aPostTableAlteration = array(); // array of <table> => post alteration queries
foreach(self::GetClasses() as $sClass)
{
@@ -5276,7 +5065,6 @@ abstract class MetaModel
$aTableInfo['Fields'][$sField]['used'] = true;
$bIndexNeeded = $oAttDef->RequiresIndex();
$bFullTextIndexNeeded = false;
if (!$bIndexNeeded)
{
// Add an index on the columns of the friendlyname
@@ -5285,13 +5073,6 @@ abstract class MetaModel
$bIndexNeeded = true;
}
}
else
{
if ($oAttDef->RequiresFullTextIndex())
{
$bFullTextIndexNeeded = true;
}
}
$sFieldDefinition = "`$sField` $sDBFieldSpec";
if (!CMDBSource::IsField($sTable, $sField))
@@ -5311,37 +5092,21 @@ abstract class MetaModel
if ($bIndexNeeded)
{
$aTableInfo['Indexes'][$sField]['used'] = true;
$sIndexName = $sField;
$aColumns = array($sField);
$aLength = self::DBGetIndexesLength($sClass, $aColumns, $aTableInfo);
$sColumns = '`'.$sField.'`';
if ($bFullTextIndexNeeded)
if (!is_null($aLength[0]))
{
$sIndexType = 'FULLTEXT INDEX';
$sColumns .= ' ('.$aLength[0].')';
}
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` ADD INDEX `$sField` ($sColumns)";
if ($bTableToCreate)
{
$aCreateTableItems[$sTable][] = "INDEX `$sField` ($sColumns)";
}
else
{
$sIndexType = 'INDEX';
$aColumns = array($sField);
$aLength = self::DBGetIndexesLength($sClass, $aColumns, $aTableInfo);
if (!is_null($aLength[0]))
{
$sColumns .= ' ('.$aLength[0].')';
}
}
$sSugFix = "ALTER TABLE `$sTable` ADD $sIndexType `$sIndexName` ($sColumns)";
$aSugFix[$sClass][$sAttCode][] = $sSugFix;
if ($bFullTextIndexNeeded)
{
// MySQL does not support multi fulltext index creation in a single query (mysql_errno = 1795)
$aPostTableAlteration[$sTable][] = $sSugFix;
}
elseif ($bTableToCreate)
{
$aCreateTableItems[$sTable][] = "$sIndexType `$sIndexName` ($sColumns)";
}
else
{
$aAlterTableItems[$sTable][] = "ADD $sIndexType `$sIndexName` ($sColumns)";
$aAlterTableItems[$sTable][] = "ADD INDEX `$sField` ($sColumns)";
}
}
@@ -5354,24 +5119,12 @@ abstract class MetaModel
$sAlterTableItemsAfterChange = '';
if ($bIndexNeeded)
{
$aColumns = array($sField);
$aLength = self::DBGetIndexesLength($sClass, $aColumns, $aTableInfo);
$aTableInfo['Indexes'][$sField]['used'] = true;
if ($bFullTextIndexNeeded)
{
$sIndexType = 'FULLTEXT INDEX';
$aColumns = null;
$aLength = null;
}
else
{
$sIndexType = 'INDEX';
$aColumns = array($sField);
$aLength = self::DBGetIndexesLength($sClass, $aColumns, $aTableInfo);
}
if (!CMDBSource::HasIndex($sTable, $sField, $aColumns, $aLength))
{
$sIndexName = $sField;
$sColumns = '`'.$sField.'`';
if (!is_null($aLength[0]))
{
@@ -5381,11 +5134,16 @@ abstract class MetaModel
$aErrors[$sClass][$sAttCode][] = "Foreign key '$sField' in table '$sTable' should have an index";
if (CMDBSource::HasIndex($sTable, $sField))
{
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` DROP INDEX `$sIndexName`";
$aAlterTableItems[$sTable][] = "DROP INDEX `$sIndexName`";
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` DROP INDEX `$sField`";
$sSugFixAfterChange = "ALTER TABLE `$sTable` ADD INDEX `$sField` ($sColumns)";
$aAlterTableItems[$sTable][] = "DROP INDEX `$sField`";
$sAlterTableItemsAfterChange = "ADD INDEX `$sField` ($sColumns)";
}
else
{
$sSugFixAfterChange = "ALTER TABLE `$sTable` ADD INDEX `$sField` ($sColumns)";
$sAlterTableItemsAfterChange = "ADD INDEX `$sField` ($sColumns)";
}
$sSugFixAfterChange = "ALTER TABLE `$sTable` ADD $sIndexType `$sIndexName` ($sColumns)";
$sAlterTableItemsAfterChange = "ADD $sIndexType `$sIndexName` ($sColumns)";
}
}
@@ -5409,15 +5167,7 @@ abstract class MetaModel
if (!empty($sSugFixAfterChange))
{
$aSugFix[$sClass][$sAttCode][] = $sSugFixAfterChange;
if ($bFullTextIndexNeeded)
{
// MySQL does not support multi fulltext index creation in a single query (mysql_errno = 1795)
$aPostTableAlteration[$sTable][] = $sSugFixAfterChange;
}
else
{
$aAlterTableItems[$sTable][] = $sAlterTableItemsAfterChange;
}
$aAlterTableItems[$sTable][] = $sAlterTableItemsAfterChange;
}
}
}
@@ -5541,10 +5291,6 @@ abstract class MetaModel
$sChangeList = implode(', ', $aChangeList);
$aCondensedQueries[] = "ALTER TABLE `$sTable` $sChangeList";
}
foreach($aPostTableAlteration as $sTable => $aChangeList)
{
$aCondensedQueries = array_merge($aCondensedQueries, $aChangeList);
}
return array($aErrors, $aSugFix, $aCondensedQueries);
}
@@ -6112,10 +5858,20 @@ abstract class MetaModel
CMDBSource::SelectDB(self::$m_sDBName);
foreach(MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass)
{
$oPHPClass::OnMetaModelStarted();
}
foreach(get_declared_classes() as $sPHPClass)
{
if (is_subclass_of($sPHPClass, 'ModuleHandlerAPI'))
{
$aCallSpec = array($sPHPClass, 'OnMetaModelStarted');
call_user_func_array($aCallSpec, array());
}
}
// if (false)
// {
// echo "Debug<br/>\n";
// self::static_var_dump();
// }
ExpressionCache::Warmup();
}
@@ -6570,7 +6326,7 @@ abstract class MetaModel
*
* @param string $sClass
* @param int $iKey id value of the object to retrieve
* @param bool $bMustBeFound see throws ArchivedObjectException
* @param bool $bMustBeFound
* @param bool $bAllowAllData if true then no rights filtering
* @param null $aModifierProperties
*
@@ -6637,14 +6393,12 @@ abstract class MetaModel
}
catch(Exception $e)
{
// In the finally block we will pop the pushed archived mode
// otherwise the application stays in ArchiveMode true which has caused hazardious behavior!
// We need to pop the pushed archived mode before the exception is thrown, otherwise the application stays in ArchiveMode true which has caused hazardious behavior!
// Note: When switching to PHP 5.6, we can use a finally block instead of duplicating this line.
utils::PopArchiveMode();
throw $e;
}
finally
{
utils::PopArchiveMode();
}
utils::PopArchiveMode();
if (empty($aRow))
{

View File

@@ -56,11 +56,6 @@ abstract class ModelReflection
abstract public function GetFiltersList($sClass);
abstract public function IsValidFilterCode($sClass, $sFilterCode);
/**
* @param string $sOQL
*
* @return \DBObjectSearch
*/
abstract public function GetQuery($sOQL);
abstract public function DictString($sStringCode, $sDefault = null, $bUserLanguageOnly = false);
@@ -80,13 +75,6 @@ abstract class ModelReflection
return vsprintf($sLocalizedFormat, $aArguments);
}
/**
* @param $sCode
* @param string $sLabel
* @param string $defaultValue
*
* @return \RunTimeIconSelectionField
*/
abstract public function GetIconSelectionField($sCode, $sLabel = '', $defaultValue = '');
abstract public function GetRootClass($sClass);

View File

@@ -25,7 +25,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class ModuleHandlerAPI implements ModuleHandlerApiInterface
abstract class ModuleHandlerAPI
{
public static function OnMetaModelStarted()
{
@@ -34,19 +34,5 @@ abstract class ModuleHandlerAPI implements ModuleHandlerApiInterface
public static function OnMenuCreation()
{
}
public function __construct()
{
}
}
interface ModuleHandlerApiInterface
{
public static function OnMetaModelStarted();
public static function OnMenuCreation();
public function __construct(); //empty params is required in order to be instantiable by MetaModel::InitClasses()
}
?>

View File

@@ -45,7 +45,7 @@ class iTopMutex
static protected $aAcquiredLocks = array(); // Number of instances of the Mutex, having the lock, in this page
public function __construct(
$sName, $sDBHost = null, $sDBUser = null, $sDBPwd = null, $bDBTlsEnabled = false, $sDBTlsCA = null
$sName, $sDBHost = null, $sDBUser = null, $sDBPwd = null, $bDBTlsEnabled = null, $sDBTlsCA = null
)
{
// Compute the name of a lock for mysql

View File

@@ -42,7 +42,7 @@
* @copyright 2006 Gregory Beaver
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
*/
//require_once 'PEAR/Exception.php';
require_once 'PEAR/Exception.php';
/**
* @package PHP_LexerGenerator
* @author Gregory Beaver <cellog@php.net>
@@ -51,5 +51,5 @@
* @version @package_version@
* @since File available since Release 0.1.0
*/
class PHP_LexerGenerator_Exception extends Exception {}
class PHP_LexerGenerator_Exception extends PEAR_Exception {}
?>

View File

@@ -22,9 +22,6 @@ class MissingQueryArgument extends CoreException
}
/**
* @method Check($oModelReflection, array $aAliases, $sSourceQuery)
*/
abstract class Expression
{
/**
@@ -50,30 +47,13 @@ abstract class Expression
/**
* recursive rendering
*
* @deprecated use RenderExpression
*
* @param array $aArgs used as input by default, or used as output if bRetrofitParams set to True
* @param bool $bRetrofitParams
*
* @return array|string
* @throws \MissingQueryArgument
*/
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
return $this->RenderExpression(false, $aArgs, $bRetrofitParams);
}
/**
* recursive rendering
*
* @param bool $bForSQL generates code for OQL if false, for SQL otherwise
* @param array $aArgs used as input by default, or used as output if bRetrofitParams set to True
* @param bool $bRetrofitParams
*
* @return array|string
* @throws \MissingQueryArgument
*/
abstract public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false);
abstract public function Render(&$aArgs = null, $bRetrofitParams = false);
/**
* @param DBObjectSearch $oSearch
@@ -86,7 +66,7 @@ abstract class Expression
*/
public function Display($oSearch, &$aArgs = null, $oAttDef = null, &$aCtx = array())
{
return $this->RenderExpression(false, $aArgs);
return $this->Render($aArgs);
}
public function GetAttDef($aClasses = array())
@@ -124,7 +104,7 @@ abstract class Expression
public function serialize()
{
return base64_encode($this->RenderExpression(false));
return base64_encode($this->Render());
}
/**
@@ -192,7 +172,7 @@ abstract class Expression
* @param string sValue The value returned by the query, for this expression
* @param string sDefault The default value if no relevant label could be computed
*
* @return string label
* @return The label
*/
public function MakeValueLabel($oFilter, $sValue, $sDefault)
{
@@ -203,7 +183,7 @@ abstract class Expression
{
return array(
'widget' => AttributeDefinition::SEARCH_WIDGET_TYPE_RAW,
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
'oql' => $this->Render($aArgs, $bRetrofitParams),
'label' => $this->Display($oSearch, $aArgs, $oAttDef),
'source' => get_class($this),
);
@@ -249,7 +229,7 @@ class SQLExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSql = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
return $this->m_sSQL;
}
@@ -305,30 +285,7 @@ class BinaryExpression extends Expression
protected $m_oRightExpr;
protected $m_sOperator;
/**
* @param \Expression $oLeftExpr
* @param string $sOperator
* @param \Expression $oRightExpr
*
* @throws \CoreException
*/
public function __construct($oLeftExpr, $sOperator, $oRightExpr)
{
$this->ValidateConstructorParams($oLeftExpr, $sOperator, $oRightExpr);
$this->m_oLeftExpr = $oLeftExpr;
$this->m_oRightExpr = $oRightExpr;
$this->m_sOperator = $sOperator;
}
/**
* @param $oLeftExpr
* @param $sOperator
* @param $oRightExpr
*
* @throws \CoreException if one of the parameter is invalid
*/
protected function ValidateConstructorParams($oLeftExpr, $sOperator, $oRightExpr)
{
if (!is_object($oLeftExpr))
{
@@ -346,11 +303,13 @@ class BinaryExpression extends Expression
{
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))
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)));
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_oRightExpr = $oRightExpr;
$this->m_sOperator = $sOperator;
}
public function IsTrue()
@@ -382,11 +341,12 @@ class BinaryExpression extends Expression
return $this->m_sOperator;
}
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
// recursive rendering
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$sOperator = $this->GetOperator();
$sLeft = $this->GetLeftExpr()->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sRight = $this->GetRightExpr()->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sLeft = $this->GetLeftExpr()->Render($aArgs, $bRetrofitParams);
$sRight = $this->GetRightExpr()->Render($aArgs, $bRetrofitParams);
return "($sLeft $sOperator $sRight)";
}
@@ -578,7 +538,6 @@ class BinaryExpression extends Expression
* @param null $oAttDef
*
* @return array
* @throws \MissingQueryArgument
*/
public function GetCriterion($oSearch, &$aArgs = null, $bRetrofitParams = false, $oAttDef = null)
{
@@ -646,7 +605,7 @@ class BinaryExpression extends Expression
$aCriteria = self::MergeCriteria($aCriteriaLeft, $aCriteriaRight, $this->GetOperator());
}
$aCriteria['oql'] = $this->RenderExpression(false, $aArgs, $bRetrofitParams);
$aCriteria['oql'] = $this->Render($aArgs, $bRetrofitParams);
$aCriteria['label'] = $this->Display($oSearch, $aArgs, $oAttDef);
if (isset($aCriteriaLeft['ref']) && isset($aCriteriaRight['ref']) && ($aCriteriaLeft['ref'] != $aCriteriaRight['ref']))
@@ -677,10 +636,6 @@ class BinaryExpression extends Expression
}
}
}
if (isset($aCriteriaLeft['widget']) && isset($aCriteriaRight['widget']) && ($aCriteriaLeft['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_TAG_SET) && ($aCriteriaRight['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_TAG_SET))
{
$aCriteriaOverride['operator'] = 'MATCHES';
}
}
return array_merge($aCriteriaLeft, $aCriteriaRight, $aCriteriaOverride);
@@ -688,58 +643,6 @@ class BinaryExpression extends Expression
}
/**
* @since 2.6 N°931 tag fields
*/
class MatchExpression extends BinaryExpression
{
/** @var \FieldExpression */
protected $m_oLeftExpr;
/** @var \ScalarExpression */
protected $m_oRightExpr;
/**
* MatchExpression constructor.
*
* @param \FieldExpression $oLeftExpr
* @param \ScalarExpression $oRightExpr
*
* @throws \CoreException
*/
public function __construct(FieldExpression $oLeftExpr, ScalarExpression $oRightExpr)
{
parent::__construct($oLeftExpr, 'MATCHES', $oRightExpr);
}
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
{
$sLeft = $this->GetLeftExpr()->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sRight = $this->GetRightExpr()->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
if ($bForSQL)
{
$sRet = "MATCH ($sLeft) AGAINST ($sRight IN BOOLEAN MODE)";
}
else
{
$sRet = "$sLeft MATCHES $sRight";
}
return $sRet;
}
public function Translate($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true)
{
/** @var \FieldExpression $oLeft */
$oLeft = $this->GetLeftExpr()->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
/** @var \ScalarExpression $oRight */
$oRight = $this->GetRightExpr()->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
return new static($oLeft, $oRight);
}
}
class UnaryExpression extends Expression
{
protected $m_value;
@@ -761,7 +664,7 @@ class UnaryExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
return CMDBSource::Quote($this->m_value);
}
@@ -869,11 +772,11 @@ class ScalarExpression extends UnaryExpression
return $aCtx['date_display']->MakeValueLabel($oSearch, $this->m_value, $this->m_value);
}
return $this->RenderExpression(false, $aArgs);
return $this->Render($aArgs);
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
if (is_null($this->m_value))
{
@@ -893,23 +796,23 @@ class ScalarExpression extends UnaryExpression
public function GetCriterion($oSearch, &$aArgs = null, $bRetrofitParams = false, $oAttDef = null)
{
$aCriterion = array();
$aCriteria = array();
switch ((string)($this->m_value))
{
case '%Y-%m-%d':
$aCriterion['unit'] = 'DAY';
$aCriteria['unit'] = 'DAY';
break;
case '%Y-%m':
$aCriterion['unit'] = 'MONTH';
$aCriteria['unit'] = 'MONTH';
break;
case '%w':
$aCriterion['unit'] = 'WEEKDAY';
$aCriteria['unit'] = 'WEEKDAY';
break;
case '%H':
$aCriterion['unit'] = 'HOUR';
$aCriteria['unit'] = 'HOUR';
break;
default:
$aValue = array();
$aValue = array('value' => $this->GetValue());
if (!is_null($oAttDef))
{
switch (true)
@@ -919,7 +822,7 @@ class ScalarExpression extends UnaryExpression
{
$oFinalAttDef = $oAttDef->GetFinalAttDef();
if($oFinalAttDef instanceof AttributeExternalKey)
{
{
if ($this->GetValue() !== 0)
{
/** @var AttributeExternalKey $oFinalAttDef */
@@ -946,79 +849,42 @@ class ScalarExpression extends UnaryExpression
IssueLog::Error($e->getMessage());
}
break;
case ($oAttDef instanceof AttributeTagSet):
try
{
if (!empty($this->GetValue()))
{
$aValues = array();
$oValue = $this->GetValue();
if (is_string($oValue))
{
$oValue = $oAttDef->GetExistingTagsFromString($oValue, true);
}
/** @var \ormTagSet $oValue */
$aTags = $oValue->GetTags();
foreach($aTags as $oTag)
{
$aValue['label'] = $oTag->Get('label');
$aValue['value'] = $oTag->Get('code');
$aValues[] = $aValue;
}
$aCriterion['values'] = $aValues;
}
else
{
$aCriterion['has_undefined'] = true;
}
} catch (Exception $e)
{
IssueLog::Error($e->getMessage());
}
break;
case $oAttDef->IsExternalKey():
try
{
if ($this->GetValue() != 0)
if ($this->GetValue() == 0)
{
$aValue['label'] = Dict::S('UI:UndefinedObject');
}
else
{
/** @var AttributeExternalKey $oAttDef */
$sTarget = $oAttDef->GetTargetClass();
$oObj = MetaModel::GetObject($sTarget, $this->GetValue(), true, true);
$aValue['label'] = $oObj->Get("friendlyname");
$aValue['value'] = $this->GetValue();
$aCriterion['values'] = array($aValue);
}
else
{
$aValue['label'] = Dict::S('Enum:Undefined');
$aValue['value'] = $this->GetValue();
$aCriterion['values'] = array($aValue);
}
} catch (Exception $e)
}
catch (Exception $e)
{
// This object cannot be seen... ignore
IssueLog::Error($e->getMessage());
}
break;
default:
try
{
$aValue['label'] = $oAttDef->GetAsPlainText($this->GetValue());
$aValue['value'] = $this->GetValue();
$aCriterion['values'] = array($aValue);
} catch (Exception $e)
{
$aValue['label'] = $this->GetValue();
$aValue['value'] = $this->GetValue();
$aCriterion['values'] = array($aValue);
}
break;
}
}
$aCriteria['values'] = array($aValue);
break;
}
$aCriterion['oql'] = $this->RenderExpression(false, $aArgs, $bRetrofitParams);
return $aCriterion;
$aCriteria['oql'] = $this->Render($aArgs, $bRetrofitParams);
return $aCriteria;
}
}
@@ -1125,7 +991,7 @@ class FieldExpression extends UnaryExpression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
if (empty($this->m_sParent))
{
@@ -1231,7 +1097,7 @@ class FieldExpression extends UnaryExpression
* @param string sValue The value returned by the query, for this expression
* @param string sDefault The default value if no relevant label could be computed
*
* @return string label
* @return The label
* @throws \CoreException
*/
public function MakeValueLabel($oFilter, $sValue, $sDefault)
@@ -1471,18 +1337,19 @@ class VariableExpression extends UnaryExpression
return $oAttDef->GetAsPlainText($sValue);
}
return $this->RenderExpression(false, $aArgs);
return $this->Render($aArgs);
}
// recursive rendering
/**
* @param bool $bForSQL
* @param array $aArgs
* @param null $aArgs
* @param bool $bRetrofitParams
*
* @return array|string
* @throws \MissingQueryArgument
*/
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
if (is_null($aArgs))
{
@@ -1600,12 +1467,12 @@ class ListExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aRes[] = $oExpr->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$aRes[] = $oExpr->Render($aArgs, $bRetrofitParams);
}
return '('.implode(', ', $aRes).')';
}
@@ -1621,11 +1488,12 @@ class ListExpression extends Expression
public function ApplyParameters($aArgs)
{
$aRes = array();
foreach ($this->m_aExpressions as $idx => $oExpr)
{
if ($oExpr instanceof VariableExpression)
{
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar($aArgs);
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar();
}
else
{
@@ -1682,6 +1550,7 @@ class ListExpression extends Expression
public function RenameParam($sOldName, $sNewName)
{
$aRes = array();
foreach ($this->m_aExpressions as $key => $oExpr)
{
$this->m_aExpressions[$key] = $oExpr->RenameParam($sOldName, $sNewName);
@@ -1690,6 +1559,7 @@ class ListExpression extends Expression
public function RenameAlias($sOldName, $sNewName)
{
$aRes = array();
foreach ($this->m_aExpressions as $key => $oExpr)
{
$oExpr->RenameAlias($sOldName, $sNewName);
@@ -1753,12 +1623,12 @@ class FunctionExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$aRes = array();
foreach ($this->m_aArgs as $iPos => $oExpr)
{
$aRes[] = $oExpr->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$aRes[] = $oExpr->Render($aArgs, $bRetrofitParams);
}
return $this->m_sVerb.'('.implode(', ', $aRes).')';
}
@@ -1774,6 +1644,7 @@ class FunctionExpression extends Expression
public function ApplyParameters($aArgs)
{
$aRes = array();
foreach ($this->m_aArgs as $idx => $oExpr)
{
if ($oExpr instanceof VariableExpression)
@@ -1867,7 +1738,7 @@ class FunctionExpression extends Expression
* @param string sValue The value returned by the query, for this expression
* @param string sDefault The default value if no relevant label could be computed
*
* @return string label
* @return The label
*/
public function MakeValueLabel($oFilter, $sValue, $sDefault)
{
@@ -1943,7 +1814,6 @@ class FunctionExpression extends Expression
$sVerb = '';
switch ($this->m_sVerb)
{
case 'ISNULL':
case 'NOW':
$sVerb = $this->VerbToNaturalLanguage();
break;
@@ -1957,7 +1827,7 @@ class FunctionExpression extends Expression
$aCtx['date_display'] = $this;
break;
default:
return $this->RenderExpression(false, $aArgs);
return $this->Render($aArgs);
}
foreach($this->m_aArgs as $oExpression)
@@ -1974,7 +1844,7 @@ class FunctionExpression extends Expression
{
$sOperation .= $sVerb;
}
return '('.$sOperation.')';
return $sOperation;
}
private function VerbToNaturalLanguage()
@@ -1994,7 +1864,7 @@ class FunctionExpression extends Expression
$aCriteria = array_merge($oExpression->GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef), $aCriteria);
}
$aCriteria['has_undefined'] = true;
$aCriteria['oql'] = $this->RenderExpression(false, $aArgs, $bRetrofitParams);
$aCriteria['oql'] = $this->Render($aArgs, $bRetrofitParams);
break;
case 'NOW':
@@ -2022,9 +1892,6 @@ class FunctionExpression extends Expression
}
}
/**
* @see https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html
*/
class IntervalExpression extends Expression
{
protected $m_oValue; // expression
@@ -2053,9 +1920,9 @@ class IntervalExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
return 'INTERVAL '.$this->m_oValue->RenderExpression($bForSQL, $aArgs, $bRetrofitParams).' '.$this->m_sUnit;
return 'INTERVAL '.$this->m_oValue->Render($aArgs, $bRetrofitParams).' '.$this->m_sUnit;
}
public function Browse(Closure $callback)
@@ -2120,7 +1987,7 @@ class IntervalExpression extends Expression
public function Display($oSearch, &$aArgs = null, $oAttDef = null, &$aCtx = array())
{
return $this->m_oValue->RenderExpression(false, $aArgs).' '.Dict::S('Expression:Unit:Long:'.$this->m_sUnit, $this->m_sUnit);
return $this->m_oValue->Render($aArgs).' '.Dict::S('Expression:Unit:Long:'.$this->m_sUnit, $this->m_sUnit);
}
}
@@ -2145,12 +2012,12 @@ class CharConcatExpression extends Expression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$sCol = $oExpr->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sCol = $oExpr->Render($aArgs, $bRetrofitParams);
// Concat will be globally NULL if one single argument is null !
$aRes[] = "COALESCE($sCol, '')";
}
@@ -2168,11 +2035,12 @@ class CharConcatExpression extends Expression
public function ApplyParameters($aArgs)
{
$aRes = array();
foreach ($this->m_aExpressions as $idx => $oExpr)
{
if ($oExpr instanceof VariableExpression)
{
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar($aArgs);
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar();
}
else
{
@@ -2256,12 +2124,12 @@ class CharConcatWSExpression extends CharConcatExpression
}
// recursive rendering
public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false)
public function Render(&$aArgs = null, $bRetrofitParams = false)
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$sCol = $oExpr->RenderExpression($bForSQL, $aArgs, $bRetrofitParams);
$sCol = $oExpr->Render($aArgs, $bRetrofitParams);
// Concat will be globally NULL if one single argument is null !
$aRes[] = "COALESCE($sCol, '')";
}

View File

@@ -140,7 +140,6 @@ class OQLLexerRaw
'/\GNOT LIKE/ ',
'/\GIN/ ',
'/\GNOT IN/ ',
'/\GMATCHES/ ',
'/\GINTERVAL/ ',
'/\GIF/ ',
'/\GELT/ ',
@@ -442,209 +441,204 @@ class OQLLexerRaw
function yy_r1_33($yy_subpatterns)
{
$this->token = OQLParser::MATCHES;
$this->token = OQLParser::INTERVAL;
}
function yy_r1_34($yy_subpatterns)
{
$this->token = OQLParser::INTERVAL;
$this->token = OQLParser::F_IF;
}
function yy_r1_35($yy_subpatterns)
{
$this->token = OQLParser::F_IF;
$this->token = OQLParser::F_ELT;
}
function yy_r1_36($yy_subpatterns)
{
$this->token = OQLParser::F_ELT;
$this->token = OQLParser::F_COALESCE;
}
function yy_r1_37($yy_subpatterns)
{
$this->token = OQLParser::F_COALESCE;
$this->token = OQLParser::F_ISNULL;
}
function yy_r1_38($yy_subpatterns)
{
$this->token = OQLParser::F_ISNULL;
$this->token = OQLParser::F_CONCAT;
}
function yy_r1_39($yy_subpatterns)
{
$this->token = OQLParser::F_CONCAT;
$this->token = OQLParser::F_SUBSTR;
}
function yy_r1_40($yy_subpatterns)
{
$this->token = OQLParser::F_SUBSTR;
$this->token = OQLParser::F_TRIM;
}
function yy_r1_41($yy_subpatterns)
{
$this->token = OQLParser::F_TRIM;
$this->token = OQLParser::F_DATE;
}
function yy_r1_42($yy_subpatterns)
{
$this->token = OQLParser::F_DATE;
$this->token = OQLParser::F_DATE_FORMAT;
}
function yy_r1_43($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_FORMAT;
$this->token = OQLParser::F_CURRENT_DATE;
}
function yy_r1_44($yy_subpatterns)
{
$this->token = OQLParser::F_CURRENT_DATE;
$this->token = OQLParser::F_NOW;
}
function yy_r1_45($yy_subpatterns)
{
$this->token = OQLParser::F_NOW;
$this->token = OQLParser::F_TIME;
}
function yy_r1_46($yy_subpatterns)
{
$this->token = OQLParser::F_TIME;
$this->token = OQLParser::F_TO_DAYS;
}
function yy_r1_47($yy_subpatterns)
{
$this->token = OQLParser::F_TO_DAYS;
$this->token = OQLParser::F_FROM_DAYS;
}
function yy_r1_48($yy_subpatterns)
{
$this->token = OQLParser::F_FROM_DAYS;
$this->token = OQLParser::F_YEAR;
}
function yy_r1_49($yy_subpatterns)
{
$this->token = OQLParser::F_YEAR;
$this->token = OQLParser::F_MONTH;
}
function yy_r1_50($yy_subpatterns)
{
$this->token = OQLParser::F_MONTH;
$this->token = OQLParser::F_DAY;
}
function yy_r1_51($yy_subpatterns)
{
$this->token = OQLParser::F_DAY;
$this->token = OQLParser::F_HOUR;
}
function yy_r1_52($yy_subpatterns)
{
$this->token = OQLParser::F_HOUR;
$this->token = OQLParser::F_MINUTE;
}
function yy_r1_53($yy_subpatterns)
{
$this->token = OQLParser::F_MINUTE;
$this->token = OQLParser::F_SECOND;
}
function yy_r1_54($yy_subpatterns)
{
$this->token = OQLParser::F_SECOND;
$this->token = OQLParser::F_DATE_ADD;
}
function yy_r1_55($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_ADD;
$this->token = OQLParser::F_DATE_SUB;
}
function yy_r1_56($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_SUB;
$this->token = OQLParser::F_ROUND;
}
function yy_r1_57($yy_subpatterns)
{
$this->token = OQLParser::F_ROUND;
$this->token = OQLParser::F_FLOOR;
}
function yy_r1_58($yy_subpatterns)
{
$this->token = OQLParser::F_FLOOR;
$this->token = OQLParser::F_INET_ATON;
}
function yy_r1_59($yy_subpatterns)
{
$this->token = OQLParser::F_INET_ATON;
$this->token = OQLParser::F_INET_NTOA;
}
function yy_r1_60($yy_subpatterns)
{
$this->token = OQLParser::F_INET_NTOA;
$this->token = OQLParser::BELOW;
}
function yy_r1_61($yy_subpatterns)
{
$this->token = OQLParser::BELOW;
$this->token = OQLParser::BELOW_STRICT;
}
function yy_r1_62($yy_subpatterns)
{
$this->token = OQLParser::BELOW_STRICT;
$this->token = OQLParser::NOT_BELOW;
}
function yy_r1_63($yy_subpatterns)
{
$this->token = OQLParser::NOT_BELOW;
$this->token = OQLParser::NOT_BELOW_STRICT;
}
function yy_r1_64($yy_subpatterns)
{
$this->token = OQLParser::NOT_BELOW_STRICT;
$this->token = OQLParser::ABOVE;
}
function yy_r1_65($yy_subpatterns)
{
$this->token = OQLParser::ABOVE;
$this->token = OQLParser::ABOVE_STRICT;
}
function yy_r1_66($yy_subpatterns)
{
$this->token = OQLParser::ABOVE_STRICT;
$this->token = OQLParser::NOT_ABOVE;
}
function yy_r1_67($yy_subpatterns)
{
$this->token = OQLParser::NOT_ABOVE;
$this->token = OQLParser::NOT_ABOVE_STRICT;
}
function yy_r1_68($yy_subpatterns)
{
$this->token = OQLParser::NOT_ABOVE_STRICT;
$this->token = OQLParser::HEXVAL;
}
function yy_r1_69($yy_subpatterns)
{
$this->token = OQLParser::HEXVAL;
$this->token = OQLParser::NUMVAL;
}
function yy_r1_70($yy_subpatterns)
{
$this->token = OQLParser::NUMVAL;
$this->token = OQLParser::STRVAL;
}
function yy_r1_71($yy_subpatterns)
{
$this->token = OQLParser::STRVAL;
$this->token = OQLParser::NAME;
}
function yy_r1_72($yy_subpatterns)
{
$this->token = OQLParser::NAME;
}
function yy_r1_73($yy_subpatterns)
{
$this->token = OQLParser::VARNAME;
}
function yy_r1_74($yy_subpatterns)
function yy_r1_73($yy_subpatterns)
{
$this->token = OQLParser::DOT;
@@ -672,25 +666,25 @@ class OQLLexer extends OQLLexerRaw
function yylex()
{
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
}
}
}

View File

@@ -139,7 +139,6 @@ f_round = "ROUND"
f_floor = "FLOOR"
f_inet_aton = "INET_ATON"
f_inet_ntoa = "INET_NTOA"
matches = "MATCHES"
below = "BELOW"
below_strict = "BELOW STRICT"
not_below = "NOT BELOW"
@@ -274,9 +273,6 @@ in {
not_in {
$this->token = OQLParser::NOT_IN;
}
matches {
$this->token = OQLParser::MATCHES;
}
interval {
$this->token = OQLParser::INTERVAL;
}
@@ -423,25 +419,25 @@ class OQLLexer extends OQLLexerRaw
function yylex()
{
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@ Example:
%left TIMES DIVIDE MOD.
%right EXP NOT.
later : solve the 2 remaining shift-reduce conflicts (JOIN)
TODO : solve the 2 remaining shift-reduce conflicts (JOIN)
*/
@@ -108,16 +108,7 @@ expression_prio1(A) ::= expression_basic(X). { A = X; }
expression_prio1(A) ::= expression_prio1(X) operator1(Y) expression_basic(Z). { A = new BinaryOqlExpression(X, Y, Z); }
expression_prio2(A) ::= expression_prio1(X). { A = X; }
expression_prio2(A) ::= expression_prio2(X) operator2(Y) expression_prio1(Z).{
if (Y == 'MATCHES')
{
A = new MatchOqlExpression(X, Z);
}
else
{
A = new BinaryOqlExpression(X, Y, Z);
}
}
expression_prio2(A) ::= expression_prio2(X) operator2(Y) expression_prio1(Z). { A = new BinaryOqlExpression(X, Y, Z); }
expression_prio3(A) ::= expression_prio2(X). { A = X; }
expression_prio3(A) ::= expression_prio3(X) operator3(Y) expression_prio2(Z). { A = new BinaryOqlExpression(X, Y, Z); }
@@ -189,22 +180,18 @@ str_value(A) ::= STRVAL(X). {A=stripslashes(substr(X, 1, strlen(X) - 2));}
operator1(A) ::= num_operator1(X). {A=X;}
operator1(A) ::= bitwise_operator1(X). {A=X;}
operator2(A) ::= num_operator2(X). {A=X;}
operator2(A) ::= str_operator(X). {A=X;}
operator2(A) ::= REGEXP(X). {A=X;}
operator2(A) ::= EQ(X). {A=X;}
operator2(A) ::= NOT_EQ(X). {A=X;}
operator3(A) ::= LOG_AND(X). {A=X;}
operator3(A) ::= bitwise_operator3(X). {A=X;}
operator4(A) ::= LOG_OR(X). {A=X;}
operator4(A) ::= bitwise_operator4(X). {A=X;}
num_operator1(A) ::= MATH_DIV(X). {A=X;}
num_operator1(A) ::= MATH_MULT(X). {A=X;}
num_operator2(A) ::= MATH_PLUS(X). {A=X;}
num_operator2(A) ::= MATH_MINUS(X). {A=X;}
num_operator2(A) ::= GT(X). {A=X;}
@@ -214,13 +201,10 @@ num_operator2(A) ::= LE(X). {A=X;}
str_operator(A) ::= LIKE(X). {A=X;}
str_operator(A) ::= NOT_LIKE(X). {A=X;}
str_operator(A) ::= MATCHES(X). {A=X;}
bitwise_operator1(A) ::= BITWISE_LEFT_SHIFT(X). {A=X;}
bitwise_operator1(A) ::= BITWISE_RIGHT_SHIFT(X). {A=X;}
bitwise_operator3(A) ::= BITWISE_AND(X). {A=X;}
bitwise_operator4(A) ::= BITWISE_OR(X). {A=X;}
bitwise_operator4(A) ::= BITWISE_XOR(X). {A=X;}

View File

@@ -84,7 +84,7 @@ class OqlInterpreter
}
/**
* @return \OqlObjectQuery|\OqlUnionQuery
* @return OqlQuery
* @throws \OQLException
*/
public function ParseQuery()

View File

@@ -160,26 +160,6 @@ class BinaryOqlExpression extends BinaryExpression implements CheckableExpressio
}
}
class MatchOqlExpression extends MatchExpression implements CheckableExpression
{
public function Check(ModelReflection $oModelReflection, $aAliases, $sSourceQuery)
{
$this->m_oLeftExpr->Check($oModelReflection, $aAliases, $sSourceQuery);
$this->m_oRightExpr->Check($oModelReflection, $aAliases, $sSourceQuery);
// Only field MATCHES scalar is allowed
if (!$this->m_oLeftExpr instanceof FieldExpression)
{
throw new OqlNormalizeException('Only "field MATCHES string" syntax is allowed', $sSourceQuery, new OqlName($this->m_oLeftExpr->RenderExpression(true), 0));
}
// Only field MATCHES scalar is allowed
if (!$this->m_oRightExpr instanceof ScalarExpression)
{
throw new OqlNormalizeException('Only "field MATCHES string" syntax is allowed', $sSourceQuery, new OqlName($this->m_oRightExpr->RenderExpression(true), 0));
}
}
}
class ScalarOqlExpression extends ScalarExpression implements CheckableExpression
{
public function Check(ModelReflection $oModelReflection, $aAliases, $sSourceQuery)

View File

@@ -1 +1 @@
2018-08-31
2015-08-31

View File

@@ -34,7 +34,7 @@ class ormCaseLog {
/**
* Initializes the log with the first (initial) entry
* @param $sLog string The text of the whole case log
* @param $aIndex array The case log index
* @param $aIndex hash The case log index
*/
public function __construct($sLog = '', $aIndex = array())
{
@@ -159,7 +159,6 @@ class ormCaseLog {
$aEntries[] = array(
'date' => '',
'user_login' => '',
'user_id' => 0,
'message' => $sTextEntry,
'message_html' => utils::TextToHtml($sTextEntry),
);
@@ -296,6 +295,7 @@ class ormCaseLog {
*/
public function GetAsSimpleHtml($aTransfoHandler = null)
{
$sStyleCaseLogHeader = '';
$sStyleCaseLogEntry = '';
$sHtml = '<ul class="case_log_simple_html">';
@@ -513,6 +513,7 @@ class ormCaseLog {
public function AddLogEntry($sText, $sOnBehalfOf = '')
{
$sText = HTMLSanitizer::Sanitize($sText);
$bMergeEntries = false;
$sDate = date(AttributeDateTime::GetInternalFormat());
if ($sOnBehalfOf == '')
{
@@ -698,6 +699,7 @@ class ormCaseLog {
{
$iPos = 0;
$index = count($this->m_aIndex) - 1;
$aIndex = $this->m_aIndex;
while($index > $iIndex)
{
$iPos += $this->m_aIndex[$index]['separator_length'];

View File

@@ -126,6 +126,7 @@ class ormDocument
*/
public function GetDisplayURL($sClass, $Id, $sAttCode)
{
// TODO: When refactoring this with the URLMaker system, mind to also change calls in the portal (look for the "p_object_document_display" route)
return utils::GetAbsoluteUrlAppRoot() . "pages/ajax.render.php?operation=display_document&class=$sClass&id=$Id&field=$sAttCode";
}
@@ -137,6 +138,7 @@ class ormDocument
{
// Compute a signature to reset the cache anytime the data changes (this is acceptable if used only with icon files)
$sSignature = md5($this->GetData());
// TODO: When refactoring this with the URLMaker system, mind to also change calls in the portal (look for the "p_object_document_display" route)
return utils::GetAbsoluteUrlAppRoot() . "pages/ajax.document.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode&s=$sSignature&cache=86400";
}

View File

@@ -42,7 +42,6 @@ class ormPassword
public function __construct($sHash = '', $sSalt = '')
{
$this->m_sHashed = $sHash;
//only used for <= 2.5 hashed password
$this->m_sSalt = $sSalt;
}
@@ -51,7 +50,8 @@ class ormPassword
*/
public function SetPassword($sClearTextPassword)
{
$this->m_sHashed = password_hash($sClearTextPassword, PASSWORD_DEFAULT);
$this->m_sSalt = SimpleCrypt::GetNewSalt();
$this->m_sHashed = $this->ComputeHash($sClearTextPassword);
}
/**
@@ -95,19 +95,10 @@ class ormPassword
public function CheckPassword($sClearTextPassword)
{
$bResult = false;
$aInfo = password_get_info($this->m_sHashed);
switch ($aInfo["algo"])
$sHashedPwd = $this->ComputeHash($sClearTextPassword);
if ($this->m_sHashed == $sHashedPwd)
{
case 0:
//unknown, assume it's a legacy password
$sHashedPwd = $this->ComputeHash($sClearTextPassword);
if ($this->m_sHashed == $sHashedPwd)
{
$bResult = true;
}
break;
default:
$bResult = password_verify($sClearTextPassword, $this->m_sHashed);
$bResult = true;
}
return $bResult;
}

View File

@@ -1,380 +0,0 @@
<?php
/**
* Copyright (c) 2010-2018 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/>
*
*/
/**
* Created by PhpStorm.
* Date: 24/08/2018
* Time: 14:35
*/
class ormSet
{
protected $sClass; // class of the field
protected $sAttCode; // attcode of the field
protected $aOriginalObjects = null;
/**
* Object from the original set, minus the removed objects
*/
protected $aPreserved = array();
/**
* New items
*/
protected $aAdded = array();
/**
* Removed items
*/
protected $aRemoved = array();
/**
* Modified items (mass edit)
*/
protected $aModified = array();
/**
* @var int Max number of tags in collection
*/
protected $iLimit;
/**
* __toString magical function overload.
*/
public function __toString()
{
$aValue = $this->GetValues();
if (!empty($aValue))
{
return implode(', ', $aValue);
}
else
{
return ' ';
}
}
/**
* ormSet constructor.
*
* @param string $sClass
* @param string $sAttCode
* @param int $iLimit
*
* @throws \Exception
*/
public function __construct($sClass, $sAttCode, $iLimit = 12)
{
$this->sAttCode = $sAttCode;
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if (!$oAttDef instanceof AttributeSet)
{
throw new Exception("ormSet: field {$sClass}:{$sAttCode} is not a set");
}
$this->sClass = $sClass;
$this->iLimit = $iLimit;
}
/**
* @return string
*/
public function GetClass()
{
return $this->sClass;
}
/**
* @return string
*/
public function GetAttCode()
{
return $this->sAttCode;
}
/**
*
* @param array $aItems
*
* @throws \CoreException
* @throws \CoreUnexpectedValue when a code is invalid
*/
public function SetValues($aItems)
{
if (!is_array($aItems))
{
throw new CoreUnexpectedValue("Wrong value {$aItems} for {$this->sClass}:{$this->sAttCode}");
}
$aValues = array();
$iCount = 0;
$bError = false;
foreach($aItems as $oItem)
{
$iCount++;
if (($this->iLimit != 0) && ($iCount > $this->iLimit))
{
$bError = true;
continue;
}
$aValues[] = $oItem;
}
$this->aPreserved = &$aValues;
$this->aRemoved = array();
$this->aAdded = array();
$this->aModified = array();
$this->aOriginalObjects = $aValues;
if ($bError)
{
throw new CoreException("Maximum number of items ({$this->iLimit}) reached for {$this->sClass}:{$this->sAttCode}");
}
}
public function Count()
{
return count($this->aPreserved) + count($this->aAdded) - count($this->aRemoved);
}
/**
* @return array of codes
*/
public function GetValues()
{
$aValues = array_merge($this->aPreserved, $this->aAdded);
return $aValues;
}
/**
* @return array of tag labels indexed by code for only the added tags
*/
private function GetAdded()
{
return $this->aAdded;
}
/**
* @return array of tag labels indexed by code for only the removed tags
*/
private function GetRemoved()
{
return $this->aRemoved;
}
/** Get the delta with another ItemSet
*
* $aDelta['added] = array of tag codes for only the added tags
* $aDelta['removed'] = array of tag codes for only the removed tags
*
* @param \ormSet $oOtherSet
*
* @return array
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \Exception
*/
public function GetDelta(ormSet $oOtherSet)
{
$oSet = new ormSet($this->sClass, $this->sAttCode, $this->iLimit);
// Set the initial value
$aOrigItems = $this->GetValues();
$oSet->SetValues($aOrigItems);
// now remove everything
foreach($aOrigItems as $oItem)
{
$oSet->Remove($oItem);
}
// now add the tags of the other ItemSet
foreach($oOtherSet->GetValues() as $oItem)
{
$oSet->Add($oItem);
}
$aDelta = array();
$aDelta['added'] = $oSet->GetAdded();
$aDelta['removed'] = $oSet->GetRemoved();
return $aDelta;
}
/**
* @return string[] list of codes for partial entries
*/
public function GetModified()
{
return $this->aModified;
}
/**
* Apply a delta to the current ItemSet
* $aDelta['added] = array of added items
* $aDelta['removed'] = array of removed items
*
* @param $aDelta
*
* @throws \CoreException
*/
public function ApplyDelta($aDelta)
{
if (isset($aDelta['removed']))
{
foreach($aDelta['removed'] as $oItem)
{
$this->Remove($oItem);
}
}
if (isset($aDelta['added']))
{
foreach($aDelta['added'] as $oItem)
{
$this->Add($oItem);
}
}
// Reset the object
$this->SetValues($this->GetValues());
}
/**
* @param string $oItem
*
* @throws \CoreException
*/
public function Add($oItem)
{
if (($this->iLimit != 0) && ($this->Count() > $this->iLimit))
{
throw new CoreException("Maximum number of items ({$this->iLimit}) reached for {$this->sClass}:{$this->sAttCode}");
}
if ($this->IsItemInList($this->aPreserved, $oItem) || $this->IsItemInList($this->aAdded, $oItem))
{
// nothing to do, already existing tag
return;
}
// if removed and added again
if (($this->RemoveItemFromList($this->aRemoved, $oItem)) !== false)
{
// put it back into preserved
$this->aPreserved[] = $oItem;
// no need to add it to aModified : was already done when calling RemoveItem method
}
else
{
$this->aAdded[] = $oItem;
$this->aModified[] = $oItem;
}
}
/**
* @param $oItem
*/
public function Remove($oItem)
{
if ($this->IsItemInList($this->aRemoved, $oItem))
{
// nothing to do, already removed tag
return;
}
if ($this->RemoveItemFromList($this->aAdded, $oItem) !== false)
{
$this->aModified[] = $oItem;
return; // if present in added, can't be in preserved !
}
if ($this->RemoveItemFromList($this->aPreserved, $oItem) !== false)
{
$this->aModified[] = $oItem;
$this->aRemoved[] = $oItem;
}
}
private function IsItemInList($aItemList, $oItem)
{
return in_array($oItem, $aItemList);
}
/**
* @param \DBObject[] $aItemList
* @param $oItem
*
* @return bool|\DBObject false if not found, else the removed element
*/
private function RemoveItemFromList(&$aItemList, $oItem)
{
if (!($this->IsItemInList($aItemList, $oItem)))
{
return false;
}
foreach ($aItemList as $index => $value)
{
if ($value === $oItem)
{
unset($aItemList[$index]);
return $oItem;
}
}
return false;
}
/**
* Populates the added and removed arrays for bulk edit
*
* @param string[] $aItems
*
* @throws \CoreException
*/
public function GenerateDiffFromArray($aItems)
{
foreach($this->GetValues() as $oCurrentItem)
{
if (!in_array($oCurrentItem, $aItems))
{
$this->Remove($oCurrentItem);
}
}
foreach($aItems as $oNewItem)
{
$this->Add($oNewItem);
}
}
/**
* Compare Item Set
*
* @param \ormSet $other
*
* @return bool true if same tag set
*/
public function Equals(ormSet $other)
{
return implode(', ', $this->GetValue()) === implode(', ', $other->GetValue());
}
}

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2018 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
@@ -85,12 +85,8 @@ class ormStopWatch
/**
* Get the working elapsed time since the start of the stop watch
* even if it is currently running
*
* @param AttributeDefinition oAttDef Attribute hosting the stop watch
* @param Object oObject Hosting object (used for query parameters)
*
* @return int|mixed
* @throws \CoreException
* @param oAttDef AttributeDefinition Attribute hosting the stop watch
* @param oObject Hosting object (used for query parameters)
*/
public function GetElapsedTime($oAttDef, $oObject)
{
@@ -264,16 +260,6 @@ class ormStopWatch
return $iRet;
}
/**
* @param $oObject
* @param $oAttDef
* @param $iPercent
* @param $iStartTime
* @param $iDurationSec
*
* @return mixed
* @throws \CoreException
*/
protected function ComputeDeadline($oObject, $oAttDef, $iPercent, $iStartTime, $iDurationSec)
{
$sWorkingTimeComputer = $oAttDef->Get('working_time_computing');
@@ -281,6 +267,11 @@ class ormStopWatch
{
$sWorkingTimeComputer = class_exists('SLAComputation') ? 'SLAComputation' : 'DefaultWorkingTimeComputer';
}
$aCallSpec = array($sWorkingTimeComputer, '__construct');
if (!is_callable($aCallSpec))
{
//throw new CoreException("Pas de constructeur pour $sWorkingTimeComputer!");
}
$oComputer = new $sWorkingTimeComputer();
$aCallSpec = array($oComputer, 'GetDeadline');
if (!is_callable($aCallSpec))
@@ -294,15 +285,6 @@ class ormStopWatch
return $iRet;
}
/**
* @param $oObject
* @param $oAttDef
* @param $iStartTime
* @param $iEndTime
*
* @return mixed
* @throws \CoreException
*/
protected function ComputeDuration($oObject, $oAttDef, $iStartTime, $iEndTime)
{
$sWorkingTimeComputer = $oAttDef->Get('working_time_computing');
@@ -402,20 +384,7 @@ class ormStopWatch
$sAttCode = $oAttDef->GetCode();
WorkingTimeRecorder::Start($oObject, $iComputationRefTime, "ormStopWatch-Deadline-$iPercent-$sAttCode", 'Core:ExplainWTC:StopWatch-Deadline', array("Class:$sClass/Attribute:$sAttCode", $iPercent));
}
$iRemaining = $iThresholdDuration - $this->iTimeSpent;
if ($iRemaining < 0)
{
if (class_exists('WorkingTimeRecorder'))
{
$sClass = get_class($oObject);
$sKey = $oObject->GetKey();
$sAttCode = $oAttDef->GetCode();
$sDate = date('Y-m-d H:i:s', $aThresholdData['deadline']);
WorkingTimeRecorder::Log(WorkingTimeRecorder::TRACE_INFO, "$sClass($sKey) ormStopWatch-Deadline-$iPercent-$sAttCode ($sDate) already reached, not changed.");
}
continue;
}
$aThresholdData['deadline'] = $this->ComputeDeadline($oObject, $oAttDef, $iPercent, $this->iLastStart, $iRemaining);
$aThresholdData['deadline'] = $this->ComputeDeadline($oObject, $oAttDef, $iPercent, $this->iLastStart, $iThresholdDuration - $this->iTimeSpent);
// OR $aThresholdData['deadline'] = $this->ComputeDeadline($oObject, $oAttDef, $iPercent, $this->iStarted, $iThresholdDuration);
if (class_exists('WorkingTimeRecorder'))
@@ -429,7 +398,7 @@ class ormStopWatch
$aThresholdData['triggered'] = false;
$aThresholdData['overrun'] = null;
}
// else
else
{
// The new threshold is in the past
// Note: the overrun can be wrong, but the correct algorithm to compute
@@ -485,10 +454,7 @@ class ormStopWatch
$aThresholdData['overrun'] = $iOverrun;
}
}
if ($aThresholdData['overrun'] == 0)
{
$aThresholdData['deadline'] = null;
}
$aThresholdData['deadline'] = null;
}
$this->iLastStart = null;
@@ -592,7 +558,7 @@ class CheckStopWatchThresholds implements iBackgroundProcess
CMDBObject::SetTrackInfo("Automatic - threshold triggered");
$oMyChange = CMDBObject::GetCurrentChange();
$oObj->DBUpdateTracked($oMyChange);
$oObj->DBUpdateTracked($oMyChange, true /*skip security*/);
}
// Activate any existing trigger

View File

@@ -1,482 +0,0 @@
<?php
/**
* Copyright (c) 2010-2018 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/>
*
*/
/**
* Created by PhpStorm.
* Date: 24/08/2018
* Time: 14:35
*/
final class ormTagSet extends ormSet
{
/**
* ormTagSet constructor.
*
* @param string $sClass
* @param string $sAttCode
* @param int $iLimit
*
* @throws \Exception
*/
public function __construct($sClass, $sAttCode, $iLimit = 12)
{
parent::__construct($sClass, $sAttCode, $iLimit);
}
/**
*
* @param array $aTagCodes
*
* @throws \CoreException
* @throws \CoreUnexpectedValue when a code is invalid
*/
public function SetValues($aTagCodes)
{
if (is_null($aTagCodes))
{
$aTagCodes = array();
}
if (!is_array($aTagCodes))
{
throw new CoreUnexpectedValue("Wrong value {$aTagCodes} for {$this->sClass}:{$this->sAttCode}");
}
$oTags = array();
$iCount = 0;
$bError = false;
foreach($aTagCodes as $sTagCode)
{
$iCount++;
if (($this->iLimit != 0) && ($iCount > $this->iLimit))
{
$bError = true;
continue;
}
$oTag = $this->GetTagFromCode($sTagCode);
$oTags[$sTagCode] = $oTag;
}
$this->aPreserved = &$oTags;
$this->aRemoved = array();
$this->aAdded = array();
$this->aModified = array();
$this->aOriginalObjects = $oTags;
if ($bError)
{
throw new CoreException("Maximum number of tags ({$this->iLimit}) reached for {$this->sClass}:{$this->sAttCode}");
}
}
/**
* @return array of tag codes
*/
public function GetValues()
{
$aValues = array();
foreach($this->aPreserved as $sTagCode => $oTag)
{
$aValues[] = $sTagCode;
}
foreach($this->aAdded as $sTagCode => $oTag)
{
$aValues[] = $sTagCode;
}
sort($aValues);
return $aValues;
}
/**
* @return array of tag labels indexed by code
*/
public function GetLabels()
{
$aTags = array();
/** @var \TagSetFieldData $oTag */
foreach($this->aPreserved as $sTagCode => $oTag)
{
try
{
$aTags[$sTagCode] = $oTag->Get('label');
} catch (CoreException $e)
{
IssueLog::Error($e->getMessage());
}
}
foreach($this->aAdded as $sTagCode => $oTag)
{
try
{
$aTags[$sTagCode] = $oTag->Get('label');
} catch (CoreException $e)
{
IssueLog::Error($e->getMessage());
}
}
ksort($aTags);
return $aTags;
}
/**
* @return array of tags indexed by code
*/
public function GetTags()
{
$aTags = array();
foreach($this->aPreserved as $sTagCode => $oTag)
{
$aTags[$sTagCode] = $oTag;
}
foreach($this->aAdded as $sTagCode => $oTag)
{
$aTags[$sTagCode] = $oTag;
}
ksort($aTags);
return $aTags;
}
/**
* @return array of tag labels indexed by code for only the added tags
*/
private function GetAddedCodes()
{
$aTags = array();
foreach($this->aAdded as $sTagCode => $oTag)
{
$aTags[] = $sTagCode;
}
ksort($aTags);
return $aTags;
}
/**
* @return array of tag labels indexed by code for only the removed tags
*/
private function GetRemovedCodes()
{
$aTags = array();
foreach($this->aRemoved as $sTagCode => $oTag)
{
$aTags[] = $sTagCode;
}
ksort($aTags);
return $aTags;
}
/**
* @return array of tag labels indexed by code for only the added tags
*/
private function GetAddedTags()
{
$aTags = array();
foreach($this->aAdded as $sTagCode => $oTag)
{
$aTags[$sTagCode] = $oTag;
}
ksort($aTags);
return $aTags;
}
/**
* @return array of tag labels indexed by code for only the removed tags
*/
private function GetRemovedTags()
{
$aTags = array();
foreach($this->aRemoved as $sTagCode => $oTag)
{
$aTags[$sTagCode] = $oTag;
}
ksort($aTags);
return $aTags;
}
/** Get the delta with another TagSet
*
* $aDelta['added] = array of tag codes for only the added tags
* $aDelta['removed'] = array of tag codes for only the removed tags
*
* @param \ormTagSet $oOtherTagSet
*
* @return array
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \Exception
*/
public function GetDelta(ormSet $oOtherTagSet)
{
$oTag = new ormTagSet($this->sClass, $this->sAttCode, 0);
// Set the initial value
$aOrigTagCodes = $this->GetValues();
$oTag->SetValues($aOrigTagCodes);
// now remove everything
foreach($aOrigTagCodes as $sTagCode)
{
$oTag->Remove($sTagCode);
}
// now add the tags of the other TagSet
foreach($oOtherTagSet->GetValues() as $sTagCode)
{
$oTag->Add($sTagCode);
}
$aDelta = array();
$aDelta['added'] = $oTag->GetAddedCodes();
$aDelta['removed'] = $oTag->GetRemovedCodes();
return $aDelta;
}
/** Get the delta with another TagSet
*
* $aDelta['added] = array of tag labels indexed by code for only the added tags
* $aDelta['removed'] = array of tag labels indexed by code for only the removed tags
*
* @param \ormTagSet $oOtherTagSet
*
* @return array
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \Exception
*/
public function GetDeltaTags(ormTagSet $oOtherTagSet)
{
$oTag = new ormTagSet($this->sClass, $this->sAttCode, 0);
// Set the initial value
$aOrigTagCodes = $this->GetValues();
$oTag->SetValues($aOrigTagCodes);
// now remove everything
foreach($aOrigTagCodes as $sTagCode)
{
$oTag->Remove($sTagCode);
}
// now add the tags of the other TagSet
foreach($oOtherTagSet->GetValues() as $sTagCode)
{
$oTag->Add($sTagCode);
}
$aDelta = array();
$aDelta['added'] = $oTag->GetAddedTags();
$aDelta['removed'] = $oTag->GetRemovedTags();
return $aDelta;
}
/**
* @return string[] list of codes for partial entries
*/
public function GetModified()
{
$aModifiedTagCodes = array_keys($this->aModified);
sort($aModifiedTagCodes);
return $aModifiedTagCodes;
}
/**
* Check whether a tag code is valid or not for this TagSet
*
* @param string $sTagCode
*
* @return bool
*/
public function IsValidTag($sTagCode)
{
try
{
$this->GetTagFromCode($sTagCode);
return true;
} catch (Exception $e)
{
return false;
}
}
/**
* @param string $sTagCode
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
*/
public function Add($sTagCode)
{
if (($this->iLimit != 0) && ($this->Count() == $this->iLimit))
{
throw new CoreException("Maximum number of tags ({$this->iLimit}) reached for {$this->sClass}:{$this->sAttCode}");
}
if ($this->IsTagInList($this->aPreserved, $sTagCode) || $this->IsTagInList($this->aAdded, $sTagCode))
{
// nothing to do, already existing tag
return;
}
// if removed then added again
if (($oTag = $this->RemoveTagFromList($this->aRemoved, $sTagCode)) !== false)
{
// put it back into preserved
$this->aPreserved[$sTagCode] = $oTag;
// no need to add it to aModified : was already done when calling Remove method
}
else
{
$oTag = $this->GetTagFromCode($sTagCode);
$this->aAdded[$sTagCode] = $oTag;
$this->aModified[$sTagCode] = $oTag;
}
}
/**
* @param $sTagCode
*/
public function Remove($sTagCode)
{
if ($this->IsTagInList($this->aRemoved, $sTagCode))
{
// nothing to do, already removed tag
return;
}
$oTag = $this->RemoveTagFromList($this->aAdded, $sTagCode);
if ($oTag !== false)
{
$this->aModified[$sTagCode] = $oTag;
return; // if present in added, can't be in preserved !
}
$oTag = $this->RemoveTagFromList($this->aPreserved, $sTagCode);
if ($oTag !== false)
{
$this->aModified[$sTagCode] = $oTag;
$this->aRemoved[$sTagCode] = $oTag;
}
}
private function IsTagInList($aTagList, $sTagCode)
{
return isset($aTagList[$sTagCode]);
}
/**
* @param \DBObject[] $aTagList
* @param string $sTagCode
*
* @return bool|\DBObject false if not found, else the removed element
*/
private function RemoveTagFromList(&$aTagList, $sTagCode)
{
if (!($this->IsTagInList($aTagList, $sTagCode)))
{
return false;
}
$oTag = $aTagList[$sTagCode];
unset($aTagList[$sTagCode]);
return $oTag;
}
/**
* @param $sTagCode
*
* @return DBObject tag
* @throws \CoreUnexpectedValue
* @throws \CoreException
*/
private function GetTagFromCode($sTagCode)
{
$aAllowedTags = $this->GetAllowedTags();
foreach($aAllowedTags as $oAllowedTag)
{
if ($oAllowedTag->Get('code') === $sTagCode)
{
return $oAllowedTag;
}
}
throw new CoreUnexpectedValue("{$sTagCode} is not defined as a valid tag for {$this->sClass}:{$this->sAttCode}");
}
/**
* @param $sTagCode
*
* @return DBObject tag
* @throws \CoreUnexpectedValue
* @throws \CoreException
*/
public function GetTagFromLabel($sTagLabel)
{
$aAllowedTags = $this->GetAllowedTags();
foreach($aAllowedTags as $oAllowedTag)
{
if ($oAllowedTag->Get('label') === $sTagLabel)
{
return $oAllowedTag->Get('code');
}
}
throw new CoreUnexpectedValue("{$sTagLabel} is not defined as a valid tag for {$this->sClass}:{$this->sAttCode}");
}
/**
* @return \TagSetFieldData[]
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
private function GetAllowedTags()
{
return TagSetFieldData::GetAllowedValues($this->sClass, $this->sAttCode);
}
/**
* Compare Tag Set
*
* @param \ormTagSet $other
*
* @return bool true if same tag set
*/
public function Equals(ormSet $other)
{
if (!($other instanceof ormTagSet))
{
return false;
}
if ($this->GetTagDataClass() !== $other->GetTagDataClass())
{
return false;
}
return implode(' ', $this->GetValues()) === implode(' ', $other->GetValues());
}
public function GetTagDataClass()
{
return TagSetFieldData::GetTagDataClassName($this->sClass, $this->sAttCode);
}
}

View File

@@ -257,13 +257,14 @@ class CoreServices implements iRestServiceProvider
*/
public function ListOperations($sVersion)
{
// 1.4 - iTop 2.5.2, 2.6.1, 2.7.0, Verb 'core/get': added pagination parameters limit and page
// 1.3 - iTop 2.2.0, Verb 'get_related': added the options 'redundancy' and 'direction' to take into account the redundancy in the impact analysis
// 1.2 - was documented in the wiki but never released ! Same as 1.3
// 1.1 - In the reply, objects have a 'key' entry so that it is no more necessary to split class::key programmaticaly
// 1.0 - Initial implementation in iTop 2.0.1
//
$aOps = array();
if (in_array($sVersion, array('1.0', '1.1', '1.2', '1.3')))
if (in_array($sVersion, array('1.0', '1.1', '1.2', '1.3', '1.4')))
{
$aOps[] = array(
'verb' => 'core/create',
@@ -299,9 +300,16 @@ class CoreServices implements iRestServiceProvider
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @param string $sVerb
* @param $aParams
*
* @return RestResult The standardized result structure (at least a message)
* @throws Exception in case of internal failure.
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \SimpleGraphException
* @throws \Exception
*/
public function ExecOperation($sVersion, $sVerb, $aParams)
{
@@ -436,8 +444,10 @@ class CoreServices implements iRestServiceProvider
$key = RestUtils::GetMandatoryParam($aParams, 'key');
$aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
$bExtendedOutput = (RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+');
$iLimit = (int)RestUtils::GetOptionalParam($aParams, 'limit', 0);
$iPage = (int)RestUtils::GetOptionalParam($aParams, 'page', 1);
$oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key);
$oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key, $iLimit, self::getOffsetFromLimitAndPage($iLimit, $iPage));
$sTargetClass = $oObjectSet->GetFilter()->GetClass();
if (UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ) != UR_ALLOWED_YES)
@@ -450,6 +460,11 @@ class CoreServices implements iRestServiceProvider
$oResult->code = RestResult::UNAUTHORIZED;
$oResult->message = "The current user does not have enough permissions for exporting data of class $sTargetClass";
}
elseif ($iPage < 1)
{
$oResult->code = RestResult::INVALID_PAGE;
$oResult->message = "The request page number is not valid. It must be an integer greater than 0";
}
else
{
while ($oObject = $oObjectSet->Fetch())
@@ -774,4 +789,15 @@ class CoreServices implements iRestServiceProvider
$oResult->message = $sRes;
}
}
/**
* @param int $iLimit
* @param int $iPage
*
* @return int Offset for a given page number
*/
protected static function getOffsetFromLimitAndPage($iLimit, $iPage)
{
return $iLimit * max(0, $iPage - 1);
}
}

View File

@@ -43,61 +43,17 @@
class SimpleCrypt
{
public static function GetNewDefaultParams()
{
if(function_exists('sodium_crypto_secretbox_open') && function_exists('random_bytes')){
$sEngineName = 'Sodium';
}
else if (function_exists('openssl_decrypt'))
{
$sEngineName = 'OpenSSL';
}
else if(function_exists('mcrypt_module_open')){
$sEngineName = 'Mcrypt';
}
else
{
$sEngineName = 'Simple';
}
$sEngineName = 'SimpleCrypt' . $sEngineName . 'Engine';
return $sEngineName::GetNewDefaultParams();
}
/**
* Constructor
* @param string $sEngineName Engine for encryption. Values: Simple, Mcrypt, Sodium or OpenSSL
* @throws Exception This library is unkown
* @param string $sEngineName Engine for encryption. Values: Simple, Mcrypt
*/
function __construct($sEngineName = 'Mcrypt')
{
switch($sEngineName){
case 'Sodium':
if(!function_exists('sodium_crypto_secretbox_open')){
$sEngineName = 'Simple';
}
break;
case 'Mcrypt':
if(!function_exists('mcrypt_module_open')){
if (function_exists('openssl_decrypt'))
{
$sEngineName = 'OpenSSLMcryptCompatibility';
}
else
{
$sEngineName = 'Simple';
}
}
break;
case 'OpenSSL':
if(!function_exists('openssl_decrypt')){
$sEngineName = 'Simple';
}
break;
case 'Simple':
break;
default:
throw new Exception(Dict::Format("Core:AttributeEncryptUnknownLibrary", $sEngineName));
}
if (($sEngineName == 'Mcrypt') && (!function_exists('mcrypt_module_open')))
{
// Defaults to Simple encryption if the mcrypt module is not present
$sEngineName = 'Simple';
}
$sEngineName = 'SimpleCrypt' . $sEngineName . 'Engine';
$this->oEngine = new $sEngineName;
}
@@ -194,7 +150,6 @@ class SimpleCrypt
*/
interface CryptEngine
{
public static function GetNewDefaultParams();
function Encrypt($key, $sString);
function Decrypt($key, $encrypted_data);
}
@@ -206,12 +161,7 @@ interface CryptEngine
*/
class SimpleCryptSimpleEngine implements CryptEngine
{
public static function GetNewDefaultParams()
{
return array( 'lib' => 'Simple', 'key' => null);
}
public function Encrypt($key, $sString)
public function Encrypt($key, $sString)
{
$result = '';
for($i=1; $i<=strlen($sString); $i++)
@@ -247,13 +197,7 @@ class SimpleCryptMcryptEngine implements CryptEngine
{
var $alg = MCRYPT_BLOWFISH;
var $td = null;
public static function GetNewDefaultParams()
{
return array('lib' => 'Mcrypt', 'key' => null);
}
public function __construct()
{
$this->td = mcrypt_module_open($this->alg,'','cbc','');
@@ -261,7 +205,7 @@ class SimpleCryptMcryptEngine implements CryptEngine
public function Encrypt($key, $sString)
{
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($this->td), MCRYPT_RAND_URANDOM); // MCRYPT_RAND_URANDOM is now useable since itop requires php >= 5.6
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($this->td), MCRYPT_RAND); // MCRYPT_RAND is the only choice on Windows prior to PHP 5.3
mcrypt_generic_init($this->td, $key, $iv);
if (empty($sString))
{
@@ -279,7 +223,7 @@ class SimpleCryptMcryptEngine implements CryptEngine
$r = mcrypt_generic_init($this->td, $key, $iv);
if (($r < 0) || ($r === false))
{
$decrypted_data = Dict::S("Core:AttributeEncryptFailedToDecrypt");
$decrypted_data = '** decryption error **';
}
else
{
@@ -294,121 +238,4 @@ class SimpleCryptMcryptEngine implements CryptEngine
mcrypt_module_close($this->td);
}
}
/**
* SodiumEngine requires Sodium extension
* Every encryption of the same string with the same key
* will return a different encrypted string.
* The key has to be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long.
*/
class SimpleCryptSodiumEngine implements CryptEngine
{
public static function GetNewDefaultParams()
{
return array('lib' => 'Sodium', 'key' => bin2hex(sodium_crypto_secretbox_keygen()));
}
public function Encrypt($key, $sString)
{
$key = hex2bin($key);
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$encrypted_string = sodium_crypto_secretbox($sString, $nonce, $key);
sodium_memzero($sString);
sodium_memzero($key);
return base64_encode($nonce.$encrypted_string);
}
public function Decrypt($key, $encrypted_data)
{
$key = hex2bin($key);
$encrypted_data = base64_decode($encrypted_data);
$nonce = mb_substr($encrypted_data, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
$encrypted_data = mb_substr($encrypted_data, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
$plaintext = sodium_crypto_secretbox_open($encrypted_data, $nonce, $key);
if ($plaintext === false)
{
$plaintext = Dict::S("Core:AttributeEncryptFailedToDecrypt");
}
sodium_memzero($encrypted_data);
sodium_memzero($key);
return $plaintext;
}
}
class SimpleCryptOpenSSLEngine implements CryptEngine
{
public static function GetNewDefaultParams()
{
return array('lib' => 'OpenSSL', 'key' => bin2hex(openssl_random_pseudo_bytes(32)));
}
public function Encrypt($key, $sString)
{
$key = hex2bin($key);
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length("AES-256-CBC"));
$encrypted_string = openssl_encrypt($sString, "AES-256-CBC", $key, 0 , $iv);
return $iv.$encrypted_string;
}
public function Decrypt($key, $encrypted_data)
{
$key = hex2bin($key);
$iv = mb_substr($encrypted_data, 0, openssl_cipher_iv_length("AES-256-CBC"), '8bit');
$encrypted_data = mb_substr($encrypted_data, openssl_cipher_iv_length("AES-256-CBC"), null, '8bit');
$plaintext = openssl_decrypt($encrypted_data,"AES-256-CBC", $key, 0 , $iv);
if ($plaintext === false)
{
$plaintext = Dict::S("Core:AttributeEncryptFailedToDecrypt");
}
return trim($plaintext);
}
}
class SimpleCryptOpenSSLMcryptCompatibilityEngine implements CryptEngine
{
public static function GetNewDefaultParams()
{
return array('lib' => 'OpenSSLMcryptCompatibility', 'key' => null);
}
//fix for php < 7.1.8 (keys are Zero padded instead of cycle padded)
static private function MakeOpenSSLBlowfishKey($key)
{
if("$key" === '')
{
return $key;
}
$len = (16+2)*4;
while(strlen($key) < $len)
{
$key .= $key;
}
$key = substr($key, 0, $len);
return $key;
}
public function Encrypt($key, $sString)
{
$key = SimpleCryptOpenSSLMcryptCompatibilityEngine::MakeOpenSSLBlowfishKey($key);
$blockSize = 8;
$len = strlen($sString);
$paddingLen = intval (($len + $blockSize -1) / $blockSize) * $blockSize - $len;
$padding = str_repeat("\0", $paddingLen);
$sData = $sString . $padding;
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length("BF-CBC"));
$encrypted_string = openssl_encrypt($sData, "BF-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
return $iv.$encrypted_string;
}
public function Decrypt($key, $encrypted_data)
{
$key = SimpleCryptOpenSSLMcryptCompatibilityEngine::MakeOpenSSLBlowfishKey($key);
$iv = mb_substr($encrypted_data, 0, openssl_cipher_iv_length("BF-CBC"), '8bit');
$encrypted_data = mb_substr($encrypted_data, openssl_cipher_iv_length("BF-CBC"), null, '8bit');
$plaintext = openssl_decrypt($encrypted_data,"BF-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
if ($plaintext === false)
{
$plaintext = Dict::S("Core:AttributeEncryptFailedToDecrypt");
}
return trim($plaintext);
}
}
?>

View File

@@ -275,7 +275,6 @@ EOF
$sAttCode = $aFieldSpec['sAttCode'];
$sField = '';
/** @var \DBObject $oObj */
$oObj = $aRow[$sAlias];
if ($oObj == null)
{
@@ -333,16 +332,11 @@ EOF
$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);
$sData .= "<td x:str>$sField</td>";
}
else if ($oAttDef instanceof AttributeTagSet)
{
$sField = $oObj->GetAsCSV($sAttCode, $this->bLocalizeOutput, '');
$sData .= "<td x:str>$sField</td>";
}
else
{
$rawValue = $oObj->Get($sAttCode);

View File

@@ -95,7 +95,7 @@ class SQLObjectQuery extends SQLQuery
$aFieldDesc = array();
foreach ($this->m_aFields as $sAlias => $oExpression)
{
$aFieldDesc[] = $oExpression->RenderExpression(false)." as <em>$sAlias</em>";
$aFieldDesc[] = $oExpression->Render()." as <em>$sAlias</em>";
}
$sFields = " =&gt; ".implode(', ', $aFieldDesc);
}
@@ -112,7 +112,7 @@ class SQLObjectQuery extends SQLQuery
$oSQLQuery = $aJoinInfo["select"];
if (isset($aJoinInfo["on_expression"]))
{
$sOnCondition = $aJoinInfo["on_expression"]->RenderExpression(false);
$sOnCondition = $aJoinInfo["on_expression"]->Render();
echo "<li>Join '$sJoinType', ON ($sOnCondition)".$oSQLQuery->DisplayHtml()."</li>\n";
}
@@ -339,12 +339,8 @@ class SQLObjectQuery extends SQLQuery
$this->PrepareRendering();
$sFrom = self::ClauseFrom($this->__aFrom, $sIndent);
$sWhere = self::ClauseWhere($this->m_oConditionExpr, $aArgs);
// Sanity
$iLimitCount = (int)$iLimitCount;
if ($iLimitCount > 0)
{
// Sanity
$iLimitStart = (int)$iLimitStart;
$sLimit = 'LIMIT '.$iLimitStart.', '.$iLimitCount;
}
else
@@ -468,7 +464,7 @@ class SQLObjectQuery extends SQLQuery
case "left":
if (isset($aJoinData["on_expression"]))
{
$sJoinCond = $aJoinData["on_expression"]->RenderExpression(true);
$sJoinCond = $aJoinData["on_expression"]->Render();
}
else
{
@@ -535,13 +531,13 @@ class SQLObjectQuery extends SQLQuery
//
foreach($this->m_aFields as $sAlias => $oExpression)
{
$oRootQuery->__aFields["`$sAlias`"] = $oExpression->RenderExpression(true);
$oRootQuery->__aFields["`$sAlias`"] = $oExpression->Render();
}
if ($this->m_aGroupBy)
{
foreach($this->m_aGroupBy as $sAlias => $oExpression)
{
$oRootQuery->__aGroupBy["`$sAlias`"] = $oExpression->RenderExpression(true);
$oRootQuery->__aGroupBy["`$sAlias`"] = $oExpression->Render();
}
}
if ($this->m_bToDelete)
@@ -555,7 +551,7 @@ class SQLObjectQuery extends SQLQuery
if (!is_null($this->m_oSelectedIdField))
{
$oRootQuery->__aSelectedIdFields[] = $this->m_oSelectedIdField->RenderExpression(true);
$oRootQuery->__aSelectedIdFields[] = $this->m_oSelectedIdField->Render();
}
// loop on joins, to complete the list of tables/fields/conditions

View File

@@ -177,7 +177,7 @@ abstract class SQLQuery
}
else
{
return $oConditionExpr->RenderExpression(true, $aArgs);
return $oConditionExpr->Render($aArgs);
}
}

View File

@@ -168,7 +168,7 @@ class SQLUnionQuery extends SQLQuery
}
foreach($this->aSelectExpr as $sSelectAlias => $oExpr)
{
$aSelectAliases[$sSelectAlias] = $oExpr->RenderExpression(true)." AS `$sSelectAlias`";
$aSelectAliases[$sSelectAlias] = $oExpr->Render()." AS `$sSelectAlias`";
}
$sSelect = implode(",$sLineSep ", $aSelectAliases);

View File

@@ -150,18 +150,15 @@ abstract class TabularBulkExport extends BulkExport
// Add the reconciliation keys
foreach(MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode)
{
if (!empty($sRemoteAttCode))
{
$sAttCodeEx = $sAttCode.'->'.$sRemoteAttCode;
if (!array_key_exists($sAttCodeEx, $aResult))
{
$oRemoteAttDef = MetaModel::GetAttributeDef($sRemoteClass, $sRemoteAttCode);
if ($this->IsExportableField($sRemoteClass, $sRemoteAttCode, $oRemoteAttDef))
{
$aResult[$sAttCodeEx] = array('code' => $sAttCodeEx, 'unique_label' => $oAttDef->GetLabel().'->'.$oRemoteAttDef->GetLabel(), 'label' => MetaModel::GetLabel($sRemoteClass, $sRemoteAttCode), 'attdef' => $oRemoteAttDef);
}
}
}
$sAttCodeEx = $sAttCode.'->'.$sRemoteAttCode;
if (!array_key_exists($sAttCodeEx, $aResult))
{
$oRemoteAttDef = MetaModel::GetAttributeDef($sRemoteClass, $sRemoteAttCode);
if ($this->IsExportableField($sRemoteClass, $sRemoteAttCode, $oRemoteAttDef))
{
$aResult[$sAttCodeEx] = array('code' => $sAttCodeEx, 'unique_label' => $oAttDef->GetLabel().'->'.$oRemoteAttDef->GetLabel(), 'label' => MetaModel::GetLabel($sRemoteClass, $sRemoteAttCode), 'attdef' => $oRemoteAttDef);
}
}
}
break;

View File

@@ -1,394 +0,0 @@
<?php
// Copyright (C) 2018 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/>
/**
* <p>Stores data for {@link AttributeTagSet} fields
*
* <p>We will have an implementation for each class/field to be able to customize rights (generated in
* \MFCompiler::CompileClass).<br> Only this abstract class will exists in the DB : the implementations won't had any
* new field.
*
* @since 2.6 N°931 tag fields
*/
abstract class TagSetFieldData extends cmdbAbstractObject
{
private static $m_aAllowedValues = array();
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
(
'category' => 'bizmodel',
'key_type' => 'autoincrement',
'name_attcode' => array('label'),
'state_attcode' => '',
'reconc_keys' => array('code'),
'db_table' => 'priv_tagfielddata',
'db_key_field' => 'id',
'db_finalclass_field' => 'finalclass',
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("code", array(
"allowed_values" => null,
"sql" => 'code',
"default_value" => '',
"is_null_allowed" => false,
"depends_on" => array(),
"validation_pattern" => '^[a-zA-Z][a-zA-Z0-9]{3,}$',
)));
MetaModel::Init_AddAttribute(new AttributeString("label", array(
"allowed_values" => null,
"sql" => 'label',
"default_value" => '',
"is_null_allowed" => false,
"depends_on" => array()
)));
MetaModel::Init_AddAttribute(new AttributeHTML("description", array(
"allowed_values" => null,
"sql" => 'description',
"default_value" => '',
"is_null_allowed" => true,
"depends_on" => array()
)));
MetaModel::Init_AddAttribute(new AttributeString("obj_class", array(
"allowed_values" => null,
"sql" => 'obj_class',
"default_value" => '',
"is_null_allowed" => false,
"depends_on" => array()
)));
MetaModel::Init_AddAttribute(new AttributeString("obj_attcode", array(
"allowed_values" => null,
"sql" => 'obj_attcode',
"default_value" => '',
"is_null_allowed" => false,
"depends_on" => array()
)));
MetaModel::Init_SetZListItems('details', array('code', 'label', 'description'));
MetaModel::Init_SetZListItems('standard_search', array('code', 'label', 'description'));
MetaModel::Init_SetZListItems('list', array('code', 'label', 'description'));
}
public function ComputeValues()
{
$sClassName = get_class($this);
$aRes = static::ExtractTagFieldName($sClassName);
$this->_Set('obj_class', $aRes['obj_class']);
$this->_Set('obj_attcode', $aRes['obj_attcode']);
}
public static function GetTagDataClassName($sClass, $sAttCode)
{
$sTagSuffix = $sClass.'__'.$sAttCode;
return 'TagSetFieldDataFor_'.$sTagSuffix;
}
/**
* Extract Tag class and attcode from the TagFieldData class name
*
* @param $sClassName
*
* @return string[]
* @throws \CoreException
*/
public static function ExtractTagFieldName($sClassName)
{
$aRes = array();
// Extract class and attcode from class name using pattern TagSetFieldDataFor_<class>_<attcode>>;
if (preg_match('@^TagSetFieldDataFor_(?<class>\w+)__(?<attcode>\w+)$@', $sClassName, $aMatches))
{
$aRes['obj_class'] = $aMatches['class'];
$aRes['obj_attcode'] = $aMatches['attcode'];
}
else
{
throw new CoreException("Bad Class name format: $sClassName");
}
return $aRes;
}
/**
* @param \DeletionPlan $oDeletionPlan
*
* @throws \CoreException
*/
public function DoCheckToDelete(&$oDeletionPlan)
{
parent::DoCheckToDelete($oDeletionPlan);
$sTagCode = $this->Get('code');
if ($this->IsCodeUsed($sTagCode))
{
$this->m_aDeleteIssues[] = Dict::S('Core:TagSetFieldData:ErrorDeleteUsedTag');
}
// Clear cache
$sClass = $this->Get('obj_class');
$sAttCode = $this->Get('obj_attcode');
$sTagDataClass = self::GetTagDataClassName($sClass, $sAttCode);
unset(self::$m_aAllowedValues[$sTagDataClass]);
}
/**
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @throws \Exception
*/
public function DoCheckToWrite()
{
$this->ComputeValues();
$sClass = $this->Get('obj_class');
$sAttCode = $this->Get('obj_attcode');
$iMaxLen = 20;
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeTagSet)
{
$iMaxLen = $oAttDef->GetTagCodeMaxLength();
}
$sTagCode = $this->Get('code');
// Check code syntax
$iMax = $iMaxLen - 1;
if (!preg_match("@^[a-zA-Z][a-zA-Z0-9]{2,$iMax}$@", $sTagCode))
{
$this->m_aCheckIssues[] = Dict::Format('Core:TagSetFieldData:ErrorTagCodeSyntax', $iMaxLen);
}
// Check that the code is not a MySQL stop word
$sSQL = "SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD";
try
{
$aResults = CMDBSource::QueryToArray($sSQL);
} catch (MySQLException $e)
{
IssueLog::Warning($e->getMessage());
$aResults = array();
}
foreach($aResults as $aResult)
{
if ($aResult['value'] == $sTagCode)
{
$this->m_aCheckIssues[] = Dict::S('Core:TagSetFieldData:ErrorTagCodeReservedWord');
break;
}
}
$sTagLabel = $this->Get('label');
$sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator');
if (empty($sTagLabel) || (strpos($sTagLabel, $sSepItem) !== false))
{
// Label must not contain | character
$this->m_aCheckIssues[] = Dict::Format('Core:TagSetFieldData:ErrorTagLabelSyntax', $sSepItem);
}
// Check that code and labels are uniques
$id = $this->GetKey();
$sClassName = get_class($this);
if (empty($id))
{
$oSearch = DBSearch::FromOQL("SELECT $sClassName WHERE (code = :tag_code OR label = :tag_label)");
}
else
{
$oSearch = DBSearch::FromOQL("SELECT $sClassName WHERE id != :id AND (code = :tag_code OR label = :tag_label)");
}
$aArgs = array('id' => $id, 'tag_code' => $sTagCode, 'tag_label' => $sTagLabel);
$oSet = new DBObjectSet($oSearch, array(), $aArgs);
if ($oSet->CountExceeds(0))
{
$this->m_aCheckIssues[] = Dict::S('Core:TagSetFieldData:ErrorDuplicateTagCodeOrLabel');
}
// Clear cache
$sTagDataClass = self::GetTagDataClassName($sClass, $sAttCode);
unset(self::$m_aAllowedValues[$sTagDataClass]);
parent::DoCheckToWrite();
}
/**
* @throws \CoreException
*/
public function OnUpdate()
{
parent::OnUpdate();
$aChanges = $this->ListChanges();
if (array_key_exists('code', $aChanges))
{
$sTagCode = $this->GetOriginal('code');
if ($this->IsCodeUsed($sTagCode))
{
throw new CoreException(Dict::S('Core:TagSetFieldData:ErrorCodeUpdateNotAllowed'));
}
}
if (array_key_exists('obj_class', $aChanges))
{
throw new CoreException(Dict::S('Core:TagSetFieldData:ErrorClassUpdateNotAllowed'));
}
if (array_key_exists('obj_attcode', $aChanges))
{
throw new CoreException(Dict::S('Core:TagSetFieldData:ErrorAttCodeUpdateNotAllowed'));
}
}
private function IsCodeUsed($sTagCode)
{
try
{
$sClass = $this->Get('obj_class');
$sAttCode = $this->Get('obj_attcode');
$oSearch = DBSearch::FromOQL("SELECT $sClass WHERE $sAttCode MATCHES '$sTagCode'");
$oSet = new DBObjectSet($oSearch);
if ($oSet->CountExceeds(0))
{
return true;
}
}
catch (Exception $e)
{
IssueLog::Warning($e->getMessage());
}
return false;
}
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
{
if ($sAttCode == 'code')
{
if ((!$this->IsNew()) && ($this->IsCodeUsed($this->Get('code'))))
{
return OPT_ATT_READONLY;
}
}
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
}
/**
* Display Tag Usage
*
* @param \WebPage $oPage
* @param bool $bEditMode
*
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
parent::DisplayBareRelations($oPage, $bEditMode);
if (!$bEditMode)
{
$sClass = $this->Get('obj_class');
$sAttCode = $this->Get('obj_attcode');
$sTagCode = $this->Get('code');
$oFilter = DBSearch::FromOQL("SELECT $sClass WHERE $sAttCode MATCHES '$sTagCode'");
$oSet = new DBObjectSet($oFilter);
$iCount = $oSet->Count();
$oPage->SetCurrentTab(Dict::Format('Core:TagSetFieldData:WhereIsThisTagTab', $iCount));
if ($iCount === 0)
{
$sNoEntries = Dict::S('Core:TagSetFieldData:NoEntryFound');
$oPage->add("<p>$sNoEntries</p>");
return;
}
$oFilter = DBSearch::FromOQL("SELECT $sClass WHERE $sAttCode MATCHES '$sTagCode'");
$oSet = new DBObjectSet($oFilter);
if ($oSet->CountExceeds(0))
{
$sClassLabel = MetaModel::GetName($sClass);
$oPage->add("<h2>$sClassLabel</h2>");
$oResultBlock = new DisplayBlock($oFilter, 'list', false);
$oResultBlock->Display($oPage, 1);
}
}
}
public static function GetClassName($sClass)
{
if ($sClass == 'TagSetFieldData')
{
$aWords = preg_split('/(?=[A-Z]+)/', $sClass);
return trim(implode(' ', $aWords));
}
try
{
$aTagFieldInfo = self::ExtractTagFieldName($sClass);
} catch (CoreException $e)
{
return $sClass;
}
$sClassDesc = MetaModel::GetName($aTagFieldInfo['obj_class']);
$sAttDesc = MetaModel::GetAttributeDef($aTagFieldInfo['obj_class'], $aTagFieldInfo['obj_attcode'])->GetLabel();
if (Dict::Exists("Class:$sClass"))
{
$sName = Dict::Format("Class:$sClass", $sClassDesc, $sAttDesc);
}
else
{
$sName = Dict::Format('Class:TagSetFieldData', $sClassDesc, $sAttDesc);
}
return $sName;
}
/**
* @param $sClass
* @param $sAttCode
*
* @return \TagSetFieldData[]
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public static function GetAllowedValues($sClass, $sAttCode)
{
$sClass = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
$sTagDataClass = self::GetTagDataClassName($sClass, $sAttCode);
if (!isset(self::$m_aAllowedValues[$sTagDataClass]))
{
$oSearch = new DBObjectSearch($sTagDataClass);
$oSearch->AddCondition('obj_class', $sClass);
$oSearch->AddCondition('obj_attcode', $sAttCode);
$oSet = new DBObjectSet($oSearch);
self::$m_aAllowedValues[$sTagDataClass] = $oSet->ToArray();
}
return self::$m_aAllowedValues[$sTagDataClass];
}
}

View File

@@ -56,20 +56,18 @@ class TemplateString
{
protected $m_sRaw;
protected $m_aPlaceholders;
public function __construct($sRaw)
{
$this->m_sRaw = $sRaw;
$this->m_aPlaceholders = null;
}
/**
* Split the string into placholders
*
* @param array $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
*
* @throws \Exception
*/
* Split the string into placholders
* @param Hash $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
* @return void
*/
protected function Analyze($aParamTypes = array())
{
if (!is_null($this->m_aPlaceholders)) return;
@@ -102,10 +100,9 @@ class TemplateString
}
/**
* Return the placeholders (for reporting purposes)
*
* @return array
*/
* Return the placeholders (for reporting purposes)
* @return void
*/
public function GetPlaceholders()
{
return $this->m_aPlaceholders;
@@ -113,11 +110,9 @@ class TemplateString
/**
* Check the format when possible
*
* @param array $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
*
* @return boolean
*/
* @param Hash $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
* @return void
*/
public function IsValid($aParamTypes = array())
{
$this->Analyze($aParamTypes);
@@ -140,12 +135,10 @@ class TemplateString
}
/**
* Apply the given parameters to replace the placeholders
*
* @param array $aParamValues Value of the expected parameters: hash array of '<param_id>' => '<value>'
*
* @return string
*/
* Apply the given parameters to replace the placeholders
* @param Hash $aParamValues Value of the expected parameters: hash array of '<param_id>' => '<value>'
* @return void
*/
public function Render($aParamValues = array())
{
$aParamTypes = array();
@@ -181,4 +174,5 @@ class TemplateString
}
return str_replace($aSearch, $aReplace, $this->m_sRaw);
}
}
}
?>

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2018 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
@@ -19,25 +19,21 @@
/**
* Persistent class Trigger and derived
* User defined triggers, that may be used in conjunction with user defined actions
* User defined triggers, that may be used in conjunction with user defined actions
*
* @copyright Copyright (C) 2010-2018 Combodo SARL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* A user defined trigger, to customize the application
* A user defined trigger, to customize the application
* A trigger will activate an action
*
* @package iTopORM
*/
abstract class Trigger extends cmdbAbstractObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
@@ -54,32 +50,25 @@ abstract class Trigger extends cmdbAbstractObject
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("action_list", array("linked_class" => "lnkTriggerAction", "ext_key_to_me" => "trigger_id", "ext_key_to_remote" => "action_id", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("action_list", array("linked_class"=>"lnkTriggerAction", "ext_key_to_me"=>"trigger_id", "ext_key_to_remote"=>"action_id", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
/**
* @param $aContextArgs
*
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function DoActivate($aContextArgs)
{
// Find the related actions
$oLinkedActions = $this->Get('action_list');
while ($oLink = $oLinkedActions->Fetch())
{
/** @var \DBObject $oLink */
$iActionId = $oLink->Get('action_id');
/** @var \Action $oAction */
$oAction = MetaModel::GetObject('Action', $iActionId);
if ($oAction->IsActive())
{
@@ -87,13 +76,11 @@ abstract class Trigger extends cmdbAbstractObject
}
}
}
/**
* Check whether the given object is in the scope of this trigger
* and can potentially be the subject of notifications
*
* @param DBObject $oObject The object to check
*
* @return bool
*/
public function IsInScope(DBObject $oObject)
@@ -104,15 +91,8 @@ abstract class Trigger extends cmdbAbstractObject
}
}
/**
* Class TriggerOnObject
*/
abstract class TriggerOnObject extends Trigger
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
@@ -129,20 +109,17 @@ abstract class TriggerOnObject extends Trigger
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClass("target_class", array("class_category" => "bizmodel", "more_values" => "User,UserExternal,UserInternal,UserLDAP,UserLocal", "sql" => "target_class", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeOQL("filter", array("allowed_values" => null, "sql" => "filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeClass("target_class", array("class_category"=>"bizmodel", "more_values"=>"User,UserExternal,UserInternal,UserLDAP,UserLocal", "sql"=>"target_class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeOQL("filter", array("allowed_values"=>null, "sql"=>"filter", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('default_search', array('description', 'target_class')); // Default criteria of the search banner
// MetaModel::Init_SetZListItems('standard_search', array('name', 'target_class', 'description')); // Criteria of the search form
// MetaModel::Init_SetZListItems('standard_search', array('name', 'target_class', 'description')); // Criteria of the search form
}
/**
* @throws \CoreException
*/
public function DoCheckToWrite()
{
parent::DoCheckToWrite();
@@ -158,7 +135,8 @@ abstract class TriggerOnObject extends Trigger
{
$this->m_aCheckIssues[] = Dict::Format('TriggerOnObject:WrongFilterClass', $this->Get('target_class'));
}
} catch (OqlException $e)
}
catch(OqlException $e)
{
$this->m_aCheckIssues[] = Dict::Format('TriggerOnObject:WrongFilterQuery', $e->getMessage());
}
@@ -168,33 +146,21 @@ abstract class TriggerOnObject extends Trigger
/**
* Check whether the given object is in the scope of this trigger
* and can potentially be the subject of notifications
*
* @param DBObject $oObject The object to check
*
* @return bool
* @throws \CoreException
*/
public function IsInScope(DBObject $oObject)
{
$sRootClass = $this->Get('target_class');
return ($oObject instanceof $sRootClass);
}
/**
* @param $aContextArgs
*
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function DoActivate($aContextArgs)
{
$bGo = true;
if (isset($aContextArgs['this->object()']))
{
/** @var \DBObject $oObject */
$oObject = $aContextArgs['this->object()'];
$bGo = $this->IsTargetObject($oObject->GetKey(), $oObject->ListChanges());
$bGo = $this->IsTargetObject($aContextArgs['this->object()']->GetKey());
}
if ($bGo)
{
@@ -202,18 +168,7 @@ abstract class TriggerOnObject extends Trigger
}
}
/**
* @param $iObjectId
* @param array $aChanges
*
* @return bool
* @throws \CoreException
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
public function IsTargetObject($iObjectId, $aChanges = array())
public function IsTargetObject($iObjectId)
{
$sFilter = trim($this->Get('filter'));
if (strlen($sFilter) > 0)
@@ -227,19 +182,14 @@ abstract class TriggerOnObject extends Trigger
{
$bRet = true;
}
return $bRet;
}
}
/**
* To trigger notifications when a ticket is updated from the portal
*/
class TriggerOnPortalUpdate extends TriggerOnObject
{
/**
* @throws \CoreException
*/
public static function Init()
{
$aParams = array
@@ -264,15 +214,8 @@ class TriggerOnPortalUpdate extends TriggerOnObject
}
}
/**
* Class TriggerOnStateChange
*/
abstract class TriggerOnStateChange extends TriggerOnObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
@@ -289,25 +232,19 @@ abstract class TriggerOnStateChange extends TriggerOnObject
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClassState("state", array("class_field" => 'target_class', "allowed_values" => null, "sql" => "state", "default_value" => null, "is_null_allowed" => false, "depends_on" => array('target_class'))));
MetaModel::Init_AddAttribute(new AttributeString("state", array("allowed_values"=>null, "sql"=>"state", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'state')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
/**
* Class TriggerOnStateEnter
*/
class TriggerOnStateEnter extends TriggerOnStateChange
{
/**
* @throws \CoreException
*/
public static function Init()
{
$aParams = array
@@ -330,18 +267,12 @@ class TriggerOnStateEnter extends TriggerOnStateChange
MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
/**
* Class TriggerOnStateLeave
*/
class TriggerOnStateLeave extends TriggerOnStateChange
{
/**
* @throws \CoreException
*/
public static function Init()
{
$aParams = array
@@ -364,18 +295,12 @@ class TriggerOnStateLeave extends TriggerOnStateChange
MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('')); // Criteria of the advanced search form
}
}
/**
* Class TriggerOnObjectCreate
*/
class TriggerOnObjectCreate extends TriggerOnObject
{
/**
* @throws \CoreException
*/
public static function Init()
{
$aParams = array
@@ -398,146 +323,12 @@ class TriggerOnObjectCreate extends TriggerOnObject
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
/**
* Class TriggerOnObjectCreate
*/
class TriggerOnObjectDelete extends TriggerOnObject
{
/**
* @throws \CoreException
*/
public static function Init()
{
$aParams = array
(
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
"state_attcode" => "",
"reconc_keys" => array('description'),
"db_table" => "priv_trigger_onobjdelete",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
/**
* Class TriggerOnObjectCreate
*/
class TriggerOnObjectUpdate extends TriggerOnObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
(
"category" => "grant_by_profile,core/cmdb,application",
"key_type" => "autoincrement",
"name_attcode" => "description",
"state_attcode" => "",
"reconc_keys" => array('description'),
"db_table" => "priv_trigger_onobjupdate",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('target_attcodes', array("allowed_values" => null, "class_field" => "target_class", "sql" => "target_attcodes", "default_value" => null, "is_null_allowed" => true, "max_items" => 20, "min_items" => 0, "attribute_definition_exclusion_list" => "AttributeDashboard,AttributeExternalField,AttributeFinalClass,AttributeFriendlyName,AttributeObsolescenceDate,AttributeObsolescenceFlag,AttributeSubItem", "attribute_definition_list" => null, "depends_on" => array('target_class'))));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'filter', 'target_attcodes', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
}
public function IsTargetObject($iObjectId, $aChanges = array())
{
if (!parent::IsTargetObject($iObjectId, $aChanges))
{
return false;
}
// Check the attribute
$oAttCodeSet = $this->Get('target_attcodes');
$aAttCodes = $oAttCodeSet->GetValues();
if (empty($aAttCodes))
{
return true;
}
foreach($aAttCodes as $sAttCode)
{
if (array_key_exists($sAttCode, $aChanges))
{
return true;
}
}
return false;
}
public function ComputeValues()
{
parent::ComputeValues();
// Remove unwanted attribute codes
$aChanges = $this->ListChanges();
if (isset($aChanges['target_attcodes']))
{
$oAttDef = MetaModel::GetAttributeDef(get_class($this), 'target_attcodes');
$aArgs = array('this' => $this);
$aAllowedValues = $oAttDef->GetAllowedValues($aArgs);
/** @var \ormSet $oValue */
$oValue = $this->Get('target_attcodes');
$aValues = $oValue->GetValues();
$bChanged = false;
foreach($aValues as $key => $sValue)
{
if (!isset($aAllowedValues[$sValue]))
{
unset($aValues[$key]);
$bChanged = true;
}
}
if ($bChanged)
{
$oValue->SetValues($aValues);
$this->Set('target_attcodes', $oValue);
}
}
}
}
/**
* Class lnkTriggerAction
*/
class lnkTriggerAction extends cmdbAbstractObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
@@ -554,11 +345,11 @@ class lnkTriggerAction extends cmdbAbstractObject
"is_link" => true,
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass" => "Action", "jointype" => '', "allowed_values" => null, "sql" => "action_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("action_name", array("allowed_values" => null, "extkey_attcode" => 'action_id', "target_attcode" => "name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass" => "Trigger", "jointype" => '', "allowed_values" => null, "sql" => "trigger_id", "is_null_allowed" => false, "on_target_delete" => DEL_AUTO, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("trigger_name", array("allowed_values" => null, "extkey_attcode" => 'trigger_id', "target_attcode" => "description")));
MetaModel::Init_AddAttribute(new AttributeInteger("order", array("allowed_values" => null, "sql" => "order", "default_value" => 0, "is_null_allowed" => true, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass"=>"Action", "jointype"=> '', "allowed_values"=>null, "sql"=>"action_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("action_name", array("allowed_values"=>null, "extkey_attcode"=> 'action_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass"=>"Trigger", "jointype"=> '', "allowed_values"=>null, "sql"=>"trigger_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("trigger_name", array("allowed_values"=>null, "extkey_attcode"=> 'trigger_id', "target_attcode"=>"description")));
MetaModel::Init_AddAttribute(new AttributeInteger("order", array("allowed_values"=>null, "sql"=>"order", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('action_id', 'trigger_id', 'order')); // Attributes to be displayed for a list
@@ -569,15 +360,8 @@ class lnkTriggerAction extends cmdbAbstractObject
}
}
/**
* Class TriggerOnThresholdReached
*/
class TriggerOnThresholdReached extends TriggerOnObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
@@ -595,14 +379,15 @@ class TriggerOnThresholdReached extends TriggerOnObject
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('stop_watch_code', array("allowed_values" => null, "class_field" => "target_class", "sql" => "stop_watch_code", "default_value" => null, "is_null_allowed" => false, "max_items" => 1, "min_items" => 1, "attribute_definition_exclusion_list" => null, "attribute_definition_list" => "AttributeStopWatch", "include_child_classes_attributes" => true, "depends_on" => array('target_class'))));
MetaModel::Init_AddAttribute(new AttributeString("threshold_index", array("allowed_values" => null, "sql" => "threshold_index", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeString("stop_watch_code", array("allowed_values"=>null, "sql"=>"stop_watch_code", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("threshold_index", array("allowed_values"=>null, "sql"=>"threshold_index", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('target_class', 'threshold_index', 'threshold_index')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
?>

View File

@@ -289,13 +289,13 @@ abstract class User extends cmdbAbstractObject
$oSet = $this->Get('profile_list');
if ($oSet->Count() == 0)
{
$this->m_aCheckIssues[] = Dict::S('Class:User/Error:AtLeastOneProfileIsNeeded');
$this->m_aCheckIssues[] = Dict::Format('Class:User/Error:AtLeastOneProfileIsNeeded');
}
}
// Only administrators can manage administrators
if (UserRights::IsAdministrator($this) && !UserRights::IsAdministrator())
{
$this->m_aCheckIssues[] = Dict::S('UI:Login:Error:AccessRestricted');
$this->m_aCheckIssues[] = Dict::Format('UI:Login:Error:AccessRestricted');
}
if (!UserRights::IsAdministrator())
@@ -304,37 +304,30 @@ abstract class User extends cmdbAbstractObject
$oAddon = UserRights::GetModuleInstance();
if (!is_null($oUser) && method_exists($oAddon, 'GetUserOrgs'))
{
if ((empty($this->GetOriginal('contactid')) && !($this->IsNew())) || empty($this->Get('contactid')))
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
if (count($aOrgs) > 0)
{
$this->m_aCheckIssues[] = Dict::S('Class:User/Error:PersonIsMandatory');
}
else
{
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
if (count($aOrgs) > 0)
// Check that the modified User belongs to one of our organization
if (!in_array($this->GetOriginal('org_id'), $aOrgs) && !in_array($this->Get('org_id'), $aOrgs))
{
// Check that the modified User belongs to one of our organization
if (!in_array($this->GetOriginal('org_id'), $aOrgs) && !in_array($this->Get('org_id'), $aOrgs))
$this->m_aCheckIssues[] = Dict::Format('Class:User/Error:UserOrganizationNotAllowed');
}
// Check users with restricted organizations when allowed organizations have changed
if ($this->IsNew() || array_key_exists('allowed_org_list', $aChanges))
{
$oSet = $this->get('allowed_org_list');
if ($oSet->Count() == 0)
{
$this->m_aCheckIssues[] = Dict::S('Class:User/Error:UserOrganizationNotAllowed');
$this->m_aCheckIssues[] = Dict::Format('Class:User/Error:AtLeastOneOrganizationIsNeeded');
}
// Check users with restricted organizations when allowed organizations have changed
if ($this->IsNew() || array_key_exists('allowed_org_list', $aChanges))
else
{
$oSet = $this->get('allowed_org_list');
if ($oSet->Count() == 0)
$aModifiedLinks = $oSet->ListModifiedLinks();
foreach($aModifiedLinks as $oLink)
{
$this->m_aCheckIssues[] = Dict::S('Class:User/Error:AtLeastOneOrganizationIsNeeded');
}
else
{
$aModifiedLinks = $oSet->ListModifiedLinks();
foreach ($aModifiedLinks as $oLink)
if (!in_array($oLink->Get('allowed_org_id'), $aOrgs))
{
if (!in_array($oLink->Get('allowed_org_id'), $aOrgs))
{
$this->m_aCheckIssues[] = Dict::S('Class:User/Error:OrganizationNotAllowed');
}
$this->m_aCheckIssues[] = Dict::Format('Class:User/Error:OrganizationNotAllowed');
}
}
}
@@ -1225,9 +1218,8 @@ class UserRights
}
/**
* @param string $sProfileName Profile name to search for
* @param User|null $oUser
*
* @param $sProfileName Profile name to search for
* @param $oUser User|null
* @return bool
*/
public static function HasProfile($sProfileName, $oUser = null)
@@ -1241,6 +1233,8 @@ class UserRights
* @param Bool Reset admin cache as well
* @return void
*/
// Reset cached data
//
public static function FlushPrivileges($bResetAdminCache = false)
{
if ($bResetAdminCache)
@@ -1261,16 +1255,12 @@ class UserRights
}
static $m_aCacheUsers;
/**
* Find a user based on its login and its type of authentication
*
* @param string $sLogin Login/identifier of the user
* @param string $sAuthentication Type of authentication used: internal|external|any
* @param bool $bAllowDisabledUsers Whether or not to retrieve disabled users (status != enabled)
*
* @return User The found user or null
* @throws \OQLException
*/
protected static function FindUser($sLogin, $sAuthentication = 'any', $bAllowDisabledUsers = false)
{
@@ -1331,24 +1321,6 @@ class UserRights
{
$_SESSION['profile_list'] = self::ListProfiles();
}
$oConfig = MetaModel::GetConfig();
$bSessionIdRegeneration = $oConfig->Get('regenerate_session_id_enabled');
if ($bSessionIdRegeneration)
{
// Protection against session fixation/injection: generate a new session id.
// Alas a PHP bug (technically a bug in the memcache session handler, https://bugs.php.net/bug.php?id=71187)
// causes session_regenerate_id to fail with a catchable fatal error in PHP 7.0 if the session handler is memcache(d).
// The bug has been fixed in PHP 7.2, but in case session_regenerate_id()
// fails we just silently ignore the error and keep the same session id...
$old_error_handler = set_error_handler(array(__CLASS__, 'VoidErrorHandler'));
session_regenerate_id();
if ($old_error_handler !== null)
{
set_error_handler($old_error_handler);
}
}
}
public static function _ResetSessionCache()
@@ -1362,19 +1334,6 @@ class UserRights
unset($_SESSION['archive_allowed']);
}
}
/**
* Fake error handler to silently discard fatal errors
* @param int $iErrNo
* @param string $sErrStr
* @param string $sErrFile
* @param int $iErrLine
* @return boolean
*/
public static function VoidErrorHandler($iErrno, $sErrStr, $sErrFile, $iErrLine)
{
return true; // Ignore the error
}
}
/**

View File

@@ -1,5 +1,5 @@
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
$version: "v2.6.0";
$version: "v2.5.4";
// Base colors
$gray-base: #000 !default;
@@ -29,12 +29,13 @@ $frame-background-color: $gray-extra-light;
$text-color: #000;
$box-radius: 0px;
$box-shadow-regular: 0 1px 1px rgba(0, 0, 0, 0.15);
$hyperlink-color: $complement-color;
$hyperlink-text-decoration: none;
////////////
// Search //
// - Boxes
//$search-criteria-box-color: #2D2D2D;
//$search-criteria-box-bg-color: #f0f3f5;
//$search-criteria-box-border-color: #3f7294;
//$search-criteria-box-border: 1px solid $search-criteria-box-border-color;
//$search-criteria-box-radius: 1px;
//
$search-criteria-box-color: #2D2D2D;
$search-criteria-box-picto-color: #E87C1E;
$search-criteria-box-bg-color: #EEEEEE;

115
css/fg.menu.css Executable file
View File

@@ -0,0 +1,115 @@
/* Styles for jQuery menu widget
Author: Maggie Wachs, maggie@filamentgroup.com
Date: September 2008
*/
/* REQUIRED STYLES - the menus will only render correctly with these rules */
.positionHelper { z-index: 2999; }
.fg-menu-container { position: absolute; top:0; left:-999px; padding: .4em; overflow: hidden; }
.fg-menu-container.fg-menu-flyout { overflow: visible; }
.fg-menu, .fg-menu ul { list-style-type:none; padding: 0; margin:0; }
.fg-menu { position:relative; }
.fg-menu-flyout .fg-menu { position:static; }
.fg-menu ul { position:absolute; top:0; }
.fg-menu ul ul { top:-1px; }
.fg-menu-container.fg-menu-ipod .fg-menu-content,
.fg-menu-container.fg-menu-ipod .fg-menu-content ul { background: none !important; }
.fg-menu.fg-menu-scroll,
.fg-menu ul.fg-menu-scroll { overflow: scroll; overflow-x: hidden; }
.fg-menu li { clear:both; float:left; width:100%; margin: 0; padding:0; border: 0; }
.fg-menu li li { font-size:1em; } /* inner li font size must be reset so that they don't blow up */
.fg-menu-flyout ul ul { padding: .4em; }
.fg-menu-flyout li { position:relative; }
.fg-menu-scroll { overflow: scroll; overflow-x: hidden; }
.fg-menu-breadcrumb { margin: 0; padding: 0; }
.fg-menu-footer { margin-top: .4em; padding: .4em; }
.fg-menu-header { margin-bottom: .4em; padding: .4em; }
.fg-menu-breadcrumb li { float: left; list-style: none; margin: 0; padding: 0 .2em; font-size: .9em; opacity: .7; }
.fg-menu-breadcrumb li.fg-menu-prev-list,
.fg-menu-breadcrumb li.fg-menu-current-crumb { clear: left; float: none; opacity: 1; }
.fg-menu-breadcrumb li.fg-menu-current-crumb { padding-top: .2em; }
.fg-menu-breadcrumb a,
.fg-menu-breadcrumb span { float: left; }
.fg-menu-footer a:link,
.fg-menu-footer a:visited { float:left; width:100%; text-decoration: none; }
.fg-menu-footer a:hover,
.fg-menu-footer a:active { }
.fg-menu-footer a span { float:left; cursor: pointer; }
.fg-menu-breadcrumb .fg-menu-prev-list a:link,
.fg-menu-breadcrumb .fg-menu-prev-list a:visited,
.fg-menu-breadcrumb .fg-menu-prev-list a:hover,
.fg-menu-breadcrumb .fg-menu-prev-list a:active { background-image: none; text-decoration:none; }
.fg-menu-breadcrumb .fg-menu-prev-list a { float: left; padding-right: .4em; }
.fg-menu-breadcrumb .fg-menu-prev-list a .ui-icon { float: left; }
.fg-menu-breadcrumb .fg-menu-current-crumb a:link,
.fg-menu-breadcrumb .fg-menu-current-crumb a:visited,
.fg-menu-breadcrumb .fg-menu-current-crumb a:hover,
.fg-menu-breadcrumb .fg-menu-current-crumb a:active { display:block; background-image:none; font-size:1.3em; text-decoration:none; }
/* REQUIRED LINK STYLES: links are "display:block" by default; if the menu options are split into
selectable node links and 'next' links, the script floats the node links left and floats the 'next' links to the right */
.fg-menu a:link,
.fg-menu a:visited,
.fg-menu a:hover,
.fg-menu a:active { float:left; width:92%; padding:.3em 3%; text-decoration:none; outline: 0 !important; }
.fg-menu a { border: 1px dashed transparent; }
.fg-menu a.ui-state-default:link,
.fg-menu a.ui-state-default:visited,
.fg-menu a.ui-state-default:hover,
.fg-menu a.ui-state-default:active,
.fg-menu a.ui-state-hover:link,
.fg-menu a.ui-state-hover:visited,
.fg-menu a.ui-state-hover:hover,
.fg-menu a.ui-state-hover:active,
.fg-menu a.ui-state-active:link,
.fg-menu a.ui-state-active:visited,
.fg-menu a.ui-state-active:hover,
.fg-menu a.ui-state-active:active { border-style: solid; font-weight: normal; }
.fg-menu a span { display:block; cursor:pointer; }
/* SUGGESTED STYLES - for use with jQuery UI Themeroller CSS */
.fg-menu-indicator span { float:left; }
.fg-menu-indicator span.ui-icon { float:right; }
.fg-menu-content.ui-widget-content,
.fg-menu-content ul.ui-widget-content { border:0; }
/* ICONS AND DIVIDERS */
.fg-menu.fg-menu-has-icons a:link,
.fg-menu.fg-menu-has-icons a:visited,
.fg-menu.fg-menu-has-icons a:hover,
.fg-menu.fg-menu-has-icons a:active { padding-left:20px; }
.fg-menu .horizontal-divider hr, .fg-menu .horizontal-divider span { padding:0; margin:5px .6em; }
.fg-menu .horizontal-divider hr { border:0; height:1px; }
.fg-menu .horizontal-divider span { font-size:.9em; text-transform: uppercase; padding-left:.2em; }

View File

@@ -92,22 +92,6 @@ table.listResults td .view-image img {
margin-left: auto;
margin-right: auto;
}
table.listResults > tbody > tr > * {
transition: background-color 400ms linear;
}
table.listResults > tbody > tr:hover > * {
cursor: pointer;
}
table.listResults > tbody > tr.selected:hover > * {
/* hover on lines is currently done toggling td.hover, and having a rule for links */
background-color: #f3b37b;
color: #000;
}
table.listResults > tbody > tr:hover > * {
/* hover on lines is currently done toggling td.hover, and having a rule for links */
background-color: #fdf5d0;
color: #000;
}
.edit-image .view-image {
display: inline-block;
}
@@ -155,7 +139,6 @@ table.listResults > tbody > tr:hover > * {
vertical-align: middle;
max-width: 90% !important;
max-height: 90% !important;
cursor: zoom-in;
}
.details .view-image .helper-middle {
display: inline-block;
@@ -196,6 +179,7 @@ tr.green td, .wizContainer tr.green td {
background-color: #b3e5b4;
}
tr td.hover, tr.even td.hover, .hover a, .hover a:visited, .hover a:hover, .wizContainer tr.even td.hover, .wizContainer tr td.hover {
background-color: #fdf5d0;
color: #000;
}
th {
@@ -343,10 +327,10 @@ a.small_action {
padding-left: 5px;
padding-top: 2px;
padding-bottom: 2px;
background: #ea7d1e url(../images/actions_left.png?v=v2.6.0) no-repeat left;
background: #ea7d1e url(../images/actions_left.png?v=v2.5.4) no-repeat left;
}
.actions_details span {
background: url(../images/actions_right.png?v=v2.6.0) no-repeat right;
background: url(../images/actions_right.png?v=v2.5.4) no-repeat right;
color: #fff;
font-weight: bold;
padding-top: 2px;
@@ -406,7 +390,7 @@ input.textSearch {
}
.ui-accordion-content ul {
list-style: none;
list-style-image: none;
list-style-image: url(data:0);
padding-left: 16px;
margin-top: 8px;
}
@@ -417,7 +401,7 @@ input.textSearch {
padding: 8px 0px 8px 8px;
margin: 0;
list-style: none;
list-style-image: none;
list-style-image: url(data:0);
border: 0;
}
.nothing {
@@ -520,7 +504,7 @@ div.actions_menu > ul {
nowidth: 70px;
padding-left: 5px;
/* Nasty work-around for IE... en attendant mieux */
background: #ea7d1e url(../images/actions_left.png?v=v2.6.0) no-repeat top left;
background: #ea7d1e url(../images/actions_left.png?v=v2.5.4) no-repeat top left;
cursor: pointer;
margin: 0;
}
@@ -532,7 +516,7 @@ div.actions_menu > ul > li {
height: 17px;
padding-right: 16px;
padding-left: 4px;
background: url(../images/actions_right.png?v=v2.6.0) no-repeat top right transparent;
background: url(../images/actions_right.png?v=v2.5.4) no-repeat top right transparent;
font-weight: bold;
color: #fff;
vertical-align: middle;
@@ -553,9 +537,6 @@ div.actions_menu > ul > li {
padding: 0;
height: 25px;
}
.itop_popup > ul > li > ul, #logOffBtn > ul > li > ul {
box-shadow: 3px 3px 5px 0px rgba(0, 0, 0, 0.5);
}
.itop_popup li a, #logOffBtn li a {
display: block;
padding: 5px 12px;
@@ -678,7 +659,7 @@ td a.dp-choose-date, a.dp-choose-date, td a.dp-choose-date:hover, a.dp-choose-da
display: block;
text-indent: -2000px;
overflow: hidden;
background: url(../images/calendar.png?v=v2.6.0) no-repeat;
background: url(../images/calendar.png?v=v2.5.4) no-repeat;
}
td a.dp-choose-date.dp-disabled, a.dp-choose-date.dp-disabled {
background-position: 0 -20px;
@@ -890,9 +871,6 @@ input.dp-applied {
left: 0px;
margin-top: -1px;
}
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_buttons, .search_form_handler .sf_criterion_area .sf_more_criterion .sfc_form_group .sfc_fg_buttons, .search_form_handler .sf_criterion_area .sf_button .sfc_form_group .sfc_fg_buttons, .search_form_handler .sf_criterion_area .search_form_criteria .sfm_content .sfc_fg_buttons, .search_form_handler .sf_criterion_area .sf_more_criterion .sfm_content .sfc_fg_buttons, .search_form_handler .sf_criterion_area .sf_button .sfm_content .sfc_fg_buttons {
white-space: nowrap;
}
.search_form_handler .sf_criterion_area .search_form_criteria {
/* Non editable criteria */
/* Draft criteria (modifications not applied) */
@@ -1137,15 +1115,6 @@ input.dp-applied {
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_enum .sfc_form_group .sfc_fg_operator_in > label .sfc_op_content {
width: 100%;
}
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_tag_set .sfc_form_group .sfc_fg_operator_in > label {
display: inline-block;
width: 100%;
line-height: initial;
white-space: nowrap;
}
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_tag_set .sfc_form_group .sfc_fg_operator_in > label .sfc_op_content {
width: 100%;
}
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_numeric .sfc_fg_operators .sfc_fg_operator.sfc_fg_operator_between .sfc_op_content_from_outer {
display: inline;
}
@@ -1332,19 +1301,19 @@ input.dp-applied {
}
/* 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 {
background: url(../images/truncated.png?v=v2.6.0) bottom repeat-x;
background: url(../images/truncated.png?v=v2.5.4) bottom repeat-x;
}
/* 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 {
background: #f9f9f1 url(../images/truncated.png?v=v2.6.0) bottom repeat-x;
background: #f9f9f1 url(../images/truncated.png?v=v2.5.4) bottom repeat-x;
}
/* 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 {
background: #fdf5d0 url(../images/truncated.png?v=v2.6.0) bottom repeat-x;
background: #fdf5d0 url(../images/truncated.png?v=v2.5.4) bottom repeat-x;
}
/* 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 {
background: #fdf5d0 url(../images/truncated.png?v=v2.6.0) bottom repeat-x;
background: #fdf5d0 url(../images/truncated.png?v=v2.5.4) bottom repeat-x;
}
table.listResults.truncated {
border-bottom: 0;
@@ -1452,7 +1421,7 @@ div#logo {
div#logo div {
height: 88px;
width: 244px;
background: url(../images/itop-logo-2.png?v=v2.6.0) left no-repeat;
background: url(../images/itop-logo-2.png?v=v2.5.4) left no-repeat;
}
#left-pane .ui-layout-north {
overflow: hidden;
@@ -1544,7 +1513,7 @@ div#logo div {
}
#global-search-image {
vertical-align: middle;
background: url(../images/search.png?v=v2.6.0) center center no-repeat;
background: url(../images/search.png?v=v2.5.4) center center no-repeat;
display: inline-block;
width: 28px;
height: 30px;
@@ -1573,7 +1542,7 @@ span.ui-icon {
margin: 0 2px;
}
.ui-layout-button-pin-down {
background: url(../images/splitter-bkg.png?v=v2.6.0) transparent;
background: url(../images/splitter-bkg.png?v=v2.5.4) transparent;
width: 16px;
background-position: -144px -144px;
}
@@ -1949,22 +1918,6 @@ fieldset .details > .field_container {
.field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn > img {
max-width: 20px;
}
.field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_set .selectize-control {
width: 100%;
}
.field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_set .selectize-control .selectize-dropdown, .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_set .selectize-control .selectize-input, .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_set .selectize-control .selectize-input input {
font-size: 12px;
}
.field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_set .selectize-control .selectize-input {
padding: 2px 2px 0px 2px;
/* padding-bottom = padding-top - item margin-bottom */
border: 1px solid #ababab;
border-radius: 0;
}
.field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_set .selectize-control .selectize-input .attribute-set-item.partial-code {
color: rgba(34, 34, 34, 0.6);
background-color: #eaeaea;
}
.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 */
}
@@ -2089,7 +2042,7 @@ img.prev, img.first, img.next, img.last {
}
div.actions_button {
float: right;
background: #ea7d1e url("../images/actions_left.png?v=v2.6.0") no-repeat scroll left top;
background: #ea7d1e url("../images/actions_left.png?v=v2.5.4") no-repeat scroll left top;
padding-left: 5px;
margin-top: 0;
margin-right: 10px;
@@ -2097,7 +2050,7 @@ div.actions_button {
vertical-align: middle;
}
div.actions_button a, .actions_button a:hover, .actions_button a:visited {
background: #ea7d1e url(../images/actions_bkg.png?v=v2.6.0) no-repeat scroll right top;
background: #ea7d1e url(../images/actions_bkg.png?v=v2.5.4) no-repeat scroll right top;
color: #fff;
padding-right: 8px;
cursor: pointer;
@@ -2121,10 +2074,10 @@ select#org_id {
cursor: not-allowed;
}
.dragHover {
background: url(./ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=v2.6.0);
background: url(./ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=v2.5.4);
}
.edit_mode .dashlet {
background: url(./ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=v2.6.0);
background: url(./ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=v2.5.4);
padding: 5px;
margin: 0;
position: relative;
@@ -2134,17 +2087,6 @@ select#org_id {
padding: 5px;
margin: 0;
}
/* Prevent cursor clicking on the calendar (eg. While editing dashlet) */
.dashlet-blocker {
position: absolute;
z-index: 9;
/* To be above calendar links & all, but below .close-box (9) */
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: not-allowed;
}
td.layout_cell {
height: 50px;
/* min-height does not work */
@@ -2169,7 +2111,7 @@ table.prop_table {
top: 0;
right: 0;
z-index: 10;
background: transparent url(../images/delete.png?v=v2.6.0) no-repeat center;
background: transparent url(../images/delete.png?v=v2.5.4) no-repeat center;
}
td.prop_value {
text-align: left;
@@ -2257,35 +2199,6 @@ a.summary, a.summary:hover {
padding: 5px;
text-align: center;
}
.dashboard-title {
display: block;
float: left;
color: #000;
font-weight: bold;
font-size: 1.2em;
margin: 10px;
}
.dashboard_contents {
width: 100%;
background-color: #fff;
}
.dashboard-selector {
display: block;
float: right;
margin-top: 10px;
}
.dashboard-selector .selector-label {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
vertical-align: super;
}
#DashboardMenu {
display: block;
float: right;
font-size: 12px;
margin: 10px;
}
#DashboardMenu > ul > li {
list-style: none;
vertical-align: middle;
@@ -2388,19 +2301,29 @@ a.summary, a.summary:hover {
border-radius: 4px;
margin-bottom: 10px;
}
.header_message {
padding: 1em;
font-size: 10pt;
background: #fff;
border: 1px solid #999;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
margin-bottom: 10px;
}
.message_info {
border: 1px solid #993;
background: url(../images/info-mini.png?v=v2.6.0) 1em 1em no-repeat #ffc;
background: url(../images/info-mini.png?v=v2.5.4) 1em 1em no-repeat #ffc;
padding-left: 3em;
}
.message_ok {
border: 1px solid #393;
background: url(../images/ok.png?v=v2.6.0) 1em 1em no-repeat #cfc;
background: url(../images/ok.png?v=v2.5.4) 1em 1em no-repeat #cfc;
padding-left: 3em;
}
.message_error {
border: 1px solid #933;
background: url(../images/error.png?v=v2.6.0) 1em 1em no-repeat #fcc;
background: url(../images/error.png?v=v2.5.4) 1em 1em no-repeat #fcc;
padding-left: 3em;
}
.fg-menu a img {
@@ -2531,18 +2454,18 @@ div.explain-printable {
}
#hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter span {
padding-left: 20px;
background: url(../images/eye-open-555.png?v=v2.6.0) 2px center no-repeat;
background: url(../images/eye-open-555.png?v=v2.5.4) 2px center no-repeat;
}
#hiddeable_chapters .ui-tabs .ui-tabs-nav li.hideable-chapter.strikethrough span {
text-decoration: line-through;
background: url(../images/eye-closed-555.png?v=v2.6.0) 2px center no-repeat;
background: url(../images/eye-closed-555.png?v=v2.5.4) 2px center no-repeat;
}
.printable-version legend {
padding-left: 26px;
background: #1c94c4 url(../images/eye-open-fff.png?v=v2.6.0) 8px center no-repeat;
background: #1c94c4 url(../images/eye-open-fff.png?v=v2.5.4) 8px center no-repeat;
}
.printable-version .strikethrough legend {
background: #1c94c4 url(../images/eye-closed-fff.png?v=v2.6.0) 8px center no-repeat;
background: #1c94c4 url(../images/eye-closed-fff.png?v=v2.5.4) 8px center no-repeat;
}
.printable-version fieldset.strikethrough span {
display: none;
@@ -2665,6 +2588,7 @@ span.search-button, span.refresh-button {
margin-right: 5px;
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
filter: gray;
opacity: 0.5;
}
#itop-breadcrumb .breadcrumb-item a {
@@ -2693,7 +2617,7 @@ span.search-button, span.refresh-button {
#itop-breadcrumb .breadcrumb-item a::after {
content: '';
position: absolute;
background-image: url(../images/breadcrumb-separator.png?v=v2.6.0);
background-image: url(../images/breadcrumb-separator.png?v=v2.5.4);
background-repeat: no-repeat;
width: 8px;
height: 16px;
@@ -2917,271 +2841,3 @@ table.listResults .originColor {
#ds_flash {
margin-bottom: 5px;
}
.menu-icon-select {
max-height: 300px;
position: absolute;
z-index: 201;
overflow-x: hidden;
overflow-y: auto;
}
.menu-icon-select > .ui-menu-item {
padding: 0.3em 3%;
}
.attribute.attribute-set .attribute-set-item::after {
content: ",";
margin-right: 0.5em;
}
.attribute.attribute-set .attribute-set-item:last-of-type::after {
content: "";
margin-right: 0;
}
.attribute.attribute-set.history-added .attribute-set-item {
font-weight: bold;
}
.attribute.attribute-set.history-removed .attribute-set-item {
text-decoration: line-through;
font-style: italic;
}
.attribute-edit .attribute-set .attribute-set-item, .attribute-tag-set.attribute-set .attribute-set-item, .selectize-control > .selectize-input > .item[data-value], .selectize-control.multi > .selectize-input > .item[data-value], .selectize-control > .selectize-input > .item[data-value].active, .selectize-control.multi > .selectize-input > .item[data-value].active {
display: inline-block;
margin-right: 3px;
margin-bottom: 3px;
padding: 4px 6px;
max-width: 120px;
background: #fdfdfd none;
border-radius: 2px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15), 0 0 1px 1px #f1f1f1;
color: #222;
text-shadow: none;
vertical-align: middle;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.attribute-edit .attribute-set .attribute-set-item::after, .attribute-tag-set.attribute-set .attribute-set-item::after, .selectize-control > .selectize-input > .item[data-value]::after, .selectize-control.multi > .selectize-input > .item[data-value]::after, .selectize-control > .selectize-input > .item[data-value].active::after, .selectize-control.multi > .selectize-input > .item[data-value].active::after {
content: "";
margin-right: 0;
}
.selectize-control > .selectize-input.has-items:after, .selectize-control.multi > .selectize-input.has-items:after {
content: "+";
display: inline-block;
font-size: 17px;
font-weight: bold;
color: #222;
}
.selectize-control > .selectize-input > .item[data-value], .selectize-control.multi > .selectize-input > .item[data-value] {
padding-right: 1.5em !important;
border: 1px solid #ddd;
}
.selectize-control > .selectize-input > .item[data-value] > .remove, .selectize-control.multi > .selectize-input > .item[data-value] > .remove {
padding-top: 0.3em;
border: none;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 36px;
height: 20px;
vertical-align: baseline;
}
/* Hide default HTML checkbox */
.switch input {
display: none;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 15px;
width: 15px;
left: 3px;
bottom: 3px;
background-color: white;
transition: 0.4s;
}
input:checked + .slider {
background-color: #ea7d1e;
}
input:focus + .slider {
box-shadow: 0 0 1px #ea7d1e;
}
input:checked + .slider:before {
transform: translateX(14.5px);
}
/* Rounded sliders */
.slider.round {
border-radius: 20px;
}
.slider.round:before {
border-radius: 7px;
}
#newsroom_menu li span {
display: block;
padding: 5px 12px;
text-decoration: none;
white-space: nowrap;
}
#newsroom_menu li li p {
text-align: left;
margin: 2px;
margin-left: 5px;
margin-right: 5px;
cursor: pointer;
background-color: transparent;
}
#newsroom_menu > ul > li > ul {
margin-top: 8px;
}
#newsroom_menu > ul > li > ul > li {
display: block;
border-bottom: 1px #ddd solid;
padding-top: 10px;
padding-bottom: 10px;
text-align: left;
}
#newsroom_menu > ul > li > ul > li:hover, #newsroom_menu > ul > li > ul > li:hover h1, #newsroom_menu > ul > li > ul > li:hover h2, #newsroom_menu > ul > li > ul > li:hover h3 {
background: #ea7d1e;
color: #fff;
}
#newsroom_menu li li:last-of-type {
border-bottom: 0;
}
#newsroom_menu li {
list-style: none;
cursor: pointer;
color: #000;
}
#newsroom_menu li ul {
width: 300px;
}
#top-left-newsroom-cell {
padding-right: 11px !important;
}
#newsroom_menu_icon {
position: relative;
top: 8px;
}
#newsroom_menu_counter_container {
position: relative;
top: -26px;
left: 4px;
}
#newsroom_menu_counter {
display: inline-block;
padding: 2px;
border-radius: 8px;
text-align: center;
width: 12px;
box-shadow: 1px 1px 2px 0px #777;
font-size: 8pt;
background-color: #1c94c4;
color: #fff;
cursor: pointer;
}
.newsroom_extra_messages_counter {
display: inline-block !important;
padding: 2px !important;
border-radius: 8px;
text-align: center;
font-size: 8pt;
min-width: 12px;
background-color: #808080;
color: #fff;
float: right;
margin-right: 5px;
}
.newsroom_menu_item > div > img {
float: left;
width: 32px;
max-height: 32px;
margin-top: 0;
margin-bottom: 0;
margin-left: 5px;
margin-right: 5px;
}
#newsroom_menu_dismiss_all, #newsroom_menu_show_all {
text-align: center !important;
}
#newsroom_show_all_submenu {
text-align: center;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
#newsroom_show_all_submenu > ul {
padding-top: 10px;
padding-bottom: 10px;
}
#newsroom_show_all_submenu > ul > li > ul {
margin-top: 8px;
}
#newsroom_show_all_submenu > ul > li > ul > li {
display: block;
border-bottom: 1px #ddd solid;
padding-left: 5px;
padding-top: 4px;
padding-bottom: 6px;
text-align: left;
}
#newsroom_show_all_submenu > ul > li > ul > li:hover {
background: #ea7d1e;
color: #fff;
}
#newsroom_show_all_submenu li ul {
width: 200px;
color: #000;
}
.no-padding {
padding: 0 !important;
}
.newsroom_menu_item_date {
padding: 0 !important;
margin-bottom: -10px;
font-size: 8pt;
text-align: right;
margin-top: -2px;
margin-right: 5px;
color: #fff;
}
#newsroom_display_size {
height: 1em;
width: 3em;
}
#newsroom_no_new_message p {
text-align: center !important;
cursor: default !important;
font-style: italic;
}
#newsroom_no_new_message {
color: #444 !important;
}
#newsroom_no_new_message:hover {
cursor: default !important;
color: #444 !important;
background-color: #fff !important;
}
#newsroom_menu h1 {
font-weight: 700;
font-size: 16px;
margin-bottom: 0.5em;
}
#newsroom_menu h2 {
font-weight: 700;
font-size: 14px;
margin-bottom: 0.5em;
}
#newsroom_menu h3, #newsroom_menu h4, #newsroom_menu h5 {
font-weight: 700;
font-size: 12px;
margin-bottom: 0.5em;
}

View File

@@ -116,29 +116,6 @@ table.listResults td .view-image {
}
}
table.listResults > tbody > tr.selected > * {
}
table.listResults > tbody > tr > * {
transition: background-color 400ms linear;
}
table.listResults > tbody > tr:hover > * {
cursor: pointer;
}
table.listResults > tbody > tr.selected:hover > * {
/* hover on lines is currently done toggling td.hover, and having a rule for links */
background-color: lighten($combodo-orange, 20%);
color: $text-color;
}
table.listResults > tbody > tr:hover > * {
/* hover on lines is currently done toggling td.hover, and having a rule for links */
background-color: #fdf5d0;
color: $text-color;
}
.edit-image {
.view-image {
display: inline-block;
@@ -202,7 +179,6 @@ table.listResults > tbody > tr:hover > * {
vertical-align: middle;
max-width: 90% !important;
max-height: 90% !important;
cursor: zoom-in;
}
.helper-middle {
// Helper to center the image (requires a span dedicated to this)
@@ -249,7 +225,7 @@ tr.green td, .wizContainer tr.green td {
}
tr td.hover, tr.even td.hover, .hover a, .hover a:visited, .hover a:hover, .wizContainer tr.even td.hover, .wizContainer tr td.hover {
//background-color: #fdf5d0;
background-color: #fdf5d0;
color: $text-color;
}
@@ -481,7 +457,7 @@ input.textSearch {
.ui-accordion-content ul {
list-style:none;
list-style-image: none;
list-style-image: url(data:0);
padding-left:16px;
margin-top: 8px;
}
@@ -494,7 +470,7 @@ input.textSearch {
padding: 8px 0px 8px 8px;
margin:0;
list-style:none;
list-style-image: none;
list-style-image: url(data:0);
border: 0;
}
@@ -629,9 +605,7 @@ div.actions_menu > ul > li {
padding: 0;
height: 25px;
}
.itop_popup > ul > li > ul, #logOffBtn > ul > li > ul {
box-shadow: 3px 3px 5px 0px rgba(0,0,0,0.5);
}
.itop_popup li a, #logOffBtn li a {
display: block;
padding: 5px 12px;
@@ -1000,10 +974,6 @@ input.dp-applied {
min-width: 100%;
left: 0px;
margin-top: -1px;
.sfc_fg_buttons{
white-space: nowrap;
}
}
}
@@ -1318,22 +1288,6 @@ input.dp-applied {
}
}
}
&.search_form_criteria_tag_set{
.sfc_form_group{
.sfc_fg_operator_in{
> label{
display: inline-block;
width: 100%;
line-height: initial;
white-space: nowrap;
.sfc_op_content{
width: 100%;
}
}
}
}
}
&.search_form_criteria_numeric {
//.sfc_form_group.advanced {
// .sfc_fg_operator_between {
@@ -2268,28 +2222,6 @@ fieldset .details>.field_container {
}
}
}
&.field_input_set{
.selectize-control{
width: 100%;
.selectize-dropdown,
.selectize-input,
.selectize-input input{
font-size: 12px;
}
.selectize-input{
padding: 2px 2px 0px 2px; /* padding-bottom = padding-top - item margin-bottom */
border: 1px solid #ABABAB;
border-radius: 0;
.attribute-set-item.partial-code{
color: transparentize($gray-darker, 0.4);
background-color: lighten($gray-lighter, 5%);
}
}
}
}
}
}
}
@@ -2478,16 +2410,6 @@ select#org_id {
padding: 5px;
margin:0;
}
/* Prevent cursor clicking on the calendar (eg. While editing dashlet) */
.dashlet-blocker {
position: absolute;
z-index: 9; /* To be above calendar links & all, but below .close-box (9) */
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: not-allowed;
}
td.layout_cell {
height: 50px; /* min-height does not work */
vertical-align: top;
@@ -2604,48 +2526,6 @@ a.summary, a.summary:hover {
text-align: center;
}
.dashboard-title-line {
}
.dashboard-title {
display: block;
float: left;
color: $text-color;
font-weight: bold;
font-size: 1.2em;
margin: 10px;
}
.dashboard_contents {
width: 100%;
background-color: $white;
}
.dashboard-selector {
display: block;
float: right;
margin-top: 10px;
.selector-label {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
vertical-align: super;
}
}
#DashboardMenu {
display: block;
float: right;
font-size: 12px;
margin: 10px;
}
#DashboardMenu > ul > li {
list-style: none;
vertical-align: middle;
@@ -2752,6 +2632,16 @@ a.summary, a.summary:hover {
border-radius: 4px;
margin-bottom: 10px;
}
.header_message {
padding: 1em;
font-size: 10pt;
background: #fff;
border: 1px solid #999;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
margin-bottom: 10px;
}
.message_info {
border: 1px solid #993;
background: url(../images/info-mini.png?v=#{$version}) 1em 1em no-repeat #ffc;
@@ -3044,6 +2934,7 @@ span.search-button, span.refresh-button {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
filter: gray;
// IE has no filter option: at least, have some effect when hovering...
opacity: 0.5;
@@ -3340,334 +3231,4 @@ table.listResults .originColor{
//Impact analysis filter
#ds_flash{
margin-bottom: 5px;
}
/////////
// Icon select
.menu-icon-select{
max-height : 300px;
position : absolute;
z-index : 201;
overflow-x : hidden;
overflow-y : auto;
}
.menu-icon-select > .ui-menu-item{
padding: .3em 3%;
}
//////////////////////
// Set attribute //
// - Readonly (object viewing, objects list)
.attribute {
&.attribute-set {
.attribute-set-item{
&::after{
content: ",";
margin-right: 0.5em;
}
&:last-of-type::after{
content: "";
margin-right: 0;
}
}
&.history-added {
.attribute-set-item {
font-weight: bold;
}
}
&.history-removed {
.attribute-set-item {
text-decoration: line-through;
font-style: italic;
}
}
}
}
// - Edit is always styled like the selectize items, see below.
%attribute-set-item-edition{
display: inline-block;
margin-right: 3px;
margin-bottom: 3px;
padding: 4px 6px;
max-width: 120px;
background: #fdfdfd none;
border-radius: 2px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15), 0 0 1px 1px rgb(241, 241, 241, 0.7);
color: $gray-darker;
text-shadow: none;
vertical-align: middle;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&::after{
content: "";
margin-right: 0;
}
}
.attribute-edit .attribute-set .attribute-set-item{
@extend %attribute-set-item-edition;
}
//////////////////////
// TagSet attribute //
// Always styled like the selectize items, see below.
.attribute-tag-set.attribute-set{
.attribute-set-item{
@extend %attribute-set-item-edition;
}
}
//////////////////////
// Selectize widget //
//
.selectize-control,
.selectize-control.multi{
> .selectize-input{
&.has-items:after {
content: "+";
display: inline-block;
font-size: 17px;
font-weight: bold;
color: $gray-darker;
}
> .item[data-value]{
@extend %attribute-set-item-edition;
padding-right: 1.5em !important;
border: 1px solid $gray-lighter;
&.active{
@extend %attribute-set-item-edition;
}
> .remove {
padding-top: 0.3em;
border: none;
}
}
}
}
// Round Toggle
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 36px;
height: 20px;
vertical-align: baseline;
}
/* Hide default HTML checkbox */
.switch input {display:none;}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 15px;
width: 15px;
left: 3px;
bottom: 3px;
background-color: white;
transition: .4s;
}
input:checked + .slider {
background-color: $combodo-orange;
}
input:focus + .slider {
box-shadow: 0 0 1px $combodo-orange;
}
input:checked + .slider:before {
transform: translateX(14.5px);
}
/* Rounded sliders */
.slider.round {
border-radius: 20px;
}
.slider.round:before {
border-radius: 7px;
}
///////////////////////////
// Newsroom menu
#newsroom_menu li span {
display: block;
padding: 5px 12px;
text-decoration: none;
white-space: nowrap;
}
#newsroom_menu li li p {
text-align: left;
margin: 2px;
margin-left: 5px;
margin-right: 5px;
cursor: pointer;
background-color: transparent;
}
#newsroom_menu > ul > li > ul {
margin-top: 8px;
}
#newsroom_menu > ul > li > ul > li {
display: block;
border-bottom: 1px #ddd solid;
padding-top: 10px;
padding-bottom: 10px;
text-align: left;
}
#newsroom_menu > ul > li > ul > li:hover, #newsroom_menu > ul > li > ul > li:hover h1, #newsroom_menu > ul > li > ul > li:hover h2, #newsroom_menu > ul > li > ul > li:hover h3 {
background: $popup-menu-highlight-color;
color: $popup-menu-text-higlight-color;
}
#newsroom_menu li li:last-of-type {
border-bottom: 0;
}
#newsroom_menu li {
list-style: none;
cursor: pointer;
color: $popup-menu-text-color;
}
#newsroom_menu li ul {
width: 300px;
}
#top-left-newsroom-cell {
padding-right: 11px !important;
}
#newsroom_menu_icon {
position:relative;
top:8px;
}
#newsroom_menu_counter_container {
position:relative;
top:-26px;
left:4px;
}
#newsroom_menu_counter {
display:inline-block;
padding:2px;
border-radius:8px;
text-align:center;
width: 12px;
box-shadow: 1px 1px 2px 0px $gray;
font-size: 8pt;
background-color:$complement-color;
color: $white;
cursor: pointer;
}
.newsroom_extra_messages_counter {
display:inline-block !important;
padding:2px !important;
border-radius:8px;
text-align:center;
font-size: 8pt;
min-width: 12px;
background-color:$gray-light;
color: $white;
float: right;
margin-right: 5px;
}
.newsroom_menu_item > div > img {
float:left;
width:32px;
max-height:32px;
margin-top: 0;
margin-bottom: 0;
margin-left:5px;
margin-right: 5px;
}
#newsroom_menu_dismiss_all, #newsroom_menu_show_all {
text-align: center !important;
}
#newsroom_show_all_submenu {
text-align: center;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
#newsroom_show_all_submenu > ul {
padding-top: 10px;
padding-bottom: 10px;
}
#newsroom_show_all_submenu > ul > li > ul {
margin-top: 8px;
}
#newsroom_show_all_submenu > ul > li > ul > li {
display: block;
border-bottom: 1px #ddd solid;
padding-left: 5px;
padding-top: 4px;
padding-bottom: 6px;
text-align: left;
}
#newsroom_show_all_submenu > ul > li > ul > li:hover {
background: $popup-menu-highlight-color;
color: $popup-menu-text-higlight-color;
}
#newsroom_show_all_submenu li ul {
width: 200px;
color:#000;
}
.no-padding {
padding: 0 !important;
}
.newsroom_menu_item_date {
padding: 0 !important;
margin-bottom: -10px;
font-size: 8pt;
text-align: right;
margin-top: -2px;
margin-right: 5px;
color: $white;
}
#newsroom_display_size {
height: 1em;
width: 3em;
}
#newsroom_no_new_message p {
text-align: center !important;
cursor: default !important;
font-style: italic;
}
#newsroom_no_new_message {
color: $gray-dark !important;
}
#newsroom_no_new_message:hover {
cursor: default !important;
color: $gray-dark !important;
background-color: $white !important;
}
#newsroom_menu h1 {
font-weight: 700;
font-size: 16px;
margin-bottom: 0.5em;
}
#newsroom_menu h2 {
font-weight: 700;
font-size: 14px;
margin-bottom: 0.5em;
}
#newsroom_menu h3, #newsroom_menu h4, #newsroom_menu h5 {
font-weight: 700;
font-size: 12px;
margin-bottom: 0.5em;
}
}

View File

@@ -16,21 +16,12 @@ div.graph_config { display:none; }
h2.printable-tab-title {
page-break-after: avoid;
}
h1 {
page-break-after: avoid;
}
div#tabbedContent_0 { border:none; }
p a, .ui-widget-content td a, p a:hover, .ui-widget-content td a:hover, p a:visited, .ui-widget-content td a:visited, td a, td a:visited, td a:hover {
padding-left: 0;
background: transparent;
}
body {
margin:10px;
}
@page {
margin: 1cm;
}
body { margin:none; }
.printable-tab {
-webkit-region-break-inside: avoid;
page-break-inside: avoid;

View File

@@ -1,394 +0,0 @@
/**
* selectize.default.css (v0.12.4) - Default Theme
* Copyright (c) 20132015 Brian Reavis & contributors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at:
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
* ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*
* @author Brian Reavis <brian@thirdroute.com>
*/
.selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder {
visibility: visible !important;
background: #f2f2f2 !important;
background: rgba(0, 0, 0, 0.06) !important;
border: 0 none !important;
-webkit-box-shadow: inset 0 0 12px 4px #ffffff;
box-shadow: inset 0 0 12px 4px #ffffff;
}
.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after {
content: '!';
visibility: hidden;
}
.selectize-control.plugin-drag_drop .ui-sortable-helper {
-webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.selectize-dropdown-header {
position: relative;
padding: 5px 8px;
border-bottom: 1px solid #d0d0d0;
background: #f8f8f8;
-webkit-border-radius: 3px 3px 0 0;
-moz-border-radius: 3px 3px 0 0;
border-radius: 3px 3px 0 0;
}
.selectize-dropdown-header-close {
position: absolute;
right: 8px;
top: 50%;
color: #303030;
opacity: 0.4;
margin-top: -12px;
line-height: 20px;
font-size: 20px !important;
}
.selectize-dropdown-header-close:hover {
color: #000000;
}
.selectize-dropdown.plugin-optgroup_columns .optgroup {
border-right: 1px solid #f2f2f2;
border-top: 0 none;
float: left;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child {
border-right: 0 none;
}
.selectize-dropdown.plugin-optgroup_columns .optgroup:before {
display: none;
}
.selectize-dropdown.plugin-optgroup_columns .optgroup-header {
border-top: 0 none;
}
.selectize-control.plugin-remove_button [data-value] {
position: relative;
padding-right: 24px !important;
}
.selectize-control.plugin-remove_button [data-value] .remove {
z-index: 1;
/* fixes ie bug (see #392) */
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 17px;
text-align: center;
font-weight: bold;
font-size: 12px;
color: inherit;
text-decoration: none;
vertical-align: middle;
display: inline-block;
padding: 2px 0 0 0;
border-left: 1px solid #0073bb;
-webkit-border-radius: 0 2px 2px 0;
-moz-border-radius: 0 2px 2px 0;
border-radius: 0 2px 2px 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.selectize-control.plugin-remove_button [data-value] .remove:hover {
background: rgba(0, 0, 0, 0.05);
}
.selectize-control.plugin-remove_button [data-value].active .remove {
border-left-color: #00578d;
}
.selectize-control.plugin-remove_button .disabled [data-value] .remove:hover {
background: none;
}
.selectize-control.plugin-remove_button .disabled [data-value] .remove {
border-left-color: #aaaaaa;
}
.selectize-control.plugin-remove_button .remove-single {
position: absolute;
right: 28px;
top: 6px;
font-size: 23px;
}
.selectize-control {
position: relative;
}
.selectize-dropdown,
.selectize-input,
.selectize-input input {
color: #303030;
font-family: inherit;
font-size: 13px;
line-height: 18px;
-webkit-font-smoothing: inherit;
}
.selectize-input,
.selectize-control.single .selectize-input.input-active {
background: #ffffff;
cursor: text;
display: inline-block;
}
.selectize-input {
border: 1px solid #d0d0d0;
padding: 8px 8px;
display: inline-block;
width: 100%;
overflow: hidden;
position: relative;
z-index: 1;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.selectize-control.multi .selectize-input.has-items {
padding: 5px 8px 2px;
}
.selectize-input.full {
background-color: #ffffff;
}
.selectize-input.disabled,
.selectize-input.disabled * {
cursor: default !important;
}
.selectize-input.focus {
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
}
.selectize-input.dropdown-active {
-webkit-border-radius: 3px 3px 0 0;
-moz-border-radius: 3px 3px 0 0;
border-radius: 3px 3px 0 0;
}
.selectize-input > * {
vertical-align: baseline;
display: -moz-inline-stack;
display: inline-block;
zoom: 1;
*display: inline;
}
.selectize-control.multi .selectize-input > div {
cursor: pointer;
margin: 0 3px 3px 0;
padding: 2px 6px;
background: #1da7ee;
color: #ffffff;
border: 1px solid #0073bb;
}
.selectize-control.multi .selectize-input > div.active {
background: #92c836;
color: #ffffff;
border: 1px solid #00578d;
}
.selectize-control.multi .selectize-input.disabled > div,
.selectize-control.multi .selectize-input.disabled > div.active {
color: #ffffff;
background: #d2d2d2;
border: 1px solid #aaaaaa;
}
.selectize-input > input {
display: inline-block !important;
padding: 0 !important;
min-height: 0 !important;
max-height: none !important;
max-width: 100% !important;
margin: 0 1px !important;
text-indent: 0 !important;
border: 0 none !important;
background: none !important;
line-height: inherit !important;
-webkit-user-select: auto !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.selectize-input > input::-ms-clear {
display: none;
}
.selectize-input > input:focus {
outline: none !important;
}
.selectize-input::after {
content: ' ';
display: block;
clear: left;
}
.selectize-input.dropdown-active::before {
content: ' ';
display: block;
position: absolute;
background: #f0f0f0;
height: 1px;
bottom: 0;
left: 0;
right: 0;
}
.selectize-dropdown {
position: absolute;
z-index: 10;
border: 1px solid #d0d0d0;
background: #ffffff;
margin: -1px 0 0 0;
border-top: 0 none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-webkit-border-radius: 0 0 3px 3px;
-moz-border-radius: 0 0 3px 3px;
border-radius: 0 0 3px 3px;
}
.selectize-dropdown [data-selectable] {
cursor: pointer;
overflow: hidden;
}
.selectize-dropdown [data-selectable] .highlight {
background: rgba(125, 168, 208, 0.2);
-webkit-border-radius: 1px;
-moz-border-radius: 1px;
border-radius: 1px;
}
.selectize-dropdown [data-selectable],
.selectize-dropdown .optgroup-header {
padding: 5px 8px;
}
.selectize-dropdown .optgroup:first-child .optgroup-header {
border-top: 0 none;
}
.selectize-dropdown .optgroup-header {
color: #303030;
background: #ffffff;
cursor: default;
}
.selectize-dropdown .active {
background-color: #f5fafd;
color: #495c68;
}
.selectize-dropdown .active.create {
color: #495c68;
}
.selectize-dropdown .create {
color: rgba(48, 48, 48, 0.5);
}
.selectize-dropdown-content {
overflow-y: auto;
overflow-x: hidden;
max-height: 200px;
-webkit-overflow-scrolling: touch;
}
.selectize-control.single .selectize-input,
.selectize-control.single .selectize-input input {
cursor: pointer;
}
.selectize-control.single .selectize-input.input-active,
.selectize-control.single .selectize-input.input-active input {
cursor: text;
}
.selectize-control.single .selectize-input:after {
content: ' ';
display: block;
position: absolute;
top: 50%;
right: 15px;
margin-top: -3px;
width: 0;
height: 0;
border-style: solid;
border-width: 5px 5px 0 5px;
border-color: #808080 transparent transparent transparent;
}
.selectize-control.single .selectize-input.dropdown-active:after {
margin-top: -4px;
border-width: 0 5px 5px 5px;
border-color: transparent transparent #808080 transparent;
}
.selectize-control.rtl.single .selectize-input:after {
left: 15px;
right: auto;
}
.selectize-control.rtl .selectize-input > input {
margin: 0 4px 0 -2px !important;
}
.selectize-control .selectize-input.disabled {
opacity: 0.5;
background-color: #fafafa;
}
.selectize-control.multi .selectize-input.has-items {
padding-left: 5px;
padding-right: 5px;
}
.selectize-control.multi .selectize-input.disabled [data-value] {
color: #999;
text-shadow: none;
background: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.selectize-control.multi .selectize-input.disabled [data-value],
.selectize-control.multi .selectize-input.disabled [data-value] .remove {
border-color: #e6e6e6;
}
.selectize-control.multi .selectize-input.disabled [data-value] .remove {
background: none;
}
.selectize-control.multi .selectize-input [data-value] {
text-shadow: 0 1px 0 rgba(0, 51, 83, 0.3);
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
background-color: #1b9dec;
background-image: -moz-linear-gradient(top, #1da7ee, #178ee9);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#1da7ee), to(#178ee9));
background-image: -webkit-linear-gradient(top, #1da7ee, #178ee9);
background-image: -o-linear-gradient(top, #1da7ee, #178ee9);
background-image: linear-gradient(to bottom, #1da7ee, #178ee9);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1da7ee', endColorstr='#ff178ee9', GradientType=0);
-webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.2),inset 0 1px rgba(255,255,255,0.03);
box-shadow: 0 1px 0 rgba(0,0,0,0.2),inset 0 1px rgba(255,255,255,0.03);
}
.selectize-control.multi .selectize-input [data-value].active {
background-color: #0085d4;
background-image: -moz-linear-gradient(top, #008fd8, #0075cf);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#008fd8), to(#0075cf));
background-image: -webkit-linear-gradient(top, #008fd8, #0075cf);
background-image: -o-linear-gradient(top, #008fd8, #0075cf);
background-image: linear-gradient(to bottom, #008fd8, #0075cf);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff008fd8', endColorstr='#ff0075cf', GradientType=0);
}
.selectize-control.single .selectize-input {
-webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.05), inset 0 1px 0 rgba(255,255,255,0.8);
box-shadow: 0 1px 0 rgba(0,0,0,0.05), inset 0 1px 0 rgba(255,255,255,0.8);
background-color: #f9f9f9;
background-image: -moz-linear-gradient(top, #fefefe, #f2f2f2);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fefefe), to(#f2f2f2));
background-image: -webkit-linear-gradient(top, #fefefe, #f2f2f2);
background-image: -o-linear-gradient(top, #fefefe, #f2f2f2);
background-image: linear-gradient(to bottom, #fefefe, #f2f2f2);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffefefe', endColorstr='#fff2f2f2', GradientType=0);
}
.selectize-control.single .selectize-input,
.selectize-dropdown.single {
border-color: #b8b8b8;
}
.selectize-dropdown .optgroup-header {
padding-top: 7px;
font-weight: bold;
font-size: 0.85em;
}
.selectize-dropdown .optgroup {
border-top: 1px solid #f0f0f0;
}
.selectize-dropdown .optgroup:first-child {
border-top: 0 none;
}

View File

@@ -1,2 +1,20 @@
<?php
/**
* Copyright (C) 2013-2020 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
*/
echo 'Access denied';

View File

@@ -39,3 +39,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Class:UserExternal' => 'Externí uživatel',
'Class:UserExternal+' => 'Uživatel definovaný mimo iTop',
));
?>

View File

@@ -24,3 +24,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Class:UserExternal' => 'Extern Bruger',
'Class:UserExternal+' => 'Bruger udenfor iTop',
));
?>

View File

@@ -26,3 +26,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:UserExternal' => 'Externer Benutzer',
'Class:UserExternal+' => 'Benutzer außerhalb von iTop',
));
?>

View File

@@ -1,24 +1,27 @@
<?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-2018 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// Dictionnay conventions
@@ -39,3 +42,7 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:UserExternal' => 'External user',
'Class:UserExternal+' => 'User authentified outside of iTop',
));
?>

Some files were not shown because too many files have changed in this diff Show More