Compare commits

...

63 Commits

Author SHA1 Message Date
vdumas
05b69208a8 N°5160 - Hiding a DashboardAttribute on the fly does not work - WIP 2022-05-17 11:01:18 +02:00
vdumas
c0f0e354dd N°5124 - ConnectableCI to NetworkDevice update failing 2022-04-26 13:03:43 +02:00
vdumas
d6f58d04f1 N°4702 - DataModel : wrong attribute type for SLA.customercontracts_list 2022-04-25 15:08:46 +02:00
vdumas
cc88ee1de0 Revert "N°4702 - DataModel : wrong attribute type for SLA.customercontracts_list"
This reverts commit 6b7183d500706a2bcf6340eca3478a7ca22ce7e3.
2022-04-25 15:08:46 +02:00
vdumas
8008e4d840 N°4702 - DataModel : wrong attribute type for SLA.customercontracts_list 2022-04-25 15:08:46 +02:00
Molkobain
a4390fbb57 Merge remote-tracking branch 'origin/support/3.0' into develop
# Conflicts:
#	test/application/search/CriterionConversionTest.php
#	test/application/search/CriterionParserTest.php
#	test/application/search/SearchFormTest.php
2022-04-25 14:03:02 +02:00
vdumas
f4170ade8a N°4702 - DataModel : wrong attribute type for SLA.customercontracts_list 2022-04-25 10:23:12 +02:00
vdumas
1d9a9bcb28 N°3889 - Missing default search zlist on SLA and SLT 2022-04-22 12:52:01 +02:00
Stephen Abello
178ba60973 N°4307 Replace SwiftMailer with Laminas-mail 2022-04-22 10:58:28 +02:00
Pierre Goiffon
c47f224566 💡 N°4919 add @since 2022-04-19 15:29:35 +02:00
Pierre Goiffon
8fcd454445 N°4919 New 'Launch setup" in Application Upgrade (#244)
Admin will now be able to re-launch the iTop setup directly from the administration console in the Administration / Application Upgrade screen.
Before the only way to launch setup on an existing iTop instance was to change permissions on the configuration file.

