mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
🌐 Update nl.dictionary.itop.ui.php (#125)
This commit is contained in:
@@ -101,7 +101,7 @@ if ($sMode == 'install')
|
||||
$oMysqli = new mysqli($sDBServer, $sDBUser, $sDBPwd);
|
||||
if ($oMysqli->connect_errno)
|
||||
{
|
||||
die("Cannot connect to the MySQL server (".$mysqli->connect_errno . ") ".$mysqli->connect_error."\nExiting");
|
||||
die("Cannot connect to the MySQL server (".$oMysqli->connect_errno . ") ".$oMysqli->connect_error."\nExiting");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -37,57 +37,68 @@ If you want to use another license, you may [create an extension][wiki new ext].
|
||||
[wiki new ext]: https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Astart#by_writing_your_own_extension
|
||||
|
||||
|
||||
## 🔀 Branch model
|
||||
## 🔀 iTop branch model
|
||||
|
||||
TL;DR:
|
||||
> **create a fork from iTop main repository,
|
||||
> create a branch based on the develop branch**
|
||||
When we first start with Git, we were using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. As
|
||||
there was some confusions about branches to use for current developed release and previous maintained release, and also because we were
|
||||
using just a very few of the GitFlow commands, we decided to add just a little modification to this branch model : since april 2020
|
||||
we don't have anymore a `master` branch.
|
||||
|
||||
We are using the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branch model. That means we have in our repo those
|
||||
main branches:
|
||||
Here are the branches we use and their meaning :
|
||||
|
||||
- develop: ongoing development version
|
||||
- release/\*: if present, that means we are working on a beta version
|
||||
- master: previous stable version
|
||||
- support/\*: maintenance branches for older versions
|
||||
- `develop`: ongoing development version
|
||||
- `release/*`: if present, that means we are working on a alpha/beta/rc version for shipping
|
||||
- `support/*`: maintenance branches for older versions
|
||||
|
||||
For example, if no beta version is currently ongoing we could have:
|
||||
For example, if no version is currently prepared for shipping we could have:
|
||||
|
||||
- develop containing future 2.8.0 version
|
||||
- master containing 2.7.x maintenance version
|
||||
- support/2.6 containing 2.6.x maintenance version
|
||||
- support/2.5 containing 2.5.x maintenance version
|
||||
- `develop` containing future 2.8.0 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 2.8.0-beta is shipped that will become:
|
||||
|
||||
- develop: future 2.9.0 version
|
||||
- release/2.8: 2.8.0-beta
|
||||
- master: 2.7.x maintenance version
|
||||
- support/2.6 containing 2.6.x maintenance version
|
||||
- support/2.5 containing 2.5.x maintenance version
|
||||
- `develop`: future 2.9.0 version
|
||||
- `release/2.8`: 2.8.0-beta
|
||||
- `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 2.8.0 final will be out:
|
||||
|
||||
- develop: future 2.9.0 version
|
||||
- master: 2.8.x maintenance version
|
||||
- support/2.7 : 2.7.x maintenance version
|
||||
- support/2.6 containing 2.6.x maintenance version
|
||||
- support/2.5 containing 2.5.x maintenance version
|
||||
- `develop`: future 2.9.0 version
|
||||
- `support/2.8`: 2.8.x maintenance version (will host developments for 2.8.1)
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
Most of the time you should based your developments on the develop branch.
|
||||
That may be different if you want to fix a bug, please use develop anyway and ask in your PR if rebase is possible.
|
||||
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.
|
||||
|
||||
|
||||
## Coding
|
||||
|
||||
### 🎨 PHP styleguide
|
||||
|
||||
Please follow [our guidelines](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Acoding_standards).
|
||||
|
||||
### 🌐 Translations
|
||||
|
||||
A [dedicated page](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Atranslation) is available in the official wiki.
|
||||
|
||||
### Where to start ?
|
||||
|
||||
1. Create a fork from our repository (see [Working with forks - GitHub Help](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/working-with-forks))
|
||||
2. Create a branch in this fork, based on the develop branch
|
||||
3. Code !
|
||||
|
||||
Do create a dedicated branch for each modification you want to propose : if you don't it will be very hard to merge back your work !
|
||||
|
||||
Most of the time you should based your developments on the develop branch.
|
||||
That may be different if you want to fix a bug, please use develop anyway and ask in your PR if rebase is possible.
|
||||
|
||||
|
||||
### 🎨 PHP styleguide
|
||||
|
||||
Please follow [our guidelines](https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Acoding_standards).
|
||||
|
||||
### ✅ Tests
|
||||
|
||||
Please create tests that covers as much as possible the code you're submitting.
|
||||
|
||||
@@ -128,6 +128,7 @@ We would like to give a special thank you to the people from the community who c
|
||||
- Schirrmann, Pascal
|
||||
- Seki, Shoji
|
||||
- Shilov, Vladimir
|
||||
- Tahri, Ahmed R. (Ousret)
|
||||
- Tulio, Marco
|
||||
- Turrubiates, Miguel
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
class DataTable
|
||||
{
|
||||
protected $iListId; // Unique ID inside the web page
|
||||
/** @var string */
|
||||
private $sDatatableContainerId;
|
||||
protected $sTableId; // identifier for saving the settings (combined with the class aliases)
|
||||
protected $oSet; // The set of objects to display
|
||||
protected $aClassAliases; // The aliases (alias => class) inside the set
|
||||
@@ -29,10 +31,10 @@ class DataTable
|
||||
protected $bShowObsoleteData;
|
||||
|
||||
/**
|
||||
* @param $iListId mixed Unique ID for this div/table in the page
|
||||
* @param $oSet DBObjectSet The set of data to display
|
||||
* @param $aClassAliases array The list of classes/aliases to be displayed in this set $sAlias => $sClassName
|
||||
* @param $sTableId mixed A string (or null) identifying this table in order to persist its settings
|
||||
* @param string $iListId Unique ID for this div/table in the page
|
||||
* @param DBObjectSet $oSet The set of data to display
|
||||
* @param array$aClassAliases The list of classes/aliases to be displayed in this set $sAlias => $sClassName
|
||||
* @param string $sTableId A string (or null) identifying this table in order to persist its settings
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
@@ -42,6 +44,7 @@ class DataTable
|
||||
public function __construct($iListId, $oSet, $aClassAliases, $sTableId = null)
|
||||
{
|
||||
$this->iListId = utils::GetSafeId($iListId); // Make a "safe" ID for jQuery
|
||||
$this->sDatatableContainerId = 'datatable_'.utils::GetSafeId($iListId);
|
||||
$this->oSet = $oSet;
|
||||
$this->aClassAliases = $aClassAliases;
|
||||
$this->sTableId = $sTableId;
|
||||
@@ -165,7 +168,7 @@ class DataTable
|
||||
$sDataTable = $this->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams);
|
||||
$sConfigDlg = $this->GetTableConfigDlg($oPage, $aColumns, $bViewLink, $iDefaultPageSize);
|
||||
|
||||
$sHtml = "<table id=\"datatable_{$this->iListId}\" class=\"datatable\">";
|
||||
$sHtml = "<table id=\"{$this->sDatatableContainerId}\" class=\"datatable\">";
|
||||
$sHtml .= "<tr><td>";
|
||||
$sHtml .= "<table style=\"width:100%;\">";
|
||||
$sHtml .= "<tr><td class=\"pagination_container\">$sObjectsCount</td><td class=\"menucontainer\">$sToolkitMenu $sActionsMenu</td></tr>";
|
||||
@@ -201,7 +204,7 @@ class DataTable
|
||||
$aOptions['oDefaultSettings'] = $this->GetAsHash($this->oDefaultSettings);
|
||||
}
|
||||
$sJSOptions = json_encode($aOptions);
|
||||
$oPage->add_ready_script("$('#datatable_{$this->iListId}').datatable($sJSOptions);");
|
||||
$oPage->add_ready_script("$('#{$this->sDatatableContainerId}').datatable($sJSOptions);");
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
@@ -418,15 +421,15 @@ EOF;
|
||||
$sHtml .= "<input id=\"dtbl_dlg_all_{$this->iListId}\" type=\"radio\" name=\"scope\" $sGenericChecked value=\"defaults\"><label for=\"dtbl_dlg_all_{$this->iListId}\"> ".Dict::S('UI:ForAllLists').'</label></p>';
|
||||
$sHtml .= "</fieldset>";
|
||||
$sHtml .= '<table style="width:100%"><tr><td style="text-align:center;">';
|
||||
$sHtml .= '<button type="button" onclick="$(\'#datatable_'.$this->iListId.'\').datatable(\'onDlgCancel\'); $(\'#datatable_dlg_'.$this->iListId.'\').dialog(\'close\')">'.Dict::S('UI:Button:Cancel').'</button>';
|
||||
$sHtml .= '<button type="button" onclick="$(\'#'.$this->sDatatableContainerId.'\').datatable(\'onDlgCancel\'); $(\'#datatable_dlg_'.$this->iListId.'\').dialog(\'close\')">'.Dict::S('UI:Button:Cancel').'</button>';
|
||||
$sHtml .= '</td><td style="text-align:center;">';
|
||||
$sHtml .= '<button type="submit" onclick="$(\'#datatable_'.$this->iListId.'\').datatable(\'onDlgOk\');$(\'#datatable_dlg_'.$this->iListId.'\').dialog(\'close\');">'.Dict::S('UI:Button:Ok').'</button>';
|
||||
$sHtml .= '<button type="submit" onclick="$(\'#'.$this->sDatatableContainerId.'\').datatable(\'onDlgOk\');$(\'#datatable_dlg_'.$this->iListId.'\').dialog(\'close\');">'.Dict::S('UI:Button:Ok').'</button>';
|
||||
$sHtml .= '</td></tr></table>';
|
||||
$sHtml .= "</form>";
|
||||
$sHtml .= "</div>";
|
||||
|
||||
$sDlgTitle = addslashes(Dict::S('UI:ListConfigurationTitle'));
|
||||
$oPage->add_ready_script("$('#datatable_dlg_{$this->iListId}').dialog({autoOpen: false, title: '$sDlgTitle', width: 500, close: function() { $('#datatable_{$this->iListId}').datatable('onDlgCancel'); } });");
|
||||
$oPage->add_ready_script("$('#datatable_dlg_{$this->iListId}').dialog({autoOpen: false, title: '$sDlgTitle', width: 500, close: function() { $('#{$this->sDatatableContainerId}').datatable('onDlgCancel'); } });");
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
@@ -745,12 +748,25 @@ EOF;
|
||||
}
|
||||
$sOQL = addslashes($this->oSet->GetFilter()->serialize());
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
var oTable = $('#{$this->iListId} table.listResults');
|
||||
<<<JS
|
||||
var oTable = $('#{$this->sDatatableContainerId} table.listResults');
|
||||
oTable.tableHover();
|
||||
oTable.tablesorter( { $sHeaders widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $('#pager{$this->iListId}'), totalRows:$iCount, size: $iPageSize, filter: '$sOQL', extra_params: '$sExtraParams', select_mode: '$sSelectModeJS', displayKey: $sDisplayKey, table_id: '{$this->iListId}', columns: $sJSColumns, class_aliases: $sJSClassAliases $sCssCount});
|
||||
EOF
|
||||
);
|
||||
oTable
|
||||
.tablesorter({ $sHeaders widgets: ['myZebra', 'truncatedList']})
|
||||
.tablesorterPager({
|
||||
container: $('#pager{$this->iListId}'),
|
||||
totalRows:$iCount,
|
||||
size: $iPageSize,
|
||||
filter: '$sOQL',
|
||||
extra_params: '$sExtraParams',
|
||||
select_mode: '$sSelectModeJS',
|
||||
displayKey: $sDisplayKey,
|
||||
table_id: '{$this->sDatatableContainerId}',
|
||||
columns: $sJSColumns,
|
||||
class_aliases: $sJSClassAliases $sCssCount
|
||||
});
|
||||
JS
|
||||
);
|
||||
if ($sFakeSortList != '')
|
||||
{
|
||||
$oPage->add_ready_script("oTable.trigger(\"fakesorton\", [$sFakeSortList]);");
|
||||
|
||||
@@ -636,14 +636,22 @@ HTML
|
||||
$oSet->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||
|
||||
$sHKAttCode = MetaModel::IsHierarchicalClass($this->sTargetClass);
|
||||
$this->DumpTree($oPage, $oSet, $sHKAttCode, $currValue);
|
||||
$bHasChildLeafs = $this->DumpTree($oPage, $oSet, $sHKAttCode, $currValue);
|
||||
|
||||
$oPage->add('</td></tr></table>');
|
||||
$oPage->add('</div>');
|
||||
|
||||
if ($bHasChildLeafs)
|
||||
{
|
||||
$oPage->add('<div class="treecontrol" id="treecontrolid"><a href="?#">'.Dict::S("UI:Treeview:CollapseAll").'</a> | <a href="?#">'.Dict::S("UI:Treeview:ExpandAll").'</a></div>');
|
||||
}
|
||||
|
||||
$oPage->add("<input type=\"button\" id=\"btn_cancel_{$this->iId}\" value=\"".Dict::S('UI:Button:Cancel')."\" onClick=\"$('#dlg_tree_{$this->iId}').dialog('close');\"> ");
|
||||
$oPage->add("<input type=\"button\" id=\"btn_ok_{$this->iId}\" value=\"".Dict::S('UI:Button:Ok')."\" onClick=\"oACWidget_{$this->iId}.DoHKOk();\">");
|
||||
|
||||
$oPage->add('</div></div>');
|
||||
|
||||
$oPage->add_ready_script("\$('#tree_$this->iId ul').treeview({ control: '#treecontrolid', persist: 'false'});\n");
|
||||
$oPage->add_ready_script("\$('#tree_$this->iId ul').treeview();\n");
|
||||
$oPage->add_ready_script("\$('#dlg_tree_$this->iId').dialog({ width: 'auto', height: 'auto', autoOpen: true, modal: true, title: '$sDialogTitle', resizeStop: oACWidget_{$this->iId}.OnHKResize, close: oACWidget_{$this->iId}.OnHKClose });\n");
|
||||
}
|
||||
@@ -673,6 +681,18 @@ HTML
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebPage $oP
|
||||
* @param \DBObjectSet $oSet
|
||||
* @param string $sParentAttCode
|
||||
* @param string $currValue
|
||||
*
|
||||
* @return bool true if there are at least one child leaf, false if only roots nodes are present
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
function DumpTree($oP, $oSet, $sParentAttCode, $currValue)
|
||||
{
|
||||
$aTree = array();
|
||||
@@ -701,6 +721,9 @@ HTML
|
||||
{
|
||||
$this->DumpNodes($oP, $iRootId, $aTree, $aNodes, $currValue);
|
||||
}
|
||||
|
||||
$bHasOnlyRootNodes = (count($aTree) === 1);
|
||||
return !$bHasOnlyRootNodes;
|
||||
}
|
||||
|
||||
function DumpNodes($oP, $iRootId, $aTree, $aNodes, $currValue)
|
||||
@@ -728,7 +751,7 @@ HTML
|
||||
$sSelect = '<input id="input_'.$fUniqueId.'_'.$aNodes[$id]->GetKey().'" type="radio" value="'.$aNodes[$id]->GetKey().'" name="selectObject" '.$sChecked.'> ';
|
||||
}
|
||||
}
|
||||
$oP->add('<li>'.$sSelect.'<label for="input_'.$fUniqueId.'_'.$aNodes[$id]->GetKey().'">'.$aNodes[$id]->GetName().'</label>');
|
||||
$oP->add('<li class="closed">'.$sSelect.'<label for="input_'.$fUniqueId.'_'.$aNodes[$id]->GetKey().'">'.$aNodes[$id]->GetName().'</label>');
|
||||
$this->DumpNodes($oP, $id, $aTree, $aNodes, $currValue);
|
||||
$oP->add("</li>\n");
|
||||
}
|
||||
|
||||
@@ -2914,9 +2914,9 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Persist an object to the DB, for the first time
|
||||
*
|
||||
/**
|
||||
* Persist an object to the DB, for the first time
|
||||
*
|
||||
* @api
|
||||
* @see DBWrite
|
||||
*
|
||||
|
||||
@@ -304,8 +304,12 @@ class EMail
|
||||
$oHeaders = $this->m_oMessage->getHeaders();
|
||||
switch(strtolower($sKey))
|
||||
{
|
||||
case 'return-path':
|
||||
$this->m_oMessage->setReturnPath($sValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
$oHeaders->addTextHeader($sKey, $sValue);
|
||||
$oHeaders->addTextHeader($sKey, $sValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3891,3 +3891,16 @@ input:checked + .slider:before {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.ui-dialog .ui-dialog-content .treecontrol {
|
||||
padding-bottom:0.3em;
|
||||
padding-left: 0.2em;
|
||||
margin-top: -0.3em;
|
||||
padding-top: 0;
|
||||
|
||||
}
|
||||
.ui-dialog .ui-dialog-content .treecontrol a {
|
||||
font-size: small;
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"license": "AGPLv3",
|
||||
"config": {
|
||||
"classmap-authoritative": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Combodo\\iTop\\Portal\\": "src/"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<information>
|
||||
<version>2.7.0</version>
|
||||
<version>2.8.0-dev</version>
|
||||
</information>
|
||||
|
||||
@@ -423,6 +423,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:Button:More' => 'More',
|
||||
'UI:Button:Less' => 'Less',
|
||||
'UI:Button:Wait' => 'Please wait while updating fields',
|
||||
'UI:Treeview:CollapseAll' => 'Collapse All',
|
||||
'UI:Treeview:ExpandAll' => 'Expand All',
|
||||
|
||||
'UI:SearchToggle' => 'Search',
|
||||
'UI:ClickToCreateNew' => 'Create a new %1$s',
|
||||
|
||||
@@ -845,7 +845,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
|
||||
'UI:ModificationTitle_Class_Object' => 'Aanpassen van %1$s: <span class="hilite">%2$s</span>',
|
||||
'UI:ClonePageTitle_Object_Class' => 'ITOP_APPLICATION_SHORT - Kloon %1$s - %2$s aanpassing',
|
||||
'UI:CloneTitle_Class_Object' => 'Klonen van %1$s: <span class="hilite">%2$s</span>',
|
||||
'UI:CreationPageTitle_Class' => 'ITOP_APPLICATION_SHORT - Nieuwe %1$s aangemaakt',
|
||||
'UI:CreationPageTitle_Class' => 'ITOP_APPLICATION_SHORT - %1$s aanmaken',
|
||||
'UI:CreationTitle_Class' => '%1$s aanmaken',
|
||||
'UI:SelectTheTypeOf_Class_ToCreate' => 'Selecteer het type %1$s dat moet worden aangemaakt:',
|
||||
'UI:Class_Object_NotUpdated' => 'Geen verandering waargenomen, %1$s (%2$s) is <strong>niet</strong> aangepast.',
|
||||
|
||||
@@ -261,7 +261,7 @@ class MFModule
|
||||
while (($sFile = readdir($hDir)) !== false)
|
||||
{
|
||||
$aMatches = array();
|
||||
if (preg_match("/^[^\\.]+.dict.".$this->sName.".php$/i", $sFile,
|
||||
if (preg_match("/^[^\\.]+.dict.".$this->sName.'.php$/i', $sFile,
|
||||
$aMatches)) // Dictionary files are named like <Lang>.dict.<ModuleName>.php
|
||||
{
|
||||
$aDictionaries[] = $this->sRootDir.'/'.$sFile;
|
||||
@@ -1855,7 +1855,7 @@ class MFElement extends Combodo\iTop\DesignElement
|
||||
* Extracts some nodes from the DOM (active nodes only !!!)
|
||||
*
|
||||
* @param string $sXPath A XPath expression
|
||||
* @param $sId
|
||||
* @param string $sId
|
||||
*
|
||||
* @return DOMNodeList
|
||||
*/
|
||||
@@ -1867,7 +1867,7 @@ class MFElement extends Combodo\iTop\DesignElement
|
||||
/**
|
||||
* Returns the node directly under the given node
|
||||
*
|
||||
* @param $sTagName
|
||||
* @param string $sTagName
|
||||
* @param bool $bMustExist
|
||||
*
|
||||
* @return MFElement
|
||||
@@ -1903,7 +1903,7 @@ class MFElement extends Combodo\iTop\DesignElement
|
||||
*
|
||||
* @param string $sElementName
|
||||
*
|
||||
* @return array|null|string
|
||||
* @return array|string if no subnode is found, return current node text, else return results as array
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function GetNodeAsArrayOfItems($sElementName = 'items')
|
||||
@@ -2068,6 +2068,8 @@ class MFElement extends Combodo\iTop\DesignElement
|
||||
/**
|
||||
* Check if the current node is under a node 'added' or 'altered'
|
||||
* Usage: In such a case, the change must not be tracked
|
||||
*
|
||||
* @return boolean true if `_alteration` flag is set on any parent of the current node
|
||||
*/
|
||||
public function IsInDefinition()
|
||||
{
|
||||
@@ -2104,14 +2106,14 @@ class MFElement extends Combodo\iTop\DesignElement
|
||||
return false;
|
||||
}
|
||||
|
||||
static $aTraceAttributes = null;
|
||||
protected static $aTraceAttributes = null;
|
||||
|
||||
/**
|
||||
* Enable/disable the trace on changed nodes
|
||||
*
|
||||
* @param array aAttributes Array of attributes (key => value) to be added onto any changed node
|
||||
*/
|
||||
static public function SetTrace($aAttributes = null)
|
||||
public static function SetTrace($aAttributes = null)
|
||||
{
|
||||
self::$aTraceAttributes = $aAttributes;
|
||||
}
|
||||
@@ -2582,9 +2584,9 @@ class MFDocument extends \Combodo\iTop\DesignDocument
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sXPath
|
||||
* @param $sId
|
||||
* @param null $oContextNode
|
||||
* @param string $sXPath
|
||||
* @param string $sId
|
||||
* @param \DOMNode $oContextNode
|
||||
*
|
||||
* @return \DOMNodeList
|
||||
*/
|
||||
|
||||
72
test/core/BulkChangeTest.inc.php
Normal file
72
test/core/BulkChangeTest.inc.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Core;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class BulkChangeTest extends ItopDataTestCase
|
||||
{
|
||||
const CREATE_TEST_ORG = true;
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
require_once(APPROOT.'core/coreexception.class.inc.php');
|
||||
require_once(APPROOT.'core/bulkchange.class.inc.php');
|
||||
|
||||
}
|
||||
|
||||
//bug 2888: csv import / data synchro issue with password validation
|
||||
public function testPasswordBulkChangeIssue()
|
||||
{
|
||||
/** @var Personn $oPerson */
|
||||
$oPerson = $this->createObject('Person', array(
|
||||
'first_name' => 'isaac',
|
||||
'name' => 'asimov',
|
||||
'email' => 'isaac.asimov@fundation.org',
|
||||
'org_id' => $this->getTestOrgId(),
|
||||
));
|
||||
|
||||
$aData = array(
|
||||
array($oPerson->Get("first_name"),
|
||||
$oPerson->Get("name"),
|
||||
$oPerson->Get("email"),
|
||||
"EN US",
|
||||
"iasimov",
|
||||
"harryseldon",
|
||||
"profileid->name:Administrator"
|
||||
)
|
||||
);
|
||||
$aAttributes = array("language" => 3, "login" => 4, "password" => 5, "profile_list" => 6);
|
||||
$aExtKeys = array("contactid" =>
|
||||
array("first_name" => 0, "name" => 1, "email" => 2));
|
||||
$oBulk = new \BulkChange(
|
||||
"UserLocal",
|
||||
$aData,
|
||||
$aAttributes,
|
||||
$aExtKeys,
|
||||
array("login"),
|
||||
null,
|
||||
null,
|
||||
"Y-m-d H:i:s", // date format
|
||||
true // localize
|
||||
);
|
||||
|
||||
$oChange = \CMDBObject::GetCurrentChange();
|
||||
$aRes = $oBulk->Process($oChange);
|
||||
static::assertNotNull($aRes);
|
||||
|
||||
foreach ($aRes as $aRow)
|
||||
{
|
||||
if (array_key_exists('__STATUS__', $aRow))
|
||||
{
|
||||
$sStatus = $aRow['__STATUS__'];
|
||||
$this->assertFalse(strstr($sStatus->GetDescription(), "CoreCannotSaveObjectException"), "CSVimport/Datasynchro: Password validation failed with: " . $sStatus->GetDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,6 +56,9 @@ class DBSearchTest extends ItopDataTestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
require_once(APPROOT.'application/itopwebpage.class.inc.php');
|
||||
require_once(APPROOT.'application/displayblock.class.inc.php');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -656,4 +659,33 @@ class DBSearchTest extends ItopDataTestCase
|
||||
static::assertEquals('', $sExceptionClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function testSelectInWithVariableExpressions()
|
||||
{
|
||||
$aReq = array(array(1, 0, 0), array(1, 1, 3), array(1, 2, 1), array(1, 0, 1), array(1, 1, 0), array(1, 2, 1));
|
||||
$sOrgs = $this->init_db(3, 4, $aReq);
|
||||
$allOrgIds = explode(",", $sOrgs);
|
||||
|
||||
$TwoOrgIdsOnly = array($allOrgIds[0], $allOrgIds[1]);
|
||||
$oSearch = DBSearch::FromOQL("SELECT UserRequest WHERE org_id IN (:org_ids)");
|
||||
self::assertNotNull($oSearch);
|
||||
$oSet = new \CMDBObjectSet($oSearch, array(), array('org_ids'=> $TwoOrgIdsOnly));
|
||||
static::assertEquals(4, $oSet->Count());
|
||||
|
||||
$_SERVER['REQUEST_URI']='FAKE_REQUEST_URI' ;
|
||||
$_SERVER['REQUEST_METHOD']='FAKE_REQUEST_METHOD';
|
||||
$oP = new \iTopWebPage("test");
|
||||
$oBlock = new \DisplayBlock($oSet->GetFilter(), 'list', false);
|
||||
$sHtml = $oBlock->GetDisplay($oP, 'package_table', array ('menu'=>true, 'display_limit'=>false));
|
||||
|
||||
$iHtmlUserRequestLineCount = substr_count($sHtml, '<tr><td data-object-class="UserRequest"');
|
||||
static::assertEquals(4, $iHtmlUserRequestLineCount, "Failed Generated html :" . $sHtml);
|
||||
$oP->output();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ try
|
||||
utils::UseParamFile();
|
||||
|
||||
$oKPI->ComputeAndReport('Data model loaded');
|
||||
|
||||
|
||||
$iRet = LoginWebPage::DoLogin(false, false, LoginWebPage::EXIT_RETURN); // Starting with iTop 2.2.0 portal users are no longer allowed to access the REST/JSON API
|
||||
$oKPI->ComputeAndReport('User login');
|
||||
|
||||
@@ -130,11 +130,26 @@ try
|
||||
{
|
||||
throw new Exception("Missing parameter 'json_data'", RestResult::MISSING_JSON);
|
||||
}
|
||||
$aJsonData = @json_decode($sJsonString);
|
||||
if ($aJsonData == null)
|
||||
|
||||
if (is_string($sJsonString))
|
||||
{
|
||||
throw new Exception("Parameter json_data is not a valid JSON structure", RestResult::INVALID_JSON);
|
||||
}
|
||||
$aJsonData = @json_decode($sJsonString);
|
||||
}
|
||||
elseif(is_array($sJsonString))
|
||||
{
|
||||
$aJsonData = (object) $sJsonString;
|
||||
$sJsonString = json_encode($aJsonData);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aJsonData = null;
|
||||
}
|
||||
|
||||
if ($aJsonData == null)
|
||||
{
|
||||
throw new Exception('Parameter json_data is not a valid JSON structure', RestResult::INVALID_JSON);
|
||||
}
|
||||
|
||||
$oKPI->ComputeAndReport('Parameters validated');
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user