This button will be enabled depending on the isDevEnv (if true it will be displayed) and `setup.launch_button.enabled` new configuration parameter (not present by default ; if set to false will always hide the button, if set to true will always display it, if not set will display button depending on isDevEnv only).

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2022-04-19 14:36:15 +02:00
Stephen Abello
ba9d5f0c4b N°3607 Handle error and fix unit test 2022-04-19 09:31:02 +02:00
Stephen Abello
0efc978004 N°3607 Change XML node format 2022-04-15 15:48:21 +02:00
Molkobain
b026e5ab87 Update branches examples on contributing guide 2022-04-13 16:22:02 +02:00
Molkobain
1e75154cc7 Merge remote-tracking branch 'origin/support/3.0' into develop 2022-04-13 16:15:26 +02:00
Thomas Casteleyn
e4a04de9f4 N°5066 - Clean CMDBSource methods (#229)
* Improve function calls

* Deprecate CMDBSource::GetServerInfo

* Improve documentation

* Update core/cmdbsource.class.inc.php

Co-authored-by: Pierre Goiffon <pierre.goiffon@combodo.com>

* Single quotes

* Apply suggestion, so  method still returns empty string instead of null

Co-authored-by: Pierre Goiffon <pierre.goiffon@combodo.com>
2022-04-12 17:10:41 +02:00
Timothee
645e612e8b N°5042 - Fixing inconsistent "Problem" tickets display compared to other types of tickets 2022-04-12 14:49:15 +02:00
Stephen Abello
26a78a10bc N°3607 Allow extensions to register variables/stylesheets to be compiled with every theme 2022-04-12 10:23:50 +02:00
Molkobain
1feb5e6ad6 Merge remote-tracking branch 'origin/support/3.0' into develop 2022-04-08 13:32:08 +02:00
Molkobain
42599eae64 N°3838 - Improve PHPDoc of \DBObjectSearch::AddCondition() as it cannot have multiple condition on the same field 2022-04-04 17:49:41 +02:00
acognet
b75f29b8d7 N°3067 - Cannot edit in place attributes with HTML editors 2022-03-28 14:18:54 +02:00
Eric Espie
81d285a143 CEX SDK V2:
* Pre and post actions
2022-03-28 09:43:46 +02:00
Molkobain
ad4442ae78 Merge remote-tracking branch 'origin/support/3.0' into develop 2022-03-23 09:49:11 +01:00
acognet
1db4b9a12e Merge remote-tracking branch 'origin/support/3.0' into develop 2022-03-16 09:44:33 +01:00
Molkobain
f4ecdf116a Merge remote-tracking branch 'origin/support/3.0' into develop 2022-03-09 19:55:35 +01:00
Pierre Goiffon
8d4545f008 N°4921 - Add support for attcode & attvalue parameters in URL to access an object (#273)
This is a way to solve problems when an object ref and id isn't equals : for example id=99 and ref = 100.
This could happen since iTop 2.7.0, see https://www.itophub.io/wiki/page?id=2_7_0%3Arelease%3A2_7_whats_new#ticket_ref_generation

Note that id parameter can be set to the object's friendlyname as a workaround, but this might not be enough for some objects where friendlyname contains more that the ref field (for example title, org, ...)

* Admin console : new UI.php URL parameters : attcode and attvalue.
Example URLs : 
/pages/UI.php?operation=details&class=UserRequest&id=99
/pages/UI.php?operation=details&class=UserRequest&attcode=ref&attvalue=R-000100

An exception will be thrown if no object is found or multiple instances are.

* User portal
New route : /object/view/{sObjectClass}/{sObjectAttCode}/{sObjectAttValue}
For example :
/pages/exec.php/object/view/UserRequest/99?exec_module=itop-portal-base&exec_page=index.php&portal_id=itop-portal
/pages/exec.php/object/view/UserRequest/ref/R-000100?exec_module=itop-portal-base&exec_page=index.php&portal_id=itop-portal

On error we will get a 404 error page
2022-03-09 10:51:21 +01:00
Molkobain
5854c199d0 Merge remote-tracking branch 'origin/support/3.0' into develop 2022-03-07 12:54:13 +01:00
Eric Espie
a937d08655 Fix CI (wrong module version) 2022-03-03 10:42:24 +01:00
Eric Espie
4bdf84bf6c Merge remote-tracking branch 'origin/support/3.0' into develop 2022-03-03 10:23:38 +01:00
Pierre Goiffon
9ce88699ca Merge remote-tracking branch 'origin/support/3.0' into develop
# Conflicts:
#	datamodels/2.x/itop-portal-base/portal/templates/bricks/browse/mode_mosaic.html.twig
#	datamodels/2.x/itop-portal-base/portal/templates/bricks/browse/mode_tree.html.twig
2022-02-22 09:40:37 +01:00
acognet
f9e8bf88c8 N°4662 - Portal: Fix broken display of the services catalogue when installing Service Provider + Sample Data 2022-02-15 09:50:44 +01:00
Pierre Goiffon
bddf7a11c8 Merge remote-tracking branch 'origin/support/3.0' into develop 2022-02-14 09:01:26 +01:00
Pierre Goiffon
ee7fb15fc2 Merge remote-tracking branch 'origin/support/3.0' into develop 2022-02-14 08:44:12 +01:00
Pierre Goiffon
8473df0f0c 💡 Add attribute phpdoc for \RestResultWithObjects::$objects 2022-02-11 18:26:16 +01:00
Pierre Goiffon
7eab003f3c N°4714 Fix setup crashing with "Call to undefined method utils::GetItopVersionWikiSyntax()"
Missed this in the merge (d437e2d6) cause there were lots of datamodels/2.x/*/module.*.php changes to discard :(
2022-02-08 15:58:34 +01:00
Pierre Goiffon
d437e2d662 Merge remote-tracking branch 'origin/support/3.0' into develop
# Conflicts:
#	application/displayblock.class.inc.php
#	core/config.class.inc.php
#	datamodels/2.x/authent-cas/module.authent-cas.php
#	datamodels/2.x/authent-external/module.authent-external.php
#	datamodels/2.x/authent-ldap/module.authent-ldap.php
#	datamodels/2.x/authent-local/module.authent-local.php
#	datamodels/2.x/combodo-backoffice-darkmoon-theme/module.combodo-backoffice-darkmoon-theme.php
#	datamodels/2.x/combodo-db-tools/module.combodo-db-tools.php
#	datamodels/2.x/itop-attachments/module.itop-attachments.php
#	datamodels/2.x/itop-backup/module.itop-backup.php
#	datamodels/2.x/itop-bridge-cmdb-ticket/module.itop-bridge-cmdb-ticket.php
#	datamodels/2.x/itop-bridge-virtualization-storage/module.itop-bridge-virtualization-storage.php
#	datamodels/2.x/itop-change-mgmt-itil/module.itop-change-mgmt-itil.php
#	datamodels/2.x/itop-change-mgmt/module.itop-change-mgmt.php
#	datamodels/2.x/itop-config-mgmt/module.itop-config-mgmt.php
#	datamodels/2.x/itop-config/module.itop-config.php
#	datamodels/2.x/itop-core-update/module.itop-core-update.php
#	datamodels/2.x/itop-datacenter-mgmt/module.itop-datacenter-mgmt.php
#	datamodels/2.x/itop-endusers-devices/module.itop-endusers-devices.php
#	datamodels/2.x/itop-faq-light/module.itop-faq-light.php
#	datamodels/2.x/itop-files-information/module.itop-files-information.php
#	datamodels/2.x/itop-full-itil/module.itop-full-itil.php
#	datamodels/2.x/itop-hub-connector/module.itop-hub-connector.php
#	datamodels/2.x/itop-incident-mgmt-itil/module.itop-incident-mgmt-itil.php
#	datamodels/2.x/itop-knownerror-mgmt/module.itop-knownerror-mgmt.php
#	datamodels/2.x/itop-portal-base/module.itop-portal-base.php
#	datamodels/2.x/itop-portal/module.itop-portal.php
#	datamodels/2.x/itop-problem-mgmt/module.itop-problem-mgmt.php
#	datamodels/2.x/itop-profiles-itil/module.itop-profiles-itil.php
#	datamodels/2.x/itop-request-mgmt-itil/module.itop-request-mgmt-itil.php
#	datamodels/2.x/itop-request-mgmt/module.itop-request-mgmt.php
#	datamodels/2.x/itop-service-mgmt-provider/module.itop-service-mgmt-provider.php
#	datamodels/2.x/itop-service-mgmt/module.itop-service-mgmt.php
#	datamodels/2.x/itop-sla-computation/module.itop-sla-computation.php
#	datamodels/2.x/itop-storage-mgmt/module.itop-storage-mgmt.php
#	datamodels/2.x/itop-structure/module.itop-structure.php
#	datamodels/2.x/itop-tickets/module.itop-tickets.php
#	datamodels/2.x/itop-virtualization-mgmt/module.itop-virtualization-mgmt.php
#	datamodels/2.x/itop-welcome-itil/module.itop-welcome-itil.php
#	datamodels/2.x/version.xml
2022-02-08 15:43:20 +01:00
Molkobain
60c372f535 Merge remote-tracking branch 'origin/support/3.0' into develop 2022-02-02 11:20:58 +01:00
Molkobain
22f9d16743 N°4415 - Remove SetupPage:log* 2022-01-27 17:37:14 +01:00
Molkobain
3d3d94e837 N°2522 - API : Deprecate SetupPage:log* 2022-01-27 17:23:12 +01:00
Molkobain
3bec96abe1 Merge remote-tracking branch 'origin/support/3.0' into develop
# Conflicts:
#	core/config.class.inc.php
#	setup/itopdesignformat.class.inc.php
2022-01-27 16:09:22 +01:00
Molkobain
44c18395b3 N°4072 - Deprecate ajax.render.php xlsx_* operations 2022-01-27 11:42:30 +01:00
Molkobain
09ff052c1f N°4072 - Add method to deprecate PHP endpoints 2022-01-27 11:42:30 +01:00
Benjamin Dalsass
9ef5fd70c0 Merge remote-tracking branch 'origin/develop' into develop 2022-01-26 08:12:13 +01:00
Benjamin Dalsass
3b599a40f3 N°4454 - Measuring the use of the queryphrase book (code review 2) 2022-01-26 08:11:16 +01:00
Molkobain
1495ab992f N°3824 - Update autoloader 2022-01-23 16:13:55 +01:00
Molkobain
d89dc1aa4d N°3824 - History: Remove deprecated APIs from 2.7 and older 2022-01-21 18:10:12 +01:00
Benjamin Dalsass
1fac2ae787 N°4454 - Measuring the use of the queryphrase book (code review) 2022-01-19 07:48:03 +01:00
Molkobain
ff7d1f2d6a Merge remote-tracking branch 'origin/support/3.0' into develop 2022-01-17 19:21:52 +01:00
Benjamin Dalsass
91d4da85e1 N°4454 - Measuring the use of the queryphrase book 2022-01-14 11:12:30 +01:00
Pierre Goiffon
dcd52d6919 N°3863 - exec.php : allow subdirectories in the page parameter (#221) 2022-01-12 17:24:30 +01:00
Molkobain
9a75ca2c21 Merge remote-tracking branch 'origin/support/3.0' into develop 2022-01-12 16:06:29 +01:00
Molkobain
812606db78 Merge remote-tracking branch 'origin/support/3.0' into develop
# Conflicts:
#	core/config.class.inc.php
2022-01-12 15:54:18 +01:00
Molkobain
c17ceb1702 N°4621 - Rename corresponding unit tests folder 2022-01-11 14:35:45 +01:00
Thomas Casteleyn
ce01dad875 utils::GetImageSize can be simplified since minimal PHP version is 7.1.3 2022-01-05 10:15:41 +01:00
Pierre Goiffon
9ca106d889 N°4621 Fix criterionconversionabstract.class.inc.php requires 2021-12-31 16:01:29 +01:00
Pierre Goiffon
5f575d524a N°4621 Fix naming inconsistencies in sources/* 2021-12-31 15:44:59 +01:00
acognet
16142bd979 Change version number to 3.1.0 2021-12-23 17:23:24 +01:00
acognet
c1e2ba8abc Change version number to 3.1.0 2021-12-23 17:05:54 +01:00
acognet
cc2efe432e Change version number to 3.1.0 2021-12-23 16:37:32 +01:00
acognet
e879ae2f11 Change version number to 3.1.0 2021-12-23 14:14:51 +01:00
Pierre Goiffon
8bcd2ce571 Merge remote-tracking branch 'origin/support/3.0' into develop
# Conflicts:
#	core/config.class.inc.php
2021-12-23 10:05:53 +01:00
acognet
d301562ffe Change version number to 3.1.0 2021-12-23 09:41:16 +01:00
acognet
caed22ea8d Change version number to 3.1.0 2021-12-23 09:39:24 +01:00
826 changed files with 53163 additions and 24285 deletions

View File

@@ -52,26 +52,26 @@ Here are the branches we use and their meaning :
For example, if no version is currently prepared for shipping we could have:
- `develop` containing future 3.0.0 version
- `develop` containing future 3.1.0 version
- `support/3.0`: 3.0.x maintenance version
- `support/2.7`: 2.7.x maintenance version
- `support/2.6`: 2.6.x maintenance version
- `support/2.5`: 2.5.x maintenance version
In this example, when 3.0.0-beta is shipped that will become:
In this example, when 3.1.0-beta is shipped that will become:
- `develop`: future 3.1.0 version
- `release/3.0.0`: 3.0.0-beta
- `develop`: future 3.2.0 version
- `release/3.1.0`: 3.1.0-beta
- `support/3.0`: 3.0.x maintenance version
- `support/2.7`: 2.7.x maintenance version
- `support/2.6`: 2.6.x maintenance version
- `support/2.5`: 2.5.x maintenance version
And when 3.0.0 final will be out:
- `develop`: future 3.1.0 version
- `support/3.0`: 3.0.x maintenance version (will host developments for 3.0.1)
- `develop`: future 3.2.0 version
- `support/3.1`: 3.1.x maintenance version (will host developments for 3.1.1)
- `support/3.0`: 3.0.x maintenance version
- `support/2.7`: 2.7.x maintenance version
- `support/2.6`: 2.6.x maintenance version
- `support/2.5`: 2.5.x maintenance version
Also note that we have a "micro-version" concept : each of those versions have a very small amount of modifications. They are made from
`support/*` branches as well. For example 2.6.2-1 and 2.6.2-2 were made from the `support/2.6.2` branch.

View File

@@ -1,12 +1,12 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader');
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader');
/**
* Class ajax_page

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader');

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader');

View File

@@ -60,11 +60,11 @@ require_once(APPROOT.'application/ui.linksdirectwidget.class.inc.php');
require_once(APPROOT.'application/ui.passwordwidget.class.inc.php');
require_once(APPROOT.'application/ui.extkeywidget.class.inc.php');
require_once(APPROOT.'application/ui.htmleditorwidget.class.inc.php');
require_once(APPROOT.'sources/application/search/searchform.class.inc.php');
require_once(APPROOT.'sources/application/search/criterionparser.class.inc.php');
require_once(APPROOT.'sources/application/search/criterionconversionabstract.class.inc.php');
require_once(APPROOT.'sources/application/search/criterionconversion/criteriontooql.class.inc.php');
require_once(APPROOT.'sources/application/search/criterionconversion/criteriontosearchform.class.inc.php');
require_once(APPROOT.'sources/Application/Search/searchform.class.inc.php');
require_once(APPROOT.'sources/Application/Search/criterionparser.class.inc.php');
require_once(APPROOT.'sources/Application/Search/criterionconversionabstract.class.inc.php');
require_once(APPROOT.'sources/Application/Search/CriterionConversion/criteriontooql.class.inc.php');
require_once(APPROOT.'sources/Application/Search/CriterionConversion/criteriontosearchform.class.inc.php');
/**
* Class cmdbAbstractObject
@@ -509,32 +509,6 @@ HTML
return $aHeaderBlocks;
}
/**
* Display history tab of an object
*
* @deprecated 3.0.0 will be removed in 3.1, see N°3824
*
* @param bool $bEditMode
* @param int $iLimitCount
* @param int $iLimitStart
*
* @param \WebPage $oPage
*
* @throws \CoreException
*
*/
public function DisplayBareHistory(WebPage $oPage, $bEditMode = false, $iLimitCount = 0, $iLimitStart = 0)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
// history block (with as a tab)
$oHistoryFilter = new DBObjectSearch('CMDBChangeOp');
$oHistoryFilter->AddCondition('objkey', $this->GetKey(), '=');
$oHistoryFilter->AddCondition('objclass', get_class($this), '=');
$oBlock = new HistoryBlock($oHistoryFilter, 'table', false);
$oBlock->SetLimit($iLimitCount, $iLimitStart);
$oBlock->Display($oPage, 'history');
}
/**
* Display properties tab of an object
*
@@ -1186,8 +1160,6 @@ HTML
$oPage->SetCurrentTab('UI:PropertiesTab');
$this->DisplayBareProperties($oPage, $bEditMode);
$this->DisplayBareRelations($oPage, $bEditMode);
// TODO 3.0.0: What to do with this?
//$this->DisplayBareHistory($oPage, $bEditMode);
// Note: Adding the JS snippet which enables the image upload should have been done directly by the ActivityPanel which would have kept the independance principle
// of the UIBlock. For now we keep it this way in order to move on and trace this known limitation in N°3736.

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader');

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="AbstractResource" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -476,7 +476,7 @@ class DisplayBlock
$oExceptionAlert = AlertUIBlockFactory::MakeForFailure('Cannot display results', $sExceptionContent);
$oHtml->AddSubBlock($oExceptionAlert);
}
IssueLog::Error('Exception during GetDisplay: '.$e->getMessage());
ExceptionLog::LogException($e);
}
} else {
// render it as an Ajax (asynchronous) call
@@ -1705,162 +1705,6 @@ JS
}
/**
* Helper class to manage 'blocks' of HTML pieces that are parts of a page and contain some list of cmdb objects
*
* Each block is actually rendered as a <div></div> tag that can be rendered synchronously
* or as a piece of Javascript/JQuery/Ajax that will get its content from another page (ajax.render.php).
* The list of cmdbObjects to be displayed into the block is defined by a filter
* Right now the type of display is either: list, count or details
* - list produces a table listing the objects
* - count produces a paragraphs with a sentence saying 'cont' objects found
* - details display (as table) the details of each object found (best if only one)
*
* @deprecated 3.0.0 will be removed in 3.1, see N°3824
*/
class HistoryBlock extends DisplayBlock
{
protected $iLimitCount;
protected $iLimitStart;
public function __construct(DBSearch $oFilter, $sStyle = 'list', $bAsynchronous = false, $aParams = array(), $oSet = null)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
parent::__construct($oFilter, $sStyle, $bAsynchronous, $aParams, $oSet);
$this->iLimitStart = 0;
$this->iLimitCount = 0;
}
public function SetLimit($iCount, $iStart = 0)
{
$this->iLimitStart = $iStart;
$this->iLimitCount = $iCount;
}
/**
* @param \WebPage $oPage
* @param array $aExtraParams
* @param string $sId
*
* @return string
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $aExtraParams and add type hinting for PHP 8.0 compatibility
* (var is unused, and all calls were already made using a default value)
*/
public function GetRenderContent(WebPage $oPage, array $aExtraParams, string $sId)
{
$sHtml = '';
$bTruncated = false;
$oSet = new CMDBObjectSet($this->m_oFilter, array('date' => false));
if (!$oPage->IsPrintableVersion()) {
if (($this->iLimitStart > 0) || ($this->iLimitCount > 0)) {
$oSet->SetLimit($this->iLimitCount, $this->iLimitStart);
if (($this->iLimitCount - $this->iLimitStart) < $oSet->Count()) {
$bTruncated = true;
}
}
}
$sHtml .= "<!-- filter: ".($this->m_oFilter->ToOQL())."-->\n";
switch ($this->m_sStyle) {
case 'toggle':
// First the latest change that the user is allowed to see
do {
$oLatestChangeOp = $oSet->Fetch();
} while (is_object($oLatestChangeOp) && ($oLatestChangeOp->GetDescription() == ''));
if (is_object($oLatestChangeOp)) {
// There is one change in the list... only when the object has been created !
$sDate = $oLatestChangeOp->GetAsHTML('date');
$oChange = MetaModel::GetObject('CMDBChange', $oLatestChangeOp->Get('change'));
$sUserInfo = $oChange->GetAsHTML('userinfo');
$sHtml .= $oPage->GetStartCollapsibleSection(Dict::Format('UI:History:LastModified_On_By', $sDate, $sUserInfo));
$sHtml .= $this->GetHistoryTable($oPage, $oSet);
$sHtml .= $oPage->GetEndCollapsibleSection();
}
break;
case 'table':
default:
if ($bTruncated)
{
$sFilter = htmlentities($this->m_oFilter->serialize(), ENT_QUOTES, 'UTF-8');
$sHtml .= '<div id="history_container"><p>';
$sHtml .= Dict::Format('UI:TruncatedResults', $this->iLimitCount, $oSet->Count());
$sHtml .= ' ';
$sHtml .= '<a href="#" onclick="DisplayHistory(\'#history_container\', \''.$sFilter.'\', 0, 0); return false;">'.Dict::S('UI:DisplayAll').'</a>';
$sHtml .= $this->GetHistoryTable($oPage, $oSet);
$sHtml .= '</p></div>';
$oPage->add_ready_script("$('#{$sId} table.listResults tr:last td').addClass('truncated');");
}
else
{
$sHtml .= $this->GetHistoryTable($oPage, $oSet);
}
$oPage->add_ready_script(InlineImage::FixImagesWidth());
$oPage->add_ready_script("$('.case-log-history-entry-toggle').on('click', function () { $(this).closest('.case-log-history-entry').toggleClass('expanded');});");
$oPage->add_ready_script(
<<<EOF
$('.history_entry').each(function() {
var jMe = $(this);
var oContent = $(this).find('.history_html_content');
if (jMe.height() < oContent.height())
{
jMe.prepend('<span class="history_truncated_toggler"></span>');
jMe.find('.history_truncated_toggler').on('click', function() {
jMe.toggleClass('history_entry_truncated');
});
}
});
EOF
);
}
return new Html($sHtml);
}
protected function GetHistoryTable(WebPage $oPage, DBObjectSet $oSet)
{
$sHtml = '';
// First the latest change that the user is allowed to see
$oSet->Rewind(); // Reset the pointer to the beginning of the set
$aChanges = array();
while($oChangeOp = $oSet->Fetch())
{
$sChangeDescription = $oChangeOp->GetDescription();
if ($sChangeDescription != '')
{
// The change is visible for the current user
$changeId = $oChangeOp->Get('change');
$aChanges[$changeId]['date'] = $oChangeOp->Get('date');
$aChanges[$changeId]['userinfo'] = $oChangeOp->Get('userinfo');
if (!isset($aChanges[$changeId]['log']))
{
$aChanges[$changeId]['log'] = array();
}
$aChanges[$changeId]['log'][] = $sChangeDescription;
}
}
$aAttribs = array('date' => array('label' => Dict::S('UI:History:Date'), 'description' => Dict::S('UI:History:Date+')),
'userinfo' => array('label' => Dict::S('UI:History:User'), 'description' => Dict::S('UI:History:User+')),
'log' => array('label' => Dict::S('UI:History:Changes') , 'description' => Dict::S('UI:History:Changes+')),
);
$aValues = array();
foreach($aChanges as $aChange)
{
$aValues[] = array('date' => AttributeDateTime::GetFormat()->Format($aChange['date']), 'userinfo' => htmlentities($aChange['userinfo'], ENT_QUOTES, 'UTF-8'), 'log' => "<ul><li>".implode('</li><li>', $aChange['log'])."</li></ul>");
}
$sHtml .= $oPage->GetTable($aAttribs, $aValues);
return $sHtml;
}
}
/**
* Displays the 'Actions' menu for a given (list of) object(s)
* The 'style' of the list (see constructor of DisplayBlock) can be either 'list' or 'details'

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader');

View File

@@ -1,9 +1,9 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWebPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/iTopWebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/iTopWebPage.php, now loadable using autoloader');
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/iTopWebPage.php, now loadable using autoloader');

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWizardWebPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/iTopWizardWebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/iTopWizardWebPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/iTopWizardWebPage.php, now loadable using autoloader');

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/NiceWebPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/NiceWebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/NiceWebPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/NiceWebPage.php, now loadable using autoloader');

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/PDFPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/PDFPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/PDFPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/PDFPage.php, now loadable using autoloader');

View File

@@ -18,8 +18,7 @@
*/
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Field\Field;
use Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
use Combodo\iTop\Application\UI\Base\Component\Input\TextArea;
@@ -51,6 +50,7 @@ abstract class Query extends cmdbAbstractObject
"is_null_allowed" => false,
"depends_on" => array(),
)));
MetaModel::Init_AddAttribute(new AttributeText("description", array(
"allowed_values" => null,
"sql" => "description",
@@ -68,6 +68,41 @@ abstract class Query extends cmdbAbstractObject
'display_style' => 'radio_horizontal',
)));
MetaModel::Init_AddAttribute(new AttributeInteger("export_count", array(
"allowed_values" => null,
"sql" => "export_count",
"default_value" => 0,
"is_null_allowed" => false,
"depends_on" => array(),
)));
MetaModel::Init_AddAttribute(new AttributeDateTime("export_last_date", array(
"allowed_values" => null,
"sql" => "export_last_date",
"default_value" => null,
"is_null_allowed" => true,
"depends_on" => array(),
)));
MetaModel::Init_AddAttribute(new AttributeExternalKey("export_last_user_id",
array(
"targetclass"=>'User',
"allowed_values"=>null,
"sql"=>'user_id',
"is_null_allowed"=>true,
"depends_on"=>array(),
"display_style"=>'select',
"always_load_in_tables"=>false,
"on_target_delete"=>DEL_SILENT
)));
MetaModel::Init_AddAttribute(new AttributeExternalField("export_last_user_contact",
array(
"allowed_values"=>null,
"extkey_attcode"=> "export_last_user_id",
"target_attcode"=>"contactid"
)));
// Display lists
MetaModel::Init_SetZListItems('details',
array('name', 'is_template', 'description')); // Attributes to be displayed for the complete details
@@ -78,6 +113,54 @@ abstract class Query extends cmdbAbstractObject
array('name', 'description', 'is_template')); // Criteria of the default search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
/**
* @inheritdoc
*
* @since 3.1.0
*/
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
{
// read only attribute
if (in_array($sAttCode, ['export_count', 'export_last_date', 'export_last_user_id'])){
return OPT_ATT_READONLY;
}
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
}
/**
* Return export url.
*
* @param array|null $aValues optional values for the query
*
* @return string|null
* @since 3.1.0
*/
abstract public function GetExportUrl(array $aValues = null) : ?string;
/**
* Update last export information.
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @since 3.1.0
*/
public function UpdateLastExportInformation() : void
{
// last export information
$this->Set('export_last_date', date(AttributeDateTime::GetSQLFormat()));
$this->Set('export_last_user_id', UserRights::GetUserObject());
$this->DBUpdate();
// increment usage counter
$this->DBIncrement('export_count');
}
}
class QueryOQL extends Query
@@ -116,13 +199,51 @@ class QueryOQL extends Query
// Display lists
MetaModel::Init_SetZListItems('details',
array('name', 'is_template', 'description', 'oql', 'fields')); // Attributes to be displayed for the complete details
array(
'col:col1' => array('fieldset:Query:baseinfo' => array('name', 'is_template', 'description', 'oql', 'fields')),
'col:col2' => array('fieldset:Query:exportInfo' => array('export_count', 'export_last_date', 'export_last_user_id', 'export_last_user_contact'))
)
); // 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', 'is_template', 'fields', 'oql')); // Criteria of the std search form
}
/** @inheritdoc */
public function GetExportUrl(array $aValues = null) : ?string
{
try{
// retrieve attributes
$sFields = trim($this->Get('fields'));
$sOql = $this->Get('oql');
// construct base url depending on version
$bExportV1Recommended = ($sFields == '');
if ($bExportV1Recommended) {
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?format=spreadsheet&login_mode=basic&query='.$this->GetKey();
}
else{
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
}
// search object from OQL
$oSearch = DBObjectSearch::FromOQL($sOql);
// inject parameters
$aParameters = $oSearch->GetQueryParams();
foreach ($aParameters as $sParam => $val) {
$paramValue = ($aValues === null || $aValues[$sParam] === null) ? $sParam : $aValues[$sParam];
$sUrl .= '&arg_' . $sParam . '=' . $paramValue;
}
return $sUrl;
}
catch(Exception $e){
return null;
}
}
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
{
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
@@ -152,9 +273,11 @@ class QueryOQL extends Query
$sUrl .= '&arg_'.$sParam.'=["'.$sParam.'"]';
}
// add text area inside field set
$oFieldSet = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:Query:UrlForExcel'));
$oTextArea = new TextArea("", $sUrl, null, 80, 3);
$oFieldUrl = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:Query:UrlForExcel'), $oTextArea, Field::ENUM_FIELD_LAYOUT_LARGE);
$oPage->AddSubBlock($oFieldUrl);
$oFieldSet->AddSubBlock($oTextArea);
$oPage->AddSubBlock($oFieldSet);
if (count($aParameters) == 0) {
$oBlock = new DisplayBlock($oSearch, 'list');
@@ -178,6 +301,7 @@ class QueryOQL extends Query
return $aFieldsMap;
}
// Rolled back until 'fields' can be properly managed by AttributeQueryAttCodeSet
//
// public function ComputeValues()

View File

@@ -234,7 +234,6 @@ class DisplayTemplate
$sTemplate = '<div class="page_header">
<div class="actions_details"><a href="#"><span>Actions</span></a></div>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/oql">SELECT CMDBChangeOp WHERE objkey = $id$ AND objclass = \'$class$\'</itopblock>
</div>
<img src="../../images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
<itoptabs>

View File

@@ -1,7 +1,6 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/oql" label="Actions">SELECT $class$ WHERE id = $id$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/oql">SELECT CMDBChangeOp WHERE objkey = $id$ AND objclass = '$class$'</itopblock>
</div>
<img src="../../images/clean.png" style="margin-top:-20px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="false" type="bare_details" encoding="text/oql">SELECT $class$ WHERE id = $id$</itopblock>

View File

@@ -975,7 +975,7 @@ HTML
$oPage->add_ready_script(<<<JS
$('#ac_create_{$this->iId}').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true});
$('#dcr_{$this->iId} form').removeAttr('onsubmit');
$('#dcr_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoCreateObject);
$('#dcr_{$this->iId} form').find('button[type="submit"]').on('click', oACWidget_{$this->iId}.DoCreateObject);
JS
);
}

View File

@@ -1944,28 +1944,18 @@ class utils
return $sCss;
}
/**
* Get the size of an image from a string.
*
* @see \getimagesizefromstring()
* @param $sImageData string The image data, as a string.
*
* @return array|false
*/
public static function GetImageSize($sImageData)
{
if (function_exists('getimagesizefromstring')) // PHP 5.4.0 or higher
{
$aRet = @getimagesizefromstring($sImageData);
}
else if(ini_get('allow_url_fopen'))
{
// work around to avoid creating a tmp file
$sUri = 'data://application/octet-stream;base64,'.base64_encode($sImageData);
$aRet = @getimagesize($sUri);
}
else
{
// Damned, need to create a tmp file
$sTempFile = tempnam(SetupUtils::GetTmpDir(), 'img-');
@file_put_contents($sTempFile, $sImageData);
$aRet = @getimagesize($sTempFile);
@unlink($sTempFile);
}
return $aRet;
return @getimagesizefromstring($sImageData);
}
/**

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/WebPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/WebPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/WebPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/WebPage.php, now loadable using autoloader');

View File

@@ -1,8 +1,8 @@
<?php
/**
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/XMLPage.php, now loadable using autoloader
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/XMLPage.php, now loadable using autoloader
* @license http://opensource.org/licenses/AGPL-3.0
* @copyright Copyright (C) 2010-2021 Combodo SARL
*/
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/XMLPage.php, now loadable using autoloader');
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/XMLPage.php, now loadable using autoloader');

View File

@@ -11,7 +11,7 @@ define('APPCONF', APPROOT.'conf/');
*
* @see ITOP_CORE_VERSION to get full iTop core version
*/
define('ITOP_DESIGN_LATEST_VERSION', '3.0');
define('ITOP_DESIGN_LATEST_VERSION', '3.1');
/**
* Constant containing the iTop core version, whatever application was built
@@ -23,6 +23,6 @@ define('ITOP_DESIGN_LATEST_VERSION', '3.0');
* @used-by utils::GetItopVersionWikiSyntax()
* @used-by iTopModulesPhpVersionIntegrationTest
*/
define('ITOP_CORE_VERSION', '3.0.1');
define('ITOP_CORE_VERSION', '3.1.0');
require_once APPROOT.'bootstrap.inc.php';

View File

@@ -11,11 +11,12 @@
"ext-mysqli": "*",
"ext-soap": "*",
"combodo/tcpdf": "6.3.5",
"laminas/laminas-mail": "^2.12",
"laminas/laminas-servicemanager": "^3.5",
"nikic/php-parser": "^4.12.0",
"pear/archive_tar": "1.4.14",
"pelago/emogrifier": "3.1.0",
"scssphp/scssphp": "1.0.6",
"swiftmailer/swiftmailer": "5.4.12",
"symfony/console": "~3.4.47",
"symfony/dotenv": "~3.4.47",
"symfony/framework-bundle": "~3.4.47",

632
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4c5cdd1e0feb4abaab8f86959ffc7a64",
"content-hash": "932a981993f694ebe4e382219fb40008",
"packages": [
{
"name": "combodo/tcpdf",
@@ -66,6 +66,530 @@
"homepage": "https://github.com/combodo-itop-libs/TCPDF",
"time": "2020-09-28T12:19:09+00:00"
},
{
"name": "container-interop/container-interop",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/container-interop/container-interop.git",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"shasum": ""
},
"require": {
"psr/container": "^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Interop\\Container\\": "src/Interop/Container/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
"homepage": "https://github.com/container-interop/container-interop",
"support": {
"issues": "https://github.com/container-interop/container-interop/issues",
"source": "https://github.com/container-interop/container-interop/tree/master"
},
"abandoned": "psr/container",
"time": "2017-02-14T19:40:03+00:00"
},
{
"name": "laminas/laminas-loader",
"version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-loader.git",
"reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-loader/zipball/5d01c2c237ae9e68bec262f339947e2ea18979bc",
"reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc",
"shasum": ""
},
"require": {
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-loader": "self.version"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.6.x-dev",
"dev-develop": "2.7.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Loader\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Autoloading and plugin loading strategies",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"loader"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-loader/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-loader/issues",
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
"source": "https://github.com/laminas/laminas-loader"
},
"time": "2019-12-31T17:18:27+00:00"
},
{
"name": "laminas/laminas-mail",
"version": "2.12.5",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-mail.git",
"reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-mail/zipball/ed5b36a0deef4ffafe6138c2ae9cafcffafab856",
"reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"laminas/laminas-loader": "^2.5",
"laminas/laminas-mime": "^2.5",
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"laminas/laminas-validator": "^2.10.2",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^7.1",
"true/punycode": "^2.1"
},
"replace": {
"zendframework/zend-mail": "^2.10.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-config": "^2.6",
"laminas/laminas-crypt": "^2.6 || ^3.0",
"laminas/laminas-servicemanager": "^3.2.1",
"phpunit/phpunit": "^7.5.20"
},
"suggest": {
"laminas/laminas-crypt": "Crammd5 support in SMTP Auth",
"laminas/laminas-servicemanager": "^2.7.10 || ^3.3.1 when using SMTP to deliver messages"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Mail",
"config-provider": "Laminas\\Mail\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Mail\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"mail"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-mail/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-mail/issues",
"rss": "https://github.com/laminas/laminas-mail/releases.atom",
"source": "https://github.com/laminas/laminas-mail"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2020-12-31T11:41:57+00:00"
},
{
"name": "laminas/laminas-mime",
"version": "2.7.4",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-mime.git",
"reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-mime/zipball/e45a7d856bf7b4a7b5bd00d6371f9961dc233add",
"reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add",
"shasum": ""
},
"require": {
"laminas/laminas-stdlib": "^2.7 || ^3.0",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-mime": "^2.7.2"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-mail": "^2.6",
"phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20"
},
"suggest": {
"laminas/laminas-mail": "Laminas\\Mail component"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7.x-dev",
"dev-develop": "2.8.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Mime\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Create and parse MIME messages and parts",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"mime"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-mime/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-mime/issues",
"rss": "https://github.com/laminas/laminas-mime/releases.atom",
"source": "https://github.com/laminas/laminas-mime"
},
"time": "2020-03-29T13:12:07+00:00"
},
{
"name": "laminas/laminas-servicemanager",
"version": "3.5.2",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-servicemanager.git",
"reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/0669e1eec8d9f61e35a5bc5012796d49f418b259",
"reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.2",
"laminas/laminas-stdlib": "^3.2.1",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0",
"psr/container": "^1.0"
},
"provide": {
"container-interop/container-interop-implementation": "^1.2",
"psr/container-implementation": "^1.0"
},
"replace": {
"zendframework/zend-servicemanager": "^3.4.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"mikey179/vfsstream": "^1.6.5",
"ocramius/proxy-manager": "^1.0 || ^2.0",
"phpbench/phpbench": "^0.13.0",
"phpunit/phpunit": "^5.7.25 || ^6.4.4"
},
"suggest": {
"laminas/laminas-stdlib": "laminas-stdlib ^2.5 if you wish to use the MergeReplaceKey or MergeRemoveKey features in Config instances",
"ocramius/proxy-manager": "ProxyManager 1.* to handle lazy initialization of services"
},
"bin": [
"bin/generate-deps-for-config-factory",
"bin/generate-factory-for-class"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.3-dev",
"dev-develop": "4.0-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Factory-Driven Dependency Injection Container",
"homepage": "https://laminas.dev",
"keywords": [
"PSR-11",
"dependency-injection",
"di",
"dic",
"laminas",
"service-manager",
"servicemanager"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
"source": "https://github.com/laminas/laminas-servicemanager"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2021-01-17T16:54:43+00:00"
},
{
"name": "laminas/laminas-stdlib",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-stdlib.git",
"reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/2b18347625a2f06a1a485acfbc870f699dbe51c6",
"reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6",
"shasum": ""
},
"require": {
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^5.6 || ^7.0"
},
"replace": {
"zendframework/zend-stdlib": "self.version"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"phpbench/phpbench": "^0.13",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev",
"dev-develop": "3.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Laminas\\Stdlib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "SPL extensions, array utilities, error handlers, and more",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"stdlib"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-stdlib/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-stdlib/issues",
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
"source": "https://github.com/laminas/laminas-stdlib"
},
"time": "2019-12-31T17:51:15+00:00"
},
{
"name": "laminas/laminas-validator",
"version": "2.13.5",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-validator.git",
"reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-validator/zipball/d334dddda43af263d6a7e5024fd2b013cb6981f7",
"reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.1",
"laminas/laminas-stdlib": "^3.2.1",
"laminas/laminas-zendframework-bridge": "^1.0",
"php": "^7.1"
},
"replace": {
"zendframework/zend-validator": "^2.13.0"
},
"require-dev": {
"laminas/laminas-cache": "^2.6.1",
"laminas/laminas-coding-standard": "~1.0.0",
"laminas/laminas-config": "^2.6",
"laminas/laminas-db": "^2.7",
"laminas/laminas-filter": "^2.6",
"laminas/laminas-http": "^2.5.4",
"laminas/laminas-i18n": "^2.6",
"laminas/laminas-math": "^2.6",
"laminas/laminas-servicemanager": "^2.7.5 || ^3.0.3",
"laminas/laminas-session": "^2.8",
"laminas/laminas-uri": "^2.5",
"phpunit/phpunit": "^7.5.20 || ^8.5.2",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0"
},
"suggest": {
"laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator",
"laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator",
"laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages",
"laminas/laminas-i18n-resources": "Translations of validator messages",
"laminas/laminas-math": "Laminas\\Math component, required by the Csrf validator",
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
"laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator",
"laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators",
"psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators"
},
"type": "library",
"extra": {
"laminas": {
"component": "Laminas\\Validator",
"config-provider": "Laminas\\Validator\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Laminas\\Validator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria",
"homepage": "https://laminas.dev",
"keywords": [
"laminas",
"validator"
],
"support": {
"chat": "https://laminas.dev/chat",
"docs": "https://docs.laminas.dev/laminas-validator/",
"forum": "https://discourse.laminas.dev",
"issues": "https://github.com/laminas/laminas-validator/issues",
"rss": "https://github.com/laminas/laminas-validator/releases.atom",
"source": "https://github.com/laminas/laminas-validator"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2021-01-06T15:05:04+00:00"
},
{
"name": "laminas/laminas-zendframework-bridge",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-zendframework-bridge.git",
"reference": "6ede70583e101030bcace4dcddd648f760ddf642"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642",
"reference": "6ede70583e101030bcace4dcddd648f760ddf642",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"extra": {
"laminas": {
"module": "Laminas\\ZendFrameworkBridge"
}
},
"autoload": {
"files": [
"src/autoload.php"
],
"psr-4": {
"Laminas\\ZendFrameworkBridge\\": "src//"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Alias legacy ZF class names to Laminas Project equivalents.",
"keywords": [
"ZendFramework",
"autoloading",
"laminas",
"zf"
],
"support": {
"forum": "https://discourse.laminas.dev/",
"issues": "https://github.com/laminas/laminas-zendframework-bridge/issues",
"rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom",
"source": "https://github.com/laminas/laminas-zendframework-bridge"
},
"funding": [
{
"url": "https://funding.communitybridge.org/projects/laminas-project",
"type": "community_bridge"
}
],
"time": "2020-09-14T14:23:00+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.12.0",
@@ -738,60 +1262,6 @@
],
"time": "2019-12-12T05:00:52+00:00"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.4.12",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "181b89f18a90f8925ef805f950d47a7190e9b950"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950",
"reference": "181b89f18a90f8925ef805f950d47a7190e9b950",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"mockery/mockery": "~0.9.1",
"symfony/phpunit-bridge": "~3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.4-dev"
}
},
"autoload": {
"files": [
"lib/swift_required.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Chris Corbyn"
},
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Swiftmailer, free feature-rich PHP mailer",
"homepage": "https://swiftmailer.symfony.com",
"keywords": [
"email",
"mail",
"mailer"
],
"time": "2018-07-31T09:26:32+00:00"
},
{
"name": "symfony/cache",
"version": "v3.4.47",
@@ -2696,6 +3166,56 @@
],
"time": "2020-10-24T10:57:07+00:00"
},
{
"name": "true/punycode",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/true/php-punycode.git",
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/polyfill-mbstring": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "~4.7",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"TrueBV\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Renan Gonçalves",
"email": "renan.saddam@gmail.com"
}
],
"description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
"homepage": "https://github.com/true/php-punycode",
"keywords": [
"idna",
"punycode"
],
"support": {
"issues": "https://github.com/true/php-punycode/issues",
"source": "https://github.com/true/php-punycode/tree/master"
},
"time": "2016-11-16T10:37:54+00:00"
},
{
"name": "twig/twig",
"version": "v1.42.4",
@@ -3007,5 +3527,5 @@
"platform-overrides": {
"php": "7.1.3"
},
"plugin-api-version": "2.1.0"
"plugin-api-version": "2.2.0"
}

View File

@@ -409,8 +409,6 @@ class AsyncSendEmail extends AsyncTask
$oNew->Set('to', $oEMail->GetRecipientTO(true /* string */));
$oNew->Set('subject', $oEMail->GetSubject());
// $oNew->Set('version', 1);
// $sMessage = serialize($oEMail);
$oNew->Set('version', 2);
$sMessage = $oEMail->SerializeV2();
$oNew->Set('message', $sMessage);

View File

@@ -351,19 +351,21 @@ class CMDBSource
}
/**
* Get the version of the database server.
*
* @return string
* @throws \MySQLException
*
* @uses \CMDBSource::QueryToCol() so needs a connection opened !
* @uses \CMDBSource::QueryToScalar() so needs a connection opened !
*/
public static function GetDBVersion()
{
$aVersions = self::QueryToCol('SELECT Version() as version', 'version');
return $aVersions[0];
return static::QueryToScalar('SELECT VERSION()', 0);
}
/**
* @return string
* @deprecated Use `CMDBSource::GetDBVersion` instead.
* @uses mysqli_get_server_info
*/
public static function GetServerInfo()
{
@@ -1499,20 +1501,14 @@ class CMDBSource
* Returns the value of the specified server variable
* @param string $sVarName Name of the server variable
* @return mixed Current value of the variable
*/
* @throws \MySQLQueryHasNoResultException|\MySQLException
*/
public static function GetServerVariable($sVarName)
{
$result = '';
$sSql = "SELECT @@$sVarName as theVar";
$aRows = self::QueryToArray($sSql);
if (count($aRows) > 0)
{
$result = $aRows[0]['theVar'];
}
return $result;
$sSql = 'SELECT @@'.$sVarName;
return static::QueryToScalar($sSql, 0) ?: '';
}
/**
* Returns the privileges of the current user
* @return string privileges in a raw format

View File

@@ -29,7 +29,7 @@ define('ITOP_APPLICATION_SHORT', 'iTop');
*
* @see ITOP_CORE_VERSION to get iTop core version
*/
define('ITOP_VERSION', '3.0.1-dev');
define('ITOP_VERSION', '3.1.0-dev');
define('ITOP_VERSION_NAME', 'Fullmoon');
define('ITOP_REVISION', 'svn');
@@ -1552,6 +1552,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'setup.launch_button.enabled' => [
'type' => 'bool',
'description' => 'If true displays in the Application Upgrade screen a button allowing to launch the setup in a single click (no more manual config file permission change needed)',
'default' => null,
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
];
public function IsProperty($sPropCode)

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<user_rights>
<profiles>
<profile id="1024" _delta="define">

View File

@@ -1732,6 +1732,7 @@ abstract class DBObject implements iDisplay
$iFlags = 0; // By default (if no life cycle) no flag at all
$sClass = get_class($this);
// The code below prevents to hide a DashboardAttribute for eg.
$aReadOnlyAtts = $this->GetReadOnlyAttributes();
if (($aReadOnlyAtts != null) && (in_array($sAttCode, $aReadOnlyAtts)))
{
@@ -3413,6 +3414,54 @@ abstract class DBObject implements iDisplay
return $this->m_iKey;
}
/**
* Increment attribute with specified value.
* This function is only applicable with AttributeInteger.
*
* @api
*
* @param string $sAttCode attribute code
* @param int $iValue value to increment (default value 1)
*
* @return int incremented value
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
public function DBIncrement(string $sAttCode, int $iValue = 1)
{
// retrieve instance class
$sClass = get_class($this);
// dirty object not allowed
if($this->m_bDirty){
throw new CoreException("Invalid DBIncrement usage, dirty objects are not allowed. Call DBUpdate before calling DBIncrement.");
}
// ensure attribute type is AttributeInteger
$oAttr = MetaModel::GetAttributeDef($sClass, $sAttCode);
if(!$oAttr instanceof AttributeInteger){
throw new CoreException(sprintf("Invalid DBIncrement usage, attribute type of {$sAttCode} is %s. Only AttributeInteger are compatibles with DBIncrement.", get_class($oAttr)));
}
// prepare SQL statement
$sTable = MetaModel::DBGetTable($sClass, $sAttCode);
$sPKField = '`'.MetaModel::DBGetKey($sClass).'`';
$sKey = CMDBSource::Quote($this->m_iKey);
$sUpdateSQL = "UPDATE `{$sTable}` SET `{$sAttCode}` = `{$sAttCode}`+{$iValue} WHERE {$sPKField} = {$sKey}";
// execute SQL query
CMDBSource::Query($sUpdateSQL);
// reload instance with new value
$this->Reload();
return $this->Get($sAttCode);
}
/**
* Activate TriggerOnObjectMention triggers for the current object
*

View File

@@ -413,6 +413,10 @@ class DBObjectSearch extends DBSearch
}
/**
* Important: If you need to add a condition on the same $sFilterCode several times with different $value values; do not use this method as the previous $value occurences will be replaced by the last. Instead use:
* * {@see \DBObjectSearch::AddConditionExpression()} in loops to add conditions one by one
* * {@see \DBObjectSearch::AddConditionForInOperatorUsingParam()} for IN/NOT IN queries with lots of params at once
*
* @param string $sFilterCode
* @param mixed $value
* @param string $sOpCode operator to use : 'IN', 'NOT IN', 'Contains',' Begins with', 'Finishes with', ...
@@ -423,8 +427,6 @@ class DBObjectSearch extends DBSearch
* @param bool $bParseSearchString
*
* @throws \CoreException
*
* @see AddConditionForInOperatorUsingParam for IN/NOT IN queries with lots of params
*/
public function AddCondition($sFilterCode, $value, $sOpCode = null, $bParseSearchString = false)
{

View File

@@ -24,13 +24,18 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
use Laminas\Mail\Header\ContentType;
use Laminas\Mail\Message;
use Laminas\Mail\Transport\File;
use Laminas\Mail\Transport\FileOptions;
use Laminas\Mail\Transport\SmtpOptions;
use Laminas\Mail\Transport\Smtp;
use Laminas\Mime\Mime;
use Laminas\Mime\Part;
use Pelago\Emogrifier\CssInliner;
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
Swift_Preferences::getInstance()->setCharset('UTF-8');
define ('EMAIL_SEND_OK', 0);
define ('EMAIL_SEND_PENDING', 1);
define ('EMAIL_SEND_ERROR', 2);
@@ -58,7 +63,8 @@ class EMail
public function __construct()
{
$this->m_aData = array();
$this->m_oMessage = Swift_Message::newInstance();
$this->m_oMessage = new Message();
$this->m_oMessage->setEncoding('UTF-8');
$this->SetRecipientFrom(MetaModel::GetConfig()->Get('email_default_sender_address'), MetaModel::GetConfig()->Get('email_default_sender_label'));
}
@@ -72,12 +78,18 @@ class EMail
{
return serialize($this->m_aData);
}
/**
* Custom de-serialization method
*
* @param string $sSerializedMessage The serialized representation of the message
*
* @return \EMail
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
*/
static public function UnSerializeV2($sSerializedMessage)
public static function UnSerializeV2($sSerializedMessage)
{
$aData = unserialize($sSerializedMessage);
$oMessage = new Email();
@@ -115,7 +127,6 @@ class EMail
$oMessage->SetSubject($aData['subject']);
}
if (array_key_exists('headers', $aData))
{
foreach($aData['headers'] as $sKey => $sValue)
@@ -155,10 +166,11 @@ class EMail
return EMAIL_SEND_PENDING;
}
/**
* @throws \Exception
*/
protected function SendSynchronous(&$aIssues, $oLog = null)
{
// If the body of the message is in HTML, embed all images based on attachments
$this->EmbedInlineImages();
$this->LoadConfig();
@@ -172,50 +184,54 @@ class EMail
$sUserName = self::$m_oConfig->Get('email_transport_smtp.username');
$sPassword = self::$m_oConfig->Get('email_transport_smtp.password');
$oTransport = Swift_SmtpTransport::newInstance($sHost, $sPort, $sEncryption);
$oTransport = new Smtp();
$aOptions= [
'host' => $sHost,
'port' => $sPort,
'connection_class' => 'login',
'connection_config' => [
'ssl' => $sEncryption,
],
];
if (strlen($sUserName) > 0)
{
$oTransport->setUsername($sUserName);
$oTransport->setPassword($sPassword);
$aOptions['connection_config']['username'] = $sUserName;
$aOptions['connection_config']['password'] = $sPassword;
}
$oOptions = new SmtpOptions($aOptions);
$oTransport->setOptions($oOptions);
break;
case 'Null':
$oTransport = Swift_NullTransport::newInstance();
$oTransport = new Smtp();
break;
case 'LogFile':
$oTransport = Swift_LogFileTransport::newInstance();
$oTransport->setLogFile(APPROOT.'log/mail.log');
$oTransport = new File();
$aOptions = new FileOptions([
'path' => APPROOT.'log/mail.log',
]);
$oTransport->setOptions($aOptions);
break;
case 'PHPMail':
default:
$oTransport = Swift_MailTransport::newInstance();
$oTransport = new Smtp();
}
$oMailer = Swift_Mailer::newInstance($oTransport);
$aFailedRecipients = array();
$this->m_oMessage->setMaxLineLength(0);
$oKPI = new ExecutionKPI();
try
{
$iSent = $oMailer->send($this->m_oMessage, $aFailedRecipients);
if ($iSent === 0)
{
// Beware: it seems that $aFailedRecipients sometimes contains the recipients that actually received the message !!!
IssueLog::Warning('Email sending failed: Some recipients were invalid, aFailedRecipients contains: '.implode(', ', $aFailedRecipients));
$aIssues = array('Some recipients were invalid.');
$oKPI->ComputeStats('Email Sent', 'Error received');
return EMAIL_SEND_ERROR;
}
else
{
$aIssues = array();
$oKPI->ComputeStats('Email Sent', 'Succeded');
return EMAIL_SEND_OK;
}
$oTransport->send($this->m_oMessage);
$aIssues = array();
$oKPI->ComputeStats('Email Sent', 'Succeded');
return EMAIL_SEND_OK;
}
catch(Laminas\Mail\Transport\Exception\RuntimeException $e){
IssueLog::Warning('Email sending failed: Some recipients were invalid');
$aIssues = array('Some recipients were invalid.');
$oKPI->ComputeStats('Email Sent', 'Error received');
return EMAIL_SEND_ERROR;
}
catch (Exception $e)
{
@@ -223,51 +239,65 @@ class EMail
throw $e;
}
}
/**
* Reprocess the body of the message (if it is an HTML message)
* to replace the URL of images based on attachments by a link
* to an embedded image (i.e. cid:....)
* to an embedded image (i.e. cid:....) and returns images to be attached as an array
*
* @param string $sBody Email body to process/alter
*
* @return array Array of Part that needs to be added as inline attachment later to render as embed
* @throws \ArchivedObjectException
* @throws \CoreException
*/
protected function EmbedInlineImages()
protected function EmbedInlineImages(string &$sBody)
{
if ($this->m_aData['body']['mimeType'] == 'text/html')
$oDOMDoc = new DOMDocument();
$oDOMDoc->preserveWhitespace = true;
@$oDOMDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sBody); // For loading HTML chunks where the character set is not specified
$oXPath = new DOMXPath($oDOMDoc);
$sXPath = '//img[@'.InlineImage::DOM_ATTR_ID.']';
$oImagesList = $oXPath->query($sXPath);
$oImagesContent = new \Laminas\Mime\Message();
$aImagesParts = [];
if ($oImagesList->length != 0)
{
$oDOMDoc = new DOMDocument();
$oDOMDoc->preserveWhitespace = true;
@$oDOMDoc->loadHTML('<?xml encoding="UTF-8"?>'.$this->m_aData['body']['body']); // For loading HTML chunks where the character set is not specified
$oXPath = new DOMXPath($oDOMDoc);
$sXPath = '//img[@'.InlineImage::DOM_ATTR_ID.']';
$oImagesList = $oXPath->query($sXPath);
if ($oImagesList->length != 0)
foreach($oImagesList as $oImg)
{
foreach($oImagesList as $oImg)
$iAttId = $oImg->getAttribute(InlineImage::DOM_ATTR_ID);
$oAttachment = MetaModel::GetObject('InlineImage', $iAttId, false, true /* Allow All Data */);
if ($oAttachment)
{
$iAttId = $oImg->getAttribute(InlineImage::DOM_ATTR_ID);
$oAttachment = MetaModel::GetObject('InlineImage', $iAttId, false, true /* Allow All Data */);
if ($oAttachment)
$sImageSecret = $oImg->getAttribute('data-img-secret');
$sAttachmentSecret = $oAttachment->Get('secret');
if ($sImageSecret !== $sAttachmentSecret)
{
$sImageSecret = $oImg->getAttribute('data-img-secret');
$sAttachmentSecret = $oAttachment->Get('secret');
if ($sImageSecret !== $sAttachmentSecret)
{
// @see N°1921
// If copying from another iTop we could get an IMG pointing to an InlineImage with wrong secret
continue;
}
$oDoc = $oAttachment->Get('contents');
$oSwiftImage = new Swift_Image($oDoc->GetData(), $oDoc->GetFileName(), $oDoc->GetMimeType());
$sCid = $this->m_oMessage->embed($oSwiftImage);
$oImg->setAttribute('src', $sCid);
// @see N°1921
// If copying from another iTop we could get an IMG pointing to an InlineImage with wrong secret
continue;
}
$oDoc = $oAttachment->Get('contents');
$sCid = uniqid('', true);
$oNewAttachment = new Part($oDoc->GetData());
$oNewAttachment->id = $sCid;
$oNewAttachment->type = $oDoc->GetMimeType();
$oNewAttachment->filename = $oDoc->GetFileName();
$oNewAttachment->disposition = Mime::DISPOSITION_INLINE;
$oNewAttachment->encoding = Mime::ENCODING_BASE64;
$oImagesContent->addPart($oNewAttachment);
$oImg->setAttribute('src', 'cid:'.$sCid);
$aImagesParts[] = $oNewAttachment;
}
}
$sHtmlBody = $oDOMDoc->saveHTML();
$this->m_oMessage->setBody($sHtmlBody, 'text/html', 'UTF-8');
}
$sBody = $oDOMDoc->saveHTML();
return $aImagesParts;
}
public function Send(&$aIssues, $bForceSynchronous = false, $oLog = null)
@@ -313,7 +343,7 @@ class EMail
break;
default:
$oHeaders->addTextHeader($sKey, $sValue);
$oHeaders->addHeaderLine($sKey, $sValue);
}
}
}
@@ -326,8 +356,7 @@ class EMail
// so let's remove the angle brackets if present, for historical reasons
$sId = str_replace(array('<', '>'), '', $sId);
$oMsgId = $this->m_oMessage->getHeaders()->get('Message-ID');
$oMsgId->SetId($sId);
$this->m_oMessage->getHeaders()->addHeaderLine('Message-ID', $sId);
}
public function SetReferences($sReferences)
@@ -349,35 +378,123 @@ class EMail
$this->AddToHeader('In-Reply-To', $sMessageId);
}
public function SetBody($sBody, $sMimeType = 'text/html', $sCustomStyles = null)
/**
* Set current Email body and process inline images.
*
* @param $sBody
* @param string $sMimeType
* @param $sCustomStyles
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
*/
public function SetBody($sBody, string $sMimeType = Mime::TYPE_HTML, $sCustomStyles = null)
{
if (($sMimeType === 'text/html') && ($sCustomStyles !== null)) {
$oBody = new Laminas\Mime\Message();
$aAdditionalParts = [];
if (($sMimeType === Mime::TYPE_HTML) && ($sCustomStyles !== null)) {
$oDomDocument = CssInliner::fromHtml($sBody)->inlineCss($sCustomStyles)->getDomDocument();
HtmlPruner::fromDomDocument($oDomDocument)->removeElementsWithDisplayNone();
$sBody = CssToAttributeConverter::fromDomDocument($oDomDocument)->convertCssToVisualAttributes()->render(); // Adds html/body tags if not already present
}
$this->m_aData['body'] = array('body' => $sBody, 'mimeType' => $sMimeType);
$this->m_oMessage->setBody($sBody, $sMimeType);
// We don't want these modifications in m_aData['body'], otherwise it'll ruin asynchronous mail as they go through this method twice
if ($sMimeType === Mime::TYPE_HTML){
$aAdditionalParts = $this->EmbedInlineImages($sBody);
}
// Add body content to as a new part
$oNewPart = new Part($sBody);
$oNewPart->encoding = Mime::ENCODING_8BIT;
$oNewPart->type = $sMimeType;
$oBody->addPart($oNewPart);
// Add additional images as new body parts
foreach ($aAdditionalParts as $oAdditionalPart) {
$oBody->addPart($oAdditionalPart);
}
if($oBody->isMultiPart()){
$oContentTypeHeader = $this->m_oMessage->getHeaders();
foreach ($oContentTypeHeader as $oHeader) {
if (!$oHeader instanceof ContentType) {
continue;
}
$oHeader->setType(Mime::MULTIPART_MIXED);
$oHeader->addParameter('boundary', $oBody->getMime()->boundary());
break;
}
}
$this->m_oMessage->setBody($oBody);
}
public function AddPart($sText, $sMimeType = 'text/html')
/**
* Add a new part to the existing body
* @param $sText
* @param string $sMimeType
*
* @return void
*/
public function AddPart($sText, string $sMimeType = Mime::TYPE_HTML)
{
if (!array_key_exists('parts', $this->m_aData))
{
$this->m_aData['parts'] = array();
}
$this->m_aData['parts'][] = array('text' => $sText, 'mimeType' => $sMimeType);
$this->m_oMessage->addPart($sText, $sMimeType);
$oNewPart = new Part($sText);
$oNewPart->encoding = Mime::ENCODING_8BIT;
$oNewPart->type = $sMimeType;
$this->m_oMessage->getBody()->addPart($oNewPart);
}
public function AddAttachment($data, $sFileName, $sMimeType)
{
$oBody = $this->m_oMessage->getBody();
if(!$oBody->isMultiPart()){
$multipart_content = new Part($oBody->generateMessage());
$multipart_content->setType($oBody->getParts()[0]->getType());
$multipart_content->setBoundary($oBody->getMime()->boundary());
$oBody = new Laminas\Mime\Message();
$oBody->addPart($multipart_content);
}
if (!array_key_exists('attachments', $this->m_aData))
{
$this->m_aData['attachments'] = array();
}
$this->m_aData['attachments'][] = array('data' => base64_encode($data), 'filename' => $sFileName, 'mimeType' => $sMimeType);
$this->m_oMessage->attach(Swift_Attachment::newInstance($data, $sFileName, $sMimeType));
$oNewAttachment = new Part($data);
$oNewAttachment->type = $sMimeType;
$oNewAttachment->filename = $sFileName;
$oNewAttachment->disposition = Mime::DISPOSITION_ATTACHMENT;
$oNewAttachment->encoding = Mime::ENCODING_BASE64;
$oBody->addPart($oNewAttachment);
if($oBody->isMultiPart()){
$oContentTypeHeader = $this->m_oMessage->getHeaders();
foreach ($oContentTypeHeader as $oHeader) {
if (!$oHeader instanceof ContentType) {
continue;
}
$oHeader->setType(Mime::MULTIPART_MIXED);
$oHeader->addParameter('boundary', $oBody->getMime()->boundary());
break;
}
}
$this->m_oMessage->setBody($oBody);
}
public function SetSubject($sSubject)
@@ -422,7 +539,7 @@ class EMail
public function GetRecipientTO($bAsString = false)
{
$aRes = $this->m_oMessage->getTo();
if ($aRes === null)
if ($aRes === null || $aRes->count() === 0)
{
// There is no "To" header field
$aRes = array();
@@ -430,8 +547,10 @@ class EMail
if ($bAsString)
{
$aStrings = array();
foreach ($aRes as $sEmail => $sName)
foreach ($aRes as $oEmail)
{
$sName = $oEmail->getName();
$sEmail = $oEmail->getEmail();
if (is_null($sName))
{
$aStrings[] = $sEmail;
@@ -496,77 +615,4 @@ class EMail
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
/**
* Extension to SwiftMailer: "debug" transport that pretends messages have been sent,
* but just log them to a file.
*
* @package Swift
* @author Denis Flaven
*/
class Swift_Transport_LogFileTransport extends Swift_Transport_NullTransport
{
protected $sLogFile;
/**
* Sends the given message.
*
* @param Swift_Mime_Message $message
* @param string[] $failedRecipients An array of failures by-reference
*
* @return int The number of sent emails
*/
public function send(Swift_Mime_Message $message, &$failedRecipients = null)
{
$hFile = @fopen($this->sLogFile, 'a');
if ($hFile)
{
$sTxt = "================== ".date('Y-m-d H:i:s')." ==================\n";
$sTxt .= $message->toString()."\n";
@fwrite($hFile, $sTxt);
@fclose($hFile);
}
return parent::send($message, $failedRecipients);
}
public function setLogFile($sFilename)
{
$this->sLogFile = $sFilename;
}
}
/**
* Pretends messages have been sent, but just log them to a file.
*
* @package Swift
* @author Denis Flaven
*/
class Swift_LogFileTransport extends Swift_Transport_LogFileTransport
{
/**
* Create a new LogFileTransport.
*/
public function __construct()
{
call_user_func_array(
array($this, 'Swift_Transport_LogFileTransport::__construct'),
Swift_DependencyContainer::getInstance()
->createDependenciesFor('transport.null')
);
}
/**
* Create a new LogFileTransport instance.
*
* @return Swift_LogFileTransport
*/
public static function newInstance()
{
return new self();
}
}

View File

@@ -1010,6 +1010,11 @@ class DeadLockLog extends LogAPI
class DeprecatedCallsLog extends LogAPI
{
public const ENUM_CHANNEL_PHP_METHOD = 'deprecated-php-method';
/**
* @var string
* @since 3.1.0
*/
public const ENUM_CHANNEL_PHP_ENDPOINT = 'deprecated-php-endpoint';
public const ENUM_CHANNEL_PHP_LIBMETHOD = 'deprecated-php-libmethod';
public const ENUM_CHANNEL_FILE = 'deprecated-file';
public const CHANNEL_DEFAULT = self::ENUM_CHANNEL_PHP_METHOD;
@@ -1222,6 +1227,35 @@ class DeprecatedCallsLog extends LogAPI
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_METHOD);
}
/**
* @param string|null $sAdditionalMessage
* @since 3.1.0
*/
public static function NotifyDeprecatedPhpEndpoint(?string $sAdditionalMessage = null): void
{
try {
if (!static::IsLogLevelEnabled(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_ENDPOINT)) {
return;
}
}
catch (ConfigException $e) {
return;
}
$aStack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
$iStackDeprecatedMethodLevel = 0; // level 0 = current method, level 1 = method containing the `NotifyDeprecatedPhpMethod` call
$sDeprecatedUrl = $_SERVER['REQUEST_URI'];
$sCallerFile = $aStack[$iStackDeprecatedMethodLevel]['file'];
$sCallerLine = $aStack[$iStackDeprecatedMethodLevel]['line'];
$sMessage = "Call to endpoint {$sDeprecatedUrl} in {$sCallerFile}#L{$sCallerLine}";
if (!is_null($sAdditionalMessage)) {
$sMessage .= ' : '.$sAdditionalMessage;
}
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_ENDPOINT);
}
public static function Log($sLevel, $sMessage, $sChannel = null, $aContext = array()): void
{
if (true === utils::IsDevelopmentEnvironment()) {

View File

@@ -7145,20 +7145,28 @@ abstract class MetaModel
/**
* @param string $sClass
* @param string $sAttCode
* @param $value
* @param mixed $value
* @param bool $bMustBeFoundUnique
* @param bool $bAllowAllData
*
* @return \DBObject if $bMustBeFoundUnique=true and no object or multiple objects found will throw a CoreException
* else will return null
*
* @return \DBObject
* @throws \CoreException
* @throws \Exception
* @throws \CoreUnexpectedValue
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*
* @since 2.7.7 Add new $bAllowAllData parameter
*/
public static function GetObjectByColumn($sClass, $sAttCode, $value, $bMustBeFoundUnique = true)
public static function GetObjectByColumn($sClass, $sAttCode, $value, $bMustBeFoundUnique = true, $bAllowAllData = false)
{
if (!isset(self::$m_aCacheObjectByColumn[$sClass][$sAttCode][$value]))
{
if (!isset(self::$m_aCacheObjectByColumn[$sClass][$sAttCode][$value])) {
self::_check_subclass($sClass);
$oObjSearch = new DBObjectSearch($sClass);
$oObjSearch->AllowAllData($bAllowAllData);
$oObjSearch->AddCondition($sAttCode, $value, '=');
$oSet = new DBObjectSet($oObjSearch);
if ($oSet->Count() == 1)

View File

@@ -135,6 +135,7 @@ class ObjectResult
*/
class RestResultWithObjects extends RestResult
{
/** @var array "DBObject_class:DBObject_key" as key, {@see \ObjectResult} as value */
public $objects;
/**

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants>
</constants>
<classes>

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-cas/3.0.1',
'authent-cas/3.1.0',
array(
// Identification
//

View File

@@ -27,7 +27,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-external/3.0.1',
'authent-external/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="UserLDAP" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -9,7 +9,7 @@ if (function_exists('ldap_connect'))
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-ldap/3.0.1',
'authent-ldap/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<module_parameters>
<parameters id="authent-local" _delta="define">

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-local/3.0.1',
'authent-local/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<branding>
<themes>
<theme id="darkmoon" _delta="define">

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-backoffice-darkmoon-theme/3.0.1',
'combodo-backoffice-darkmoon-theme/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<menus>
<menu id="DBToolsMenu" xsi:type="WebPageMenuNode" _delta="define">
<rank>30</rank>

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-db-tools/3.0.1',
'combodo-db-tools/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Attachment" _delta="define">
<parent>DBObject</parent>

View File

@@ -19,7 +19,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-attachments/3.0.1',
'itop-attachments/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<menus>
<menu id="BackupStatus" xsi:type="WebPageMenuNode" _delta="define">
<rank>50</rank>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-backup/3.0.1',
'itop-backup/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants></constants>
<classes>
<class id="lnkFunctionalCIToTicket" _delta="define">

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-cmdb-ticket/3.0.1',
'itop-bridge-cmdb-ticket/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="lnkVirtualDeviceToVolume" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-virtualization-storage/3.0.1',
'itop-bridge-virtualization-storage/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Change" _delta="define">
<parent>Ticket</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt-itil/3.0.1',
'itop-change-mgmt-itil/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Change" _delta="define">
<parent>Ticket</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt/3.0.1',
'itop-change-mgmt/3.1.0',
array(
// Identification
//
@@ -85,7 +85,7 @@ class ChangeManagementInstaller extends ModuleInstallerAPI
if (CMDBSource::IsField($sSourceTable, $sField) && CMDBSource::IsField($sTargetTable, $sField) && CMDBSource::IsField($sSourceTable, $sSourceKeyField) && CMDBSource::IsField($sTargetTable, $sTargetKeyField))
{
SetupWebPage::log_info("Issue #464 - Copying change/start_date into ticket/start_date");
SetupLog::Info("Issue #464 - Copying change/start_date into ticket/start_date");
$sRepair = "UPDATE `$sTargetTable`, `$sSourceTable` SET `$sTargetTable`.`$sField` = `$sSourceTable`.`$sField` WHERE `$sTargetTable`.`$sField` IS NULL AND`$sTargetTable`.`$sTargetKeyField` = `$sSourceTable`.`$sSourceKeyField`";
CMDBSource::Query($sRepair);
}

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="FunctionalCI" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -5828,30 +5828,69 @@
<type>Overload-cmdbAbstractObject</type>
<code><![CDATA[ protected function UpdateConnectedNetworkDevice()
{
$oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'));
if (is_object($oDevice) && (get_class($oDevice) == 'NetworkDevice'))
{
// Note: in case a port has been changed, search with the original values
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
$aFields = array('networkdevice_id','connectableci_id','network_port','device_port','connection_type');
$aChanges = $this->ListPreviousValuesForUpdatedAttributes();
$aPrev = array(); // Previous values of the current link object before it was modified
foreach ($aFields as $sFieldCode) {
$aPrev[$sFieldCode] = array_key_exists($sFieldCode, $aChanges) ? $aChanges[$sFieldCode] : $this->Get($sFieldCode);
}
$sPrevLink = ($aPrev['connection_type'] == 'uplink') ? 'downlink' : 'uplink';
$sConnLink = ($this->Get('connection_type') == 'uplink') ? 'downlink' : 'uplink';
$oNewDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'), false);
$oPrevDevice = MetaModel::GetObject('ConnectableCI', $aPrev['connectableci_id'], false);
$bNew = (is_object($oNewDevice) && (get_class($oNewDevice) == 'NetworkDevice'));
$bPrev = (is_object($oPrevDevice) && (get_class($oPrevDevice) == 'NetworkDevice'));
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport AND connection_type = :link";
if ($bPrev) { // There was a twin
// Retrieve twin link using previous values of the current link
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
array(),
array(
'network' => $aPrev['connectableci_id'],
'device' => $aPrev['networkdevice_id'],
'devport' => $aPrev['network_port'],
'nwport' => $aPrev['device_port'],
'link' => $sPrevLink,
)
);
if ($bNew) { // and a twin must still exist, so update the existing
while ($oConnection = $oConnectionSet->Fetch()) {
$oConnection->Set('networkdevice_id', $this->Get('connectableci_id'));
$oConnection->Set('connectableci_id', $this->Get('networkdevice_id'));
$oConnection->Set('network_port', $this->Get('device_port'));
$oConnection->Set('device_port', $this->Get('network_port'));
$oConnection->Set('connection_type',$sConnLink);
$oConnection->DBUpdate();
}
}
else { // and no twin is needed anymore, so delete the existing
while ($oConnection = $oConnectionSet->Fetch()) {
$oConnection->DBDelete();
}
}
}
elseif ($bNew) { // There was no twin but a twin must exist now
// Search for a twin link using current values inverted
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
array(),
array(
'network' => $this->Get('connectableci_id'),
'device' => $this->Get('networkdevice_id'),
'devport' => $this->GetOriginal('network_port'),
'nwport' => $this->GetOriginal('device_port'),
'devport' => $this->Get('device_port'),
'nwport' => $this->Get('network_port'),
'link' => $sConnLink,
)
);
$sLink = $this->Get('connection_type');
$sConnLink = ($sLink == 'uplink') ? 'downlink' : 'uplink';
// There should be one link - do it in a safe manner anyway
while ($oConnection = $oConnectionSet->Fetch())
{
$oConnection->Set('connection_type', $sConnLink);
$oConnection->Set('network_port', $this->Get('device_port'));
$oConnection->Set('device_port', $this->Get('network_port'));
$oConnection->DBUpdate();
if ($oConnectionSet->Count() == 0) {
$oNewLink = new lnkConnectableCIToNetworkDevice();
$oNewLink->Set('networkdevice_id', $this->Get('connectableci_id'));
$oNewLink->Set('connectableci_id', $this->Get('networkdevice_id'));
$oNewLink->Set('network_port', $this->Get('device_port'));
$oNewLink->Set('device_port', $this->Get('network_port'));
$oNewLink->Set('connection_type', $sConnLink);
$oNewLink->DBInsert();
}
}
}]]></code>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config-mgmt/3.0.1',
'itop-config-mgmt/3.1.0',
array(
// Identification
//

View File

@@ -189,14 +189,16 @@ try {
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('operation', 'save'));
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('transaction_id', utils::GetNewTransactionId()));
// - Cancel button
//--- Cancel button
$oCancelButton = ButtonUIBlockFactory::MakeForCancel(Dict::S('config-cancel'), 'cancel_button', null, true, 'cancel_button');
$oCancelButton->SetOnClickJsCode("return ResetConfig();");
$oForm->AddSubBlock($oCancelButton);
// - Submit button
//--- Submit button
$oSubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('config-apply'), null, Dict::S('config-apply'), true, 'submit_button');
$oForm->AddSubBlock($oSubmitButton);
//--- Config editor
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('prev_config', $sOriginalConfigEscaped, 'prev_config'));
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('new_config', $sConfigEscaped));
$oForm->AddHtml("<div id =\"new_config\" style=\"position: absolute; top: ".$iEditorTopMargin."em; bottom: 0; left: 5px; right: 5px;\"></div>");

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<menus>
<menu id="ConfigEditor" xsi:type="WebPageMenuNode" _delta="define">
<rank>10</rank>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config/3.0.1',
'itop-config/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<menus>
<menu id="iTopUpdate" xsi:type="WebPageMenuNode" _delta="define">
<rank>60</rank>

View File

@@ -54,6 +54,7 @@ Dict::Add('EN US', 'English', 'English', array(
'iTopUpdate:UI:Status' => 'Status',
'iTopUpdate:UI:Action' => 'Update',
'iTopUpdate:UI:Setup' => ITOP_APPLICATION_SHORT.' Setup',
'iTopUpdate:UI:History' => 'Versions History',
'iTopUpdate:UI:Progress' => 'Progress of the upgrade',
@@ -81,6 +82,9 @@ Dict::Add('EN US', 'English', 'English', array(
'iTopUpdate:UI:SetupLaunch' => 'Launch '.ITOP_APPLICATION_SHORT.' Setup',
'iTopUpdate:UI:SetupLaunchConfirm' => 'This will launch '.ITOP_APPLICATION_SHORT.' setup, are you sure?',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start',
'iTopUpdate:UI:SetupMessage:EnterMaintenance' => 'Entering maintenance mode',

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-core-update/3.0.1',
'itop-core-update/3.1.0',
array(
// Identification
//

View File

@@ -17,6 +17,7 @@ use Dict;
use Exception;
use IssueLog;
use MetaModel;
use SecurityException;
use SetupUtils;
use utils;
@@ -211,8 +212,7 @@ class AjaxController extends Controller
CoreUpdater::UpdateDatabase();
$iResponseCode = 200;
}
catch (Exception $e)
{
catch (Exception $e) {
IssueLog::Error("Compile: ".$e->getMessage());
$aParams['sError'] = $e->getMessage();
$iResponseCode = 500;
@@ -220,4 +220,22 @@ class AjaxController extends Controller
$this->DisplayJSONPage($aParams, $iResponseCode);
}
/**
* @throws \SecurityException if CSRF token invalid
*
* @since 3.1.0 N°4919
*/
public function OperationLaunchSetup()
{
$sTransactionId = utils::ReadParam('transaction_id', '', false, 'transaction_id');
if (false === utils::IsTransactionValid($sTransactionId)) {
throw new SecurityException('Access forbidden');
}
$sConfigFile = APPCONF.'production/config-itop.php';
@chmod($sConfigFile, 0770); // Allow overwriting the file
header('Location: ../setup/');
}
}

View File

@@ -35,6 +35,25 @@ class UpdateController extends Controller
$oSet = new DBObjectSet($oFilter, ['installed' => false]); // Most recent first
$aParams['oSet'] = $oSet;
$oConfig = utils::GetConfig();
$bConfigParamSetupLaunchButtonEnabled = $oConfig->Get('setup.launch_button.enabled');
if (is_null($bConfigParamSetupLaunchButtonEnabled)) {
$bIsSetupLaunchButtonEnabled = utils::IsDevelopmentEnvironment();
} else if (false === $bConfigParamSetupLaunchButtonEnabled) {
$bIsSetupLaunchButtonEnabled = false;
} else {
$bIsSetupLaunchButtonEnabled = $bConfigParamSetupLaunchButtonEnabled || utils::IsDevelopmentEnvironment();
}
$aParams['bIsSetupLaunchButtonEnabled'] = $bIsSetupLaunchButtonEnabled;
if ($bIsSetupLaunchButtonEnabled) {
$sLaunchSetupUrl = utils::GetAbsoluteUrlModulePage('itop-core-update', 'ajax.php',
[
'operation' => 'LaunchSetup',
'transaction_id' => $sTransactionId,
]);;
$aParams['sLaunchSetupUrl'] = $sLaunchSetupUrl;
}
$this->DisplayPage($aParams);
}

View File

@@ -87,6 +87,14 @@
{% EndUIFieldSet %}
{% if bIsSetupLaunchButtonEnabled %}
{% UIFieldSet Standard {'sLegend':'iTopUpdate:UI:Setup'|dict_s} %}
{% UIForm Standard {'sId':'launch-setup-form', Action:sLaunchSetupUrl} %}
{% UIButton ForDestructiveAction {'sLabel':'iTopUpdate:UI:SetupLaunch'|dict_s, 'sName':'launch-setup', 'sValue':'launch-setup', 'bIsSubmit':true, 'sId':'launch-setup'} %}
{% EndUIForm %}
{% EndUIFieldSet %}
{% endif %}
{% UIFieldSet Standard {'sLegend':'iTopUpdate:UI:History'|dict_s} %}
{% UIDataTable ForRendering {'sListId':'iboupdatehistory', 'oSet':oSet} %}{% EndUIDataTable %}
{% EndUIFieldSet %}

View File

@@ -101,3 +101,7 @@ $("#check-update").on("click", function(e) {
e.stopPropagation();
return false;
});
$("#launch-setup-form").on("submit", function () {
return window.confirm("{{ 'iTopUpdate:UI:SetupLaunchConfirm'|dict_s }}");
});

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Rack" _delta="define">
<parent>PhysicalDevice</parent>

View File

@@ -18,7 +18,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-datacenter-mgmt/3.0.1',
'itop-datacenter-mgmt/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="TelephonyCI" _delta="define">
<parent>PhysicalDevice</parent>

View File

@@ -25,7 +25,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-endusers-devices/3.0.1',
'itop-endusers-devices/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="FAQ" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-faq-light/3.0.1',
'itop-faq-light/3.1.0',
array(
// Identification
//

View File

@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
</itop_design>

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-files-information/3.0.1',
'itop-files-information/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Ticket">
<methods>

View File

@@ -6,7 +6,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-full-itil/3.0.1',
'itop-full-itil/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<constants>
</constants>
<classes>

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-hub-connector/3.0.1',
'itop-hub-connector/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Incident" _delta="define">
<parent>Ticket</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-incident-mgmt-itil/3.0.1',
'itop-incident-mgmt-itil/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="KnownError" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-knownerror-mgmt/3.0.1',
'itop-knownerror-mgmt/3.1.0',
array(
// Identification
//

View File

@@ -20,7 +20,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-portal-base/3.0.1', array(
'itop-portal-base/3.1.0', array(
// Identification
'label' => 'Portal Development Library',
'category' => 'Portal',

View File

@@ -35,6 +35,11 @@ p_object_view:
defaults:
_controller: 'Combodo\iTop\Portal\Controller\ObjectController::ViewAction'
p_object_view_from_attribute:
path: '/object/view/{sObjectClass}/{sObjectAttCode}/{sObjectAttValue}'
defaults:
_controller: 'Combodo\iTop\Portal\Controller\ObjectController::ViewFromAttributeAction'
p_object_apply_stimulus:
path: '/object/apply-stimulus/{sStimulusCode}/{sObjectClass}/{sObjectId}'
defaults:

View File

@@ -66,11 +66,11 @@ class ObjectController extends BrickController
const DEFAULT_LIST_LENGTH = 10;
/**
* Displays an cmdbAbstractObject if the connected user is allowed to.
* Displays an cmdbAbstractObject (from its ID) if the connected user is allowed to.
*
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sObjectClass (Class must be instance of cmdbAbstractObject)
* @param string $sObjectId
* @param string $sObjectClass (Class must be an instance of cmdbAbstractObject)
* @param string $sObjectId
*
* @return \Symfony\Component\HttpFoundation\Response
*
@@ -83,29 +83,19 @@ class ObjectController extends BrickController
*/
public function ViewAction(Request $oRequest, $sObjectClass, $sObjectId)
{
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
/** @var \Combodo\iTop\Portal\Routing\UrlGenerator $oUrlGenerator */
$oUrlGenerator = $this->get('url_generator');
/** @var \Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper $oObjectFormHandler */
$oObjectFormHandler = $this->get('object_form_handler');
/** @var \Combodo\iTop\Portal\Helper\SecurityHelper $oSecurityHelper */
$oSecurityHelper = $this->get('security_helper');
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
$oScopeValidator = $this->get('scope_validator');
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
$oBrickCollection = $this->get('brick_collection');
// Checking parameters
if ($sObjectClass === '' || $sObjectId === '')
{
if ($sObjectClass === '' || $sObjectId === '') {
IssueLog::Info(__METHOD__.' at line '.__LINE__.' : sObjectClass and sObjectId expected, "'.$sObjectClass.'" and "'.$sObjectId.'" given.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, Dict::Format('UI:Error:2ParametersMissing', 'class', 'id'));
}
// Checking security layers
if (!$oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sObjectClass, $sObjectId))
{
if (!$oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sObjectClass, $sObjectId)) {
IssueLog::Warning(__METHOD__.' at line '.__LINE__.' : User #'.UserRights::GetUserId().' not allowed to read '.$sObjectClass.'::'.$sObjectId.' object.');
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
}
@@ -113,14 +103,97 @@ class ObjectController extends BrickController
// Retrieving object
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */,
$oScopeValidator->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
if ($oObject === null)
{
if ($oObject === null) {
// We should never be there as the secuirty helper makes sure that the object exists, but just in case.
IssueLog::Info(__METHOD__.' at line '.__LINE__.' : Could not load object '.$sObjectClass.'::'.$sObjectId.'.');
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
}
return $this->PrepareViewObjectResponse($oRequest, $oObject);
}
/**
* Displays an cmdbAbstractObject (if the connected user is allowed to) from a specific attribute. If several or none objects are found with the attribute value, an exception is thrown.
*
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sObjectClass (Class must be an instance of cmdbAbstractObject)
* @param string $sObjectAttCode
* @param string $sObjectAttValue
*
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response|null
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*
* @since 2.7.7 method creation
*/
public function ViewFromAttributeAction(Request $oRequest, $sObjectClass, $sObjectAttCode, $sObjectAttValue)
{
/** @var \Combodo\iTop\Portal\Helper\SecurityHelper $oSecurityHelper */
$oSecurityHelper = $this->get('security_helper');
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
$oScopeValidator = $this->get('scope_validator');
// Checking parameters
if ($sObjectClass === '' || $sObjectAttCode === '' || $sObjectAttValue === '') {
IssueLog::Info(__METHOD__.' at line '.__LINE__.' : sObjectClass and sObjectAttCode/sObjectAttValue expected, "'
.$sObjectClass.'" and "'.$sObjectAttCode.' / '.$sObjectAttValue.'" given.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, Dict::Format('UI:Error:3ParametersMissing', 'class', 'attcode', 'attvalue'));
}
$oObject = MetaModel::GetObjectByColumn($sObjectClass, $sObjectAttCode, $sObjectAttValue, false,
$oScopeValidator->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
if ($oObject === null) {
// null if object not found or multiple matches
IssueLog::Info(__METHOD__.' at line '.__LINE__.' : Could not load object '.$sObjectClass.'" and "'.$sObjectAttCode.' / '.$sObjectAttValue.'.');
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
}
// Checking security layers
$sObjectId = $oObject->GetKey();
if (!$oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sObjectClass, $sObjectId)) {
IssueLog::Warning(__METHOD__.' at line '.__LINE__.' : User #'.UserRights::GetUserId().' not allowed to read '.$sObjectClass.'::'.$sObjectId.' object.');
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
}
return $this->PrepareViewObjectResponse($oRequest, $oObject);
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \DBObject $oObject
*
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response|null
* @throws \ArchivedObjectException
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*
* @since 2.7.7 method creation (refactor for new `p_object_view_from_attribute` route)
*/
protected function PrepareViewObjectResponse(Request $oRequest, DBObject $oObject)
{
/** @var \Combodo\iTop\Portal\Helper\SecurityHelper $oSecurityHelper */
$oSecurityHelper = $this->get('security_helper');
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
/** @var \Combodo\iTop\Portal\Routing\UrlGenerator $oUrlGenerator */
$oUrlGenerator = $this->get('url_generator');
/** @var \Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper $oObjectFormHandler */
$oObjectFormHandler = $this->get('object_form_handler');
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
$oBrickCollection = $this->get('brick_collection');
$sOperation = $oRequestManipulator->ReadParam('operation', '');
$sObjectClass = get_class($oObject);
$sObjectId = $oObject->GetKey();
$aData = array('sMode' => 'view');
$aData['form'] = $oObjectFormHandler->HandleForm($oRequest, $aData['sMode'], $sObjectClass, $sObjectId);
@@ -128,8 +201,7 @@ class ObjectController extends BrickController
$oObject->GetName());
// Add an edit button if user is allowed
if ($oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sObjectClass, $sObjectId))
{
if ($oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sObjectClass, $sObjectId)) {
$sModifyUrl = $oUrlGenerator->generate('p_object_edit', array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId));
$oModifyButton = new JSButtonItem(
'modify_object',
@@ -141,27 +213,19 @@ class ObjectController extends BrickController
}
// Preparing response
if ($oRequest->isXmlHttpRequest())
{
if ($oRequest->isXmlHttpRequest()) {
// We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
if (empty($sOperation))
{
if (empty($sOperation)) {
$oResponse = $this->render('itop-portal-base/portal/templates/bricks/object/modal.html.twig', $aData);
}
else
{
} else {
$oResponse = new JsonResponse($aData);
}
}
else
{
} else {
// Adding brick if it was passed
$sBrickId = $oRequestManipulator->ReadParam('sBrickId', '');
if (!empty($sBrickId))
{
if (!empty($sBrickId)) {
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
if ($oBrick !== null)
{
if ($oBrick !== null) {
$aData['oBrick'] = $oBrick;
}
}
@@ -864,6 +928,7 @@ class ObjectController extends BrickController
if (!empty($sQuery))
{
$oFullExpr = null;
/** @noinspection SlowArrayOperationsInLoopInspection */
for ($i = 0; $i < count($aAttCodes); $i++)
{
// Checking if the current attcode is an external key in order to search on the friendlyname

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<portals>
<portal id="itop-portal" _delta="define"><!-- ID must match module_design[id] -->
<url>pages/exec.php?exec_module=itop-portal-base&amp;exec_page=index.php&amp;portal_id=itop-portal</url><!-- portal_id must match module_design[id] -->

View File

@@ -20,7 +20,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-portal/3.0.1', array(
'itop-portal/3.1.0', array(
// Identification
'label' => 'Enhanced Customer Portal',
'category' => 'Portal',

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Problem" _delta="define">
<parent>Ticket</parent>
@@ -175,6 +175,10 @@
<default_value>1</default_value>
<is_null_allowed>false</is_null_allowed>
<display_style>list</display_style>
<dependencies>
<attribute id="impact"/>
<attribute id="urgency"/>
</dependencies>
</field>
<field id="related_change_id" xsi:type="AttributeExternalKey">
<filter><![CDATA[SELECT Change WHERE status != "closed"]]></filter>
@@ -564,10 +568,10 @@
<rank>50</rank>
</item>
<item id="related_incident_list">
<rank>50</rank>
<rank>60</rank>
</item>
<item id="col:col1">
<rank>60</rank>
<rank>70</rank>
<items>
<item id="fieldset:Ticket:baseinfo">
<rank>10</rank>
@@ -575,31 +579,44 @@
<item id="ref">
<rank>10</rank>
</item>
<item id="title">
<item id="org_id">
<rank>20</rank>
</item>
<item id="org_id">
<item id="caller_id">
<rank>30</rank>
</item>
<item id="status">
<rank>40</rank>
</item>
<item id="priority">
<item id="product">
<rank>50</rank>
</item>
<item id="service_id">
<item id="title">
<rank>60</rank>
</item>
<item id="servicesubcategory_id">
<item id="description">
<rank>70</rank>
</item>
<item id="product">
<rank>80</rank>
</item>
</items>
</item>
<item id="fieldset:Ticket:moreinfo">
<rank>20</rank>
<items>
<item id="service_id">
<rank>10</rank>
</item>
<item id="servicesubcategory_id">
<rank>20</rank>
</item>
</items>
</item>
</items>
</item>
<item id="col:col2">
<rank>80</rank>
<items>
<item id="fieldset:Ticket:Type">
<rank>10</rank>
<items>
<item id="impact">
<rank>10</rank>
@@ -607,18 +624,13 @@
<item id="urgency">
<rank>20</rank>
</item>
<item id="description">
<item id="priority">
<rank>30</rank>
</item>
</items>
</item>
</items>
</item>
<item id="col:col2">
<rank>70</rank>
<items>
<item id="fieldset:Ticket:date">
<rank>10</rank>
<rank>20</rank>
<items>
<item id="start_date">
<rank>10</rank>
@@ -637,22 +649,25 @@
</item>
</items>
</item>
</items>
</item>
<item id="col:col3">
<rank>90</rank>
<items>
<item id="fieldset:Ticket:contact">
<rank>20</rank>
<rank>10</rank>
<items>
<item id="caller_id">
<item id="team_id">
<rank>10</rank>
</item>
<item id="team_id">
<rank>20</rank>
</item>
<item id="agent_id">
<rank>30</rank>
<rank>20</rank>
</item>
</items>
</item>
<item id="fieldset:Ticket:relation">
<rank>30</rank>
<rank>20</rank>
<items>
<item id="related_change_id">
<rank>10</rank>
@@ -743,9 +758,9 @@
<menus>
<menu id="ProblemManagement" xsi:type="MenuGroup" _delta="define_if_not_exists">
<rank>42</rank>
<style>
<decoration_classes>fas fa-question</decoration_classes>
</style>
<style>
<decoration_classes>fas fa-question</decoration_classes>
</style>
</menu>
<menu id="Problem:Shortcuts" xsi:type="TemplateMenuNode" _delta="define_if_not_exists">
<rank>5</rank>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-problem-mgmt/3.0.1',
'itop-problem-mgmt/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes/>
<user_rights>
<groups>

View File

@@ -19,7 +19,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-profiles-itil/3.0.1',
'itop-profiles-itil/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="UserRequest" _delta="define">
<parent>Ticket</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-request-mgmt-itil/3.0.1',
'itop-request-mgmt-itil/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="UserRequest" _delta="define">
<parent>Ticket</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-request-mgmt/3.0.1',
'itop-request-mgmt/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Organization">
<fields>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-service-mgmt-provider/3.0.1',
'itop-service-mgmt-provider/3.1.0',
array(
// Identification
//

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="3.0">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
<classes>
<class id="Organization">
<fields>
@@ -1544,120 +1544,100 @@ public function PrefillSearchForm(&$aContextParam)
</reconciliation>
</properties>
<fields>
<field id="name" xsi:type="AttributeString">
<sql>name</sql>
<default_value/>
<is_null_allowed>false</is_null_allowed>
</field>
<field id="description" xsi:type="AttributeText">
<sql>description</sql>
<default_value/>
<is_null_allowed>true</is_null_allowed>
</field>
<field id="org_id" xsi:type="AttributeExternalKey">
<sql>org_id</sql>
<target_class>Organization</target_class>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_MANUAL</on_target_delete>
</field>
<field id="organization_name" xsi:type="AttributeExternalField">
<extkey_attcode>org_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="slts_list" xsi:type="AttributeLinkedSetIndirect">
<linked_class>lnkSLAToSLT</linked_class>
<ext_key_to_me>sla_id</ext_key_to_me>
<count_min>0</count_min>
<count_max>0</count_max>
<ext_key_to_remote>slt_id</ext_key_to_remote>
<duplicates/>
</field>
<field id="customercontracts_list" xsi:type="AttributeLinkedSetIndirect">
<linked_class>lnkCustomerContractToService</linked_class>
<ext_key_to_me>sla_id</ext_key_to_me>
<count_min>0</count_min>
<count_max>0</count_max>
<ext_key_to_remote>customercontract_id</ext_key_to_remote>
<duplicates>true</duplicates>
</field>
</fields>
<methods>
<method id="DoCheckToWrite">
<static>false</static>
<access>public</access>
<code><![CDATA[
public function DoCheckToWrite()
{
parent::DoCheckToWrite();
$aCustomerContracts = $this->Get("customercontracts_list");
foreach ($aCustomerContracts as $sAttCode => $oCustomerContracts)
{
// Recurse inside the subdirectories
$sOql = "SELECT lnkCustomerContractToService AS ccs WHERE ccs.customercontract_id=:customercontract_id AND ccs.service_id=:service_id";
$aQueryParams['customercontract_id'] = $oCustomerContracts->Get("customercontract_id");
$aQueryParams['service_id'] = $oCustomerContracts->Get("service_id");
if ($this->Get("id") != null)
{
$sOql = $sOql." AND ccs.sla_id!=:sla_id";
$aQueryParams['sla_id'] = $this->Get("id");
}
$oQuery = DBSearch::FromOQL($sOql, $aQueryParams);
$oResultSql = new DBObjectSet($oQuery);
$oResultSql->OptimizeColumnLoad(['ccs' => ['customercontract_name','service_name']]);
if ($aCurrentRow = $oResultSql->Fetch())
{
$this->m_aCheckIssues[] = Dict::Format('Class:SLA/Error:UniqueLnkCustomerContractToService',$aCurrentRow->Get('customercontract_name'),$aCurrentRow->Get('service_name'));
}
}
}
]]></code>
</method>
</methods>
<field id="name" xsi:type="AttributeString">
<sql>name</sql>
<default_value/>
<is_null_allowed>false</is_null_allowed>
</field>
<field id="description" xsi:type="AttributeText">
<sql>description</sql>
<default_value/>
<is_null_allowed>true</is_null_allowed>
</field>
<field id="org_id" xsi:type="AttributeExternalKey">
<sql>org_id</sql>
<target_class>Organization</target_class>
<is_null_allowed>false</is_null_allowed>
<on_target_delete>DEL_MANUAL</on_target_delete>
</field>
<field id="organization_name" xsi:type="AttributeExternalField">
<extkey_attcode>org_id</extkey_attcode>
<target_attcode>name</target_attcode>
</field>
<field id="slts_list" xsi:type="AttributeLinkedSetIndirect">
<linked_class>lnkSLAToSLT</linked_class>
<ext_key_to_me>sla_id</ext_key_to_me>
<count_min>0</count_min>
<count_max>0</count_max>
<ext_key_to_remote>slt_id</ext_key_to_remote>
<duplicates/>
</field>
<field id="customercontracts_list" xsi:type="AttributeLinkedSet">
<linked_class>lnkCustomerContractToService</linked_class>
<ext_key_to_me>sla_id</ext_key_to_me>
<count_min>0</count_min>
<count_max>0</count_max>
<edit_mode>none</edit_mode>
</field>
</fields>
<methods/>
<presentation>
<details>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="org_id">
<rank>20</rank>
</item>
<item id="description">
<rank>30</rank>
</item>
<item id="slts_list">
<rank>40</rank>
</item>
<item id="customercontracts_list">
<rank>50</rank>
</item>
</items>
</details>
<search>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="org_id">
<rank>20</rank>
</item>
<item id="description">
<rank>30</rank>
</item>
</items>
</search>
<list>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="org_id">
<rank>20</rank>
</item>
</items>
</list>
</presentation>
<details>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="org_id">
<rank>20</rank>
</item>
<item id="description">
<rank>30</rank>
</item>
<item id="slts_list">
<rank>40</rank>
</item>
<item id="customercontracts_list">
<rank>50</rank>
</item>
</items>
</details>
<search>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="org_id">
<rank>20</rank>
</item>
<item id="description">
<rank>30</rank>
</item>
</items>
</search>
<default_search>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="org_id">
<rank>20</rank>
</item>
<item id="description">
<rank>30</rank>
</item>
</items>
</default_search>
<list>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="org_id">
<rank>20</rank>
</item>
</items>
</list>
</presentation>
</class>
<class id="SLT" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -1748,83 +1728,110 @@ public function PrefillSearchForm(&$aContextParam)
<values>
<value id="hours">
<code>hours</code>
</value>
<value id="minutes">
<code>minutes</code>
</value>
</values>
<sql>unit</sql>
<default_value/>
<is_null_allowed>true</is_null_allowed>
<display_style>radio_horizontal</display_style>
</field>
</fields>
</value>
<value id="minutes">
<code>minutes</code>
</value>
</values>
<sql>unit</sql>
<default_value/>
<is_null_allowed>true</is_null_allowed>
<display_style>radio_horizontal</display_style>
</field>
<field id="slas_list" xsi:type="AttributeLinkedSetIndirect">
<linked_class>lnkSLAToSLT</linked_class>
<ext_key_to_me>slt_id</ext_key_to_me>
<count_min>0</count_min>
<count_max>0</count_max>
<ext_key_to_remote>sla_id</ext_key_to_remote>
<duplicates/>
</field>
</fields>
<methods/>
<presentation>
<details>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="priority">
<rank>20</rank>
</item>
<item id="request_type">
<rank>30</rank>
</item>
<item id="metric">
<rank>40</rank>
</item>
<item id="value">
<rank>50</rank>
</item>
<item id="unit">
<rank>60</rank>
</item>
</items>
</details>
<search>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="priority">
<rank>20</rank>
</item>
<item id="request_type">
<rank>30</rank>
</item>
<item id="metric">
<rank>40</rank>
</item>
<item id="value">
<rank>50</rank>
</item>
<item id="unit">
<rank>60</rank>
</item>
</items>
</search>
<list>
<items>
<item id="priority">
<rank>10</rank>
</item>
<item id="request_type">
<rank>20</rank>
</item>
<item id="metric">
<rank>30</rank>
</item>
<item id="value">
<rank>40</rank>
</item>
<item id="unit">
<rank>50</rank>
</item>
</items>
</list>
</presentation>
</item>
<item id="priority">
<rank>20</rank>
</item>
<item id="request_type">
<rank>30</rank>
</item>
<item id="metric">
<rank>40</rank>
</item>
<item id="value">
<rank>50</rank>
</item>
<item id="unit">
<rank>60</rank>
</item>
<item id="slas_list">
<rank>100</rank>
</item>
</items>
</details>
<search>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="priority">
<rank>20</rank>
</item>
<item id="request_type">
<rank>30</rank>
</item>
<item id="metric">
<rank>40</rank>
</item>
<item id="value">
<rank>50</rank>
</item>
<item id="unit">
<rank>60</rank>
</item>
</items>
</search>
<default_search>
<items>
<item id="name">
<rank>10</rank>
</item>
<item id="priority">
<rank>20</rank>
</item>
<item id="request_type">
<rank>30</rank>
</item>
<item id="metric">
<rank>40</rank>
</item>
</items>
</default_search>
<list>
<items>
<item id="priority">
<rank>10</rank>
</item>
<item id="request_type">
<rank>20</rank>
</item>
<item id="metric">
<rank>30</rank>
</item>
<item id="value">
<rank>40</rank>
</item>
<item id="unit">
<rank>50</rank>
</item>
</items>
</list>
</presentation>
</class>
<class id="lnkSLAToSLT" _delta="define">
<parent>cmdbAbstractObject</parent>

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